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