Index: /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/model.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/model.js	(revision 20792)
+++ /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/model.js	(revision 20793)
@@ -5,4 +5,12 @@
 
 function model () {
+    function ones(...args) {
+        var array = [];
+        for (var i = 0; i < args[0]; ++i) {
+            array.push(args.length === 1 ? 1 : ones(args.slice(1)));
+        }
+        return array;
+    }
+
 	//methods
 		this.disp = function() { //{{{
@@ -111,5 +119,5 @@
 
 		} //}}}
-        this.extrude = function(md, ...args) { //{{{
+        this.extrude = function(md) { //{{{
         //EXTRUDE - vertically extrude a 2d mesh
         //
@@ -134,5 +142,5 @@
 
         //some checks on list of arguments
-            var argc = args.length;
+            var argc = arguments.length;
 
             if ((argc > 4) | (argc < 2)) {
@@ -142,5 +150,5 @@
             //Extrude the mesh
             if (argc==2) { //list of coefficients
-                clist=args[0];
+                clist=arguments[0];
 
                 if (clist.some(function(x) { return x < 0; }) | clist.some(function(x) { return x > 1; }))
@@ -156,22 +164,22 @@
                 numlayers=extrusionlist.length;
             } else if (argc==3) { //one polynomial law
-                if (args[2]<=0) {
+                if (arguments[2]<=0) {
                     //help extrude;
                     throw 'extrusionexponent must be >=0';
                 }
-                numlayers=args[0];
+                numlayers=arguments[0];
 
                 extrusionlist = [];
 
                 for (var i = 0; i < numlayers; i++) {
-                    extrusionlist.push(Math.pow(i/(numlayers-1), args[2]));
+                    extrusionlist.push(Math.pow(i/(numlayers-1), arguments[2]));
                 };
 
             } else if (argc==4) { //two polynomial laws
-                numlayers=args[0];
-                lowerexp=args[1];
-                upperexp=args[2];
-
-                if (args[1]<=0 | args[2]<=0) {
+                numlayers=arguments[0];
+                lowerexp=arguments[1];
+                upperexp=arguments[2];
+
+                if (arguments[1]<=0 | args[2]<=0) {
                     throw 'lower and upper extrusionexponents must be >=0';
                 }
@@ -202,14 +210,15 @@
 
             if (numlayers<2) {
-                error('number of layers should be at least 2');
+                console.error('number of layers should be at least 2');
             }
 
             if (md.mesh.domaintype() !== '3D') {
-                error('Cannot extrude a 3d mesh (extrude cannot be called more than once)');
+                console.error('Cannot extrude a 3d mesh (extrude cannot be called more than once)');
             }
 
             //Initialize with the 2d mesh
             mesh2d = md.mesh;
-            md.mesh=mesh3dprisms();
+            md.mesh=new mesh3dprisms();
+
             md.mesh.x                           = mesh2d.x;
             md.mesh.y                           = mesh2d.y;
@@ -244,88 +253,88 @@
             };
 
-            number_nodes3d=size(x3d,1); //number of 3d nodes for the non extruded part of the mesh
-
-                //Extrude elements 
-                elements3d=[];
-                for (var i = 0; i < numlayers; i++) {
-                    elements3d.push(md.mesh.elements+(i-1)*md.mesh.numberofvertices, md.mesh.elements+i*md.mesh.numberofvertices); //Create the elements of the 3d mesh for the non extruded part
-                };
-
-                number_el3d=size(elements3d,1); //number of 3d nodes for the non extruded part of the mesh
-
-                function fillArray(value, len) {
-                    if (len == 0) return [];
-                    var a = [value];
-                    while (a.length * 2 <= len) a = a.concat(a);
-                    if (a.length < len) a = a.concat(a.slice(0, len - a.length));
-                    return a;
-                }
-
-                //Keep a trace of lower and upper nodes
-                //lowervertex=NaN*ones(number_nodes3d,1);
-                //uppervertex=NaN*ones(number_nodes3d,1);
-
-                lowervertex = fillArray(null, number_nodes3d);
-                uppervertex = fillArray(null, number_nodes3d);
-
-                //lowervertex(md.mesh.numberofvertices+1:end)=1:(numlayers-1)*md.mesh.numberofvertices;
-                //uppervertex(1:(numlayers-1)*md.mesh.numberofvertices)=md.mesh.numberofvertices+1:number_nodes3d;
-
-                for (var i = md.mesh.numberofvertices+1, k = 1; i < lowervertex.length && k <= (numlayers-1)*md.mesh.numberofvertices; i++, k++) {
-                    lowervertex[i] = k;
-                };
-
-                for (var i = 1, k = md.mesh.numberofvertices+1; i <= (numlayers-1)*md.mesh.numberofvertices && k <= number_nodes3d; i++, k++) {
-                    uppervertex[i] = k;
-                };
-
-                md.mesh.lowervertex=lowervertex;
-                md.mesh.uppervertex=uppervertex;
-
-                //same for lower and upper elements
-                lowerelements = fillArray(null, number_el3d);
-                upperelements = fillArray(null, number_el3d);
-                //lowerelements(md.mesh.numberofelements+1:end)=1:(numlayers-2)*md.mesh.numberofelements;
-                //upperelements(1:(numlayers-2)*md.mesh.numberofelements)=md.mesh.numberofelements+1:(numlayers-1)*md.mesh.numberofelements;
-
-                for (var i = md.mesh.numberofvertices+1, k = 1; i < lowerelements.length && k <= (numlayers-2)*md.mesh.numberofelements; i++, k++) {
-                    lowerelements[i] = k;
-                };
-
-                for (var i = 1, k = md.mesh.numberofelements + 1; i <= (numlayers-2)*md.mesh.numberofelements && k <= (numlayers-1)*md.mesh.numberofelements; i++, k++) {
-                    upperelements[i] = k;
-                };
-
-                md.mesh.lowerelements=lowerelements;
-                md.mesh.upperelements=upperelements;
-
-                //Save old mesh 
-                md.mesh.x2d=md.mesh.x;
-                md.mesh.y2d=md.mesh.y;
-                md.mesh.elements2d=md.mesh.elements;
-                md.mesh.numberofelements2d=md.mesh.numberofelements;
-                md.mesh.numberofvertices2d=md.mesh.numberofvertices;
-
-                //Build global 3d mesh 
-                md.mesh.elements=elements3d;
-                md.mesh.x=x3d;
-                md.mesh.y=y3d;
-                md.mesh.z=z3d;
-                md.mesh.numberofelements=number_el3d;
-                md.mesh.numberofvertices=number_nodes3d;
-                md.mesh.numberoflayers=numlayers;
-
-                //Ok, now deal with the other fields from the 2d mesh:
-
-                    //bedinfo and surface info
-                md.mesh.vertexonbase=project3d(md,'vector',ones(md.mesh.numberofvertices2d,1),'type','node','layer',1);
-                md.mesh.vertexonsurface=project3d(md,'vector',ones(md.mesh.numberofvertices2d,1),'type','node','layer',md.mesh.numberoflayers);
-                md.mesh.vertexonboundary=project3d(md,'vector',md.mesh.vertexonboundary,'type','node');
-
-                //lat long
-                md.mesh.lat=project3d(md,'vector',md.mesh.lat,'type','node');
-                md.mesh.long=project3d(md,'vector',md.mesh.long,'type','node');
-
-                md.geometry=extrude(md.geometry,md);
+            number_nodes3d=x3d.length; //number of 3d nodes for the non extruded part of the mesh
+
+            //Extrude elements 
+            elements3d=[];
+            for (var i = 0; i < numlayers; i++) {
+                elements3d.push(md.mesh.elements+(i-1)*md.mesh.numberofvertices, md.mesh.elements+i*md.mesh.numberofvertices); //Create the elements of the 3d mesh for the non extruded part
+            };
+
+            number_el3d=elements3d.length; //number of 3d nodes for the non extruded part of the mesh
+
+            function fillArray(value, len) {
+                if (len == 0) return [];
+                var a = [value];
+                while (a.length * 2 <= len) a = a.concat(a);
+                if (a.length < len) a = a.concat(a.slice(0, len - a.length));
+                return a;
+            }
+
+            //Keep a trace of lower and upper nodes
+            //lowervertex=NaN*ones(number_nodes3d,1);
+            //uppervertex=NaN*ones(number_nodes3d,1);
+
+            lowervertex = fillArray(null, number_nodes3d);
+            uppervertex = fillArray(null, number_nodes3d);
+
+            //lowervertex(md.mesh.numberofvertices+1:end)=1:(numlayers-1)*md.mesh.numberofvertices;
+            //uppervertex(1:(numlayers-1)*md.mesh.numberofvertices)=md.mesh.numberofvertices+1:number_nodes3d;
+
+            for (var i = md.mesh.numberofvertices+1, k = 1; i < lowervertex.length && k <= (numlayers-1)*md.mesh.numberofvertices; i++, k++) {
+                lowervertex[i] = k;
+            };
+
+            for (var i = 1, k = md.mesh.numberofvertices+1; i <= (numlayers-1)*md.mesh.numberofvertices && k <= number_nodes3d; i++, k++) {
+                uppervertex[i] = k;
+            };
+
+            md.mesh.lowervertex=lowervertex;
+            md.mesh.uppervertex=uppervertex;
+
+            //same for lower and upper elements
+            lowerelements = fillArray(null, number_el3d);
+            upperelements = fillArray(null, number_el3d);
+            //lowerelements(md.mesh.numberofelements+1:end)=1:(numlayers-2)*md.mesh.numberofelements;
+            //upperelements(1:(numlayers-2)*md.mesh.numberofelements)=md.mesh.numberofelements+1:(numlayers-1)*md.mesh.numberofelements;
+
+            for (var i = md.mesh.numberofvertices+1, k = 1; i < lowerelements.length && k <= (numlayers-2)*md.mesh.numberofelements; i++, k++) {
+                lowerelements[i] = k;
+            };
+
+            for (var i = 1, k = md.mesh.numberofelements + 1; i <= (numlayers-2)*md.mesh.numberofelements && k <= (numlayers-1)*md.mesh.numberofelements; i++, k++) {
+                upperelements[i] = k;
+            };
+
+            md.mesh.lowerelements=lowerelements;
+            md.mesh.upperelements=upperelements;
+
+            //Save old mesh 
+            md.mesh.x2d=md.mesh.x;
+            md.mesh.y2d=md.mesh.y;
+            md.mesh.elements2d=md.mesh.elements;
+            md.mesh.numberofelements2d=md.mesh.numberofelements;
+            md.mesh.numberofvertices2d=md.mesh.numberofvertices;
+
+            //Build global 3d mesh 
+            md.mesh.elements=elements3d;
+            md.mesh.x=x3d;
+            md.mesh.y=y3d;
+            md.mesh.z=z3d;
+            md.mesh.numberofelements=number_el3d;
+            md.mesh.numberofvertices=number_nodes3d;
+            md.mesh.numberoflayers=numlayers;
+
+            //Ok, now deal with the other fields from the 2d mesh:
+
+            //bedinfo and surface info
+            md.mesh.vertexonbase=project3d(md,'vector',ones(md.mesh.numberofvertices2d,1),'type','node','layer',1);
+            md.mesh.vertexonsurface=project3d(md,'vector',ones(md.mesh.numberofvertices2d,1),'type','node','layer',md.mesh.numberoflayers);
+            md.mesh.vertexonboundary=project3d(md,'vector',md.mesh.vertexonboundary,'type','node');
+
+            //lat long
+            md.mesh.lat=project3d(md,'vector',md.mesh.lat,'type','node');
+            md.mesh.long=project3d(md,'vector',md.mesh.long,'type','node');
+
+            md.geometry=extrude(md.geometry,md);
                 md.friction  = extrude(md.friction,md);
                 md.inversion = extrude(md.inversion,md);
@@ -373,5 +382,5 @@
 
                     for (var i = 0; i < md.mesh.elementconnectivity.length; ++i) {
-                        if (md.mesh.elementconnectivity[i] === null || typeof md.mesh.elementconectivity[i] === 'undefined') {
+                        if (md.mesh.elementconnectivity[i] === null || typeof md.mesh.elementconnectivity[i] === 'undefined') {
                             md.mesh.elementconnectivity[i] = 0;
                         }
Index: /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/project3d.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/project3d.js	(revision 20793)
+++ /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/project3d.js	(revision 20793)
@@ -0,0 +1,123 @@
+project3d = function() {
+    //PROJECT3D - vertically project a vector from 2d mesh
+    //
+    //   vertically project a vector from 2d mesh (split in noncoll and coll areas) into a 3d mesh.
+    //   This vector can be a node vector of size (md.mesh.numberofvertices2d,N/A) or an 
+    //   element vector of size (md.mesh.numberofelements2d,N/A). 
+    //   arguments: 
+    //      'vector': 2d vector
+    //      'type': 'element' or 'node'. 
+    //   options: 
+    //      'layer' a layer number where vector should keep its values. If not specified, all layers adopt the 
+    //             value of the 2d vector.
+    //      'padding': default to 0 (value adopted by other 3d layers not being projected0
+    //
+    //   Egs:
+    // md.extruded_vector=project3d(md,'vector',vector2d,'type','node','layer',1,'padding',null);
+    // md.extruded_vector=project3d(md,'vector',vector2d,'type','element','padding',0);
+    // md.extruded_vector=project3d(md,'vector',vector2d,'type','node');
+
+    //some regular checks
+    
+
+    function ones(...args) {
+        var array = [];
+        for (var i = 0; i < args[0]; ++i) {
+            array.push(args.length === 1 ? 1 : ones(args.slice(1)));
+        }
+        return array;
+    }
+
+    function remove_first_n(start, arglist) { // Using slice() on arguments is discouraged because it prevents optimizations in engines such as V8
+        var args = [];
+
+        for (var i = start; i < arglist.length; i++) {
+            args.push(arglist[i]);
+        }
+
+        return args;
+    }
+
+    if (arguments.length===1 || arguments.length===0) {
+        //help project3d
+        console.error('project3d bad usage');
+    }
+
+    var md = arguments[0];
+
+    if (md.mesh.elementtype() !== 'Penta') {
+        console.error('input model is not 3d');
+    }
+
+    //retrieve parameters from options.
+    options      = new pairoptions(remove_first_n(1, arguments)); // slice to remove md
+    vector2d     = options.getfieldvalue('vector');     //mandatory
+    type         = options.getfieldvalue('type');       //mandatory
+    layer        = options.getfieldvalue('layer',0);    //optional (do all layers default:)
+    paddingvalue = options.getfieldvalue('padding',0);  //0 by default
+
+    if (vector2d.length === 1) {
+        projected_vector=vector2d;
+    } else if (type.toLowerCase() === 'node') {
+
+        //Initialize 3d vector
+        console.log(vector2d.length + " " + md.mesh.numberofvertices2d);
+        if (vector2d.length===md.mesh.numberofvertices2d) {
+                projected_vector=ones(md.mesh.numberofvertices,  vector2d[0].length).map(function(arr) { return arr.fill(paddingvalue); });
+        } else if (vector2d.length===md.mesh.numberofvertices2d+1) {
+            projected_vector=ones(md.mesh.numberofvertices+1,vector2d[0].length).map(function(arr) { return arr.fill(paddingvalue); });
+            projected_vector[projected_vector.length-1] = projected_vector[projected_vector.length-1].map(function(element, index) { return vector2d[vector2d.length-1][index]; });
+            vector2d.pop(); // Remove last array
+        } else {
+            console.error('vector length not supported')
+        }
+
+            //Fill in
+        if (layer===0) {
+            for (var i = 1; i < md.mesh.numberoflayers; ++i) {
+                var vec_idx = 0;
+
+                for (var j = (i-1)*md.mesh.numberofvertices2d+1, vec_idx = 0; j <= i * md.mesh.numberofvertices2d && vec_idx < vector2d.length; ++j, ++vec_idx) {
+                    projected_vector[j].map(function(element, index) { return vector2d[vec_idx][index]; });
+                }
+
+            }
+        } else {
+            var vec_idx = 0;
+
+            for (var i = (layer-1)*md.mesh.numberofvertices2d+1, vec_idx = 0; i <= layer * md.mesh.numberofvertices2d && vec_idx < vector2d.length; ++i, ++vec_idx) {
+                projected_vector[i] = vector2d[vec_idx];
+            }
+        }
+    } else if (type.toLowerCase() === 'element') {
+            //Initialize 3d vector
+        if (vector2d.length===md.mesh.numberofelements2d) {
+                projected_vector = ones(md.mesh.numberofelements,  vector2d[0].length).map(function(arr) { return arr.fill(paddingvalue); });
+        } else if (vector2d.length===md.mesh.numberofelements2d+1) {
+            projected_vector = ones(md.mesh.numberofelements+1,  vector2d[0].length).map(function(arr) { return arr.fill(paddingvalue); });
+
+            projected_vector[projected_vector.length-1].map(function(element, index) { return vector2d[vector2d.length-1][index]; });
+
+            vector2d.pop();
+        } else {
+            console.error('vector length not supported')
+        }
+
+            //Fill in
+        if (layer===0) {
+            for (var i = 1; i < md.mesh.numberoflayers-1; ++i) {
+                var vec_idx=0;
+                for (var j = (i-1)*md.mesh.numberofelements2d+1, vec_idx = 0; j <= i * md.mesh.numberofelements2d && vec_idx < vector2d.length; ++j, ++vec_idx) {
+                    projected_vector[j].map(function(element, index) { return vector2d[vec_idx][index]; });
+                }
+            }
+        } else {
+            var vec_idx=0;
+            for (var i = (layer-1)*md.mesh.numberofelements2d+1, vec_idx = 0; i <= layer * md.mesh.numberofelements2d && vec_idx < vector2d.length; ++i, ++vec_idx) {
+                projected_vector[i].map(function(element, index) { return vector2d[vec_idx][index]; });
+            }
+        }
+    } else {
+        console.error('project3d error message: unknown projection type');
+    }
+};
