Index: /issm/trunk-jpl/src/m/classes/SMBd18opdd.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/SMBd18opdd.m	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/SMBd18opdd.m	(revision 27453)
@@ -172,6 +172,6 @@
 			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);
-			WriteData(fid, prefix, 'object', self, 'fieldname', 'steps_per_step', 'format', 'Integer');
-			WriteData(fid, prefix, 'object', self, 'fieldname', 'averaging', 'format', 'Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','steps_per_step','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','averaging','format','Integer');
 
 			if self.isd18opd
Index: /issm/trunk-jpl/src/m/classes/SMBd18opdd.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/SMBd18opdd.py	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/SMBd18opdd.py	(revision 27453)
@@ -40,44 +40,45 @@
         self.requested_outputs = []
 
-        # Set defaults
-        self.setdefaultparameters()
+        if len(args) == 0:
+            self.setdefaultparameters()
+        else:
+            raise Exception('constructor not supported')
     #}}}
     def __repr__(self):  # {{{
-        string = "   surface forcings parameters:"
-
-        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 (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]'))
-        string = "%s\n%s" % (string, fielddisplay(self, 's0t', 'should be set to elevation from temperature source (between 0 and a few 1000s m, default is 0) [m]'))
-        string = "%s\n%s" % (string, fielddisplay(self, 'rlaps', 'present day lapse rate [degree/km]'))
-        if self.isd18opd:
-            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)'))
+        s = '   surface forcings parameters:\n'
+        s += '{}\n'.format(fielddisplay(self, 'isd18opd', 'is delta18o parametrisation from present day temperature and precipitation activated (0 or 1, default is 0)'))
+        s += '{}\n'.format(fielddisplay(self, 'issetpddfac', 'is user passing in defined pdd factors (0 or 1, default is 0)'))
+        s += '{}\n'.format(fielddisplay(self, 'desfac', 'desertification elevation factor (between 0 and 1, default is 0.5) [m]'))
+        s += '{}\n'.format(ielddisplay(self, 's0p', 'should be set to elevation from precip source (between 0 and a few 1000s m, default is 0) [m]'))
+        s += '{}\n'.format(fielddisplay(self, 's0t', 'should be set to elevation from temperature source (between 0 and a few 1000s m, default is 0) [m]'))
+        s += '{}\n'.format(fielddisplay(self, 'rlaps', 'present day lapse rate [degree/km]'))
+
+        if self.isd18opd:
+            s += '{}\n'.format(fielddisplay(self, 'temperatures_presentday', 'monthly present day surface temperatures [K], required if delta18o/mungsm is activated'))
+            s += '{}\n'.format(fielddisplay(self, 'precipitations_presentday', 'monthly surface precipitation [m/yr water eq], required if delta18o or mungsm is activated'))
+            s += '{}\n'.format(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)'))
+            s += '{}\n'.format(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'))
+                s += '{}\n'.format(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'))
+                s += '{}\n'.format(fielddisplay(self, 'precipitations_reconstructed', 'monthly historical precipitation [m/yr water eq], required if delta18o/mungsm/d18opd is activated and isprecipscaled is not activated'))
+
+            s += '{}\n'.format(fielddisplay(self, 'delta18o', 'delta18o [per mil], required if pdd is activated and delta18o activated'))
+            s += '{}\n'.format(fielddisplay(self, 'dpermil', 'degree per mil, required if d18opd is activated'))
+            s += '{}\n'.format(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 for all the domain [mm ice equiv/day/degree C]'))
-            string = "%s\n%s" % (string, fielddisplay(self, 'pddfac_ice', 'Pdd factor for ice for all the domain [mm ice equiv/day/degree C]'))
-        string = "%s\n%s" % (string, fielddisplay(self, 'steps_per_step', 'number of smb steps per time step'))
-        string = "%s\n%s" % (string, fielddisplay(self, 'averaging', 'averaging methods from short to long steps'))
-        string = "%s\n\t\t%s" % (string, '0: Arithmetic (default)')
-        string = "%s\n\t\t%s" % (string, '1: Geometric')
-        string = "%s\n\t\t%s" % (string, '2: Harmonic')
-
-        string = "%s\n%s" % (string, fielddisplay(self, 'requested_outputs', 'additional outputs requested'))
-
-        return string
+            s += '{}\n'.format(fielddisplay(self, 'pddfac_snow', 'Pdd factor for snow for all the domain [mm ice equiv/day/degree C]'))
+            s += '{}\n'.format(fielddisplay(self, 'pddfac_ice', 'Pdd factor for ice for all the domain [mm ice equiv/day/degree C]'))
+
+        s += '{}\n'.format(fielddisplay(self, 'steps_per_step', 'number of smb steps per time step'))
+        s += '{}\n'.format(fielddisplay(self, 'averaging', 'averaging methods from short to long steps'))
+        s += '\t\t{}\n'.format('0: Arithmetic (default)')
+        s += '\t\t{}\n'.format('1: Geometric')
+        s += '\t\t{}\n'.format('2: Harmonic')
+        s += '{}\n'.format(fielddisplay(self, 'requested_outputs', 'additional outputs requested'))
+        return s
     #}}}
     def extrude(self, md):  # {{{
@@ -205,4 +206,3 @@
             outputs = outputscopy
         WriteData(fid, prefix, 'data', outputs, 'name', 'md.smb.requested_outputs', 'format', 'StringArray')
-
     # }}}
Index: /issm/trunk-jpl/src/m/classes/SMBdebrisML.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/SMBdebrisML.m	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/SMBdebrisML.m	(revision 27453)
@@ -11,5 +11,5 @@
 	end
 	methods
-		function self = SMBhenning(varargin) % {{{
+		function self = SMBdebrisML(varargin) % {{{
 			switch nargin
 				case 0
@@ -57,6 +57,6 @@
 
 			WriteData(fid,prefix,'name','md.smb.model','data',14,'format','Integer');
-			WriteData(fid, prefix, 'object', self, 'fieldname', 'steps_per_step', 'format', 'Integer');
-			WriteData(fid, prefix, 'object', self, 'fieldname', 'averaging', 'format', 'Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','steps_per_step','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','averaging','format','Integer');
 
 			%process requested outputs
Index: /issm/trunk-jpl/src/m/classes/SMBforcing.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/SMBforcing.m	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/SMBforcing.m	(revision 27453)
@@ -54,5 +54,5 @@
 			md = checkfield(md,'fieldname','smb.steps_per_step','>=',1,'numel',[1]);
 			md = checkfield(md,'fieldname','smb.requested_outputs','stringrow',1);
-			md = checkfield(md, 'fieldname', 'smb.averaging', 'numel', [1], 'values', [0, 1, 2]);
+			md = checkfield(md,'fieldname','smb.averaging','numel',[1],'values',[0 1 2]);
 		end % }}}
 		function disp(self) % {{{
@@ -71,7 +71,7 @@
 
 			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, 'fieldname', 'steps_per_step', 'format', 'Integer');
-			WriteData(fid, prefix, 'object', self, 'fieldname', 'averaging', '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',yts);
+			WriteData(fid,prefix,'object',self,'fieldname','steps_per_step','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','averaging','format','Integer');
 
 			%process requested outputs
Index: /issm/trunk-jpl/src/m/classes/SMBforcing.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/SMBforcing.py	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/SMBforcing.py	(revision 27453)
@@ -20,5 +20,9 @@
         self.averaging = 0
 
-        if len(args) == 0:
+        nargs = len(args)
+        if nargs == 0:
+            self.setdefaultparameters()
+        elif nargs == 1:
+            # TODO: Replace the following with constructor
             self.setdefaultparameters()
         else:
@@ -30,9 +34,9 @@
         s += '{}\n'.format(fielddisplay(self, 'mass_balance', 'surface mass balance [m/yr ice eq]'))
         s += '{}\n'.format(fielddisplay(self, 'steps_per_step', 'number of smb steps per time step'))
-        s += '{}\n'.format(fielddisplay(self, 'requested_outputs', 'additional outputs requested'))
         s += '{}\n'.format(fielddisplay(self, 'averaging', 'averaging methods from short to long steps'))
         s += '\t\t{}\n'.format('0: Arithmetic (default)')
         s += '\t\t{}\n'.format('1: Geometric')
         s += '\t\t{}\n'.format('2: Harmonic')
+        s += '{}\n'.format(fielddisplay(self, 'requested_outputs', 'additional outputs requested'))
         return s
     #}}}
Index: /issm/trunk-jpl/src/m/classes/SMBhenning.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/SMBhenning.m	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/SMBhenning.m	(revision 27453)
@@ -73,6 +73,6 @@
 			WriteData(fid,prefix,'name','md.smb.model','data',7,'format','Integer');
 			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, 'fieldname', 'steps_per_step', 'format', 'Integer');
-			WriteData(fid, prefix, 'object', self, 'fieldname', 'averaging', 'format', 'Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','steps_per_step','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','averaging','format','Integer');
 
 			%process requested outputs
Index: /issm/trunk-jpl/src/m/classes/SMBhenning.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/SMBhenning.py	(revision 27453)
+++ /issm/trunk-jpl/src/m/classes/SMBhenning.py	(revision 27453)
@@ -0,0 +1,92 @@
+import numpy as np
+
+from checkfield import checkfield
+from fielddisplay import fielddisplay
+from project3d import project3d
+from WriteData import WriteData
+
+
+class SMBforcing(object):
+    """SMBhenning class definition
+
+    Usage:
+        SMBhenning = SMBhenning()
+    """
+
+    def __init__(self, *args):  # {{{
+        self.smbref = np.nan
+        self.steps_per_step = 1
+        self.averaging = 0
+        self.requested_outputs = []
+
+        nargs = len(args)
+        if nargs == 0:
+            self.setdefaultparameters()
+        elif nargs == 1:
+            # TODO: Replace the following with constructor
+            self.setdefaultparameters()
+        else:
+            raise Exception('constructor not supported')
+    #}}}
+
+    def __repr__(self):  # {{{
+        s = '   surface forcings parameters:\n'
+        s += '{}\n'.format(fielddisplay(self, 'mass_balance', 'surface mass balance [m/yr ice eq]'))
+        s += '{}\n'.format(fielddisplay(self, 'steps_per_step', 'number of smb steps per time step'))
+        s += '{}\n'.format(fielddisplay(self, 'averaging', 'averaging methods from short to long steps'))
+        s += '\t\t{}\n'.format('0: Arithmetic (default)')
+        s += '\t\t{}\n'.format('1: Geometric')
+        s += '\t\t{}\n'.format('2: Harmonic')
+        s += '{}\n'.format(fielddisplay(self, 'requested_outputs', 'additional outputs requested'))
+        return s
+    #}}}
+
+    def extrude(self, md):  # {{{
+        self.smbref = project3d(md, 'vector', self.smbref, 'type', 'node')
+        return self
+    #}}}
+
+    def defaultoutputs(self, md):  # {{{
+        return ['SmbMassBalance']
+    #}}}
+
+    def initialize(self, md):  # {{{
+        if np.all(np.isnan(self.smbref)):
+            self.smbref = np.zeros((md.mesh.numberofvertices))
+            print("      no smb.smbref specified: values set as zero")
+        return self
+    #}}}
+
+    def checkconsistency(self, md, solution, analyses):  # {{{
+        if solution == 'TransientSolution' and not md.transient.issmb:
+            return
+        if 'MasstransportAnalysis' in analyses:
+            md = checkfield(md, 'fieldname', 'smb.mass_balance', 'timeseries', 1, 'NaN', 1, 'Inf', 1)
+        if 'BalancethicknessAnalysis' in analyses:
+            md = checkfield(md, 'fieldname', 'smb.mass_balance', 'size', [md.mesh.numberofvertices], 'NaN', 1, 'Inf', 1)
+        md = checkfield(md, 'fieldname', 'smb.steps_per_step', '>=', 1, 'numel', [1])
+        md = checkfield(md, 'fieldname', 'smb.averaging', 'numel', [1], 'values', [0, 1, 2])
+        md = checkfield(md, 'fieldname', 'smb.requested_outputs', 'stringrow', 1)
+        return md
+    # }}}
+
+    def marshall(self, prefix, md, fid):  # {{{
+        yts = md.constants.yts
+        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', yts)
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'steps_per_step', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'averaging', '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.smb.requested_outputs', 'format', 'StringArray')
+    # }}}
+
+    def setdefaultparameters(self):  #{{{
+        self.requested_outputs = ['default']
+        return self
+    # }}}
Index: /issm/trunk-jpl/src/m/classes/SMBsemic.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/SMBsemic.m	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/SMBsemic.m	(revision 27453)
@@ -12,14 +12,14 @@
 		dailywindspeed		= NaN;
 		dailypressure		= NaN;
-		dailyairdensity	= NaN;
+		dailyairdensity		= NaN;
 		dailyairhumidity	= NaN;
 		dailytemperature	= NaN;
 		desfac				= 0;
-		rlaps					= 0;
+		rlaps				= 0;
 		rdl					= 0;
-		s0gcm					= NaN;
-		steps_per_step = 1;
-		averaging = 0;
-		requested_outputs = {};
+		s0gcm				= NaN;
+		steps_per_step		= 1;
+		averaging			= 0;
+		requested_outputs	= {};
 	end
 	methods
@@ -115,4 +115,6 @@
 		function marshall(self,prefix,md,fid) % {{{
 
+			yts=md.constants.yts;
+
 			WriteData(fid,prefix,'name','md.smb.model','data',12,'format','Integer');
 
@@ -121,15 +123,15 @@
 			WriteData(fid,prefix,'object',self,'class','smb','fieldname','rlaps','format','Double');
 			WriteData(fid,prefix,'object',self,'class','smb','fieldname','rdl','format','Double');
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailysnowfall','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailyrainfall','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailydsradiation','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailydlradiation','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailywindspeed','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailypressure','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailyairdensity','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailyairhumidity','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
-			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailytemperature','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
-			WriteData(fid, prefix, 'object', self, 'fieldname', 'steps_per_step', 'format', 'Integer');
-			WriteData(fid, prefix, 'object', self, 'fieldname', 'averaging', 'format', 'Integer');
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailysnowfall','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts);
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailyrainfall','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts);
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailydsradiation','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts);
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailydlradiation','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts);
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailywindspeed','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts);
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailypressure','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts);
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailyairdensity','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts);
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailyairhumidity','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts);
+			WriteData(fid,prefix,'object',self,'class','smb','fieldname','dailytemperature','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts);
+			WriteData(fid,prefix,'object',self,'fieldname','steps_per_step','format','Integer');
+			WriteData(fid,prefix,'object',self,'fieldname','averaging','format','Integer');
 			%process requested outputs
 			outputs = self.requested_outputs;
Index: /issm/trunk-jpl/src/m/classes/SMBsemic.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/SMBsemic.py	(revision 27453)
+++ /issm/trunk-jpl/src/m/classes/SMBsemic.py	(revision 27453)
@@ -0,0 +1,148 @@
+from math import log
+
+import numpy as np
+
+from checkfield import checkfield
+from fielddisplay import fielddisplay
+from project3d import project3d
+from WriteData import WriteData
+
+
+class SMBsemic(object):
+    """SMBsemic class definition
+
+    Usage:
+        SMBsemic = SMBsemic()
+    """
+
+    def __init__(self, *args):  # {{{
+        self.dailysnowfall = np.nan
+        self.dailyrainfall = np.nan
+        self.dailydsradiation = np.nan
+        self.dailydlradiation = np.nan
+        self.dailypressure = np.nan
+        self.dailyairdensity = np.nan
+        self.dailyairhumidity = np.nan
+        self.dailytemperature = np.nan
+        self.desfac = 0
+        self.rlaps = 0
+        self.rdl = 0
+        self.s0gcm = np.nan
+        self.steps_per_step = 1
+        self.averaging = 0
+        self.requested_outputs = []
+
+        if len(args) == 0:
+            self.setdefaultparameters()
+        else:
+            raise Exception('constructor not supported')
+    #}}}
+
+    def __repr__(self):  # {{{
+        s = '   surface forcings parameters:\n'
+        s += '   Interface for coupling GCM data to the energy balance model SEMIC (Krapp et al (2017) https://doi.org/10.5194/tc-11-1519-2017).\n'
+        s += '   The implemented coupling uses daily mean GCM input to calculate yearly mean smb, accumulation, ablation, and surface temperature.\n'
+        s += '   smb and temperatures are updated every year\n'
+        s += '\n   SEMIC parameters:\n'
+        s += '{}\n'.format(fielddisplay(self, 'dailysnowfall', 'daily surface dailysnowfall [m/s]'))
+        s += '{}\n'.format(fielddisplay(self, 'dailyrainfall', 'daily surface dailyrainfall [m/s]'))
+        s += '{}\n'.format(fielddisplay(self, 'dailydsradiation', 'daily downwelling shortwave radiation [W/m2]'))
+        s += '{}\n'.format(fielddisplay(self, 'dailydlradiation', 'daily downwelling longwave radiation [W/m2]'))
+        s += '{}\n'.format(fielddisplay(self, 'dailywindspeed', 'daily surface wind speed [m/s]'))
+        s += '{}\n'.format(fielddisplay(self, 'dailypressure', 'daily surface pressure [Pa]'))
+        s += '{}\n'.format(fielddisplay(self, 'dailyairdensity', 'daily air density [kg/m3]'))
+        s += '{}\n'.format(fielddisplay(self, 'dailyairhumidity', 'daily air specific humidity [kg/kg]'))
+        s += '{}\n'.format(fielddisplay(self, 'rlaps', 'present day lapse rate (default is 7.4 [degree/km]; Erokhina et al. 2017)'))
+        s += '{}\n'.format(fielddisplay(self, 'desfac', 'desertification elevation factor (default is -log(2.0)/1000 [1/km]; Vizcaino et al. 2010)'))
+        s += '{}\n'.format(fielddisplay(self, 'rdl', 'longwave downward radiation decrease (default is 0.29 [W/m^2/km]; Marty et al. 2002)'))
+        s += '{}\n'.format(fielddisplay(self, 's0gcm', 'GCM reference elevation; (default is 0) [m]'))
+        s += '{}\n'.format(fielddisplay(self, 'steps_per_step', 'number of smb steps per time step'))
+        s += '{}\n'.format(fielddisplay(self, 'averaging', 'averaging methods from short to long steps'))
+        s += '\t\t{}\n'.format('0: Arithmetic (default)')
+        s += '\t\t{}\n'.format('1: Geometric')
+        s += '\t\t{}\n'.format('2: Harmonic')
+        s += '{}\n'.format(fielddisplay(self, 'requested_outputs', 'additional outputs requested'))
+        return s
+    #}}}
+
+    def extrude(self, md):  # {{{
+        self.dailysnowfall = project3d(md, 'vector', self.dailysnowfall, 'type', 'node')
+        self.dailyrainfall = project3d(md, 'vector', self.dailyrainfall, 'type', 'node')
+        self.dailydsradiation = project3d(md, 'vector', self.dailydsradiation, 'type', 'node')
+        self.dailydlradiation = project3d(md, 'vector', self.dailydlradiation, 'type', 'node')
+        self.dailywindspeed = project3d(md, 'vector', self.dailywindspeed, 'type', 'node')
+        self.dailypressure = project3d(md, 'vector', self.dailypressure, 'type', 'node')
+        self.dailyairdensity = project3d(md, 'vector', self.dailyairdensity, 'type', 'node')
+        self.dailyairhumidity = project3d(md, 'vector', self.dailyairhumidity, 'type', 'node')
+        self.dailytemperature = project3d(md, 'vector', self.dailytemperature, 'type', 'node')
+        self.s0gcm = project3d(md, 'vector', self.s0gcm, 'type', 'node')
+        return self
+    #}}}
+
+    def defaultoutputs(self, md):  # {{{
+        return ['SmbMassBalance']
+    #}}}
+
+    def initialize(self, md):  # {{{
+        if np.all(np.isnan(self.s0gcm)):
+            self.s0gcm = np.zeros((md.mesh.numberofvertices))
+            print("      no SMBsemic.s0gcm specified: values set as zero")
+        return self
+    #}}}
+
+    def setdefaultparameters(self):  #{{{
+        self.desfac = -log(2.0) / 1000
+        self.rlaps = 7.4
+        self.rdl = 0.29
+        self.requested_outputs = ['default']
+        return self
+    # }}}
+
+    def checkconsistency(self, md, solution, analyses):  # {{{
+        if 'MasstransportAnalysis' in analyses:
+            md = checkfield(md, 'fieldname', 'smb.desfac', '<=', 1, 'numel', 1)
+            md = checkfield(md, 'fieldname', 'smb.s0gcm', '>=', 0, 'NaN', 1, 'Inf', 1, 'size', [md.mesh.numberofvertices, 1])
+            md = checkfield(md, 'fieldname', 'smb.rlaps', '>=', 0, 'numel', 1)
+            md = checkfield(md, 'fieldname', 'smb.rdl', '>=', 0, 'numel', 1)
+            md = checkfield(md, 'fieldname', 'smb.dailysnowfall', 'timeseries', 1, 'NaN', 1, 'Inf', 1)
+            md = checkfield(md, 'fieldname', 'smb.dailyrainfall', 'timeseries', 1, 'NaN', 1, 'Inf', 1)
+            md = checkfield(md, 'fieldname', 'smb.dailydsradiation', 'timeseries', 1, 'NaN', 1, 'Inf', 1)
+            md = checkfield(md, 'fieldname', 'smb.dailydlradiation', 'timeseries', 1, 'NaN', 1, 'Inf', 1)
+            md = checkfield(md, 'fieldname', 'smb.dailywindspeed', 'timeseries', 1, 'NaN', 1, 'Inf', 1)
+            md = checkfield(md, 'fieldname', 'smb.dailypressure', 'timeseries', 1, 'NaN', 1, 'Inf', 1)
+            md = checkfield(md, 'fieldname', 'smb.dailyairdensity', 'timeseries', 1, 'NaN', 1, 'Inf', 1)
+            md = checkfield(md, 'fieldname', 'smb.dailyairhumidity', 'timeseries', 1, 'NaN', 1, 'Inf', 1)
+            md = checkfield(md, 'fieldname', 'smb.dailytemperature', 'timeseries', 1, 'NaN', 1, 'Inf', 1)
+        md = checkfield(md, 'fieldname', 'smb.steps_per_step', '>=', 1, 'numel', [1])
+        md = checkfield(md, 'fieldname', 'smb.averaging', 'numel', [1], 'values', [0, 1, 2])
+        md = checkfield(md, 'fieldname', 'smb.requested_outputs', 'stringrow', 1)
+        return md
+    # }}}
+
+    def marshall(self, prefix, md, fid):  # {{{
+        yts = md.constants.yts
+        WriteData(fid, prefix, 'name', 'md.smb.model', 'data', 12, 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 'desfac', 'format', 'Double')
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 's0gcm', 'format', 'DoubleMat', 'mattype', 1)
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 'rlaps', 'format', 'Double')
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 'rdl', 'format', 'Double')
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 'dailysnowfall', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 'dailyrainfall', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 'dailydsradiation', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 'dailydlradiation', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 'dailywindspeed', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 'dailypressure', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 'dailyairdensity', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 'dailyairhumidity', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'class' ,'smb', 'fieldname', 'dailytemperature', 'format', 'DoubleMat', 'mattype', 1, 'timeserieslength', md.mesh.numberofvertices + 1, 'yts', yts)
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'steps_per_step', 'format', 'Integer')
+        WriteData(fid, prefix, 'object', self, 'fieldname', 'averaging', '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.smb.requested_outputs', 'format', 'StringArray')
+    # }}}
Index: /issm/trunk-jpl/src/m/classes/debris.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/debris.py	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/debris.py	(revision 27453)
@@ -8,5 +8,5 @@
 
 class debris(object):
-    """DEBRIS class definition
+    """debris class definition
 
     Usage:
Index: /issm/trunk-jpl/src/m/classes/frontalforcings.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/frontalforcings.m	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/frontalforcings.m	(revision 27453)
@@ -1,3 +1,3 @@
-%FRONTAL FORCINGS class definition
+%FRONTALFORCINGS class definition
 %
 %   Usage:
Index: /issm/trunk-jpl/src/m/classes/frontalforcings.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/frontalforcings.py	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/frontalforcings.py	(revision 27453)
@@ -8,9 +8,8 @@
 
 class frontalforcings(object):
-    """
-    FRONTAL FORCINGS class definition
+    """frontalforcings class definition
 
-       Usage:
-          frontalforcings = frontalforcings()
+    Usage:
+        frontalforcings = frontalforcings()
     """
 
Index: /issm/trunk-jpl/src/m/classes/lovenumbers.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/lovenumbers.py	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/lovenumbers.py	(revision 27453)
@@ -8,5 +8,5 @@
 
 class lovenumbers(object):  #{{{
-    """LOVENUMBERS class definition
+    """lovenumbers class definition
 
     Usage:
Index: /issm/trunk-jpl/src/m/classes/model.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/model.py	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/model.py	(revision 27453)
@@ -75,5 +75,5 @@
 
 class model(object):
-    """MODEL - class definition
+    """model class definition
 
     Usage:
Index: /issm/trunk-jpl/src/m/classes/sampling.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/sampling.py	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/sampling.py	(revision 27453)
@@ -10,5 +10,5 @@
 
 class sampling(object):
-    """SAMPLING class definition
+    """sampling class definition
 
     Usage:
Index: /issm/trunk-jpl/src/m/classes/solidearthsettings.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/solidearthsettings.py	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/solidearthsettings.py	(revision 27453)
@@ -7,5 +7,5 @@
 
 class solidearthsettings(object):
-    """SOLIDEARTHSETTINGS class definition
+    """solidearthsettings class definition
 
     Usage:
Index: /issm/trunk-jpl/src/m/classes/transient.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/transient.py	(revision 27452)
+++ /issm/trunk-jpl/src/m/classes/transient.py	(revision 27453)
@@ -30,5 +30,8 @@
         self.requested_outputs = []
 
-        self.setdefaultparameters()
+        if len(args) == 0:
+            self.setdefaultparameters()
+        else:
+            raise Exception('constructor not supported')
     # }}}
 
Index: /issm/trunk-jpl/src/m/coordsystems/gmtmask.py
===================================================================
--- /issm/trunk-jpl/src/m/coordsystems/gmtmask.py	(revision 27452)
+++ /issm/trunk-jpl/src/m/coordsystems/gmtmask.py	(revision 27453)
@@ -10,10 +10,9 @@
 
 def gmtmask(lat, long, *args):
-    '''
-    GMTMASK - figure out which lat, long points are on the ocean
+    """GMTMASK - figure out which lat, long points are on the ocean
 
-        Usage:
-            mask.ocean = gmtmask(md.mesh.lat, md.mesh.long)
-    '''
+    Usage:
+        mask.ocean = gmtmask(md.mesh.lat, md.mesh.long)
+    """
     lenlat = len(lat)
     mask = np.empty(lenlat)
@@ -30,5 +29,5 @@
         print(('gmtmask: num vertices ' + str(lenlat)))
 
-    #Check lat and long size is not more than 50,000. If so, recursively call gmtmask:
+    # Check lat and long size is not more than 50,000. If so, recursively call gmtmask.
     if lenlat > 50000:
         for i in range(int(ceil(lenlat / 50000))):
@@ -39,13 +38,13 @@
         return mask
 
-    #First, write our lat, long file for gmt:
+    # First, write our lat, long file for gmt
     nv = lenlat
     #print(np.transpose([int, lat, np.arange(1, nv + 1)]))
     np.savetxt('./all_vertices.txt', np.transpose([long, lat, np.arange(1, nv + 1)]), delimiter='\t', fmt='%.10f')
 
-    #figure out which vertices are on the ocean, which one on the continent:
+    # Figure out which vertices are on the ocean, which one on the continent:
     subprocess.call('gmt select ./all_vertices.txt -h0 -Df -R0/360/-90/90 -A0 -JQ180/200 -Nk/s/s/k/s > ./oce_vertices.txt', shell=True)
 
-    #read the con_vertices.txt file and flag our mesh vertices on the continent
+    # Read the con_vertices.txt file and flag our mesh vertices on the continent
     fid = open('./oce_vertices.txt', 'r')
     line = fid.readline()
