Changeset 26300


Ignore:
Timestamp:
06/07/21 11:12:48 (4 years ago)
Author:
dlcheng
Message:

CHG (JS): Large update of JS classes in for solid earth/sea level solver.

Location:
issm/trunk-jpl/src/m
Files:
1 added
34 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk-jpl/src/m/array/arrayoperations.js

    r23006 r26300  
    5454        for (var a = 0; a < arguments.length; a++) {
    5555        arg = arguments[a];
    56         if (arg instanceof Array) {
     56        if (arg instanceof Array || arg instanceof Float64Array) {
    5757            size = arg.length;
    5858            array = arg;
     
    6464        for (var a = 0; a < arguments.length; a++) {
    6565        arg = arguments[a];
    66         if (arg instanceof Array && arg.length != size) {
     66        if ((arg instanceof Array || arg instanceof Float64Array) && arg.length != size) {
    6767            throw Error("ArrayAdd error message: arrays provided as arguments are not of the same length!");
    68         } else if (!(arg instanceof Array) && typeof arg != 'number') {
     68        } else if (!(arg instanceof Array || arg instanceof Float64Array) && typeof arg != 'number') {
    6969            throw Error("ArrayAdd error message: arguments provided are not of the type Array or Number!");
    7070        }
     
    7575                if (a != initial) {
    7676                        arg = arguments[a];
    77                         if (arg instanceof Array) {
     77                        if (arg instanceof Array || arg instanceof Float64Array) {
    7878                                for(var i = 0; i < result.length; i++){
    7979                                        result[i] += arg[i];
    8080                                }
    81                         } else if (typeof arg != 'number') {
     81                        } else if (typeof arg === 'number') {
    8282                                for(var i = 0; i < result.length; i++){
    8383                                        result[i] += arg;
     
    9494        for (var a = 0; a < arguments.length; a++) {
    9595        arg = arguments[a];
    96         if (arg instanceof Array) {
     96        if (arg instanceof Array || arg instanceof Float64Array) {
    9797            size = arg.length;
    9898            array = arg;
     
    104104        for (var a = 0; a < arguments.length; a++) {
    105105        arg = arguments[a];
    106         if (arg instanceof Array && arg.length != size) {
     106        if ((arg instanceof Array || arg instanceof Float64Array) && arg.length != size) {
    107107            throw Error("ArrayAdd error message: arrays provided as arguments are not of the same length!");
    108         } else if (!(arg instanceof Array) && typeof arg != 'number') {
     108        } else if (!(arg instanceof Array || arg instanceof Float64Array) && typeof arg != 'number') {
    109109            throw Error("ArrayAdd error message: arguments provided are not of the type Array or Number!");
    110110        }
     
    115115                if (a !== initial) {
    116116                        arg = arguments[a];
    117                         if (arg instanceof Array) {
     117                        if (arg instanceof Array || arg instanceof Float64Array) {
    118118                                for(var i = 0; i < result.length; i++){
    119119                                        result[i] -= arg[i];
    120120                                }
    121                         } else if (typeof arg != 'number') {
     121                        } else if (typeof arg === 'number') {
    122122                                for(var i = 0; i < result.length; i++){
    123123                                        result[i] -= arg;
     124                                }
     125                        }
     126        }
     127        }
     128        return result;
     129} //}}}
     130function ArraySubtract2D(){ //{{{
     131    //Takes in any number of scalars or arrays, and calculates the subtraction. Scalars are treated as similar length arrays of the scalar.
     132    //Determine reference array and size
     133    var size, array, arg, initial;
     134        for (var a = 0; a < arguments.length; a++) {
     135        arg = arguments[a];
     136        if (arg instanceof Array || arg instanceof Float64Array) {
     137            size = arg.length;
     138            array = arg;
     139                        initial = a;
     140            break;
     141        }
     142    }
     143        //check internal consistency of arrays provided!:
     144        for (var a = 0; a < arguments.length; a++) {
     145        arg = arguments[a];
     146        if ((arg instanceof Array || arg instanceof Float64Array) && arg.length != size) {
     147            throw Error("ArrayAdd error message: arrays provided as arguments are not of the same length!");
     148        } else if (!(arg instanceof Array || arg instanceof Float64Array) && typeof arg != 'number') {
     149            throw Error("ArrayAdd error message: arguments provided are not of the type Array or Number!");
     150        }
     151        }
     152        //calculate the result, using the first argument to initialize:
     153        var result = [];
     154        for (var a = 0; a < arguments.length; a++) {
     155                if (a !== initial) {
     156                        arg = arguments[a];
     157                        if (arg instanceof Array || arg instanceof Float64Array) {
     158                                for(var i = 0; i < array.length; i++){
     159                                        result[i] = [];
     160                                        for(var j = 0; j < array[i].length; j++){
     161                                            result[i][j] = array[i][j] - arg[i][j];
     162                                        }
     163                                }
     164                        } else if (typeof arg === 'number') {
     165                                for(var i = 0; i < array.length; i++){
     166                                        result[i] = [];
     167                                        for(var j = 0; j < array[i].length; j++){
     168                                            result[i][j] = array[i][j] - arg;
     169                                        }
    124170                                }
    125171                        }
     
    134180        for (var a = 0; a < arguments.length; a++) {
    135181        arg = arguments[a];
    136         if (arg instanceof Array) {
     182        if (arg instanceof Array || arg instanceof Float64Array) {
    137183            size = arg.length;
    138184            array = arg;
     
    144190        for (var a = 0; a < arguments.length; a++) {
    145191        arg = arguments[a];
    146         if (arg instanceof Array && arg.length != size) {
     192        if ((arg instanceof Array || arg instanceof Float64Array) && arg.length != size) {
    147193            throw Error("ArrayAdd error message: arrays provided as arguments are not of the same length!");
    148         } else if (!(arg instanceof Array) && typeof arg != 'number') {
     194        } else if (!(arg instanceof Array || arg instanceof Float64Array) && typeof arg != 'number') {
    149195            throw Error("ArrayAdd error message: arguments provided are not of the type Array or Number!");
    150196        }
     
    155201                if (a !== initial) {
    156202                        arg = arguments[a];
    157                         if (arg instanceof Array) {
     203                        if (arg instanceof Array || arg instanceof Float64Array) {
    158204                                for(var i = 0; i < result.length; i++){
    159205                                        result[i] *= arg[i];
    160206                                }
    161                         } else if (typeof arg != 'number') {
     207                        } else if (typeof arg === 'number') {
    162208                                for(var i = 0; i < result.length; i++){
    163209                                        result[i] *= arg;
     
    174220        for (var a = 0; a < arguments.length; a++) {
    175221        arg = arguments[a];
    176         if (arg instanceof Array) {
     222        if (arg instanceof Array || arg instanceof Float64Array) {
    177223            size = arg.length;
    178224            array = arg;
     
    184230        for (var a = 0; a < arguments.length; a++) {
    185231        arg = arguments[a];
    186         if (arg instanceof Array && arg.length != size) {
     232        if ((arg instanceof Array || arg instanceof Float64Array) && arg.length != size) {
    187233            throw Error("ArrayAdd error message: arrays provided as arguments are not of the same length!");
    188         } else if (!(arg instanceof Array) && typeof arg != 'number') {
     234        } else if (!(arg instanceof Array || arg instanceof Float64Array) && typeof arg != 'number') {
    189235            throw Error("ArrayAdd error message: arguments provided are not of the type Array or Number!");
    190236        }
     
    195241                if (a !== initial) {
    196242                        arg = arguments[a];
    197                         if (arg instanceof Array) {
     243                        if (arg instanceof Array || arg instanceof Float64Array) {
    198244                                for(var i = 0; i < result.length; i++){
    199245                                        result[i] /= arg[i];
    200246                                }
    201                         } else if (typeof arg != 'number') {
     247                        } else if (typeof arg === 'number') {
    202248                                for(var i = 0; i < result.length; i++){
    203249                                        result[i] /= arg;
     
    282328
    283329} //}}}
    284 function ArrayOr(){ //{{{
    285     if (arguments.length<2)throw Error("ArrayOr error message: sum has to be for at least two arrays!");
    286 
    287         //check internal consistency of arrays provided!:
    288         var firstarray=arguments[0];
    289         var firstsize=firstarray.length;
    290        
    291         for(var a=1;a<arguments.length;a++){
    292                 var array=arguments[a];
    293                 if(array.length!=firstsize)throw Error("ArrayOr error message: arrays provided as arguments are not of the same length!");
    294         }
    295 
    296         //do the or:
    297         var or=NewArrayFill(firstsize,0);
    298         for(var a=0;a<arguments.length;a++){
    299                 var array=arguments[a];
    300                 for(var i=0;i<array.length;i++){
    301                         or[i] = or[i] | array[i];
    302                 }
    303         }
    304         return or;
    305 
    306 } //}}}
    307330function ArrayConcat(a, b) { //{{{
    308331        // Make sure that both typed arrays are of the same type
     
    322345} //}}}
    323346function ArrayCol(matrix, cols) { //{{{
    324     var column = [];
    325     if (cols instanceof Array) {
     347    var columns = [];
     348    if (cols instanceof Array || cols instanceof Float64Array) {
    326349        for (var i = 0; i < matrix.length; i++){
    327             var row = [];
    328             for (var j = cols[0]; j <= cols[1]; j++){
    329                 row.push(matrix[i][j]);
     350            var col = [];
     351            for (var j = 0; j < cols.length; j++){
     352                col.push(matrix[i][cols[j]]);
    330353            }
    331             column.push(row);
     354            columns.push(col);
    332355        }
    333356
    334357    } else if (typeof cols == 'number') {
    335358        for (var i = 0; i < matrix.length; i++){
    336             column.push(matrix[i][cols]);
     359            columns.push(matrix[i][cols]);
    337360        }
    338361    } else {
    339362        throw new Error("ArrayCol error: cols must be a single integer or an array with 2 integers!");
    340363    }
    341    return column;
     364   return columns;
    342365} //}}}
    343366function ListToMatrix(list, elementsPerSubArray) { //{{{
     
    445468    return 0;
    446469} //}}}
    447 function ArrayUnique(arr) { //{{{
    448 
    449         return arr.reverse().filter(function (e, i, arr) {
    450                     return arr.indexOf(e, i+1) === -1;
    451         }).reverse();
    452 } //}}}
    453 function ArraySort(array) { //{{{
    454 
    455         return array.sort(function(a, b) {
    456                 return a - b;
    457         });
    458 
     470function ArrayUnique(arr,rows) { //{{{
     471        if (arguments.length == 2){
     472                if (rows == 'rows') {
     473                        //See Matlab unique function and https://stackoverflow.com/a/20339709/1905613
     474                        let equals = (a, b) => JSON.stringify(a) === JSON.stringify(b);
     475                        let uniques = [];
     476                        let indexA = [];
     477                        let indexC = [];
     478                        let itemsFound = {};;
     479                        for(let i = 0, l = arr.length; i < l; i++) {
     480                                let stringified = JSON.stringify(arr[i]);
     481                                if (typeof(itemsFound[stringified]) != 'undefined') {
     482                                        indexC.push(itemsFound[stringified]);
     483                                        continue;
     484                                }
     485                                uniques.push(arr[i]);
     486                                indexA.push(i);
     487                                itemsFound[stringified] = uniques.length-1;
     488                                indexC.push(itemsFound[stringified]);
     489                        }
     490                        //assert arr == uniques[indexC,:];
     491                        for (let i = 0; i < indexC.length; i++) {
     492                                if (!equals(arr[i], uniques[indexC[i]])) {
     493                                        throw new Error('bad implementation'); 
     494                                }
     495                        }
     496                        //assert uniques == arr[indexA, :];
     497                        for (let i = 0; i < indexA.length; i++) {
     498                                if (!equals(uniques[i], arr[indexA[i]])) {
     499                                        throw new Error('bad implementation'); 
     500                                }
     501                        }
     502                        let [uniquesSorted, indexInToOut, indexOutToIn] = ArraySortWithIndices(uniques);
     503                        //indexMapping is the index of the edge in the old array
     504                        indexCSorted = []; //indexC.length == arr.length
     505                        //assert uniquesSorted[i,:] = uniques[indexInToOut[i],:]
     506                        for (let i = 0; i < indexInToOut.length; i++) {
     507                                if (!equals(uniquesSorted[i], uniques[indexInToOut[i]])) {
     508                                        console.log(i, uniquesSorted[indexInToOut[i]], uniques[i]);
     509                                        throw new Error('bad implementation'); 
     510                                }
     511                        }
     512                        //assert uniques[i,:] = uniquesSorted[indexOutToIn[i],:]
     513                        for (let i = 0; i < indexOutToIn.length; i++) {
     514                                if (!equals(uniques[i], uniquesSorted[indexOutToIn[i]])) {
     515                                        console.log(i, uniques[indexOutToIn[i]], uniquesSorted[i]);
     516                                        throw new Error('bad implementation'); 
     517                                }
     518                        }
     519                        //GOAL: assert arr[i,:] == uniquesSorted[indexCSorted[i], :]
     520                        //GIVEN: assert arr[i,:] == uniques[indexC[i],:];
     521                        //GIVEN: assert uniquesSorted[i,:] = uniques[indexInToOut[i],:]
     522                        //GIVEN: assert uniques[i,:] = uniquesSorted[indexOutToIn[i],:]
     523                        //assert uniques[indexC[i],:] == uniquesSorted[indexOutToIn[indexC[i]],:]
     524                        //assert uniquesSorted[indexCSorted[i],:]; == uniquesSorted[indexOutToIn[indexC[i]],:];
     525                        for (let i = 0; i < arr.length; i++) {
     526                                indexCSorted[i] = indexOutToIn[indexC[i]];
     527                        }
     528                        for (let i = 0; i < indexC.length; i++) {
     529                                if (!equals(arr[i], uniquesSorted[indexCSorted[i]])) {
     530                                        console.log(i, arr[i], uniquesSorted[indexCSorted[i]]);
     531                                        throw new Error('bad implementation'); 
     532                                }
     533                        }
     534
     535                        indexASorted = []; //indexA.length == uniques.length
     536                        //GOAL: uniquesSorted[i, :] == arr[indexASorted[i], :]
     537                        //GIVEN: assert arr[i,:] == uniques[indexC[i],:];
     538                        //GIVEN: assert arr[indexA[i],:] == uniques[i,:];
     539                        //GIVEN: assert uniques[indexInToOut[i],:] == uniquesSorted[i,:]
     540                        //GIVEN: assert uniques[i,:] = uniquesSorted[indexOutToIn[i],:]
     541                        //assert uniquesSorted[i,:] == uniques[indexInToOut[i],:]
     542                        //assert uniques[indexInToOut[i],:] == arr[indexA[indexInToOut[i]],:];
     543                        //assert indexA[indexInToOut] == indexASorted
     544                        //indexASorted == indexA[indexMapping[i]]
     545                        for (let i = 0; i < indexA.length; i++) {
     546                                indexASorted[i] = indexA[indexInToOut[i]];
     547                        }
     548                        //assert uniques == arr[indexA, :];
     549                        for (let i = 0; i < indexASorted.length; i++) {
     550                                if (!equals(uniquesSorted[i], arr[indexASorted[i]])) {
     551                                        throw new Error('bad implementation'); 
     552                                }
     553                        }
     554                        console.log('Good uniques');
     555                        return [uniquesSorted, indexASorted, indexCSorted];
     556                } else {
     557                        throw new Error('ArrayUnique non "rows" not supported');       
     558                }
     559        } else {
     560                return arr.reverse().filter(function (e, i, arr) {
     561                                return arr.indexOf(e, i+1) === -1;
     562                }).reverse();
     563        }
     564} //}}}
     565function ArraySortWithIndices(toSort, sortingFunction) { //{{{
     566        //returns the sorted and index such that toSort[index[i]] == sorted[i]
     567        let toSortCopy = [];
     568        for (var i = 0; i < toSort.length; i++) {
     569            toSortCopy[i] = [toSort[i], i];
     570        }
     571        if (typeof(sortingFunction) == 'undefined') {
     572                let numeric2DFunction = function(a, b) {
     573                        if (a[0][0] == b[0][0]) {
     574                return a[0][1] - b[0][1];
     575                        } else {
     576                            return a[0][0] - b[0][0];
     577                        }
     578                };
     579                sortingFunction = numeric2DFunction;
     580        }
     581        toSortCopy.sort(sortingFunction);
     582        let indicesInToOut = [];
     583        let indicesOutToIn = [];
     584        let sorted = [];
     585        for (var j = 0; j < toSortCopy.length; j++) {
     586            indicesInToOut[j] = toSortCopy[j][1];
     587            indicesOutToIn[toSortCopy[j][1]] = j;
     588            sorted[j] = toSortCopy[j][0];
     589        }
     590        return [sorted, indicesInToOut, indicesOutToIn];
     591} //}}}
     592function ArraySort(array,dim) { //{{{
     593        let numericFunction = function(a, b) {
     594            return a - b;
     595        };
     596        let numeric2DFunction = function(a, b) {
     597            return a[0] - b[0];
     598        };
     599        if (arguments.length == 2){
     600                if (dim == 1) {
     601                        array.sort(numeric2DFunction);
     602                } else if (dim == 2) {
     603                        for (let i = 0; i < array.length; i++) {
     604                                array[i].sort(numericFunction);
     605                        }
     606                } else {
     607                        throw new Error('ArraySort dim > 2 not yet supported')
     608                }
     609                return array;
     610        } else {
     611                return array.sort(numericFunction);
     612        }
    459613} //}}}
    460614function ArrayRange(lower, upper) { //{{{
     
    515669} //}}}
    516670function ArrayAnd(array1,array2) { //{{{
    517 
    518         var array=array1;
    519         for (var i=0;i<array1.length;i++)array[i]=array1[i] & array2[i];
     671        var array = new Array(array1.length);
     672        for (var i=0;i<array1.length;i++) {
     673                array[i]=array1[i] & array2[i];
     674        }
     675        return array;
     676} //}}}
     677function ArrayOr(array1,array2) { //{{{
     678        var array = new Array(array1.length);
     679        for (var i=0;i<array1.length;i++) {
     680                array[i]=array1[i] | array2[i];
     681        }
     682        return array;
     683} //}}}
     684function ArrayEqual(array1,array2) { //{{{
     685        var array = new Array(array1.length);
     686
     687        if (typeof(array1[0]) == 'number') {
     688                if (typeof(array2) == 'number') {
     689                        for(var i=0;i<array1.length;i++){
     690                                array[i] = array1[i] == array2;
     691                        }
     692                } else {
     693                        for(var i=0;i<array1.length;i++){
     694                                array[i] = array1[i] == array2[i];
     695                        }
     696                }
     697        } else { //provide support for 2d arrays
     698                if (typeof(array2) == 'number') {
     699                        for(var i=0;i<array1.length;i++){
     700                                array[i] = new Array(array1[i].length);
     701                                for(var j=0;j<array1[i].length;j++){
     702                                        array[i][j] = array1[i][j] == array2;
     703                                }
     704                        }
     705                } else {
     706                        for(var i=0;i<array1.length;i++){
     707                                array[i] = new Array(array1[i].length);
     708                                for(var j=0;j<array1[i].length;j++){
     709                                        array[i][j] = array1[i][j] == array2[i][j];
     710                                }
     711                        }
     712                }
     713        }
     714        return array;
     715} //}}}
     716function ArrayLessThan(array1,array2) { //{{{
     717        var array = new Array(array1.length);
     718
     719        if (typeof(array2) == 'number') {
     720                for(var i=0;i<array1.length;i++){
     721                        array[i] = array1[i] < array2;
     722                }
     723        } else {
     724                for(var i=0;i<array1.length;i++){
     725                        array[i] = array1[i] < array2[i];
     726                }
     727        }
     728        return array;
     729} //}}}
     730function ArrayGreaterThan(array1,array2) { //{{{
     731        var array = new Array(array1.length);
     732        if (typeof(array2) == 'number') {
     733                for(var i=0;i<array1.length;i++){
     734                        array[i] = array1[i] > array2;
     735                }
     736        } else {
     737                for(var i=0;i<array1.length;i++){
     738                        array[i] = array1[i] > array2[i];
     739                }
     740        }
     741        return array;
     742} //}}}
     743function ArrayLessEqualThan(array1,array2) { //{{{
     744        var array = new Array(array1.length);
     745        if (typeof(array2) == 'number') {
     746                for(var i=0;i<array1.length;i++){
     747                        array[i] = array1[i] <= array2;
     748                }
     749        } else {
     750                for(var i=0;i<array1.length;i++){
     751                        array[i] = array1[i] <= array2[i];
     752                }
     753        }
     754        return array;
     755} //}}}
     756function ArrayGreaterEqualThan(array1,array2) { //{{{
     757        var array = new Array(array1.length);
     758        if (typeof(array2) == 'number') {
     759                for(var i=0;i<array1.length;i++){
     760                        array[i] = array1[i] >= array2;
     761                }
     762        } else {
     763                for(var i=0;i<array1.length;i++){
     764                        array[i] = array1[i] >= array2[i];
     765                }
     766        }
    520767        return array;
    521768} //}}}
     
    551798        return arr;
    552799} //}}}
    553 function NewArrayFillIncrement(size,start,increment) { //{{{
     800function NewArrayFillIncrement(start,size,increment) { //{{{
    554801        var array=new Array(size);
    555802
     
    559806
    560807        return array;
     808} //}}}
     809function ones(size) { //{{{
     810        return NewArrayFill(size,1);
     811} //}}}
     812function zeros(size) { //{{{
     813        return NewArrayFill(size,0);
    561814} //}}}
    562815function ArrayFind(array,value) { //{{{
     
    611864        }
    612865        return indices;
     866} //}}}
     867function ArrayIndex(array1,array2,value) { //{{{
     868        //Change behavior between get (if no value is provided) to set (if value to set is provided)
     869        if (arguments.length == 2){
     870                let data = []
     871                if (typeof(array2[0]) == 'number') {
     872                        for (let i=0;i<array2.length;i++){
     873                                data.push(array1[array2[i]]);
     874                        }
     875                } else {
     876                        //2d index array
     877                        for (let i=0;i<array2.length;i++){
     878                                let data2 = [];
     879                                for (let j=0;j<array2[i].length;j++){
     880                                    data2.push(array1[array2[i][j]]);
     881                                }
     882                                data.push(data2);
     883                        }
     884                }
     885                return data;
     886        } else {
     887                for (var i=0;i<array2.length;i++){
     888                        array1[array2[i]]=value;
     889                }
     890                return array1;
     891        }
    613892} //}}}
    614893function Create2DArray(rows,cols) { //{{{
     
    644923
    645924        // Handle Array
    646         if (obj instanceof Array) {
     925        if (obj instanceof Array || arg instanceof Float64Array) {
    647926                copy = [];
    648927                for (var i = 0, len = obj.length; i < len; i++) {
  • issm/trunk-jpl/src/m/classes/SMBforcing.js

    r21065 r26300  
    1212                console.log(sprintf('   surface forcings parameters:'));
    1313                fielddisplay(this,'mass_balance','surface mass balance [m/yr ice eq]');
     14                fielddisplay(this,'steps_per_step', 'number of smb steps per time step');
    1415                fielddisplay(this,'requested_outputs','additional outputs requested');
     16                fielddisplay(this,'averaging','averaging methods from short to long steps');
     17                console.log(sprintf('%51s  0: Arithmetic (default)',' '));
     18                console.log(sprintf('%51s  1: Geometric',' '));
     19                console.log(sprintf('%51s  2: Harmonic',' '));
    1520        } // }}}
    1621        this.defaultoutputs = function(){ // {{{
     
    3338    } // }}}
    3439    this.checkconsistency = function(md,solution,analyses) { //{{{
    35 
     40                if (solution=='TransientSolution' && md.transient.issmb == 0) return;
    3641        if(ArrayAnyEqual(ArrayIsMember('MasstransportAnalysis',analyses),1)){
    3742            checkfield(md,'fieldname','smb.mass_balance','timeseries',1,'NaN',1,'Inf',1);
     
    4045            checkfield(md,'fieldname','smb.mass_balance','size',[md.mesh.numberofvertices,1],'NaN',1,'Inf',1);
    4146        }
    42         checkfield(md,'fieldname','smb.requested_outputs','stringrow',1);
    43 
     47                checkfield(md,'fieldname','smb.steps_per_step','>=',1,'numel',[1]);
     48                checkfield(md,'fieldname','smb.requested_outputs','stringrow',1);
     49                checkfield(md,'fieldname','smb.averaging','numel',[1],'values',[0,1,2]);
    4450    } // }}}
    4551    this.marshall=function(md,prefix,fid) { //{{{
     
    4955        WriteData(fid,prefix,'name','md.smb.model','data',1,'format','Integer');
    5056        WriteData(fid,prefix,'object',this,'class','smb','fieldname','mass_balance','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
     57                WriteData(fid,prefix,'object',this,'fieldname','steps_per_step','format','Integer');
     58                WriteData(fid,prefix,'object',this,'fieldname','averaging','format','Integer');
    5159
    5260        //process requested outputs
     
    6674        //properties
    6775    // {{{
    68         this.mass_balance = NaN;
    69         this.requested_outputs      = [];
     76        this.mass_balance          = NaN;
     77        this.requested_outputs = [];
     78        this.steps_per_step    = 1;
     79        this.averaging         = 0;
    7080        this.setdefaultparameters();
    7181    // }}}
  • issm/trunk-jpl/src/m/classes/amr.js

    r22435 r26300  
    77        //methods
    88        this.setdefaultparameters = function(){// {{{
     9
     10                //hmin and hmax
    911                this.hmin                                                               = 100.;
    1012                this.hmax                                                               = 100.e3;
     13
     14                //fields
    1115                this.fieldname                                                  = "Vel";
    1216                this.err                                                                = 3.;
     17
     18                //keep metric?
    1319                this.keepmetric                                                 = 1;
     20
     21                //control of element lengths
    1422                this.gradation                                                  = 1.5;
     23
     24                //other criterias
    1525                this.groundingline_resolution                   = 500.;
    1626                this.groundingline_distance                             = 0;
     
    2535                this.deviatoricerror_groupthreshold             = 0;   
    2636                this.deviatoricerror_maximum                    = 0;   
     37
     38                //is restart? This calls femmodel->ReMesh() before first time step.
     39                this.restart                                                    = 0;
    2740        }// }}}
    2841        this.disp= function(){// {{{
     
    4558                fielddisplay(this,'deviatoricerror_groupthreshold','maximum group threshold deviatoricstress error permitted');
    4659                fielddisplay(this,'deviatoricerror_maximum','maximum deviatoricstress error permitted');
     60                fielddisplay(this,'deviatoricerror_maximum','maximum deviatoricstress error permitted');
     61                fielddisplay(this,'restart','indicates if ReMesh() will call before first time step');
    4762        }// }}}
    4863        this.classname= function(){// {{{
     
    6782                checkfield(md,'fieldname','amr.deviatoricerror_groupthreshold','numel',[1],'>=',0,'<=',1,'NaN',1);
    6883                checkfield(md,'fieldname','amr.deviatoricerror_maximum','numel',[1],'>=',0,'NaN',1,'Inf',1);
     84                checkfield(md,'fieldname','amr.restart','numel',[1],'>=',0,'<=',1,'NaN',1);
    6985        } // }}}
    7086        this.marshall=function(md,prefix,fid) { //{{{
     
    88104                WriteData(fid,prefix,'object',this,'fieldname','deviatoricerror_groupthreshold','format','Double');
    89105                WriteData(fid,prefix,'object',this,'fieldname','deviatoricerror_maximum','format','Double');
     106                WriteData(fid,prefix,'object',this,'fieldname','restart','format','Integer');
    90107        }//}}}
    91108        this.fix=function() { //{{{
     
    111128        this.deviatoricerror_groupthreshold             = 0.;
    112129        this.deviatoricerror_maximum                    = 0.;
     130        this.restart                                                    = 0.;
    113131
    114132        this.setdefaultparameters();
  • issm/trunk-jpl/src/m/classes/balancethickness.js

    r21065 r26300  
    4040                        WriteData(fid,prefix,'object',this,'fieldname','thickening_rate','format','DoubleMat','mattype',1,'scale',1/yts);
    4141                        WriteData(fid,prefix,'object',this,'fieldname','stabilization','format','Integer');
     42
     43                        WriteData(fid,prefix,'object',this,'fieldname','slopex','format','DoubleMat','mattype',1);
     44                        WriteData(fid,prefix,'object',this,'fieldname','slopey','format','DoubleMat','mattype',1);
    4245                        WriteData(fid,prefix,'object',this,'fieldname','omega','format','DoubleMat','mattype',1);
    4346
     
    5356        this.thickening_rate   = NaN;
    5457        this.stabilization     = 0;
     58
    5559        this.omega             = NaN;
     60        this.slopex            = NaN;
     61        this.slopey            = NaN;
    5662        this.setdefaultparameters();
    5763        //}}}
  • issm/trunk-jpl/src/m/classes/calving.js

    r24305 r26300  
    3535                this.fix=function() { //{{{
    3636                        this.calvingrate=NullFix(this.calvingrate,NaN);
     37                        this.meltingrate=NullFix(this.meltingrate,NaN);
    3738                }//}}}
    3839        //properties
  • issm/trunk-jpl/src/m/classes/constants.js

    r20896 r26300  
    1919                        //the reference temperature for enthalpy model (cf Aschwanden)
    2020                        this.referencetemperature=223.15;
     21
     22                        //gravitational constant:
     23                        this.gravitational_constant = 6.67259e-11;
    2124                }// }}}
    2225                this.disp = function () { //{{{
     
    2730                        fielddisplay(this,'yts','number of seconds in a year [s/yr]');
    2831                        fielddisplay(this,'referencetemperature','reference temperature used in the enthalpy model [K]');
     32                        fielddisplay(this,'gravitational_constant','Newtonian constant of gravitation [m^3/kg/s^2]');
    2933
    3034                } //}}}
     
    3943                        checkfield(md,'fieldname','constants.yts','>',0,'size',[1,1]);
    4044                        checkfield(md,'fieldname','constants.referencetemperature','size',[1,1]);
     45                        checkfield(md,'fieldname','constants.gravitational_constant','size',[1,1]);
    4146
    4247                } // }}}
     
    4550                        WriteData(fid,prefix,'object',this,'fieldname','yts','format','Double');
    4651                        WriteData(fid,prefix,'object',this,'fieldname','referencetemperature','format','Double');
     52                        WriteData(fid,prefix,'object',this,'fieldname','gravitational_constant','format','Double');
    4753                }//}}}
    4854                this.fix=function() { //{{{
     
    5056        //properties
    5157        // {{{
    52                 this.g                    = 0.;
    53                 this.omega                = 0.;
    54                 this.yts                  = 0.;
    55                 this.referencetemperature = 0.;
     58                this.g                                            = 0.;
     59                this.omega                                        = 0.;
     60                this.yts                                          = 0.;
     61                this.referencetemperature         = 0.;
     62                this.gravitational_constant   = 0.;
    5663                this.setdefaultparameters();
    5764                //}}}
  • issm/trunk-jpl/src/m/classes/flowequation.js

    r25626 r26300  
    2222                fielddisplay(this,'isSSA','is the Shelfy-Stream Approximation (SSA) used ?');
    2323                fielddisplay(this,'isL1L2','is the L1L2 approximation used ?');
    24                 fielddisplay(this,'isMLHO','is the MLHO approximation used ?');
     24                fielddisplay(this,'isMLHO','is the Mono-Layer Higher-Order approximation used?');
    2525                fielddisplay(this,'isHO','is the Higher-Order (HO) approximation used ?');
    2626                fielddisplay(this,'isFS','are the Full-FS (FS) equations used ?');
     27                fielddisplay(this,'isNitscheBC','is weakly imposed condition used?');
     28                fielddisplay(this,'FSNitscheGamma','Gamma value for the Nitsche term (default: 1e6)');
    2729                fielddisplay(this,'fe_SSA',"Finite Element for SSA  'P1', 'P1bubble' 'P1bubblecondensed' 'P2'");
    2830                fielddisplay(this,'fe_HO', "Finite Element for HO   'P1' 'P1bubble' 'P1bubblecondensed' 'P1xP2' 'P2xP1' 'P2'");
     
    6062                        checkfield(md,'fieldname','flowequation.isHO','numel',[1],'values',[0, 1]);
    6163                        checkfield(md,'fieldname','flowequation.isFS','numel',[1],'values',[0, 1]);
     64                        checkfield(md,'fieldname','flowequation.isNitscheBC','numel',[1],'values',[0, 1]);
     65                        checkfield(md,'fieldname','flowequation.FSNitscheGamma','numel',[1], '>=', 0);
    6266                        checkfield(md,'fieldname','flowequation.fe_SSA','values',['P1','P1bubble','P1bubblecondensed','P2','P2bubble']);
    6367                        checkfield(md,'fieldname','flowequation.fe_HO' ,'values',['P1','P1bubble','P1bubblecondensed','P1xP2','P2xP1','P2','P2bubble','P1xP3','P2xP4']);
     
    8084                        }
    8185                        else if (md.mesh.domaintype() =='2Dvertical'){
    82                                 checkfield(md,'fieldname','flowequation.vertex_equation','size',[md.mesh.numberofvertices, 1],'values',[2,5,6]);
    83                                 checkfield(md,'fieldname','flowequation.element_equation','size',[md.mesh.numberofelements, 1],'values',[2,5,6]);
     86                                checkfield(md,'fieldname','flowequation.vertex_equation','size',[md.mesh.numberofvertices, 1],'values',[2,4,5]);
     87                                checkfield(md,'fieldname','flowequation.element_equation','size',[md.mesh.numberofelements, 1],'values',[2,4,5]);
    8488                        }
    8589                        else if (md.mesh.domaintype() =='3D'){
    86                                 checkfield(md,'fieldname','flowequation.vertex_equation','size',[md.mesh.numberofvertices, 1],'values',[0,1,2,3,4,5,6,7,8,9]);
    87                                 checkfield(md,'fieldname','flowequation.element_equation','size',[md.mesh.numberofelements, 1],'values',[0,1,2,3,4,5,6,7,8,9]);
     90                                checkfield(md,'fieldname','flowequation.vertex_equation','size',[md.mesh.numberofvertices, 1],'values',[0,1,2,3,4,5,6,7,8]);
     91                                checkfield(md,'fieldname','flowequation.element_equation','size',[md.mesh.numberofelements, 1],'values',[0,1,2,3,4,5,6,7,8]);
    8892                        }
    8993                        else throw Error('Case not supported yet');
    9094                       
    9195                        if (!(this.isSIA | this.isSSA | this.isL1L2 | this.isMLHO | this.isHO | this.isFS)){
    92                                 md = checkmessage(md,['no element types set for this model']);
     96                                checkmessage(md,['no element types set for this model']);
    9397                        }
    9498                        if(ArrayAnyEqual(ArrayIsMember('StressbalanceSIAAnalysis', analyses),1)){
    9599                                if (ArrayAnyEqual(this.element_equation,1)){
    96                                         if(this.vertex_equation & ArrayAnyBelowStrict(md.mask.ocean_levelset)){
     100                                        if(this.vertex_equation & ArrayAnyBelowStrict(md.mask.groundedice_levelset)){
    97101                                                console.log(sprintf("\n !!! Warning: SIA's model is not consistent on ice shelves !!!\n"));
    98102                                        }
     
    107111                        WriteData(fid,prefix,'object',this,'fieldname','isHO','format','Boolean');
    108112                        WriteData(fid,prefix,'object',this,'fieldname','isFS','format','Boolean');
     113                        WriteData(fid,prefix,'object',this,'fieldname','isNitscheBC','format','Boolean');
     114                        WriteData(fid,prefix,'object',this,'fieldname','FSNitscheGamma','format','Double');
    109115                        WriteData(fid,prefix,'object',this,'fieldname','fe_SSA','data',this.fe_SSA,'format','String');
    110116                        WriteData(fid,prefix,'object',this,'fieldname','fe_HO','data',this.fe_HO,'format','String');
     
    135141        this.isHO                           = 0;
    136142        this.isFS                           = 0;
     143        this.isNitscheBC                    = 0;
     144        this.FSNitscheGamma                 = 0;
    137145        this.fe_SSA                         = '';
    138146        this.fe_HO                          = '';
  • issm/trunk-jpl/src/m/classes/fourierlove.js

    r22383 r26300  
    1111        this.setdefaultparameters = function() { // {{{
    1212                //we setup an elastic love number computation by default.
    13                 this.nfreq=1;
    14                 this.frequencies=[0]; //Hz
    15                 this.sh_nmax=256; // .35 degree, 40 km at the equator.
    16                 this.sh_nmin=1;
    17                 this.g0=10; // m/s^2;
    18                 this.r0=6378*1e3; //m;
    19                 this.mu0=10**11; // Pa
    20                 this.allow_layer_deletion=1;
    21                 this.love_kernels=0;
    22                 this.forcing_type = 11;
     13                        this.nfreq=1;
     14                        this.frequencies=[0]; //Hz
     15                        this.sh_nmax=256; // .35 degree, 40 km at the equator.
     16                        this.sh_nmin=1;
     17                        // work on matlab script for computing g0 for given Earth's structure.
     18                        this.g0=9.81; // m/s^2;
     19                        this.r0=6371*1e3; //m;
     20                        this.mu0=10^11; // Pa
     21                        this.Gravitational_Constant=6.67259e-11; // m^3 kg^-1 s^-2
     22                        this.allow_layer_deletion=1;
     23                        this.underflow_tol=1e-16; //threshold of deep to surface love number ratio to trigger the deletion of layer
     24                        this.integration_steps_per_layer=100;
     25                        this.istemporal=0;
     26                        this.n_temporal_iterations=8;
     27                        this.time=[0]; //s
     28                        this.love_kernels=0;
     29                        this.forcing_type = 11; // surface loading
     30                        this.inner_core_boundary=1;
     31                        this.core_mantle_boundary=2;
     32                        this.complex_computation=0;
    2333        } // }}}
    2434        this.disp = function() { // {{{
     
    2838                fielddisplay(this,'sh_nmin','minimum spherical harmonic degree (default 1)');
    2939                fielddisplay(this,'g0','adimensioning constant for gravity (default 10) [m/s^2]');
    30                 fielddisplay(this,'r0','adimensioning constant for radius (default 6378*10^3) [m]');
     40                fielddisplay(this,'r0','adimensioning constant for radius (default 6371*10^3) [m]');
    3141                fielddisplay(this,'mu0','adimensioning constant for stress (default 10^11) [Pa]');
     42                fielddisplay(this,'Gravitational_Constant','Newtonian constant of gravitation (default 6.67259e-11 [m^3 kg^-1 s^-2])');
    3243                fielddisplay(this,'allow_layer_deletion','allow for migration of the integration boundary with increasing spherical harmonics degree (default 1)');
     44                fielddisplay(this,'underflow_tol','threshold of deep to surface love number ratio to trigger the deletion of layers (default 2.2204460492503131E-016)');
     45                fielddisplay(this,'integration_steps_per_layer','number of radial steps to propagate the yi system from the bottom to the top of each layer (default 100)');
     46                fielddisplay(this,'istemporal','1 for time-dependent love numbers, 0 for frequency-dependent or elastic love numbers (default 0)', 'If 1: use fourierlove function build_frequencies_from_time to meet consistency');
     47                fielddisplay(this,'n_temporal_iterations','max number of iterations in the inverse Laplace transform. Also the number of spectral samples per time step requested (default 8)');
     48                fielddisplay(this,'time','time vector for deformation if istemporal (default 0) [s]');
    3349                fielddisplay(this,'love_kernels','compute love numbers at depth? (default 0)');
    34                 fielddisplay(this,'forcing_type',['integer indicating the nature and depth of the forcing for the Love number calculation (default 11) :','1:  Inner core boundary -- Volumic Potential','2:  Inner core boundary -- Pressure','3:  Inner core boundary -- Loading','4:  Inner core boundary -- Tangential traction','5:  Core mantle boundary -- Volumic Potential','6:  Core mantle boundary -- Pressure','7:  Core mantle boundary -- Loading','8:  Core mantle boundary -- Tangential traction','9:  Surface -- Volumic Potential','10: Surface -- Pressure','11: Surface -- Loading','12: Surface -- Tangential traction ']);
     50                fielddisplay(this,'forcing_type','integer indicating the nature and depth of the forcing for the Love number calculation (default 11) :','1:  Inner core boundary -- Volumic Potential','2:  Inner core boundary -- Pressure','3:  Inner core boundary -- Loading','4:  Inner core boundary -- Tangential traction','5:  Core mantle boundary -- Volumic Potential','6:  Core mantle boundary -- Pressure','7:  Core mantle boundary -- Loading','8:  Core mantle boundary -- Tangential traction','9:  Surface -- Volumic Potential','10: Surface -- Pressure','11: Surface -- Loading','12: Surface -- Tangential traction ');
     51                fielddisplay(this,'inner_core_boundary','interface index in materials.radius locating forcing. Only used for forcing_type 1--4 (default 1)');
     52                fielddisplay(this,'core_mantle_boundary','interface index in materials.radius locating forcing. Only used for forcing_type 5--8 (default 2)');
    3553
    3654        } // }}}
    3755        this.checkconsistency = function(md,solution,analyses) { // {{{
    3856
    39                 md = checkfield(md,'fieldname','love.nfreq','NaN',1,'Inf',1,'numel',1,'>',0);
    40                 md = checkfield(md,'fieldname','love.frequencies','NaN',1,'Inf',1,'numel',md.love.nfreq);
    41                 md = checkfield(md,'fieldname','love.sh_nmax','NaN',1,'Inf',1,'numel',1,'>',0);
    42                 md = checkfield(md,'fieldname','love.sh_nmin','NaN',1,'Inf',1,'numel',1,'>',0);
    43                 md = checkfield(md,'fieldname','love.g0','NaN',1,'Inf',1,'numel',1,'>',0);
    44                 md = checkfield(md,'fieldname','love.r0','NaN',1,'Inf',1,'numel',1,'>',0);
    45                 md = checkfield(md,'fieldname','love.mu0','NaN',1,'Inf',1,'numel',1,'>',0);
    46                 md = checkfield(md,'fieldname','love.allow_layer_deletion','values',[0, 1]);
    47                 md = checkfield(md,'fieldname','love.love_kernels','values',[0, 1]);
    48                 md = checkfield(md,'fieldname','love.forcing_type','NaN',1,'Inf',1,'numel',1,'>',0, '<=', 12);
    49                 if (md.love.sh_nmin<=1 && md.love.forcing_type==9) {
     57                if (ArrayAnyEqual(ArrayIsMember('LoveAnalysis',analyses),1)) return;
     58
     59                checkfield(md,'fieldname','love.nfreq','NaN',1,'Inf',1,'numel',1,'>',0);
     60                checkfield(md,'fieldname','love.frequencies','NaN',1,'Inf',1,'numel',md.love.nfreq);
     61                checkfield(md,'fieldname','love.sh_nmax','NaN',1,'Inf',1,'numel',1,'>',0);
     62                checkfield(md,'fieldname','love.sh_nmin','NaN',1,'Inf',1,'numel',1,'>',0);
     63                checkfield(md,'fieldname','love.g0','NaN',1,'Inf',1,'numel',1,'>',0);
     64                checkfield(md,'fieldname','love.r0','NaN',1,'Inf',1,'numel',1,'>',0);
     65                checkfield(md,'fieldname','love.mu0','NaN',1,'Inf',1,'numel',1,'>',0);
     66                checkfield(md,'fieldname','love.Gravitational_Constant','NaN',1,'Inf',1,'numel',1,'>',0);
     67                checkfield(md,'fieldname','love.allow_layer_deletion','values',[0, 1]);
     68                checkfield(md,'fieldname','love.underflow_tol','NaN',1,'Inf',1,'numel',1,'>',0);
     69                checkfield(md,'fieldname','love.integration_steps_per_layer','NaN',1,'Inf',1,'numel',1,'>',0);
     70                checkfield(md,'fieldname','love.love_kernels','values',[0, 1]);
     71                checkfield(md,'fieldname','love.forcing_type','NaN',1,'Inf',1,'numel',1,'>',0, '<=', 12);
     72                checkfield(md,'fieldname','love.complex_computation','NaN',1,'Inf',1,'numel',1,'values',[0, 1]);
     73
     74                checkfield(md,'fieldname','love.istemporal','values',[0, 1]);
     75
     76                if (md.love.istemporal==1){
     77                        checkfield(md,'fieldname','love.n_temporal_iterations','NaN',1,'Inf',1,'numel',1,'>',0);
     78                        checkfield(md,'fieldname','love.time','NaN',1,'Inf',1,'numel',md.love.nfreq/2/md.love.n_temporal_iterations);
     79                }
     80                if (md.love.sh_nmin<=1 && md.love.forcing_type==9 || md.love.forcing_type==5 || md.love.forcing_type==1) {
    5081                        throw 'Degree 1 not supported for Volumetric Potential forcing. Use sh_min>=2 for this kind of calculation.';
    5182                }
     83
     84                //need 'litho' material:
     85                console.log('md.fourierlove check consistency only paritally implemented for litho material');
     86                /*
     87                if ~isa(md.materials,'materials') | ~sum(strcmpi(md.materials.nature,'litho'))
     88                        error('Need a ''litho'' material to run a Fourier Love number analysis');
     89                end
     90
     91                mat=find(strcmpi(md.materials.nature,'litho'));
     92                if (md.love.forcing_type<=4) {
     93                        checkfield(md,'fieldname','love.inner_core_boundary','NaN',1,'Inf',1,'numel',1,'>',0, '<=', md.materials(mat).numlayers);
     94                } else if (md.love.forcing_type<=8) {
     95                        checkfield(md,'fieldname','love.core_mantle_boundary','NaN',1,'Inf',1,'numel',1,'>',0, '<=', md.materials(mat).numlayers);
     96                } */
    5297        } // }}}
    5398        this.marshall = function(md,prefix,fid) { // {{{
     
    60105                WriteData(fid,prefix,'object',this,'fieldname','r0','format','Double');
    61106                WriteData(fid,prefix,'object',this,'fieldname','mu0','format','Double');
     107                WriteData(fid,prefix,'object',this,'fieldname','Gravitational_Constant','format','Double');
    62108                WriteData(fid,prefix,'object',this,'fieldname','allow_layer_deletion','format','Boolean');
     109                WriteData(fid,prefix,'object',this,'fieldname','underflow_tol','format','Double');
     110                WriteData(fid,prefix,'object',this,'fieldname','integration_steps_per_layer','format','Integer');
     111                WriteData(fid,prefix,'object',this,'fieldname','istemporal','format','Boolean');
     112                WriteData(fid,prefix,'object',this,'fieldname','n_temporal_iterations','format','Integer');
     113                WriteData(fid,prefix,'object',this,'fieldname','complex_computation','format','Boolean');
     114                //note: no need to marshall the time vector, we have frequencies
    63115                WriteData(fid,prefix,'object',this,'fieldname','love_kernels','format','Boolean');
    64116                WriteData(fid,prefix,'object',this,'fieldname','forcing_type','format','Integer');
     117                WriteData(fid,prefix,'object',this,'fieldname','inner_core_boundary','format','Integer');
     118                WriteData(fid,prefix,'object',this,'fieldname','core_mantle_boundary','format','Integer');
    65119
    66120        } // }}}
    67121        //properties
    68122        // {{{
    69                
    70         this.nfreq                =  NaN;
    71         this.frequencies          =  NaN;
    72         this.sh_nmax              =  NaN;
    73         this.sh_nmin              =  NaN;
    74         this.g0                   =  NaN;
    75         this.r0                   =  NaN;
    76         this.mu0                  =  NaN;
    77         this.allow_layer_deletion =  NaN;
    78         this.love_kernels =  NaN;
    79         this.forcing_type         =  NaN;
     123        this.nfreq                              = NaN;
     124        this.frequencies                        = NaN;
     125        this.sh_nmax                            = NaN;
     126        this.sh_nmin                            = NaN;
     127        this.g0                                 = NaN;
     128        this.r0                                 = NaN;
     129        this.mu0                                = NaN;
     130        this.Gravitational_Constant     = 0;
     131        this.allow_layer_deletion               = NaN;
     132        this.underflow_tol              = 0;
     133        this.integration_steps_per_layer= 0;
     134        this.istemporal                                 = 0;
     135        this.n_temporal_iterations              = 0;
     136        this.time                                   = 0;
     137        this.love_kernels                               = NaN;
     138        this.forcing_type                       = NaN;
     139        this.inner_core_boundary            = 0;
     140        this.core_mantle_boundary           = 0;
     141        this.complex_computation        = 0;
    80142       
    81143        //set defaults
  • issm/trunk-jpl/src/m/classes/friction.js

    r21945 r26300  
    1414                fielddisplay(this,'p','p exponent');
    1515                fielddisplay(this,'q','q exponent');
     16                fielddisplay(this,'effective_pressure','Effective Pressure for the forcing if not coupled [Pa]');
    1617                fielddisplay(this,'coupling','Coupling flag: 0 for default, 1 for forcing(provide md.friction.effective_pressure)  and 2 for coupled(not implemented yet)');
     18                fielddisplay(this,'effective_pressure_limit','Neff do not allow to fall below a certain limit: effective_pressure_limit*rho_ice*g*thickness (default 0)');
    1719        } // }}}
    1820        this.extrude = function(md) {//{{{
     
    4244                                return;
    4345                        }
    44                         md = checkfield(md,'fieldname','friction.coefficient','timeseries',1,'NaN',1,'Inf',1);
    45                         md = checkfield(md,'fieldname','friction.q','NaN',1,'Inf',1,'size',[md.mesh.numberofelements ,1]);
    46                         md = checkfield(md,'fieldname','friction.p','NaN',1,'Inf',1,'size',[md.mesh.numberofelements ,1]);
    47                         md = checkfield(md,'fieldname','friction.coupling','numel',[1],'values',[0, 1, 2]);
     46                        checkfield(md,'fieldname','friction.coefficient','timeseries',1,'NaN',1,'Inf',1);
     47                        checkfield(md,'fieldname','friction.q','NaN',1,'Inf',1,'size',[md.mesh.numberofelements ,1]);
     48                        checkfield(md,'fieldname','friction.p','NaN',1,'Inf',1,'size',[md.mesh.numberofelements ,1]);
     49                        checkfield(md,'fieldname','friction.coupling','numel',[1],'values',[0, 1, 2]);
     50                        checkfield(md,'fieldname','friction.effective_pressure_limit','numel',[1],'>=',0);
    4851                        switch (this.coupling) {
    4952                                case 0:
    5053                                case 1:
    51                                         md = checkfield(md,'fieldname','friction.effective_pressure','NaN',1,'Inf',1,'timeseries',1);
     54                                        checkfield(md,'fieldname','friction.effective_pressure','NaN',1,'Inf',1,'timeseries',1);
    5255                                        break;
    5356                                case 2:
     
    6366
    6467                        WriteData(fid,prefix,'name','md.friction.law','data',1,'format','Integer');
    65                         WriteData(fid,prefix,'object',this,'fieldname','coefficient','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
    66                         //WriteData(fid,prefix,'object',this,'fieldname','coefficient','format','DoubleMat','mattype',1);
     68                        let mattype,tsl;
     69                        if ((size(this.coefficient,1)==md.mesh.numberofvertices | size(this.coefficient,1)==md.mesh.numberofvertices+1)) {
     70                                mattype=1;
     71                                tsl = md.mesh.numberofvertices;
     72                        } else {
     73                                mattype=2;
     74                                tsl = md.mesh.numberofelements;
     75                        }
     76                        WriteData(fid,prefix,'object',this,'fieldname','coefficient','format','DoubleMat','mattype',mattype,'timeserieslength',tsl+1,'yts',md.constants.yts);
    6777                        WriteData(fid,prefix,'object',this,'fieldname','p','format','DoubleMat','mattype',2);
    6878                        WriteData(fid,prefix,'object',this,'fieldname','q','format','DoubleMat','mattype',2);
    6979                        WriteData(fid,prefix,'class','friction','object',this,'fieldname','coupling','format','Integer');
     80                        WriteData(fid,prefix,'object',this,'class','friction','fieldname','effective_pressure_limit','format','Double');
    7081                        switch (this.coupling) {
    7182                                case 0:
     
    7990                                        console.error('not supported yet');             
    8091                        }
    81                        
    82 
    8392                }//}}}
    8493                this.fix=function() { //{{{
     
    8695        //properties
    8796        //{{{
    88         this.coefficient = NaN;
    89         this.p           = NaN;
    90         this.q           = NaN;
    91         this.coupling    = 0;
    92         this.effective_pressure = NaN;
     97        this.coefficient                          = NaN;
     98        this.p                                            = NaN;
     99        this.q                                            = NaN;
     100        this.coupling                             = 0;
     101        this.effective_pressure           = NaN;
     102        this.effective_pressure_limit = 0;
    93103        this.setdefaultparameters();
    94104        //}}}
  • issm/trunk-jpl/src/m/classes/geometry.js

    r23721 r26300  
    3030
    3131                        if ((solution=='TransientSolution' & md.trans.isgia) | (solution=='GiaSolution')){
    32                                 checkfield(md,'fieldname','geometry.thickness','timeseries',1,'NaN',1,'Inf',1);
     32                                checkfield(md,'fieldname','geometry.thickness','timeseries',1,'NaN',1,'Inf',1,'>=',0);
    3333                        }
    3434                        else{
     
    3838                                for(var i=0;i<md.mesh.numberofvertices;i++){
    3939                                        if (Math.abs(md.geometry.thickness[i]-md.geometry.surface[i]+md.geometry.base[i])>Math.pow(10,9)){
    40                                                 md = checkmessage(md,'equality thickness=surface-base violated');
     40                                                checkmessage(md,'equality thickness=surface-base violated');
    4141                                                break;
    4242                                        }
     
    4848                } // }}}
    4949                this.marshall=function(md,prefix,fid) { //{{{
     50                        let length_thickness=size(this.thickness,1);
     51                        if (length_thickness==md.mesh.numberofvertices || length_thickness==md.mesh.numberofvertices+1) {
     52                                WriteData(fid,prefix,'object',this,'fieldname','thickness','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
     53                        } else if (length_thickness==md.mesh.numberofelements || length_thickness==md.mesh.numberofelements+1) {
     54                                WriteData(fid,prefix,'object',this,'fieldname','thickness','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofelements+1,'yts',md.constants.yts);
     55                        } else {
     56                                error('geometry thickness time series should be a vertex or element time series');
     57                        }
    5058                        WriteData(fid,prefix,'object',this,'fieldname','surface','format','DoubleMat','mattype',1);
    51                         WriteData(fid,prefix,'object',this,'fieldname','thickness','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
    5259                        WriteData(fid,prefix,'object',this,'fieldname','base','format','DoubleMat','mattype',1);
    5360                        WriteData(fid,prefix,'object',this,'fieldname','bed','format','DoubleMat','mattype',1);
  • issm/trunk-jpl/src/m/classes/groundingline.js

    r24866 r26300  
    88        this.setdefaultparameters = function(){// {{{
    99                //Type of migration
    10                 this.migration='AggressiveMigration';
    11                 this.friction_interpolation='SubelementFriction1';
    12                 this.melt_interpolation='NoMeltOnPartiallyFloating';
     10                this.migration                          = 'SubelementMigration';
     11                this.friction_interpolation     = 'SubelementFriction1';
     12                this.melt_interpolation         = 'NoMeltOnPartiallyFloating';
    1313
    1414        }// }}}
     
    2929                        checkfield(md,'fieldname','groundingline.melt_interpolation','values',['NoMeltOnPartiallyFloating', 'SubelementMelt1', 'SubelementMelt2', 'FullMeltOnPartiallyFloating']);
    3030
    31                         if(this.migration !='None' & md.trans.isgroundingline==1 & solution == 'TransientSolution'){
     31                        if (this.migration !='None'){
    3232                                if (isNaN(md.geometry.bed)){
    3333                                        md.checkmessage('requesting grounding line migration, but bathymetry is absent!');
    3434                                }
    3535                                for (var i=0;i<md.mesh.numberofvertices;i++){
    36                                         if(md.mask.ocean_levelset[i]>0){
     36                                        if(md.mask.groundedice_levelset[i]>0){
    3737                                                md.checkmessage('base not equal to bed on grounded ice!');
    3838                                                break;
    3939                                        }
    4040                                        if(md.geometry.bed[i] - md.geometry.base[i] > Math.pow(10,-9)){
    41                                                 md = checkmessage(md,'bed superior to base on floating ice!');
     41                                                checkmessage(md,'bed superior to base on floating ice!');
    4242                                                break;
    4343                                        }
  • issm/trunk-jpl/src/m/classes/initialization.js

    r21065 r26300  
    1717                fielddisplay(this,'pressure','pressure field [Pa]');
    1818                fielddisplay(this,'temperature','temperature [K]');
     19                fielddisplay(this,'enthalpy','enthalpy [J]');
    1920                fielddisplay(this,'waterfraction','fraction of water in the ice');
    2021                fielddisplay(this,'sediment_head','sediment water head of subglacial system [m]');
    2122                fielddisplay(this,'epl_head','epl water head of subglacial system [m]');
    2223                fielddisplay(this,'epl_thickness','epl layer thickness [m]');
    23                 fielddisplay(this,'watercolumn','thickness of subglacial water [m]');
     24                fielddisplay(this,'watercolumn','subglacial water sheet thickness (for Shreve and GlaDS) [m]');
     25                fielddisplay(this,'hydraulic_potential','Hydraulic potential (for GlaDS) [Pa]');
     26                fielddisplay(this,'channelarea','subglacial water channel area (for GlaDS) [m2]');
     27                fielddisplay(this,'sample','Realization of a Gaussian random field');
     28                fielddisplay(this,'bottompressure','Bottom pressures');
     29                fielddisplay(this,'dsl','Dynamic sea level.');
     30                fielddisplay(this,'str','Steric sea level.');
    2431
    2532        }// }}}
     
    5158                                checkfield(md,'fieldname','initialization.vy','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
    5259                        }
     60                        if(ArrayAnyEqual(ArrayIsMember('OceantransportAnalysis',analyses),1)){
     61                                if (strcmp(solution,'TransientSolution') && md.transient.isslc && md.transient.isoceantransport) {
     62                                        checkfield(md,'fieldname','initialization.bottompressure','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
     63                                        checkfield(md,'fieldname','initialization.dsl','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
     64                                        checkfield(md,'fieldname','initialization.str','NaN',1,'Inf',1,'size',[1, 1]);
     65                                }
     66                        }
    5367                        if(ArrayAnyEqual(ArrayIsMember('BalancethicknessSolution',analyses),1) & (solution=='BalancethicknessSolution')){
    5468                                checkfield(md,'fieldname','initialization.vx','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
     
    6579                                }
    6680                        }
    67                         if(ArrayAnyEqual(ArrayIsMember('ThermalAnalysis',analyses),1)){
     81                        if ((ArrayAnyEqual(ArrayIsMember('ThermalAnalysis',analyses),1)) && !strcmp(solution,'TransientSolution') && md.transient.isthermal == 0){
    6882                                checkfield(md,'fieldname','initialization.vx','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
    6983                                checkfield(md,'fieldname','initialization.vy','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
    70                                 if (md.mesh.dimension() == 3){
    71                                         checkfield(md,'fieldname','initialization.vz','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices ,1]);
    72                                 }
    73                                 checkfield(md,'fieldname','initialization.pressure','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices ,1]);
    74                                 checkfield(md,'fieldname','initialization.temperature','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices ,1]);
    75                         }
    76                         if( ArrayAnyEqual(ArrayIsMember('EnthalpyAnalysis',analyses),1) & md.thermal.isenthalpy){
    77                                 checkfield(md,'fieldname','initialization.waterfraction','>=',0,'size',[md.mesh.numberofvertices, 1]);
    78                                 checkfield(md,'fieldname','initialization.watercolumn'  ,'>=',0,'size',[md.mesh.numberofvertices, 1]);
    79                         }
    80                         if(ArrayAnyEqual(ArrayIsMember('HydrologyShreveAnalysis',analyses),1)){
     84                                if (md.mesh.dimension()==3) {
     85                                        checkfield(md,'fieldname','initialization.vz','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
     86                                }
     87                                checkfield(md,'fieldname','initialization.pressure','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
     88                                checkfield(md,'fieldname','initialization.temperature','NaN',1,'Inf',1,'size','universal');
     89                        }
     90                        if (ArrayAnyEqual(ArrayIsMember('EnthalpyAnalysis',analyses),1) && md.thermal.isenthalpy){
     91                                checkfield(md,'fieldname','initialization.waterfraction','>=',0,'size','universal');
     92                                checkfield(md,'fieldname','initialization.watercolumn'  ,'>=',0,'size','universal');
     93                        }
     94                        if (ArrayAnyEqual(ArrayIsMember('HydrologyShreveAnalysis',analyses),1)){
    8195                                if (md.hydrology.type() == 'hydrologyshreve'){
    8296                                        checkfield(md,'fieldname','initialization.watercolumn','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices ,1]);
    8397                                }
    8498                        }
    85                         if(ArrayAnyEqual(ArrayIsMember('HydrologyDCInefficientAnalysis',analyses),1)){
     99                        if (ArrayAnyEqual(ArrayIsMember('HydrologyTwsAnalysis',analyses),1)){
     100                                if (md.hydrology.type() == 'hydrologytws'){
     101                                        checkfield(md,'fieldname','initialization.watercolumn','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices ,1]);
     102                                }
     103                        }
     104                        if (ArrayAnyEqual(ArrayIsMember('SealevelchangeAnalysis',analyses),1)){
     105                                if (strcmp(solution,'TransientSolution') && md.transient.isslc) {
     106                                        checkfield(md,'fieldname','initialization.sealevel','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
     107                                }
     108                        }
     109                        if (ArrayAnyEqual(ArrayIsMember('HydrologyGlaDSAnalysis',analyses),1)){
     110                                if (md.hydrology.type() == 'hydrologyglads'){
     111                                        checkfield(md,'fieldname','initialization.watercolumn','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
     112                                        checkfield(md,'fieldname','initialization.hydraulic_potential','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
     113                                        checkfield(md,'fieldname','initialization.channelarea','NaN',1,'Inf',1,'>=',0,'size',[md.mesh.numberofedges, 1]);
     114                                }
     115                        }
     116                        if (ArrayAnyEqual(ArrayIsMember('HydrologyDCInefficientAnalysis',analyses),1)){
    86117                                if (md.hydrology.type() == 'hydrologydc'){
    87118                                        checkfield(md,'fieldname','initialization.sediment_head','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
    88119                                }
    89120                        }
    90                         if(ArrayAnyEqual(ArrayIsMember('HydrologyDCEfficientAnalysis',analyses),1)){
     121                        if (ArrayAnyEqual(ArrayIsMember('HydrologyDCEfficientAnalysis',analyses),1)){
    91122                                if (md.hydrology.type() == 'hydrologydc'){
    92123                                        if (md.hydrology.isefficientlayer==1){
     
    96127                                }
    97128                        }
     129                        if (ArrayAnyEqual(ArrayIsMember('SamplingAnalysis',analyses),1) && !strcmp(solution,'TransientSolution')&& md.transient.issampling == 0){
     130                                if (!isNaN(md.initialization.sample)) {
     131                                        checkfield(md,'fieldname','initialization.sample','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]);
     132                                }
     133                        }
    98134                } //}}}
    99135                this.marshall=function(md,prefix,fid) { //{{{
     
    105141                        WriteData(fid,prefix,'object',this,'fieldname','vz','format','DoubleMat','mattype',1,'scale',1./yts);
    106142                        WriteData(fid,prefix,'object',this,'fieldname','pressure','format','DoubleMat','mattype',1);
     143                        WriteData(fid,prefix,'object',this,'fieldname','sealevel','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
     144                        WriteData(fid,prefix,'object',this,'fieldname','bottompressure','format','DoubleMat','mattype',1);
     145                        WriteData(fid,prefix,'object',this,'fieldname','str','format','DoubleMat','mattype',1);
     146                        WriteData(fid,prefix,'object',this,'fieldname','dsl','format','DoubleMat','mattype',1);
    107147                        WriteData(fid,prefix,'object',this,'fieldname','temperature','format','DoubleMat','mattype',1);
    108148                        WriteData(fid,prefix,'object',this,'fieldname','waterfraction','format','DoubleMat','mattype',1);
     
    111151                        WriteData(fid,prefix,'object',this,'fieldname','epl_thickness','format','DoubleMat','mattype',1);
    112152                        WriteData(fid,prefix,'object',this,'fieldname','watercolumn','format','DoubleMat','mattype',1);
     153                        WriteData(fid,prefix,'object',this,'fieldname','channelarea','format','DoubleMat','mattype',1);
     154                        WriteData(fid,prefix,'object',this,'fieldname','hydraulic_potential','format','DoubleMat','mattype',1);
     155                        WriteData(fid,prefix,'object',this,'fieldname','sample','format','DoubleMat','mattype',1);
    113156
    114157                        if (md.thermal.isenthalpy){
    115                                 tpmp=NewArrayFill(md.mesh.numberofvertices,0);
    116                                 for (var i=0;i<md.mesh.numberofvertices;i++) tpmp[i]= md.materials.meltingpoint - md.materials.beta*md.initialization.pressure[i];
    117                                 enthalpy=NewArrayFill(md.mesh.numberofvertices,0);
    118                                 for (var i=0;i<md.mesh.numberofvertices;i++)enthalpy[i] = md.materials.heatcapacity*(md.initialization.temperature[i]-md.constants.referencetemperature);
    119                                
    120                                 for (var i=0;i<md.mesh.numberofvertices;i++)if(md.initialization.temperature[i]>=tpmp[i]){
    121                                         enthalpy[i] = md.materials.heatcapacity*(tpmp[i] - md.constants.referencetemperature) + md.materials.latentheat*md.initialization.waterfraction[i];
     158                                let enthalpy;
     159                                if (isNaN(self.enthalpy) && this.enthalpy.length <= 1) {
     160                                        tpmp=NewArrayFill(md.mesh.numberofvertices,0);
     161                                        for (var i=0;i<md.mesh.numberofvertices;i++) tpmp[i]= md.materials.meltingpoint - md.materials.beta*md.initialization.pressure[i];
     162                                        enthalpy=NewArrayFill(md.mesh.numberofvertices,0);
     163                                        for (var i=0;i<md.mesh.numberofvertices;i++)enthalpy[i] = md.materials.heatcapacity*(md.initialization.temperature[i]-md.constants.referencetemperature);
     164                                        for (var i=0;i<md.mesh.numberofvertices;i++)if(md.initialization.temperature[i]>=tpmp[i]){
     165                                                enthalpy[i] = md.materials.heatcapacity*(tpmp[i] - md.constants.referencetemperature) + md.materials.latentheat*md.initialization.waterfraction[i];
     166                                        }
     167                                } else {
     168                                        enthalpy = this.enthalpy;
    122169                                }
    123170                                WriteData(fid,prefix,'data',enthalpy,'format','DoubleMat','mattype',1,'name','md.initialization.enthalpy');
     
    136183        //properties
    137184        // {{{
    138         this.vx            = NaN;
    139         this.vy            = NaN;
    140         this.vz            = NaN;
    141         this.vel           = NaN;
    142         this.pressure      = NaN;
    143         this.temperature   = NaN;
    144         this.waterfraction = NaN;
    145         this.sediment_head = NaN;
    146         this.epl_head      = NaN;
    147         this.epl_thickness = NaN;
    148         this.watercolumn   = NaN;
     185        this.vx                  = NaN;
     186        this.vy                  = NaN;
     187        this.vz                  = NaN;
     188        this.vel                 = NaN;
     189        this.pressure            = NaN;
     190        this.temperature         = NaN;
     191        this.enthalpy            = NaN;
     192        this.waterfraction       = NaN;
     193        this.sediment_head       = NaN;
     194        this.epl_head            = NaN;
     195        this.epl_thickness       = NaN;
     196        this.watercolumn         = NaN;
     197        this.hydraulic_potential = NaN;
     198        this.channelarea         = NaN;
     199        this.sealevel            = NaN;
     200        this.bottompressure      = NaN;
     201        this.dsl                 = NaN;
     202        this.str                 = NaN;
     203        this.sample              = NaN;
    149204        this.setdefaultparameters();
    150205
  • issm/trunk-jpl/src/m/classes/inversion.js

    r22098 r26300  
    140140                        WriteData(fid,prefix,'object',this,'fieldname','iscontrol','format','Boolean');
    141141                        WriteData(fid,prefix,'object',this,'fieldname','incomplete_adjoint','format','Boolean');
     142                        WriteData(fid,prefix,'object',this,'fieldname','vel_obs','format','DoubleMat','mattype',1,'scale',1/yts);
    142143                        if (!this.iscontrol) return;
    143144                        WriteData(fid,prefix,'object',this,'fieldname','nsteps','format','Integer');
  • issm/trunk-jpl/src/m/classes/issmsettings.js

    r25637 r26300  
    55
    66function issmsettings (){
    7         //methods
    8         this.setdefaultparameters = function(){// {{{
    9                 //are we short in memory ? (0 faster but requires more memory)
    10                 this.lowmem=0;
     7    //methods
     8    this.setdefaultparameters = function(){// {{{
     9        //are we short in memory ? (0 faster but requires more memory)
     10        this.lowmem=0;
    1111
    12                 //i/o:
    13                 this.io_gather=1;
     12        //i/o:
     13        this.io_gather=1;
    1414
    15                 //results frequency by default every step
    16                 this.output_frequency=1;
     15        //results frequency by default every step
     16        this.output_frequency=1;
    1717
    18                 //checkpoints frequency, by default never:
    19                 this.checkpoint_frequency=0;
     18        //coupling frequency of the stress balance solver by default every step
     19        this.sb_coupling_frequency=1;
    2020
    21                 //this option can be activated to load automatically the results
    22                 //onto the model after a parallel run by waiting for the lock file
    23                 //N minutes that is generated once the solution has converged
    24                 //0 to deactivate
    25                 this.waitonlock=Infinity;
     21        //checkpoints frequency, by default never:
     22        this.checkpoint_frequency=0;
    2623
    27                 //upload options:
    28                 upload_port         = 0;
    29                
    30                 //throw an error if solver residue exceeds this value
    31                 this.solver_residue_threshold=1e-6;
     24        //this option can be activated to load automatically the results
     25        //onto the model after a parallel run by waiting for the lock file
     26        //N minutes that is generated once the solution has converged
     27        //0 to deactivate
     28        this.waitonlock=Infinity;
    3229
    33         }// }}}
    34         this.disp= function(){// {{{
    35                 console.log(sprintf('   issmsettings class echo:'));
    36                
    37                 fielddisplay(this,'results_on_nodes','results are output for all the nodes of each element');
    38                 fielddisplay(this,'io_gather','I/O gathering strategy for result outputs (default 1)');
    39                 fielddisplay(this,'lowmem','is the memory limited ? (0 or 1)');
    40                 fielddisplay(this,'output_frequency','frequency at which results are saved in all solutions with multiple time_steps');
    41                 fielddisplay(this,'checkpoint_frequency','frequency at which the runs are being recorded, allowing for a restart');
    42                 fielddisplay(this,'waitonlock','maximum number of minutes to wait for batch results (NaN to deactivate)');
    43                 fielddisplay(this,'upload_server','server hostname where model should be uploaded');
    44                 fielddisplay(this,'upload_path','path on server where model should be uploaded');
    45                 fielddisplay(this,'upload_login','server login');
    46                 fielddisplay(this,'upload_port','port login (default is 0)');
    47                 fielddisplay(this,'upload_filename','unique id generated when uploading the file to server');
    48                 fielddisplay(this,'solver_residue_threshold','throw an error if solver residue exceeds this value');
     30        //upload options:
     31        this.upload_port         = 0;
     32
     33        //throw an error if solver residue exceeds this value
     34        this.solver_residue_threshold=1e-6;
     35
     36    }// }}}
     37    this.disp= function(){// {{{
     38        console.log(sprintf('   issmsettings class echo:'));
     39
     40        fielddisplay(this,'results_on_nodes','results are output for all the nodes of each element');
     41        fielddisplay(this,'io_gather','I/O gathering strategy for result outputs (default 1)');
     42        fielddisplay(this,'lowmem','is the memory limited ? (0 or 1)');
     43        fielddisplay(this,'output_frequency','frequency at which results are saved in all solutions with multiple time_steps');
     44        fielddisplay(this,'checkpoint_frequency','frequency at which the runs are being recorded, allowing for a restart');
     45        fielddisplay(this,'waitonlock','maximum number of minutes to wait for batch results (NaN to deactivate)');
     46        fielddisplay(this,'upload_server','server hostname where model should be uploaded');
     47        fielddisplay(this,'upload_path','path on server where model should be uploaded');
     48        fielddisplay(this,'upload_login','server login');
     49        fielddisplay(this,'upload_port','port login (default is 0)');
     50        fielddisplay(this,'upload_filename','unique id generated when uploading the file to server');
     51        fielddisplay(this,'solver_residue_threshold','throw an error if solver residue exceeds this value');
    4952
    5053
    51         }// }}}
    52         this.classname= function(){// {{{
    53                 return "issmsettings";
     54    }// }}}
     55    this.classname= function(){// {{{
     56        return "issmsettings";
    5457
    55         }// }}}
    56                 this.checkconsistency = function(md,solution,analyses) { // {{{
     58    }// }}}
     59        this.checkconsistency = function(md,solution,analyses) { // {{{
    5760
    58                         checkfield(md,'fieldname','settings.results_on_nodes','numel',[1],'values',[0, 1]);
    59                         checkfield(md,'fieldname','settings.io_gather','numel',[1],'values',[0, 1]);
    60                         checkfield(md,'fieldname','settings.lowmem','numel',[1],'values',[0, 1]);
    61                         checkfield(md,'fieldname','settings.output_frequency','numel',[1],'>=',1);
    62                         checkfield(md,'fieldname','settings.checkpoint_frequency','numel',[1],'>=',0);
    63                         checkfield(md,'fieldname','settings.waitonlock','numel',[1]);
    64                         checkfield(md,'fieldname','settings.solver_residue_threshold','numel',[1],'>',0);
    65                 } // }}}
    66                 this.marshall=function(md,prefix,fid) { //{{{
    67                         WriteData(fid,prefix,'object',this,'class','settings','fieldname','results_on_nodes','format','Boolean');
    68                         WriteData(fid,prefix,'object',this,'class','settings','fieldname','io_gather','format','Boolean');
    69                         WriteData(fid,prefix,'object',this,'class','settings','fieldname','lowmem','format','Boolean');
    70                         WriteData(fid,prefix,'object',this,'class','settings','fieldname','output_frequency','format','Integer');
    71                         WriteData(fid,prefix,'object',this,'class','settings','fieldname','checkpoint_frequency','format','Integer');
    72                         WriteData(fid,prefix,'object',this,'class','settings','fieldname','solver_residue_threshold','format','Double');
    73                         if (this.waitonlock>0) WriteData(fid,prefix,'name','md.settings.waitonlock','data',true,'format','Boolean');
    74                         else WriteData(fid,prefix,'name','md.settings.waitonlock','data',false,'format','Boolean');
    75                 }//}}}
    76                 this.fix=function() { //{{{
    77                 }//}}}
    78         //properties
    79         // {{{
    80         this.results_on_nodes    = 0;
    81         this.io_gather           = 0;
    82         this.lowmem              = 0;
    83         this.output_frequency    = 0;
    84         this.checkpoint_frequency   = 0;
    85         this.waitonlock          = 0;
    86         this.upload_server       = '';
    87         this.upload_path         = '';
    88         this.upload_login        = '';
    89         this.upload_port         = 0;
    90         this.upload_filename     = '';
    91         this.solver_residue_threshold = 0;
    92         this.setdefaultparameters();
    93         //}}}
     61                checkfield(md,'fieldname','settings.results_on_nodes','stringrow',1);
     62                checkfield(md,'fieldname','settings.io_gather','numel',[1],'values',[0, 1]);
     63                checkfield(md,'fieldname','settings.lowmem','numel',[1],'values',[0, 1]);
     64                checkfield(md,'fieldname','settings.output_frequency','numel',[1],'>=',1);
     65                checkfield(md,'fieldname','settings.sb_coupling_frequency','numel',[1],'>=',1);
     66                checkfield(md,'fieldname','settings.checkpoint_frequency','numel',[1],'>=',0);
     67                checkfield(md,'fieldname','settings.waitonlock','numel',[1]);
     68                checkfield(md,'fieldname','settings.solver_residue_threshold','numel',[1],'>',0);
     69        } // }}}
     70        this.marshall=function(md,prefix,fid) { //{{{
     71                WriteData(fid,prefix,'object',this,'class','settings','fieldname','results_on_nodes','format','StringArray');
     72                WriteData(fid,prefix,'object',this,'class','settings','fieldname','io_gather','format','Boolean');
     73                WriteData(fid,prefix,'object',this,'class','settings','fieldname','lowmem','format','Boolean');
     74                WriteData(fid,prefix,'object',this,'class','settings','fieldname','output_frequency','format','Integer');
     75                WriteData(fid,prefix,'object',this,'class','settings','fieldname','sb_coupling_frequency','format','Integer');
     76                WriteData(fid,prefix,'object',this,'class','settings','fieldname','checkpoint_frequency','format','Integer');
     77                WriteData(fid,prefix,'object',this,'class','settings','fieldname','waitonlock','data',this.waitonlock>0,'format','Boolean');
     78                WriteData(fid,prefix,'object',this,'class','settings','fieldname','solver_residue_threshold','format','Double');
     79        }//}}}
     80        this.fix=function() { //{{{
     81        }//}}}
     82        //properties
     83    // {{{
     84    this.results_on_nodes        = '';
     85    this.io_gather               = 0;
     86    this.lowmem                  = 0;
     87    this.output_frequency        = 0;
     88    this.sb_coupling_frequency   = 0;
     89    this.checkpoint_frequency    = 0;
     90    this.waitonlock              = 0;
     91    this.upload_server           = '';
     92    this.upload_path             = '';
     93    this.upload_login            = '';
     94    this.upload_port             = 0;
     95    this.upload_filename         = '';
     96    this.solver_residue_threshold = 0;
     97    this.setdefaultparameters();
     98    //}}}
    9499}
  • issm/trunk-jpl/src/m/classes/levelset.js

    r24039 r26300  
    1111                this.stabilization              = 2;
    1212                this.reinit_frequency   = 5;
     13                this.kill_icebergs      = 1;
     14                this.migration_max      = 1e12; //No need for general cases, unless specified
     15
     16                //Linear elements by default
     17                this.fe='P1';
    1318       
    1419        }// }}}
     
    1924                fielddisplay(this,'spclevelset','Levelset constraints (NaN means no constraint)');
    2025                fielddisplay(this,'reinit_frequency','Amount of time steps after which the levelset function in re-initialized (NaN: no re-initialization).');
     26                fielddisplay(this,'kill_icebergs','remove floating icebergs to prevent rigid body motions (1: true, 0: false)');
     27                fielddisplay(this,'migration_max','maximum allowed migration rate (m/a)');
     28                fielddisplay(this,'fe','Finite Element type: "P1" (default), or "P2"');
    2129
    2230        }// }}}
    23         this.extrude = function(md) {//{{{
    24                 this.spclevelset=project3d(md,'vector',this.spclevelset,'type','node');
    25                 return this;
    26         }//}}}
     31    this.extrude = function(md) {//{{{
     32        this.spclevelset=project3d(md,'vector',this.spclevelset,'type','node');
     33        return this;
     34    }//}}}
    2735        this.classname= function(){// {{{
    2836                return "levelset";
     
    3442                checkfield(md,'fieldname','levelset.spclevelset','Inf',1,'timeseries',1);
    3543                checkfield(md,'fieldname','levelset.stabilization','values',[0,1,2]);
     44                checkfield(md,'fieldname','levelset.kill_icebergs','numel',1,'values',[0, 1]);
     45                checkfield(md,'fieldname','levelset.migration_max','numel',1,'NaN',1,'Inf',1,'>',0);
     46                checkfield(md,'fieldname','levelset.fe','values',['P1','P2']);
    3647        } //}}}
    3748        this.marshall=function(md,prefix,fid) { //{{{
     49
     50                let yts=md.constants.yts;
     51
    3852                WriteData(fid,prefix,'object',this,'fieldname','stabilization','format','Integer');
    3953                WriteData(fid,prefix,'object',this,'fieldname','spclevelset','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
    4054                WriteData(fid,prefix,'object',this,'fieldname','reinit_frequency','format','Integer');
    41 
     55                WriteData(fid,prefix,'object',this,'fieldname','kill_icebergs','format','Boolean');
     56                WriteData(fid,prefix,'object',this,'fieldname','migration_max','format','Double','scale',1/yts);
     57                WriteData(fid,prefix,'object',this,'fieldname','fe','format','String');
    4258        }//}}}
    43         this.fix=function() { //{{{
    44                 this.spclevelset=NullFix(this.spclevelset,NaN);
    45         }//}}}
     59                this.fix=function() { //{{{
     60                        this.spclevelset=NullFix(this.spclevelset,NaN);
     61                }//}}}
    4662        //properties
    4763        // {{{
    4864
    4965        this.stabilization              = 0;
    50         this.spclevelset                        = NaN;
     66        this.spclevelset                = NaN;
    5167        this.reinit_frequency   = NaN;
     68        this.kill_icebergs      = 0;
     69        this.migration_max      = 0.;
     70        this.fe                 = 'P1';
    5271
    5372        this.setdefaultparameters();
  • issm/trunk-jpl/src/m/classes/mask.js

    r24867 r26300  
    77        //properties
    88        // {{{
    9                 this.ocean_levelset                           = NaN;
    10                 this.ice_levelset                           = NaN;
     9                this.ocean_levelset     = NaN;
     10                this.ice_levelset       = NaN;
    1111                //}}}
    1212        //methods
     
    1414                } // }}}
    1515                this.disp = function () { //{{{
    16                         console.log(sprintf("   mask:"));
     16                        console.log(sprintf("   masks:"));
    1717
    18                         fielddisplay(this,"ocean_levelset","presence of ocean if < 0, coastline/grounding line if = 0, no ocean if > 0");
    19                         fielddisplay(this,"ice_levelset","presence of ice if < 0, icefront position if = 0, no ice if > 0");
     18                        fielddisplay(this,'ocean_levelset','presence of ocean if < 0, coastline/grounding line if = 0, no ocean if > 0');
     19                        fielddisplay(this,'ice_levelset','presence of ice if < 0, icefront position if = 0, no ice if > 0');
    2020                } //}}}
    2121                this.extrude = function(md) {//{{{
     
    2828                } //}}}
    2929                this.checkconsistency = function(md,solution,analyses){ //{{{
     30                        if (solution=='LoveSolution') return;
    3031
    3132                        checkfield(md,'fieldname','mask.ocean_levelset','size',[md.mesh.numberofvertices, 1]);
     
    4647                this.fix=function() { //{{{
    4748                }//}}}
    48 
    4949}
  • issm/trunk-jpl/src/m/classes/mesh3dprisms.js

    r22879 r26300  
    2323
    2424            if(ArrayAnyEqual(ArrayIsMember(NewArrayFillIncrement(md.mesh.numberofvertices,1,1),ArraySort(ArrayUnique(MatrixToList(md.mesh.elements)))),0)){
    25                                 //md = checkmessage(md,'orphan nodes have been found. Check the mesh outline'); @TODO
     25                                //checkmessage(md,'orphan nodes have been found. Check the mesh outline'); @TODO
    2626                md.checkmessage('orphan nodes have been found. Check the mesh outline');
    2727                        }
     
    127127        } //}}}
    128128
    129         //properties (SetAccess=public)
     129        //properties
     130        // {{{
    130131        this.x                           = NaN;
    131132        this.y                           = NaN;
     
    139140        this.long                        = NaN;
    140141        this.epsg                        = 0;
    141                   this.scale_factor                = NaN;
     142                this.scale_factor                = NaN;
    142143
    143144        this.vertexonbase                = NaN;
     
    161162        this.extractedvertices           = NaN;
    162163        this.extractedelements           = NaN;
     164        //}}}
    163165}
  • issm/trunk-jpl/src/m/classes/qmu.js

    r22098 r26300  
    1212                console.log(sprintf('   qmu parameters:'));
    1313
    14                 /*fielddisplay(this,'isdakota','is qmu analysis activated?');
     14                fielddisplay(this,'isdakota','is qmu analysis activated?');
     15                fielddisplay(this,'output','are we outputting ISSM results, default is 0');
     16                /*
    1517                for (var i=0;i<this.variables.length;i++){
    1618                        console.log(sprintf('         variables%s:  (arrays of each variable class)',...
     
    106108                this.marshall=function(md,prefix,fid) { //{{{
    107109                        WriteData(fid,prefix,'object',this,'fieldname','isdakota','format','Boolean');
     110                        WriteData(fid,prefix,'object',this,'fieldname','output','format','Boolean');
    108111                        if (!this.isdakota){
    109112                                WriteData(fid,prefix,'data',0,'name','md.qmu.mass_flux_segments_present','format','Boolean');
     
    129132
    130133        this.isdakota                    = 0;
     134        this.output                      = 0;
    131135        this.variables                   = []
    132136        this.responses                   = [];
  • issm/trunk-jpl/src/m/classes/slr.js

    r24521 r26300  
    114114                } //}}}
    115115                this.marshall=function(md,prefix,fid) { //{{{
    116 
     116                        console.log('WARNING: NOT MARHSALLING SLR FOR NOW.');
     117                        return;
    117118                        WriteData(fid,prefix,'object',this,'fieldname','deltathickness','format','DoubleMat','mattype',2);
    118119                        WriteData(fid,prefix,'object',this,'fieldname','sealevel','mattype',1,'format','DoubleMat','timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts);
  • issm/trunk-jpl/src/m/classes/stressbalance.js

    r24866 r26300  
    158158                WriteData(fid,prefix,'object',this,'class','stressbalance','fieldname','referential','format','DoubleMat','mattype',1);
    159159
    160                 var lx=NewArrayFill(this.loadingforce.length,0); for(var i=0;i<lx.length;i++)lx[i]=this.loadingforce[i][0];
    161                 var ly=NewArrayFill(this.loadingforce.length,0); for(var i=0;i<lx.length;i++)ly[i]=this.loadingforce[i][1];
    162                 var lz=NewArrayFill(this.loadingforce.length,0); for(var i=0;i<lx.length;i++)lz[i]=this.loadingforce[i][2];
    163 
    164                 WriteData(fid,prefix,'data',lx,'format','DoubleMat','mattype',1,'name','md.stressbalance.loadingforcex');
    165                 WriteData(fid,prefix,'data',ly,'format','DoubleMat','mattype',1,'name','md.stressbalance.loadingforcey');
    166                 WriteData(fid,prefix,'data',lz,'format','DoubleMat','mattype',1,'name','md.stressbalance.loadingforcez');
     160                if (size(this.loadingforce,1)==3) {
     161                        WriteData(fid,prefix,'data',ArrayCol(this.loadingforce,0),'format','DoubleMat','mattype',1,'name','md.stressbalance.loadingforcex');
     162                        WriteData(fid,prefix,'data',ArrayCol(this.loadingforce,1),'format','DoubleMat','mattype',1,'name','md.stressbalance.loadingforcey');
     163                        WriteData(fid,prefix,'data',ArrayCol(this.loadingforce,2),'format','DoubleMat','mattype',1,'name','md.stressbalance.loadingforcez');
     164                }
    167165
    168166                //process requested outputs
  • issm/trunk-jpl/src/m/classes/thermal.js

    r24140 r26300  
    6464                return "thermal";
    6565        }// }}}
    66         this.extrude = function(md) {//{{{
    67                 this.spctemperature=project3d(md,'vector',this.spctemperature,'type','node','layer',md.mesh.numberoflayers,'padding',NaN);
    68                 if (md.initialization.temperature.length===md.mesh.numberofvertices) {
    69                         this.spctemperature = NewArrayFill(md.mesh.numberofvertices, NaN);
    70                         var pos=ArrayFindNot(md.mesh.vertexonsurface, 0);
     66    this.extrude = function(md) {//{{{
     67        this.spctemperature=project3d(md,'vector',this.spctemperature,'type','node','layer',md.mesh.numberoflayers,'padding',NaN);
     68        if (md.initialization.temperature.length===md.mesh.numberofvertices) {
     69            this.spctemperature = NewArrayFill(md.mesh.numberofvertices, NaN);
     70            var pos=ArrayFindNot(md.mesh.vertexonsurface, 0);
    7171                        // impose observed temperature on surface
    7272                        for (var i=0,posIndex=0,count=0;i<md.initialization.temperature.length;i++){
     
    8989//                              }
    9090//                      }
    91                 }
     91        }
    9292
    93                 return this;
    94         }//}}}
     93        return this;
     94    }//}}}
    9595        this.checkconsistency = function(md,solution,analyses){ // {{{
    9696
     
    104104                        checkfield(md,'fieldname','thermal.isdrainicecolumn','numel',[1],'values',[0, 1]);
    105105                        checkfield(md,'fieldname','thermal.watercolumn_upperlimit','>=',0);
    106 
     106                       
    107107                        for(var i=0;i<md.mesh.numberofvertices;i++){
    108108                                for(var j=0;j<md.thermal.spctemperature[0].length;j++){
     
    123123                                        md.checkmessage('for a steadystate computation, thermal.reltol (relative convergence criterion) must be defined!');
    124124                                }
     125                                checkfield(md,'fieldname','thermal.reltol','>',0.,'message','reltol must be larger than zero');
    125126                        }
    126                         checkfield(md,'fieldname','thermal.reltol','>',0.,'message','reltol must be larger than zero');
    127127                }
    128128                checkfield(md,'fieldname','thermal.requested_outputs','stringrow',1);
     
    163163        //properties
    164164        // {{{
    165 
    166         this.spctemperature    = NaN;
    167         this.penalty_threshold = 0;
    168         this.stabilization     = 0;
    169         this.reltol        = 0;
    170         this.maxiter           = 0;
    171         this.penalty_lock      = 0;
    172         this.penalty_factor    = 0;
    173         this.isenthalpy        = 0;
    174         this.isdynamicbasalspc = 0;
    175         this.isdrainicecolumn  = 0;
    176         this.watercolumn_upperlimit=0;
    177         this.fe                = 'P1';
    178         this.requested_outputs = [];
     165        this.spctemperature             = NaN;
     166        this.penalty_threshold          = 0;
     167        this.stabilization              = 0;
     168        this.reltol                                     = 0;
     169        this.maxiter                    = 0;
     170        this.penalty_lock               = 0;
     171        this.penalty_factor             = 0;
     172        this.isenthalpy                 = 0;
     173        this.isdynamicbasalspc          = 0;
     174        this.isdrainicecolumn           = 0;
     175        this.watercolumn_upperlimit = 0;
     176        this.fe                         = 'P1';
     177        this.requested_outputs          = [];
    179178
    180179        this.setdefaultparameters();
  • issm/trunk-jpl/src/m/classes/timestepping.js

    r26195 r26300  
    66function timestepping (){
    77        //methods
    8         this.setdefaultparameters = function(){// {{{
     8        this.setdefaultparameters = function(){ //{{{
    99                //time between 2 time steps
    1010                this.time_step=1./2.;
     
    1414
    1515                //should we interpolate forcings between timesteps?
    16                 this.interp_forcings=1;
     16                this.interp_forcing=1;
    1717                this.cycle_forcing=0;
    18         }// }}}
    19         this.disp= function(){// {{{
     18        } //}}}
     19        this.disp= function(){ //{{{
    2020
    2121                var unit;
     
    2525                fielddisplay(this,'final_time','final time to stop the simulation ['+ unit + ']');
    2626                fielddisplay(this,'time_step','length of time steps [' +unit+ ']');
    27                 fielddisplay(this,'interp_forcings','interpolate in time between requested forcing values ? (0 or 1)');
     27                fielddisplay(this,'interp_forcing','interpolate in time between requested forcing values ? (0 or 1)');
    2828                fielddisplay(this,'cycle_forcing','cycle through forcing ? (0 or 1)');
    2929                fielddisplay(this,'coupling_time','length of coupling time steps with ocean model [' +unit+ ']');
    3030
    31         }// }}}
    32         this.classname= function(){// {{{
     31        } //}}}
     32        this.classname= function(){ //{{{
    3333                return "timestepping";
    3434
    35         }// }}}
     35        } //}}}
    3636        this.checkconsistency = function(md,solution,analyses) { //{{{
    3737
     
    3939                checkfield(md,'fieldname','timestepping.final_time','numel',[1],'NaN',1,'Inf',1);
    4040                checkfield(md,'fieldname','timestepping.time_step','numel',[1],'>=',0,'NaN',1,'Inf',1);
    41                 checkfield(md,'fieldname','timestepping.interp_forcings','numel',[1],'values',[0,1]);
     41                checkfield(md,'fieldname','timestepping.interp_forcing','numel',[1],'values',[0,1]);
    4242                checkfield(md,'fieldname','timestepping.cycle_forcing','numel',[1],'values',[0,1]);
    4343                checkfield(md,'fieldname','timestepping.coupling_time','numel',[1],'>=',0,'NaN',1,'Inf',1);
    4444                if (this.final_time-this.start_time<0){
    4545                        md.checkmessage('timestepping.final_time should be larger than timestepping.start_time');
     46                }
     47                if (solution=='TransientSolution'){
     48                        checkfield(md,'fieldname','timestepping.time_step','numel',[1],'>',0,'NaN',1,'Inf',1);
     49                        checkfield(md,'fieldname','timestepping.time_step','numel',[1],'>=',0,'NaN',1,'Inf',1);
    4650                }
    4751        } // }}}
     
    5559                WriteData(fid,prefix,'object',this,'fieldname','final_time','format','Double','scale',scale);
    5660                WriteData(fid,prefix,'object',this,'fieldname','time_step','format','Double','scale',scale);
    57                 WriteData(fid,prefix,'object',this,'fieldname','interp_forcings','format','Boolean');
     61                WriteData(fid,prefix,'object',this,'fieldname','interp_forcing','format','Boolean');
    5862                WriteData(fid,prefix,'object',this,'fieldname','cycle_forcing','format','Boolean');
    5963                WriteData(fid,prefix,'object',this,'fieldname','coupling_time','format','Double','scale',scale);
     
    6771        this.final_time      = 0.;
    6872        this.time_step       = 0.;
    69         this.interp_forcings = 1;
    70         this.cycle_forcing   = 0;
     73        this.interp_forcing  = 1;
     74        this.cycle_forcing   = 1;
    7175        this.coupling_time   = 0.;
    7276
  • issm/trunk-jpl/src/m/classes/trans.js

    r22718 r26300  
    7979                        WriteData(fid,prefix,'object',this,'fieldname','issmb','format','Boolean');
    8080                        WriteData(fid,prefix,'object',this,'fieldname','ismasstransport','format','Boolean');
     81                        WriteData(fid,prefix,'object',this,'fieldname','isoceantransport','format','Boolean');
    8182                        WriteData(fid,prefix,'object',this,'fieldname','isstressbalance','format','Boolean');
    8283                        WriteData(fid,prefix,'object',this,'fieldname','isthermal','format','Boolean');
    8384                        WriteData(fid,prefix,'object',this,'fieldname','isgroundingline','format','Boolean');
    84                         WriteData(fid,prefix,'object',this,'fieldname','isgia','format','Boolean');
    8585                        WriteData(fid,prefix,'object',this,'fieldname','isesa','format','Boolean');
    8686                        WriteData(fid,prefix,'object',this,'fieldname','isdamageevolution','format','Boolean');
    8787                        WriteData(fid,prefix,'object',this,'fieldname','ishydrology','format','Boolean');
    8888                        WriteData(fid,prefix,'object',this,'fieldname','ismovingfront','format','Boolean');
    89                         WriteData(fid,prefix,'object',this,'fieldname','isslr','format','Boolean');
     89                        WriteData(fid,prefix,'object',this,'fieldname','issampling','format','Boolean');
     90                        WriteData(fid,prefix,'object',this,'fieldname','isslc','format','Boolean');
    9091                        WriteData(fid,prefix,'object',this,'fieldname','isoceancoupling','format','Boolean');
    91                         WriteData(fid,prefix,'object',this,'fieldname','iscoupler','format','Boolean');
    9292                        WriteData(fid,prefix,'object',this,'fieldname','amr_frequency','format','Integer');
    9393
  • issm/trunk-jpl/src/m/plot/applyoptions.js

    r23051 r26300  
    1 function applyoptions(md, data, options, canvas){ //{{{
     1'use strict';
     2
     3function applyoptions(md, data, options, canvas) {
    24        //APPLYOPTIONS - apply colobar, text, cloud, and expdisp options to current plot
    35        //
     
    810
    911        //{{{ colorbar
    10         var gl = canvas.gl;
    11         if (options.exist('colorbar')) {
    12                 if (options.getfieldvalue('colorbar')==1) {
    13                         //{{{ Variable options initialization
    14                         var caxis = options.getfieldvalue('caxis');
    15                         var ccanvasid, ctitleid, clabelsid, ccanvas, ctitle, clabels, ccontext, cmap, colorbar, cwidth, cheight, cgradient, color, y, x;
    16                         //}}}
    17                         //{{{ Create colorbar labels
    18                         var labels = [];
    19                         var cdivisions = options.getfieldvalue('colorbarnticks', 6);
    20                         var caxisdelta = caxis[1] - caxis[0];
    21                         var precision = options.getfieldvalue('colorbarprecision', 3);
    22                         var format = options.getfieldvalue('colorbarformat', 'f').toLowerCase();
    23                         if (options.getfieldvalue('log','off')!='off') {
    24                                 for (var i=cdivisions; i >= 0; i--) {
    25                                         var scale = (Math.log10(caxis[1])-Math.log10(caxis[0]))/Math.log10(options.getfieldvalue('log', 10));
    26                                         if (format === 'f') {
    27                                                 labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10))+scale*(cdivisions-i)/cdivisions)).toFixed(precision);
    28                                         }
    29                                         else if (format === 'e') {
    30                                                 labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10))+scale*(cdivisions-i)/cdivisions)).toPrecision(precision);
    31                                         }
    32                                         else {
    33                                                 labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(caxis[0])/Math.log10(options.getfieldvalue('log', 10))+scale*(cdivisions-i)/cdivisions)).toFixed(precision);
    34                                         }
     12        let gl = canvas.gl;
     13       
     14        if (options.getfieldvalue('colorbar', false)) {
     15                //{{{ Create colorbar labels
     16                let cAxis = options.getfieldvalue('caxis');
     17                let labels = [];
     18                let divisions = options.getfieldvalue('colorbarnticks', 6);
     19                let cAxisDelta = cAxis[1] - cAxis[0];
     20                let precision = options.getfieldvalue('colorbarprecision', 3);
     21                let format = options.getfieldvalue('colorbarformat', 'f').toLowerCase();
     22                if (options.getfieldvalue('log','off') !== 'off') {
     23                        for (let i = divisions; i >= 0; i--) {
     24                                let scale = (Math.log10(cAxis[1]) - Math.log10(cAxis[0])) / Math.log10(options.getfieldvalue('log', 10));
     25                                if (format === 'f') {
     26                                        labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(cAxis[0]) / Math.log10(options.getfieldvalue('log', 10)) + scale * (divisions - i) / divisions)).toFixed(precision);
     27                                } else if (format === 'e') {
     28                                        labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(cAxis[0]) / Math.log10(options.getfieldvalue('log', 10)) + scale * (divisions - i) / divisions)).toPrecision(precision);
     29                                } else {
     30                                        labels[i] = (Math.pow(options.getfieldvalue('log', 10), Math.log10(cAxis[0]) / Math.log10(options.getfieldvalue('log', 10)) + scale * (divisions - i) / divisions)).toFixed(precision);
     31                                }
     32                        }
     33                } else {
     34                        for (let i = divisions; i >= 0; i--) {
     35                                if (format === 'f') {
     36                                        labels[i] = (cAxisDelta * (divisions - i) / divisions + cAxis[0]).toFixed(precision);
     37                                } else if (format === 'e') {
     38                                        labels[i] = (cAxisDelta * (divisions - i) / divisions + cAxis[0]).toPrecision(precision);
     39                                } else {
     40                                        labels[i] = (cAxisDelta * (divisions - i) / divisions + cAxis[0]).toFixed(precision);
     41                                }
     42                        }
     43                } //}}}
     44                //{{{ Initialize colorbar canvas
     45                let cCanvasId = options.getfieldvalue('colorbarid', options.getfieldvalue('canvasid') + ('-colorbar-canvas'));
     46                let cCanvasIdBase = cCanvasId.substring(0, cCanvasId.lastIndexOf('-canvas'));
     47                let cCanvas = document.getElementById(cCanvasId);
     48                let cWidth = cCanvas.width * options.getfieldvalue('colorbarwidth', 1);
     49                let cHeight = cCanvas.height * options.getfieldvalue('colorbarheight', 1);
     50                let cContext = cCanvas.getContext('2d');
     51                let cMap = options.getfieldvalue('colormap', 'amp');
     52               
     53                // If value of cMap is of type array, assume we have a custom colorbar; otherwise, look up colormap by name from global letiable "colorbars"
     54                let colorbar = null;
     55               
     56                if (vesl.arrays.isArray(cMap)) {
     57                        colorbar = cMap;
     58                } else {
     59                for (let colormap in colorbars) {
     60                        if (colormap === cMap) {
     61                                colorbar = colorbars[cMap];
     62                                break;
     63                }
     64            }
     65           
     66            if (colorbar === null) {
     67                for (let colormap in cmoceanColormaps) {
     68                        if (colormap === cMap) {
     69                                colorbar = cmoceanColormaps[cMap];
     70                                break;
     71                    }
     72                }
     73            }
     74                }
     75               
     76                let gradient = cContext.createLinearGradient(0, 0, 0, cHeight);
     77                //}}}
     78                //{{{ Draw colorbar gradient
     79                // TODO: Allow for passing the opacity in as a fourth value of each array of a colormap?
     80                let applyOpacityToColorbar  = options.getfieldvalue('applyOpacityToColorbar', false);
     81                let color                   = null;
     82                let background              = options.getfieldvalue('colorbarBackground', null);
     83                let offset                  = 1 / (colorbar.length - 1) / 2;
     84                let opacity                 = options.getfieldvalue('opacity', 1.0);
     85                let position                = null;
     86                let scaling                 = 1 - 2 * offset;
     87               
     88                if (!applyOpacityToColorbar) {
     89                opacity = 1.0;
     90                }
     91               
     92                if (background !== null) {
     93                background = [background[0] * 255, background[1] * 255, background[2] * 255];
     94                $('#' + cCanvasId).css('background', 'rgba(' + background.toString() + ', 1.0');
     95                }
     96               
     97                for (let i = 0; i < colorbar.length; i++) {
     98                        color = colorbar[colorbar.length - i - 1];
     99                        color = [Math.round(color[0] * 255), Math.round(color[1] * 255), Math.round(color[2] * 255)];
     100                        position = (i / (colorbar.length - 1) * scaling) + offset;
     101                        gradient.addColorStop(position, 'rgba(' + color.toString() + ', ' + opacity + ')');
     102                }
     103               
     104                cContext.clearRect(0, 0, cWidth, cHeight);
     105                cContext.beginPath();
     106                cContext.fillStyle = gradient;
     107                cContext.fillRect(0, 0, cWidth, cHeight);
     108                //}}}
     109                //{{{ Draw colorbar border
     110                cContext.beginPath();
     111                cContext.lineWidth = '1';
     112                cContext.strokeStyle=options.getfieldvalue('colorbarfontcolor','black');
     113                cContext.rect(0, 0, cWidth, cHeight);
     114                cContext.stroke();
     115                //}}}
     116                //{{{ Draw colorbar labels
     117                let cLabelsId = cCanvasIdBase + '-labels';
     118                let cLabels = $('#' + cLabelsId);
     119                let cLabelString = '';
     120                let x, y;
     121                cLabels.empty();
     122                for (let i = 0; i <= divisions; i++) {
     123                        y = (i + 0.5) / (divisions + 1) * cHeight;
     124                        x = 0.2 * cWidth;
     125                        cLabelString += '<li><span>' + labels[i] + '</span></li>';
     126                        cContext.beginPath();
     127                        cContext.moveTo(0, y);
     128                        cContext.lineTo(x, y);
     129                        cContext.moveTo(cWidth - x, y);
     130                        cContext.lineTo(cWidth, y);
     131                        cContext.stroke();
     132                }
     133                cLabels.append(cLabelString);
     134                //}}}
     135                //{{{ Draw colorbar title
     136                let cTitleId = cCanvasIdBase + '-heading';
     137                let cTitle = $('#' + cTitleId);
     138                if (options.exist('colorbartitle')) { cTitle.html(options.getfieldvalue('colorbartitle')); }
     139                //}}}
     140                //{{{ Setup texture/alpha canvases
     141                let $canvas     = $(canvas);
     142                let tCanvasId   = options.getfieldvalue('texturecanvasid', 'texturecanvas');
     143                let aCanvasId   = options.getfieldvalue('alphacanvasid', 'alphacanvas');
     144                let tCanvas     = document.getElementById(tCanvasId);
     145                let aCanvas     = document.getElementById(aCanvasId);
     146               
     147                if (tCanvas == null) {
     148                        $('<canvas id="' + tCanvasId + '" width="256" height="256" style="display: none;"></canvas>').insertAfter($canvas);
     149                        tCanvas = document.getElementById(tCanvasId);
     150                }
     151               
     152                if (aCanvas == null) {
     153                        $('<canvas id="' + aCanvasId + '" width="256" height="256" style="display: none;"></canvas>').insertAfter($canvas);
     154                        aCanvas = document.getElementById(aCanvasId);
     155                }
     156       
     157                //Set up canvas drawing contexes and gradients.
     158                let tContext = tCanvas.getContext('2d');
     159                let aContext = aCanvas.getContext('2d');
     160                let tGradient = tContext.createLinearGradient(0, 0, 0, 256);
     161                let aGradient = aContext.createLinearGradient(0, 0, 0, 256);
     162               
     163                //Determine where in gradient to start unit mesh transparency
     164                let maskAlphaEnabled = options.getfieldvalue('maskAlphaEnabled', false);
     165                let maskAlphaTolerance = options.getfieldvalue('maskAlphaTolerance', 0.1);
     166                let maskAlphaValue = options.getfieldvalue('maskAlphaValue', 1.1);
     167                let maskAlphaUseColor = options.getfieldvalue('maskAlphaUseColor', false);
     168                let maskAlphaColor = options.getfieldvalue('maskAlphaColor', 'rgba(0.0, 0.0, 255, 1.0)');
     169                let alphaValue = (maskAlphaValue - cAxis[0]) / cAxisDelta;
     170               
     171                //Apply transparency to alpha map that enables alpha to be read from texture, and to actual texture alpha.
     172                for (let i = 0; i < colorbar.length; i++) {
     173                        color = colorbar[colorbar.length - i - 1];
     174                        color = [Math.round(color[0] * 255), Math.round(color[1] * 255), Math.round(color[2] * 255)];
     175                        let colorStop = i / (colorbar.length - 1);
     176                        if (maskAlphaEnabled && (colorStop > 1 - alphaValue || colorStop == colorbar.length - 1)) {
     177                                if (maskAlphaUseColor) {
     178                                        tGradient.addColorStop(colorStop, maskAlphaColor);
     179                                        aGradient.addColorStop(colorStop, 'rgb(255, 255, 255)');
     180                                } else {
     181                                        tGradient.addColorStop(colorStop, 'rgba(' + color.toString() + ', 0.0)');
     182                                        aGradient.addColorStop(colorStop, 'rgb(0, 0, 0)');
    35183                                }
    36184                        } else {
    37                                 for (var i=cdivisions; i >= 0; i--) {
    38                                         if (format === 'f') {
    39                                                 labels[i] = (caxisdelta*(cdivisions-i)/cdivisions+caxis[0]).toFixed(precision);
    40                                         }
    41                                         else if (format === 'e') {
    42                                                 labels[i] = (caxisdelta*(cdivisions-i)/cdivisions+caxis[0]).toPrecision(precision);
    43                                         }
    44                                         else {
    45                                                 labels[i] = (caxisdelta*(cdivisions-i)/cdivisions+caxis[0]).toFixed(precision);
    46                                         }
    47                                 }
    48                         } //}}}
    49                         //{{{ Initialize colorbar canvas
    50                         let colorbarSlug = options.getfieldvalue('colorbarSlug', options.getfieldvalue('canvasid') + '-colorbar');
    51                         ccanvasid = colorbarSlug + '-canvas';
    52                         ccanvas = $('#'+ccanvasid)[0];
    53                         cwidth = ccanvas.width*options.getfieldvalue('colorbarwidth', 1);
    54                         cheight = ccanvas.height*options.getfieldvalue('colorbarheight', 1);
    55                         ccontext = ccanvas.getContext('2d');
    56                         ccontext.clearRect(0, 0, cwidth, cheight);
    57                         ccontext.beginPath();
    58                         cmap = options.getfieldvalue('colormap','jet');
    59                         colorbar = colorbars[cmap];
    60                         cgradient = ccontext.createLinearGradient(0, 0, 0, cheight);
    61                         //}}}
    62                         //{{{ Draw colorbar gradient
    63                         var position;
    64                         var offset = 1 / (colorbar.length - 1) / 2;
    65                         var scaling = 1 - 2 * offset;
    66                         for (var i=0; i < colorbar.length; i++) {
    67                                 color = colorbar[colorbar.length-i-1];
    68                                 color = [Math.round(color[0]*255), Math.round(color[1]*255), Math.round(color[2]*255)];
    69                                 position = (i / (colorbar.length - 1) * scaling) + offset;
    70                                 cgradient.addColorStop(position, 'rgba(' + color.toString() + ', 1.0)');
    71                         }
    72                         ccontext.fillStyle=cgradient;
    73                         ccontext.fillRect(0, 0, cwidth, cheight);
    74                         //}}}
    75                         //{{{ Draw colorbar border
    76                         ccontext.beginPath();
    77                         ccontext.lineWidth='1';
    78                         ccontext.strokeStyle=options.getfieldvalue('colorbarfontcolor','black');
    79                         ccontext.rect(0, 0, cwidth, cheight);
    80                         ccontext.stroke();
    81                         //}}}
    82                         //{{{ Draw colorbar labels
    83                         clabelsid = colorbarSlug + '-labels';
    84                         clabels = $('#'+clabelsid);
    85                         var clabelstring = '';
    86                         clabels.empty();
    87                         for (var i=0; i <= cdivisions; i++) {
    88                                 y = (i+0.5)/(cdivisions+1)*cheight;
    89                                 x = 0.2*cwidth;
    90                                 clabelstring += '<li><span>'+labels[i]+'</span></li>';
    91                                 ccontext.beginPath();
    92                                 ccontext.moveTo(0, y);
    93                                 ccontext.lineTo(x, y);
    94                                 ccontext.moveTo(cwidth-x, y);
    95                                 ccontext.lineTo(cwidth, y);
    96                                 ccontext.stroke();
    97                         }
    98                         clabels.append(clabelstring);
    99                         //}}}
    100                         //{{{ Draw colorbar title
    101                         ctitleid = colorbarSlug + '-heading';
    102                         ctitle = $('#'+ctitleid);
    103                         if (options.exist('colorbarHeader')) { ctitle.html(options.getfieldvalue('colorbarHeader')); }
    104                         //}}}
     185                                tGradient.addColorStop(colorStop, 'rgba(' + color.toString() + ', 1.0)');
     186                                aGradient.addColorStop(colorStop, 'rgb(255, 255, 255)');
     187                        }
     188                }
     189               
     190                //Draw gradients to canvaes.
     191                tContext.fillStyle = tGradient;
     192                aContext.fillStyle = aGradient;
     193                tContext.fillRect(0, 0, 256, 256);
     194                aContext.fillRect(0, 0, 256, 256);
     195               
     196                //Allow for special texture colors, drawing each color in equal width vertical rectangles. The last rectanglar section is reserved for the colormap.
     197                if (options.exist('maskregion')) {
     198                        let maskObject = options.getfieldvalue('maskregion',{'enabled':false});
     199                        if (maskObject.enabled && !vesl.helpers.isEmptyOrUndefined(maskObject.colors)) {
     200                                let x = 0;
     201                                let sections = Object.keys(maskObject.colors).length + 1;
     202                                let size = 256;
     203                                let width = Math.floor(1 / sections * size);
     204                                for (let color in maskObject.colors) {
     205                                        tContext.fillStyle = maskObject.colors[color];
     206                                        tContext.fillRect(x++ * width, 0, width, size);
     207                                }
     208                        }
     209                }
     210               
     211                //Read canvases as images, and load as textures in Three.js
     212                let tURL            = tCanvas.toDataURL();
     213                let aURL            = aCanvas.toDataURL();
     214                let textureMap      = new THREE.TextureLoader().load(tURL);
     215                let alphaMap        = new THREE.TextureLoader().load(aURL);
     216                let unitOptions         = options.getfieldvalue('unitOptions', {'name' : 'unit'});
     217                let unitName            = unitOptions.name;
     218                let unitSceneNode       = canvas.unitNodes[unitName].sceneNode;
     219                unitSceneNode.material.map          = textureMap;
     220                unitSceneNode.material.emissiveMap  = textureMap;
     221                unitSceneNode.material.color        = new THREE.Color(0xffffff);
     222                unitSceneNode.material.needsUpdate  = true;
     223               
     224                //Only apply alpha map if enabled.
     225                if (maskAlphaEnabled) {
     226                        unitSceneNode.material.alphaMap = alphaMap;
    105227                }
    106228        } //}}}
    107         //{{{ texture canvas
    108         var tcontext, tcanvas, tcanvasid, tURL, tgradient;
    109         tcanvasid = 'texturecanvas';
    110         var tcanvas = document.getElementById(tcanvasid);
    111         if (tcanvas == null) {
    112                 $('<canvas id="texturecanvas" width="256" height="256" style="display: none;"></canvas>').insertAfter('#'+String(options.getfieldvalue('canvasid')));
    113                 tcanvas = document.getElementById(tcanvasid);
    114         }
    115         tcontext = tcanvas.getContext('2d');
    116         tgradient = tcontext.createLinearGradient(0, 0, 0, 256);
    117 
    118         var cmap = options.getfieldvalue('colormap','jet');
    119         var colorbar = colorbars[cmap];
    120         for (var i = 0; i < colorbar.length; i++) {
    121                 color = colorbar[colorbar.length - i - 1];
    122                 color = [Math.round(color[0] * 255), Math.round(color[1] * 255), Math.round(color[2] * 255)];
    123                 tgradient.addColorStop(i / (colorbar.length - 1), 'rgba(' + color.toString() + ', 1.0)');
    124         }
    125         tcontext.fillStyle = tgradient;
    126         tcontext.fillRect(0, 0, 256, 256);
    127 
    128         //Allow for special texture colors, drawing each color in equal width vertical rectangles. The last rectanglar section is reserved for the colormap.
    129         if (options.exist('maskregion')) {
    130                 var maskObject = options.getfieldvalue('maskregion',{'enabled':false});
    131                 if (maskObject.enabled && !vesl.helpers.isEmptyOrUndefined(maskObject.colors)) {
    132                         var x = 0;
    133                         var sections = Object.keys(maskObject.colors).length + 1;
    134                         var size = 256;
    135                         var width = Math.floor(1 / sections * size);
    136                         for (var color in maskObject.colors) {
    137                                 tcontext.fillStyle = maskObject.colors[color];
    138                                 tcontext.fillRect(x++ * width, 0, width, size);
    139                         }
    140                 }
    141         }
    142 
    143         tURL = tcanvas.toDataURL();
    144         if (options.getfieldvalue('clf','on')=='off') {
    145                 canvas.nodes['unit' + (Object.keys(canvas.nodes).length - 1)].texture = initTexture(canvas.gl, tURL);
    146         } else {
    147                 canvas.nodes.unit.texture = initTexture(canvas.gl, tURL);
    148         }
    149229        //}}}
    150         //{{{ text display
    151         var ctx;
    152         var overlaycanvasid;
    153         var overlaycanvas;
    154         //Only intialize overlay canvas once by checking if it's already been defined
    155         if (vesl.helpers.isEmptyOrUndefined(canvas.overlaycanvas)) {
    156                 //Get drawing context and save reference on main WebGL canvas
    157                 overlaycanvasid = options.getfieldvalue('overlayid', options.getfieldvalue('canvasid') + '-overlay')
    158                 overlaycanvas = $('#' + overlaycanvasid)[0];
    159                 ctx = overlaycanvas.getContext('2d');
    160                 canvas.overlaycanvas = overlaycanvas;
    161         }
    162         overlaycanvas = canvas.overlaycanvas;
    163         ctx = overlaycanvas.getContext('2d');
    164 
    165         if (options.exist('textlabels')) {//{{{
    166                 //Attatch new overlay handler to display text labels
    167                 var textLabels = options.getfieldvalue('textlabels',[]);
    168                 canvas.overlayHandlers['text'] = function(canvas) {
    169                         for (var i = 0; i < textLabels.length; i++) {
    170                                 //Get text label to display
    171                                 var textLabel = textLabels[i];
    172                                 textLabel = {
    173                                         position: defaultFor(textLabel.position, vec3.create()),
    174                                         text: defaultFor(textLabel.text, ''),
    175                                         fontSize: defaultFor(textLabel.fontSize, 18),
    176                                         fontColor: defaultFor(textLabel.fontColor, 'black'),
    177 
    178                                 };
    179 
    180                                 // function declared in slr-gfm sim-front-end-controller.js
    181                                 // if labels are behind the globe sphere then skip iteartion and do not display them
    182                                 if (vesl.ui.isLabelVisible(textLabel)) {
    183                                         //Transform from world space to viewport space
    184                                         var screenPoint = vec3.transformMat4(vec3.create(), textLabel.position, canvas.camera.vpMatrix);
    185                                         var x = (screenPoint[0] + 1.0) * (canvas.width / 2) + canvas.selector.offset().left;
    186                                         var y = (-screenPoint[1] + 1.0) * (canvas.height / 2) + canvas.selector.offset().top;
    187 
    188                                         //Draw text
    189                                         ctx.font = 'bold ' + String(textLabel.fontSize) + 'px Arial Black, sans-serif';
    190                                         ctx.fillStyle = textLabel.fontColor;
    191                                         ctx.strokeStyle = 'white';
    192                                         ctx.textAlign = 'center';
    193                                         ctx.textBaseline = 'middle';
    194                                         ctx.fillText(textLabel.text, x, y);
    195                                         ctx.strokeText(textLabel.text, x, y);
    196                                 }
    197                         }
    198                 }
    199         }//}}}
    200 
    201         //{{{ additional rendering nodes
    202         if (options.exist('render')) {
    203                 var meshresults = processmesh(md, data, options);
    204                 var x = meshresults[0];
    205                 var y = meshresults[1];
    206                 var z = meshresults[2];
    207                 var elements = meshresults[3];
    208                 var is2d = meshresults[4];
    209                 var isplanet = meshresults[5];
    210 
    211                 var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]);
    212                 var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]);
    213                 var zlim = options.getfieldvalue('zlim', [ArrayMin(z), ArrayMax(z)]);
    214 
    215                 var global = vec3.length([(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2]) < 6371000/10; //tolerance for global models = center is 637100 meters away from center of earth
    216                 var translation = global ? [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2] : canvas.view.position;
    217 
    218                 var renderObjects = options.getfieldvalue('render',{});
    219 
    220                 for (var renderObject in renderObjects) {
    221                         //Modify renderObejct?
    222                         var object = renderObjects[renderObject];
    223                         object = {
    224                                 enabled: defaultFor(object.enabled, true),                                      //Toggle display of the render object node
    225                                 scale: defaultFor(object.scale, 1),                                                     //Model matrix scaling
    226                                 x: defaultFor(object.x, [0.0, 1.0, 0.0, 0.0, 0.0, 0.0]),        //x coordinate array
    227                                 y: defaultFor(object.y, [0.0, 0.0, 0.0, 1.0, 0.0, 0.0]),        //y coordinate array
    228                                 z: defaultFor(object.z, [0.0, 0.0, 0.0, 0.0, 0.0, 1.0]),        //z coordinate array
    229                                 indices: defaultFor(object.indices, []),                                        //indices array
    230                                 name: defaultFor(object.name, 'NY'),                                            //Text to display for cities.
    231                                 size: defaultFor(object.size, 1),                                                       //Physical size of the object in meters
    232                                 color: defaultFor(object.color, 'black'),                                       //Diffuse color of object
    233                                 height: defaultFor(object.height, 25000),                                       //Height of object along y axis, currently for clouds only
    234                                 range: defaultFor(object.range, 120000),                                        //Range of sz plane to spawn object, currently for clouds only
    235                                 quantity: defaultFor(object.quantity, 15),                                      //Quantity of objects to display, currently for clouds only
    236                                 source: defaultFor(object.source, 'NY'),                                        //Quantity of objects to display, currently for clouds only
    237                                 targets: defaultFor(object.targets, ['NY'])                                     //Quantity of objects to display, currently for clouds only
    238                         };
    239                         if (!object.enabled) { continue; }
    240                         if ('sky' === renderObject && !('sky' in canvas.nodes)) {
    241                                 var mesh = GL.Mesh.icosahedron({size: 6371000 * canvas.atmosphere.scaleHeight, subdivisions: 5});
    242                                 var texture = initTexture(gl, canvas.assetsPath + '/textures/TychoSkymapII_t4_2k.jpg');
    243                                 node = new Node(
    244                                         'canvas', canvas,
    245                                         'options', options,
    246                                         'renderObject', object,
    247                                         'name', 'sky',
    248                                         'shaderName', 'SkyFromSpace',
    249                                         'cullFace', gl.FRONT,
    250                                         'mesh', mesh,
    251                                         'texture',texture,
    252                                         'translation',translation
    253                                 );
    254                         }
    255                         if ('space' === renderObject && !('space' in canvas.nodes)) {
    256                                 var mesh = GL.Mesh.sphere({size: 6371000 * 20});
    257                                 var texture = initTexture(gl, canvas.assetsPath + '/textures/TychoSkymapII_t4_2k.jpg');
    258                                 node = new Node(
    259                                         'canvas', canvas,
    260                                         'options', options,
    261                                         'renderObject', object,
    262                                         'name', 'space',
    263                                         'shaderName', 'Textured',
    264                                         'cullFace', gl.FRONT,
    265                                         'drawOrder', 2,
    266                                         'mesh', mesh,
    267                                         'texture',texture,
    268                                         'translation',translation
    269                                 );
    270                         }
    271                         if ('coastlines' === renderObject) {
    272                                 node = new Node(
    273                                         'canvas', canvas,
    274                                         'options', options,
    275                                         'renderObject', object,
    276                                         'name', 'coastlines',
    277                                         'shaderName', 'Colored',
    278                                         'drawMode', gl.LINE_STRIP,
    279                                         'lineWidth', options.getfieldvalue('linewidth', 1),
    280                                         'scale', [object.scale, object.scale, object.scale],
    281                                         'rotation', [-90, 0, 0]
    282                                 );
    283                                 node.patch('Vertices', [object.x, object.y, object.z], 'FaceColor', 'none');
    284                         }
    285                         if ('graticule' === renderObject && !('graticule' in canvas.nodes)) {
    286                                 node = new Node(
    287                                         'canvas', canvas,
    288                                         'options', options,
    289                                         'renderObject', object,
    290                                         'name', 'graticule',
    291                                         'shaderName', 'Colored',
    292                                         'drawMode', gl.LINE_STRIP,
    293                                         'lineWidth', options.getfieldvalue('linewidth', 1),
    294                                         'scale', [object.scale, object.scale, object.scale],
    295                                         'rotation', [-90, 180, 0]
    296                                 );
    297                                 node.patch('Vertices', [object.x, object.y, object.z], 'FaceColor', 'none');
    298                         }
    299                         if ('cities' === renderObject && !('cities' in canvas.nodes)) {
    300                                 var mesh = GL.Mesh.icosahedron({size: object.size, subdivisions: 1});
    301                                 node = new Node(
    302                                         'canvas', canvas,
    303                                         'options', options,
    304                                         'renderObject', object,
    305                                         'name', 'cities',
    306                                         'shaderName', 'ColoredDiffuse',
    307                                         'diffuseColor', object.color,
    308                                         'lineWidth', options.getfieldvalue('linewidth', 1),
    309                                         'scale', [object.scale, object.scale, object.scale],
    310                                         'rotation', [-90, 0, 0]
    311                                 );
    312                                 node.geometryShader('Mesh', mesh, 'Vertices', [object.x, object.y, object.z], 'Indices', object.indices);
    313                         }
    314                         if ('axis' === renderObject && !('axis' in canvas.nodes)) {
    315                                 node = new Node(
    316                                         'canvas', canvas,
    317                                         'options', options,
    318                                         'renderObject', object,
    319                                         'name', 'axis',
    320                                         'shaderName', 'Colored',
    321                                         'drawMode', gl.LINES,
    322                                         'diffuseColor', [1.0, 0.0, 0.0, 1.0],
    323                                         'lineWidth', options.getfieldvalue('linewidth', 1),
    324                                         'scale', [object.scale, object.scale, object.scale],
    325                                         'rotation', [0, 0, 0]
    326                                 );
    327                                 node.patch('Vertices', [object.x, object.y, object.z], 'FaceColor', 'none');
    328                         }
    329                         if ('city' === renderObject && !vesl.helpers.isEmptyOrUndefined(overlaycanvas)) {
    330                                 //city
    331                                 var mesh = GL.Mesh.sphere({size: object.size});
    332                                 node = new Node(
    333                                         'canvas', canvas,
    334                                         'options', options,
    335                                         'renderObject', object,
    336                                         'name', 'city',
    337                                         'shaderName', 'ColoredDiffuse',
    338                                         'diffuseColor', object.color,
    339                                         'mesh', mesh,
    340                                         'translation', [object.x, object.z, -object.y]
    341                                 );
    342                                 //Attatch new overlay handler to display city name
    343                                 canvas.overlayHandlers['city'] = function(canvas) {
    344                                         var node = canvas.nodes['city'];
    345                                         var object = node.renderObject;
    346                                         var screenPoint = vec3.transformMat4(vec3.create(), node.translation, canvas.camera.vpMatrix);
    347                                         var x = (screenPoint[0] + 1.0) * (canvas.width / 2) + canvas.selector.offset().left;
    348                                         var y = (-screenPoint[1] + 1.0) * (canvas.height / 2) + canvas.selector.offset().top;
    349 
    350                                         ctx.font = 'bold ' + String(options.getfieldvalue('colorbarfontsize', 22))+'px Arial Black, sans-serif';
    351                                         ctx.fillStyle = options.getfieldvalue('colorbarfontcolor','black');
    352                                         ctx.strokeStyle = 'white';
    353                                         ctx.textAlign = 'center';
    354                                         ctx.textBaseline = 'middle';
    355                                         ctx.fillText(object.name, x, y);
    356                                         ctx.strokeText(object.name, x, y);
    357                                 }
    358                         }
    359                         if ('clouds' === renderObject && !('clouds0' in canvas.nodes)) {
    360                                 //clouds
    361                                 var mesh = GL.Mesh.fromURL(canvas.assetsPath + '/obj/cloud.obj');
    362                                 for (var i = 0; i < object.quantity; i++) {
    363                                         //TODO: More options, less magic numbers. Add animation. Better shading.
    364                                         var offset = [randomizeAxis(translation[0], object.range),
    365                                                                                                 randomizeCloudHeight(translation[1], object),
    366                                                                                                 randomizeAxis(translation[2], object.range)];
    367                                         var randomSize = randomizeCloudSize(object.scale);
    368                                         var randomColor = randomizeCloudColor();
    369                                         node = new Node(
    370                                                 'canvas', canvas,
    371                                                 'options', options,
    372                                                 'renderObject', object,
    373                                                 'name', 'clouds' + i,
    374                                                 'shaderName', 'ColoredDiffuse',
    375                                                 'diffuseColor', [randomColor, randomColor, randomColor, 1.0],
    376                                                 'specularColor', [0.1, 0.1, 0.1, 1.0],
    377                                                 'mesh', mesh,
    378                                                 'scale', [randomSize, randomSize, randomSize],
    379                                                 'translation', offset
    380                                         );
    381                                 }
    382                         }
    383                         if ('citylines' === renderObject) {
    384                                 //city
    385                                 node = new Node(
    386                                         'canvas', canvas,
    387                                         'options', options,
    388                                         'renderObject', object,
    389                                         'name', 'citylines',
    390                                         'shaderName', 'ColoredDiffuse',
    391                                         'drawMode', gl.LINES,
    392                                         'diffuseColor', object.color,
    393                                         'lineWidth', options.getfieldvalue('linewidth', 1),
    394                                         'scale', [object.scale, object.scale, object.scale],
    395                                         'rotation', [0, 0, 0]
    396                                 );
    397 
    398                                 //For each target city, calculate the shortest line across the earth by performing a quaternion slerp.
    399                                 //Treat source and target city as vectors to rotate to from the north pole.
    400                                 //Then, slerp between the two rotations, and generate points across equidistance points on the earth to create the line.
    401                                 var north = vec3.fromValues(0, 1, 0);
    402                                 var source = object.source;
    403                                 var sourceXYZ = vec3.fromValues(xcity[source], zcity[source], -ycity[source]);
    404                                 var radius = vec3.length(sourceXYZ);
    405                                 var lineSteps = 50;
    406                                 var lineX = [];
    407                                 var lineY = [];
    408                                 var lineZ = [];
    409                                 var lineXYZ = vec3.create();
    410 
    411                                 for (var i = 0; i < object.targets.length; i++) {
    412                                         var target = object.targets[i];
    413                                         var targetXYZ = vec3.fromValues(xcity[target], zcity[target], -ycity[target]);
    414                                         var axis = vec3.cross(vec3.create(), sourceXYZ, targetXYZ);
    415                                         vec3.normalize(axis, axis);
    416 
    417                                         //Get the total angle between the two cities.
    418                                         var sourceXYZAxis = vec3.normalize(vec3.create(), sourceXYZ);
    419                                         var targetXYZAxis = vec3.normalize(vec3.create(), targetXYZ);
    420                                         var dotProduct = vec3.dot(sourceXYZAxis, targetXYZAxis);
    421                                         var totalAngle = Math.acos(dotProduct); //theta = arccos(u . v / (||u|| * ||v||); in this case, ||u|| and ||v|| are 1, since u and v are unit vectors.
    422 
    423                                         var lineQuat = quat.create();
    424                                         for (var j = 1; j <= lineSteps; j++) {
    425                                                 //Calculate the partial rotation to obtain points on the line between the two cities.
    426                                                 var angle = j / lineSteps * totalAngle;
    427                                                 quat.setAxisAngle(lineQuat, axis, angle);
    428                                                 quat.normalize(lineQuat, lineQuat);
    429                                                 vec3.transformQuat(lineXYZ, sourceXYZ, lineQuat);
    430                                                 //GL.LINES needs 2 points for each line - at the beginning, just use the sourceXYZ.
    431                                                 //TODO: Eliminate this if statement.
    432                                                 if (j === 1) {
    433                                                         lineX.push(sourceXYZ[0]);
    434                                                         lineY.push(sourceXYZ[1]);
    435                                                         lineZ.push(sourceXYZ[2]);
    436                                                 } else {
    437                                                         lineX.push(lineX[lineX.length - 1]);
    438                                                         lineY.push(lineY[lineY.length - 1]);
    439                                                         lineZ.push(lineZ[lineZ.length - 1]);
    440                                                 }
    441                                                 lineX.push(lineXYZ[0]);
    442                                                 lineY.push(lineXYZ[1]);
    443                                                 lineZ.push(lineXYZ[2]);
    444                                         }
    445                                 }
    446                                 node.patch('Vertices', [lineX, lineY, lineZ]);
    447                         }
    448                 }
    449         } //}}}
     230        //{{{ Data marker
     231        // TODO: Default parameters are already being handled by /js/vesl/DataMarker.js::constructor, so perhaps we should be initializing this elsewhere and/or by some other manner   
     232        if (vesl.helpers.isEmptyOrUndefined(canvas.dataMarker)) { // Only define data marker once
     233                let dataMarker                  = {};
     234                let dataMarkerOptions   = options.getfieldvalue('dataMarker', {});
     235               
     236                dataMarker = {
     237                        enabled: defaultFor(dataMarkerOptions.enabled, false)
     238                };
     239               
     240                // Only initialize data marker object if we have enabled data markers for this canvas
     241                if (dataMarker.enabled) {
     242                        dataMarker.object = new vesl.DataMarker(
     243                                {
     244                                        canvas                  : canvas,
     245                                        hasMarker               : defaultFor(dataMarkerOptions.hasMarker, true),
     246                                        markerImgPath   : defaultFor(dataMarkerOptions.markerImgPath, '/canvas/data-markers/data-marker.svg'),
     247                                        hasTooltip              : defaultFor(dataMarkerOptions.hasTooltip, false),
     248                                        tooltipFormat   : defaultFor(dataMarkerOptions.tooltipFormat, ''),
     249                                        tooltipFields   : defaultFor(dataMarkerOptions.tooltipFields, null),
     250                                        width                   : defaultFor(dataMarkerOptions.width, 32),
     251                                        height                  : defaultFor(dataMarkerOptions.height, 32)
     252                                }
     253                        );
     254                }
     255               
     256                canvas.dataMarker = dataMarker;
     257        }
     258        //}}}
     259        //contours
     260        if (options.exist('contourlevels')) {
     261                plot_contour(md,data,options,canvas);
     262        }
    450263} //}}}
    451 
    452 function randomizeCloudHeight(canvasGroundHeight, object) {
    453                 // -+7000 seems a reasonable range
    454                 var maxHeight = object.height + 7000;
    455                 var minHeigth = object.height - 7000;
    456                 var randomHeight = (Math.random() * (maxHeight - minHeigth)) + minHeigth;
    457 
    458                 return canvasGroundHeight + randomHeight;
    459 }
    460 
    461 // assumes that originAxisValue is the mid-value between min and max.
    462 function randomizeAxis(originAxisValue, range) {
    463                 return originAxisValue + (Math.random() - 0.5) * (range * 2);
    464 }
    465 
    466 function randomizeCloudSize(scale) {
    467         var maxResize = 1.3;
    468         var minResize = 0.5;
    469         var randomizationFactor = Math.random() * (maxResize - minResize) + minResize;
    470         return scale * randomizationFactor;
    471 }
    472 
    473 function randomizeCloudColor() {
    474         var lighestColor = 1;
    475         var darkestColor = 0.9;
    476         var randomColor = Math.random() * (lighestColor - darkestColor) + darkestColor;
    477         return randomColor;
    478 }
     264function drawGroundingLines(md, canvas, options, renderObject, lines, colors) { //{{{
     265        let renderObjects = options.getfieldvalue('render',{});
     266        let state = canvas.state;
     267        let scene = state.scene;
     268       
     269        let group = scene.getObjectByName('groundingLines');
     270        if (group !== undefined) {
     271                scene.remove(group); //Remove old group if already exists
     272        }
     273        group = new THREE.Group();
     274        group.name = 'groundingLines';
     275       
     276        //Plot multiple grounding lines, each consisting of multiple polygons.
     277        for (let i = 0; i < lines.length; i++) {
     278                let groundingLine = lines[i]; //of type Proxy (not object or array), thus must iterate without length attribute
     279                let color = processColor(colors[i]);
     280                let x = [];
     281                let y = [];
     282                let z = [];
     283                //In order to show polygons correctly, must convert from line strip to line segments
     284                for (let j in groundingLine) {
     285                        let polygon = groundingLine[j]
     286                        let lineStripX = polygon['x'];
     287                        let lineStripY = polygon['y'];
     288                        let lineStripZ = polygon['z'];
     289                        let lineSegmentsX = [lineStripX[0]];
     290                        let lineSegmentsY = [lineStripY[0]];
     291                        let lineSegmentsZ = [lineStripZ[0]];
     292                        //Must push same coordinates as end of previous segment and beginning of next segment
     293                        for (let k = 1; k < lineStripX.length - 1; k++) {
     294                                lineSegmentsX.push(lineStripX[k], lineStripX[k]);
     295                                lineSegmentsY.push(lineStripY[k], lineStripY[k]);
     296                                lineSegmentsZ.push(lineStripZ[k], lineStripZ[k]);
     297                        }
     298                        //Cap off last coordinate
     299                        lineSegmentsX.push(lineStripX[lineStripX.length - 1]);
     300                        lineSegmentsY.push(lineStripY[lineStripY.length - 1]);
     301                        lineSegmentsZ.push(lineStripZ[lineStripZ.length - 1]);
     302                        //Add polygon coordinates to existing groundingLine
     303                        x = x.concat(lineSegmentsX);
     304                        y = y.concat(lineSegmentsY);
     305                        if (renderObject.followsBed) {
     306                                z = z.concat(lineSegmentsZ);
     307                        } else {
     308                                z = z.concat(NewArrayFill(lineSegmentsX.length, 10 * i));
     309                        }
     310                }
     311                z = ArrayScale(z, options.getfieldvalue('heightscale', 1));
     312                let vertices = [x, y, z];
     313                //console.log('ArrayMin(x):', ArrayMin(x), 'ArrayMax(x):', ArrayMax(x), 'ArrayMin(y):', ArrayMin(y), 'ArrayMax(y):', ArrayMax(y));
     314                       
     315                let node = new Node(
     316                        'canvas', canvas,
     317                        'options', options,
     318                        'renderObject', renderObject,
     319                        'name', 'groundingLine_' + String(i),
     320                        'shaderName', 'lines',
     321                        //'dashed', dashed,
     322                        'depthTest', false,
     323                        'diffuseColor', color,
     324                        'lineWidth', renderObject.lineWidth,
     325                        //'lineWidth', options.getfieldvalue('linewidth', 3),
     326                        'scale', [renderObject.scale, renderObject.scale, renderObject.scale]
     327                );
     328                node.patch('Vertices', vertices, 'group', group, 'ViewReset', false);
     329        }
     330        scene.add(group);
     331        return group;
     332} //}}}
     333function drawText(state, options, textLabels) { //{{{
     334        let camera = state.camera;
     335        let overlayCanvas = state.overlayCanvas;
     336        let ctx = overlayCanvas.getContext('2d');
     337        let widthHalf = overlayCanvas.width / 2
     338        let heightHalf = overlayCanvas.height / 2;
     339       
     340        for (let i = 0; i < textLabels.length; i++) {
     341                let textLabel = textLabels[i];
     342                let position = textLabel.position.clone();
     343                let text = textLabel.text;
     344               
     345                //Project world coordinates to screenspace coordinates
     346                position.project(camera);
     347                let x = (position.x * widthHalf) + widthHalf;
     348                let y = -(position.y * heightHalf) + heightHalf;
     349               
     350                ctx.font = 'bold ' + String(options.getfieldvalue('colorbarfontsize', 22))+'px Arial Black, sans-serif';
     351                ctx.fillStyle = options.getfieldvalue('colorbarfontcolor','black');
     352                ctx.strokeStyle = 'white';
     353                ctx.textAlign = 'center';
     354                ctx.textBaseline = 'middle';
     355                ctx.fillText(text, x, y);
     356                ctx.strokeText(text, x, y);
     357        }
     358} //}}}
     359function processColor(color) { //{{{
     360        //Update the diffuse color with an RGB color name or vec4 containing r, g, b, and opacity values from 0.0 to 1.0
     361        if (typeof color === 'string') {
     362                color = new THREE.Color(color);
     363        } else if (Array.isArray(color)) {
     364                color = new THREE.Color().fromArray(color);
     365        }
     366        return color;
     367} //}}}
  • issm/trunk-jpl/src/m/plot/plot_manager.js

    r21768 r26300  
    1 function plot_manager(md,options,subplotwidth,nlines,ncols,i){ //{{{
     1'use strict';
     2
     3function plot_manager(md, options, subplotwidth, nlines, ncols, i) { //{{{
    24        //PLOT__MANAGER - distribute the plots, called by plotmodel
    35        //
    46        //   Usage:
    5         //      plot_manager(md,options,subplotwidth,i);
     7        //      plot_manager(md, options, subplotwidth, i);
    68        //
    79        //   See also: PLOTMODEL, PLOT_UNIT
     10        let canvas      = document.getElementById(options.getfieldvalue('canvasid'));
     11        let data        = options.getfieldvalue('data'); // Get data to be displayed
     12        let dataresults = null;
     13        let datatype    = 0;
     14        let     data2       = null;
    815                       
    9         //parse options and get a structure of options.
    10         checkplotoptions(md,options);
    11        
    12         //get data to be displayed
    13         var data = options.getfieldvalue('data');
    14         var canvas = initCanvas(options);
    15         var gl = canvas.gl;
    16 
    17         //figure out if this is a special plot
    18         if (typeof data === 'string'){
    19                
    20                 switch(data){
    21 
     16        // Parse options and get a structure of options
     17        checkplotoptions(md, options);
     18
     19        // Figure out if this is a special plot
     20        if (typeof data === 'string') {
     21                switch(data) {
    2222                        case 'boundaries':
    23                                 plot_boundaries(md,options,subplotwidth,i);
    24                                 return;
     23                                plot_boundaries(md, options, subplotwidth, i);
     24                                return;
     25                               
    2526                        case 'BC':
    26                                 plot_BC(md,options,subplotwidth,i,data);
    27                                 return;
     27                                plot_BC(md, options, subplotwidth, i, data);
     28                                return;
     29                               
    2830                        case 'edges':
    29                                 plot_edges(md,options,subplotwidth,i,data);
    30                                 return;
     31                                plot_edges(md, options, subplotwidth, i, data);
     32                                return;
     33                               
    3134                        case 'elementnumbering':
    32                                 plot_elementnumbering(md,options,subplotwidth,i);
    33                                 return;
     35                                plot_elementnumbering(md, options, subplotwidth, i);
     36                                return;
     37                               
    3438                        case 'highlightelements':
    35                                 plot_highlightelements(md,options,subplotwidth,i);
    36                                 return;
     39                                plot_highlightelements(md, options, subplotwidth, i);
     40                                return;
     41                               
    3742                        case 'qmumean':
    38                                 plot_qmumean(md,options,nlines,ncols,i);
    39                                 return;
     43                                plot_qmumean(md, options, nlines, ncols, i);
     44                                return;
     45                               
    4046                        case 'qmustddev':
    41                                 plot_qmustddev(md,options,nlines,ncols,i);
    42                                 return;
     47                                plot_qmustddev(md, options, nlines, ncols, i);
     48                                return;
     49                               
    4350                        case 'qmuhistnorm':
    44                                 plot_qmuhistnorm(md,options,nlines,ncols,i);
    45                                 return;
     51                                plot_qmuhistnorm(md, options, nlines, ncols, i);
     52                                return;
     53                               
    4654                        case 'qmu_mass_flux_segments':
    47                                 plot_qmu_mass_flux_segments(md,options,nlines,ncols,i);
    48                                 return;
     55                                plot_qmu_mass_flux_segments(md, options, nlines, ncols, i);
     56                                return;
     57                               
    4958                        case 'part_hist':
    50                                 plot_parthist(md,options,nlines,ncols,i);
    51                                 return;
     59                                plot_parthist(md, options, nlines, ncols, i);
     60                                return;
     61                               
    5262                        case 'part_hist_n':
    53                                 plot_parthistn(md,options,nlines,ncols,i);
    54                                 return;
     63                                plot_parthistn(md, options, nlines, ncols, i);
     64                                return;
     65                               
    5566                        case 'part_hist_w':
    56                                 plot_parthistw(md,options,nlines,ncols,i);
    57                                 return;
     67                                plot_parthistw(md, options, nlines, ncols, i);
     68                                return;
     69                               
    5870                        case 'elements_type':
    59                                 plot_elementstype(md,options,subplotwidth,i);
    60                                 return;
     71                                plot_elementstype(md, options, subplotwidth, i);
     72                                return;
     73                               
    6174                        case 'vertexnumbering':
    62                                 plot_vertexnumbering(md,options,subplotwidth,i);
    63                                 return;
     75                                plot_vertexnumbering(md, options, subplotwidth, i);
     76                                return;
     77                               
    6478                        case 'highlightvertices':
    65                                 plot_highlightvertices(md,options,subplotwidth,i);
    66                                 return;
     79                                plot_highlightvertices(md, options, subplotwidth, i);
     80                                return;
     81                               
    6782                        case 'basal_drag':
    68                                 plot_basaldrag(md,options,subplotwidth,i,data);
    69                                 return;
     83                                plot_basaldrag(md, options, subplotwidth, i, data);
     84                                return;
     85                               
    7086                        case 'basal_dragx':
    71                                 plot_basaldrag(md,options,subplotwidth,i,data);
    72                                 return;
     87                                plot_basaldrag(md, options, subplotwidth, i, data);
     88                                return;
     89                               
    7390                        case 'basal_dragy':
    74                                 plot_basaldrag(md,options,subplotwidth,i,data);
    75                                 return;
     91                                plot_basaldrag(md, options, subplotwidth, i, data);
     92                                return;
     93                               
    7694                        case 'driving_stress':
    77                                 plot_drivingstress(md,options,subplotwidth,i);
    78                                 return;
     95                                plot_drivingstress(md, options, subplotwidth, i);
     96                                return;
     97                               
    7998                        case 'mesh':
    80                                 plot_mesh(md,options,canvas);
    81                                 return;
     99                                plot_mesh(md, options, canvas);
     100                                return;
     101                               
    82102                        case 'none':
    83                                 //if (!(options.exist('overlay'))){
    84                                 //      plot_none(md,options,nlines,ncols,i);
    85                                 //}
    86                                 return;
     103                                return;
     104                               
    87105                        case 'penalties':
    88                                 plot_penalties(md,options,subplotwidth,i);
    89                                 return;
     106                                plot_penalties(md, options, subplotwidth, i);
     107                                return;
     108                               
    90109                        case 'partition':
    91                                 plot_partition(md,options,nlines,ncols,i);
    92                                 return;
     110                                plot_partition(md, options, nlines, ncols, i);
     111                                return;
     112                               
    93113                        case 'referential':
    94                                 plot_referential(md,options,nlines,ncols,i);
    95                                 return;
     114                                plot_referential(md, options, nlines, ncols, i);
     115                                return;
     116                               
    96117                        case 'riftvel':
    97                                 plot_riftvel(md,options,nlines,ncols,i);
    98                                 return;
     118                                plot_riftvel(md, options, nlines, ncols, i);
     119                                return;
     120                               
    99121                        case 'riftnumbering':
    100                                 plot_riftnumbering(md,options,nlines,ncols,i);
    101                                 return;
     122                                plot_riftnumbering(md, options, nlines, ncols, i);
     123                                return;
     124                               
    102125                        case 'rifts':
    103                                 plot_rifts(md,options,nlines,ncols,i);
    104                                 return;
     126                                plot_rifts(md, options, nlines, ncols, i);
     127                                return;
     128                               
    105129                        case 'riftrelvel':
    106                                 plot_riftrelvel(md,options,nlines,ncols,i);
    107                                 return;
     130                                plot_riftrelvel(md, options, nlines, ncols, i);
     131                                return;
     132                               
    108133                        case 'riftpenetration':
    109                                 plot_riftpenetration(md,options,nlines,ncols,i);
    110                                 return;
     134                                plot_riftpenetration(md, options, nlines, ncols, i);
     135                                return;
     136                               
    111137                        case 'riftfraction':
    112                                 plot_riftfraction(md,options,nlines,ncols,i);
    113                                 return;
     138                                plot_riftfraction(md, options, nlines, ncols, i);
     139                                return;
     140                               
    114141                        case 'sarpwr':
    115                                 plot_sarpwr(md,options,subplotwidth,i);
    116                                 return;
     142                                plot_sarpwr(md, options, subplotwidth, i);
     143                                return;
     144                               
    117145                        case 'time_dependant':
    118                                 plot_vstime(md,options,nlines,ncols,i);
    119                                 return;
     146                                plot_vstime(md, options, nlines, ncols, i);
     147                                return;
     148                               
    120149                        case 'icefront':
    121                                 plot_icefront(md,options,subplotwidth,i,data);
    122                                 return;
     150                                plot_icefront(md, options, subplotwidth, i, data);
     151                                return;
     152                               
    123153                        case 'segments':
    124                                 plot_segments(md,options,subplotwidth,i,data);
    125                                 return;
     154                                plot_segments(md, options, subplotwidth, i, data);
     155                                return;
     156                               
    126157                        case 'quiver':
    127                                 plot_quiver(md,options,canvas);
    128                                 return;
     158                                plot_quiver(md, options, canvas);
     159                                return;
     160                               
    129161                        case 'strainrate_tensor':
    130162                        case 'strainrate':
     
    145177                        case 'deviatoricstress_principalaxis2':
    146178                        case 'deviatoricstress_principalaxis3':
    147                                 plot_tensor(md,options,subplotwidth,i,data);
    148                                 return;
     179                                plot_tensor(md, options, subplotwidth, i, data);
     180                                return;
     181                               
    149182                        case 'thermaltransient_results':
    150                                 plot_thermaltransient_results(md,options,subplotwidth,i);
    151                                 return;
     183                                plot_thermaltransient_results(md, options, subplotwidth, i);
     184                                return;
     185                               
    152186                        case 'transient_movie':
    153                                 plot_transient_movie(md,options,canvas);
    154                                 return;
     187                                plot_transient_movie(md, options, canvas);
     188                                return;
     189                               
    155190                        case 'transient_results':
    156                                 plot_transient_results(md,options,subplotwidth,i);
    157                                 return;
     191                                plot_transient_results(md, options, subplotwidth, i);
     192                                return;
     193                               
    158194                        case 'transient_field':
    159                                 plot_transient_field(md,options,subplotwidth,i);
    160                                 return;
     195                                plot_transient_field(md, options, subplotwidth, i);
     196                                return;
     197                               
    161198                        default:
    162                                 if (data in md){
    163                                         data=md[data];
    164                                 }
    165                                 else{
     199                                if (data in md) {
     200                                        data = md[data];
     201                                } else {
    166202                                        error('plot error message: data provided not supported yet. Type plotdoc for help');
    167203                                }
     
    169205        }
    170206
    171         //Figure out if this is a semi-transparent plot.
    172         if (options.getfieldvalue('overlay','off')=='on'){
    173                 plot_overlay(md,data,options,canvas);
    174         }
    175 
    176         //Figure out if this is a semi-transparent plot.
    177         if (options.exist('googlemaps')){
    178                 plot_googlemaps(md,data,options,nlines,ncols,i);
    179                 return;
    180         }
    181 
    182         //Figure out if this is a semi-transparent plot.
    183         if (options.exist('gridded')){
    184                 plot_gridded(md,data,options,nlines,ncols,i);
    185                 return;
    186         }
    187 
    188         //Figure out if this is a Section plot
    189         if (options.exist('sectionvalue')){
    190                 plot_section(md,data,options,nlines,ncols,i);
     207        // Figure out if this is a semi-transparent plot.
     208        if (options.getfieldvalue('overlay', 'off') === 'on') {
     209                plot_overlay(md, data, options, canvas);
     210                //return;
     211        }
     212
     213        // Figure out if this is a semi-transparent plot.
     214        if (options.exist('googlemaps')) {
     215                plot_googlemaps(md, data, options, nlines, ncols, i);
     216                return;
     217        }
     218
     219        // Figure out if this is a semi-transparent plot.
     220        if (options.exist('gridded')) {
     221                plot_gridded(md, data, options, nlines, ncols, i);
     222                return;
     223        }
     224
     225        // Figure out if this is a Section plot
     226        if (options.exist('sectionvalue')) {
     227                plot_section(md, data, options, nlines, ncols, i);
    191228                return;
    192229        }
    193230
    194231        //Figure out if this is a Profile plot
    195         if (options.exist('profile')){
    196                 plot_profile(md,data,options,nlines,ncols,i);
     232        if (options.exist('profile')) {
     233                plot_profile(md, data, options, nlines, ncols, i);
    197234                return;
    198235        }
    199236       
    200         var     dataresults = processdata(md,data,options);
    201         var     data2 = dataresults[0];
    202         var     datatype = dataresults[1];
     237        dataresults = processdata(md, data, options);
     238        data2      = dataresults[0];
     239        datatype    = dataresults[1];
    203240       
    204         //plot unit
    205         plot_unit(md,data2,datatype,options,canvas);
    206 
    207         applyoptions(md,data2,options,canvas);
     241        // Plot unit
     242        plot_unit(md, data2, datatype, options, canvas);
     243
     244        applyoptions(md, data2, options, canvas);
    208245} //}}}
  • issm/trunk-jpl/src/m/plot/plot_mesh.js

    r22894 r26300  
    77        //   See also: PLOTMODEL, PLOT_MANAGER
    88
    9         // If we already have the overlay and are using caching, short circuit
    10         if ('mesh' in canvas.nodes && options.getfieldvalue('cachenodes', 'off') === 'on') {
    11                 return;
    12         }
    13        
    14         /*
    15                 Local variables
    16         */
    179        //{{{
    1810        //Process data and model
    19         var meshresults = processmesh(md, [], options);
    20         var x = meshresults[0];
    21         var y = meshresults[1];
    22         var z = meshresults[2];
    23         var elements = meshresults[3];
    24         var is2d = meshresults[4];
    25         var isplanet = meshresults[5];
    26                
    27         //Compute coordinates and data range:
    28         var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]);
    29         var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]);
    30         var zlim = options.getfieldvalue('zlim', [ArrayMin(z), ArrayMax(z)]);
    31        
    32         //Handle heightscale
    33         var vertices, scale;
    34         if (md.mesh.classname() !== 'mesh3dsurface') {
    35                 vertices = [x, y, z];
    36                 scale = [1, 1, options.getfieldvalue('heightscale', 1)];
    37         }
    38         else {
    39                 vertices = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskregion',{'enabled':false}));
    40                 scale = [1, 1, 1];
    41         }
     11        let meshresults = processmesh(md, [], options);
     12        meshresults = scaleMesh(md, meshresults, options);
     13        let x = meshresults[0];
     14        let y = meshresults[1];
     15        let z = meshresults[2];
     16        let elements = meshresults[3];
     17        let is2d = meshresults[4];
     18        let isplanet = meshresults[5];
     19        let vertices = meshresults[6];
     20        let scale = meshresults[7];
    4221       
    4322        //Compute gl variables:
    44         var edgecolor = options.getfieldvalue('edgecolor', 'black');
    45         var node = new Node(
     23        let edgecolor = options.getfieldvalue('edgecolor', 'black');
     24        let node = new Node(
    4625                'canvas', canvas,
    4726                'options', options,
     27                'md', md,
    4828                'name', 'mesh',
    49                 'shaderName', 'Colored',
    50                 'alpha', options.getfieldvalue('alpha', 1.0),
    51                 //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]],
    52                 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2],
    53                 'drawMode', canvas.gl.LINES,
    54                 'diffuseColor', edgecolor,
     29                'cullFace', THREE.DoubleSide,
     30                'shaderName', 'lines',
     31                'opacity', options.getfieldvalue('opacity', 1.0),
    5532                'lineWidth', options.getfieldvalue('linewidth', 1),
    56                 'maskEnabled', options.getfieldvalue('innermask','off') == 'on',
    57                 'maskHeight', options.getfieldvalue('innermaskheight', 150.0) / options.getfieldvalue('heightscale', 1),
    58                 'maskColor', options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]),
    59                 'rotation', [-90, 0, 0],
    6033                'scale', scale
    6134        );
    6235        //}}}
    6336        //{{{ node plot
    64         if (elements[0].length==6){ //prisms
    65         }
    66         else if (elements[0].length==4){ //tetras
    67         }
    68         else{ //2D triangular elements
     37        if (elements[0].length === 6) { //prisms
     38                //We can skip bottom and every other side to avoid drawing edges twice.
     39                let abc = elements.map(function(value, index) { return [value[0], value[1], value[2]]; }); //top
     40                // let dfe = elements.map(function(value, index) { return [value[3], value[5], value[4]]; }); //bottom
     41                // let aeb = elements.map(function(value, index) { return [value[0], value[4], value[1]]; }); //1st side upper right
     42                let ade = elements.map(function(value, index) { return [value[0], value[3], value[4]]; }); //1st side lower left
     43                // let bfc = elements.map(function(value, index) { return [value[1], value[5], value[2]]; }); //2nd side upper right
     44                let bef = elements.map(function(value, index) { return [value[1], value[4], value[5]]; }); //2nd side lower left
     45                // let cda = elements.map(function(value, index) { return [value[2], value[3], value[0]]; }); //3rd side upper right
     46                let cfd = elements.map(function(value, index) { return [value[2], value[5], value[3]]; }); //3rd side lower left
     47                let prismElements = abc.concat(ade, bef, cfd);
     48                node.patch('Faces', prismElements, 'Vertices', vertices, 'FaceColor', 'none', 'EdgeColor', edgecolor);
     49        } else if (elements[0].length === 4) { //tetras
     50        // TODO: Implement handling for tetras
     51        } else { // 2D triangular elements
    6952                node.patch('Faces', elements, 'Vertices', vertices, 'FaceColor', 'none', 'EdgeColor', edgecolor);
    7053        }
  • issm/trunk-jpl/src/m/plot/plot_overlay.js

    r22894 r26300  
    1 function plot_overlay(md, data, options, canvas){ //{{{
    2         //PLOT_OVERLAY - Function for plotting a georeferenced image. 
    3         //
    4         //   Usage:
    5         //      plot_overlay(md, data, options, canvas);
    6         //
    7         //   See also: PLOTMODEL, PLOT_MANAGER
     1'use strict';
    82
    9         // If we already have the overlay and are using caching, short circuit
    10         if ('overlay' in canvas.nodes && options.getfieldvalue('cachenodes', 'off') === 'on') {
    11                 return;
     3/**
     4 * Global Function: plotOverlay
     5 *
     6 * Plot a georeferenced image
     7 *
     8 * Dependencies:
     9 *      - /ext/proj4-<version>
     10 *
     11 * See Also:
     12 *      - /js/plotmodel.js
     13 *      - /js/plotmanager.js
     14 */
     15function plot_overlay(md, data, options, canvas) {
     16    let elements        = null;
     17    let meshresults     = null; // results from call to processmesh
     18    let newX            = null; // scaled x-coordinates (array)
     19    let newY            = null; // scaled y-coordinates (array)
     20    let newZ            = null; // scaled z-coordinates (array)
     21    let position        = null; // x-, y-, and z-coordinates of vertex (object)
     22    let renderObject    = null;
     23    let reproject       = false; // default; whether or not to reproject overlay
     24    let result          = null; // First, projection of radar overlay onto mesh; then, projection of overlay onto mesh
     25    let scale           = null; // coordinate scalars (array)
     26        let vertices        = null;
     27    let x               = null; // x-coordinates from results (array)
     28    let xlim            = null; // x-cooridinate limits (array)
     29    let y               = null; // y-coordinates from results (array)
     30    let ylim            = null; // y-cooridinate limits (array)
     31    let z               = null; // z-coordinates from results (array)
     32   
     33        // Process data and model
     34    meshresults = processmesh(md, [], options);
     35        x           = meshresults[0];
     36        y           = meshresults[1];
     37        z           = meshresults[2];
     38        elements    = meshresults[3];
     39       
     40        if (md.mesh.classname().startsWith('mesh2d')) {
     41                if (vesl.helpers.isNaN(md.geometry.surface) || (md.geometry.surface[0] !== undefined && vesl.helpers.isNaN(md.geometry.surface[0]))) {
     42                        md.geometry.surface = NewArrayFill(x.length, 0);
     43                        z = NewArrayFill(x.length, 0);
     44                } else {
     45                        z = md.geometry.surface;
     46                }
    1247        }
    1348       
    14         /*
    15                 Local variables
    16         */
    17         //{{{
    18         //Process data and model
    19         var meshresults = processmesh(md, [], options);
    20         var x = meshresults[0];
    21         var y = meshresults[1];
    22         var z = meshresults[2];
    23         var elements = meshresults[3];
    24         var is2d = meshresults[4];
    25         var isplanet = meshresults[5];
    26         if (md.mesh.classname() !== 'mesh3dsurface') z = md.geometry.surface;
     49        // Compute coordinates and data range
     50        xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]);
     51        ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]);
    2752       
    28         //Compute coordinates and data range:
    29         var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]);
    30         var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]);
    31         var zlim = options.getfieldvalue('zlim', [ArrayMin(md.geometry.surface), ArrayMax(md.geometry.surface)]);
    32        
    33         //Handle radaroverlay
     53        // Handle radaroverlay
    3454        if (md.radaroverlay.outerx) {
    35                 var result = Node.prototype.mergeVertices(x, y, z, elements, md.radaroverlay.outerx, md.radaroverlay.outery, md.radaroverlay.outerheight, md.radaroverlay.outerindex);
    36                 x = result.x;
    37                 y = result.y;
    38                 z = result.z;
    39                 elements = result.elements;
     55                result      = Node.prototype.mergeVertices(x, y, z, elements, md.radaroverlay.outerx, md.radaroverlay.outery, md.radaroverlay.outerheight, md.radaroverlay.outerindex);
     56                x           = result.x;
     57                y           = result.y;
     58                z           = result.z;
     59                elements    = result.elements;
    4060        }
    4161       
    42         //Handle heightscale
    43         var vertices, scale;
    44         if (md.mesh.classname() !== 'mesh3dsurface') {
    45                 vertices = [x, y, z];
    46                 scale = [1, 1, options.getfieldvalue('heightscale', 1)];
    47         }
    48         else {
    49                 vertices = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskregion',{'enabled':false}));
    50                 scale = [1, 1, 1];
     62        // Handle heightscale
     63        renderObject = options.getfieldvalue('render', {});
     64       
     65        if ('overlay' in renderObject && renderObject.overlay.reproject !== undefined) {
     66                reproject = renderObject.overlay.reproject;
    5167        }
    5268       
    53         //Compute gl variables:
    54         var edgecolor = options.getfieldvalue('edgecolor', 'black');
    55         var texture = initTexture(gl, options.getfieldvalue('overlay_image'));
    56         var node = new Node(
     69        if (reproject) {
     70                //NOTE: This is being hardcoded for now, as we want to display Josh's greenland-ice-retreat model on a globe.
     71                // If mesh3dprisims do not need to be displayed on a globe, add an option to the view/render objects to specify the reprojection.
     72                // Currently, we are also hardcoding the reprojection from EPSG:3413 (WGS 84 / NSIDC Sea Ice Polar Stereographic North) to EPSG:4326 (WGS 84, standard 2d spherical projection))
     73                // projection definitions are taken from http://epsg.io/XXXXX.js, where XXXXX is the projection number.
     74                // Can be dynamically taken and retrieved via md.mesh.epsg, but again, hardcoded for efficiency.
     75                proj4.defs("EPSG:3413","+proj=stere +lat_0=90 +lat_ts=70 +lon_0=-45 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs"); // http://epsg.io/3413.js
     76                //Don't need to redefine EPSG:4326, as it is defined by default - however, this is still included just in case.
     77                // proj4.defs("EPSG:4326","+proj=longlat +datum=WGS84 +no_defs"); // http://epsg.io/4326.js
     78                //Create empty copies of XYZ to avoid rescaling md.geomtery.surface in the case that z = md.geomtery.surface
     79                newX = NewArrayFill(x.length, 0);
     80                newY = NewArrayFill(x.length, 0);
     81                newZ = NewArrayFill(x.length, 0);
     82               
     83                for (let i = 0; i < x.length; ++i) {
     84                        result      = proj4('EPSG:3413','EPSG:4326', [x[i], y[i]]);
     85                        position    = vesl.geo.geographicToCartesian(vesl.EARTH_RADIUS + z[i], result[1], result[0], true);
     86                        newX[i]     = position.x;
     87                        newY[i]     = position.y;
     88                        newZ[i]     = position.z;
     89                }
     90               
     91                x           = newX;
     92                y           = newY;
     93                z           = newZ;
     94                vertices    = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskregion',{'enabled':false, 'reproject':reproject}), true);
     95                scale       = [1, 1, 1];
     96    } else {
     97                vertices    = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskregion',{'enabled':false, 'reproject':reproject}), true);
     98                scale       = [1, 1, 1];
     99        }
     100       
     101        // Compute coordinates and data range
     102        xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]);
     103        ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]);
     104       
     105        // Compute GL variables
     106        let texture         = new THREE.TextureLoader().load(options.getfieldvalue('overlay_image'));
     107        let groundEnabled   = false;
     108        let name            = 'overlay';
     109       
     110        if ('ground' in renderObject) {
     111        groundEnabled = renderObject.ground.enabled;
     112    }
     113   
     114        if ('overlay' in renderObject) {
     115        name = renderObject.overlay.name;
     116    }
     117   
     118        let shaderName = groundEnabled ? 'ground' : 'overlay';
     119       
     120        let node = new Node(
    57121                'canvas', canvas,
    58122                'options', options,
    59                 'name', 'overlay',
    60                 'shaderName', 'ground' in options.getfieldvalue('render', {}) ? 'GroundFromSpace' : 'TexturedDiffuse',
    61                 'alpha', options.getfieldvalue('outeralpha', 1.0),
    62                 //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]],
    63                 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2],
    64                 'ambientColor', [0.1, 0.1, 0.1 ,1.0],
    65                 'diffuseColor', [1.0, 1.0, 1.0 ,1.0],
    66                 'specularStrength', 0.0,
    67                 'maskEnabled', options.getfieldvalue('outermask','off') == 'on',
    68                 'maskHeight', options.getfieldvalue('outermaskheight', 150.0),
    69                 'maskColor', options.getfieldvalue('outermaskcolor',[0.0, 0.0, 1.0, 1.0]),
     123                'md', md,
     124                'name', name,
     125                'shaderName', shaderName,
     126                'opacity', options.getfieldvalue('outeropacity', 1.0),
     127                'cullFace', THREE.DoubleSide,
    70128                'texture', texture,
    71                 'rotation', [-90, 0, 0],
    72129                'scale', scale
    73130        );
    74         //}}}
     131        canvas.overlayNode = node;
    75132
    76         var xRange = xlim[1] - xlim[0];
    77         var yRange = ylim[1] - ylim[0];
    78         var coordArray = [new Array(x.length), new Array(x.length)];
     133        let xRange      = xlim[1] - xlim[0];
     134        let yRange      = ylim[1] - ylim[0];
     135        let coordArray = [new Array(x.length), new Array(x.length)];
    79136       
    80         //generate mesh:
    81         if (md.mesh.classname() == 'mesh3dsurface') {
    82                 var xyz, magnitude;
    83                 for(var i = 0; i < x.length; i++){
    84                         xyz = vec3.fromValues(vertices[0][i], vertices[1][i], vertices[2][i]);
    85                         magnitude = vec3.length(xyz);
     137        // Generate mesh
     138        if (reproject || md.mesh.classname().startsWith('mesh3d')) {
     139                let magnitude   = 0;
     140                let xyz         = null;
    86141               
    87                         coordArray[0][i] = Math.atan2(xyz[1], xyz[0]) / (2 * Math.PI) + 0.5;
    88                         coordArray[1][i] = Math.asin(xyz[2] / magnitude) / Math.PI + 0.5;
     142                for (let i = 0; i < x.length; ++i) {
     143                        xyz                 = vec3.fromValues(vertices[0][i], vertices[1][i], vertices[2][i]);
     144                        magnitude           = vec3.length(xyz);
     145               
     146                        coordArray[0][i]    = Math.atan2(xyz[1], xyz[0]) / (2 * Math.PI) + 0.5;
     147                        coordArray[1][i]    = Math.asin(xyz[2] / magnitude) / Math.PI + 0.5;
    89148                }
    90         }
    91         else {
    92                 for(var i = 0; i < x.length; i++){
     149        } else {
     150                for (let i = 0; i < x.length; ++i) {
    93151                        coordArray[0][i] = (vertices[0][i] - xlim[0]) / xRange;
    94152                        coordArray[1][i] = (vertices[1][i] - ylim[0]) / yRange;
    95153                }
    96154        }
     155       
    97156        node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', coordArray, 'FaceColor', 'interp');
    98 } //}}}
     157}
  • issm/trunk-jpl/src/m/plot/plot_quiver.js

    r22894 r26300  
    2121        var is2d = meshresults[4];
    2222        var isplanet = meshresults[5];
    23         if (md.mesh.classname() !== 'mesh3dsurface') z = md.geometry.surface;
     23        if (!md.mesh.classname().startsWith('mesh3d')) {
     24                z = md.geometry.surface;
     25        }
    2426               
    2527        //Compute coordinates and data range:
     
    3537        //Handle heightscale
    3638        var vertices, scale;
    37         if (md.mesh.classname() !== 'mesh3dsurface') {
     39        if (!md.mesh.classname().startsWith('mesh3d')) {
    3840                vertices = [x, y, z];
    3941                scale = [1, 1, options.getfieldvalue('heightscale', 1)];
    4042        }
    4143        else {
    42                 vertices = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskregion',{'enabled':false}));
     44                vertices = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskregion',{'enabled':false}), true);
    4345                scale = [1, 1, 1];
    4446        }
     
    5153                'name', 'quiver',
    5254                'shaderName', 'Colored',
    53                 'alpha', options.getfieldvalue('alpha', 1.0),
     55                'opacity', options.getfieldvalue('opacity', 1.0),
    5456                //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]],
    5557                'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2],
  • issm/trunk-jpl/src/m/plot/plot_transient_movie.js

    r23008 r26300  
    1 function plot_transient_movie(md, options, canvas) {//{{{
    2         /**
    3          * PLOT_TRANSIENT_MOVIE - plot a transient result as a movie
    4          *
    5          * Usage:
    6          *      plot_transient_movie(md, options, canvas);
    7          *
    8          * See also: PLOTMODEL, PLOT_MANAGER
    9          */
     1'use strict';
    102
    11         // Loop over the time steps
    12         let data                = options.getfieldvalue('transient_field_data');
    13         let dataType    = {};
    14         let steps               = new Array(data.length);
    15 
    16         for (let i = 0, numSteps = steps.length; i < numSteps; ++i) {
     3/**
     4 * Global Function: plot_transient_movie
     5 *
     6 * Parameters:
     7 *              options                 - Object containing a number of property/value pairs.
     8 *              animation               - Object containing a number of property/value pairs related to transient solution animation.
     9 *              progressText    - Object containing a number of property/value pairs related to updating the playback slider text on frame change.
     10 *              unit                    - String (default: '') which is appended to the frame index with a single white space before updating #playback-progress-text on frame change.
     11 *              update                  - Boolean (default: true) indicating whether or not to update #playback-progress-text on frame change with the frame index. Set this to 'false' if you would rather manage the update of #playback-progress-text via 'onMovieUpdate' handler (or by some other means).
     12 *
     13 * See Also:
     14 *              - /web/js/plotmodel.js
     15 *              - /web/js/plot_manager.js
     16 *
     17 * TODO:
     18 *              - Update function signature/handling to use ES6 default parameters for 'unit' and 'handling'.
     19 */
     20function plot_transient_movie(md, options, canvas) {
     21        //loop over the time steps
     22        let data = options.getfieldvalue('transient_field_data');
     23        let steps = new Array(data.length);
     24       
     25        for (let i = 0; i < steps.length; i++) {
    1726                steps[i] = i;
    1827        }
    19 
    20         // Calculate caxis
     28       
     29        //calculate caxis
    2130        if (!options.exist('caxis')) {
    22                 let range                       = [Infinity, -Infinity];
    23                 let     dataResults;
    24 
     31                let range = [Infinity, -Infinity];
     32                let dataresults;
    2533                for (let i in steps) {
    26                         dataResults = processdata(md, data[i], options);
    27                         range[0] = Math.min(range[0], ArrayMin(dataResults[1]));
    28                         range[1] = Math.max(range[1], ArrayMax(dataResults[1]));
     34                        dataresults = processdata(md, data[i], options);
     35                        range[0] = Math.min(range[0], ArrayMin(dataresults[1]));
     36                        range[1] = Math.max(range[1], ArrayMax(dataresults[1]));
    2937                }
    30 
    31                 dataType = dataResults[1];
    3238                options.addfielddefault('caxis', range);
    3339        }
     40       
     41        //Create unit node
     42        let dataresults = processdata(md, data[0], options);
     43        let data2 = dataresults[0];
     44        let datatype = dataresults[1];
     45        plot_unit(md, data2, datatype, options, canvas);
     46        let unitOptions = options.getfieldvalue('unitOptions', {'name' : 'unit'});
     47        let unitName    = unitOptions.name;
     48        let node                = canvas.unitNodes[unitName];
     49       
     50        //process data
     51        let processedData = [];
     52        for (let i in steps) {
     53                dataresults = processdata(md, data[i].slice(), options);
     54                processedData[i] = dataresults[0];
     55        }
     56       
     57        //process mesh
     58        let meshresults = processmesh(md, data2, options);
     59        meshresults = scaleMesh(md, meshresults, options);
     60        let x = meshresults[0];
     61        let y = meshresults[1];
     62        let z = meshresults[2];
     63        let elements = meshresults[3];
     64        let is2d = meshresults[4];
     65        let isplanet = meshresults[5];
     66        let vertices = meshresults[6];
     67        let scale = meshresults[7];
     68       
     69        //process options
     70        if (canvas.animation !== undefined && canvas.animation.handler !== undefined) {
     71                clearInterval(canvas.animation.handler);
     72        }
     73        let animation = options.getfieldvalue('animation', {});
     74       
     75        let progressText = null;
     76        if (!vesl.helpers.isEmptyOrUndefined(animation.progressText)) {
     77                progressText = {
     78                                        update  : defaultFor(animation.progressText.update, true),
     79                                        unit    : defaultFor(animation.progressText.unit,       '')
     80                                };
     81        } else {
     82                progressText = {
     83                                        update  : false,
     84                                        unit    : ''
     85                                };
     86        }
     87        canvas.animation = {
     88                frame: defaultFor(animation.frame,                      0),
     89                play: defaultFor(animation.play,                        true),
     90                fps: defaultFor(animation.fps,                          4),
     91                interval: defaultFor(animation.interval,        1000 / defaultFor(animation.fps, 4)),
     92                loop: defaultFor(animation.loop,                        true),
     93                handler:                                                {}, // Initialized below
     94                progressText:                                           progressText
     95        }
     96        //display movie
     97        canvas.unitMovieData = processedData;
     98        canvas.animation.totalFrames = processedData.length;
     99        canvas.animation.frame = 0;
    34100
    35         // Create unit node if it does not already exist
    36         if (!('unit' in canvas.nodes)) {
    37                 let     dataResults = processdata(md, data[0],options);
    38                 let     data2           = dataResults[0];
    39                 let     dataType        = dataResults[1];
    40 
    41                 // Plot unit
    42                 plot_unit(md,data2,dataType,options,canvas);
     101        let slider = null;
     102       
     103        if (!vesl.helpers.isEmptyOrUndefined(canvas.playbackControls)) {
     104                if (!vesl.helpers.isEmptyOrUndefined(canvas.playbackControls.slider)) {
     105                        slider = canvas.playbackControls.slider;
     106                }
     107               
     108               
     109                if (!vesl.helpers.isEmptyOrUndefined(canvas.playbackControls.progressText)) {
     110                        progressText = canvas.playbackControls.progressText;
     111                }
    43112        }
    44 
    45         // Setup rendering node
    46         let node = canvas.nodes.unit;
    47 
    48         node.options    = options;
    49         node.alpha              = options.getfieldvalue('alpha', 1.0);
    50         node.caxis              = options.getfieldvalue('caxis');
    51         node.enabled    = options.getfieldvalue('nodata', 'off') === 'off';
    52         node.log                = options.getfieldvalue('log', false);
    53 
    54         // Process data
    55         let     dataResults;
    56         let processedData = [];
    57 
    58         for (let i in steps) {
    59                 dataResults             = processdata(md, data[i].slice(), options);
    60                 processedData[i]        = dataResults[0];
    61         }
    62 
    63         // Display movie
    64         canvas.unitMovieData            = processedData;
    65         canvas.animation.frame          = 0;
    66         canvas.animation.handler        = setInterval(function () {
     113       
     114        clearInterval(canvas.animation.handler);
     115        canvas.animation.handler = setInterval(function() {
    67116                // Update current animation frame
    68                 let frame               = canvas.animation.frame;
    69                 let numFrames   = steps.length;
    70 
     117                let frame = canvas.animation.frame;
     118               
    71119                if (canvas.animation.play) {
    72                         if (canvas.animation.increment) {
    73                                 if (frame >= numFrames - 1) {
    74                                         if (canvas.animation.loop) {
    75                                                 frame = 0;
    76                                         } else {
    77                                                 toggleMoviePlay(canvas);
    78                                         }
     120                        if (frame >= steps.length - 1) {
     121                                if (canvas.animation.loop) {
     122                                        frame = 0;
    79123                                } else {
    80                                         frame = (frame + 1) % numFrames;
     124                                        canvas.animation.play = !canvas.animation.play;
    81125                                }
     126                        } else {
     127                                frame = (frame + 1) % steps.length;
    82128                        }
    83129                }
    84 
    85                 // If frame has changed, update unit node and data marker display
     130               
     131                //If frame has changed, update unit node and data marker display.
    86132                if (frame !== canvas.animation.lastFrame) {
     133                        canvas.state.dispatchEvent('onMovieUpdate', canvas, frame, node);
     134                       
     135                        //Rescale in case surface has changed
     136                        if (md.mesh.classname() === 'mesh3dsurface' || md.mesh.classname() === 'mesh3dprisms') {
     137                                vertices = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskregion',{'enabled':false, 'reproject':false}), true);
     138                        } else {
     139                                vertices = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskregion',{'enabled':false, 'reproject':false}), true);
     140                                //vertices = [x, y, z];
     141                        }
     142       
     143                        node.updateBuffer('Vertices', vertices);
    87144                        node.updateBuffer('Coords', processedData[frame]);
    88                         canvas.unitData = processedData[frame];
    89 
     145                        canvas.unitData[unitName] = processedData[frame];
    90146                        if (canvas.graph.enabled) {
    91147                                vesl.graph.draw(canvas);
    92148                        }
    93 
    94                         if (!vesl.helpers.isEmptyOrUndefined(canvas.playbackControls.slider)) {
    95                                 canvas.playbackControls.slider.val(frame);
     149                        if (slider != null) {
     150                                slider.val(frame);
    96151                        }
    97 
    98                         if (!vesl.helpers.isEmptyOrUndefined(canvas.playbackControls.progressText)) {
    99                                 canvas.playbackControls.progressText.html(steps[frame].toFixed(0) + ' ' + options.getfieldvalue('movietimeunit', 'yr'));
     152                        if (!vesl.helpers.isEmptyOrUndefined(progressText) && canvas.animation.progressText.update) {
     153                                if (canvas.animation.progressText.unit === '') {
     154                                        progressText.html(steps[frame].toFixed(0));
     155                                } else {
     156                                        progressText.html(steps[frame].toFixed(0) + ' ' + canvas.animation.progressText.unit);
     157                                }
    100158                        }
    101 
    102                         if (!vesl.helpers.isEmptyOrUndefined(canvas.nodes.quiver)) {
    103                                 plot_quiver(md, options, canvas, false);
    104                         }
     159                        //if (!vesl.helpers.isEmptyOrUndefined(canvas.nodes.quiver)) {
     160                        //      plot_quiver(md,options,canvas,false);
     161                        //}
     162                       
    105163                }
    106 
    107                 // Save new frame info
    108                 canvas.animation.lastFrame      = canvas.animation.frame;
    109                 canvas.animation.frame          = frame;
     164               
     165                //Save new frame info.
     166                canvas.animation.lastFrame = canvas.animation.frame;
     167                canvas.animation.frame = frame;
    110168        }, canvas.animation.interval);
    111 
    112         // Update progress bar with new frame info
    113         if (!vesl.helpers.isEmptyOrUndefined(canvas.playbackControls.slider)) {
    114                 canvas.playbackControls.slider.val(canvas.animation.frame);
    115                 canvas.playbackControls.slider.setUpperBound(steps.length - 1);
     169       
     170        //Update progress bar with new frame info.
     171        if (!vesl.helpers.isEmptyOrUndefined(slider)) {
     172                slider.max(steps.length - 1);
     173                slider.val(canvas.animation.frame);
    116174        }
    117 
     175                               
    118176        applyoptions(md, [], options, canvas);
    119 }//}}}
     177}
  • issm/trunk-jpl/src/m/plot/plot_unit.js

    r22894 r26300  
     1'use strict';
     2
    13function plot_unit(md, data, datatype, options, canvas) { //{{{
    24        //PLOT_UNIT - unit plot, display data
     
    68        //
    79        //   See also: PLOTMODEL, PLOT_MANAGER
    8 
    9         var name = 'unit';
    10         if ('unit' in canvas.nodes) {
    11                 if (options.getfieldvalue('clf','on')=='on') {
    12                         for (var node in canvas.nodes) {
    13                                 if (vesl.string.startsWith(node, 'unit')) {
    14                                         delete canvas.octrees[node];
    15                                         delete canvas.nodes[node];
    16                                 }
     10       
     11        //{{{
     12        // Process data and model
     13        let meshresults = processmesh(md, data, options);
     14        meshresults = scaleMesh(md, meshresults, options);
     15        let x = meshresults[0];
     16        let y = meshresults[1];
     17        let z = meshresults[2];
     18        let elements = meshresults[3];
     19        let is2d = meshresults[4];
     20        let isplanet = meshresults[5];
     21        let vertices = meshresults[6];
     22        let scale = meshresults[7];
     23       
     24        //Compute gl variables:
     25        let edgecolor = options.getfieldvalue('edgecolor', [1.0, 1.0, 1.0, 1.0]);
     26        let maskzeros = options.getfieldvalue('maskzeros', {});
     27       
     28        let unitOptions = options.getfieldvalue('unitOptions', {'name' : 'unit'});
     29        let unitName    = unitOptions.name;
     30       
     31        let node = new Node(
     32                'canvas', canvas,
     33                'options', options,
     34                'md', md,
     35                'name', unitName,
     36                'shaderName', 'unit',
     37                'opacity', options.getfieldvalue('opacity', 1.0),
     38                'caxis', options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]),
     39                'cullFace', THREE.FrontSide,
     40                'enabled', options.getfieldvalue('nodata', 'off') === 'off',
     41                'log', options.getfieldvalue('log',false),
     42                'maskObject', options.getfieldvalue('maskregion', {'enabled': false}),
     43                'maskZerosColor', defaultFor(maskzeros.color, [1.0, 1.0, 1.0, 1.0]),
     44                'maskZerosEnabled', defaultFor(maskzeros.enabled, false),
     45                'maskZerosTolerance', defaultFor(maskzeros.tolerance, 1e-3),
     46                'maskZerosZeroValue', defaultFor(maskzeros.zeroValue, 0.5),
     47                'scale', scale
     48        );
     49        //}
     50       
     51        if (vesl.helpers.isEmptyOrUndefined(canvas.unitNodes)) {
     52                canvas.unitNodes = {};
     53        }
     54       
     55        if (vesl.helpers.isEmptyOrUndefined(canvas.unitData)) {
     56                canvas.unitData = {};
     57        }
     58       
     59        // If option 'clf' is on, remove all cached data associated with this unit
     60        if (options.getfieldvalue('clf', 'on') === 'on') {
     61                delete canvas.unitNodes[unitName];
     62                canvas.unitData[unitName] = data;
     63               
     64                for (let i = 0, numUnits = canvas.state.scene.children.length; i < numUnits; ++i) {
     65                        if (canvas.state.scene.children[i].name === unitName) {
     66                                canvas.state.scene.children.splice(i, 1);
     67                                break;
    1768                        }
    1869                }
    19                 else {
    20                         name = 'unit' + Object.keys(canvas.nodes).length;
    21                 }
    22         }
    23 
    24         //{{{ declare variables:
    25         //Process data and model
    26         var meshresults = processmesh(md, data, options);
    27         var x = meshresults[0];
    28         var y = meshresults[1];
    29         var z = meshresults[2];
    30         var elements = meshresults[3];
    31         var is2d = meshresults[4];
    32         var isplanet = meshresults[5];
    33         if (md.mesh.classname() !== 'mesh3dsurface') {
    34                 if (vesl.helpers.isNaN(md.geometry.surface) || (md.geometry.surface[0] !== undefined && vesl.helpers.isNaN(md.geometry.surface[0]))) {
    35                         md.geometry.surface = NewArrayFill(x.length, 0);
    36                 }
    37                 z = md.geometry.surface;
    3870        }
    3971       
    40         //Compute coordinates and data range:
    41         var xlim = options.getfieldvalue('xlim', [ArrayMin(x), ArrayMax(x)]);
    42         var ylim = options.getfieldvalue('ylim', [ArrayMin(y), ArrayMax(y)]);
    43         var zlim = options.getfieldvalue('zlim', [ArrayMin(z), ArrayMax(z)]);
     72        canvas.unitNodes[unitName] = node;
    4473       
    45         //Handle heightscale
    46         var vertices, scale;
    47         if (md.mesh.classname() !== 'mesh3dsurface') {
    48                 vertices = [x, y, z];
    49                 scale = [1, 1, options.getfieldvalue('heightscale', 1)];
    50         }
    51         else {
    52                 vertices = Node.prototype.scaleVertices(md, x, y, z, elements, options.getfieldvalue('heightscale', 1), options.getfieldvalue('maskregion',{'enabled':false}));
    53                 scale = [1, 1, 1];
    54         }
    55 
    56         //Compute gl variables:
    57         var edgecolor = options.getfieldvalue('edgecolor', [1.0, 1.0, 1.0 ,1.0]);
    58         var maskzeros = options.getfieldvalue('maskzeros', {});
    59         var render = options.getfieldvalue('render', {});
    60         var cullFace = ("unit" in render) ? canvas.gl[render.unit.cullFace] : canvas.gl.BACK;
    61         var node = new Node(
    62                 'canvas', canvas,
    63                 'options', options,
    64                 'name', name,
    65                 'shaderName', 'TexturedDiffuse',
    66                 'alpha', options.getfieldvalue('alpha', 1.0),
    67                 'caxis', options.getfieldvalue('caxis',[ArrayMin(data), ArrayMax(data)]),
    68                 'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, (zlim[0] + zlim[1]) / 2],
    69                 'cullFace', cullFace,
    70                 'lightingBias', canvas.view.lightingBias,
    71                 'diffuseColor', edgecolor,
    72                 'specularStrength', 0.0,
    73                 'enabled', options.getfieldvalue('nodata','off') == 'off' || (("unit" in render) && render.unit.enabled),
    74                 'log', options.getfieldvalue('log',false),
    75                 'maskEnabled', options.getfieldvalue('innermask','off') == 'on',
    76                 'maskHeight', options.getfieldvalue('innermaskheight', 150.0) / options.getfieldvalue('heightscale', 1),
    77                 'maskColor', options.getfieldvalue('innermaskcolor',[0.0, 0.0, 1.0, 1.0]),
    78                 'maskObject', options.getfieldvalue('maskregion',{'enabled':false}),
    79                 'maskZerosColor', defaultFor(maskzeros.color,[1.0, 1.0, 1.0, 1.0]),
    80                 'maskZerosEnabled', defaultFor(maskzeros.enabled,false),
    81                 'maskZerosTolerance', defaultFor(maskzeros.tolerance,1e-3),
    82                 'maskZerosZeroValue', defaultFor(maskzeros.zeroValue,0.5),
    83                 'rotation', [-90, 0, 0],
    84                 'scale', ("unit" in render) ? [render.unit.scale, render.unit.scale, render.unit.scale] : scale
    85         );
    86         //}
    87         if (options.getfieldvalue('clf','on')=='on') {
    88                 canvas.unitNode = node;
    89                 canvas.unitData = data;
    90         }
    9174        //}}}
    92         switch(datatype){
     75        switch(datatype) {
    9376                //{{{ element plot
    9477                case 1:
    9578                        //WARNING: NaN are not properly found (NaN != NaN = true)
    96                         pos=ArrayFindNot(data, NaN); //needed for element on water
    97                         if (elements[0].length==6){ //prisms
    98                         }
    99                         else if (elements[0].length==4){ //tetras
    100                         }
    101                         else{ //triangular elements
     79                        let pos = ArrayFindNot(data, NaN); //needed for element on water
     80                       
     81                        if (elements[0].length === 6) { // prisms
     82                                let abc = elements.map(function(value, index) { return [value[0], value[1], value[2]]; }); //top
     83                                let dfe = elements.map(function(value, index) { return [value[3], value[5], value[4]]; }); //bottom
     84                                let aeb = elements.map(function(value, index) { return [value[0], value[4], value[1]]; }); //1st side upper right
     85                                let ade = elements.map(function(value, index) { return [value[0], value[3], value[4]]; }); //1st side lower left
     86                                let bfc = elements.map(function(value, index) { return [value[1], value[5], value[2]]; }); //2nd side upper right
     87                                let bef = elements.map(function(value, index) { return [value[1], value[4], value[5]]; }); //2nd side lower left
     88                                let cda = elements.map(function(value, index) { return [value[2], value[3], value[0]]; }); //3rd side upper right
     89                                let cfd = elements.map(function(value, index) { return [value[2], value[5], value[3]]; }); //3rd side lower left
     90                                let prismElements = abc.concat(dfe, aeb, ade, bfc, bef, cda, cfd);
     91                                node.patch('Faces', prismElements, 'Vertices', vertices, 'FaceVertexCData', data, 'FaceColor', 'flat', 'EdgeColor', edgecolor);
     92                        } else if (elements[0].length === 4) { // tetras
     93                        // TODO: Implement handling for tetras
     94                        } else { // triangular elements
    10295                                node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', data, 'FaceColor', 'flat', 'EdgeColor', edgecolor);
    10396                        }
     97                       
    10498                        break;
    10599                //}}}
    106100                //{{{ node plot
    107101                case 2:
    108                         if (elements[0].length==6){ //prisms
    109                         }
    110                         else if (elements[0].length==4){ //tetras
    111                         }
    112                         else{ //triangular elements     
     102                        if (elements[0].length === 6) { // prisms
     103                                let abc = elements.map(function(value, index) { return [value[0], value[1], value[2]]; }); //top
     104                                let dfe = elements.map(function(value, index) { return [value[3], value[5], value[4]]; }); //bottom
     105                                let aeb = elements.map(function(value, index) { return [value[0], value[4], value[1]]; }); //1st side upper right
     106                                let ade = elements.map(function(value, index) { return [value[0], value[3], value[4]]; }); //1st side lower left
     107                                let bfc = elements.map(function(value, index) { return [value[1], value[5], value[2]]; }); //2nd side upper right
     108                                let bef = elements.map(function(value, index) { return [value[1], value[4], value[5]]; }); //2nd side lower left
     109                                let cda = elements.map(function(value, index) { return [value[2], value[3], value[0]]; }); //3rd side upper right
     110                                let cfd = elements.map(function(value, index) { return [value[2], value[5], value[3]]; }); //3rd side lower left
     111                                let prismElements = abc.concat(dfe, aeb, ade, bfc, bef, cda, cfd);
     112                                node.patch('Faces', prismElements, 'Vertices', vertices, 'FaceVertexCData', data, 'FaceColor', 'interp', 'EdgeColor', edgecolor);
     113                        } else if (elements[0].length === 4) { // tetras
     114                        // TODO: Implement handling for tetras
     115                        } else { // triangular elements
    113116                                node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', data, 'FaceColor', 'interp', 'EdgeColor', edgecolor);
    114117                        }
     118                       
    115119                        break;
    116120                //}}}
    117121                //{{{ quiver plot
    118122                case 3:
    119                         if (is2d){
     123                        if (is2d) {
    120124                                //plot_quiver(x, y, data(:, 1), data(:, 2), options);
    121                         }
    122                         else{
     125                        } else {
    123126                                //plot_quiver3(x, y, z, data(:, 1), data(:, 2), data(:, 3), options);
    124127                        }
     128                       
    125129                        break;
    126130                //}}}
  • issm/trunk-jpl/src/m/plot/plotdoc.js

    r22894 r26300  
    2424        console.log('           "height": height to spawn clouds at (ex: 7500)');
    2525        console.log('           "quantity": quantity of clouds to spawn (ex: 10)');
    26         console.log('       "caxis": modify  colorbar range. (array of type [a, b] where b>=a)');
     26        console.log('       "caxis": modify colorbar range (array of type [a, b] where b>=a)');
    2727        console.log('       "colorbar": add colorbar (default "off", ex: "on", "off")');
    2828        console.log('       "colorbarid": colorbar canvas id (string)');
     
    3939        console.log('       "dataMarker": object cotaining data marker parameters. See webgl.js for defaults. (ex: {"enabled":true,"format":["<div id="sim-plot"></div>"],"labels":["thickness","velocity","value"],"animated":true})');
    4040        console.log('           "enabled": toggle data marker displays (default true, ex: false)');
    41         console.log('           "image": image used for marking the clicked point (ex: "/canvas/data-markers/data-marker.svg")');
    42         console.log('           "labels": when displaying a sim-plot graph, display these model fields. (ex: ["thickness","velocity","value"])');
    43         console.log('           "font": font to be used for display (ex: "24px "Comic Sans MS", cursive")');
    44         console.log('           "format": an array compatible with sprintf that will be displayed as html (ex: ["X: %.2e<br>Y: %.2e<br>Z: %.2e]<br>Value: %0.1f","x","y","z","value"])');
    45         console.log('                   "size": specifiy the width and height of the data markers (default [32,32], ex: [24,32], [105,10])');
     41        console.log('           "hasMarker": whether or not the data marker has a marker (default true, ex: false)');
     42        console.log('           "markerImgPath": path to image to use for marker (default "/canvas/data-markers/data-marker.svg")');
     43        console.log('           "hasTooltip": whether or not the data marker has a tooltip (default false, ex: true)');
     44        console.log('           "tooltipFormat": C-style format string to be used when on calls to vesl.DataMarker.tooltipContent to format passed data points (default "", ex: ["X: %.2e<br>Y: %.2e<br>Z: %.2e])');   
     45        console.log('           "width": width, in pixels, of the data marker (default 32)');   
     46        console.log('           "height": height, in pixels, of the data marker (default 32)');
    4647        console.log('       "displayview": print view value to console (default "off", ex: "on", "off")');
    4748        console.log('       "displayzoom": print zoom value to console (default "off", ex: "on", "off")');
     
    6061        console.log('       "outermask*": Special mask that colors all parts of a overlay mesh below a height a certain color. provide outermaskheight and outermaskcolor options also (default "off", ex: "on", "off")');
    6162        console.log('       "overlay": overlay a radar amplitude image behind (default "off", ex: "on", "off")');
    62         console.log('       "overlay_image": path to overlay image (default "", ex: "./images/radar.png")');
     63        console.log('       "overlay_image": path to overlay image (default "", ex: "./img/radar.png")');
    6364        console.log('       "quiver": add quiver plot overlay for velocities. (default "off", ex: "on", "off")');
    6465        console.log('       "scaling": scaling factor used by quiver plots. Default is 0.4');
    65         console.log('       "alpha": transparency coefficient 0.0 to 1.0, the lower, the more transparent. (default 1.0, ex: 0.5, 0.25)');
     66        console.log('       "opacity": transparency coefficient 0.0 to 1.0, the lower, the more transparent. (default 1.0, ex: 0.5, 0.25)');
    6667        console.log('       "render": a object containing a list of default object to render. (default {}, ex: {"sky", "space"})');
    6768        console.log('           "sky": render the atmosphere. (ex: {"enabled":true})');
  • issm/trunk-jpl/src/m/plot/plotmodel.js

    r22894 r26300  
    1 function plotmodel(md){ //{{{
    2         //Convert arguments to array:
    3         var args = Array.prototype.slice.call(arguments);
     1'use strict';
    42
    5         //First process options
    6         var options = new plotoptions(args.slice(1,args.length));
     3function plotmodel(md) { //{{{
     4        let args            = Array.prototype.slice.call(arguments); // Convert arguments to array
     5    let canvas          = null;
     6    let ncols           = 0;
     7    let nlines          = 0;
     8    let numberofplots   = 0;
     9    let options         = new plotoptions(args.slice(1, args.length)); // Process options
     10    let subplotwidth    = Math.ceil(Math.sqrt(options.numberofplots)); // Get number of subplots
     11   
     12        // Get figure number and number of plots
     13        numberofplots = options.numberofplots;
     14
     15        // If nlines and ncols specified, then bypass.
     16        if (options.list[0].exist('nlines')) {
     17                nlines = options.list[0].getfieldvalue('nlines');
     18        } else {
     19                nlines = Math.ceil(numberofplots / subplotwidth);
     20        }
    721       
    8         //get number of subplots
    9         subplotwidth=Math.ceil(Math.sqrt(options.numberofplots));
    10        
    11         //Get figure number and number of plots
    12         numberofplots=options.numberofplots;
    13 
    14         //if nlines and ncols specified, then bypass.
    15         var nlines,ncols;
    16         if (options.list[0].exist('nlines')){
    17                 nlines=options.list[0].getfieldvalue('nlines');
    18         }
    19         else {
    20                 nlines=Math.ceil(numberofplots/subplotwidth);
    21         }
    2222        if (options.list[0].exist('ncols')){
    23                 ncols=options.list[0].getfieldvalue('ncols');
    24         }
    25         else {
    26                 ncols=subplotwidth;
     23                ncols = options.list[0].getfieldvalue('ncols');
     24        } else {
     25                ncols = subplotwidth;
    2726        }
    2827       
    2928        //check that nlines and ncols were given at the same time!
    30         if ((options.list[0].exist('ncols') & !options.list[0].exist('nlines')) | (options.list[0].exist('nlines') & !options.list[0].exist('ncols'))) throw Error('plotmodel error message: nlines and ncols need to be specified together, or not at all');
     29        if ((options.list[0].exist('ncols') && !options.list[0].exist('nlines'))
     30            || ((options.list[0].exist('nlines') && !options.list[0].exist('ncols')))) {
     31            throw Error('plotmodel error message: nlines and ncols need to be specified together, or not at all');
     32    }
    3133
    32         //go through subplots
    33         if (numberofplots){
    34                 //Reinitialize all canvases
    35                 for (var i=0;i<numberofplots;i++){
    36                         if (options.list[i].getfieldvalue('clf','on')!='off') document.getElementById(options.list[i].getfieldvalue('canvasid')).initialized = false;
     34        // Go through subplots
     35        if (numberofplots) {
     36                // Go through all data plottable and close window if an error occurs
     37
     38                let canvases = [];
     39                for (let i = 0; i < numberofplots; ++i) {
     40                        canvases[i] = document.getElementById(options.list[i].getfieldvalue('canvasid'));
     41                        canvases[i].state.dispatchEvent('onPlotModelStart', canvases[i], options.list[i]);
    3742                }
    38                 //Go through all data plottable and close window if an error occurs
    39                 for (var i=0;i<numberofplots;i++){
    40                         plot_manager(options.list[i].getfieldvalue('model',md),options.list[i],subplotwidth,nlines,ncols,i);
     43                for (let i = 0; i < numberofplots; ++i) {
     44                        canvases[i].state.dispatchEvent('onPlotManagerStart', canvases[i], options.list[i]);
     45                        plot_manager(options.list[i].getfieldvalue('model',md), options.list[i], subplotwidth, nlines, ncols, i);
     46                        canvases[i].state.dispatchEvent('onPlotManagerEnd', canvases[i], options.list[i]);
    4147
    42                         //List all unused options
     48                        // List all unused options
    4349                        options.list[i].displayunused();
     50                }
     51                for (let i = 0; i < numberofplots; ++i) {
     52                        canvases[i].state.dispatchEvent('onPlotModelEnd', canvases[i], options.list[i]);
    4453                }
    4554        }
  • issm/trunk-jpl/src/m/solve/WriteData.js

    r21911 r26300  
    1 function WriteData(fid,prefix){
     1function WriteData(fid,prefix){ //{{{
    22//WRITEDATA - write model field into binary buffer
    33//
     
    7474        }
    7575
     76        let recordlengthtype = 'int';
     77        if (svnversion >= 22708) {
     78                recordlengthtype = 'long long';
     79        }
     80
    7681        //Step 1: write the name to identify this record uniquely
    7782        fid.fwrite(name.length,'int');
     
    8388
    8489                //first write length of record
    85                 fid.fwrite(4+4,'int');  //1 bool (disguised as an int)+code
     90                fid.fwrite(4+4,recordlengthtype);  //1 bool (disguised as an int)+code
    8691
    8792                //write data code:
     
    95100
    96101                //first write length of record
    97                 fid.fwrite(4+4,'int');  //1 integer + code
     102                fid.fwrite(4+4,recordlengthtype);  //1 integer + code
    98103
    99104                //write data code:
     
    107112
    108113                //first write length of record
    109                 fid.fwrite(8+4,'int');  //1 double+code
     114                fid.fwrite(8+4,recordlengthtype);  //1 double+code
    110115
    111116                //write data code:
     
    117122        else if (format == 'String'){ // {{{
    118123                //first write length of record
    119                 fid.fwrite(data.length+4+4,'int');  //string + string size + code
     124                fid.fwrite(data.length+4+4,recordlengthtype);  //string + string size + code
    120125
    121126                //write data code:
     
    141146
    142147                //first write length of record
    143                 fid.fwrite(4+4+8*s[0]*s[1]+4+4,'int');  //2 integers (32 bits) + the double matrix + code + matrix type
     148                fid.fwrite(4+4+8*s[0]*s[1]+4+4,recordlengthtype);  //2 integers (32 bits) + the double matrix + code + matrix type
    144149
    145150                //write data code and matrix type:
     
    167172
    168173                //first write length of record
    169                 fid.fwrite(4+4+8*s[0]*s[1]+4+4,'int');  //2 integers (32 bits) + the double matrix + code + matrix type
     174                fid.fwrite(4+4+8*s[0]*s[1]+4+4,recordlengthtype);  //2 integers (32 bits) + the double matrix + code + matrix type
    170175
    171176                //write data code and matrix type:
     
    197202                var recordlength=4+4+8*s[0]*s[1]+4+4; //2 integers (32 bits) + the double matrix + code + matrix type
    198203                if (recordlength>Math.pow(2,31)) throw Error(sprintf("field '%s' cannot be marshalled because it is larger than 2^31 bytes!",name));
    199                 fid.fwrite(recordlength,'int');
     204                fid.fwrite(recordlength,recordlengthtype);
    200205
    201206                //write data code and matrix type:
     
    224229
    225230                //write length of record
    226                 fid.fwrite(recordlength,'int');
     231                fid.fwrite(recordlength,recordlengthtype);
    227232
    228233                //write data code:
     
    259264
    260265                //write length of record
    261                 fid.fwrite(recordlength,'int');
     266                fid.fwrite(recordlength,recordlengthtype);
    262267
    263268                //write data code:
     
    278283                                        format.toString(),name));
    279284        }
    280 }
    281 
     285} //}}}
    282286function FormatToCode(format){ // {{{
    283287        //This routine takes the format string, and hardcodes it into an integer, which
  • issm/trunk-jpl/src/m/solve/solve.js

    r25955 r26300  
    1 function solve(md, solutionstring) {//{{{
    2 /**
    3  * SOLVE - apply solution sequence for this model
    4  *
    5  *      Usage:
    6  *              solve(md, solutionstring, varargin);
    7  *              where varargin is a list of paired arguments of string OR enums
    8  *
    9  *      solution types available comprise:
    10  *              - 'Stressbalance'               or 'sb'
    11  *              - 'Masstransport'               or 'mt'
    12  *              - 'Thermal'                             or 'th'
    13  *              - 'Steadystate'                 or 'ss'
    14  *              - 'Transient'                   or 'tr'
    15  *              - 'Balancethickness'    or 'mc'
    16  *              - 'Balancevelocity'             or 'bv'
    17  *              - 'BedSlope'                    or 'bsl'
    18  *              - 'SurfaceSlope'                or 'ssl'
    19  *              - 'Hydrology'                   or 'hy'
    20  *              - 'DamageEvolution'             or 'da'
    21  *              - 'Gia'                                 or 'gia'
    22  *              - 'Sealevelchange'              or 'slc'
    23  *
    24  *      extra options:
    25  *              - loadonly              : do not solve, only load results
    26  *              - runtimename           : true or false (default is true), makes name unique
    27  *              - checkconsistency      : 'yes' or 'no' (default is 'yes'), ensures checks on consistency of model
    28  *              - restart                       : directory name (relative to the execution directory) where the restart file is located
    29  *              - successCallback       : callback function to be called on success
    30  *              - errorCallback         : callback function to be called on error
    31  *
    32  *      reporting:
    33  *              With no optional arguments for reporting, progress and error reporting is written to the DOM element with ID 'solve-button'.
    34  *              - solveButtonId         : overrides default solve button ID
    35  *              - callout                       : Callout to report progress/errors to; overrides reporting to solve button
    36  *              - withProgressBar       : reports progress of certain solution stages with a progress bar; will not display if a Callout has not been provided
    37  *
    38  *      Examples:
    39  *              md = solve(md, 'Stressbalance');
    40  *              md = solve(md, 'sb');
    41  */
    42         if (typeof solutionstring !== 'string') {
    43                 throw Error(sprintf("%s\n", "ISSM's solve function only accepts strings for solution sequences. Type help solve to get a list of supported solutions."));
    44         }
    45 
    46         //recover and process solve options
    47         let solutionStringLowerCase = solutionstring.toLowerCase();
    48        
    49         if ((solutionStringLowerCase === 'sb') || (solutionStringLowerCase === 'stressbalance')) {
     1async function solve(md, solutionstring, ...varargin) { //{{{
     2/*
     3SOLVE - apply solution sequence for this model
     4
     5Usage:
     6        solve(md, solutionstring[, ...]);
     7
     8where varargin is a list of paired arguments of string OR enums
     9
     10Solution types available comprise:
     11- 'Stressbalance'                       or 'sb'
     12- 'Masstransport'                       or 'mt'
     13- 'Oceantransport'                      or 'oceant'
     14- 'Thermal'                                     or 'th'
     15- 'Steadystate'                         or 'ss'
     16- 'Transient'                           or 'tr'
     17- 'Balancethickness'            or 'mc'
     18- 'BalancethicknessSoft'        or 'mcsoft'
     19- 'Balancevelocity'                     or 'bv'
     20- 'BedSlope'                            or 'bsl'
     21- 'SurfaceSlope'                        or 'ssl'
     22- 'Hydrology'                           or 'hy'
     23- 'DamageEvolution'                     or 'da'
     24- 'Gia'                                         or 'gia'
     25- 'Love'                                        or 'lv'
     26- 'Esa'                                         or 'esa'
     27- 'Sampling'                            or 'smp'
     28- 'Gmsh'
     29
     30Extra options (these all need to be passed in via the third parameter, which is
     31a rest parameter):
     32- loadonly              : do not solve, only load results
     33- runtimename           : true or false (default is true); makes name unique
     34- checkconsistency      : true or false (default is true); checks consistency of model
     35- restart                       : directory name (relative to the execution directory) where the restart file is located
     36
     37Examples:
     38        md = solve(md, 'Stressbalance');
     39        md = solve(md, 'sb');
     40       
     41NOTE:
     42- We do not strictly need to return md as objects are passed by reference in
     43JavaScript, but we do so to mirror MATLAB and Python APIs.
     44
     45TODO:
     46- Refactor UI reporting structure so we do not have to check if it is defined
     47*/     
     48 
     49/*
     50        // Check that md exists and that it is a model
     51        if (md === null || md === undefined || md.constructor.name !== 'model') {
     52                throw new Error('md needs to be an instance of the model class');
     53        }
     54*/
     55       
     56        if (typeof(solutionstring) !== 'string') {
     57                throw new Error('ISSM\'s solve function only accepts strings for solution sequences. Type help solve to get a list of supported solutions.');
     58        }
     59
     60        // Recover and process solve options
     61        if (vesl.strings.strcmpi(solutionstring, 'sb') || vesl.strings.strcmpi(solutionstring, 'Stressbalance')) {
    5062                solutionstring = 'StressbalanceSolution';
    51         } else if ((solutionStringLowerCase === 'mt') || (solutionStringLowerCase === 'masstransport')) {
     63        } else if (vesl.strings.strcmpi(solutionstring, 'mt') || vesl.strings.strcmpi(solutionstring, 'Masstransport')) {
    5264                solutionstring = 'MasstransportSolution';       
    53         } else if ((solutionStringLowerCase === 'th') || (solutionStringLowerCase === 'thermal')) {
     65        } else if (vesl.strings.strcmpi(solutionstring, 'oceant') || vesl.strings.strcmpi(solutionstring, 'Oceantransport')) {
     66                solutionstring = 'OceantransportSolution';     
     67        } else if (vesl.strings.strcmpi(solutionstring, 'th') || vesl.strings.strcmpi(solutionstring, 'Thermal')) {
    5468                solutionstring = 'ThermalSolution';
    55         } else if ((solutionStringLowerCase === 'st') || (solutionStringLowerCase === 'steadystate')) {
     69        } else if (vesl.strings.strcmpi(solutionstring, 'st') || vesl.strings.strcmpi(solutionstring, 'Steadystate')) {
    5670                solutionstring = 'SteadystateSolution';
    57         } else if ((solutionStringLowerCase === 'tr') || (solutionStringLowerCase === 'transient')) {
     71        } else if (vesl.strings.strcmpi(solutionstring, 'tr') || vesl.strings.strcmpi(solutionstring, 'Transient')) {
    5872                solutionstring = 'TransientSolution';
    59         } else if ((solutionStringLowerCase === 'mc') || (solutionStringLowerCase === 'balancethickness')) {
     73        } else if (vesl.strings.strcmpi(solutionstring, 'mc') || vesl.strings.strcmpi(solutionstring, 'Balancethickness')) {
    6074                solutionstring = 'BalancethicknessSolution';
    61         } else if ((solutionStringLowerCase === 'bv') || (solutionStringLowerCase === 'balancevelocity')) {
     75        } else if (vesl.strings.strcmpi(solutionstring, 'mcsoft') || vesl.strings.strcmpi(solutionstring, 'BalancethicknessSoft')) {
     76                solutionstring = 'BalancethicknessSoftSolution';
     77        } else if (vesl.strings.strcmpi(solutionstring, 'bv') || vesl.strings.strcmpi(solutionstring, 'Balancevelocity')) {
    6278                solutionstring = 'BalancevelocitySolution';
    63         } else if ((solutionStringLowerCase === 'bsl') || (solutionStringLowerCase === 'bedslope')) {
     79        } else if (vesl.strings.strcmpi(solutionstring, 'bsl') || vesl.strings.strcmpi(solutionstring, 'BedSlope')) {
    6480                solutionstring = 'BedSlopeSolution';
    65         } else if ((solutionStringLowerCase === 'ssl') || (solutionStringLowerCase === 'surfaceslope')) {
     81        } else if (vesl.strings.strcmpi(solutionstring, 'ssl') || vesl.strings.strcmpi(solutionstring, 'SurfaceSlope')) {
    6682                solutionstring = 'SurfaceSlopeSolution';
    67         } else if ((solutionStringLowerCase === 'hy') || (solutionStringLowerCase === 'hydrology')) {
     83        } else if (vesl.strings.strcmpi(solutionstring, 'hy') || vesl.strings.strcmpi(solutionstring, 'Hydrology')) {
    6884                solutionstring = 'HydrologySolution';
    69         } else if ((solutionStringLowerCase === 'da') || (solutionStringLowerCase === 'damageevolution')) {
     85        } else if (vesl.strings.strcmpi(solutionstring, 'da') || vesl.strings.strcmpi(solutionstring, 'DamageEvolution')) {
    7086                solutionstring = 'DamageEvolutionSolution';
    71         } else if ((solutionStringLowerCase === 'gia') || (solutionStringLowerCase === 'gia')) {
     87        } else if (vesl.strings.strcmpi(solutionstring, 'gia') || vesl.strings.strcmpi(solutionstring, 'Gia')) {
    7288                solutionstring = 'GiaSolution';
    73         } else if ((solutionStringLowerCase === 'slc') || (solutionStringLowerCase === 'sealevelchange')) {
    74                 solutionstring = 'SealevelriseSolution';
     89        } else if (vesl.strings.strcmpi(solutionstring, 'lv') || vesl.strings.strcmpi(solutionstring, 'Love')) {
     90                solutionstring = 'LoveSolution';
     91        } else if (vesl.strings.strcmpi(solutionstring, 'Esa')) {
     92                solutionstring = 'EsaSolution';
     93        } else if (vesl.strings.strcmpi(solutionstring, 'smp') || vesl.strings.strcmpi(solutionstring, 'Sampling')) {
     94                solutionstring = 'SamplingSolution';
     95        } else if (vesl.strings.strcmpi(solutionstring, 'gmsh')) {
     96                solutionstring = 'GmshSolution';
     97        } else if (vesl.strings.strcmpi(solutionstring, 'gmt')) {
     98                solutionstring = 'GmtSolution';
    7599        } else {
    76                 throw Error(sprintf("%s%s%s\n",'solutionstring ',solutionstring,' not supported!'));
    77         }
    78        
    79         // Process options
    80         let args        = Array.prototype.slice.call(arguments);
    81         let options = new pairoptions(args.slice(2, args.length));
    82         options.addfield('solutionstring', solutionstring);
    83 
    84         // recover some fields
     100                throw new Error('solutionstring ' + solutionstring + ' not supported!');
     101        }
     102        let options = new pairoptions(varargin, 'solutionstring', solutionstring);
     103       
     104        // Recover some fields
    85105        md.priv.solution        = solutionstring;
    86         cluster                         = md.cluster;
    87 
    88         //check model consistency
     106        let cluster             = md.cluster;
     107       
     108        // NOTE: Batch scripts are not currently implemented
     109        let batch = 0;
     110        if (options.getfieldvalue('batch', 'no') === 'yes') {
     111                batch = 1;
     112        }
     113       
     114        // Check model consistency
    89115        if (options.getfieldvalue('checkconsistency', 'yes') === 'yes') {
    90116                if (md.verbose.solution) {
     
    94120                ismodelselfconsistent(md);
    95121        }
    96 
     122       
    97123        // If we are restarting, actually use the provided runtime name:
    98124        restart = options.getfieldvalue('restart', '');
    99125
    100126        // First, build a runtime name that is unique
    101         if (restart === 1 ) {
     127        if (restart === 1) {
    102128                // Leave the runtimename as is
    103129        } else {
    104                 if (!(restart === '')) {
    105                         md.priv.runtimename=restart;
    106                 } else if (options.getfieldvalue('runtimename',true)) {
    107                         let c = new Date().getTime();
    108                         md.priv.runtimename = sprintf('%s-%g', md.miscellaneous.name, c);
     130                if (restart !== '') {
     131                        md.priv.runtimename = restart;
    109132                } else {
    110                         md.priv.runtimename = md.miscellaneous.name;
    111                 }
    112         }
    113 
    114         // If running qmu analysis, some preprocessing of dakota files using models fields needs to be carried out
     133                        if (options.getfieldvalue('runtimename', true)) {
     134                                let c = new Date().getTime();
     135                                md.priv.runtimename = sprintf('%s-%g', md.miscellaneous.name, c);
     136                        } else {
     137                                md.priv.runtimename = md.miscellaneous.name;
     138                        }
     139                }
     140        }
     141
     142        // If running QMU analysis, some preprocessing of Dakota files using model fields needs to be carried out
    115143        if (md.qmu.isdakota) {
    116                 throw Error("solve error message: qmu runs not supported yet!");
    117                 //md.preqmu(options);
    118         }
    119 
     144                throw new Error("QMU not supported yet!");
     145                //md = preqmu(md, options);
     146        }
     147       
    120148        // Do we load results only?
    121149        if (options.getfieldvalue('loadonly', false)){
     
    124152        }
    125153
    126         // Marshall into a binary array (fid) all the fields of model
    127         let fid = marshall(md); // bin file
    128        
    129         //deal with toolkits options:
    130         toolkitsstring = md.toolkits.ToolkitsFile(md.miscellaneous.name + '.toolkits'); // toolkits file
    131 
    132 
    133154        /*
    134                 Set success callback function
    135                
    136                 Default: do nothing if no success callback function requested
     155        Write all input arrays (as opposed to, under MATLAB/Python, input binary
     156        files)
     157       
     158        NOTE: The JavaScript implementation diverges significantly from the
     159                  MATLAB/Python APIs here.
    137160        */
    138         //{{{
    139         function successCallbackDefault() {
    140                 solving = false;
    141         };
    142        
    143         let successCallback = options.getfieldvalue('successCallback', successCallbackDefault);
    144         //}}}
    145        
    146        
    147         /*
    148                 Set error callback function
    149                
    150                 Default: do nothing if no error callback function requested
    151         */
    152         //{{{
    153         function errorCallbackDefault() {
    154                 solving = false;
    155         };
    156        
    157         let errorCallback = options.getfieldvalue('errorCallback', errorCallbackDefault);
    158         //}}}
    159        
    160        
    161         /*
    162                 Set solve button ID
    163                
    164                 Default: update #solve-button element with progress updates
    165         */
    166         //{{{
    167         let solveButtonId = options.getfieldvalue('solveButtonId', '#solve-button');
    168         //}}}
    169        
    170        
    171         /*
    172                 Set Callout
    173         */
    174         //{{{
    175         var callout = {};
    176        
    177         // Default: Callout is an empty object
    178         callout = options.getfieldvalue('callout', {});
    179         //}}}
    180        
    181        
    182         /*
    183                 Set progress bar display boolean
    184                
    185                 Default: no progress bar
    186                
    187                 NOTE: must have supplied a callout for progress bar to display
    188         */
    189         //{{{
    190         let withProgressBar = options.getfieldvalue('withProgressBar', false);
    191         //}}}
    192 
     161        let fid = null; // bin file equivalent
     162        //TODO: FIND A BETTER WAY TO DO THIS! (IE, SYNC UP WRITEDATA AND HAVE A FULL DEMARSHALL/READMODEL IN PYTHON
     163        if (solutionstring === 'GmshSolution') {
     164                //open file for binary writing
     165                fid = new fileptr('mode','w');
     166        } else if (solutionstring === 'GmtSolution') {
     167                //open file for binary writing
     168                fid = new fileptr('mode','w');
     169                let prefix='md.mesh';
     170                WriteData(fid,prefix,'object',md.mesh,'fieldname','lat','format','DoubleMat','mattype',1);
     171                WriteData(fid,prefix,'object',md.mesh,'fieldname','long','format','DoubleMat','mattype',1);
     172        } else {
     173                // Marshall into a binary array (fid) all the fields of model
     174                fid = marshall(md); // bin file
     175        }
     176        let toolkitsstring = md.toolkits.ToolkitsFile(md.miscellaneous.name + '.toolkits'); // toolkits file equivalent
    193177
    194178        if (cluster.classname() === 'local') {//{{{
    195179
    196                 // We are running locally on the machine, using the issm module
     180                // We are running locally on the machine, using the ISSM module
    197181                console.log('running issm locally');
    198182               
    199                 // Call issm
     183                // Call ISSM
    200184                let outputs = issm(fid, toolkitsstring, solutionstring, md.miscellaneous.name);
    201185               
    202                 // Recover output arguments:
     186                // Recover output
    203187                let outputbuffer                = outputs[0];
    204188                let outputbuffersize    = outputs[1];
    205189                       
    206190                // Load results
    207                 md = loadresultsfrombuffer(md, outputbuffer, outputbuffersize);
    208                
    209                 // Call success callback 
    210                 successCallback();
    211 
    212                 return md;
     191                md = loadresultsfrombuffer(md, outputbuffer, outputbuffersize); // TODO: Pass reporting construct to loadresultsfrombuffer
     192               
     193                // Call success callback
     194                if (vesl.helpers.isFunction(vesl.ui.reporting.success_callback)) {
     195                        vesl.ui.reporting.success_callback();
     196                }
    213197        //}}}
    214         } else {//{{{
     198        } else { //{{{
    215199                // We are running somewhere else on a computational server. Send the buffer to that server and retrieve output.
    216200                console.log('running issm remotely');
    217201               
    218                 cluster.UploadAndRun(
     202                await cluster.uploadandrun(
    219203                        md,
    220204                        fid,
     
    223207                        md.miscellaneous.name,
    224208                        md.priv.runtimename,
    225                         successCallback,
    226                         errorCallback,
    227                         solveButtonId,
    228                         callout,
    229                         withProgressBar
    230                 );
    231 
     209                        options
     210                );/*
     211.catch(function(e) {
     212                        if (vesl.helpers.isDefined(vesl.ui) && vesl.helpers.isDefined(vesl.ui.reporting) && vesl.helpers.isFunction(vesl.ui.reporting.error_callback)) {
     213                                vesl.ui.reporting.error_callback(e);
     214                        }
     215                }).catch(function(e) {
     216                        // Handle unexpected errors (source: http://thecodebarbarian.com/async-await-error-handling-in-javascript.html)
     217                        console.log(e);
     218                });
     219                       
     220                if (vesl.helpers.isDefined(vesl.ui) && vesl.helpers.isDefined(vesl.ui.reporting) && vesl.helpers.isFunction(vesl.ui.reporting.success_callback)) {
     221                        vesl.ui.reporting.success_callback(md);
     222                }
     223*/
     224               
     225                // Why is md undefined at vesl.ui.reporting.success_callback(md)? See issm-refactor
     226               
    232227                return md;
    233         }//}}}
    234 }//}}}
    235 
     228        } //}}}
     229} //}}}
Note: See TracChangeset for help on using the changeset viewer.