Index: /issm/trunk-jpl/src/m/classes/clusters/generic.js
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/generic.js	(revision 21436)
+++ /issm/trunk-jpl/src/m/classes/clusters/generic.js	(revision 21437)
@@ -43,5 +43,5 @@
 			fid=fopen(modelname+'.queue','w');
 			fprintf(fid,'#!%s\n',cluster.shell);
-			fprintf(fid,'mpiexec -np %i %s/%s %s %s %s 2> %s.errlog >%s.outlog ',cluster.np,cluster.codepath,executable,solution,cluster.executionpath+'/'+dirname,modelname,modelname,modelname);					
+			fprintf(fid,'mpiexec -np %i %s/%s %s %s %s 2> %s.errlog >%s.outlog ',cluster.np,cluster.codepath,executable,EnumToString(solution),cluster.executionpath+'/'+dirname,modelname,modelname,modelname);					
 			fclose(fid);
 	} //}}}
@@ -92,5 +92,5 @@
 			}
 			var responseText = window.atob(request.responseText.slice(request.position + 10).replace(/\s/g, ''));
-            var buffer = str2ab(responseText);
+            var buffer = pako.inflate(str2ab(responseText));
 			var returnBuffer = new Uint8Array(buffer);
 			var returnBuffer_size = returnBuffer.byteLength;
@@ -115,33 +115,40 @@
 		
 		var npbuffer = this.str2ab(md.cluster.np.toString());
+		npbuffer = pako.deflate(npbuffer);
 		var nplength = new Uint32Array(1);
 		nplength[0] = npbuffer.byteLength;
 		
 		var codeversionbuffer = this.str2ab(md.cluster.codeversion.toString());
+		codeversionbuffer = pako.deflate(codeversionbuffer);
 		var codeversionlength = new Uint32Array(1);
 		codeversionlength[0] = codeversionbuffer.byteLength;
 		
 		var runtimenamebuffer = this.str2ab(runtimename);
+		runtimenamebuffer = pako.deflate(runtimenamebuffer);
 		var runtimenamelength = new Uint32Array(1);
 		runtimenamelength[0] = runtimenamebuffer.byteLength;
 		
 		var namebuffer = this.str2ab(name);
+		namebuffer = pako.deflate(namebuffer);
 		var namelength = new Uint32Array(1);
 		namelength[0] = namebuffer.byteLength;
 		
 		var toolkitsbuffer = this.str2ab(toolkitsstring);
+		toolkitsbuffer = pako.deflate(toolkitsbuffer);
 		var toolkitslength = new Uint32Array(1);
 		toolkitslength[0] = toolkitsbuffer.byteLength;
 		
 		var solutionbuffer = this.str2ab(solutionstring);
+		solutionbuffer = pako.deflate(solutionbuffer);
 		var solutionlength = new Uint32Array(1);
 		solutionlength[0] = solutionbuffer.byteLength;
 		
-		var binbuffer = new Uint8Array(fid.rawbuffer()); //seems that 16 array bytes length could be incompatible.
+		var binbuffer = new Uint8Array(fid.rawbuffer()); //seems that 16 bits length could be incompatible.
+		binbuffer = pako.deflate(binbuffer);
 		var binlength = new Uint32Array(1);
 		binlength[0] = binbuffer.byteLength;
 		
 		var data = new Blob([nplength,npbuffer,codeversionlength,codeversionbuffer,runtimenamelength,runtimenamebuffer,namelength,namebuffer,toolkitslength,toolkitsbuffer,solutionlength,solutionbuffer,binlength,binbuffer]);
-	
+		
 		request.open("POST", this.url, true);
 		request.responseType = 'application/octet-stream';
Index: /issm/trunk-jpl/src/m/plot/plot_manager.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_manager.js	(revision 21436)
+++ /issm/trunk-jpl/src/m/plot/plot_manager.js	(revision 21437)
@@ -15,8 +15,7 @@
 	var gl = canvas.gl;
 	//TODO: each plot_ should add their node to the canvas.node array
-
 	//figure out if this is a special plot
 	if (typeof data === 'string'){
-
+		
 		switch(data){
 
Index: /issm/trunk-jpl/src/m/plot/plot_quiver.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_quiver.js	(revision 21436)
+++ /issm/trunk-jpl/src/m/plot/plot_quiver.js	(revision 21437)
@@ -1,31 +1,29 @@
-function plot_quiver(md,options,canvas) { //{{{
-	//PLOT_QUIVER - quiver plot with colors
+function plot_unit(md,data,datatype,options,canvas) { //{{{
+	//PLOT_UNIT - unit plot, display data
 	//
 	//   Usage:
-	//      plot_quiver(md,options,canvas)
+	//      plot_unit(md,data,options,canvas);
 	//
 	//   See also: PLOTMODEL, PLOT_MANAGER
 
 	//declare variables:  {{{
-	var vertices = [];
-	var indices = [];
-	var colors = [];
+	//Process data and model
+	var meshresults = processmesh(md,data,options);
+	var x = meshresults[0]; 
+	var y = meshresults[1]; 
+	var z = meshresults[2]; 
+	var elements = meshresults[3];
+	var is2d = meshresults[4]; 
+	var isplanet = meshresults[5];
+	
+	var vertices = new Float32Array(x.length * 3);
+	var texcoords = new Float32Array(x.length * 2);
+	var indices = new Uint16Array(elements.length * 3);
+	var nanindices = {};
 	var xmin,xmax;
 	var ymin,ymax;
 	var zmin,zmax;
-	var scale,matrixscale,vertexscale;
-	
-	//Process data and model
-	var meshresults = processmesh(md,[],options);
-	var x = meshresults[0]; 
-	var y = meshresults[1]; 
-	var z = meshresults[2]; 
-	var elements = meshresults[3]; 
-	var is2d = meshresults[4]; 
-	var isplanet = meshresults[5];
-	var v = md.initialization.vel;
-	var vx = md.initialization.vx;
-	var vy = md.initialization.vy;
-		
+	var datamin,datamax,datadelta;
+	var matrixscale,vertexscale;
 	//Compue scaling through matrices for 2d meshes and vertices for 3d meshes
 	if (!md.geometry.surface) {
@@ -58,4 +56,5 @@
 	zmin = zlim[0];
 	zmax = zlim[1];
+	var caxis;
 
 	//Compute gl variables:
@@ -63,75 +62,236 @@
 	var node = Node(gl);
 	canvas.nodes[canvas.nodes.length] = node;
-	node.name = "quiver";
-	node.shaderName = "Colored";
+	canvas.unitNode = node;
+	node.name = "unit";
+	node.shaderName = "Textured";
 	node.shader = gl.shaders[node.shaderName];
-	node.lineWidth = options.getfieldvalue('linewidth',1);
 	node.scale = [1, 1, matrixscale];
 	node.rotation = [-90, 0, 0];
 	node.translation = [0, 0, 0];
 	node.center = [(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2];
-	node.drawMode = gl.LINES;
-	node.useIndexBuffer = false;
-	node.drawOrder = 0;
+	node.alpha = options.getfieldvalue('alpha',1.0);
+	node.drawOrder = 1;
 	node.maskEnabled = options.getfieldvalue('innermask','off') == 'on';
-	node.maskHeight = options.getfieldvalue('innermaskheight',150.0)*options.getfieldvalue('heightscale',1);
+	node.maskHeight = options.getfieldvalue('innermaskheight',150.0);
 	node.maskColor = options.getfieldvalue('innermaskcolor',[0.0,0.0,1.0,1.0]);
+	node.enabled = options.getfieldvalue('nodata','off') == 'off';
 	updateModelMatrix(node);
 
-	//retrieve some options
-	var edgecolor=new RGBColor(options.getfieldvalue('edgecolor','black'));
-	if (edgecolor.ok) edgecolor = [edgecolor.r/255.0, edgecolor.g/255.0, edgecolor.b/255.0, 1.0];
-	else throw Error(sprintf("s%s%s\n","initWebGL error message: cound not find out edgecolor color for curent canvas ",canvas));
-
-	//node plot {{{
-	if (elements[0].length==6){ //prisms
-	}
-	else if (elements[0].length==4){ //tetras
-	}
-	else{ //2D triangular elements
-		var xyz = vec3.create();
-		var xyz = vec3.create();
-		var direction = vec3.create();
-		var vertex = vec3.create();
-		var vertexBase = vec3.create();
-		var verticesArrow = [vec3.fromValues(0.0, 0.0, 0.0), vec3.fromValues(1.0, 0.0, 0.0), vec3.fromValues(0.667, -0.167, 0.0), vec3.fromValues(1.0, 0.0, 0.0), vec3.fromValues(0.667, 0.166, 0.0), vec3.fromValues(1.0, 0.0, 0.0)];
-		var magnitude;
-		var color = edgecolor;
-		var scaling = options.getfieldvalue('scaling',1);
-		var scale;
-		for(var i = 0; i < x.length; i++){
-			//Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing
-			if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i])) continue;
-			//Scale vertices
-			xyz = vec3.fromValues(x[i], y[i], z[i]);
-			magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale;
-			vec3.normalize(direction, xyz);
-			vec3.scale(vertex, direction, magnitude);
-			vec3.copy(vertexBase, vertex);
-			
-			scale = scaling*v[i];
-			var modelMatrix = mat4.create();
-			var scaleMatrix = mat4.create();
-			var rotationMatrix = mat4.create();
-			mat4.scale(scaleMatrix, scaleMatrix, vec3.fromValues(scale, scale, scale));
-			mat4.rotate(rotationMatrix, rotationMatrix, Math.atan2(vy[i], vx[i]), [0.0, 0.0, 1.0]);
-			mat4.multiply(modelMatrix, rotationMatrix, scaleMatrix);
-
-			var temp = vec3.fromValues(0.0, 0.0, 0.0);
-			for (var j = 0; j < 6; j++){
-				vec3.transformMat4(vertex, verticesArrow[j], modelMatrix);
-				vec3.add(vertex, vertex, vertexBase);
-				vertices[vertices.length] = vertex[0];
-				vertices[vertices.length] = vertex[1];
-				vertices[vertices.length] = vertex[2];
+	switch(datatype){
+		//element plot {{{
+		case 1:
+			pos=ArrayFindNot(data,NaN); //needed for element on water
+			if (elements[0].length==6){ //prisms
+			}
+			else if (elements[0].length==4){ //tetras
+			}
+			else{ //2D triangular elements
+			}
+			break;
+		//}}}
+		//node plot {{{
+		case 2:
+			if (elements[0].length==6){ //prisms
+			}
+			else if (elements[0].length==4){ //tetras
+			}
+			else{ //triangular elements	
+				caxis = options.getfieldvalue('caxis',[ArrayMin(data),ArrayMax(data)]);
+				if (options.getfieldvalue('log','off')!='off') caxis = [Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log',10)),Math.log10(caxis[1])/Math.log10(options.getfieldvalue('log',10))];
+				datamin = caxis[0];
+				datamax = caxis[1];
+				datadelta = datamax - datamin;
+
+				var xyz = vec3.create();
+				var direction = vec3.create();
+				var vertex = vec3.create();
+				var magnitude;
+
+				for(var i = 0, vindex = 0, tindex = 0; i < x.length; i++){
+					//Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing
+					if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i]) || isNaN(data[i])) {
+						nanindices[i] = i;
+						vertices[vindex++] = vertex[0];
+						vertices[vindex++] = vertex[1];
+						vertices[vindex++] = vertex[2];
+						
+						texcoords[tindex++] = 0.5;
+						texcoords[tindex++] = 0.0;
+						continue;
+					}
+
+					//Scale vertices
+					xyz = vec3.fromValues(x[i], y[i], z[i]);
+					magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale;
+					vec3.normalize(direction, xyz);
+					vec3.scale(vertex, direction, magnitude);
+					vertices[vindex++] = vertex[0];
+					vertices[vindex++] = vertex[1];
+					vertices[vindex++] = vertex[2];
+
+					texcoords[tindex++] = 0.5;
+					texcoords[tindex++] = clamp((data[i] - datamin) / datadelta, 0.0, 1.0);
+				}
+
+				//linearize the elements array: 
+				var element;
+				for(var i = 0, iindex = 0; i < elements.length; i++){
+					element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1];
+					if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue;
+					indices[iindex++] = element[0];
+					indices[iindex++] = element[1];
+					indices[iindex++] = element[2];
+				}
+			}
+			node.mesh = GL.Mesh.load({vertices:vertices, coords:texcoords, triangles:indices}, null, null, gl);
+			node.mesh.octree = new GL.Octree(node.mesh);
+			break;
+		//}}}
+		//quiver plot {{{
+		case 3:
+			if (is2d){
+				//plot_quiver(x,y,data(:,1),data(:,2),options);
+			}
+			else{
+				//plot_quiver3(x,y,z,data(:,1),data(:,2),data(:,3),options);
+			}
+			break;
+		//}}}
+		//node transient plot {{{
+		case 5:
+			if (elements[0].length==6){ //prisms
+			}
+			else if (elements[0].length==4){//tetras
+			}
+			else{ //triangular elements
+				var xyz = vec3.create();
+				var direction = vec3.create();
+				var vertex = vec3.create();
+				var magnitude;
+				var timestamps = data[data.length-1];
+				for(var i = 0, vindex = 0, tindex = 0; i < x.length; i++){
+					//Check for NaN values and remove from indices array as necessary, but preserve vertex array spacing
+					if (isNaN(x[i]) || isNaN(y[i]) || isNaN(z[i]) || isNaN(data[i][0])) {
+						nanindices[i] = i;
+					}
+					else {
+						//Scale vertices
+						xyz = vec3.fromValues(x[i], y[i], z[i]);
+						magnitude = vec3.length(xyz) + md.geometry.surface[i] * vertexscale;
+						vec3.normalize(direction, xyz);
+						vec3.scale(vertex, direction, magnitude);
+					}
+					vertices[vindex++] = vertex[0];
+					vertices[vindex++] = vertex[1];
+					vertices[vindex++] = vertex[2];
+				}	
+				//Transpose data to obtain column addressable data matrix
+				data = data[0].map(function(col, i) { 
+					return data.map(function(row) { 
+						return row[i]
+					})
+				});
+				//Prevent evaluation of datasubarray min/max if caxis exists
+				if (options.exist('caxis')) caxis = options.getfieldvalue('caxis');
+				else caxis = [ArrayMin(data[0]),ArrayMax(data[0].slice(0,-1))];
+				if (options.getfieldvalue('log','off')!='off') caxis = [Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log',10)),Math.log10(caxis[1])/Math.log10(options.getfieldvalue('log',10))];
+				//Prepare texcoords to hold array of data values
+				texcoords = [];
+				for(var i = 0; i < data.length; i++){					
+					datamin = caxis[0];
+					datamax = caxis[1];
+					datadelta = datamax - datamin;
+					//Precalculate arrays for each datasubarray, trimming off timestamp value by using x.length instead of data[i].length
+					texcoords[i] = new Float32Array(x.length * 2);
+					for(var j = 0, index = 0; j < x.length; j++){
+						texcoords[i][index++] = 0.5;
+						texcoords[i][index++] = clamp((data[i][j] - datamin) / datadelta, 0.0, 1.0);
+					}
+				}
 				
-				colors[colors.length] = color[0];
-				colors[colors.length] = color[1];
-				colors[colors.length] = color[2];
-				colors[colors.length] = color[3];
-			}
-		}
-	}
-	//}}}
-	node.mesh = GL.Mesh.load({vertices:vertices, colors:colors}, null, null, gl);
+				//linearize the elements array:
+				var element;
+				for(var i = 0, iindex = 0; i < elements.length; i++){
+					element = [elements[i][0] - 1, elements[i][1] - 1, elements[i][2] - 1];
+					if (element[0] in nanindices || element[1] in nanindices || element[2] in nanindices) continue;
+					indices[iindex++] = element[0];
+					indices[iindex++] = element[1];
+					indices[iindex++] = element[2];
+				}
+				var frame =
+				//Initialize movie loop
+				node.movieLoop = canvas.movieOptions.loop;
+				node.movieInterval = 1000 / canvas.movieOptions.fps;
+				node.movieTimestamps = timestamps;
+				node.movieLength = timestamps.length;
+				node.movieFrame = 0;
+
+				var quiverVelFrames = {};
+				for(var i=0; i < md.results.length; i++){
+					quiverVelFrames[Math.floor(md.results[i].time)] = md.results[i];
+				}
+
+				if (canvas.movieHandler) { clearInterval(canvas.movieHandler); }
+				canvas.movieHandler = setInterval(function () {
+						node.movieFrame = canvas.movieFrame;
+						if (canvas.moviePlay && canvas.movieIncrement) {
+							if (canvas.movieReverse) {
+								if (node.movieFrame == 0) {
+									if (node.movieLoop) {
+										node.movieFrame = node.movieLength - 1;
+									}
+									else {
+										toggleMoviePlay(canvas);
+									}
+								}
+								else {
+									node.movieFrame = node.movieFrame - 1;
+								}
+							}
+							else { 
+								if (node.movieFrame == node.movieLength - 1) {
+									if (node.movieLoop) {
+										node.movieFrame = 0;
+									}
+									else { 
+										toggleMoviePlay(canvas);
+									}
+								}
+								else {
+									node.movieFrame = node.movieFrame + 1;
+								}
+							}
+						}
+						if (canvas.progressBar) {
+							canvas.progressBar.val(node.movieFrame);
+							canvas.progressBar.slider('refresh');
+						}
+						if (canvas.timeLabel) { canvas.timeLabel.html(node.movieTimestamps[node.movieFrame].toFixed(0) + " " + options.getfieldvalue("movietimeunit","yr")); }
+
+						var buffer = node.mesh.getBuffer("coords");
+						buffer.data = texcoords[node.movieFrame];
+						buffer.upload(canvas.gl.DYNAMIC_DRAW);
+						node.mesh.octree = new GL.Octree(node.mesh);
+					
+						if(options.getfieldvalue('quiver') == 'data'){
+							plot_quiver(md,options,canvas, {vel:quiverVelFrames[node.movieFrame].Vel, vx:quiverVelFrames[node.movieFrame].Vx, vy:quiverVelFrames[node.movieFrame].Vy});
+
+						}
+						canvas.movieFrame = node.movieFrame;
+					}, node.movieInterval);
+				if (canvas.progressBar) {
+					canvas.movieFrame = 0;
+					canvas.progressBar.val(0);
+					canvas.progressBar.attr('max', node.movieLength-1);
+					canvas.progressBar.slider('refresh');
+				}
+				
+			}
+			node.mesh = GL.Mesh.load({vertices:vertices, coords:texcoords[0], triangles:indices}, null, null, gl);
+			node.mesh.octree = new GL.Octree(node.mesh);
+			break;
+		//}}}
+		default:
+			throw Error(sprintf("%s%i%s\n",'case ',datatype,' not supported'));
+	}
 } //}}}
Index: /issm/trunk-jpl/src/m/plot/plot_unit.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_unit.js	(revision 21436)
+++ /issm/trunk-jpl/src/m/plot/plot_unit.js	(revision 21437)
@@ -26,5 +26,4 @@
 	var datamin,datamax,datadelta;
 	var matrixscale,vertexscale;
-
 	//Compue scaling through matrices for 2d meshes and vertices for 3d meshes
 	if (!md.geometry.surface) {
@@ -220,5 +219,5 @@
 					indices[iindex++] = element[2];
 				}
-			
+				var frame =
 				//Initialize movie loop
 				node.movieLoop = canvas.movieOptions.loop;
@@ -227,4 +226,10 @@
 				node.movieLength = timestamps.length;
 				node.movieFrame = 0;
+
+				var quiverVelFrames = {};
+				for(var i=0; i < md.results.length; i++){
+					quiverVelFrames[Math.floor(md.results[i].time)] = md.results[i];
+				}
+
 				if (canvas.movieHandler) { clearInterval(canvas.movieHandler); }
 				canvas.movieHandler = setInterval(function () {
@@ -268,5 +273,9 @@
 						buffer.upload(canvas.gl.DYNAMIC_DRAW);
 						node.mesh.octree = new GL.Octree(node.mesh);
-
+					
+						if(options.getfieldvalue('quiver') == 'data'){
+							plot_quiver(md,options,canvas, {vel:quiverVelFrames[node.movieFrame].Vel, vx:quiverVelFrames[node.movieFrame].Vx, vy:quiverVelFrames[node.movieFrame].Vy});
+
+						}
 						canvas.movieFrame = node.movieFrame;
 					}, node.movieInterval);
Index: /issm/trunk-jpl/src/m/plot/webgl.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/webgl.js	(revision 21436)
+++ /issm/trunk-jpl/src/m/plot/webgl.js	(revision 21437)
@@ -1,2 +1,4 @@
+/*This is where we have all our webgl relevant functionality for the plotting routines: */
+
 /*This is where we have all our webgl relevant functionality for the plotting routines: */
 
@@ -92,6 +94,47 @@
 	if (backgroundcolor.ok) { canvas.backgroundcolor = [backgroundcolor.r/255.0, backgroundcolor.g/255.0, backgroundcolor.b/255.0, 1.0]; }
 	else { throw Error(sprintf('s%s%s\n','initWebGL error message: cound not find out background color for curent canvas ',canvas)); }
-	
+
+	//TODO: Make permalinks more robust and less interdependent on UI
+	//Override with parameters from URL, if any
+	if (!canvas.usedparemters) {
+		function getJsonFromUrl() {
+			var query = location.search.substr(1);
+			var result = {};
+			query.split("&").forEach(function(part) {
+				var item = part.split("=");
+				result[item[0]] = decodeURIComponent(item[1]);
+			});
+			return result;
+		}
+		parameters = getJsonFromUrl();
+		
+		if (parameters["rotation"]) {
+			canvas.rotation = JSON.parse(parameters["rotation"]);
+		}
+		if (parameters["view"]) {
+			canvas.view = JSON.parse(parameters["view"]);
+		}
+		if (parameters["zoom"]) {
+			canvas.zoom = JSON.parse(parameters["zoom"]);
+		}
+		if (parameters["initial"]) {
+			initial = JSON.parse(parameters["initial"]);
+			if (!initial) {
+				if (typeof SolveGlacier == 'function') {
+					SolveGlacier();
+				}
+				if (typeof SolveSlr == 'function') {
+					SolveSlr();
+				}
+			}
+		}
+		canvas.usedparemters = true;
+	}
+
 	return gl;
+} //}}}
+function generatePermalink() { //{{{
+	var permalink = window.location.origin + window.location.pathname + "?rotation=" + JSON.stringify(canvas.rotation) + "&view=" + JSON.stringify(canvas.view) + "&zoom=" + JSON.stringify(canvas.zoom) + "&initial=" + JSON.stringify(initial);
+	window.prompt("Share this simulation: ", permalink);
 } //}}}
 function loadShaders(gl,rootPath) { //{{{
