Index: /issm/trunk-jpl/jenkins/javascript/karma/karma.conf.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/karma.conf.js	(revision 20823)
+++ /issm/trunk-jpl/jenkins/javascript/karma/karma.conf.js	(revision 20824)
@@ -12,4 +12,5 @@
     // list of files / patterns to load in the browser
     files: [
+      'node_modules/mathjs/dist/math.min.js',
       'lib/bin/EnumDefinitions.js',
       'lib/bin/issm-binaries.js',
@@ -32,4 +33,10 @@
       'lib/bin/thermal.js',
       'lib/bin/masstransport.js',
+      'lib/bin/calving.js',
+      'lib/bin/hydrologyshreve.js',
+      'lib/bin/matice.js',
+      'lib/bin/damage.js',
+      'lib/bin/qmu.js',
+      'lib/bin/basalforcings.js',
       'lib/bin/project3d.js',
       'lib/bin/model.js',
Index: /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/basalforcings.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/basalforcings.js	(revision 20824)
+++ /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/basalforcings.js	(revision 20824)
@@ -0,0 +1,80 @@
+//BASAL FORCINGS class definition
+//
+//   Usage:
+//      basalforcings=basalforcings();
+
+function basalforcings(){
+	//methods
+	this.setdefaultparameters = function() {//{{{
+
+	} // }}}
+	this.disp = function(){ // {{{
+		console.log(sprintf('   basal forcings parameters:'));
+
+		fielddisplay(this,'groundedice_melting_rate','basal melting rate (positive if melting) [m/yr]');
+		fielddisplay(this,'floatingice_melting_rate','basal melting rate (positive if melting) [m/yr]');
+		fielddisplay(this,'geothermalflux','geothermal heat flux [W/m^2]');
+
+	} // }}}
+    this.extrude = function(md) {//{{{
+        this.groundedice_melting_rate=project3d(md,'vector',this.groundedice_melting_rate,'type','node','layer',1); 
+        this.floatingice_melting_rate=project3d(md,'vector',this.floatingice_melting_rate,'type','node','layer',1); 
+        this.geothermalflux=project3d(md,'vector',this.geothermalflux,'type','node','layer',1); //bedrock only gets geothermal flux
+        return this;
+    }//}}}
+	this.classname = function(){ // {{{
+		return "basalforcings";
+	} // }}}
+		this.initialize = function (md){ // {{{
+
+			if (isNaN(this.groundedice_melting_rate)){
+				this.groundedice_melting_rate=NewArrayFill(md.mesh.numberofvertices,0);
+				console.log('      no basalforcings.groundedice_melting_rate specified: values set as zero');
+			}
+
+			if (isNaN(this.floatingice_melting_rate)){
+				this.floatingice_melting_rate=NewArrayFill(md.mesh.numberofvertices,0);
+				console.log('      no basalforcings.floatingice_melting_rate specified: values set as zero');
+			}
+
+		} // }}}
+		this.checkconsistency = function(md,solution,analyses) { //{{{
+
+			if(ArrayAnyEqual(ArrayIsMember(MasstransportAnalysisEnum(),analyses),1)){
+				if (!(solution==TransientSolutionEnum() & md.trans.ismasstransport==0)){
+					checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1);
+					checkfield(md,'fieldname','basalforcings.floatingice_melting_rate','NaN',1,'Inf',1,'timeseries',1);
+				}
+			}
+
+			if(ArrayAnyEqual(ArrayIsMember(BalancethicknessAnalysisEnum(),analyses),1)){
+				checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
+				checkfield(md,'fieldname','basalforcings.floatingice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
+			}
+			if(ArrayAnyEqual(ArrayIsMember(ThermalAnalysisEnum(),analyses),1)){
+				if (!(solution==TransientSolutionEnum() & md.trans.isthermal==0)){
+					checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1);
+					checkfield(md,'fieldname','basalforcings.floatingice_melting_rate','NaN',1,'Inf',1,'timeseries',1);
+					checkfield(md,'fieldname','basalforcings.geothermalflux','NaN',1,'Inf',1,'timeseries',1,'>=',0);
+				}
+			}
+		} // }}}
+		this.marshall=function(md,prefix,fid) { //{{{
+
+			var yts=365.0*24.0*3600.0;
+
+			WriteData(fid,prefix,'name','md.basalforcings.model','data',FloatingMeltRateEnum(),'format','Integer');
+			WriteData(fid,prefix,'object',this,'fieldname','groundedice_melting_rate','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
+			WriteData(fid,prefix,'object',this,'fieldname','floatingice_melting_rate','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1)
+			WriteData(fid,prefix,'object',this,'fieldname','geothermalflux','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1);
+		}//}}}
+		this.fix=function() { //{{{
+		}//}}}
+	//properties
+	//{{{
+	this.groundedice_melting_rate  = NaN;
+	this.floatingice_melting_rate  = NaN;
+	this.geothermalflux            = NaN;
+	this.setdefaultparameters();
+	//}}}
+}
Index: /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/matlabfunc.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/matlabfunc.js	(revision 20823)
+++ /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/matlabfunc.js	(revision 20824)
@@ -41,2 +41,22 @@
     return indices;
 }
+
+function ArrayFind2D(array, value) {
+    var indices = [];
+
+    for (var i = 0; i < array.length; ++i) {
+        for (var j = 0; j < array[0].length; ++j) {
+            if (array[i][j] === value) {
+                indices.push(array[i][j]);
+            }
+        }
+    }
+
+    return indices;
+}
+
+function getMatrixWidth(matrix) {
+    return matrix.reduce(function (result, row) {
+        return Math.max(result, row.length);
+    }, 0);
+}
Index: /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/model.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/model.js	(revision 20823)
+++ /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/model.js	(revision 20824)
@@ -359,5 +359,5 @@
                     for (var i = 0; i < md.mesh.elementconnectivity.length; i++) {
                         if (md.mesh.elementconnectivity[i] == 0) {
-                            md.mesh.elementconnectivity[i] = null;
+                            md.mesh.elementconnectivity[i] = NaN;
                         }
                     };
@@ -371,11 +371,5 @@
                     };
 
-                    md.mesh.elementconnectivity(find(isnan(md.mesh.elementconnectivity)))=0;
-
-                    for (var i = 0; i < md.mesh.elementconnectivity.length; ++i) {
-                        if (md.mesh.elementconnectivity[i] === null || typeof md.mesh.elementconnectivity[i] === 'undefined') {
-                            md.mesh.elementconnectivity[i] = 0;
-                        }
-                    }
+                    md.mesh.elementconnectivity.map(function(x) { return (isNaN(x)) ? 0 : x; });
                 }
 
@@ -383,6 +377,6 @@
                 md.damage=md.damage.extrude(md);
                 md.mask=md.mask.extrude(md);
-                md.qmu=extrude(md.qmu,md);
-                md.basalforcings=extrude(md.basalforcings,md);
+                md.qmu=md.qmu.extrude(md);
+                md.basalforcings=md.basalforcings.extrude(md);
 
                 //increase connectivity if less than 25:
Index: /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/qmu.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/qmu.js	(revision 20824)
+++ /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/qmu.js	(revision 20824)
@@ -0,0 +1,153 @@
+//QMU class definition
+//
+//   Usage:
+//      qmu=new qmu();
+
+function qmu (){
+	//methods
+	this.setdefaultparameters = function(){// {{{
+	}// }}}
+	this.disp= function(){// {{{
+
+		console.log(sprintf('   qmu parameters:'));
+
+		/*fielddisplay(this,'isdakota','is qmu analysis activated?');
+		for (var i=0;i<this.variables.length;i++){
+			console.log(sprintf('         variables%s:  (arrays of each variable class)',...
+						string_dim(this.variables,i)));
+		}
+		fnames=fieldnames(this.variables(i));
+		maxlen=0;
+		for j=1:numel(fnames)
+			maxlen=max(maxlen,length(fnames{j}));
+		end
+
+			for j=1:numel(fnames)
+				console.log(sprintf(['            %-' num2str(maxlen+1) 's:    [%ix%i]    ''%s'''],...
+							fnames{j},size(this.variables.(fnames{j})),class(this.variables.(fnames{j}))));
+		end
+			end
+			for i=1:numel(this.responses)
+				console.log(sprintf('         responses%s:  (arrays of each response class)',...
+							string_dim(this.responses,i)));
+		fnames=fieldnames(this.responses(i));
+		maxlen=0;
+		for j=1:numel(fnames)
+			maxlen=max(maxlen,length(fnames{j}));
+		end
+
+			for j=1:numel(fnames)
+				console.log(sprintf(['            %-' num2str(maxlen+1) 's:    [%ix%i]    ''%s'''],...
+							fnames{j},size(this.responses.(fnames{j})),class(this.responses.(fnames{j}))));
+		end
+			end
+			fielddisplay(this,'numberofresponses','number of responses') 
+			for i=1:numel(this.method);
+		if strcmp(class(this.method(i)),'dakota_method')
+			console.log(sprintf('            method%s :    ''%s''',...
+						string_dim(this.method,i),this.method(i).method));
+		end
+			end
+			for i=1:numel(this.params)
+				console.log(sprintf('         params%s:  (array of method-independent parameters)',...
+							string_dim(this.params,i)));
+		fnames=fieldnames(this.params(i));
+		maxlen=0;
+		for j=1:numel(fnames)
+			maxlen=max(maxlen,length(fnames{j}));
+		end
+
+			for j=1:numel(fnames)
+				console.log(sprintf(['            %-' num2str(maxlen+1) 's: %s'],...
+							fnames{j},any2str(this.params(i).(fnames{j}))));
+		end
+			end
+			for i=1:numel(this.results)
+				console.log(sprintf('         results%s:  (information from dakota files)',...
+							string_dim(this.results,i)));
+		fnames=fieldnames(this.results(i));
+		maxlen=0;
+		for j=1:numel(fnames)
+			maxlen=max(maxlen,length(fnames{j}));
+		end
+
+			for j=1:numel(fnames)
+				console.log(sprintf(['            %-' num2str(maxlen+1) 's:    [%ix%i]    ''%s'''],...
+							fnames{j},size(this.results.(fnames{j})),class(this.results.(fnames{j}))));
+		end
+			end
+			fielddisplay(this,'partition','user provided mesh partitioning, defaults to metis if not specified') 
+			fielddisplay(this,'numberofpartitions','number of partitions for semi-discrete qmu') 
+			fielddisplay(this,'variabledescriptors','');
+		fielddisplay(this,'responsedescriptors','');
+		fielddisplay(this,'method','array of dakota_method class');
+		fielddisplay(this,'mass_flux_profile_directory','directory for mass flux profiles');
+		fielddisplay(this,'mass_flux_profiles','list of mass_flux profiles');
+		fielddisplay(this,'mass_flux_segments','');
+		fielddisplay(this,'adjacency','');
+		fielddisplay(this,'vertex_weight','weight applied to each mesh vertex');
+		*/
+
+	}// }}}
+    this.extrude = function(md) {//{{{
+        console.log("ORIGINAL");
+        console.log(this.partition);
+        console.log("TRANSPOSE");
+        console.log(math.transpose(this.partition));
+        this.partition=project3d(md,'vector',math.transpose(this.partition),'type','node');
+        return this;
+    }//}}}
+	this.classname= function(){// {{{
+		return "qmu";
+	}// }}}
+		this.checkconsistency = function(md,solution,analyses) { //{{{
+
+			///Early return
+			if (!md.qmu.isdakota) return;
+			else md.checkmessage('qmu runs not supported yet!');
+
+		} // }}}
+		this.marshall=function(md,prefix,fid) { //{{{
+			WriteData(fid,prefix,'object',this,'fieldname','isdakota','format','Boolean');
+			if (!this.isdakota){
+				WriteData(fid,prefix,'data',0,'name','md.qmu.mass_flux_segments_present','format','Boolean');
+			}
+			else{
+				WriteData(fid,prefix,'object',this,'fieldname','partition','format','DoubleMat','mattype',2);
+				WriteData(fid,prefix,'object',this,'fieldname','numberofpartitions','format','Integer');
+				WriteData(fid,prefix,'object',this,'fieldname','numberofresponses','format','Integer');
+				WriteData(fid,prefix,'object',this,'fieldname','variabledescriptors','format','StringArray');
+				WriteData(fid,prefix,'object',this,'fieldname','responsedescriptors','format','StringArray');
+				if (this.mass_flux_segments.length){
+					WriteData(fid,prefix,'data',this.mass_flux_segments,'name','md.qmu.mass_flux_segments','format','MatArray');
+					flag=true; 
+				}
+				else flag=false; 
+				WriteData(fid,prefix,'data',flag,'name','md.qmu.mass_flux_segments_present','format','Boolean');
+			}
+		}//}}}
+		this.fix=function() { //{{{
+		}//}}}
+	//properties 
+	// {{{
+
+	this.isdakota                    = 0;
+	this.variables                   = []
+	this.responses                   = [];
+	this.method                      = []
+	this.params                      = []
+	this.results                     = []
+	this.partition                   = NaN;
+	this.numberofpartitions          = 0;
+	this.numberofresponses           = 0;
+	this.variabledescriptors         = []
+	this.responsedescriptors         = []
+	this.mass_flux_profile_directory = NaN;
+	this.mass_flux_profiles          = NaN;
+	this.mass_flux_segments          = []
+	this.adjacency                   = NaN;
+	this.vertex_weight               = NaN;
+
+	this.setdefaultparameters();
+	//}}}
+}
Index: /issm/trunk-jpl/jenkins/javascript/karma/package.json
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/package.json	(revision 20823)
+++ /issm/trunk-jpl/jenkins/javascript/karma/package.json	(revision 20824)
@@ -9,4 +9,5 @@
     "karma-junit-reporter": "^1.0.0",
     "karma-requirejs": "^1.0.0",
+    "mathjs": "^3.2.1",
     "requirejs": "^2.2.0"
   }
Index: /issm/trunk-jpl/src/m/classes/basalforcings.js
===================================================================
--- /issm/trunk-jpl/src/m/classes/basalforcings.js	(revision 20823)
+++ /issm/trunk-jpl/src/m/classes/basalforcings.js	(revision 20824)
@@ -17,4 +17,10 @@
 
 	} // }}}
+    this.extrude = function(md) {//{{{
+        this.groundedice_melting_rate=project3d(md,'vector',this.groundedice_melting_rate,'type','node','layer',1); 
+        this.floatingice_melting_rate=project3d(md,'vector',this.floatingice_melting_rate,'type','node','layer',1); 
+        this.geothermalflux=project3d(md,'vector',this.geothermalflux,'type','node','layer',1); //bedrock only gets geothermal flux
+        return this;
+    }//}}}
 	this.classname = function(){ // {{{
 		return "basalforcings";
Index: /issm/trunk-jpl/src/m/classes/model.js
===================================================================
--- /issm/trunk-jpl/src/m/classes/model.js	(revision 20823)
+++ /issm/trunk-jpl/src/m/classes/model.js	(revision 20824)
@@ -359,5 +359,5 @@
                     for (var i = 0; i < md.mesh.elementconnectivity.length; i++) {
                         if (md.mesh.elementconnectivity[i] == 0) {
-                            md.mesh.elementconnectivity[i] = null;
+                            md.mesh.elementconnectivity[i] = NaN;
                         }
                     };
@@ -371,11 +371,5 @@
                     };
 
-                    md.mesh.elementconnectivity(find(isnan(md.mesh.elementconnectivity)))=0;
-
-                    for (var i = 0; i < md.mesh.elementconnectivity.length; ++i) {
-                        if (md.mesh.elementconnectivity[i] === null || typeof md.mesh.elementconnectivity[i] === 'undefined') {
-                            md.mesh.elementconnectivity[i] = 0;
-                        }
-                    }
+                    md.mesh.elementconnectivity.map(function(x) { return (isNaN(x)) ? 0 : x; });
                 }
 
@@ -383,6 +377,6 @@
                 md.damage=md.damage.extrude(md);
                 md.mask=md.mask.extrude(md);
-                md.qmu=extrude(md.qmu,md);
-                md.basalforcings=extrude(md.basalforcings,md);
+                md.qmu=md.qmu.extrude(md);
+                md.basalforcings=md.basalforcings.extrude(md);
 
                 //increase connectivity if less than 25:
Index: /issm/trunk-jpl/src/m/classes/qmu.js
===================================================================
--- /issm/trunk-jpl/src/m/classes/qmu.js	(revision 20823)
+++ /issm/trunk-jpl/src/m/classes/qmu.js	(revision 20824)
@@ -90,4 +90,12 @@
 
 	}// }}}
+    this.extrude = function(md) {//{{{
+        console.log("ORIGINAL");
+        console.log(this.partition);
+        console.log("TRANSPOSE");
+        console.log(math.transpose(this.partition));
+        this.partition=project3d(md,'vector',math.transpose(this.partition),'type','node');
+        return this;
+    }//}}}
 	this.classname= function(){// {{{
 		return "qmu";
