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')) {
|
---|
62 | solutionstring = 'StressbalanceSolution';
|
---|
63 | } else if (vesl.strings.strcmpi(solutionstring, 'mt') || vesl.strings.strcmpi(solutionstring, 'Masstransport')) {
|
---|
64 | solutionstring = 'MasstransportSolution';
|
---|
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')) {
|
---|
68 | solutionstring = 'ThermalSolution';
|
---|
69 | } else if (vesl.strings.strcmpi(solutionstring, 'st') || vesl.strings.strcmpi(solutionstring, 'Steadystate')) {
|
---|
70 | solutionstring = 'SteadystateSolution';
|
---|
71 | } else if (vesl.strings.strcmpi(solutionstring, 'tr') || vesl.strings.strcmpi(solutionstring, 'Transient')) {
|
---|
72 | solutionstring = 'TransientSolution';
|
---|
73 | } else if (vesl.strings.strcmpi(solutionstring, 'mc') || vesl.strings.strcmpi(solutionstring, 'Balancethickness')) {
|
---|
74 | solutionstring = 'BalancethicknessSolution';
|
---|
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')) {
|
---|
78 | solutionstring = 'BalancevelocitySolution';
|
---|
79 | } else if (vesl.strings.strcmpi(solutionstring, 'bsl') || vesl.strings.strcmpi(solutionstring, 'BedSlope')) {
|
---|
80 | solutionstring = 'BedSlopeSolution';
|
---|
81 | } else if (vesl.strings.strcmpi(solutionstring, 'ssl') || vesl.strings.strcmpi(solutionstring, 'SurfaceSlope')) {
|
---|
82 | solutionstring = 'SurfaceSlopeSolution';
|
---|
83 | } else if (vesl.strings.strcmpi(solutionstring, 'hy') || vesl.strings.strcmpi(solutionstring, 'Hydrology')) {
|
---|
84 | solutionstring = 'HydrologySolution';
|
---|
85 | } else if (vesl.strings.strcmpi(solutionstring, 'da') || vesl.strings.strcmpi(solutionstring, 'DamageEvolution')) {
|
---|
86 | solutionstring = 'DamageEvolutionSolution';
|
---|
87 | } else if (vesl.strings.strcmpi(solutionstring, 'gia') || vesl.strings.strcmpi(solutionstring, 'Gia')) {
|
---|
88 | solutionstring = 'GiaSolution';
|
---|
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';
|
---|
99 | } else {
|
---|
100 | throw new Error('solutionstring ' + solutionstring + ' not supported!');
|
---|
101 | }
|
---|
102 | let options = new pairoptions(varargin, 'solutionstring', solutionstring);
|
---|
103 |
|
---|
104 | // Recover some fields
|
---|
105 | md.priv.solution = solutionstring;
|
---|
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
|
---|
115 | if (options.getfieldvalue('checkconsistency', 'yes') === 'yes') {
|
---|
116 | if (md.verbose.solution) {
|
---|
117 | console.log('checking model consistency');
|
---|
118 | }
|
---|
119 |
|
---|
120 | ismodelselfconsistent(md);
|
---|
121 | }
|
---|
122 |
|
---|
123 | // If we are restarting, actually use the provided runtime name:
|
---|
124 | restart = options.getfieldvalue('restart', '');
|
---|
125 |
|
---|
126 | // First, build a runtime name that is unique
|
---|
127 | if (restart === 1) {
|
---|
128 | // Leave the runtimename as is
|
---|
129 | } else {
|
---|
130 | if (restart !== '') {
|
---|
131 | md.priv.runtimename = restart;
|
---|
132 | } else {
|
---|
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
|
---|
143 | if (md.qmu.isdakota) {
|
---|
144 | throw new Error("QMU not supported yet!");
|
---|
145 | //md = preqmu(md, options);
|
---|
146 | }
|
---|
147 |
|
---|
148 | // Do we load results only?
|
---|
149 | if (options.getfieldvalue('loadonly', false)){
|
---|
150 | loadresultsfromcluster(md);
|
---|
151 | return;
|
---|
152 | }
|
---|
153 |
|
---|
154 | /*
|
---|
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.
|
---|
160 | */
|
---|
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
|
---|
177 |
|
---|
178 | if (cluster.classname() === 'local') {//{{{
|
---|
179 |
|
---|
180 | // We are running locally on the machine, using the ISSM module
|
---|
181 | console.log('running issm locally');
|
---|
182 |
|
---|
183 | // Call ISSM
|
---|
184 | let outputs = issm(fid, toolkitsstring, solutionstring, md.miscellaneous.name);
|
---|
185 |
|
---|
186 | // Recover output
|
---|
187 | let outputbuffer = outputs[0];
|
---|
188 | let outputbuffersize = outputs[1];
|
---|
189 |
|
---|
190 | // Load results
|
---|
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 | }
|
---|
197 | //}}}
|
---|
198 | } else { //{{{
|
---|
199 | // We are running somewhere else on a computational server. Send the buffer to that server and retrieve output.
|
---|
200 | console.log('running issm remotely');
|
---|
201 |
|
---|
202 | await cluster.uploadandrun(
|
---|
203 | md,
|
---|
204 | fid,
|
---|
205 | toolkitsstring,
|
---|
206 | solutionstring,
|
---|
207 | md.miscellaneous.name,
|
---|
208 | md.priv.runtimename,
|
---|
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 |
|
---|
227 | return md;
|
---|
228 | } //}}}
|
---|
229 | } //}}}
|
---|