Index: /issm/trunk-jpl/src/py3/boundaryconditions/PattynSMB.py
===================================================================
--- /issm/trunk-jpl/src/py3/boundaryconditions/PattynSMB.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/boundaryconditions/PattynSMB.py	(revision 23670)
@@ -1,4 +1,4 @@
 import os
-import numpy as np
+import numpy as  np
 def PattynSMB(md,Tf):
 	"""
Index: /issm/trunk-jpl/src/py3/boundaryconditions/SetIceSheetBC.py
===================================================================
--- /issm/trunk-jpl/src/py3/boundaryconditions/SetIceSheetBC.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/boundaryconditions/SetIceSheetBC.py	(revision 23670)
@@ -1,4 +1,4 @@
 import os
-import numpy
+import numpy as np
 from ContourToMesh import ContourToMesh
 
@@ -14,16 +14,16 @@
 
 	#node on Dirichlet
-	pos=numpy.nonzero(md.mesh.vertexonboundary)
-	md.stressbalance.spcvx=float('nan')*numpy.ones(md.mesh.numberofvertices)
-	md.stressbalance.spcvy=float('nan')*numpy.ones(md.mesh.numberofvertices)
-	md.stressbalance.spcvz=float('nan')*numpy.ones(md.mesh.numberofvertices)
+	pos=np.nonzero(md.mesh.vertexonboundary)
+	md.stressbalance.spcvx=float('nan')*np.ones((md.mesh.numberofvertices))
+	md.stressbalance.spcvy=float('nan')*np.ones((md.mesh.numberofvertices))
+	md.stressbalance.spcvz=float('nan')*np.ones((md.mesh.numberofvertices))
 	md.stressbalance.spcvx[pos]=0
 	md.stressbalance.spcvy[pos]=0
 	md.stressbalance.spcvz[pos]=0
-	md.stressbalance.referential=float('nan')*numpy.ones((md.mesh.numberofvertices,6))
-	md.stressbalance.loadingforce=0*numpy.ones((md.mesh.numberofvertices,3))
+	md.stressbalance.referential=float('nan')*np.ones((md.mesh.numberofvertices,6))
+	md.stressbalance.loadingforce=0*np.ones((md.mesh.numberofvertices,3))
 
 	#Dirichlet Values
-	if isinstance(md.inversion.vx_obs,numpy.ndarray) and numpy.size(md.inversion.vx_obs,axis=0)==md.mesh.numberofvertices and isinstance(md.inversion.vy_obs,numpy.ndarray) and numpy.size(md.inversion.vy_obs,axis=0)==md.mesh.numberofvertices:
+	if isinstance(md.inversion.vx_obs,np.ndarray) and np.size(md.inversion.vx_obs,axis=0)==md.mesh.numberofvertices and isinstance(md.inversion.vy_obs,np.ndarray) and np.size(md.inversion.vy_obs,axis=0)==md.mesh.numberofvertices:
 		print("      boundary conditions for stressbalance model: spc set as observed velocities")
 		md.stressbalance.spcvx[pos]=md.inversion.vx_obs[pos]
@@ -39,18 +39,18 @@
 
 	#Deal with other boundary conditions
-	if numpy.all(numpy.isnan(md.balancethickness.thickening_rate)):
-		md.balancethickness.thickening_rate=numpy.zeros((md.mesh.numberofvertices,1))
+	if np.all(np.isnan(md.balancethickness.thickening_rate)):
+		md.balancethickness.thickening_rate=np.zeros((md.mesh.numberofvertices))
 		print("      no balancethickness.thickening_rate specified: values set as zero")
-	md.masstransport.spcthickness=float('nan')*numpy.ones((md.mesh.numberofvertices,1))
-	md.balancethickness.spcthickness=float('nan')*numpy.ones((md.mesh.numberofvertices,1))
-	md.damage.spcdamage=float('nan')*numpy.ones((md.mesh.numberofvertices,1))
+	md.masstransport.spcthickness=float('nan')*np.ones((md.mesh.numberofvertices))
+	md.balancethickness.spcthickness=float('nan')*np.ones((md.mesh.numberofvertices))
+	md.damage.spcdamage=float('nan')*np.ones((md.mesh.numberofvertices))
 
-	if isinstance(md.initialization.temperature,numpy.ndarray) and numpy.size(md.initialization.temperature,axis=0)==md.mesh.numberofvertices:
-		md.thermal.spctemperature=float('nan')*numpy.ones((md.mesh.numberofvertices,1))
+	if isinstance(md.initialization.temperature,np.ndarray) and np.size(md.initialization.temperature,axis=0)==md.mesh.numberofvertices:
+		md.thermal.spctemperature=float('nan')*np.ones((md.mesh.numberofvertices))
 		if hasattr(md.mesh,'vertexonsurface'):
-			pos=numpy.nonzero(md.mesh.vertexonsurface)[0]
+			pos=np.nonzero(md.mesh.vertexonsurface)[0]
 			md.thermal.spctemperature[pos]=md.initialization.temperature[pos]    #impose observed temperature on surface
-		if not isinstance(md.basalforcings.geothermalflux,numpy.ndarray) or not numpy.size(md.basalforcings.geothermalflux)==md.mesh.numberofvertices:
-			md.basalforcings.geothermalflux=50.*10**-3*numpy.ones((md.mesh.numberofvertices,1))    #50 mW/m^2
+		if not isinstance(md.basalforcings.geothermalflux,np.ndarray) or not np.size(md.basalforcings.geothermalflux)==md.mesh.numberofvertices:
+			md.basalforcings.geothermalflux=50.*10**-3*np.ones((md.mesh.numberofvertices))    #50 mW/m^2
 	else:
 		print("      no thermal boundary conditions created: no observed temperature found")
Index: /issm/trunk-jpl/src/py3/boundaryconditions/SetIceShelfBC.py
===================================================================
--- /issm/trunk-jpl/src/py3/boundaryconditions/SetIceShelfBC.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/boundaryconditions/SetIceShelfBC.py	(revision 23670)
@@ -1,4 +1,4 @@
 import os
-import numpy
+import numpy as np
 from ContourToMesh import ContourToMesh
 import MatlabFuncs as m
@@ -26,19 +26,19 @@
 		if not os.path.exists(icefrontfile):
 			raise IOError("SetIceShelfBC error message: ice front file '%s' not found." % icefrontfile)
-		[nodeinsideicefront,dum]=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,icefrontfile,'node',2)
-		nodeonicefront=numpy.logical_and(md.mesh.vertexonboundary,nodeinsideicefront.reshape(-1))
+		nodeinsideicefront=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,icefrontfile,'node',2)
+		nodeonicefront=np.logical_and(md.mesh.vertexonboundary,nodeinsideicefront.reshape(-1))
 	else:
-		nodeonicefront=numpy.zeros((md.mesh.numberofvertices),bool)
+		nodeonicefront=np.zeros((md.mesh.numberofvertices),bool)
 
 #	pos=find(md.mesh.vertexonboundary & ~nodeonicefront);
-	pos=numpy.nonzero(numpy.logical_and(md.mesh.vertexonboundary,numpy.logical_not(nodeonicefront)))[0]
-	md.stressbalance.spcvx=float('nan')*numpy.ones(md.mesh.numberofvertices)
-	md.stressbalance.spcvy=float('nan')*numpy.ones(md.mesh.numberofvertices)
-	md.stressbalance.spcvz=float('nan')*numpy.ones(md.mesh.numberofvertices)
-	md.stressbalance.referential=float('nan')*numpy.ones((md.mesh.numberofvertices,6))
-	md.stressbalance.loadingforce=0*numpy.ones((md.mesh.numberofvertices,3))
+	pos=np.nonzero(np.logical_and(md.mesh.vertexonboundary,np.logical_not(nodeonicefront)))[0]
+	md.stressbalance.spcvx=float('nan')*np.ones(md.mesh.numberofvertices)
+	md.stressbalance.spcvy=float('nan')*np.ones(md.mesh.numberofvertices)
+	md.stressbalance.spcvz=float('nan')*np.ones(md.mesh.numberofvertices)
+	md.stressbalance.referential=float('nan')*np.ones((md.mesh.numberofvertices,6))
+	md.stressbalance.loadingforce=0*np.ones((md.mesh.numberofvertices,3))
 
 	#Icefront position
-	pos=numpy.nonzero(nodeonicefront)[0]
+	pos=np.nonzero(nodeonicefront)[0]
 	md.mask.ice_levelset[pos]=0
 
@@ -53,10 +53,10 @@
 		values=md.mask.ice_levelset[md.mesh.segments[:,0:-1]-1]
 		segmentsfront=1-values
-		numpy.sum(segmentsfront,axis=1)!=numbernodesfront
-		segments=numpy.nonzero(numpy.sum(segmentsfront,axis=1)!=numbernodesfront)[0]
+		np.sum(segmentsfront,axis=1)!=numbernodesfront
+		segments=np.nonzero(np.sum(segmentsfront,axis=1)!=numbernodesfront)[0]
 		#Find all nodes for these segments and spc them
 		pos=md.mesh.segments[segments,0:-1]-1
 	else:
-		pos=numpy.nonzero(md.mesh.vertexonboundary)[0]
+		pos=np.nonzero(md.mesh.vertexonboundary)[0]
 	md.stressbalance.spcvx[pos]=0
 	md.stressbalance.spcvy[pos]=0
@@ -64,10 +64,10 @@
 																													   
 	#Dirichlet Values
-	if isinstance(md.inversion.vx_obs,numpy.ndarray) and numpy.size(md.inversion.vx_obs,axis=0)==md.mesh.numberofvertices and isinstance(md.inversion.vy_obs,numpy.ndarray) and numpy.size(md.inversion.vy_obs,axis=0)==md.mesh.numberofvertices:
+	if isinstance(md.inversion.vx_obs,np.ndarray) and np.size(md.inversion.vx_obs,axis=0)==md.mesh.numberofvertices and isinstance(md.inversion.vy_obs,np.ndarray) and np.size(md.inversion.vy_obs,axis=0)==md.mesh.numberofvertices:
 		#reshape to rank-2 if necessary to match spc arrays
-		if numpy.ndim(md.inversion.vx_obs)==1:
-			md.inversion.vx_obs=md.inversion.vx_obs.reshape(-1,1)
-		if numpy.ndim(md.inversion.vy_obs)==1:
-			md.inversion.vy_obs=md.inversion.vy_obs.reshape(-1,1)
+		if np.ndim(md.inversion.vx_obs)==1:
+			md.inversion.vx_obs=md.inversion.vx_obs.reshape(-1,)
+		if np.ndim(md.inversion.vy_obs)==1:
+			md.inversion.vy_obs=md.inversion.vy_obs.reshape(-1,)
 		print("      boundary conditions for stressbalance model: spc set as observed velocities")
 		md.stressbalance.spcvx[pos]=md.inversion.vx_obs[pos]
@@ -81,18 +81,18 @@
 
 	#Deal with other boundary conditions
-	if numpy.all(numpy.isnan(md.balancethickness.thickening_rate)):
-		md.balancethickness.thickening_rate=numpy.zeros((md.mesh.numberofvertices,1))
+	if np.all(np.isnan(md.balancethickness.thickening_rate)):
+		md.balancethickness.thickening_rate=np.zeros((md.mesh.numberofvertices))
 		print("      no balancethickness.thickening_rate specified: values set as zero")
-	md.masstransport.spcthickness=float('nan')*numpy.ones((md.mesh.numberofvertices,1))
-	md.balancethickness.spcthickness=float('nan')*numpy.ones((md.mesh.numberofvertices,1))
-	md.damage.spcdamage=float('nan')*numpy.ones((md.mesh.numberofvertices,1))
+	md.masstransport.spcthickness=float('nan')*np.ones((md.mesh.numberofvertices))
+	md.balancethickness.spcthickness=float('nan')*np.ones((md.mesh.numberofvertices))
+	md.damage.spcdamage=float('nan')*np.ones((md.mesh.numberofvertices))
 
-	if isinstance(md.initialization.temperature,numpy.ndarray) and numpy.size(md.initialization.temperature,axis=0)==md.mesh.numberofvertices:
-		md.thermal.spctemperature=float('nan')*numpy.ones((md.mesh.numberofvertices,1))
+	if isinstance(md.initialization.temperature,np.ndarray) and np.size(md.initialization.temperature,axis=0)==md.mesh.numberofvertices:
+		md.thermal.spctemperature=float('nan')*np.ones((md.mesh.numberofvertices))
 		if hasattr(md.mesh,'vertexonsurface'):
-			pos=numpy.nonzero(md.mesh.vertexonsurface)[0]
+			pos=np.nonzero(md.mesh.vertexonsurface)[0]
 			md.thermal.spctemperature[pos]=md.initialization.temperature[pos]    #impose observed temperature on surface
-		if not isinstance(md.basalforcings.geothermalflux,numpy.ndarray) or not numpy.size(md.basalforcings.geothermalflux,axis=0)==md.mesh.numberofvertices:
-			md.basalforcings.geothermalflux=numpy.zeros((md.mesh.numberofvertices,1))
+		if not isinstance(md.basalforcings.geothermalflux,np.ndarray) or not np.size(md.basalforcings.geothermalflux,axis=0)==md.mesh.numberofvertices:
+			md.basalforcings.geothermalflux=np.zeros((md.mesh.numberofvertices))
 	else:
 		print("      no thermal boundary conditions created: no observed temperature found")
Index: /issm/trunk-jpl/src/py3/boundaryconditions/SetMarineIceSheetBC.py
===================================================================
--- /issm/trunk-jpl/src/py3/boundaryconditions/SetMarineIceSheetBC.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/boundaryconditions/SetMarineIceSheetBC.py	(revision 23670)
@@ -1,4 +1,4 @@
 import os
-import numpy
+import numpy as np
 from ContourToMesh import ContourToMesh
 import MatlabFuncs as m
@@ -28,26 +28,26 @@
 		if not os.path.exists(icefrontfile):
 			raise IOError("SetMarineIceSheetBC error message: ice front file '%s' not found." % icefrontfile)
-		[incontour,dum]=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,icefrontfile,'node',2)
-		vertexonicefront=numpy.logical_and(md.mesh.vertexonboundary,incontour.reshape(-1))
+		incontour=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,icefrontfile,'node',2)
+		vertexonicefront=np.logical_and(md.mesh.vertexonboundary,incontour.reshape(-1))
 	else:
 		#Guess where the ice front is
-		vertexonfloatingice=numpy.zeros((md.mesh.numberofvertices,1))
-		pos=numpy.nonzero(numpy.sum(md.mask.groundedice_levelset[md.mesh.elements-1]<0.,axis=1) >0.)[0]
+		vertexonfloatingice=np.zeros((md.mesh.numberofvertices))
+		pos=np.nonzero(np.sum(md.mask.groundedice_levelset[md.mesh.elements-1]<0.,axis=1) >0.)[0]
 		vertexonfloatingice[md.mesh.elements[pos].astype(int)-1]=1.
-		vertexonicefront=numpy.logical_and(numpy.reshape(md.mesh.vertexonboundary,(-1,1)),vertexonfloatingice>0.)
+		vertexonicefront=np.logical_and(np.reshape(md.mesh.vertexonboundary,(-1,)),vertexonfloatingice>0.)
 
 #	pos=find(md.mesh.vertexonboundary & ~vertexonicefront);
-	pos=numpy.nonzero(numpy.logical_and(md.mesh.vertexonboundary,numpy.logical_not(vertexonicefront)))[0]
-	if not numpy.size(pos):
+	pos=np.nonzero(np.logical_and(md.mesh.vertexonboundary,np.logical_not(vertexonicefront)))[0]
+	if not np.size(pos):
 		print("SetMarineIceSheetBC warning: ice front all around the glacier, no dirichlet found. Dirichlet must be added manually.")
 
-	md.stressbalance.spcvx=float('nan')*numpy.ones(md.mesh.numberofvertices)
-	md.stressbalance.spcvy=float('nan')*numpy.ones(md.mesh.numberofvertices)
-	md.stressbalance.spcvz=float('nan')*numpy.ones(md.mesh.numberofvertices)
-	md.stressbalance.referential=float('nan')*numpy.ones((md.mesh.numberofvertices,6))
-	md.stressbalance.loadingforce=0*numpy.ones((md.mesh.numberofvertices,3))
+	md.stressbalance.spcvx=float('nan')*np.ones(md.mesh.numberofvertices)
+	md.stressbalance.spcvy=float('nan')*np.ones(md.mesh.numberofvertices)
+	md.stressbalance.spcvz=float('nan')*np.ones(md.mesh.numberofvertices)
+	md.stressbalance.referential=float('nan')*np.ones((md.mesh.numberofvertices,6))
+	md.stressbalance.loadingforce=0*np.ones((md.mesh.numberofvertices,3))
 
 	#Position of ice front
-	pos=numpy.nonzero(vertexonicefront)[0]
+	pos=np.nonzero(vertexonicefront)[0]
 	md.mask.ice_levelset[pos]=0
 
@@ -62,10 +62,10 @@
 		values=md.mask.ice_levelset[md.mesh.segments[:,0:-1]-1]
 		segmentsfront=1-values
-		numpy.sum(segmentsfront,axis=1)!=numbernodesfront
-		segments=numpy.nonzero(numpy.sum(segmentsfront,axis=1)!=numbernodesfront)[0]
+		np.sum(segmentsfront,axis=1)!=numbernodesfront
+		segments=np.nonzero(np.sum(segmentsfront,axis=1)!=numbernodesfront)[0]
 		#Find all nodes for these segments and spc them
 		pos=md.mesh.segments[segments,0:-1]-1
 	else:
-		pos=numpy.nonzero(md.mesh.vertexonboundary)[0]
+		pos=np.nonzero(md.mesh.vertexonboundary)[0]
 	md.stressbalance.spcvx[pos]=0
 	md.stressbalance.spcvy[pos]=0
@@ -73,5 +73,5 @@
 
 	#Dirichlet Values
-	if isinstance(md.inversion.vx_obs,numpy.ndarray) and numpy.size(md.inversion.vx_obs,axis=0)==md.mesh.numberofvertices and isinstance(md.inversion.vy_obs,numpy.ndarray) and numpy.size(md.inversion.vy_obs,axis=0)==md.mesh.numberofvertices:
+	if isinstance(md.inversion.vx_obs,np.ndarray) and np.size(md.inversion.vx_obs,axis=0)==md.mesh.numberofvertices and isinstance(md.inversion.vy_obs,np.ndarray) and np.size(md.inversion.vy_obs,axis=0)==md.mesh.numberofvertices:
 		print("      boundary conditions for stressbalance model: spc set as observed velocities")
 		md.stressbalance.spcvx[pos]=md.inversion.vx_obs[pos]
@@ -80,6 +80,6 @@
 		print("      boundary conditions for stressbalance model: spc set as zero")
 
-	md.hydrology.spcwatercolumn=numpy.zeros((md.mesh.numberofvertices,2))
-	pos=numpy.nonzero(md.mesh.vertexonboundary)[0]
+	md.hydrology.spcwatercolumn=np.zeros((md.mesh.numberofvertices,2))
+	pos=np.nonzero(md.mesh.vertexonboundary)[0]
 	md.hydrology.spcwatercolumn[pos,0]=1
 
@@ -89,20 +89,20 @@
 
 	#Deal with other boundary conditions
-	if numpy.all(numpy.isnan(md.balancethickness.thickening_rate)):
-		md.balancethickness.thickening_rate=numpy.zeros((md.mesh.numberofvertices,1))
+	if np.all(np.isnan(md.balancethickness.thickening_rate)):
+		md.balancethickness.thickening_rate=np.zeros((md.mesh.numberofvertices))
 		print("      no balancethickness.thickening_rate specified: values set as zero")
 
-	md.masstransport.spcthickness=float('nan')*numpy.ones((md.mesh.numberofvertices,1))
-	md.balancethickness.spcthickness=float('nan')*numpy.ones((md.mesh.numberofvertices,1))
-	md.damage.spcdamage=float('nan')*numpy.ones((md.mesh.numberofvertices,1))
+	md.masstransport.spcthickness=float('nan')*np.ones((md.mesh.numberofvertices))
+	md.balancethickness.spcthickness=float('nan')*np.ones((md.mesh.numberofvertices))
+	md.damage.spcdamage=float('nan')*np.ones((md.mesh.numberofvertices))
 
-	if isinstance(md.initialization.temperature,numpy.ndarray) and numpy.size(md.initialization.temperature,axis=0)==md.mesh.numberofvertices:
-		md.thermal.spctemperature=float('nan')*numpy.ones((md.mesh.numberofvertices,1))
+	if isinstance(md.initialization.temperature,np.ndarray) and np.size(md.initialization.temperature,axis=0)==md.mesh.numberofvertices:
+		md.thermal.spctemperature=float('nan')*np.ones((md.mesh.numberofvertices))
 		if hasattr(md.mesh,'vertexonsurface'):
-			pos=numpy.nonzero(md.mesh.vertexonsurface)[0]
+			pos=np.nonzero(md.mesh.vertexonsurface)[0]
 			md.thermal.spctemperature[pos]=md.initialization.temperature[pos]    #impose observed temperature on surface
-		if not isinstance(md.basalforcings.geothermalflux,numpy.ndarray) or not numpy.size(md.basalforcings.geothermalflux,axis=0)==md.mesh.numberofvertices:
-			md.basalforcings.geothermalflux=numpy.zeros((md.mesh.numberofvertices,1))
-			md.basalforcings.geothermalflux[numpy.nonzero(md.mask.groundedice_levelset>0.)]=50.*10.**-3    #50mW/m2
+		if not isinstance(md.basalforcings.geothermalflux,np.ndarray) or not np.size(md.basalforcings.geothermalflux,axis=0)==md.mesh.numberofvertices:
+			md.basalforcings.geothermalflux=np.zeros((md.mesh.numberofvertices))
+			md.basalforcings.geothermalflux[np.nonzero(md.mask.groundedice_levelset>0.)]=50.*10.**-3    #50mW/m2
 	else:
 		print("      no thermal boundary conditions created: no observed temperature found")
Index: /issm/trunk-jpl/src/py3/classes/SMBcomponents.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/SMBcomponents.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/SMBcomponents.py	(revision 23670)
@@ -1,4 +1,3 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import *
 from project3d import *
@@ -39,14 +38,14 @@
 	def initialize(self,md): # {{{
 
-		if numpy.all(numpy.isnan(self.accumulation)):
-			self.accumulation=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.accumulation)):
+			self.accumulation=np.zeros((md.mesh.numberofvertices))
 			print("      no SMB.accumulation specified: values set as zero")
 
-		if numpy.all(numpy.isnan(self.runoff)):
-			self.runoff=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.runoff)):
+			self.runoff=np.zeros((md.mesh.numberofvertices))
 			print("      no SMB.runoff specified: values set as zero")
 
-		if numpy.all(numpy.isnan(self.evaporation)):
-			self.evaporation=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.evaporation)):
+			self.evaporation=np.zeros((md.mesh.numberofvertices))
 			print("      no SMB.evaporation specified: values set as zero")
 
@@ -55,20 +54,20 @@
 	def checkconsistency(self,md,solution,analyses):    # {{{
 
-		if MasstransportAnalysisEnum() in analyses:
+		if 'MasstransportAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.accumulation','timeseries',1,'NaN',1,'Inf',1)
 
-		if BalancethicknessAnalysisEnum() in analyses:
+		if 'BalancethicknessAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.accumulation','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 
-		if MasstransportAnalysisEnum() in analyses:
+		if 'MasstransportAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.runoff','timeseries',1,'NaN',1,'Inf',1)
 
-		if BalancethicknessAnalysisEnum() in analyses:
+		if 'BalancethicknessAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.runoff','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 
-		if MasstransportAnalysisEnum() in analyses:
+		if 'MasstransportAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.evaporation','timeseries',1,'NaN',1,'Inf',1)
 
-		if BalancethicknessAnalysisEnum() in analyses:
+		if 'BalancethicknessAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.evaporation','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 		
@@ -77,12 +76,12 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.0*24.0*3600.0
+		yts=md.constants.yts
 
-		WriteData(fid,'enum',SmbEnum(),'data',SMBcomponentsEnum(),'format','Integer');
-		WriteData(fid,'object',self,'class','smb','fieldname','accumulation','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'class','smb','fieldname','runoff','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'class','smb','fieldname','evaporation','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
+		WriteData(fid,prefix,'name','md.smb.model','data',2,'format','Integer');
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','accumulation','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','runoff','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','evaporation','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
 		
 		#process requested outputs
@@ -92,5 +91,5 @@
 			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
 			outputs    =outputscopy
-		WriteData(fid,'data',outputs,'enum',SmbRequestedOutputsEnum(),'format','StringArray')
+		WriteData(fid,prefix,'data',outputs,'name','md.smb.requested_outputs','format','StringArray')
 
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/SMBd18opdd.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/SMBd18opdd.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/SMBd18opdd.py	(revision 23670)
@@ -1,5 +1,4 @@
-import numpy
+import numpy as np
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -21,12 +20,20 @@
 		self.rlapslgm                  = 0.
 		self.dpermil                   = 0.
+		self.f                         = 0.
 		self.Tdiff                     = float('NaN')
 		self.sealev                    = float('NaN')
 		self.ismungsm                  = 0
 		self.isd18opd                  = 0
+		self.issetpddfac               = 0
+		self.istemperaturescaled       = 0
+		self.isprecipscaled            = 0
 		self.delta18o                  = float('NaN')
 		self.delta18o_surface          = float('NaN')
 		self.temperatures_presentday   = float('NaN')
 		self.precipitations_presentday = float('NaN')
+		self.temperatures_reconstructed   = float('NaN')
+		self.precipitations_reconstructed = float('NaN')
+		self.pddfac_snow               = float('NaN')
+		self.pddfac_ice                = float('NaN')
 
 		#set defaults
@@ -38,4 +45,5 @@
 
 		string="%s\n%s"%(string,fielddisplay(self,'isd18opd','is delta18o parametrisation from present day temperature and precipitation activated (0 or 1, default is 0)'))
+		string="%s\n%s"%(string,fielddisplay(self,'issetpddfac','is user passing in defined pdd factors at each vertex (0 or 1, default is 0)'))
 		string="%s\n%s"%(string,fielddisplay(self,'desfac','desertification elevation factor (between 0 and 1, default is 0.5) [m]'))
 		string="%s\n%s"%(string,fielddisplay(self,'s0p','should be set to elevation from precip source (between 0 and a few 1000s m, default is 0) [m]'))
@@ -45,6 +53,20 @@
 			string="%s\n%s"%(string,fielddisplay(self,'temperatures_presentday','monthly present day surface temperatures [K], required if delta18o/mungsm is activated'))
 			string="%s\n%s"%(string,fielddisplay(self,'precipitations_presentday','monthly surface precipitation [m/yr water eq], required if delta18o or mungsm is activated'))
+			string="%s\n%s"%(string,fielddisplay(self,'istemperaturescaled','if delta18o parametrisation from present day temperature and precipitation is activated, is temperature scaled to delta18o value? (0 or 1, default is 1)'))
+			string="%s\n%s"%(string,fielddisplay(self,'isprecipscaled','if delta18o parametrisation from present day temperature and precipitation is activated, is precipitation scaled to delta18o value? (0 or 1, default is 1)'))
+			
+			if self.istemperaturescaled==0:
+				string="%s\n%s"%(string,fielddisplay(self,'temperatures_reconstructed','monthly historical surface temperatures [K], required if delta18o/mungsm/d18opd is activated and istemperaturescaled is not activated'))
+				
+			if self.isprecipscaled==0:
+				string="%s\n%s"%(string,fielddisplay(self,'precipitations_reconstructed','monthly historical precipitation [m/yr water eq], required if delta18o/mungsm/d18opd is activated and isprecipscaled is not activated'))
+
 			string="%s\n%s"%(string,fielddisplay(self,'delta18o','delta18o [per mil], required if pdd is activated and delta18o activated'))
 			string="%s\n%s"%(string,fielddisplay(self,'dpermil','degree per mil, required if d18opd is activated'))
+			string="%s\n%s"%(string,fielddisplay(self,'f','precip/temperature scaling factor, required if d18opd is activated'))
+
+		if self.issetpddfac==1:
+			string="%s\n%s"%(string,fielddisplay(self,'pddfac_snow','Pdd factor for snow, at each vertex [mm ice equiv/day/degree C]'))
+			string="%s\n%s"%(string,fielddisplay(self,'pddfac_ice','Pdd factor for ice, at each vertex [mm ice equiv/day/degree C]'))
 		string="%s\n%s"%(string,fielddisplay(self,'requested_outputs','additional outputs requested'))
 
@@ -55,4 +77,9 @@
 		if self.isd18opd: self.temperatures_presentday=project3d(md,'vector',self.temperatures_presentday,'type','node')
 		if self.isd18opd: self.precipitations_presentday=project3d(md,'vector',self.precipitations_presentday,'type','node')
+		if self.istemperaturescaled==0: self.temperatures_reconstructed=project3d(md,'vector',self.temperatures_reconstructed,'type','node')
+		if self.isprecipscaled==0: self.temperatures_reconstructed=project3d(md,'vector',self.precipitations_reconstructed,'type','node')
+		if self.isd18opd: self.precipitations_presentday=project3d(md,'vector',self.precipitations_presentday,'type','node')
+		if self.issetpddfac: self.pddfac_snow=project3d(md,'vector',self.pddfac_snow,'type','node')
+		if self.issetpddfac: self.pddfac_ice=project3d(md,'vector',self.pddfac_ice,'type','node')
 		self.s0p=project3d(md,'vector',self.s0p,'type','node')
 		self.s0t=project3d(md,'vector',self.s0t,'type','node')
@@ -65,10 +92,10 @@
 	def initialize(self,md): # {{{
 
-		if numpy.all(numpy.isnan(self.s0p)):
-			self.s0p=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.s0p)):
+			self.s0p=np.zeros((md.mesh.numberofvertices))
 			print("      no SMBd18opdd.s0p specified: values set as zero")
 
-		if numpy.all(numpy.isnan(self.s0t)):
-			self.s0t=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.s0t)):
+			self.s0t=np.zeros((md.mesh.numberofvertices))
 			print("      no SMBd18opdd.s0t specified: values set as zero")
 			
@@ -80,52 +107,90 @@
 		self.ismungsm   = 0
 		self.isd18opd   = 1
+		self.istemperaturescaled = 1
+		self.isprecipscaled = 1
 		self.desfac     = 0.5
 		self.rlaps      = 6.5 
 		self.rlapslgm   = 6.5
 		self.dpermil    = 2.4
-
+		self.f          = 0.169
+		self.issetpddfac = 0
 		return self
 	#}}}
 	def checkconsistency(self,md,solution,analyses):    # {{{
 
-		if MasstransportAnalysisEnum() in analyses:
+		if 'MasstransportAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.desfac','<=',1,'numel',[1])
-			md = checkfield(md,'fieldname','smb.s0p','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices,1])
-			md = checkfield(md,'fieldname','smb.s0t','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices,1])
+			md = checkfield(md,'fieldname','smb.s0p','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
+			md = checkfield(md,'fieldname','smb.s0t','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 			md = checkfield(md,'fieldname','smb.rlaps','>=',0,'numel',[1])
 			md = checkfield(md,'fieldname','smb.rlapslgm','>=',0,'numel',[1])
 
 			if self.isd18opd:
+				lent=float(np.size(self.temperatures_presentday,1))
+				lenp=float(np.size(self.precipitations_presentday,1))
+				multt=np.ceil(lent/12.)*12.
+				multp=np.ceil(lenp/12.)*12.
 				md = checkfield(md,'fieldname','smb.temperatures_presentday','size',[md.mesh.numberofvertices+1,12],'NaN',1,'Inf',1,'timeseries',1)
 				md = checkfield(md,'fieldname','smb.precipitations_presentday','size',[md.mesh.numberofvertices+1,12],'NaN',1,'Inf',1,'timeseries',1)
-				md = checkfield(md,'fieldname','smb.delta18o','NaN',1,'Inf',1,'size',[2,numpy.nan],'singletimeseries',1)
+
+				if self.istemperaturescaled==0:
+					lent=float(np.size(self.temperatures_reconstructed,1))
+					multt=np.ceil(lent/12.)*12.
+					md = checkfield(md,'fieldname','smb.temperatures_reconstructed','size',[md.mesh.numberofvertices+1,multt],'NaN',1,'Inf',1,'timeseries',1)
+
+				if self.isprecipscaled==0:
+					lenp=float(np.size(self.precipitations_reconstructed,1))
+					multp=np.ceil(lent/12.)*12.
+					md = checkfield(md,'fieldname','smb.precipitations_reconstructed','size',[md.mesh.numberofvertices+1,multt],'NaN',1,'Inf',1,'timeseries',1)
+
+				md = checkfield(md,'fieldname','smb.delta18o','NaN',1,'Inf',1,'size',[2,np.nan],'singletimeseries',1)
 				md = checkfield(md,'fieldname','smb.dpermil','>=',0,'numel',[1])
-		
+				md = checkfield(md,'fieldname','smb.f','>=',0,'numel',[1])
+
+			if self.issetpddfac:
+				md = checkfield(md,'fieldname','smb.pddfac_snow','>=',0,'NaN',1,'Inf',1)
+				md = checkfield(md,'fieldname','smb.pddfac_ice','>=',0,'NaN',1,'Inf',1)
+
 		md = checkfield(md,'fieldname','masstransport.requested_outputs','stringrow',1)
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-
-		yts=365.0*24.0*3600.0
-
-		WriteData(fid,'enum',SmbEnum(),'data',SMBd18opddEnum(),'format','Integer')
-
-		WriteData(fid,'object',self,'class','smb','fieldname','ismungsm','format','Boolean')
-		WriteData(fid,'object',self,'class','smb','fieldname','isd18opd','format','Boolean')
-		WriteData(fid,'object',self,'class','smb','fieldname','desfac','format','Double')
-		WriteData(fid,'object',self,'class','smb','fieldname','s0p','format','DoubleMat','mattype',1);
-		WriteData(fid,'object',self,'class','smb','fieldname','s0t','format','DoubleMat','mattype',1);
-		WriteData(fid,'object',self,'class','smb','fieldname','rlaps','format','Double')
-		WriteData(fid,'object',self,'class','smb','fieldname','rlapslgm','format','Double')
-		WriteData(fid,'object',self,'class','smb','fieldname','Tdiff','format','DoubleMat','mattype',1,'timeserieslength',2)
-		WriteData(fid,'object',self,'class','smb','fieldname','sealev','format','DoubleMat','mattype',1,'timeserieslength',2)
+	def marshall(self,prefix,md,fid):    # {{{
+
+		yts=md.constants.yts
+
+		WriteData(fid,prefix,'name','md.smb.model','data',5,'format','Integer')
+
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','ismungsm','format','Boolean')
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','isd18opd','format','Boolean')
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','issetpddfac','format','Boolean');
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','desfac','format','Double')
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','s0p','format','DoubleMat','mattype',1);
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','s0t','format','DoubleMat','mattype',1);
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','rlaps','format','Double')
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','rlapslgm','format','Double')
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','Tdiff','format','DoubleMat','mattype',1,'timeserieslength',2,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','sealev','format','DoubleMat','mattype',1,'timeserieslength',2,'yts',md.constants.yts)
 
 		if self.isd18opd:
-			WriteData(fid,'object',self,'class','smb','fieldname','temperatures_presentday','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-			WriteData(fid,'object',self,'class','smb','fieldname','precipitations_presentday','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-			WriteData(fid,'object',self,'class','smb','fieldname','delta18o','format','DoubleMat','mattype',1,'timeserieslength',2)
-			WriteData(fid,'object',self,'class','smb','fieldname','dpermil','format','Double')
-			
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','temperatures_presentday','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','precipitations_presentday','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','istemperaturescaled','format','Boolean')
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','isprecipscaled','format','Boolean')
+
+			if self.istemperaturescaled==0:
+				WriteData(fid,prefix,'object',self,'class','smb','fieldname','temperatures_reconstructed','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+
+			if self.isprecipscaled==0:
+				WriteData(fid,prefix,'object',self,'class','smb','fieldname','precipitations_reconstructed','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','delta18o','format','DoubleMat','mattype',1,'timeserieslength',2,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dpermil','format','Double')
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','f','format','Double')
+
+		if self.issetpddfac:
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','pddfac_snow','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','pddfac_ice','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+
 		#process requested outputs
 		outputs = self.requested_outputs
@@ -134,5 +199,5 @@
 			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
 			outputs    =outputscopy
-		WriteData(fid,'data',outputs,'enum',SmbRequestedOutputsEnum(),'format','StringArray')
+		WriteData(fid,prefix,'data',outputs,'name','md.smb.requested_outputs','format','StringArray')
 
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/SMBforcing.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/SMBforcing.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/SMBforcing.py	(revision 23670)
@@ -1,5 +1,4 @@
-import numpy
+import numpy as np
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -34,6 +33,6 @@
 	def initialize(self,md): # {{{
 
-		if numpy.all(numpy.isnan(self.mass_balance)):
-			self.mass_balance=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.mass_balance)):
+			self.mass_balance=np.zeros((md.mesh.numberofvertices))
 			print("      no SMBforcing.mass_balance specified: values set as zero")
 
@@ -42,8 +41,8 @@
 	def checkconsistency(self,md,solution,analyses):    # {{{
 
-		if MasstransportAnalysisEnum() in analyses:
+		if 'MasstransportAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.mass_balance','timeseries',1,'NaN',1,'Inf',1)
 
-		if BalancethicknessAnalysisEnum() in analyses:
+		if 'BalancethicknessAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.mass_balance','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 
@@ -51,10 +50,11 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.0*24.0*3600.0
+		yts=md.constants.yts
 
-		WriteData(fid,'enum',SmbEnum(),'data',SMBforcingEnum(),'format','Integer');
-		WriteData(fid,'object',self,'class','smb','fieldname','mass_balance','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
+		WriteData(fid,prefix,'name','md.smb.model','data',1,'format','Integer');
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','mass_balance','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		#WriteData(fid,prefix,'object',self,'class','smb','fieldname','mass_balance','format','CompressedMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
 		
 		#process requested outputs
@@ -64,5 +64,5 @@
 			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
 			outputs    =outputscopy
-		WriteData(fid,'data',outputs,'enum',SmbRequestedOutputsEnum(),'format','StringArray')
+		WriteData(fid,prefix,'data',outputs,'name','md.smb.requested_outputs','format','StringArray')
 
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/SMBgradients.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/SMBgradients.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/SMBgradients.py	(revision 23670)
@@ -1,4 +1,3 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -48,5 +47,5 @@
 	def checkconsistency(self,md,solution,analyses):    # {{{
 
-		if MasstransportAnalysisEnum() in analyses:
+		if 'MasstransportAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.href','timeseries',1,'NaN',1,'Inf',1)
 			md = checkfield(md,'fieldname','smb.smbref','timeseries',1,'NaN',1,'Inf',1)
@@ -57,13 +56,13 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.0*24.0*3600.0
+		yts=md.constants.yts
 
-		WriteData(fid,'enum',SmbEnum(),'data',SMBgradientsEnum(),'format','Integer');
-		WriteData(fid,'object',self,'class','smb','fieldname','href','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'class','smb','fieldname','smbref','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'class','smb','fieldname','b_pos','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'class','smb','fieldname','b_neg','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
+		WriteData(fid,prefix,'name','md.smb.model','data',6,'format','Integer');
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','href','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','smbref','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','b_pos','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','b_neg','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
 		
 		#process requested outputs
@@ -73,5 +72,5 @@
 			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
 			outputs    =outputscopy
-		WriteData(fid,'data',outputs,'enum',SmbRequestedOutputsEnum(),'format','StringArray')
+		WriteData(fid,prefix,'data',outputs,'name','md.smb.requested_outputs','format','StringArray')
 
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/SMBmeltcomponents.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/SMBmeltcomponents.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/SMBmeltcomponents.py	(revision 23670)
@@ -1,4 +1,3 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import *
 from project3d import *
@@ -30,8 +29,8 @@
 	def extrude(self,md): # {{{
 
-		self.mass_balance=project3d(md,'vector',self.accumulation,'type','node');
-		self.mass_balance=project3d(md,'vector',self.evaporation,'type','node');
-		self.mass_balance=project3d(md,'vector',self.melt,'type','node');
-		self.mass_balance=project3d(md,'vector',self.refreeze,'type','node');
+		self.accumulation=project3d(md,'vector',self.accumulation,'type','node');
+		self.evaporation=project3d(md,'vector',self.evaporation,'type','node');
+		self.melt=project3d(md,'vector',self.melt,'type','node');
+		self.refreeze=project3d(md,'vector',self.refreeze,'type','node');
 		return self
 	#}}}
@@ -41,18 +40,18 @@
 	def initialize(self,md): # {{{
 
-		if numpy.all(numpy.isnan(self.accumulation)):
-			self.accumulation=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.accumulation)):
+			self.accumulation=np.zeros((md.mesh.numberofvertices))
 			print("      no SMB.accumulation specified: values set as zero")
 
-		if numpy.all(numpy.isnan(self.evaporation)):
-			self.evaporation=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.evaporation)):
+			self.evaporation=np.zeros((md.mesh.numberofvertices))
 			print("      no SMB.evaporation specified: values set as zero")
 
-		if numpy.all(numpy.isnan(self.melt)):
-			self.melt=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.melt)):
+			self.melt=np.zeros((md.mesh.numberofvertices))
 			print("      no SMB.melt specified: values set as zero")
 
-		if numpy.all(numpy.isnan(self.refreeze)):
-			self.refreeze=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.refreeze)):
+			self.refreeze=np.zeros((md.mesh.numberofvertices))
 			print("      no SMB.refreeze specified: values set as zero")
 
@@ -61,26 +60,26 @@
 	def checkconsistency(self,md,solution,analyses):    # {{{
 
-		if MasstransportAnalysisEnum() in analyses:
+		if 'MasstransportAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.accumulation','timeseries',1,'NaN',1,'Inf',1)
 
-		if BalancethicknessAnalysisEnum() in analyses:
+		if 'BalancethicknessAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.accumulation','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 
-		if MasstransportAnalysisEnum() in analyses:
+		if 'MasstransportAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.melt','timeseries',1,'NaN',1,'Inf',1)
 
-		if BalancethicknessAnalysisEnum() in analyses:
+		if 'BalancethicknessAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.melt','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 
-		if MasstransportAnalysisEnum() in analyses:
+		if 'MasstransportAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.refreeze','timeseries',1,'NaN',1,'Inf',1)
 
-		if BalancethicknessAnalysisEnum() in analyses:
+		if 'BalancethicknessAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.refreeze','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 
-		if MasstransportAnalysisEnum() in analyses:
+		if 'MasstransportAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.evaporation','timeseries',1,'NaN',1,'Inf',1)
 
-		if BalancethicknessAnalysisEnum() in analyses:
+		if 'BalancethicknessAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.evaporation','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 
@@ -88,14 +87,14 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.0*24.0*3600.0
+		yts=md.constants.yts
 
-		WriteData(fid,'enum',SmbEnum(),'data',SMBmeltcomponentsEnum(),'format','Integer');
-		WriteData(fid,'object',self,'class','smb','fieldname','accumulation','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'class','smb','fieldname','evaporation','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'class','smb','fieldname','melt','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'class','smb','fieldname','refreeze','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		
+		WriteData(fid,prefix,'name','md.smb.model','data',3,'format','Integer');
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','accumulation','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','evaporation','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','melt','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','refreeze','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+
 		#process requested outputs
 		outputs = self.requested_outputs
@@ -104,5 +103,5 @@
 			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
 			outputs    =outputscopy
-		WriteData(fid,'data',outputs,'enum',SmbRequestedOutputsEnum(),'format','StringArray')
+		WriteData(fid,prefix,'data',outputs,'name','md.smb.requested_outputs','format','StringArray')
 
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/SMBpdd.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/SMBpdd.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/SMBpdd.py	(revision 23670)
@@ -1,5 +1,4 @@
-import numpy
+import numpy as np
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -27,4 +26,5 @@
 		self.isdelta18o                = 0
 		self.ismungsm                  = 0
+		self.issetpddfac               = 0
 		self.delta18o                  = float('NaN')
 		self.delta18o_surface          = float('NaN')
@@ -95,10 +95,10 @@
 	def initialize(self,md): # {{{
 
-		if numpy.all(numpy.isnan(self.s0p)):
-			self.s0p=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.s0p)):
+			self.s0p=np.zeros((md.mesh.numberofvertices))
 			print("      no SMBpdd.s0p specified: values set as zero")
 
-		if numpy.all(numpy.isnan(self.s0t)):
-			self.s0t=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.s0t)):
+			self.s0t=np.zeros((md.mesh.numberofvertices))
 			print("      no SMBpdd.s0t specified: values set as zero")
 
@@ -118,8 +118,8 @@
 	def checkconsistency(self,md,solution,analyses):    # {{{
 
-		if MasstransportAnalysisEnum() in analyses:
+		if 'MasstransportAnalysis' in analyses:
 			md = checkfield(md,'fieldname','smb.desfac','<=',1,'numel',[1])
-			md = checkfield(md,'fieldname','smb.s0p','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices,1])
-			md = checkfield(md,'fieldname','smb.s0t','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices,1])
+			md = checkfield(md,'fieldname','smb.s0p','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
+			md = checkfield(md,'fieldname','smb.s0t','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 			md = checkfield(md,'fieldname','smb.rlaps','>=',0,'numel',[1])
 			md = checkfield(md,'fieldname','smb.rlapslgm','>=',0,'numel',[1])
@@ -129,12 +129,12 @@
 				md = checkfield(md,'fieldname','smb.precipitation','NaN',1,'Inf',1,'timeseries',1)
 			elif self.isdelta18o:
-				md = checkfield(md,'fieldname','smb.delta18o','NaN',1,'Inf',1,'size',[2,numpy.nan],'singletimeseries',1)
-				md = checkfield(md,'fieldname','smb.delta18o_surface','NaN',1,'Inf',1,'size',[2,numpy.nan],'singletimeseries',1)
+				md = checkfield(md,'fieldname','smb.delta18o','NaN',1,'Inf',1,'size',[2,np.nan],'singletimeseries',1)
+				md = checkfield(md,'fieldname','smb.delta18o_surface','NaN',1,'Inf',1,'size',[2,np.nan],'singletimeseries',1)
 				md = checkfield(md,'fieldname','smb.temperatures_presentday','size',[md.mesh.numberofvertices+1,12],'NaN',1,'Inf',1,'timeseries',1)
 				md = checkfield(md,'fieldname','smb.temperatures_lgm','size',[md.mesh.numberofvertices+1,12],'NaN',1,'Inf',1,'timeseries',1)
 				md = checkfield(md,'fieldname','smb.precipitations_presentday','size',[md.mesh.numberofvertices+1,12],'NaN',1,'Inf',1,'timeseries',1)
 				md = checkfield(md,'fieldname','smb.precipitations_lgm','size',[md.mesh.numberofvertices+1,12],'NaN',1,'Inf',1,'timeseries',1)                                       
-				md = checkfield(md,'fieldname','smb.Tdiff','NaN',1,'Inf',1,'size',[2,numpy.nan],'singletimeseries',1)
-				md = checkfield(md,'fieldname','smb.sealev','NaN',1,'Inf',1,'size',[2,numpy.nan],'singletimeseries',1)
+				md = checkfield(md,'fieldname','smb.Tdiff','NaN',1,'Inf',1,'size',[2,np.nan],'singletimeseries',1)
+				md = checkfield(md,'fieldname','smb.sealev','NaN',1,'Inf',1,'size',[2,np.nan],'singletimeseries',1)
 			elif self.ismungsm:
 				md = checkfield(md,'fieldname','smb.temperatures_presentday','size',[md.mesh.numberofvertices+1,12],'NaN',1,'Inf',1,'timeseries',1)
@@ -142,45 +142,46 @@
 				md = checkfield(md,'fieldname','smb.precipitations_presentday','size',[md.mesh.numberofvertices+1,12],'NaN',1,'Inf',1,'timeseries',1)
 				md = checkfield(md,'fieldname','smb.precipitations_lgm','size',[md.mesh.numberofvertices+1,12],'NaN',1,'Inf',1,'timeseries',1)                                       
-				md = checkfield(md,'fieldname','smb.Pfac','NaN',1,'Inf',1,'size',[2,numpy.nan],'singletimeseries',1)
-				md = checkfield(md,'fieldname','smb.Tdiff','NaN',1,'Inf',1,'size',[2,numpy.nan],'singletimeseries',1)
-				md = checkfield(md,'fieldname','smb.sealev','NaN',1,'Inf',1,'size',[2,numpy.nan],'singletimeseries',1)
+				md = checkfield(md,'fieldname','smb.Pfac','NaN',1,'Inf',1,'size',[2,np.nan],'singletimeseries',1)
+				md = checkfield(md,'fieldname','smb.Tdiff','NaN',1,'Inf',1,'size',[2,np.nan],'singletimeseries',1)
+				md = checkfield(md,'fieldname','smb.sealev','NaN',1,'Inf',1,'size',[2,np.nan],'singletimeseries',1)
 
 		md = checkfield(md,'fieldname','masstransport.requested_outputs','stringrow',1)
 		return md
 	#}}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.0*24.0*3600.0
+		yts=md.constants.yts
 
-		WriteData(fid,'enum',SmbEnum(),'data',SMBpddEnum(),'format','Integer')
+		WriteData(fid,prefix,'name','md.smb.model','data',4,'format','Integer')
 
-		WriteData(fid,'object',self,'class','smb','fieldname','isdelta18o','format','Boolean')
-		WriteData(fid,'object',self,'class','smb','fieldname','ismungsm','format','Boolean')
-		WriteData(fid,'object',self,'class','smb','fieldname','desfac','format','Double')
-		WriteData(fid,'object',self,'class','smb','fieldname','s0p','format','DoubleMat','mattype',1);
-		WriteData(fid,'object',self,'class','smb','fieldname','s0t','format','DoubleMat','mattype',1);
-		WriteData(fid,'object',self,'class','smb','fieldname','rlaps','format','Double')
-		WriteData(fid,'object',self,'class','smb','fieldname','rlapslgm','format','Double')
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','isdelta18o','format','Boolean')
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','ismungsm','format','Boolean')
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','issetpddfac','format','Boolean');
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','desfac','format','Double')
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','s0p','format','DoubleMat','mattype',1);
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','s0t','format','DoubleMat','mattype',1);
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','rlaps','format','Double')
+		WriteData(fid,prefix,'object',self,'class','smb','fieldname','rlapslgm','format','Double')
 
 		if (self.isdelta18o==0 and self.ismungsm==0):
-			WriteData(fid,'object',self,'class','smb','fieldname','monthlytemperatures','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-			WriteData(fid,'object',self,'class','smb','fieldname','precipitation','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','monthlytemperatures','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','precipitation','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
 		elif self.isdelta18o:
-			WriteData(fid,'object',self,'class','smb','fieldname','temperatures_presentday','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-			WriteData(fid,'object',self,'class','smb','fieldname','temperatures_lgm','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-			WriteData(fid,'object',self,'class','smb','fieldname','precipitations_presentday','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-			WriteData(fid,'object',self,'class','smb','fieldname','precipitations_lgm','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-			WriteData(fid,'object',self,'class','smb','fieldname','delta18o_surface','format','DoubleMat','mattype',1,'timeserieslength',2)
-			WriteData(fid,'object',self,'class','smb','fieldname','delta18o','format','DoubleMat','mattype',1,'timeserieslength',2)
-			WriteData(fid,'object',self,'class','smb','fieldname','Tdiff','format','DoubleMat','mattype',1,'timeserieslength',2)
-			WriteData(fid,'object',self,'class','smb','fieldname','sealev','format','DoubleMat','mattype',1,'timeserieslength',2)			
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','temperatures_presentday','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','temperatures_lgm','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','precipitations_presentday','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','precipitations_lgm','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','delta18o_surface','format','DoubleMat','mattype',1,'timeserieslength',2,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','delta18o','format','DoubleMat','mattype',1,'timeserieslength',2,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','Tdiff','format','DoubleMat','mattype',1,'timeserieslength',2,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','sealev','format','DoubleMat','mattype',1,'timeserieslength',2,'yts',md.constants.yts)			
 		elif self.ismungsm:
-			WriteData(fid,'object',self,'class','smb','fieldname','temperatures_presentday','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-			WriteData(fid,'object',self,'class','smb','fieldname','temperatures_lgm','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-			WriteData(fid,'object',self,'class','smb','fieldname','precipitations_presentday','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-			WriteData(fid,'object',self,'class','smb','fieldname','precipitations_lgm','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-			WriteData(fid,'object',self,'class','smb','fieldname','Pfac','format','DoubleMat','mattype',1,'timeserieslength',2)
-			WriteData(fid,'object',self,'class','smb','fieldname','Tdiff','format','DoubleMat','mattype',1,'timeserieslength',2)
-			WriteData(fid,'object',self,'class','smb','fieldname','sealev','format','DoubleMat','mattype',1,'timeserieslength',2)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','temperatures_presentday','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','temperatures_lgm','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','precipitations_presentday','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','precipitations_lgm','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','Pfac','format','DoubleMat','mattype',1,'timeserieslength',2,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','Tdiff','format','DoubleMat','mattype',1,'timeserieslength',2,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','sealev','format','DoubleMat','mattype',1,'timeserieslength',2,'yts',md.constants.yts)
 			
 		#process requested outputs
@@ -190,5 +191,5 @@
 			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
 			outputs    =outputscopy
-		WriteData(fid,'data',outputs,'enum',SmbRequestedOutputsEnum(),'format','StringArray')
+		WriteData(fid,prefix,'data',outputs,'name','md.smb.requested_outputs','format','StringArray')
 
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/autodiff.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/autodiff.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/autodiff.py	(revision 23670)
@@ -1,7 +1,6 @@
-import numpy
+import numpy as np
 from dependent import dependent
 from independent import independent
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -15,14 +14,15 @@
 	"""
 	def __init__(self,*args):    # {{{
-		self.isautodiff   = False
-		self.dependents   = []
-		self.independents = []
-		self.driver       = 'fos_forward'
-		self.obufsize     = float('NaN')
-		self.lbufsize     = float('NaN')
-		self.cbufsize     = float('NaN')
-		self.tbufsize     = float('NaN')
-		self.gcTriggerMaxSize     = float('NaN')
-		self.gcTriggerRatio     = float('NaN')
+		self.isautodiff				= False
+		self.dependents				= []
+		self.independents			= []
+		self.driver						= 'fos_forward'
+		self.obufsize					= float('NaN')
+		self.lbufsize					= float('NaN')
+		self.cbufsize					= float('NaN')
+		self.tbufsize					= float('NaN')
+		self.gcTriggerMaxSize = float('NaN')
+		self.gcTriggerRatio   = float('NaN')
+		self.tapeAlloc				= float('NaN')
 		if not len(args):
 			self.setdefaultparameters()
@@ -30,7 +30,7 @@
 			raise RuntimeError("constructor not supported")
 	# }}}
+
 	def __repr__(self):    # {{{
 		s ="      automatic differentiation parameters:\n"
-
 		s+="%s\n" % fielddisplay(self,'isautodiff',"indicates if the automatic differentiation is activated")
 		s+="%s\n" % fielddisplay(self,'dependents',"list of dependent variables")
@@ -43,23 +43,25 @@
 		s+="%s\n" % fielddisplay(self,'gcTriggerRatio',"free location block sorting/consolidation triggered if the ratio between allocated and used locations exceeds gcTriggerRatio")
 		s+="%s\n" % fielddisplay(self,'gcTriggerMaxSize',"free location block sorting/consolidation triggered if the allocated locations exceed gcTriggerMaxSize)")
+		s+="%s\n" % fielddisplay(self,'tapeAlloc','Iteration count of a priori memory allocation of the AD tape');
 
 		return s
 	# }}}
+
 	def setdefaultparameters(self):    # {{{
-		
-		self.obufsize     = 524288
-		self.lbufsize     = 524288
-		self.cbufsize     = 524288
-		self.tbufsize     = 524288
-		self.gcTriggerRatio=2.0
-		self.gcTriggerMaxSize=65536
+		self.obufsize					= 524288
+		self.lbufsize					= 524288
+		self.cbufsize					= 524288
+		self.tbufsize					= 524288
+		self.gcTriggerRatio		=	2.0
+		self.gcTriggerMaxSize	=	65536
+		self.tapeAlloc				= 15000000;
 		return self
 	# }}}
+
 	def checkconsistency(self,md,solution,analyses):    # {{{
-
-		#Early return 
+		#Early return
 		if not self.isautodiff:
-			return md 
-		
+			return md
+
 		md = checkfield(md,'fieldname','autodiff.obufsize','>=',524288)
 		md = checkfield(md,'fieldname','autodiff.lbufsize','>=',524288)
@@ -67,10 +69,11 @@
 		md = checkfield(md,'fieldname','autodiff.tbufsize','>=',524288)
 		md = checkfield(md,'fieldname','autodiff.gcTriggerRatio','>=',2.0)
-		md = checkfield(md,'fieldname','autodiff.gcTriggerMaxSize','>=',2000000)
+		md = checkfield(md,'fieldname','autodiff.gcTriggerMaxSize','>=',65536)
+		md = checkfield(md,'fieldname','autodiff.tapeAlloc','>=',0);
 
 		#Driver value:
 		md = checkfield(md,'fieldname','autodiff.driver','values',['fos_forward','fov_forward','fov_forward_all','fos_reverse','fov_reverse','fov_reverse_all'])
 
-		#go through our dependents and independents and check consistency: 
+		#go through our dependents and independents and check consistency:
 		for dep in self.dependents:
 			dep.checkconsistency(md,solution,analyses)
@@ -80,54 +83,56 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'object',self,'fieldname','isautodiff','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','driver','format','String')
+
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'object',self,'fieldname','isautodiff','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','driver','format','String')
 
 		#early return
 		if not self.isautodiff:
-			WriteData(fid,'data',False,'enum',AutodiffMassFluxSegmentsPresentEnum(),'format','Boolean')
-			WriteData(fid,'data',False,'enum',AutodiffKeepEnum(),'format','Boolean')
+			WriteData(fid,prefix,'data',False,'name','md.autodiff.mass_flux_segments_present','format','Boolean')
+			WriteData(fid,prefix,'data',False,'name','md.autodiff.keep','format','Boolean')
 			return
-			
+
 		#buffer sizes {{{
-		WriteData(fid,'object',self,'fieldname','obufsize','format','Double');
-		WriteData(fid,'object',self,'fieldname','lbufsize','format','Double');
-		WriteData(fid,'object',self,'fieldname','cbufsize','format','Double');
-		WriteData(fid,'object',self,'fieldname','tbufsize','format','Double');
-		WriteData(fid,'object',self,'fieldname','gcTriggerRatio','format','Double');
-		WriteData(fid,'object',self,'fieldname','gcTriggerMaxSize','format','Double');
+		WriteData(fid,prefix,'object',self,'fieldname','obufsize','format','Double');
+		WriteData(fid,prefix,'object',self,'fieldname','lbufsize','format','Double');
+		WriteData(fid,prefix,'object',self,'fieldname','cbufsize','format','Double');
+		WriteData(fid,prefix,'object',self,'fieldname','tbufsize','format','Double');
+		WriteData(fid,prefix,'object',self,'fieldname','gcTriggerRatio','format','Double');
+		WriteData(fid,prefix,'object',self,'fieldname','gcTriggerMaxSize','format','Double');
+		WriteData(fid,prefix,'object',self,'fieldname','tapeAlloc','format','Integer');
 		#}}}
 		#process dependent variables {{{
 		num_dependent_objects=len(self.dependents)
-		WriteData(fid,'data',num_dependent_objects,'enum',AutodiffNumDependentObjectsEnum(),'format','Integer')
+		WriteData(fid,prefix,'data',num_dependent_objects,'name','md.autodiff.num_dependent_objects','format','Integer')
 
 		if num_dependent_objects:
 			names=[]
-			types=numpy.zeros(num_dependent_objects)
-			indices=numpy.zeros(num_dependent_objects)
+			types=np.zeros(num_dependent_objects)
+			indices=np.zeros(num_dependent_objects)
 
 			for i,dep in enumerate(self.dependents):
-				names[i]=dep.name
+				names.append(dep.name)
 				types[i]=dep.typetoscalar()
 				indices[i]=dep.index
 
-			WriteData(fid,'data',names,'enum',AutodiffDependentObjectNamesEnum(),'format','StringArray')
-			WriteData(fid,'data',types,'enum',AutodiffDependentObjectTypesEnum(),'format','IntMat','mattype',3)
-			WriteData(fid,'data',indices,'enum',AutodiffDependentObjectIndicesEnum(),'format','IntMat','mattype',3)
+			WriteData(fid,prefix,'data',names,'name','md.autodiff.dependent_object_names','format','StringArray')
+			WriteData(fid,prefix,'data',types,'name','md.autodiff.dependent_object_types','format','IntMat','mattype',3)
+			WriteData(fid,prefix,'data',indices,'name','md.autodiff.dependent_object_indices','format','IntMat','mattype',3)
 		#}}}
 		#process independent variables {{{
 		num_independent_objects=len(self.independents)
-		WriteData(fid,'data',num_independent_objects,'enum',AutodiffNumIndependentObjectsEnum(),'format','Integer')
+		WriteData(fid,prefix,'data',num_independent_objects,'name','md.autodiff.num_independent_objects','format','Integer')
 
 		if num_independent_objects:
-			names=numpy.zeros(num_independent_objects)
-			types=numpy.zeros(num_independent_objects)
+			names=[None] * num_independent_objects
+			types=np.zeros(num_independent_objects)
 
 			for i,indep in enumerate(self.independents):
-				names[i]=StringToEnum(indep.name)[0]
+				names[i]=indep.name
 				types[i]=indep.typetoscalar()
 
-			WriteData(fid,'data',names,'enum',AutodiffIndependentObjectNamesEnum(),'format','IntMat','mattype',3)
-			WriteData(fid,'data',types,'enum',AutodiffIndependentObjectTypesEnum(),'format','IntMat','mattype',3)
+			WriteData(fid,prefix,'data',names,'name','md.autodiff.independent_object_names','format','StringArray')
+			WriteData(fid,prefix,'data',types,'name','md.autodiff.independent_object_types','format','IntMat','mattype',3)
 		#}}}
 		#if driver is fos_forward, build index:  {{{
@@ -136,5 +141,5 @@
 
 			for indep in self.independents:
-				if not numpy.isnan(indep.fos_forward_index):
+				if not np.isnan(indep.fos_forward_index):
 					index+=indep.fos_forward_index
 					break
@@ -146,5 +151,5 @@
 
 			index-=1    #get c-index numbering going
-			WriteData(fid,'data',index,'enum',AutodiffFosForwardIndexEnum(),'format','Integer')
+			WriteData(fid,prefix,'data',index,'name','md.autodiff.fos_forward_index','format','Integer')
 		#}}}
 		#if driver is fos_reverse, build index:  {{{
@@ -153,5 +158,5 @@
 
 			for dep in self.dependents:
-				if not numpy.isnan(dep.fos_reverse_index):
+				if not np.isnan(dep.fos_reverse_index):
 					index+=dep.fos_reverse_index
 					break
@@ -163,5 +168,5 @@
 
 			index-=1    #get c-index numbering going
-			WriteData(fid,'data',index,'enum',AutodiffFosReverseIndexEnum(),'format','Integer')
+			WriteData(fid,prefix,'data',index,'name','md.autodiff.fos_reverse_index','format','Integer')
 		#}}}
 		#if driver is fov_forward, build indices:  {{{
@@ -180,5 +185,5 @@
 
 			indices-=1    #get c-indices numbering going
-			WriteData(fid,'data',indices,'enum',AutodiffFovForwardIndicesEnum(),'format','IntMat','mattype',3)
+			WriteData(fid,prefix,'data',indices,'name','md.autodiff.fov_forward_indices','format','IntMat','mattype',3)
 		#}}}
 		#deal with mass fluxes:  {{{
@@ -186,22 +191,22 @@
 
 		if mass_flux_segments:
-			WriteData(fid,'data',mass_flux_segments,'enum',MassFluxSegmentsEnum(),'format','MatArray')
+			WriteData(fid,prefix,'data',mass_flux_segments,'name','md.autodiff.mass_flux_segments','format','MatArray')
 			flag=True
 		else:
 			flag=False
-		WriteData(fid,'data',flag,'enum',AutodiffMassFluxSegmentsPresentEnum(),'format','Boolean')
+		WriteData(fid,prefix,'data',flag,'name','md.autodiff.mass_flux_segments_present','format','Boolean')
 		#}}}
 		#deal with trace keep on: {{{
 		keep=False
 
-		#From ADOLC userdoc: 
-		# The optional integer argument keep of trace on determines whether the numerical values of all active variables are 
-		# recorded in a buffered temporary array or file called the taylor stack. This option takes effect if keep = 1 and 
-		# prepares the scene for an immediately following gradient evaluation by a call to a routine implementing the reverse 
-		# mode as described in the Section 4 and Section 5. 
+		#From ADOLC userdoc:
+		# The optional integer argument keep of trace on determines whether the numerical values of all active variables are
+		# recorded in a buffered temporary array or file called the taylor stack. This option takes effect if keep = 1 and
+		# prepares the scene for an immediately following gradient evaluation by a call to a routine implementing the reverse
+		# mode as described in the Section 4 and Section 5.
 		#
 
 		if len(self.driver)<=3:
-			keep=False    #there is no "_reverse" string within the driver string: 
+			keep=False    #there is no "_reverse" string within the driver string:
 		else:
 			if strncmpi(self.driver[3:],'_reverse',8):
@@ -209,5 +214,5 @@
 			else:
 				keep=False
-		WriteData(fid,'data',keep,'enum',AutodiffKeepEnum(),'format','Boolean')
+		WriteData(fid,prefix,'data',keep,'name','md.autodiff.keep','format','Boolean')
 		#}}}
 
Index: /issm/trunk-jpl/src/py3/classes/balancethickness.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/balancethickness.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/balancethickness.py	(revision 23670)
@@ -1,4 +1,3 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -16,4 +15,8 @@
 		self.thickening_rate   = float('NaN')
 		self.stabilization     = 0
+		
+		self.omega	       = float('NaN')
+		self.slopex	       = float('NaN')
+		self.slopey	       = float('NaN')
 
 		#set defaults
@@ -39,5 +42,5 @@
 	def checkconsistency(self,md,solution,analyses):    # {{{
 		#Early return
-		if not solution==BalancethicknessSolutionEnum():
+		if not solution=='BalancethicknessSolution':
 			return md
 
@@ -45,13 +48,16 @@
 		md = checkfield(md,'fieldname','balancethickness.thickening_rate','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 		md = checkfield(md,'fieldname','balancethickness.stabilization','size',[1],'values',[0,1,2,3])
-
+		#md = checkfield(md,'fieldname','balancethickness.omega','size', [md.mesh.numberofvertices],'NaN',1,'Inf',1,'>=',0);
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.0*24.0*3600.0
+		yts=md.constants.yts
 
-		WriteData(fid,'object',self,'fieldname','spcthickness','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'fieldname','thickening_rate','format','DoubleMat','mattype',1,'scale',1./yts)
-		WriteData(fid,'object',self,'fieldname','stabilization','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','spcthickness','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','thickening_rate','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'fieldname','stabilization','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','slopex','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','slopey','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','omega','format','DoubleMat','mattype',1)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/bamggeom.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/bamggeom.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/bamggeom.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 
 class bamggeom(object):
@@ -10,12 +10,12 @@
 
 	def __init__(self,*args):    # {{{
-		self.Vertices=numpy.empty((0,3))
-		self.Edges=numpy.empty((0,3))
-		self.TangentAtEdges=numpy.empty((0,4))
-		self.Corners=numpy.empty((0,1))
-		self.RequiredVertices=numpy.empty((0,1))
-		self.RequiredEdges=numpy.empty((0,1))
-		self.CrackedEdges=numpy.empty((0,0))
-		self.SubDomains=numpy.empty((0,4))
+		self.Vertices=np.empty((0,3))
+		self.Edges=np.empty((0,3))
+		self.TangentAtEdges=np.empty((0,4))
+		self.Corners=np.empty((0,1))
+		self.RequiredVertices=np.empty((0,1))
+		self.RequiredEdges=np.empty((0,1))
+		self.CrackedEdges=np.empty((0,0))
+		self.SubDomains=np.empty((0,4))
 
 		if not len(args):
@@ -25,5 +25,5 @@
 		elif len(args) == 1:
 			object=args[0]
-			for field in list(object.keys()):
+			for field in object.keys():
 				if field in vars(self):
 					setattr(self,field,object[field])
Index: /issm/trunk-jpl/src/py3/classes/bamgmesh.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/bamgmesh.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/bamgmesh.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 
 class bamgmesh(object):
@@ -10,20 +10,19 @@
 
 	def __init__(self,*args):    # {{{
-		self.Vertices=numpy.empty((0,3))
-		self.Edges=numpy.empty((0,3))
-		self.Triangles=numpy.empty((0,0))
-		self.Quadrilaterals=numpy.empty((0,0))
-		self.IssmEdges=numpy.empty((0,0))
-		self.IssmSegments=numpy.empty((0,0))
-		self.VerticesOnGeomVertex=numpy.empty((0,0))
-		self.VerticesOnGeomEdge=numpy.empty((0,0))
-		self.EdgesOnGeomEdge=numpy.empty((0,0))
-		self.SubDomains=numpy.empty((0,4))
-		self.SubDomainsFromGeom=numpy.empty((0,0))
-		self.ElementConnectivity=numpy.empty((0,0))
-		self.NodalConnectivity=numpy.empty((0,0))
-		self.NodalElementConnectivity=numpy.empty((0,0))
-		self.CrackedVertices=numpy.empty((0,0))
-		self.CrackedEdges=numpy.empty((0,0))
+		self.Vertices=np.empty((0,3))
+		self.Edges=np.empty((0,3))
+		self.Triangles=np.empty((0,0))
+		self.IssmEdges=np.empty((0,0))
+		self.IssmSegments=np.empty((0,0))
+		self.VerticesOnGeomVertex=np.empty((0,0))
+		self.VerticesOnGeomEdge=np.empty((0,0))
+		self.EdgesOnGeomEdge=np.empty((0,0))
+		self.SubDomains=np.empty((0,4))
+		self.SubDomainsFromGeom=np.empty((0,0))
+		self.ElementConnectivity=np.empty((0,0))
+		self.NodalConnectivity=np.empty((0,0))
+		self.NodalElementConnectivity=np.empty((0,0))
+		self.CrackedVertices=np.empty((0,0))
+		self.CrackedEdges=np.empty((0,0))
 
 		if not len(args):
@@ -33,5 +32,5 @@
 		elif len(args) == 1:
 			object=args[0]
-			for field in list(object.keys()):
+			for field in object.keys():
 				if field in vars(self):
 					setattr(self,field,object[field])
@@ -45,5 +44,4 @@
 		s+="    Edges: %s\n" % str(self.Edges)
 		s+="    Triangles: %s\n" % str(self.Triangles)
-		s+="    Quadrilaterals: %s\n" % str(self.Quadrilaterals)
 		s+="    IssmEdges: %s\n" % str(self.IssmEdges)
 		s+="    IssmSegments: %s\n" % str(self.IssmSegments)
Index: /issm/trunk-jpl/src/py3/classes/basalforcings.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/basalforcings.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/basalforcings.py	(revision 23670)
@@ -1,8 +1,7 @@
 from fielddisplay import fielddisplay
 from project3d import project3d
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
-import numpy
+import numpy as np
 
 class basalforcings(object):
@@ -39,11 +38,14 @@
 	def initialize(self,md): # {{{
 
-		if numpy.all(numpy.isnan(self.groundedice_melting_rate)):
-			self.groundedice_melting_rate=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.groundedice_melting_rate)):
+			self.groundedice_melting_rate=np.zeros((md.mesh.numberofvertices))
 			print("      no basalforcings.groundedice_melting_rate specified: values set as zero")
 
-		if numpy.all(numpy.isnan(self.floatingice_melting_rate)):
-			self.floatingice_melting_rate=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.floatingice_melting_rate)):
+			self.floatingice_melting_rate=np.zeros((md.mesh.numberofvertices))
 			print("      no basalforcings.floatingice_melting_rate specified: values set as zero")
+		#if np.all(np.isnan(self.geothermalflux)):
+			#self.geothermalflux=np.zeros((md.mesh.numberofvertices))
+			#print "      no basalforcings.geothermalflux specified: values set as zero"
 
 		return self
@@ -54,13 +56,13 @@
 	def checkconsistency(self,md,solution,analyses):    # {{{
 
-		if MasstransportAnalysisEnum() in analyses and not (solution==TransientSolutionEnum() and not md.transient.ismasstransport):
+		if 'MasstransportAnalysis' in analyses and not (solution=='TransientSolution' and not md.transient.ismasstransport):
 			md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1)
 			md = checkfield(md,'fieldname','basalforcings.floatingice_melting_rate','NaN',1,'Inf',1,'timeseries',1)
 
-		if BalancethicknessAnalysisEnum() in analyses:
+		if 'BalancethicknessAnalysis' in analyses:
 			md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 			md = checkfield(md,'fieldname','basalforcings.floatingice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 
-		if ThermalAnalysisEnum() in analyses and not (solution==TransientSolutionEnum() and not md.transient.isthermal):
+		if 'ThermalAnalysis' in analyses and not (solution=='TransientSolution' and not md.transient.isthermal):
 			md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1)
 			md = checkfield(md,'fieldname','basalforcings.floatingice_melting_rate','NaN',1,'Inf',1,'timeseries',1)
@@ -69,11 +71,11 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.0*24.0*3600.0
+		yts=md.constants.yts
 
-		WriteData(fid,'enum',BasalforcingsEnum(),'data',FloatingMeltRateEnum(),'format','Integer');
-		WriteData(fid,'object',self,'fieldname','groundedice_melting_rate','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'fieldname','floatingice_melting_rate','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'fieldname','geothermalflux','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
+		WriteData(fid,prefix,'name','md.basalforcings.model','data',1,'format','Integer');
+		WriteData(fid,prefix,'object',self,'fieldname','groundedice_melting_rate','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'fieldname','floatingice_melting_rate','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'fieldname','geothermalflux','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/calving.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/calving.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/calving.py	(revision 23670)
@@ -1,6 +1,4 @@
 from fielddisplay import fielddisplay
 from project3d import project3d
-from EnumDefinitions import *
-from StringToEnum import StringToEnum
 from checkfield import checkfield
 from WriteData import WriteData
@@ -16,6 +14,4 @@
 	def __init__(self): # {{{
 
-		self.stabilization = 0
-		self.spclevelset   = float('NaN')
 		self.calvingrate   = float('NaN')
 		self.meltingrate   = float('NaN')
@@ -27,21 +23,13 @@
 	def __repr__(self): # {{{
 		string='   Calving parameters:'
-		string="%s\n%s"%(string,fielddisplay(self,'stabilization','0: no, 1: artificial_diffusivity, 2: streamline upwinding'))
-		string="%s\n%s"%(string,fielddisplay(self,'spclevelset','levelset constraints (NaN means no constraint)'))
 		string="%s\n%s"%(string,fielddisplay(self,'calvingrate','calving rate at given location [m/a]'))
-		string="%s\n%s"%(string,fielddisplay(self,'meltingrate','melting rate at given location [m/a]'))
 
 		return string
 		#}}}
 	def extrude(self,md): # {{{
-		self.spclevelset=project3d(md,'vector',self.spclevelset,'type','node')
 		self.calvingrate=project3d(md,'vector',self.calvingrate,'type','node')
-		self.meltingrate=project3d(md,'vector',self.meltingrate,'type','node')
 		return self
 	#}}}
 	def setdefaultparameters(self): # {{{
-
-		#stabilization = 2 by default
-		self.stabilization = 2
 
 		return self
@@ -50,22 +38,16 @@
 
 		#Early return
-		if (solution!=TransientSolutionEnum()) or (not md.transient.iscalving):
+		if (solution!='TransientSolution') or (not md.transient.ismovingfront):
 			return md
 
-		md = checkfield(md,'fieldname','calving.spclevelset','Inf',1,'timeseries',1)
-		md = checkfield(md,'fieldname','calving.stabilization','values',[0,1,2]);
 		md = checkfield(md,'fieldname','calving.calvingrate','>=',0,'timeseries',1,'NaN',1,'Inf',1);
-		md = checkfield(md,'fieldname','calving.meltingrate','>=',0,'timeseries',1,'NaN',1,'Inf',1);
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.*24.*3600.
+		yts=md.constants.yts
 
-		WriteData(fid,'enum',CalvingLawEnum(),'data',DefaultCalvingEnum(),'format','Integer');
-		WriteData(fid,'enum',LevelsetStabilizationEnum(),'data',self.stabilization,'format','Integer');
-		WriteData(fid,'enum',SpclevelsetEnum(),'data',self.spclevelset,'format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1);
-		WriteData(fid,'object',self,'fieldname','calvingrate','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'scale',1./yts)
-		WriteData(fid,'object',self,'fieldname','meltingrate','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'scale',1./yts)
+		WriteData(fid,prefix,'name','md.calving.law','data',1,'format','Integer');
+		WriteData(fid,prefix,'object',self,'fieldname','calvingrate','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts,'scale',1./yts)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/calvinglevermann.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/calvinglevermann.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/calvinglevermann.py	(revision 23670)
@@ -1,5 +1,3 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
-from StringToEnum import StringToEnum
 from checkfield import checkfield
 from WriteData import WriteData
@@ -15,6 +13,4 @@
 	def __init__(self): # {{{
 
-		self.stabilization = 0
-		self.spclevelset   = float('NaN')
 		self.coeff         = float('NaN')
 		self.meltingrate   = float('NaN')
@@ -26,21 +22,13 @@
 	def __repr__(self): # {{{
 		string='   Calving Levermann parameters:'
-		string="%s\n%s"%(string,fielddisplay(self,'spclevelset','levelset constraints (NaN means no constraint)'))
-		string="%s\n%s"%(string,fielddisplay(self,'stabilization','0: no, 1: artificial_diffusivity, 2: streamline upwinding'))
 		string="%s\n%s"%(string,fielddisplay(self,'coeff','proportionality coefficient in Levermann model'))
-		string="%s\n%s"%(string,fielddisplay(self,'meltingrate','melting rate at given location [m/a]'))
 
 		return string
 		#}}}
 	def extrude(self,md): # {{{
-		self.spclevelset=project3d(md,'vector',self.spclevelset,'type','node')
 		self.coeff=project3d(md,'vector',self.coeff,'type','node')
-		self.meltingrate=project3d(md,'vector',self.meltingrate,'type','node')
 		return self
 	#}}}
 	def setdefaultparameters(self): # {{{
-
-		#stabilization = 2 by default
-		self.stabilization = 2
 
 		#Proportionality coefficient in Levermann model
@@ -50,19 +38,13 @@
 
 		#Early return
-		if (solution!=TransientSolutionEnum()) or (not md.transient.iscalving):
+		if (solution!='TransientSolution') or (not md.transient.ismovingfront):
 			return md
 
-		md = checkfield(md,'fieldname','calving.spclevelset','Inf',1,'timeseries',1)
-		md = checkfield(md,'fieldname','calving.stabilization','values',[0,1,2]);
 		md = checkfield(md,'fieldname','calving.coeff','size',[md.mesh.numberofvertices],'>',0)
-		md = checkfield(md,'fieldname','calving.meltingrate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices],'>=',0)
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		yts=365.*24.*3600.
-		WriteData(fid,'enum',CalvingLawEnum(),'data',CalvingLevermannEnum(),'format','Integer');
-		WriteData(fid,'enum',LevelsetStabilizationEnum(),'data',self.stabilization,'format','Integer');
-		WriteData(fid,'enum',SpclevelsetEnum(),'data',self.spclevelset,'format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1);
-		WriteData(fid,'enum',CalvinglevermannCoeffEnum(),'data',self.coeff,'format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'fieldname','meltingrate','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'scale',1./yts)
+	def marshall(self,prefix,md,fid):    # {{{
+		yts=md.constants.yts
+		WriteData(fid,prefix,'name','md.calving.law','data',3,'format','Integer');
+		WriteData(fid,prefix,'object',self,'fieldname','coeff','format','DoubleMat','mattype',1)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/clusters/generic.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/clusters/generic.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/clusters/generic.py	(revision 23670)
@@ -4,5 +4,4 @@
 import subprocess
 from IssmConfig import IssmConfig
-from EnumToString import EnumToString
 from issmdir import issmdir
 from pairoptions import pairoptions
@@ -18,8 +17,8 @@
 	   Usage:
 	      cluster=generic('name','astrid','np',3);
-	      cluster=generic('name',oshostname(),'np',3,'login','username');
+	      cluster=generic('name',gethostname(),'np',3,'login','username');
 	"""
 
-	def __init__(self,**kwargs):    # {{{
+	def __init__(self,*args):    # {{{
 
 		self.name=''
@@ -28,5 +27,5 @@
 		self.port=0
 		self.interactive=1
-		self.codepath=issmdir()+'/bin'
+		self.codepath=IssmConfig('ISSM_PREFIX')[0]+'/bin'
 		self.executionpath=issmdir()+'/execution'
 		self.valgrind=issmdir()+'/externalpackages/valgrind/install/bin/valgrind'
@@ -35,5 +34,5 @@
 
 		#use provided options to change fields
-		options=pairoptions(**kwargs)
+		options=pairoptions(*args)
 
 		#get name
@@ -69,12 +68,14 @@
 		return md
 	# }}}
-	def BuildQueueScript(self,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota):    # {{{
+	def BuildQueueScript(self,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling):    # {{{
 
 		executable='issm.exe';
 		if isdakota:
-			version=IssmConfig('_DAKOTA_VERSION_')[0:2]
-			version=float(version)
+			version=IssmConfig('_DAKOTA_VERSION_')
+			version=float(version[0])
 			if version>=6:
 				executable='issm_dakota.exe'
+		if isoceancoupling:
+			executable='issm_ocean.exe'
 
 		#write queuing script 
@@ -86,12 +87,12 @@
 				if self.interactive: 
 					if IssmConfig('_HAVE_MPI_')[0]:
-						fid.write('mpiexec -np %i %s/%s %s %s/%s %s ' % (self.np,self.codepath,executable,EnumToString(solution)[0],self.executionpath,dirname,modelname))
+						fid.write('mpiexec -np %i %s/%s %s %s/%s %s ' % (self.np,self.codepath,executable,solution,self.executionpath,dirname,modelname))
 					else:
-						fid.write('%s/%s %s %s/%s %s ' % (self.codepath,executable,EnumToString(solution)[0],self.executionpath,dirname,modelname))
+						fid.write('%s/%s %s %s/%s %s ' % (self.codepath,executable,solution,self.executionpath,dirname,modelname))
 				else:
 					if IssmConfig('_HAVE_MPI_')[0]:
-						fid.write('mpiexec -np %i %s/%s %s %s/%s %s 2> %s.errlog >%s.outlog ' % (self.np,self.codepath,executable,EnumToString(solution)[0],self.executionpath,dirname,modelname,modelname,modelname))
+						fid.write('mpiexec -np %i %s/%s %s %s/%s %s 2> %s.errlog >%s.outlog ' % (self.np,self.codepath,executable,solution,self.executionpath,dirname,modelname,modelname,modelname))
 					else:
-						fid.write('%s/%s %s %s/%s %s 2> %s.errlog >%s.outlog ' % (self.codepath,executable,EnumToString(solution)[0],self.executionpath,dirname,modelname,modelname,modelname))
+						fid.write('%s/%s %s %s/%s %s 2> %s.errlog >%s.outlog ' % (self.codepath,executable,solution,self.executionpath,dirname,modelname,modelname,modelname))
 			elif isgprof:
 				fid.write('\n gprof %s/%s gmon.out > %s.performance' % (self.codepath,executable,modelname))
@@ -101,8 +102,8 @@
 				if IssmConfig('_HAVE_MPI_')[0]:
 					fid.write('mpiexec -np %i %s --leak-check=full --suppressions=%s %s/%s %s %s/%s %s 2> %s.errlog >%s.outlog ' % \
-							(self.np,self.valgrind,self.valgrindsup,self.codepath,executable,EnumToString(solution)[0],self.executionpath,dirname,modelname,modelname,modelname))
+							(self.np,self.valgrind,self.valgrindsup,self.codepath,executable,solution,self.executionpath,dirname,modelname,modelname,modelname))
 				else:	
 					fid.write('%s --leak-check=full --suppressions=%s %s/%s %s %s/%s %s 2> %s.errlog >%s.outlog ' % \
-							(self.valgrind,self.valgrindsup,self.codepath,executable,EnumToString(solution)[0],self.executionpath,dirname,modelname,modelname,modelname))
+							(self.valgrind,self.valgrindsup,self.codepath,executable,solution,self.executionpath,dirname,modelname,modelname,modelname))
 
 			if not io_gather:    #concatenate the output files:
@@ -115,8 +116,8 @@
 			fid.write('@echo off\n')
 			if self.interactive:
-				fid.write('"%s/%s" %s "%s/%s" %s ' % (self.codepath,executable,EnumToString(solution)[0],self.executionpath,dirname,modelname))
+				fid.write('"%s/%s" %s "%s/%s" %s ' % (self.codepath,executable,solution,self.executionpath,dirname,modelname))
 			else:
 				fid.write('"%s/%s" %s "%s/%s" %s 2> %s.errlog >%s.outlog' % \
-					(self.codepath,executable,EnumToString(solution)[0],self.executionpath,dirname,modelname,modelname,modelname))
+					(self.codepath,executable,solution,self.executionpath,dirname,modelname,modelname,modelname))
 			fid.close()
 
@@ -156,8 +157,8 @@
 			fid.write('@echo off\n')
 			if self.interactive:
-				fid.write('"%s/issm.exe" %s "%s/%s" %s ' % (self.codepath,EnumToString(solution)[0],self.executionpath,modelname,modelname))
+				fid.write('"%s/issm.exe" %s "%s/%s" %s ' % (self.codepath,solution,self.executionpath,modelname,modelname))
 			else:
 				fid.write('"%s/issm.exe" %s "%s/%s" %s 2> %s.errlog >%s.outlog' % \
-					(self.codepath,EnumToString(solution)[0],self.executionpath,modelname,modelname,modelname,modelname))
+					(self.codepath,solution,self.executionpath,modelname,modelname,modelname,modelname))
 			fid.close()
 
@@ -183,5 +184,5 @@
 
 	# }}}
-	def LaunchQueueJob(self,modelname,dirname,filelist,restart):    # {{{
+	def LaunchQueueJob(self,modelname,dirname,filelist,restart,batch):    # {{{
 
 		print('launching solution sequence on remote cluster')
@@ -189,6 +190,10 @@
 			launchcommand='cd %s && cd %s chmod 777 %s.queue && ./%s.queue' % (self.executionpath,dirname,modelname,modelname)
 		else:
-			launchcommand='cd %s && rm -rf ./%s && mkdir %s && cd %s && mv ../%s.tar.gz ./ && tar -zxf %s.tar.gz  && chmod 777 %s.queue && ./%s.queue' % \
-				(self.executionpath,dirname,dirname,dirname,dirname,dirname,modelname,modelname)
+			if batch:
+				launchcommand='cd %s && rm -rf ./%s && mkdir %s && cd %s && mv ../%s.tar.gz ./ && tar -zxf %s.tar.gz' % \
+						(self.executionpath,dirname,dirname,dirname,dirname,dirname)
+			else:
+				launchcommand='cd %s && rm -rf ./%s && mkdir %s && cd %s && mv ../%s.tar.gz ./ && tar -zxf %s.tar.gz  && chmod 777 %s.queue && ./%s.queue' % \
+					(self.executionpath,dirname,dirname,dirname,dirname,dirname,modelname,modelname)
 		issmssh(self.name,self.login,self.port,launchcommand)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/clusters/pfe.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/clusters/pfe.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/clusters/pfe.py	(revision 23670)
@@ -4,5 +4,4 @@
 import subprocess
 from fielddisplay import fielddisplay
-from EnumToString import EnumToString
 from pairoptions import pairoptions
 from issmssh import issmssh
@@ -25,5 +24,5 @@
 	"""
 
-	def __init__(self,**kwargs):
+	def __init__(self,*args):
 		# {{{
 
@@ -45,5 +44,5 @@
 
 		#use provided options to change fields
-		options=pairoptions(**kwargs)
+		options=pairoptions(*args)
 
 		#initialize cluster using user settings if provided
@@ -134,5 +133,5 @@
 		return self
 	# }}}
-	def BuildQueueScript(self,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota):
+	def BuildQueueScript(self,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling):
 		# {{{
 
@@ -143,4 +142,6 @@
 			if version>=6:
 				executable='issm_dakota.exe'
+		if isoceancoupling:
+			executable='issm_ocean.exe'
 
 		#write queuing script 
@@ -162,5 +163,5 @@
 		fid.write('source $ISSM_DIR/etc/environment.sh\n')
 		fid.write('cd %s/%s/\n\n' % (self.executionpath,dirname))
-		fid.write('mpiexec -np %i %s/%s %s %s/%s %s\n' % (self.nprocs(),self.codepath,executable,str(EnumToString(solution)[0]),self.executionpath,dirname,modelname))
+		fid.write('mpiexec -np %i %s/%s %s %s/%s %s\n' % (self.nprocs(),self.codepath,executable,str(solution),self.executionpath,dirname,modelname))
 		
 		fid.close()
@@ -180,5 +181,5 @@
 
 		# }}}
-	def LaunchQueueJob(self,modelname,dirname,filelist,restart):
+	def LaunchQueueJob(self,modelname,dirname,filelist,restart,batch):
 			# {{{
 
Index: /issm/trunk-jpl/src/py3/classes/constants.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/constants.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/constants.py	(revision 23670)
@@ -1,4 +1,3 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -13,7 +12,8 @@
 
 	def __init__(self): # {{{
-		self.g                    = 0
-		self.yts                  = 0
-		self.referencetemperature = 0
+		self.g                    = 0.
+		self.omega                = 0.
+		self.yts                  = 0.
+		self.referencetemperature = 0.
 		
 		#set defaults
@@ -25,4 +25,5 @@
 
 		string="%s\n%s"%(string,fielddisplay(self,"g","gravitational acceleration [m/s^2]"))
+		string="%s\n%s"%(string,fielddisplay(self,"omega","angular velocity of Earth [rad/s]"))
 		string="%s\n%s"%(string,fielddisplay(self,"yts","number of seconds in a year [s/yr]"))
 		string="%s\n%s"%(string,fielddisplay(self,"referencetemperature","reference temperature used in the enthalpy model [K]"))
@@ -35,6 +36,9 @@
 		self.g=9.81
 
+		#Earth's rotation speed 
+		self.omega = 7.292*1e-5;
+
 		#converstion from year to seconds
-		self.yts=365*24*3600
+		self.yts=365.*24.*3600.
 
 		#the reference temperature for enthalpy model (cf Aschwanden)
@@ -45,13 +49,14 @@
 	def checkconsistency(self,md,solution,analyses):    # {{{
 
-		md = checkfield(md,'fieldname','constants.g','>',0,'size',[1])
-		md = checkfield(md,'fieldname','constants.yts','>',0,'size',[1])
-		md = checkfield(md,'fieldname','constants.referencetemperature','size',[1])
+		md = checkfield(md,'fieldname','constants.g','>=',0,'size',[1,1])
+		md = checkfield(md,'fieldname','constants.omega','>=',0,'size',[1,1])
+		md = checkfield(md,'fieldname','constants.yts','>',0,'size',[1,1])
+		md = checkfield(md,'fieldname','constants.referencetemperature','size',[1,1])
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'object',self,'fieldname','g','format','Double')
-		WriteData(fid,'object',self,'fieldname','yts','format','Double')
-		WriteData(fid,'object',self,'fieldname','referencetemperature','format','Double')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'object',self,'fieldname','g','format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','yts','format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','referencetemperature','format','Double')
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/damage.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/damage.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/damage.py	(revision 23670)
@@ -1,9 +1,6 @@
 from fielddisplay import fielddisplay
 from project3d import project3d
-from EnumDefinitions import *
-from StringToEnum import StringToEnum
 from checkfield import checkfield
 from WriteData import WriteData
-import MatlabFuncs as m
 
 class damage(object):
@@ -16,27 +13,26 @@
 
 	def __init__(self,*args):    # {{{
-			
-		#damage: 
-		self.isdamage           = 0.
-		self.D			= float('NaN')
-		self.law		= float('NaN')
-		self.spcdamage		= float('NaN')
-		self.max_damage		= float('NaN')
-		
+		#damage:
+		self.isdamage   = 0.
+		self.D					= float('NaN')
+		self.law				= float('NaN')
+		self.spcdamage	= float('NaN')
+		self.max_damage	= float('NaN')
+
 		#numerical
-		self.stabilization	= float('NaN')
-		self.maxiter		= float('NaN')
-		self.elementinterp      = ''
+		self.stabilization = float('NaN')
+		self.maxiter			 = float('NaN')
+		self.elementinterp = ''
 
-		#general parameters for evolution law: 
-		self.stress_threshold   = float('NaN')
-		self.kappa              = float('NaN')
-		self.c1                 = float('NaN')
-		self.c2                 = float('NaN')
-		self.c3                 = float('NaN')
-		self.c4                 = float('NaN')
-		self.healing		= float('NaN')
-		self.equiv_stress       = float('NaN')
-		self.requested_outputs  = []
+		#general parameters for evolution law:
+		self.stress_threshold  = float('NaN')
+		self.kappa             = float('NaN')
+		self.c1                = float('NaN')
+		self.c2                = float('NaN')
+		self.c3                = float('NaN')
+		self.c4                = float('NaN')
+		self.healing					 = float('NaN')
+		self.equiv_stress      = float('NaN')
+		self.requested_outputs = []
 
 		if not len(args):
@@ -44,9 +40,8 @@
 		else:
 			raise RuntimeError("constructor not supported")
+	# }}}
 
-	# }}}
 	def __repr__(self):    # {{{
 		s ='   Damage:\n'
-		
 		s+="%s\n" % fielddisplay(self,"isdamage","is damage mechanics being used? [0 (default) or 1]")
 		if self.isdamage:
@@ -70,4 +65,5 @@
 		return s
 	# }}}
+
 	def extrude(self,md): # {{{
 		self.D=project3d(md,'vector',self.D,'type','node')
@@ -75,16 +71,15 @@
 		return self
 	#}}}
+
 	def setdefaultparameters(self):    # {{{
+		#damage parameters:
+		self.isdamage		=	0
+		self.D					=	0
+		self.law				=	0
+		self.max_damage	=	1-1e-5 #if damage reaches 1, solve becomes singular, as viscosity becomes nil
 
-		#damage parameters: 
-		self.isdamage=0
-		self.D=0
-		self.law=0
-
-		self.max_damage=1-1e-5 #if damage reaches 1, solve becomes singular, as viscosity becomes nil
-		
 		#Type of stabilization used
 		self.stabilization=4
-			
+
 		#Maximum number of iterations
 		self.maxiter=100
@@ -93,5 +88,5 @@
 		self.elementinterp='P1'
 
-		#damage evolution parameters 
+		#damage evolution parameters
 		self.stress_threshold=1.3e5
 		self.kappa=2.8
@@ -108,6 +103,6 @@
 		return self
 	# }}}
+
 	def defaultoutputs(self,md): # {{{
-		
 		if md.mesh.domaintype().lower()=='2dhorizontal':
 			list = ['DamageDbar']
@@ -115,8 +110,7 @@
 			list = ['DamageD']
 		return list
+	#}}}
 
-	#}}}
 	def checkconsistency(self,md,solution,analyses):    # {{{
-
 		md = checkfield(md,'fieldname','damage.isdamage','numel',[1],'values',[0,1])
 		if self.isdamage:
@@ -139,29 +133,29 @@
 			md = checkfield(md,'fieldname','damage.requested_outputs','stringrow',1)
 		elif self.law != 0:
-			if (solution==DamageEvolutionSolutionEnum):
+			if (solution=='DamageEvolutionSolution'):
 				raise RuntimeError('Invalid evolution law (md.damage.law) for a damage solution')
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
 
-		WriteData(fid,'object',self,'fieldname','isdamage','format','Boolean')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'object',self,'fieldname','isdamage','format','Boolean')
 		if self.isdamage:
-			WriteData(fid,'object',self,'fieldname','D','format','DoubleMat','mattype',1)
-			WriteData(fid,'object',self,'fieldname','law','format','Integer')
-			WriteData(fid,'object',self,'fieldname','spcdamage','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-			WriteData(fid,'object',self,'fieldname','max_damage','format','Double')
-			WriteData(fid,'object',self,'fieldname','stabilization','format','Integer')
-			WriteData(fid,'object',self,'fieldname','maxiter','format','Integer')
-			WriteData(fid,'enum',DamageElementinterpEnum(),'data',StringToEnum(self.elementinterp)[0],'format','Integer')
-			WriteData(fid,'object',self,'fieldname','stress_threshold','format','Double')
-			WriteData(fid,'object',self,'fieldname','kappa','format','Double')
-			WriteData(fid,'object',self,'fieldname','c1','format','Double')
-			WriteData(fid,'object',self,'fieldname','c2','format','Double')
-			WriteData(fid,'object',self,'fieldname','c3','format','Double')
-			WriteData(fid,'object',self,'fieldname','c4','format','Double')
-			WriteData(fid,'object',self,'fieldname','healing','format','Double')
-			WriteData(fid,'object',self,'fieldname','equiv_stress','format','Integer')
-			
+			WriteData(fid,prefix,'object',self,'fieldname','D','format','DoubleMat','mattype',1)
+			WriteData(fid,prefix,'object',self,'fieldname','law','format','Integer')
+			WriteData(fid,prefix,'object',self,'fieldname','spcdamage','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'fieldname','max_damage','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','stabilization','format','Integer')
+			WriteData(fid,prefix,'object',self,'fieldname','maxiter','format','Integer')
+			WriteData(fid,prefix,'name','md.damage.elementinterp','data',self.elementinterp,'format','String')
+			WriteData(fid,prefix,'object',self,'fieldname','stress_threshold','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','kappa','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','c1','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','c2','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','c3','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','c4','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','healing','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','equiv_stress','format','Integer')
+
 		#process requested outputs
 		outputs = self.requested_outputs
@@ -170,4 +164,5 @@
 			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
 			outputs    =outputscopy
-		WriteData(fid,'data',outputs,'enum',DamageEvolutionRequestedOutputsEnum(),'format','StringArray')
+		if self.isdamage:
+			WriteData(fid,prefix,'data',outputs,'name','md.damage.requested_outputs','format','StringArray')
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/debug.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/debug.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/debug.py	(revision 23670)
@@ -30,5 +30,5 @@
 		return self
 	#}}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'object',self,'fieldname','profiling','format','Boolean')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'object',self,'fieldname','profiling','format','Boolean')
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/dependent.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/dependent.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/dependent.py	(revision 23670)
@@ -1,8 +1,7 @@
 import os.path
-import numpy
+import numpy as np
 from pairoptions import pairoptions
 from fielddisplay import fielddisplay
-import MatlabFuncs as m
-from EnumDefinitions import *
+from MatlabFuncs import *
 from MeshProfileIntersection import MeshProfileIntersection
 
@@ -28,5 +27,5 @@
 
 		#use provided options to change fields
-		options=pairoptions(**kwargs)
+		options=pairoptions(*args)
 
 		self.name=options.getfieldvalue('name','')
@@ -44,13 +43,13 @@
 			#process the file and retrieve segments
 			mesh=options.getfieldvalue('mesh')
-			self.segments=MeshProfileIntersection(mesh.elements,mesh.x,mesh.y,self.exp)
+			self.segments=MeshProfileIntersection(mesh.elements,mesh.x,mesh.y,self.exp)[0]
 	# }}}
 	def __repr__(self):    # {{{
 		s ="   dependent variable:\n"
 
-		s+="%s\n" % fielddisplay(self,'name',"variable name (must match corresponding Enum)")
+		s+="%s\n" % fielddisplay(self,'name',"variable name (must match corresponding String)")
 		s+="%s\n" % fielddisplay(self,'type',"type of variable ('vertex' or 'scalar')")
 
-		if not numpy.isnan(self.fos_reverse_index):
+		if not np.isnan(self.fos_reverse_index):
 			s+="%s\n" % fielddisplay(self,'fos_reverse_index',"index for fos_reverse driver of ADOLC")
 		if self.exp:
@@ -71,5 +70,5 @@
 				raise RuntimeError("dependent checkconsistency error: index for segments should be >=0")
 
-		if not numpy.isnan(self.fos_reverse_index):
+		if not np.isnan(self.fos_reverse_index):
 			if not strcmpi(driver,'fos_reverse'):
 				raise TypeError("cannot declare a dependent with a fos_reverse_index when the driver is not fos_reverse!")
Index: /issm/trunk-jpl/src/py3/classes/flowequation.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/flowequation.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/flowequation.py	(revision 23670)
@@ -1,7 +1,6 @@
-import numpy
+import numpy as np
 import copy
 from project3d import project3d
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -17,5 +16,5 @@
 
 	def __init__(self): # {{{
-		
+
 		self.isSIA                          = 0
 		self.isSSA                          = 0
@@ -50,5 +49,5 @@
 		string="%s\n%s"%(string,fielddisplay(self,'isFS',"are the Full-FS (FS) equations used ?"))
 		string="%s\n%s"%(string,fielddisplay(self,'fe_SSA',"Finite Element for SSA: 'P1', 'P1bubble' 'P1bubblecondensed' 'P2'"))
-		string="%s\n%s"%(string,fielddisplay(self,'fe_HO' ,"Finite Element for HO:  'P1' 'P1bubble' 'P1bubblecondensed' 'P1xP2' 'P2xP1' 'P2'"))
+		string="%s\n%s"%(string,fielddisplay(self,'fe_HO' ,"Finite Element for HO:  'P1','P1bubble','P1bubblecondensed','P1xP2','P2xP1','P2','P2bubble','P1xP3','P2xP4'"))
 		string="%s\n%s"%(string,fielddisplay(self,'fe_FS' ,"Finite Element for FS:  'P1P1' (debugging only) 'P1P1GLS' 'MINIcondensed' 'MINI' 'TaylorHood' 'LATaylorHood' 'XTaylorHood'"))
 		string="%s\n%s"%(string,fielddisplay(self,'vertex_equation',"flow equation for each vertex"))
@@ -83,5 +82,5 @@
 
 		#Early return
-		if (StressbalanceAnalysisEnum() not in analyses and StressbalanceSIAAnalysisEnum() not in analyses) or (solution==TransientSolutionEnum() and not md.transient.isstressbalance):
+		if ('StressbalanceAnalysis' not in analyses and 'StressbalanceSIAAnalysis' not in analyses) or (solution=='TransientSolution' and not md.transient.isstressbalance):
 			return md
 
@@ -93,5 +92,5 @@
 		md = checkfield(md,'fieldname','flowequation.fe_SSA','values',['P1','P1bubble','P1bubblecondensed','P2','P2bubble'])
 		md = checkfield(md,'fieldname','flowequation.fe_HO' ,'values',['P1','P1bubble','P1bubblecondensed','P1xP2','P2xP1','P2','P2bubble','P1xP3','P2xP4'])
-		md = checkfield(md,'fieldname','flowequation.fe_FS' ,'values',['P1P1','P1P1GLS','MINIcondensed','MINI','TaylorHood','XTaylorHood','OneLayerP4z','CrouzeixRaviart'])
+		md = checkfield(md,'fieldname','flowequation.fe_FS' ,'values',['P1P1','P1P1GLS','MINIcondensed','MINI','TaylorHood','LATaylorHood','XTaylorHood','OneLayerP4z','CrouzeixRaviart','LACrouzeixRaviart'])
 		md = checkfield(md,'fieldname','flowequation.borderSSA','size',[md.mesh.numberofvertices],'values',[0,1])
 		md = checkfield(md,'fieldname','flowequation.borderHO','size',[md.mesh.numberofvertices],'values',[0,1])
@@ -105,7 +104,10 @@
 			md = checkfield(md,'fieldname','flowequation.vertex_equation','size',[md.mesh.numberofvertices],'values',[1,2])
 			md = checkfield(md,'fieldname','flowequation.element_equation','size',[md.mesh.numberofelements],'values',[1,2])
+		elif m.strcmp(md.mesh.domaintype(),'2Dvertical'):
+			md = checkfield(md,'fieldname','flowequation.vertex_equation','size',[md.mesh.numberofvertices],'values',[2,4,5])
+			md = checkfield(md,'fieldname','flowequation.element_equation','size',[md.mesh.numberofelements],'values',[2,4,5])
 		elif m.strcmp(md.mesh.domaintype(),'3D'):
-			md = checkfield(md,'fieldname','flowequation.vertex_equation','size',[md.mesh.numberofvertices],'values',numpy.arange(0,8+1))
-			md = checkfield(md,'fieldname','flowequation.element_equation','size',[md.mesh.numberofelements],'values',numpy.arange(0,8+1))
+			md = checkfield(md,'fieldname','flowequation.vertex_equation','size',[md.mesh.numberofvertices],'values',np.arange(0,8+1))
+			md = checkfield(md,'fieldname','flowequation.element_equation','size',[md.mesh.numberofelements],'values',np.arange(0,8+1))
 		else:
 			raise RuntimeError('mesh type not supported yet')
@@ -113,50 +115,31 @@
 			md.checkmessage("no element types set for this model")
 
-		if StressbalanceSIAAnalysisEnum() in analyses:
+		if 'StressbalanceSIAAnalysis' in analyses:
 			if any(self.element_equation==1):
-				if numpy.any(numpy.logical_and(self.vertex_equation,md.mask.groundedice_levelset)):
+				if np.any(np.logical_and(self.vertex_equation,md.mask.groundedice_levelset)):
 					print("\n !!! Warning: SIA's model is not consistent on ice shelves !!!\n")
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'object',self,'fieldname','isSIA','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','isSSA','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','isL1L2','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','isHO','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','isFS','format','Boolean')
-		WriteData(fid,'enum',FlowequationFeSSAEnum(),'data',StringToEnum(self.fe_SSA)[0],'format','Integer')
-		WriteData(fid,'enum',FlowequationFeHOEnum() ,'data',StringToEnum(self.fe_HO)[0] ,'format','Integer')
-		WriteData(fid,'enum',FlowequationFeFSEnum() ,'data',StringToEnum(self.fe_FS)[0] ,'format','Integer')
-		WriteData(fid,'enum',AugmentedLagrangianREnum(),'data',self.augmented_lagrangian_r ,'format','Double')
-		WriteData(fid,'enum',AugmentedLagrangianRhopEnum(),'data',self.augmented_lagrangian_rhop ,'format','Double')
-		WriteData(fid,'enum',AugmentedLagrangianRlambdaEnum(),'data',self.augmented_lagrangian_rlambda ,'format','Double')
-		WriteData(fid,'enum',AugmentedLagrangianRholambdaEnum(),'data',self.augmented_lagrangian_rholambda ,'format','Double')
-		WriteData(fid,'enum',AugmentedLagrangianThetaEnum() ,'data',self.XTH_theta ,'format','Double')
-		WriteData(fid,'object',self,'fieldname','borderSSA','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'fieldname','borderHO','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'fieldname','borderFS','format','DoubleMat','mattype',1)
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'object',self,'fieldname','isSIA','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','isSSA','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','isL1L2','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','isHO','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','isFS','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','fe_SSA','data',self.fe_SSA,'format','String')
+		WriteData(fid,prefix,'object',self,'fieldname','fe_HO','data',self.fe_HO,'format','String')
+		WriteData(fid,prefix,'object',self,'fieldname','fe_FS','data',self.fe_FS ,'format','String')
+		WriteData(fid,prefix,'object',self,'fieldname','augmented_lagrangian_r','format','Double');
+		WriteData(fid,prefix,'object',self,'fieldname','augmented_lagrangian_rhop','format','Double');
+		WriteData(fid,prefix,'object',self,'fieldname','augmented_lagrangian_rlambda','format','Double');
+		WriteData(fid,prefix,'object',self,'fieldname','augmented_lagrangian_rholambda','format','Double');
+		WriteData(fid,prefix,'object',self,'fieldname','XTH_theta','data',self.XTH_theta ,'format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','borderSSA','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','borderHO','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','borderFS','format','DoubleMat','mattype',1)
 		#convert approximations to enums
-		data=copy.deepcopy(self.vertex_equation)
-		data[numpy.nonzero(data==0)]=NoneApproximationEnum()
-		data[numpy.nonzero(data==1)]=SIAApproximationEnum()
-		data[numpy.nonzero(data==2)]=SSAApproximationEnum()
-		data[numpy.nonzero(data==3)]=L1L2ApproximationEnum()
-		data[numpy.nonzero(data==4)]=HOApproximationEnum()
-		data[numpy.nonzero(data==5)]=FSApproximationEnum()
-		data[numpy.nonzero(data==6)]=SSAHOApproximationEnum()
-		data[numpy.nonzero(data==7)]=HOFSApproximationEnum()
-		data[numpy.nonzero(data==8)]=SSAFSApproximationEnum()
-		WriteData(fid,'data',data,'enum',FlowequationVertexEquationEnum(),'format','DoubleMat','mattype',1)
-		data=copy.deepcopy(self.element_equation)
-		data[numpy.nonzero(data==0)]=NoneApproximationEnum()
-		data[numpy.nonzero(data==1)]=SIAApproximationEnum()
-		data[numpy.nonzero(data==2)]=SSAApproximationEnum()
-		data[numpy.nonzero(data==3)]=L1L2ApproximationEnum()
-		data[numpy.nonzero(data==4)]=HOApproximationEnum()
-		data[numpy.nonzero(data==5)]=FSApproximationEnum()
-		data[numpy.nonzero(data==6)]=SSAHOApproximationEnum()
-		data[numpy.nonzero(data==7)]=SSAFSApproximationEnum()
-		data[numpy.nonzero(data==8)]=HOFSApproximationEnum()
-		WriteData(fid,'data',data,'enum',FlowequationElementEquationEnum(),'format','DoubleMat','mattype',2)
+		WriteData(fid,prefix,'data',self.vertex_equation,'name','md.flowequation.vertex_equation','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'data',self.element_equation,'name','md.flowequation.element_equation','format','DoubleMat','mattype',2)
+
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/friction.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/friction.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/friction.py	(revision 23670)
@@ -1,5 +1,5 @@
+import numpy as np
 from fielddisplay import fielddisplay
 from project3d import project3d
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -17,5 +17,6 @@
 		self.p           = float('NaN')
 		self.q           = float('NaN')
-
+		self.coupling  	 = 0
+		self.effective_pressure	= float('NaN')
 		#set defaults
 		self.setdefaultparameters()
@@ -23,9 +24,11 @@
 		#}}}
 	def __repr__(self): # {{{
-		string="Basal shear stress parameters: Sigma_b = coefficient^2 * Neff ^r * |u_b|^(s-1) * u_b,\n(effective stress Neff=rho_ice*g*thickness+rho_water*g*bed, r=q/p and s=1/p)"
+		string="Basal shear stress parameters: Sigma_b = coefficient^2 * Neff ^r * |u_b|^(s-1) * u_b,\n(effective stress Neff=rho_ice*g*thickness+rho_water*g*base, r=q/p and s=1/p)"
 
 		string="%s\n%s"%(string,fielddisplay(self,"coefficient","friction coefficient [SI]"))
 		string="%s\n%s"%(string,fielddisplay(self,"p","p exponent"))
 		string="%s\n%s"%(string,fielddisplay(self,"q","q exponent"))
+		string="%s\n%s"%(string,fielddisplay(self,'coupling','Coupling flag 0: uniform sheet (negative pressure ok, default), 1: ice pressure only, 2: water pressure assuming uniform sheet (no negative pressure), 3: use provided effective_pressure, 4: used coupled model (not implemented yet)'))
+		string="%s\n%s"%(string,fielddisplay(self,'effective_pressure','Effective Pressure for the forcing if not coupled [Pa]'))
 		return string
 		#}}}
@@ -34,4 +37,9 @@
 		self.p=project3d(md,'vector',self.p,'type','element')
 		self.q=project3d(md,'vector',self.q,'type','element')
+		#if self.coupling==0: #doesnt work with empty loop, so just skip it?
+		if self.coupling in[3,4]:
+			self.effective_pressure=project3d(md,'vector',self.effective_pressure,'type','node','layer',1)
+		elif self.coupling > 4:
+			raise ValueError('md.friction.coupling larger than 4, not supported yet')
 		return self
 	#}}}
@@ -42,5 +50,5 @@
 
 		#Early return
-		if StressbalanceAnalysisEnum() not in analyses and ThermalAnalysisEnum() not in analyses:
+		if 'StressbalanceAnalysis' not in analyses and 'ThermalAnalysis' not in analyses:
 			return md
 
@@ -48,11 +56,20 @@
 		md = checkfield(md,'fieldname','friction.q','NaN',1,'Inf',1,'size',[md.mesh.numberofelements])
 		md = checkfield(md,'fieldname','friction.p','NaN',1,'Inf',1,'size',[md.mesh.numberofelements])
-
+		md = checkfield(md,'fieldname','friction.coupling','numel',[1],'values',[0,1,2,3,4])
+		if self.coupling==3:
+			md = checkfield(md,'fieldname','friction.effective_pressure','NaN',1,'Inf',1,'timeseries',1)
+		elif self.coupling > 4:
+			raise ValueError('md.friction.coupling larger than 4, not supported yet')
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'enum',FrictionLawEnum(),'data',1,'format','Integer')
-		WriteData(fid,'object',self,'fieldname','coefficient','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'fieldname','p','format','DoubleMat','mattype',2)
-		WriteData(fid,'object',self,'fieldname','q','format','DoubleMat','mattype',2)
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'name','md.friction.law','data',1,'format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','coefficient','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','p','format','DoubleMat','mattype',2)
+		WriteData(fid,prefix,'object',self,'fieldname','q','format','DoubleMat','mattype',2)
+		WriteData(fid,prefix,'class','friction','object',self,'fieldname','coupling','format','Integer')
+		if self.coupling in[3,4]:
+			WriteData(fid,prefix,'class','friction','object',self,'fieldname','effective_pressure','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		elif self.coupling > 4:
+			raise ValueError('md.friction.coupling larger than 4, not supported yet')
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/frictioncoulomb.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/frictioncoulomb.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/frictioncoulomb.py	(revision 23670)
@@ -1,5 +1,4 @@
 from fielddisplay import fielddisplay
 from project3d import project3d
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -18,5 +17,6 @@
         self.p = float('NaN')
 	self.q = float('NaN')
-
+	self.coupling  	 = 0
+	self.effective_pressure	= float('NaN')
 	#set defaults
 	self.setdefaultparameters()
@@ -30,4 +30,6 @@
 	string="%s\n%s"%(string,fielddisplay(self,"p","p exponent"))
 	string="%s\n%s"%(string,fielddisplay(self,"q","q exponent"))
+	string="%s\n%s"%(string,fielddisplay(self,'coupling','Coupling flag: 0 for default, 1 for forcing(provide md.friction.effective_pressure)  and 2 for coupled(not implemented yet)'))
+	string="%s\n%s"%(string,fielddisplay(self,'effective_pressure','Effective Pressure for the forcing if not coupled [Pa]'))
 	return string
     #}}}
@@ -37,4 +39,10 @@
 	self.p=project3d(md,'vector',self.p,'type','element')
 	self.q=project3d(md,'vector',self.q,'type','element')
+	if self.coupling==1:
+		self.effective_pressure=project3d(md,'vector',self.effective_pressure,'type','node','layer',1)
+	elif self.coupling==2:
+		raise ValueError('coupling not supported yet')
+	elif self.coupling > 2:
+		raise ValueError('md.friction.coupling larger than 2, not supported yet')	
 	return self
     #}}}
@@ -45,5 +53,5 @@
 
 	#Early return
-	if StressbalanceAnalysisEnum() not in analyses and ThermalAnalysisEnum() not in analyses:
+	if 'StressbalanceAnalysis' not in analyses and 'ThermalAnalysis' not in analyses:
 	    return md
 
@@ -52,12 +60,25 @@
 	md = checkfield(md,'fieldname','friction.q','NaN',1,'Inf',1,'size',[md.mesh.numberofelements])
 	md = checkfield(md,'fieldname','friction.p','NaN',1,'Inf',1,'size',[md.mesh.numberofelements])
+	if self.coupling==1:
+		md = checkfield(md,'fieldname','friction.effective_pressure','NaN',1,'Inf',1,'timeseries',1)
+	elif self.coupling==2:
+		raise ValueError('coupling not supported yet')
+	elif self.coupling > 2:
+		raise ValueError('md.friction.coupling larger than 2, not supported yet')
+	return md
 
-	return md
     # }}}
-    def marshall(self,md,fid):    # {{{
-	WriteData(fid,'enum',FrictionLawEnum(),'data',1,'format','Integer')
-	WriteData(fid,'object',self,'fieldname','coefficient','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'enum',FrictionCoefficientEnum())
-	WriteData(fid,'object',self,'fieldname','coefficientcoulomb','format','DoubleMat','mattype',1,'enum',FrictionCoefficientcoulombEnum())
-	WriteData(fid,'object',self,'fieldname','p','format','DoubleMat','mattype',2,'enum',FrictionPEnum())
-	WriteData(fid,'object',self,'fieldname','q','format','DoubleMat','mattype',2,'enum',FrictionQEnum())
+    def marshall(self,prefix,md,fid):    # {{{
+	WriteData(fid,prefix,'name','md.friction.law','data',7,'format','Integer')
+	WriteData(fid,prefix,'object',self,'fieldname','coefficient','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+	WriteData(fid,prefix,'object',self,'fieldname','coefficientcoulomb','format','DoubleMat','mattype',1)
+	WriteData(fid,prefix,'object',self,'fieldname','p','format','DoubleMat','mattype',2)
+	WriteData(fid,prefix,'object',self,'fieldname','q','format','DoubleMat','mattype',2)
+	WriteData(fid,prefix,'class','friction','object',self,'fieldname','coupling','format','Integer')
+	if self.coupling==1:
+		WriteData(fid,prefix,'class','friction','object',self,'fieldname','effective_pressure','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+	elif self.coupling==2:
+		raise ValueError('coupling not supported yet')
+	elif self.coupling > 2:
+		raise ValueError('md.friction.coupling larger than 2, not supported yet')	
     # }}}
Index: /issm/trunk-jpl/src/py3/classes/frictionweertman.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/frictionweertman.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/frictionweertman.py	(revision 23670)
@@ -1,5 +1,4 @@
 from fielddisplay import fielddisplay
 from project3d import project3d
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -34,5 +33,5 @@
 
 		#Early return
-		if StressbalanceAnalysisEnum() not in analyses and ThermalAnalysisEnum() not in analyses:
+		if 'StressbalanceAnalysis' not in analyses and 'ThermalAnalysis' not in analyses:
 			return md
 
@@ -42,7 +41,7 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'enum',FrictionLawEnum(),'data',2,'format','Integer')
-		WriteData(fid,'class','friction','object',self,'fieldname','C','format','DoubleMat','mattype',1)
-		WriteData(fid,'class','friction','object',self,'fieldname','m','format','DoubleMat','mattype',2)
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'name','md.friction.law','data',2,'format','Integer')
+		WriteData(fid,prefix,'class','friction','object',self,'fieldname','C','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'class','friction','object',self,'fieldname','m','format','DoubleMat','mattype',2)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/geometry.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/geometry.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/geometry.py	(revision 23670)
@@ -1,5 +1,4 @@
 from project3d import project3d
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -14,9 +13,9 @@
 
 	def __init__(self): # {{{
-		self.surface           = float('NaN')
-		self.thickness         = float('NaN')
+		self.surface		= float('NaN')
+		self.thickness		= float('NaN')
 		self.base               = float('NaN')
-		self.bed        = float('NaN')
-		self.hydrostatic_ratio = float('NaN')
+		self.bed		= float('NaN')
+		self.hydrostatic_ratio	= float('NaN')
 
 		#set defaults
@@ -46,19 +45,24 @@
 	def checkconsistency(self,md,solution,analyses):    # {{{
 
-		md = checkfield(md,'fieldname','geometry.surface'  ,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
-		md = checkfield(md,'fieldname','geometry.base'      ,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
-		md = checkfield(md,'fieldname','geometry.thickness','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices],'>',0,'timeseries',1)
-		if any(abs(self.thickness-self.surface+self.base)>10**-9):
-			md.checkmessage("equality thickness=surface-base violated")
-		if solution==TransientSolutionEnum() and md.transient.isgroundingline:
-			md = checkfield(md,'fieldname','geometry.bed','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
+		if (solution=='TransientSolution' and md.transient.isgia) or (solution=='GiaSolution'):
+			md = checkfield(md,'fieldname','geometry.thickness','NaN',1,'Inf',1,'>=',0,'timeseries',1)
+		elif solution=='LoveSolution':
+			return
+		else:
+			md = checkfield(md,'fieldname','geometry.surface'  ,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
+			md = checkfield(md,'fieldname','geometry.base'      ,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
+			md = checkfield(md,'fieldname','geometry.thickness','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices],'>',0,'timeseries',1)
+			if any(abs(self.thickness-self.surface+self.base)>10**-9):
+				md.checkmessage("equality thickness=surface-base violated")
+			if solution=='TransientSolution' and md.transient.isgroundingline:
+				md = checkfield(md,'fieldname','geometry.bed','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'data',self.surface,'format','DoubleMat','mattype',1,'enum',SurfaceEnum())
-		WriteData(fid,'data',self.thickness,'format','DoubleMat','mattype',1,'enum',ThicknessEnum(),'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'data',self.base,'format','DoubleMat','mattype',1,'enum',BaseEnum())
-		WriteData(fid,'data',self.bed,'format','DoubleMat','mattype',1,'enum',BedEnum())
-		WriteData(fid,'object',self,'fieldname','hydrostatic_ratio','format','DoubleMat','mattype',1)
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'object',self,'fieldname','surface','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','thickness','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'fieldname','base','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','bed','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','hydrostatic_ratio','format','DoubleMat','mattype',1)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/groundingline.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/groundingline.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/groundingline.py	(revision 23670)
@@ -1,6 +1,4 @@
-import numpy
+import numpy as np
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
-from StringToEnum import StringToEnum
 from checkfield import checkfield
 from WriteData import WriteData
@@ -17,4 +15,6 @@
 	def __init__(self): # {{{
 		self.migration=''
+		self.friction_interpolation=''
+		self.melt_interpolation=''
 
 		#set defaults
@@ -25,5 +25,7 @@
 		string='   grounding line migration parameters:'
 
-		string="%s\n%s"%(string,fielddisplay(self,'migration','type of grounding line migration: ''SoftMigration'',''AggressiveMigration'',''SubelementMigration'',''SubelementMigration2'',''Contact'',''None'''))
+		string="%s\n%s"%(string,fielddisplay(self,'migration','type of grounding line migration: ''SoftMigration'',''SubelementMigration'',''AggressiveMigration'',''Contact'',''None'''))
+		string="%s\n%s"%(string,fielddisplay(self,'migration','type of friction interpolation on partially floating elements: ''SubelementFriction1'',''SubelementFriction2'',''NoFrictionOnPartiallyFloating'''))
+		string="%s\n%s"%(string,fielddisplay(self,'migration','type of melt interpolation on partially floating elements: ''SubelementMelt1'',''SubelementMelt2'',''NoMeltOnPartiallyFloating'',''FullMeltOnPartiallyFloating'''))
 		return string
 		#}}}	
@@ -31,5 +33,7 @@
 
 		#Type of migration
-		self.migration='None'
+		self.migration='SubelementMigration'
+		self.friction_interpolation='SubelementFriction1'
+		self.melt_interpolation='NoMeltOnPartiallyFloating'
 
 		return self
@@ -37,11 +41,13 @@
 	def checkconsistency(self,md,solution,analyses):    # {{{
 
-		md = checkfield(md,fieldname='groundingline.migration',values=['None','AggressiveMigration','SoftMigration','SubelementMigration','SubelementMigration2','Contact','GroundingOnly'])
+		md = checkfield(md,'fieldname','groundingline.migration','values',['None','SubelementMigration','AggressiveMigration','SoftMigration','Contact','GroundingOnly'])
+		md = checkfield(md,'fieldname','groundingline.friction_interpolation','values',['SubelementFriction1','SubelementFriction2','NoFrictionOnPartiallyFloating'])
+		md = checkfield(md,'fieldname','groundingline.melt_interpolation','values',['SubelementMelt1','SubelementMelt2','NoMeltOnPartiallyFloating','FullMeltOnPartiallyFloating'])
 
-		if not m.strcmp(self.migration,'None'):
-			if numpy.any(numpy.isnan(md.geometry.bed)):
+		if(not m.strcmp(self.migration,'None') and md.transient.isgroundingline and solution=='TransientSolution'):
+			if np.any(np.isnan(md.geometry.bed)):
 				md.checkmessage("requesting grounding line migration, but bathymetry is absent!")
-			pos=numpy.nonzero(md.mask.groundedice_levelset>0.)[0]
-			if any(numpy.abs(md.geometry.base[pos]-md.geometry.bed[pos])>10**-10):
+			pos=np.nonzero(md.mask.groundedice_levelset>0.)[0]
+			if any(np.abs(md.geometry.base[pos]-md.geometry.bed[pos])>10**-10):
 				md.checkmessage("base not equal to bed on grounded ice!")
 			if any(md.geometry.bed - md.geometry.base > 10**-9):
@@ -50,5 +56,7 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'data',StringToEnum(self.migration)[0],'enum',GroundinglineMigrationEnum(),'format','Integer')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'data',self.migration,'name','md.groundingline.migration','format','String')
+		WriteData(fid,prefix,'data',self.friction_interpolation,'name','md.groundingline.friction_interpolation','format','String')
+		WriteData(fid,prefix,'data',self.melt_interpolation,'name','md.groundingline.melt_interpolation','format','String')
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/hydrologydc.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/hydrologydc.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/hydrologydc.py	(revision 23670)
@@ -1,6 +1,5 @@
-import numpy
+import numpy as np
 from project3d import project3d
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -21,19 +20,22 @@
 		self.rel_tol                  = 0
 		self.max_iter                 = 0
+		self.steps_per_step           = 0
 		self.sedimentlimit_flag       = 0
 		self.sedimentlimit            = 0
 		self.transfer_flag            = 0
+		self.unconfined_flag          = 0
 		self.leakage_factor           = 0
-		self.basal_moulin_input       = float('NaN')
-
-		self.spcsediment_head         = float('NaN')
-		self.sediment_transmitivity   = float('NaN')
+		self.basal_moulin_input       = np.nan
+		self.requested_outputs        = []
+
+		self.spcsediment_head         = np.nan
+		self.mask_thawed_node         = np.nan
+		self.sediment_transmitivity   = np.nan
 		self.sediment_compressibility = 0
 		self.sediment_porosity        = 0
 		self.sediment_thickness       = 0
 
-
-		self.spcepl_head              = float('NaN')
-		self.mask_eplactive_node      = float('NaN')
+		self.spcepl_head              = np.nan
+		self.mask_eplactive_node      = np.nan
 		self.epl_compressibility      = 0
 		self.epl_porosity             = 0
@@ -44,5 +46,5 @@
 		self.epl_conductivity         = 0
 		self.eplflip_lock             = 0
-				 
+
 		#set defaults
 		self.setdefaultparameters()
@@ -57,5 +59,7 @@
 		string="%s\n%s"%(string,fielddisplay(self,'rel_tol','tolerance of the nonlinear iteration for the transfer between layers [dimensionless]'))
 		string="%s\n%s"%(string,fielddisplay(self,'max_iter','maximum number of nonlinear iteration'))
+		string="%s\n%s"%(string,fielddisplay(self,'steps_per_step','number of hydrology steps per time step'))
 		string="%s\n%s"%(string,fielddisplay(self,'basal_moulin_input','water flux at a given point [m3 s-1]'))
+		string="%s\n%s"%(string,fielddisplay(self,'requested_outputs','additional outputs requested'))
 		string="%s\n%s"%(string,fielddisplay(self,'sedimentlimit_flag','what kind of upper limit is applied for the inefficient layer'))
 		string="%s\n\t\t%s"%(string,'0: no limit')
@@ -63,5 +67,5 @@
 		string="%s\n\t\t%s"%(string,'2: hydrostatic pressure')
 		string="%s\n\t\t%s"%(string,'3: normal stress')
-	
+
 		if self.sedimentlimit_flag==1:
 			string="%s\n%s"%(string,fielddisplay(self,'sedimentlimit','user defined upper limit for the inefficient layer [m]'))
@@ -70,7 +74,11 @@
 		string="%s\n\t\t%s"%(string,'0: no transfer')
 		string="%s\n\t\t%s"%(string,'1: constant leakage factor: leakage_factor')
-			 
+
 		if self.transfer_flag is 1:
 			string="%s\n%s"%(string,fielddisplay(self,'leakage_factor','user defined leakage factor [m]'))
+
+		string="%s\n%s"%(string,fielddisplay(self,'unconfined_flag','using an unconfined scheme or not (transitory)'))
+		string="%s\n\t\t%s"%(string,'0: Confined only')
+		string="%s\n\t\t%s"%(string,'1: Confined-Unconfined')
 
 		string="%s\n%s"%(string,'   - for the sediment layer')
@@ -80,4 +88,5 @@
 		string="%s\n%s"%(string,fielddisplay(self,'sediment_thickness','sediment thickness [m]'))
 		string="%s\n%s"%(string,fielddisplay(self,'sediment_transmitivity','sediment transmitivity [m^2/s]'))
+		string="%s\n%s"%(string,fielddisplay(self,'mask_thawed_node','IDS is deactivaed (0) on frozen nodes'))
 
 		if self.isefficientlayer==1:
@@ -87,6 +96,6 @@
 			string="%s\n%s"%(string,fielddisplay(self,'epl_compressibility','epl compressibility [Pa^-1]'))
 			string="%s\n%s"%(string,fielddisplay(self,'epl_porosity','epl [dimensionless]'))
-			string="%s\n%s"%(string,fielddisplay(self,'epl_max_thickness','epl initial thickness [m]'))
-			string="%s\n%s"%(string,fielddisplay(self,'epl_initial_thickness','epl initial thickness [m]'))			
+			string="%s\n%s"%(string,fielddisplay(self,'epl_max_thickness','epl maximal thickness [m]'))
+			string="%s\n%s"%(string,fielddisplay(self,'epl_initial_thickness','epl initial thickness [m]'))
 			string="%s\n%s"%(string,fielddisplay(self,'epl_colapse_thickness','epl colapsing thickness [m]'))
 			string="%s\n%s"%(string,fielddisplay(self,'epl_thick_comp','epl thickness computation flag'))
@@ -97,14 +106,13 @@
 	def extrude(self,md): # {{{
 		self.spcsediment_head=project3d(md,'vector',self.spcsediment_head,'type','node','layer',1)
-		self.spcepl_head=project3d(md,'vector',self.spcepl_head,'type','node','layer',1)
-		self.mask_eplactive_node=project3d(md,'vector',self.mask_eplactive_node,'type','node','layer',1)
 		self.sediment_transmitivity=project3d(md,'vector',self.sediment_transmitivity,'type','node','layer',1)
 		self.basal_moulin_input=project3d(md,'vector',self.basal_moulin_input,'type','node','layer',1)
+		self.mask_thawed_node=project3d(md,'vector',self.mask_thawed_node,'type','node','layer',1)
 		if self.isefficientlayer==1 :
 			self.spcepl_head=project3d(md,'vector',self.spcepl_head,'type','node','layer',1)
+			self.mask_eplactive_node=project3d(md,'vector',self.mask_eplactive_node,'type','node','layer',1)
 		return self
 	#}}}
-	def setdefaultparameters(self): #{{{ 
-
+	def setdefaultparameters(self): #{{{
 		#Parameters from de Fleurian 2014
 		self.water_compressibility    = 5.04e-10
@@ -114,8 +122,11 @@
 		self.rel_tol                  = 1.0e-06
 		self.max_iter                 = 100
+		self.steps_per_step           = 1
 		self.sedimentlimit_flag       = 0
 		self.sedimentlimit            = 0
 		self.transfer_flag            = 0
+		self.unconfined_flag          = 0
 		self.leakage_factor           = 10.0
+		self.requested_outputs        = ['default']
 
 		self.sediment_compressibility = 1.0e-08
@@ -125,25 +136,38 @@
 
 		self.epl_compressibility      = 1.0e-08
+		self.epl_conductivity         = 8.0e-02
 		self.epl_porosity             = 0.4
 		self.epl_initial_thickness    = 1.0
-		self.epl_colapse_thickness    = 1.0e-3
+		self.epl_colapse_thickness    = self.sediment_transmitivity/self.epl_conductivity
 		self.epl_thick_comp           = 1
 		self.epl_max_thickness        = 5.0
-		self.epl_conductivity         = 8.0e-02
 		self.eplflip_lock             = 0
-		
+
 		return self
 	# }}}
+
+	def defaultoutputs(self,md): # {{{
+		list = ['SedimentHeadHydrostep','SedimentHeadResidual','EffectivePressureHydrostep']
+		if self.isefficientlayer==1:
+			list.extend(['EplHeadHydrostep','HydrologydcMaskEplactiveNode','HydrologydcMaskEplactiveElt','EplHeadSlopeX','EplHeadSlopeY','HydrologydcEplThicknessHydrostep'])
+		if self.steps_per_step>1:
+			list.extend(['EffectivePressure','SedimentHead'])
+			if self.isefficientlayer==1:
+				list.extend(['EplHead','HydrologydcEplThickness'])
+		return list
+	#}}}
+
 	def initialize(self,md): # {{{
-		if numpy.all(numpy.isnan(self.basal_moulin_input)):
-			self.basal_moulin_input=numpy.zeros((md.mesh.numberofvertices,1))
+		self.epl_colapse_thickness = self.sediment_transmitivity/self.epl_conductivity
+		if np.all(np.isnan(self.basal_moulin_input)):
+			self.basal_moulin_input=np.zeros((md.mesh.numberofvertices))
 			print("      no hydrology.basal_moulin_input specified: values set as zero")
 
 		return self
 	# }}}
-	def checkconsistency(self,md,solution,analyses): #{{{ 
+	def checkconsistency(self,md,solution,analyses): #{{{
 
 		#Early return
-		if HydrologyDCInefficientAnalysisEnum() not in analyses and HydrologyDCEfficientAnalysisEnum() not in analyses:
+		if 'HydrologyDCInefficientAnalysis' not in analyses and 'HydrologyDCEfficientAnalysis' not in analyses:
 			return md
 
@@ -154,6 +178,9 @@
 		md = checkfield(md,'fieldname','hydrology.rel_tol','>',0.,'numel',[1])
 		md = checkfield(md,'fieldname','hydrology.max_iter','>',0.,'numel',[1])
+		md = checkfield(md,'fieldname','hydrology.steps_per_step','>',0.,'numel',[1])
 		md = checkfield(md,'fieldname','hydrology.sedimentlimit_flag','numel',[1],'values',[0,1,2,3])
 		md = checkfield(md,'fieldname','hydrology.transfer_flag','numel',[1],'values',[0,1])
+		md = checkfield(md,'fieldname','hydrology.unconfined_flag','numel',[1],'values',[0,1])
+		md = checkfield(md,'fieldname','hydrology.requested_outputs','stringrow',1)
 
 		if self.sedimentlimit_flag==1:
@@ -168,8 +195,9 @@
 		md = checkfield(md,'fieldname','hydrology.sediment_porosity','>',0.,'numel',[1])
 		md = checkfield(md,'fieldname','hydrology.sediment_thickness','>',0.,'numel',[1])
-		md = checkfield(md,'fieldname','hydrology.sediment_transmitivity','>=',0,'size',[md.mesh.numberofvertices,1])
+		md = checkfield(md,'fieldname','hydrology.sediment_transmitivity','>=',0,'size',[md.mesh.numberofvertices])
+		md = checkfield(md,'fieldname','hydrology.mask_thawed_node','size',[md.mesh.numberofvertices],'values',[0,1])
 		if self.isefficientlayer==1:
 			md = checkfield(md,'fieldname','hydrology.spcepl_head','Inf',1,'timeseries',1)
-			md = checkfield(md,'fieldname','hydrology.mask_eplactive_node','size',[md.mesh.numberofvertices,1],'values',[0,1])
+			md = checkfield(md,'fieldname','hydrology.mask_eplactive_node','size',[md.mesh.numberofvertices],'values',[0,1])
 			md = checkfield(md,'fieldname','hydrology.epl_compressibility','>',0.,'numel',[1])
 			md = checkfield(md,'fieldname','hydrology.epl_porosity','>',0.,'numel',[1])
@@ -183,37 +211,48 @@
 			md = checkfield(md,'fieldname','hydrology.epl_conductivity','numel',[1],'>',0.)
 	# }}}
-	def marshall(self,md,fid): #{{{ 
-		WriteData(fid,'enum',HydrologyModelEnum(),'data',HydrologydcEnum(),'format','Integer')
-		WriteData(fid,'object',self,'fieldname','water_compressibility','format','Double')
-		WriteData(fid,'object',self,'fieldname','isefficientlayer','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','penalty_factor','format','Double')
-		WriteData(fid,'object',self,'fieldname','penalty_lock','format','Integer')
-		WriteData(fid,'object',self,'fieldname','rel_tol','format','Double')
-		WriteData(fid,'object',self,'fieldname','max_iter','format','Integer')
-		WriteData(fid,'object',self,'fieldname','sedimentlimit_flag','format','Integer')
-		WriteData(fid,'object',self,'fieldname','transfer_flag','format','Integer')
+	def marshall(self,prefix,md,fid): #{{{
+		WriteData(fid,prefix,'name','md.hydrology.model','data',1,'format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','water_compressibility','format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','isefficientlayer','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','penalty_factor','format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','penalty_lock','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','rel_tol','format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','max_iter','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','steps_per_step','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','sedimentlimit_flag','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','transfer_flag','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','unconfined_flag','format','Integer')
 		if self.sedimentlimit_flag==1:
-			WriteData(fid,'object',self,'fieldname','sedimentlimit','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','sedimentlimit','format','Double')
 
 		if self.transfer_flag==1:
-			WriteData(fid,'object',self,'fieldname','leakage_factor','format','Double')
-
-		WriteData(fid,'object',self,'fieldname','basal_moulin_input','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'fieldname','spcsediment_head','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'fieldname','sediment_compressibility','format','Double')
-		WriteData(fid,'object',self,'fieldname','sediment_porosity','format','Double')			
-		WriteData(fid,'object',self,'fieldname','sediment_thickness','format','Double')
-		WriteData(fid,'object',self,'fieldname','sediment_transmitivity','format','DoubleMat','mattype',1)		
-
-		if self.isefficientlayer==1:	
-			WriteData(fid,'object',self,'fieldname','spcepl_head','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)	
-			WriteData(fid,'object',self,'fieldname','mask_eplactive_node','format','DoubleMat','mattype',1)
-			WriteData(fid,'object',self,'fieldname','epl_compressibility','format','Double')			
-			WriteData(fid,'object',self,'fieldname','epl_porosity','format','Double')			
-			WriteData(fid,'object',self,'fieldname','epl_max_thickness','format','Double')
-			WriteData(fid,'object',self,'fieldname','epl_initial_thickness','format','Double')			
-			WriteData(fid,'object',self,'fieldname','epl_colapse_thickness','format','Double')
-			WriteData(fid,'object',self,'fieldname','epl_thick_comp','format','Integer')			
-			WriteData(fid,'object',self,'fieldname','epl_conductivity','format','Double')
-			WriteData(fid,'object',self,'fieldname','eplflip_lock','format','Integer')
-	# }}}
+			WriteData(fid,prefix,'object',self,'fieldname','leakage_factor','format','Double')
+
+		WriteData(fid,prefix,'object',self,'fieldname','basal_moulin_input','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'fieldname','spcsediment_head','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'fieldname','sediment_compressibility','format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','sediment_porosity','format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','sediment_thickness','format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','sediment_transmitivity','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','mask_thawed_node','format','DoubleMat','mattype',1)
+
+		if self.isefficientlayer==1:
+			WriteData(fid,prefix,'object',self,'fieldname','spcepl_head','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+			WriteData(fid,prefix,'object',self,'fieldname','mask_eplactive_node','format','DoubleMat','mattype',1)
+			WriteData(fid,prefix,'object',self,'fieldname','epl_compressibility','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','epl_porosity','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','epl_max_thickness','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','epl_initial_thickness','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','epl_colapse_thickness','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','epl_thick_comp','format','Integer')
+			WriteData(fid,prefix,'object',self,'fieldname','epl_conductivity','format','Double')
+			WriteData(fid,prefix,'object',self,'fieldname','eplflip_lock','format','Integer')
+
+		#process requested outputs
+		outputs = self.requested_outputs
+		indices = [i for i, x in enumerate(outputs) if x == 'default']
+		if len(indices) > 0:
+			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
+			outputs    =outputscopy
+		WriteData(fid,prefix,'data',outputs,'name','md.hydrology.requested_outputs','format','StringArray')
+	# }}}
Index: /issm/trunk-jpl/src/py3/classes/hydrologyshreve.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/hydrologyshreve.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/hydrologyshreve.py	(revision 23670)
@@ -1,4 +1,3 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -15,5 +14,5 @@
 		self.spcwatercolumn = float('NaN')
 		self.stabilization  = 0
-
+		self.requested_outputs = []
 		#set defaults
 		self.setdefaultparameters()
@@ -25,4 +24,5 @@
 		string="%s\n%s"%(string,fielddisplay(self,'spcwatercolumn','water thickness constraints (NaN means no constraint) [m]'))
 		string="%s\n%s"%(string,fielddisplay(self,'stabilization','artificial diffusivity (default is 1). can be more than 1 to increase diffusivity.'))
+		string="%s\n%s"%(string,fielddisplay(self,'requested_outputs','additional outputs requested'))
 		return string
 		#}}}
@@ -34,21 +34,34 @@
 		#Type of stabilization to use 0:nothing 1:artificial_diffusivity
 		self.stabilization=1
-
+		self.requested_outputs= ['default']
 		return self
 	#}}}
+	def defaultoutputs(self,md): # {{{
+		list = ['Watercolumn','HydrologyWaterVx','HydrologyWaterVy']
+		return list
+	#}}}
+
 	def checkconsistency(self,md,solution,analyses):    # {{{
 		
 		#Early return
-		if HydrologyShreveAnalysisEnum() not in analyses:
+		if 'HydrologyShreveAnalysis' not in analyses:
 			return md
 
 		md = checkfield(md,'fieldname','hydrology.spcwatercolumn','Inf',1,'timeseries',1)
 		md = checkfield(md,'fieldname','hydrology.stabilization','>=',0)
-
+		md = checkfield(md,'fieldname','hydrology.requested_outputs','stringrow',1)
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'enum',HydrologyModelEnum(),'data',HydrologyshreveEnum(),'format','Integer');
-		WriteData(fid,'object',self,'fieldname','spcwatercolumn','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'fieldname','stabilization','format','Double')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'name','md.hydrology.model','data',2,'format','Integer');
+		WriteData(fid,prefix,'object',self,'fieldname','spcwatercolumn','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'fieldname','stabilization','format','Double')
+		#process requested outputs
+		outputs = self.requested_outputs
+		indices = [i for i, x in enumerate(outputs) if x == 'default']
+		if len(indices) > 0:
+			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
+			outputs    =outputscopy
+		WriteData(fid,prefix,'data',outputs,'name','md.hydrology.requested_outputs','format','StringArray')
+
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/independent.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/independent.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/independent.py	(revision 23670)
@@ -1,7 +1,7 @@
-import numpy
+import numpy as np
 from pairoptions import pairoptions
 from fielddisplay import fielddisplay
-import MatlabFuncs as m
-from EnumDefinitions import *
+from checkfield import checkfield
+from MatlabFuncs import *
 
 class independent(object):
@@ -13,9 +13,9 @@
 	"""
 
-	def __init__(self,**kwargs):    # {{{
+	def __init__(self,*args):    # {{{
 		self.name                 = ''
 		self.type                 = ''
 		self.fos_forward_index    = float('NaN')
-		self.fov_forward_indices  = numpy.array([])
+		self.fov_forward_indices  = np.array([])
 		self.nods                 = 0
 
@@ -24,5 +24,5 @@
 
 		#use provided options to change fields
-		options=pairoptions(**kwargs)
+		options=pairoptions(*args)
 
 		#OK get other fields
@@ -32,9 +32,9 @@
 		s ="   independent variable:\n"
 
-		s+="%s\n" % fielddisplay(self,'name',"variable name (must match corresponding Enum)")
+		s+="%s\n" % fielddisplay(self,'name',"variable name (must match corresponding String)")
 		s+="%s\n" % fielddisplay(self,'type',"type of variable ('vertex' or 'scalar')")
-		if not numpy.isnan(self.fos_forward_index):
+		if not np.isnan(self.fos_forward_index):
 			s+="%s\n" % fielddisplay(self,'fos_forward_index',"index for fos_foward driver of ADOLC")
-		if numpy.any(numpy.logical_not(numpy.isnan(self.fov_forward_indices))):
+		if np.any(np.logical_not(np.isnan(self.fov_forward_indices))):
 			s+="%s\n" % fielddisplay(self,'fov_forward_indices',"indices for fov_foward driver of ADOLC")
 
@@ -46,5 +46,5 @@
 	# }}}
 	def checkconsistency(self,md,i,solution,analyses,driver):    # {{{
-		if not numpy.isnan(self.fos_forward_index):
+		if not np.isnan(self.fos_forward_index):
 			if not strcmpi(driver,'fos_forward'):
 				raise TypeError("cannot declare an independent with a fos_forward_index when the driver is not fos_forward!")
@@ -52,10 +52,10 @@
 				raise TypeError("independent checkconsistency error: nods should be set to the size of the independent variable")
 
-		if self.fov_forward_indices:
+		if len(self.fov_forward_indices) > 0:
 			if not strcmpi(driver,'fov_forward'):
 				raise TypeError("cannot declare an independent with fov_forward_indices when the driver is not fov_forward!")
 			if self.nods==0:
 				raise TypeError("independent checkconsistency error: nods should be set to the size of the independent variable")
-			md = checkfield(md,'fieldname',"autodiff.independents[%d].fov_forward_indices" % i,'>=',1,'<=',self.nods,'size',[float('NaN'),1])
+			md = checkfield(md,'fieldname',"autodiff.independents[%d].fov_forward_indices" % i,'>=',1,'<=',self.nods)
 
 		return md
Index: /issm/trunk-jpl/src/py3/classes/initialization.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/initialization.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/initialization.py	(revision 23670)
@@ -1,6 +1,5 @@
-import numpy
+import numpy as np
 from project3d import project3d
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -62,5 +61,13 @@
 
 		#Lithostatic pressure by default
-		self.pressure=md.constants.g*md.materials.rho_ice*(md.geometry.surface-md.mesh.z.reshape(-1,1))
+		#		self.pressure=md.constants.g*md.materials.rho_ice*(md.geometry.surface[:,0]-md.mesh.z)
+		#self.pressure=md.constants.g*md.materials.rho_ice*(md.geometry.surface-md.mesh.z.reshape(-1,))
+
+		if np.ndim(md.geometry.surface)==2:
+			print('Reshaping md.geometry.surface for you convenience but you should fix it in you files')
+			self.pressure=md.constants.g*md.materials.rho_ice*(md.geometry.surface.reshape(-1,)-md.mesh.z)
+		else:
+			self.pressure=md.constants.g*md.materials.rho_ice*(md.geometry.surface-md.mesh.z)
+
 		return self
 	#}}}
@@ -69,19 +76,19 @@
 	#}}}
 	def checkconsistency(self,md,solution,analyses):    # {{{
-		if StressbalanceAnalysisEnum() in analyses:
-			if not numpy.any(numpy.logical_or(numpy.isnan(md.initialization.vx),numpy.isnan(md.initialization.vy))):
+		if 'StressbalanceAnalysis' in analyses:
+			if not np.any(np.logical_or(np.isnan(md.initialization.vx),np.isnan(md.initialization.vy))):
 				md = checkfield(md,'fieldname','initialization.vx','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 				md = checkfield(md,'fieldname','initialization.vy','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
-		if MasstransportAnalysisEnum() in analyses:
+		if 'MasstransportAnalysis' in analyses:
 			md = checkfield(md,'fieldname','initialization.vx','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 			md = checkfield(md,'fieldname','initialization.vy','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
-		if BalancethicknessAnalysisEnum() in analyses:
+		if 'BalancethicknessAnalysis' in analyses:
 			md = checkfield(md,'fieldname','initialization.vx','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 			md = checkfield(md,'fieldname','initialization.vy','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 			#Triangle with zero velocity
-			if numpy.any(numpy.logical_and(numpy.sum(numpy.abs(md.initialization.vx[md.mesh.elements-1]),axis=1)==0,\
-			                               numpy.sum(numpy.abs(md.initialization.vy[md.mesh.elements-1]),axis=1)==0)):
+			if np.any(np.logical_and(np.sum(np.abs(md.initialization.vx[md.mesh.elements-1]),axis=1)==0,\
+			                               np.sum(np.abs(md.initialization.vy[md.mesh.elements-1]),axis=1)==0)):
 				md.checkmessage("at least one triangle has all its vertices with a zero velocity")
-		if ThermalAnalysisEnum() in analyses:
+		if 'ThermalAnalysis' in analyses:
 			md = checkfield(md,'fieldname','initialization.vx','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 			md = checkfield(md,'fieldname','initialization.vy','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
@@ -90,43 +97,45 @@
 				md = checkfield(md,'fieldname','initialization.vz','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 			md = checkfield(md,'fieldname','initialization.pressure','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
-			if (EnthalpyAnalysisEnum() in analyses and md.thermal.isenthalpy):
+			if ('EnthalpyAnalysis' in analyses and md.thermal.isenthalpy):
 				md = checkfield(md,'fieldname','initialization.waterfraction','>=',0,'size',[md.mesh.numberofvertices])
 				md = checkfield(md,'fieldname','initialization.watercolumn'  ,'>=',0,'size',[md.mesh.numberofvertices])
-		if HydrologyShreveAnalysisEnum() in analyses:
+				pos = np.nonzero(md.initialization.waterfraction > 0.)[0]
+				if(pos.size):
+					md = checkfield(md,'fieldname', 'delta Tpmp', 'field', np.absolute(md.initialization.temperature[pos]-(md.materials.meltingpoint-md.materials.beta*md.initialization.pressure[pos])),'<',1e-11,	'message','set temperature to pressure melting point at locations with waterfraction>0');
+		if 'HydrologyShreveAnalysis' in analyses:
 			if hasattr(md.hydrology,'hydrologyshreve'):
 				md = checkfield(md,'fieldname','initialization.watercolumn','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
-		if HydrologyDCInefficientAnalysisEnum() in analyses:
+		if 'HydrologyDCInefficientAnalysis' in analyses:
 			if hasattr(md.hydrology,'hydrologydc'):
-				md = checkfield(md,'fieldname','initialization.sediment_head','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices,1])
-		if HydrologyDCEfficientAnalysisEnum() in analyses:
+				md = checkfield(md,'fieldname','initialization.sediment_head','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
+		if 'HydrologyDCEfficientAnalysis' in analyses:
 			if hasattr(md.hydrology,'hydrologydc'):
 				if md.hydrology.isefficientlayer==1:
-					md = checkfield(md,'fieldname','initialization.epl_head','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices,1])
-					md = checkfield(md,'fieldname','initialization.epl_thickness','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices,1])
+					md = checkfield(md,'fieldname','initialization.epl_head','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
+					md = checkfield(md,'fieldname','initialization.epl_thickness','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.0*24.0*3600.0
+		yts=md.constants.yts
 
-		WriteData(fid,'data',self.vx,'format','DoubleMat','mattype',1,'enum',VxEnum(),'scale',1./yts)
-		WriteData(fid,'data',self.vy,'format','DoubleMat','mattype',1,'enum',VyEnum(),'scale',1./yts)
-		WriteData(fid,'data',self.vz,'format','DoubleMat','mattype',1,'enum',VzEnum(),'scale',1./yts)
-		WriteData(fid,'data',self.pressure,'format','DoubleMat','mattype',1,'enum',PressureEnum())
-		WriteData(fid,'data',self.temperature,'format','DoubleMat','mattype',1,'enum',TemperatureEnum())
-		WriteData(fid,'data',self.waterfraction,'format','DoubleMat','mattype',1,'enum',WaterfractionEnum())
-		WriteData(fid,'data',self.watercolumn,'format','DoubleMat','mattype',1,'enum',WatercolumnEnum())
-		WriteData(fid,'data',self.sediment_head,'format','DoubleMat','mattype',1,'enum',SedimentHeadEnum())
-		WriteData(fid,'data',self.epl_head,'format','DoubleMat','mattype',1,'enum',EplHeadEnum())
-		WriteData(fid,'data',self.epl_thickness,'format','DoubleMat','mattype',1,'enum',HydrologydcEplThicknessEnum())
-
+		WriteData(fid,prefix,'object',self,'fieldname','vx','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'fieldname','vy','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'fieldname','vz','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'fieldname','pressure','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','temperature','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','waterfraction','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','sediment_head','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','epl_head','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','epl_thickness','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','watercolumn','format','DoubleMat','mattype',1)
 		
 		if md.thermal.isenthalpy:
 			tpmp = md.materials.meltingpoint - md.materials.beta*md.initialization.pressure;
-			pos  = numpy.nonzero(md.initialization.temperature > tpmp)[0]
+			pos  = np.nonzero(md.initialization.waterfraction > 0.)[0]
 			enthalpy      = md.materials.heatcapacity*(md.initialization.temperature-md.constants.referencetemperature);
-			enthalpy[pos] = md.materials.heatcapacity*tpmp[pos].reshape(-1,1) - md.constants.referencetemperature + md.materials.latentheat*md.initialization.waterfraction[pos].reshape(-1,1)
-			WriteData(fid,'data',enthalpy,'format','DoubleMat','mattype',1,'enum',EnthalpyEnum());
+			enthalpy[pos] = md.materials.heatcapacity*(tpmp[pos].reshape(-1,) - md.constants.referencetemperature) + md.materials.latentheat*md.initialization.waterfraction[pos].reshape(-1,)
+			WriteData(fid,prefix,'data',enthalpy,'format','DoubleMat','mattype',1,'name','md.initialization.enthalpy');
 
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/inversion.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/inversion.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/inversion.py	(revision 23670)
@@ -1,7 +1,5 @@
-import numpy
+import numpy as np
 from project3d import project3d
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
-from StringToEnum import StringToEnum
 from checkfield import checkfield
 from WriteData import WriteData
@@ -24,5 +22,5 @@
 		self.nsteps                      = 0
 		self.maxiter_per_step            = float('NaN')
-		self.cost_functions              = float('NaN')
+		self.cost_functions              = '' 
 		self.cost_functions_coefficients = float('NaN')
 		self.gradient_scaling            = float('NaN')
@@ -78,9 +76,9 @@
 		self.vel_obs=project3d(md,'vector',self.vel_obs,'type','node')
 		self.thickness_obs=project3d(md,'vector',self.thickness_obs,'type','node')
-		if not numpy.any(numpy.isnan(self.cost_functions_coefficients)):
+		if not np.any(np.isnan(self.cost_functions_coefficients)):
 			self.cost_functions_coefficients=project3d(md,'vector',self.cost_functions_coefficients,'type','node')
-		if not numpy.any(numpy.isnan(self.min_parameters)):
+		if not np.any(np.isnan(self.min_parameters)):
 			self.min_parameters=project3d(md,'vector',self.min_parameters,'type','node')
-		if not numpy.any(numpy.isnan(self.max_parameters)):
+		if not np.any(np.isnan(self.max_parameters)):
 			self.max_parameters=project3d(md,'vector',self.max_parameters,'type','node')
 		return self
@@ -100,5 +98,5 @@
 		#maximum number of iteration in the optimization algorithm for
 		#each step
-		self.maxiter_per_step=20*numpy.ones(self.nsteps)
+		self.maxiter_per_step=20*np.ones(self.nsteps)
 
 		#the inversed parameter is updated as follows:
@@ -107,13 +105,13 @@
 		#inversed parameter (10^8 for B, 50 for drag) and can be decreased
 		#after the first iterations
-		self.gradient_scaling=50*numpy.ones((self.nsteps,1))
+		self.gradient_scaling=50*np.ones((self.nsteps,1))
 
 		#several responses can be used:
-		self.cost_functions=101
+		self.cost_functions=[101,]
 
 		#step_threshold is used to speed up control method. When
 		#misfit(1)/misfit(0) < self.step_threshold, we go directly to
 		#the next step
-		self.step_threshold=.7*numpy.ones(self.nsteps) #30 per cent decrement
+		self.step_threshold=.7*np.ones(self.nsteps) #30 per cent decrement
 
 		#cost_function_threshold is a criteria to stop the control methods.
@@ -130,6 +128,6 @@
 			return md
 
-		num_controls=numpy.size(md.inversion.control_parameters)
-		num_costfunc=numpy.size(md.inversion.cost_functions)
+		num_controls=np.size(md.inversion.control_parameters)
+		num_costfunc=np.size(md.inversion.cost_functions)
 
 		md = checkfield(md,'fieldname','inversion.iscontrol','values',[0,1])
@@ -146,9 +144,9 @@
 
 		#Only SSA, HO and FS are supported right now
-		if solution==StressbalanceSolutionEnum():
+		if solution=='StressbalanceSolution':
 			if not (md.flowequation.isSSA or md.flowequation.isHO or md.flowequation.isFS or md.flowequation.isL1L2):
 				md.checkmessage("'inversion can only be performed for SSA, HO or FS ice flow models");
 
-		if solution==BalancethicknessSolutionEnum():
+		if solution=='BalancethicknessSolution':
 			md = checkfield(md,'fieldname','inversion.thickness_obs','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 		else:
@@ -158,37 +156,37 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.0*24.0*3600.0
+		yts=md.constants.yts
 
-		WriteData(fid,'enum',InversionTypeEnum(),'data',0,'format','Integer')
-		WriteData(fid,'object',self,'fieldname','iscontrol','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','incomplete_adjoint','format','Boolean')
+		WriteData(fid,prefix,'name','md.inversion.type','data',0,'format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','iscontrol','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','incomplete_adjoint','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','vel_obs','format','DoubleMat','mattype',1,'scale',1./yts)
 		if not self.iscontrol:
 			return
-		WriteData(fid,'object',self,'fieldname','nsteps','format','Integer')
-		WriteData(fid,'object',self,'fieldname','maxiter_per_step','format','DoubleMat','mattype',3)
-		WriteData(fid,'object',self,'fieldname','cost_functions_coefficients','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'fieldname','gradient_scaling','format','DoubleMat','mattype',3)
-		WriteData(fid,'object',self,'fieldname','cost_function_threshold','format','Double')
-		WriteData(fid,'object',self,'fieldname','min_parameters','format','DoubleMat','mattype',3)
-		WriteData(fid,'object',self,'fieldname','max_parameters','format','DoubleMat','mattype',3)
-		WriteData(fid,'object',self,'fieldname','step_threshold','format','DoubleMat','mattype',3)
-		WriteData(fid,'object',self,'fieldname','vx_obs','format','DoubleMat','mattype',1,'scale',1./yts)
-		WriteData(fid,'object',self,'fieldname','vy_obs','format','DoubleMat','mattype',1,'scale',1./yts)
-		WriteData(fid,'object',self,'fieldname','vz_obs','format','DoubleMat','mattype',1,'scale',1./yts)
-		WriteData(fid,'object',self,'fieldname','thickness_obs','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'fieldname','surface_obs','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','nsteps','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','maxiter_per_step','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'fieldname','cost_functions_coefficients','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','gradient_scaling','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'fieldname','cost_function_threshold','format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','min_parameters','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'fieldname','max_parameters','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'fieldname','step_threshold','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'fieldname','vx_obs','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'fieldname','vy_obs','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'fieldname','vz_obs','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'fieldname','thickness_obs','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','surface_obs','format','DoubleMat','mattype',1)
 
 		#process control parameters
 		num_control_parameters=len(self.control_parameters)
-		data=numpy.array([StringToEnum(control_parameter)[0] for control_parameter in self.control_parameters]).reshape(1,-1)
-		WriteData(fid,'data',data,'enum',InversionControlParametersEnum(),'format','DoubleMat','mattype',3)
-		WriteData(fid,'data',num_control_parameters,'enum',InversionNumControlParametersEnum(),'format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','control_parameters','format','StringArray')
+		WriteData(fid,prefix,'data',num_control_parameters,'name','md.inversion.num_control_parameters','format','Integer')
 
 		#process cost functions
-		num_cost_functions=numpy.size(self.cost_functions)
+		num_cost_functions=np.size(self.cost_functions)
 		data=marshallcostfunctions(self.cost_functions)
-		WriteData(fid,'data',numpy.array(data).reshape(1,-1),'enum',InversionCostFunctionsEnum(),'format','DoubleMat','mattype',3)
-		WriteData(fid,'data',num_cost_functions,'enum',InversionNumCostFunctionsEnum(),'format','Integer')
+		WriteData(fid,prefix,'data',data,'name','md.inversion.cost_functions','format','StringArray')
+		WriteData(fid,prefix,'data',num_cost_functions,'name','md.inversion.num_cost_functions','format','Integer')
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/linearbasalforcings.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/linearbasalforcings.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/linearbasalforcings.py	(revision 23670)
@@ -1,7 +1,6 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
-import numpy
+import numpy as np
 
 class linearbasalforcings(object):
@@ -52,6 +51,6 @@
 	def initialize(self,md): # {{{
 
-		if numpy.all(numpy.isnan(self.groundedice_melting_rate)):
-			self.groundedice_melting_rate=numpy.zeros((md.mesh.numberofvertices,1))
+		if np.all(np.isnan(self.groundedice_melting_rate)):
+			self.groundedice_melting_rate=np.zeros((md.mesh.numberofvertices))
 			print("      no basalforcings.groundedice_melting_rate specified: values set as zero")
 
@@ -68,41 +67,34 @@
 	def checkconsistency(self,md,solution,analyses):    # {{{
 
-		if MasstransportAnalysisEnum() in analyses and not (solution==TransientSolutionEnum() and not md.transient.ismasstransport):
+		if 'MasstransportAnalysis' in analyses and not (solution=='TransientSolution' and not md.transient.ismasstransport):
 			md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1)
-			md = checkfield(md,'fieldname','basalforcings.deepwater_melting_rate','>=',0);
-			md = checkfield(md,'fieldname','basalforcings.deepwater_elevation','<',md.basalforcings.upperwater_elevation);
-			md = checkfield(md,'fieldname','basalforcings.upperwater_elevation','<',0);
+			md = checkfield(md,'fieldname','basalforcings.deepwater_melting_rate','>=',0,'singletimeseries',1)
+			md = checkfield(md,'fieldname','basalforcings.deepwater_elevation','<','basalforcings.upperwater_elevation','singletimeseries',1)
+			md = checkfield(md,'fieldname','basalforcings.upperwater_elevation','<=',0,'singletimeseries',1)
 
-		if BalancethicknessAnalysisEnum() in analyses:
+		if 'BalancethicknessAnalysis' in analyses:
 			md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
-			md = checkfield(md,'fieldname','basalforcings.deepwater_melting_rate','>=',0);
-			md = checkfield(md,'fieldname','basalforcings.deepwater_elevation','<',md.basalforcings.upperwater_elevation);
-			md = checkfield(md,'fieldname','basalforcings.upperwater_elevation','<',0);
+			md = checkfield(md,'fieldname','basalforcings.deepwater_melting_rate','>=',0,'singletimeseries',1)
+			md = checkfield(md,'fieldname','basalforcings.deepwater_elevation','<','basalforcings.upperwater_elevation','singletimeseries',1)
+			md = checkfield(md,'fieldname','basalforcings.upperwater_elevation','<=',0,'singletimeseries',1)
 
-		if ThermalAnalysisEnum() in analyses and not (solution==TransientSolutionEnum() and not md.transient.isthermal):
+		if 'ThermalAnalysis' in analyses and not (solution=='TransientSolution' and not md.transient.isthermal):
 			md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1)
-			md = checkfield(md,'fieldname','basalforcings.deepwater_melting_rate','>=',0);
-			md = checkfield(md,'fieldname','basalforcings.deepwater_elevation','<',md.basalforcings.upperwater_elevation);
-			md = checkfield(md,'fieldname','basalforcings.upperwater_elevation','<',0);
+			md = checkfield(md,'fieldname','basalforcings.deepwater_melting_rate','>=',0,'singletimeseries',1)
+			md = checkfield(md,'fieldname','basalforcings.deepwater_elevation','<','basalforcings.upperwater_elevation','singletimeseries',1)
+			md = checkfield(md,'fieldname','basalforcings.upperwater_elevation','<=',0,'singletimeseries',1)
 			md = checkfield(md,'fieldname','basalforcings.geothermalflux','NaN',1,'Inf',1,'timeseries',1,'>=',0)
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.0*24.0*3600.0
+		yts=md.constants.yts
 
-		floatingice_melting_rate = numpy.zeros((md.mesh.numberofvertices,1))
-		pos=numpy.nonzero(md.geometry.base<=md.basalforcings.deepwater_elevation)
-		floatingice_melting_rate[pos]=md.basalforcings.deepwater_melting_rate
-		pos=numpy.nonzero(numpy.logical_and(md.geometry.base>md.basalforcings.deepwater_elevation,md.geometry.base<md.basalforcings.upperwater_elevation))
-		floatingice_melting_rate[pos]=md.basalforcings.deepwater_melting_rate*(md.geometry.base[pos]-md.basalforcings.upperwater_elevation)/(md.basalforcings.deepwater_elevation-md.basalforcings.upperwater_elevation)
-
-		WriteData(fid,'enum',BasalforcingsEnum(),'data',LinearFloatingMeltRateEnum(),'format','Integer');
-		WriteData(fid,'object',self,'fieldname','groundedice_melting_rate','enum',BasalforcingsGroundediceMeltingRateEnum(),'format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'data',floatingice_melting_rate,'enum',BasalforcingsFloatingiceMeltingRateEnum(),'format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'fieldname','geothermalflux','enum',BasalforcingsGeothermalfluxEnum(),'format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'fieldname','deepwater_melting_rate','enum',BasalforcingsDeepwaterMeltingRateEnum(),'format','Double','scale',1./yts)
-		WriteData(fid,'object',self,'fieldname','deepwater_elevation','enum',BasalforcingsDeepwaterElevationEnum(),'format','Double')
-		WriteData(fid,'object',self,'fieldname','upperwater_elevation','enum',BasalforcingsUpperwaterElevationEnum(),'format','Double')
+		WriteData(fid,prefix,'name','md.basalforcings.model','data',2,'format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','groundedice_melting_rate','name','md.basalforcings.groundedice_melting_rate','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'fieldname','geothermalflux','name','md.basalforcings.geothermalflux','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'fieldname','deepwater_melting_rate','format','DoubleMat','mattype',3,'timeserieslength',2,'name','md.basalforcings.deepwater_melting_rate','scale',1./yts,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'fieldname','deepwater_elevation','format','DoubleMat','mattype',3,'name','md.basalforcings.deepwater_elevation','yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'fieldname','upperwater_elevation','format','DoubleMat','mattype',3,'name','md.basalforcings.upperwater_elevation','yts',md.constants.yts)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/m1qn3inversion.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/m1qn3inversion.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/m1qn3inversion.py	(revision 23670)
@@ -1,7 +1,5 @@
-import numpy
+import numpy as np
 from project3d import project3d
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
-from StringToEnum import StringToEnum
 from checkfield import checkfield
 from WriteData import WriteData
@@ -100,9 +98,9 @@
 		self.vel_obs=project3d(md,'vector',self.vel_obs,'type','node')
 		self.thickness_obs=project3d(md,'vector',self.thickness_obs,'type','node')
-		if not numpy.any(numpy.isnan(self.cost_functions_coefficients)):
+		if not np.any(np.isnan(self.cost_functions_coefficients)):
 			self.cost_functions_coefficients=project3d(md,'vector',self.cost_functions_coefficients,'type','node')
-		if not numpy.any(numpy.isnan(self.min_parameters)):
+		if not np.any(np.isnan(self.min_parameters)):
 			self.min_parameters=project3d(md,'vector',self.min_parameters,'type','node')
-		if not numpy.any(numpy.isnan(self.max_parameters)):
+		if not np.any(np.isnan(self.max_parameters)):
 			self.max_parameters=project3d(md,'vector',self.max_parameters,'type','node')
 		return self
@@ -139,6 +137,6 @@
 			return md
 
-		num_controls=numpy.size(md.inversion.control_parameters)
-		num_costfunc=numpy.size(md.inversion.cost_functions)
+		num_controls=np.size(md.inversion.control_parameters)
+		num_costfunc=np.size(md.inversion.cost_functions)
 
 		md = checkfield(md,'fieldname','inversion.iscontrol','values',[0,1])
@@ -155,5 +153,5 @@
 		md = checkfield(md,'fieldname','inversion.max_parameters','size',[md.mesh.numberofvertices,num_controls])
 
-		if solution==BalancethicknessSolutionEnum():
+		if solution=='BalancethicknessSolution':
 			md = checkfield(md,'fieldname','inversion.thickness_obs','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 		else:
@@ -163,36 +161,35 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.0*24.0*3600.0
+		yts=md.constants.yts
 
-		WriteData(fid,'object',self,'class','inversion','fieldname','iscontrol','format','Boolean')
-		WriteData(fid,'enum',InversionTypeEnum(),'data',2,'format','Integer')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','iscontrol','format','Boolean')
+		WriteData(fid,prefix,'name','md.inversion.type','data',2,'format','Integer')
 		if not self.iscontrol:
 			return
-		WriteData(fid,'object',self,'class','inversion','fieldname','incomplete_adjoint','format','Boolean')
-		WriteData(fid,'object',self,'class','inversion','fieldname','control_scaling_factors','format','DoubleMat','mattype',3)
-		WriteData(fid,'object',self,'class','inversion','fieldname','maxsteps','format','Integer')
-		WriteData(fid,'object',self,'class','inversion','fieldname','maxiter','format','Integer')
-		WriteData(fid,'object',self,'class','inversion','fieldname','dxmin','format','Double')
-		WriteData(fid,'object',self,'class','inversion','fieldname','gttol','format','Double')
-		WriteData(fid,'object',self,'class','inversion','fieldname','cost_functions_coefficients','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'class','inversion','fieldname','min_parameters','format','DoubleMat','mattype',3)
-		WriteData(fid,'object',self,'class','inversion','fieldname','max_parameters','format','DoubleMat','mattype',3)
-		WriteData(fid,'object',self,'class','inversion','fieldname','vx_obs','format','DoubleMat','mattype',1,'scale',1./yts)
-		WriteData(fid,'object',self,'class','inversion','fieldname','vy_obs','format','DoubleMat','mattype',1,'scale',1./yts)
-		WriteData(fid,'object',self,'class','inversion','fieldname','vz_obs','format','DoubleMat','mattype',1,'scale',1./yts)
-		WriteData(fid,'object',self,'class','inversion','fieldname','thickness_obs','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','incomplete_adjoint','format','Boolean')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','control_scaling_factors','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','maxsteps','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','maxiter','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','dxmin','format','Double')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','gttol','format','Double')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','cost_functions_coefficients','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','min_parameters','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','max_parameters','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','vx_obs','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','vy_obs','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','vz_obs','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','thickness_obs','format','DoubleMat','mattype',1)
 
 		#process control parameters
 		num_control_parameters=len(self.control_parameters)
-		data=numpy.array([StringToEnum(control_parameter)[0] for control_parameter in self.control_parameters]).reshape(1,-1)
-		WriteData(fid,'data',data,'enum',InversionControlParametersEnum(),'format','DoubleMat','mattype',3)
-		WriteData(fid,'data',num_control_parameters,'enum',InversionNumControlParametersEnum(),'format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','control_parameters','format','StringArray')
+		WriteData(fid,prefix,'data',num_control_parameters,'name','md.inversion.num_control_parameters','format','Integer')
 
 		#process cost functions
-		num_cost_functions=numpy.size(self.cost_functions)
+		num_cost_functions=np.size(self.cost_functions)
 		data=marshallcostfunctions(self.cost_functions)
-		WriteData(fid,'data',numpy.array(data).reshape(1,-1),'enum',InversionCostFunctionsEnum(),'format','DoubleMat','mattype',3)
-		WriteData(fid,'data',num_cost_functions,'enum',InversionNumCostFunctionsEnum(),'format','Integer')
+		WriteData(fid,prefix,'data',data,'name','md.inversion.cost_functions','format','StringArray')
+		WriteData(fid,prefix,'data',num_cost_functions,'name','md.inversion.num_cost_functions','format','Integer')
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/mask.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/mask.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/mask.py	(revision 23670)
@@ -1,6 +1,5 @@
-import numpy
+import numpy as np
 from fielddisplay import fielddisplay
 from project3d import project3d
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -39,25 +38,16 @@
 	#}}}
 	def checkconsistency(self,md,solution,analyses):    # {{{
+		if(solution=='LoveSolution'):
+			return
 
 		md = checkfield(md,'fieldname','mask.ice_levelset'        ,'size',[md.mesh.numberofvertices])
-		isice=numpy.array(md.mask.ice_levelset<=0,int)
-		if numpy.sum(isice)==0:
+		isice=np.array(md.mask.ice_levelset<=0,int)
+		if np.sum(isice)==0:
 			raise TypeError("no ice present in the domain")
-
-		icefront=numpy.sum(md.mask.ice_levelset[md.mesh.elements-1]==0,axis=1)
-		if (max(icefront)==3 and m.strcmp(md.mesh.elementtype(),'Tria')) or (max(icefront==6) and m.strcmp(md.mesh.elementtype(),'Penta')):
-			raise TypeError("At least one element has all nodes on ice front, change md.mask.ice_levelset to fix it")
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'object',self,'fieldname','groundedice_levelset','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'fieldname','ice_levelset','format','DoubleMat','mattype',1)
-
-		# get mask of vertices of elements with ice
-		isice=numpy.array(md.mask.ice_levelset<0.,int)
-		vlist = numpy.zeros((md.mesh.numberofvertices,1), dtype=int)
-		pos=numpy.nonzero(numpy.sum(isice[md.mesh.elements-1],axis=1))[0]
-		vlist[md.mesh.elements[pos,:]-1]=1
-		WriteData(fid,'data',vlist,'enum',IceMaskNodeActivationEnum(),'format','DoubleMat','mattype',1);
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'object',self,'fieldname','groundedice_levelset','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'fieldname','ice_levelset','format','DoubleMat','mattype',1)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/massfluxatgate.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/massfluxatgate.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/massfluxatgate.py	(revision 23670)
@@ -1,4 +1,3 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from pairoptions import pairoptions
 from checkfield import checkfield
@@ -15,8 +14,8 @@
 	"""
 
-	def __init__(self,**kwargs): # {{{
+	def __init__(self,*args): # {{{
 
 		self.name            = ''
-		self.definitionenum  = 0
+		self.definitionstring  = ''
 		self.profilename     = ''
 		self.segments        = float('NaN')
@@ -26,5 +25,5 @@
 
 		#use provided options to change fields
-		options=pairoptions(**kwargs)
+		options=pairoptions(*args)
 
 		#OK get other fields
@@ -36,8 +35,11 @@
 		string="   Massfluxatgate:"
 		string="%s\n%s"%(string,fielddisplay(self,'name','identifier for this massfluxatgate response'))
-		string="%s\n%s"%(string,fielddisplay(self,'definitionenum','enum that identifies this output definition uniquely, from Outputdefinition[1-10]Enum'))
+		string="%s\n%s"%(string,fielddisplay(self,'definitionstring','string that identifies this output definition uniquely, from Outputdefinition[1-100]'))
 		string="%s\n%s"%(string,fielddisplay(self,'profilename','name of file (shapefile or argus file) defining a profile (or gate)'))
 		return string
 		#}}}
+	def extrude(self,md): # {{{
+		return self
+	   #}}}
 	def setdefaultparameters(self): # {{{
 		return self
@@ -50,6 +52,11 @@
 		if  not isinstance(self.profilename, str):
 			raise RuntimeError("massfluxatgate error message: 'profilename' field should be a string!") 
-
-			md = checkfield(md,'field',self.definitionenum,'values',[Outputdefinition1Enum(),Outputdefinition2Enum(),Outputdefinition3Enum(),Outputdefinition4Enum(),Outputdefinition5Enum(),Outputdefinition6Enum(),Outputdefinition7Enum(),Outputdefinition8Enum(),Outputdefinition9Enum(),Outputdefinition10Enum()])
+		
+		OutputdefinitionStringArray=[]
+		for i in range(1,100):
+			x='Outputdefinition'+str(i)
+			OutputdefinitionStringArray.append(x)
+			
+		md = checkfield(md,'field',self.definitionstring,'values',OutputdefinitionStringArray)
 		
 		#check the profilename points to a file!: 
@@ -59,5 +66,5 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 		
 		#before marshalling, we need to create the segments out of the profilename: 
@@ -65,7 +72,7 @@
 
 		#ok, marshall name and segments: 
-		WriteData(fid,'object',self,'fieldname','name','format','String')
-		WriteData(fid,'object',self,'fieldname','definitionenum','format','Integer')
-		WriteData(fid,'object',self,'fieldname','segments','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'data',self.name,'name','md.massfluxatgate.name','format','String');
+		WriteData(fid,prefix,'data',self.definitionstring,'name','md.massfluxatgate.definitionstring','format','String');
+		WriteData(fid,prefix,'data',self.segments,'name','md.massfluxatgate.segments','format','DoubleMat','mattype',1);
 
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/masstransport.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/masstransport.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/masstransport.py	(revision 23670)
@@ -1,6 +1,4 @@
 from fielddisplay import fielddisplay
 from project3d import project3d
-from EnumDefinitions import *
-from StringToEnum import StringToEnum
 from checkfield import checkfield
 from WriteData import WriteData
@@ -69,5 +67,5 @@
 
 		#Early return
-		if (MasstransportAnalysisEnum() not in analyses) or (solution==TransientSolutionEnum() and not md.transient.ismasstransport):
+		if ('MasstransportAnalysis' not in analyses) or (solution=='TransientSolution' and not md.transient.ismasstransport):
 			return md
 
@@ -81,15 +79,15 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
-		yts=365.*24.*3600.
+		yts=md.constants.yts
 
-		WriteData(fid,'object',self,'fieldname','spcthickness','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'fieldname','isfreesurface','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','min_thickness','format','Double')
-		WriteData(fid,'data',StringToEnum(self.hydrostatic_adjustment)[0],'format','Integer','enum',MasstransportHydrostaticAdjustmentEnum())
-		WriteData(fid,'object',self,'fieldname','stabilization','format','Integer')
-		WriteData(fid,'object',self,'fieldname','vertex_pairing','format','DoubleMat','mattype',3)
-		WriteData(fid,'object',self,'fieldname','penalty_factor','format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','spcthickness','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'fieldname','isfreesurface','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','min_thickness','format','Double')
+		WriteData(fid,prefix,'data',self.hydrostatic_adjustment,'format','String','name','md.masstransport.hydrostatic_adjustment')
+		WriteData(fid,prefix,'object',self,'fieldname','stabilization','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','vertex_pairing','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'fieldname','penalty_factor','format','Double')
 
 		#process requested outputs
@@ -99,4 +97,4 @@
 			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
 			outputs    =outputscopy
-		WriteData(fid,'data',outputs,'enum',MasstransportRequestedOutputsEnum(),'format','StringArray')
+		WriteData(fid,prefix,'data',outputs,'name','md.masstransport.requested_outputs','format','StringArray')
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/matdamageice.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/matdamageice.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/matdamageice.py	(revision 23670)
@@ -1,6 +1,4 @@
 from fielddisplay import fielddisplay
 from project3d import project3d
-from EnumDefinitions import MaterialsEnum, MatdamageiceEnum, MaterialsRheologyLawEnum, MaterialsRhoSeawaterEnum
-from StringToEnum import StringToEnum
 from checkfield import checkfield
 from WriteData import WriteData
@@ -31,9 +29,13 @@
 		self.rheology_law              = ''
 
-		#gia: 
+		#giaivins: 
 		self.lithosphere_shear_modulus  = 0.
 		self.lithosphere_density        = 0.
 		self.mantle_shear_modulus       = 0.
 		self.mantle_density             = 0.
+		
+		#SLR
+		self.earth_density= 5512;  # average density of the Earth, (kg/m^3)
+
 
 		self.setdefaultparameters()
@@ -54,11 +56,13 @@
 		string="%s\n%s"%(string,fielddisplay(self,"mixed_layer_capacity","mixed layer capacity [W/kg/K]"))
 		string="%s\n%s"%(string,fielddisplay(self,"thermal_exchange_velocity","thermal exchange velocity [m/s]"))
-		string="%s\n%s"%(string,fielddisplay(self,"rheology_B","flow law parameter [Pa/s^(1/n)]"))
+		string="%s\n%s"%(string,fielddisplay(self,"rheology_B","flow law parameter [Pa s^(1/n)]"))
 		string="%s\n%s"%(string,fielddisplay(self,"rheology_n","Glen's flow law exponent"))
-		string="%s\n%s"%(string,fielddisplay(self,"rheology_law","law for the temperature dependance of the rheology: 'None', 'Cuffey', 'Paterson', 'Arrhenius' or 'LliboutryDuval'"))
+		string="%s\n%s"%(string,fielddisplay(self,"rheology_law","law for the temperature dependance of the rheology: 'None', 'BuddJacka', 'Cuffey', 'CuffeyTemperate', 'Paterson', 'Arrhenius' or 'LliboutryDuval'"))
 		string="%s\n%s"%(string,fielddisplay(self,"lithosphere_shear_modulus","Lithosphere shear modulus [Pa]"))
 		string="%s\n%s"%(string,fielddisplay(self,"lithosphere_density","Lithosphere density [g/cm^-3]"))
 		string="%s\n%s"%(string,fielddisplay(self,"mantle_shear_modulus","Mantle shear modulus [Pa]"))
 		string="%s\n%s"%(string,fielddisplay(self,"mantle_density","Mantle density [g/cm^-3]"))
+		string="%s\n%s"%(string,fielddisplay(self,"earth_density","Mantle density [kg/m^-3]"))
+
 
 		return string
@@ -115,4 +119,8 @@
 		self.mantle_shear_modulus       = 1.45*10**11 # (Pa)
 		self.mantle_density             = 3.34        # (g/cm^-3)
+		
+		#SLR
+		self.earth_density= 5512;  #average density of the Earth, (kg/m^3)
+
 
 		return self
@@ -125,32 +133,36 @@
 		md = checkfield(md,'fieldname','materials.rheology_B','>',0,'size',[md.mesh.numberofvertices])
 		md = checkfield(md,'fieldname','materials.rheology_n','>',0,'size',[md.mesh.numberofelements])
-		md = checkfield(md,'fieldname','materials.rheology_law','values',['None','Cuffey','Paterson','Arrhenius','LliboutryDuval'])
+		md = checkfield(md,'fieldname','materials.rheology_law','values',['None', 'BuddJacka', 'Cuffey', 'CuffeyTemperate', 'Paterson','Arrhenius','LliboutryDuval'])
 		md = checkfield(md,'fieldname','materials.lithosphere_shear_modulus','>',0,'numel',[1]);
 		md = checkfield(md,'fieldname','materials.lithosphere_density','>',0,'numel',[1]);
 		md = checkfield(md,'fieldname','materials.mantle_shear_modulus','>',0,'numel',[1]);
 		md = checkfield(md,'fieldname','materials.mantle_density','>',0,'numel',[1]);
+		md = checkfield(md,'fieldname','materials.earth_density','>',0,'numel',[1]);
+
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'enum',MaterialsEnum(),'data',MatdamageiceEnum(),'format','Integer');
-		WriteData(fid,'object',self,'class','materials','fieldname','rho_ice','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','rho_water','enum',MaterialsRhoSeawaterEnum(),'format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','rho_freshwater','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','mu_water','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','heatcapacity','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','latentheat','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','thermalconductivity','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','temperateiceconductivity','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','meltingpoint','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','beta','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','mixed_layer_capacity','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','thermal_exchange_velocity','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','rheology_B','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'class','materials','fieldname','rheology_n','format','DoubleMat','mattype',2)
-		WriteData(fid,'data',StringToEnum(self.rheology_law)[0],'enum',MaterialsRheologyLawEnum(),'format','Integer')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'name','md.materials.type','data',1,'format','Integer');
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','rho_ice','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','rho_water','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','rho_freshwater','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','mu_water','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','heatcapacity','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','latentheat','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','thermalconductivity','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','temperateiceconductivity','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','meltingpoint','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','beta','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','mixed_layer_capacity','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','thermal_exchange_velocity','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','rheology_B','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','rheology_n','format','DoubleMat','mattype',2)
+		WriteData(fid,prefix,'data',self.rheology_law,'name','md.materials.rheology_law','format','String')
 
-		WriteData(fid,'object',self,'class','materials','fieldname','lithosphere_shear_modulus','format','Double');
-		WriteData(fid,'object',self,'class','materials','fieldname','lithosphere_density','format','Double','scale',10.**3.);
-		WriteData(fid,'object',self,'class','materials','fieldname','mantle_shear_modulus','format','Double');
-		WriteData(fid,'object',self,'class','materials','fieldname','mantle_density','format','Double','scale',10.**3.);
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','lithosphere_shear_modulus','format','Double');
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','lithosphere_density','format','Double','scale',10.**3.);
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','mantle_shear_modulus','format','Double');
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','mantle_density','format','Double','scale',10.**3.);
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','earth_density','format','Double');
+
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/matice.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/matice.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/matice.py	(revision 23670)
@@ -1,6 +1,4 @@
 from fielddisplay import fielddisplay
 from project3d import project3d
-from EnumDefinitions import *
-from StringToEnum import StringToEnum
 from checkfield import checkfield
 from WriteData import WriteData
@@ -31,9 +29,14 @@
 		self.rheology_law              = ''
 
-		#gia: 
+		#giaivins: 
 		self.lithosphere_shear_modulus  = 0.
 		self.lithosphere_density        = 0.
 		self.mantle_shear_modulus       = 0.
-		self.mantle_density             = 0.
+		self.mantle_density             = 0.  
+		
+		#SLR
+		self.earth_density= 5512;  
+
+
 
 		self.setdefaultparameters()
@@ -54,11 +57,13 @@
 		string="%s\n%s"%(string,fielddisplay(self,"mixed_layer_capacity","mixed layer capacity [W/kg/K]"))
 		string="%s\n%s"%(string,fielddisplay(self,"thermal_exchange_velocity","thermal exchange velocity [m/s]"))
-		string="%s\n%s"%(string,fielddisplay(self,"rheology_B","flow law parameter [Pa/s^(1/n)]"))
+		string="%s\n%s"%(string,fielddisplay(self,"rheology_B","flow law parameter [Pa s^(1/n)]"))
 		string="%s\n%s"%(string,fielddisplay(self,"rheology_n","Glen's flow law exponent"))
-		string="%s\n%s"%(string,fielddisplay(self,"rheology_law","law for the temperature dependance of the rheology: 'None', 'Cuffey', 'Paterson', 'Arrhenius' or 'LliboutryDuval'"))
+		string="%s\n%s"%(string,fielddisplay(self,"rheology_law","law for the temperature dependance of the rheology: 'None', 'BuddJacka', 'Cuffey', 'CuffeyTemperate', 'Paterson', 'Arrhenius' or 'LliboutryDuval'"))
 		string="%s\n%s"%(string,fielddisplay(self,"lithosphere_shear_modulus","Lithosphere shear modulus [Pa]"))
 		string="%s\n%s"%(string,fielddisplay(self,"lithosphere_density","Lithosphere density [g/cm^-3]"))
 		string="%s\n%s"%(string,fielddisplay(self,"mantle_shear_modulus","Mantle shear modulus [Pa]"))
 		string="%s\n%s"%(string,fielddisplay(self,"mantle_density","Mantle density [g/cm^-3]"))
+		string="%s\n%s"%(string,fielddisplay(self,"earth_density","Mantle density [kg/m^-3]"))
+
 
 		return string
@@ -115,4 +120,8 @@
 		self.mantle_shear_modulus       = 1.45*10**11 # (Pa)
 		self.mantle_density             = 3.34        # (g/cm^-3)
+		
+		#SLR
+		self.earth_density= 5512;  # average density of the Earth, (kg/m^3)
+
 
 		return self
@@ -125,33 +134,36 @@
 		md = checkfield(md,'fieldname','materials.rheology_B','>',0,'timeseries',1,'NaN',1,'Inf',1)
 		md = checkfield(md,'fieldname','materials.rheology_n','>',0,'size',[md.mesh.numberofelements])
-		md = checkfield(md,'fieldname','materials.rheology_law','values',['None','Cuffey','Paterson','Arrhenius','LliboutryDuval'])
+		md = checkfield(md,'fieldname','materials.rheology_law','values',['None','BuddJacka','Cuffey','CuffeyTemperate','Paterson','Arrhenius','LliboutryDuval'])
 		md = checkfield(md,'fieldname','materials.lithosphere_shear_modulus','>',0,'numel',[1]);
 		md = checkfield(md,'fieldname','materials.lithosphere_density','>',0,'numel',[1]);
 		md = checkfield(md,'fieldname','materials.mantle_shear_modulus','>',0,'numel',[1]);
 		md = checkfield(md,'fieldname','materials.mantle_density','>',0,'numel',[1]);
+		md = checkfield(md,'fieldname','materials.earth_density','>',0,'numel',[1]);
+
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'enum',MaterialsEnum(),'data',MaticeEnum(),'format','Integer');
-		WriteData(fid,'object',self,'class','materials','fieldname','rho_ice','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','rho_water','enum',MaterialsRhoSeawaterEnum(),'format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','rho_freshwater','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','mu_water','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','heatcapacity','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','latentheat','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','thermalconductivity','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','temperateiceconductivity','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','meltingpoint','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','beta','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','mixed_layer_capacity','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','thermal_exchange_velocity','format','Double')
-		WriteData(fid,'object',self,'class','materials','fieldname','rheology_B','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'class','materials','fieldname','rheology_B','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'class','materials','fieldname','rheology_n','format','DoubleMat','mattype',2)
-		WriteData(fid,'data',StringToEnum(self.rheology_law)[0],'enum',MaterialsRheologyLawEnum(),'format','Integer')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'name','md.materials.type','data',3,'format','Integer');
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','rho_ice','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','rho_water','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','rho_freshwater','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','mu_water','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','heatcapacity','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','latentheat','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','thermalconductivity','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','temperateiceconductivity','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','meltingpoint','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','beta','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','mixed_layer_capacity','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','thermal_exchange_velocity','format','Double')
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','rheology_B','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','rheology_n','format','DoubleMat','mattype',2)
+		WriteData(fid,prefix,'data',self.rheology_law,'name','md.materials.rheology_law','format','String')
 
-		WriteData(fid,'object',self,'class','materials','fieldname','lithosphere_shear_modulus','format','Double');
-		WriteData(fid,'object',self,'class','materials','fieldname','lithosphere_density','format','Double','scale',10.**3.);
-		WriteData(fid,'object',self,'class','materials','fieldname','mantle_shear_modulus','format','Double');
-		WriteData(fid,'object',self,'class','materials','fieldname','mantle_density','format','Double','scale',10.**3.);
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','lithosphere_shear_modulus','format','Double');
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','lithosphere_density','format','Double','scale',10.**3.);
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','mantle_shear_modulus','format','Double');
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','mantle_density','format','Double','scale',10.**3.);
+		WriteData(fid,prefix,'object',self,'class','materials','fieldname','earth_density','format','Double');
+
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/mesh2d.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/mesh2d.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/mesh2d.py	(revision 23670)
@@ -1,8 +1,7 @@
-import numpy
+import numpy as np
 from fielddisplay import fielddisplay
 from checkfield import checkfield
+import MatlabFuncs as m
 from WriteData import WriteData
-from EnumDefinitions import *
-import MatlabFuncs as m
 
 class mesh2d(object):
@@ -25,4 +24,5 @@
 		self.long                        = float('NaN');
 		self.epsg                        = 0;
+		self.scale_factor                = float('NaN');
 
 		self.vertexonboundary            = float('NaN');
@@ -57,6 +57,6 @@
 		string="%s\n%s"%(string,fielddisplay(self,"segments","edges on domain boundary (vertex1 vertex2 element)"))
 		string="%s\n%s"%(string,fielddisplay(self,"segmentmarkers","number associated to each segment"))
-		string="%s\n%s"%(string,fielddisplay(self,"vertexconnectivity","list of vertices connected to vertex_i"))
-		string="%s\n%s"%(string,fielddisplay(self,"elementconnectivity","list of vertices connected to element_i"))
+		string="%s\n%s"%(string,fielddisplay(self,"vertexconnectivity","list of elements connected to vertex_i"))
+		string="%s\n%s"%(string,fielddisplay(self,"elementconnectivity","list of elements adjacent to element_i"))
 		string="%s\n%s"%(string,fielddisplay(self,"average_vertex_connectivity","average number of vertices connected to one vertex"))
 
@@ -69,4 +69,5 @@
 		string="%s\n%s"%(string,fielddisplay(self,"long","vertices longitude [degrees]"))
 		string="%s\n%s"%(string,fielddisplay(self,"epsg","EPSG code (ex: 3413 for UPS Greenland, 3031 for UPS Antarctica)"))
+		string="%s\n%s"%(string,fielddisplay(self,"scale_factor","Projection correction for volume, area, etc. computation"))
 		return string
 		#}}}
@@ -83,17 +84,21 @@
 	#}}}
 	def checkconsistency(self,md,solution,analyses):    # {{{
+		if(solution=='LoveSolution'):
+			return
 
 		md = checkfield(md,'fieldname','mesh.x','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 		md = checkfield(md,'fieldname','mesh.y','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
-		md = checkfield(md,'fieldname','mesh.elements','NaN',1,'Inf',1,'>',0,'values',numpy.arange(1,md.mesh.numberofvertices+1))
+		md = checkfield(md,'fieldname','mesh.elements','NaN',1,'Inf',1,'>',0,'values',np.arange(1,md.mesh.numberofvertices+1))
 		md = checkfield(md,'fieldname','mesh.elements','size',[md.mesh.numberofelements,3])
-#		if numpy.any(numpy.logical_not(m.ismember(numpy.arange(1,md.mesh.numberofvertices+1),md.mesh.elements))):
-		if any(numpy.logical_not(m.ismember(numpy.arange(1,md.mesh.numberofvertices+1),md.mesh.elements))):
-			[x for x in A if not x in B]
+		if np.any(np.logical_not(m.ismember(np.arange(1,md.mesh.numberofvertices+1),md.mesh.elements))):
 			md.checkmessage("orphan nodes have been found. Check the mesh outline")
 		md = checkfield(md,'fieldname','mesh.numberofelements','>',0)
 		md = checkfield(md,'fieldname','mesh.numberofvertices','>',0)
 		md = checkfield(md,'fieldname','mesh.average_vertex_connectivity','>=',9,'message',"'mesh.average_vertex_connectivity' should be at least 9 in 2d")
-		if solution==ThermalSolutionEnum():
+		md = checkfield(md,'fieldname','mesh.segments','NaN',1,'Inf',1,'>',0,'size',[np.nan,3]);
+		if(np.size(self.scale_factor)>1):
+                        md = checkfield(md,'fieldname','mesh.scale_factor','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
+                
+		if solution=='ThermalSolution':
 			md.checkmessage("thermal not supported for 2d mesh")
 
@@ -109,14 +114,20 @@
 		return "Tria"
 	#}}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'enum',DomainTypeEnum(),'data',StringToEnum("Domain"+self.domaintype())[0],'format','Integer');
-		WriteData(fid,'enum',DomainDimensionEnum(),'data',self.dimension(),'format','Integer');
-		WriteData(fid,'enum',MeshElementtypeEnum(),'data',StringToEnum(self.elementtype())[0],'format','Integer');
-		WriteData(fid,'object',self,'class','mesh','fieldname','x','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'class','mesh','fieldname','y','format','DoubleMat','mattype',1)
-		WriteData(fid,'enum',MeshZEnum(),'data',numpy.zeros(self.numberofvertices),'format','DoubleMat','mattype',1);
-		WriteData(fid,'object',self,'class','mesh','fieldname','elements','format','DoubleMat','mattype',2)
-		WriteData(fid,'object',self,'class','mesh','fieldname','numberofelements','format','Integer')
-		WriteData(fid,'object',self,'class','mesh','fieldname','numberofvertices','format','Integer')
-		WriteData(fid,'object',self,'class','mesh','fieldname','average_vertex_connectivity','format','Integer')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'name','md.mesh.domain_type','data',"Domain"+self.domaintype(),'format','String');
+		WriteData(fid,prefix,'name','md.mesh.domain_dimension','data',self.dimension(),'format','Integer');
+		WriteData(fid,prefix,'name','md.mesh.elementtype','data',self.elementtype(),'format','String');
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','x','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','y','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'name','md.mesh.z','data',np.zeros(self.numberofvertices),'format','DoubleMat','mattype',1);
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','elements','format','DoubleMat','mattype',2)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','numberofelements','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','numberofvertices','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','average_vertex_connectivity','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','vertexonboundary','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','segments','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','scale_factor','format','DoubleMat','mattype',1)
+		if md.transient.isoceancoupling:
+			WriteData(fid,prefix,'object',self,'class','mesh','fieldname','lat','format','DoubleMat','mattype',1)
+			WriteData(fid,prefix,'object',self,'class','mesh','fieldname','long','format','DoubleMat','mattype',1)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/mesh3dprisms.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/mesh3dprisms.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/mesh3dprisms.py	(revision 23670)
@@ -1,5 +1,4 @@
-import numpy
+import numpy as np
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import *
 import MatlabFuncs as m
@@ -26,4 +25,5 @@
 		self.long                        = float('NaN');
 		self.epsg                        = 0;
+		self.scale_factor                = float('NaN');
 
 		self.vertexonbase                = float('NaN');
@@ -74,11 +74,11 @@
 		string="%s\n%s"%(string,fielddisplay(self,"vertexonbase","lower vertices flags list"))
 		string="%s\n%s"%(string,fielddisplay(self,"vertexonsurface","upper vertices flags list"))
-		string="%s\n%s"%(string,fielddisplay(self,"uppervertex","upper vertex list (-1 for vertex on the upper surface)"))
-		string="%s\n%s"%(string,fielddisplay(self,"upperelements","upper element list (-1 for element on the upper layer)"))
-		string="%s\n%s"%(string,fielddisplay(self,"lowervertex","lower vertex list (-1 for vertex on the lower surface)"))
-		string="%s\n%s"%(string,fielddisplay(self,"lowerelements","lower element list (-1 for element on the lower layer)"))
+		string="%s\n%s"%(string,fielddisplay(self,"uppervertex","upper vertex list (NaN for vertex on the upper surface)"))
+		string="%s\n%s"%(string,fielddisplay(self,"upperelements","upper element list (NaN for element on the upper layer)"))
+		string="%s\n%s"%(string,fielddisplay(self,"lowervertex","lower vertex list (NaN for vertex on the lower surface)"))
+		string="%s\n%s"%(string,fielddisplay(self,"lowerelements","lower element list (NaN for element on the lower layer)"))
 		string="%s\n%s"%(string,fielddisplay(self,"vertexonboundary","vertices on the boundary of the domain flag list"))
-		string="%s\n%s"%(string,fielddisplay(self,"vertexconnectivity","list of vertices connected to vertex_i"))
-		string="%s\n%s"%(string,fielddisplay(self,"elementconnectivity","list of vertices connected to element_i"))
+		string="%s\n%s"%(string,fielddisplay(self,"vertexconnectivity","list of elements connected to vertex_i"))
+		string="%s\n%s"%(string,fielddisplay(self,"elementconnectivity","list of elements adjacent to element_i"))
 		string="%s\n%s"%(string,fielddisplay(self,"average_vertex_connectivity","average number of vertices connected to one vertex"))
 
@@ -91,4 +91,5 @@
 		string="%s\n%s"%(string,fielddisplay(self,"long","vertices longitude [degrees]"))
 		string="%s\n%s"%(string,fielddisplay(self,"epsg","EPSG code (ex: 3413 for UPS Greenland, 3031 for UPS Antarctica)"))
+		string="%s\n%s"%(string,fielddisplay(self,"scale_factor","Projection correction for volume, area, etc. computation"))
 		return string
 		#}}}
@@ -109,7 +110,7 @@
 		md = checkfield(md,'fieldname','mesh.y','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 		md = checkfield(md,'fieldname','mesh.z','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
-		md = checkfield(md,'fieldname','mesh.elements','NaN',1,'Inf',1,'>',0,'values',numpy.arange(1,md.mesh.numberofvertices+1))
+		md = checkfield(md,'fieldname','mesh.elements','NaN',1,'Inf',1,'>',0,'values',np.arange(1,md.mesh.numberofvertices+1))
 		md = checkfield(md,'fieldname','mesh.elements','size',[md.mesh.numberofelements,6])
-		if numpy.any(numpy.logical_not(m.ismember(numpy.arange(1,md.mesh.numberofvertices+1),md.mesh.elements))):
+		if np.any(np.logical_not(m.ismember(np.arange(1,md.mesh.numberofvertices+1),md.mesh.elements))):
 			md.checkmessage("orphan nodes have been found. Check the mesh3dprisms outline")
 		md = checkfield(md,'fieldname','mesh.numberoflayers','>=',0)
@@ -119,4 +120,6 @@
 		md = checkfield(md,'fieldname','mesh.vertexonsurface','size',[md.mesh.numberofvertices],'values',[0,1])
 		md = checkfield(md,'fieldname','mesh.average_vertex_connectivity','>=',24,'message',"'mesh.average_vertex_connectivity' should be at least 24 in 3d")
+		if(np.size(self.scale_factor)>1):
+                        md = checkfield(md,'fieldname','mesh.scale_factor','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
 
 		return md
@@ -131,22 +134,26 @@
 		return "Penta"
 	#}}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'enum',DomainTypeEnum(),'data',StringToEnum("Domain"+self.domaintype())[0],'format','Integer');
-		WriteData(fid,'enum',DomainDimensionEnum(),'data',self.dimension(),'format','Integer');
-		WriteData(fid,'enum',MeshElementtypeEnum(),'data',StringToEnum(self.elementtype())[0],'format','Integer');
-		WriteData(fid,'object',self,'class','mesh','fieldname','x','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'class','mesh','fieldname','y','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'class','mesh','fieldname','z','format','DoubleMat','mattype',1)
-		WriteData(fid,'object',self,'class','mesh','fieldname','elements','format','DoubleMat','mattype',2)
-		WriteData(fid,'object',self,'class','mesh','fieldname','numberoflayers','format','Integer')
-		WriteData(fid,'object',self,'class','mesh','fieldname','numberofelements','format','Integer')
-		WriteData(fid,'object',self,'class','mesh','fieldname','numberofvertices','format','Integer')
-		WriteData(fid,'object',self,'class','mesh','fieldname','vertexonbase','format','BooleanMat','mattype',1)
-		WriteData(fid,'object',self,'class','mesh','fieldname','vertexonsurface','format','BooleanMat','mattype',1)
-		WriteData(fid,'object',self,'class','mesh','fieldname','lowerelements','format','DoubleMat','mattype',2)
-		WriteData(fid,'object',self,'class','mesh','fieldname','upperelements','format','DoubleMat','mattype',2)
-		WriteData(fid,'object',self,'class','mesh','fieldname','average_vertex_connectivity','format','Integer')
-		WriteData(fid,'object',self,'class','mesh','fieldname','elements2d','format','DoubleMat','mattype',3)
-		WriteData(fid,'object',self,'class','mesh','fieldname','numberofvertices2d','format','Integer')
-		WriteData(fid,'object',self,'class','mesh','fieldname','numberofelements2d','format','Integer')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'name','md.mesh.domain_type','data',"Domain"+self.domaintype(),'format','String');
+		WriteData(fid,prefix,'name','md.mesh.domain_dimension','data',self.dimension(),'format','Integer');
+		WriteData(fid,prefix,'name','md.mesh.elementtype','data',self.elementtype(),'format','String');
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','x','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','y','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','z','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','elements','format','DoubleMat','mattype',2)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','numberoflayers','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','numberofelements','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','numberofvertices','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','vertexonbase','format','BooleanMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','vertexonsurface','format','BooleanMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','lowerelements','format','DoubleMat','mattype',2)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','upperelements','format','DoubleMat','mattype',2)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','average_vertex_connectivity','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','elements2d','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','numberofvertices2d','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','numberofelements2d','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','mesh','fieldname','scale_factor','format','DoubleMat','mattype',1)
+		if md.transient.isoceancoupling:
+			WriteData(fid,prefix,'object',self,'class','mesh','fieldname','lat','format','DoubleMat','mattype',1)
+			WriteData(fid,prefix,'object',self,'class','mesh','fieldname','long','format','DoubleMat','mattype',1)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/miscellaneous.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/miscellaneous.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/miscellaneous.py	(revision 23670)
@@ -1,5 +1,4 @@
 from collections import OrderedDict
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -37,5 +36,5 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    #  {{{
-		WriteData(fid,'object',self,'fieldname','name','format','String')
+	def marshall(self,prefix,md,fid):    #  {{{
+		WriteData(fid,prefix,'object',self,'fieldname','name','format','String');
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/mismipbasalforcings.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/mismipbasalforcings.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/mismipbasalforcings.py	(revision 23670)
@@ -1,10 +1,10 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
+from project3d import project3d
 from checkfield import checkfield
 from WriteData import WriteData
-import numpy
+import numpy as np
 
 class mismipbasalforcings(object):
-    """
+    """ 
     MISMIP Basal Forcings class definition
 
@@ -13,5 +13,5 @@
     """
 
-    def __init__(self,md): # {{{
+    def __init__(self): # {{{
 
         self.groundedice_melting_rate = float('NaN')
@@ -20,8 +20,4 @@
         self.upperdepth_melt = float('NaN')
         self.geothermalflux = float('NaN')
-
-        if numpy.all(numpy.isnan(self.groundedice_melting_rate)):
-            self.groundedice_melting_rate=numpy.zeros(md.mesh.numberofvertices)
-            print(' no basalforcings.groundedice_melting_rate specified: values set as zero')
 
 	self.setdefaultparameters()
@@ -35,20 +31,25 @@
         string="%s\n%s"%(string,fielddisplay(self,"upperdepth_melt","Depth above which melt rate is zero [m]"))
         string="%s\n%s"%(string,fielddisplay(self,"geothermalflux","Geothermal heat flux [W/m^2]"))
-
 	return string
     #}}}
     def extrude(self,md): # {{{
-	self.coefficient=project3d(md,'vector',self.coefficient,'type','node','layer',1)
-	self.p=project3d(md,'vector',self.p,'type','element')
-	self.q=project3d(md,'vector',self.q,'type','element')
+        self.groundedice_melting_rate=project3d(md,'vector',self.groundedice_melting_rate,'type','node','layer',1)
+        self.geothermalflux=project3d(md,'vector',self.geothermalflux,'type','node','layer',1)    #bedrock only gets geothermal flux
 	return self
     #}}}
+    def initialize(self,md): # {{{
+        if np.all(np.isnan(self.groundedice_melting_rate)):
+            self.groundedice_melting_rate=np.zeros((md.mesh.numberofvertices))
+            print(' no basalforcings.groundedice_melting_rate specified: values set as zero')
+	if np.all(np.isnan(self.geothermalflux)):
+			self.geothermalflux=np.zeros((md.mesh.numberofvertices))
+			print("      no basalforcings.geothermalflux specified: values set as zero")
+        return self
+    #}}}
     def setdefaultparameters(self): # {{{
-
         # default values for melting parameterization
         self.meltrate_factor = 0.2
         self.threshold_thickness = 75.
         self.upperdepth_melt = -100.
-
 	return self
     #}}}
@@ -56,5 +57,5 @@
 
 	#Early return
-        if MasstransportAnalysisEnum() in analyses and not (solution==TransientSolutionEnum() and md.transient.ismasstransport==0):
+        if 'MasstransportAnalysis' in analyses and not (solution=='TransientSolution' and md.transient.ismasstransport==0):
 
 	    md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1)
@@ -63,5 +64,5 @@
 	    md = checkfield(md,'fieldname','basalforcings.upperdepth_melt','<=',0,'numel',[1])
 
-        if BalancethicknessAnalysisEnum() in analyses:
+        if 'BalancethicknessAnalysis' in analyses:
 
 	    md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices])
@@ -70,5 +71,5 @@
 	    md = checkfield(md,'fieldname','basalforcings.upperdepth_melt','<=',0,'numel',[1])
 
-        if ThermalAnalysisEnum() in analyses and not (solution==TransientSolutionEnum() and md.transient.isthermal==0):
+        if 'ThermalAnalysis' in analyses and not (solution=='TransientSolution' and md.transient.isthermal==0):
 
 	    md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1)
@@ -79,5 +80,5 @@
 	return md
     # }}}
-    def marshall(self,md,fid):    # {{{
+    def marshall(self,prefix,md,fid):    # {{{
 
         yts=md.constants.yts
@@ -85,14 +86,10 @@
             print('WARNING: value of yts for MISMIP+ runs different from ISSM default!')
 
-        floatingice_melting_rate = numpy.zeros((md.mesh.numberofvertices,1))
-        floatingice_melting_rate = md.basalforcings.meltrate_factor*numpy.tanh((md.geometry.base-md.geometry.bed)/md.basalforcings.threshold_thickness)*numpy.amax(md.basalforcings.upperdepth_melt-md.geometry.base,0)
-
-	WriteData(fid,'enum',BasalforcingsEnum(),'data',MismipFloatingMeltRateEnum(),'format','Integer')
-	WriteData(fid,'data',floatingice_melting_rate,'format','DoubleMat','enum',BasalforcingsFloatingiceMeltingRateEnum(),'mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-	WriteData(fid,'object',self,'fieldname','groundedice_melting_rate','format','DoubleMat','enum',BasalforcingsGroundediceMeltingRateEnum(),'mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-	WriteData(fid,'object',self,'fieldname','geothermalflux','enum',BasalforcingsGeothermalfluxEnum(),'format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-	WriteData(fid,'object',self,'fieldname','meltrate_factor','format','Double','enum',BasalforcingsMeltrateFactorEnum(),'scale',1./yts)
-	WriteData(fid,'object',self,'fieldname','threshold_thickness','format','Double','enum',BasalforcingsThresholdThicknessEnum())
-	WriteData(fid,'object',self,'fieldname','upperdepth_melt','format','Double','enum',BasalforcingsUpperdepthMeltEnum())
+	WriteData(fid,prefix,'name','md.basalforcings.model','data',3,'format','Integer')
+	WriteData(fid,prefix,'object',self,'fieldname','groundedice_melting_rate','format','DoubleMat','name','md.basalforcings.groundedice_melting_rate','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+	WriteData(fid,prefix,'object',self,'fieldname','geothermalflux','name','md.basalforcings.geothermalflux','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+	WriteData(fid,prefix,'object',self,'fieldname','meltrate_factor','format','Double','scale',1./yts)
+	WriteData(fid,prefix,'object',self,'fieldname','threshold_thickness','format','Double')
+	WriteData(fid,prefix,'object',self,'fieldname','upperdepth_melt','format','Double')
 
     # }}}
Index: /issm/trunk-jpl/src/py3/classes/model.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/model.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/model.py	(revision 23670)
@@ -1,156 +1,281 @@
 #module imports {{{
-import numpy
+import numpy as np
 import copy
 import sys
-import MatlabFuncs as m
+from mesh2d import mesh2d
+from mesh3dprisms import mesh3dprisms
+from mask import mask
+from geometry import geometry
+from constants import constants
+from SMBforcing import SMBforcing
+from SMBpdd import SMBpdd
+from SMBd18opdd import SMBd18opdd
+from SMBgradients import SMBgradients
+from SMBcomponents import SMBcomponents
+from SMBmeltcomponents import SMBmeltcomponents
+from basalforcings import basalforcings
+from matice import matice
+from levelset import levelset
+from calving import calving
+from fourierlove import fourierlove
+from calvinglevermann import calvinglevermann
+#from calvingpi import calvingpi
+from frontalforcings import frontalforcings
+from damage import damage
+from friction import friction
+from flowequation import flowequation
+from timestepping import timestepping
+from timesteppingadaptive import timesteppingadaptive
+from initialization import initialization
+from rifts import rifts
+from slr import slr
+from debug import debug
+from verbose import verbose
+from issmsettings import issmsettings
+from toolkits import toolkits
+from generic import generic
+from pfe import pfe
+from vilje import vilje
+from hexagon import hexagon
+from cyclone import cyclone
+from stallo import stallo
+from balancethickness import balancethickness
+from stressbalance import stressbalance
+from groundingline import groundingline
+from hydrologyshreve import hydrologyshreve
+from hydrologydc import hydrologydc
+from masstransport import masstransport
+from thermal import thermal
+from steadystate import steadystate
+from transient import transient
+from giaivins import giaivins
+from esa import esa
+from autodiff import autodiff
+from inversion import inversion
+from outputdefinition import outputdefinition
+from qmu import qmu
+from amr import amr
+from results import results
+from radaroverlay import radaroverlay
+from miscellaneous import miscellaneous
+from private import private
+from mumpsoptions import mumpsoptions
+from iluasmoptions import iluasmoptions
+from project3d import project3d
+from project2d import project2d
+from FlagElements import FlagElements
+from NodeConnectivity import NodeConnectivity
+from ElementConnectivity import ElementConnectivity
+from contourenvelope import contourenvelope
+from DepthAverage import DepthAverage
 #}}}
 
 class model(object):
 	#properties
-	def __init__(self,*filename):#{{{
-
-		def netCDFread(filename):
-			def walktree(data):
-				keys = data.groups.keys()
-				yield keys
-				for key in keys:
-					for children in walktree(data.groups[str(key)]):
-						yield children
-
-			if path.exists(filename):
-				print ('Opening {} for reading '.format(filename))
-				NCData=Dataset(filename, 'r')
-				class_dict={}
-				
-				for children in walktree(NCData):
-					for child in children:
-						class_dict[str(child)]=str(getattr(NCData.groups[str(child)],'classtype'))
-
-				return class_dict
-
-		if filename:		
-			classtype=netCDFread(filename[0])
-		else:
-			classtype=self.properties()
-			
-		VT=[v[0] for v in dict.values(classtype)]
-		classnames=[classname for classname in dict.keys(classtype)]
-		module=map(__import__,VT)
-
-		for i,mod in enumerate(module):
-			self.__dict__[classnames[i]] = getattr(mod,str(classtype[str(classnames[i])][0]))()
-
-	#}}}
-
+	def __init__(self):#{{{
+
+		# classtype=model.properties
+
+		# for classe in dict.keys(classtype):
+		# 	print classe
+		# 	self.__dict__[classe] = classtype[str(classe)]
+
+		self.mesh           = mesh2d()
+		self.mask           = mask()
+		self.geometry       = geometry()
+		self.constants      = constants()
+		self.smb            = SMBforcing()
+		self.basalforcings  = basalforcings()
+		self.materials      = matice()
+		self.damage         = damage()
+		self.friction       = friction()
+		self.flowequation   = flowequation()
+		self.timestepping   = timestepping()
+		self.initialization = initialization()
+		self.rifts          = rifts()
+		self.slr            = slr()
+
+		self.debug    = debug()
+		self.verbose  = verbose()
+		self.settings = issmsettings()
+		self.toolkits = toolkits()
+		self.cluster  = generic()
+
+		self.balancethickness = balancethickness()
+		self.stressbalance    = stressbalance()
+		self.groundingline    = groundingline()
+		self.hydrology        = hydrologyshreve()
+		self.masstransport    = masstransport()
+		self.thermal          = thermal()
+		self.steadystate      = steadystate()
+		self.transient        = transient()
+		self.levelset         = levelset()
+		self.calving          = calving()
+		self.frontalforcings  = frontalforcings()
+		self.gia              = giaivins()
+		self.love							= fourierlove()
+		self.esa							= esa()
+		self.autodiff					= autodiff()
+		self.inversion				= inversion()
+		self.qmu							= qmu()
+		self.amr							= amr()
+
+		self.results          = results()
+		self.outputdefinition = outputdefinition()
+		self.radaroverlay     = radaroverlay()
+		self.miscellaneous    = miscellaneous()
+		self.private          = private()
+		#}}}
 	def properties(self):    # {{{
 		# ordered list of properties since vars(self) is random
-		return {'mesh':['mesh2d','mesh properties'],\
-		        'mask':['mask','defines grounded and floating elements'],\
-		        'geometry':['geometry','surface elevation, bedrock topography, ice thickness,...'],\
-		        'constants':['constants','physical constants'],\
-		        'smb':['SMBpdd','surface forcings'],\
-		        'basalforcings':['basalforcings','bed forcings'],\
-		        'materials':['matice','material properties'],\
-		        'damage':['damage','damage propagation laws'],\
-		        'friction':['friction','basal friction/drag properties'],\
-		        'flowequation':['flowequation','flow equations'],\
-		        'timestepping':['timestepping','time stepping for transient models'],\
-		        'initialization':['initialization','initial guess/state'],\
-		        'rifts':['rifts','rifts properties'],\
-		        'debug':['debug','debugging tools (valgrind, gprof)'],\
-		        'verbose':['verbose','verbosity level in solve'],\
-		        'settings':['settings','settings properties'],\
-		        'toolkits':['toolkits','PETSc options for each solution'],\
-		        'cluster':['generic','cluster parameters (number of cpus...)'],\
-		        'balancethickness':['balancethickness','parameters for balancethickness solution'],\
-		        'stressbalance':['stressbalance','parameters for stressbalance solution'],\
-		        'groundingline':['groundingline','parameters for groundingline solution'],\
-		        'hydrology':['hydrologyshreve','parameters for hydrology solution'],\
-		        'masstransport':['masstransport','parameters for masstransport solution'],\
-		        'thermal':['thermal','parameters for thermal solution'],\
-		        'steadystate':['steadystate','parameters for steadystate solution'],\
-		        'transient':['transient','parameters for transient solution'],\
-		        'calving':['calving','parameters for calving'],\
-						'gia':['gia','Parameters for gia model'],\
-		        'autodiff':['autodiff','automatic differentiation parameters'],\
-		        'flaim':['flaim','flaim parameters'],\
-		        'inversion':['inversion','parameters for inverse methods'],\
-		        'qmu':['qmu','dakota properties'],\
-		        'outputdefinition':['outputdefinition','output definition'],\
-		        'results':['results','model results'],\
-		        'radaroverlay':['radaroverlay','radar image for plot overlay'],\
-		        'miscellaneous':['miscellaneous','miscellaneous fields'],\
-		        'private':['private','...']}
+		return ['mesh',
+		        'mask',
+		        'geometry',
+		        'constants',
+		        'smb',
+		        'basalforcings',
+		        'materials',
+		        'damage',
+		        'friction',
+		        'flowequation',
+		        'timestepping',
+		        'initialization',
+		        'rifts',
+		        'slr',
+		        'debug',
+		        'verbose',
+		        'settings',
+		        'toolkits',
+		        'cluster',
+		        'balancethickness',
+		        'stressbalance',
+		        'groundingline',
+		        'hydrology',
+		        'masstransport',
+		        'thermal',
+		        'steadystate',
+		        'transient',
+		        'levelset',
+		        'calving',
+						'frontalforcings',
+						'love',
+						'gia',
+						'esa',
+		        'autodiff',
+		        'inversion',
+		        'qmu',
+		        'amr',
+		        'outputdefinition',
+		        'results',
+		        'radaroverlay',
+		        'miscellaneous',
+		        'private']
 	# }}}
-
 	def __repr__(obj): #{{{
-		string = "Model Description"
-		for i,mod in enumerate(dict.keys(obj.properties())):
-			tmp="%19s: %-22s -- %s" % (mod,"[%s,%s]" % ("1x1",obj.__dict__[mod].__class__.__name__),obj.properties()[mod][1])
-			string="\n".join([string, tmp])
+		#print "Here %s the number: %d" % ("is", 37)
+		string="%19s: %-22s -- %s" % ("mesh","[%s,%s]" % ("1x1",obj.mesh.__class__.__name__),"mesh properties")
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("mask","[%s,%s]" % ("1x1",obj.mask.__class__.__name__),"defines grounded and floating elements"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("geometry","[%s,%s]" % ("1x1",obj.geometry.__class__.__name__),"surface elevation, bedrock topography, ice thickness,..."))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("constants","[%s,%s]" % ("1x1",obj.constants.__class__.__name__),"physical constants"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("smb","[%s,%s]" % ("1x1",obj.smb.__class__.__name__),"surface mass balance"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("basalforcings","[%s,%s]" % ("1x1",obj.basalforcings.__class__.__name__),"bed forcings"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("materials","[%s,%s]" % ("1x1",obj.materials.__class__.__name__),"material properties"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("damage","[%s,%s]" % ("1x1",obj.damage.__class__.__name__),"damage propagation laws"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("friction","[%s,%s]" % ("1x1",obj.friction.__class__.__name__),"basal friction/drag properties"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("flowequation","[%s,%s]" % ("1x1",obj.flowequation.__class__.__name__),"flow equations"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("timestepping","[%s,%s]" % ("1x1",obj.timestepping.__class__.__name__),"time stepping for transient models"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("initialization","[%s,%s]" % ("1x1",obj.initialization.__class__.__name__),"initial guess/state"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("rifts","[%s,%s]" % ("1x1",obj.rifts.__class__.__name__),"rifts properties"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("slr","[%s,%s]" % ("1x1",obj.slr.__class__.__name__),"slr forcings"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("debug","[%s,%s]" % ("1x1",obj.debug.__class__.__name__),"debugging tools (valgrind, gprof)"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("verbose","[%s,%s]" % ("1x1",obj.verbose.__class__.__name__),"verbosity level in solve"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("settings","[%s,%s]" % ("1x1",obj.settings.__class__.__name__),"settings properties"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("toolkits","[%s,%s]" % ("1x1",obj.toolkits.__class__.__name__),"PETSc options for each solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("cluster","[%s,%s]" % ("1x1",obj.cluster.__class__.__name__),"cluster parameters (number of cpus...)"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("balancethickness","[%s,%s]" % ("1x1",obj.balancethickness.__class__.__name__),"parameters for balancethickness solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("stressbalance","[%s,%s]" % ("1x1",obj.stressbalance.__class__.__name__),"parameters for stressbalance solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("groundingline","[%s,%s]" % ("1x1",obj.groundingline.__class__.__name__),"parameters for groundingline solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("hydrology","[%s,%s]" % ("1x1",obj.hydrology.__class__.__name__),"parameters for hydrology solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("masstransport","[%s,%s]" % ("1x1",obj.masstransport.__class__.__name__),"parameters for masstransport solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("thermal","[%s,%s]" % ("1x1",obj.thermal.__class__.__name__),"parameters for thermal solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("steadystate","[%s,%s]" % ("1x1",obj.steadystate.__class__.__name__),"parameters for steadystate solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("transient","[%s,%s]" % ("1x1",obj.transient.__class__.__name__),"parameters for transient solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("levelset","[%s,%s]" % ("1x1",obj.levelset.__class__.__name__),"parameters for moving boundaries (level-set method)"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("calving","[%s,%s]" % ("1x1",obj.calving.__class__.__name__),"parameters for calving"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("frontalforcings","[%s,%s]" % ("1x1",obj.frontalforcings.__class__.__name__),"parameters for frontalforcings"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("gia","[%s,%s]" % ("1x1",obj.gia.__class__.__name__),"parameters for gia solution"))
+		string="%s\n%s" % (string,'%19s: %-22s -- %s' % ("love","[%s,%s]" % ("1x1",obj.love.__class__.__name__),"parameters for love solution"))
+		string="%s\n%s" % (string,'%19s: %-22s -- %s' % ("esa","[%s,%s]" % ("1x1",obj.esa.__class__.__name__),"parameters for elastic adjustment solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("autodiff","[%s,%s]" % ("1x1",obj.autodiff.__class__.__name__),"automatic differentiation parameters"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("inversion","[%s,%s]" % ("1x1",obj.inversion.__class__.__name__),"parameters for inverse methods"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("qmu","[%s,%s]" % ("1x1",obj.qmu.__class__.__name__),"dakota properties"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("amr","[%s,%s]" % ("1x1",obj.amr.__class__.__name__),"adaptive mesh refinement properties"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("outputdefinition","[%s,%s]" % ("1x1",obj.outputdefinition.__class__.__name__),"output definition"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("results","[%s,%s]" % ("1x1",obj.results.__class__.__name__),"model results"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("radaroverlay","[%s,%s]" % ("1x1",obj.radaroverlay.__class__.__name__),"radar image for plot overlay"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("miscellaneous","[%s,%s]" % ("1x1",obj.miscellaneous.__class__.__name__),"miscellaneous fields"))
 		return string
 	# }}}
-
 	def checkmessage(self,string):    # {{{
-		print(("model not consistent: ", string))
+		print("model not consistent: ", string)
 		self.private.isconsistent=False
 		return self
 	# }}}
-
-	def extract(md,area):    # {{{
+	#@staticmethod
+	def extract(self,area):    # {{{
 		"""
 		extract - extract a model according to an Argus contour or flag list
 
-   This routine extracts a submodel from a bigger model with respect to a given contour
-   md must be followed by the corresponding exp file or flags list
-   It can either be a domain file (argus type, .exp extension), or an array of element flags. 
-   If user wants every element outside the domain to be 
-   extract2d, add '~' to the name of the domain file (ex: '~HO.exp')
-   an empty string '' will be considered as an empty domain
-   a string 'all' will be considered as the entire domain
-
-   Usage:
-      md2=extract(md,area)
-
-   Examples:
-      md2=extract(md,'Domain.exp')
-
-   See also: EXTRUDE, COLLAPSE
+		   This routine extracts a submodel from a bigger model with respect to a given contour
+		   md must be followed by the corresponding exp file or flags list
+		   It can either be a domain file (argus type, .exp extension), or an array of element flags.
+		   If user wants every element outside the domain to be
+		   extract2d, add '~' to the name of the domain file (ex: '~HO.exp')
+		   an empty string '' will be considered as an empty domain
+		   a string 'all' will be considered as the entire domain
+
+		   Usage:
+		      md2=extract(md,area)
+
+		   Examples:
+		      md2=extract(md,'Domain.exp')
+
+		   See also: EXTRUDE, COLLAPSE
 		"""
 
 		#copy model
-		md1=copy.deepcopy(md)
+		md1=copy.deepcopy(self)
 
 		#get elements that are inside area
 		flag_elem=FlagElements(md1,area)
-		if not numpy.any(flag_elem):
+		if not np.any(flag_elem):
 			raise RuntimeError("extracted model is empty")
 
 		#kick out all elements with 3 dirichlets
-		spc_elem=numpy.nonzero(numpy.logical_not(flag_elem))[0]
-		spc_node=numpy.unique(md1.mesh.elements[spc_elem,:])-1
-		flag=numpy.ones(md1.mesh.numberofvertices)
+		spc_elem=np.nonzero(np.logical_not(flag_elem))[0]
+		spc_node=np.unique(md1.mesh.elements[spc_elem,:])-1
+		flag=np.ones(md1.mesh.numberofvertices)
 		flag[spc_node]=0
-		pos=numpy.nonzero(numpy.logical_not(numpy.sum(flag[md1.mesh.elements-1],axis=1)))[0]
+		pos=np.nonzero(np.logical_not(np.sum(flag[md1.mesh.elements-1],axis=1)))[0]
 		flag_elem[pos]=0
-	
+
 		#extracted elements and nodes lists
-		pos_elem=numpy.nonzero(flag_elem)[0]
-		pos_node=numpy.unique(md1.mesh.elements[pos_elem,:])-1
-	
+		pos_elem=np.nonzero(flag_elem)[0]
+		pos_node=np.unique(md1.mesh.elements[pos_elem,:])-1
+
 		#keep track of some fields
 		numberofvertices1=md1.mesh.numberofvertices
 		numberofelements1=md1.mesh.numberofelements
-		numberofvertices2=numpy.size(pos_node)
-		numberofelements2=numpy.size(pos_elem)
-		flag_node=numpy.zeros(numberofvertices1)
+		numberofvertices2=np.size(pos_node)
+		numberofelements2=np.size(pos_elem)
+		flag_node=np.zeros(numberofvertices1)
 		flag_node[pos_node]=1
-	
+
 		#Create Pelem and Pnode (transform old nodes in new nodes and same thing for the elements)
-		Pelem=numpy.zeros(numberofelements1,int)
-		Pelem[pos_elem]=numpy.arange(1,numberofelements2+1)
-		Pnode=numpy.zeros(numberofvertices1,int)
-		Pnode[pos_node]=numpy.arange(1,numberofvertices2+1)
-	
+		Pelem=np.zeros(numberofelements1,int)
+		Pelem[pos_elem]=np.arange(1,numberofelements2+1)
+		Pnode=np.zeros(numberofvertices1,int)
+		Pnode[pos_node]=np.arange(1,numberofvertices2+1)
+
 		#renumber the elements (some node won't exist anymore)
 		elements_1=copy.deepcopy(md1.mesh.elements)
@@ -165,8 +290,10 @@
 
 		#OK, now create the new model!
+
 		#take every field from model
 		md2=copy.deepcopy(md1)
 
 		#automatically modify fields
+
 		#loop over model fields
 		model_fields=vars(md1)
@@ -174,18 +301,18 @@
 			#get field
 			field=getattr(md1,fieldi)
-			fieldsize=numpy.shape(field)
-			if hasattr(field,'__dict__') and not m.ismember(fieldi,['results'])[0]:    #recursive call
+			fieldsize=np.shape(field)
+			if hasattr(field,'__dict__') and not fieldi in ['results']:    #recursive call
 				object_fields=vars(field)
 				for fieldj in object_fields:
 					#get field
 					field=getattr(getattr(md1,fieldi),fieldj)
-					fieldsize=numpy.shape(field)
+					fieldsize=np.shape(field)
 					if len(fieldsize):
 						#size = number of nodes * n
-						if   fieldsize[0]==numberofvertices1:
+						if fieldsize[0]==numberofvertices1:
 							setattr(getattr(md2,fieldi),fieldj,field[pos_node])
 						elif fieldsize[0]==numberofvertices1+1:
-							setattr(getattr(md2,fieldi),fieldj,numpy.vstack((field[pos_node],field[-1,:])))
-							#size = number of elements * n
+							setattr(getattr(md2,fieldi),fieldj,np.vstack((field[pos_node],field[-1,:])))
+						#size = number of elements * n
 						elif fieldsize[0]==numberofelements1:
 							setattr(getattr(md2,fieldi),fieldj,field[pos_elem])
@@ -196,6 +323,6 @@
 						setattr(md2,fieldi,field[pos_node])
 					elif fieldsize[0]==numberofvertices1+1:
-						setattr(md2,fieldi,numpy.hstack((field[pos_node],field[-1,:])))
-						#size = number of elements * n
+						setattr(md2,fieldi,np.hstack((field[pos_node],field[-1,:])))
+					#size = number of elements * n
 					elif fieldsize[0]==numberofelements1:
 						setattr(md2,fieldi,field[pos_elem])
@@ -207,59 +334,58 @@
 		md2.mesh.numberofvertices=numberofvertices2
 		md2.mesh.elements=elements_2
-		
+
 		#mesh.uppervertex mesh.lowervertex
 		if md1.mesh.__class__.__name__=='mesh3dprisms':
 			md2.mesh.uppervertex=md1.mesh.uppervertex[pos_node]
-			pos=numpy.nonzero(numpy.logical_not(md2.mesh.uppervertex==-1))[0]
-			md2.mesh.uppervertex[pos]=Pnode[md2.mesh.uppervertex[pos]-1]
-			
+			pos=np.where(~np.isnan(md2.mesh.uppervertex))[0]
+			md2.mesh.uppervertex[pos]=Pnode[md2.mesh.uppervertex[pos].astype(int)-1]
+
 			md2.mesh.lowervertex=md1.mesh.lowervertex[pos_node]
-			pos=numpy.nonzero(numpy.logical_not(md2.mesh.lowervertex==-1))[0]
-			md2.mesh.lowervertex[pos]=Pnode[md2.mesh.lowervertex[pos]-1]
-			
+			pos=np.where(~np.isnan(md2.mesh.lowervertex))[0]
+			md2.mesh.lowervertex[pos]=Pnode[md2.mesh.lowervertex[pos].astype(int)-1]
+
 			md2.mesh.upperelements=md1.mesh.upperelements[pos_elem]
-			pos=numpy.nonzero(numpy.logical_not(md2.mesh.upperelements==-1))[0]
-			md2.mesh.upperelements[pos]=Pelem[md2.mesh.upperelements[pos]-1]
-			
+			pos=np.where(~np.isnan(md2.mesh.upperelements))[0]
+			md2.mesh.upperelements[pos]=Pelem[md2.mesh.upperelements[pos].astype(int)-1]
+
 			md2.mesh.lowerelements=md1.mesh.lowerelements[pos_elem]
-			pos=numpy.nonzero(numpy.logical_not(md2.mesh.lowerelements==-1))[0]
-			md2.mesh.lowerelements[pos]=Pelem[md2.mesh.lowerelements[pos]-1]
-			
-		#Initial 2d mesh 
+			pos=np.where(~np.isnan(md2.mesh.lowerelements))[0]
+			md2.mesh.lowerelements[pos]=Pelem[md2.mesh.lowerelements[pos].astype(int)-1]
+
+		#Initial 2d mesh
 		if md1.mesh.__class__.__name__=='mesh3dprisms':
-			flag_elem_2d=flag_elem[numpy.arange(0,md1.mesh.numberofelements2d)]
-			pos_elem_2d=numpy.nonzero(flag_elem_2d)[0]
-			flag_node_2d=flag_node[numpy.arange(0,md1.mesh.numberofvertices2d)]
-			pos_node_2d=numpy.nonzero(flag_node_2d)[0]
-		
-			md2.mesh.numberofelements2d=numpy.size(pos_elem_2d)
-			md2.mesh.numberofvertices2d=numpy.size(pos_node_2d)
+			flag_elem_2d=flag_elem[np.arange(0,md1.mesh.numberofelements2d)]
+			pos_elem_2d=np.nonzero(flag_elem_2d)[0]
+			flag_node_2d=flag_node[np.arange(0,md1.mesh.numberofvertices2d)]
+			pos_node_2d=np.nonzero(flag_node_2d)[0]
+
+			md2.mesh.numberofelements2d=np.size(pos_elem_2d)
+			md2.mesh.numberofvertices2d=np.size(pos_node_2d)
 			md2.mesh.elements2d=md1.mesh.elements2d[pos_elem_2d,:]
 			md2.mesh.elements2d[:,0]=Pnode[md2.mesh.elements2d[:,0]-1]
 			md2.mesh.elements2d[:,1]=Pnode[md2.mesh.elements2d[:,1]-1]
 			md2.mesh.elements2d[:,2]=Pnode[md2.mesh.elements2d[:,2]-1]
-		
+
 			md2.mesh.x2d=md1.mesh.x[pos_node_2d]
 			md2.mesh.y2d=md1.mesh.y[pos_node_2d]
-		
+
 		#Edges
-		if m.strcmp(md.mesh.domaintype(),'2Dhorizontal'):
-			if numpy.ndim(md2.mesh.edges)>1 and numpy.size(md2.mesh.edges,axis=1)>1:    
-				#do not use ~isnan because there are some numpy.nans...
+		if md1.mesh.domaintype()=='2Dhorizontal':
+			if np.ndim(md2.mesh.edges)>1 and np.size(md2.mesh.edges,axis=1)>1:    #do not use ~isnan because there are some np.nans...
 				#renumber first two columns
-				pos=numpy.nonzero(md2.mesh.edges[:,3]!=-1)[0]
-				md2.mesh.edges[:  ,0]=Pnode[md2.mesh.edges[:,0]-1]
-				md2.mesh.edges[:  ,1]=Pnode[md2.mesh.edges[:,1]-1]
-				md2.mesh.edges[:  ,2]=Pelem[md2.mesh.edges[:,2]-1]
+				pos=np.nonzero(md2.mesh.edges[:,3]!=-1)[0]
+				md2.mesh.edges[:,0]=Pnode[md2.mesh.edges[:,0]-1]
+				md2.mesh.edges[:,1]=Pnode[md2.mesh.edges[:,1]-1]
+				md2.mesh.edges[:,2]=Pelem[md2.mesh.edges[:,2]-1]
 				md2.mesh.edges[pos,3]=Pelem[md2.mesh.edges[pos,3]-1]
 				#remove edges when the 2 vertices are not in the domain.
-				md2.mesh.edges=md2.mesh.edges[numpy.nonzero(numpy.logical_and(md2.mesh.edges[:,0],md2.mesh.edges[:,1]))[0],:]
+				md2.mesh.edges=md2.mesh.edges[np.nonzero(np.logical_and(md2.mesh.edges[:,0],md2.mesh.edges[:,1]))[0],:]
 				#Replace all zeros by -1 in the last two columns
-				pos=numpy.nonzero(md2.mesh.edges[:,2]==0)[0]
+				pos=np.nonzero(md2.mesh.edges[:,2]==0)[0]
 				md2.mesh.edges[pos,2]=-1
-				pos=numpy.nonzero(md2.mesh.edges[:,3]==0)[0]
+				pos=np.nonzero(md2.mesh.edges[:,3]==0)[0]
 				md2.mesh.edges[pos,3]=-1
 				#Invert -1 on the third column with last column (Also invert first two columns!!)
-				pos=numpy.nonzero(md2.mesh.edges[:,2]==-1)[0]
+				pos=np.nonzero(md2.mesh.edges[:,2]==-1)[0]
 				md2.mesh.edges[pos,2]=md2.mesh.edges[pos,3]
 				md2.mesh.edges[pos,3]=-1
@@ -268,60 +394,60 @@
 				md2.mesh.edges[pos,0]=values
 				#Finally remove edges that do not belong to any element
-				pos=numpy.nonzero(numpy.logical_and(md2.mesh.edges[:,1]==-1,md2.mesh.edges[:,2]==-1))[0]
-				md2.mesh.edges=numpy.delete(md2.mesh.edges,pos,axis=0)
+				pos=np.nonzero(np.logical_and(md2.mesh.edges[:,1]==-1,md2.mesh.edges[:,2]==-1))[0]
+				md2.mesh.edges=np.delete(md2.mesh.edges,pos,axis=0)
 
 		#Penalties
-		if numpy.any(numpy.logical_not(numpy.isnan(md2.stressbalance.vertex_pairing))):
-			for i in range(numpy.size(md1.stressbalance.vertex_pairing,axis=0)):
+		if np.any(np.logical_not(np.isnan(md2.stressbalance.vertex_pairing))):
+			for i in range(np.size(md1.stressbalance.vertex_pairing,axis=0)):
 				md2.stressbalance.vertex_pairing[i,:]=Pnode[md1.stressbalance.vertex_pairing[i,:]]
-			md2.stressbalance.vertex_pairing=md2.stressbalance.vertex_pairing[numpy.nonzero(md2.stressbalance.vertex_pairing[:,0])[0],:]
-		if numpy.any(numpy.logical_not(numpy.isnan(md2.masstransport.vertex_pairing))):
-			for i in range(numpy.size(md1.masstransport.vertex_pairing,axis=0)):
+			md2.stressbalance.vertex_pairing=md2.stressbalance.vertex_pairing[np.nonzero(md2.stressbalance.vertex_pairing[:,0])[0],:]
+		if np.any(np.logical_not(np.isnan(md2.masstransport.vertex_pairing))):
+			for i in range(np.size(md1.masstransport.vertex_pairing,axis=0)):
 				md2.masstransport.vertex_pairing[i,:]=Pnode[md1.masstransport.vertex_pairing[i,:]]
-				md2.masstransport.vertex_pairing=md2.masstransport.vertex_pairing[numpy.nonzero(md2.masstransport.vertex_pairing[:,0])[0],:]
+			md2.masstransport.vertex_pairing=md2.masstransport.vertex_pairing[np.nonzero(md2.masstransport.vertex_pairing[:,0])[0],:]
 
 		#recreate segments
 		if md1.mesh.__class__.__name__=='mesh2d':
-			[md2.mesh.vertexconnectivity]=NodeConnectivity(md2.mesh.elements,md2.mesh.numberofvertices)
-			[md2.mesh.elementconnectivity]=ElementConnectivity(md2.mesh.elements,md2.mesh.vertexconnectivity)
+			md2.mesh.vertexconnectivity=NodeConnectivity(md2.mesh.elements,md2.mesh.numberofvertices)[0]
+			md2.mesh.elementconnectivity=ElementConnectivity(md2.mesh.elements,md2.mesh.vertexconnectivity)[0]
 			md2.mesh.segments=contourenvelope(md2)
-			md2.mesh.vertexonboundary=numpy.zeros(numberofvertices2,bool)
+			md2.mesh.vertexonboundary=np.zeros(numberofvertices2,bool)
 			md2.mesh.vertexonboundary[md2.mesh.segments[:,0:2]-1]=True
 		else:
 			#First do the connectivity for the contourenvelope in 2d
-			[md2.mesh.vertexconnectivity]=NodeConnectivity(md2.mesh.elements2d,md2.mesh.numberofvertices2d)
-			[md2.mesh.elementconnectivity]=ElementConnectivity(md2.mesh.elements2d,md2.mesh.vertexconnectivity)
+			md2.mesh.vertexconnectivity=NodeConnectivity(md2.mesh.elements2d,md2.mesh.numberofvertices2d)[0]
+			md2.mesh.elementconnectivity=ElementConnectivity(md2.mesh.elements2d,md2.mesh.vertexconnectivity)[0]
 			segments=contourenvelope(md2)
-			md2.mesh.vertexonboundary=numpy.zeros(numberofvertices2/md2.mesh.numberoflayers,bool)
+			md2.mesh.vertexonboundary=np.zeros(numberofvertices2/md2.mesh.numberoflayers,bool)
 			md2.mesh.vertexonboundary[segments[:,0:2]-1]=True
-			md2.mesh.vertexonboundary=numpy.tile(md2.mesh.vertexonboundary,md2.mesh.numberoflayers)
+			md2.mesh.vertexonboundary=np.tile(md2.mesh.vertexonboundary,md2.mesh.numberoflayers)
 			#Then do it for 3d as usual
-			[md2.mesh.vertexconnectivity]=NodeConnectivity(md2.mesh.elements,md2.mesh.numberofvertices)
-			[md2.mesh.elementconnectivity]=ElementConnectivity(md2.mesh.elements,md2.mesh.vertexconnectivity)
+			md2.mesh.vertexconnectivity=NodeConnectivity(md2.mesh.elements,md2.mesh.numberofvertices)[0]
+			md2.mesh.elementconnectivity=ElementConnectivity(md2.mesh.elements,md2.mesh.vertexconnectivity)[0]
 
 		#Boundary conditions: Dirichlets on new boundary
 		#Catch the elements that have not been extracted
-		orphans_elem=numpy.nonzero(numpy.logical_not(flag_elem))[0]
-		orphans_node=numpy.unique(md1.mesh.elements[orphans_elem,:])-1
+		orphans_elem=np.nonzero(np.logical_not(flag_elem))[0]
+		orphans_node=np.unique(md1.mesh.elements[orphans_elem,:])-1
 		#Figure out which node are on the boundary between md2 and md1
-		nodestoflag1=numpy.intersect1d(orphans_node,pos_node)
+		nodestoflag1=np.intersect1d(orphans_node,pos_node)
 		nodestoflag2=Pnode[nodestoflag1].astype(int)-1
-		if numpy.size(md1.stressbalance.spcvx)>1 and numpy.size(md1.stressbalance.spcvy)>2 and numpy.size(md1.stressbalance.spcvz)>2:
-			if numpy.size(md1.inversion.vx_obs)>1 and numpy.size(md1.inversion.vy_obs)>1:
-				md2.stressbalance.spcvx[nodestoflag2]=md2.inversion.vx_obs[nodestoflag2] 
+		if np.size(md1.stressbalance.spcvx)>1 and np.size(md1.stressbalance.spcvy)>2 and np.size(md1.stressbalance.spcvz)>2:
+			if np.size(md1.inversion.vx_obs)>1 and np.size(md1.inversion.vy_obs)>1:
+				md2.stressbalance.spcvx[nodestoflag2]=md2.inversion.vx_obs[nodestoflag2]
 				md2.stressbalance.spcvy[nodestoflag2]=md2.inversion.vy_obs[nodestoflag2]
 			else:
-				md2.stressbalance.spcvx[nodestoflag2]=numpy.nan
-				md2.stressbalance.spcvy[nodestoflag2]=numpy.nan
+				md2.stressbalance.spcvx[nodestoflag2]=np.nan
+				md2.stressbalance.spcvy[nodestoflag2]=np.nan
 				print("\n!! extract warning: spc values should be checked !!\n\n")
 			#put 0 for vz
 			md2.stressbalance.spcvz[nodestoflag2]=0
-		if numpy.any(numpy.logical_not(numpy.isnan(md1.thermal.spctemperature))):
-			md2.thermal.spctemperature[nodestoflag2,0]=1
+		if np.any(np.logical_not(np.isnan(md1.thermal.spctemperature))):
+			md2.thermal.spctemperature[nodestoflag2]=1
 
 		#Results fields
 		if md1.results:
 			md2.results=results()
-			for solutionfield,field in list(md1.results.__dict__.items()):
+			for solutionfield,field in md1.results.__dict__.items():
 				if   isinstance(field,list):
 					setattr(md2.results,solutionfield,[])
@@ -332,8 +458,8 @@
 							fieldr=getattr(md2.results,solutionfield)[i]
 							#get subfields
-							for solutionsubfield,subfield in list(fieldi.__dict__.items()):
-								if   numpy.size(subfield)==numberofvertices1:
+							for solutionsubfield,subfield in fieldi.__dict__.items():
+								if   np.size(subfield)==numberofvertices1:
 									setattr(fieldr,solutionsubfield,subfield[pos_node])
-								elif numpy.size(subfield)==numberofelements1:
+								elif np.size(subfield)==numberofelements1:
 									setattr(fieldr,solutionsubfield,subfield[pos_elem])
 								else:
@@ -346,18 +472,35 @@
 						fieldr=getattr(md2.results,solutionfield)
 						#get subfields
-						for solutionsubfield,subfield in list(field.__dict__.items()):
-							if   numpy.size(subfield)==numberofvertices1:
+						for solutionsubfield,subfield in field.__dict__.items():
+							if   np.size(subfield)==numberofvertices1:
 								setattr(fieldr,solutionsubfield,subfield[pos_node])
-							elif numpy.size(subfield)==numberofelements1:
+							elif np.size(subfield)==numberofelements1:
 								setattr(fieldr,solutionsubfield,subfield[pos_elem])
 							else:
 								setattr(fieldr,solutionsubfield,subfield)
 
+		#OutputDefinitions fields
+		if md1.outputdefinition.definitions:
+			for solutionfield,field in md1.outputdefinition.__dict__.items():
+				if isinstance(field,list):
+					#get each definition
+					for i,fieldi in enumerate(field):
+						if fieldi:
+							fieldr=getattr(md2.outputdefinition,solutionfield)[i]
+							#get subfields
+							for solutionsubfield,subfield in fieldi.__dict__.items():
+								if   np.size(subfield)==numberofvertices1:
+									setattr(fieldr,solutionsubfield,subfield[pos_node])
+								elif np.size(subfield)==numberofelements1:
+									setattr(fieldr,solutionsubfield,subfield[pos_elem])
+								else:
+									setattr(fieldr,solutionsubfield,subfield)
+
 		#Keep track of pos_node and pos_elem
 		md2.mesh.extractedvertices=pos_node+1
 		md2.mesh.extractedelements=pos_elem+1
+
 		return md2
 	# }}}
-
 	def extrude(md,*args):    # {{{
 		"""
@@ -369,5 +512,5 @@
 		    - follow two polynomial laws, one for the lower part and one for the upper part of the mesh
 		    - be discribed by a list of coefficients (between 0 and 1)
- 
+
 
 		   Usage:
@@ -402,5 +545,5 @@
 				raise TypeError("extrusionexponent must be >=0")
 			numlayers=args[0]
-			extrusionlist=(numpy.arange(0.,float(numlayers-1)+1.,1.)/float(numlayers-1))**args[1]
+			extrusionlist=(np.arange(0.,float(numlayers-1)+1.,1.)/float(numlayers-1))**args[1]
 
 		elif len(args)==3:    #two polynomial laws
@@ -412,7 +555,7 @@
 				raise TypeError("lower and upper extrusionexponents must be >=0")
 
-			lowerextrusionlist=(numpy.arange(0.,1.+2./float(numlayers-1),2./float(numlayers-1)))**lowerexp/2.
-			upperextrusionlist=(numpy.arange(0.,1.+2./float(numlayers-1),2./float(numlayers-1)))**upperexp/2.
-			extrusionlist=numpy.unique(numpy.concatenate((lowerextrusionlist,1.-upperextrusionlist)))
+			lowerextrusionlist=(np.arange(0.,1.+2./float(numlayers-1),2./float(numlayers-1)))**lowerexp/2.
+			upperextrusionlist=(np.arange(0.,1.+2./float(numlayers-1),2./float(numlayers-1)))**upperexp/2.
+			extrusionlist=np.unique(np.concatenate((lowerextrusionlist,1.-upperextrusionlist)))
 
 		if numlayers<2:
@@ -429,20 +572,21 @@
 		md.mesh.numberofelements            = mesh2d.numberofelements
 		md.mesh.numberofvertices            = mesh2d.numberofvertices
-		
+
 		md.mesh.lat                         = mesh2d.lat
 		md.mesh.long                        = mesh2d.long
 		md.mesh.epsg                        = mesh2d.epsg
-		
+		md.mesh.scale_factor                = mesh2d.scale_factor
+
 		md.mesh.vertexonboundary            = mesh2d.vertexonboundary
 		md.mesh.vertexconnectivity          = mesh2d.vertexconnectivity
 		md.mesh.elementconnectivity         = mesh2d.elementconnectivity
 		md.mesh.average_vertex_connectivity = mesh2d.average_vertex_connectivity
-		
+
 		md.mesh.extractedvertices           = mesh2d.extractedvertices
 		md.mesh.extractedelements           = mesh2d.extractedelements
-		
-		x3d=numpy.empty((0))
-		y3d=numpy.empty((0))
-		z3d=numpy.empty((0))    #the lower node is on the bed
+
+		x3d=np.empty((0))
+		y3d=np.empty((0))
+		z3d=np.empty((0))    #the lower node is on the bed
 		thickness3d=md.geometry.thickness    #thickness and bed for these nodes
 		bed3d=md.geometry.base
@@ -450,33 +594,33 @@
 		#Create the new layers
 		for i in range(numlayers):
-			x3d=numpy.concatenate((x3d,md.mesh.x))
-			y3d=numpy.concatenate((y3d,md.mesh.y))
+			x3d=np.concatenate((x3d,md.mesh.x))
+			y3d=np.concatenate((y3d,md.mesh.y))
 			#nodes are distributed between bed and surface accordingly to the given exponent
-			z3d=numpy.concatenate((z3d,(bed3d+thickness3d*extrusionlist[i]).reshape(-1)))
-		number_nodes3d=numpy.size(x3d)    #number of 3d nodes for the non extruded part of the mesh
-
-		#Extrude elements 
-		elements3d=numpy.empty((0,6),int)
+			z3d=np.concatenate((z3d,(bed3d+thickness3d*extrusionlist[i]).reshape(-1)))
+		number_nodes3d=np.size(x3d)    #number of 3d nodes for the non extruded part of the mesh
+
+		#Extrude elements
+		elements3d=np.empty((0,6),int)
 		for i in range(numlayers-1):
-			elements3d=numpy.vstack((elements3d,numpy.hstack((md.mesh.elements+i*md.mesh.numberofvertices,md.mesh.elements+(i+1)*md.mesh.numberofvertices))))    #Create the elements of the 3d mesh for the non extruded part
-		number_el3d=numpy.size(elements3d,axis=0)    #number of 3d nodes for the non extruded part of the mesh
+			elements3d=np.vstack((elements3d,np.hstack((md.mesh.elements+i*md.mesh.numberofvertices,md.mesh.elements+(i+1)*md.mesh.numberofvertices))))    #Create the elements of the 3d mesh for the non extruded part
+		number_el3d=np.size(elements3d,axis=0)    #number of 3d nodes for the non extruded part of the mesh
 
 		#Keep a trace of lower and upper nodes
-		lowervertex=-1*numpy.ones(number_nodes3d,int)
-		uppervertex=-1*numpy.ones(number_nodes3d,int)
-		lowervertex[md.mesh.numberofvertices:]=numpy.arange(1,(numlayers-1)*md.mesh.numberofvertices+1)
-		uppervertex[:(numlayers-1)*md.mesh.numberofvertices]=numpy.arange(md.mesh.numberofvertices+1,number_nodes3d+1)
+		lowervertex=np.nan*np.ones(number_nodes3d,int)
+		uppervertex=np.nan*np.ones(number_nodes3d,int)
+		lowervertex[md.mesh.numberofvertices:]=np.arange(1,(numlayers-1)*md.mesh.numberofvertices+1)
+		uppervertex[:(numlayers-1)*md.mesh.numberofvertices]=np.arange(md.mesh.numberofvertices+1,number_nodes3d+1)
 		md.mesh.lowervertex=lowervertex
 		md.mesh.uppervertex=uppervertex
 
 		#same for lower and upper elements
-		lowerelements=-1*numpy.ones(number_el3d,int)
-		upperelements=-1*numpy.ones(number_el3d,int)
-		lowerelements[md.mesh.numberofelements:]=numpy.arange(1,(numlayers-2)*md.mesh.numberofelements+1)
-		upperelements[:(numlayers-2)*md.mesh.numberofelements]=numpy.arange(md.mesh.numberofelements+1,(numlayers-1)*md.mesh.numberofelements+1)
+		lowerelements=np.nan*np.ones(number_el3d,int)
+		upperelements=np.nan*np.ones(number_el3d,int)
+		lowerelements[md.mesh.numberofelements:]=np.arange(1,(numlayers-2)*md.mesh.numberofelements+1)
+		upperelements[:(numlayers-2)*md.mesh.numberofelements]=np.arange(md.mesh.numberofelements+1,(numlayers-1)*md.mesh.numberofelements+1)
 		md.mesh.lowerelements=lowerelements
 		md.mesh.upperelements=upperelements
 
-		#Save old mesh 
+		#Save old mesh
 		md.mesh.x2d=md.mesh.x
 		md.mesh.y2d=md.mesh.y
@@ -485,5 +629,5 @@
 		md.mesh.numberofvertices2d=md.mesh.numberofvertices
 
-		#Build global 3d mesh 
+		#Build global 3d mesh
 		md.mesh.elements=elements3d
 		md.mesh.x=x3d
@@ -497,6 +641,6 @@
 
 		#bedinfo and surface info
-		md.mesh.vertexonbase=project3d(md,'vector',numpy.ones(md.mesh.numberofvertices2d,bool),'type','node','layer',1)
-		md.mesh.vertexonsurface=project3d(md,'vector',numpy.ones(md.mesh.numberofvertices2d,bool),'type','node','layer',md.mesh.numberoflayers)
+		md.mesh.vertexonbase=project3d(md,'vector',np.ones(md.mesh.numberofvertices2d,bool),'type','node','layer',1)
+		md.mesh.vertexonsurface=project3d(md,'vector',np.ones(md.mesh.numberofvertices2d,bool),'type','node','layer',md.mesh.numberoflayers)
 		md.mesh.vertexonboundary=project3d(md,'vector',md.mesh.vertexonboundary,'type','node')
 
@@ -504,4 +648,5 @@
 		md.mesh.lat=project3d(md,'vector',md.mesh.lat,'type','node')
 		md.mesh.long=project3d(md,'vector',md.mesh.long,'type','node')
+		md.mesh.scale_factor=project3d(md,'vector',md.mesh.scale_factor,'type','node')
 
 		md.geometry.extrude(md)
@@ -518,21 +663,25 @@
 		# Calving variables
 		md.hydrology.extrude(md)
+		md.levelset.extrude(md)
 		md.calving.extrude(md)
+		md.frontalforcings.extrude(md)
 
 		#connectivity
-		md.mesh.elementconnectivity=numpy.tile(md.mesh.elementconnectivity,(numlayers-1,1))
-		md.mesh.elementconnectivity[numpy.nonzero(md.mesh.elementconnectivity==0)]=-sys.maxsize-1
-		if not numpy.isnan(md.mesh.elementconnectivity).all():
+		md.mesh.elementconnectivity=np.tile(md.mesh.elementconnectivity,(numlayers-1,1))
+		md.mesh.elementconnectivity[np.nonzero(md.mesh.elementconnectivity==0)]=-sys.maxsize-1
+		if not np.isnan(md.mesh.elementconnectivity).all():
 			for i in range(1,numlayers-1):
 				md.mesh.elementconnectivity[i*md.mesh.numberofelements2d:(i+1)*md.mesh.numberofelements2d,:] \
-					=md.mesh.elementconnectivity[i*md.mesh.numberofelements2d:(i+1)*md.mesh.numberofelements2d,:]+md.mesh.numberofelements2d
-				md.mesh.elementconnectivity[numpy.nonzero(md.mesh.elementconnectivity<0)]=0
+						=md.mesh.elementconnectivity[i*md.mesh.numberofelements2d:(i+1)*md.mesh.numberofelements2d,:]+md.mesh.numberofelements2d
+				md.mesh.elementconnectivity[np.nonzero(md.mesh.elementconnectivity<0)]=0
 
 		md.materials.extrude(md)
-		md.damage.extrude(md)
+		if md.damage.isdamage==1:
+			md.damage.extrude(md)
 		md.gia.extrude(md)
 		md.mask.extrude(md)
 		md.qmu.extrude(md)
 		md.basalforcings.extrude(md)
+		md.outputdefinition.extrude(md)
 
 		#increase connectivity if less than 25:
@@ -541,58 +690,90 @@
 
 		return md
-	# }}}
+		# }}}
 	def collapse(md): #{{{
 		'''
 		collapses a 3d mesh into a 2d mesh
-			
+
 		This routine collapses a 3d model into a 2d model and collapses all
 		the fileds of the 3d model by taking their depth-averaged values
-			
+
 		Usage:
 			md=collapse(md)
-		'''	
+		'''
 
 		#Check that the model is really a 3d model
 		if md.mesh.domaintype().lower() != '3d':
 			raise Exception("only a 3D model can be collapsed")
-		
+
+		#dealing with the friction law
 		#drag is limited to nodes that are on the bedrock.
-		md.friction.coefficient=project2d(md,md.friction.coefficient,1)
+		if hasattr(md.friction,'coefficient'):
+			md.friction.coefficient=project2d(md,md.friction.coefficient,1)
 
 		#p and q (same deal, except for element that are on the bedrock: )
-		md.friction.p=project2d(md,md.friction.p,1)
-		md.friction.q=project2d(md,md.friction.q,1)
+		if hasattr(md.friction,'p'):
+			md.friction.p=project2d(md,md.friction.p,1)
+		if hasattr(md.friction,'q'):
+			md.friction.q=project2d(md,md.friction.q,1)
+
+		if hasattr(md.friction,'coefficientcoulomb'):
+			md.friction.coefficientcoulomb=project2d(md,md.friction.coefficientcoulomb,1)
+		if hasattr(md.friction,'C'):
+			md.friction.C=project2d(md,md.friction.C,1)
+		if hasattr(md.friction,'As'):
+			md.friction.As=project2d(md,md.friction.As,1)
+		if hasattr(md.friction,'effective_pressure') and not np.isnan(md.friction.effective_pressure).all():
+			md.friction.effective_pressure=project2d(md,md.friction.effective_pressure,1)
+		if hasattr(md.friction,'water_layer'):
+			md.friction.water_layer=project2d(md,md.friction.water_layer,1)
+		if hasattr(md.friction,'m'):
+			md.friction.m=project2d(md,md.friction.m,1)
 
 		#observations
-		if not numpy.isnan(md.inversion.vx_obs).all(): md.inversion.vx_obs=project2d(md,md.inversion.vx_obs,md.mesh.numberoflayers) 
-		if not numpy.isnan(md.inversion.vy_obs).all(): md.inversion.vy_obs=project2d(md,md.inversion.vy_obs,md.mesh.numberoflayers) 
-		if not numpy.isnan(md.inversion.vel_obs).all(): md.inversion.vel_obs=project2d(md,md.inversion.vel_obs,md.mesh.numberoflayers) 
-		if not numpy.isnan(md.inversion.cost_functions_coefficients).all(): md.inversion.cost_functions_coefficients=project2d(md,md.inversion.cost_functions_coefficients,md.mesh.numberoflayers) 
-		if isinstance(md.inversion.min_parameters,numpy.ndarray):
-			if md.inversion.min_parameters.size>1: md.inversion.min_parameters=project2d(md,md.inversion.min_parameters,md.mesh.numberoflayers) 
-			if isinstance(md.inversion.max_parameters,numpy.ndarray):
-				if md.inversion.max_parameters.size>1: md.inversion.max_parameters=project2d(md,md.inversion.max_parameters,md.mesh.numberoflayers) 
-				if not numpy.isnan(md.smb.mass_balance).all():
-					md.smb.mass_balance=project2d(md,md.smb.mass_balance,md.mesh.numberoflayers) 
-					
-		if not numpy.isnan(md.balancethickness.thickening_rate).all(): md.balancethickness.thickening_rate=project2d(md,md.balancethickness.thickening_rate,md.mesh.numberoflayers) 
+		if not np.isnan(md.inversion.vx_obs).all():
+			md.inversion.vx_obs=project2d(md,md.inversion.vx_obs,md.mesh.numberoflayers)
+		if not np.isnan(md.inversion.vy_obs).all():
+			md.inversion.vy_obs=project2d(md,md.inversion.vy_obs,md.mesh.numberoflayers)
+		if not np.isnan(md.inversion.vel_obs).all():
+			md.inversion.vel_obs=project2d(md,md.inversion.vel_obs,md.mesh.numberoflayers)
+		if not np.isnan(md.inversion.cost_functions_coefficients).all():
+			md.inversion.cost_functions_coefficients=project2d(md,md.inversion.cost_functions_coefficients,md.mesh.numberoflayers)
+		if isinstance(md.inversion.min_parameters,np.ndarray):
+			if md.inversion.min_parameters.size>1:
+				md.inversion.min_parameters=project2d(md,md.inversion.min_parameters,md.mesh.numberoflayers)
+		if isinstance(md.inversion.max_parameters,np.ndarray):
+			if md.inversion.max_parameters.size>1:
+				md.inversion.max_parameters=project2d(md,md.inversion.max_parameters,md.mesh.numberoflayers)
+		if not np.isnan(md.smb.mass_balance).all():
+			md.smb.mass_balance=project2d(md,md.smb.mass_balance,md.mesh.numberoflayers)
 
 		#results
-		if not numpy.isnan(md.initialization.vx).all(): md.initialization.vx=DepthAverage(md,md.initialization.vx)
-		if not numpy.isnan(md.initialization.vy).all(): md.initialization.vy=DepthAverage(md,md.initialization.vy)
-		if not numpy.isnan(md.initialization.vz).all(): md.initialization.vz=DepthAverage(md,md.initialization.vz)
-		if not numpy.isnan(md.initialization.vel).all(): md.initialization.vel=DepthAverage(md,md.initialization.vel)
-		if not numpy.isnan(md.initialization.temperature).all(): md.initialization.temperature=DepthAverage(md,md.initialization.temperature)
-		if not numpy.isnan(md.initialization.pressure).all(): md.initialization.pressure=project2d(md,md.initialization.pressure,1)
-		if not numpy.isnan(md.initialization.sediment_head).all(): md.initialization.sediment_head=project2d(md,md.initialization.sediment_head,1)
-		if not numpy.isnan(md.initialization.epl_head).all(): md.initialization.epl_head=project2d(md,md.initialization.epl_head,1)
-		if not numpy.isnan(md.initialization.epl_thickness).all(): md.initialization.epl_thickness=project2d(md,md.initialization.epl_thickness,1)
-
-		#gia
-		if not numpy.isnan(md.gia.mantle_viscosity).all(): md.gia.mantle_viscosity=project2d(md,md.gia.mantle_viscosity,1) 
-		if not numpy.isnan(md.gia.lithosphere_thickness).all(): md.gia.lithosphere_thickness=project2d(md,md.gia.lithosphere_thickness,1) 
+		if not np.isnan(md.initialization.vx).all():
+			md.initialization.vx=DepthAverage(md,md.initialization.vx)
+		if not np.isnan(md.initialization.vy).all():
+			md.initialization.vy=DepthAverage(md,md.initialization.vy)
+		if not np.isnan(md.initialization.vz).all():
+			md.initialization.vz=DepthAverage(md,md.initialization.vz)
+		if not np.isnan(md.initialization.vel).all():
+			md.initialization.vel=DepthAverage(md,md.initialization.vel)
+		if not np.isnan(md.initialization.temperature).all():
+			md.initialization.temperature=DepthAverage(md,md.initialization.temperature)
+		if not np.isnan(md.initialization.pressure).all():
+			md.initialization.pressure=project2d(md,md.initialization.pressure,1)
+		if not np.isnan(md.initialization.sediment_head).all():
+			md.initialization.sediment_head=project2d(md,md.initialization.sediment_head,1)
+		if not np.isnan(md.initialization.epl_head).all():
+			md.initialization.epl_head=project2d(md,md.initialization.epl_head,1)
+		if not np.isnan(md.initialization.epl_thickness).all():
+			md.initialization.epl_thickness=project2d(md,md.initialization.epl_thickness,1)
+
+		#giaivins
+		if not np.isnan(md.gia.mantle_viscosity).all():
+			md.gia.mantle_viscosity=project2d(md,md.gia.mantle_viscosity,1)
+		if not np.isnan(md.gia.lithosphere_thickness).all():
+			md.gia.lithosphere_thickness=project2d(md,md.gia.lithosphere_thickness,1)
 
 		#elementstype
-		if not numpy.isnan(md.flowequation.element_equation).all():
+		if not np.isnan(md.flowequation.element_equation).all():
 			md.flowequation.element_equation=project2d(md,md.flowequation.element_equation,1)
 			md.flowequation.vertex_equation=project2d(md,md.flowequation.vertex_equation,1)
@@ -602,10 +783,11 @@
 
 		# Hydrologydc variables
-		if hasattr(md.hydrology,'hydrologydc'):
+		if type(md.hydrology) is 'hydrologydc':
 			md.hydrology.spcsediment_head=project2d(md,md.hydrology.spcsediment_head,1)
-			md.hydrology.mask_eplactive_node=project2d(md,md.hydrology.mask_eplactive_node,1)
 			md.hydrology.sediment_transmitivity=project2d(md,md.hydrology.sediment_transmitivity,1)
 			md.hydrology.basal_moulin_input=project2d(md,md.hydrology.basal_moulin_input,1)
+			md.hydrology.mask_thawed_node=project2d(md,md.hydrology.mask_thawed_node,1)
 			if md.hydrology.isefficientlayer == 1:
+				md.hydrology.mask_eplactive_node=project2d(md,md.hydrology.mask_eplactive_node,1)
 				md.hydrology.spcepl_head=project2d(md,md.hydrology.spcepl_head,1)
 
@@ -617,18 +799,19 @@
 		md.stressbalance.loadingforce=project2d(md,md.stressbalance.loadingforce,md.mesh.numberoflayers)
 		md.masstransport.spcthickness=project2d(md,md.masstransport.spcthickness,md.mesh.numberoflayers)
-		if not numpy.isnan(md.damage.spcdamage).all(): md.damage.spcdamage=project2d(md,md.damage.spcdamage,md.mesh.numberoflayers-1)
 		md.thermal.spctemperature=project2d(md,md.thermal.spctemperature,md.mesh.numberoflayers-1)
+		if not np.isnan(md.damage.spcdamage).all():
+			md.damage.spcdamage=project2d(md,md.damage.spcdamage,md.mesh.numberoflayers-1)
 
 		#materials
 		md.materials.rheology_B=DepthAverage(md,md.materials.rheology_B)
 		md.materials.rheology_n=project2d(md,md.materials.rheology_n,1)
-		
-		#damage: 
+
+		#damage:
 		if md.damage.isdamage:
 			md.damage.D=DepthAverage(md,md.damage.D)
 
 		#special for thermal modeling:
-		md.basalforcings.groundedice_melting_rate=project2d(md,md.basalforcings.groundedice_melting_rate,1) 
-		md.basalforcings.floatingice_melting_rate=project2d(md,md.basalforcings.floatingice_melting_rate,1) 
+		md.basalforcings.groundedice_melting_rate=project2d(md,md.basalforcings.groundedice_melting_rate,1)
+		md.basalforcings.floatingice_melting_rate=project2d(md,md.basalforcings.floatingice_melting_rate,1)
 		md.basalforcings.geothermalflux=project2d(md,md.basalforcings.geothermalflux,1) #bedrock only gets geothermal flux
 
@@ -644,14 +827,24 @@
 		md.geometry.thickness=project2d(md,md.geometry.thickness,1)
 		md.geometry.base=project2d(md,md.geometry.base,1)
-		if isinstance(md.geometry.bed,numpy.ndarray):
+		if isinstance(md.geometry.bed,np.ndarray):
 			md.geometry.bed=project2d(md,md.geometry.bed,1)
-			md.mask.groundedice_levelset=project2d(md,md.mask.groundedice_levelset,1)
-			md.mask.ice_levelset=project2d(md,md.mask.ice_levelset,1)
-
-		#lat long
-		if isinstance(md.mesh.lat,numpy.ndarray):
-			if md.mesh.lat.size==md.mesh.numberofvertices:  md.mesh.lat=project2d(md,md.mesh.lat,1) 
-			if isinstance(md.mesh.long,numpy.ndarray):
-				if md.mesh.long.size==md.mesh.numberofvertices: md.mesh.long=project2d(md,md.mesh.long,1) 
+		md.mask.groundedice_levelset=project2d(md,md.mask.groundedice_levelset,1)
+		md.mask.ice_levelset=project2d(md,md.mask.ice_levelset,1)
+
+		#OutputDefinitions
+		if md.outputdefinition.definitions:
+			for solutionfield,field in md.outputdefinition.__dict__.items():
+				if isinstance(field,list):
+					#get each definition
+					for i,fieldi in enumerate(field):
+						if fieldi:
+							fieldr=getattr(md.outputdefinition,solutionfield)[i]
+							#get subfields
+							for solutionsubfield,subfield in fieldi.__dict__.items():
+								if   np.size(subfield)==md.mesh.numberofvertices:
+									setattr(fieldr,solutionsubfield,project2d(md,subfield,1))
+								elif np.size(subfield)==md.mesh.numberofelements:
+									setattr(fieldr,solutionsubfield,project2d(md,subfield,1))
+
 
 		#Initialize with the 2d mesh
@@ -662,7 +855,22 @@
 		mesh.numberofelements=md.mesh.numberofelements2d
 		mesh.elements=md.mesh.elements2d
-		if not numpy.isnan(md.mesh.vertexonboundary).all(): mesh.vertexonboundary=project2d(md,md.mesh.vertexonboundary,1)
-		if not numpy.isnan(md.mesh.elementconnectivity).all(): mesh.elementconnectivity=project2d(md,md.mesh.elementconnectivity,1)
+		if not np.isnan(md.mesh.vertexonboundary).all():
+			mesh.vertexonboundary=project2d(md,md.mesh.vertexonboundary,1)
+		if not np.isnan(md.mesh.elementconnectivity).all():
+			mesh.elementconnectivity=project2d(md,md.mesh.elementconnectivity,1)
+		if isinstance(md.mesh.lat,np.ndarray):
+			if md.mesh.lat.size==md.mesh.numberofvertices:
+				mesh.lat=project2d(md,md.mesh.lat,1)
+		if isinstance(md.mesh.long,np.ndarray):
+			if md.mesh.long.size==md.mesh.numberofvertices:
+				md.mesh.long=project2d(md,md.mesh.long,1)
+		mesh.epsg=md.mesh.epsg
+		if isinstance(md.mesh.scale_factor,np.ndarray):
+			if md.mesh.scale_factor.size==md.mesh.numberofvertices:
+				md.mesh.scale_factor=project2d(md,md.mesh.scale_factor,1)
 		md.mesh=mesh
+		md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices)[0]
+		md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity)[0]
+		md.mesh.segments=contourenvelope(md)
 
 		return md
Index: /issm/trunk-jpl/src/py3/classes/organizer.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/organizer.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/organizer.py	(revision 23670)
@@ -6,5 +6,5 @@
 from savevars import savevars
 from model import model
-from dbm.ndbm import whichdb
+from dbm import whichdb
 import MatlabFuncs as m
 
@@ -26,5 +26,5 @@
 	"""
 
-	def __init__(self,**kwargs):    # {{{
+	def __init__(self,*args):    # {{{
 		self._currentstep  =0
 		self.repository    ='./'
@@ -35,5 +35,5 @@
 
 		#process options
-		options=pairoptions.pairoptions(**kwargs)
+		options=pairoptions.pairoptions(*args)
 
 		#Get prefix
@@ -86,5 +86,5 @@
 		if os.path.exists(path):
 			struc=loadvars(path)
-			name=name=[key for key in list(struc.keys())]
+			name=name=[key for key in struc.keys()]
 			md=struc.name[0]
 		else:
@@ -98,5 +98,5 @@
 		if not isinstance(string,str):
 			raise TypeError("argument provided is not a string")
-		path1=os.path.join(self.repository,self.prefix+'.step#'+string+'.python')
+		path1=os.path.join(self.repository,self.prefix+string+'.python')
 		path2=os.path.join(self.repository,string)
 
@@ -115,5 +115,5 @@
 				raise IOError("Could find neither '%s' nor '%s'" % (path,path2))
 			else:
-				print(("--> Branching '%s' from trunk '%s'" % (self.prefix,self.trunkprefix)))
+				print("--> Branching '%s' from trunk '%s'" % (self.prefix,self.trunkprefix))
 				md=loadmodel(path2)
 				return md
@@ -142,10 +142,10 @@
 		if 0 in self.requestedsteps:
 			if self._currentstep==1:
-				print(("   prefix: %s" % self.prefix))
-			print(("   step #%i : %s" % (self.steps[self._currentstep-1]['id'],self.steps[self._currentstep-1]['string'])))
+				print("   prefix: %s" % self.prefix)
+			print("   step #%i : %s" % (self.steps[self._currentstep-1]['id'],self.steps[self._currentstep-1]['string']))
 
 		#Ok, now if _currentstep is a member of steps, return true
 		if self._currentstep in self.requestedsteps:
-			print(("\n   step #%i : %s\n" % (self.steps[self._currentstep-1]['id'],self.steps[self._currentstep-1]['string'])))
+			print("\n   step #%i : %s\n" % (self.steps[self._currentstep-1]['id'],self.steps[self._currentstep-1]['string']))
 			bool=True
 
@@ -164,8 +164,8 @@
 
 		if (name=='default'):
-			name=os.path.join(self.repository,self.prefix+'step#'+self.steps[self._currentstep-1]['string']+'.python')
-                else:
-                    name=os.path.join(self.repository,name)
-		print(("saving model as: '%s'" % name))
+			name=os.path.join(self.repository,self.prefix+self.steps[self._currentstep-1]['string']+'.python')
+		else:
+			name=os.path.join(self.repository,name)
+		print("saving model as: '%s'" % name)
 
 		#check that md is a model
Index: /issm/trunk-jpl/src/py3/classes/outputdefinition.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/outputdefinition.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/outputdefinition.py	(revision 23670)
@@ -1,8 +1,6 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
-from StringToEnum import StringToEnum
 from checkfield import checkfield
 from WriteData import WriteData
-import numpy as np
+import numpy as  np
 
 class outputdefinition(object):
@@ -24,4 +22,10 @@
 		return string
 		#}}}
+	def extrude(self,md): # {{{
+		for definition in self.definitions:
+			definition.extrude(md);
+
+		return self
+	 #}}}
 	def setdefaultparameters(self): # {{{
 		return self
@@ -34,16 +38,13 @@
 
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		
-		enums=np.zeros(len(self.definitions),)
-		
+	def marshall(self,prefix,md,fid):    # {{{
+		data=[];
 		for i in range(len(self.definitions)):
-			self.definitions[i].marshall(md,fid);
-			classdefinition=self.definitions[i].__class__.__name__
+			self.definitions[i].marshall(prefix,md,fid);
+			classdefinition=self.definitions[i].__class__.__name__;
 			classdefinition=classdefinition[0].upper()+classdefinition[1:]
-			enums[i]=StringToEnum(classdefinition)[0]
-		
-		enums=np.unique(enums);
-		
-		WriteData(fid,'data',enums,'enum',OutputdefinitionListEnum(),'format','DoubleMat','mattype',1);
+			data.append(classdefinition)
+
+		data=np.unique(data);
+		WriteData(fid,prefix,'data',data,'name','md.outputdefinition.list','format','StringArray');
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/pairoptions.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/pairoptions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/pairoptions.py	(revision 23670)
@@ -11,5 +11,5 @@
 	"""
 
-	def __init__(self,**kwargs): # {{{
+	def __init__(self,*arg): # {{{
 		self.functionname = ''
 		self.list         = OrderedDict()
@@ -21,8 +21,8 @@
 
 		#initialize list
-		if not len(kwargs):
+		if not len(arg):
 			pass    #Do nothing,
 		else:
-			self.buildlist(**kwargs)
+			self.buildlist(*arg)
 	# }}}
 	def __repr__(self):    # {{{
@@ -30,5 +30,5 @@
 		if self.list:
 			s+="   list: (%ix%i)\n\n" % (len(self.list),2)
-			for item in list(self.list.items()):
+			for item in self.list.items():
 				if   isinstance(item[1],str):
 					s+="     field: %-10s value: '%s'\n" % (item[0],item[1])
@@ -41,29 +41,25 @@
 		return s
 	# }}}
-	def buildlist(self,**kwargs):    # {{{
+	def buildlist(self,*arg):    # {{{
 		"""BUILDLIST - build list of objects from input"""
-		# #check length of input
-		# if len(arg) % 2:
-		# 	raise TypeError('Invalid parameter/value pair arguments') 
-		# numoptions = len(arg)/2
 
-		# #go through arg and build list of objects
-		# for i in xrange(numoptions):
-		# 	if isinstance(arg[2*i],(str,unicode)):
-		# 		self.list[arg[2*i]] = arg[2*i+1];
-		# 	else:
-		# 		#option is not a string, ignore it
-		# 		print "WARNING: option number %d is not a string and will be ignored." % (i+1)
+		#check length of input
+		if len(arg) % 2:
+			raise TypeError('Invalid parameter/value pair arguments') 
+		numoptions = len(arg)/2
 
 		#go through arg and build list of objects
-		print(kwargs)
-		for name,value in kwargs.items():
-			self.list[name] = value
-		# }}}
+		for i in range(numoptions):
+			if isinstance(arg[2*i],str):
+				self.list[arg[2*i]] = arg[2*i+1];
+			else:
+				#option is not a string, ignore it
+				print("WARNING: option number %d is not a string and will be ignored." % (i+1))
+	# }}}
 	def addfield(self,field,value):    # {{{
 		"""ADDFIELD - add a field to an options list"""
 		if isinstance(field,str):
 			if field in self.list:
-				print(("WARNING: field '%s' with value=%s exists and will be overwritten with value=%s." % (field,str(self.list[field]),str(value))))
+				print("WARNING: field '%s' with value=%s exists and will be overwritten with value=%s." % (field,str(self.list[field]),str(value)))
 			self.list[field] = value
 	# }}}
@@ -76,9 +72,9 @@
 	def AssignObjectFields(self,obj2):    # {{{
 		"""ASSIGNOBJECTFIELDS - assign object fields from options"""
-		for item in list(self.list.items()):
+		for item in self.list.items():
 			if item[0] in dir(obj2):
 				setattr(obj2,item[0],item[1])
 			else:
-				print(("WARNING: field '%s' is not a property of '%s'." % (item[0],type(obj2))))
+				print("WARNING: field '%s' is not a property of '%s'." % (item[0],type(obj2)))
 		return obj2
 	# }}}
@@ -154,5 +150,5 @@
 			#warn user if requested
 			if warn:
-				print(("removefield info: option '%s' has been removed from the list of options." % field))
+				print("removefield info: option '%s' has been removed from the list of options." % field)
 	# }}}
 	def marshall(self,md,fid,firstindex):    # {{{
@@ -162,13 +158,15 @@
 			value = item[1]
 
-			#Write option name
-			WriteData(fid,'enum',(firstindex-1)+2*i+1,'data',name,'format','String')
+			raise NameError('need to sync with MATLAB')
 
-			#Write option value
-			if   isinstance(value,str):
-				WriteData(fid,'enum',(firstindex-1)+2*i+2,'data',value,'format','String')
-			elif isinstance(value,(bool,int,float)):
-				WriteData(fid,'enum',(firstindex-1)+2*i+2,'data',value,'format','Double')
-			else:
-				raise TypeError("Cannot marshall option '%s': format not supported yet." % name)
+			##Write option name
+			#WriteData(fid,prefix,'enum',(firstindex-1)+2*i+1,'data',name,'format','String')
+
+			##Write option value
+			#if   isinstance(value,(str,unicode)):
+			#	WriteData(fid,prefix,'enum',(firstindex-1)+2*i+2,'data',value,'format','String')
+			#elif isinstance(value,(bool,int,long,float)):
+			#	WriteData(fid,prefix,'enum',(firstindex-1)+2*i+2,'data',value,'format','Double')
+			#else:
+				#raise TypeError("Cannot marshall option '%s': format not supported yet." % name)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/plotoptions.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/plotoptions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/plotoptions.py	(revision 23670)
@@ -7,13 +7,13 @@
 
 		Usage:
-			plotoptions=plotoptions(**kwargs)
+			plotoptions=plotoptions(*arg)
 	'''
 
-	def __init__(self,**kwargs):# {{{
+	def __init__(self,*arg):# {{{
 		self.numberofplots = 0
 		self.figurenumber  = 1
 		self.list          = OrderedDict()
 
-		self.buildlist(**kwargs)
+		self.buildlist(*arg)
 		#}}}
 	def __repr__(self): #{{{
@@ -23,5 +23,5 @@
 		if self.list:
 			s+="	list: (%ix%i)\n" % (len(self.list),2)
-			for item in list(self.list.items()):
+			for item in self.list.items():
 				#s+="	options of plot number %i\n" % item
 				if   isinstance(item[1],str):
@@ -35,15 +35,27 @@
 		return s
 	#}}}
-	def buildlist(self,**kwargs): #{{{
+	def buildlist(self,*arg): #{{{
+		#check length of input
+		if len(arg) % 2:
+			raise TypeError('Invalid parameter/value pair arguments')
 
-		for name,value in kwargs.items():
-			self.rawlist[name] = value
+		#go through args and build list (like pairoptions)
+		rawoptions=pairoptions.pairoptions(*arg)
+		numoptions=len(arg)/2
+		rawlist=[] # cannot be a dict since they do not support duplicate keys
 
-		#get figure number 
+		for i in range(numoptions):
+			if isinstance(arg[2*i],str):
+				rawlist.append([arg[2*i],arg[2*i+1]])
+			else:
+				#option is not a string, ignore it
+				print("WARNING: option number %d is not a string and will be ignored." % (i+1))
+
+		#get figure number
 		self.figurenumber=rawoptions.getfieldvalue('figure',1)
 		rawoptions.removefield('figure',0)
 
-		#get number of subplots 
-		numberofplots=Counter(x for sublist in rawlist for x in sublist if isinstance(x,str))['data']
+		#get number of subplots
+		numberofplots=len([1 for sublist in rawlist for x in sublist if str(x)=='data'])
 		self.numberofplots=numberofplots
 
@@ -64,5 +76,5 @@
 			#if alloptions flag is on, apply to all plots
 			if (allflag and 'data' not in rawlist[i][0] and '#' not in rawlist[i][0]):
-				
+
 				for j in range(numberofplots):
 					self.list[j].addfield(rawlist[i][0],rawlist[i][1])
@@ -94,5 +106,5 @@
 							raise ValueError('error: in option i-j both i and j must be integers')
 						for j in range(int(nums[0])-1,int(nums[1])):
-							self.list[j].addfield(field,rawlist[i][1])	
+							self.list[j].addfield(field,rawlist[i][1])
 
 					# Deal with #i
@@ -103,5 +115,5 @@
 						self.list[int(plotnum)-1].addfield(field,rawlist[i][1])
 			else:
-				
+
 				#go through all subplots and assign key-value pairs
 				j=0
@@ -113,4 +125,4 @@
 						j=j+1
 				if j+1>numberofplots:
-					print(("WARNING: too many instances of '%s' in options" % rawlist[i][0]))
+					print("WARNING: too many instances of '%s' in options" % rawlist[i][0])
 	#}}}
Index: /issm/trunk-jpl/src/py3/classes/private.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/private.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/private.py	(revision 23670)
@@ -1,5 +1,4 @@
 from collections import OrderedDict
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 
@@ -20,4 +19,5 @@
 		#set defaults
 		self.setdefaultparameters()
+
 		#}}}
 	def __repr__(self): # {{{
Index: /issm/trunk-jpl/src/py3/classes/qmu.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/qmu.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/qmu.py	(revision 23670)
@@ -1,10 +1,12 @@
-import numpy
+import numpy as np
+from MatlabFuncs import *
+from IssmConfig import *
 from project3d import project3d
 from collections import OrderedDict
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
-import MatlabFuncs as m
+from helpers import *
+from dakota_method import *
 
 class qmu(object):
@@ -18,8 +20,8 @@
 	def __init__(self): # {{{
 		self.isdakota                    = 0
-		self.variables                   = OrderedDict()
-		self.responses                   = OrderedDict()
+		self.variables                   = OrderedStruct()
+		self.responses                   = OrderedStruct()
 		self.method                      = OrderedDict()
-		self.params                      = OrderedDict()
+		self.params                      = OrderedStruct()
 		self.results                     = OrderedDict()
 		self.partition                   = float('NaN')
@@ -42,38 +44,43 @@
 
 		s+="%s\n" % fielddisplay(self,'isdakota','is qmu analysis activated?')
-		for i,variable in enumerate(self.variables.items()):
-			s+="         variables%s:  (arrays of each variable class)\n" % \
-					string_dim(self.variables,i)
-			fnames=vars(variable)
-			maxlen=0
-			for fname in fnames:
-				maxlen=max(maxlen,len(fname))
+		maxlen = 0
+		s+="         variables:  (arrays of each variable class)\n"
 
-			for fname in fnames:
-				s+="'            %-*s:    [%ix%i]    '%s'\n" % \
-						(maxlen+1,fname,size(getattr(variable,fname)),type(getattr(variable,fname)))
+		# OrderedStruct's iterator returns individual name/array-of-functions pairs
+		for variable in self.variables:
+			fname=variable[0]
+			maxlen=max(maxlen,len(fname))
+			size = np.shape(variable[1])
+			a = size[0]
+			b = 1 if len(size) < 2 else size[1]
+			s+="            %-*s:    [%ix%i]    '%s'\n" %  (maxlen+1,fname,a,b,type(variable[1][0]))
 
-		for i,response in enumerate(self.responses.items()):
-			s+="         responses%s:  (arrays of each response class)\n" % \
-					string_dim(self.responses,i)
-			fnames=vars(response)
-			maxlen=0
-			for fname in fnames:
-				maxlen=max(maxlen,len(fname))
+		s+="         responses:  (arrays of each response class)\n"
+		for response in self.responses:
+			fname=response[0]
+			maxlen=max(maxlen,len(fname))
+			size = np.shape(response[1])
+			a = size[0]
+			b = 1 if len(size) < 2 else size[1]
+			s+="            %-*s:    [%ix%i]    '%s'\n" %  (maxlen+1,fname,a,b,type(response[1][0]))
 
-			for fname in fnames:
-				s+="            %-*s:    [%ix%i]    '%s'\n" % \
-						(maxlen+1,fname,size(getattr(response,fname)),type(getattr(response,fname)))
+		s+="%s\n" % fielddisplay(self,'numberofresponses','number of responses')
 
-		s+="%s\n" % fielddisplay(self,'numberofresponses','number of responses') 
+		if type(self.method) != OrderedDict:
+			self.method = [self.method]
+		# self.method must be iterable
+		for method in self.method:
+			if isinstance(method,dakota_method):
+				s+="            method :    '%s'\n" % (method.method)
 
-		for i,method in enumerate(self.method.items()):
-			if isinstance(method,'dakota_method'):
-				s+="            method%s :    '%s'\n" % \
-						(string_dim(method,i),method.method)
-
-		for i,param in enumerate(self.params.items()):
-			s+="         params%s:  (array of method-independent parameters)\n" % \
-					string_dim(self.params,i)
+		# params could be have a number of forms (mainly 1 struct or many)
+		if type(self.params) == OrderedStruct:
+			params = [self.params]
+		else:
+			params = np.hstack(np.atleast_1d(np.array(self.params)))
+		for param in params:
+			print(type(param))
+			print(param)
+			s+="         params:  (array of method-independent parameters)\n"
 			fnames=vars(param)
 			maxlen=0
@@ -82,10 +89,10 @@
 
 			for fname in fnames:
-				s+="            %-*s: %s\n" % \
-						(maxlen+1,fname,any2str(getattr(param,fname)))
+				s+="            %-*s: %s\n" %  (maxlen+1,fname,str(getattr(param,fname)))
 
-		for i,result in enumerate(self.results.items()):
-			s+="         results%s:  (information from dakota files)\n" % \
-					string_dim(self.results,i)
+		# results could be have a number of forms (mainly 1 struct or many)
+		results = np.hstack(np.atleast_1d(np.array(self.results)))
+		for result in results:
+			s+="         results:  (information from dakota files)\n"
 			fnames=vars(result)
 			maxlen=0
@@ -94,6 +101,9 @@
 
 			for fname in fnames:
-				s+="            %-*s:    [%ix%i]    '%s'\n" % \
-						(maxlen+1,fname,size(getattr(result,fname)),type(getattr(result,fname)))
+				size = np.shape(response[1])
+				a = size[0]
+				b = 0 if len(size) < 2 else size[1]
+				size = np.shape(getattr(result,fname))
+				s+="            %-*s:    [%ix%i]    '%s'\n" % (maxlen+1,fname,a,b,type(getattr(result,fname)))
 
 		s+="%s\n" % fielddisplay(self,'partition','user provided mesh partitioning, defaults to metis if not specified') 
@@ -111,5 +121,5 @@
 	# }}}
 	def extrude(self,md): # {{{
-		self.partition=project3d(md,'vector',numpy.transpose(self.partition),'type','node')
+		self.partition=project3d(md,'vector',np.transpose(self.partition),'type','node')
 		return self
 	#}}}
@@ -123,35 +133,48 @@
 			return
 
-		if not md.qmu.params.evaluation_concurrency==1:
-			md.checkmessage("concurrency should be set to 1 when running dakota in library mode")
-		if md.qmu.partition:
-			if not numpy.size(md.qmu.partition)==md.mesh.numberofvertices:
-				md.checkmessage("user supplied partition for qmu analysis should have size md.mesh.numberofvertices x 1")
-			if not min(md.qmu.partition)==0:
+		version=IssmConfig('_DAKOTA_VERSION_')
+		version=float(version[0])
+
+		if version < 6:
+			if not md.qmu.params.evaluation_concurrency==1:
+				md.checkmessage("concurrency should be set to 1 when running dakota in library mode")
+		else:
+			if not strcmpi(self.params.evaluation_scheduling,'master'):
+				md.checkmessage('evaluation_scheduling in qmu.params should be set to "master"')
+
+			if md.cluster.np <= 1:
+				md.checkmessage('in parallel library mode, Dakota needs to run on at least 2 cpus, 1 cpu for the master, 1 cpu for the slave. Modify md.cluser.np accordingly.')
+					
+			if self.params.processors_per_evaluation < 1:
+				md.checkmessage('in parallel library mode, Dakota needs to run at least one slave on one cpu (md.qmu.params.processors_per_evaluation >=1)!')
+				
+			if np.mod(md.cluster.np-1,self.params.processors_per_evaluation):
+				md.checkmessage('in parallel library mode, the requirement is for md.cluster.np = md.qmu.params.processors_per_evaluation * number_of_slaves, where number_of_slaves will automatically be determined by Dakota. Modify md.cluster.np accordingly')
+		
+		if np.size(md.qmu.partition) > 0:
+			if np.size(md.qmu.partition)!=md.mesh.numberofvertices and np.size(md.qmu.partition) != md.mesh.numberofelements:
+				md.checkmessage("user supplied partition for qmu analysis should have size (md.mesh.numberofvertices x 1) or (md.mesh.numberofelements x 1)")
+			if not min(md.qmu.partition.flatten())==0:
 				md.checkmessage("partition vector not indexed from 0 on")
-			if max(md.qmu.partition)>=md.qmu.numberofpartitions:
+			if max(md.qmu.partition.flatten())>=md.qmu.numberofpartitions:
 				md.checkmessage("for qmu analysis, partitioning vector cannot go over npart, number of partition areas")
-
-		if not m.strcmpi(md.cluster.name,'none'):
-			if not md.settings.waitonlock:
-				md.checkmessage("waitonlock should be activated when running qmu in parallel mode!")
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'object',self,'fieldname','isdakota','format','Boolean')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'object',self,'fieldname','isdakota','format','Boolean')
 		if not self.isdakota:
-			WriteData(fid,'data',False,'enum',QmuMassFluxSegmentsPresentEnum(),'format','Boolean');
+			WriteData(fid,prefix,'data',False,'name','md.qmu.mass_flux_segments_present','format','Boolean');
 			return
-		WriteData(fid,'object',self,'fieldname','partition','format','DoubleMat','mattype',2)
-		WriteData(fid,'object',self,'fieldname','numberofpartitions','format','Integer')
-		WriteData(fid,'object',self,'fieldname','numberofresponses','format','Integer')
-		WriteData(fid,'object',self,'fieldname','variabledescriptors','format','StringArray')
-		WriteData(fid,'object',self,'fieldname','responsedescriptors','format','StringArray')
-		if not self.mass_flux_segments:
-			WriteData(fid,'data',self.mass_flux_segments,'enum',MassFluxSegmentsEnum(),'format','MatArray');
+		WriteData(fid,prefix,'object',self,'fieldname','partition','format','DoubleMat','mattype',2)
+		WriteData(fid,prefix,'object',self,'fieldname','numberofpartitions','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','numberofresponses','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','variabledescriptors','format','StringArray')
+		WriteData(fid,prefix,'object',self,'fieldname','responsedescriptors','format','StringArray')
+		if not isempty(self.mass_flux_segments):
+			WriteData(fid,prefix,'data',self.mass_flux_segments,'name','md.qmu.mass_flux_segments','format','MatArray');
 			flag=True; 
 		else:
 			flag=False; 
-		WriteData(fid,'data',flag,'enum',QmuMassFluxSegmentsPresentEnum(),'format','Boolean');
+		WriteData(fid,prefix,'data',flag,'name','md.qmu.mass_flux_segments_present','format','Boolean');
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/results.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/results.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/results.py	(revision 23670)
@@ -1,6 +1,6 @@
-import numpy
+import numpy as np
+from pairoptions import pairoptions
 from fielddisplay import fielddisplay
 import MatlabFuncs as m
-from EnumDefinitions import *
 
 class results(object):
@@ -12,5 +12,5 @@
 	"""
 
-	def __init__(self):    # {{{
+	def __init__(self,*args):    # {{{
 		pass
 	# }}}
@@ -25,5 +25,5 @@
 			s+="%s\n" % fielddisplay(self,'SolutionType',"solution type")
 
-		for name in list(self.__dict__.keys()):
+		for name in self.__dict__.keys():
 			if name not in ['step','time','SolutionType','errlog','outlog']:
 				if   isinstance(getattr(self,name),list):
@@ -48,5 +48,5 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 		pass
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/rifts.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/rifts.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/rifts.py	(revision 23670)
@@ -1,5 +1,4 @@
-import numpy
+import numpy as np
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -34,5 +33,5 @@
 	#}}}
 	def checkconsistency(self,md,solution,analyses):    # {{{
-		if (not self.riftstruct) or numpy.any(isnans(self.riftstruct)):
+		if (not self.riftstruct) or np.any(isnans(self.riftstruct)):
 			numrifts=0
 		else:
@@ -44,19 +43,19 @@
 			if not isinstance(self.riftstruct,list):
 				md.checkmessage("rifts.riftstruct should be a structure!")
-			if numpy.any(md.mesh.segmentmarkers>=2):
+			if np.any(md.mesh.segmentmarkers>=2):
 				#We have segments with rift markers, but no rift structure!
 				md.checkmessage("model should be processed for rifts (run meshprocessrifts)!")
 			for i,rift in enumerate(self.riftstruct):
-				md = checkfield(md,'fieldname',"rifts.riftstruct[%d]['fill']" % i,'values',[WaterEnum(),AirEnum(),IceEnum(),MelangeEnum()])
+				md = checkfield(md,'fieldname',"rifts.riftstruct[%d]['fill']" % i,'values',['Water','Air','Ice','Melange',0,1,2,3])
 		else:
-			if self.riftstruct and numpy.any(numpy.logical_not(isnans(self.riftstruct))):
+			if self.riftstruct and np.any(np.logical_not(isnans(self.riftstruct))):
 				md.checkmessage("riftstruct should be NaN since numrifts is 0!")
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
 		#Process rift info
-		if (not self.riftstruct) or numpy.any(isnans(self.riftstruct)):
+		if (not self.riftstruct) or np.any(isnans(self.riftstruct)):
 			numrifts=0
 		else:
@@ -65,11 +64,20 @@
 		numpairs=0
 		for rift in self.riftstruct:
-			numpairs+=numpy.size(rift['penaltypairs'],axis=0)
+			numpairs+=np.size(rift['penaltypairs'],axis=0)
+
+		# Convert strings in riftstruct to hard coded numbers
+		FillDict={'Air':0,
+							'Ice':1,
+							'Melange':2,
+							'Water':3}
+		for rift in self.riftstruct:
+			if rift['fill'] in ['Air','Ice','Melange','Water']:
+				rift['fill'] = FillDict[rift['fill']]
 
 		# 2 for nodes + 2 for elements+ 2 for  normals + 1 for length + 1 for fill + 1 for friction + 1 for fraction + 1 for fractionincrement + 1 for state.
-		data=numpy.zeros((numpairs,12))
+		data=np.zeros((numpairs,12))
 		count=0
 		for rift in self.riftstruct:
-			numpairsforthisrift=numpy.size(rift['penaltypairs'],0)
+			numpairsforthisrift=np.size(rift['penaltypairs'],0)
 			data[count:count+numpairsforthisrift,0:7]=rift['penaltypairs']
 			data[count:count+numpairsforthisrift,7]=rift['fill']
@@ -80,5 +88,5 @@
 			count+=numpairsforthisrift
 
-		WriteData(fid,'data',numrifts,'enum',RiftsNumriftsEnum(),'format','Integer')
-		WriteData(fid,'data',data,'enum',RiftsRiftstructEnum(),'format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'data',numrifts,'name','md.rifts.numrifts','format','Integer')
+		WriteData(fid,prefix,'data',data,'name','md.rifts.riftstruct','format','DoubleMat','mattype',3)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/steadystate.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/steadystate.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/steadystate.py	(revision 23670)
@@ -1,5 +1,4 @@
-import numpy
+import numpy as np
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -49,5 +48,5 @@
 
 		#Early return
-		if not solution==SteadystateSolutionEnum():
+		if not solution=='SteadystateSolution':
 			return md
 
@@ -55,5 +54,5 @@
 			md.checkmessage("for a steadystate computation, timestepping.time_step must be zero.")
 
-		if numpy.isnan(md.stressbalance.reltol):
+		if np.isnan(md.stressbalance.reltol):
 			md.checkmessage("for a steadystate computation, stressbalance.reltol (relative convergence criterion) must be defined!")
 
@@ -62,7 +61,7 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'object',self,'fieldname','reltol','format','Double')
-		WriteData(fid,'object',self,'fieldname','maxiter','format','Integer')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'object',self,'fieldname','reltol','format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','maxiter','format','Integer')
 
 		#process requested outputs
@@ -72,4 +71,4 @@
 			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
 			outputs    =outputscopy
-		WriteData(fid,'data',outputs,'enum',SteadystateRequestedOutputsEnum(),'format','StringArray')
+		WriteData(fid,prefix,'data',outputs,'name','md.steadystate.requested_outputs','format','StringArray')
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/stressbalance.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/stressbalance.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/stressbalance.py	(revision 23670)
@@ -1,8 +1,7 @@
-import numpy
+import numpy as np
 import sys
 import copy
 from project3d import project3d
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -123,5 +122,5 @@
 
 		#Early return
-		if StressbalanceAnalysisEnum() not in analyses:
+		if 'StressbalanceAnalysis' not in analyses:
 			return md
 
@@ -142,51 +141,53 @@
 		#singular solution
 #		if ~any((~isnan(md.stressbalance.spcvx)+~isnan(md.stressbalance.spcvy))==2),
-		if not numpy.any(numpy.logical_and(numpy.logical_not(numpy.isnan(md.stressbalance.spcvx)),numpy.logical_not(numpy.isnan(md.stressbalance.spcvy)))):
+		if not np.any(np.logical_and(np.logical_not(np.isnan(md.stressbalance.spcvx)),np.logical_not(np.isnan(md.stressbalance.spcvy)))):
 			print("\n !!! Warning: no spc applied, model might not be well posed if no basal friction is applied, check for solution crash\n")
 		#CHECK THAT EACH LINES CONTAINS ONLY NAN VALUES OR NO NAN VALUES
 #		if any(sum(isnan(md.stressbalance.referential),2)~=0 & sum(isnan(md.stressbalance.referential),2)~=6),
-		if numpy.any(numpy.logical_and(numpy.sum(numpy.isnan(md.stressbalance.referential),axis=1)!=0,numpy.sum(numpy.isnan(md.stressbalance.referential),axis=1)!=6)):
+		if np.any(np.logical_and(np.sum(np.isnan(md.stressbalance.referential),axis=1)!=0,np.sum(np.isnan(md.stressbalance.referential),axis=1)!=6)):
 			md.checkmessage("Each line of stressbalance.referential should contain either only NaN values or no NaN values")
 		#CHECK THAT THE TWO VECTORS PROVIDED ARE ORTHOGONAL
 #		if any(sum(isnan(md.stressbalance.referential),2)==0),
-		if numpy.any(numpy.sum(numpy.isnan(md.stressbalance.referential),axis=1)==0):
-			pos=[i for i,item in enumerate(numpy.sum(numpy.isnan(md.stressbalance.referential),axis=1)) if item==0]
-#			numpy.inner (and numpy.dot) calculate all the dot product permutations, resulting in a full matrix multiply
-#			if numpy.any(numpy.abs(numpy.inner(md.stressbalance.referential[pos,0:2],md.stressbalance.referential[pos,3:5]).diagonal())>sys.float_info.epsilon):
+		if np.any(np.sum(np.isnan(md.stressbalance.referential),axis=1)==0):
+			pos=[i for i,item in enumerate(np.sum(np.isnan(md.stressbalance.referential),axis=1)) if item==0]
+#			np.inner (and np.dot) calculate all the dot product permutations, resulting in a full matrix multiply
+#			if np.any(np.abs(np.inner(md.stressbalance.referential[pos,0:2],md.stressbalance.referential[pos,3:5]).diagonal())>sys.float_info.epsilon):
 #				md.checkmessage("Vectors in stressbalance.referential (columns 1 to 3 and 4 to 6) must be orthogonal")
 			for item in md.stressbalance.referential[pos,:]:
-				if numpy.abs(numpy.inner(item[0:2],item[3:5]))>sys.float_info.epsilon:
+				if np.abs(np.inner(item[0:2],item[3:5]))>sys.float_info.epsilon:
 					md.checkmessage("Vectors in stressbalance.referential (columns 1 to 3 and 4 to 6) must be orthogonal")
 		#CHECK THAT NO rotation specified for FS Grounded ice at base
 		if m.strcmp(md.mesh.domaintype(),'3D') and md.flowequation.isFS:
-			pos=numpy.nonzero(numpy.logical_and(md.mask.groundedice_levelset,md.mesh.vertexonbase))
-			if numpy.any(numpy.logical_not(numpy.isnan(md.stressbalance.referential[pos,:]))):
+			pos=np.nonzero(np.logical_and(md.mask.groundedice_levelset,md.mesh.vertexonbase))
+			if np.any(np.logical_not(np.isnan(md.stressbalance.referential[pos,:]))):
 				md.checkmessage("no referential should be specified for basal vertices of grounded ice")
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-
-		yts=365.0*24.0*3600.0
-
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','spcvx','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','spcvy','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','spcvz','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','restol','format','Double')
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','reltol','format','Double')
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','abstol','format','Double','scale',1./yts)
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','isnewton','format','Integer')
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','FSreconditioning','format','Double')
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','maxiter','format','Integer')
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','shelf_dampening','format','Integer')
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','vertex_pairing','format','DoubleMat','mattype',3)
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','penalty_factor','format','Double')
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','rift_penalty_lock','format','Integer')
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','rift_penalty_threshold','format','Integer')
-		WriteData(fid,'object',self,'class','stressbalance','fieldname','referential','format','DoubleMat','mattype',1)
-
-		WriteData(fid,'data',self.loadingforce[:,0],'format','DoubleMat','mattype',1,'enum',LoadingforceXEnum())
-		WriteData(fid,'data',self.loadingforce[:,1],'format','DoubleMat','mattype',1,'enum',LoadingforceYEnum())
-		WriteData(fid,'data',self.loadingforce[:,2],'format','DoubleMat','mattype',1,'enum',LoadingforceZEnum())
+	def marshall(self,prefix,md,fid):    # {{{
+
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','vertex_pairing','format','DoubleMat','mattype',3)
+
+		yts=md.constants.yts
+
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','spcvx','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','spcvy','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','spcvz','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','restol','format','Double')
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','reltol','format','Double')
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','abstol','format','Double','scale',1./yts)
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','isnewton','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','FSreconditioning','format','Double')
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','maxiter','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','shelf_dampening','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','penalty_factor','format','Double')
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','rift_penalty_lock','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','rift_penalty_threshold','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','referential','format','DoubleMat','mattype',1)
+
+		if isinstance(self.loadingforce, (list, tuple, np.ndarray)) and np.size(self.loadingforce,1) == 3:
+			WriteData(fid,prefix,'data',self.loadingforce[:,0],'format','DoubleMat','mattype',1,'name','md.stressbalance.loadingforcex')
+			WriteData(fid,prefix,'data',self.loadingforce[:,1],'format','DoubleMat','mattype',1,'name','md.stressbalance.loadingforcey')
+			WriteData(fid,prefix,'data',self.loadingforce[:,2],'format','DoubleMat','mattype',1,'name','md.stressbalance.loadingforcez')
 
 		#process requested outputs
@@ -196,4 +197,4 @@
 			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
 			outputs    =outputscopy
-		WriteData(fid,'data',outputs,'enum',StressbalanceRequestedOutputsEnum(),'format','StringArray')
+		WriteData(fid,prefix,'data',outputs,'name','md.stressbalance.requested_outputs','format','StringArray')
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/taoinversion.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/taoinversion.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/taoinversion.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 from project3d import project3d
 from WriteData import WriteData
@@ -5,31 +5,32 @@
 from fielddisplay import fielddisplay
 from IssmConfig import IssmConfig
-from EnumDefinitions import *
 from marshallcostfunctions import marshallcostfunctions
+from supportedcontrols import *
+from supportedcostfunctions import *
 
-
-class taoinversion:
+class taoinversion(object):
 	def __init__(self):
-		iscontrol                   = 0
-		incomplete_adjoint          = 0
-		control_parameters          = float('NaN')
-		maxsteps                    = 0
-		maxiter                     = 0
-		fatol                       = 0
-		frtol                       = 0
-		gatol                       = 0
-		grtol                       = 0
-		gttol                       = 0
-		algorithm                   = ''
-		cost_functions              = float('NaN')
-		cost_functions_coefficients = float('NaN')
-		min_parameters              = float('NaN')
-		max_parameters              = float('NaN')
-		vx_obs                      = float('NaN')
-		vy_obs                      = float('NaN')
-		vz_obs                      = float('NaN')
-		vel_obs                     = float('NaN')
-		thickness_obs               = float('NaN')
-		surface_obs                 = float('NaN')
+		self.iscontrol                   = 0
+		self.incomplete_adjoint          = 0
+		self.control_parameters          = float('NaN')
+		self.maxsteps                    = 0
+		self.maxiter                     = 0
+		self.fatol                       = 0
+		self.frtol                       = 0
+		self.gatol                       = 0
+		self.grtol                       = 0
+		self.gttol                       = 0
+		self.algorithm                   = ''
+		self.cost_functions              = float('NaN')
+		self.cost_functions_coefficients = float('NaN')
+		self.min_parameters              = float('NaN')
+		self.max_parameters              = float('NaN')
+		self.vx_obs                      = float('NaN')
+		self.vy_obs                      = float('NaN')
+		self.vz_obs                      = float('NaN')
+		self.vel_obs                     = float('NaN')
+		self.thickness_obs               = float('NaN')
+		self.surface_obs                 = float('NaN')
+		self.setdefaultparameters()
 
 	def __repr__(self):
@@ -90,14 +91,13 @@
 
 		#minimization algorithm
-		PETSCMAJOR = IssmConfig('_PETSC_MAJOR_')
-		PETSCMINOR = IssmConfig('_PETSC_MINOR_')
+		PETSCMAJOR = IssmConfig('_PETSC_MAJOR_')[0]
+		PETSCMINOR = IssmConfig('_PETSC_MINOR_')[0]
 		if(PETSCMAJOR>3 or (PETSCMAJOR==3 and PETSCMINOR>=5)):
 			self.algorithm = 'blmvm';
 		else:
 			self.algorithm = 'tao_blmvm';
-		
+
 		#several responses can be used:
 		self.cost_functions=101;
-
 		return self
 
@@ -110,8 +110,8 @@
 		if numel(self.cost_functions_coefficients) > 1:
 			self.cost_functions_coefficients=project3d(md,'vector',self.cost_functions_coefficients,'type','node')
-		
+
 		if numel(self.min_parameters) > 1:
 			self.min_parameters=project3d(md,'vector',self.min_parameters,'type','node')
-		
+
 		if numel(self.max_parameters)>1:
 			self.max_parameters=project3d(md,'vector',self.max_parameters,'type','node')
@@ -120,15 +120,15 @@
 
 	def checkconsistency(self,md,solution,analyses):
-		if not self.control:
+		if not self.iscontrol:
 			return md
-		if not IssmConfig('_HAVE_TAO_'):
-			md = checkmessage(md,['TAO has not been installed, ISSM needs to be reconfigured and recompiled with TAO'])
+		if not IssmConfig('_HAVE_TAO_')[0]:
+			md = md.checkmessage('TAO has not been installed, ISSM needs to be reconfigured and recompiled with TAO')
 
 
-		num_controls= numpy.numel(md.inversion.control_parameters)
-		num_costfunc= numpy.size(md.inversion.cost_functions,2)
+		num_controls= np.size(md.inversion.control_parameters)
+		num_costfunc= np.size(md.inversion.cost_functions)
 
 		md = checkfield(md,'fieldname','inversion.iscontrol','values',[0, 1])
-		md = checkfield(md,'fieldname','inversion.incomplete_adjoint','values',[0, 1])
+		md = checkfield(md,'fieldname','inversion.incomplete_adjoint','values',[0,1])
 		md = checkfield(md,'fieldname','inversion.control_parameters','cell',1,'values',supportedcontrols())
 		md = checkfield(md,'fieldname','inversion.maxsteps','numel',1,'>=',0)
@@ -141,13 +141,13 @@
 
 
-		PETSCMAJOR = IssmConfig('_PETSC_MAJOR_')
-		PETSCMINOR = IssmConfig('_PETSC_MINOR_')
+		PETSCMAJOR = IssmConfig('_PETSC_MAJOR_')[0]
+		PETSCMINOR = IssmConfig('_PETSC_MINOR_')[0]
 		if(PETSCMAJOR>3 or (PETSCMAJOR==3 and PETSCMINOR>=5)):
-			md = checkfield(md,'fieldname','inversion.algorithm','values',{'blmvm','cg','lmvm'})
+			md = checkfield(md,'fieldname','inversion.algorithm','values',['blmvm','cg','lmvm'])
 		else:
-			md = checkfield(md,'fieldname','inversion.algorithm','values',{'tao_blmvm','tao_cg','tao_lmvm'})
+			md = checkfield(md,'fieldname','inversion.algorithm','values',['tao_blmvm','tao_cg','tao_lmvm'])
 
 
-		md = checkfield(md,'fieldname','inversion.cost_functions','size',[1, num_costfunc],'values',supportedcostfunctions())
+		md = checkfield(md,'fieldname','inversion.cost_functions','size', [num_costfunc],'values',supportedcostfunctions())
 		md = checkfield(md,'fieldname','inversion.cost_functions_coefficients','size',[md.mesh.numberofvertices, num_costfunc],'>=',0)
 		md = checkfield(md,'fieldname','inversion.min_parameters','size',[md.mesh.numberofvertices, num_controls])
@@ -155,46 +155,45 @@
 
 
-		if solution==BalancethicknessSolutionEnum():
-			md = checkfield(md,'fieldname','inversion.thickness_obs','size',[md.mesh.numberofvertices, 1],'NaN',1,'Inf',1)
-		elif solution==BalancethicknessSoftSolutionEnum():
-			md = checkfield(md,'fieldname','inversion.thickness_obs','size',[md.mesh.numberofvertices, 1],'NaN',1,'Inf',1)
+		if solution=='BalancethicknessSolution':
+			md = checkfield(md,'fieldname','inversion.thickness_obs','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
+		elif solution=='BalancethicknessSoftSolution':
+			md = checkfield(md,'fieldname','inversion.thickness_obs','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 		else:
-			md = checkfield(md,'fieldname','inversion.vx_obs','size',[md.mesh.numberofvertices, 1],'NaN',1,'Inf',1)
-			md = checkfield(md,'fieldname','inversion.vy_obs','size',[md.mesh.numberofvertices, 1],'NaN',1,'Inf',1)
+			md = checkfield(md,'fieldname','inversion.vx_obs','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
+			md = checkfield(md,'fieldname','inversion.vy_obs','size',[md.mesh.numberofvertices],'NaN',1,'Inf',1)
 
-		def marshall(self, md, fid):
+	def marshall(self,prefix,md,fid):
 
-			yts=365.0*24.0*3600.0;
-			WriteData(fid,'object',self,'class','inversion','fieldname','iscontrol','format','Boolean')
-			WriteData(fid,'enum',InversionTypeEnum(),'data',1,'format','Integer')
-			if not self.iscontrol:
-				return
-			WriteData(fid,'object',self,'class','inversion','fieldname','incomplete_adjoint','format','Boolean')
-			WriteData(fid,'object',self,'class','inversion','fieldname','maxsteps','format','Integer')
-			WriteData(fid,'object',self,'class','inversion','fieldname','maxiter','format','Integer')
-			WriteData(fid,'object',self,'class','inversion','fieldname','fatol','format','Double')
-			WriteData(fid,'object',self,'class','inversion','fieldname','frtol','format','Double')
-			WriteData(fid,'object',self,'class','inversion','fieldname','gatol','format','Double')
-			WriteData(fid,'object',self,'class','inversion','fieldname','grtol','format','Double')
-			WriteData(fid,'object',self,'class','inversion','fieldname','gttol','format','Double')
-			WriteData(fid,'object',self,'class','inversion','fieldname','algorithm','format','String')
-			WriteData(fid,'object',self,'class','inversion','fieldname','cost_functions_coefficients','format','DoubleMat','mattype',1)
-			WriteData(fid,'object',self,'class','inversion','fieldname','min_parameters','format','DoubleMat','mattype',3)
-			WriteData(fid,'object',self,'class','inversion','fieldname','max_parameters','format','DoubleMat','mattype',3)
-			WriteData(fid,'object',self,'class','inversion','fieldname','vx_obs','format','DoubleMat','mattype',1,'scale',1./yts)
-			WriteData(fid,'object',self,'class','inversion','fieldname','vy_obs','format','DoubleMat','mattype',1,'scale',1./yts)
-			WriteData(fid,'object',self,'class','inversion','fieldname','vz_obs','format','DoubleMat','mattype',1,'scale',1./yts)
-			WriteData(fid,'object',self,'class','inversion','fieldname','thickness_obs','format','DoubleMat','mattype',1)
-			WriteData(fid,'object',self,'class','inversion','fieldname','surface_obs','format','DoubleMat','mattype',1)
+		yts=md.constants.yts;
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','iscontrol','format','Boolean')
+		WriteData(fid,prefix,'name','md.inversion.type','data',1,'format','Integer')
+		if not self.iscontrol:
+			return
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','incomplete_adjoint','format','Boolean')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','maxsteps','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','maxiter','format','Integer')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','fatol','format','Double')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','frtol','format','Double')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','gatol','format','Double')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','grtol','format','Double')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','gttol','format','Double')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','algorithm','format','String')
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','cost_functions_coefficients','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','min_parameters','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','max_parameters','format','DoubleMat','mattype',3)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','vx_obs','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','vy_obs','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','vz_obs','format','DoubleMat','mattype',1,'scale',1./yts)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','thickness_obs','format','DoubleMat','mattype',1)
+		WriteData(fid,prefix,'object',self,'class','inversion','fieldname','surface_obs','format','DoubleMat','mattype',1)
 
-			#process control parameters
-			num_control_parameters = numpy.numel(self.control_parameters)
-			data = numpy.array([StringToEnum(self.control_parameter[0]) for control_parameter in self.control_parameters]).reshape(1,-1)
-			WriteData(fid,'data',data,'enum',InversionControlParametersEnum(),'format','DoubleMat','mattype',3)
-			WriteData(fid,'data',num_control_parameters,'enum',InversionNumControlParametersEnum(),'format','Integer')
+		#process control parameters
+		num_control_parameters = np.size(self.control_parameters)
+		WriteData(fid,prefix,'object',self,'fieldname','control_parameters','format','StringArray')
+		WriteData(fid,prefix,'data',num_control_parameters,'name','md.inversion.num_control_parameters','format','Integer')
 
-			#process cost functions
-			num_cost_functions = numpy.size(self.cost_functions,2)
-			data= marshallcostfunctions(self.cost_functions)
-			WriteData(fid,'data',data,'enum',InversionCostFunctionsEnum(),'format','DoubleMat','mattype',3)
-			WriteData(fid,'data',num_cost_functions,'enum',InversionNumCostFunctionsEnum(),'format','Integer')
+		#process cost functions
+		num_cost_functions = np.size(self.cost_functions)
+		data= marshallcostfunctions(self.cost_functions)
+		WriteData(fid,prefix,'data',data,'name','md.inversion.cost_functions','format','StringArray')
+		WriteData(fid,prefix,'data',num_cost_functions,'name','md.inversion.num_cost_functions','format','Integer')
Index: /issm/trunk-jpl/src/py3/classes/thermal.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/thermal.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/thermal.py	(revision 23670)
@@ -1,9 +1,7 @@
-import numpy
+import numpy as  np
 from project3d import project3d
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
-import MatlabFuncs as m
 
 class thermal(object):
@@ -24,5 +22,6 @@
 		self.penalty_factor    = 0
 		self.isenthalpy        = 0
-		self.isdynamicbasalspc = 0;
+		self.isdynamicbasalspc = 0
+		self.fe                = 'P1'
 		self.requested_outputs = []
 
@@ -45,8 +44,8 @@
 		#}}}
 	def extrude(self,md): # {{{
-		self.spctemperature=project3d(md,'vector',self.spctemperature,'type','node','layer',md.mesh.numberoflayers,'padding',numpy.nan)
-		if isinstance(md.initialization.temperature,numpy.ndarray) and numpy.size(md.initialization.temperature,axis=0)==md.mesh.numberofvertices:
-			self.spctemperature=numpy.nan*numpy.ones((md.mesh.numberofvertices,1))
-			pos=numpy.nonzero(md.mesh.vertexonsurface)[0]
+		self.spctemperature=project3d(md,'vector',self.spctemperature,'type','node','layer',md.mesh.numberoflayers,'padding',np.nan)
+		if isinstance(md.initialization.temperature,np.ndarray) and np.size(md.initialization.temperature,axis=0)==md.mesh.numberofvertices:
+			self.spctemperature=float('NaN')*np.ones((md.mesh.numberofvertices))
+			pos=np.where(md.mesh.vertexonsurface)[0]
 			self.spctemperature[pos]=md.initialization.temperature[pos]    #impose observed temperature on surface
 		return self
@@ -81,5 +80,8 @@
 
 		#will basal boundary conditions be set dynamically
-		self.isdynamicbasalspc=0;
+		self.isdynamicbasalspc=0
+
+		#Finite element interpolation
+		self.fe='P1'
 
 		#default output
@@ -91,33 +93,45 @@
 
 		#Early return
-		if (ThermalAnalysisEnum() not in analyses and EnthalpyAnalysisEnum() not in analyses) or (solution==TransientSolutionEnum() and not md.transient.isthermal):
+		if ('ThermalAnalysis' not in analyses and 'EnthalpyAnalysis' not in analyses) or (solution=='TransientSolution' and not md.transient.isthermal):
 			return md
 
 		md = checkfield(md,'fieldname','thermal.stabilization','numel',[1],'values',[0,1,2])
 		md = checkfield(md,'fieldname','thermal.spctemperature','Inf',1,'timeseries',1)
-		if EnthalpyAnalysisEnum() in analyses and md.thermal.isenthalpy and md.mesh.dimension()==3:
-			pos=numpy.nonzero(numpy.logical_not(numpy.isnan(md.thermal.spctemperature[0:md.mesh.numberofvertices])))
-			replicate=numpy.tile(md.geometry.surface-md.mesh.z,(1,numpy.size(md.thermal.spctemperature,axis=1)))
-			md = checkfield(md,'fieldname','thermal.spctemperature[numpy.nonzero(numpy.logical_not(numpy.isnan(md.thermal.spctemperature[0:md.mesh.numberofvertices,:])))]','<',md.materials.meltingpoint-md.materials.beta*md.materials.rho_ice*md.constants.g*replicate[pos],'message',"spctemperature should be below the adjusted melting point")
+		md = checkfield(md,'fieldname','thermal.requested_outputs','stringrow',1)
+
+		if 'EnthalpyAnalysis' in analyses and md.thermal.isenthalpy and md.mesh.dimension()==3:
+			TEMP = md.thermal.spctemperature[:-1].flatten(-1)
+			pos=np.where(~np.isnan(TEMP))
+			try:
+				spccol=np.size(md.thermal.spctemperature,1)
+			except IndexError:
+				spccol=1
+
+			replicate=np.tile(md.geometry.surface-md.mesh.z,(spccol)).flatten(-1)
+
+			control=md.materials.meltingpoint-md.materials.beta*md.materials.rho_ice*md.constants.g*replicate+10**-5
+
+			md = checkfield(md,'fieldname','thermal.spctemperature','field',md.thermal.spctemperature.flatten(-1)[pos],'<=',control[pos],'message',"spctemperature should be below the adjusted melting point")
 			md = checkfield(md,'fieldname','thermal.isenthalpy','numel',[1],'values',[0,1])
 			md = checkfield(md,'fieldname','thermal.isdynamicbasalspc','numel',[1],'values',[0,1]);
 			if(md.thermal.isenthalpy):
-				if numpy.isnan(md.stressbalance.reltol):
+				if np.isnan(md.stressbalance.reltol):
 					md.checkmessage("for a steadystate computation, thermal.reltol (relative convergence criterion) must be defined!")
 				md = checkfield(md,'fieldname','thermal.reltol','>',0.,'message',"reltol must be larger than zero");
-		md = checkfield(md,'fieldname','thermal.requested_outputs','stringrow',1)
+
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'object',self,'fieldname','spctemperature','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1)
-		WriteData(fid,'object',self,'fieldname','penalty_threshold','format','Integer')
-		WriteData(fid,'object',self,'fieldname','stabilization','format','Integer')
-		WriteData(fid,'object',self,'fieldname','reltol','format','Double');
-		WriteData(fid,'object',self,'fieldname','maxiter','format','Integer')
-		WriteData(fid,'object',self,'fieldname','penalty_lock','format','Integer')
-		WriteData(fid,'object',self,'fieldname','penalty_factor','format','Double')
-		WriteData(fid,'object',self,'fieldname','isenthalpy','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','isdynamicbasalspc','format','Boolean');
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'object',self,'fieldname','spctemperature','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts)
+		WriteData(fid,prefix,'object',self,'fieldname','penalty_threshold','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','stabilization','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','reltol','format','Double');
+		WriteData(fid,prefix,'object',self,'fieldname','maxiter','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','penalty_lock','format','Integer')
+		WriteData(fid,prefix,'object',self,'fieldname','penalty_factor','format','Double')
+		WriteData(fid,prefix,'object',self,'fieldname','isenthalpy','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','fe','format','String');
+		WriteData(fid,prefix,'object',self,'fieldname','isdynamicbasalspc','format','Boolean');
 
 		#process requested outputs
@@ -127,4 +141,4 @@
 			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
 			outputs    =outputscopy
-		WriteData(fid,'data',outputs,'enum',ThermalRequestedOutputsEnum(),'format','StringArray')
+		WriteData(fid,prefix,'data',outputs,'name','md.thermal.requested_outputs','format','StringArray')
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/timestepping.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/timestepping.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/timestepping.py	(revision 23670)
@@ -1,4 +1,3 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -16,7 +15,6 @@
 		self.final_time      = 0.
 		self.time_step       = 0.
-		self.time_adapt      = 0
-		self.cfl_coefficient = 0.
 		self.interp_forcings = 1
+		self.coupling_time   = 0.
 		
 		#set defaults
@@ -29,7 +27,6 @@
 		string="%s\n%s"%(string,fielddisplay(self,"final_time","final time to stop the simulation [yr]"))
 		string="%s\n%s"%(string,fielddisplay(self,"time_step","length of time steps [yr]"))
-		string="%s\n%s"%(string,fielddisplay(self,"time_adapt","use cfl condition to define time step ? (0 or 1) "))
-		string="%s\n%s"%(string,fielddisplay(self,"cfl_coefficient","coefficient applied to cfl condition"))
 		string="%s\n%s"%(string,fielddisplay(self,"interp_forcings","interpolate in time between requested forcing values ? (0 or 1)"))
+		string="%s\n%s"%(string,fielddisplay(self,"coupling_time","length of coupling time steps with ocean model [yr]"))
 		return string
 		#}}}
@@ -42,8 +39,4 @@
 		self.final_time=10.*self.time_step
 
-		#time adaptation? 
-		self.time_adapt=0
-		self.cfl_coefficient=0.5
-		
 		#should we interpolate forcings between timesteps?
 		self.interp_forcings=1
@@ -56,21 +49,19 @@
 		md = checkfield(md,'fieldname','timestepping.final_time','numel',[1],'NaN',1,'Inf',1)
 		md = checkfield(md,'fieldname','timestepping.time_step','numel',[1],'>=',0,'NaN',1,'Inf',1)
-		md = checkfield(md,'fieldname','timestepping.time_adapt','numel',[1],'values',[0,1])
-		md = checkfield(md,'fieldname','timestepping.cfl_coefficient','numel',[1],'>',0,'<=',1)
 		if self.final_time-self.start_time<0:
 			md.checkmessage("timestepping.final_time should be larger than timestepping.start_time")
+			md = checkfield(md,'fieldname','timestepping.coupling_time','numel',[1],'>=',0,'NaN',1,'Inf',1)
 		md = checkfield(md,'fieldname','timestepping.interp_forcings','numel',[1],'values',[0,1])
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
+	def marshall(self,prefix,md,fid):    # {{{
 
 		yts=md.constants.yts
-		
-		WriteData(fid,'object',self,'fieldname','start_time','format','Double','scale',yts)
-		WriteData(fid,'object',self,'fieldname','final_time','format','Double','scale',yts)
-		WriteData(fid,'object',self,'fieldname','time_step','format','Double','scale',yts)
-		WriteData(fid,'object',self,'fieldname','time_adapt','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','cfl_coefficient','format','Double')
-		WriteData(fid,'object',self,'fieldname','interp_forcings','format','Boolean')
+		WriteData(fid,prefix,'name','md.timestepping.type','data',1,'format','Integer');
+		WriteData(fid,prefix,'object',self,'fieldname','start_time','format','Double','scale',yts)
+		WriteData(fid,prefix,'object',self,'fieldname','final_time','format','Double','scale',yts)
+		WriteData(fid,prefix,'object',self,'fieldname','time_step','format','Double','scale',yts)
+		WriteData(fid,prefix,'object',self,'fieldname','interp_forcings','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','coupling_time','format','Double','scale',yts)
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/toolkits.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/toolkits.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/toolkits.py	(revision 23670)
@@ -2,8 +2,8 @@
 from mumpsoptions import mumpsoptions
 from iluasmoptions import iluasmoptions
-from EnumToString import EnumToString
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
+from issmgslsolver import issmgslsolver
+from issmmumpssolver import issmmumpssolver
 
 class toolkits(object):
@@ -30,10 +30,10 @@
 			else:
 				raise IOError("ToolkitsFile error: need at least Mumps or Gsl to define issm solver type")
+
 		#The other properties are dynamic
 	# }}}
 	def __repr__(self):    # {{{
-		print('enter repr')
 		s ="List of toolkits options per analysis:\n\n"
-		for analysis in list(vars(self).keys()):
+		for analysis in vars(self).keys():
 			s+="%s\n" % fielddisplay(self,analysis,'')
 
@@ -41,15 +41,10 @@
 	# }}}
 	def addoptions(self,analysis,*args):    # {{{
-		print('enter addoption')
 		# Usage example:
-		#    md.toolkits=addoptions(md.toolkits,StressbalanceAnalysisEnum(),FSoptions());
-		#    md.toolkits=addoptions(md.toolkits,StressbalanceAnalysisEnum());
-
-		#Convert analysis from enum to string
-		[analysis]=EnumToString(analysis)
+		#    md.toolkits=addoptions(md.toolkits,'StressbalanceAnalysis',FSoptions());
+		#    md.toolkits=addoptions(md.toolkits,'StressbalanceAnalysis');
 
 		#Create dynamic property if property does not exist yet
 		if not hasattr(self,analysis):
-#			exec("self.%s = None" % analysis)
 			setattr(self,analysis,None)
 
@@ -61,6 +56,5 @@
 	# }}}
 	def checkconsistency(self,md,solution,analyses):    # {{{
-		print('enter check')
-		for analysis in list(vars(self).keys()):
+		for analysis in vars(self).keys():
 			if not getattr(self,analysis):
 				md.checkmessage("md.toolkits.%s is empty" % analysis)
@@ -86,15 +80,14 @@
 
 		#write header
-		fid.write("%s%s%s\n" % ('%Petsc options file: ',filename,' written from Matlab toolkits array'))
+		fid.write("%s%s%s\n" % ('%Toolkits options file: ',filename,' written from Python toolkits array'))
 
 		#start writing options
-		for analysis in list(vars(self).keys()):
+		for analysis in vars(self).keys():
 			options=getattr(self,analysis)
 
 			#first write analysis:
 			fid.write("\n+%s\n" % analysis)    #append a + to recognize it's an analysis enum
-
 			#now, write options
-			for optionname,optionvalue in list(options.items()):
+			for optionname,optionvalue in options.items():
 
 				if not optionvalue:
Index: /issm/trunk-jpl/src/py3/classes/transient.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/transient.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/transient.py	(revision 23670)
@@ -1,4 +1,3 @@
 from fielddisplay import fielddisplay
-from EnumDefinitions import *
 from checkfield import checkfield
 from WriteData import WriteData
@@ -13,5 +12,5 @@
 
 	def __init__(self): # {{{
-		self.issmb   = False
+		self.issmb   	       = False
 		self.ismasstransport   = False
 		self.isstressbalance   = False
@@ -19,8 +18,12 @@
 		self.isgroundingline   = False
 		self.isgia             = False
+		self.isesa             = False
 		self.isdamageevolution = False
-		self.islevelset        = False
-		self.iscalving         = False
+		self.ismovingfront     = False
 		self.ishydrology       = False
+		self.isslr             = False
+		self.iscoupler         = False
+		self.amr_frequency     = 0
+		self.isoceancoupling   = False
 		self.requested_outputs = []
 
@@ -37,8 +40,12 @@
 		string="%s\n%s"%(string,fielddisplay(self,'isgroundingline','indicates if a groundingline migration is used in the transient'))
 		string="%s\n%s"%(string,fielddisplay(self,'isgia','indicates if a postglacial rebound is used in the transient'))
+		string="%s\n%s"%(string,fielddisplay(self,'isesa','indicates whether an elastic adjustment model is used in the transient'))
 		string="%s\n%s"%(string,fielddisplay(self,'isdamageevolution','indicates whether damage evolution is used in the transient'))
-		string="%s\n%s"%(string,fielddisplay(self,'islevelset','LEVELSET METHOD DESCRIPTION'))
-		string="%s\n%s"%(string,fielddisplay(self,'iscalving','indicates whether calving is used in the transient'))
+		string="%s\n%s"%(string,fielddisplay(self,'ismovingfront','indicates whether a moving front capability is used in the transient'))
 		string="%s\n%s"%(string,fielddisplay(self,'ishydrology','indicates whether an hydrology model is used'))
+		string="%s\n%s"%(string,fielddisplay(self,'isslr','indicates if a sea level rise solution is used in the transient'))
+		string="%s\n%s"%(string,fielddisplay(self,'isoceancoupling','indicates whether coupling with an ocean model is used in the transient'))
+		string="%s\n%s"%(string,fielddisplay(self,'iscoupler','indicates whether different models are being run with need for coupling'))
+		string="%s\n%s"%(string,fielddisplay(self,'amr_frequency','frequency at which mesh is refined in simulations with multiple time_steps'))
 		string="%s\n%s"%(string,fielddisplay(self,'requested_outputs','list of additional outputs requested'))
 		return string
@@ -61,8 +68,32 @@
 		self.isgroundingline   = False
 		self.isgia             = False
+		self.isesa             = False
 		self.isdamageevolution = False
-		self.islevelset        = False
-		self.iscalving         = False
+		self.ismovingfront     = False
 		self.ishydrology       = False
+		self.isoceancoupling   = False
+		self.isslr             = False
+		self.iscoupler         = False
+		self.amr_frequency	  = 0
+
+		#default output
+		self.requested_outputs=[]
+		return self
+	#}}}
+	def deactivateall(self):#{{{
+		self.issmb             = False
+		self.ismasstransport   = False
+		self.isstressbalance   = False
+		self.isthermal         = False
+		self.isgroundingline   = False
+		self.isgia             = False
+		self.isesa             = False
+		self.isdamageevolution = False
+		self.ismovingfront     = False
+		self.ishydrology       = False
+		self.isslr             = False
+		self.isoceancoupling   = False
+		self.iscoupler         = False
+		self.amr_frequency     = 0
 
 		#default output
@@ -73,14 +104,18 @@
 		
 		#full analysis: Stressbalance, Masstransport and Thermal but no groundingline migration for now
-		self.issmb = True
-		self.ismasstransport = True
-		self.isstressbalance = True
-		self.isthermal       = True
-		self.isgroundingline = False
-		self.isgia           = False
+		self.issmb             = True
+		self.ismasstransport   = True
+		self.isstressbalance   = True
+		self.isthermal         = True
+		self.isgroundingline   = False
+		self.isgia             = False
+		self.isesa             = False
 		self.isdamageevolution = False
-		self.islevelset      = False
-		self.iscalving       = False
-		self.ishydrology     = False
+		self.ismovingfront     = False
+		self.ishydrology       = False
+		self.isslr             = False
+		self.isoceancoupling   = False
+		self.iscoupler         = False
+		self.amr_frequency     = 0
 
 		#default output
@@ -91,5 +126,5 @@
 
 		#Early return
-		if not solution==TransientSolutionEnum():
+		if not solution=='TransientSolution':
 			return md
 
@@ -100,23 +135,34 @@
 		md = checkfield(md,'fieldname','transient.isgroundingline','numel',[1],'values',[0,1])
 		md = checkfield(md,'fieldname','transient.isgia','numel',[1],'values',[0,1])
+		md = checkfield(md,'fieldname','transient.isesa','numel',[1],'values',[0,1])
 		md = checkfield(md,'fieldname','transient.isdamageevolution','numel',[1],'values',[0,1])
-		md = checkfield(md,'fieldname','transient.islevelset','numel',[1],'values',[0,1])
 		md = checkfield(md,'fieldname','transient.ishydrology','numel',[1],'values',[0,1])
-		md = checkfield(md,'fieldname','transient.iscalving','numel',[1],'values',[0,1]);
+		md = checkfield(md,'fieldname','transient.ismovingfront','numel',[1],'values',[0,1]);
+		md = checkfield(md,'fieldname','transient.isslr','numel',[1],'values',[0,1])
+		md = checkfield(md,'fieldname','transient.isoceancoupling','numel',[1],'values',[0,1])
+		md = checkfield(md,'fieldname','transient.iscoupler','numel',[1],'values',[0,1])
+		md = checkfield(md,'fieldname','transient.amr_frequency','numel',[1],'>=',0,'NaN',1,'Inf',1)
 		md = checkfield(md,'fieldname','transient.requested_outputs','stringrow',1)
+
+		if (solution!='TransientSolution') and (md.transient.iscoupling):
+				md.checkmessage("Coupling with ocean can only be done in transient simulations!")
 
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'object',self,'fieldname','issmb','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','ismasstransport','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','isstressbalance','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','isthermal','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','isgroundingline','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','isgia','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','isdamageevolution','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','islevelset','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','ishydrology','format','Boolean')
-		WriteData(fid,'object',self,'fieldname','iscalving','format','Boolean')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'object',self,'fieldname','issmb','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','ismasstransport','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','isstressbalance','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','isthermal','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','isgroundingline','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','isgia','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','isesa','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','isdamageevolution','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','ishydrology','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','ismovingfront','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','isslr','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','isoceancoupling','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','iscoupler','format','Boolean')
+		WriteData(fid,prefix,'object',self,'fieldname','amr_frequency','format','Integer')
 
 		#process requested outputs
@@ -126,4 +172,4 @@
 			outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
 			outputs    =outputscopy
-		WriteData(fid,'data',outputs,'enum',TransientRequestedOutputsEnum(),'format','StringArray')
+		WriteData(fid,prefix,'data',outputs,'name','md.transient.requested_outputs','format','StringArray')
 	# }}}
Index: /issm/trunk-jpl/src/py3/classes/verbose.py
===================================================================
--- /issm/trunk-jpl/src/py3/classes/verbose.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/classes/verbose.py	(revision 23670)
@@ -1,5 +1,4 @@
 from pairoptions import pairoptions
 import MatlabFuncs as m
-from EnumDefinitions import *
 from WriteData import WriteData
 
@@ -29,5 +28,5 @@
 	"""
 
-	def __init__(self,*args,**kwargs):    # {{{
+	def __init__(self,*args):    # {{{
 		#BEGINFIELDS
 		self.mprocessor  = False
@@ -42,5 +41,5 @@
 		#ENDFIELDS
 
-		if not kwargs and not args:
+		if not len(args):
 			#Don't do anything
 			self.solution=True;
@@ -64,9 +63,9 @@
 		else:
 			#Use options to initialize object
-			self=pairoptions(**kwargs).AssignObjectFields(self)
+			self=pairoptions(*args).AssignObjectFields(self)
 
 			#Cast to logicals
 			listproperties=vars(self)
-			for fieldname,fieldvalue in list(listproperties.items()):
+			for fieldname,fieldvalue in listproperties.items():
 				if isinstance(fieldvalue,bool) or isinstance(fieldvalue,(int,float)):
 					setattr(self,fieldname,bool(fieldvalue))
@@ -134,5 +133,5 @@
 		return md
 	# }}}
-	def marshall(self,md,fid):    # {{{
-		WriteData(fid,'data',self.VerboseToBinary(),'enum',VerboseEnum(),'format','Integer')
+	def marshall(self,prefix,md,fid):    # {{{
+		WriteData(fid,prefix,'data',self.VerboseToBinary(),'name','md.verbose','format','Integer')
 	# }}}
Index: /issm/trunk-jpl/src/py3/consistency/checkfield.py
===================================================================
--- /issm/trunk-jpl/src/py3/consistency/checkfield.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/consistency/checkfield.py	(revision 23670)
@@ -1,14 +1,14 @@
-import numpy
+import numpy as np
 import os
 from pairoptions import pairoptions
 import MatlabFuncs as m
 
-def checkfield(md,**kwargs):
+def checkfield(md,*args):
 	"""
 	CHECKFIELD - check field consistency
 
 	   Used to check model consistency.,
-	   Requires: 
-	   'field' or 'fieldname' option. If 'fieldname' is provided, it will retrieve it from the model md. (md.(fieldname)) 
+	   Requires:
+	   'field' or 'fieldname' option. If 'fieldname' is provided, it will retrieve it from the model md. (md.(fieldname))
              If 'field' is provided, it will assume the argument following 'field' is a numeric array.
 
@@ -33,5 +33,5 @@
 
 	#get options
-	options=pairoptions(**kwargs)
+	options=pairoptions(*args)
 
 	#get field from model
@@ -40,9 +40,9 @@
 		fieldname=options.getfieldvalue('fieldname','no fieldname')
 	else:
-		fieldname=options.getfieldvalue('fieldname') 
-		exec("field=md.%s" % fieldname)
+		fieldname=options.getfieldvalue('fieldname')
+		exec("field=md.{}".format(fieldname))
 
 	if isinstance(field,(bool,int,float)):
-		field=numpy.array([field])
+		field=np.array([field])
 
 	#check empty
@@ -55,28 +55,34 @@
 	if options.exist('size'):
 		fieldsize=options.getfieldvalue('size')
-		if   len(fieldsize) == 1:
-			if   numpy.isnan(fieldsize[0]):
+		if len(fieldsize) == 1:
+			if np.isnan(fieldsize[0]):
 				pass
-			elif not numpy.size(field,0)==fieldsize[0]:
-				md = md.checkmessage(options.getfieldvalue('message',\
-					"field '%s' size should be %d" % (fieldname,fieldsize[0])))
+			elif np.ndim(field)==1:
+				if not np.size(field)==fieldsize[0]:
+					md = md.checkmessage(options.getfieldvalue('message',"field {} size should be {}".format(fieldname,fieldsize[0])))
+			else:
+				try:
+					exec("md.{}=np.squeeze(field)".format(fieldname))
+					print(('{} had been squeezed if it was a matrix with only one column'.format(fieldname)))
+				except IndexError:
+					md = md.checkmessage(options.getfieldvalue('message',"field {} should have {} dimension".format(fieldname,len(fieldsize))))
 		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])))
-	
+			if   np.isnan(fieldsize[0]):
+				if not np.size(field,1)==fieldsize[1]:
+					md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have %d columns" % (fieldname,fieldsize[1])))
+			elif np.isnan(fieldsize[1]):
+				if not np.size(field,0)==fieldsize[0]:
+					md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have %d lines" % (fieldname,fieldsize[0])))
+			elif fieldsize[1]==1:
+				if (not np.size(field,0)==fieldsize[0]):
+					md = md.checkmessage(options.getfieldvalue('message',"field '%s' size should be %d x %d" % (fieldname,fieldsize[0],fieldsize[1])))
+			else:
+				if (not np.size(field,0)==fieldsize[0]) or (not np.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 numpy.size(field) not in fieldnumel:
+		if (type(fieldnumel) == int and np.size(field) != fieldnumel) or (type(fieldnumel) == list and np.size(field) not in fieldnumel):
 			if   len(fieldnumel)==1:
 				md = md.checkmessage(options.getfieldvalue('message',\
@@ -91,13 +97,15 @@
 	#check NaN
 	if options.getfieldvalue('NaN',0):
-		if numpy.any(numpy.isnan(field)):
+		if np.any(np.isnan(field)):
 			md = md.checkmessage(options.getfieldvalue('message',\
 				"NaN values found in field '%s'" % fieldname))
+
 
 	#check Inf
 	if options.getfieldvalue('Inf',0):
-		if numpy.any(numpy.isinf(field)):
+		if np.any(np.isinf(field)):
 			md = md.checkmessage(options.getfieldvalue('message',\
 				"Inf values found in field '%s'" % fieldname))
+
 
 	#check cell
@@ -123,25 +131,75 @@
 	#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)))
+		lowerbound = options.getfieldvalue('>=')
+		if np.size(lowerbound)>1: #checking elementwise
+			if any(field<upperbound):
+				md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
+		else:
+			minval=np.nanmin(field)
+			if options.getfieldvalue('timeseries',0):
+				minval=np.nanmin(field[:-1])
+			elif options.getfieldvalue('singletimeseries',0):
+				if np.size(field)==1: #some singletimeseries are just one value
+					minval=field
+				else:
+					minval=np.nanmin(field[0])
+
+			if minval<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)))
+		if np.size(lowerbound)>1: #checking elementwise
+			if any(field<=upperbound):
+				md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
+		else:
+			minval=np.nanmin(field)
+			if options.getfieldvalue('timeseries',0) :
+				minval=np.nanmin(field[:-1])
+			elif options.getfieldvalue('singletimeseries',0):
+				if np.size(field)==1: #some singletimeseries are just one value
+					minval=field
+				else:
+					minval=np.nanmin(field[0])
+
+			if minval<=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 np.size(upperbound)>1: #checking elementwise
+			if any(field>upperbound):
+				md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
+		else:
+			maxval=np.nanmax(field)
+			if options.getfieldvalue('timeseries',0):
+				maxval=np.nanmax(field[:-1])
+			elif  options.getfieldvalue('singletimeseries',0):
+				if np.size(field)==1: #some singletimeseries are just one value
+					maxval=field
+				else:
+					maxval=np.nanmax(field[0])
+			if maxval>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)))
+		if np.size(upperbound)>1: #checking elementwise
+			if any(field>=upperbound):
+				md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
+
+		else:
+			maxval=np.nanmax(field)
+			if options.getfieldvalue('timeseries',0):
+				maxval=np.nanmax(field[:-1])
+			elif options.getfieldvalue('singletimeseries',0):
+				if np.size(field)==1: #some singletimeseries are just one value
+					maxval=field.copy()
+				else:
+					maxval=np.nanmax(field[0])
+
+				if maxval>=upperbound:
+					md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
 
 	#check file
@@ -158,13 +216,13 @@
 	#Check forcings (size and times)
 	if options.getfieldvalue('timeseries',0):
-		if   numpy.size(field,0)==md.mesh.numberofvertices:
-			if numpy.ndim(field)>1 and not numpy.size(field,1)==1:
+		if np.size(field,0)==md.mesh.numberofvertices or np.size(field,0)==md.mesh.numberofelements:
+			if np.ndim(field)>1 and not np.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 or numpy.size(field,0)==2:
-			if not all(field[-1,:]==numpy.sort(field[-1,:])):
+		elif np.size(field,0)==md.mesh.numberofvertices+1 or np.size(field,0)==md.mesh.numberofelements+1:
+			if np.ndim(field) > 1 and not all(field[-1,:]==np.sort(field[-1,:])):
 				md = md.checkmessage(options.getfieldvalue('message',\
 					"field '%s' columns should be sorted chronologically" % fieldname))
-			if any(field[-1,0:-1]==field[-1,1:]):
+			if np.ndim(field) > 1 and any(field[-1,0:-1]==field[-1,1:]):
 				md = md.checkmessage(options.getfieldvalue('message',\
 					"field '%s' columns must not contain duplicate timesteps" % fieldname))
@@ -175,6 +233,6 @@
 	#Check single value forcings (size and times)
 	if options.getfieldvalue('singletimeseries',0):
-		if numpy.size(field,0)==2:
-			if not all(field[-1,:]==numpy.sort(field[-1,:])):
+		if np.size(field,0)==2:
+			if not all(field[-1,:]==np.sort(field[-1,:])):
 				md = md.checkmessage(options.getfieldvalue('message',\
 						"field '%s' columns should be sorted chronologically" % fieldname))
@@ -182,8 +240,11 @@
 				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 2 lines" % fieldname))
+		elif np.size(field,0) == 1:
+			if np.ndim(field) > 1 and not np.size(field,1) == 1:
+				md = md.checkmessage(options.getfieldvalue('message',\
+				"field '%s' should be either a scalar or have 2 lines" % fieldname))
+		else:
+				md = md.checkmessage(options.getfieldvalue('message',\
+				"field '%s' should have 2 lines or be a scalar" % fieldname))
 
 	return md
-
Index: /issm/trunk-jpl/src/py3/consistency/ismodelselfconsistent.py
===================================================================
--- /issm/trunk-jpl/src/py3/consistency/ismodelselfconsistent.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/consistency/ismodelselfconsistent.py	(revision 23670)
@@ -1,5 +1,2 @@
-from EnumDefinitions import *
-from EnumToString import EnumToString
-
 def AnalysisConfiguration(solutiontype): #{{{
 	"""
@@ -10,45 +7,45 @@
 	"""
 
-	if   solutiontype == StressbalanceSolutionEnum():
-		analyses=[StressbalanceAnalysisEnum(),StressbalanceVerticalAnalysisEnum(),StressbalanceSIAAnalysisEnum(),L2ProjectionBaseAnalysisEnum()]
+	if   solutiontype == 'StressbalanceSolution':
+		analyses=['StressbalanceAnalysis','StressbalanceVerticalAnalysis','StressbalanceSIAAnalysis','L2ProjectionBaseAnalysis']
 
-	elif solutiontype == SteadystateSolutionEnum():
-		analyses=[StressbalanceAnalysisEnum(),StressbalanceVerticalAnalysisEnum(),StressbalanceSIAAnalysisEnum(),L2ProjectionBaseAnalysisEnum(),ThermalAnalysisEnum(),MeltingAnalysisEnum()]
+	elif solutiontype == 'SteadystateSolution':
+		analyses=['StressbalanceAnalysis','StressbalanceVerticalAnalysis','StressbalanceSIAAnalysis','L2ProjectionBaseAnalysis','ThermalAnalysis','MeltingAnalysis','EnthalpyAnalysis']
 
-	elif solutiontype == ThermalSolutionEnum():
-		analyses=[EnthalpyAnalysisEnum(),ThermalAnalysisEnum(),MeltingAnalysisEnum()]
+	elif solutiontype == 'ThermalSolution':
+		analyses=['EnthalpyAnalysis','ThermalAnalysis','MeltingAnalysis']
 
-	elif solutiontype == MasstransportSolutionEnum():
-		analyses=[MasstransportAnalysisEnum()]
+	elif solutiontype == 'MasstransportSolution':
+		analyses=['MasstransportAnalysis']
 
-	elif solutiontype == BalancethicknessSolutionEnum():
-		analyses=[BalancethicknessAnalysisEnum()]
+	elif solutiontype == 'BalancethicknessSolution':
+		analyses=['BalancethicknessAnalysis']
 
-	elif solutiontype == SurfaceSlopeSolutionEnum():
-		analyses=[L2ProjectionBaseAnalysisEnum()]
+	elif solutiontype == 'SurfaceSlopeSolution':
+		analyses=['L2ProjectionBaseAnalysis']
 
-	elif solutiontype == BalancevelocitySolutionEnum():
-		analyses=[BalancevelocityAnalysisEnum()]
+	elif solutiontype == 'BalancevelocitySolution':
+		analyses=['BalancevelocityAnalysis']
 
-	elif solutiontype == BedSlopeSolutionEnum():
-		analyses=[L2ProjectionBaseAnalysisEnum()]
+	elif solutiontype == 'BedSlopeSolution':
+		analyses=['L2ProjectionBaseAnalysis']
 
-	elif solutiontype == GiaSolutionEnum():
-		analyses=[GiaAnalysisEnum()]
+	elif solutiontype == 'GiaSolution':
+		analyses=['GiaIvinsAnalysis']
 
-	elif solutiontype == TransientSolutionEnum():
-		analyses=[StressbalanceAnalysisEnum(),StressbalanceVerticalAnalysisEnum(),StressbalanceSIAAnalysisEnum(),L2ProjectionBaseAnalysisEnum(),ThermalAnalysisEnum(),MeltingAnalysisEnum(),EnthalpyAnalysisEnum(),MasstransportAnalysisEnum()]
+        elif solutiontype == 'LoveSolution':
+                analyses=['LoveAnalysis']
 
-	elif solutiontype == FlaimSolutionEnum():
-		analyses=[FlaimAnalysisEnum()]
+	elif solutiontype == 'TransientSolution':
+		analyses=['StressbalanceAnalysis','StressbalanceVerticalAnalysis','StressbalanceSIAAnalysis','L2ProjectionBaseAnalysis','ThermalAnalysis','MeltingAnalysis','EnthalpyAnalysis','MasstransportAnalysis']
 
-	elif solutiontype == HydrologySolutionEnum():
-		analyses=[L2ProjectionBaseAnalysisEnum(),HydrologyShreveAnalysisEnum(),HydrologyDCInefficientAnalysisEnum(),HydrologyDCEfficientAnalysisEnum()]
+	elif solutiontype == 'HydrologySolution':
+		analyses=['L2ProjectionBaseAnalysis','HydrologyShreveAnalysis','HydrologyDCInefficientAnalysis','HydrologyDCEfficientAnalysis']
 
-	elif DamageEvolutionSolutionEnum():
-		analyses=[DamageEvolutionAnalysisEnum()]
+	elif 'DamageEvolutionSolution':
+		analyses=['DamageEvolutionAnalysis']
 
 	else:
-		raise TypeError("solution type: '%s' not supported yet!" % EnumToString(solutiontype)[0])
+		raise TypeError("solution type: '%s' not supported yet!" % solutiontype)
 
 	return analyses
@@ -84,5 +81,5 @@
 
 		#Check consistency of the object
-		exec("md.%s.checkconsistency(md,solution,analyses)" % field)
+		exec("md.{}.checkconsistency(md,solution,analyses)".format(field))
 
 	#error message if mode is not consistent
Index: /issm/trunk-jpl/src/py3/contrib/bamg/YamsCall.py
===================================================================
--- /issm/trunk-jpl/src/py3/contrib/bamg/YamsCall.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/contrib/bamg/YamsCall.py	(revision 23670)
@@ -29,19 +29,19 @@
 	#Compute Hessian
 	t1=time.time()
-	print("%s" % '      computing Hessian...')
+	print(("%s" % '      computing Hessian...'))
 	hessian=ComputeHessian(md.mesh.elements,md.mesh.x,md.mesh.y,field,'node')
 	t2=time.time()
-	print("%s%d%s\n" % (' done (',t2-t1,' seconds)'))
+	print(("%s%d%s\n" % (' done (',t2-t1,' seconds)')))
 
 	#Compute metric
 	t1=time.time()
-	print("%s" % '      computing metric...')
+	print(("%s" % '      computing metric...'))
 	metric=ComputeMetric(hessian,scale,epsilon,hmin,hmax,numpy.empty(0,int))
 	t2=time.time()
-	print("%s%d%s\n" % (' done (',t2-t1,' seconds)'))
+	print(("%s%d%s\n" % (' done (',t2-t1,' seconds)')))
 
 	#write files
 	t1=time.time()
-	print("%s" % '      writing initial mesh files...')
+	print(("%s" % '      writing initial mesh files...'))
 	numpy.savetxt('carre0.met',metric)
 
@@ -80,8 +80,8 @@
 	f.close()
 	t2=time.time()
-	print("%s%d%s\n" % (' done (',t2-t1,' seconds)'))
+	print(("%s%d%s\n" % (' done (',t2-t1,' seconds)')))
 
 	#call yams
-	print("%s\n" % '      call Yams...')
+	print(("%s\n" % '      call Yams...'))
 	if   m.ispc():
 		#windows
@@ -96,5 +96,5 @@
 	#plug new mesh
 	t1=time.time()
-	print("\n%s" % '      reading final mesh files...')
+	print(("\n%s" % '      reading final mesh files...'))
 	Tria=numpy.loadtxt('carre1.tria',int)
 	Coor=numpy.loadtxt('carre1.coor',float)
@@ -107,9 +107,9 @@
 	numberofelements2=md.mesh.numberofelements
 	t2=time.time()
-	print("%s%d%s\n\n" % (' done (',t2-t1,' seconds)'))
+	print(("%s%d%s\n\n" % (' done (',t2-t1,' seconds)')))
 
 	#display number of elements
-	print("\n%s %i" % ('      inital number of elements:',numberofelements1))
-	print("\n%s %i\n\n" % ('      new    number of elements:',numberofelements2))
+	print(("\n%s %i" % ('      inital number of elements:',numberofelements1)))
+	print(("\n%s %i\n\n" % ('      new    number of elements:',numberofelements2)))
 
 	#clean up:
Index: /issm/trunk-jpl/src/py3/contrib/netCDF/export_netCDF.py
===================================================================
--- /issm/trunk-jpl/src/py3/contrib/netCDF/export_netCDF.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/contrib/netCDF/export_netCDF.py	(revision 23670)
@@ -12,5 +12,5 @@
 	if path.exists(filename):
 		print(('File {} allready exist'.format(filename)))
-		newname=input('Give a new name or "delete" to replace: ')
+		newname=eval(input('Give a new name or "delete" to replace: '))
 		if newname=='delete':
 			remove(filename)
@@ -72,5 +72,5 @@
 					for field in subfields:
 						if str(field)!='errlog' and str(field)!='outlog' and str(field)!='SolutionType':
-							print('Treating '+str(group)+'.'+str(supfield)+'.'+str(field))
+							print(('Treating '+str(group)+'.'+str(supfield)+'.'+str(field)))
 							Var=md.results.__dict__[supfield].__dict__[field]
 							DimDict=CreateVar(NCData,Var,field,NCgroup,DimDict,False)
@@ -80,5 +80,5 @@
 			
 			for field in fields:
-				print('Treating ' +str(group)+'.'+str(field))
+				print(('Treating ' +str(group)+'.'+str(field)))
 				NCgroup.__setattr__('classtype', md.__dict__[group].__class__.__name__)
 				Var=md.__dict__[group].__dict__[field]
@@ -119,5 +119,5 @@
 		charvar=stringtochar(numpy.array(var))
 		print(charvar)
-		print(charvar.shape)
+		print((charvar.shape))
 		for elt in range(0,val_dim):
 			try:
@@ -152,7 +152,7 @@
 				if time!=0:
 					timevar=md.results.__dict__[supfield].__getitem__(time).__dict__[field]
-					print('Treating results.'+str(supfield)+'.'+str(field)+' for time '+str(time))
+					print(('Treating results.'+str(supfield)+'.'+str(field)+' for time '+str(time)))
 					vartab=numpy.column_stack((vartab,timevar))
-			print(numpy.shape(vartab))
+			print((numpy.shape(vartab)))
 			try:
 				ncvar[:,:]=vartab[:,:]
@@ -190,5 +190,5 @@
 					DimDict[len(NewDim)]='Dimension'+str(index)
 					output=output+[str(DimDict[shape[dim]])]
-					print('Defining dimension ' +'Dimension'+str(index))
+					print(('Defining dimension ' +'Dimension'+str(index)))
 		elif type(shape[0])==str:#dealling with a dictionnary
 			try:
@@ -199,5 +199,5 @@
 				DimDict[len(NewDim)]='Dimension'+str(index)
 				output=[str(DimDict[numpy.shape(dict.keys(var))[0]])]+['Dimension6']
-				print('Defining dimension ' +'Dimension'+str(index))
+				print(('Defining dimension ' +'Dimension'+str(index)))
 			break
 	if istime:
@@ -215,4 +215,4 @@
 				DimDict[len(NewDim)]='Dimension'+str(index)
 				output=output+[str(DimDict[stringlength])]
-				print('Defining dimension ' +'Dimension'+str(index))
+				print(('Defining dimension ' +'Dimension'+str(index)))
 	return tuple(output), DimDict
Index: /issm/trunk-jpl/src/py3/contrib/paraview/exportVTK.py
===================================================================
--- /issm/trunk-jpl/src/py3/contrib/paraview/exportVTK.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/contrib/paraview/exportVTK.py	(revision 23670)
@@ -28,5 +28,5 @@
 	if os.path.exists(filename):
 		print(('File {} allready exist'.format(filename)))
-		newname=input('Give a new name or "delete" to replace: ')
+		newname=eval(input('Give a new name or "delete" to replace: '))
 		if newname=='delete':
 			filelist = glob.glob(filename+'/*')
Index: /issm/trunk-jpl/src/py3/coordsystems/ll2xy.py
===================================================================
--- /issm/trunk-jpl/src/py3/coordsystems/ll2xy.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/coordsystems/ll2xy.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np 
+import numpy as  np 
 
 def ll2xy(lat,lon,sgn=-1,central_meridian=0,standard_parallel=71):
Index: /issm/trunk-jpl/src/py3/coordsystems/xy2ll.py
===================================================================
--- /issm/trunk-jpl/src/py3/coordsystems/xy2ll.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/coordsystems/xy2ll.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 from math import pi
 
@@ -37,8 +37,8 @@
 		raise Exception('bad usage: type "help(xy2ll)" for details')
 
-	# if x,y passed as lists, convert to numpy arrays
-	if type(x) != "numpy.ndarray":
+	# if x,y passed as lists, convert to np.arrays
+	if type(x) != "np.ndarray":
 		x=np.array(x)
-	if type(y) != "numpy.ndarray":
+	if type(y) != "np.ndarray":
 		y=np.array(y)
 
@@ -73,5 +73,5 @@
 	res1 = np.nonzero(rho <= 0.1)[0]
 	if len(res1) > 0:
-		lat[res1] = 90. * sgn
+		lat[res1] = pi/2. * sgn
 		lon[res1] = 0.0
 	
Index: /issm/trunk-jpl/src/py3/dev/devpath.py
===================================================================
--- /issm/trunk-jpl/src/py3/dev/devpath.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/dev/devpath.py	(revision 23670)
@@ -4,13 +4,11 @@
 
 #Recover ISSM_DIR and USERNAME
-ISSM_DIR = os.getenv('ISSM_DIRPY3')
+ISSM_DIR = os.getenv('ISSM_DEV_DIR')
 USERNAME = os.getenv('USER')
 JPL_SVN  = os.getenv('JPL_SVN')
 if(ISSM_DIR==None):
 	raise NameError('"ISSM_DIR" environment variable is empty! You should define ISSM_DIR in your .cshrc or .bashrc!')
-if(JPL_SVN==None):
-	warnings.warn('"JPL_SVN" environment variable is empty! add it to your .cshrc or .bashrc if you want to do distant computing')
 
-#Go through src/m and append any directory that contains a *.py file to PATH 
+#Go through src/m and append any directory that contains a *.py file to PATH
 for root,dirs,files in os.walk(ISSM_DIR+ '/src/py3'):
 	if '.svn' in dirs:
@@ -21,5 +19,8 @@
 				if root not in sys.path:
 					sys.path.append(root)
-				
+
+#Also add the Nightly run directory
+sys.path.append(ISSM_DIR + '/test/NightlyRun')
+
 sys.path.append(ISSM_DIR + '/lib')
 sys.path.append(ISSM_DIR + '/src/wrappers/python/.libs')
@@ -29,8 +30,9 @@
 		sys.path.append(JPL_SVN + '/usr/' + USERNAME)
 	else:
-		raise NameError ('cluster settings should be in, '+ JPL_SVN +'/usr/' + USERNAME)
+		warnings.warn('cluster settings should be in, '+ JPL_SVN +'/usr/' + USERNAME)
 
 #Manual imports for commonly used functions
-#from plotmodel import plotmodel
+from runme import runme		#first because plotmodel may fail
+from plotmodel import plotmodel
 
 #c = get_ipython().config
@@ -40,3 +42,4 @@
 #c.InteractiveShellApp.exec_lines.append('print "Warning: disable autoreload in startup.py to improve performance." ')
 
-print("\n  ISSM development path correctly loaded\n\n")
+print("\n  ISSM development path correctly loaded")
+print(("Current path is {}\n\n".format(ISSM_DIR)))
Index: /issm/trunk-jpl/src/py3/dev/issmversion.py
===================================================================
--- /issm/trunk-jpl/src/py3/dev/issmversion.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/dev/issmversion.py	(revision 23670)
@@ -15,5 +15,5 @@
 print(' ')
 print('Build date: '+IssmConfig('PACKAGE_BUILD_DATE')[0])
-print('Copyright (c) 2009-2015 California Institute of Technology')
+print('Copyright (c) 2009-2018 California Institute of Technology')
 print(' ')
 print('    to get started type: issmdoc')
Index: /issm/trunk-jpl/src/py3/exp/expcoarsen.py
===================================================================
--- /issm/trunk-jpl/src/py3/exp/expcoarsen.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/exp/expcoarsen.py	(revision 23670)
@@ -1,4 +1,4 @@
 import os.path
-import numpy as np
+import numpy as  np
 from collections import OrderedDict
 from expread import expread
Index: /issm/trunk-jpl/src/py3/exp/expdisp.py
===================================================================
--- /issm/trunk-jpl/src/py3/exp/expdisp.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/exp/expdisp.py	(revision 23670)
@@ -1,27 +1,59 @@
 from expread import expread
-import numpy as np
+import numpy as  np
+from matplotlib.path import Path
+import matplotlib.patches as patches
 
-def expdisp(domainoutline,ax,linestyle='--k',linewidth=1,unitmultiplier=1.):
+def expdisp(ax,options):
     '''
     plot the contents of a domain outline file
 
-    This routine reads in a domain outline file and plots all of the x,y contours
+    This routine reads in an exp file and plots all of the x,y points/lines/patches
 
-    'ax' is a handle to the current plot axes, onto which the contours are to be drawn
+    'ax' is a handle to the current plot axes, onto which we want to plot
 
     Usage:
-        expdisp(domainoutline,ax)
+        expdisp(ax,options)
 
-    Example:
-        expdisp('domain.exp',plt.gca(),linestyle='--k',linewidth=2,unitmultiplier=1.e3)
+    List of options passable to plotmodel:
+        'expdisp'      : path (or list of paths) to the exp file to be plotted
+        'explinewidth' : linewidth
+        'explinestyle' : matplotlib linestyle string
+        'explinecolor' : matplotlib color string
+        'expfill'      : (True/False) fill a closed contour
+        'expfillcolor' : Color for a filled contour, only used if expfill is True
+        'expfillalpha' : alpha transparency for filled contour
+
+    All options should be passed as lists of length len(number of exp files passed)
     '''
 
-    domain=expread(domainoutline)
-
-    for i in range(len(domain)):
-        if domain[i]['nods']==1:
-            ax.plot(domain[i]['x']*unitmultiplier,domain[i]['y']*unitmultiplier,'o',mec='k',mfc='r',ms=10)
-        else:
-            x=domain[i]['x'].tolist() # since expread returns a string representation of the arrays
-            y=domain[i]['y'].tolist()
-            ax.plot(x*unitmultiplier,y*unitmultiplier,linestyle,linewidth=linewidth)
+    filenames=options.getfieldvalue('expdisp')
+    linewidth=options.getfieldvalue('explinewidth',[1]*len(filenames))
+    linestyle=options.getfieldvalue('explinestyle',['-']*len(filenames))
+    linecolor=options.getfieldvalue('explinecolor',['k']*len(filenames))
+    fill=options.getfieldvalue('expfill',[0]*len(filenames))
+    alpha=options.getfieldvalue('expfillalpha',[1]*len(filenames))
+    facecolor=options.getfieldvalue('expfillcolor',['r']*len(filenames))
+    unitmultiplier=options.getfieldvalue('unit',1)
+    for i in range(len(filenames)):
+	linestylei=linestyle[i]
+        linecolori=linecolor[i]
+        linewidthi=linewidth[i]
+        alphai=alpha[i]
+        facecolori=facecolor[i]
+	filenamei=filenames[i]
+        filli=fill[i]
+        domain=expread(filenamei)
+        for j in range(len(domain)):
+            if domain[j]['nods']==1:
+                ax.plot(domain[j]['x']*unitmultiplier,domain[j]['y']*unitmultiplier,'o',mec='k',mfc='r',ms=10)
+            elif filli:
+                verts=np.column_stack((domain[j]['x'],domain[j]['y']))
+                codes=[Path.MOVETO] + [Path.LINETO]*(len(domain[j]['x'])-2) + [Path.CLOSEPOLY]
+                path=Path(verts, codes)
+                patch=patches.PathPatch(path,facecolor=facecolori,edgecolor=linecolori,alpha=alphai,
+                        lw=linewidthi)
+                ax.add_patch(patch)
+            else:
+                x=domain[j]['x'].tolist() # since expread returns a string representation of the arrays
+                y=domain[j]['y'].tolist()
+                ax.plot(x*unitmultiplier,y*unitmultiplier,ls=linestylei,lw=linewidthi,c=linecolori)
Index: /issm/trunk-jpl/src/py3/exp/expread.py
===================================================================
--- /issm/trunk-jpl/src/py3/exp/expread.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/exp/expread.py	(revision 23670)
@@ -1,9 +1,11 @@
 import os.path
-import numpy
+import numpy as np
 from collections import OrderedDict
 import MatlabFuncs as m
 
 def expread(filename):
+
 	"""
+
 	EXPREAD - read a file exp and build a Structure
 
@@ -23,6 +25,6 @@
 
 	   See also EXPDOC, EXPWRITEASVERTICES
+
 	"""
-
 	#some checks
 	if not os.path.exists(filename):
@@ -31,14 +33,10 @@
 	#initialize number of profile
 	contours=[]
-
 	#open file
 	fid=open(filename,'r')
-
 	#loop over the number of profiles
 	while True:
-
 		#update number of profiles
 		contour=OrderedDict()
-
 		#Get file name
 		A=fid.readline()
@@ -50,4 +48,5 @@
 		if not (len(A) == 2 and m.strcmp(A[0],'##') and m.strncmp(A[1],'Name:',5)):
 			break
+
 		if len(A[1])>5: 
 			contour['name']=A[1][5:-1]
@@ -59,5 +58,4 @@
 		if not (len(A) == 2 and m.strcmp(A[0],'##') and m.strncmp(A[1],'Icon:',5)):
 			break
-
 		#Get Info
 		A=fid.readline().split()
@@ -72,11 +70,10 @@
 		#Get Info
 		A=fid.readline().split()
-		if not (len(A) == 5 and m.strcmp(A[0],'#') and m.strcmp(A[1],'X') and m.strcmp(A[2],'pos') \
-		                                         and m.strcmp(A[3],'Y') and m.strcmp(A[4],'pos')):
+		if not (len(A) == 5 and m.strcmp(A[0],'#') and m.strcmp(A[1],'X') and m.strcmp(A[2],'pos') 
+						and m.strcmp(A[3],'Y') and m.strcmp(A[4],'pos')):
 			break
-
 		#Get Coordinates
-		contour['x']=numpy.empty(contour['nods'])
-		contour['y']=numpy.empty(contour['nods'])
+		contour['x']=np.empty(contour['nods'])
+		contour['y']=np.empty(contour['nods'])
 		for i in range(int(contour['nods'])):
 			A=fid.readline().split()
@@ -93,8 +90,5 @@
 
 		contours.append(contour)
-
 	#close file
 	fid.close()
-
 	return contours
-
Index: /issm/trunk-jpl/src/py3/exp/expwrite.py
===================================================================
--- /issm/trunk-jpl/src/py3/exp/expwrite.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/exp/expwrite.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 
 def expwrite(contours,filename):
@@ -21,5 +21,5 @@
 	fid=open(filename,'w')
 	for x,y in zip(contours['x'],contours['y']):
-		#if numpy.size(contour['x'])!=numpy.size(contour['y']):
+		#if np.size(contour['x'])!=np.size(contour['y']):
 		if len(x)!=len(y):
 			raise RuntimeError("contours x and y coordinates must be of identical size")
@@ -36,6 +36,6 @@
 		fid.write("%s\n" % '## Icon:0')
 		fid.write("%s\n" % '# Points Count Value')
-		#fid.write("%i %f\n" % (numpy.size(contour['x']),contour['density']))
-		fid.write("%i %f\n" % (numpy.size(x),density))
+		#fid.write("%i %f\n" % (np.size(contour['x']),contour['density']))
+		fid.write("%i %f\n" % (np.size(x),density))
 		fid.write("%s\n" % '# X pos Y pos')
 		#for x,y in zip(contour['x'],contour['y']):
Index: /issm/trunk-jpl/src/py3/extrusion/DepthAverage.py
===================================================================
--- /issm/trunk-jpl/src/py3/extrusion/DepthAverage.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/extrusion/DepthAverage.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 from project2d import project2d
 
@@ -46,5 +46,5 @@
 
 	if vec2d:
-		vector_average=vector_average.reshape(-1,1)
+		vector_average=vector_average.reshape(-1,)
 
 	return vector_average
Index: /issm/trunk-jpl/src/py3/extrusion/project2d.py
===================================================================
--- /issm/trunk-jpl/src/py3/extrusion/project2d.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/extrusion/project2d.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 
 def project2d(md3d,value,layer):
@@ -45,5 +45,5 @@
 
 	if vec2d:
-		projection_value=projection_value.reshape(-1,1)
+		projection_value=projection_value.reshape(-1,)
 
 	return projection_value
Index: /issm/trunk-jpl/src/py3/extrusion/project3d.py
===================================================================
--- /issm/trunk-jpl/src/py3/extrusion/project3d.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/extrusion/project3d.py	(revision 23670)
@@ -1,6 +1,6 @@
-import numpy
+import numpy as np
 from pairoptions import pairoptions
 
-def project3d(md,**kwargs):
+def project3d(md,*args):
 	"""
 	PROJECT3D - vertically project a vector from 2d mesh
@@ -30,5 +30,5 @@
 
 	#retrieve parameters from options.
-	options      = pairoptions(**kwargs)
+	options      = pairoptions(*args)
 	vector2d     = options.getfieldvalue('vector')       #mandatory
 	vectype      = options.getfieldvalue('type')         #mandatory
@@ -37,9 +37,9 @@
 
 	vector1d=False
-	if isinstance(vector2d,numpy.ndarray) and numpy.ndim(vector2d)==1:
+	if isinstance(vector2d,np.ndarray) and np.ndim(vector2d)==1:
 		vector1d=True
-		vector2d=vector2d.reshape(-1,1)
+		vector2d=vector2d.reshape(-1,)
 
-	if isinstance(vector2d,(bool,int,float)) or numpy.size(vector2d)==1:
+	if isinstance(vector2d,(bool,int,float)) or np.size(vector2d)==1:
 		projected_vector=vector2d
 
@@ -47,38 +47,69 @@
 
 		#Initialize 3d vector
-		if vector2d.shape[0]==md.mesh.numberofvertices2d:
-			projected_vector=(paddingvalue*numpy.ones((md.mesh.numberofvertices,  numpy.size(vector2d,axis=1)))).astype(vector2d.dtype)
-		elif vector2d.shape[0]==md.mesh.numberofvertices2d+1:
-			projected_vector=(paddingvalue*numpy.ones((md.mesh.numberofvertices+1,numpy.size(vector2d,axis=1)))).astype(vector2d.dtype)
-			projected_vector[-1,:]=vector2d[-1,:]
-			vector2d=vector2d[:-1,:]
+		if np.ndim(vector2d)==1:
+			if vector2d.shape[0]==md.mesh.numberofvertices2d:
+				projected_vector=(paddingvalue*np.ones((md.mesh.numberofvertices))).astype(vector2d.dtype)
+			elif vector2d.shape[0]==md.mesh.numberofvertices2d+1:
+				projected_vector=(paddingvalue*np.ones((md.mesh.numberofvertices+1))).astype(vector2d.dtype)
+				projected_vector[-1]=vector2d[-1]
+				vector2d=vector2d[:-1]
+			else:
+				raise TypeError("vector length not supported")
+			#Fill in
+			if layer==0:
+				for i in range(md.mesh.numberoflayers):
+					projected_vector[(i*md.mesh.numberofvertices2d):((i+1)*md.mesh.numberofvertices2d)]=vector2d
+			else:
+				projected_vector[((layer-1)*md.mesh.numberofvertices2d):(layer*md.mesh.numberofvertices2d)]=vector2d
 		else:
-			raise TypeError("vector length not supported")
+			if vector2d.shape[0]==md.mesh.numberofvertices2d:
+				projected_vector=(paddingvalue*np.ones((md.mesh.numberofvertices,np.size(vector2d,axis=1)))).astype(vector2d.dtype)
+			elif vector2d.shape[0]==md.mesh.numberofvertices2d+1:
+				projected_vector=(paddingvalue*np.ones((md.mesh.numberofvertices+1,np.size(vector2d,axis=1)))).astype(vector2d.dtype)
+				projected_vector[-1,:]=vector2d[-1,:]
+				vector2d=vector2d[:-1,:]
+			else:
+				raise TypeError("vector length not supported")
+			#Fill in
+			if layer==0:
+				for i in range(md.mesh.numberoflayers):
+					projected_vector[(i*md.mesh.numberofvertices2d):((i+1)*md.mesh.numberofvertices2d),:]=vector2d
+			else:
+				projected_vector[((layer-1)*md.mesh.numberofvertices2d):(layer*md.mesh.numberofvertices2d),:]=vector2d
 
-		#Fill in
-		if layer==0:
-			for i in range(md.mesh.numberoflayers):
-				projected_vector[(i*md.mesh.numberofvertices2d):((i+1)*md.mesh.numberofvertices2d),:]=vector2d
-		else:
-			projected_vector[((layer-1)*md.mesh.numberofvertices2d):(layer*md.mesh.numberofvertices2d),:]=vector2d
 
 	elif vectype.lower()=='element':
 
 		#Initialize 3d vector
-		if vector2d.shape[0]==md.mesh.numberofelements2d:
-			projected_vector=(paddingvalue*numpy.ones((md.mesh.numberofelements,  numpy.size(vector2d,axis=1)))).astype(vector2d.dtype)
-		elif vector2d.shape[0]==md.mesh.numberofelements2d+1:
-			projected_vector=(paddingvalue*numpy.ones((md.mesh.numberofelements+1,numpy.size(vector2d,axis=1)))).astype(vector2d.dtype)
-			projected_vector[-1,:]=vector2d[-1,:]
-			vector2d=vector2d[:-1,:]
+		if np.ndim(vector2d)==1:
+			if vector2d.shape[0]==md.mesh.numberofelements2d:
+				projected_vector=(paddingvalue*np.ones((md.mesh.numberofelements))).astype(vector2d.dtype)
+			elif vector2d.shape[0]==md.mesh.numberofelements2d+1:
+				projected_vector=(paddingvalue*np.ones((md.mesh.numberofelements+1))).astype(vector2d.dtype)
+				projected_vector[-1]=vector2d[-1]
+				vector2d=vector2d[:-1]
+			else:
+				raise TypeError("vector length not supported")
+			#Fill in
+			if layer==0:
+				for i in range(md.mesh.numberoflayers-1):
+					projected_vector[(i*md.mesh.numberofelements2d):((i+1)*md.mesh.numberofelements2d)]=vector2d
+			else:
+				projected_vector[((layer-1)*md.mesh.numberofelements2d):(layer*md.mesh.numberofelements2d)]=vector2d
 		else:
-			raise TypeError("vector length not supported")
-
-		#Fill in
-		if layer==0:
-			for i in range(md.mesh.numberoflayers-1):
-				projected_vector[(i*md.mesh.numberofelements2d):((i+1)*md.mesh.numberofelements2d),:]=vector2d
-		else:
-			projected_vector[((layer-1)*md.mesh.numberofelements2d):(layer*md.mesh.numberofelements2d),:]=vector2d
+			if vector2d.shape[0]==md.mesh.numberofelements2d:
+				projected_vector=(paddingvalue*np.ones((md.mesh.numberofelements,  np.size(vector2d,axis=1)))).astype(vector2d.dtype)
+			elif vector2d.shape[0]==md.mesh.numberofelements2d+1:
+				projected_vector=(paddingvalue*np.ones((md.mesh.numberofelements+1,np.size(vector2d,axis=1)))).astype(vector2d.dtype)
+				projected_vector[-1,:]=vector2d[-1,:]
+				vector2d=vector2d[:-1,:]
+			else:
+				raise TypeError("vector length not supported")
+			#Fill in
+			if layer==0:
+				for i in range(md.mesh.numberoflayers-1):
+					projected_vector[(i*md.mesh.numberofelements2d):((i+1)*md.mesh.numberofelements2d),:]=vector2d
+			else:
+				projected_vector[((layer-1)*md.mesh.numberofelements2d):(layer*md.mesh.numberofelements2d),:]=vector2d
 
 	else:
Index: /issm/trunk-jpl/src/py3/geometry/FlagElements.py
===================================================================
--- /issm/trunk-jpl/src/py3/geometry/FlagElements.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/geometry/FlagElements.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 import os
 #from basinzoom import basinzoon
@@ -24,8 +24,8 @@
 	if   isinstance(region,str):
 		if   not region:
-			flag=numpy.zeros(md.mesh.numberofelements,bool)
+			flag=np.zeros(md.mesh.numberofelements,bool)
 			invert=0
 		elif m.strcmpi(region,'all'):
-			flag=numpy.ones(md.mesh.numberofelements,bool)
+			flag=np.ones(md.mesh.numberofelements,bool)
 			invert=0
 		else:
@@ -44,18 +44,18 @@
 				xlim,ylim=basinzoom('basin',region)
 				flag_nodes=p.logical_and_n(md.mesh.x<xlim[1],md.mesh.x>xlim[0],md.mesh.y<ylim[1],md.mesh.y>ylim[0])
-				flag=numpy.prod(flag_nodes[md.mesh.elements],axis=1).astype(bool)
+				flag=np.prod(flag_nodes[md.mesh.elements],axis=1).astype(bool)
 			else:
 				#ok, flag elements
-				[flag,dum]=ContourToMesh(md.mesh.elements[:,0:3].copy(),md.mesh.x,md.mesh.y,region,'element',1)
+				flag=ContourToMesh(md.mesh.elements[:,0:3].copy(),md.mesh.x,md.mesh.y,region,'element',1)
 				flag=flag.astype(bool)
 
 		if invert:
-			flag=numpy.logical_not(flag)
+			flag=np.logical_not(flag)
 
-	elif isinstance(region,numpy.ndarray) or isinstance(region,bool):
-		if numpy.size(region,0)==md.mesh.numberofelements:
+	elif isinstance(region,np.ndarray) or isinstance(region,bool):
+		if np.size(region,0)==md.mesh.numberofelements:
 			flag=region
-		elif numpy.size(region,0)==md.mesh.numberofvertices:
-			flag=(numpy.sum(region[md.mesh.elements-1]>0,axis=1)==numpy.size(md.mesh.elements,1))
+		elif np.size(region,0)==md.mesh.numberofvertices:
+			flag=(np.sum(region[md.mesh.elements-1]>0,axis=1)==np.size(md.mesh.elements,1))
 		else:
 			raise TypeError("Flaglist for region must be of same size as number of elements in model.")
Index: /issm/trunk-jpl/src/py3/geometry/GetAreas.py
===================================================================
--- /issm/trunk-jpl/src/py3/geometry/GetAreas.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/geometry/GetAreas.py	(revision 23670)
@@ -1,5 +1,5 @@
-import numpy
+import numpy as np
 
-def GetAreas(index,x,y,z=numpy.array([])):
+def GetAreas(index,x,y,z=np.array([])):
 	"""
 	GETAREAS - compute areas or volumes of elements
@@ -18,19 +18,19 @@
 
 	#get number of elements and number of nodes
-	nels=numpy.size(index,axis=0)
-	nods=numpy.size(x)
+	nels=np.size(index,axis=0)
+	nods=np.size(x)
 
 	#some checks
-	if numpy.size(y)!=nods or (z and numpy.size(z)!=nods):
+	if np.size(y)!=nods or (z and np.size(z)!=nods):
 		raise TypeError("GetAreas error message: x,y and z do not have the same length.")
-	if numpy.max(index)>nods:
+	if np.max(index)>nods:
 		raise TypeError("GetAreas error message: index should not have values above %d." % nods)
-	if (not z and numpy.size(index,axis=1)!=3):
+	if (not z and np.size(index,axis=1)!=3):
 		raise TypeError("GetAreas error message: index should have 3 columns for 2d meshes.")
-	if (z and numpy.size(index,axis=1)!=6):
+	if (z and np.size(index,axis=1)!=6):
 		raise TypeError("GetAreas error message: index should have 6 columns for 3d meshes.")
 
 	#initialization
-	areas=numpy.zeros(nels)
+	areas=np.zeros(nels)
 	x1=x[index[:,0]-1]
 	x2=x[index[:,1]-1]
@@ -46,5 +46,5 @@
 	else:
 		#V=area(triangle)*1/3(z1+z2+z3)
-		thickness=numpy.mean(z[index[:,3:6]-1])-numpy.mean(z[index[:,0:3]-1])
+		thickness=np.mean(z[index[:,3:6]-1])-np.mean(z[index[:,0:3]-1])
 		areas=(0.5*((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1)))*thickness
 
Index: /issm/trunk-jpl/src/py3/geometry/SegIntersect.py
===================================================================
--- /issm/trunk-jpl/src/py3/geometry/SegIntersect.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/geometry/SegIntersect.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 
 def SegIntersect(seg1,seg2):
@@ -24,14 +24,14 @@
 	yD=seg2[1,1]
 
-	O2A=numpy.array([xA,yA])-numpy.array([xD/2.+xC/2.,yD/2.+yC/2.])
-	O2B=numpy.array([xB,yB])-numpy.array([xD/2.+xC/2.,yD/2.+yC/2.])
-	O1C=numpy.array([xC,yC])-numpy.array([xA/2.+xB/2.,yB/2.+yA/2.])
-	O1D=numpy.array([xD,yD])-numpy.array([xA/2.+xB/2.,yB/2.+yA/2.])
+	O2A=np.array([xA,yA])-np.array([xD/2.+xC/2.,yD/2.+yC/2.])
+	O2B=np.array([xB,yB])-np.array([xD/2.+xC/2.,yD/2.+yC/2.])
+	O1C=np.array([xC,yC])-np.array([xA/2.+xB/2.,yB/2.+yA/2.])
+	O1D=np.array([xD,yD])-np.array([xA/2.+xB/2.,yB/2.+yA/2.])
 
-	n1=numpy.array([yA-yB,xB-xA])    #normal vector to segA
-	n2=numpy.array([yC-yD,xD-xC])    #normal vector to segB
+	n1=np.array([yA-yB,xB-xA])    #normal vector to segA
+	n2=np.array([yC-yD,xD-xC])    #normal vector to segB
 
-	test1=numpy.dot(n2,O2A)
-	test2=numpy.dot(n2,O2B)
+	test1=np.dot(n2,O2A)
+	test2=np.dot(n2,O2B)
 
 	if test1*test2>0:
@@ -39,6 +39,6 @@
 		return bval
 
-	test3=numpy.dot(n1,O1C)
-	test4=numpy.dot(n1,O1D)
+	test3=np.dot(n1,O1C)
+	test4=np.dot(n1,O1D)
 
 	if test3*test4>0:
@@ -47,12 +47,12 @@
 
 	#if colinear
-	if test1*test2==0 and test3*test4==0 and numpy.linalg.det(numpy.hstack((n1.reshape((-1,1)),n2.reshape(-1,1))))==0:
+	if test1*test2==0 and test3*test4==0 and np.linalg.det(np.hstack((n1.reshape((-1,)),n2.reshape(-1,))))==0:
 
 		#projection on the axis O1O2
-		O2O1=numpy.array([xA/2.+xB/2.,yB/2.+yA/2.])-numpy.array([xD/2.+xC/2.,yD/2.+yC/2.])
-		O1A=numpy.dot(O2O1,(O2A-O2O1))
-		O1B=numpy.dot(O2O1,(O2B-O2O1))
-		O1C=numpy.dot(O2O1,O1C)
-		O1D=numpy.dot(O2O1,O1D)
+		O2O1=np.array([xA/2.+xB/2.,yB/2.+yA/2.])-np.array([xD/2.+xC/2.,yD/2.+yC/2.])
+		O1A=np.dot(O2O1,(O2A-O2O1))
+		O1B=np.dot(O2O1,(O2B-O2O1))
+		O1C=np.dot(O2O1,O1C)
+		O1D=np.dot(O2O1,O1D)
 
 		#test if one point is included in the other segment (->bval=1)
Index: /issm/trunk-jpl/src/py3/geometry/slope.py
===================================================================
--- /issm/trunk-jpl/src/py3/geometry/slope.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/geometry/slope.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 from GetNodalFunctionsCoeff import  GetNodalFunctionsCoeff
 
@@ -34,6 +34,6 @@
 
 	summation=np.array([[1],[1],[1]])
-	sx=np.dot(surf[index-1]*alpha,summation).reshape(-1,)
-	sy=np.dot(surf[index-1]*beta,summation).reshape(-1,)
+	sx=np.dot(surf[index-1,0]*alpha,summation).reshape(-1,)
+	sy=np.dot(surf[index-1,0]*beta,summation).reshape(-1,)
 
 	s=np.sqrt(sx**2+sy**2)
Index: /issm/trunk-jpl/src/py3/interp/SectionValues.py
===================================================================
--- /issm/trunk-jpl/src/py3/interp/SectionValues.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/interp/SectionValues.py	(revision 23670)
@@ -1,5 +1,5 @@
 import os
 from expread import expread
-import numpy as np
+import numpy as  np
 from project2d import project2d
 #from InterpFromMesh2d import InterpFromMesh2d
@@ -127,5 +127,5 @@
 
 		#Interpolation of data on specified points
-		data_interp=InterpFromMeshToMesh3d(md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.z,data,X3,Y3,Z3,np.nan)
+		data_interp=InterpFromMeshToMesh3d(md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.z,data,X3,Y3,Z3,np.nan)[0]
 	
 		#build outputs
Index: /issm/trunk-jpl/src/py3/interp/averaging.py
===================================================================
--- /issm/trunk-jpl/src/py3/interp/averaging.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/interp/averaging.py	(revision 23670)
@@ -1,6 +1,9 @@
-import numpy as np
+import numpy as  np
 from GetAreas import GetAreas
-from scipy.sparse import csc_matrix
 import MatlabFuncs as m
+try:
+	from scipy.sparse import csc_matrix
+except ImportError:
+	print("could not import scipy, no averaging capabilities enabled")
 
 def averaging(md,data,iterations,layer=0):
Index: /issm/trunk-jpl/src/py3/interp/holefiller.py
===================================================================
--- /issm/trunk-jpl/src/py3/interp/holefiller.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/interp/holefiller.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 from scipy.spatial import cKDTree
 
Index: /issm/trunk-jpl/src/py3/interp/interp.py
===================================================================
--- /issm/trunk-jpl/src/py3/interp/interp.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/interp/interp.py	(revision 23670)
@@ -1,4 +1,4 @@
 # module for inperpolating/smoothing data
-import numpy as np
+import numpy as  np
 from scipy.interpolate import CloughTocher2DInterpolator, Rbf
 from scipy.spatial import cKDTree
Index: /issm/trunk-jpl/src/py3/inversions/marshallcostfunctions.py
===================================================================
--- /issm/trunk-jpl/src/py3/inversions/marshallcostfunctions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/inversions/marshallcostfunctions.py	(revision 23670)
@@ -1,33 +1,45 @@
 import copy
-from EnumDefinitions import *
 
 def marshallcostfunctions(cost_functions):
 
-	#copy list first
-	data=copy.deepcopy(cost_functions)
+	cfDict={101:'SurfaceAbsVelMisfit',
+					102:'SurfaceRelVelMisfit',
+					103:'SurfaceLogVelMisfit',
+					104:'SurfaceLogVxVyMisfit',
+					105:'SurfaceAverageVelMisfit',
+					201:'ThicknessAbsMisfit',
+					501:'DragCoefficientAbsGradient',
+					502:'RheologyBbarAbsGradient',
+					503:'ThicknessAbsGradient',
+					504:'ThicknessAlongGradient',
+					505:'ThicknessAcrossGradient',}
 
-	#convert to  Enums
-	pos=[i for i,x in enumerate(cost_functions) if x==101];
-	for i in pos: data[i]=SurfaceAbsVelMisfitEnum()        
-	pos=[i for i,x in enumerate(cost_functions) if x==102];
-	for i in pos: data[i]=SurfaceRelVelMisfitEnum()        
-	pos=[i for i,x in enumerate(cost_functions) if x==103];
-	for i in pos: data[i]=SurfaceLogVelMisfitEnum()        
-	pos=[i for i,x in enumerate(cost_functions) if x==104];
-	for i in pos: data[i]=SurfaceLogVxVyMisfitEnum()       
-	pos=[i for i,x in enumerate(cost_functions) if x==105];
-	for i in pos: data[i]=SurfaceAverageVelMisfitEnum()    
-	pos=[i for i,x in enumerate(cost_functions) if x==201];
-	for i in pos: data[i]=ThicknessAbsMisfitEnum()         
-	pos=[i for i,x in enumerate(cost_functions) if x==501];
-	for i in pos: data[i]=DragCoefficientAbsGradientEnum() 
-	pos=[i for i,x in enumerate(cost_functions) if x==502];
-	for i in pos: data[i]=RheologyBbarAbsGradientEnum()    
-	pos=[i for i,x in enumerate(cost_functions) if x==503];
-	for i in pos: data[i]=ThicknessAbsGradientEnum()       
-	pos=[i for i,x in enumerate(cost_functions) if x==504];
-	for i in pos: data[i]=ThicknessAlongGradientEnum()     
-	pos=[i for i,x in enumerate(cost_functions) if x==505];
-	for i in pos: data[i]=ThicknessAcrossGradientEnum()    
+	data=[cfDict[cf] for cf in cost_functions]
+	# #copy list first
+	# data=copy.deepcopy(cost_functions)
+
+	# #convert to strings 
+	# pos=[i for i,x in enumerate(cost_functions) if x==101];
+	# for i in pos: data[i]='SurfaceAbsVelMisfit'        
+	# pos=[i for i,x in enumerate(cost_functions) if x==102];
+	# for i in pos: data[i]='SurfaceRelVelMisfit'        
+	# pos=[i for i,x in enumerate(cost_functions) if x==103];
+	# for i in pos: data[i]='SurfaceLogVelMisfit'        
+	# pos=[i for i,x in enumerate(cost_functions) if x==104];
+	# for i in pos: data[i]='SurfaceLogVxVyMisfit'       
+	# pos=[i for i,x in enumerate(cost_functions) if x==105];
+	# for i in pos: data[i]='SurfaceAverageVelMisfit'    
+	# pos=[i for i,x in enumerate(cost_functions) if x==201];
+	# for i in pos: data[i]='ThicknessAbsMisfit'         
+	# pos=[i for i,x in enumerate(cost_functions) if x==501];
+	# for i in pos: data[i]='DragCoefficientAbsGradient' 
+	# pos=[i for i,x in enumerate(cost_functions) if x==502];
+	# for i in pos: data[i]='RheologyBbarAbsGradient'    
+	# pos=[i for i,x in enumerate(cost_functions) if x==503];
+	# for i in pos: data[i]='ThicknessAbsGradient'       
+	# pos=[i for i,x in enumerate(cost_functions) if x==504];
+	# for i in pos: data[i]='ThicknessAlongGradient'     
+	# pos=[i for i,x in enumerate(cost_functions) if x==505];
+	# for i in pos: data[i]='ThicknessAcrossGradient'    
 
 	return data
Index: /issm/trunk-jpl/src/py3/inversions/parametercontroldrag.py
===================================================================
--- /issm/trunk-jpl/src/py3/inversions/parametercontroldrag.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/inversions/parametercontroldrag.py	(revision 23670)
@@ -20,5 +20,5 @@
 
 	#process options
-	options=pairoptions(**kwargs)
+	options=pairoptions(*args)
 
 	#control type
Index: /issm/trunk-jpl/src/py3/io/loadmodel.py
===================================================================
--- /issm/trunk-jpl/src/py3/io/loadmodel.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/io/loadmodel.py	(revision 23670)
@@ -1,4 +1,5 @@
 from loadvars import loadvars
 from dbm import whichdb
+from netCDF4 import Dataset
 
 def loadmodel(path):
@@ -17,19 +18,17 @@
 		pass
 	else:
-		raise IOError("loadmodel error message: file '%s' does not exist" % path)
+		try:
+			NCFile=Dataset(path,mode='r')
+			NCFile.close()
+			pass
+		except RuntimeError:
+			raise IOError("loadmodel error message: file '%s' does not exist" % path)
+		#	try:
+	#recover model on file and name it md
+	struc=loadvars(path)
+	name=[key for key in struc.keys()]
+	if len(name)>1:
+		raise IOError("loadmodel error message: file '%s' contains several variables. Only one model should be present." % path)
 
-	try:
-		#recover model on file and name it md
-		struc=loadvars(path)
-
-		name=[key for key in struc.keys()]
-		if len(name)>1:
-			raise IOError("loadmodel error message: file '%s' contains several variables. Only one model should be present." % path)
-
-		md=struc[name[0]]
-		return md
-
-	except Exception as me:
-		print(me)
-		raise IOError("could not load model '%s'" % path)
-
+	md=struc[name[0]]
+	return md
Index: /issm/trunk-jpl/src/py3/io/loadvars.py
===================================================================
--- /issm/trunk-jpl/src/py3/io/loadvars.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/io/loadvars.py	(revision 23670)
@@ -1,5 +1,12 @@
 import shelve
 import os.path
+import numpy as  np
+from netCDF4 import Dataset
+from netCDF4 import chartostring
+from re import findall
+from os import path
+from collections import OrderedDict
 from dbm import whichdb
+from model import *
 
 def loadvars(*args):
@@ -51,25 +58,156 @@
 	if whichdb(filename):
 		print("Loading variables from file '%s'." % filename)
-	else:
-		raise IOError("File '%s' not found." % filename)
-
-	my_shelf = shelve.open(filename,'r') # 'r' for read-only
-
-	if nvdict:
-		for name in nvdict.keys():
-			try:
+
+		my_shelf = shelve.open(filename,'r') # 'r' for read-only
+		if nvdict:
+			for name in nvdict.keys():
+				try:
+					nvdict[name] = my_shelf[name]
+					print("Variable '%s' loaded." % name)
+				except KeyError:
+					value = None
+					print("Variable '%s' not found." % name)
+
+		else:
+			for name in my_shelf.keys():
 				nvdict[name] = my_shelf[name]
 				print("Variable '%s' loaded." % name)
-			except KeyError:
-				value = None
-				print("Variable '%s' not found." % name)
+
+		my_shelf.close()
 
 	else:
-		for name in my_shelf.keys():
-			nvdict[name] = my_shelf[name]
-			print("Variable '%s' loaded." % name)
-
-	my_shelf.close()
-
+		try:
+			NCFile=Dataset(filename,mode='r')
+			NCFile.close()
+		except RuntimeError:
+			raise IOError("File '%s' not found." % filename)
+
+		classtype,classtree=netCDFread(filename)
+		nvdict['md']=model()
+		NCFile=Dataset(filename,mode='r')
+		for mod in dict.keys(classtype):
+			if np.size(classtree[mod])>1:
+				curclass=NCFile.groups[classtree[mod][0]].groups[classtree[mod][1]]
+				if classtype[mod][0]=='list':
+					keylist=[key for key in curclass.groups]
+					try:
+						steplist=[int(key) for key in curclass.groups]
+					except ValueError:
+						steplist=[int(findall(r'\d+',key)[0]) for key in keylist]
+					indexlist=[index*(len(curclass.groups)-1)/max(1,max(steplist)) for index in steplist]
+					listtype=curclass.groups[keylist[0]].classtype
+					if listtype=='dict':
+						nvdict['md'].__dict__[classtree[mod][0]].__dict__[classtree[mod][1]] = [OrderedDict() for i in range(max(1,len(curclass.groups)))]
+					else:
+						nvdict['md'].__dict__[classtree[mod][0]].__dict__[classtree[mod][1]] = [getattr(__import__(listtype),listtype)() for i in range(max(1,len(curclass.groups)))]
+					Tree=nvdict['md'].__dict__[classtree[mod][0]].__dict__[classtree[mod][1]][:]
+				else:
+					nvdict['md'].__dict__[classtree[mod][0]].__dict__[classtree[mod][1]] = getattr(classtype[mod][1],classtype[mod][0])()
+					Tree=nvdict['md'].__dict__[classtree[mod][0]].__dict__[classtree[mod][1]]
+			else:
+				curclass=NCFile.groups[classtree[mod][0]]
+				nvdict['md'].__dict__[mod] = getattr(classtype[mod][1],classtype[mod][0])()
+				Tree=nvdict['md'].__dict__[classtree[mod][0]]
+			#treating groups that are lists
+			for i in range(0,max(1,len(curclass.groups))):
+				if len(curclass.groups)>0:
+					listclass=curclass.groups[keylist[i]]
+				else:
+					listclass=curclass
+				for var in listclass.variables:
+					if var not in ['errlog','outlog']:
+						varval=listclass.variables[str(var)]
+						vardim=varval.ndim
+						try:
+							val_type=str(varval.dtype)
+						except AttributeError:
+							val_type=type(varval)
+						if vardim==0:
+							if type(Tree)==list:
+								t=indexlist[i]
+								if listtype=='dict':
+									Tree[t][str(var)]=varval[0]
+								else:
+									Tree[t].__dict__[str(var)]=varval[0]
+							else:
+								if str(varval[0])=='':
+									Tree.__dict__[str(var)]=[]
+								elif varval[0]=='True':
+									Tree.__dict__[str(var)]=True
+								elif varval[0]=='False':
+									Tree.__dict__[str(var)]=False
+								else:
+									Tree.__dict__[str(var)]=varval[0]
+
+						elif vardim==1:
+							if varval.dtype==str:
+								if varval.shape[0]==1:
+									Tree.__dict__[str(var)]=[str(varval[0]),]
+								elif 'True' in varval[:] or 'False' in varval[:]:
+									Tree.__dict__[str(var)]=np.asarray([V=='True' for V in varval[:]],dtype=bool)
+								else:
+									Tree.__dict__[str(var)]=[str(vallue) for vallue in varval[:]]
+							else:
+								if type(Tree)==list:
+									t=indexlist[i]
+									if listtype=='dict':
+										Tree[t][str(var)]=varval[:]
+									else:
+										Tree[t].__dict__[str(var)]=varval[:]
+								else:
+									try:
+										#some thing specifically require a list
+										mdtype=type(Tree.__dict__[str(var)])
+									except KeyError:
+										mdtype=float
+									if mdtype==list:
+										Tree.__dict__[str(var)]=[mdval for mdval in varval[:]]
+									else:
+										Tree.__dict__[str(var)]=varval[:]
+						elif vardim==2:
+							#dealling with dict
+							if varval.dtype==str: #that is for toolkits wich needs to be ordered
+								if any(varval[:,0]=='toolkit'):								#toolkit definition have to be first
+									Tree.__dict__[str(var)]=OrderedDict([('toolkit', str(varval[np.where(varval[:,0]=='toolkit')[0][0],1]))])
+
+								strings1=[str(arg[0]) for arg in varval if arg[0]!='toolkits']
+								strings2=[str(arg[1]) for arg in varval if arg[0]!='toolkits']
+								Tree.__dict__[str(var)].update(list(zip(strings1, strings2)))
+							else:
+								if type(Tree)==list:
+									#t=int(keylist[i][-1])-1
+									t=indexlist[i]
+									if listtype=='dict':
+										Tree[t][str(var)]=varval[:,:]
+									else:
+										Tree[t].__dict__[str(var)]=varval[:,:]
+								else:
+									Tree.__dict__[str(var)]=varval[:,:]
+						elif vardim==3:
+							if type(Tree)==list:
+								t=indexlist[i]
+								if listtype=='dict':
+									Tree[t][str(var)]=varval[:,:,:]
+								else:
+									Tree[t].__dict__[str(var)]=varval[:,:,:]
+							else:
+								Tree.__dict__[str(var)]=varval[:,:,:]
+						else:
+							print('table dimension greater than 3 not implemented yet')
+				for attr in listclass.ncattrs():
+					if  attr!='classtype': #classtype is for treatment, don't get it back
+						if type(Tree)==list:
+							t=indexlist[i]
+							if listtype=='dict':
+								Tree[t][str(attr).swapcase()]=str(listclass.getncattr(attr))
+							else:
+								Tree[t].__dict__[str(attr).swapcase()]=str(listclass.getncattr(attr))
+						else:
+							Tree.__dict__[str(attr).swapcase()]=str(listclass.getncattr(attr))
+							if listclass.getncattr(attr)=='True':
+								Tree.__dict__[str(attr).swapcase()]=True
+							elif listclass.getncattr(attr)=='False':
+								Tree.__dict__[str(attr).swapcase()]=False
+		NCFile.close()
 	if   len(args) >= 2 and isinstance(args[1],str):    # (value)
 		value=[nvdict[name] for name in args[1:]]
@@ -83,2 +221,28 @@
 		return nvdict
 
+
+def netCDFread(filename):
+	print(('Opening {} for reading '.format(filename)))
+	NCData=Dataset(filename, 'r')
+	class_dict={}
+	class_tree={}
+
+	for group in NCData.groups:
+		if len(NCData.groups[group].groups)>0:
+			for subgroup in NCData.groups[group].groups:
+				classe=str(group)+'.'+str(subgroup)
+				class_dict[classe]=[str(getattr(NCData.groups[group].groups[subgroup],'classtype')),]
+				if class_dict[classe][0] not in ['dict','list','cell']:
+					class_dict[classe].append(__import__(class_dict[classe][0]))
+				class_tree[classe]=[group,subgroup]
+		else:
+			classe=str(group)
+			try:
+				class_dict[classe]=[str(getattr(NCData.groups[group],'classtype')),]
+				if class_dict[classe][0] not in ['dict','list','cell']:
+					class_dict[classe].append(__import__(class_dict[classe][0]))
+					class_tree[classe]=[group,]
+			except AttributeError:
+				print(('group {} is empty'.format(group)))
+	NCData.close()
+	return class_dict,class_tree
Index: /issm/trunk-jpl/src/py3/materials/TMeltingPoint.py
===================================================================
--- /issm/trunk-jpl/src/py3/materials/TMeltingPoint.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/materials/TMeltingPoint.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 
 def TMeltingPoint(reftemp,pressure):
Index: /issm/trunk-jpl/src/py3/materials/cuffey.py
===================================================================
--- /issm/trunk-jpl/src/py3/materials/cuffey.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/materials/cuffey.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 
 def cuffey(temperature):
@@ -6,5 +6,5 @@
 
 	   rigidity (in s^(1/3)Pa) is the flow law parameter in the flow law sigma=B*e(1/3)
-		(Cuffey and Paterson, p75). 
+		(Cuffey and Paterson, p75).
 	   temperature is in Kelvin degrees
 
@@ -12,38 +12,55 @@
 	      rigidity=cuffey(temperature)
 	"""
-	
-	if numpy.any(temperature<0.):
+
+	if np.any(temperature<0.):
 		raise RuntimeError("input temperature should be in Kelvin (positive)")
-	
-	T = temperature.reshape(-1,)-273.15
 
-	rigidity=numpy.zeros_like(T)
-	pos=numpy.nonzero(T<=-45)
-	rigidity[pos]=10**8*(-0.000396645116301*(T[pos]+50)**3+ 0.013345579471334*(T[pos]+50)**2  -0.356868703259105*(T[pos]+50)+7.272363035371383)
-	pos=numpy.nonzero(numpy.logical_and(-45<=T,T<-40))
-	rigidity[pos]=10**8*(-0.000396645116301*(T[pos]+45)**3+ 0.007395902726819*(T[pos]+45)**2  -0.253161292268336*(T[pos]+45)+5.772078366321591)
-	pos=numpy.nonzero(numpy.logical_and(-40<=T,T<-35))
-	rigidity[pos]=10**8*(0.000408322072669*(T[pos]+40)**3+  0.001446225982305*(T[pos]+40)**2  -0.208950648722716*(T[pos]+40)+4.641588833612773)
-	pos=numpy.nonzero(numpy.logical_and(-35<=T,T<-30))
-	rigidity[pos]=10**8*(-0.000423888728124*(T[pos]+35)**3+ 0.007571057072334*(T[pos]+35)**2  -0.163864233449525*(T[pos]+35)+3.684031498640382)
-	pos=numpy.nonzero(numpy.logical_and(-30<=T,T<-25))
-	rigidity[pos]=10**8*(0.000147154327025*(T[pos]+30)**3+ 0.001212726150476*(T[pos]+30)**2  -0.119945317335478*(T[pos]+30)+3.001000667185614)
-	pos=numpy.nonzero(numpy.logical_and(-25<=T,T<-20))
-	rigidity[pos]=10**8*(-0.000193435838672*(T[pos]+25)**3+ 0.003420041055847*(T[pos]+25)**2  -0.096781481303861*(T[pos]+25)+2.449986525148220)
-	pos=numpy.nonzero(numpy.logical_and(-20<=T,T<-15))
-	rigidity[pos]=10**8*(0.000219771255067*(T[pos]+20)**3+  0.000518503475772*(T[pos]+20)**2  -0.077088758645767*(T[pos]+20)+2.027400665191131)
-	pos=numpy.nonzero(numpy.logical_and(-15<=T,T<-10))
-	rigidity[pos]=10**8*(-0.000653438900191*(T[pos]+15)**3+ 0.003815072301777*(T[pos]+15)**2  -0.055420879758021*(T[pos]+15)+1.682390865739973)
-	pos=numpy.nonzero(numpy.logical_and(-10<=T,T<-5))
-	rigidity[pos]=10**8*(0.000692439419762*(T[pos]+10)**3 -0.005986511201093 *(T[pos]+10)**2 -0.066278074254598*(T[pos]+10)+1.418983411970382)
-	pos=numpy.nonzero(numpy.logical_and(-5<=T,T<-2))
-	rigidity[pos]=10**8*(-0.000132282004110*(T[pos]+5)**3 +0.004400080095332*(T[pos]+5)**2    -0.074210229783403*(T[pos]+5)+ 1.024485188140279)
-	pos=numpy.nonzero(-2<=T)
-	rigidity[pos]=10**8*(-0.000132282004110*(T[pos]+2)**3 +0.003209542058346*(T[pos]+2)**2    -0.051381363322371*(T[pos]+2)+ 0.837883605537096)
+	if np.ndim(temperature)==2:
+		#T = temperature.reshape(-1,)-273.15
+		T = temperature.flatten()-273.15
+	elif isinstance(temperature,float) or isinstance(temperature,int):
+		T = np.array([temperature])-273.15
+	else:
+		T = temperature-273.15
+
+
+	rigidity=np.zeros_like(T)
+	pos=np.nonzero(T<=-45)
+	if len(pos):
+		rigidity[pos]=10**8*(-0.000396645116301*(T[pos]+50)**3+ 0.013345579471334*(T[pos]+50)**2  -0.356868703259105*(T[pos]+50)+7.272363035371383)
+	pos=np.nonzero(np.logical_and(-45<=T,T<-40))
+	if len(pos):
+		rigidity[pos]=10**8*(-0.000396645116301*(T[pos]+45)**3+ 0.007395902726819*(T[pos]+45)**2  -0.253161292268336*(T[pos]+45)+5.772078366321591)
+	pos=np.nonzero(np.logical_and(-40<=T,T<-35))
+	if len(pos):
+		rigidity[pos]=10**8*(0.000408322072669*(T[pos]+40)**3+  0.001446225982305*(T[pos]+40)**2  -0.208950648722716*(T[pos]+40)+4.641588833612773)
+	pos=np.nonzero(np.logical_and(-35<=T,T<-30))
+	if len(pos):
+		rigidity[pos]=10**8*(-0.000423888728124*(T[pos]+35)**3+ 0.007571057072334*(T[pos]+35)**2  -0.163864233449525*(T[pos]+35)+3.684031498640382)
+	pos=np.nonzero(np.logical_and(-30<=T,T<-25))
+	if len(pos):
+		rigidity[pos]=10**8*(0.000147154327025*(T[pos]+30)**3+ 0.001212726150476*(T[pos]+30)**2  -0.119945317335478*(T[pos]+30)+3.001000667185614)
+	pos=np.nonzero(np.logical_and(-25<=T,T<-20))
+	if len(pos):
+		rigidity[pos]=10**8*(-0.000193435838672*(T[pos]+25)**3+ 0.003420041055847*(T[pos]+25)**2  -0.096781481303861*(T[pos]+25)+2.449986525148220)
+	pos=np.nonzero(np.logical_and(-20<=T,T<-15))
+	if len(pos):
+		rigidity[pos]=10**8*(0.000219771255067*(T[pos]+20)**3+  0.000518503475772*(T[pos]+20)**2  -0.077088758645767*(T[pos]+20)+2.027400665191131)
+	pos=np.nonzero(np.logical_and(-15<=T,T<-10))
+	if len(pos):
+		rigidity[pos]=10**8*(-0.000653438900191*(T[pos]+15)**3+ 0.003815072301777*(T[pos]+15)**2  -0.055420879758021*(T[pos]+15)+1.682390865739973)
+	pos=np.nonzero(np.logical_and(-10<=T,T<-5))
+	if len(pos):
+		rigidity[pos]=10**8*(0.000692439419762*(T[pos]+10)**3 -0.005986511201093 *(T[pos]+10)**2 -0.066278074254598*(T[pos]+10)+1.418983411970382)
+	pos=np.nonzero(np.logical_and(-5<=T,T<-2))
+	if len(pos):
+		rigidity[pos]=10**8*(-0.000132282004110*(T[pos]+5)**3 +0.004400080095332*(T[pos]+5)**2    -0.074210229783403*(T[pos]+5)+ 1.024485188140279)
+	pos=np.nonzero(-2<=T)
+	if len(pos):
+		rigidity[pos]=10**8*(-0.000132282004110*(T[pos]+2)**3 +0.003209542058346*(T[pos]+2)**2    -0.051381363322371*(T[pos]+2)+ 0.837883605537096)
 
 	#Now make sure that rigidity is positive
-	pos=numpy.nonzero(rigidity<0)
-	rigidity[pos]=1**6 
+	pos=np.nonzero(rigidity<0)
+	rigidity[pos]=1**6
 
 	return rigidity
-
Index: /issm/trunk-jpl/src/py3/materials/paterson.py
===================================================================
--- /issm/trunk-jpl/src/py3/materials/paterson.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/materials/paterson.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 
 def paterson(temperature):
@@ -12,12 +12,12 @@
 	"""
 	
-	if numpy.any(temperature<0.):
+	if np.any(temperature<0.):
 		raise RuntimeError("input temperature should be in Kelvin (positive)")
 
-	if numpy.ndim(temperature)==2:
+	if np.ndim(temperature)==2:
 		#T = temperature.reshape(-1,)-273.15
 		T = temperature.flatten()-273.15
 	elif isinstance(temperature,float) or isinstance(temperature,int):
-		T = numpy.array([temperature])-273.15
+		T = np.array([temperature])-273.15
 	else:
 		T = temperature-273.15
@@ -36,41 +36,41 @@
 	# rigidity=fittedmodel(temperature);
 
-	rigidity=numpy.zeros_like(T)
-	pos1=numpy.nonzero(T<=-45)[0]
+	rigidity=np.zeros_like(T)
+	pos1=np.nonzero(T<=-45)[0]
 	if len(pos1):
 		rigidity[pos1]=10**8*(-0.000292866376675*(T[pos1]+50)**3+ 0.011672640664130*(T[pos1]+50)**2  -0.325004442485481*(T[pos1]+50)+  6.524779401948101)
-	pos2=numpy.nonzero(numpy.logical_and(-45<=T,T<-40))[0]
+	pos2=np.nonzero(np.logical_and(-45<=T,T<-40))[0]
 	if len(pos2):
 		rigidity[pos2]=10**8*(-0.000292866376675*(T[pos2]+45)**3+ 0.007279645014004*(T[pos2]+45)**2  -0.230243014094813*(T[pos2]+45)+  5.154964909039554)
-	pos3=numpy.nonzero(numpy.logical_and(-40<=T,T<-35))[0]
+	pos3=np.nonzero(np.logical_and(-40<=T,T<-35))[0]
 	if len(pos3):
 		rigidity[pos3]=10**8*(0.000072737147457*(T[pos3]+40)**3+  0.002886649363879*(T[pos3]+40)**2  -0.179411542205399*(T[pos3]+40)+  4.149132666831214)
-	pos4=numpy.nonzero(numpy.logical_and(-35<=T,T<-30))[0]
+	pos4=np.nonzero(np.logical_and(-35<=T,T<-30))[0]
 	if len(pos4):
 		rigidity[pos4]=10**8*(-0.000086144770023*(T[pos4]+35)**3+ 0.003977706575736*(T[pos4]+35)**2  -0.145089762507325*(T[pos4]+35)+  3.333333333333331)
-	pos5=numpy.nonzero(numpy.logical_and(-30<=T,T<-25))[0]
+	pos5=np.nonzero(np.logical_and(-30<=T,T<-25))[0]
 	if len(pos5):
 		rigidity[pos5]=10**8*(-0.000043984685769*(T[pos5]+30)**3+ 0.002685535025386*(T[pos5]+30)**2  -0.111773554501713*(T[pos5]+30)+  2.696559088937191)
-	pos6=numpy.nonzero(numpy.logical_and(-25<=T,T<-20))[0]
+	pos6=np.nonzero(np.logical_and(-25<=T,T<-20))[0]
 	if len(pos6):
 		rigidity[pos6]=10**8*(-0.000029799523463*(T[pos6]+25)**3+ 0.002025764738854*(T[pos6]+25)**2  -0.088217055680511*(T[pos6]+25)+  2.199331606342181)
-	pos7=numpy.nonzero(numpy.logical_and(-20<=T,T<-15))[0]
+	pos7=np.nonzero(np.logical_and(-20<=T,T<-15))[0]
 	if len(pos7):
 		rigidity[pos7]=10**8*(0.000136920904777*(T[pos7]+20)**3+  0.001578771886910*(T[pos7]+20)**2  -0.070194372551690*(T[pos7]+20)+  1.805165505978111)
-	pos8=numpy.nonzero(numpy.logical_and(-15<=T,T<-10))[0]
+	pos8=np.nonzero(np.logical_and(-15<=T,T<-10))[0]
 	if len(pos8):
 		rigidity[pos8]=10**8*(-0.000899763781026*(T[pos8]+15)**3+ 0.003632585458564*(T[pos8]+15)**2  -0.044137585824322*(T[pos8]+15)+  1.510778053489523)
-	pos9=numpy.nonzero(numpy.logical_and(-10<=T,T<-5))[0]
+	pos9=np.nonzero(np.logical_and(-10<=T,T<-5))[0]
 	if len(pos9):
 		rigidity[pos9]=10**8*(0.001676964325070*(T[pos9]+10)**3-  0.009863871256831*(T[pos9]+10)**2  -0.075294014815659*(T[pos9]+10)+  1.268434288203714)
-	pos10=numpy.nonzero(numpy.logical_and(-5<=T,T<-2))[0]
+	pos10=np.nonzero(np.logical_and(-5<=T,T<-2))[0]
 	if len(pos10):
 		rigidity[pos10]=10**8*(-0.003748937622487*(T[pos10]+5)**3+0.015290593619213*(T[pos10]+5)**2  -0.048160403003748*(T[pos10]+5)+  0.854987973338348)
-	pos11=numpy.nonzero(-2<=T)[0]
+	pos11=np.nonzero(-2<=T)[0]
 	if len(pos11):
 		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=numpy.nonzero(rigidity<0)[0]
+	pos=np.nonzero(rigidity<0)[0]
 	if len(pos):
 		rigidity[pos]=1.e6 
Index: /issm/trunk-jpl/src/py3/mech/analyticaldamage.py
===================================================================
--- /issm/trunk-jpl/src/py3/mech/analyticaldamage.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mech/analyticaldamage.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 from averaging import averaging
 #from plotmodel import plotmodel
Index: /issm/trunk-jpl/src/py3/mech/backstressfrominversion.py
===================================================================
--- /issm/trunk-jpl/src/py3/mech/backstressfrominversion.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mech/backstressfrominversion.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 from averaging import averaging
 from thomasparams import thomasparams
Index: /issm/trunk-jpl/src/py3/mech/calcbackstress.py
===================================================================
--- /issm/trunk-jpl/src/py3/mech/calcbackstress.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mech/calcbackstress.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 from averaging import averaging
 from thomasparams import thomasparams
Index: /issm/trunk-jpl/src/py3/mech/damagefrominversion.py
===================================================================
--- /issm/trunk-jpl/src/py3/mech/damagefrominversion.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mech/damagefrominversion.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 
 def damagefrominversion(md):
Index: /issm/trunk-jpl/src/py3/mech/mechanicalproperties.py
===================================================================
--- /issm/trunk-jpl/src/py3/mech/mechanicalproperties.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mech/mechanicalproperties.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 from GetNodalFunctionsCoeff import GetNodalFunctionsCoeff
 from results import results
@@ -109,5 +109,5 @@
 		#eigenvalues and vectors for stress
 		value,directions=np.linalg.eig(stress);
-		idx=abs(value).argsort()[::-1] # sort in descending order
+		idx=value.argsort()[::-1] # sort in descending algebraic (not absolute) order
 		value=value[idx]
 		directions=directions[:,idx]
@@ -117,5 +117,5 @@
 		#eigenvalues and vectors for strain
 		value,directions=np.linalg.eig(strain);
-		idx=abs(value).argsort()[::-1] # sort in descending order
+		idx=value.argsort()[::-1] # sort in descending order
 		value=value[idx]
 		directions=directions[:,idx]
@@ -125,14 +125,4 @@
 	##plug onto the model
 	##NB: Matlab sorts the eigen value in increasing order, we want the reverse
-	stress=results()
-	stress.xx=tau_xx
-	stress.yy=tau_yy
-	stress.xy=tau_xy
-	stress.principalvalue1=valuesstress[:,0]
-	stress.principalaxis1=directionsstress[:,0:2]
-	stress.principalvalue2=valuesstress[:,1]
-	stress.principalaxis2=directionsstress[:,2:4]
-	stress.effectivevalue=1./np.sqrt(2.)*np.sqrt(stress.xx**2+stress.yy**2+2.*stress.xy**2)
-	md.results.stress=stress
 	
 	strainrate=results()
Index: /issm/trunk-jpl/src/py3/mech/robintemperature.py
===================================================================
--- /issm/trunk-jpl/src/py3/mech/robintemperature.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mech/robintemperature.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 from scipy.special import erf
 
Index: /issm/trunk-jpl/src/py3/mech/steadystateiceshelftemp.py
===================================================================
--- /issm/trunk-jpl/src/py3/mech/steadystateiceshelftemp.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mech/steadystateiceshelftemp.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 
 def steadystateiceshelftemp(md,surfacetemp,basaltemp):
@@ -18,5 +18,4 @@
       temperature=steadystateiceshelftemp(md,surfacetemp,basaltemp)
 	"""
-
 	if len(md.geometry.thickness)!=md.mesh.numberofvertices:
 		raise ValueError('steadystateiceshelftemp error message: thickness should have a length of ' + md.mesh.numberofvertices)
Index: /issm/trunk-jpl/src/py3/mech/thomasparams.py
===================================================================
--- /issm/trunk-jpl/src/py3/mech/thomasparams.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mech/thomasparams.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 from averaging import averaging
 
Index: /issm/trunk-jpl/src/py3/mesh/ComputeHessian.py
===================================================================
--- /issm/trunk-jpl/src/py3/mesh/ComputeHessian.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mesh/ComputeHessian.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 from GetNodalFunctionsCoeff import GetNodalFunctionsCoeff
 from GetAreas import GetAreas
@@ -20,9 +20,9 @@
 
 	#some variables
-	numberofnodes=numpy.size(x)
-	numberofelements=numpy.size(index,axis=0)
+	numberofnodes=np.size(x)
+	numberofelements=np.size(index,axis=0)
 
 	#some checks
-	if numpy.size(field)!=numberofnodes and numpy.size(field)!=numberofelements:
+	if np.size(field)!=numberofnodes and np.size(field)!=numberofelements:
 		raise TypeError("ComputeHessian error message: the given field size not supported yet")
 	if not m.strcmpi(type,'node') and not m.strcmpi(type,'element'):
@@ -33,34 +33,33 @@
 	linesize=3*numberofelements
 
-	#get areas and nodal functions coefficients N(x,y)=alpha x + beta y + gamma 
+	#get areas and nodal functions coefficients N(x,y)=alpha x + beta y + gamma
 	[alpha,beta,dum]=GetNodalFunctionsCoeff(index,x,y)
 	areas=GetAreas(index,x,y)
 
 	#compute weights that hold the volume of all the element holding the node i
-	weights=m.sparse(line,numpy.ones((linesize,1)),numpy.tile(areas.reshape(-1,1),(3,1)),numberofnodes,1)
+	weights=m.sparse(line,np.ones((linesize,1),dtype=int),np.tile(areas,(3,1)),numberofnodes,1)
 
 	#compute field on nodes if on elements
-	if numpy.size(field,axis=0)==numberofelements:
-		field=m.sparse(line,numpy.ones((linesize,1)),numpy.tile(areas*field,(3,1)),numberofnodes,1)/weights
+	if np.size(field,axis=0)==numberofelements:
+		field=m.sparse(line,np.ones((linesize,1),dtype=int),np.tile(areas*field,(3,1)),numberofnodes,1)/weights
 
 	#Compute gradient for each element
-	grad_elx=numpy.sum(field[index-1,0]*alpha,axis=1) 
-	grad_ely=numpy.sum(field[index-1,0]*beta,axis=1)
+	grad_elx=np.sum(field[index-1]*alpha,axis=1)
+	grad_ely=np.sum(field[index-1]*beta,axis=1)
 
 	#Compute gradient for each node (average of the elements around)
-	gradx=m.sparse(line,numpy.ones((linesize,1)),numpy.tile((areas*grad_elx).reshape(-1,1),(3,1)),numberofnodes,1)
-	grady=m.sparse(line,numpy.ones((linesize,1)),numpy.tile((areas*grad_ely).reshape(-1,1),(3,1)),numberofnodes,1)
+	gradx=m.sparse(line,np.ones((linesize,1),dtype=int),np.tile((areas*grad_elx),(3,1)),numberofnodes,1)
+	grady=m.sparse(line,np.ones((linesize,1),dtype=int),np.tile((areas*grad_ely),(3,1)),numberofnodes,1)
 	gradx=gradx/weights
 	grady=grady/weights
 
 	#Compute hessian for each element
-	hessian=numpy.hstack((numpy.sum(gradx[index-1,0]*alpha,axis=1).reshape(-1,1),numpy.sum(grady[index-1,0]*alpha,axis=1).reshape(-1,1),numpy.sum(grady[index-1,0]*beta,axis=1).reshape(-1,1)))
+	hessian=np.vstack((np.sum(gradx[index-1,0]*alpha,axis=1),np.sum(grady[index-1,0]*alpha,axis=1),np.sum(grady[index-1,0]*beta,axis=1))).T
 
 	if m.strcmpi(type,'node'):
 		#Compute Hessian on the nodes (average of the elements around)
-		hessian=numpy.hstack((m.sparse(line,numpy.ones((linesize,1)),numpy.tile((areas*hessian[:,0]).reshape(-1,1),(3,1)),numberofnodes,1)/weights, \
-			m.sparse(line,numpy.ones((linesize,1)),numpy.tile((areas*hessian[:,1]).reshape(-1,1),(3,1)),numberofnodes,1)/weights, \
-			m.sparse(line,numpy.ones((linesize,1)),numpy.tile((areas*hessian[:,2]).reshape(-1,1),(3,1)),numberofnodes,1)/weights ))
+		hessian=np.hstack((m.sparse(line,np.ones((linesize,1),dtype=int),np.tile((areas*hessian[:,0]),(3,1)),numberofnodes,1)/weights,
+											 m.sparse(line,np.ones((linesize,1),dtype=int),np.tile((areas*hessian[:,1]),(3,1)),numberofnodes,1)/weights,
+											 m.sparse(line,np.ones((linesize,1),dtype=int),np.tile((areas*hessian[:,2]),(3,1)),numberofnodes,1)/weights ))
 
 	return hessian
-
Index: /issm/trunk-jpl/src/py3/mesh/ComputeMetric.py
===================================================================
--- /issm/trunk-jpl/src/py3/mesh/ComputeMetric.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mesh/ComputeMetric.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 
 def ComputeMetric(hessian,scale,epsilon,hmin,hmax,pos):
@@ -17,21 +17,21 @@
 	b=hessian[:,1]
 	d=hessian[:,2]
-	lambda1=0.5*((a+d)+numpy.sqrt(4.*b**2+(a-d)**2))
-	lambda2=0.5*((a+d)-numpy.sqrt(4.*b**2+(a-d)**2))
-	pos1=numpy.nonzero(lambda1==0.)[0]
-	pos2=numpy.nonzero(lambda2==0.)[0]
-	pos3=numpy.nonzero(numpy.logical_and(b==0.,lambda1==lambda2))[0]
+	lambda1=0.5*((a+d)+np.sqrt(4.*b**2+(a-d)**2))
+	lambda2=0.5*((a+d)-np.sqrt(4.*b**2+(a-d)**2))
+	pos1=np.nonzero(lambda1==0.)[0]
+	pos2=np.nonzero(lambda2==0.)[0]
+	pos3=np.nonzero(np.logical_and(b==0.,lambda1==lambda2))[0]
 
 	#Modify the eigen values to control the shape of the elements
-	lambda1=numpy.minimum(numpy.maximum(numpy.abs(lambda1)*scale/epsilon,1./hmax**2),1./hmin**2)
-	lambda2=numpy.minimum(numpy.maximum(numpy.abs(lambda2)*scale/epsilon,1./hmax**2),1./hmin**2)
+	lambda1=np.minimum(np.maximum(np.abs(lambda1)*scale/epsilon,1./hmax**2),1./hmin**2)
+	lambda2=np.minimum(np.maximum(np.abs(lambda2)*scale/epsilon,1./hmax**2),1./hmin**2)
 
 	#compute eigen vectors
-	norm1=numpy.sqrt(8.*b**2+2.*(d-a)**2+2.*(d-a)*numpy.sqrt((a-d)**2+4.*b**2))
+	norm1=np.sqrt(8.*b**2+2.*(d-a)**2+2.*(d-a)*np.sqrt((a-d)**2+4.*b**2))
 	v1x=2.*b/norm1
-	v1y=((d-a)+numpy.sqrt((a-d)**2+4.*b**2))/norm1
-	norm2=numpy.sqrt(8.*b**2+2.*(d-a)**2-2.*(d-a)*numpy.sqrt((a-d)**2+4.*b**2))
+	v1y=((d-a)+np.sqrt((a-d)**2+4.*b**2))/norm1
+	norm2=np.sqrt(8.*b**2+2.*(d-a)**2-2.*(d-a)*np.sqrt((a-d)**2+4.*b**2))
 	v2x=2.*b/norm2
-	v2y=((d-a)-numpy.sqrt((a-d)**2+4.*b**2))/norm2
+	v2y=((d-a)-np.sqrt((a-d)**2+4.*b**2))/norm2
 
 	v1x[pos3]=1.
@@ -41,32 +41,32 @@
 
 	#Compute new metric (for each node M=V*Lambda*V^-1)
-	metric=numpy.hstack((((v1x*v2y-v1y*v2x)**(-1)*( lambda1*v2y*v1x-lambda2*v1y*v2x)).reshape(-1,1), \
-		                 ((v1x*v2y-v1y*v2x)**(-1)*( lambda1*v1y*v2y-lambda2*v1y*v2y)).reshape(-1,1), \
-		                 ((v1x*v2y-v1y*v2x)**(-1)*(-lambda1*v2x*v1y+lambda2*v1x*v2y)).reshape(-1,1)))
+	metric=np.vstack((((v1x*v2y-v1y*v2x)**(-1)*( lambda1*v2y*v1x-lambda2*v1y*v2x)).reshape(-1,),
+										((v1x*v2y-v1y*v2x)**(-1)*( lambda1*v1y*v2y-lambda2*v1y*v2y)).reshape(-1,),
+										((v1x*v2y-v1y*v2x)**(-1)*(-lambda1*v2x*v1y+lambda2*v1x*v2y)).reshape(-1,))).T
 
 	#some corrections for 0 eigen values
-	metric[pos1,:]=numpy.tile(numpy.array([[1./hmax**2,0.,1./hmax**2]]),(numpy.size(pos1),1))
-	metric[pos2,:]=numpy.tile(numpy.array([[1./hmax**2,0.,1./hmax**2]]),(numpy.size(pos2),1))
+	metric[pos1,:]=np.tile(np.array([[1./hmax**2,0.,1./hmax**2]]),(np.size(pos1),1))
+	metric[pos2,:]=np.tile(np.array([[1./hmax**2,0.,1./hmax**2]]),(np.size(pos2),1))
 
 	#take care of water elements
-	metric[pos ,:]=numpy.tile(numpy.array([[1./hmax**2,0.,1./hmax**2]]),(numpy.size(pos ),1))
+	metric[pos ,:]=np.tile(np.array([[1./hmax**2,0.,1./hmax**2]]),(np.size(pos ),1))
 
 	#take care of NaNs if any (use Numpy eig in a loop)
-	pos=numpy.nonzero(numpy.isnan(metric))[0]
-	if numpy.size(pos):
-		print((" %i NaN found in the metric. Use Numpy routine..." % numpy.size(pos)))
+	pos=np.nonzero(np.isnan(metric))[0]
+	if np.size(pos):
+		print((" %i NaN found in the metric. Use Numpy routine..." % np.size(pos)))
 		for posi in pos:
-			H=numpy.array([[hessian[posi,0],hessian[posi,1]],[hessian[posi,1],hessian[posi,2]]])
-			[v,u]=numpy.linalg.eig(H)
-			v=numpy.diag(v)
+			H=np.array([[hessian[posi,0],hessian[posi,1]],[hessian[posi,1],hessian[posi,2]]])
+			[v,u]=np.linalg.eig(H)
+			v=np.diag(v)
 			lambda1=v[0,0]
 			lambda2=v[1,1]
-			v[0,0]=numpy.minimum(numpy.maximum(numpy.abs(lambda1)*scale/epsilon,1./hmax**2),1./hmin**2)
-			v[1,1]=numpy.minimum(numpy.maximum(numpy.abs(lambda2)*scale/epsilon,1./hmax**2),1./hmin**2)
+			v[0,0]=np.minimum(np.maximum(np.abs(lambda1)*scale/epsilon,1./hmax**2),1./hmin**2)
+			v[1,1]=np.minimum(np.maximum(np.abs(lambda2)*scale/epsilon,1./hmax**2),1./hmin**2)
 
-			metricTria=numpy.dot(numpy.dot(u,v),numpy.linalg.inv(u))
-			metric[posi,:]=numpy.array([metricTria[0,0],metricTria[0,1],metricTria[1,1]])
+			metricTria=np.dot(np.dot(u,v),np.linalg.inv(u))
+			metric[posi,:]=np.array([metricTria[0,0],metricTria[0,1],metricTria[1,1]])
 
-	if numpy.any(numpy.isnan(metric)):
+	if np.any(np.isnan(metric)):
 		raise RunTimeError("ComputeMetric error message: NaN in the metric despite our efforts...")
 
Index: /issm/trunk-jpl/src/py3/mesh/ElementsFromEdge.py
===================================================================
--- /issm/trunk-jpl/src/py3/mesh/ElementsFromEdge.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mesh/ElementsFromEdge.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 import PythonFuncs as p
 
@@ -12,11 +12,11 @@
 	"""
 
-	edgeelements=numpy.nonzero(\
-		p.logical_or_n(numpy.logical_and(elements[:,0]==A,elements[:,1]==B), \
-					 numpy.logical_and(elements[:,0]==A,elements[:,2]==B), \
-					 numpy.logical_and(elements[:,1]==A,elements[:,2]==B), \
-					 numpy.logical_and(elements[:,1]==A,elements[:,0]==B), \
-					 numpy.logical_and(elements[:,2]==A,elements[:,0]==B), \
-					 numpy.logical_and(elements[:,2]==A,elements[:,1]==B), \
+	edgeelements=np.nonzero(\
+		p.logical_or_n(np.logical_and(elements[:,0]==A,elements[:,1]==B), \
+					 np.logical_and(elements[:,0]==A,elements[:,2]==B), \
+					 np.logical_and(elements[:,1]==A,elements[:,2]==B), \
+					 np.logical_and(elements[:,1]==A,elements[:,0]==B), \
+					 np.logical_and(elements[:,2]==A,elements[:,0]==B), \
+					 np.logical_and(elements[:,2]==A,elements[:,1]==B), \
 		))[0]+1
 
Index: /issm/trunk-jpl/src/py3/mesh/GetNodalFunctionsCoeff.py
===================================================================
--- /issm/trunk-jpl/src/py3/mesh/GetNodalFunctionsCoeff.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mesh/GetNodalFunctionsCoeff.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 
 def GetNodalFunctionsCoeff(index,x,y):
@@ -23,18 +23,18 @@
 
 	#get nels and nods
-	nels=numpy.size(index,axis=0)
-	nods=numpy.size(x)
+	nels=np.size(index,axis=0)
+	nods=np.size(x)
 
 	#some checks
-	if numpy.size(y)!=nods:
+	if np.size(y)!=nods:
 		raise TypeError("GetNodalFunctionsCoeff error message: x and y do not have the same length.")
-	if numpy.max(index)>nods:
+	if np.max(index)>nods:
 		raise TypeError("GetNodalFunctionsCoeff error message: index should not have values above %d." % nods)
-	if numpy.size(index,axis=1)!=3:
+	if np.size(index,axis=1)!=3:
 		raise TypeError("GetNodalFunctionsCoeff error message: only 2d meshes supported. index should have 3 columns.")
 
 	#initialize output
-	alpha=numpy.zeros((nels,3))
-	beta=numpy.zeros((nels,3))
+	alpha=np.zeros((nels,3))
+	beta=np.zeros((nels,3))
 
 	#compute nodal functions coefficients N(x,y)=alpha x + beta y +gamma
@@ -48,10 +48,10 @@
 
 	#get alpha and beta
-	alpha=numpy.hstack(((invdet*(y2-y3)).reshape(-1,1),(invdet*(y3-y1)).reshape(-1,1),(invdet*(y1-y2)).reshape(-1,1)))
-	beta =numpy.hstack(((invdet*(x3-x2)).reshape(-1,1),(invdet*(x1-x3)).reshape(-1,1),(invdet*(x2-x1)).reshape(-1,1)))
+	alpha=np.vstack(((invdet*(y2-y3)).reshape(-1,),(invdet*(y3-y1)).reshape(-1,),(invdet*(y1-y2)).reshape(-1,))).T
+	beta =np.vstack(((invdet*(x3-x2)).reshape(-1,),(invdet*(x1-x3)).reshape(-1,),(invdet*(x2-x1)).reshape(-1,))).T
 
 	#get gamma if requested
-	gamma=numpy.zeros((nels,3))
-	gamma=numpy.hstack(((invdet*(x2*y3-x3*y2)).reshape(-1,1),(invdet*(y1*x3-y3*x1)).reshape(-1,1),(invdet*(x1*y2-x2*y1)).reshape(-1,1)))
+	gamma=np.zeros((nels,3))
+	gamma=np.vstack(((invdet*(x2*y3-x3*y2)).reshape(-1,),(invdet*(y1*x3-y3*x1)).reshape(-1,),(invdet*(x1*y2-x2*y1)).reshape(-1,))).T
 
 	return alpha,beta,gamma
Index: /issm/trunk-jpl/src/py3/mesh/bamg.py
===================================================================
--- /issm/trunk-jpl/src/py3/mesh/bamg.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mesh/bamg.py	(revision 23670)
@@ -1,5 +1,7 @@
 import os.path
-import numpy
-from mesh2d import mesh2d
+import numpy as  np
+from mesh2d import *
+from mesh2dvertical import *
+from mesh3dsurface import *
 from collections import OrderedDict
 from pairoptions import pairoptions
@@ -13,5 +15,5 @@
 from ContourToNodes import ContourToNodes
 
-def bamg(md,*kwargs):
+def bamg(md,*args):
 	"""
 	BAMG - mesh generation
@@ -20,4 +22,8 @@
 
 	   - domain :            followed by an ARGUS file that prescribes the domain outline
+	   - holes :             followed by an ARGUS file that prescribes the holes
+     - subdomains :        followed by an ARGUS file that prescribes the list of
+	                         subdomains (that need to be inside domain)
+
 	   - hmin :              minimum edge length (default is 10^-100)
 	   - hmax :              maximum edge length (default is 10^100)
@@ -37,5 +43,4 @@
 	                         1 -> use Green formula
 	   - KeepVertices :      try to keep initial vertices when adaptation is done on an existing mesh (default 1)
-	   - MaxCornerAngle :    maximum angle of corners in degree (default is 10)
 	   - maxnbv :            maximum number of vertices used to allocate memory (default is 10^6)
 	   - maxsubdiv :         maximum subdivision of exisiting elements (default is 10)
@@ -49,5 +54,4 @@
 	   - power :             power applied to the metric (default is 1)
 	   - splitcorners :      split triangles whuch have 3 vertices on the outline (default is 1)
-	   - geometricalmetric : take the geometry into account to generate the metric (default is 0)
 	   - verbose :           level of verbosity (default is 1)
 
@@ -66,5 +70,5 @@
 
 	#process options
-	options=pairoptions(**kwargs)
+	options=pairoptions(*args)
 #	options=deleteduplicates(options,1);
 
@@ -74,36 +78,133 @@
 	bamg_mesh=bamgmesh()
 
+	subdomain_ref = 1
+	hole_ref = 1
+
 	# Bamg Geometry parameters {{{
 	if options.exist('domain'):
-
 		#Check that file exists
 		domainfile=options.getfieldvalue('domain')
-		if not os.path.exists(domainfile):
-			raise IOError("bamg error message: file '%s' not found" % domainfile)
-		domain=expread(domainfile)
+		if type(domainfile) == str:
+			if not os.path.exists(domainfile):
+				raise IOError("bamg error message: file '%s' not found" % domainfile)
+			domain=expread(domainfile)
+		else:
+			domain=domainfile
 
 		#Build geometry 
 		count=0
 		for i,domaini in enumerate(domain):
-
 			#Check that the domain is closed
 			if (domaini['x'][0]!=domaini['x'][-1] or domaini['y'][0]!=domaini['y'][-1]):
 				raise RuntimeError("bamg error message: all contours provided in ''domain'' should be closed")
 
-			#Checks that all holes are INSIDE the principle domain outline
+			#Checks that all holes are INSIDE the principle domain outline princial domain should be index 0
 			if i:
-				flags=ContourToNodes(domaini['x'],domaini['y'],domainfile,0)
-				if numpy.any(numpy.logical_not(flags)):
+				flags=ContourToNodes(domaini['x'],domaini['y'],domainfile,0)[0]
+				if np.any(np.logical_not(flags)):
 					raise RuntimeError("bamg error message: All holes should be strictly inside the principal domain")
+
+			#Check orientation
+			nods=domaini['nods']-1#the domain are closed 1=end;
+
+			test = np.sum((domaini['x'][1:nods+1] - domaini['x'][0:nods])*(domaini['y'][1:nods+1] + domaini['y'][0:nods]))
+			if (i==0 and test>0) or (i>0 and test<0):
+				print('At least one contour was not correctly oriented and has been re-oriented')
+				domaini['x'] = np.flipud(domaini['x'])
+				domaini['y'] = np.flipud(domaini['y'])
+
 
 			#Add all points to bamg_geometry
 			nods=domaini['nods']-1    #the domain are closed 0=end
-			bamg_geometry.Vertices=numpy.vstack((bamg_geometry.Vertices,numpy.hstack((domaini['x'][0:nods].reshape(-1,1),domaini['y'][0:nods].reshape(-1,1),numpy.ones((nods,1))))))
-			bamg_geometry.Edges   =numpy.vstack((bamg_geometry.Edges,   numpy.hstack((numpy.arange(count+1,count+nods+1).reshape(-1,1),numpy.hstack((numpy.arange(count+2,count+nods+1),count+1)).reshape(-1,1),1.*numpy.ones((nods,1))))))
+			bamg_geometry.Vertices=np.vstack((bamg_geometry.Vertices,np.vstack((domaini['x'][0:nods],domaini['y'][0:nods],np.ones((nods)))).T))
+			bamg_geometry.Edges   =np.vstack((bamg_geometry.Edges,np.vstack((np.arange(count+1,count+nods+1),np.hstack((np.arange(count+2,count+nods+1),count+1)),1.*np.ones((nods)))).T))
 			if i:
-				bamg_geometry.SubDomains=numpy.vstack((bamg_geometry.SubDomains,[2,count+1,1,1]))
-
+				bamg_geometry.SubDomains=np.vstack((bamg_geometry.SubDomains,[2,count+1,1,-subdomain_ref]))
+				subdomain_ref = subdomain_ref+1;
+			else:
+				bamg_geometry.SubDomains=np.vstack((bamg_geometry.SubDomains,[2,count+1,1,0]))
+			
 			#update counter
 			count+=nods
+
+		#Deal with domain holes
+		if options.exist('holes'):
+			holesfile=options.getfieldvalue('holes')
+			if type(holesfile) == str:
+				if not os.path.exists(holesfile):
+					raise IOError("bamg error message: file '%s' not found" % holesfile)
+				holes=expread(holesfile)
+			else:
+				holes=holesfile
+
+			#Build geometry 
+			for i,holei in enumerate(holes):
+				#Check that the hole is closed
+				if (holei['x'][0]!=holei['x'][-1] or holei['y'][0]!=holei['y'][-1]):
+					raise RuntimeError("bamg error message: all contours provided in ''hole'' should be closed")
+
+				#Checks that all holes are INSIDE the principle domain outline princial domain should be index 0
+				flags=ContourToNodes(holei['x'],holei['y'],domainfile,0)[0]
+				if np.any(np.logical_not(flags)):
+					raise RuntimeError("bamg error message: All holes should be strictly inside the principal domain")
+
+				#Check orientation
+				nods=holei['nods']-1#the hole are closed 1=end;
+				test = np.sum((holei['x'][1:nods+1] - holei['x'][0:nods])*(holei['y'][1:nods+1] + holei['y'][0:nods]))
+				if test<0:
+					print('At least one hole was not correctly oriented and has been re-oriented')
+					holei['x'] = np.flipud(holei['x'])
+					holei['y'] = np.flipud(holei['y'])
+
+				#Add all points to bamg_geometry
+				nods=holei['nods']-1    #the hole are closed 0=end
+				bamg_geometry.Vertices=np.vstack((bamg_geometry.Vertices,np.vstack((holei['x'][0:nods],holei['y'][0:nods],np.ones((nods)))).T))
+				bamg_geometry.Edges   =np.vstack((bamg_geometry.Edges,np.vstack((np.arange(count+1,count+nods+1),np.hstack((np.arange(count+2,count+nods+1),count+1)),1.*np.ones((nods)))).T))
+				#update counter
+				count+=nods
+
+		#And subdomains
+		if options.exist('subdomains'):
+			subdomainfile=options.getfieldvalue('subdomains')
+			if type(subdomainfile) == str:
+				if not os.path.exists(subdomainfile):
+					raise IOError("bamg error message: file '%s' not found" % subdomainfile)
+				subdomains=expread(subdomainfile)
+			else:
+				subdomains=subdomainfile
+
+			#Build geometry 
+			for i,subdomaini in enumerate(subdomains):
+				#Check that the subdomain is closed
+				if (subdomaini['x'][0]!=subdomaini['x'][-1] or subdomaini['y'][0]!=subdomaini['y'][-1]):
+					raise RuntimeError("bamg error message: all contours provided in ''subdomain'' should be closed")
+
+				#Checks that all subdomains are INSIDE the principle subdomain outline princial domain should be index 0
+				if i:
+					flags=ContourToNodes(subdomaini['x'],subdomaini['y'],domainfile,0)[0]
+					if np.any(np.logical_not(flags)):
+						raise RuntimeError("bamg error message: All subdomains should be strictly inside the principal subdomain")
+
+				#Check orientation
+				nods=subdomaini['nods']-1#the subdomain are closed 1=end;
+
+				test = np.sum((subdomaini['x'][1:nods+1] - subdomaini['x'][0:nods])*(subdomaini['y'][1:nods+1] + subdomaini['y'][0:nods]))
+				if test>0:
+					print('At least one subcontour was not correctly oriented and has been re-oriented')
+					subdomaini['x'] = np.flipud(subdomaini['x'])
+					subdomaini['y'] = np.flipud(subdomaini['y'])
+
+				#Add all points to bamg_geometry
+				nods=subdomaini['nods']-1    #the subdomain are closed 0=end
+				bamg_geometry.Vertices=np.vstack((bamg_geometry.Vertices,np.vstack((subdomaini['x'][0:nods],subdomaini['y'][0:nods],np.ones((nods)))).T))
+				bamg_geometry.Edges   =np.vstack((bamg_geometry.Edges,np.vstack((np.arange(count+1,count+nods+1),np.hstack((np.arange(count+2,count+nods+1),count+1)),1.*np.ones((nods)))).T))
+				#update counter
+				count+=nods
+			
+		if options.getfieldvalue('vertical',0):
+			if np.size(options.getfieldvalue('Markers',[]))!=np.size(bamg_geometry.Edges,0):
+				raise RuntimeError('for 2d vertical mesh, ''Markers'' option is required, and should be of size ' + str(np.size(bamg_geometry.Edges,0)))
+			if np.size(options.getfieldvalue('Markers',[]))==np.size(bamg_geometry.Edges,0):
+				bamg_geometry.Edges[:,2]=options.getfieldvalue('Markers')
 
 		#take care of rifts
@@ -119,14 +220,14 @@
 
 				#detect whether all points of the rift are inside the domain
-				flags=ContourToNodes(rifti['x'],rifti['y'],domain[0],0)
-				if numpy.all(numpy.logical_not(flags)):
+				flags=ContourToNodes(rifti['x'],rifti['y'],domain[0],0)[0]
+				if np.all(np.logical_not(flags)):
 					raise RuntimeError("one rift has all its points outside of the domain outline")
 
-				elif numpy.any(numpy.logical_not(flags)):
+				elif np.any(np.logical_not(flags)):
 					#We LOTS of work to do
 					print("Rift tip outside of or on the domain has been detected and is being processed...")
 
 					#check that only one point is outside (for now)
-					if numpy.sum(numpy.logical_not(flags).astype(int))!=1:
+					if np.sum(np.logical_not(flags).astype(int))!=1:
 						raise RuntimeError("bamg error message: only one point outside of the domain is supported yet")
 
@@ -136,6 +237,6 @@
 						pass
 					elif not flags[-1]:
-						rifti['x']=numpy.flipud(rifti['x'])
-						rifti['y']=numpy.flipud(rifti['y'])
+						rifti['x']=np.flipud(rifti['x'])
+						rifti['y']=np.flipud(rifti['y'])
 					else:
 						raise RuntimeError("bamg error message: only a rift tip can be outside of the domain")
@@ -146,6 +247,6 @@
 					x2=rifti['x'][1]
 					y2=rifti['y'][1]
-					for j in range(0,numpy.size(domain[0]['x'])-1):
-						if SegIntersect(numpy.array([[x1,y1],[x2,y2]]),numpy.array([[domain[0]['x'][j],domain[0]['y'][j]],[domain[0]['x'][j+1],domain[0]['y'][j+1]]])):
+					for j in range(0,np.size(domain[0]['x'])-1):
+						if SegIntersect(np.array([[x1,y1],[x2,y2]]),np.array([[domain[0]['x'][j],domain[0]['y'][j]],[domain[0]['x'][j+1],domain[0]['y'][j+1]]])):
 
 							#Get position of the two nodes of the edge in domain
@@ -161,11 +262,11 @@
 #							x=det([det([x1 y1; x2 y2])  x1-x2;det([x3 y3; x4 y4])  x3-x4])/det([x1-x2 y1-y2;x3-x4 y3-y4]);
 #							y=det([det([x1 y1; x2 y2])  y1-y2;det([x3 y3; x4 y4])  y3-y4])/det([x1-x2 y1-y2;x3-x4 y3-y4]);
-							x=numpy.linalg.det(numpy.array([[numpy.linalg.det(numpy.array([[x1,y1],[x2,y2]])),x1-x2],[numpy.linalg.det(numpy.array([[x3,y3],[x4,y4]])),x3-x4]]))/numpy.linalg.det(numpy.array([[x1-x2,y1-y2],[x3-x4,y3-y4]]))
-							y=numpy.linalg.det(numpy.array([[numpy.linalg.det(numpy.array([[x1,y1],[x2,y2]])),y1-y2],[numpy.linalg.det(numpy.array([[x3,y3],[x4,y4]])),y3-y4]]))/numpy.linalg.det(numpy.array([[x1-x2,y1-y2],[x3-x4,y3-y4]]))
+							x=np.linalg.det(np.array([[np.linalg.det(np.array([[x1,y1],[x2,y2]])),x1-x2],[np.linalg.det(np.array([[x3,y3],[x4,y4]])),x3-x4]]))/np.linalg.det(np.array([[x1-x2,y1-y2],[x3-x4,y3-y4]]))
+							y=np.linalg.det(np.array([[np.linalg.det(np.array([[x1,y1],[x2,y2]])),y1-y2],[np.linalg.det(np.array([[x3,y3],[x4,y4]])),y3-y4]]))/np.linalg.det(np.array([[x1-x2,y1-y2],[x3-x4,y3-y4]]))
 
 							segdis= sqrt((x4-x3)**2+(y4-y3)**2)
-							tipdis=numpy.array([sqrt((x-x3)**2+(y-y3)**2),sqrt((x-x4)**2+(y-y4)**2)])
-
-							if numpy.min(tipdis)/segdis < options.getfieldvalue('toltip',0):
+							tipdis=np.array([sqrt((x-x3)**2+(y-y3)**2),sqrt((x-x4)**2+(y-y4)**2)])
+
+							if np.min(tipdis)/segdis < options.getfieldvalue('toltip',0):
 								print("moving tip-domain intersection point")
 
@@ -179,8 +280,8 @@
 								#OK, now we can add our own rift
 								nods=rifti['nods']-1
-								bamg_geometry.Vertices=numpy.vstack((bamg_geometry.Vertices,numpy.hstack((rifti['x'][1:].reshape(-1,1),rifti['y'][1:].reshape(-1,1),numpy.ones((nods,1))))))
-								bamg_geometry.Edges=numpy.vstack((bamg_geometry.Edges,\
-									numpy.array([[pos,count+1,(1+i)]]),\
-									numpy.hstack((numpy.arange(count+1,count+nods).reshape(-1,1),numpy.arange(count+2,count+nods+1).reshape(-1,1),(1+i)*numpy.ones((nods-1,1))))))
+								bamg_geometry.Vertices=np.vstack((bamg_geometry.Vertices,np.hstack((rifti['x'][1:].reshape(-1,),rifti['y'][1:].reshape(-1,),np.ones((nods,1))))))
+								bamg_geometry.Edges=np.vstack((bamg_geometry.Edges,\
+									np.array([[pos,count+1,(1+i)]]),\
+									np.hstack((np.arange(count+1,count+nods).reshape(-1,),np.arange(count+2,count+nods+1).reshape(-1,),(1+i)*np.ones((nods-1,1))))))
 								count+=nods
 
@@ -189,22 +290,22 @@
 							else:
 								#Add intersection point to Vertices
-								bamg_geometry.Vertices=numpy.vstack((bamg_geometry.Vertices,numpy.array([[x,y,1]])))
+								bamg_geometry.Vertices=np.vstack((bamg_geometry.Vertices,np.array([[x,y,1]])))
 								count+=1
 
 								#Decompose the crossing edge into 2 subedges
-								pos=numpy.nonzero(numpy.logical_and(bamg_geometry.Edges[:,0]==i1,bamg_geometry.Edges[:,1]==i2))[0]
+								pos=np.nonzero(np.logical_and(bamg_geometry.Edges[:,0]==i1,bamg_geometry.Edges[:,1]==i2))[0]
 								if not pos:
 									raise RuntimeError("bamg error message: a problem occurred...")
-								bamg_geometry.Edges=numpy.vstack((bamg_geometry.Edges[0:pos-1,:],\
-									numpy.array([[bamg_geometry.Edges[pos,0],count                     ,bamg_geometry.Edges[pos,2]]]),\
-									numpy.array([[count                     ,bamg_geometry.Edges[pos,1],bamg_geometry.Edges[pos,2]]]),\
+								bamg_geometry.Edges=np.vstack((bamg_geometry.Edges[0:pos-1,:],\
+									np.array([[bamg_geometry.Edges[pos,0],count                     ,bamg_geometry.Edges[pos,2]]]),\
+									np.array([[count                     ,bamg_geometry.Edges[pos,1],bamg_geometry.Edges[pos,2]]]),\
 									bamg_geometry.Edges[pos+1:,:]))
 
 								#OK, now we can add our own rift
 								nods=rifti['nods']-1
-								bamg_geometry.Vertices=numpy.vstack((bamg_geometry.Vertices,numpy.hstack((rifti['x'][1:].reshape(-1,1),rifti['y'][1:].reshape(-1,1),numpy.ones((nods,1))))))
-								bamg_geometry.Edges=numpy.vstack((bamg_geometry.Edges,\
-									numpy.array([[count,count+1,2]]),\
-									numpy.hstack((numpy.arange(count+1,count+nods).reshape(-1,1),numpy.arange(count+2,count+nods+1).reshape(-1,1),(1+i)*numpy.ones((nods-1,1))))))
+								bamg_geometry.Vertices=np.vstack((bamg_geometry.Vertices,np.hstack((rifti['x'][1:].reshape(-1,),rifti['y'][1:].reshape(-1,),np.ones((nods,1))))))
+								bamg_geometry.Edges=np.vstack((bamg_geometry.Edges,\
+									np.array([[count,count+1,2]]),\
+									np.hstack((np.arange(count+1,count+nods).reshape(-1,),np.arange(count+2,count+nods+1).reshape(-1,),(1+i)*np.ones((nods-1,1))))))
 								count+=nods
 
@@ -213,6 +314,6 @@
 				else:
 					nods=rifti['nods']-1
-					bamg_geometry.Vertices=numpy.vstack(bamg_geometry.Vertices, numpy.hstack(rifti['x'][:],rifti['y'][:],numpy.ones((nods+1,1))))
-					bamg_geometry.Edges   =numpy.vstack(bamg_geometry.Edges, numpy.hstack(numpy.arange(count+1,count+nods).reshape(-1,1),numpy.arange(count+2,count+nods+1).reshape(-1,1),i*numpy.ones((nods,1))))
+					bamg_geometry.Vertices=np.vstack(bamg_geometry.Vertices, np.hstack(rifti['x'][:],rifti['y'][:],np.ones((nods+1,1))))
+					bamg_geometry.Edges   =np.vstack(bamg_geometry.Edges, np.hstack(np.arange(count+1,count+nods).reshape(-1,),np.arange(count+2,count+nods+1).reshape(-1,),i*np.ones((nods,1))))
 					count=+nods+1
 
@@ -224,18 +325,18 @@
 			if all(isinstance(track,str)):
 				A=expread(track)
-				track=numpy.hstack((A.x.reshape(-1,1),A.y.reshape(-1,1)))
+				track=np.hstack((A.x.reshape(-1,),A.y.reshape(-1,)))
 			else:
 				track=float(track)    #for some reason, it is of class "single"
-			if numpy.size(track,axis=1)==2:
-				track=numpy.hstack((track,3.*numpy.ones((size(track,axis=0),1))))
+			if np.size(track,axis=1)==2:
+				track=np.hstack((track,3.*np.ones((size(track,axis=0),1))))
 
 			#only keep those inside
-			flags=ContourToNodes(track[:,0],track[:,1],domainfile,0)
-			track=track[numpy.nonzero(flags),:]
+			flags=ContourToNodes(track[:,0],track[:,1],domainfile,0)[0]
+			track=track[np.nonzero(flags),:]
 
 			#Add all points to bamg_geometry
-			nods=numpy.size(track,axis=0)
-			bamg_geometry.Vertices=numpy.vstack((bamg_geometry.Vertices,track))
-			bamg_geometry.Edges   =numpy.vstack((bamg_geometry.Edges,numpy.hstack((numpy.arange(count+1,count+nods).reshape(-1,1),numpy.arange(count+2,count+nods+1).reshape(-1,1),3.*numpy.ones((nods-1,1))))))
+			nods=np.size(track,axis=0)
+			bamg_geometry.Vertices=np.vstack((bamg_geometry.Vertices,track))
+			bamg_geometry.Edges   =np.vstack((bamg_geometry.Edges,np.hstack((np.arange(count+1,count+nods).reshape(-1,),np.arange(count+2,count+nods+1).reshape(-1,),3.*np.ones((nods-1,1))))))
 
 			#update counter
@@ -247,15 +348,13 @@
 			#recover RequiredVertices
 			requiredvertices=options.getfieldvalue('RequiredVertices')    #for some reason, it is of class "single"
-			if numpy.size(requiredvertices,axis=1)==2:
-				requiredvertices=numpy.hstack((requiredvertices,4.*numpy.ones((numpy.size(requiredvertices,axis=0),1))))
-			
+			if np.size(requiredvertices,axis=1)==2:
+				requiredvertices=np.hstack((requiredvertices,4.*np.ones((np.size(requiredvertices,axis=0),1))))
 
 			#only keep those inside
 			flags=ContourToNodes(requiredvertices[:,0],requiredvertices[:,1],domainfile,0)[0]
-			requiredvertices=requiredvertices[numpy.nonzero(flags)[0],:]
-
+			requiredvertices=requiredvertices[np.nonzero(flags)[0],:]
 			#Add all points to bamg_geometry
-			nods=numpy.size(requiredvertices,axis=0)
-			bamg_geometry.Vertices=numpy.vstack((bamg_geometry.Vertices,requiredvertices))
+			nods=np.size(requiredvertices,axis=0)
+			bamg_geometry.Vertices=np.vstack((bamg_geometry.Vertices,requiredvertices))
 
 			#update counter
@@ -277,6 +376,7 @@
 			bamg_mesh=bamgmesh(md.private.bamg['mesh'].__dict__)
 		else:
-			bamg_mesh.Vertices=numpy.hstack((md.mesh.x.reshape(-1,1),md.mesh.y.reshape(-1,1),numpy.ones((md.mesh.numberofvertices,1))))
-			bamg_mesh.Triangles=numpy.hstack((md.mesh.elements,numpy.ones((md.mesh.numberofelements,1))))
+			bamg_mesh.Vertices=np.vstack((md.mesh.x,md.mesh.y,np.ones((md.mesh.numberofvertices)))).T
+			#bamg_mesh.Vertices=np.hstack((md.mesh.x.reshape(-1,),md.mesh.y.reshape(-1,),np.ones((md.mesh.numberofvertices,1))))
+			bamg_mesh.Triangles=np.hstack((md.mesh.elements,np.ones((md.mesh.numberofelements,1))))
 
 		if isinstance(md.rifts.riftstruct,dict):
@@ -288,19 +388,18 @@
 	bamg_options['coeff']=options.getfieldvalue('coeff',1.)
 	bamg_options['cutoff']=options.getfieldvalue('cutoff',10.**-5)
-	bamg_options['err']=options.getfieldvalue('err',numpy.array([[0.01]]))
+	bamg_options['err']=options.getfieldvalue('err',np.array([[0.01]]))
 	bamg_options['errg']=options.getfieldvalue('errg',0.1)
-	bamg_options['field']=options.getfieldvalue('field',numpy.empty((0,1)))
+	bamg_options['field']=options.getfieldvalue('field',np.empty((0,1)))
 	bamg_options['gradation']=options.getfieldvalue('gradation',1.5)
 	bamg_options['Hessiantype']=options.getfieldvalue('Hessiantype',0)
 	bamg_options['hmin']=options.getfieldvalue('hmin',10.**-100)
 	bamg_options['hmax']=options.getfieldvalue('hmax',10.**100)
-	bamg_options['hminVertices']=options.getfieldvalue('hminVertices',numpy.empty((0,1)))
-	bamg_options['hmaxVertices']=options.getfieldvalue('hmaxVertices',numpy.empty((0,1)))
-	bamg_options['hVertices']=options.getfieldvalue('hVertices',numpy.empty((0,1)))
+	bamg_options['hminVertices']=options.getfieldvalue('hminVertices',np.empty((0,1)))
+	bamg_options['hmaxVertices']=options.getfieldvalue('hmaxVertices',np.empty((0,1)))
+	bamg_options['hVertices']=options.getfieldvalue('hVertices',np.empty((0,1)))
 	bamg_options['KeepVertices']=options.getfieldvalue('KeepVertices',1)
-	bamg_options['MaxCornerAngle']=options.getfieldvalue('MaxCornerAngle',10.)
 	bamg_options['maxnbv']=options.getfieldvalue('maxnbv',10**6)
 	bamg_options['maxsubdiv']=options.getfieldvalue('maxsubdiv',10.)
-	bamg_options['metric']=options.getfieldvalue('metric',numpy.empty((0,1)))
+	bamg_options['metric']=options.getfieldvalue('metric',np.empty((0,1)))
 	bamg_options['Metrictype']=options.getfieldvalue('Metrictype',0)
 	bamg_options['nbjacobi']=options.getfieldvalue('nbjacobi',1)
@@ -309,37 +408,76 @@
 	bamg_options['power']=options.getfieldvalue('power',1.)
 	bamg_options['splitcorners']=options.getfieldvalue('splitcorners',1)
-	bamg_options['geometricalmetric']=options.getfieldvalue('geometricalmetric',0)
-	bamg_options['random']=options.getfieldvalue('rand',True)
 	bamg_options['verbose']=options.getfieldvalue('verbose',1)
 	#}}}
 
 	#call Bamg
-	[bamgmesh_out,bamggeom_out]=BamgMesher(bamg_mesh.__dict__,bamg_geometry.__dict__,bamg_options)
+	bamgmesh_out,bamggeom_out=BamgMesher(bamg_mesh.__dict__,bamg_geometry.__dict__,bamg_options)
 
 	# plug results onto model
+	if options.getfieldvalue('vertical',0):
+		md.mesh=mesh2dvertical()
+		md.mesh.x=bamgmesh_out['Vertices'][:,0].copy()
+		md.mesh.y=bamgmesh_out['Vertices'][:,1].copy()
+		md.mesh.elements=bamgmesh_out['Triangles'][:,0:3].astype(int)
+		md.mesh.edges=bamgmesh_out['IssmEdges'].astype(int)
+		md.mesh.segments=bamgmesh_out['IssmSegments'][:,0:3].astype(int)
+		md.mesh.segmentmarkers=bamgmesh_out['IssmSegments'][:,3].astype(int)
+
+		#Fill in rest of fields:
+		md.mesh.numberofelements=np.size(md.mesh.elements,axis=0)
+		md.mesh.numberofvertices=np.size(md.mesh.x)
+		md.mesh.numberofedges=np.size(md.mesh.edges,axis=0)
+		md.mesh.vertexonboundary=np.zeros(md.mesh.numberofvertices,bool)
+		md.mesh.vertexonboundary[md.mesh.segments[:,0:2]-1]=True
+
+		#Now, build the connectivity tables for this mesh. Doubled in matlab for some reason
+		md.mesh.vertexonboundary=np.zeros(md.mesh.numberofvertices,)
+		md.mesh.vertexonboundary[md.mesh.segments[:,0:2]-1]=1
+
+	elif options.getfieldvalue('3dsurface',0):
+		md.mesh=mesh3dsurface()
+		md.mesh.x=bamgmesh_out['Vertices'][:,0].copy()
+		md.mesh.y=bamgmesh_out['Vertices'][:,1].copy()
+		md.mesh.z=md.mesh.x
+		md.mesh.z[:]=0
+		md.mesh.elements=bamgmesh_out['Triangles'][:,0:3].astype(int)
+		md.mesh.edges=bamgmesh_out['IssmEdges'].astype(int)
+		md.mesh.segments=bamgmesh_out['IssmSegments'][:,0:3].astype(int)
+		md.mesh.segmentmarkers=bamgmesh_out['IssmSegments'][:,3].astype(int)
+
+		#Fill in rest of fields:
+		md.mesh.numberofelements=np.size(md.mesh.elements,axis=0)
+		md.mesh.numberofvertices=np.size(md.mesh.x)
+		md.mesh.numberofedges=np.size(md.mesh.edges,axis=0)
+		md.mesh.vertexonboundary=np.zeros(md.mesh.numberofvertices,bool)
+		md.mesh.vertexonboundary[md.mesh.segments[:,0:2]-1]=True
+
+	else:
+		md.mesh=mesh2d()
+		md.mesh.x=bamgmesh_out['Vertices'][:,0].copy()
+		md.mesh.y=bamgmesh_out['Vertices'][:,1].copy()
+		md.mesh.elements=bamgmesh_out['Triangles'][:,0:3].astype(int)
+		md.mesh.edges=bamgmesh_out['IssmEdges'].astype(int)
+		md.mesh.segments=bamgmesh_out['IssmSegments'][:,0:3].astype(int)
+		md.mesh.segmentmarkers=bamgmesh_out['IssmSegments'][:,3].astype(int)
+
+		#Fill in rest of fields:
+		md.mesh.numberofelements=np.size(md.mesh.elements,axis=0)
+		md.mesh.numberofvertices=np.size(md.mesh.x)
+		md.mesh.numberofedges=np.size(md.mesh.edges,axis=0)
+		md.mesh.vertexonboundary=np.zeros(md.mesh.numberofvertices,bool)
+		md.mesh.vertexonboundary[md.mesh.segments[:,0:2]-1]=True
+
+	#Bamg private fields
 	md.private.bamg=OrderedDict()
 	md.private.bamg['mesh']=bamgmesh(bamgmesh_out)
 	md.private.bamg['geometry']=bamggeom(bamggeom_out)
-	md.mesh = mesh2d()
-	md.mesh.x=bamgmesh_out['Vertices'][:,0].copy()
-	md.mesh.y=bamgmesh_out['Vertices'][:,1].copy()
-	md.mesh.elements=bamgmesh_out['Triangles'][:,0:3].astype(int)
-	md.mesh.edges=bamgmesh_out['IssmEdges'].astype(int)
-	md.mesh.segments=bamgmesh_out['IssmSegments'][:,0:3].astype(int)
-	md.mesh.segmentmarkers=bamgmesh_out['IssmSegments'][:,3].astype(int)
-
-	#Fill in rest of fields:
-	md.mesh.numberofelements=numpy.size(md.mesh.elements,axis=0)
-	md.mesh.numberofvertices=numpy.size(md.mesh.x)
-	md.mesh.numberofedges=numpy.size(md.mesh.edges,axis=0)
-	md.mesh.vertexonboundary=numpy.zeros(md.mesh.numberofvertices,bool)
-	md.mesh.vertexonboundary[md.mesh.segments[:,0:2]-1]=True
 	md.mesh.elementconnectivity=md.private.bamg['mesh'].ElementConnectivity
-	md.mesh.elementconnectivity[numpy.nonzero(numpy.isnan(md.mesh.elementconnectivity))]=0
+	md.mesh.elementconnectivity[np.nonzero(np.isnan(md.mesh.elementconnectivity))]=0
 	md.mesh.elementconnectivity=md.mesh.elementconnectivity.astype(int)
 
 	#Check for orphan
-	if numpy.any(numpy.logical_not(numpy.in1d(numpy.arange(1,md.mesh.numberofvertices+1),md.mesh.elements.flat))):
-		raise RuntimeError("Output mesh has orphans. Decrease MaxCornerAngle to prevent outside points (ex: 0.01)")
+	if np.any(np.logical_not(np.in1d(np.arange(1,md.mesh.numberofvertices+1),md.mesh.elements.flat))):
+		raise RuntimeError("Output mesh has orphans. Check your Domain and/or RequiredVertices")
 
 	return md
@@ -351,5 +489,5 @@
 	print("Checking Edge crossing...")
 	i=0
-	while (i<numpy.size(geom.Edges,axis=0)):
+	while (i<np.size(geom.Edges,axis=0)):
 
 		#edge counter
@@ -364,5 +502,5 @@
 
 		j=i    #test edges located AFTER i only
-		while (j<numpy.size(geom.Edges,axis=0)):
+		while (j<np.size(geom.Edges,axis=0)):
 
 			#edge counter
@@ -381,13 +519,13 @@
 
 			#Check if the two edges are crossing one another
-			if SegIntersect(numpy.array([[x1,y1],[x2,y2]]),numpy.array([[x3,y3],[x4,y4]])):
+			if SegIntersect(np.array([[x1,y1],[x2,y2]]),np.array([[x3,y3],[x4,y4]])):
 
 				#Get coordinate of intersection point (http://mathworld.wolfram.com/Line-LineIntersection.html)
-				x=numpy.linalg.det(numpy.array([numpy.linalg.det(numpy.array([[x1,y1],[x2,y2]])),x1-x2],[numpy.linalg.det(numpy.array([[x3,y3],[x4,y4]])),x3-x4])/numpy.linalg.det(numpy.array([[x1-x2,y1-y2],[x3-x4,y3-y4]])))
-				y=numpy.linalg.det(numpy.array([numpy.linalg.det(numpy.array([[x1,y1],[x2,y2]])),y1-y2],[numpy.linalg.det(numpy.array([[x3,y3],[x4,y4]])),y3-y4])/numpy.linalg.det(numpy.array([[x1-x2,y1-y2],[x3-x4,y3-y4]])))
+				x=np.linalg.det(np.array([np.linalg.det(np.array([[x1,y1],[x2,y2]])),x1-x2],[np.linalg.det(np.array([[x3,y3],[x4,y4]])),x3-x4])/np.linalg.det(np.array([[x1-x2,y1-y2],[x3-x4,y3-y4]])))
+				y=np.linalg.det(np.array([np.linalg.det(np.array([[x1,y1],[x2,y2]])),y1-y2],[np.linalg.det(np.array([[x3,y3],[x4,y4]])),y3-y4])/np.linalg.det(np.array([[x1-x2,y1-y2],[x3-x4,y3-y4]])))
 
 				#Add vertex to the list of vertices
-				geom.Vertices=numpy.vstack((geom.Vertices,[x,y,min(color1,color2)]))
-				id=numpy.size(geom.Vertices,axis=0)
+				geom.Vertices=np.vstack((geom.Vertices,[x,y,min(color1,color2)]))
+				id=np.size(geom.Vertices,axis=0)
 
 				#Update edges i and j
@@ -395,7 +533,7 @@
 				edgej=geom.Edges[j,:].copy()
 				geom.Edges[i,:]    =[edgei(0),id      ,edgei(2)]
-				geom.Edges=numpy.vstack((geom.Edges,[id      ,edgei(1),edgei(2)]))
+				geom.Edges=np.vstack((geom.Edges,[id      ,edgei(1),edgei(2)]))
 				geom.Edges[j,:]    =[edgej(0),id      ,edgej(2)]
-				geom.Edges=numpy.vstack((geom.Edges,[id      ,edgej(1),edgej(2)]))
+				geom.Edges=np.vstack((geom.Edges,[id      ,edgej(1),edgej(2)]))
 
 				#update current edge second tip
@@ -407,5 +545,5 @@
 	i=0
 	num=0
-	while (i<numpy.size(geom.Vertices,axis=0)):
+	while (i<np.size(geom.Vertices,axis=0)):
 
 		#vertex counter
@@ -425,7 +563,7 @@
 
 			#update edges
-			posedges=numpy.nonzero(geom.Edges==i)
+			posedges=np.nonzero(geom.Edges==i)
 			geom.Edges[posedges[0],:]=[]
-			posedges=numpy.nonzero(geom.Edges>i)
+			posedges=np.nonzero(geom.Edges>i)
 			geom.Edges[posedges]=geom.Edges[posedges]-1
 
Index: /issm/trunk-jpl/src/py3/mesh/meshconvert.py
===================================================================
--- /issm/trunk-jpl/src/py3/mesh/meshconvert.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mesh/meshconvert.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 from collections import OrderedDict
 from BamgConvertMesh import BamgConvertMesh 
@@ -43,8 +43,8 @@
 
 	#Fill in rest of fields:
-	md.mesh.numberofelements   = numpy.size(md.mesh.elements,axis=0)
-	md.mesh.numberofvertices   = numpy.size(md.mesh.x)
-	md.mesh.numberofedges      = numpy.size(md.mesh.edges,axis=0)
-	md.mesh.vertexonboundary   = numpy.zeros(md.mesh.numberofvertices,bool)
+	md.mesh.numberofelements   = np.size(md.mesh.elements,axis=0)
+	md.mesh.numberofvertices   = np.size(md.mesh.x)
+	md.mesh.numberofedges      = np.size(md.mesh.edges,axis=0)
+	md.mesh.vertexonboundary   = np.zeros(md.mesh.numberofvertices,bool)
 	md.mesh.vertexonboundary[md.mesh.segments[:,0:2]-1] = True
 
Index: /issm/trunk-jpl/src/py3/mesh/rifts/meshprocessoutsiderifts.py
===================================================================
--- /issm/trunk-jpl/src/py3/mesh/rifts/meshprocessoutsiderifts.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mesh/rifts/meshprocessoutsiderifts.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 from ElementsFromEdge import ElementsFromEdge
 import MatlabFuncs as m
@@ -19,5 +19,5 @@
 
 		tips=rift.tips
-		outsidetips=tips[numpy.nonzero(flags[rift.tips-1])[0]]
+		outsidetips=tips[np.nonzero(flags[rift.tips-1])[0]]
 
 		#we have found outsidetips, tips that touch the domain outline. go through them
@@ -26,10 +26,10 @@
 			#find tip in the segments, take first segment (there should be 2) that holds tip, 
 			#and node_connected_to_tip is the other node on this segment:
-			tipindex=numpy.nonzero(rift.segments[:,0]==tip)[0]
+			tipindex=np.nonzero(rift.segments[:,0]==tip)[0]
 			if tipindex:
 				tipindex=tipindex[0]
 				node_connected_to_tip=rift.segments[tipindex,1]
 			else:
-				tipindex=numpy.nonzero(rift.segments[:,1]==tip)[0]
+				tipindex=np.nonzero(rift.segments[:,1]==tip)[0]
 				tipindex=tipindex[0]
 				node_connected_to_tip=rift.segments[tipindex,1]
@@ -41,5 +41,5 @@
 			B=node_connected_to_tip
 
-			elements=numpy.empty(0,int)
+			elements=np.empty(0,int)
 
 			while flags(B):    #as long as B does not belong to the domain outline, keep looking.
@@ -48,37 +48,37 @@
 				#rule out those we already detected
 				already_detected=m.ismember(edgeelements,elements)
-				nextelement=edgeelements(numpy.nonzero(numpy.logical_not(already_detected))[0])
+				nextelement=edgeelements(np.nonzero(np.logical_not(already_detected))[0])
 				#add new detected element to the list of elements we are looking for.
-				elements=numpy.concatenate((elements,nextelement))
+				elements=np.concatenate((elements,nextelement))
 				#new B:
-				B=md.mesh.elements[nextelement-1,numpy.nonzero(numpy.logical_not(m.ismember(md.mesh.elements[nextelement-1,:],numpy.array([A,B]))))]
+				B=md.mesh.elements[nextelement-1,np.nonzero(np.logical_not(m.ismember(md.mesh.elements[nextelement-1,:],np.array([A,B]))))]
 		
 			#take the list of elements on one side of the rift that connect to the tip, 
 			#and duplicate the tip on them, so as to open the rift to the outside.
-			num=numpy.size(md.mesh.x)+1
-			md.mesh.x=numpy.concatenate((md.mesh.x,md.mesh.x[tip]))
-			md.mesh.y=numpy.concatenate((md.mesh.y,md.mesh.y[tip]))
+			num=np.size(md.mesh.x)+1
+			md.mesh.x=np.concatenate((md.mesh.x,md.mesh.x[tip]))
+			md.mesh.y=np.concatenate((md.mesh.y,md.mesh.y[tip]))
 			md.mesh.numberofvertices=num
 		
 			#replace tip in elements
 			newelements=md.mesh.elements[elements-1,:]
-			pos=numpy.nonzero(newelements==tip)
+			pos=np.nonzero(newelements==tip)
 			newelements[pos]=num
 			md.mesh.elements[elements-1,:]=newelements
-			rift.tips=numpy.concatenate((rift.tips,num))
+			rift.tips=np.concatenate((rift.tips,num))
 
 			#deal with segments
-			tipsegments=numpy.nonzero(numpy.logical_or(md.mesh.segments[:,0]==tip,md.mesh.segments[:,1]==tip))[0]
+			tipsegments=np.nonzero(np.logical_or(md.mesh.segments[:,0]==tip,md.mesh.segments[:,1]==tip))[0]
 			for segment_index in tipsegments:
-				pos=numpy.nonzero(md.mesh.segments[segment_index,0:2]!=tip)[0]
+				pos=np.nonzero(md.mesh.segments[segment_index,0:2]!=tip)[0]
 				other_node=md.mesh.segments[segment_index,pos]
 				if not isconnected(md.mesh.elements,other_node,tip):
-					pos=numpy.nonzero(md.mesh.segments[segment_index,0:2]==tip)[0]
+					pos=np.nonzero(md.mesh.segments[segment_index,0:2]==tip)[0]
 					md.mesh.segments[segment_index,pos]=num
 
 	#Fill in rest of fields:
-	md.mesh.numberofelements=numpy.size(md.mesh.elements,axis=0)
-	md.mesh.numberofvertices=numpy.size(md.mesh.x)
-	md.mesh.vertexonboundary=numpy.zeros(numpy.size(md.mesh.x),bool)
+	md.mesh.numberofelements=np.size(md.mesh.elements,axis=0)
+	md.mesh.numberofvertices=np.size(md.mesh.x)
+	md.mesh.vertexonboundary=np.zeros(np.size(md.mesh.x),bool)
 	md.mesh.vertexonboundary[md.mesh.segments[:,0:2]-1]=True
 	md.rifts.numrifts=length(md.rifts.riftstruct)
Index: /issm/trunk-jpl/src/py3/mesh/rifts/meshprocessrifts.py
===================================================================
--- /issm/trunk-jpl/src/py3/mesh/rifts/meshprocessrifts.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mesh/rifts/meshprocessrifts.py	(revision 23670)
@@ -1,4 +1,4 @@
-import numpy
-from TriMeshProcessRifts import TriMeshProcessRifts
+import numpy as np
+from ProcessRifts import ProcessRifts
 from ContourToMesh import ContourToMesh
 from meshprocessoutsiderifts import meshprocessoutsiderifts
@@ -22,5 +22,5 @@
 
 	#Call MEX file
-	[md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.segments,md.mesh.segmentmarkers,md.rifts.riftstruct]=TriMeshProcessRifts(md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.segments,md.mesh.segmentmarkers)
+	md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.segments,md.mesh.segmentmarkers,md.rifts.riftstruct=ProcessRifts(md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.segments,md.mesh.segmentmarkers)
 	md.mesh.elements=md.mesh.elements.astype(int)
 	md.mesh.x=md.mesh.x.reshape(-1)
@@ -29,20 +29,20 @@
 	md.mesh.segmentmarkers=md.mesh.segmentmarkers.astype(int)
 	if not isinstance(md.rifts.riftstruct,list) or not md.rifts.riftstruct:
-		raise RuntimeError("TriMeshProcessRifts did not find any rift")
+		raise RuntimeError("ProcessRifts did not find any rift")
 
 	#Fill in rest of fields:
 	numrifts=len(md.rifts.riftstruct)
-	md.mesh.numberofelements=numpy.size(md.mesh.elements,axis=0)
-	md.mesh.numberofvertices=numpy.size(md.mesh.x)
-	md.mesh.vertexonboundary=numpy.zeros(numpy.size(md.mesh.x),bool)
+	md.mesh.numberofelements=np.size(md.mesh.elements,axis=0)
+	md.mesh.numberofvertices=np.size(md.mesh.x)
+	md.mesh.vertexonboundary=np.zeros(np.size(md.mesh.x),bool)
 	md.mesh.vertexonboundary[md.mesh.segments[:,0:2]-1]=True
 
 	#get coordinates of rift tips
 	for rift in md.rifts.riftstruct:
-		rift['tip1coordinates']=numpy.hstack((md.mesh.x[rift['tips'][0,0].astype(int)-1].reshape(-1,1),md.mesh.y[rift['tips'][0,0].astype(int)-1].reshape(-1,1)))
-		rift['tip2coordinates']=numpy.hstack((md.mesh.x[rift['tips'][0,1].astype(int)-1].reshape(-1,1),md.mesh.y[rift['tips'][0,1].astype(int)-1].reshape(-1,1)))
+		rift['tip1coordinates']=np.hstack((md.mesh.x[rift['tips'][0,0].astype(int)-1].reshape(-1,),md.mesh.y[rift['tips'][0,0].astype(int)-1].reshape(-1,)))
+		rift['tip2coordinates']=np.hstack((md.mesh.x[rift['tips'][0,1].astype(int)-1].reshape(-1,),md.mesh.y[rift['tips'][0,1].astype(int)-1].reshape(-1,)))
 
 	#In case we have rifts that open up the domain outline, we need to open them: 
-	[flags,dum]=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,domainoutline,'node',0)
+	flags=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,domainoutline,'node',0)
 	found=0
 	for rift in md.rifts.riftstruct:
@@ -58,6 +58,6 @@
 	#get elements that are not correctly oriented in the correct direction:
 	aires=GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y)
-	pos=numpy.nonzero(aires<0)[0]
-	md.mesh.elements[pos,:]=numpy.hstack((md.mesh.elements[pos,1].reshape(-1,1),md.mesh.elements[pos,0].reshape(-1,1),md.mesh.elements[pos,2].reshape(-1,1)))
+	pos=np.nonzero(aires<0)[0]
+	md.mesh.elements[pos,:]=np.vstack((md.mesh.elements[pos,1],md.mesh.elements[pos,0],md.mesh.elements[pos,2])).T
 
 	return md
Index: /issm/trunk-jpl/src/py3/mesh/roundmesh.py
===================================================================
--- /issm/trunk-jpl/src/py3/mesh/roundmesh.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mesh/roundmesh.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 import os
 from collections import OrderedDict
@@ -20,12 +20,10 @@
 
 	#Get number of points on the circle
-	pointsonedge=numpy.floor((2.*numpy.pi*radius) / resolution)
+	pointsonedge=np.floor((2.*np.pi*radius) / resolution)+1 #+1 to close the outline
 
 	#Calculate the cartesians coordinates of the points
-	x_list=numpy.ones(pointsonedge)
-	y_list=numpy.ones(pointsonedge)
-	theta=numpy.linspace(0.,2.*numpy.pi,num=pointsonedge,endpoint=False)
-	x_list=roundsigfig(radius*x_list*numpy.cos(theta),12)
-	y_list=roundsigfig(radius*y_list*numpy.sin(theta),12)
+	theta=np.linspace(0.,2.*np.pi,pointsonedge)
+	x_list=roundsigfig(radius*np.cos(theta),12)
+	y_list=roundsigfig(radius*np.sin(theta),12)
 	A=OrderedDict()
 	A['x']=[x_list]
@@ -39,5 +37,5 @@
 
 	#move the closest node to the center
-	pos=numpy.argmin(md.mesh.x**2+md.mesh.y**2)
+	pos=np.argmin(md.mesh.x**2+md.mesh.y**2)
 	md.mesh.x[pos]=0.
 	md.mesh.y[pos]=0.
@@ -50,10 +48,10 @@
 def roundsigfig(x,n):
 
-	digits=numpy.ceil(numpy.log10(numpy.abs(x)))
+	digits=np.ceil(np.log10(np.abs(x)))
 	x=x/10.**digits
-	x=numpy.round(x,decimals=n)
+	x=np.round(x,decimals=n)
 	x=x*10.**digits
 
-	pos=numpy.nonzero(numpy.isnan(x))
+	pos=np.nonzero(np.isnan(x))
 	x[pos]=0.
 
Index: /issm/trunk-jpl/src/py3/mesh/squaremesh.py
===================================================================
--- /issm/trunk-jpl/src/py3/mesh/squaremesh.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mesh/squaremesh.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 from NodeConnectivity import NodeConnectivity
 from ElementConnectivity import ElementConnectivity 
@@ -22,7 +22,7 @@
 
 	#initialization
-	index=numpy.zeros((nel,3),int)
-	x=numpy.zeros((nx*ny))
-	y=numpy.zeros((nx*ny))
+	index=np.zeros((nel,3),int)
+	x=np.zeros((nx*ny))
+	y=np.zeros((nx*ny))
 
 	#create coordinates
@@ -43,17 +43,17 @@
 
 	#Scale  x and y
-	x=x/numpy.max(x)*Lx
-	y=y/numpy.max(y)*Ly
+	x=x/np.max(x)*Lx
+	y=y/np.max(y)*Ly
 
 	#create segments
-	segments=numpy.zeros((2*(nx-1)+2*(ny-1),3),int)
+	segments=np.zeros((2*(nx-1)+2*(ny-1),3),int)
 	#left edge:
-	segments[0:ny-1,:]=numpy.hstack((numpy.arange(2,ny+1).reshape(-1,1),numpy.arange(1,ny).reshape(-1,1),(2*numpy.arange(1,ny)-1).reshape(-1,1)))
+	segments[0:ny-1,:]=np.vstack((np.arange(2,ny+1),np.arange(1,ny),(2*np.arange(1,ny)-1))).T
 	#right edge:
-	segments[ny-1:2*(ny-1),:]=numpy.hstack((numpy.arange(ny*(nx-1)+1,nx*ny).reshape(-1,1),numpy.arange(ny*(nx-1)+2,nx*ny+1).reshape(-1,1),2*numpy.arange((ny-1)*(nx-2)+1,(nx-1)*(ny-1)+1).reshape(-1,1)))
+	segments[ny-1:2*(ny-1),:]=np.vstack((np.arange(ny*(nx-1)+1,nx*ny),np.arange(ny*(nx-1)+2,nx*ny+1),2*np.arange((ny-1)*(nx-2)+1,(nx-1)*(ny-1)+1))).T
 	#front edge:
-	segments[2*(ny-1):2*(ny-1)+(nx-1),:]=numpy.hstack((numpy.arange(2*ny,ny*nx+1,ny).reshape(-1,1),numpy.arange(ny,ny*(nx-1)+1,ny).reshape(-1,1),numpy.arange(2*(ny-1),2*(nx-1)*(ny-1)+1,2*(ny-1)).reshape(-1,1)))
+	segments[2*(ny-1):2*(ny-1)+(nx-1),:]=np.vstack((np.arange(2*ny,ny*nx+1,ny),np.arange(ny,ny*(nx-1)+1,ny),np.arange(2*(ny-1),2*(nx-1)*(ny-1)+1,2*(ny-1)))).T
 	#back edge
-	segments[2*(ny-1)+(nx-1):2*(nx-1)+2*(ny-1),:]=numpy.hstack((numpy.arange(1,(nx-2)*ny+2,ny).reshape(-1,1),numpy.arange(ny+1,ny*(nx-1)+2,ny).reshape(-1,1),numpy.arange(1,2*(nx-2)*(ny-1)+2,2*(ny-1)).reshape(-1,1)))
+	segments[2*(ny-1)+(nx-1):2*(nx-1)+2*(ny-1),:]=np.vstack((np.arange(1,(nx-2)*ny+2,ny),np.arange(ny+1,ny*(nx-1)+2,ny),np.arange(1,2*(nx-2)*(ny-1)+2,2*(ny-1)))).T
 
 	#plug coordinates and nodes
@@ -62,5 +62,5 @@
 	md.mesh.y=y
 	md.mesh.numberofvertices=nods
-	md.mesh.vertexonboundary=numpy.zeros((nods),bool)
+	md.mesh.vertexonboundary=np.zeros((nods),bool)
 	md.mesh.vertexonboundary[segments[:,0:2]-1]=True
 
@@ -71,6 +71,6 @@
 
 	#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)
+	md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices)[0]
+	md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity)[0]
 
 	return md
Index: /issm/trunk-jpl/src/py3/mesh/triangle.py
===================================================================
--- /issm/trunk-jpl/src/py3/mesh/triangle.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/mesh/triangle.py	(revision 23670)
@@ -1,7 +1,8 @@
-import numpy
+import os.path
+import numpy as np
 from mesh2d import mesh2d
-from TriMesh import TriMesh
 from NodeConnectivity import NodeConnectivity
 from ElementConnectivity import ElementConnectivity
+from Triangle_python import Triangle_python
 import MatlabFuncs as m
 
@@ -10,5 +11,5 @@
 	TRIANGLE - create model mesh using the triangle package
 
-	   This routine creates a model mesh using TriMesh and a domain outline, to within a certain resolution
+	   This routine creates a model mesh using Triangle and a domain outline, to within a certain resolution
 	   where md is a @model object, domainname is the name of an Argus domain outline file, 
 	   and resolution is a characteristic length for the mesh (same unit as the domain outline
@@ -43,7 +44,11 @@
 	area = resolution**2
 
-	#Mesh using TriMesh
+	#Check that file exist (this is a very very common mistake)
+	if not os.path.exists(domainname):
+		raise IOError("file '%s' not found" % domainname)
+
+	#Mesh using Triangle
 	md.mesh=mesh2d()
-	[md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.segments,md.mesh.segmentmarkers]=TriMesh(domainname,riftname,area)
+	md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.segments,md.mesh.segmentmarkers=Triangle_python(domainname,riftname,area)
 	md.mesh.elements=md.mesh.elements.astype(int)
 	md.mesh.segments=md.mesh.segments.astype(int)
@@ -51,12 +56,12 @@
 
 	#Fill in rest of fields:
-	md.mesh.numberofelements = numpy.size(md.mesh.elements,axis=0)
-	md.mesh.numberofvertices = numpy.size(md.mesh.x)
-	md.mesh.vertexonboundary = numpy.zeros(md.mesh.numberofvertices,bool)
+	md.mesh.numberofelements = np.size(md.mesh.elements,axis=0)
+	md.mesh.numberofvertices = np.size(md.mesh.x)
+	md.mesh.vertexonboundary = np.zeros(md.mesh.numberofvertices,bool)
 	md.mesh.vertexonboundary[md.mesh.segments[:,0:2]-1] = True
 
 	#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)
+	md.mesh.vertexconnectivity = NodeConnectivity(md.mesh.elements, md.mesh.numberofvertices)[0]
+	md.mesh.elementconnectivity = ElementConnectivity(md.mesh.elements, md.mesh.vertexconnectivity)[0]
 
 	return md
Index: /issm/trunk-jpl/src/py3/miscellaneous/MatlabFuncs.py
===================================================================
--- /issm/trunk-jpl/src/py3/miscellaneous/MatlabFuncs.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/miscellaneous/MatlabFuncs.py	(revision 23670)
@@ -49,27 +49,27 @@
 
 def ismember(a,s):
-	import numpy
+	import numpy as np
 
-	if not isinstance(s,(tuple,list,dict,numpy.ndarray)):
+	if not isinstance(s,(tuple,list,dict,np.ndarray)):
 		s=[s]
 
-	if not isinstance(a,(tuple,list,dict,numpy.ndarray)):
+	if not isinstance(a,(tuple,list,dict,np.ndarray)):
 		a=[a]
 
-	if not isinstance(a,numpy.ndarray):
+	if not isinstance(a,np.ndarray):
 		b=[item in s for item in a]
 
 	else:
-		if not isinstance(s,numpy.ndarray):
-			b=numpy.empty_like(a)
+		if not isinstance(s,np.ndarray):
+			b=np.empty_like(a)
 			for i,item in enumerate(a.flat):
 				b.flat[i]=item in s
 		else:
-			b=numpy.in1d(a.flat,s.flat).reshape(a.shape)
+			b=np.in1d(a.flat,s.flat).reshape(a.shape)
 
 	return b
 
 def det(a):
-	import numpy
+	import numpy as np
 
 	if   a.shape==(1,):
@@ -83,12 +83,12 @@
 
 def sparse(ivec,jvec,svec,m=0,n=0,nzmax=0):
-	import numpy
+	import numpy as np
 
 	if not m:
-		m=numpy.max(ivec)
+		m=np.max(ivec)
 	if not n:
-		n=numpy.max(jvec)
+		n=np.max(jvec)
 
-	a=numpy.zeros((m,n))
+	a=np.zeros((m,n))
 
 	for i,j,s in zip(ivec.reshape(-1,order='F'),jvec.reshape(-1,order='F'),svec.reshape(-1,order='F')):
@@ -98,10 +98,9 @@
 
 def heaviside(x):
-	import numpy
+	import numpy as np
 
-	y=numpy.zeros_like(x)
-	y[numpy.nonzero(x> 0.)]=1.
-	y[numpy.nonzero(x==0.)]=0.5
+	y=np.zeros_like(x)
+	y[np.nonzero(x> 0.)]=1.
+	y[np.nonzero(x==0.)]=0.5
 
 	return y
-
Index: /issm/trunk-jpl/src/py3/miscellaneous/PythonFuncs.py
===================================================================
--- /issm/trunk-jpl/src/py3/miscellaneous/PythonFuncs.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/miscellaneous/PythonFuncs.py	(revision 23670)
@@ -1,5 +1,6 @@
+import numpy as np
+
 def logical_and_n(*arg):
-	from numpy import logical_and
-
+	
 	if len(arg):
 		result=arg[0]
@@ -12,6 +13,5 @@
 
 def logical_or_n(*arg):
-	from numpy import logical_or
-
+	
 	if len(arg):
 		result=arg[0]
Index: /issm/trunk-jpl/src/py3/miscellaneous/fielddisplay.py
===================================================================
--- /issm/trunk-jpl/src/py3/miscellaneous/fielddisplay.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/miscellaneous/fielddisplay.py	(revision 23670)
@@ -1,4 +1,4 @@
 #Module import 
-import numpy
+import numpy as np
 from math import isnan
 import MatlabFuncs as m
@@ -33,5 +33,5 @@
 
 	#matrix
-	elif isinstance(field,numpy.ndarray):
+	elif isinstance(field,np.ndarray):
 		string=displayunit(offset,name,str(field.shape),comment)
 
Index: /issm/trunk-jpl/src/py3/miscellaneous/isnans.py
===================================================================
--- /issm/trunk-jpl/src/py3/miscellaneous/isnans.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/miscellaneous/isnans.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 
 def isnans(array):
@@ -13,5 +13,5 @@
 		returnvalue=0
 	else:
-		returnvalue=numpy.isnan(array)
+		returnvalue=np.isnan(array)
 
 	return returnvalue
Index: /issm/trunk-jpl/src/py3/os/issmssh.py
===================================================================
--- /issm/trunk-jpl/src/py3/os/issmssh.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/os/issmssh.py	(revision 23670)
@@ -1,3 +1,4 @@
 from socket import gethostname
+from sys import platform as _platform
 import subprocess
 import os
@@ -45,15 +46,16 @@
 	# (from http://code.google.com/p/robotframework/issues/detail?id=995)
 
-	# Make FreeBSD use blocking I/O like other platforms
-	import sys
-	import fcntl
-	from os import O_NONBLOCK
+	if _platform == "darwin":
+		# Make FreeBSD use blocking I/O like other platforms
+		import sys
+		import fcntl
+		from os import O_NONBLOCK
+		
+		fd = sys.stdin.fileno()
+		flags = fcntl.fcntl(fd, fcntl.F_GETFL)
+		fcntl.fcntl(fd, fcntl.F_SETFL, flags & ~O_NONBLOCK)
+		
+		fd = sys.stdout.fileno()
+		flags = fcntl.fcntl(fd, fcntl.F_GETFL)
+		fcntl.fcntl(fd, fcntl.F_SETFL, flags & ~O_NONBLOCK)
 
-	fd = sys.stdin.fileno()
-	flags = fcntl.fcntl(fd, fcntl.F_GETFL)
-	fcntl.fcntl(fd, fcntl.F_SETFL, flags & ~O_NONBLOCK)
-
-	fd = sys.stdout.fileno()
-	flags = fcntl.fcntl(fd, fcntl.F_GETFL)
-	fcntl.fcntl(fd, fcntl.F_SETFL, flags & ~O_NONBLOCK)
-
Index: /issm/trunk-jpl/src/py3/parameterization/contourenvelope.py
===================================================================
--- /issm/trunk-jpl/src/py3/parameterization/contourenvelope.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/parameterization/contourenvelope.py	(revision 23670)
@@ -1,4 +1,4 @@
 import os.path
-import numpy
+import numpy as np
 import copy
 from NodeConnectivity import NodeConnectivity
@@ -40,8 +40,8 @@
 	#Now, build the connectivity tables for this mesh.
 	#Computing connectivity
-	if numpy.size(md.mesh.vertexconnectivity,axis=0)!=md.mesh.numberofvertices and numpy.size(md.mesh.vertexconnectivity,axis=0)!=md.mesh.numberofvertices2d:
-		[md.mesh.vertexconnectivity]=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices)
-	if numpy.size(md.mesh.elementconnectivity,axis=0)!=md.mesh.numberofelements and numpy.size(md.mesh.elementconnectivity,axis=0)!=md.mesh.numberofelements2d:
-		[md.mesh.elementconnectivity]=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity)
+	if np.size(md.mesh.vertexconnectivity,axis=0)!=md.mesh.numberofvertices and np.size(md.mesh.vertexconnectivity,axis=0)!=md.mesh.numberofvertices2d:
+		md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices)[0]
+	if np.size(md.mesh.elementconnectivity,axis=0)!=md.mesh.numberofelements and np.size(md.mesh.elementconnectivity,axis=0)!=md.mesh.numberofelements2d:
+		md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity)[0]
 
 	#get nodes inside profile
@@ -65,22 +65,22 @@
 			#get flag list of elements and nodes inside the contour
 			nodein=ContourToMesh(elements,x,y,file,'node',1)
-			elemin=(numpy.sum(nodein(elements),axis=1)==numpy.size(elements,axis=1))
+			elemin=(np.sum(nodein(elements),axis=1)==np.size(elements,axis=1))
 			#modify element connectivity
-			elemout=numpy.nonzero(numpy.logical_not(elemin))[0]
+			elemout=np.nonzero(np.logical_not(elemin))[0]
 			elementconnectivity[elemout,:]=0
-			elementconnectivity[numpy.nonzero(m.ismember(elementconnectivity,elemout+1))]=0
+			elementconnectivity[np.nonzero(m.ismember(elementconnectivity,elemout+1))]=0
 		else:
 			#get flag list of elements and nodes inside the contour
-			nodein=numpy.zeros(numberofvertices)
-			elemin=numpy.zeros(numberofelements)
+			nodein=np.zeros(numberofvertices)
+			elemin=np.zeros(numberofelements)
 
-			pos=numpy.nonzero(flags)
+			pos=np.nonzero(flags)
 			elemin[pos]=1
 			nodein[elements[pos,:]-1]=1
 
 			#modify element connectivity
-			elemout=numpy.nonzero(numpy.logical_not(elemin))[0]
+			elemout=np.nonzero(np.logical_not(elemin))[0]
 			elementconnectivity[elemout,:]=0
-			elementconnectivity[numpy.nonzero(m.ismember(elementconnectivity,elemout+1))]=0
+			elementconnectivity[np.nonzero(m.ismember(elementconnectivity,elemout+1))]=0
 
 	#Find element on boundary
@@ -88,23 +88,23 @@
 	flag=copy.deepcopy(elementconnectivity)
 	if len(args)==1:
-		flag[numpy.nonzero(flag)]=elemin[flag[numpy.nonzero(flag)]]
-	elementonboundary=numpy.logical_and(numpy.prod(flag,axis=1)==0,numpy.sum(flag,axis=1)>0)
+		flag[np.nonzero(flag)]=elemin[flag[np.nonzero(flag)]]
+	elementonboundary=np.logical_and(np.prod(flag,axis=1)==0,np.sum(flag,axis=1)>0)
 
 	#Find segments on boundary
-	pos=numpy.nonzero(elementonboundary)[0]
-	num_segments=numpy.size(pos)
-	segments=numpy.zeros((num_segments*3,3),int)
+	pos=np.nonzero(elementonboundary)[0]
+	num_segments=np.size(pos)
+	segments=np.zeros((num_segments*3,3),int)
 	count=0
 
 	for el1 in pos:
-		els2=elementconnectivity[el1,numpy.nonzero(elementconnectivity[el1,:])[0]]-1
-		if numpy.size(els2)>1:
-			flag=numpy.intersect1d(numpy.intersect1d(elements[els2[0],:],elements[els2[1],:]),elements[el1,:])
+		els2=elementconnectivity[el1,np.nonzero(elementconnectivity[el1,:])[0]]-1
+		if np.size(els2)>1:
+			flag=np.intersect1d(np.intersect1d(elements[els2[0],:],elements[els2[1],:]),elements[el1,:])
 			nods1=elements[el1,:]
-			nods1=numpy.delete(nods1,numpy.nonzero(nods1==flag))
+			nods1=np.delete(nods1,np.nonzero(nods1==flag))
 			segments[count,:]=[nods1[0],nods1[1],el1+1]
 
-			ord1=numpy.nonzero(nods1[0]==elements[el1,:])[0][0]
-			ord2=numpy.nonzero(nods1[1]==elements[el1,:])[0][0]
+			ord1=np.nonzero(nods1[0]==elements[el1,:])[0][0]
+			ord2=np.nonzero(nods1[1]==elements[el1,:])[0][0]
 
 			#swap segment nodes if necessary
@@ -113,20 +113,20 @@
 				segments[count,0]=segments[count,1]
 				segments[count,1]=temp
-			segments[count,0:2]=numpy.flipud(segments[count,0:2])
+			segments[count,0:2]=np.flipud(segments[count,0:2])
 			count+=1
 		else:
 			nods1=elements[el1,:]
-			flag=numpy.setdiff1d(nods1,elements[els2,:])
+			flag=np.setdiff1d(nods1,elements[els2,:])
 			for j in range(0,3):
-				nods=numpy.delete(nods1,j)
-				if numpy.any(m.ismember(flag,nods)):
+				nods=np.delete(nods1,j)
+				if np.any(m.ismember(flag,nods)):
 					segments[count,:]=[nods[0],nods[1],el1+1]
-					ord1=numpy.nonzero(nods[0]==elements[el1,:])[0][0]
-					ord2=numpy.nonzero(nods[1]==elements[el1,:])[0][0]
+					ord1=np.nonzero(nods[0]==elements[el1,:])[0][0]
+					ord2=np.nonzero(nods[1]==elements[el1,:])[0][0]
 					if ( (ord1==0 and ord2==1) or (ord1==1 and ord2==2) or (ord1==2 and ord2==0) ):
 						temp=segments[count,0]
 						segments[count,0]=segments[count,1]
 						segments[count,1]=temp
-					segments[count,0:2]=numpy.flipud(segments[count,0:2])
+					segments[count,0:2]=np.flipud(segments[count,0:2])
 					count+=1
 	segments=segments[0:count,:]
Index: /issm/trunk-jpl/src/py3/parameterization/setflowequation.py
===================================================================
--- /issm/trunk-jpl/src/py3/parameterization/setflowequation.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/parameterization/setflowequation.py	(revision 23670)
@@ -1,10 +1,8 @@
-import numpy
+import numpy as np
 from model import model
 from pairoptions import pairoptions
-import MatlabFuncs as m
-import PythonFuncs as p
 from FlagElements import FlagElements
 
-def setflowequation(md,**kwargs):
+def setflowequation(md,*args):
 	"""
 	SETFLOWEQUATION - associate a solution type to each element
@@ -28,15 +26,14 @@
 
 	#some checks on list of arguments
-	if not isinstance(md,model) or not len(kwargs):
+	if not isinstance(md,model) or not len(args):
 		raise TypeError("setflowequation error message")
 
 	#process options
-	options=pairoptions(**kwargs)
-	print(options)
-#	options=deleteduplicates(options,1);
+	options=pairoptions(*args)
+	#	options=deleteduplicates(options,1);
 
 	#Find_out what kind of coupling to use
 	coupling_method=options.getfieldvalue('coupling','tiling')
-	if coupling_method is not 'tiling' or not 'penalties':
+	if not coupling_method in ['tiling','penalties']:
 		raise TypeError("coupling type can only be: tiling or penalties")
 
@@ -48,13 +45,11 @@
 	FSflag   = FlagElements(md,options.getfieldvalue('FS',''))
 	filltype     = options.getfieldvalue('fill','none')
-
 	#Flag the elements that have not been flagged as filltype
-	if filltype is 'SIA':
-		SIAflag[numpy.nonzero(numpy.logical_not(p.logical_or_n(SSAflag,HOflag)))]=True
-	elif filltype is 'SSA':
-		SSAflag[numpy.nonzero(numpy.logical_not(p.logical_or_n(SIAflag,HOflag,FSflag)))]=True
-	elif filltype is 'HO':
-		HOflag[numpy.nonzero(numpy.logical_not(p.logical_or_n(SIAflag,SSAflag,FSflag)))]=True
-
+	if 'SIA' in filltype:
+		SIAflag= ~SSAflag & ~HOflag
+	elif 'SSA' in filltype:
+		SSAflag=~SIAflag & ~HOflag & ~FSflag
+	elif 'HO' in filltype:
+		HOflag=~SIAflag & ~SSAflag & ~FSflag
 	#check that each element has at least one flag
 	if not any(SIAflag+SSAflag+L1L2flag+HOflag+FSflag):
@@ -64,7 +59,16 @@
 	if any(SIAflag+SSAflag+L1L2flag+HOflag+FSflag>1):
 		print("setflowequation warning message: some elements have several types, higher order type is used for them")
-		SIAflag[numpy.nonzero(numpy.logical_and(SIAflag,SSAflag))]=False
-		SIAflag[numpy.nonzero(numpy.logical_and(SIAflag,HOflag))]=False
-		SSAflag[numpy.nonzero(numpy.logical_and(SSAflag,HOflag))]=False
+		SIAflag[np.where(np.logical_and(SIAflag,SSAflag))]=False
+		SIAflag[np.where(np.logical_and(SIAflag,HOflag))]=False
+		SSAflag[np.where(np.logical_and(SSAflag,HOflag))]=False
+
+		#check that L1L2 is not coupled to any other model for now
+		if any(L1L2flag) and any(SIAflag+SSAflag+HOflag+FSflag):
+			raise TypeError('L1L2 cannot be coupled to any other model')
+
+		#Check that no HO or FS for 2d mesh
+		if domaintype(md.mesh)=='2Dhorizontal':
+			if any(FSflag+HOflag):
+				raise TypeError('FS and HO elements not allowed in 2d mesh, extrude it first')
 
 	#FS can only be used alone for now:
@@ -73,81 +77,76 @@
 
 	#Initialize node fields
-	nodeonSIA=numpy.zeros(md.mesh.numberofvertices,bool)
-	nodeonSIA[md.mesh.elements[numpy.nonzero(SIAflag),:]-1]=True
-	nodeonSSA=numpy.zeros(md.mesh.numberofvertices,bool)
-	nodeonSSA[md.mesh.elements[numpy.nonzero(SSAflag),:]-1]=True
-	nodeonL1L2=numpy.zeros(md.mesh.numberofvertices,bool)
-	nodeonL1L2[md.mesh.elements[numpy.nonzero(L1L2flag),:]-1]=True
-	nodeonHO=numpy.zeros(md.mesh.numberofvertices,bool)
-	nodeonHO[md.mesh.elements[numpy.nonzero(HOflag),:]-1]=True
-	nodeonFS=numpy.zeros(md.mesh.numberofvertices,bool)
-	noneflag=numpy.zeros(md.mesh.numberofelements,bool)
+	nodeonSIA=np.zeros(md.mesh.numberofvertices,bool)
+	nodeonSIA[md.mesh.elements[np.where(SIAflag),:]-1]=True
+	nodeonSSA=np.zeros(md.mesh.numberofvertices,bool)
+	nodeonSSA[md.mesh.elements[np.where(SSAflag),:]-1]=True
+	nodeonL1L2=np.zeros(md.mesh.numberofvertices,bool)
+	nodeonL1L2[md.mesh.elements[np.where(L1L2flag),:]-1]=True
+	nodeonHO=np.zeros(md.mesh.numberofvertices,bool)
+	nodeonHO[md.mesh.elements[np.where(HOflag),:]-1]=True
+	nodeonFS=np.zeros(md.mesh.numberofvertices,bool)
+	noneflag=np.zeros(md.mesh.numberofelements,bool)
 
 	#First modify FSflag to get rid of elements contrained everywhere (spc + border with HO or SSA)
 	if any(FSflag):
-#		fullspcnodes=double((~isnan(md.stressbalance.spcvx)+~isnan(md.stressbalance.spcvy)+~isnan(md.stressbalance.spcvz))==3 | (nodeonHO & nodeonFS));         %find all the nodes on the boundary of the domain without icefront
-		fullspcnodes=numpy.logical_or(numpy.logical_not(numpy.isnan(md.stressbalance.spcvx)).astype(int)+ \
-		                              numpy.logical_not(numpy.isnan(md.stressbalance.spcvy)).astype(int)+ \
-		                              numpy.logical_not(numpy.isnan(md.stressbalance.spcvz)).astype(int)==3, \
-		                              numpy.logical_and(nodeonHO,nodeonFS)).astype(int)    #find all the nodes on the boundary of the domain without icefront
-#		fullspcelems=double(sum(fullspcnodes(md.mesh.elements),2)==6);         %find all the nodes on the boundary of the domain without icefront
-		fullspcelems=(numpy.sum(fullspcnodes[md.mesh.elements-1],axis=1)==6).astype(int)    #find all the nodes on the boundary of the domain without icefront
-		FSflag[numpy.nonzero(fullspcelems.reshape(-1))]=False
-		nodeonFS[md.mesh.elements[numpy.nonzero(FSflag),:]-1]=True
+		fullspcnodes=np.logical_or(~np.isnan(md.stressbalance.spcvx)+~np.isnan(md.stressbalance.spcvy)+~np.isnan(md.stressbalance.spcvz),np.logical_and(nodeonHO,nodeonFS))    #find all the nodes on the boundary of the domain without icefront
+		fullspcelems=np.sum(fullspcnodes[md.mesh.elements-1],axis=1)==6    #find all the nodes on the boundary of the domain without icefront
+		FSflag[np.where(fullspcelems.reshape(-1))]=False
+		nodeonFS[md.mesh.elements[np.where(FSflag),:]-1]=True
 
 	#Then complete with NoneApproximation or the other model used if there is no FS
 	if any(FSflag): 
 		if   any(HOflag):    #fill with HO
-			HOflag[numpy.logical_not(FSflag)]=True
-			nodeonHO[md.mesh.elements[numpy.nonzero(HOflag),:]-1]=True
+			HOflag[~FSflag]=True
+			nodeonHO[md.mesh.elements[np.where(HOflag),:]-1]=True
 		elif any(SSAflag):    #fill with SSA
-			SSAflag[numpy.logical_not(FSflag)]=True
-			nodeonSSA[md.mesh.elements[numpy.nonzero(SSAflag),:]-1]=True
+			SSAflag[~FSflag]=True
+			nodeonSSA[md.mesh.elements[np.where(SSAflag),:]-1]=True
 		else:    #fill with none 
-			noneflag[numpy.nonzero(numpy.logical_not(FSflag))]=True
+			noneflag[np.where(~FSflag)]=True
 
 	#Now take care of the coupling between SSA and HO
-	md.stressbalance.vertex_pairing=numpy.array([])
-	nodeonSSAHO=numpy.zeros(md.mesh.numberofvertices,bool)
-	nodeonHOFS=numpy.zeros(md.mesh.numberofvertices,bool)
-	nodeonSSAFS=numpy.zeros(md.mesh.numberofvertices,bool)
-	SSAHOflag=numpy.zeros(md.mesh.numberofelements,bool)
-	SSAFSflag=numpy.zeros(md.mesh.numberofelements,bool)
-	HOFSflag=numpy.zeros(md.mesh.numberofelements,bool)
-	if coupling_method is 'penalties':
+	md.stressbalance.vertex_pairing=np.array([])
+	nodeonSSAHO=np.zeros(md.mesh.numberofvertices,bool)
+	nodeonHOFS=np.zeros(md.mesh.numberofvertices,bool)
+	nodeonSSAFS=np.zeros(md.mesh.numberofvertices,bool)
+	SSAHOflag=np.zeros(md.mesh.numberofelements,bool)
+	SSAFSflag=np.zeros(md.mesh.numberofelements,bool)
+	HOFSflag=np.zeros(md.mesh.numberofelements,bool)
+	if coupling_method=='penalties':
 		#Create the border nodes between HO and SSA and extrude them
 		numnodes2d=md.mesh.numberofvertices2d
 		numlayers=md.mesh.numberoflayers
-		bordernodes2d=numpy.nonzero(numpy.logical_and(nodeonHO[0:numnodes2d],nodeonSSA[0:numnodes2d]))[0]+1    #Nodes connected to two different types of elements
+		bordernodes2d=np.where(np.logical_and(nodeonHO[0:numnodes2d],nodeonSSA[0:numnodes2d]))[0]+1    #Nodes connected to two different types of elements
 
 		#initialize and fill in penalties structure
-		if numpy.all(numpy.logical_not(numpy.isnan(bordernodes2d))):
-			penalties=numpy.zeros((0,2))
+		if np.all(np.logical_not(np.isnan(bordernodes2d))):
+			penalties=np.zeros((0,2))
 			for	i in range(1,numlayers):
-				penalties=numpy.vstack((penalties,numpy.hstack((bordernodes2d.reshape(-1,1),bordernodes2d.reshape(-1,1)+md.mesh.numberofvertices2d*(i)))))
+				penalties=np.vstack((penalties,np.vstack((bordernodes2d,bordernodes2d+md.mesh.numberofvertices2d*(i))).T))
 			md.stressbalance.vertex_pairing=penalties
 
-	elif coupling_method is 'tiling':
-		if   any(SSAflag) and any(HOflag):    #coupling SSA HO
+	elif coupling_method=='tiling':
+		if any(SSAflag) and any(HOflag):    #coupling SSA HO
 			#Find node at the border
-			nodeonSSAHO[numpy.nonzero(numpy.logical_and(nodeonSSA,nodeonHO))]=True
+			nodeonSSAHO[np.where(np.logical_and(nodeonSSA,nodeonHO))]=True
 			#SSA elements in contact with this layer become SSAHO elements
-			matrixelements=m.ismember(md.mesh.elements-1,numpy.nonzero(nodeonSSAHO)[0])
-			commonelements=numpy.sum(matrixelements,axis=1)!=0
-			commonelements[numpy.nonzero(HOflag)]=False    #only one layer: the elements previously in SSA
-			SSAflag[numpy.nonzero(commonelements)]=False    #these elements are now SSAHOelements
-			SSAHOflag[numpy.nonzero(commonelements)]=True
+			matrixelements=nodeonSSAHO[md.mesh.elements-1]
+			commonelements=np.sum(matrixelements,axis=1)!=0
+			commonelements[np.where(HOflag)]=False    #only one layer: the elements previously in SSA
+			SSAflag[np.where(commonelements)]=False    #these elements are now SSAHOelements
+			SSAHOflag[np.where(commonelements)]=True
 			nodeonSSA[:]=False
-			nodeonSSA[md.mesh.elements[numpy.nonzero(SSAflag),:]-1]=True
+			nodeonSSA[md.mesh.elements[np.where(SSAflag),:]-1]=True
 
 			#rule out elements that don't touch the 2 boundaries
-			pos=numpy.nonzero(SSAHOflag)[0]
-			elist=numpy.zeros(numpy.size(pos),dtype=int)
-			elist = elist + numpy.sum(nodeonSSA[md.mesh.elements[pos,:]-1],axis=1).astype(bool)
-			elist = elist - numpy.sum(nodeonHO[md.mesh.elements[pos,:]-1]  ,axis=1).astype(bool)
-			pos1=numpy.nonzero(elist==1)[0]
+			pos=np.where(SSAHOflag)[0]
+			elist=np.zeros(np.size(pos),dtype=int)
+			elist = elist + np.sum(nodeonSSA[md.mesh.elements[pos,:]-1],axis=1).astype(bool)
+			elist = elist - np.sum(nodeonHO[md.mesh.elements[pos,:]-1]  ,axis=1).astype(bool)
+			pos1=np.where(elist==1)[0]
 			SSAflag[pos[pos1]]=True
 			SSAHOflag[pos[pos1]]=False
-			pos2=numpy.nonzero(elist==-1)[0]
+			pos2=np.where(elist==-1)[0]
 			HOflag[pos[pos2]]=True
 			SSAHOflag[pos[pos2]]=False
@@ -155,31 +154,31 @@
 			#Recompute nodes associated to these elements
 			nodeonSSA[:]=False
-			nodeonSSA[md.mesh.elements[numpy.nonzero(SSAflag),:]-1]=True
+			nodeonSSA[md.mesh.elements[np.where(SSAflag),:]-1]=True
 			nodeonHO[:]=False
-			nodeonHO[md.mesh.elements[numpy.nonzero(HOflag),:]-1]=True
+			nodeonHO[md.mesh.elements[np.where(HOflag),:]-1]=True
 			nodeonSSAHO[:]=False
-			nodeonSSAHO[md.mesh.elements[numpy.nonzero(SSAHOflag),:]-1]=True
+			nodeonSSAHO[md.mesh.elements[np.where(SSAHOflag),:]-1]=True
 
 		elif any(HOflag) and any(FSflag):    #coupling HO FS
 			#Find node at the border
-			nodeonHOFS[numpy.nonzero(numpy.logical_and(nodeonHO,nodeonFS))]=True
+			nodeonHOFS[np.where(np.logical_and(nodeonHO,nodeonFS))]=True
 			#FS elements in contact with this layer become HOFS elements
-			matrixelements=m.ismember(md.mesh.elements-1,numpy.nonzero(nodeonHOFS)[0])
-			commonelements=numpy.sum(matrixelements,axis=1)!=0
-			commonelements[numpy.nonzero(HOflag)]=False    #only one layer: the elements previously in SSA
-			FSflag[numpy.nonzero(commonelements)]=False    #these elements are now SSAHOelements
-			HOFSflag[numpy.nonzero(commonelements)]=True
-			nodeonFS=numpy.zeros(md.mesh.numberofvertices,bool)
-			nodeonFS[md.mesh.elements[numpy.nonzero(FSflag),:]-1]=True
+			matrixelements=nodeonHOFS[md.mesh.elements-1]
+			commonelements=np.sum(matrixelements,axis=1)!=0
+			commonelements[np.where(HOflag)]=False    #only one layer: the elements previously in SSA
+			FSflag[np.where(commonelements)]=False    #these elements are now SSAHOelements
+			HOFSflag[np.where(commonelements)]=True
+			nodeonFS=np.zeros(md.mesh.numberofvertices,bool)
+			nodeonFS[md.mesh.elements[np.where(FSflag),:]-1]=True
 
 			#rule out elements that don't touch the 2 boundaries
-			pos=numpy.nonzero(HOFSflag)[0]
-			elist=numpy.zeros(numpy.size(pos),dtype=int)
-			elist = elist + numpy.sum(nodeonFS[md.mesh.elements[pos,:]-1],axis=1).astype(bool)
-			elist = elist - numpy.sum(nodeonHO[md.mesh.elements[pos,:]-1],axis=1).astype(bool)
-			pos1=numpy.nonzero(elist==1)[0]
+			pos=np.where(HOFSflag)[0]
+			elist=np.zeros(np.size(pos),dtype=int)
+			elist = elist + np.sum(nodeonFS[md.mesh.elements[pos,:]-1],axis=1).astype(bool)
+			elist = elist - np.sum(nodeonHO[md.mesh.elements[pos,:]-1],axis=1).astype(bool)
+			pos1=np.where(elist==1)[0]
 			FSflag[pos[pos1]]=True
 			HOFSflag[pos[pos1]]=False
-			pos2=numpy.nonzero(elist==-1)[0]
+			pos2=np.where(elist==-1)[0]
 			HOflag[pos[pos2]]=True
 			HOFSflag[pos[pos2]]=False
@@ -187,31 +186,30 @@
 			#Recompute nodes associated to these elements
 			nodeonFS[:]=False
-			nodeonFS[md.mesh.elements[numpy.nonzero(FSflag),:]-1]=True
+			nodeonFS[md.mesh.elements[np.where(FSflag),:]-1]=True
 			nodeonHO[:]=False
-			nodeonHO[md.mesh.elements[numpy.nonzero(HOflag),:]-1]=True
+			nodeonHO[md.mesh.elements[np.where(HOflag),:]-1]=True
 			nodeonHOFS[:]=False
-			nodeonHOFS[md.mesh.elements[numpy.nonzero(HOFSflag),:]-1]=True
-
+			nodeonHOFS[md.mesh.elements[np.where(HOFSflag),:]-1]=True
 		elif any(FSflag) and any(SSAflag):
 			#Find node at the border
-			nodeonSSAFS[numpy.nonzero(numpy.logical_and(nodeonSSA,nodeonFS))]=True
+			nodeonSSAFS[np.where(np.logical_and(nodeonSSA,nodeonFS))]=True
 			#FS elements in contact with this layer become SSAFS elements
-			matrixelements=m.ismember(md.mesh.elements-1,numpy.nonzero(nodeonSSAFS)[0])
-			commonelements=numpy.sum(matrixelements,axis=1)!=0
-			commonelements[numpy.nonzero(SSAflag)]=False    #only one layer: the elements previously in SSA
-			FSflag[numpy.nonzero(commonelements)]=False    #these elements are now SSASSAelements
-			SSAFSflag[numpy.nonzero(commonelements)]=True
-			nodeonFS=numpy.zeros(md.mesh.numberofvertices,bool)
-			nodeonFS[md.mesh.elements[numpy.nonzero(FSflag),:]-1]=True
+			matrixelements=nodeonSSAFS[md.mesh.elements-1]
+			commonelements=np.sum(matrixelements,axis=1)!=0
+			commonelements[np.where(SSAflag)]=False    #only one layer: the elements previously in SSA
+			FSflag[np.where(commonelements)]=False    #these elements are now SSASSAelements
+			SSAFSflag[np.where(commonelements)]=True
+			nodeonFS=np.zeros(md.mesh.numberofvertices,bool)
+			nodeonFS[md.mesh.elements[np.where(FSflag),:]-1]=True
 
 			#rule out elements that don't touch the 2 boundaries
-			pos=numpy.nonzero(SSAFSflag)[0]
-			elist=numpy.zeros(numpy.size(pos),dtype=int)
-			elist = elist + numpy.sum(nodeonSSA[md.mesh.elements[pos,:]-1],axis=1).astype(bool)
-			elist = elist - numpy.sum(nodeonFS[md.mesh.elements[pos,:]-1]  ,axis=1).astype(bool)
-			pos1=numpy.nonzero(elist==1)[0]
+			pos=np.where(SSAFSflag)[0]
+			elist=np.zeros(np.size(pos),dtype=int)
+			elist = elist + np.sum(nodeonSSA[md.mesh.elements[pos,:]-1],axis=1).astype(bool)
+			elist = elist - np.sum(nodeonFS[md.mesh.elements[pos,:]-1],axis=1).astype(bool)
+			pos1=np.where(elist==1)[0]
 			SSAflag[pos[pos1]]=True
 			SSAFSflag[pos[pos1]]=False
-			pos2=numpy.nonzero(elist==-1)[0]
+			pos2=np.where(elist==-1)[0]
 			FSflag[pos[pos2]]=True
 			SSAFSflag[pos[pos2]]=False
@@ -219,9 +217,9 @@
 			#Recompute nodes associated to these elements
 			nodeonSSA[:]=False
-			nodeonSSA[md.mesh.elements[numpy.nonzero(SSAflag),:]-1]=True
+			nodeonSSA[md.mesh.elements[np.where(SSAflag),:]-1]=True
 			nodeonFS[:]=False
-			nodeonFS[md.mesh.elements[numpy.nonzero(FSflag),:]-1]=True
+			nodeonFS[md.mesh.elements[np.where(FSflag),:]-1]=True
 			nodeonSSAFS[:]=False
-			nodeonSSAFS[md.mesh.elements[numpy.nonzero(SSAFSflag),:]-1]=True
+			nodeonSSAFS[md.mesh.elements[np.where(SSAFSflag),:]-1]=True
 
 		elif any(FSflag) and any(SIAflag):
@@ -229,14 +227,14 @@
 
 	#Create SSAHOApproximation where needed
-	md.flowequation.element_equation=numpy.zeros(md.mesh.numberofelements,int)
-	md.flowequation.element_equation[numpy.nonzero(noneflag)]=0
-	md.flowequation.element_equation[numpy.nonzero(SIAflag)]=1
-	md.flowequation.element_equation[numpy.nonzero(SSAflag)]=2
-	md.flowequation.element_equation[numpy.nonzero(L1L2flag)]=3
-	md.flowequation.element_equation[numpy.nonzero(HOflag)]=4
-	md.flowequation.element_equation[numpy.nonzero(FSflag)]=5
-	md.flowequation.element_equation[numpy.nonzero(SSAHOflag)]=6
-	md.flowequation.element_equation[numpy.nonzero(SSAFSflag)]=7
-	md.flowequation.element_equation[numpy.nonzero(HOFSflag)]=8
+	md.flowequation.element_equation=np.zeros(md.mesh.numberofelements,int)
+	md.flowequation.element_equation[np.where(noneflag)]=0
+	md.flowequation.element_equation[np.where(SIAflag)]=1
+	md.flowequation.element_equation[np.where(SSAflag)]=2
+	md.flowequation.element_equation[np.where(L1L2flag)]=3
+	md.flowequation.element_equation[np.where(HOflag)]=4
+	md.flowequation.element_equation[np.where(FSflag)]=5
+	md.flowequation.element_equation[np.where(SSAHOflag)]=6
+	md.flowequation.element_equation[np.where(SSAFSflag)]=7
+	md.flowequation.element_equation[np.where(HOFSflag)]=8
 
 	#border
@@ -246,25 +244,25 @@
 
 	#Create vertices_type
-	md.flowequation.vertex_equation=numpy.zeros(md.mesh.numberofvertices,int)
-	pos=numpy.nonzero(nodeonSSA)
+	md.flowequation.vertex_equation=np.zeros(md.mesh.numberofvertices,int)
+	pos=np.where(nodeonSSA)
 	md.flowequation.vertex_equation[pos]=2
-	pos=numpy.nonzero(nodeonL1L2)
+	pos=np.where(nodeonL1L2)
 	md.flowequation.vertex_equation[pos]=3
-	pos=numpy.nonzero(nodeonHO)
+	pos=np.where(nodeonHO)
 	md.flowequation.vertex_equation[pos]=4
-	pos=numpy.nonzero(nodeonFS)
+	pos=np.where(nodeonFS)
 	md.flowequation.vertex_equation[pos]=5
 	#DO SIA LAST! Otherwise spcs might not be set up correctly (SIA should have priority)
-	pos=numpy.nonzero(nodeonSIA)
+	pos=np.where(nodeonSIA)
 	md.flowequation.vertex_equation[pos]=1
 	if any(FSflag):
-		pos=numpy.nonzero(numpy.logical_not(nodeonFS))
+		pos=np.where(np.logical_not(nodeonFS))
 		if not (any(HOflag) or any(SSAflag)):
 			md.flowequation.vertex_equation[pos]=0
-	pos=numpy.nonzero(nodeonSSAHO)
+	pos=np.where(nodeonSSAHO)
 	md.flowequation.vertex_equation[pos]=6
-	pos=numpy.nonzero(nodeonHOFS)
+	pos=np.where(nodeonHOFS)
 	md.flowequation.vertex_equation[pos]=7
-	pos=numpy.nonzero(nodeonSSAFS)
+	pos=np.where(nodeonSSAFS)
 	md.flowequation.vertex_equation[pos]=8
 
Index: /issm/trunk-jpl/src/py3/parameterization/sethydrostaticmask.py
===================================================================
--- /issm/trunk-jpl/src/py3/parameterization/sethydrostaticmask.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/parameterization/sethydrostaticmask.py	(revision 23670)
@@ -1,6 +1,7 @@
-import numpy
+import numpy as np
 import os
 from model import model
 from FlagElements import FlagElements
+import pairoptions
 from ContourToMesh import ContourToMesh
 
@@ -19,5 +20,5 @@
    """
 
-	if numpy.size(md.geometry.bed,axis=0)!=md.mesh.numberofvertices or numpy.size(md.geometry.base,axis=0)!=md.mesh.numberofvertices or numpy.size(md.geometry.thickness,axis=0)!=md.mesh.numberofvertices:
+	if np.size(md.geometry.bed,axis=0)!=md.mesh.numberofvertices or np.size(md.geometry.base,axis=0)!=md.mesh.numberofvertices or np.size(md.geometry.thickness,axis=0)!=md.mesh.numberofvertices:
 		raise IOError("hydrostaticmask error message: fields in md.geometry do not have the right size.")
 
@@ -26,8 +27,8 @@
 
    #Check consistency of geometry
-	if any(md.geometry.base[numpy.nonzero(md.mask.groundedice_levelset>0.)]!=md.geometry.bed[numpy.nonzero(md.mask.groundedice_levelset>0.)]):
+	if any(md.geometry.base[np.nonzero(md.mask.groundedice_levelset>0.)]!=md.geometry.bed[np.nonzero(md.mask.groundedice_levelset>0.)]):
 	   print "WARNING: md.geometry.bed and md.geometry.base not equal on grounded ice"
 
-	if any(md.geometry.base[numpy.nonzero(md.mask.groundedice_levelset<=0.)]<md.geometry.bed[numpy.nonzero(md.mask.groundedice_levelset<=0.)]):
+	if any(md.geometry.base[np.nonzero(md.mask.groundedice_levelset<=0.)]<md.geometry.bed[np.nonzero(md.mask.groundedice_levelset<=0.)]):
 		print "WARNING: md.geometry.base < md.geometry.bed on floating ice"
 
Index: /issm/trunk-jpl/src/py3/parameterization/setmask.py
===================================================================
--- /issm/trunk-jpl/src/py3/parameterization/setmask.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/parameterization/setmask.py	(revision 23670)
@@ -1,10 +1,10 @@
-import numpy
+import numpy as np
 import os
 from model import model
 from FlagElements import FlagElements
-from pairoptions import pairoptions
+import pairoptions
 from ContourToMesh import ContourToMesh
 
-def setmask(md, floatingicename, groundedicename, **kwargs):
+def setmask(md, floatingicename, groundedicename, *args):
 	"""
 	SETMASK - establish boundaries between grounded and floating ice.
@@ -26,6 +26,9 @@
 		raise TypeError("setmask error message")
 
+	if len(args)%2:
+		raise TypeError("odd number of arguments provided in setmask")
+
 	#process options
-	options=pairoptions(**kwargs)
+	options=pairoptions.pairoptions(*args)
 
 	#Get assigned fields
@@ -41,28 +44,28 @@
 	#arrays come from domain outlines that can intersect one another: 
 
-	elementonfloatingice = numpy.logical_and(elementonfloatingice,numpy.logical_not(elementongroundedice))
-	elementongroundedice = numpy.logical_not(elementonfloatingice)
+	elementonfloatingice = np.logical_and(elementonfloatingice,np.logical_not(elementongroundedice))
+	elementongroundedice = np.logical_not(elementonfloatingice)
 
 	#the order here is important. we choose vertexongroundedice as default on the grounding line.
-	vertexonfloatingice = numpy.zeros(md.mesh.numberofvertices,'bool')
-	vertexongroundedice = numpy.zeros(md.mesh.numberofvertices,'bool')
-	vertexongroundedice[md.mesh.elements[numpy.nonzero(elementongroundedice),:]-1]=True
-	vertexonfloatingice[numpy.nonzero(numpy.logical_not(vertexongroundedice))]=True
+	vertexonfloatingice = np.zeros(md.mesh.numberofvertices,'bool')
+	vertexongroundedice = np.zeros(md.mesh.numberofvertices,'bool')
+	vertexongroundedice[md.mesh.elements[np.nonzero(elementongroundedice),:]-1]=True
+	vertexonfloatingice[np.nonzero(np.logical_not(vertexongroundedice))]=True
 	#}}}
 
 	#level sets
-	md.mask.groundedice_levelset = -1.*numpy.ones(md.mesh.numberofvertices)
-	md.mask.groundedice_levelset[md.mesh.elements[numpy.nonzero(elementongroundedice),:]-1]=1.
+	md.mask.groundedice_levelset = -1.*np.ones(md.mesh.numberofvertices)
+	md.mask.groundedice_levelset[md.mesh.elements[np.nonzero(elementongroundedice),:]-1]=1.
 
-	if(len(kwargs)):
-		md.mask.ice_levelset = 1.*numpy.ones(md.mesh.numberofvertices)
+	if(len(args)):
+		md.mask.ice_levelset = 1.*np.ones(md.mesh.numberofvertices)
 		icedomainfile = options.getfieldvalue('icedomain','none')
 		if not os.path.exists(icedomainfile):
 			raise IOError("setmask error message: ice domain file '%s' not found." % icedomainfile)
 		#use contourtomesh to set ice values inside ice domain
-		[vertexinsideicedomain,elementinsideicedomain]=ContourToMesh(elements,x,y,icedomainfile,'node',1)
-		md.mask.ice_levelset[numpy.nonzero(vertexinsideicedomain)[0]] = -1.
+		vertexinsideicedomain,elementinsideicedomain=ContourToMesh(elements,x,y,icedomainfile,'node',1)
+		md.mask.ice_levelset[np.nonzero(vertexinsideicedomain)[0]] = -1.
 	else:
-		md.mask.ice_levelset = -1.*numpy.ones(md.mesh.numberofvertices)
+		md.mask.ice_levelset = -1.*np.ones(md.mesh.numberofvertices)
 
 	return md
Index: /issm/trunk-jpl/src/py3/plot/applyoptions.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/applyoptions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/applyoptions.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 from cmaptools import truncate_colormap
 from plot_contour import plot_contour
@@ -10,10 +10,9 @@
 	from mpl_toolkits.mplot3d import Axes3D
 	import matplotlib as mpl
-	import pylab as p
 	import matplotlib.pyplot as plt
 except ImportError:
 	print("could not import pylab, matplotlib has not been installed, no plotting capabilities enabled")
 
-def applyoptions(md,data,options,fig,ax):
+def applyoptions(md,data,options,fig,axgrid,gridindex):
 	'''
 	APPLYOPTIONS - apply options to current plot
@@ -30,7 +29,7 @@
 	# get handle to current figure and axes instance
 	#fig = p.gcf()
-	#ax=p.gca()
-
-	#font {{{
+	ax=	axgrid[gridindex]
+
+	# {{{ font
 	fontsize=options.getfieldvalue('fontsize',8)
 	fontweight=options.getfieldvalue('fontweight','normal')
@@ -39,33 +38,31 @@
 				'fontweight'	:fontweight,
 				'family'			:fontfamily}
-	#}}}
-
-	#title {{{
+	# }}}
+	# {{{ title
 	if options.exist('title'):
 		title=options.getfieldvalue('title')
 		if options.exist('titlefontsize'):
 			titlefontsize=options.getfieldvalue('titlefontsize')
-else:
-	titlefontsize=fontsize
-	if options.exist('titlefontweight'):
-		titlefontweight=options.getfieldvalue('titlefontweight')
-else:
-	titlefontweight=fontweight
-	#title font
-	titlefont=font.copy()
-	titlefont['size']=titlefontsize
-	titlefont['weight']=titlefontweight
-	ax.set_title(title,**titlefont)
-	#}}}
-		
-	#xlabel, ylabel, zlabel {{{
+		else:
+			titlefontsize=fontsize
+		if options.exist('titlefontweight'):
+			titlefontweight=options.getfieldvalue('titlefontweight')
+		else:
+			titlefontweight=fontweight
+		#title font
+		titlefont=font.copy()
+		titlefont['size']=titlefontsize
+		titlefont['weight']=titlefontweight
+		ax.set_title(title,**titlefont)
+	# }}}
+	# {{{ xlabel, ylabel, zlabel
 	if options.exist('labelfontsize'):
 		labelfontsize=options.getfieldvalue('labelfontsize')
-else:
-	labelfontsize=fontsize
+	else:
+		labelfontsize=fontsize
 	if options.exist('labelfontweight'):
 		labelfontweight=options.getfieldvalue('labelfontweight')
-else:
-	labelfontweight=fontweight
+	else:
+		labelfontweight=fontweight
 
 	#font dict for labels
@@ -76,67 +73,62 @@
 	if options.exist('xlabel'):
 		ax.set_xlabel(options.getfieldvalue('xlabel'),**labelfont)
-		if options.exist('ylabel'):
-			ax.set_ylabel(options.getfieldvalue('ylabel'),**labelfont)
-			if options.exist('zlabel'):
-				ax.set_zlabel(options.getfieldvalue('zlabel'),**labelfont)
-				#}}}
-
-	#xticks, yticks, zticks (tick locations) {{{
+	if options.exist('ylabel'):
+		ax.set_ylabel(options.getfieldvalue('ylabel'),**labelfont)
+	if options.exist('zlabel'):
+		ax.set_zlabel(options.getfieldvalue('zlabel'),**labelfont)
+	# }}}
+	# {{{ xticks, yticks, zticks (tick locations)
 	if options.exist('xticks'):
 		if options.exist('xticklabels'):
 			xticklabels=options.getfieldvalue('xticklabels')
 			ax.set_xticks(options.getfieldvalue('xticks'),xticklabels)
-else:
-	ax.set_xticks(options.getfieldvalue('xticks'))
+		else:
+			ax.set_xticks(options.getfieldvalue('xticks'))
 	if options.exist('yticks'):
 		if options.exist('yticklabels'):
 			yticklabels=options.getfieldvalue('yticklabels')
 			ax.set_yticks(options.getfieldvalue('yticks'),yticklabels)
-else:
-	ax.set_yticks(options.getfieldvalue('yticks'))
+		else:
+			ax.set_yticks(options.getfieldvalue('yticks'))
 	if options.exist('zticks'):
 		if options.exist('zticklabels'):
 			zticklabels=options.getfieldvalue('zticklabels')
 			ax.set_zticks(options.getfieldvalue('zticks'),zticklabels)
-else:
-	ax.set_zticks(options.getfieldvalue('zticks'))
-	#}}}
-
-	#xticklabels,yticklabels,zticklabels {{{
+		else:
+			ax.set_zticks(options.getfieldvalue('zticks'))
+	# }}}
+	# {{{ xticklabels,yticklabels,zticklabels
 	if options.getfieldvalue('ticklabels','off')=='off' or options.getfieldvalue('ticklabels',0)==0:
 		options.addfielddefault('xticklabels',[])
 		options.addfielddefault('yticklabels',[])
 		# TODO check if ax has a z-axis (e.g. is 3D)
-		if options.exist('xticklabels'):
-			xticklabels=options.getfieldvalue('xticklabels')
-			ax.set_xticklabels(xticklabels)
-			if options.exist('yticklabels'):
-				yticklabels=options.getfieldvalue('yticklabels')
-				ax.set_yticklabels(yticklabels)
-				if options.exist('zticklabels'):
-					zticklabels=options.getfieldvalue('zticklabels')
-					ax.set_zticklabels(zticklabels)
-					#}}}
-
-	#ticklabel notation {{{
+	if options.exist('xticklabels'):
+		xticklabels=options.getfieldvalue('xticklabels')
+		ax.set_xticklabels(xticklabels)
+	if options.exist('yticklabels'):
+		yticklabels=options.getfieldvalue('yticklabels')
+		ax.set_yticklabels(yticklabels)
+	if options.exist('zticklabels'):
+		zticklabels=options.getfieldvalue('zticklabels')
+		ax.set_zticklabels(zticklabels)
+	# }}}
+	# {{{ ticklabel notation
 	#ax.ticklabel_format(style='sci',scilimits=(0,0))
-	#}}}
-
-	#ticklabelfontsize {{{
+	# }}}
+	# {{{ ticklabelfontsize
 	if options.exist('ticklabelfontsize'):
 		for label in ax.get_xticklabels() + ax.get_yticklabels():
 			label.set_fontsize(options.getfieldvalue('ticklabelfontsize'))
-			if int(md.mesh.dimension)==3: 
-				for label in ax.get_zticklabels():
-					label.set_fontsize(options.getfieldvalue('ticklabelfontsize'))
-					#}}}
-
-	#view
+		if int(md.mesh.dimension)==3:
+			for label in ax.get_zticklabels():
+				label.set_fontsize(options.getfieldvalue('ticklabelfontsize'))
+	# }}}
+	# {{{ view TOFIX
 	#if int(md.mesh.dimension) == 3 and options.exist('layer'):
 	#	#options.getfieldvalue('view') ?
 	#	ax=fig.gca(projection='3d')
 	#plt.show()
-
-	#axis {{{
+	# }}}
+	# {{{ axis
 	if options.exist('axis'):
 		if options.getfieldvalue('axis',True)=='off':
@@ -144,131 +136,117 @@
 			p.setp(ax.get_xticklabels(), visible=False)
 			p.setp(ax.get_yticklabels(), visible=False)
-			# }}}
-
-	#box
+	# }}}
+	# {{{ box
 	if options.exist('box'):
 		eval(options.getfieldvalue('box'))
-
-	#xlim, ylim, zlim {{{
-	if options.exist('xlim'):
+	# }}}
+	# {{{ xlim, ylim, zlim
+ 	if options.exist('xlim'):
 		ax.set_xlim(options.getfieldvalue('xlim'))
-		if options.exist('ylim'):
-			ax.set_ylim(options.getfieldvalue('ylim'))
-			if options.exist('zlim'):
-				ax.set_zlim(options.getfieldvalue('zlim'))
-				#}}}
-
-	#latlon
-
-	#Basinzoom
-
-	#ShowBasins
-
-	#clim {{{
+	if options.exist('ylim'):
+		ax.set_ylim(options.getfieldvalue('ylim'))
+	if options.exist('zlim'):
+		ax.set_zlim(options.getfieldvalue('zlim'))
+	# }}}
+	# {{{ latlon TODO
+	# }}}
+	# {{{ Basinzoom TODO
+	# }}}
+	# {{{ ShowBasins TODO
+	# }}}
+	# {{{ clim
 	if options.exist('clim'):
 		lims=options.getfieldvalue('clim')
 		assert len(lims)==2, 'error, clim should be passed as a list of length 2'
-elif options.exist('caxis'):
-	lims=options.getfieldvalue('caxis')
-	assert len(lims)==2, 'error, caxis should be passed as a list of length 2'
-	options.addfielddefault('clim',lims)
-else:
-	if len(data)>0: lims=[data.min(),data.max()]
-else: lims=[0,1]
-#}}}
-
-	#shading
+	elif options.exist('caxis'):
+		lims=options.getfieldvalue('caxis')
+		assert len(lims)==2, 'error, caxis should be passed as a list of length 2'
+		options.addfielddefault('clim',lims)
+	else:
+		if len(data)>0:
+			lims=[data.min(),data.max()]
+		else:
+			lims=[0,1]
+	# }}}
+	# {{{ shading TODO
 	#if options.exist('shading'):
-
-	#grid {{{
+	# }}}
+	# {{{ grid
 	if options.exist('grid'):
 		if 'on' in options.getfieldvalue('grid','on'):
 			ax.grid()
-			#}}}
-
-	#colormap {{{
-	# default sequential colormap
-	defaultmap=truncate_colormap(mpl.cm.gnuplot2,0.1,0.9,128)
-	cmap=options.getfieldvalue('colormap',defaultmap)
-	norm = mpl.colors.Normalize(vmin=lims[0], vmax=lims[1])
-	options.addfield('colornorm',norm)
+	# }}}
+	# {{{ colormap
+	if options.exist('colornorm'):
+		norm=options.getfieldvalue('colornorm')
+	if options.exist('colormap'):
+		cmap=options.getfieldvalue('colormap')
 	cbar_extend=0
 	if options.exist('cmap_set_over'):
-		over=options.getfieldvalue('cmap_set_over','0.5')
-		cmap.set_over(over)
 		cbar_extend+=1
-		if options.exist('cmap_set_under'):
-			under=options.getfieldvalue('cmap_set_under','0.5')
-			cmap.set_under(under)
-			cbar_extend+=2
-			options.addfield('colormap',cmap)
-			#}}}
-
-	#contours {{{
+	if options.exist('cmap_set_under'):
+		cbar_extend+=2
+	# }}}
+	# {{{ contours
 	if options.exist('contourlevels'):
 		plot_contour(md,data,options,ax)
-		#}}}
-
-	#wrapping
-
-	#colorbar {{{
+	# }}}
+	# {{{ wrapping TODO
+	# }}}
+	# {{{ colorbar
 	if options.getfieldvalue('colorbar',1)==1:
 		if cbar_extend==0:
 			extend='neither'
-elif cbar_extend==1:
-	extend='max'
-elif cbar_extend==2:
-	extend='min'
-elif cbar_extend==3:
-	extend='both'
-	cb = mpl.colorbar.ColorbarBase(ax.cax, cmap=cmap, norm=norm, extend=extend)
-	if options.exist('alpha'):
-		cb.set_alpha(options.getfieldvalue('alpha'))
+		elif cbar_extend==1:
+			extend='max'
+		elif cbar_extend==2:
+			extend='min'
+		elif cbar_extend==3:
+			extend='both'
+		cb = mpl.colorbar.ColorbarBase(ax.cax,cmap=cmap, norm=norm, extend=extend)
+		if options.exist('alpha'):
+			cb.set_alpha(options.getfieldvalue('alpha'))
 		if options.exist('colorbarnumticks'):
 			cb.locator=MaxNLocator(nbins=options.getfieldvalue('colorbarnumticks',5))
-else:
-	cb.locator=MaxNLocator(nbins=5) # default 5 ticks
-	if options.exist('colorbartickspacing'):
-		locs=np.arange(lims[0],lims[1]+1,options.getfieldvalue('colorbartickspacing'))
-		cb.set_ticks(locs)
+		else:
+			cb.locator=MaxNLocator(nbins=5) # default 5 ticks
+		if options.exist('colorbartickspacing'):
+			locs=np.arange(lims[0],lims[1]+1,options.getfieldvalue('colorbartickspacing'))
+			cb.set_ticks(locs)
 		if options.exist('colorbarlines'):
 			locs=np.arange(lims[0],lims[1]+1,options.getfieldvalue('colorbarlines'))
 			cb.add_lines(locs,['k' for i in range(len(locs))],np.ones_like(locs))
-			if options.exist('colorbarlineatvalue'):
-				locs=options.getfieldvalue('colorbarlineatvalue')
-				colors=options.getfieldvalue('colorbarlineatvaluecolor',['k' for i in range (len(locs))])
-				widths=options.getfieldvalue('colorbarlineatvaluewidth',np.ones_like(locs))
-				cb.add_lines(locs,colors,widths)
-				if options.exist('colorbartitle'):
-					if options.exist('colorbartitlepad'):
-						cb.set_label(options.getfieldvalue('colorbartitle'),labelpad=options.getfieldvalue('colorbartitlepad'),fontsize=fontsize)
-else:
-	cb.set_label(options.getfieldvalue('colorbartitle'),fontsize=fontsize)
-	cb.ax.tick_params(labelsize=fontsize)
-	cb.solids.set_rasterized(True)
-	cb.update_ticks()
-	cb.set_alpha(1)
-	cb.draw_all()
-	plt.sca(ax) # return to original axes control
-	#}}}
-
-        #expdisp {{{
-				if options.exist('expdisp'):
-					filename=options.getfieldvalue('expdisp')
-					style=options.getfieldvalue('expstyle','k')
-					linewidth=options.getfieldvalue('explinewidth',1)
-					for i in range(len(filename)):
-						filenamei=filename[i]
-						stylei=style[i]
-						if type(linewidth)==list:
-							linewidthi=linewidth[i]
-else:
-	linewidthi=linewidth
-	expdisp(filenamei,ax,linestyle=stylei,linewidth=linewidthi,unitmultiplier=options.getfieldvalue('unit',1))
-	#}}}
-
-	#area
-
-	#text {{{
+		if options.exist('colorbarlineatvalue'):
+			locs=options.getfieldvalue('colorbarlineatvalue')
+			colors=options.getfieldvalue('colorbarlineatvaluecolor',['k' for i in range (len(locs))])
+			widths=options.getfieldvalue('colorbarlineatvaluewidth',np.ones_like(locs))
+			cb.add_lines(locs,colors,widths)
+		if options.exist('colorbartitle'):
+			if options.exist('colorbartitlepad'):
+				cb.set_label(options.getfieldvalue('colorbartitle'),
+										 labelpad=options.getfieldvalue('colorbartitlepad'),fontsize=fontsize)
+			else:
+				cb.set_label(options.getfieldvalue('colorbartitle'),fontsize=fontsize)
+		cb.ax.tick_params(labelsize=fontsize)
+		cb.solids.set_rasterized(True)
+		cb.update_ticks()
+		cb.draw_all()
+		if options.exist('colorbarfontsize'):
+			colorbarfontsize=options.getfieldvalue('colorbarfontsize')
+			cb.ax.tick_params(labelsize=colorbarfontsize)
+			# cb.set_ticks([0,-10])
+			# cb.set_ticklabels([-10,0,10])
+		if options.exist('colorbarticks'):
+			colorbarticks=options.getfieldvalue('colorbarticks')
+			cb.set_ticks(colorbarticks)
+		plt.sca(ax) # return to original axes control
+	# }}}
+	# {{{ expdisp
+	if options.exist('expdisp'):
+	 	expdisp(ax,options)
+	# }}}
+	# {{{ area TODO
+	# }}}
+	# {{{ text
 	if options.exist('text'):
 		text=options.getfieldvalue('text')
@@ -281,35 +259,33 @@
 		for label,x,y,size,color,weight,rotation in zip(text,textx,texty,textfontsize,textcolor,textweight,textrotation):
 			ax.text(x,y,label,transform=ax.transAxes,fontsize=size,color=color,weight=weight,rotation=rotation)
-			#}}}
-
-	#north arrow
-
-	#scale ruler
-
-	#streamlines
+	# }}}
+	# {{{ north arrow TODO
+	# }}}
+	# {{{ scale ruler TODO
+	# }}}
+	# {{{ streamlines TOFIX
 	if options.exist('streamlines'):
 		plot_streamlines(md,options,ax)
-
-
-	#axis positions
-
-	#figure position
-
-	#axes position
-
-	#showregion
-
-	#flat edges of a partition
-
-	#scatter
-
-	#backgroundcolor
-
-	#figurebackgroundcolor
-
-	#lighting
-
-	#point cloud
-
-	#inset
-	
+	# }}}
+	# {{{ axis positions TODO
+	# }}}
+	# {{{ figure position TODO
+	# }}}
+	# {{{ axes position TODO
+	# }}}
+	# {{{ showregion TODO
+	# }}}
+	# {{{ flat edges of a partition TODO
+	# }}}
+	# {{{ scatter TODO
+	# }}}
+	# {{{ backgroundcolor TODO
+	# }}}
+	# {{{ figurebackgroundcolor TODO
+	# }}}
+	# {{{ lighting TODO
+	# }}}
+	# {{{ point cloud TODO
+	# }}}
+	# {{{ inset TODO
+	# }}}
Index: /issm/trunk-jpl/src/py3/plot/checkplotoptions.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/checkplotoptions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/checkplotoptions.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 
 def checkplotoptions(md,options):
@@ -13,6 +13,5 @@
 	'''
 
-
-	#units
+	# {{{ units
 	if options.exist('unit'):
 		if 'km' in options.getfieldvalue('unit','km'):
@@ -20,26 +19,26 @@
 		elif '100km' in options.getfieldvalue('unit','100km'):
 			options.changefieldvalue('unit',10**-5)
-	
-	#density
+	# }}}
+	# {{{ density
 	if options.exist('density'):
 		density=options.getfieldvalue('density')
 		options.changefieldvalue('density',abs(ceil(density)))
-		
-	#show section
+	# }}}
+	# {{{ show section
 	if options.exist('showsection'):
 		if 'on' in options.getfieldvalue('showsection','on'):
 			options.changefieldvalue('showsection',4)
-			
-	#smooth values
+	# }}}	
+	# {{{ smooth values
 	if options.exist('smooth'):
 		if 'on' in options.getfieldvalue('smooth','on'):
 			options.changefieldvalue('smooth',0)
-
-	#contouronly values
+	# }}}
+	# {{{ contouronly values
 	if options.exist('contouronly'):
 		if 'on' in options.getfieldvalue('contouronly','on'):
 			options.changefieldvalue('contouronly',1)
-
-	#colorbar
+	# }}}
+	# {{{ colorbar
 	if options.exist('colorbar'):
 		if 'on' in options.getfieldvalue('colorbar','on'):
@@ -47,8 +46,7 @@
 		elif 'off' in options.getfieldvalue('colorbar','off'):
 			options.changefieldvalue('colorbar',0)
-
-	#text
+	# }}}
+	# {{{ text
 	if options.exist('text'):
-
 		# text values (coerce to list for consistent functionality)
 		textlist=[]
@@ -56,27 +54,26 @@
 		textlist.extend([text] if isinstance(text,str) else text)
 		numtext=len(textlist)
-
 		# text position	
 		textpos=options.getfieldvalue('textposition',[0.5,0.5])
 		if not isinstance(textpos,list):
 			raise Exception('textposition should be passed as a list')
-			if any(isinstance(i,list) for i in textpos):
-				textx=[item[0] for item in textpos]
-				texty=[item[1] for item in textpos]
-			else:
-				textx=[textpos[0]]
-				texty=[textpos[1]]
+		if any(isinstance(i,list) for i in textpos):
+		    textx=[item[0] for item in textpos]
+		    texty=[item[1] for item in textpos]
+                else:
+                    textx=[textpos[0]]
+                    texty=[textpos[1]]
 		if len(textx)!=numtext or len(texty)!=numtext:
 			raise Exception('textposition should contain one list of x,y vertices for every text instance')
 
 		# font size
-	if options.exist('textfontsize'):
-		textfontsize=options.getfieldvalue('textfontsize',12)
-		sizelist=[]
-		sizelist.extend(textsize if isinstance(textfontsize,list) else [textfontsize])
-	else:
-		sizelist=[12]
-	if len(sizelist)==1:
-		sizelist=np.tile(sizelist,numtext)
+		if options.exist('textfontsize'):
+			textfontsize=options.getfieldvalue('textfontsize',12)
+			sizelist=[]
+			sizelist.extend(textsize if isinstance(textfontsize,list) else [textfontsize])
+		else:
+			sizelist=[12]
+		if len(sizelist)==1:
+			sizelist=np.tile(sizelist,numtext)
 
 		# font color
@@ -108,5 +105,5 @@
 			rotationlist=[0]
 		if len(rotationlist)==1:
-			rotationlist=np.tile(rotationlist,numtext)
+				rotationlist=np.tile(rotationlist,numtext)
 
 		options.changefieldvalue('text',textlist)
@@ -117,6 +114,6 @@
 		options.changefieldvalue('textweight',weightlist)
 		options.changefieldvalue('textrotation',rotationlist)
-
-	#expdisp
+	# }}}
+	# {{{ expdisp
 	expdispvaluesarray=[]
 	expstylevaluesarray=[]
@@ -136,14 +133,13 @@
 			else:
 				expstylevaluesarray.append('-k')
-
 	options.changefieldvalue('expstyle',expstylevaluesarray)
 	options.changefieldvalue('expdisp',expdispvaluesarray)
-
-	#latlonnumbering
+	# }}}
+	# {{{ latlonnumbering
 	if options.exist('latlonclick'):
 		if 'on' in options.getfieldvalue('latlonclick','on'):
 			options.changefieldvalue('latlonclick',1)
-
-	#northarrow
+	# }}}
+	# {{{ northarrow
 	if options.exist('northarrow'):
 		if 'on' in options.getfieldvalue('northarrow','on'):
@@ -152,17 +148,15 @@
 			Ly=max(md.mesh.y)-min(md.mesh.y)
 			options.changefieldvalue('northarrow',[min(md.mesh.x)+1./6.*Lx, min(md.mesh.y)+5./6.*Ly, 1./15.*Ly, 0.25, 1./250.*Ly])
-
-	#scale ruler
+	# }}}
+	# {{{ scale ruler
 	if options.exist('scaleruler'):
-		if 'on' in options.exist('scaleruler','on'):
+		if 'on' in options.getfieldvalue('scaleruler','off'):
 			Lx=max(md.mesh.x)-min(md.mesh.x)
 			Ly=max(md.mesh.y)-min(md.mesh.y)
-			options.changefieldvalue('scaleruler',[min(md.mesh.x)+6./8.*Lx, min(md.mesh.y)+1./10.*Ly, 10**(ceil(log10(Lx)))/5, floor(Lx/100), 5])
-
-	#log scale
+			options.changefieldvalue('scaleruler',[min(md.mesh.x)+6./8.*Lx, min(md.mesh.y)+1./10.*Ly, 10**(np.ceil(np.log10(Lx)))/5, np.floor(Lx/100), 5])
+	# }}}
+	# {{{ log scale
 	if options.exist('log'):
-		if options.exist('clim'):
-			options.changefieldvalue('clim',log(options.getfieldvalue('clim'))/log(options.getfieldvalue('log')))
-			options.changefieldvalue('cutoff',log(options.getfieldvalue('cutoff',1.5))/log(options.getfieldvalue('log')))
-
+		options.changefieldvalue('cutoff',np.log10(options.getfieldvalue('cutoff',1.5))/np.log10(options.getfieldvalue('log')))
+	# }}}
 	return options
Index: /issm/trunk-jpl/src/py3/plot/colormaps/cmaptools.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/colormaps/cmaptools.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/colormaps/cmaptools.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 
 try:
Index: /issm/trunk-jpl/src/py3/plot/export_gl.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/export_gl.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/export_gl.py	(revision 23670)
@@ -2,5 +2,5 @@
 from checkplotoptions import checkplotoptions
 from model import model
-import numpy as np
+import numpy as  np
 import math
 from writejsfile import writejsfile
Index: /issm/trunk-jpl/src/py3/plot/plot_contour.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/plot_contour.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/plot_contour.py	(revision 23670)
@@ -1,6 +1,9 @@
 from averaging import averaging
-import matplotlib.pyplot as plt
 from processmesh import processmesh
 from processdata import processdata
+try:
+	import matplotlib.pyplot as plt
+except ImportError:
+	print("could not import pylab, matplotlib has not been installed, no plotting capabilities enabled")
 
 def plot_contour(md,datain,options,ax):
@@ -31,8 +34,8 @@
 	# retrieve necessary options
 	levels=options.getfieldvalue('contourlevels')
-	colors=options.getfieldvalue('contourcolors')
 	norm=options.getfieldvalue('colornorm')
-	linestyles=options.getfieldvalue('contourlinestyles')
-	linewidths=options.getfieldvalue('contourlinewidths')
+	colors=options.getfieldvalue('contourcolors','y')
+	linestyles=options.getfieldvalue('contourlinestyles','-')
+	linewidths=options.getfieldvalue('contourlinewidths',1)
 
 	ax.tricontour(x,y,elements,data,levels,colors=colors,norm=norm,linestyles=linestyles,linewidths=linewidths)
Index: /issm/trunk-jpl/src/py3/plot/plot_manager.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/plot_manager.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/plot_manager.py	(revision 23670)
@@ -7,4 +7,7 @@
 from checkplotoptions import checkplotoptions
 from plot_mesh import plot_mesh
+from plot_BC import plot_BC
+from plot_elementnumbering import plot_elementnumbering
+from plot_vertexnumbering import plot_vertexnumbering
 from processmesh import processmesh
 from processdata import processdata
@@ -22,5 +25,5 @@
 	from plot_overlay import plot_overlay
 
-def plot_manager(md,options,fig,ax):
+def plot_manager(md,options,fig,axgrid,gridindex):
 	'''
 	PLOT_MANAGER - distribute the plots called by plotmodel
@@ -39,8 +42,62 @@
 	#parse options and get a structure of options
 	options=checkplotoptions(md,options)
+	#get data to be plotted
+	data=options.getfieldvalue('data')
+	#add ticklabel has a default option
+	options.addfielddefault('ticklabels','on')
 
-	#get data to be plotted
-	data=options.getfieldvalue('data');
+	ax=axgrid[gridindex]
+	# {{{ basemap plot TOFIX
+	#if options.exist('basemap'):
+	#	plot_basemap(md,data,options,nrows,ncols,i)
+	# }}}
+	# {{{ overlay plot
+	if options.exist('overlay') and overlaysupport:
+		plot_overlay(md,data,options,ax)
+		options.addfielddefault('alpha',0.5)
+		options.addfielddefault('xlim',[min(md.mesh.x),max(md.mesh.x)])
+		options.addfielddefault('ylim',[min(md.mesh.y),max(md.mesh.y)])
+	# }}}
+	# {{{ dealing with special plot
+	if isinstance(data,str):
+		if data=='mesh': 
+			plot_mesh(md,options,fig,axgrid,gridindex)
 
+			#fig.delaxes(fig.axes[1]) # hack to remove colorbar after the fact
+			return
+		elif data=='BC': 
+			plot_BC(md,options,fig,axgrid,gridindex)
+			return
+		elif data=='elementnumbering': 
+			plot_elementnumbering(md,options,fig,axgrid,gridindex)
+			return
+		elif data=='vertexnumbering': 
+			plot_vertexnumbering(md,options,fig,axgrid,gridindex)
+			return
+		elif data=='none':
+			print('no data provided to plot (TODO: write plot_none.py)')
+			applyoptions(md,[],options,fig,axgrid,gridindex)
+			return
+		else:
+			print("WARNING: '%s' is not implemented or is not a valid string for option 'data'" % data)
+	# }}}
+	# {{{ Gridded plot TODO
+	# }}}
+	# {{{ Section plot TODO
+	# }}}
+	# {{{ Profile plot TODO
+	# }}}
+
+	#process data and model
+	x,y,z,elements,is2d,isplanet=processmesh(md,data,options)
+	data2,datatype=processdata(md,data,options)
+	#plot unit
+	plot_unit(x,y,z,elements,data2,is2d,isplanet,datatype,options,fig,axgrid,gridindex)
+	#apply all options
+	applyoptions(md,data2,options,fig,axgrid,gridindex)
+
+	#ground overlay on kml plot_unit
+
+	# Bits and pieces
 	#initialize plot handle variable
 	#handle=None
@@ -49,54 +106,9 @@
 	#p.subplot(nrows,ncols,i,aspect='equal')
 
-	##basemap plot
-	#if options.exist('basemap'):
-	#	plot_basemap(md,data,options,nrows,ncols,i)
-
-	#overlay plot
-	if options.exist('overlay') and overlaysupport:
-		plot_overlay(md,data,options,ax)
-		options.addfielddefault('alpha',0.5)
-		options.addfielddefault('xlim',[min(md.mesh.x),max(md.mesh.x)])
-		options.addfielddefault('ylim',[min(md.mesh.y),max(md.mesh.y)])
-
-	#figure out if this is a special plot
-	if isinstance(data,str):
-
-		# convert string to lower case for a case-insensitive comparison
-		if data.lower()=='mesh': 
-			plot_mesh(md,options,ax)
-			applyoptions(md,[],options,fig,ax)
-			fig.delaxes(fig.axes[1]) # hack to remove colorbar after the fact
-			return
-		elif data.lower()=='none':
-			print('no data provided to plot (TODO: write plot_none.py)')
-			applyoptions(md,[],options,fig,ax)
-			return
-		else:
-			print(("WARNING: '%s' is not implemented or is not a valid string for option 'data'" % data))
+	#standard plot
+	#if not handle:
+	#	p.subplot(nrows,ncols,i,aspect='equal')
 
 	#elif data in vars(md):
 	#else:
 		#print "'data' not a string, plotting model properties yet to be implemented..."
-
-	#Gridded plot
-
-	#Section plot
-
-	#Profile plot
-
-	#process data and model
-	x,y,z,elements,is2d,isplanet=processmesh(md,data,options)
-	data2,datatype=processdata(md,data,options)
-
-	#standard plot
-	#if not handle:
-	#	p.subplot(nrows,ncols,i,aspect='equal')
-
-	#plot unit
-	plot_unit(x,y,z,elements,data2,is2d,isplanet,datatype,options,ax)
-
-	#apply all options
-	applyoptions(md,data2,options,fig,ax)
-	
-	#ground overlay on kml plot_unit
Index: /issm/trunk-jpl/src/py3/plot/plot_mesh.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/plot_mesh.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/plot_mesh.py	(revision 23670)
@@ -4,8 +4,11 @@
 	print("could not import pylab, matplotlib has not been installed, no plotting capabilities enabled")
 
+import numpy as np
 from processmesh import processmesh
 from applyoptions import applyoptions
-
-def plot_mesh(md,options,ax):
+from mpl_toolkits.mplot3d.art3d import Line3DCollection
+from mpl_toolkits.axes_grid1 import inset_locator
+from mpl_toolkits.mplot3d import Axes3D
+def plot_mesh(md,options,fig,axgrid,gridindex):
 	'''
 	PLOT_MESH - plot model mesh
@@ -16,14 +19,41 @@
 		See also: PLOTMODEL
 	'''
+	x,y,z,elements,is2d,isplanet=processmesh(md,'mesh',options)
 
-	x,y,z,elements,is2d,isplanet=processmesh(md,[],options)
-
+	ax=axgrid[gridindex]
+	fig.delaxes(axgrid.cbar_axes[gridindex])
+	
 	if is2d:
 		ax.triplot(x,y,elements)
 	else:
-		print('WARNING: only 2D mesh plot is currently implemented')
-	
+		ax=inset_locator.inset_axes(axgrid[gridindex],width='100%',height='100%',loc=3,borderpad=0,axes_class=Axes3D)
+		
+		AB=elements[:,0:2]
+		BC=elements[:,1:3]
+		CA=np.vstack((elements[:,2],elements[:,0])).T
+		DE=elements[:,3:5]
+		EF=elements[:,4:]
+		FD=np.vstack((elements[:,5],elements[:,3])).T
+		AD=np.vstack((elements[:,0],elements[:,3])).T
+		BE=np.vstack((elements[:,1],elements[:,4])).T
+		CF=np.vstack((elements[:,2],elements[:,5])).T
+		
+		tmpa=np.vstack((AB,BC,CA,DE,EF,FD,AD,BE,CF))
+		#deleting segments that appear multiple times
+		tmpb = np.ascontiguousarray(tmpa).view(np.dtype((np.void, tmpa.dtype.itemsize * tmpa.shape[1])))
+		_, idx = np.unique(tmpb, return_index=True)
+		triel= tmpa[idx]
+		
+		for triangle in triel:
+			tri=list(zip(x[triangle],y[triangle],z[triangle]))
+			pl3=Line3DCollection([tri],edgecolor='r')
+			ax.add_collection3d(pl3)
+			
+		ax.set_xlim([min(x),max(x)])
+		ax.set_ylim([min(y),max(y)])
+		ax.set_zlim([min(z),max(z)])
 	#apply options
 	options.addfielddefault('title','Mesh')
 	options.addfielddefault('colorbar','off')
 	options.addfielddefault('ticklabels','on')
+	applyoptions(md,[],options,fig,axgrid,gridindex)
Index: /issm/trunk-jpl/src/py3/plot/plot_overlay.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/plot_overlay.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/plot_overlay.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy as np
+import numpy as  np
 from processmesh import processmesh
 from processdata import processdata
@@ -5,13 +5,11 @@
 import matplotlib.pyplot as plt
 import matplotlib as mpl
+import os
 try:
-    from mpl_toolkits.basemap import Basemap
+	from mpl_toolkits.basemap import Basemap
 except ImportError:
-    print('Basemap toolkit not installed')
-
-import os
-
+	print('Basemap toolkit not installed')
 try:
-        from osgeo import gdal
+	from osgeo import gdal
 except ImportError:
 	print('osgeo/gdal for python not installed, plot_overlay is disabled')
@@ -25,24 +23,23 @@
 
 	x,y,z,elements,is2d,isplanet=processmesh(md,[],options)
-
-	if data=='none' or data==None:
+	try:
+		data,datatype=processdata(md,data,options)
+		imageonly=0
+	except (TypeError,ValueError):#that should catch None and 'none' but may also catch unwanted errors
 		imageonly=1
 		data=np.float('nan')*np.ones((md.mesh.numberofvertices,))
 		datatype=1
-	else:
-		imageonly=0
-		data,datatype=processdata(md,data,options)
 
 	if not is2d:
 		raise Exception('overlay plot not supported for 3D meshes, project on a 2D layer first')
 
-	if not options.exist('geotiff_name'):
-		raise Exception('overlay error: provide geotiff_name with path to geotiff file')
-	geotiff=options.getfieldvalue('geotiff_name')
+	if not options.exist('overlay_image'):
+		raise Exception('overlay error: provide overlay_image with path to geotiff file')
+	image=options.getfieldvalue('overlay_image')
 
 	xlim=options.getfieldvalue('xlim',[min(md.mesh.x),max(md.mesh.x)])
 	ylim=options.getfieldvalue('ylim',[min(md.mesh.y),max(md.mesh.y)])
 
-	gtif=gdal.Open(geotiff)
+	gtif=gdal.Open(image)
 	trans=gtif.GetGeoTransform()
 	xmin=trans[0]
@@ -50,6 +47,5 @@
 	ymin=trans[3]+gtif.RasterYSize*trans[5]
 	ymax=trans[3]
-	
-	# allow supplied geotiff to have limits smaller than basemap or model limits
+	# allow supplied image to have limits smaller than basemap or model limits
 	x0=max(min(xlim),xmin)
 	x1=min(max(xlim),xmax)
@@ -57,10 +53,10 @@
 	y1=min(max(ylim),ymax)
 	inputname='temp.tif'
-	os.system('gdal_translate -quiet -projwin ' + str(x0) + ' ' + str(y1) + ' ' + str(x1) + ' ' + str(y0) + ' ' + geotiff + ' ' + inputname)
-	
+	os.system('gdal_translate -quiet -projwin ' + str(x0) + ' ' + str(y1) + ' ' + str(x1) + ' ' + str(y0) + ' ' + image+ ' ' + inputname)
+
 	gtif=gdal.Open(inputname)
 	arr=gtif.ReadAsArray()
 	#os.system('rm -rf ./temp.tif')
-	
+
 	if gtif.RasterCount>=3:  # RGB array
 		r=gtif.GetRasterBand(1).ReadAsArray()
@@ -84,7 +80,7 @@
 		plt.hist(arr.flatten(),bins=256,range=(0.,1.))
 		plt.title('histogram of overlay image, use for setting overlaylims')
-                plt.show()
+		plt.show()
 		plt.sca(ax) # return to original axes/figure
-		
+
 	# get parameters from cropped geotiff
 	trans=gtif.GetGeoTransform()
@@ -94,6 +90,6 @@
 	ymax=trans[3]
 	dx=trans[1]
-	dy=trans[5]	
-	
+	dy=trans[5]
+
 	xarr=np.arange(xmin,xmax,dx)
 	yarr=np.arange(ymin,ymax,-dy) # -dy since origin='upper' (not sure how robust this is)
@@ -102,31 +98,35 @@
 	norm=mpl.colors.Normalize(vmin=overlaylims[0],vmax=overlaylims[1])
 
+	pc=ax.pcolormesh(xg, yg, np.flipud(arr), cmap=mpl.cm.Greys, norm=norm)
+
 	if options.exist('basemap'):
 		# create coordinate grid in map projection units (for plotting)
-		lat,lon=xy2ll(xlim,ylim,-1,0,71)
-                #plt.sca(ax)
-                width=xmax-xmin
-                height=ymax-ymin
-                lat_0,lon_0=xy2ll(xmin+width/2.,ymin+height/2.,-1,0,71)
-	        m=Basemap(projection='spstere',
-                        llcrnrlon=lon[0],llcrnrlat=lat[0],urcrnrlon=lon[1],urcrnrlat=lat[1],
-                        epsg=3031,
-                        resolution='c')
-                        #width=width,height=height,lon_0=lon_0,lat_0=lat_0,
-                        #lat_0=-90,lon_0=0,lat_ts=-71,
-                        #llcrnrx=x0,llcrnry=y0,urcrnrx=x1,urcrnry=y1)
-                #test
-                #m.ax=ax
-	        meridians=np.arange(-180.,181.,1.)
-	        parallels=np.arange(-80.,80.,1.)
-	        m.drawparallels(parallels,labels=[0,0,1,1]) # labels=[left,right,top,bottom]
-	        m.drawmeridians(meridians,labels=[1,1,0,0])
-                m.drawcoastlines()
-	        pc=m.pcolormesh(xg, yg, np.flipud(arr), cmap=mpl.cm.Greys, norm=norm, ax=ax)
+		if md.mesh.epsg==3413:
+			hemisphere=1
+			st_lat=70
+			lon_0=45
+		elif md.mesh.epsg==3031:
+			hemisphere=-1
+			st_lat=71
+			lon_0=0
+		else:
+			hemisphere=input('epsg code {} is not supported chose your hemisphere (1 for North, -1 for south)'.format(mesh.epsg))
 
-	else:
-	        pc=ax.pcolormesh(xg, yg, np.flipud(arr), cmap=mpl.cm.Greys, norm=norm)
-        
-	#rasterization? 
+		lat,lon=xy2ll(xlim,ylim,hemisphere,lon_0,st_lat)
+		extent=[np.diff(xlim)[0],np.diff(ylim)[0]]
+		center=[lon[0]+np.diff(lon)[0]*0.5,lat[0]+np.diff(lat)[0]*0.5]
+		m=Basemap(llcrnrlon=lon[0],llcrnrlat=lat[0],urcrnrlon=lon[1],urcrnrlat=lat[1],
+							lon_0=center[0],lat_0=center[1],#width=extent[0],height=extent[1],#
+							epsg=md.mesh.epsg,anchor='NW',
+							resolution='i',ax=ax)
+
+		meridians=np.arange(np.floor(lon[0]),np.ceil(lon[1]),1.)
+		parallels=np.arange(np.floor(lat[0]),np.ceil(lat[1]),1.)
+		m.drawparallels(parallels,labels=[1,0,0,0],ax=ax) # labels=[left,right,top,bottom]
+		m.drawmeridians(meridians,labels=[0,0,1,0],ax=ax)
+		m.drawcoastlines(ax=ax)
+		m.drawmapboundary(ax=ax)
+
+	#rasterization?
 	if options.getfieldvalue('rasterized',0):
 		pc.set_rasterized(True)
Index: /issm/trunk-jpl/src/py3/plot/plot_streamlines.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/plot_streamlines.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/plot_streamlines.py	(revision 23670)
@@ -1,13 +1,16 @@
-import numpy as np
-import matplotlib.pyplot as plt
-import matplotlib.tri as tri
+import numpy as  np
 from processmesh import processmesh
 from processdata import processdata
-from scipy.interpolate import griddata
 from ContourToMesh import ContourToMesh
+try:
+	import matplotlib.pyplot as plt
+	import matplotlib.tri as tri
+	from scipy.interpolate import griddata
+except ImportError:
+	print("could not import pylab, matplotlib has not been installed, no plotting capabilities enabled")
 
 def plot_streamlines(md,options,ax):
     '''
-    plot streamlines on a figure, using by default vx and vy components in md.initialization. 
+    plot streamlines on a figure, using by default vx and vy components in md.initialization.
 
     Usage:
@@ -22,5 +25,5 @@
         streamlineswidthscale: scaling multiplier for linewidth scaled by velocity
         streamlinesarrowsize: size of arrows on lines (default 1)
-        
+
     '''
 
@@ -33,5 +36,5 @@
     arrowsize=options.getfieldvalue('streamlinesarrowsize',1)
 
-    #process mesh and data 
+    #process mesh and data
     x,y,z,elements,is2d,isplanet=processmesh(md,vx,options)
     u,datatype=processdata(md,vx,options)
Index: /issm/trunk-jpl/src/py3/plot/plot_unit.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/plot_unit.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/plot_unit.py	(revision 23670)
@@ -1,92 +1,236 @@
 from cmaptools import truncate_colormap
+from plot_quiver import plot_quiver
+from scipy.interpolate import griddata
+import numpy as  np
 try:
-    import pylab as p
-    import matplotlib as mpl
-    import matplotlib.pyplot as plt
-    import numpy as np
+	import matplotlib as mpl
+	import matplotlib.pyplot as plt
+	from mpl_toolkits.axes_grid1 import inset_locator
+	from mpl_toolkits.mplot3d import Axes3D
+	from mpl_toolkits.mplot3d.art3d import Poly3DCollection
 except ImportError:
-    print("could not import pylab, matplotlib has not been installed, no plotting capabilities enabled")
-
-def plot_unit(x,y,z,elements,data,is2d,isplanet,datatype,options,ax):
-    """
-    PLOT_UNIT - unit plot, display data
-    
-    	Usage:
-    		plot_unit(x,y,z,elements,data,is2d,isplanet,datatype,options)
-    
-    	See also: PLOTMODEL, PLOT_MANAGER
-    """
-    
-    #edgecolor
-    edgecolor=options.getfieldvalue('edgecolor','None')
-    
-    #number of colorlevels for plots
-    colorlevels=options.getfieldvalue('colorlevels',128)
-    
-    alpha=options.getfieldvalue('alpha',1)
-    
-    #colormap
-    # default sequential colormap
-    defaultmap=truncate_colormap(mpl.cm.gnuplot2,0.1,0.9,128)
-    cmap=options.getfieldvalue('colormap',defaultmap)
-    if options.exist('cmap_set_over'):
-        over=options.getfieldvalue('cmap_set_over','0.5')
-        cmap.set_over(over)
-    if options.exist('cmap_set_under'):
-        under=options.getfieldvalue('cmap_set_under','0.5')
-        cmap.set_under(under)
-    
-    #normalize colormap if clim/caxis specified
-    if options.exist('clim'):
-        lims=options.getfieldvalue('clim',[np.amin(data),np.amax(data)])
-    elif options.exist('caxis'):
-        lims=options.getfieldvalue('caxis',[np.amin(data),np.amax(data)])
-    else:
-        if np.amin(data)==np.amax(data):
-            lims=[np.amin(data)-0.5,np.amax(data)+0.5]
-        else:
-    	    lims=[np.amin(data),np.amax(data)]
-    norm = mpl.colors.Normalize(vmin=lims[0], vmax=lims[1])
-    if datatype==1:
-       #element plot
-        if is2d:
-    	    tri=ax.tripcolor(x,y,elements,data,colorlevels,cmap=cmap,norm=norm,alpha=alpha,edgecolors=edgecolor)
-    	else:
-    	    raise ValueError('plot_unit error: 3D element plot not supported yet')
-    	return 
-    
-    elif datatype==2:
-    	#node plot
-    	if is2d:
-    	    tri=ax.tricontourf(x,y,elements,data,colorlevels,cmap=cmap,norm=norm,alpha=alpha,extend='both')
-    	    if edgecolor != 'None':
-    	        ax.triplot(x,y,elements,color=edgecolor)
-    	else:
-    	    raise ValueError('plot_unit error: 3D node plot not supported yet')
-    	return
-    
-    elif datatype==3:
-        vx=data[:,0]
-        vy=data[:,1]
-        #TODO write plot_quiver.py to handle this here
-        color=np.sqrt(vx**2+vy**2)
-        scale=options.getfieldvalue('scale',1000)
-        width=options.getfieldvalue('width',0.005*(np.amax(x)-np.amin(y)))
-        headwidth=options.getfieldvalue('headwidth',3)
-        headlength=options.getfieldvalue('headlength',5)
-        Q=ax.quiver(x,y,vx,vy,color,cmap=cmap,norm=norm,scale=scale,
-                width=width,headwidth=headwidth,headlength=headlength)
-    	return
-    
-    elif datatype==4:
-    	#P1 patch plot
-    	print('plot_unit message: P1 patch plot not implemented yet')
-    	return
-    
-    elif datatype==5:
-    	print('plot_unit message: P0 patch plot not implemented yet')
-    	return
-    
-    else:
-    	raise ValueError('datatype=%d not supported' % datatype)
-    
+	print("could not import pylab, matplotlib has not been installed, no plotting capabilities enabled")
+
+def plot_unit(x,y,z,elements,data,is2d,isplanet,datatype,options,fig,axgrid,gridindex):
+	"""
+	PLOT_UNIT - unit plot, display data
+
+	Usage:
+	plot_unit(x,y,z,elements,data,is2d,isplanet,datatype,options)
+
+	See also: PLOTMODEL, PLOT_MANAGER
+	"""
+	#if we are plotting 3d replace the current axis
+	if not is2d:
+		axgrid[gridindex].axis('off')
+		ax=inset_locator.inset_axes(axgrid[gridindex],width='100%',height='100%',loc=3,borderpad=0,axes_class=Axes3D)
+		ax.set_axis_bgcolor((0.7,0.7,0.7))
+	else:
+		ax=axgrid[gridindex]
+
+	#edgecolor
+	edgecolor=options.getfieldvalue('edgecolor','None')
+
+	# colormap
+	# {{{ give number of colorlevels and transparency
+	colorlevels=options.getfieldvalue('colorlevels',128)
+	alpha=options.getfieldvalue('alpha',1)
+	if alpha<1:
+		antialiased=True
+	else:
+		antialiased=False
+	# }}}
+	# {{{ define wich colormap to use
+	try:
+		defaultmap=plt.cm.get_cmap('viridis',colorlevels)
+	except AttributeError:
+		print("Viridis can't be found (probably too old Matplotlib) reverting to gnuplot colormap")
+		defaultmap=truncate_colormap('gnuplot2',0.1,0.9,colorlevels)
+	cmap=options.getfieldvalue('colormap',defaultmap)
+	if options.exist('cmap_set_over'):
+		over=options.getfieldvalue('cmap_set_over','0.5')
+		cmap.set_over(over)
+	if options.exist('cmap_set_under'):
+		under=options.getfieldvalue('cmap_set_under','0.5')
+		cmap.set_under(under)
+	options.addfield('colormap',cmap)
+	# }}}
+	# {{{ if plotting only one of several layers reduce dataset, same for surface
+	if options.getfieldvalue('layer',0)>=1:
+		plotlayer=options.getfieldvalue('layer',0)
+		if datatype==1:
+			slicesize=np.shape(elements)[0]
+		elif datatype in [2,3]:
+			slicesize=len(x)
+		data=data[(plotlayer-1)*slicesize:plotlayer*slicesize]
+	# }}}
+	# {{{ Get the colormap limits
+	if options.exist('clim'):
+		lims=options.getfieldvalue('clim',[np.amin(data),np.amax(data)])
+	elif options.exist('caxis'):
+		lims=options.getfieldvalue('caxis',[np.amin(data),np.amax(data)])
+	else:
+		if np.amin(data)==np.amax(data):
+			lims=[np.amin(data)-0.5,np.amax(data)+0.5]
+		else:
+			lims=[np.amin(data),np.amax(data)]
+	# }}}
+	# {{{ Set the spread of the colormap (default is normal
+	if options.exist('log'):
+		norm = mpl.colors.LogNorm(vmin=lims[0], vmax=lims[1])
+	else:
+		norm = mpl.colors.Normalize(vmin=lims[0], vmax=lims[1])
+	if options.exist('log'):
+		norm = mpl.colors.LogNorm(vmin=lims[0], vmax=lims[1])
+	else:
+		norm = mpl.colors.Normalize(vmin=lims[0], vmax=lims[1])
+	options.addfield('colornorm',norm)
+	# }}}
+
+	# Plot depending on the datatype
+	# {{{ data are on elements
+
+	if datatype==1:
+		if is2d:
+			if options.exist('mask'):
+				triangles=mpl.tri.Triangulation(x,y,elements,data.mask)
+			else:
+				triangles=mpl.tri.Triangulation(x,y,elements)
+			tri=ax.tripcolor(triangles,data,colorlevels,cmap=cmap,norm=norm,alpha=alpha,edgecolors=edgecolor)
+		else:
+			#first deal with colormap
+			loccmap = plt.cm.ScalarMappable(cmap=cmap)
+			loccmap.set_array([min(data),max(data)])
+			loccmap.set_clim(vmin=min(data),vmax=max(data))
+
+			#dealing with prism sides
+			recface=np.vstack((elements[:,0],elements[:,1],elements[:,4],elements[:,3])).T
+			eltind=np.arange(0,np.shape(elements)[0])
+			recface=np.vstack((recface,np.vstack((elements[:,1],elements[:,2],elements[:,5],elements[:,4])).T))
+			eltind=np.hstack((eltind,np.arange(0,np.shape(elements)[0])))
+			recface=np.vstack((recface,np.vstack((elements[:,2],elements[:,0],elements[:,3],elements[:,5])).T))
+			eltind=np.hstack((eltind,np.arange(0,np.shape(elements)[0])))
+			tmp = np.ascontiguousarray(np.sort(recface)).view(np.dtype((np.void, recface.dtype.itemsize * recface.shape[1])))
+			_, idx, recur = np.unique(tmp, return_index=True, return_counts=True)
+			recel= recface[idx[np.where(recur==1)]]
+			recindex=eltind[idx[np.where(recur==1)]]
+			for i,rectangle in enumerate(recel):
+				rec=list(zip(x[rectangle],y[rectangle],z[rectangle]))
+				pl3=Poly3DCollection([rec])
+				color=loccmap.to_rgba(data[recindex[i]])
+				pl3.set_edgecolor(color)
+				pl3.set_color(color)
+				ax.add_collection3d(pl3)
+
+			#dealing with prism bases
+			triface=np.vstack((elements[:,0:3],elements[:,3:6]))
+			eltind=np.arange(0,np.shape(elements)[0])
+			eltind=np.hstack((eltind,np.arange(0,np.shape(elements)[0])))
+			tmp = np.ascontiguousarray(triface).view(np.dtype((np.void, triface.dtype.itemsize * triface.shape[1])))
+			_, idx,recur = np.unique(tmp, return_index=True,return_counts=True)
+			#we keep only top and bottom elements
+			triel= triface[idx[np.where(recur==1)]]
+			triindex=eltind[idx[np.where(recur==1)]]
+			for i,triangle in enumerate(triel):
+				tri=list(zip(x[triangle],y[triangle],z[triangle]))
+				pl3=Poly3DCollection([tri])
+				color=loccmap.to_rgba(data[triindex[i]])
+				pl3.set_edgecolor(color)
+				pl3.set_color(color)
+				ax.add_collection3d(pl3)
+	
+			ax.set_xlim([min(x),max(x)])
+			ax.set_ylim([min(y),max(y)])
+			ax.set_zlim([min(z),max(z)])
+
+			#raise ValueError('plot_unit error: 3D element plot not supported yet')
+		return 
+
+	# }}}
+	# {{{ data are on nodes
+
+	elif datatype==2:
+		if is2d:
+			if np.ma.is_masked(data):
+				EltMask=np.asarray([np.any(np.in1d(index,np.where(data.mask))) for index in elements])
+				triangles=mpl.tri.Triangulation(x,y,elements,EltMask)
+			else:
+				triangles=mpl.tri.Triangulation(x,y,elements)
+				#tri=ax.tricontourf(triangles,data,colorlevels,cmap=cmap,norm=norm,alpha=alpha)
+			if options.exist('log'):
+				if alpha<1:#help with antialiasing
+					tri=ax.tricontour(triangles,data,colorlevels,cmap=cmap,norm=norm,alpha=0.1,antialiased=antialiased)
+				tri=ax.tricontourf(triangles,data,colorlevels,cmap=cmap,norm=norm,alpha=alpha,antialiased=antialiased)
+			else:
+				if alpha<1:#help with antialiasing
+					tri=ax.tricontour(triangles,data,colorlevels,cmap=cmap,norm=norm,alpha=0.1,antialiased=antialiased)
+				tri=ax.tricontourf(triangles,data,colorlevels,cmap=cmap,norm=norm,alpha=alpha,extend='both',antialiased=antialiased)
+			if edgecolor != 'None':
+				ax.triplot(x,y,elements,color=edgecolor)
+		else:
+			#first deal with the colormap
+			loccmap = plt.cm.ScalarMappable(cmap=cmap)
+			loccmap.set_array([min(data),max(data)])
+			loccmap.set_clim(vmin=min(data),vmax=max(data))
+
+			#deal with prism sides
+			recface=np.vstack((elements[:,0],elements[:,1],elements[:,4],elements[:,3])).T
+			recface=np.vstack((recface,np.vstack((elements[:,1],elements[:,2],elements[:,5],elements[:,4])).T))
+			recface=np.vstack((recface,np.vstack((elements[:,2],elements[:,0],elements[:,3],elements[:,5])).T))
+			tmp = np.ascontiguousarray(np.sort(recface)).view(np.dtype((np.void, recface.dtype.itemsize * recface.shape[1])))
+			_, idx, recur = np.unique(tmp, return_index=True, return_counts=True)
+			recel= recface[idx[np.where(recur==1)]]
+			for rectangle in recel:
+				rec=list(zip(x[rectangle],y[rectangle],z[rectangle]))
+				pl3=Poly3DCollection([rec])
+				color=loccmap.to_rgba(np.mean(data[rectangle]))
+				pl3.set_edgecolor(color)
+				pl3.set_color(color)
+				ax.add_collection3d(pl3)
+
+			#deal with prism faces
+			triface=np.vstack((elements[:,0:3],elements[:,3:6]))
+			tmp = np.ascontiguousarray(triface).view(np.dtype((np.void, triface.dtype.itemsize * triface.shape[1])))
+			_, idx,recur = np.unique(tmp, return_index=True,return_counts=True)
+			#we keep only top and bottom elements
+			triel= triface[idx[np.where(recur==1)]]
+			for triangle in triel:
+				tri=list(zip(x[triangle],y[triangle],z[triangle]))
+				pl3=Poly3DCollection([tri])
+				color=loccmap.to_rgba(np.mean(data[triangle]))
+				pl3.set_edgecolor(color)
+				pl3.set_color(color)
+				ax.add_collection3d(pl3)
+
+			ax.set_xlim([min(x),max(x)])
+			ax.set_ylim([min(y),max(y)])
+			ax.set_zlim([min(z),max(z)])
+			#raise ValueError('plot_unit error: 3D element plot not supported yet')
+		return
+
+	# }}}
+	# {{{ plotting quiver
+	elif datatype==3:
+		if is2d:
+			Q=plot_quiver(x,y,data,options,ax)
+		else:
+			raise ValueError('plot_unit error: 3D node plot not supported yet')
+		return
+	
+	# }}}
+	# {{{ plotting P1 Patch (TODO)
+
+	elif datatype==4:
+		print('plot_unit message: P1 patch plot not implemented yet')
+		return
+
+	# }}}
+	# {{{ plotting P0 Patch (TODO)
+
+	elif datatype==5:
+		print('plot_unit message: P0 patch plot not implemented yet')
+		return
+
+	# }}}
+	else:
+		raise ValueError('datatype=%d not supported' % datatype)
Index: /issm/trunk-jpl/src/py3/plot/plotmodel.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/plotmodel.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/plotmodel.py	(revision 23670)
@@ -1,4 +1,7 @@
-import numpy as np
+import numpy as  np
 from plotoptions import plotoptions
+from plotdoc import plotdoc
+from plot_manager import plot_manager
+from math import ceil, sqrt
 
 try:
@@ -6,21 +9,17 @@
 	import matplotlib.pyplot as plt
 	from mpl_toolkits.axes_grid1 import ImageGrid, AxesGrid
+	from mpl_toolkits.mplot3d import Axes3D
 except ImportError:
 	print("could not import pylab, matplotlib has not been installed, no plotting capabilities enabled")
 
-from plot_manager import plot_manager
-from math import ceil, sqrt
-
 def plotmodel(md,*args):
-	'''
-	at command prompt, type 'plotdoc' for additional documentation
+	'''	at command prompt, type 'plotdoc()' for additional documentation
 	'''
 
-	#First process options 
+	#First process options
 	options=plotoptions(*args)
 
 	#get number of subplots
 	subplotwidth=ceil(sqrt(options.numberofplots))
-	
 	#Get figure number and number of plots
 	figurenumber=options.figurenumber
@@ -37,5 +36,5 @@
 		nrows=np.ceil(numberofplots/subplotwidth)
 		nr=False
-	
+
 	if options.list[0].exist('ncols'):
 		ncols=options.list[0].getfieldvalue('ncols')
@@ -46,12 +45,11 @@
 	ncols=int(ncols)
 	nrows=int(nrows)
-	
+
 	#check that nrows and ncols were given at the same time!
 	if not nr==nc:
 		raise Exception('error: nrows and ncols need to be specified together, or not at all')
-	
+
 	#Go through plots
 	if numberofplots:
-		
 		#if plt.fignum_exists(figurenumber): 
 		#	plt.cla()
@@ -60,22 +58,32 @@
 		if options.list[0].exist('figsize'):
 			figsize=options.list[0].getfieldvalue('figsize')
-			fig=plt.figure(figurenumber,figsize=(figsize[0],figsize[1]),tight_layout=True)
+			fig=plt.figure(figurenumber,figsize=(figsize[0],figsize[1]))#,tight_layout=True)
 		else:
-			fig=plt.figure(figurenumber,tight_layout=True)
+			fig=plt.figure(figurenumber)#,tight_layout=True)
 		fig.clf()
 
+		backgroundcolor=options.list[0].getfieldvalue('backgroundcolor',(0.7,0.7,0.7))
+		fig.set_facecolor(backgroundcolor)
+
+
+		translator={'on':'each',
+								'off':'None',
+								'one':'single'}
 		# options needed to define plot grid
+		plotnum=options.numberofplots
 		direction=options.list[0].getfieldvalue('direction','row') # row,column
 		axes_pad=options.list[0].getfieldvalue('axes_pad',0.25)
 		add_all=options.list[0].getfieldvalue('add_all',True) # True,False
 		share_all=options.list[0].getfieldvalue('share_all',True) # True,False
-		label_mode=options.list[0].getfieldvalue('label_mode','1') # 1,L,all
-		cbar_mode=options.list[0].getfieldvalue('cbar_mode','each') # none,single,each
-		cbar_location=options.list[0].getfieldvalue('cbar_location','right') # right,top
-		cbar_size=options.list[0].getfieldvalue('cbar_size','5%')
-		cbar_pad=options.list[0].getfieldvalue('cbar_pad','2.5%') # None or %
-		
-		axgrid=ImageGrid(fig, 111,
+		label_mode=options.list[0].getfieldvalue('label_mode','L') # 1,L,all
+		colorbar=options.list[0].getfieldvalue('colorbar','on') # on, off (single)
+		cbar_mode=translator[colorbar]
+		cbar_location=options.list[0].getfieldvalue('colorbarpos','right') # right,top
+		cbar_size=options.list[0].getfieldvalue('colorbarsize','5%')
+		cbar_pad=options.list[0].getfieldvalue('colorbarpad','2.5%') # None or %
+
+		axgrid=ImageGrid(fig,111,
 				nrows_ncols=(nrows,ncols),
+				ngrids=plotnum,
 				direction=direction,
 				axes_pad=axes_pad,
@@ -86,13 +94,12 @@
 				cbar_location=cbar_location,
 				cbar_size=cbar_size,
-				cbar_pad=cbar_pad
-				)
+				cbar_pad=cbar_pad)
 
-		if cbar_mode=='none':
-			for ax in axgrid.cbar_axes: fig._axstack.remove(ax)
+		if cbar_mode=='None':
+			for ax in axgrid.cbar_axes: 
+				fig._axstack.remove(ax)
 
-		for i in range(numberofplots):
-			plot_manager(options.list[i].getfieldvalue('model',md),options.list[i],fig,axgrid[i])
-
+		for i,ax in enumerate(axgrid.axes_all):
+			plot_manager(options.list[i].getfieldvalue('model',md),options.list[i],fig,axgrid,i)
 		fig.show()
 	else:
Index: /issm/trunk-jpl/src/py3/plot/processdata.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/processdata.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/processdata.py	(revision 23670)
@@ -1,108 +1,138 @@
-from math import isnan
-import numpy as np
+import numpy as  np
 
 def processdata(md,data,options):
-    """
-    PROCESSDATA - process data to be plotted
+	"""
+	PROCESSDATA - process data to be plotted
+	
+	datatype = 1 -> elements
+	datatype = 2 -> nodes
+	datatype = 3 -> node quivers
+	datatype = 4 -> patch
+	
+	Usage:
+	data,datatype=processdata(md,data,options);
+	
+	See also: PLOTMODEL, PROCESSMESH
+	"""
+	# {{{ Initialisation and grabbing auxiliaries
+	# check format
+	if (len(data)==0 or (len(data)==1 and not isinstance(data,dict) and np.isnan(data).all())):
+		raise ValueError("processdata error message: 'data' provided is empty")
+	# get the shape
+	if 'numberofvertices2d' in dir(md.mesh):
+		numberofvertices2d=md.mesh.numberofvertices2d
+		numberofelements2d=md.mesh.numberofelements2d
+	else:
+		numberofvertices2d=np.nan
+		numberofelements2d=np.nan
+	procdata=np.copy(data)
+	#initialize datatype
+	datatype=0
+	# get datasize
+	if np.ndim(procdata)==1:
+		datasize=(np.shape(procdata)[0],1)
+	elif np.ndim(procdata)==2:
+		datasize=np.shape(procdata)
+	elif np.ndim(procdata)==3:
+		if np.shape(procdata)[0]==2:
+			#treating a dim two list that needs to be stacked
+			procdata=np.hstack((procdata[0,:,:],procdata[1,:,:]))
+			datasize=np.shape(procdata)
+		else:
+			raise ValueError('data list contains more than two vectore, we can not cope with that')
+	else:
+		raise ValueError('data passed to plotmodel has bad dimensions; check that column vectors are rank-1')
+  # }}}      
+	# {{{ process NaN's if any
+	nanfill=options.getfieldvalue('nan',-9999)
+	if np.any(np.isnan(procdata)):
+		lb=np.nanmin(procdata)
+		ub=np.nanmax(procdata)
+		if lb==ub:
+			lb=lb-0.5
+			ub=ub+0.5
+			nanfill=lb-1
+			#procdata[np.isnan(procdata)]=nanfill
+		procdata=np.ma.array(procdata,mask=np.isnan(procdata))
+		options.addfielddefault('clim',[lb,ub])
+		options.addfielddefault('cmap_set_under','1')
+		print("WARNING: nan's treated as", nanfill, "by default.  Change using pairoption 'nan',nan_fill_value in plotmodel call")
+  # }}}  
+	# {{{ log
+	if options.exist('log'):
+		cutoff=options.getfieldvalue('log',1)
+		procdata[np.where(procdata<cutoff)]=cutoff
+	# }}}
+	# {{{ quiver plot
+	if datasize[1]>1 and datasize[0]!= md.mesh.numberofvertices+1:
+		if datasize[0]==md.mesh.numberofvertices and datasize[1]==2:
+			datatype=3
+		else:
+			raise ValueError('plotmodel error message: data should have two columns of length md.mesh.numberofvertices for a quiver plot')
+	# }}}  
+	# {{{ element data
+
+	if datasize[0]==md.mesh.numberofelements and datasize[1]==1:
+		#initialize datatype if non patch
+		if datatype!=4 and datatype!=5:
+			datatype=1
+		# {{{mask
+		if options.exist('mask'):
+			flags=options.getfieldvalue('mask')
+			hide=np.invert(flags)
+			if np.size(flags)==md.mesh.numberofvertices:
+				EltMask=np.asarray([np.any(np.in1d(index,np.where(hide))) for index in md.mesh.elements-1])
+				procdata=np.ma.array(procdata,mask=EltMask)
+				options.addfielddefault('cmap_set_bad','w')
+			elif np.size(flags)==md.mesh.numberofelements:
+				procdata=np.ma.array(procdata,mask=hide)
+				options.addfielddefault('cmap_set_bad','w')
+			else:
+				print('plotmodel warning: mask length not supported yet (supported length are md.mesh.numberofvertices and md.mesh.numberofelements')
+		# }}}  
+
+	# }}}  
+	# {{{ node data
+	if datasize[0]==md.mesh.numberofvertices and datasize[1]==1:
+		datatype=2
+		# {{{ Mask
+		if options.exist('mask'):
+			flags=options.getfieldvalue('mask')
+			hide=np.invert(flags)
+			if np.size(flags)==md.mesh.numberofvertices:
+				procdata=np.ma.array(procdata,mask=hide)
+				options.addfielddefault('cmap_set_bad','w')
+			elif np.size(flags)==md.mesh.numberofelements:
+				NodeMask=np.zeros(np.shape(md.mesh.x),dtype=bool)
+				HideElt=md.mesh.elements[np.where(hide)[0]]-1
+				NodeMask[HideElt]=True
+				procdata=np.ma.array(procdata,mask=NodeMask)
+				options.addfielddefault('cmap_set_bad','w')
+			else:
+				print('plotmodel warning: mask length not supported yet (supported length are md.mesh.numberofvertices and md.mesh.numberofelements')
+	  # }}}  
+	# }}}  
+	# {{{ spc time series
+	if datasize[0]==md.mesh.numberofvertices+1:
+		datatype=2
+		spccol=options.getfieldvalue('spccol',0)
+		print('multiple-column spc field; specify column to plot using option "spccol"')
+		print('column ', spccol, ' plotted for time: ', procdata[-1,spccol])
+		procdata=procdata[0:-1,spccol]
     
-    	datatype = 1 -> elements
-    	datatype = 2 -> nodes
-    	datatype = 3 -> node quivers
-    	datatype = 4 -> patch
-    
-    	Usage:
-    		data,datatype=processdata(md,data,options);
-    
-    	See also: PLOTMODEL, PROCESSMESH
-    """
-    
-    #check format
-    if (len(data)==0 or (len(data)==1 and not isinstance(data,dict) and isnan(data).all())):
-        raise ValueError("processdata error message: 'data' provided is empty")
-    
-    #needed later on
-    if 'numberofvertices2d' in dir(md.mesh):
-    	numberofvertices2d=md.mesh.numberofvertices2d
-    	numberofelements2d=md.mesh.numberofelements2d
-    else:
-    	numberofvertices2d=np.nan
-    	numberofelements2d=np.nan
-    
-    procdata=np.copy(data)
-    
-    #process patch
-    
-    #initialize datatype
-    datatype=0
-    
-    #get datasize
-    if np.ndim(procdata)==1:
-    	datasize=np.array([len(procdata),1])
-    else:
-    	datasize=np.shape(procdata)
-        if len(datasize)>2:
-            raise ValueError('data passed to plotmodel has more than 2 dimensions; check that column vectors are rank-1')
-    
-    #process NaN's if any
-    nanfill=options.getfieldvalue('nan',-9999)
-    if np.any(np.isnan(procdata)):
-    	lb=np.min(data[~np.isnan(data)])
-    	ub=np.max(data[~np.isnan(data)])
-    	if lb==ub:
-    	    lb=lb-0.5
-    	    ub=ub+0.5
-    	    nanfill=lb-1
-    	procdata[np.isnan(procdata)]=nanfill
-    	options.addfielddefault('clim',[lb,ub])
-    	options.addfielddefault('cmap_set_under','1')
-    	print(("WARNING: nan's treated as", nanfill, "by default.  Change using pairoption 'nan',nan_fill_value in plotmodel call"))
-    
-    #quiver plot
-    if datasize[1]>1 and datasize[0]!= md.mesh.numberofvertices+1:
-        if datasize[0]==md.mesh.numberofvertices and datasize[1]==2:
-            datatype=3
-        else:
-            raise ValueError('plotmodel error message: data should have two columns of length md.mesh.numberofvertices for a quiver plot')
-    
-    #non-patch processing 
-    
-    #element data
-    if datasize[0]==md.mesh.numberofelements and datasize[1]==1:
-    	
-    	#initialize datatype if non patch
-    	if datatype!=4 and datatype!=5:
-    	    datatype=1
-    
-    	#mask?
-    
-    	#log?
-    
-    #node data
-    if datasize[0]==md.mesh.numberofvertices and datasize[1]==1:
-    	datatype=2
-    
-    #spc time series? 
-    if datasize[0]==md.mesh.numberofvertices+1:
-    	datatype=2
-        spccol=options.getfieldvalue('spccol',0)
-        print('multiple-column spc field; specify column to plot using option "spccol"')
-        print(('column ', spccol, ' plotted for time: ', procdata[-1,spccol]))
-        procdata=procdata[0:-1,spccol]
-    
-    	#mask?
-    
-    	#log?
+		#mask?
     
     #layer projection?
     
     #control arrow density if quiver plot
-    
-    #convert rank-2 array to rank-1
-    if np.ndim(procdata)==2 and np.shape(procdata)[1]==1:
-    	procdata=procdata.reshape(-1,)
-    
-    #if datatype is still zero, error out
-    if datatype==0:
-    	raise ValueError("processdata error: data provided not recognized or not supported")
-    else:
-    	return procdata, datatype
+	# }}}  
+	# {{{ convert rank-2 array to rank-1
+	if np.ndim(procdata)==2 and np.shape(procdata)[1]==1:
+		procdata=procdata.reshape(-1,)
+	# }}}  
+	# {{{ if datatype is still zero, error out
+	if datatype==0:
+		raise ValueError("processdata error: data provided not recognized or not supported")
+	else:
+		return procdata, datatype
+  # }}}  
Index: /issm/trunk-jpl/src/py3/plot/processmesh.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/processmesh.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/processmesh.py	(revision 23670)
@@ -1,71 +1,47 @@
 from math import isnan
-import MatlabFuncs as m
-import numpy as np
+import numpy as  np
 
 def processmesh(md,data,options):
 	"""
 	PROCESSMESH - process the mesh for plotting
-
+	
 	Usage:
-		x,y,z,elements,is2d=processmech(md,data,options)
-
+	x,y,z,elements,is2d=processmech(md,data,options)
+	
 	See also: PLOTMODEL, PROCESSDATA
 	"""
-
-	#some checks
+	
+	# {{{ check mesh size parameters
 	if md.mesh.numberofvertices==0:
 		raise ValueError('processmesh error: mesh is empty')
 	if md.mesh.numberofvertices==md.mesh.numberofelements:
 		raise ValueError('processmesh error: the number of elements is the same as the number of nodes')
+	# }}}
+  # {{{ treating coordinates
 
-	if len(data)==0 or not isinstance(data,dict):
+	try:
+		z=md.mesh.z
+	except AttributeError:
+		z=np.zeros(np.shape(md.mesh.x))
+	elements=md.mesh.elements-1
+	
+	if options.getfieldvalue('layer',0)>=1:
+		x=md.mesh.x2d
+		y=md.mesh.y2d
+		z=np.zeros(np.shape(x))
+		elements=md.mesh.elements2d-1
+	elif 'latlon' in options.getfieldvalue('coord','xy'):
+		x=md.mesh.long
+		y=md.mesh.lat
+	else:
+		x=md.mesh.x
+		y=md.mesh.y
+
+	#is it a 2D plot?
+	if md.mesh.dimension()==2 or options.getfieldvalue('layer',0)>=1:
+		is2d=1
+	else:
+		is2d=0
 		
-		if 'latlon' not in options.getfieldvalue('coord','xy').lower(): #convert to lower case for comparison
-			x=md.mesh.x
-			if 'x2d' in dir(md.mesh): x2d=md.mesh.x2d
-			y=md.mesh.y
-			if 'y2d' in dir(md.mesh): y2d=md.mesh.x2d
-		else:
-			x=md.mesh.long
-			y=md.mesh.lat
-
-		if 'z' in dir(md.mesh):
-			z=md.mesh.z
-		else:
-			z=np.zeros_like(md.mesh.x)
-		
-		if 'elements2d' in dir(md.mesh): 
-			elements2d=md.mesh.elements2d
-			elements2d=elements2d-1  # subtract one since python indexes from zero
-		elements=md.mesh.elements
-		elements=elements-1
-
-		#is it a 2D plot?
-		if md.mesh.dimension()==2:
-			is2d=1
-		else:
-			if options.getfieldvalue('layer',0)>=1:
-				is2d=1
-			else:
-				is2d=0
-
-		#layer projection?
-		if options.getfieldvalue('layer',0)>=1:
-			 if 'latlon' in options.getfieldvalue('coord','xy').lower():
-				 raise ValueError('processmesh error: cannot work with 3D mesh in lat-lon coords')
-			#we modify the mesh temporarily to a 2D mesh from which the 3D mesh was extruded
-			 x=x2d
-			 y=y2d
-			 z=zeros(size(x2d))
-			 elements=elements2d
-	
-	else:
-		#Process mesh for plotting 
-		if md.mesh.dimension()==2:
-			is2d=1
-		else:
-			# process polycollection here for 3D plot
-			is2d=0
-	
 	#units
 	if options.exist('unit'):
Index: /issm/trunk-jpl/src/py3/plot/writejsfield.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/writejsfield.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/writejsfield.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 def writejsfield(fid,name,variable,nods):
 #WRITEJSFIELD - write variable to javascript file 
@@ -8,5 +8,5 @@
 	#write array:
 	#if not isinstance(variable, list):
-	if type(variable[0])==numpy.float64:
+	if type(variable[0])==np.float64:
 		fid.write('<!-- {0}{{{{{{-->\n'.format(name))
 		fid.write('{0}=['.format(name))
Index: /issm/trunk-jpl/src/py3/plot/writejsfile.py
===================================================================
--- /issm/trunk-jpl/src/py3/plot/writejsfile.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/plot/writejsfile.py	(revision 23670)
@@ -1,3 +1,3 @@
-import numpy
+import numpy as np
 from writejsfield import writejsfield
 def writejsfile(filename,model,keyname):
@@ -48,5 +48,5 @@
 		fid.write('result["shortlabel"]="{0}";\n'.format(results[i].shortlabel))
 		fid.write('result["unit"]="{0}";\n'.format(results[i].unit))
-		if type(results[i].data)==numpy.float64:
+		if type(results[i].data)==np.float64:
 			fid.write('result["time_range"]=[{0},{1}];\n'.format(results[i].time_range[0],results[i].time_range[1]))
 		fid.write('results["{0}"]=result;\n'.format(i))
Index: /issm/trunk-jpl/src/py3/shp/shp2exp.py
===================================================================
--- /issm/trunk-jpl/src/py3/shp/shp2exp.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/shp/shp2exp.py	(revision 23670)
@@ -33,5 +33,5 @@
 		geom=shp.shapes()[i].shapeType
 		if geom==5: # polygon
-         expdict['closed']=1
+			expdict['closed']=1
 			tmpx=[p[0] for p in shp.shapes()[i].points]
 			tmpy=[q[1] for q in shp.shapes()[i].points]
@@ -39,5 +39,5 @@
 			y.append(tmpy)
 		elif geom==3: # line
-         expdict['closed']=0
+			expdict['closed']=0
 			tmpx=[p[0] for p in shp.shapes()[i].points]
 			tmpy=[q[1] for q in shp.shapes()[i].points]
@@ -45,5 +45,5 @@
 			y.append(tmpy)
 		elif geom==1: # point
-         expdict['closed']=0
+			expdict['closed']=0
 			x.append(shp.shapes()[i].points[0][0])
 			y.append(shp.shapes()[i].points[0][1])
Index: /issm/trunk-jpl/src/py3/solve/WriteData.py
===================================================================
--- /issm/trunk-jpl/src/py3/solve/WriteData.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solve/WriteData.py	(revision 23670)
@@ -1,14 +1,11 @@
-import numpy
-import math
+import numpy as np
 import struct
 import pairoptions
 import MatlabFuncs as m
-from EnumDefinitions import *
-from EnumToString import EnumToString
-
-def WriteData(fid,**kwargs):
+
+def WriteData(fid,prefix,*args):
 	"""
 	WRITEDATA - write model field in binary file
- 
+
 	   Usage:
 	      WriteData(fid,varargin)
@@ -16,5 +13,5 @@
 
 	#process options
-	options=pairoptions.pairoptions(**kwargs)
+	options=pairoptions.pairoptions(*args)
 
 	#Get data properties
@@ -24,13 +21,14 @@
 		fieldname = options.getfieldvalue('fieldname')
 		classname = options.getfieldvalue('class',str(type(obj)).rsplit('.')[-1].split("'")[0])
-		if options.exist('enum'):
-			enum = options.getfieldvalue('enum')
-		else:
-			enum = BuildEnum(classname+'_'+fieldname)
-		data      = getattr(obj,fieldname)
+		name      = options.getfieldvalue('name',prefix+'.'+fieldname);
+		if options.exist('data'):
+			data = options.getfieldvalue('data')
+		else:
+			data      = getattr(obj,fieldname)
 	else:
 		#No processing required
 		data = options.getfieldvalue('data')
-		enum = options.getfieldvalue('enum')
+		name = options.getfieldvalue('name')
+
 	format  = options.getfieldvalue('format')
 	mattype = options.getfieldvalue('mattype',0)    #only required for matrices
@@ -44,31 +42,31 @@
 	#Scale data if necesarry
 	if options.exist('scale'):
+		data=np.array(data)
 		scale = options.getfieldvalue('scale')
-		if numpy.size(data) > 1 :
-			if numpy.size(data,0)==timeserieslength:
-				data=numpy.array(data)
-				data[0:-1,:] = scale*data[0:-1,:]
-			else:
-				data  = scale*data
+		if np.size(data) > 1 and np.ndim(data) > 1 and np.size(data,0)==timeserieslength:
+			data[0:-1,:] = scale*data[0:-1,:]
 		else:
 			data  = scale*data
-	if numpy.size(data) > 1 :
-		if numpy.size(data,0)==timeserieslength:
-			yts=365.0*24.0*3600.0
+	if np.size(data) > 1 and np.size(data,0)==timeserieslength:
+		yts = options.getfieldvalue('yts')
+		if np.ndim(data) > 1:
 			data[-1,:] = yts*data[-1,:]
+		else:
+			data[-1] = yts*data[-1]
 
 	#Step 1: write the enum to identify this record uniquely
-	fid.write(struct.pack('i',enum)) 
+	fid.write(struct.pack('i',len(name)))
+	fid.write(struct.pack('%ds' % len(name),name))
 
 	#Step 2: write the data itself.
 	if   m.strcmpi(format,'Boolean'):    # {{{
 #		if len(data) !=1:
-#			raise ValueError('field %s cannot be marshalled as it has more than one element!' % EnumToString(enum)[0])
+#			raise ValueError('field %s cannot be marshalled as it has more than one element!' % name[0])
 
 		#first write length of record
 		fid.write(struct.pack('i',4+4))  #1 bool (disguised as an int)+code
 
-		#write data code: 
-		fid.write(struct.pack('i',FormatToCode(format))) 
+		#write data code:
+		fid.write(struct.pack('i',FormatToCode(format)))
 
 		#now write integer
@@ -78,28 +76,28 @@
 	elif m.strcmpi(format,'Integer'):    # {{{
 #		if len(data) !=1:
-#			raise ValueError('field %s cannot be marshalled as it has more than one element!' % EnumToString(enum)[0])
+#			raise ValueError('field %s cannot be marshalled as it has more than one element!' % name[0])
 
 		#first write length of record
 		fid.write(struct.pack('i',4+4))  #1 integer + code
 
-		#write data code: 
-		fid.write(struct.pack('i',FormatToCode(format))) 
+		#write data code:
+		fid.write(struct.pack('i',FormatToCode(format)))
 
 		#now write integer
-		fid.write(struct.pack('i',data)) 
+		fid.write(struct.pack('i',data))
 		# }}}
 
 	elif m.strcmpi(format,'Double'):    # {{{
 #		if len(data) !=1:
-#			raise ValueError('field %s cannot be marshalled as it has more than one element!' % EnumToString(enum)[0])
+#			raise ValueError('field %s cannot be marshalled as it has more than one element!' % name[0])
 
 		#first write length of record
 		fid.write(struct.pack('i',8+4))  #1 double+code
 
-		#write data code: 
-		fid.write(struct.pack('i',FormatToCode(format))) 
+		#write data code:
+		fid.write(struct.pack('i',FormatToCode(format)))
 
 		#now write double
-		fid.write(struct.pack('d',data)) 
+		fid.write(struct.pack('d',data))
 		# }}}
 
@@ -108,10 +106,10 @@
 		fid.write(struct.pack('i',len(data)+4+4))  #string + string size + code
 
-		#write data code: 
-		fid.write(struct.pack('i',FormatToCode(format))) 
+		#write data code:
+		fid.write(struct.pack('i',FormatToCode(format)))
 
 		#now write string
-		fid.write(struct.pack('i',len(data))) 
-		fid.write(struct.pack('%ds' % len(data),data)) 
+		fid.write(struct.pack('i',len(data)))
+		fid.write(struct.pack('%ds' % len(data),data))
 		# }}}
 
@@ -119,10 +117,10 @@
 
 		if   isinstance(data,bool):
-			data=numpy.array([data])
+			data=np.array([data])
 		elif isinstance(data,(list,tuple)):
-			data=numpy.array(data).reshape(-1,1)
-		if numpy.ndim(data) == 1:
-			if numpy.size(data):
-				data=data.reshape(numpy.size(data),1)
+			data=np.array(data).reshape(-1,)
+		if np.ndim(data) == 1:
+			if np.size(data):
+				data=data.reshape(np.size(data),)
 			else:
 				data=data.reshape(0,0)
@@ -131,20 +129,26 @@
 		s=data.shape
 		#if matrix = NaN, then do not write anything
-		if s[0]==1 and s[1]==1 and math.isnan(data[0][0]):
+		if np.ndim(data)==2 and np.product(s)==1 and np.all(np.isnan(data)):
 			s=(0,0)
 
 		#first write length of record
-		fid.write(struct.pack('i',4+4+8*s[0]*s[1]+4+4))    #2 integers (32 bits) + the double matrix + code + matrix type
-
-		#write data code and matrix type: 
-		fid.write(struct.pack('i',FormatToCode(format))) 
+		fid.write(struct.pack('i',4+4+8*np.product(s)+4+4))    #2 integers (32 bits) + the double matrix + code + matrix type
+
+		#write data code and matrix type:
+		fid.write(struct.pack('i',FormatToCode(format)))
 		fid.write(struct.pack('i',mattype))
 
 		#now write matrix
-		fid.write(struct.pack('i',s[0])) 
-		fid.write(struct.pack('i',s[1])) 
-		for i in range(s[0]):
-			for j in range(s[1]):
-				fid.write(struct.pack('d',float(data[i][j])))    #get to the "c" convention, hence the transpose
+		if np.ndim(data)==1:
+			fid.write(struct.pack('i',s[0]))
+			fid.write(struct.pack('i',1))
+			for i in range(s[0]):
+				fid.write(struct.pack('d',float(data[i])))    #get to the "c" convention, hence the transpose
+		else:
+			fid.write(struct.pack('i',s[0]))
+			fid.write(struct.pack('i',s[1]))
+			for i in range(s[0]):
+				for j in range(s[1]):
+					fid.write(struct.pack('d',float(data[i][j])))    #get to the "c" convention, hence the transpose
 		# }}}
 
@@ -152,10 +156,10 @@
 
 		if   isinstance(data,int):
-			data=numpy.array([data])
+			data=np.array([data])
 		elif isinstance(data,(list,tuple)):
-			data=numpy.array(data).reshape(-1,1)
-		if numpy.ndim(data) == 1:
-			if numpy.size(data):
-				data=data.reshape(numpy.size(data),1)
+			data=np.array(data).reshape(-1,)
+		if np.ndim(data) == 1:
+			if np.size(data):
+				data=data.reshape(np.size(data),)
 			else:
 				data=data.reshape(0,0)
@@ -164,20 +168,26 @@
 		s=data.shape
 		#if matrix = NaN, then do not write anything
-		if s[0]==1 and s[1]==1 and math.isnan(data[0][0]):
+		if np.ndim(data)==2 and np.product(s)==1 and np.all(np.isnan(data)):
 			s=(0,0)
 
 		#first write length of record
-		fid.write(struct.pack('i',4+4+8*s[0]*s[1]+4+4))    #2 integers (32 bits) + the double matrix + code + matrix type
-
-		#write data code and matrix type: 
-		fid.write(struct.pack('i',FormatToCode(format))) 
+		fid.write(struct.pack('i',4+4+8*np.product(s)+4+4))    #2 integers (32 bits) + the double matrix + code + matrix type
+
+		#write data code and matrix type:
+		fid.write(struct.pack('i',FormatToCode(format)))
 		fid.write(struct.pack('i',mattype))
 
 		#now write matrix
-		fid.write(struct.pack('i',s[0])) 
-		fid.write(struct.pack('i',s[1])) 
-		for i in range(s[0]):
-			for j in range(s[1]):
-				fid.write(struct.pack('d',float(data[i][j])))    #get to the "c" convention, hence the transpose
+		if np.ndim(data) == 1:
+			fid.write(struct.pack('i',s[0]))
+			fid.write(struct.pack('i',1))
+			for i in range(s[0]):
+				fid.write(struct.pack('d',float(data[i])))    #get to the "c" convention, hence the transpose
+		else:
+			fid.write(struct.pack('i',s[0]))
+			fid.write(struct.pack('i',s[1]))
+			for i in range(s[0]):
+				for j in range(s[1]):
+					fid.write(struct.pack('d',float(data[i][j])))    #get to the "c" convention, hence the transpose
 		# }}}
 
@@ -185,10 +195,10 @@
 
 		if   isinstance(data,(bool,int,float)):
-			data=numpy.array([data])
+			data=np.array([data])
 		elif isinstance(data,(list,tuple)):
-			data=numpy.array(data).reshape(-1,1)
-		if numpy.ndim(data) == 1:
-			if numpy.size(data):
-				data=data.reshape(numpy.size(data),1)
+			data=np.array(data).reshape(-1,)
+		if np.ndim(data) == 1:
+			if np.size(data):
+				data=data.reshape(np.size(data),)
 			else:
 				data=data.reshape(0,0)
@@ -197,24 +207,100 @@
 		s=data.shape
 		#if matrix = NaN, then do not write anything
-		if s[0]==1 and s[1]==1 and math.isnan(data[0][0]):
+		if np.ndim(data)==1 and np.product(s)==1 and np.all(np.isnan(data)):
 			s=(0,0)
 
 		#first write length of record
-		recordlength=4+4+8*s[0]*s[1]+4+4; #2 integers (32 bits) + the double matrix + code + matrix type
-		if recordlength > 2**31 :
-			raise ValueError('field %s cannot be marshalled because it is larger than 4^31 bytes!' % EnumToString(enum)[0])
+		recordlength=4+4+8*np.product(s)+4+4; #2 integers (32 bits) + the double matrix + code + matrix type
+		if recordlength > 4**31 :
+			raise ValueError('field %s cannot be marshalled because it is larger than 4^31 bytes!' % enum)
 
 		fid.write(struct.pack('i',recordlength))  #2 integers (32 bits) + the double matrix + code + matrix type
 
-		#write data code and matrix type: 
-		fid.write(struct.pack('i',FormatToCode(format))) 
+		#write data code and matrix type:
+		fid.write(struct.pack('i',FormatToCode(format)))
 		fid.write(struct.pack('i',mattype))
 
 		#now write matrix
-		fid.write(struct.pack('i',s[0])) 
-		fid.write(struct.pack('i',s[1])) 
-		for i in range(s[0]):
+		if np.ndim(data) == 1:
+			fid.write(struct.pack('i',s[0]))
+			fid.write(struct.pack('i',1))
+			for i in range(s[0]):
+				fid.write(struct.pack('d',float(data[i])))    #get to the "c" convention, hence the transpose
+		else:
+			fid.write(struct.pack('i',s[0]))
+			fid.write(struct.pack('i',s[1]))
+			for i in range(s[0]):
+				for j in range(s[1]):
+					fid.write(struct.pack('d',float(data[i][j])))    #get to the "c" convention, hence the transpose
+		# }}}
+
+	elif m.strcmpi(format,'CompressedMat'):    # {{{
+
+		if   isinstance(data,(bool,int,float)):
+			data=np.array([data])
+		elif isinstance(data,(list,tuple)):
+			data=np.array(data).reshape(-1,)
+		if np.ndim(data) == 1:
+			if np.size(data):
+				data=data.reshape(np.size(data),)
+			else:
+				data=data.reshape(0,0)
+
+		#Get size
+		s=data.shape
+		if np.ndim(data) == 1:
+		   n2=1
+		else:
+			n2=s[1]
+
+		#if matrix = NaN, then do not write anything
+		if np.ndim(data)==1 and np.product(s)==1 and np.all(np.isnan(data)):
+			s=(0,0)
+			n2=0
+
+		#first write length of record
+		recordlength=4+4+8+8+1*(s[0]-1)*n2+8*n2+4+4 #2 integers (32 bits) + the matrix + code + matrix type
+		if recordlength > 4**31 :
+			raise ValueError('field %s cannot be marshalled because it is larger than 4^31 bytes!' % enum)
+
+		fid.write(struct.pack('i',recordlength))  #2 integers (32 bits) + the matrix + code + matrix type
+
+		#write data code and matrix type:
+		fid.write(struct.pack('i',FormatToCode(format)))
+		fid.write(struct.pack('i',mattype))
+
+		#Write offset and range
+		A = data[0:s[0]-1]
+		offsetA = A.min()
+		rangeA = A.max() - offsetA
+
+		if rangeA == 0:
+			A = A*0
+		else:
+			A = (A-offsetA)/rangeA*255.
+
+		#now write matrix
+		if np.ndim(data) == 1:
+			fid.write(struct.pack('i',s[0]))
+			fid.write(struct.pack('i',1))
+			fid.write(struct.pack('d',float(offsetA)))
+			fid.write(struct.pack('d',float(rangeA)))
+			for i in range(s[0]-1):
+				fid.write(struct.pack('B',int(A[i])))
+
+			fid.write(struct.pack('d',float(data[s[0]-1])))    #get to the "c" convention, hence the transpose
+
+		elif np.product(s) > 0:
+			fid.write(struct.pack('i',s[0]))
+			fid.write(struct.pack('i',s[1]))
+			fid.write(struct.pack('d',float(offsetA)))
+			fid.write(struct.pack('d',float(rangeA)))
+			for i in range(s[0]-1):
+				for j in range(s[1]):
+					fid.write(struct.pack('B',int(A[i][j])))    #get to the "c" convention, hence the transpose
+
 			for j in range(s[1]):
-				fid.write(struct.pack('d',float(data[i][j])))    #get to the "c" convention, hence the transpose
+				fid.write(struct.pack('d',float(data[s[0]-1][j])))
+
 		# }}}
 
@@ -225,40 +311,46 @@
 		for matrix in data:
 			if   isinstance(matrix,(bool,int,float)):
-				matrix=numpy.array([matrix])
+				matrix=np.array([matrix])
 			elif isinstance(matrix,(list,tuple)):
-				matrix=numpy.array(matrix).reshape(-1,1)
-			if numpy.ndim(matrix) == 1:
-				if numpy.size(matrix):
-					matrix=matrix.reshape(numpy.size(matrix),1)
+				matrix=np.array(matrix).reshape(-1,)
+			if np.ndim(matrix) == 1:
+				if np.size(matrix):
+					matrix=matrix.reshape(np.size(matrix),)
 				else:
 					matrix=matrix.reshape(0,0)
 
 			s=matrix.shape
-			recordlength+=4*2+s[0]*s[1]*8    #row and col of matrix + matrix of doubles
+			recordlength+=4*2+np.product(s)*8    #row and col of matrix + matrix of doubles
 
 		#write length of record
-		fid.write(struct.pack('i',recordlength)) 
-
-		#write data code: 
-		fid.write(struct.pack('i',FormatToCode(format))) 
+		fid.write(struct.pack('i',recordlength))
+
+		#write data code:
+		fid.write(struct.pack('i',FormatToCode(format)))
 
 		#write data, first number of records
-		fid.write(struct.pack('i',len(data))) 
-
-		#write each matrix: 
+		fid.write(struct.pack('i',len(data)))
+
 		for matrix in data:
 			if   isinstance(matrix,(bool,int,float)):
-				matrix=numpy.array([matrix])
+				matrix=np.array([matrix])
 			elif isinstance(matrix,(list,tuple)):
-				matrix=numpy.array(matrix).reshape(-1,1)
-			if numpy.ndim(matrix) == 1:
-				matrix=matrix.reshape(numpy.size(matrix),1)
+				matrix=np.array(matrix).reshape(-1,)
+			if np.ndim(matrix) == 1:
+				matrix=matrix.reshape(np.size(matrix),)
 
 			s=matrix.shape
-			fid.write(struct.pack('i',s[0])) 
-			fid.write(struct.pack('i',s[1])) 
-			for i in range(s[0]):
-				for j in range(s[1]):
-					fid.write(struct.pack('d',float(matrix[i][j])))
+
+			if np.ndim(matrix) == 1:
+				fid.write(struct.pack('i',s[0]))
+				fid.write(struct.pack('i',1))
+				for i in range(s[0]):
+					fid.write(struct.pack('d',float(matrix[i])))    #get to the "c" convention, hence the transpose
+			else:
+				fid.write(struct.pack('i',s[0]))
+				fid.write(struct.pack('i',s[1]))
+				for i in range(s[0]):
+					for j in range(s[1]):
+						fid.write(struct.pack('d',float(matrix[i][j])))
 		# }}}
 
@@ -271,49 +363,26 @@
 
 		#write length of record
-		fid.write(struct.pack('i',recordlength)) 
-
-		#write data code: 
-		fid.write(struct.pack('i',FormatToCode(format))) 
+		fid.write(struct.pack('i',recordlength))
+
+		#write data code:
+		fid.write(struct.pack('i',FormatToCode(format)))
 
 		#now write length of string array
-		fid.write(struct.pack('i',len(data))) 
+		fid.write(struct.pack('i',len(data)))
 
 		#now write the strings
 		for string in data:
-			fid.write(struct.pack('i',len(string))) 
-			fid.write(struct.pack('%ds' % len(string),string)) 
+			fid.write(struct.pack('i',len(string)))
+			fid.write(struct.pack('%ds' % len(string),string))
 		# }}}
 
 	else:    # {{{
-		raise TypeError('WriteData error message: data type: %d not supported yet! (%s)' % (format,EnumToString(enum)[0]))
+		raise TypeError('WriteData error message: data type: %d not supported yet! (%s)' % (format,enum))
 	# }}}
-
-def BuildEnum(string): # {{{
-	"""
-	BUILDENUM - build enum out of string
- 
-    Usage:
-       enum=BuildEnum(string)
-	"""
-
-	if '_' in string:
-		substrs=string.split('_')
-		string=''
-		for substr in substrs:
-			string+=substr[0].upper()+substr[1:]
-	else:
-		#take first letter of string and make it uppercase: 
-		string=string[0].upper()+string[1:]
-
-	#Get Enum
-	enum=StringToEnum(string)[0]
-
-	return enum
-# }}}
 
 def FormatToCode(format): # {{{
 	"""
-	This routine takes the format string, and hardcodes it into an integer, which 
-	is passed along the record, in order to identify the nature of the dataset being 
+	This routine takes the format string, and hardcodes it into an integer, which
+	is passed along the record, in order to identify the nature of the dataset being
 	sent.
 	"""
@@ -337,4 +406,6 @@
 	elif m.strcmpi(format,'StringArray'):
 		code=9
+	elif m.strcmpi(format,'CompressedMat'):
+		code=10
 	else:
 		raise InputError('FormatToCode error message: data type not supported yet!')
@@ -342,3 +413,2 @@
 	return code
 # }}}
-
Index: /issm/trunk-jpl/src/py3/solve/loadresultsfromcluster.py
===================================================================
--- /issm/trunk-jpl/src/py3/solve/loadresultsfromcluster.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solve/loadresultsfromcluster.py	(revision 23670)
@@ -3,4 +3,6 @@
 import platform
 from loadresultsfromdisk import loadresultsfromdisk
+
+from helpers import *
 
 def loadresultsfromcluster(md,runtimename=False):
@@ -23,6 +25,6 @@
 		filelist.append(md.miscellaneous.name+'.qmu.err')
 		filelist.append(md.miscellaneous.name+'.qmu.out')
-		if 'tabular_graphics_data' in md.qmu.params:
-			if md.qmu.params['tabular_graphics_data']:
+		if 'tabular_graphics_data' in fieldnames(md.qmu.params):
+			if md.qmu.params.tabular_graphics_data:
 				filelist.append('dakota_tabular.dat')
 	else:
@@ -31,9 +33,21 @@
 
 	#If we are here, no errors in the solution sequence, call loadresultsfromdisk.
-	md=loadresultsfromdisk(md,md.miscellaneous.name+'.outbin')
-
+	if os.path.exists(md.miscellaneous.name+'.outbin'):
+		if os.path.getsize(md.miscellaneous.name+'.outbin')>0:
+			md=loadresultsfromdisk(md,md.miscellaneous.name+'.outbin')
+		else:
+			print('WARNING, outbin file is empty for run '+md.miscellaneous.name)
+	elif not md.qmu.isdakota:
+		print('WARNING, outbin file does not exist '+md.miscellaneous.name)
+		
 	#erase the log and output files
 	if md.qmu.isdakota:
-		filename=os.path.join('qmu'+str(os.getpid()),md.miscellaneous.name)
+		#filename=os.path.join('qmu'+str(os.getpid()),md.miscellaneous.name)
+		filename = md.miscellaneous.name
+
+		# this will not work like normal as dakota doesn't generate outbin files,
+		#   instead calls postqmu to store results directly in the model
+		#   at md.results.dakota via dakota_out_parse
+		md=loadresultsfromdisk(md,md.miscellaneous.name+'.outbin')
 	else:
 		filename=md.miscellaneous.name
@@ -49,5 +63,6 @@
 	if hostname==cluster.name:
 		if md.qmu.isdakota:
-			filename=os.path.join('qmu'+str(os.getpid()),md.miscellaneous.name)
+			#filename=os.path.join('qmu'+str(os.getpid()),md.miscellaneous.name)
+			filename = md.miscellaneous.name
 			TryRem('.queue',filename)
 		else:
@@ -59,10 +74,16 @@
 				TryRem('.bat',filename)
 
+		# remove this for bin file debugging
 		TryRem('.bin',filename)
+
+	#cwd = os.getcwd().split('/')[-1]
+	if md.qmu.isdakota:
+		os.chdir('..')
+		#TryRem('',cwd)
 
 	return md
 
 def TryRem(extension,filename):
-	try:	
+	try:
 		os.remove(filename+extension)
 	except OSError:
Index: /issm/trunk-jpl/src/py3/solve/loadresultsfromdisk.py
===================================================================
--- /issm/trunk-jpl/src/py3/solve/loadresultsfromdisk.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solve/loadresultsfromdisk.py	(revision 23670)
@@ -2,6 +2,6 @@
 from results import results
 from parseresultsfromdisk import parseresultsfromdisk
-from EnumToString import EnumToString
 import MatlabFuncs as m
+from postqmu import postqmu
 
 def loadresultsfromdisk(md,filename):
@@ -28,5 +28,5 @@
 
 		#load results onto model
-		structure=parseresultsfromdisk(filename,not md.settings.io_gather)
+		structure=parseresultsfromdisk(md,filename,not md.settings.io_gather)
 		if not len(structure):
 			raise RuntimeError("No result found in binary file '%s'. Check for solution crash." % filename)
@@ -58,10 +58,5 @@
 	#post processes qmu results if necessary
 	else:
-
-		if not isinstance(md.private.solution,str):
-			[md.private.solution]=EnumToString(md.private.solution)
-		md=postqmu(md)
-		os.chdir('..')
+		md=postqmu(md,filename)
 
 	return md
-
Index: /issm/trunk-jpl/src/py3/solve/marshall.py
===================================================================
--- /issm/trunk-jpl/src/py3/solve/marshall.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solve/marshall.py	(revision 23670)
@@ -1,4 +1,3 @@
 from WriteData import WriteData
-from EnumDefinitions import *
 
 def marshall(md):
@@ -12,6 +11,6 @@
 	      marshall(md)
 	"""
-
-	print("marshalling file '%s.bin'." % md.miscellaneous.name)
+	if md.verbose.solution:
+		print("marshalling file '%s.bin'." % md.miscellaneous.name)
 
 	#open file for binary writing
@@ -21,15 +20,8 @@
 		raise IOError("marshall error message: could not open '%s.bin' file for binary writing." % md.miscellaneous.name)
 
-	#First, write MaximumNumberOfEnum to make sure that the Enums are synchronized
-	WriteData(fid,'enum',MaximumNumberOfDefinitionsEnum(),'data',True,'format','Boolean')
-
-	#Go through all model fields: check that it is a class and call checkconsistency
-	fields=vars(md)
-
-#	for field in fields.iterkeys():
 	for field in md.properties():
 
 		#Some properties do not need to be marshalled
-		if field in ['results','radaroverlay','toolkits','cluster','flaim','private']:
+		if field in ['results','radaroverlay','toolkits','cluster','private']:
 			continue
 
@@ -40,8 +32,8 @@
 		#Marshall current object
 		#print "marshalling %s ..." % field
-		exec("md.%s.marshall(md,fid)" % field)
+		exec("md.{}.marshall('md.{}',md,fid)".format(field,field))
 
-	#Last, write MaximumNumberOfEnum+1 to make sure that the binary file is not corrupt
-	WriteData(fid,'enum',MaximumNumberOfDefinitionsEnum()+1,'data',True,'format','Boolean');
+	#Last, write "md.EOF" to make sure that the binary file is not corrupt
+	WriteData(fid,'XXX','name','md.EOF','data',True,'format','Boolean');
 
 	#close file
Index: /issm/trunk-jpl/src/py3/solve/parseresultsfromdisk.py
===================================================================
--- /issm/trunk-jpl/src/py3/solve/parseresultsfromdisk.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solve/parseresultsfromdisk.py	(revision 23670)
@@ -1,31 +1,16 @@
 import struct
-import numpy
+import numpy as np
 from collections import OrderedDict
 import results as resultsclass
-import MatlabFuncs as m
-
-def parseresultsfromdisk(filename,iosplit):
-	"""
-	PARSERESULTSFROMDISK - ...
-
-	   Usage:
-	      results=parseresultsfromdisk(filename,iosplit)
-	"""
-
+
+def parseresultsfromdisk(md,filename,iosplit):
 	if iosplit:
-		results=parseresultsfromdiskiosplit(filename)
+		saveres=parseresultsfromdiskiosplit(md,filename)
 	else:
-		results=parseresultsfromdiskioserial(filename)
-
-	return results
-
-def parseresultsfromdiskioserial(filename):    # {{{
-	"""
-	PARSERESULTSFROMDISK - ...
-	 
-	    Usage:
-	       results=parseresultsfromdiskioserial(filename)
-	"""
-
+		saveres=parseresultsfromdiskioserial(md,filename)
+
+	return saveres
+
+def parseresultsfromdiskioserial(md,filename):    # {{{
 	#Open file
 	try:
@@ -35,72 +20,58 @@
 
 	#initialize results: 
-	results=[]
-	results.append(None)
+	saveres=[]
 
 	#Read fields until the end of the file.
-	result=ReadData(fid)
+	loadres=ReadData(fid,md)
 
 	counter=0
 	check_nomoresteps=0
-	step=result['step']
-
-	while result:
-
+	step=loadres['step']
+
+	while loadres:
+		#check that the new result does not add a step, which would be an error: 
 		if check_nomoresteps:
-			#check that the new result does not add a step, which would be an error: 
-			if result['step']>=1:
+			if loadres['step']>=1:
 				raise TypeError("parsing results for a steady-state core, which incorporates transient results!")
 
 		#Check step, increase counter if this is a new step
-		if(step!=result['step'] and result['step']>1):
+		if(step!=loadres['step'] and loadres['step']>1):
 			counter = counter + 1
-			step    = result['step']
-
-		#Add result
-		if result['step']==0:
+			step    = loadres['step']
+
+		#Add result
+		if loadres['step']==0:
 			#if we have a step = 0, this is a steady state solution, don't expect more steps. 
 			index = 0;
 			check_nomoresteps=1
-	
-		elif result['step']==1:
+		elif loadres['step']==1:
 			index = 0
 		else:
 			index = counter;
-	
-		if index > len(results)-1:
-			for i in range(len(results)-1,index-1):
-				results.append(None)
-			results.append(resultsclass.results())
 		
-		elif results[index] is None:
-			results[index]=resultsclass.results()
-
+		if index > len(saveres)-1:
+			for i in range(len(saveres)-1,index-1):
+				saveres.append(None)
+			saveres.append(resultsclass.results())
+		elif saveres[index] is None:
+			saveres[index]=resultsclass.results()
 			
 		#Get time and step
-		if result['step'] != -9999.:
-			setattr(results[index],'step',result['step'])
-		if result['time'] != -9999.:
-			setattr(results[index],'time',result['time']) 
-	
-		#Add result
-		if hasattr(results[index],result['fieldname']) and not m.strcmp(result['fieldname'],'SolutionType'):
-			setattr(results[index],result['fieldname'],numpy.vstack((getattr(results[index],result['fieldname']),result['field'])))
-		else:
-			setattr(results[index],result['fieldname'],result['field'])
-
-		#read next result
-		result=ReadData(fid)
+		if loadres['step'] != -9999.:
+			saveres[index].__dict__['step']=loadres['step']
+		if loadres['time'] != -9999.:
+			saveres[index].__dict__['time']=loadres['time']
+
+		#Add result
+		saveres[index].__dict__[loadres['fieldname']]=loadres['field']
+
+		#read next result
+		loadres=ReadData(fid,md)
 
 	fid.close()
 
-	return results
-	# }}}
-def parseresultsfromdiskiosplit(filename):    # {{{
-	"""
-	PARSERESULTSFROMDISKIOSPLIT - ...
-	 
-	    Usage:
-	       results=parseresultsfromdiskiosplit(filename)
-	"""
+	return saveres
+	# }}}
+def parseresultsfromdiskiosplit(md,filename):    # {{{
 
 	#Open file
@@ -110,63 +81,63 @@
 		raise IOError("loadresultsfromdisk error message: could not open '%s' for binary reading." % filename)
 
-	results=[]
+	saveres=[]
 
 	#if we have done split I/O, ie, we have results that are fragmented across patches, 
 	#do a first pass, and figure out the structure of results
-	result=ReadDataDimensions(fid)
-	while result:
+	loadres=ReadDataDimensions(fid)
+	while loadres:
 
 		#Get time and step
-		if result['step'] > len(results):
-			for i in range(len(results),result['step']-1):
-				results.append(None)
-			results.append(resultsclass.results())
-		setattr(results[result['step']-1],'step',result['step'])
-		setattr(results[result['step']-1],'time',result['time']) 
-
-		#Add result
-		setattr(results[result['step']-1],result['fieldname'],float('NaN'))
-
-		#read next result
-		result=ReadDataDimensions(fid)
+		if loadres['step'] > len(saveres):
+			for i in range(len(saveres),loadres['step']-1):
+				saveres.append(None)
+			saveres.append(resultsclass.results())
+		setattr(saveres[loadres['step']-1],'step',loadres['step'])
+		setattr(saveres[loadres['step']-1],'time',loadres['time']) 
+
+		#Add result
+		setattr(saveres[loadres['step']-1],loadres['fieldname'],float('NaN'))
+
+		#read next result
+		loadres=ReadDataDimensions(fid)
 
 	#do a second pass, and figure out the size of the patches
 	fid.seek(0)    #rewind
-	result=ReadDataDimensions(fid)
-	while result:
-
-		#read next result
-		result=ReadDataDimensions(fid)
+	loadres=ReadDataDimensions(fid)
+	while loadres:
+
+		#read next result
+		loadres=ReadDataDimensions(fid)
 
 	#third pass, this time to read the real information
 	fid.seek(0)    #rewind
-	result=ReadData(fid)
-	while result:
+	loadres=ReadData(fid,md)
+	while loadres:
 
 		#Get time and step
-		if result['step']> len(results):
-			for i in range(len(results),result['step']-1):
-				results.append(None)
-			results.append(resultsclass.results())
-		setattr(results[result['step']-1],'step',result['step'])
-		setattr(results[result['step']-1],'time',result['time']) 
-
-		#Add result
-		setattr(results[result['step']-1],result['fieldname'],result['field'])
-
-		#read next result
-		result=ReadData(fid)
+		if loadres['step']> len(saveres):
+			for i in range(len(saveres),loadres['step']-1):
+				saveres.append(None)
+			saveres.append(saveresclass.saveres())
+		setattr(saveres[loadres['step']-1],'step',loadres['step'])
+		setattr(saveres[loadres['step']-1],'time',loadres['time']) 
+
+		#Add result
+		setattr(saveres[loadres['step']-1],loadres['fieldname'],loadres['field'])
+
+		#read next result
+		loadres=ReadData(fid,md)
 
 	#close file
 	fid.close()
 
-	return results
-	# }}}
-def ReadData(fid):    # {{{
+	return saveres
+	# }}}
+def ReadData(fid,md):    # {{{
 	"""
 	READDATA - ...
 	 
 	    Usage:
-	       field=ReadData(fid)
+	       field=ReadData(fid,md)
 	"""
 
@@ -182,5 +153,5 @@
 		M=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
 		if   type==1:
-			field=numpy.array(struct.unpack('%dd' % M,fid.read(M*struct.calcsize('d'))),dtype=float)
+			field=np.array(struct.unpack('%dd' % M,fid.read(M*struct.calcsize('d'))),dtype=float)
 		elif type==2:
 			field=struct.unpack('%ds' % M,fid.read(M))[0][:-1]
@@ -188,48 +159,97 @@
 			N=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
 #			field=transpose(fread(fid,[N M],'double'));
-			field=numpy.zeros(shape=(M,N),dtype=float)
+			field=np.zeros(shape=(M,N),dtype=float)
 			for i in range(M):
 				field[i,:]=struct.unpack('%dd' % N,fid.read(N*struct.calcsize('d')))
+		elif type==4:
+			N=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
+#			field=transpose(fread(fid,[N M],'int'));
+			field=np.zeros(shape=(M,N),dtype=int)
+			for i in range(M):
+				field[i,:]=struct.unpack('%ii' % N,fid.read(N*struct.calcsize('i')))
 		else:
 			raise TypeError("cannot read data of type %d" % type)
 
 		#Process units here FIXME: this should not be done here!
-		yts=365.0*24.0*3600.0
-		if m.strcmp(fieldname,'BalancethicknessThickeningRate'):
-			field = field*yts
-		elif m.strcmp(fieldname,'Time'):
-			field = field/yts
-		elif m.strcmp(fieldname,'HydrologyWaterVx'):
-			field = field*yts
-		elif m.strcmp(fieldname,'HydrologyWaterVy'):
-			field = field*yts
-		elif m.strcmp(fieldname,'Vx'):
-			field = field*yts
-		elif m.strcmp(fieldname,'Vy'):
-			field = field*yts
-		elif m.strcmp(fieldname,'Vz'):
-			field = field*yts
-		elif m.strcmp(fieldname,'Vel'):
-			field = field*yts
-		elif m.strcmp(fieldname,'BasalforcingsGroundediceMeltingRate'):
-			field = field*yts
-		elif m.strcmp(fieldname,'TotalSmb'):
-			field = field/10.**12.*yts #(GigaTon/year)
-		elif m.strcmp(fieldname,'SmbMassBalance'):
-			field = field*yts
-		elif m.strcmp(fieldname,'CalvingCalvingrate'):
-			field = field*yts
-
-
-		result=OrderedDict()
-		result['fieldname']=fieldname
-		result['time']=time
-		result['step']=step
-		result['field']=field
+		yts=md.constants.yts
+		if fieldname=='BalancethicknessThickeningRate':
+			field = field*yts
+		elif fieldname=='HydrologyWaterVx':
+			field = field*yts
+		elif fieldname=='HydrologyWaterVy':
+			field = field*yts
+		elif fieldname=='Vx':
+			field = field*yts
+		elif fieldname=='Vy':
+			field = field*yts
+		elif fieldname=='Vz':
+			field = field*yts
+		elif fieldname=='Vel':
+			field = field*yts
+		elif fieldname=='BasalforcingsGroundediceMeltingRate':
+			field = field*yts
+		elif fieldname=='BasalforcingsFloatingiceMeltingRate':
+			field = field*yts
+		elif fieldname=='TotalFloatingBmb':
+			field = field/10.**12*yts #(GigaTon/year)
+		elif fieldname=='TotalFloatingBmbScaled':
+			field = field/10.**12*yts #(GigaTon/year)
+		elif fieldname=='TotalGroundedBmb':
+			field = field/10.**12*yts #(GigaTon/year)
+		elif fieldname=='TotalGroundedBmbScaled':
+			field = field/10.**12*yts #(GigaTon/year)
+		elif fieldname=='TotalSmb':
+			field = field/10.**12*yts #(GigaTon/year)
+		elif fieldname=='TotalSmbScaled':
+			field = field/10.**12*yts #(GigaTon/year)
+		elif fieldname=='SmbMassBalance':
+			field = field*yts
+		elif fieldname=='SmbPrecipitation':
+			field = field*yts
+		elif fieldname=='SmbRunoff':
+			field = field*yts
+                elif fieldname=='SmbEvaporation':
+                        field = field*yts;
+                elif fieldname=='SmbRefreeze':
+                        field = field*yts;
+		elif fieldname=='SmbEC':
+			field = field*yts
+		elif fieldname=='SmbAccumulation':
+			field = field*yts
+		elif fieldname=='SmbMelt':
+			field = field*yts
+    		elif fieldname=='SmbMAdd':
+        		field = field*yts
+		elif fieldname=='CalvingCalvingrate':
+			field = field*yts
+		elif fieldname=='LoveKernelsReal' or fieldname=='LoveKernelsImag':
+			nlayer = md.materials.numlayers
+			degmax = md.love.sh_nmax
+			nfreq  = md.love.nfreq
+			#for numpy 1.8+ only
+			#temp_field = np.full((degmax+1,nfreq,nlayer+1,6),0.0)
+			temp_field = np.empty((degmax+1,nfreq,nlayer+1,6))
+			temp_field.fill(0.0)
+			for ii in range(degmax+1):
+				for jj in range(nfreq):
+					for kk in range(nlayer+1):
+						ll = ii*(nlayer+1)*6 + (kk*6+1)
+						for mm in range(6):
+							temp_field[ii,jj,kk,mm] = field[ll+mm-1,jj]
+			field=temp_field
+
+		if time !=-9999:
+			time = time/yts
+
+		saveres=OrderedDict()
+		saveres['fieldname']=fieldname
+		saveres['time']=time
+		saveres['step']=step
+		saveres['field']=field
 
 	except struct.error as e:
-		result=None
-
-	return result
+		saveres=None
+
+	return saveres
 	# }}}
 def ReadDataDimensions(fid):    # {{{
@@ -262,14 +282,14 @@
 			raise TypeError("cannot read data of type %d" % type)
 
-		result=OrderedDict()
-		result['fieldname']=fieldname
-		result['time']=time
-		result['step']=step
-		result['M']=M
-		result['N']=N
+		saveres=OrderedDict()
+		saveres['fieldname']=fieldname
+		saveres['time']=time
+		saveres['step']=step
+		saveres['M']=M
+		saveres['N']=N
 
 	except struct.error as e:
-		result=None
-
-	return result
-	# }}}
+		saveres=None
+
+	return saveres
+	# }}}
Index: /issm/trunk-jpl/src/py3/solve/solve.py
===================================================================
--- /issm/trunk-jpl/src/py3/solve/solve.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solve/solve.py	(revision 23670)
@@ -3,61 +3,94 @@
 import shutil
 from pairoptions import pairoptions
-from EnumDefinitions import *
-from EnumToString import EnumToString
 from ismodelselfconsistent import ismodelselfconsistent
 from marshall import marshall
 from waitonlock import waitonlock
 from loadresultsfromcluster import loadresultsfromcluster
-import MatlabFuncs as m
+from preqmu import *
+#from MatlabFuncs import *
 
-def solve(md,solutionenum,**kwargs):
+def solve(md,solutionstring,*args):
 	"""
 	SOLVE - apply solution sequence for this model
  
 	   Usage:
-	      md=solve(md,solutionenum,varargin)
+	      md=solve(md,solutionstring,varargin)
 	      where varargin is a list of paired arguments of string OR enums
  
-	   solution types available comprise:
-	      - StressbalanceSolutionEnum
-	      - MasstransportSolutionEnum
-	      - ThermalSolutionEnum
-	      - SteadystateSolutionEnum
-	      - TransientSolutionEnum
-	      - BalancethicknessSolutionEnum
-	      - BedSlopeSolutionEnum
-	      - SurfaceSlopeSolutionEnum
-	      - HydrologySolutionEnum
-	      - FlaimSolutionEnum
- 
+		solution types available comprise:
+		 - 'Stressbalance'    or 'sb'
+		 - 'Masstransport'    or 'mt'
+		 - 'Thermal'          or 'th'
+		 - 'Steadystate'      or 'ss'
+		 - 'Transient'        or 'tr'
+		 - 'Balancethickness' or 'mc'
+		 - 'Balancevelocity'  or 'bv'
+		 - 'BedSlope'         or 'bsl'
+		 - 'SurfaceSlope'     or 'ssl'
+		 - 'Hydrology'        or 'hy'
+		 - 'DamageEvolution'  or 'da'
+		 - 'Gia'              or 'gia'
+		 - 'Esa'	      or 'esa'
+		 - 'Sealevelrise'     or 'slr'
+		 - 'Love'             or 'lv'
+
 	   extra options:
-	      - loadonly : does not solve. only load results
+        - loadonly : does not solve. only load results
 		  - checkconsistency : 'yes' or 'no' (default is 'yes'), ensures checks on consistency of model
 		  - restart: 'directory name (relative to the execution directory) where the restart file is located.
  
 	   Examples:
-	      md=solve(md,StressbalanceSolutionEnum);
+	      md=solve(md,'Stressbalance');
+         md=solve(md,'sb');
 	"""
 
 	#recover and process solve options
-	if EnumToString(solutionenum)[0][-8:] != 'Solution':
-		raise ValueError("solutionenum '%s' not supported!" % EnumToString(solutionenum)[0])
-	options=pairoptions(solutionenum=solutionenum,**kwargs)
+	if solutionstring.lower() == 'sb' or solutionstring.lower() == 'stressbalance':
+		solutionstring = 'StressbalanceSolution';
+	elif solutionstring.lower() == 'mt' or solutionstring.lower() == 'masstransport':
+		solutionstring = 'MasstransportSolution';	
+	elif solutionstring.lower() == 'th' or solutionstring.lower() == 'thermal':
+		solutionstring = 'ThermalSolution';
+	elif solutionstring.lower() == 'st' or solutionstring.lower() == 'steadystate':
+		solutionstring = 'SteadystateSolution';
+	elif solutionstring.lower() == 'tr' or solutionstring.lower() == 'transient':
+		solutionstring = 'TransientSolution';
+	elif solutionstring.lower() == 'mc' or solutionstring.lower() == 'balancethickness':
+		solutionstring = 'BalancethicknessSolution';
+	elif solutionstring.lower() == 'bv' or solutionstring.lower() == 'balancevelocity':
+		solutionstring = 'BalancevelocitySolution';
+	elif solutionstring.lower() == 'bsl' or solutionstring.lower() == 'bedslope':
+		solutionstring = 'BedSlopeSolution';
+	elif solutionstring.lower() == 'ssl' or solutionstring.lower() == 'surfaceslope':
+		solutionstring = 'SurfaceSlopeSolution';
+	elif solutionstring.lower() == 'hy' or solutionstring.lower() == 'hydrology':
+		solutionstring = 'HydrologySolution';
+	elif solutionstring.lower() == 'da' or solutionstring.lower() == 'damageevolution':
+		solutionstring = 'DamageEvolutionSolution';
+	elif solutionstring.lower() == 'gia' or solutionstring.lower() == 'gia':
+		solutionstring = 'GiaSolution';
+        elif solutionstring.lower() == 'lv' or solutionstring.lower() == 'love':
+                solutionstring = 'LoveSolution';
+	elif solutionstring.lower() == 'esa':
+		solutionstring = 'EsaSolution';
+	elif solutionstring.lower() == 'slr' or solutionstring.lower() == 'sealevelrise':
+		solutionstring = 'SealevelriseSolution';
+	else: 	
+		raise ValueError("solutionstring '%s' not supported!" % solutionstring)
+	options=pairoptions('solutionstring',solutionstring,*args)
 
 	#recover some fields
-	md.private.solution=solutionenum
-	cluster=md.cluster
+	md.private.solution=solutionstring
+	cluster=md.cluster 
+	if options.getfieldvalue('batch','no')=='yes':
+		batch=1
+	else:
+		batch=0;
 
 	#check model consistency
-	if m.strcmpi(options.getfieldvalue('checkconsistency','yes'),'yes'):
-		print("checking model consistency")
-		if solutionenum == FlaimSolutionEnum():
-			md.private.isconsistent=True
-			md.mesh.checkconsistency(md,solutionenum)
-			md.flaim.checkconsistency(md,solutionenum)
-			if not md.private.isconsistent:
-				raise RuntimeError("Model not consistent, see messages above.")
-		else:
-			ismodelselfconsistent(md)
+	if options.getfieldvalue('checkconsistency','yes')=='yes':
+		if md.verbose.solution:
+			print("checking model consistency")
+		ismodelselfconsistent(md)
 
 	#First, build a runtime name that is unique
@@ -80,10 +113,4 @@
 		md=preqmu(md,options)
 
-	#flaim analysis
-	if solutionenum == FlaimSolutionEnum():
-		md=flaim_sol(md,options)
-		[md.private.solution]=EnumToString(solutionenum)
-		return md
-
 	#Do we load results only?
 	if options.getfieldvalue('loadonly',False):
@@ -95,8 +122,8 @@
 	marshall(md)                                           # bin file
 	md.toolkits.ToolkitsFile(md.miscellaneous.name+'.toolkits')    # toolkits file
-	cluster.BuildQueueScript(md.private.runtimename,md.miscellaneous.name,md.private.solution,md.settings.io_gather,md.debug.valgrind,md.debug.gprof,md.qmu.isdakota)    # queue file
+	cluster.BuildQueueScript(md.private.runtimename,md.miscellaneous.name,md.private.solution,md.settings.io_gather,md.debug.valgrind,md.debug.gprof,md.qmu.isdakota,md.transient.isoceancoupling)    # queue file
 
 	#Stop here if batch mode
-	if m.strcmpi(options.getfieldvalue('batch','no'),'yes'):
+	if options.getfieldvalue('batch','no')=='yes':
 		print('batch mode requested: not launching job interactively')
 		print('launch solution sequence on remote cluster by hand')
@@ -113,5 +140,5 @@
 	
 	#Launch job
-	cluster.LaunchQueueJob(md.miscellaneous.name,md.private.runtimename,filelist,restart)
+	cluster.LaunchQueueJob(md.miscellaneous.name,md.private.runtimename,filelist,restart,batch)
 
 	#wait on lock
@@ -122,10 +149,11 @@
 			print('The results must be loaded manually with md=loadresultsfromcluster(md).')
 		else:            #load results
-			print('loading results from cluster')
+			if md.verbose.solution:
+				print('loading results from cluster')
 			md=loadresultsfromcluster(md)
 
 	#post processes qmu results if necessary
 	if md.qmu.isdakota:
-		if not strncmpi(options['keep'],'y',1):
+		if not strncmpi(options.getfieldvalue('keep','y'),'y',1):
 			shutil.rmtree('qmu'+str(os.getpid()))
 
Index: /issm/trunk-jpl/src/py3/solve/waitonlock.py
===================================================================
--- /issm/trunk-jpl/src/py3/solve/waitonlock.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solve/waitonlock.py	(revision 23670)
@@ -48,5 +48,5 @@
 		#loop till file .lock exist or time is up
 		while ispresent==0 and etime<timelimit:
-			ispresent=os.path.exist(filename)
+			ispresent=os.path.exists(filename)
 			time.sleep(1)
 			etime+=1/60
Index: /issm/trunk-jpl/src/py3/solvers/asmoptions.py
===================================================================
--- /issm/trunk-jpl/src/py3/solvers/asmoptions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solvers/asmoptions.py	(revision 23670)
@@ -8,7 +8,7 @@
 	
 	#retrieve options provided in varargin
-	arguments=pairoptions.pairoptions(**kwargs) 
+	arguments=pairoptions.pairoptions(*args) 
 	
-	options=[['toolkit','petsc'],['mat_type','aij'],['ksp_type','gmres'],['pc_type','asm'],['sub_pc_type','lu'],['pc_asm_overlap',3],['ksp_max_it',100],['ksp_rtol',1e-30]];
+	options=[['toolkit','petsc'],['mat_type','mpiaij'],['ksp_type','gmres'],['pc_type','asm'],['sub_pc_type','lu'],['pc_asm_overlap',3],['ksp_max_it',100],['ksp_rtol',1e-30]];
 
 	#now, go through our arguments, and write over default options.
Index: /issm/trunk-jpl/src/py3/solvers/iluasmoptions.py
===================================================================
--- /issm/trunk-jpl/src/py3/solvers/iluasmoptions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solvers/iluasmoptions.py	(revision 23670)
@@ -11,5 +11,5 @@
 			 
 	#retrieve options provided in varargin
-	options=pairoptions.pairoptions(**kwargs)
+	options=pairoptions.pairoptions(*args)
 	iluasm=OrderedDict()
 
Index: /issm/trunk-jpl/src/py3/solvers/issmgslsolver.py
===================================================================
--- /issm/trunk-jpl/src/py3/solvers/issmgslsolver.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solvers/issmgslsolver.py	(revision 23670)
@@ -1,5 +1,6 @@
+from collections import OrderedDict
 import pairoptions
 
-def issmgslsolver(**kwargs):
+def issmgslsolver(*args):
 	#ISSMSOLVE - return issm solver options
 	#
@@ -8,7 +9,11 @@
 	
 	#retrieve options provided in varargin
-	arguments=pairoptions.pairoptions(**kwargs) 
+	arguments=pairoptions.pairoptions(*args) 
 	
-	options=[['toolkit','issm'],['mat_type','dense'],['vec_type','seq'],['solver_type','gsl']];
+	options=OrderedDict()
+	options['toolkit'] = 'issm'
+	options['mat_type'] = 'dense'
+	options['vec_type'] = 'seq'
+	options['solver_type'] = 'gsl'
 
 	#now, go through our arguments, and write over default options.
Index: /issm/trunk-jpl/src/py3/solvers/issmmumpssolver.py
===================================================================
--- /issm/trunk-jpl/src/py3/solvers/issmmumpssolver.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solvers/issmmumpssolver.py	(revision 23670)
@@ -1,5 +1,6 @@
+from collections import OrderedDict
 import pairoptions
 
-def issmmumpssolver(**kwargs):
+def issmmumpssolver(*args):
 	#ISSMSOLVE - return issm solver options
 	#
@@ -8,7 +9,11 @@
 	
 	#retrieve options provided in varargin
-	arguments=pairoptions.pairoptions(**kwargs) 
+	arguments=pairoptions.pairoptions(*args) 
 	
-	options=[['toolkit','issm'],['mat_type','mpidense'],['vec_type','mpi'],['solver_type','mumps']];
+	options=OrderedDict()
+	options['toolkit'] = 'issm'
+	options['mat_type'] = 'mpidense'
+	options['vec_type'] = 'mpi'
+	options['solver_type'] = 'mumps'
 
 	#now, go through our arguments, and write over default options.
Index: /issm/trunk-jpl/src/py3/solvers/jacobiasmoptions.py
===================================================================
--- /issm/trunk-jpl/src/py3/solvers/jacobiasmoptions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solvers/jacobiasmoptions.py	(revision 23670)
@@ -1,5 +1,5 @@
 import pairoptions
 
-def jacobiasmoptions(**kwargs):
+def jacobiasmoptions(*args):
 	#ASMOPTIONS - return Additive Shwartz Method with Jacobi preconditioner petsc options
 	#
@@ -8,7 +8,7 @@
 	
 	#retrieve options provided in varargin
-	arguments=pairoptions.pairoptions(**kwargs) 
+	arguments=pairoptions.pairoptions(*args) 
 	
-	options=[['toolkit','petsc'],['mat_type','aij'],['ksp_type','gmres'],['pc_type','asm'],['sub_pc_type','jacobi'],['pc_asm_overlap',3],['ksp_max_it',100],['ksp_rtol',1e-15]];
+	options=[['toolkit','petsc'],['mat_type','mpiaij'],['ksp_type','gmres'],['pc_type','asm'],['sub_pc_type','jacobi'],['pc_asm_overlap',3],['ksp_max_it',100],['ksp_rtol',1e-15]];
 
 	#now, go through our arguments, and write over default options.
Index: /issm/trunk-jpl/src/py3/solvers/jacobicgoptions.py
===================================================================
--- /issm/trunk-jpl/src/py3/solvers/jacobicgoptions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solvers/jacobicgoptions.py	(revision 23670)
@@ -8,7 +8,7 @@
 	
 	#retrieve options provided in varargin
-	arguments=pairoptions.pairoptions(**kwargs) 
+	arguments=pairoptions.pairoptions(*args) 
 	
-	options=[['toolkit','petsc'],['mat_type','aij'],['ksp_type','cg'],['ksp_max_it',100],['ksp_rtol',1e-15]];
+	options=[['toolkit','petsc'],['mat_type','mpiaij'],['ksp_type','cg'],['ksp_max_it',100],['ksp_rtol',1e-15]];
 
 	#now, go through our arguments, and write over default options.
Index: /issm/trunk-jpl/src/py3/solvers/matlaboptions.py
===================================================================
--- /issm/trunk-jpl/src/py3/solvers/matlaboptions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solvers/matlaboptions.py	(revision 23670)
@@ -1,5 +1,5 @@
 import pairoptions
 
-def matlaboptions(**kwargs):
+def matlaboptions(*args):
 	#MATLABOPTIONS - return Matlab petsc options
 	#
@@ -8,5 +8,5 @@
 	
 	#retrieve options provided in varargin
-	arguments=pairoptions.pairoptions(**kwargs) 
+	arguments=pairoptions.pairoptions(*args) 
 	
 	options=[['toolkit','petsc'],['ksp_type','matlab']];
Index: /issm/trunk-jpl/src/py3/solvers/mumpsoptions.py
===================================================================
--- /issm/trunk-jpl/src/py3/solvers/mumpsoptions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solvers/mumpsoptions.py	(revision 23670)
@@ -3,5 +3,5 @@
 from IssmConfig import IssmConfig
 
-def mumpsoptions(**kwargs):
+def mumpsoptions(*args):
 	"""
 	MUMPSOPTIONS - return MUMPS direct solver  petsc options
@@ -12,10 +12,11 @@
 
 	#retrieve options provided in varargin
-	options=pairoptions.pairoptions(**kwargs)
+	options=pairoptions.pairoptions(*args)
 	mumps=OrderedDict()
 
 	#default mumps options
-	PETSC_VERSION=IssmConfig('_PETSC_MAJOR_')[0]
-	if PETSC_VERSION==2.:
+	PETSC_MAJOR=IssmConfig('_PETSC_MAJOR_')[0]
+	PETSC_MINOR=IssmConfig('_PETSC_MINOR_')[0]
+	if PETSC_MAJOR==2.:
 		mumps['toolkit']='petsc'
 		mumps['mat_type']=options.getfieldvalue('mat_type','aijmumps')
@@ -23,14 +24,14 @@
 		mumps['pc_type']=options.getfieldvalue('pc_type','lu')
 		mumps['mat_mumps_icntl_14']=options.getfieldvalue('mat_mumps_icntl_14',120)
-		mumps['pc_factor_shift_positive_definite']=options.getfieldvalue('pc_factor_shift_positive_definite','true')
-	if PETSC_VERSION==3.:
+	if PETSC_MAJOR==3.:
 		mumps['toolkit']='petsc'
 		mumps['mat_type']=options.getfieldvalue('mat_type','mpiaij')
 		mumps['ksp_type']=options.getfieldvalue('ksp_type','preonly')
 		mumps['pc_type']=options.getfieldvalue('pc_type','lu')
-		mumps['pc_factor_mat_solver_package']=options.getfieldvalue('pc_factor_mat_solver_package','mumps')
+		if PETSC_MINOR>8.:
+			mumps['pc_factor_mat_solver_type']=options.getfieldvalue('pc_factor_mat_solver_type','mumps')
+		else:
+			mumps['pc_factor_mat_solver_package']=options.getfieldvalue('pc_factor_mat_solver_package','mumps')
 		mumps['mat_mumps_icntl_14']=options.getfieldvalue('mat_mumps_icntl_14',120)
-		mumps['pc_factor_shift_positive_definite']=options.getfieldvalue('pc_factor_shift_positive_definite','true')
 
 	return mumps
-
Index: /issm/trunk-jpl/src/py3/solvers/soroptions.py
===================================================================
--- /issm/trunk-jpl/src/py3/solvers/soroptions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solvers/soroptions.py	(revision 23670)
@@ -1,5 +1,5 @@
 import pairoptions
 
-def soroptions(**kwargs):
+def soroptions(*args):
 	#SOROPTIONS - return Relaxation Solver petsc options
 	#
@@ -8,7 +8,7 @@
 	
 	#retrieve options provided in varargin
-	arguments=pairoptions.pairoptions(**kwargs) 
+	arguments=pairoptions.pairoptions(*args) 
 	
-	options=[['toolkit','petsc'],['mat_type','aij'],['ksp_type','cg'],['pc_type','sor'],['pc_sor_omega',1.1],['pc_sor_its',2]];
+	options=[['toolkit','petsc'],['mat_type','mpiaij'],['ksp_type','cg'],['pc_type','sor'],['pc_sor_omega',1.1],['pc_sor_its',2]];
 
 	#now, go through our arguments, and write over default options.
Index: /issm/trunk-jpl/src/py3/solvers/stokesoptions.py
===================================================================
--- /issm/trunk-jpl/src/py3/solvers/stokesoptions.py	(revision 23669)
+++ /issm/trunk-jpl/src/py3/solvers/stokesoptions.py	(revision 23670)
@@ -2,5 +2,5 @@
 from IssmConfig import IssmConfig
 
-def stokesoptions(**kwargs):
+def stokesoptions(*args):
 	#STOKESOPTIONS - return STOKES multi-physics solver petsc options
 	#
@@ -9,5 +9,5 @@
 	
 	#retrieve options provided in varargin
-	arguments=pairoptions.pairoptions(**kwargs) 
+	arguments=pairoptions.pairoptions(*args) 
 
 
