-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmdl.c
131 lines (105 loc) · 2.57 KB
/
mdl.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright 2014 Bobby Powers. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sd.h"
typedef struct {
double *series;
} Result;
static void die(const char *, ...);
static void usage(void);
static const char *argv0;
void __attribute__((noreturn))
die(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
exit(EXIT_FAILURE);
}
void
usage(void)
{
die("Usage: %s [OPTION...] PATH\n" \
"Simulate system dynamics models.\n\n" \
"Options:\n" \
" -help:\tshow this message\n",
argv0);
}
int
main(int argc, char *const argv[])
{
int err = 0;
SDProject *p;
SDSim *s;
int nvars, nsteps, n;
Result *results;
const char *fmt;
const char **names = NULL;
const char *path = NULL;
for (argv0 = argv[0], argv++, argc--; argc > 0; argv++, argc--) {
char const* arg = argv[0];
if (strcmp("-help", arg) == 0) {
usage();
} else if (arg[0] == '-') {
fprintf(stderr, "unknown arg '%s'\n", arg);
usage();
} else {
if (!path) {
path = arg;
} else {
fprintf(stderr, "specify a single path to a model\n");
usage();
}
}
}
if (!path) {
fprintf(stderr, "specify a single path to a model\n");
usage();
}
p = sd_project_open(path, &err);
if (err)
die("error opening project: %s\n", sd_error_str(err));
s = sd_sim_new(p, NULL);
if (!s)
die("couldn't create simulation context\n");
sd_sim_run_to_end(s);
nsteps = sd_sim_get_stepcount(s);
nvars = sd_sim_get_varcount(s);
names = calloc(nvars, sizeof(*names));
results = calloc(nvars, sizeof(*results));
if (!names || !results)
die("out of memory\n");
if (sd_sim_get_varnames(s, names, nvars) != nvars)
die("get_varnames unexpected result != %d\n", nvars);
for (int v = 0; v < nvars; v++) {
Result *result = results + v;
result->series = calloc(nsteps, sizeof(double));
n = sd_sim_get_series(s, names[v], result->series, nsteps);
if (n != nsteps)
die("short series read of %d for '%s' (%d/%d)\n", n, names[v], v, nvars);
fmt = v == nvars-1 ? "%s\n" : "%s\t";
printf(fmt, names[v]);
}
for (int i = 0; i < nsteps; i++) {
for (int v = 0; v < nvars; v++) {
Result *result = results + v;
fmt = v == nvars-1 ? "%f\n" : "%f\t";
printf(fmt, result->series[i]);
}
}
for (int i = 0; i < nvars; i++) {
Result *r = results + i;
free(r->series);
}
free(results);
free(names);
sd_sim_unref(s);
sd_project_unref(p);
fflush(stdout);
return 0;
}