Index: /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/GetAreas.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/GetAreas.js	(revision 21209)
+++ /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/GetAreas.js	(revision 21209)
@@ -0,0 +1,95 @@
+GetAreas = function(index,x,y,varargin) {
+    //GETAREAS - compute areas or volumes of elements
+    //
+    //   compute areas of triangular elements or volumes 
+    //   of pentahedrons
+    //
+    //   Usage:
+    //      areas  =GetAreas(index,x,y);
+    //      volumes=GetAreas(index,x,y,z);
+    //
+    //   Examples:
+    //      areas  =GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y);
+    //      volumes=GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y,md.z);
+
+    //get number of elements and number of nodes
+    function zeros(...args) {
+        var array = [];
+        for (var i = 0; i < args[0]; ++i) {
+            array.push(args.length == 1 ? 0 : zeros(args.slice(1)));
+        }
+        return array;
+    }
+    nels=index.length;
+    nods=x.length;
+    if (arguments.length===4)
+        z=varargin[0];
+
+    //some checks
+    if (arguments.length!==3 && arguments.length!==4) {
+        //help GetAreas
+        console.error('GetAreas error message: bad usage')
+    }
+    if ((y.length!==nods) || (arguments.length===4 && z.length!==nods)) {
+        console.error('GetAreas error message: x,y and z do not have the same length')
+    }
+    if (Math.max.apply(null, index)>nods) {
+        console.error(['GetAreas error message: index should not have values above ' + nods.toString() ]);
+    }
+    if ((arguments.length===3 && index[0].length!==3)) {
+        console.error('GetAreas error message: index should have 3 columns for 2d meshes.')
+    }
+    if ((arguments.length===4 && index[0].length!==6)) {
+        console.error('GetAreas error message: index should have 6 columns for 3d meshes.')
+    }
+
+    //initialization
+    areas=zeros(nels,1);
+
+    var getColumnArray = function(arr, col) {
+       return arr.map(function(value,index) { return value[col]; }); 
+    };
+
+    x1=getColumnArray(index, 0).map(function(value) { return x[value]; }).map(function(v) { return v === undefined ? 0 : v; }); 
+    x2=getColumnArray(index, 1).map(function(value) { return x[value]; }).map(function(v) { return v === undefined ? 0 : v; }); 
+    x3=getColumnArray(index, 2).map(function(value) { return x[value]; }).map(function(v) { return v === undefined ? 0 : v; });
+    y1=getColumnArray(index, 0).map(function(value) { return y[value]; }).map(function(v) { return v === undefined ? 0 : v; }); 
+    y2=getColumnArray(index, 1).map(function(value) { return y[value]; }).map(function(v) { return v === undefined ? 0 : v; }); 
+    y3=getColumnArray(index, 2).map(function(value) { return y[value]; }).map(function(v) { return v === undefined ? 0 : v; });
+
+    //compute the volume of each element
+    if (arguments.length===3) {
+        //compute the surface of the triangle
+        areas=math.multiply(0.5, math.subtract(math.multiply(math.subtract(x2,x1), math.subtract(y3,y1)), math.multiply(math.subtract(y2,y1), math.subtract(x3,x1))));
+    } else {
+        //V=area(triangle)*1/3(z1+z2+z3)
+
+        var tempind1 = [];
+        index.forEach(function(value, idx) {
+            tempind1.push(value[3]);
+            tempind1.push(value[4]);
+            tempind1.push(value[5]);
+        });
+
+        var tempind2 = [];
+        index.forEach(function(value, idx) {
+            tempind2.push(value[0]);
+            tempind2.push(value[1]);
+            tempind2.push(value[2]);
+        });
+        
+        var tempz1 = tempind1.map(function(value, idx) {
+            return z[value][2];
+        });
+
+        var tempz2 = tempind2.map(function(value, idx) {
+            return z[value][2];
+        })
+
+        thickness = math.subtract(math.mean(tempz1), math.mean(tempz2));
+
+        areas=math.multiply(math.multiply(0.5, math.subtract(math.multiply(math.subtract(x2,x1), math.subtract(y3,y1)), math.multiply(math.subtract(y2,y1), math.subtract(x3,x1)))), thickness);
+    }
+
+    return areas;
+};
Index: /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/adjacency.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/adjacency.js	(revision 21209)
+++ /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/adjacency.js	(revision 21209)
@@ -0,0 +1,61 @@
+adjacency = function(md) {
+    //ADJACENCY -  compute adjacency matrix, list of vertices and list of weights.
+    //
+    //  function to create the adjacency matrix from the connectivity table.
+    //
+    //  the required output is:
+    //    md.adj_mat     (double [sparse nv x nv], vertex adjacency matrix)
+    //    md.qmu.vertex_weight        (double [nv], vertex weights)
+
+    var indi=[[md.mesh.elements.map(function(x) { return x[0]; })], [md.mesh.elements.map(function(x) { return x[1]; })], [md.mesh.elements.map(function(x) { return x[2]; })]];
+    var indj=[md.mesh.elements.map(function(x) { return x[1];  }), [md.mesh.elements.map(function(x) { return x[2]; })], [md.mesh.elements.map(function(x) { return x[0]; })]];
+    var values=1;
+
+    md.qmu.adjacency=math.eye(md.mesh.numberofvertices, md.mesh.numberofvertices, 'sparse');
+
+    for (var i = 0; i < indi.length; ++i) {
+        for (var j = 0; j < indj.length; ++j) {
+            //md.qmu.adjacency[indi[i]][indj[j]] = values;
+            md.qmu.adjacency.subset(math.index(i, j), values);
+        }
+    }
+
+    var tempadj = math.subset(md.qmu.adjacency, math.index(0,math.range(0, math.size(md.qmu.adjacency)._data[1])))
+
+    //var tempadj = md.qmu.adjacency[0].map(function(col, i) { return md.qmu.adjacency.map(function(row) { return row[i]; }); });
+    //md.qmu.adjacency=[md.qmu.adjacency[0].map(function(x, idx) { return md.qmu.adjacency.map(function(row, jdx) { return md.qmu.adjacency[idx][jdx] | tempadj[i][j]; })})];
+    //md.qmu.adjacency=[tempadj.map(function(x, idx) { return md.qmu.adjacency.map(function(row, jdx) { return md.qmu.adjacency.subset(math.index(idx, jdx), md.qmu.adjacency.get([idx, jdx]) | tempadj.get([idx,jdx]));})})];
+
+    for (var i = 0; i < math.size(md.qmu.adjacency)._data[0]; ++i) {
+        for (var j = 0; j < math.size(md.qmu.adjacency)._data[1]; ++j) {
+            md.qmu.adjacency.subset(math.index(i,j), md.qmu.adjacency.subset(math.index(i,j)) | md.qmu.adjacency.subset(math.index(j,i)));
+        }
+    }
+    //[tempadj.forEach(function(x, idx) { md.qmu.adjacency.forEach(function(y, jdx) { console.log(idx, jdx); return md.qmu.adjacency.subset(math.index(idx, jdx), md.qmu.adjacency.subset(math.index(idx, jdx)) );})})];
+
+    //now, build vwgt:
+    areas=GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y);
+
+    //get node connectivity
+    md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices);
+
+    connectivity=md.mesh.vertexconnectivity.map(function(row) { return row.slice(0,row.length-1); });
+    pos=[];
+    for (var i = 0; i < connectivity.length; ++i) {
+        if ((connectivity[i] !== 0)) {
+                pos.push(i);
+        }
+    }
+
+    console.log(areas);
+
+    var tempconn = pos.map(function(val, idx) { return connectivity[val]; });
+
+    pos.forEach(function(val, idx) {
+        connectivity[val] = areas[connectivity[val]]/3;
+    });
+
+    md.qmu.vertex_weight=math.sum(connectivity);
+
+    return md;
+};
Index: /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/partitioner.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/partitioner.js	(revision 21209)
+++ /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/partitioner.js	(revision 21209)
@@ -0,0 +1,116 @@
+partitioner = function(md,...args) {
+function zeros(...args) {
+	var array = [];
+	for (var i = 0; i < args[0]; ++i) {
+		array.push(args.length == 1 ? 0 : zeros(args.slice(1)));
+	}
+	return array;
+}
+//PARTITIONER - partition mesh 
+//
+//   List of options to partitioner: 
+//
+//   package: 'chaco', 'metis' or 'scotch'
+//   npart: number of partitions.
+//   weighting: 'on' or 'off': default off
+//   section:  1 by defaults(1=bisection, 2=quadrisection, 3=octasection)
+//   recomputeadjacency:  'on' by default (set to 'off' to compute existing one)
+//   Output: md.qmu.partition recover the partition vector
+//   
+//   Usage:
+//      md=partitioner(md,'package','chaco','npart',100,'weighting','on');
+//
+
+//get options: 
+options= new pairoptions(args.slice());
+
+//set defaults
+options.addfielddefault('package','chaco');
+options.addfielddefault('npart',10);
+options.addfielddefault('weighting','on');
+options.addfielddefault('section',1);
+options.addfielddefault('recomputeadjacency','on');
+
+//get package: 
+package=options.getfieldvalue('package');
+npart=options.getfieldvalue('npart');
+recomputeadjacency=options.getfieldvalue('recomputeadjacency');
+
+if(md.mesh.dimension()===3) {
+	//partitioning essentially happens in 2D. So partition in 2D, then 
+    //extrude the partition vector vertically. 
+	md3d=md; //save  for later
+	md.mesh.elements=md.mesh.elements2d;
+	md.mesh.x=md.mesh.x2d;
+	md.mesh.y=md.mesh.y2d;
+	md.mesh.numberofvertices=md.mesh.numberofvertices2d;
+	md.mesh.numberofelements=md.mesh.numberofelements2d;
+	md.qmu.vertex_weight=[];
+	md.mesh.vertexconnectivity=[];
+}
+
+//adjacency matrix if needed:
+if (recomputeadjacency.toLowerCase() === 'on') {
+	md=adjacency(md);
+} else {
+	disp('skipping adjacency matrix computation as requested in the options');
+}
+
+if (package.toLowerCase() === 'chaco') {
+
+	//  default method (from chaco.m)
+	method=[[1], [1], [0], [0], [1], [1], [50], [0], [.001], [7654321]];
+	method[0]=3;    //  global method (3=inertial (geometric))
+	method[2]=0;    //  vertex weights (0=off, 1=on)
+
+	//specify bisection
+	method[5]=options.getfieldvalue('section');//  ndims (1=bisection, 2=quadrisection, 3=octasection)
+
+    //are we using weights? 
+    if (options.getfieldvalue('weighting').toLowerCase() === 'on') {
+            weights=Math.floor(md.qmu.vertex_weight/math.min(md.qmu.vertex_weight));
+            method[2]=1;
+    } else { 
+        weights=[];
+    }
+
+	//  partition into nparts
+    if (md.mesh.classname() === 'mesh2d') {
+        //TODO convert to column
+		part=Chaco(md.qmu.adjacency,weights,[],md.mesh.x, md.mesh.y,zeros(md.mesh.numberofvertices,1),method,npart,[])+1; //index partitions from 1 up. like metis.
+	} else {
+        //TODO convert to column
+		part=Chaco(md.qmu.adjacency,weights,[],md.mesh.x, md.mesh.y,md.mesh.z,method,npart,[])+1; //index partitions from 1 up. like metis.
+	}
+} else if (package.toLowerCase() === 'scotch') {
+	//are we using weights? 
+    if (options.getfieldvalue('weighting').toLowerCase() === 'on') {
+		weights=floor(md.qmu.vertex_weight/min(md.qmu.vertex_weight));
+	}
+	maptab=Scotch(md.qmu.adjacency,[],weights,[],'cmplt',[npart]);
+
+    part=maptab.filter(function(x, idx) { return idx });//index partitions from 1 up. like metis.
+} else if (package.toLowerCase() === 'linear') {
+
+    part = part.slice(0, md.mesh.numberofvertices);
+} else if (package.toLowerCase() === 'metis') {
+	[element_partitioning,part]=MeshPartition(md.mesh,md.qmu.numberofpartitions);
+} else {
+	console.error(['partitioner error message: could not find ' + package + ' partitioner']);
+	//help partitioner
+}
+
+//extrude if we are in 3d
+if (md.mesh.dimension() === 3) {
+	md3d.qmu.vertex_weight=md.qmu.vertex_weight;
+	md3d.qmu.adjacency=md.qmu.adjacency;
+	md=md3d;
+
+    //TODO convert to column vec
+	part=project3d(md,'vector',part,'type','node');
+}
+
+md.qmu.partition=part;
+
+return md;
+};
Index: /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/supportedcontrols.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/supportedcontrols.js	(revision 21209)
+++ /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/supportedcontrols.js	(revision 21209)
@@ -0,0 +1,16 @@
+function supportedcontrols() {
+    var list = [
+        'BalancethicknessThickeningRate',
+        'FrictionCoefficient',
+        'FrictionAs',
+        'MaterialsRheologyBbar',
+        'DamageDbar',
+        'Vx',
+        'Vy',
+        'Thickness',
+        'BalancethicknessOmega',
+        'BalancethicknessApparentMassbalance',
+        'MaterialsRheologyB'];
+
+    return list;
+}
Index: /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/supportedcostfunctions.js
===================================================================
--- /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/supportedcostfunctions.js	(revision 21209)
+++ /issm/trunk-jpl/jenkins/javascript/karma/lib/bin/supportedcostfunctions.js	(revision 21209)
@@ -0,0 +1,10 @@
+function supportedcostfunctions() {
+    function range(start, count) {
+      return Array.apply(0, Array(count))
+        .map(function (element, index) { 
+          return index + start;  
+      });
+    }
+    var list = range(101,5).concat(range(201,1).concat(range(501,7)).concat(range(510,1)).concat(range(601,4)));
+    return list;
+}
