Index: /issm/trunk-jpl/jenkins/javascript/karma/karma.conf.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/karma.conf.js	(revision 20811)
+++ /issm/trunk-jpl/jenkins/javascript/karma/karma.conf.js	(revision 20812)
@@ -30,7 +30,10 @@
       'lib/bin/flowequation.js',
       'lib/bin/stressbalance.js',
+      'lib/bin/thermal.js',
+      'lib/bin/masstransport.js',
       'lib/bin/project3d.js',
       'lib/bin/model.js',
-      'scripts/specs/temp.spec.js'
+      //'scripts/specs/temp.spec.js'
+      'scripts/specs/issm-ajax.spec.js'
       //'scripts/specs/3.spec.js'
     ],
Index: /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/masstransport.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/masstransport.js	(revision 20812)
+++ /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/masstransport.js	(revision 20812)
@@ -0,0 +1,104 @@
+//MASSTRANSPORT class definition
+//
+//   Usage:
+//      masstransport=new masstransport();
+
+function masstransport (){
+	//methods
+	this.setdefaultparameters = function(){// {{{
+
+		//Type of stabilization to use 0:nothing 1:artificial_diffusivity 3:Discontinuous Galerkin
+		this.stabilization=1;
+
+		//Factor applied to compute the penalties kappa=max(stiffness matrix)*10^penalty_factor
+		this.penalty_factor=3;
+
+		//Minimum ice thickness that can be used
+		this.min_thickness=1;
+
+		//Hydrostatic adjustment
+		this.hydrostatic_adjustment='Absolute';
+
+		//default output
+		this.requested_outputs=['default'];
+
+	}// }}}
+	this.disp= function(){// {{{
+		console.log(sprintf('   Masstransport solution parameters:'));
+		fielddisplay(this,'spcthickness','thickness constraints (NaN means no constraint) [m]');
+		fielddisplay(this,'isfreesurface','do we use free surfaces (FS only) are mass conservation');
+		fielddisplay(this,'min_thickness','minimum ice thickness allowed [m]');
+		fielddisplay(this,'hydrostatic_adjustment',"adjustment of ice shelves surface and bed elevations: 'Incremental' or 'Absolute' ");
+		fielddisplay(this,'stabilization','0: no, 1: artificial_diffusivity, 2: streamline upwinding, 3: discontinuous Galerkin, 4: Flux Correction Transport');
+
+		console.log(sprintf('\n      %s','Penalty options:'));
+		fielddisplay(this,'penalty_factor','offset used by penalties: penalty = Kmax*10^offset');
+		fielddisplay(this,'vertex_pairing','pairs of vertices that are penalized');
+		fielddisplay(this,'requested_outputs','additional outputs requested');
+
+	}// }}}
+	this.classname= function(){// {{{
+		return "masstransport";
+	}// }}}
+    this.extrude = function(md) {
+        this.spcthickness=project3d(md,'vector',this.spcthickness,'type','node');
+        return this;
+    }
+		this.checkconsistency = function (md,solution,analyses){  // {{{
+
+			//Early return
+			if(!ArrayAnyEqual(ArrayIsMember(HydrologyShreveAnalysisEnum(),analyses),1) | (solution==TransientSolutionEnum() & md.trans.ismasstransport==0)) return; 
+
+			checkfield(md,'fieldname','masstransport.spcthickness','Inf',1,'timeseries',1);
+			checkfield(md,'fieldname','masstransport.isfreesurface','values',[0 ,1]);
+			checkfield(md,'fieldname','masstransport.hydrostatic_adjustment','values',['Absolute', 'Incremental']);
+			checkfield(md,'fieldname','masstransport.stabilization','values',[0,1,2,3,4]);
+			checkfield(md,'fieldname','masstransport.min_thickness','>',0);
+			checkfield(md,'fieldname','masstransport.requested_outputs','stringrow',1);
+
+		} // }}}
+		this.marshall=function(md,prefix,fid) { //{{{
+
+			var yts=365.*24.*3600.;
+
+			WriteData(fid,prefix,'object',this,'fieldname','spcthickness','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1);
+			WriteData(fid,prefix,'object',this,'fieldname','isfreesurface','format','Boolean');
+			WriteData(fid,prefix,'object',this,'fieldname','min_thickness','format','Double');
+			WriteData(fid,prefix,'data',StringToEnum(this.hydrostatic_adjustment),'format','Integer','name','md.masstransport.hydrostatic_adjustment');
+			WriteData(fid,prefix,'object',this,'fieldname','stabilization','format','Integer');
+			WriteData(fid,prefix,'object',this,'fieldname','vertex_pairing','format','DoubleMat','mattype',3);
+			WriteData(fid,prefix,'object',this,'fieldname','penalty_factor','format','Double');
+
+			//process requested outputs
+			var outputs = this.requested_outputs;
+			for (var i=0;i<outputs.length;i++){
+				if (outputs[i] == 'default') {
+					outputs.splice(i,1);
+					var newoutputs=this.defaultoutputs(md);
+					for (var j=0;j<newoutputs.length;j++) outputs.push(newoutputs[j]);
+				}
+			}
+			WriteData(fid,prefix,'data',outputs,'name','md.masstransport.requested_outputs','format','StringArray');
+		}//}}}
+		this.defaultoutputs = function(md) { //{{{
+			return ['Thickness','Surface','Base'];
+		}//}}}
+		this.fix=function() { //{{{
+			this.spcthickness=NullFix(this.spcthickness,NaN);
+			this.vertex_pairing=NullFix(this.vertex_pairing,NaN);
+		}//}}}
+	//properties 
+	// {{{
+
+	this.spcthickness           = NaN;
+	this.isfreesurface          = 0;
+	this.min_thickness          = 0;
+	this.hydrostatic_adjustment = 0;
+	this.stabilization          = 0;
+	this.vertex_pairing         = NaN;
+	this.penalty_factor         = 0;
+	this.requested_outputs      = [];
+
+	this.setdefaultparameters();
+	//}}}
+}
Index: /issm/trunk-jpl/jenkins/javascript/karma/scripts/specs/issm-ajax.spec.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/scripts/specs/issm-ajax.spec.js	(revision 20811)
+++ /issm/trunk-jpl/jenkins/javascript/karma/scripts/specs/issm-ajax.spec.js	(revision 20812)
@@ -13,5 +13,5 @@
     it("contains test101", function(done) {
         $.ajax({
-            url: 'http://localhost:8080/test188.js',
+            url: 'http://localhost:8080/test107.js',
             dataType: 'script',
             success: onAjaxSuccess,
Index: /issm/trunk-jpl/src/m/classes/masstransport.js
===================================================================
--- /issm/trunk-jpl/src/m/classes/masstransport.js	(revision 20811)
+++ /issm/trunk-jpl/src/m/classes/masstransport.js	(revision 20812)
@@ -41,4 +41,8 @@
 		return "masstransport";
 	}// }}}
+    this.extrude = function(md) {
+        this.spcthickness=project3d(md,'vector',this.spcthickness,'type','node');
+        return this;
+    }
 		this.checkconsistency = function (md,solution,analyses){  // {{{
 
Index: /issm/trunk-jpl/src/m/classes/stressbalance.js
===================================================================
--- /issm/trunk-jpl/src/m/classes/stressbalance.js	(revision 20811)
+++ /issm/trunk-jpl/src/m/classes/stressbalance.js	(revision 20812)
@@ -76,5 +76,5 @@
 		return "stressbalance";
 	}// }}}
-    this.extrude = function() {//{{{
+    this.extrude = function(md) {//{{{
         this.spcvx=project3d(md,'vector',this.spcvx,'type','node');
         this.spcvy=project3d(md,'vector',this.spcvy,'type','node');
Index: /issm/trunk-jpl/src/m/classes/thermal.js
===================================================================
--- /issm/trunk-jpl/src/m/classes/thermal.js	(revision 20811)
+++ /issm/trunk-jpl/src/m/classes/thermal.js	(revision 20812)
@@ -52,4 +52,16 @@
 		return "thermal";
 	}// }}}
+    this.extrude = function(md) {//{{{
+        this.spctemperature=project3d(md,'vector',this.spctemperature,'type','node','layer',md.mesh.numberoflayers,'padding',NaN);
+        if (md.initialization.temperature.length===md.mesh.numberofvertices) {
+            this.spctemperature = ArrayFill2D(Create2DArray(md.mesh.numberofvertices, 1), NaN);
+            var pos=ArrayFindNot2D(md.mesh.vertexonsurface, 0);
+            pos.forEach(function(x) { // impose observed temperature on surface
+                this.spctemperature[x] = md.initialization.temperature[x];
+            });
+        }
+
+        return this;
+    }//}}}
 	this.checkconsistency = function(md,solution,analyses){ // {{{
 
