Changeset 26300
- Timestamp:
- 06/07/21 11:12:48 (4 years ago)
- 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 54 54 for (var a = 0; a < arguments.length; a++) { 55 55 arg = arguments[a]; 56 if (arg instanceof Array ) {56 if (arg instanceof Array || arg instanceof Float64Array) { 57 57 size = arg.length; 58 58 array = arg; … … 64 64 for (var a = 0; a < arguments.length; a++) { 65 65 arg = arguments[a]; 66 if ( arg instanceof Array&& arg.length != size) {66 if ((arg instanceof Array || arg instanceof Float64Array) && arg.length != size) { 67 67 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') { 69 69 throw Error("ArrayAdd error message: arguments provided are not of the type Array or Number!"); 70 70 } … … 75 75 if (a != initial) { 76 76 arg = arguments[a]; 77 if (arg instanceof Array ) {77 if (arg instanceof Array || arg instanceof Float64Array) { 78 78 for(var i = 0; i < result.length; i++){ 79 79 result[i] += arg[i]; 80 80 } 81 } else if (typeof arg != 'number') {81 } else if (typeof arg === 'number') { 82 82 for(var i = 0; i < result.length; i++){ 83 83 result[i] += arg; … … 94 94 for (var a = 0; a < arguments.length; a++) { 95 95 arg = arguments[a]; 96 if (arg instanceof Array ) {96 if (arg instanceof Array || arg instanceof Float64Array) { 97 97 size = arg.length; 98 98 array = arg; … … 104 104 for (var a = 0; a < arguments.length; a++) { 105 105 arg = arguments[a]; 106 if ( arg instanceof Array&& arg.length != size) {106 if ((arg instanceof Array || arg instanceof Float64Array) && arg.length != size) { 107 107 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') { 109 109 throw Error("ArrayAdd error message: arguments provided are not of the type Array or Number!"); 110 110 } … … 115 115 if (a !== initial) { 116 116 arg = arguments[a]; 117 if (arg instanceof Array ) {117 if (arg instanceof Array || arg instanceof Float64Array) { 118 118 for(var i = 0; i < result.length; i++){ 119 119 result[i] -= arg[i]; 120 120 } 121 } else if (typeof arg != 'number') {121 } else if (typeof arg === 'number') { 122 122 for(var i = 0; i < result.length; i++){ 123 123 result[i] -= arg; 124 } 125 } 126 } 127 } 128 return result; 129 } //}}} 130 function 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 } 124 170 } 125 171 } … … 134 180 for (var a = 0; a < arguments.length; a++) { 135 181 arg = arguments[a]; 136 if (arg instanceof Array ) {182 if (arg instanceof Array || arg instanceof Float64Array) { 137 183 size = arg.length; 138 184 array = arg; … … 144 190 for (var a = 0; a < arguments.length; a++) { 145 191 arg = arguments[a]; 146 if ( arg instanceof Array&& arg.length != size) {192 if ((arg instanceof Array || arg instanceof Float64Array) && arg.length != size) { 147 193 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') { 149 195 throw Error("ArrayAdd error message: arguments provided are not of the type Array or Number!"); 150 196 } … … 155 201 if (a !== initial) { 156 202 arg = arguments[a]; 157 if (arg instanceof Array ) {203 if (arg instanceof Array || arg instanceof Float64Array) { 158 204 for(var i = 0; i < result.length; i++){ 159 205 result[i] *= arg[i]; 160 206 } 161 } else if (typeof arg != 'number') {207 } else if (typeof arg === 'number') { 162 208 for(var i = 0; i < result.length; i++){ 163 209 result[i] *= arg; … … 174 220 for (var a = 0; a < arguments.length; a++) { 175 221 arg = arguments[a]; 176 if (arg instanceof Array ) {222 if (arg instanceof Array || arg instanceof Float64Array) { 177 223 size = arg.length; 178 224 array = arg; … … 184 230 for (var a = 0; a < arguments.length; a++) { 185 231 arg = arguments[a]; 186 if ( arg instanceof Array&& arg.length != size) {232 if ((arg instanceof Array || arg instanceof Float64Array) && arg.length != size) { 187 233 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') { 189 235 throw Error("ArrayAdd error message: arguments provided are not of the type Array or Number!"); 190 236 } … … 195 241 if (a !== initial) { 196 242 arg = arguments[a]; 197 if (arg instanceof Array ) {243 if (arg instanceof Array || arg instanceof Float64Array) { 198 244 for(var i = 0; i < result.length; i++){ 199 245 result[i] /= arg[i]; 200 246 } 201 } else if (typeof arg != 'number') {247 } else if (typeof arg === 'number') { 202 248 for(var i = 0; i < result.length; i++){ 203 249 result[i] /= arg; … … 282 328 283 329 } //}}} 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 } //}}}307 330 function ArrayConcat(a, b) { //{{{ 308 331 // Make sure that both typed arrays are of the same type … … 322 345 } //}}} 323 346 function ArrayCol(matrix, cols) { //{{{ 324 var column = [];325 if (cols instanceof Array ) {347 var columns = []; 348 if (cols instanceof Array || cols instanceof Float64Array) { 326 349 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]]); 330 353 } 331 column .push(row);354 columns.push(col); 332 355 } 333 356 334 357 } else if (typeof cols == 'number') { 335 358 for (var i = 0; i < matrix.length; i++){ 336 column .push(matrix[i][cols]);359 columns.push(matrix[i][cols]); 337 360 } 338 361 } else { 339 362 throw new Error("ArrayCol error: cols must be a single integer or an array with 2 integers!"); 340 363 } 341 return column ;364 return columns; 342 365 } //}}} 343 366 function ListToMatrix(list, elementsPerSubArray) { //{{{ … … 445 468 return 0; 446 469 } //}}} 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 470 function 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 } //}}} 565 function 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 } //}}} 592 function 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 } 459 613 } //}}} 460 614 function ArrayRange(lower, upper) { //{{{ … … 515 669 } //}}} 516 670 function 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 } //}}} 677 function 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 } //}}} 684 function 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 } //}}} 716 function 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 } //}}} 730 function 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 } //}}} 743 function 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 } //}}} 756 function 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 } 520 767 return array; 521 768 } //}}} … … 551 798 return arr; 552 799 } //}}} 553 function NewArrayFillIncrement(s ize,start,increment) { //{{{800 function NewArrayFillIncrement(start,size,increment) { //{{{ 554 801 var array=new Array(size); 555 802 … … 559 806 560 807 return array; 808 } //}}} 809 function ones(size) { //{{{ 810 return NewArrayFill(size,1); 811 } //}}} 812 function zeros(size) { //{{{ 813 return NewArrayFill(size,0); 561 814 } //}}} 562 815 function ArrayFind(array,value) { //{{{ … … 611 864 } 612 865 return indices; 866 } //}}} 867 function 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 } 613 892 } //}}} 614 893 function Create2DArray(rows,cols) { //{{{ … … 644 923 645 924 // Handle Array 646 if (obj instanceof Array ) {925 if (obj instanceof Array || arg instanceof Float64Array) { 647 926 copy = []; 648 927 for (var i = 0, len = obj.length; i < len; i++) { -
issm/trunk-jpl/src/m/classes/SMBforcing.js
r21065 r26300 12 12 console.log(sprintf(' surface forcings parameters:')); 13 13 fielddisplay(this,'mass_balance','surface mass balance [m/yr ice eq]'); 14 fielddisplay(this,'steps_per_step', 'number of smb steps per time step'); 14 15 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',' ')); 15 20 } // }}} 16 21 this.defaultoutputs = function(){ // {{{ … … 33 38 } // }}} 34 39 this.checkconsistency = function(md,solution,analyses) { //{{{ 35 40 if (solution=='TransientSolution' && md.transient.issmb == 0) return; 36 41 if(ArrayAnyEqual(ArrayIsMember('MasstransportAnalysis',analyses),1)){ 37 42 checkfield(md,'fieldname','smb.mass_balance','timeseries',1,'NaN',1,'Inf',1); … … 40 45 checkfield(md,'fieldname','smb.mass_balance','size',[md.mesh.numberofvertices,1],'NaN',1,'Inf',1); 41 46 } 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]); 44 50 } // }}} 45 51 this.marshall=function(md,prefix,fid) { //{{{ … … 49 55 WriteData(fid,prefix,'name','md.smb.model','data',1,'format','Integer'); 50 56 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'); 51 59 52 60 //process requested outputs … … 66 74 //properties 67 75 // {{{ 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; 70 80 this.setdefaultparameters(); 71 81 // }}} -
issm/trunk-jpl/src/m/classes/amr.js
r22435 r26300 7 7 //methods 8 8 this.setdefaultparameters = function(){// {{{ 9 10 //hmin and hmax 9 11 this.hmin = 100.; 10 12 this.hmax = 100.e3; 13 14 //fields 11 15 this.fieldname = "Vel"; 12 16 this.err = 3.; 17 18 //keep metric? 13 19 this.keepmetric = 1; 20 21 //control of element lengths 14 22 this.gradation = 1.5; 23 24 //other criterias 15 25 this.groundingline_resolution = 500.; 16 26 this.groundingline_distance = 0; … … 25 35 this.deviatoricerror_groupthreshold = 0; 26 36 this.deviatoricerror_maximum = 0; 37 38 //is restart? This calls femmodel->ReMesh() before first time step. 39 this.restart = 0; 27 40 }// }}} 28 41 this.disp= function(){// {{{ … … 45 58 fielddisplay(this,'deviatoricerror_groupthreshold','maximum group threshold deviatoricstress error permitted'); 46 59 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'); 47 62 }// }}} 48 63 this.classname= function(){// {{{ … … 67 82 checkfield(md,'fieldname','amr.deviatoricerror_groupthreshold','numel',[1],'>=',0,'<=',1,'NaN',1); 68 83 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); 69 85 } // }}} 70 86 this.marshall=function(md,prefix,fid) { //{{{ … … 88 104 WriteData(fid,prefix,'object',this,'fieldname','deviatoricerror_groupthreshold','format','Double'); 89 105 WriteData(fid,prefix,'object',this,'fieldname','deviatoricerror_maximum','format','Double'); 106 WriteData(fid,prefix,'object',this,'fieldname','restart','format','Integer'); 90 107 }//}}} 91 108 this.fix=function() { //{{{ … … 111 128 this.deviatoricerror_groupthreshold = 0.; 112 129 this.deviatoricerror_maximum = 0.; 130 this.restart = 0.; 113 131 114 132 this.setdefaultparameters(); -
issm/trunk-jpl/src/m/classes/balancethickness.js
r21065 r26300 40 40 WriteData(fid,prefix,'object',this,'fieldname','thickening_rate','format','DoubleMat','mattype',1,'scale',1/yts); 41 41 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); 42 45 WriteData(fid,prefix,'object',this,'fieldname','omega','format','DoubleMat','mattype',1); 43 46 … … 53 56 this.thickening_rate = NaN; 54 57 this.stabilization = 0; 58 55 59 this.omega = NaN; 60 this.slopex = NaN; 61 this.slopey = NaN; 56 62 this.setdefaultparameters(); 57 63 //}}} -
issm/trunk-jpl/src/m/classes/calving.js
r24305 r26300 35 35 this.fix=function() { //{{{ 36 36 this.calvingrate=NullFix(this.calvingrate,NaN); 37 this.meltingrate=NullFix(this.meltingrate,NaN); 37 38 }//}}} 38 39 //properties -
issm/trunk-jpl/src/m/classes/constants.js
r20896 r26300 19 19 //the reference temperature for enthalpy model (cf Aschwanden) 20 20 this.referencetemperature=223.15; 21 22 //gravitational constant: 23 this.gravitational_constant = 6.67259e-11; 21 24 }// }}} 22 25 this.disp = function () { //{{{ … … 27 30 fielddisplay(this,'yts','number of seconds in a year [s/yr]'); 28 31 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]'); 29 33 30 34 } //}}} … … 39 43 checkfield(md,'fieldname','constants.yts','>',0,'size',[1,1]); 40 44 checkfield(md,'fieldname','constants.referencetemperature','size',[1,1]); 45 checkfield(md,'fieldname','constants.gravitational_constant','size',[1,1]); 41 46 42 47 } // }}} … … 45 50 WriteData(fid,prefix,'object',this,'fieldname','yts','format','Double'); 46 51 WriteData(fid,prefix,'object',this,'fieldname','referencetemperature','format','Double'); 52 WriteData(fid,prefix,'object',this,'fieldname','gravitational_constant','format','Double'); 47 53 }//}}} 48 54 this.fix=function() { //{{{ … … 50 56 //properties 51 57 // {{{ 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.; 56 63 this.setdefaultparameters(); 57 64 //}}} -
issm/trunk-jpl/src/m/classes/flowequation.js
r25626 r26300 22 22 fielddisplay(this,'isSSA','is the Shelfy-Stream Approximation (SSA) used ?'); 23 23 fielddisplay(this,'isL1L2','is the L1L2 approximation used ?'); 24 fielddisplay(this,'isMLHO','is the M LHO approximation used?');24 fielddisplay(this,'isMLHO','is the Mono-Layer Higher-Order approximation used?'); 25 25 fielddisplay(this,'isHO','is the Higher-Order (HO) approximation used ?'); 26 26 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)'); 27 29 fielddisplay(this,'fe_SSA',"Finite Element for SSA 'P1', 'P1bubble' 'P1bubblecondensed' 'P2'"); 28 30 fielddisplay(this,'fe_HO', "Finite Element for HO 'P1' 'P1bubble' 'P1bubblecondensed' 'P1xP2' 'P2xP1' 'P2'"); … … 60 62 checkfield(md,'fieldname','flowequation.isHO','numel',[1],'values',[0, 1]); 61 63 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); 62 66 checkfield(md,'fieldname','flowequation.fe_SSA','values',['P1','P1bubble','P1bubblecondensed','P2','P2bubble']); 63 67 checkfield(md,'fieldname','flowequation.fe_HO' ,'values',['P1','P1bubble','P1bubblecondensed','P1xP2','P2xP1','P2','P2bubble','P1xP3','P2xP4']); … … 80 84 } 81 85 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]); 84 88 } 85 89 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]); 88 92 } 89 93 else throw Error('Case not supported yet'); 90 94 91 95 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']); 93 97 } 94 98 if(ArrayAnyEqual(ArrayIsMember('StressbalanceSIAAnalysis', analyses),1)){ 95 99 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)){ 97 101 console.log(sprintf("\n !!! Warning: SIA's model is not consistent on ice shelves !!!\n")); 98 102 } … … 107 111 WriteData(fid,prefix,'object',this,'fieldname','isHO','format','Boolean'); 108 112 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'); 109 115 WriteData(fid,prefix,'object',this,'fieldname','fe_SSA','data',this.fe_SSA,'format','String'); 110 116 WriteData(fid,prefix,'object',this,'fieldname','fe_HO','data',this.fe_HO,'format','String'); … … 135 141 this.isHO = 0; 136 142 this.isFS = 0; 143 this.isNitscheBC = 0; 144 this.FSNitscheGamma = 0; 137 145 this.fe_SSA = ''; 138 146 this.fe_HO = ''; -
issm/trunk-jpl/src/m/classes/fourierlove.js
r22383 r26300 11 11 this.setdefaultparameters = function() { // {{{ 12 12 //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; 23 33 } // }}} 24 34 this.disp = function() { // {{{ … … 28 38 fielddisplay(this,'sh_nmin','minimum spherical harmonic degree (default 1)'); 29 39 fielddisplay(this,'g0','adimensioning constant for gravity (default 10) [m/s^2]'); 30 fielddisplay(this,'r0','adimensioning constant for radius (default 637 8*10^3) [m]');40 fielddisplay(this,'r0','adimensioning constant for radius (default 6371*10^3) [m]'); 31 41 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])'); 32 43 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]'); 33 49 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)'); 35 53 36 54 } // }}} 37 55 this.checkconsistency = function(md,solution,analyses) { // {{{ 38 56 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) { 50 81 throw 'Degree 1 not supported for Volumetric Potential forcing. Use sh_min>=2 for this kind of calculation.'; 51 82 } 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 } */ 52 97 } // }}} 53 98 this.marshall = function(md,prefix,fid) { // {{{ … … 60 105 WriteData(fid,prefix,'object',this,'fieldname','r0','format','Double'); 61 106 WriteData(fid,prefix,'object',this,'fieldname','mu0','format','Double'); 107 WriteData(fid,prefix,'object',this,'fieldname','Gravitational_Constant','format','Double'); 62 108 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 63 115 WriteData(fid,prefix,'object',this,'fieldname','love_kernels','format','Boolean'); 64 116 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'); 65 119 66 120 } // }}} 67 121 //properties 68 122 // {{{ 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; 80 142 81 143 //set defaults -
issm/trunk-jpl/src/m/classes/friction.js
r21945 r26300 14 14 fielddisplay(this,'p','p exponent'); 15 15 fielddisplay(this,'q','q exponent'); 16 fielddisplay(this,'effective_pressure','Effective Pressure for the forcing if not coupled [Pa]'); 16 17 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)'); 17 19 } // }}} 18 20 this.extrude = function(md) {//{{{ … … 42 44 return; 43 45 } 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); 48 51 switch (this.coupling) { 49 52 case 0: 50 53 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); 52 55 break; 53 56 case 2: … … 63 66 64 67 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); 67 77 WriteData(fid,prefix,'object',this,'fieldname','p','format','DoubleMat','mattype',2); 68 78 WriteData(fid,prefix,'object',this,'fieldname','q','format','DoubleMat','mattype',2); 69 79 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'); 70 81 switch (this.coupling) { 71 82 case 0: … … 79 90 console.error('not supported yet'); 80 91 } 81 82 83 92 }//}}} 84 93 this.fix=function() { //{{{ … … 86 95 //properties 87 96 //{{{ 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; 93 103 this.setdefaultparameters(); 94 104 //}}} -
issm/trunk-jpl/src/m/classes/geometry.js
r23721 r26300 30 30 31 31 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); 33 33 } 34 34 else{ … … 38 38 for(var i=0;i<md.mesh.numberofvertices;i++){ 39 39 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'); 41 41 break; 42 42 } … … 48 48 } // }}} 49 49 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 } 50 58 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);52 59 WriteData(fid,prefix,'object',this,'fieldname','base','format','DoubleMat','mattype',1); 53 60 WriteData(fid,prefix,'object',this,'fieldname','bed','format','DoubleMat','mattype',1); -
issm/trunk-jpl/src/m/classes/groundingline.js
r24866 r26300 8 8 this.setdefaultparameters = function(){// {{{ 9 9 //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'; 13 13 14 14 }// }}} … … 29 29 checkfield(md,'fieldname','groundingline.melt_interpolation','values',['NoMeltOnPartiallyFloating', 'SubelementMelt1', 'SubelementMelt2', 'FullMeltOnPartiallyFloating']); 30 30 31 if (this.migration !='None' & md.trans.isgroundingline==1 & solution == 'TransientSolution'){31 if (this.migration !='None'){ 32 32 if (isNaN(md.geometry.bed)){ 33 33 md.checkmessage('requesting grounding line migration, but bathymetry is absent!'); 34 34 } 35 35 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){ 37 37 md.checkmessage('base not equal to bed on grounded ice!'); 38 38 break; 39 39 } 40 40 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!'); 42 42 break; 43 43 } -
issm/trunk-jpl/src/m/classes/initialization.js
r21065 r26300 17 17 fielddisplay(this,'pressure','pressure field [Pa]'); 18 18 fielddisplay(this,'temperature','temperature [K]'); 19 fielddisplay(this,'enthalpy','enthalpy [J]'); 19 20 fielddisplay(this,'waterfraction','fraction of water in the ice'); 20 21 fielddisplay(this,'sediment_head','sediment water head of subglacial system [m]'); 21 22 fielddisplay(this,'epl_head','epl water head of subglacial system [m]'); 22 23 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.'); 24 31 25 32 }// }}} … … 51 58 checkfield(md,'fieldname','initialization.vy','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]); 52 59 } 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 } 53 67 if(ArrayAnyEqual(ArrayIsMember('BalancethicknessSolution',analyses),1) & (solution=='BalancethicknessSolution')){ 54 68 checkfield(md,'fieldname','initialization.vx','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]); … … 65 79 } 66 80 } 67 if (ArrayAnyEqual(ArrayIsMember('ThermalAnalysis',analyses),1)){81 if ((ArrayAnyEqual(ArrayIsMember('ThermalAnalysis',analyses),1)) && !strcmp(solution,'TransientSolution') && md.transient.isthermal == 0){ 68 82 checkfield(md,'fieldname','initialization.vx','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]); 69 83 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)){ 81 95 if (md.hydrology.type() == 'hydrologyshreve'){ 82 96 checkfield(md,'fieldname','initialization.watercolumn','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices ,1]); 83 97 } 84 98 } 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)){ 86 117 if (md.hydrology.type() == 'hydrologydc'){ 87 118 checkfield(md,'fieldname','initialization.sediment_head','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices, 1]); 88 119 } 89 120 } 90 if (ArrayAnyEqual(ArrayIsMember('HydrologyDCEfficientAnalysis',analyses),1)){121 if (ArrayAnyEqual(ArrayIsMember('HydrologyDCEfficientAnalysis',analyses),1)){ 91 122 if (md.hydrology.type() == 'hydrologydc'){ 92 123 if (md.hydrology.isefficientlayer==1){ … … 96 127 } 97 128 } 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 } 98 134 } //}}} 99 135 this.marshall=function(md,prefix,fid) { //{{{ … … 105 141 WriteData(fid,prefix,'object',this,'fieldname','vz','format','DoubleMat','mattype',1,'scale',1./yts); 106 142 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); 107 147 WriteData(fid,prefix,'object',this,'fieldname','temperature','format','DoubleMat','mattype',1); 108 148 WriteData(fid,prefix,'object',this,'fieldname','waterfraction','format','DoubleMat','mattype',1); … … 111 151 WriteData(fid,prefix,'object',this,'fieldname','epl_thickness','format','DoubleMat','mattype',1); 112 152 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); 113 156 114 157 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; 122 169 } 123 170 WriteData(fid,prefix,'data',enthalpy,'format','DoubleMat','mattype',1,'name','md.initialization.enthalpy'); … … 136 183 //properties 137 184 // {{{ 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; 149 204 this.setdefaultparameters(); 150 205 -
issm/trunk-jpl/src/m/classes/inversion.js
r22098 r26300 140 140 WriteData(fid,prefix,'object',this,'fieldname','iscontrol','format','Boolean'); 141 141 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); 142 143 if (!this.iscontrol) return; 143 144 WriteData(fid,prefix,'object',this,'fieldname','nsteps','format','Integer'); -
issm/trunk-jpl/src/m/classes/issmsettings.js
r25637 r26300 5 5 6 6 function issmsettings (){ 7 8 9 10 7 //methods 8 this.setdefaultparameters = function(){// {{{ 9 //are we short in memory ? (0 faster but requires more memory) 10 this.lowmem=0; 11 11 12 13 12 //i/o: 13 this.io_gather=1; 14 14 15 16 15 //results frequency by default every step 16 this.output_frequency=1; 17 17 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; 20 20 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; 26 23 27 //upload options: 28 upload_port = 0; 29 30 //throw an error if solver residue exceeds this value31 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; 32 29 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'); 49 52 50 53 51 52 53 54 }// }}} 55 this.classname= function(){// {{{ 56 return "issmsettings"; 54 57 55 56 58 }// }}} 59 this.checkconsistency = function(md,solution,analyses) { // {{{ 57 60 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 //}}} 94 99 } -
issm/trunk-jpl/src/m/classes/levelset.js
r24039 r26300 11 11 this.stabilization = 2; 12 12 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'; 13 18 14 19 }// }}} … … 19 24 fielddisplay(this,'spclevelset','Levelset constraints (NaN means no constraint)'); 20 25 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"'); 21 29 22 30 }// }}} 23 24 25 26 31 this.extrude = function(md) {//{{{ 32 this.spclevelset=project3d(md,'vector',this.spclevelset,'type','node'); 33 return this; 34 }//}}} 27 35 this.classname= function(){// {{{ 28 36 return "levelset"; … … 34 42 checkfield(md,'fieldname','levelset.spclevelset','Inf',1,'timeseries',1); 35 43 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']); 36 47 } //}}} 37 48 this.marshall=function(md,prefix,fid) { //{{{ 49 50 let yts=md.constants.yts; 51 38 52 WriteData(fid,prefix,'object',this,'fieldname','stabilization','format','Integer'); 39 53 WriteData(fid,prefix,'object',this,'fieldname','spclevelset','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); 40 54 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'); 42 58 }//}}} 43 this.fix=function() { //{{{44 this.spclevelset=NullFix(this.spclevelset,NaN);45 }//}}}59 this.fix=function() { //{{{ 60 this.spclevelset=NullFix(this.spclevelset,NaN); 61 }//}}} 46 62 //properties 47 63 // {{{ 48 64 49 65 this.stabilization = 0; 50 this.spclevelset 66 this.spclevelset = NaN; 51 67 this.reinit_frequency = NaN; 68 this.kill_icebergs = 0; 69 this.migration_max = 0.; 70 this.fe = 'P1'; 52 71 53 72 this.setdefaultparameters(); -
issm/trunk-jpl/src/m/classes/mask.js
r24867 r26300 7 7 //properties 8 8 // {{{ 9 this.ocean_levelset 10 this.ice_levelset 9 this.ocean_levelset = NaN; 10 this.ice_levelset = NaN; 11 11 //}}} 12 12 //methods … … 14 14 } // }}} 15 15 this.disp = function () { //{{{ 16 console.log(sprintf(" mask :"));16 console.log(sprintf(" masks:")); 17 17 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'); 20 20 } //}}} 21 21 this.extrude = function(md) {//{{{ … … 28 28 } //}}} 29 29 this.checkconsistency = function(md,solution,analyses){ //{{{ 30 if (solution=='LoveSolution') return; 30 31 31 32 checkfield(md,'fieldname','mask.ocean_levelset','size',[md.mesh.numberofvertices, 1]); … … 46 47 this.fix=function() { //{{{ 47 48 }//}}} 48 49 49 } -
issm/trunk-jpl/src/m/classes/mesh3dprisms.js
r22879 r26300 23 23 24 24 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'); @TODO25 //checkmessage(md,'orphan nodes have been found. Check the mesh outline'); @TODO 26 26 md.checkmessage('orphan nodes have been found. Check the mesh outline'); 27 27 } … … 127 127 } //}}} 128 128 129 //properties (SetAccess=public) 129 //properties 130 // {{{ 130 131 this.x = NaN; 131 132 this.y = NaN; … … 139 140 this.long = NaN; 140 141 this.epsg = 0; 141 142 this.scale_factor = NaN; 142 143 143 144 this.vertexonbase = NaN; … … 161 162 this.extractedvertices = NaN; 162 163 this.extractedelements = NaN; 164 //}}} 163 165 } -
issm/trunk-jpl/src/m/classes/qmu.js
r22098 r26300 12 12 console.log(sprintf(' qmu parameters:')); 13 13 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 /* 15 17 for (var i=0;i<this.variables.length;i++){ 16 18 console.log(sprintf(' variables%s: (arrays of each variable class)',... … … 106 108 this.marshall=function(md,prefix,fid) { //{{{ 107 109 WriteData(fid,prefix,'object',this,'fieldname','isdakota','format','Boolean'); 110 WriteData(fid,prefix,'object',this,'fieldname','output','format','Boolean'); 108 111 if (!this.isdakota){ 109 112 WriteData(fid,prefix,'data',0,'name','md.qmu.mass_flux_segments_present','format','Boolean'); … … 129 132 130 133 this.isdakota = 0; 134 this.output = 0; 131 135 this.variables = [] 132 136 this.responses = []; -
issm/trunk-jpl/src/m/classes/slr.js
r24521 r26300 114 114 } //}}} 115 115 this.marshall=function(md,prefix,fid) { //{{{ 116 116 console.log('WARNING: NOT MARHSALLING SLR FOR NOW.'); 117 return; 117 118 WriteData(fid,prefix,'object',this,'fieldname','deltathickness','format','DoubleMat','mattype',2); 118 119 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 158 158 WriteData(fid,prefix,'object',this,'class','stressbalance','fieldname','referential','format','DoubleMat','mattype',1); 159 159 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 } 167 165 168 166 //process requested outputs -
issm/trunk-jpl/src/m/classes/thermal.js
r24140 r26300 64 64 return "thermal"; 65 65 }// }}} 66 67 68 69 70 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); 71 71 // impose observed temperature on surface 72 72 for (var i=0,posIndex=0,count=0;i<md.initialization.temperature.length;i++){ … … 89 89 // } 90 90 // } 91 91 } 92 92 93 94 93 return this; 94 }//}}} 95 95 this.checkconsistency = function(md,solution,analyses){ // {{{ 96 96 … … 104 104 checkfield(md,'fieldname','thermal.isdrainicecolumn','numel',[1],'values',[0, 1]); 105 105 checkfield(md,'fieldname','thermal.watercolumn_upperlimit','>=',0); 106 106 107 107 for(var i=0;i<md.mesh.numberofvertices;i++){ 108 108 for(var j=0;j<md.thermal.spctemperature[0].length;j++){ … … 123 123 md.checkmessage('for a steadystate computation, thermal.reltol (relative convergence criterion) must be defined!'); 124 124 } 125 checkfield(md,'fieldname','thermal.reltol','>',0.,'message','reltol must be larger than zero'); 125 126 } 126 checkfield(md,'fieldname','thermal.reltol','>',0.,'message','reltol must be larger than zero');127 127 } 128 128 checkfield(md,'fieldname','thermal.requested_outputs','stringrow',1); … … 163 163 //properties 164 164 // {{{ 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 = []; 179 178 180 179 this.setdefaultparameters(); -
issm/trunk-jpl/src/m/classes/timestepping.js
r26195 r26300 6 6 function timestepping (){ 7 7 //methods 8 this.setdefaultparameters = function(){ //{{{8 this.setdefaultparameters = function(){ //{{{ 9 9 //time between 2 time steps 10 10 this.time_step=1./2.; … … 14 14 15 15 //should we interpolate forcings between timesteps? 16 this.interp_forcing s=1;16 this.interp_forcing=1; 17 17 this.cycle_forcing=0; 18 } //}}}19 this.disp= function(){ //{{{18 } //}}} 19 this.disp= function(){ //{{{ 20 20 21 21 var unit; … … 25 25 fielddisplay(this,'final_time','final time to stop the simulation ['+ unit + ']'); 26 26 fielddisplay(this,'time_step','length of time steps [' +unit+ ']'); 27 fielddisplay(this,'interp_forcing s','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)'); 28 28 fielddisplay(this,'cycle_forcing','cycle through forcing ? (0 or 1)'); 29 29 fielddisplay(this,'coupling_time','length of coupling time steps with ocean model [' +unit+ ']'); 30 30 31 } //}}}32 this.classname= function(){ //{{{31 } //}}} 32 this.classname= function(){ //{{{ 33 33 return "timestepping"; 34 34 35 } //}}}35 } //}}} 36 36 this.checkconsistency = function(md,solution,analyses) { //{{{ 37 37 … … 39 39 checkfield(md,'fieldname','timestepping.final_time','numel',[1],'NaN',1,'Inf',1); 40 40 checkfield(md,'fieldname','timestepping.time_step','numel',[1],'>=',0,'NaN',1,'Inf',1); 41 checkfield(md,'fieldname','timestepping.interp_forcing s','numel',[1],'values',[0,1]);41 checkfield(md,'fieldname','timestepping.interp_forcing','numel',[1],'values',[0,1]); 42 42 checkfield(md,'fieldname','timestepping.cycle_forcing','numel',[1],'values',[0,1]); 43 43 checkfield(md,'fieldname','timestepping.coupling_time','numel',[1],'>=',0,'NaN',1,'Inf',1); 44 44 if (this.final_time-this.start_time<0){ 45 45 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); 46 50 } 47 51 } // }}} … … 55 59 WriteData(fid,prefix,'object',this,'fieldname','final_time','format','Double','scale',scale); 56 60 WriteData(fid,prefix,'object',this,'fieldname','time_step','format','Double','scale',scale); 57 WriteData(fid,prefix,'object',this,'fieldname','interp_forcing s','format','Boolean');61 WriteData(fid,prefix,'object',this,'fieldname','interp_forcing','format','Boolean'); 58 62 WriteData(fid,prefix,'object',this,'fieldname','cycle_forcing','format','Boolean'); 59 63 WriteData(fid,prefix,'object',this,'fieldname','coupling_time','format','Double','scale',scale); … … 67 71 this.final_time = 0.; 68 72 this.time_step = 0.; 69 this.interp_forcing s= 1;70 this.cycle_forcing = 0;73 this.interp_forcing = 1; 74 this.cycle_forcing = 1; 71 75 this.coupling_time = 0.; 72 76 -
issm/trunk-jpl/src/m/classes/trans.js
r22718 r26300 79 79 WriteData(fid,prefix,'object',this,'fieldname','issmb','format','Boolean'); 80 80 WriteData(fid,prefix,'object',this,'fieldname','ismasstransport','format','Boolean'); 81 WriteData(fid,prefix,'object',this,'fieldname','isoceantransport','format','Boolean'); 81 82 WriteData(fid,prefix,'object',this,'fieldname','isstressbalance','format','Boolean'); 82 83 WriteData(fid,prefix,'object',this,'fieldname','isthermal','format','Boolean'); 83 84 WriteData(fid,prefix,'object',this,'fieldname','isgroundingline','format','Boolean'); 84 WriteData(fid,prefix,'object',this,'fieldname','isgia','format','Boolean');85 85 WriteData(fid,prefix,'object',this,'fieldname','isesa','format','Boolean'); 86 86 WriteData(fid,prefix,'object',this,'fieldname','isdamageevolution','format','Boolean'); 87 87 WriteData(fid,prefix,'object',this,'fieldname','ishydrology','format','Boolean'); 88 88 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'); 90 91 WriteData(fid,prefix,'object',this,'fieldname','isoceancoupling','format','Boolean'); 91 WriteData(fid,prefix,'object',this,'fieldname','iscoupler','format','Boolean');92 92 WriteData(fid,prefix,'object',this,'fieldname','amr_frequency','format','Integer'); 93 93 -
issm/trunk-jpl/src/m/plot/applyoptions.js
r23051 r26300 1 function applyoptions(md, data, options, canvas){ //{{{ 1 'use strict'; 2 3 function applyoptions(md, data, options, canvas) { 2 4 //APPLYOPTIONS - apply colobar, text, cloud, and expdisp options to current plot 3 5 // … … 8 10 9 11 //{{{ 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)'); 35 183 } 36 184 } 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; 105 227 } 106 228 } //}}} 107 //{{{ texture canvas108 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 }149 229 //}}} 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 } 450 263 } //}}} 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 } 264 function 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 } //}}} 333 function 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 } //}}} 359 function 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 3 function plot_manager(md, options, subplotwidth, nlines, ncols, i) { //{{{ 2 4 //PLOT__MANAGER - distribute the plots, called by plotmodel 3 5 // 4 6 // Usage: 5 // plot_manager(md, options,subplotwidth,i);7 // plot_manager(md, options, subplotwidth, i); 6 8 // 7 9 // 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; 8 15 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) { 22 22 case 'boundaries': 23 plot_boundaries(md,options,subplotwidth,i); 24 return; 23 plot_boundaries(md, options, subplotwidth, i); 24 return; 25 25 26 case 'BC': 26 plot_BC(md,options,subplotwidth,i,data); 27 return; 27 plot_BC(md, options, subplotwidth, i, data); 28 return; 29 28 30 case 'edges': 29 plot_edges(md,options,subplotwidth,i,data); 30 return; 31 plot_edges(md, options, subplotwidth, i, data); 32 return; 33 31 34 case 'elementnumbering': 32 plot_elementnumbering(md,options,subplotwidth,i); 33 return; 35 plot_elementnumbering(md, options, subplotwidth, i); 36 return; 37 34 38 case 'highlightelements': 35 plot_highlightelements(md,options,subplotwidth,i); 36 return; 39 plot_highlightelements(md, options, subplotwidth, i); 40 return; 41 37 42 case 'qmumean': 38 plot_qmumean(md,options,nlines,ncols,i); 39 return; 43 plot_qmumean(md, options, nlines, ncols, i); 44 return; 45 40 46 case 'qmustddev': 41 plot_qmustddev(md,options,nlines,ncols,i); 42 return; 47 plot_qmustddev(md, options, nlines, ncols, i); 48 return; 49 43 50 case 'qmuhistnorm': 44 plot_qmuhistnorm(md,options,nlines,ncols,i); 45 return; 51 plot_qmuhistnorm(md, options, nlines, ncols, i); 52 return; 53 46 54 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 49 58 case 'part_hist': 50 plot_parthist(md,options,nlines,ncols,i); 51 return; 59 plot_parthist(md, options, nlines, ncols, i); 60 return; 61 52 62 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 55 66 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 58 70 case 'elements_type': 59 plot_elementstype(md,options,subplotwidth,i); 60 return; 71 plot_elementstype(md, options, subplotwidth, i); 72 return; 73 61 74 case 'vertexnumbering': 62 plot_vertexnumbering(md,options,subplotwidth,i); 63 return; 75 plot_vertexnumbering(md, options, subplotwidth, i); 76 return; 77 64 78 case 'highlightvertices': 65 plot_highlightvertices(md,options,subplotwidth,i); 66 return; 79 plot_highlightvertices(md, options, subplotwidth, i); 80 return; 81 67 82 case 'basal_drag': 68 plot_basaldrag(md,options,subplotwidth,i,data); 69 return; 83 plot_basaldrag(md, options, subplotwidth, i, data); 84 return; 85 70 86 case 'basal_dragx': 71 plot_basaldrag(md,options,subplotwidth,i,data); 72 return; 87 plot_basaldrag(md, options, subplotwidth, i, data); 88 return; 89 73 90 case 'basal_dragy': 74 plot_basaldrag(md,options,subplotwidth,i,data); 75 return; 91 plot_basaldrag(md, options, subplotwidth, i, data); 92 return; 93 76 94 case 'driving_stress': 77 plot_drivingstress(md,options,subplotwidth,i); 78 return; 95 plot_drivingstress(md, options, subplotwidth, i); 96 return; 97 79 98 case 'mesh': 80 plot_mesh(md,options,canvas); 81 return; 99 plot_mesh(md, options, canvas); 100 return; 101 82 102 case 'none': 83 //if (!(options.exist('overlay'))){ 84 // plot_none(md,options,nlines,ncols,i); 85 //} 86 return; 103 return; 104 87 105 case 'penalties': 88 plot_penalties(md,options,subplotwidth,i); 89 return; 106 plot_penalties(md, options, subplotwidth, i); 107 return; 108 90 109 case 'partition': 91 plot_partition(md,options,nlines,ncols,i); 92 return; 110 plot_partition(md, options, nlines, ncols, i); 111 return; 112 93 113 case 'referential': 94 plot_referential(md,options,nlines,ncols,i); 95 return; 114 plot_referential(md, options, nlines, ncols, i); 115 return; 116 96 117 case 'riftvel': 97 plot_riftvel(md,options,nlines,ncols,i); 98 return; 118 plot_riftvel(md, options, nlines, ncols, i); 119 return; 120 99 121 case 'riftnumbering': 100 plot_riftnumbering(md,options,nlines,ncols,i); 101 return; 122 plot_riftnumbering(md, options, nlines, ncols, i); 123 return; 124 102 125 case 'rifts': 103 plot_rifts(md,options,nlines,ncols,i); 104 return; 126 plot_rifts(md, options, nlines, ncols, i); 127 return; 128 105 129 case 'riftrelvel': 106 plot_riftrelvel(md,options,nlines,ncols,i); 107 return; 130 plot_riftrelvel(md, options, nlines, ncols, i); 131 return; 132 108 133 case 'riftpenetration': 109 plot_riftpenetration(md,options,nlines,ncols,i); 110 return; 134 plot_riftpenetration(md, options, nlines, ncols, i); 135 return; 136 111 137 case 'riftfraction': 112 plot_riftfraction(md,options,nlines,ncols,i); 113 return; 138 plot_riftfraction(md, options, nlines, ncols, i); 139 return; 140 114 141 case 'sarpwr': 115 plot_sarpwr(md,options,subplotwidth,i); 116 return; 142 plot_sarpwr(md, options, subplotwidth, i); 143 return; 144 117 145 case 'time_dependant': 118 plot_vstime(md,options,nlines,ncols,i); 119 return; 146 plot_vstime(md, options, nlines, ncols, i); 147 return; 148 120 149 case 'icefront': 121 plot_icefront(md,options,subplotwidth,i,data); 122 return; 150 plot_icefront(md, options, subplotwidth, i, data); 151 return; 152 123 153 case 'segments': 124 plot_segments(md,options,subplotwidth,i,data); 125 return; 154 plot_segments(md, options, subplotwidth, i, data); 155 return; 156 126 157 case 'quiver': 127 plot_quiver(md,options,canvas); 128 return; 158 plot_quiver(md, options, canvas); 159 return; 160 129 161 case 'strainrate_tensor': 130 162 case 'strainrate': … … 145 177 case 'deviatoricstress_principalaxis2': 146 178 case 'deviatoricstress_principalaxis3': 147 plot_tensor(md,options,subplotwidth,i,data); 148 return; 179 plot_tensor(md, options, subplotwidth, i, data); 180 return; 181 149 182 case 'thermaltransient_results': 150 plot_thermaltransient_results(md,options,subplotwidth,i); 151 return; 183 plot_thermaltransient_results(md, options, subplotwidth, i); 184 return; 185 152 186 case 'transient_movie': 153 plot_transient_movie(md,options,canvas); 154 return; 187 plot_transient_movie(md, options, canvas); 188 return; 189 155 190 case 'transient_results': 156 plot_transient_results(md,options,subplotwidth,i); 157 return; 191 plot_transient_results(md, options, subplotwidth, i); 192 return; 193 158 194 case 'transient_field': 159 plot_transient_field(md,options,subplotwidth,i); 160 return; 195 plot_transient_field(md, options, subplotwidth, i); 196 return; 197 161 198 default: 162 if (data in md){ 163 data=md[data]; 164 } 165 else{ 199 if (data in md) { 200 data = md[data]; 201 } else { 166 202 error('plot error message: data provided not supported yet. Type plotdoc for help'); 167 203 } … … 169 205 } 170 206 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); 191 228 return; 192 229 } 193 230 194 231 //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); 197 234 return; 198 235 } 199 236 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]; 203 240 204 // plot unit205 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); 208 245 } //}}} -
issm/trunk-jpl/src/m/plot/plot_mesh.js
r22894 r26300 7 7 // See also: PLOTMODEL, PLOT_MANAGER 8 8 9 // If we already have the overlay and are using caching, short circuit10 if ('mesh' in canvas.nodes && options.getfieldvalue('cachenodes', 'off') === 'on') {11 return;12 }13 14 /*15 Local variables16 */17 9 //{{{ 18 10 //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]; 42 21 43 22 //Compute gl variables: 44 varedgecolor = options.getfieldvalue('edgecolor', 'black');45 varnode = new Node(23 let edgecolor = options.getfieldvalue('edgecolor', 'black'); 24 let node = new Node( 46 25 'canvas', canvas, 47 26 'options', options, 27 'md', md, 48 28 '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), 55 32 '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],60 33 'scale', scale 61 34 ); 62 35 //}}} 63 36 //{{{ 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 69 52 node.patch('Faces', elements, 'Vertices', vertices, 'FaceColor', 'none', 'EdgeColor', edgecolor); 70 53 } -
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'; 8 2 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 */ 15 function 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 } 12 47 } 13 48 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)]); 27 52 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 34 54 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; 40 60 } 41 61 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; 51 67 } 52 68 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( 57 121 'canvas', canvas, 58 122 '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, 70 128 'texture', texture, 71 'rotation', [-90, 0, 0],72 129 'scale', scale 73 130 ); 74 //}}}131 canvas.overlayNode = node; 75 132 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)]; 79 136 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; 86 141 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; 89 148 } 90 } 91 else { 92 for(var i = 0; i < x.length; i++){ 149 } else { 150 for (let i = 0; i < x.length; ++i) { 93 151 coordArray[0][i] = (vertices[0][i] - xlim[0]) / xRange; 94 152 coordArray[1][i] = (vertices[1][i] - ylim[0]) / yRange; 95 153 } 96 154 } 155 97 156 node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', coordArray, 'FaceColor', 'interp'); 98 } //}}}157 } -
issm/trunk-jpl/src/m/plot/plot_quiver.js
r22894 r26300 21 21 var is2d = meshresults[4]; 22 22 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 } 24 26 25 27 //Compute coordinates and data range: … … 35 37 //Handle heightscale 36 38 var vertices, scale; 37 if ( md.mesh.classname() !== 'mesh3dsurface') {39 if (!md.mesh.classname().startsWith('mesh3d')) { 38 40 vertices = [x, y, z]; 39 41 scale = [1, 1, options.getfieldvalue('heightscale', 1)]; 40 42 } 41 43 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); 43 45 scale = [1, 1, 1]; 44 46 } … … 51 53 'name', 'quiver', 52 54 'shaderName', 'Colored', 53 ' alpha', options.getfieldvalue('alpha', 1.0),55 'opacity', options.getfieldvalue('opacity', 1.0), 54 56 //'center', [(xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2, md.mesh.classname() === 'mesh3dsurface' ? (zlim[0] + zlim[1]) / 2 : zlim[0]], 55 57 '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'; 10 2 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 */ 20 function 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++) { 17 26 steps[i] = i; 18 27 } 19 20 // Calculate caxis28 29 //calculate caxis 21 30 if (!options.exist('caxis')) { 22 let range = [Infinity, -Infinity]; 23 let dataResults; 24 31 let range = [Infinity, -Infinity]; 32 let dataresults; 25 33 for (let i in steps) { 26 data Results = processdata(md, data[i], options);27 range[0] = Math.min(range[0], ArrayMin(data Results[1]));28 range[1] = Math.max(range[1], ArrayMax(data Results[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])); 29 37 } 30 31 dataType = dataResults[1];32 38 options.addfielddefault('caxis', range); 33 39 } 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; 34 100 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 } 43 112 } 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() { 67 116 // Update current animation frame 68 let frame = canvas.animation.frame; 69 let numFrames = steps.length; 70 117 let frame = canvas.animation.frame; 118 71 119 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; 79 123 } else { 80 frame = (frame + 1) % numFrames;124 canvas.animation.play = !canvas.animation.play; 81 125 } 126 } else { 127 frame = (frame + 1) % steps.length; 82 128 } 83 129 } 84 85 // If frame has changed, update unit node and data marker display130 131 //If frame has changed, update unit node and data marker display. 86 132 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); 87 144 node.updateBuffer('Coords', processedData[frame]); 88 canvas.unitData = processedData[frame]; 89 145 canvas.unitData[unitName] = processedData[frame]; 90 146 if (canvas.graph.enabled) { 91 147 vesl.graph.draw(canvas); 92 148 } 93 94 if (!vesl.helpers.isEmptyOrUndefined(canvas.playbackControls.slider)) { 95 canvas.playbackControls.slider.val(frame); 149 if (slider != null) { 150 slider.val(frame); 96 151 } 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 } 100 158 } 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 105 163 } 106 107 // Save new frame info108 canvas.animation.lastFrame 109 canvas.animation.frame 164 165 //Save new frame info. 166 canvas.animation.lastFrame = canvas.animation.frame; 167 canvas.animation.frame = frame; 110 168 }, canvas.animation.interval); 111 112 // Update progress bar with new frame info113 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); 116 174 } 117 175 118 176 applyoptions(md, [], options, canvas); 119 } //}}}177 } -
issm/trunk-jpl/src/m/plot/plot_unit.js
r22894 r26300 1 'use strict'; 2 1 3 function plot_unit(md, data, datatype, options, canvas) { //{{{ 2 4 //PLOT_UNIT - unit plot, display data … … 6 8 // 7 9 // 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; 17 68 } 18 69 } 19 else {20 name = 'unit' + Object.keys(canvas.nodes).length;21 }22 }23 24 //{{{ declare variables:25 //Process data and model26 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;38 70 } 39 71 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; 44 73 45 //Handle heightscale46 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] : scale85 );86 //}87 if (options.getfieldvalue('clf','on')=='on') {88 canvas.unitNode = node;89 canvas.unitData = data;90 }91 74 //}}} 92 switch(datatype) {75 switch(datatype) { 93 76 //{{{ element plot 94 77 case 1: 95 78 //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 102 95 node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', data, 'FaceColor', 'flat', 'EdgeColor', edgecolor); 103 96 } 97 104 98 break; 105 99 //}}} 106 100 //{{{ node plot 107 101 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 113 116 node.patch('Faces', elements, 'Vertices', vertices, 'FaceVertexCData', data, 'FaceColor', 'interp', 'EdgeColor', edgecolor); 114 117 } 118 115 119 break; 116 120 //}}} 117 121 //{{{ quiver plot 118 122 case 3: 119 if (is2d) {123 if (is2d) { 120 124 //plot_quiver(x, y, data(:, 1), data(:, 2), options); 121 } 122 else{ 125 } else { 123 126 //plot_quiver3(x, y, z, data(:, 1), data(:, 2), data(:, 3), options); 124 127 } 128 125 129 break; 126 130 //}}} -
issm/trunk-jpl/src/m/plot/plotdoc.js
r22894 r26300 24 24 console.log(' "height": height to spawn clouds at (ex: 7500)'); 25 25 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)'); 27 27 console.log(' "colorbar": add colorbar (default "off", ex: "on", "off")'); 28 28 console.log(' "colorbarid": colorbar canvas id (string)'); … … 39 39 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})'); 40 40 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)'); 46 47 console.log(' "displayview": print view value to console (default "off", ex: "on", "off")'); 47 48 console.log(' "displayzoom": print zoom value to console (default "off", ex: "on", "off")'); … … 60 61 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")'); 61 62 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: "./im ages/radar.png")');63 console.log(' "overlay_image": path to overlay image (default "", ex: "./img/radar.png")'); 63 64 console.log(' "quiver": add quiver plot overlay for velocities. (default "off", ex: "on", "off")'); 64 65 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)'); 66 67 console.log(' "render": a object containing a list of default object to render. (default {}, ex: {"sky", "space"})'); 67 68 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'; 4 2 5 //First process options 6 var options = new plotoptions(args.slice(1,args.length)); 3 function 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 } 7 21 8 //get number of subplots9 subplotwidth=Math.ceil(Math.sqrt(options.numberofplots));10 11 //Get figure number and number of plots12 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 }22 22 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; 27 26 } 28 27 29 28 //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 } 31 33 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]); 37 42 } 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]); 41 47 42 // List all unused options48 // List all unused options 43 49 options.list[i].displayunused(); 50 } 51 for (let i = 0; i < numberofplots; ++i) { 52 canvases[i].state.dispatchEvent('onPlotModelEnd', canvases[i], options.list[i]); 44 53 } 45 54 } -
issm/trunk-jpl/src/m/solve/WriteData.js
r21911 r26300 1 function WriteData(fid,prefix){ 1 function WriteData(fid,prefix){ //{{{ 2 2 //WRITEDATA - write model field into binary buffer 3 3 // … … 74 74 } 75 75 76 let recordlengthtype = 'int'; 77 if (svnversion >= 22708) { 78 recordlengthtype = 'long long'; 79 } 80 76 81 //Step 1: write the name to identify this record uniquely 77 82 fid.fwrite(name.length,'int'); … … 83 88 84 89 //first write length of record 85 fid.fwrite(4+4, 'int'); //1 bool (disguised as an int)+code90 fid.fwrite(4+4,recordlengthtype); //1 bool (disguised as an int)+code 86 91 87 92 //write data code: … … 95 100 96 101 //first write length of record 97 fid.fwrite(4+4, 'int'); //1 integer + code102 fid.fwrite(4+4,recordlengthtype); //1 integer + code 98 103 99 104 //write data code: … … 107 112 108 113 //first write length of record 109 fid.fwrite(8+4, 'int'); //1 double+code114 fid.fwrite(8+4,recordlengthtype); //1 double+code 110 115 111 116 //write data code: … … 117 122 else if (format == 'String'){ // {{{ 118 123 //first write length of record 119 fid.fwrite(data.length+4+4, 'int'); //string + string size + code124 fid.fwrite(data.length+4+4,recordlengthtype); //string + string size + code 120 125 121 126 //write data code: … … 141 146 142 147 //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 type148 fid.fwrite(4+4+8*s[0]*s[1]+4+4,recordlengthtype); //2 integers (32 bits) + the double matrix + code + matrix type 144 149 145 150 //write data code and matrix type: … … 167 172 168 173 //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 type174 fid.fwrite(4+4+8*s[0]*s[1]+4+4,recordlengthtype); //2 integers (32 bits) + the double matrix + code + matrix type 170 175 171 176 //write data code and matrix type: … … 197 202 var recordlength=4+4+8*s[0]*s[1]+4+4; //2 integers (32 bits) + the double matrix + code + matrix type 198 203 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); 200 205 201 206 //write data code and matrix type: … … 224 229 225 230 //write length of record 226 fid.fwrite(recordlength, 'int');231 fid.fwrite(recordlength,recordlengthtype); 227 232 228 233 //write data code: … … 259 264 260 265 //write length of record 261 fid.fwrite(recordlength, 'int');266 fid.fwrite(recordlength,recordlengthtype); 262 267 263 268 //write data code: … … 278 283 format.toString(),name)); 279 284 } 280 } 281 285 } //}}} 282 286 function FormatToCode(format){ // {{{ 283 287 //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')) { 1 async function solve(md, solutionstring, ...varargin) { //{{{ 2 /* 3 SOLVE - apply solution sequence for this model 4 5 Usage: 6 solve(md, solutionstring[, ...]); 7 8 where varargin is a list of paired arguments of string OR enums 9 10 Solution 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 30 Extra options (these all need to be passed in via the third parameter, which is 31 a 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 37 Examples: 38 md = solve(md, 'Stressbalance'); 39 md = solve(md, 'sb'); 40 41 NOTE: 42 - We do not strictly need to return md as objects are passed by reference in 43 JavaScript, but we do so to mirror MATLAB and Python APIs. 44 45 TODO: 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')) { 50 62 solutionstring = 'StressbalanceSolution'; 51 } else if ( (solutionStringLowerCase === 'mt') || (solutionStringLowerCase === 'masstransport')) {63 } else if (vesl.strings.strcmpi(solutionstring, 'mt') || vesl.strings.strcmpi(solutionstring, 'Masstransport')) { 52 64 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')) { 54 68 solutionstring = 'ThermalSolution'; 55 } else if ( (solutionStringLowerCase === 'st') || (solutionStringLowerCase === 'steadystate')) {69 } else if (vesl.strings.strcmpi(solutionstring, 'st') || vesl.strings.strcmpi(solutionstring, 'Steadystate')) { 56 70 solutionstring = 'SteadystateSolution'; 57 } else if ( (solutionStringLowerCase === 'tr') || (solutionStringLowerCase === 'transient')) {71 } else if (vesl.strings.strcmpi(solutionstring, 'tr') || vesl.strings.strcmpi(solutionstring, 'Transient')) { 58 72 solutionstring = 'TransientSolution'; 59 } else if ( (solutionStringLowerCase === 'mc') || (solutionStringLowerCase === 'balancethickness')) {73 } else if (vesl.strings.strcmpi(solutionstring, 'mc') || vesl.strings.strcmpi(solutionstring, 'Balancethickness')) { 60 74 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')) { 62 78 solutionstring = 'BalancevelocitySolution'; 63 } else if ( (solutionStringLowerCase === 'bsl') || (solutionStringLowerCase === 'bedslope')) {79 } else if (vesl.strings.strcmpi(solutionstring, 'bsl') || vesl.strings.strcmpi(solutionstring, 'BedSlope')) { 64 80 solutionstring = 'BedSlopeSolution'; 65 } else if ( (solutionStringLowerCase === 'ssl') || (solutionStringLowerCase === 'surfaceslope')) {81 } else if (vesl.strings.strcmpi(solutionstring, 'ssl') || vesl.strings.strcmpi(solutionstring, 'SurfaceSlope')) { 66 82 solutionstring = 'SurfaceSlopeSolution'; 67 } else if ( (solutionStringLowerCase === 'hy') || (solutionStringLowerCase === 'hydrology')) {83 } else if (vesl.strings.strcmpi(solutionstring, 'hy') || vesl.strings.strcmpi(solutionstring, 'Hydrology')) { 68 84 solutionstring = 'HydrologySolution'; 69 } else if ( (solutionStringLowerCase === 'da') || (solutionStringLowerCase === 'damageevolution')) {85 } else if (vesl.strings.strcmpi(solutionstring, 'da') || vesl.strings.strcmpi(solutionstring, 'DamageEvolution')) { 70 86 solutionstring = 'DamageEvolutionSolution'; 71 } else if ( (solutionStringLowerCase === 'gia') || (solutionStringLowerCase === 'gia')) {87 } else if (vesl.strings.strcmpi(solutionstring, 'gia') || vesl.strings.strcmpi(solutionstring, 'Gia')) { 72 88 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'; 75 99 } 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 85 105 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 89 115 if (options.getfieldvalue('checkconsistency', 'yes') === 'yes') { 90 116 if (md.verbose.solution) { … … 94 120 ismodelselfconsistent(md); 95 121 } 96 122 97 123 // If we are restarting, actually use the provided runtime name: 98 124 restart = options.getfieldvalue('restart', ''); 99 125 100 126 // First, build a runtime name that is unique 101 if (restart === 1 127 if (restart === 1) { 102 128 // Leave the runtimename as is 103 129 } 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; 109 132 } 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 115 143 if (md.qmu.isdakota) { 116 throw Error("solve error message: qmu runsnot supported yet!");117 //md .preqmu(options);118 } 119 144 throw new Error("QMU not supported yet!"); 145 //md = preqmu(md, options); 146 } 147 120 148 // Do we load results only? 121 149 if (options.getfieldvalue('loadonly', false)){ … … 124 152 } 125 153 126 // Marshall into a binary array (fid) all the fields of model127 let fid = marshall(md); // bin file128 129 //deal with toolkits options:130 toolkitsstring = md.toolkits.ToolkitsFile(md.miscellaneous.name + '.toolkits'); // toolkits file131 132 133 154 /* 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. 137 160 */ 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 193 177 194 178 if (cluster.classname() === 'local') {//{{{ 195 179 196 // We are running locally on the machine, using the issmmodule180 // We are running locally on the machine, using the ISSM module 197 181 console.log('running issm locally'); 198 182 199 // Call issm183 // Call ISSM 200 184 let outputs = issm(fid, toolkitsstring, solutionstring, md.miscellaneous.name); 201 185 202 // Recover output arguments:186 // Recover output 203 187 let outputbuffer = outputs[0]; 204 188 let outputbuffersize = outputs[1]; 205 189 206 190 // 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 } 213 197 //}}} 214 } else { //{{{198 } else { //{{{ 215 199 // We are running somewhere else on a computational server. Send the buffer to that server and retrieve output. 216 200 console.log('running issm remotely'); 217 201 218 cluster.UploadAndRun(202 await cluster.uploadandrun( 219 203 md, 220 204 fid, … … 223 207 md.miscellaneous.name, 224 208 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 232 227 return md; 233 }//}}} 234 }//}}} 235 228 } //}}} 229 } //}}}
Note:
See TracChangeset
for help on using the changeset viewer.