[26300] | 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.');
|
---|
[21065] | 58 | }
|
---|
| 59 |
|
---|
[26300] | 60 | // Recover and process solve options
|
---|
| 61 | if (vesl.strings.strcmpi(solutionstring, 'sb') || vesl.strings.strcmpi(solutionstring, 'Stressbalance')) {
|
---|
[21065] | 62 | solutionstring = 'StressbalanceSolution';
|
---|
[26300] | 63 | } else if (vesl.strings.strcmpi(solutionstring, 'mt') || vesl.strings.strcmpi(solutionstring, 'Masstransport')) {
|
---|
[21065] | 64 | solutionstring = 'MasstransportSolution';
|
---|
[26300] | 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')) {
|
---|
[21065] | 68 | solutionstring = 'ThermalSolution';
|
---|
[26300] | 69 | } else if (vesl.strings.strcmpi(solutionstring, 'st') || vesl.strings.strcmpi(solutionstring, 'Steadystate')) {
|
---|
[21065] | 70 | solutionstring = 'SteadystateSolution';
|
---|
[26300] | 71 | } else if (vesl.strings.strcmpi(solutionstring, 'tr') || vesl.strings.strcmpi(solutionstring, 'Transient')) {
|
---|
[21065] | 72 | solutionstring = 'TransientSolution';
|
---|
[26300] | 73 | } else if (vesl.strings.strcmpi(solutionstring, 'mc') || vesl.strings.strcmpi(solutionstring, 'Balancethickness')) {
|
---|
[21065] | 74 | solutionstring = 'BalancethicknessSolution';
|
---|
[26300] | 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')) {
|
---|
[21065] | 78 | solutionstring = 'BalancevelocitySolution';
|
---|
[26300] | 79 | } else if (vesl.strings.strcmpi(solutionstring, 'bsl') || vesl.strings.strcmpi(solutionstring, 'BedSlope')) {
|
---|
[21065] | 80 | solutionstring = 'BedSlopeSolution';
|
---|
[26300] | 81 | } else if (vesl.strings.strcmpi(solutionstring, 'ssl') || vesl.strings.strcmpi(solutionstring, 'SurfaceSlope')) {
|
---|
[21065] | 82 | solutionstring = 'SurfaceSlopeSolution';
|
---|
[26300] | 83 | } else if (vesl.strings.strcmpi(solutionstring, 'hy') || vesl.strings.strcmpi(solutionstring, 'Hydrology')) {
|
---|
[21065] | 84 | solutionstring = 'HydrologySolution';
|
---|
[26300] | 85 | } else if (vesl.strings.strcmpi(solutionstring, 'da') || vesl.strings.strcmpi(solutionstring, 'DamageEvolution')) {
|
---|
[21065] | 86 | solutionstring = 'DamageEvolutionSolution';
|
---|
[26300] | 87 | } else if (vesl.strings.strcmpi(solutionstring, 'gia') || vesl.strings.strcmpi(solutionstring, 'Gia')) {
|
---|
[21584] | 88 | solutionstring = 'GiaSolution';
|
---|
[26300] | 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';
|
---|
[22831] | 99 | } else {
|
---|
[26300] | 100 | throw new Error('solutionstring ' + solutionstring + ' not supported!');
|
---|
[19780] | 101 | }
|
---|
[26300] | 102 | let options = new pairoptions(varargin, 'solutionstring', solutionstring);
|
---|
[19780] | 103 |
|
---|
[26300] | 104 | // Recover some fields
|
---|
[22880] | 105 | md.priv.solution = solutionstring;
|
---|
[26300] | 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
|
---|
[22880] | 115 | if (options.getfieldvalue('checkconsistency', 'yes') === 'yes') {
|
---|
| 116 | if (md.verbose.solution) {
|
---|
[19780] | 117 | console.log('checking model consistency');
|
---|
| 118 | }
|
---|
[22880] | 119 |
|
---|
[21097] | 120 | ismodelselfconsistent(md);
|
---|
[19780] | 121 | }
|
---|
[26300] | 122 |
|
---|
[22880] | 123 | // If we are restarting, actually use the provided runtime name:
|
---|
| 124 | restart = options.getfieldvalue('restart', '');
|
---|
[20269] | 125 |
|
---|
[22880] | 126 | // First, build a runtime name that is unique
|
---|
[26300] | 127 | if (restart === 1) {
|
---|
[22880] | 128 | // Leave the runtimename as is
|
---|
| 129 | } else {
|
---|
[26300] | 130 | if (restart !== '') {
|
---|
| 131 | md.priv.runtimename = restart;
|
---|
[22880] | 132 | } else {
|
---|
[26300] | 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 | }
|
---|
[19780] | 139 | }
|
---|
| 140 | }
|
---|
| 141 |
|
---|
[26300] | 142 | // If running QMU analysis, some preprocessing of Dakota files using model fields needs to be carried out
|
---|
[22880] | 143 | if (md.qmu.isdakota) {
|
---|
[26300] | 144 | throw new Error("QMU not supported yet!");
|
---|
| 145 | //md = preqmu(md, options);
|
---|
[19780] | 146 | }
|
---|
[26300] | 147 |
|
---|
[22880] | 148 | // Do we load results only?
|
---|
| 149 | if (options.getfieldvalue('loadonly', false)){
|
---|
[19780] | 150 | loadresultsfromcluster(md);
|
---|
| 151 | return;
|
---|
| 152 | }
|
---|
| 153 |
|
---|
[22824] | 154 | /*
|
---|
[26300] | 155 | Write all input arrays (as opposed to, under MATLAB/Python, input binary
|
---|
| 156 | files)
|
---|
[22824] | 157 |
|
---|
[26300] | 158 | NOTE: The JavaScript implementation diverges significantly from the
|
---|
| 159 | MATLAB/Python APIs here.
|
---|
[22824] | 160 | */
|
---|
[26300] | 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
|
---|
[19793] | 177 |
|
---|
[22880] | 178 | if (cluster.classname() === 'local') {//{{{
|
---|
[22831] | 179 |
|
---|
[26300] | 180 | // We are running locally on the machine, using the ISSM module
|
---|
[19793] | 181 | console.log('running issm locally');
|
---|
| 182 |
|
---|
[26300] | 183 | // Call ISSM
|
---|
[22880] | 184 | let outputs = issm(fid, toolkitsstring, solutionstring, md.miscellaneous.name);
|
---|
[19816] | 185 |
|
---|
[26300] | 186 | // Recover output
|
---|
[22880] | 187 | let outputbuffer = outputs[0];
|
---|
| 188 | let outputbuffersize = outputs[1];
|
---|
[19816] | 189 |
|
---|
[22880] | 190 | // Load results
|
---|
[26300] | 191 | md = loadresultsfrombuffer(md, outputbuffer, outputbuffersize); // TODO: Pass reporting construct to loadresultsfrombuffer
|
---|
[20269] | 192 |
|
---|
[26300] | 193 | // Call success callback
|
---|
| 194 | if (vesl.helpers.isFunction(vesl.ui.reporting.success_callback)) {
|
---|
| 195 | vesl.ui.reporting.success_callback();
|
---|
| 196 | }
|
---|
[22831] | 197 | //}}}
|
---|
[26300] | 198 | } else { //{{{
|
---|
[22831] | 199 | // We are running somewhere else on a computational server. Send the buffer to that server and retrieve output.
|
---|
[22716] | 200 | console.log('running issm remotely');
|
---|
[22831] | 201 |
|
---|
[26300] | 202 | await cluster.uploadandrun(
|
---|
[22831] | 203 | md,
|
---|
| 204 | fid,
|
---|
| 205 | toolkitsstring,
|
---|
| 206 | solutionstring,
|
---|
| 207 | md.miscellaneous.name,
|
---|
| 208 | md.priv.runtimename,
|
---|
[26300] | 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 |
|
---|
[20269] | 227 | return md;
|
---|
[26300] | 228 | } //}}}
|
---|
| 229 | } //}}}
|
---|