1 /* siminit.c
2
3 Copyright (c) 1991-2017 Free Software Foundation, Inc.
4
5 This file is part of GNU MCSim.
6
7 GNU MCSim is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 3
10 of the License, or (at your option) any later version.
11
12 GNU MCSim is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU MCSim; if not, see <http://www.gnu.org/licenses/>
19
20 Contains initialization routines for the simulation
21 */
22
23 #include <stdlib.h>
24
25 #include "lexerr.h"
26 #include "modelu.h"
27 #include "random.h"
28 #include "simi.h"
29 #include "siminit.h"
30
31
32 /* ----------------------------------------------------------------------------
33 GetModelInfo
34
35 Gets information about the model that we are using for all of the
36 simulations.
37 */
38
GetModelInfo(PMODELINFO pmi)39 void GetModelInfo (PMODELINFO pmi)
40 {
41 pmi->nModelVars = (long) GetNModelVars ();
42 pmi->pdModelVars = GetModelVector ();
43
44 if ((pmi->nStates = (long) GetNStates()) != 0) { /* FB improved 28/07/97 */
45 if (!(pmi->pStateHvar = (HVAR*) malloc (pmi->nStates * sizeof(HVAR))))
46 ReportError(NULL, RE_OUTOFMEM | RE_FATAL, "GetModelInfo", NULL);
47
48 GetStateHandles (pmi->pStateHvar);
49 }
50 else {
51 pmi->pStateHvar = NULL;
52 }
53
54 } /* GetModelInfo */
55
56
57 /* ----------------------------------------------------------------------------
58 InitIntegratorSpec
59 */
60
InitIntegratorSpec(PINTSPEC pis)61 void InitIntegratorSpec (PINTSPEC pis)
62 {
63 pis->iAlgo = IAL_DEFAULT;
64
65 pis->dRtol = RTOL_DEFAULT;
66 pis->dAtol = ATOL_DEFAULT;
67
68 /* Lsodes specific */
69 pis->iopt = IOPT_DEFAULT;
70 pis->itask = ITASK_DEFAULT;
71 pis->itol = ITOL_DEFAULT;
72 pis->iMf = IMF_DEFAULT;
73 pis->liw = LSODES_IWORKSIZE;
74 pis->lrw = LSODES_RWORKSIZE;
75
76 /* Cvodes specific */
77 pis->maxsteps = MXSTEPS_DEFAULT;
78 pis->maxnef = MAXNEF_DEFAULT;
79 pis->maxcor = MAXCOR_DEFAULT;
80 pis->maxncf = MAXNCF_DEFAULT;
81 pis->nlscoef = NLSCOEF_DEFAULT;
82
83 if ( !(pis->iwork = InitlVector (pis->liw)) ||
84 !(pis->rwork = InitdVector (pis->lrw)))
85 ReportError (NULL, RE_OUTOFMEM | RE_FATAL,
86 "InitIntegratorSpec()", NULL);
87
88 /* Euler specific */
89 pis->dTStep = TSTEP_DEFAULT;
90
91 } /* InitIntegratorSpec */
92
93
94 /* ----------------------------------------------------------------------------
95 InitOutputSpec
96 */
97
InitOutputSpec(POUTSPEC pos)98 void InitOutputSpec (POUTSPEC pos)
99 {
100 pos->nOutputs = 0;
101 pos->pszOutputNames = NULL;
102 pos->phvar_out = NULL;
103
104 pos->nData = 0;
105 pos->pszDataNames = NULL;
106 pos->phvar_dat = NULL;
107
108 pos->plistPrintRecs = NULL; /* List of Print() records read in */
109 pos->plistDataRecs = NULL; /* List of Data() records read in */
110
111 pos->pcOutputTimes = NULL; /* Count of output times for each var */
112 pos->piCurrentOut = NULL; /* Index to current output for each var */
113 pos->prgdOutputTimes = NULL; /* Array of output times for each var */
114 pos->prgdOutputVals = NULL; /* Array of output values for each var */
115
116 pos->pcData = NULL;
117 pos->prgdDataVals = NULL; /* Array of data values for each var */
118
119 pos->cDistinctTimes = 0; /* Init output times list to empty */
120 pos->rgdDistinctTimes = NULL;
121
122 } /* InitOutputSpec */
123
124
125 /* ----------------------------------------------------------------------------
126 InitExperiment
127
128 */
129
InitExperiment(PEXPERIMENT pexp,PMODELINFO pmodelinfo)130 void InitExperiment (PEXPERIMENT pexp, PMODELINFO pmodelinfo)
131 {
132 pexp->iExp = 0; /* Number of current experiment */
133 pexp->dT0 = T0_DEFAULT; /* Simulation times */
134 pexp->dTfinal = TFINAL_DEFAULT;
135
136 pexp->dTime = 0.0; /* Current time, not used for global */
137
138 pexp->pmodelinfo = pmodelinfo; /* Same model for all experiments */
139 pexp->plistParmMods = InitList(); /* List of parameter modifications */
140
141 InitIntegratorSpec (&pexp->is);
142 InitOutputSpec (&pexp->os);
143
144 } /* InitExperiment */
145
146
147 /* ----------------------------------------------------------------------------
148 InitMonteCarlo
149
150 */
151
InitMonteCarlo(PMONTECARLO pmc)152 void InitMonteCarlo (PMONTECARLO pmc)
153 {
154 pmc->nRuns = NSIMULATIONS_DEFAULT;
155
156 pmc->szMCOutfilename = NULL; /* File name for Monte Carlo output */
157 pmc->pfileMCOut = NULL; /* Output file for Monte Carlo */
158
159 pmc->szSetPointsFilename = NULL;
160 pmc->pfileSetPoints = NULL;
161
162 pmc->plistMCVars = NULL;
163 pmc->rgdParms = NULL;
164 pmc->rghvar = NULL;
165 pmc->rgpMCVar = NULL;
166
167 } /* InitMonteCarlo */
168
169
170 /* ----------------------------------------------------------------------------
171 InitGibbs
172 */
173
InitGibbs(PGIBBSDATA pgd)174 void InitGibbs (PGIBBSDATA pgd)
175 {
176 pgd->nMaxIter = NSIMULATIONS_DEFAULT;
177 pgd->nSimTypeFlag = 0;
178 pgd->nPrintIter = NSIMULATIONS_DEFAULT;
179 pgd->nPrintFreq = 1;
180 pgd->nMaxPerkSetIter = 300000;
181
182 pgd->szGout = NULL; /* Filename for Gibbs output */
183 pgd->pfileOut = NULL; /* File for Gibbs output */
184
185 pgd->szGrestart = NULL; /* Parm file for restarting Gibbs */
186 pgd->pfileRestart = NULL; /* File for Gibbs restart */
187
188 pgd->szGdata = NULL; /* Filename for Gibbs input data */
189
190 /* for tempered MCMC */
191 pgd->nPerks = 0; /* number of perks (inverse temperatures) */
192 pgd->indexT = 0; /* start at hot temperature */
193 pgd->dCZero = 100;
194 pgd->dNZero = 100; /* must be > 0 */
195 pgd->startT = 0;
196 pgd->endT = 0;
197
198 pgd->rglTransAttempts = NULL;
199 pgd->rglTransAccepts = NULL;
200
201 } /* InitGibbs */
202
203
204 /* ----------------------------------------------------------------------------
205 InitAnalysis
206
207 Initializes an analysis structure and its associated
208 sub-structures for integration, output, experiments, and
209 Monte Carlo.
210 */
211
InitAnalysis(PANALYSIS panal)212 void InitAnalysis (PANALYSIS panal)
213 {
214 int i;
215
216 if (!panal) return;
217
218 /* those will eventually be changed by command-line options */
219 panal->bDependents = FALSE;
220 panal->bOutputIter = FALSE;
221 panal->nOutputFreq = 0;
222 panal->bPrintConvergence = FALSE;
223
224 panal->iType = AT_DEFAULTSIM; /* Type of analysis, default to simple sim */
225
226 panal->dSeed = SEED_DEFAULT; /* The random generator seed for everybody */
227
228 panal->wContext = CN_GLOBAL; /* Begin in global context */
229 panal->pexpCurrent = &panal->expGlobal;
230
231 GetModelInfo (&panal->modelinfo); /* The model we are using */
232
233 /* Global experiment settings */
234 InitExperiment (&panal->expGlobal, &panal->modelinfo);
235
236 panal->szOutfilename = NULL;
237 panal->pfileOut = NULL;
238 panal->bCommandLineSpec = FALSE;
239 panal->bAllocatedFileName = FALSE;
240
241 /* Init all experiments NULL */
242 panal->iExpts = 0;
243 for (i = 0; i < MAX_INSTANCES; i++) panal->rgpExps[i] = NULL;
244
245 InitMonteCarlo (&panal->mc); /* Monte Carlo specifications */
246 InitGibbs (&panal->gd); /* Gibbs specifications */
247
248 } /* InitAnalysis */
249
250
251 /* ----------------------------------------------------------------------------
252 InitOutputs
253
254 Returns TRUE if ok, FALSE otherwise.
255 */
256
InitOutputs(PEXPERIMENT pexp,PINT piOut,PDOUBLE pdTout)257 BOOL InitOutputs (PEXPERIMENT pexp, PINT piOut, PDOUBLE pdTout)
258 {
259 int j;
260 BOOL bReturn = FALSE;
261
262 if (!pexp->os.nOutputs)
263 ReportError (NULL, RE_NOOUTPUTS, (PSTR) &pexp->iExp, NULL);
264
265 else {
266 *piOut = 0; /* Keep track of out times */
267 *pdTout = pexp->os.rgdDistinctTimes[0];
268 for (j = 0; j < pexp->os.nOutputs; j++)
269 pexp->os.piCurrentOut[j] = 0;
270
271 bReturn = TRUE;
272 } /* else */
273
274 return (bReturn);
275
276 } /* InitOutputs */
277
278
279 /* ----------------------------------------------------------------------------
280 InitOneOutVar
281
282 Initializes information for one output to be printed. Creates space
283 for outputs.
284 */
285
InitOneOutVar(PVOID pData,PVOID pInfo)286 int InitOneOutVar (PVOID pData, PVOID pInfo)
287 {
288 PPRINTREC ppr = (PPRINTREC) pData;
289 POUTSPEC pos = (POUTSPEC) pInfo;
290 int i = pos->nOutputs++; /* Index of current cell */
291
292 pos->pszOutputNames[i] = ppr->szOutputName;
293 pos->phvar_out[i] = ppr->hvar;
294 pos->pcOutputTimes[i] = ppr->cTimes;
295 pos->piCurrentOut[i] = 0;
296
297 pos->prgdOutputTimes[i] = ppr->pdTimes;
298 pos->prgdOutputVals[i] = InitdVector (ppr->cTimes);
299 if (pos->prgdOutputTimes[i] == NULL || pos->prgdOutputVals[i] == NULL)
300 ReportError (NULL, RE_OUTOFMEM | RE_FATAL, "InitOneOutVar()", NULL);
301
302 return 0;
303
304 } /* InitOneOutVar */
305
306
307 /* ----------------------------------------------------------------------------
308 InitOneDataVar
309
310 Initializes information for one data specification.
311 */
312
InitOneDataVar(PVOID pData,PVOID pInfo)313 int InitOneDataVar (PVOID pData, PVOID pInfo)
314 {
315
316 PDATAREC pda = (PDATAREC) pData;
317 POUTSPEC pos = (POUTSPEC) pInfo;
318 int i = pos->nData++; /* Index of current cell */
319
320 pos->prgdDataVals[i] = pda->pdData; /* point to the data read in */
321 pos->pcData[i] = pda->cData;
322 pos->phvar_dat[i] = pda->hvar;
323 pos->pszDataNames[i] = pda->szDataName;
324
325 return 0;
326
327 } /* InitOneDataVar */
328
329
330 /* ----------------------------------------------------------------------------
331 FindNewPoint
332
333 Finds the new point. Return FALSE if the sort is finished, i.e. no
334 new point can be found.
335 */
336
FindNewPoint(POUTSPEC pos,PINT piPoint)337 BOOL FindNewPoint (POUTSPEC pos, PINT piPoint)
338 {
339 for (*piPoint = 0; *piPoint < pos->nOutputs; (*piPoint)++)
340 if (pos->piCurrentOut[*piPoint] < pos->pcOutputTimes[*piPoint])
341 break;
342
343 return (*piPoint < pos->nOutputs ? TRUE : FALSE);
344
345 } /* FindNewPoint */
346
347
348 /* ----------------------------------------------------------------------------
349 CreateOutputSchedule
350
351 Creates a single output time array from the individual times. This
352 will be used to efficiently schedule the outputs.
353
354 This routines sorts n sorted arrays into 1 array of undetermined
355 length omitting duplicate entries.
356
357 The algorithm works as follows. A counter is kept into each
358 array. A current test "point" is found as the element of the
359 first array whose counter is not past the end. Thus, we start
360 with the point at the first element of the first array.
361
362 Looping through the list of arrays, if another array is found
363 whose counter element is less than the point, then the point is
364 switched to this element. If no such element is found, the point
365 is added to the new list. If an array element found which is equal
366 to the point the counter for that array is incremented.
367
368 The pos->piCurrentOut fields are used for counters. They are not
369 reset, since InitOutputs() must be called before running the
370 simulation anyway.
371 */
372
CreateOutputSchedule(POUTSPEC pos)373 void CreateOutputSchedule (POUTSPEC pos)
374 {
375 int i, cTimes = 0, iPoint;
376 BOOL bCont = TRUE;
377
378 for (i = 0; i < pos->nOutputs; i++) /* Find max size of array */
379 cTimes += pos->pcOutputTimes[i];
380
381 if ( !(pos->rgdDistinctTimes = InitdVector (cTimes)))
382 ReportError (NULL, RE_OUTOFMEM | RE_FATAL, "CreateOutputSchedule()",NULL);
383
384 cTimes = 0;
385 FindNewPoint (pos, &iPoint);
386 while (bCont) {
387
388 for (i = 0; i < pos->nOutputs; i++)
389 if (i != iPoint && pos->piCurrentOut[i] < pos->pcOutputTimes[i]) {
390
391 if (pos->prgdOutputTimes[i][pos->piCurrentOut[i]]
392 < pos->prgdOutputTimes[iPoint][pos->piCurrentOut[iPoint]])
393 iPoint = i;
394
395 else if (pos->prgdOutputTimes[i][pos->piCurrentOut[i]]
396 == pos->prgdOutputTimes[iPoint][pos->piCurrentOut[iPoint]])
397 pos->piCurrentOut[i]++;
398 } /* if */
399
400 pos->rgdDistinctTimes[cTimes++] =
401 pos->prgdOutputTimes[iPoint][pos->piCurrentOut[iPoint]];
402
403 if (++pos->piCurrentOut[iPoint] >= pos->pcOutputTimes[iPoint])
404 bCont = FindNewPoint (pos, &iPoint);
405
406 } /* while */
407
408 pos->cDistinctTimes = cTimes; /* Save number of distinct times */
409
410 } /* CreateOutputSchedule */
411
412
413 /* ----------------------------------------------------------------------------
414 PrepareOutSpec
415
416 Prepares an output spec determined by the plistPrintRecs
417 and plistDataRecs specifications.
418 Adjusts final time eventually to match the last output time
419 */
420
PrepareOutSpec(PEXPERIMENT pexp)421 BOOL PrepareOutSpec (PEXPERIMENT pexp)
422 {
423 POUTSPEC pos = &pexp->os;
424 BOOL bReturn = FALSE;
425 int cDat = ListLength(pos->plistDataRecs);
426 int cOut = ListLength(pos->plistPrintRecs);
427
428 if (!cOut)
429 ReportError (NULL, RE_NOOUTPUTS, (PSTR) &pexp->iExp, NULL);
430 else { /* ok, cOut is not null */
431 pos->pszOutputNames = (PSTR *) malloc (cOut * sizeof(PSTR));
432 pos->phvar_out = (HVAR *) malloc (cOut * sizeof(HVAR));
433 pos->pcOutputTimes = InitiVector (cOut);
434 pos->piCurrentOut = InitiVector (cOut);
435 pos->prgdOutputTimes = InitpdVector (cOut);
436 pos->prgdOutputVals = InitpdVector (cOut);
437
438 if (pos->pszOutputNames == NULL || pos->phvar_out == NULL ||
439 pos->pcOutputTimes == NULL || pos->piCurrentOut == NULL ||
440 pos->prgdOutputTimes == NULL || pos->prgdOutputVals == NULL)
441 ReportError (NULL, RE_OUTOFMEM | RE_FATAL, "PrepareOutSpec()", NULL);
442 else {
443 pos->nOutputs = 0; /* Current cell counter in callback */
444 ForAllList (pos->plistPrintRecs, InitOneOutVar, (PVOID) &pexp->os);
445 pos->nOutputs = cOut; /* Set count of outputs for real */
446
447 CreateOutputSchedule (pos); /* Create single output time list */
448
449 /* Adjust the final time to match the last output time */
450 pexp->dTfinal = pos->rgdDistinctTimes[pos->cDistinctTimes - 1];
451
452 if (pexp->dTfinal == pexp->dT0) {
453 printf ("\nError: starting and final times are equal in Simulation %d "
454 "- Exiting.\n\n", pexp->iExp);
455 exit(0);
456 }
457
458 bReturn = TRUE;
459
460 } /* else */
461 } /* else */
462
463 if (!cDat)
464 ; /* cDat is null, but it's allowed */
465 else { /* ok, cDat is not null */
466 pos->prgdDataVals = InitpdVector (cDat);
467 pos->pcData = InitiVector (cDat);
468 pos->pszDataNames = (PSTR *) malloc (cDat * sizeof(PSTR));
469 pos->phvar_dat = (HVAR *) malloc (cDat * sizeof(HVAR));
470
471 if (pos->prgdDataVals == NULL || pos->phvar_dat == NULL ||
472 pos->pszDataNames == NULL || pos->pcData == NULL)
473 ReportError (NULL, RE_OUTOFMEM | RE_FATAL, "PrepareOutSpec()", NULL);
474 else {
475 pos->nData = 0; /* Current cell counter in callback */
476 ForAllList (pos->plistDataRecs, InitOneDataVar, (PVOID) &pexp->os);
477 pos->nData = cDat; /* Set count of data for real */
478
479 /* ForAllList(pos->plistDataRecs, &FreeDataRec, NULL); */
480 FreeList (&pos->plistDataRecs, NULL, FALSE);
481 } /* else */
482 } /* else */
483
484 return (bReturn);
485
486 } /* PrepareOutSpec */
487
488
489 /* ----------------------------------------------------------------------------
490 PrintOutSpec
491
492 */
493
PrintOutSpec(PEXPERIMENT pexp)494 BOOL PrintOutSpec (PEXPERIMENT pexp)
495 {
496 POUTSPEC pos = &pexp->os;
497 int j, i, cOut = pos->nOutputs;
498
499 printf ("%d Outputs:\n", cOut);
500
501 for (i = 0; i < cOut; i++) {
502 printf (" %#0lx %s: ", pos->phvar_out[i], pos->pszOutputNames[i]);
503 for (j = 0; j < pos->pcOutputTimes[i]; j++)
504 printf ("%g ", pos->prgdOutputTimes[i][j]);
505 printf ("\n");
506 }
507
508 return 0;
509
510 } /* PrintOutSpec */
511
512 /* End */
513