@abi-software/simulationvuer 3.0.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index-BX7g0eM9.js +71147 -0
- package/dist/{quill-CuAVUOyy-B7CbeCk7.js → quill-B7JfuUb2-B-kKsgWs.js} +5 -8
- package/dist/simulationvuer.js +2 -70205
- package/dist/simulationvuer.umd.cjs +375 -266
- package/dist/style.css +1 -1
- package/package.json +3 -2
- package/src/components/SimulationVuer.vue +20 -218
- package/src/components/common.js +0 -9
- package/src/components/json.js +51 -53
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abi-software/simulationvuer",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"serve": "vite serve --host --force",
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@abi-software/plotvuer": "1.0.7",
|
|
21
|
-
"@opencor/opencor": "^0.
|
|
21
|
+
"@opencor/opencor": "^0.20251205.1",
|
|
22
22
|
"element-plus": "2.8.4",
|
|
23
23
|
"jsonschema": "^1.4.0",
|
|
24
|
+
"mathjs": "^15.1.0",
|
|
24
25
|
"unplugin-vue-components": "^0.26.0",
|
|
25
26
|
"vue": "^3.4.21"
|
|
26
27
|
},
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
<div class="container" v-if="opencorOmexFile === null">
|
|
4
4
|
<p v-if="!hasValidSimulationUiInfo && !showUserMessage" class="default error"><span class="error">Error:</span> {{ errorMessage }}.</p>
|
|
5
5
|
<div class="main" v-if="hasValidSimulationUiInfo">
|
|
6
|
-
<div class="main-left" :class="{'with-buttons':
|
|
7
|
-
<p class="default name"
|
|
8
|
-
<el-divider
|
|
6
|
+
<div class="main-left" :class="{'with-buttons': uuid}">
|
|
7
|
+
<p class="default name">{{ name }}</p>
|
|
8
|
+
<el-divider></el-divider>
|
|
9
9
|
<p class="default input-parameters">Input parameters</p>
|
|
10
10
|
<div class="input scrollbar">
|
|
11
11
|
<SimulationVuerInput v-for="(input, index) in simulationUiInfo.input"
|
|
@@ -20,18 +20,15 @@
|
|
|
20
20
|
/>
|
|
21
21
|
</div>
|
|
22
22
|
<div class="buttons-container">
|
|
23
|
-
<div class="primary-button"
|
|
23
|
+
<div class="primary-button">
|
|
24
24
|
<el-button type="primary" size="small" @click="startSimulation()">Run Simulation</el-button>
|
|
25
25
|
</div>
|
|
26
26
|
<div class="secondary-button" v-if="uuid">
|
|
27
27
|
<el-button size="small" @click="runOnOsparc()">Run on oSPARC</el-button>
|
|
28
28
|
</div>
|
|
29
|
-
<div class="secondary-button"
|
|
29
|
+
<div class="secondary-button">
|
|
30
30
|
<el-button size="small" @click="viewDataset()">View Dataset</el-button>
|
|
31
31
|
</div>
|
|
32
|
-
<div class="secondary-button" v-if="libopencorSet && idType === 'pmr_path'">
|
|
33
|
-
<el-button size="small" @click="viewWorkspace()">View Workspace</el-button>
|
|
34
|
-
</div>
|
|
35
32
|
<p class="default note" v-if="uuid">Additional parameters are available on oSPARC</p>
|
|
36
33
|
</div>
|
|
37
34
|
</div>
|
|
@@ -63,8 +60,6 @@ import SimulationVuerInput from "./SimulationVuerInput.vue";
|
|
|
63
60
|
import { ElButton, ElDivider, ElLoading } from "element-plus";
|
|
64
61
|
import { evaluateValue, finaliseUi, OPENCOR_SOLVER_NAME } from "./common.js";
|
|
65
62
|
import { validJson } from "./json.js";
|
|
66
|
-
import libOpenCOR from "https://mapcore-demo.org/current/opencor-wasm/0.0.3/libopencor.js";
|
|
67
|
-
import { markRaw } from "vue";
|
|
68
63
|
import { create, all } from "mathjs";
|
|
69
64
|
import OpenCOR from '@opencor/opencor';
|
|
70
65
|
import '@opencor/opencor/style.css';
|
|
@@ -157,8 +152,6 @@ export default {
|
|
|
157
152
|
isMounted: false,
|
|
158
153
|
isSimulationValid: true,
|
|
159
154
|
layout: [],
|
|
160
|
-
libopencor: undefined,
|
|
161
|
-
libopencorSet: false,
|
|
162
155
|
model: undefined,
|
|
163
156
|
name: null,
|
|
164
157
|
opencorBasedSimulation: true,
|
|
@@ -193,150 +186,6 @@ export default {
|
|
|
193
186
|
},
|
|
194
187
|
};
|
|
195
188
|
},
|
|
196
|
-
/**
|
|
197
|
-
* @public
|
|
198
|
-
* Manage the file associated with the given `url` and `fileContents`.
|
|
199
|
-
* @arg `url`
|
|
200
|
-
* @arg `fileContents`
|
|
201
|
-
*/
|
|
202
|
-
manageFile(url, fileContents) {
|
|
203
|
-
let file = this.fileManager.file(url);
|
|
204
|
-
|
|
205
|
-
if (file === null) {
|
|
206
|
-
file = new this.libopencor.File(url);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const fileContentsPtr = this.libopencor._malloc(fileContents.length);
|
|
210
|
-
const mem = new Uint8Array(this.libopencor.HEAPU8.buffer, fileContentsPtr, fileContents.length);
|
|
211
|
-
|
|
212
|
-
mem.set(fileContents);
|
|
213
|
-
|
|
214
|
-
file.setContents(fileContentsPtr, fileContents.length);
|
|
215
|
-
|
|
216
|
-
this.libopencor._free(fileContentsPtr);
|
|
217
|
-
|
|
218
|
-
return file;
|
|
219
|
-
},
|
|
220
|
-
/**
|
|
221
|
-
* @public
|
|
222
|
-
* Run a PMR-based COMBINE archive using libOpenCOR.
|
|
223
|
-
*/
|
|
224
|
-
runSimulation() {
|
|
225
|
-
if (this.instance === undefined) {
|
|
226
|
-
// Retrieve an instance of the model.
|
|
227
|
-
|
|
228
|
-
const document = new this.libopencor.SedDocument(this.fileManager.file(PMR_URL + this.id));
|
|
229
|
-
|
|
230
|
-
this.model = markRaw(document.model());
|
|
231
|
-
this.instance = markRaw(document.instantiate());
|
|
232
|
-
|
|
233
|
-
document.delete();
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Run the simulation after passing some changes, if any, to the model.
|
|
237
|
-
|
|
238
|
-
this.model.removeAllChanges();
|
|
239
|
-
|
|
240
|
-
for (const [parameter, value] of Object.entries(this.parametersData())) {
|
|
241
|
-
const parameterParts = parameter.split("/")
|
|
242
|
-
|
|
243
|
-
this.model.addChange(new this.libopencor.SedChangeAttribute(parameterParts[0], parameterParts[1], value.toString()));
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
this.instance.run();
|
|
247
|
-
|
|
248
|
-
// Retrieve the simulation results.
|
|
249
|
-
|
|
250
|
-
const res = {};
|
|
251
|
-
const instanceTask = this.instance.task(0);
|
|
252
|
-
let foundAllOutputs = true;
|
|
253
|
-
let foundOutput;
|
|
254
|
-
|
|
255
|
-
for (const output of this.outputData()) {
|
|
256
|
-
foundOutput = false;
|
|
257
|
-
|
|
258
|
-
if (output === instanceTask.voiName) {
|
|
259
|
-
res[output] = instanceTask.voiAsArray;
|
|
260
|
-
|
|
261
|
-
foundOutput = true;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (res[output] === undefined) {
|
|
265
|
-
for (let i = 0; i < instanceTask.stateCount; ++i) {
|
|
266
|
-
if (output === instanceTask.stateName(i)) {
|
|
267
|
-
res[output] = instanceTask.stateAsArray(i);
|
|
268
|
-
|
|
269
|
-
foundOutput = true;
|
|
270
|
-
|
|
271
|
-
break;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (res[output] === undefined) {
|
|
277
|
-
for (let i = 0; i < instanceTask.rateCount; ++i) {
|
|
278
|
-
if (output === instanceTask.rateName(i)) {
|
|
279
|
-
res[output] = instanceTask.rateAsArray(i);
|
|
280
|
-
|
|
281
|
-
foundOutput = true;
|
|
282
|
-
|
|
283
|
-
break;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (res[output] === undefined) {
|
|
289
|
-
for (let i = 0; i < instanceTask.constantCount; ++i) {
|
|
290
|
-
if (output === instanceTask.constantName(i)) {
|
|
291
|
-
res[output] = instanceTask.constantAsArray(i);
|
|
292
|
-
|
|
293
|
-
foundOutput = true;
|
|
294
|
-
|
|
295
|
-
break;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (res[output] === undefined) {
|
|
301
|
-
for (let i = 0; i < instanceTask.computedConstantCount; ++i) {
|
|
302
|
-
if (output === instanceTask.computedConstantName(i)) {
|
|
303
|
-
res[output] = instanceTask.computedConstantAsArray(i);
|
|
304
|
-
|
|
305
|
-
foundOutput = true;
|
|
306
|
-
|
|
307
|
-
break;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (res[output] === undefined) {
|
|
313
|
-
for (let i = 0; i < instanceTask.algebraicCount; ++i) {
|
|
314
|
-
if (output === instanceTask.algebraicName(i)) {
|
|
315
|
-
res[output] = instanceTask.algebraicAsArray(i);
|
|
316
|
-
|
|
317
|
-
foundOutput = true;
|
|
318
|
-
|
|
319
|
-
break;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
if (!foundOutput) {
|
|
325
|
-
console.warn("SIMULATION: output '" + output + "' could not be found.");
|
|
326
|
-
|
|
327
|
-
foundAllOutputs = false;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
if (foundAllOutputs) {
|
|
332
|
-
this.processSimulationResults(res);
|
|
333
|
-
} else {
|
|
334
|
-
this.hasValidSimulationUiInfo = false;
|
|
335
|
-
this.errorMessage = "some outputs could not be found";
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
this.showUserMessage = false;
|
|
339
|
-
},
|
|
340
189
|
/**
|
|
341
190
|
* @public
|
|
342
191
|
* Build the simulation UI using `simulationUiInfo`, a JSON object that describes the contents of the simulation UI.
|
|
@@ -349,7 +198,7 @@ export default {
|
|
|
349
198
|
|
|
350
199
|
// Make sure that the simulation UI information is valid.
|
|
351
200
|
|
|
352
|
-
this.hasValidSimulationUiInfo = validJson(this.simulationUiInfo
|
|
201
|
+
this.hasValidSimulationUiInfo = validJson(this.simulationUiInfo);
|
|
353
202
|
|
|
354
203
|
if (!this.hasValidSimulationUiInfo) {
|
|
355
204
|
this.errorMessage = "the simulation.json file is malformed";
|
|
@@ -357,26 +206,23 @@ export default {
|
|
|
357
206
|
return;
|
|
358
207
|
}
|
|
359
208
|
|
|
360
|
-
// Retrieve and keep track of the solver to be used for the simulation
|
|
361
|
-
// needed.
|
|
362
|
-
|
|
363
|
-
if (this.libopencor === undefined) {
|
|
364
|
-
this.simulationUiInfo.simulation.solvers.forEach((solver) => {
|
|
365
|
-
if ((solver.if === undefined) || evaluateValue(this, solver.if)) {
|
|
366
|
-
this.solver = solver;
|
|
367
|
-
}
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
if (this.solver === undefined) {
|
|
371
|
-
this.hasValidSimulationUiInfo = false;
|
|
372
|
-
this.errorMessage = "no solver name and/or solver version specified";
|
|
209
|
+
// Retrieve and keep track of the solver to be used for the simulation.
|
|
373
210
|
|
|
374
|
-
|
|
211
|
+
this.simulationUiInfo.simulation.solvers.forEach((solver) => {
|
|
212
|
+
if ((solver.if === undefined) || evaluateValue(this, solver.if)) {
|
|
213
|
+
this.solver = solver;
|
|
375
214
|
}
|
|
215
|
+
});
|
|
376
216
|
|
|
377
|
-
|
|
217
|
+
if (this.solver === undefined) {
|
|
218
|
+
this.hasValidSimulationUiInfo = false;
|
|
219
|
+
this.errorMessage = "no solver name and/or solver version specified";
|
|
220
|
+
|
|
221
|
+
return;
|
|
378
222
|
}
|
|
379
223
|
|
|
224
|
+
this.opencorBasedSimulation = this.solver.name === OPENCOR_SOLVER_NAME;
|
|
225
|
+
|
|
380
226
|
// Initialise our UI.
|
|
381
227
|
|
|
382
228
|
this.simulationUiInfo.output.data.forEach((data) => {
|
|
@@ -433,40 +279,6 @@ export default {
|
|
|
433
279
|
finaliseUi(this);
|
|
434
280
|
});
|
|
435
281
|
},
|
|
436
|
-
/**
|
|
437
|
-
* @public
|
|
438
|
-
* Extract the simulation UI JSON file from the given file contents and build the simulation UI.
|
|
439
|
-
* @arg `libopencor`
|
|
440
|
-
* @arg `fileContents`
|
|
441
|
-
*/
|
|
442
|
-
extractAndBuildSimulationUi(libopencor, fileContents) {
|
|
443
|
-
this.libopencor = markRaw(libopencor);
|
|
444
|
-
this.libopencorSet = true;
|
|
445
|
-
this.fileManager = markRaw(this.libopencor.FileManager.instance());
|
|
446
|
-
|
|
447
|
-
const file = this.manageFile(PMR_URL + this.id, fileContents);
|
|
448
|
-
|
|
449
|
-
if (file.type.value !== libopencor.File.Type.COMBINE_ARCHIVE.value) {
|
|
450
|
-
this.showUserMessage = false;
|
|
451
|
-
} else {
|
|
452
|
-
const decoder = new TextDecoder();
|
|
453
|
-
const simulationJson = file.childFileFromFileName("simulation.json");
|
|
454
|
-
|
|
455
|
-
if (simulationJson === null) {
|
|
456
|
-
this.errorMessage = "no simulation JSON file could be found";
|
|
457
|
-
|
|
458
|
-
this.showUserMessage = false;
|
|
459
|
-
} else {
|
|
460
|
-
const simulationUiInfo = JSON.parse(decoder.decode(simulationJson.contents()));
|
|
461
|
-
|
|
462
|
-
this.showUserMessage = false;
|
|
463
|
-
|
|
464
|
-
this.$nextTick(() => {
|
|
465
|
-
this.buildSimulationUi(simulationUiInfo);
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
},
|
|
470
282
|
/**
|
|
471
283
|
* @public
|
|
472
284
|
* Run the simulation-based dataset directly on oSPARC. Not all simulation-based datasets can be run directly on
|
|
@@ -749,18 +561,8 @@ export default {
|
|
|
749
561
|
this.opencorOmexFile = this.id;
|
|
750
562
|
} else if (this.idType === IdType.PMR_PATH) {
|
|
751
563
|
this.opencorOmexFile = PMR_URL + this.id;
|
|
752
|
-
} else {
|
|
753
|
-
|
|
754
|
-
// the simulation UI.
|
|
755
|
-
|
|
756
|
-
this.userMessage = "Retrieving COMBINE archive...";
|
|
757
|
-
this.showUserMessage = true;
|
|
758
|
-
|
|
759
|
-
this.$nextTick(() => {
|
|
760
|
-
libOpenCOR().then((libopencor) => {
|
|
761
|
-
this.extractAndBuildSimulationUi(libopencor, this.id);
|
|
762
|
-
});
|
|
763
|
-
});
|
|
564
|
+
} else { // IdType.RAW_COMBINE_ARCHIVE
|
|
565
|
+
this.opencorOmexFile = this.id;
|
|
764
566
|
}
|
|
765
567
|
},
|
|
766
568
|
mounted: function () {
|
package/src/components/common.js
CHANGED
|
@@ -28,15 +28,6 @@ export function updateUi(parent) {
|
|
|
28
28
|
|
|
29
29
|
parent.$refs.simInput[index].visible = (input.visible === undefined) ? true : evaluateValue(parent, input.visible);
|
|
30
30
|
});
|
|
31
|
-
|
|
32
|
-
if (parent.libopencor !== undefined) {
|
|
33
|
-
parent.userMessage = "Running the model...";
|
|
34
|
-
parent.showUserMessage = true;
|
|
35
|
-
|
|
36
|
-
parent.$nextTick(() => {
|
|
37
|
-
parent.runSimulation();
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
31
|
});
|
|
41
32
|
}
|
|
42
33
|
|
package/src/components/json.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Validator } from "jsonschema";
|
|
2
2
|
import { OPENCOR_SOLVER_NAME } from "./common.js";
|
|
3
3
|
|
|
4
|
-
export function validJson(json
|
|
4
|
+
export function validJson(json) {
|
|
5
5
|
// Check the JSON against our schema.
|
|
6
6
|
|
|
7
7
|
const validator = new Validator();
|
|
@@ -214,7 +214,7 @@ export function validJson(json, simulationInfoNeeded) {
|
|
|
214
214
|
type: "array",
|
|
215
215
|
},
|
|
216
216
|
},
|
|
217
|
-
required:
|
|
217
|
+
required: true,
|
|
218
218
|
type: "object",
|
|
219
219
|
},
|
|
220
220
|
},
|
|
@@ -436,87 +436,85 @@ export function validJson(json, simulationInfoNeeded) {
|
|
|
436
436
|
|
|
437
437
|
// Make sure that the simulation information makes sense.
|
|
438
438
|
|
|
439
|
-
|
|
440
|
-
let needOpencorSettings = false;
|
|
441
|
-
|
|
442
|
-
if (!json.simulation.solvers.every((solver) => {
|
|
443
|
-
if (solver.if !== undefined) {
|
|
444
|
-
if (solver.if === "") {
|
|
445
|
-
console.warn("JSON: a simulation solver if must not be empty.");
|
|
446
|
-
|
|
447
|
-
return false;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
if (solver.input !== undefined) {
|
|
452
|
-
if (solver.input.name === "") {
|
|
453
|
-
console.warn("JSON: a simulation solver input name must not be empty.");
|
|
454
|
-
|
|
455
|
-
return false;
|
|
456
|
-
}
|
|
439
|
+
let needOpencorSettings = false;
|
|
457
440
|
|
|
458
|
-
|
|
459
|
-
|
|
441
|
+
if (!json.simulation.solvers.every((solver) => {
|
|
442
|
+
if (solver.if !== undefined) {
|
|
443
|
+
if (solver.if === "") {
|
|
444
|
+
console.warn("JSON: a simulation solver if must not be empty.");
|
|
460
445
|
|
|
461
|
-
|
|
462
|
-
}
|
|
446
|
+
return false;
|
|
463
447
|
}
|
|
448
|
+
}
|
|
464
449
|
|
|
465
|
-
|
|
466
|
-
|
|
450
|
+
if (solver.input !== undefined) {
|
|
451
|
+
if (solver.input.name === "") {
|
|
452
|
+
console.warn("JSON: a simulation solver input name must not be empty.");
|
|
467
453
|
|
|
468
454
|
return false;
|
|
469
455
|
}
|
|
470
456
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
if (solver.version === "") {
|
|
474
|
-
console.warn("JSON: a simulation solver version must not be empty.");
|
|
457
|
+
if (solver.input.value === "") {
|
|
458
|
+
console.warn("JSON: a simulation solver input value must not be empty.");
|
|
475
459
|
|
|
476
460
|
return false;
|
|
477
461
|
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (solver.name === "") {
|
|
465
|
+
console.warn("JSON: a simulation solver name must not be empty.");
|
|
478
466
|
|
|
479
|
-
return true;
|
|
480
|
-
})) {
|
|
481
467
|
return false;
|
|
482
468
|
}
|
|
483
469
|
|
|
484
|
-
|
|
485
|
-
|
|
470
|
+
needOpencorSettings = needOpencorSettings || (solver.name === OPENCOR_SOLVER_NAME);
|
|
471
|
+
|
|
472
|
+
if (solver.version === "") {
|
|
473
|
+
console.warn("JSON: a simulation solver version must not be empty.");
|
|
486
474
|
|
|
487
475
|
return false;
|
|
488
476
|
}
|
|
489
477
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
478
|
+
return true;
|
|
479
|
+
})) {
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
493
482
|
|
|
494
|
-
|
|
495
|
-
|
|
483
|
+
if (needOpencorSettings && (json.simulation.opencor === undefined)) {
|
|
484
|
+
console.warn("JSON: the simulation solver for OpenCOR is specified so simulation OpenCOR settings must also be specified.");
|
|
496
485
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
if (json.simulation.opencor.endingPoint <= 0.0) {
|
|
500
|
-
console.warn("JSON: the simulation OpenCOR ending point (" + json.simulation.opencor.endingPoint + ") must be greater than zero.");
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
501
488
|
|
|
502
|
-
|
|
503
|
-
|
|
489
|
+
if (json.simulation.opencor !== undefined) {
|
|
490
|
+
if (json.simulation.opencor.resource === "") {
|
|
491
|
+
console.warn("JSON: the simulation OpenCOR resource must not be empty.");
|
|
504
492
|
|
|
505
|
-
|
|
506
|
-
|
|
493
|
+
return false;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (json.simulation.opencor.endingPoint !== undefined) {
|
|
497
|
+
if (json.simulation.opencor.pointInterval !== undefined) {
|
|
498
|
+
if (json.simulation.opencor.endingPoint <= 0.0) {
|
|
499
|
+
console.warn("JSON: the simulation OpenCOR ending point (" + json.simulation.opencor.endingPoint + ") must be greater than zero.");
|
|
500
|
+
|
|
501
|
+
return false;
|
|
502
|
+
}
|
|
507
503
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
} else {
|
|
511
|
-
console.warn("JSON: a simulation OpenCOR ending point is specified so a simulation OpenCOR point interval must also be specified.");
|
|
504
|
+
if (json.simulation.opencor.pointInterval <= 0.0) {
|
|
505
|
+
console.warn("JSON: the simulation OpenCOR point interval (" + json.simulation.opencor.pointInterval + ") must be greater than zero.");
|
|
512
506
|
|
|
513
507
|
return false;
|
|
514
508
|
}
|
|
515
|
-
} else
|
|
516
|
-
console.warn("JSON: a simulation OpenCOR point
|
|
509
|
+
} else {
|
|
510
|
+
console.warn("JSON: a simulation OpenCOR ending point is specified so a simulation OpenCOR point interval must also be specified.");
|
|
517
511
|
|
|
518
512
|
return false;
|
|
519
513
|
}
|
|
514
|
+
} else if (json.simulation.opencor.pointInterval !== undefined) {
|
|
515
|
+
console.warn("JSON: a simulation OpenCOR point interval is specified so a simulation OpenCOR ending point must also be specified.");
|
|
516
|
+
|
|
517
|
+
return false;
|
|
520
518
|
}
|
|
521
519
|
}
|
|
522
520
|
|