piegy 2.3.6__tar.gz → 2.3.7__tar.gz

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.
Files changed (34) hide show
  1. {piegy-2.3.6 → piegy-2.3.7}/MANIFEST.in +1 -0
  2. {piegy-2.3.6/src/piegy.egg-info → piegy-2.3.7}/PKG-INFO +1 -1
  3. {piegy-2.3.6 → piegy-2.3.7}/pyproject.toml +1 -1
  4. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/C_core/patch.c +8 -4
  5. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/C_core/patch.h +5 -5
  6. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/C_core/sim_funcs.c +80 -79
  7. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/C_core/sim_funcs.h +18 -16
  8. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/__version__.py +2 -1
  9. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/data_tools.py +29 -41
  10. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/figures.py +3 -3
  11. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/simulation.py +4 -4
  12. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/test_var.py +15 -9
  13. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/tools/figure_tools.py +1 -1
  14. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/tools/find_C.py +3 -4
  15. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/videos.py +14 -11
  16. {piegy-2.3.6 → piegy-2.3.7/src/piegy.egg-info}/PKG-INFO +1 -1
  17. {piegy-2.3.6 → piegy-2.3.7}/src/piegy.egg-info/SOURCES.txt +0 -1
  18. piegy-2.3.6/src/piegy/C_core/runner.c +0 -61
  19. {piegy-2.3.6 → piegy-2.3.7}/LICENSE.txt +0 -0
  20. {piegy-2.3.6 → piegy-2.3.7}/README.md +0 -0
  21. {piegy-2.3.6 → piegy-2.3.7}/setup.cfg +0 -0
  22. {piegy-2.3.6 → piegy-2.3.7}/setup.py +0 -0
  23. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/C_core/Makefile +0 -0
  24. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/C_core/model.c +0 -0
  25. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/C_core/model.h +0 -0
  26. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/__init__.py +0 -0
  27. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/analysis.py +0 -0
  28. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/build_info.py +0 -0
  29. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/simulation_py.py +0 -0
  30. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/tools/__init__.py +0 -0
  31. {piegy-2.3.6 → piegy-2.3.7}/src/piegy/tools/file_tools.py +0 -0
  32. {piegy-2.3.6 → piegy-2.3.7}/src/piegy.egg-info/dependency_links.txt +0 -0
  33. {piegy-2.3.6 → piegy-2.3.7}/src/piegy.egg-info/requires.txt +0 -0
  34. {piegy-2.3.6 → piegy-2.3.7}/src/piegy.egg-info/top_level.txt +0 -0
@@ -4,3 +4,4 @@ include LICENSE.txt
4
4
  include src/piegy/C_core/*.c
5
5
  include src/piegy/C_core/*.h
6
6
  include src/piegy/C_core/Makefile
7
+ exclude src/piegy/C_core/runner.c
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: piegy
3
- Version: 2.3.6
3
+ Version: 2.3.7
4
4
  Summary: Payoff-Driven Stochastic Spatial Model for Evolutionary Game Theory
5
5
  Author-email: Chenning Xu <cxu7@caltech.edu>
6
6
  License: BSD 3-Clause License
@@ -4,7 +4,7 @@ build-backend = 'setuptools.build_meta'
4
4
 
5
5
  [project]
6
6
  name = 'piegy'
7
- version = '2.3.6'
7
+ version = '2.3.7'
8
8
  description = 'Payoff-Driven Stochastic Spatial Model for Evolutionary Game Theory'
9
9
  readme = 'README.md'
10
10
  requires-python = '>=3.7'
@@ -5,10 +5,10 @@
5
5
 
6
6
  #include "patch.h"
7
7
 
8
- void patch_init(patch_t* p, uint32_t U, uint32_t V, size_t i, size_t j) {
8
+ void patch_init(patch_t* p, uint32_t U, uint32_t V, size_t row, size_t col) {
9
9
  if (p == NULL) return;
10
- p->i = i;
11
- p->j = j;
10
+ p->row = row;
11
+ p->col = col;
12
12
 
13
13
  p->U = U;
14
14
  p->V = V;
@@ -30,14 +30,18 @@ void patch_init(patch_t* p, uint32_t U, uint32_t V, size_t i, size_t j) {
30
30
  }
31
31
 
32
32
 
33
- void set_nb(patch_t* world, size_t* nb_start, size_t ij, size_t NM) {
33
+ void set_nb(patch_t* world, double* P_start, size_t* nb_start, size_t ij, size_t NM) {
34
34
  // nb_start is the where patch ij's neighbor indices start
35
+ size_t num_nb = 0;
35
36
  for (size_t k = 0; k < 4; k++) {
36
37
  if (nb_start[k] != NM) {
37
38
  // neighbor is valid
38
39
  world[ij].nb[k] = &world[nb_start[k]];
40
+ num_nb += 1;
39
41
  } else {
40
42
  world[ij].nb[k] = NULL;
41
43
  }
42
44
  }
45
+ P_start[0] *= (0.25 * num_nb); // scale total migration rates by how many neighbors the patch has
46
+ P_start[1] *= (0.25 * num_nb);
43
47
  }
@@ -14,10 +14,10 @@
14
14
 
15
15
 
16
16
  typedef struct patch_t {
17
- size_t i;
18
- size_t j;
17
+ size_t row;
18
+ size_t col;
19
19
 
20
- uint32_t U;
20
+ uint32_t U; // store as double directly to avoid runtime conversion (to double)
21
21
  uint32_t V;
22
22
  double U_pi;
23
23
  double V_pi;
@@ -34,8 +34,8 @@ typedef struct patch_t {
34
34
  } patch_t;
35
35
 
36
36
  // in .c
37
- void patch_init(patch_t* p, uint32_t U, uint32_t V, size_t i, size_t j);
38
- void set_nb(patch_t* world, size_t* nb_start, size_t ij, size_t NM);
37
+ void patch_init(patch_t* p, uint32_t U, uint32_t V, size_t row, size_t col);
38
+ void set_nb(patch_t* world, double* P_start, size_t* nb_start, size_t ij, size_t NM) ;
39
39
 
40
40
  #endif // PATCH_H
41
41
 
@@ -76,68 +76,60 @@ static double single_init(const model_t* restrict mod, patch_t* restrict world,
76
76
  size_t M = mod->M;
77
77
  size_t NM = N * M;
78
78
  size_t max_record = mod->max_record;
79
- size_t ij = 0; // used to track index i * M + j in double for loops
79
+ size_t ij_out = 0; // used to track index i * M + j in double for loops, "out" means not the "looper" in for loop
80
80
 
81
81
  // init world
82
82
  for (size_t i = 0; i < N; i++) {
83
83
  for (size_t j = 0; j < M; j++) {
84
- patch_init(&world[ij], mod->I[ij * 2], mod->I[ij * 2 + 1], i, j);
85
- ij++;
84
+ patch_init(&world[ij_out], mod->I[ij_out * 2], mod->I[ij_out * 2 + 1], i, j);
85
+ ij_out++;
86
86
  }
87
87
  }
88
88
 
89
89
  // init nb_indices
90
- ij = 0;
90
+ ij_out = 0;
91
91
  if (mod->boundary) {
92
92
  for (size_t i = 0; i < N; i++) {
93
93
  for (size_t j = 0; j < M; j++) {
94
- find_nb_zero_flux(&nb_indices[ij * 4], i, j, N, M, NM);
95
- ij++;
94
+ find_nb_zero_flux(&nb_indices[ij_out * 4], i, j, N, M, NM);
95
+ ij_out++;
96
96
  }
97
97
  }
98
98
  } else {
99
99
  for (size_t i = 0; i < N; i++) {
100
100
  for (size_t j = 0; j < M; j++) {
101
- find_nb_periodical(&nb_indices[ij * 4], i, j, N, M, NM);
102
- ij++;
101
+ find_nb_periodical(&nb_indices[ij_out * 4], i, j, N, M, NM);
102
+ ij_out++;
103
103
  }
104
104
  }
105
105
  }
106
106
 
107
107
 
108
108
  // set nb pointers for patches
109
- ij = 0;
110
- for (size_t i = 0; i < N; i++) {
111
- for (size_t j = 0; j < M; j++) {
112
- set_nb(world, &nb_indices[ij * 4], ij, NM);
113
- ij++;
114
- }
109
+ for (size_t ij = 0; ij < NM; ij++) {
110
+ set_nb(world, &(mod->P[ij * 6]), &nb_indices[ij * 4], ij, NM);
115
111
  }
116
112
 
117
113
  //////// Begin Running ////////
118
114
 
119
115
  // init payoff & natural death rates
120
- ij = 0;
121
- for (size_t i = 0; i < N; i++) {
122
- for (size_t j = 0; j < M; j++) {
123
- update_pi_k(&world[ij], &(mod->X[ij * 4]), &(mod->P[ij * 6]));
124
- ij++;
125
- }
116
+ for (size_t ij = 0; ij < N; ij++) {
117
+ update_pi_k(&world[ij], &(mod->X[ij * 4]), &(mod->P[ij * 6]));
126
118
  }
127
119
 
128
120
  // init migration rates & store patch rates
129
- ij = 0;
121
+ ij_out = 0;
130
122
  for (size_t i = 0; i < N; i++) {
131
123
  for (size_t j = 0; j < M; j++) {
132
- uint8_t mig_result = init_mig(&world[ij], &(mod->P[ij * 6])); // init mig rates for all 4 directions
124
+ uint8_t mig_result = init_mig(&world[ij_out], &(mod->P[ij_out * 6])); // init mig rates for all 4 directions
133
125
  if (mig_result == SIM_OVERFLOW) {
134
126
  return -1 * SIM_OVERFLOW;
135
127
  }
136
- double ij_rates = world[ij].sum_pi_death_rates + world[ij].sum_mig_rates;
137
- patch_rates[ij] = ij_rates;
128
+ double ij_rates = world[ij_out].sum_pi_death_rates + world[ij_out].sum_mig_rates;
129
+ patch_rates[ij_out] = ij_rates;
138
130
  sum_rates_by_row[i] += ij_rates;
139
131
  *sum_rates_p = *sum_rates_p + ij_rates; // can't do *sum_rates_p += ij_rates
140
- ij++;
132
+ ij_out++;
141
133
  }
142
134
  }
143
135
 
@@ -176,18 +168,16 @@ static double single_init(const model_t* restrict mod, patch_t* restrict world,
176
168
  // store data
177
169
  if (time > mod->record_itv) {
178
170
  size_t recod_idx = (size_t) (time / mod->record_itv);
179
- ij = 0;
180
- for (size_t i = 0; i < N; i++) {
181
- for (size_t j = 0; j < M; j++) {
182
- for (size_t k = 0; k < recod_idx; k++) {
183
- mod->U1d[ij * max_record + k] += world[ij].U;
184
- mod->V1d[ij * max_record + k] += world[ij].V;
185
- mod->Upi_1d[ij * max_record + k] += world[ij].U_pi;
186
- mod->Vpi_1d[ij * max_record + k] += world[ij].V_pi;
187
- }
188
- ij++;
171
+
172
+ for (size_t ij = 0; ij < NM; ij++) {
173
+ size_t ij_max_record = ij * max_record;
174
+ for (size_t k = 0; k < recod_idx; k++) {
175
+ mod->U1d[ij_max_record + k] += world[ij].U;
176
+ mod->V1d[ij_max_record + k] += world[ij].V;
177
+ mod->Upi_1d[ij_max_record + k] += world[ij].U_pi;
178
+ mod->Vpi_1d[ij_max_record + k] += world[ij].V_pi;
189
179
  }
190
- }
180
+ }
191
181
  }
192
182
 
193
183
  return time;
@@ -204,10 +194,15 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
204
194
  size_t max_record = mod->max_record;
205
195
  double record_itv = mod->record_itv;
206
196
  bool boundary = mod->boundary;
197
+ double* X = mod->X;
198
+ double* P = mod->P;
199
+ double* U1d = mod->U1d;
200
+ double* V1d = mod->V1d;
201
+ double* Upi_1d = mod->Upi_1d;
202
+ double* Vpi_1d = mod->Vpi_1d;
207
203
 
208
204
  // print progress
209
205
  double one_progress = 0.0;
210
- double current_progress = one_progress;
211
206
  if (mod->print_pct != -1) {
212
207
  one_progress = maxtime * mod->print_pct / 100.0;
213
208
  fprintf(stdout, "\r ");
@@ -216,12 +211,13 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
216
211
  } else {
217
212
  one_progress = 2.0 * maxtime;
218
213
  }
214
+ double current_progress = one_progress;
219
215
 
220
216
  // update sum of rates every 1e5 rounds
221
217
  // many rates are updated each time, rather than re-calculated.
222
218
  // So need to re-calculate from scratch every some rounds to reduce numerical errors
223
219
  size_t curr_update_sum_round = 0; // current round
224
- size_t update_sum_rounds = UPDATE_SUM_ROUNDS_SM; // recalculate sum every this many rounds
220
+ size_t update_sum_freq = UPDATE_SUM_ROUNDS_SM; // recalculate sum every this many rounds
225
221
 
226
222
  // Initialize simulation
227
223
  patch_t* world = (patch_t*) calloc(NM, sizeof(patch_t));
@@ -251,32 +247,33 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
251
247
  fflush(stdout);
252
248
  single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
253
249
  return ACCURACY_ERROR;
254
- }
255
- size_t record_index = time / mod->record_itv;
250
+ }
251
+ size_t record_index = (size_t) (time / mod->record_itv);
256
252
  double record_time = time - record_index * record_itv;
257
253
 
258
254
 
259
255
  while (time < maxtime) {
260
-
261
- // Print progress
262
- if (time > current_progress) {
263
- uint8_t curr_prog = (uint8_t)(time * 100 / maxtime);
264
- if (curr_prog < 10) {
265
- fprintf(stdout, "\r%s: %d %%", message, (int)(time * 100 / maxtime));
266
- } else {
267
- fprintf(stdout, "\r%s: %d%%", message, (int)(time * 100 / maxtime));
268
- }
269
- fflush(stdout);
270
- //fflush(stdout); // Make sure it prints immediately
271
- current_progress += one_progress;
272
- }
273
256
 
274
- // update sums
257
+ // update sums and print progress
275
258
  curr_update_sum_round++;
276
- if (curr_update_sum_round > update_sum_rounds) {
259
+ if (curr_update_sum_round > update_sum_freq) {
277
260
  curr_update_sum_round = 0;
278
261
 
279
- update_sum_rounds = UPDATE_SUM_ROUNDS_LG; // assume can make it larger
262
+ // Print progress
263
+ if (time > current_progress) {
264
+ uint8_t curr_prog = (uint8_t)(time * 100 / maxtime);
265
+ if (curr_prog < 10) {
266
+ fprintf(stdout, "\r%s: %d %%", message, (int)(time * 100 / maxtime));
267
+ } else {
268
+ fprintf(stdout, "\r%s: %d%%", message, (int)(time * 100 / maxtime));
269
+ }
270
+ fflush(stdout);
271
+ //fflush(stdout); // Make sure it prints immediately
272
+ current_progress += one_progress;
273
+ }
274
+
275
+ // update sum
276
+ update_sum_freq = UPDATE_SUM_ROUNDS_LG; // assume can make it larger
280
277
  for (size_t ij = 0; ij < NM; ij++) {
281
278
  double sum_U_weight = 0;
282
279
  double sum_V_weight = 0;
@@ -285,19 +282,19 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
285
282
  sum_V_weight += world[ij].V_weight[k];
286
283
  }
287
284
  if (sum_U_weight > ACCURATE_BOUND || sum_V_weight > ACCURATE_BOUND) {
288
- update_sum_rounds = UPDATE_SUM_ROUNDS_SM; // values too large, put back the small update frequency
285
+ update_sum_freq = UPDATE_SUM_ROUNDS_SM; // values too large, put back the small update frequency
289
286
  }
290
287
  world[ij].sum_U_weight = sum_U_weight;
291
288
  world[ij].sum_V_weight = sum_V_weight;
292
289
  // patch_rates are updated every time a patch is changed
293
290
  }
294
- size_t ij = 0;
291
+ size_t ij_out = 0;
295
292
  sum_rates = 0;
296
293
  for (size_t i = 0; i < N; i++) {
297
294
  double sum_rates_by_row_i = 0;
298
295
  for (size_t j = 0; j < M; j++) {
299
- sum_rates_by_row_i += patch_rates[ij];
300
- ij++;
296
+ sum_rates_by_row_i += patch_rates[ij_out];
297
+ ij_out++;
301
298
  }
302
299
  sum_rates_by_row[i] = sum_rates_by_row_i;
303
300
  sum_rates += sum_rates_by_row_i;
@@ -318,8 +315,8 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
318
315
  sum_rates_by_row[si1] -= patch_rates[sij1];
319
316
  sum_rates -= patch_rates[sij1];
320
317
 
321
- update_pi_k(&world[sij1], &(mod->X[sij1 * 4]), &(mod->P[sij1 * 6]));
322
- update_mig_just_rate(&world[sij1], &(mod->P[sij1 * 6]));
318
+ update_pi_k(&world[sij1], &(X[sij1 * 4]), &(P[sij1 * 6]));
319
+ update_mig_just_rate(&world[sij1], &(P[sij1 * 6]));
323
320
 
324
321
  patch_rates[sij1] = world[sij1].sum_pi_death_rates + world[sij1].sum_mig_rates;
325
322
  sum_rates_by_row[si1] += patch_rates[sij1];
@@ -331,11 +328,11 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
331
328
  sum_rates -= patch_rates[sij1];
332
329
  sum_rates -= patch_rates[sij2];
333
330
 
334
- update_pi_k(&world[sij1], &(mod->X[sij1 * 4]), &(mod->P[sij1 * 6])); // update both patches' payoffs first
335
- update_pi_k(&world[sij2], &(mod->X[sij2 * 4]), &(mod->P[sij2 * 6]));
331
+ update_pi_k(&world[sij1], &(X[sij1 * 4]), &(P[sij1 * 6])); // update both patches' payoffs first
332
+ update_pi_k(&world[sij2], &(X[sij2 * 4]), &(P[sij2 * 6]));
336
333
 
337
- if (update_mig_weight_rate(&world[sij1], &(mod->P[sij1 * 6]), rela_loc) == SIM_OVERFLOW ||
338
- update_mig_weight_rate(&world[sij2], &(mod->P[sij2 * 6]), rela_loc ^ 1) == SIM_OVERFLOW) {
334
+ if (update_mig_weight_rate(&world[sij1], &(P[sij1 * 6]), rela_loc) == SIM_OVERFLOW ||
335
+ update_mig_weight_rate(&world[sij2], &(P[sij2 * 6]), rela_loc ^ 1) == SIM_OVERFLOW) {
339
336
 
340
337
  fprintf(stdout, "\nError: overflow at t = %f\n", time);
341
338
  fflush(stdout);
@@ -357,7 +354,7 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
357
354
  size_t nb_idx = nb_indices[sij1 * 4 + k];
358
355
  if (nb_idx == NM) { continue; } // invalid neighbor
359
356
  // all neighbors, as long as exists, need to change
360
- if (update_mig_weight_rate(&world[nb_idx], &(mod->P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
357
+ if (update_mig_weight_rate(&world[nb_idx], &(P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
361
358
  fprintf(stdout, "\nError: overflow at t = %f\n", time);
362
359
  fflush(stdout);
363
360
  single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
@@ -372,7 +369,7 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
372
369
  if (nb_idx == NM) { continue; }
373
370
  if (k != rela_loc) {
374
371
  // nb_idx isn't the second last-changed patch
375
- if (update_mig_weight_rate(&world[nb_idx], &(mod->P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
372
+ if (update_mig_weight_rate(&world[nb_idx], &(P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
376
373
  fprintf(stdout, "\nError: overflow at t = %f\n", time);
377
374
  fflush(stdout);
378
375
  single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
@@ -386,7 +383,7 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
386
383
  if (nb_idx == NM) { continue; }
387
384
  if (k != (rela_loc ^ 1)) {
388
385
  // nb_idx isn't the first last-changed patch
389
- if (update_mig_weight_rate(&world[nb_idx], &(mod->P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
386
+ if (update_mig_weight_rate(&world[nb_idx], &(P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
390
387
  fprintf(stdout, "\nError: overflow at t = %f\n", time);
391
388
  fflush(stdout);
392
389
  single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
@@ -437,11 +434,12 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
437
434
  size_t upper = record_index + multi_records;
438
435
 
439
436
  for (size_t ij = 0; ij < NM; ij++) {
437
+ size_t ij_max_record = ij * max_record;
440
438
  for (size_t k = record_index; k < upper; k++) {
441
- mod->U1d[ij * max_record + k] += world[ij].U;
442
- mod->V1d[ij * max_record + k] += world[ij].V;
443
- mod->Upi_1d[ij * max_record + k] += world[ij].U_pi;
444
- mod->Vpi_1d[ij * max_record + k] += world[ij].V_pi;
439
+ U1d[ij_max_record + k] += world[ij].U;
440
+ V1d[ij_max_record + k] += world[ij].V;
441
+ Upi_1d[ij_max_record + k] += world[ij].U_pi;
442
+ Vpi_1d[ij_max_record + k] += world[ij].V_pi;
445
443
  }
446
444
  }
447
445
  record_index += multi_records;
@@ -450,11 +448,12 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
450
448
  } else {
451
449
  // if already exceeds maxtime
452
450
  for (size_t ij = 0; ij < NM; ij++) {
451
+ size_t ij_max_record = ij * max_record;
453
452
  for (size_t k = record_index; k < max_record; k++) {
454
- mod->U1d[ij * max_record + k] += world[ij].U;
455
- mod->V1d[ij * max_record + k] += world[ij].V;
456
- mod->Upi_1d[ij * max_record + k] += world[ij].U_pi;
457
- mod->Vpi_1d[ij * max_record + k] += world[ij].V_pi;
453
+ U1d[ij_max_record + k] += world[ij].U;
454
+ V1d[ij_max_record + k] += world[ij].V;
455
+ Upi_1d[ij_max_record + k] += world[ij].U_pi;
456
+ Vpi_1d[ij_max_record + k] += world[ij].V_pi;
458
457
  }
459
458
  }
460
459
  }
@@ -552,8 +551,10 @@ uint8_t run(model_t* restrict mod, char* message, size_t msg_len) {
552
551
 
553
552
  double stop = clock();
554
553
 
555
- fprintf(stdout, "\r%sruntime: %.3fs \n", message, (double)(stop - start) / CLOCKS_PER_SEC);
556
- fflush(stdout);
554
+ if (mod->print_pct != -1) {
555
+ fprintf(stdout, "\r%sruntime: %.3fs \n", message, (double)(stop - start) / CLOCKS_PER_SEC);
556
+ fflush(stdout);
557
+ }
557
558
  return SUCCESS;
558
559
  }
559
560
 
@@ -18,8 +18,8 @@
18
18
 
19
19
 
20
20
 
21
- // upper bound for RNG is 2^24 + 1
22
- #define RAND_UPPER_PLUS_2 (double) (0x3fffffffu + 2)
21
+ // upper bound for RNG is 2^30 + 1
22
+ #define RAND_UPPER_PLUS_2 (double) ((1LL << 30) + 1)
23
23
 
24
24
  // directions of migration
25
25
  // so that 3 - mig_dir = reflection of it. Used to track neighbors
@@ -37,19 +37,24 @@
37
37
  #define SIM_OVERFLOW 3
38
38
  #define ACCURACY_ERROR 4
39
39
 
40
+
41
+ /**
42
+ * Handling Numerical Errors:
43
+ * half of the rates / values related to rates are calculated on a cumulative basis. i.e., updated over time instead of re-calculating from scratch
44
+ * numerival errors might explode in this case, so need to re-calculate every sometime
45
+ */
46
+
40
47
  // where exp(x) is considered overflow
41
48
  // below the actual bound (709) to preserve accuracy
42
49
  #define EXP_OVERFLOW_BOUND 500
43
- #define ACCURATE_BOUND 10000000000LL
50
+
51
+ // Compare current rates with this bound
52
+ #define ACCURATE_BOUND 1LL << 33 // about 8.6 * 10^9
44
53
 
45
54
  // how frequent to update rates & sum of rates in single test (recalculate)
46
- #define UPDATE_SUM_ROUNDS_SM 100
55
+ #define UPDATE_SUM_ROUNDS_SM 100 // small, more frequent if some rate is larger than ACCURATE_BOUND
47
56
  #define UPDATE_SUM_ROUNDS_LG 10000
48
57
 
49
-
50
- static uint64_t pcg_state = 0;
51
- static uint64_t pcg_inc = 0;
52
-
53
58
 
54
59
 
55
60
 
@@ -109,7 +114,7 @@ static inline double random01() {
109
114
  uint32_t r1 = rand() & 0x7fff; // RAND_MAX is different across machines, ensure 15 bits
110
115
  uint32_t r2 = rand() & 0x7fff;
111
116
 
112
- double r_combined = (r1 << 15) + r2; // discard the lower 3 bits, which are unstable
117
+ double r_combined = (r1 << 15) + r2;
113
118
  return (r_combined + 1) / RAND_UPPER_PLUS_2;
114
119
  }
115
120
 
@@ -121,8 +126,8 @@ static inline void update_pi_k(patch_t* restrict p, const double* restrict M_sta
121
126
  // M_start: start index of patch (i, j)'s matrix
122
127
  // P_start: start index of p's patch variables, i.e., ij * 6
123
128
 
124
- double U = (double) p->U;
125
- double V = (double) p->V;
129
+ uint32_t U = p->U;
130
+ uint32_t V = p->V;
126
131
  double sum = U + V;
127
132
  double U_ratio = U / sum;
128
133
  double V_ratio = V / sum;
@@ -165,8 +170,8 @@ static inline void update_mig_just_rate(patch_t* restrict p, const double* restr
165
170
  double* p_U_weight = p->U_weight;
166
171
  double* p_V_weight = p->V_weight;
167
172
 
168
- double mu1_U = P_start[0] * (double)p->U;
169
- double mu2_V = P_start[1] * (double)p->V;
173
+ double mu1_U = P_start[0] * p->U;
174
+ double mu2_V = P_start[1] * p->V;
170
175
 
171
176
  double mu1_U_divide_sum = mu1_U / p->sum_U_weight;
172
177
  double mu2_V_divide_sum = mu2_V / p->sum_V_weight;
@@ -349,9 +354,6 @@ static inline void change_popu(patch_t* restrict p, uint8_t s) {
349
354
  p->V -= 1;
350
355
  }
351
356
  return;
352
- //default:
353
- // fprintf(stderr, "Bug: invalid event number in change_popu: %hhu\n", s);
354
- // return;
355
357
  }
356
358
  }
357
359
 
@@ -1,4 +1,4 @@
1
- __version__ = '2.3.6'
1
+ __version__ = '2.3.7'
2
2
 
3
3
  '''
4
4
  version history:
@@ -43,4 +43,5 @@ version history:
43
43
  2.3.4: change back to the mig & payoff rules in version 2.3.2
44
44
  2.3.5: improved accuracy for simulation, now can better handle large mig rates. Numerical errors are now being checked and reduced automatically based on how large the values are.
45
45
  2.3.6: index error due to reduced accuracy is now explicitly handled.
46
+ 2.3.7: update migration rules on the boundary. mu values are scaled based on how many neighbors a patch has. Minor debugging in several modules.
46
47
  '''
@@ -29,12 +29,8 @@ def save_data(mod, dirs = '', print_msg = True):
29
29
  except AttributeError:
30
30
  raise ValueError('mod is not a model object')
31
31
 
32
- if dirs != '':
33
- # add slash '/'
34
- if dirs[:-1] != '/':
35
- dirs += '/'
36
- if not os.path.exists(dirs):
37
- os.makedirs(dirs)
32
+ if not os.path.exists(dirs):
33
+ os.makedirs(dirs)
38
34
 
39
35
  data = []
40
36
 
@@ -64,14 +60,11 @@ def save_data(mod, dirs = '', print_msg = True):
64
60
  outputs.append(mod.Vpi.tolist())
65
61
  # H&Vpi_total are not saved, will be calculated when reading the data
66
62
  data.append(outputs)
67
-
68
- data_json = json.dumps(data)
69
- data_bytes = data_json.encode('utf-8')
70
- data_dirs = dirs + 'data.json.gz'
71
-
72
- with gzip.open(data_dirs, 'w') as f:
73
- f.write(data_bytes)
74
-
63
+
64
+ data_dirs = os.path.join(dirs, 'data.json.gz')
65
+ with gzip.open(data_dirs, 'wb') as f:
66
+ f.write(json.dumps(data).encode('utf-8'))
67
+
75
68
  if print_msg:
76
69
  print('data saved: ' + data_dirs)
77
70
 
@@ -89,35 +82,30 @@ def read_data(dirs):
89
82
  - mod: a piegy.model.model object read from the data.
90
83
  '''
91
84
 
92
- if dirs != '':
93
- # add slash '/'
94
- if dirs[:-1] != '/':
95
- dirs += '/'
96
- if not os.path.exists(dirs):
97
- raise FileNotFoundError('dirs not found: ' + dirs)
98
-
99
- if not os.path.isfile(dirs + 'data.json.gz'):
85
+ if not os.path.exists(dirs):
86
+ raise FileNotFoundError('dirs not found: ' + dirs)
87
+
88
+ data_dirs = os.path.join(dirs, 'data.json.gz')
89
+ if not os.path.isfile(data_dirs):
100
90
  raise FileNotFoundError('data not found in ' + dirs)
101
91
 
102
- with gzip.open(dirs + 'data.json.gz', 'r') as f:
103
- data_bytes = f.read()
104
- data_json = data_bytes.decode('utf-8')
105
- data = json.loads(data_json)
106
-
107
- # inputs
108
- try:
109
- mod = simulation.model(N = data[0][0], M = data[0][1], maxtime = data[0][2], record_itv = data[0][3],
110
- sim_time = data[0][4], boundary = data[0][5], I = data[0][6], X = data[0][7], P = data[0][8],
111
- print_pct = data[0][9], seed = data[0][10], check_overflow = data[0][11])
112
- except:
113
- raise ValueError('Invalid input parameters saved in data')
114
-
115
- # outputs
116
- try:
117
- mod.set_data(data_empty = False, max_record = data[1][0], compress_itv = data[1][1],
118
- U = data[1][2], V = data[1][3], Upi = data[1][4], Vpi = data[1][5])
119
- except:
120
- raise ValueError('Invalid model results saved in data')
92
+ with gzip.open(data_dirs, 'rb') as f:
93
+ data = json.loads(f.read().decode('utf-8'))
94
+
95
+ # inputs
96
+ try:
97
+ mod = simulation.model(N = data[0][0], M = data[0][1], maxtime = data[0][2], record_itv = data[0][3],
98
+ sim_time = data[0][4], boundary = data[0][5], I = data[0][6], X = data[0][7], P = data[0][8],
99
+ print_pct = data[0][9], seed = data[0][10], check_overflow = data[0][11])
100
+ except:
101
+ raise ValueError('Invalid input parameters saved in data')
102
+
103
+ # outputs
104
+ try:
105
+ mod.set_data(data_empty = False, max_record = data[1][0], compress_itv = data[1][1],
106
+ U = data[1][2], V = data[1][3], Upi = data[1][4], Vpi = data[1][5])
107
+ except:
108
+ raise ValueError('Invalid model results saved in data')
121
109
 
122
110
  return mod
123
111
 
@@ -332,15 +332,15 @@ def pi_bar(mod, ax_U = None, ax_V = None, U_color = 'violet', V_color = 'yellowg
332
332
  end_index = int(mod.max_record * end)
333
333
 
334
334
  Upi_ave = figure_t.ave_interval_1D(mod.Upi, start_index, end_index)
335
- V_pi_ave = figure_t.ave_interval_1D(mod.Vpi, start_index, end_index)
335
+ Vpi_ave = figure_t.ave_interval_1D(mod.Vpi, start_index, end_index)
336
336
 
337
337
  U_title = figure_t.gen_title(r'$p_H$', start, end)
338
338
  U_text = figure_t.gen_text(np.mean(Upi_ave), np.std(Upi_ave))
339
339
  V_title = figure_t.gen_title(r'$p_D$', start, end)
340
- V_text = figure_t.gen_text(np.mean(V_pi_ave), np.std(V_pi_ave))
340
+ V_text = figure_t.gen_text(np.mean(Vpi_ave), np.std(Vpi_ave))
341
341
 
342
342
  ax_U = figure_t.bar(Upi_ave, ax_U, U_color, 'Patches', 'Payoff ' + r'$p_H$', U_title, U_text)
343
- ax_V = figure_t.bar(V_pi_ave, ax_V, V_color, 'Patches', 'Payoff ' + r'$p_D$', V_title, V_text)
343
+ ax_V = figure_t.bar(Vpi_ave, ax_V, V_color, 'Patches', 'Payoff ' + r'$p_D$', V_title, V_text)
344
344
 
345
345
  return ax_U, ax_V
346
346
 
@@ -450,11 +450,11 @@ def run(mod, message = ""):
450
450
  elif result == SIM_OVERFLOW:
451
451
  LIB.mod_free_py(ctypes.byref(mod_c))
452
452
  del mod_c
453
- raise OverflowError('Overflow in simulation. Possibly due to too large w1, w2, or payoff matrix values.')
453
+ raise OverflowError('Overflow in simulation. Possibly due to too large w1, w2, or payoff.')
454
454
  elif result == ACCURACY_ERROR:
455
455
  LIB.mod_free_py(ctypes.byref(mod_c))
456
456
  del mod_c
457
- raise RuntimeError('Accuracy dropped catastrophically during simulation. Possibly due to too large w1, w2, or payoff matrix values.')
457
+ raise RuntimeError('Accuracy dropped catastrophically during simulation. Possibly due to too large w1, w2, or payoff.')
458
458
  else:
459
459
  LIB.mod_free_py(ctypes.byref(mod_c))
460
460
  del mod_c
@@ -529,9 +529,9 @@ def check_overflow_func(mod):
529
529
  w1_pi = pi_expected[i][j] * mod.P[i][j][2] # w1 * U_pi
530
530
  w2_pi = pi_expected[i][j] * mod.P[i][j][3] # w2 * V_pi
531
531
  if ((w1_pi > EXP_OVERFLOW_BOUND) or (w2_pi > EXP_OVERFLOW_BOUND)):
532
- print("Warning: might cause overflow in simulation. \n\t w1, w2, or payoff matrix values too large")
532
+ print("Warning: might cause overflow in simulation. w1, w2, or payoff matrix values too large")
533
533
  return
534
534
  if ((w1_pi > EXP_TOO_LARGE_BOUND) or (w2_pi > EXP_TOO_LARGE_BOUND)):
535
- print("Warning: might have low accuracy in simulation. \n\t w1, w2, or payoff matrix values too large")
535
+ print("Warning: might have low accuracy in simulation. w1, w2, or payoff matrix values too large")
536
536
  return
537
537
 
@@ -92,6 +92,7 @@ def test_var1(mod, var, values, dirs, compress_itv = None):
92
92
  if compress_itv != None:
93
93
  sim2.compress_data(compress_itv)
94
94
  data_t.save_data(sim2, var_dirs[k], print_msg = False)
95
+ del sim2
95
96
  except (OverflowError, RuntimeError):
96
97
  print(current_var_str + ' raised error, skipped')
97
98
  continue
@@ -139,6 +140,7 @@ def test_var2(mod, var1, var2, values1, values2, dirs, compress_itv = None):
139
140
  if compress_itv != None:
140
141
  sim2.compress_data(compress_itv)
141
142
  data_t.save_data(sim2, var_dirs[k1][k2], print_msg = False)
143
+ del sim2
142
144
  except (OverflowError, RuntimeError):
143
145
  print(current_var_str + ' raised error, skipped')
144
146
  continue
@@ -185,6 +187,7 @@ def var_UV1(var, values, var_dirs, ax_U = None, ax_V = None, start = 0.95, end =
185
187
 
186
188
  U_ave.append(sum(figure_t.ave_interval_1D(simk.U, start_index, end_index)) / NM)
187
189
  V_ave.append(sum(figure_t.ave_interval_1D(simk.V, start_index, end_index)) / NM)
190
+ del simk
188
191
 
189
192
  #### plot ####
190
193
  if ax_U == None:
@@ -253,6 +256,7 @@ def var_UV2(var1, var2, values1, values2, var_dirs, ax_U = None, ax_V = None, va
253
256
 
254
257
  U_ave[k1].append(sum(figure_t.ave_interval_1D(simk.U, start_index, end_index)) / NM)
255
258
  V_ave[k1].append(sum(figure_t.ave_interval_1D(simk.V, start_index, end_index)) / NM)
259
+ del simk
256
260
 
257
261
  U_ave = np.array(U_ave)
258
262
  V_ave = np.array(V_ave)
@@ -340,7 +344,6 @@ def var_pi1(var, values, var_dirs, ax_U = None, ax_V = None, start = 0.95, end =
340
344
 
341
345
  U_ave.append(np.sum(figure_t.ave_interval(simk.Upi, start_index, end_index)) / NM)
342
346
  V_ave.append(np.sum(figure_t.ave_interval(simk.Vpi, start_index, end_index)) / NM)
343
-
344
347
  del simk
345
348
 
346
349
  #### plot ####
@@ -406,8 +409,7 @@ def var_pi2(var1, var2, values1, values2, var_dirs, ax_U = None, ax_V = None, va
406
409
 
407
410
  U_ave[k1].append(np.sum(figure_t.ave_interval(simk.Upi, start_index, end_index)) / NM)
408
411
  V_ave[k1].append(np.sum(figure_t.ave_interval(simk.Vpi, start_index, end_index)) / NM)
409
-
410
- del simk # manually delete this large object
412
+ del simk
411
413
 
412
414
  U_ave = np.array(U_ave)
413
415
  V_ave = np.array(V_ave)
@@ -507,14 +509,16 @@ def var_convergence1(var_dirs, interval = 20, start = 0.8, fluc = 0.07):
507
509
 
508
510
  diverge_list = []
509
511
 
510
- for dirs in var_dirs:
512
+ for k in range(len(var_dirs)):
513
+ dirs = var_dirs[k]
511
514
  try:
512
- mod = data_t.read_data(dirs)
515
+ simk = data_t.read_data(dirs)
513
516
  except FileNotFoundError:
514
517
  print(dirs + ' data not found, skipped')
515
518
  continue
516
- if not analysis.check_convergence(mod, interval, start, fluc):
519
+ if not analysis.check_convergence(simk, interval, start, fluc):
517
520
  diverge_list.append(dirs)
521
+ del simk
518
522
 
519
523
  return diverge_list
520
524
 
@@ -574,14 +578,16 @@ def var_convergence2(var_dirs, interval = 20, start = 0.8, fluc = 0.07):
574
578
  diverge_list = []
575
579
 
576
580
  for sublist in var_dirs:
577
- for dirs in sublist:
581
+ for k in range(len(sublist)):
582
+ dirs = sublist[k]
578
583
  try:
579
- mod = data_t.read_data(dirs)
584
+ simk = data_t.read_data(dirs)
580
585
  except FileNotFoundError:
581
586
  print(dirs + ' data not found, skipped')
582
587
  continue
583
- if not analysis.check_convergence(mod, interval, start, fluc):
588
+ if not analysis.check_convergence(simk, interval, start, fluc):
584
589
  diverge_list.append(dirs)
590
+ del simk
585
591
 
586
592
  return diverge_list
587
593
 
@@ -187,7 +187,7 @@ def ave_interval_1D(data, start_index, end_index):
187
187
  M = len(data[0])
188
188
 
189
189
  if start_index == end_index:
190
- start_index = end_index - 1
190
+ end_index = start_index + 1 # exactly one record
191
191
 
192
192
  data_ave = np.zeros(N * M)
193
193
 
@@ -9,9 +9,8 @@ def find_C():
9
9
  C_core_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'C_core')
10
10
  C_list = os.listdir(C_core_path)
11
11
  for file in C_list:
12
- if file[-3:] == '.so':
13
- return C_core_path + '/' + file
14
- if file[-4:] == '.pyd':
15
- return C_core_path + '/' + file
12
+ if (file[-3:] == '.so') or (file[-4:] == '.pyd') or (file[-4:] == '.dll') or (file[-4:] == '.lib'):
13
+ if 'piegyc' in file:
14
+ return C_core_path + '/' + file
16
15
 
17
16
  raise FileNotFoundError('C computation core not found. You can either compile manully or use the Python core instead. Please see docs.')
@@ -27,7 +27,6 @@ import matplotlib.style as mplstyle
27
27
  import numpy as np
28
28
  import os
29
29
  from cv2 import imread, VideoWriter, VideoWriter_fourcc
30
- from moviepy import ImageSequenceClip
31
30
 
32
31
 
33
32
  # a list of supported figures
@@ -144,7 +143,7 @@ def frame_lim(mod, func, frames):
144
143
  U_ylim = get_max_lim(U_ylist)
145
144
  V_xlim = get_max_lim(V_xlist)
146
145
  V_ylim = get_max_lim(V_ylist)
147
-
146
+
148
147
  return U_xlim, U_ylim, V_xlim, V_ylim
149
148
 
150
149
 
@@ -200,14 +199,15 @@ def make_mp4(video_dir, frame_dir, fps):
200
199
  if (file[-4:] == '.png') and ('frame' in file):
201
200
  frame_path.append(os.path.join(frame_dir, file))
202
201
 
202
+ # setup cv2 video writer
203
203
  first_frame = imread(frame_path[0])
204
204
  height, width, _ = first_frame.shape
205
205
  fourcc = VideoWriter_fourcc(*'mp4v')
206
206
  video_writer = VideoWriter(video_dir, fourcc, fps, (width, height))
207
207
 
208
208
  for file in frame_path:
209
- frame = imread(file)
210
- video_writer.write(frame)
209
+ frame = imread(file)
210
+ video_writer.write(frame)
211
211
  video_writer.release()
212
212
 
213
213
 
@@ -236,9 +236,9 @@ def make_video(mod, func_name = 'UV_hmap', frames = 100, dpi = 200, fps = 30, U_
236
236
  # convert color if invalid colors are given
237
237
  U_color, V_color = convert_color(func_name, U_color, V_color)
238
238
 
239
- # set fast style for faster speed
240
- original_rc = mpl.rcParams.copy()
241
- mplstyle.use('fast')
239
+ # set Agg backend for faster speed
240
+ original_backend = mpl.get_backend()
241
+ mpl.use("Agg")
242
242
 
243
243
  # print progress
244
244
  one_progress = frames / 100
@@ -267,7 +267,7 @@ def make_video(mod, func_name = 'UV_hmap', frames = 100, dpi = 200, fps = 30, U_
267
267
 
268
268
  #### for loop ####
269
269
 
270
- for i in range(frames - 1):
270
+ for i in range(frames):
271
271
  if i > current_progress:
272
272
  print('making frames', round(i / frames * 100), '%', end = '\r')
273
273
  current_progress += one_progress
@@ -277,9 +277,9 @@ def make_video(mod, func_name = 'UV_hmap', frames = 100, dpi = 200, fps = 30, U_
277
277
  fig_U, ax_U = plt.subplots(figsize = figsize)
278
278
  fig_V, ax_V = plt.subplots(figsize = figsize)
279
279
  else:
280
- fig_U, ax_U = plt.subplots(figsize = figsize)#, constrained_layout = True)
281
- fig_V, ax_V = plt.subplots(figsize = figsize)#, constrained_layout = True)
282
-
280
+ fig_U, ax_U = plt.subplots(figsize = figsize)
281
+ fig_V, ax_V = plt.subplots(figsize = figsize)
282
+
283
283
  if 'hmap' in func_name:
284
284
  func(mod, ax_U = ax_U, ax_V = ax_V, U_color = U_color, V_color = V_color, start = i / frames, end = (i + 1) / frames, vrange_U = U_clim, vrange_V = V_clim)
285
285
  else:
@@ -304,6 +304,9 @@ def make_video(mod, func_name = 'UV_hmap', frames = 100, dpi = 200, fps = 30, U_
304
304
  plt.close(fig_V)
305
305
 
306
306
  #### for loop ends ####
307
+
308
+ # reset to original backend
309
+ mpl.use(original_backend)
307
310
 
308
311
  # frames done
309
312
  print('making mp4... ', end = '\r')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: piegy
3
- Version: 2.3.6
3
+ Version: 2.3.7
4
4
  Summary: Payoff-Driven Stochastic Spatial Model for Evolutionary Game Theory
5
5
  Author-email: Chenning Xu <cxu7@caltech.edu>
6
6
  License: BSD 3-Clause License
@@ -23,7 +23,6 @@ src/piegy/C_core/model.c
23
23
  src/piegy/C_core/model.h
24
24
  src/piegy/C_core/patch.c
25
25
  src/piegy/C_core/patch.h
26
- src/piegy/C_core/runner.c
27
26
  src/piegy/C_core/sim_funcs.c
28
27
  src/piegy/C_core/sim_funcs.h
29
28
  src/piegy/tools/__init__.py
@@ -1,61 +0,0 @@
1
- #include <stdbool.h>
2
- #include <stdlib.h>
3
- #include <stdint.h>
4
- #include <stdio.h>
5
-
6
- #include "model.h"
7
- #include "patch.h"
8
- #include "sim_funcs.h"
9
-
10
-
11
- int main() {
12
- size_t N = 1;
13
- size_t M = 100;
14
- double maxtime = 300;
15
- double record_itv = 0.1;
16
- size_t sim_time = 1;
17
- bool boundary = true;
18
- uint32_t I_single[2] = {3, 3};
19
- double X_single[4] = {-1, 4, 0, 2};
20
- double P_single[6] = {0.5, 0.5, 80, 80, 0.001, 0.001};
21
- int32_t print_pct = 1;
22
- int32_t seed = 36; // -1 for None
23
-
24
- uint32_t I[N * M * 2];
25
- double X[N * M * 4];
26
- double P[N * M * 6];
27
-
28
- //printf("sizeof(patch_t) = %zu bytes\n", sizeof(patch_t));
29
- size_t ij = 0;
30
- for (size_t i = 0; i < N; i++) {
31
- for (size_t j = 0; j < M; j++) {
32
- I[ij * 2] = I_single[0];
33
- I[ij * 2 + 1] = I_single[1];
34
-
35
- for (size_t k = 0; k < 4; k++) {
36
- X[ij * 4 + k] = X_single[k];
37
- }
38
- for (size_t k = 0; k < 6; k++) {
39
- P[ij * 6 + k] = P_single[k];
40
- }
41
- ++ij;
42
- }
43
- }
44
-
45
- model_t* mod = malloc(sizeof(model_t));
46
- mod_init(mod, N, M, maxtime, record_itv, sim_time, boundary, I, X, P, print_pct, seed);
47
-
48
- char message[20] = ""; // writable buffer with enough space
49
- uint8_t result = run(mod, message, 20);
50
-
51
- /*for (size_t i = 0; i < mod->max_record; i++) {
52
- fprintf(stdout, "%f ", mod->U1d[i]);
53
- }
54
- fprintf(stdout, "\n");
55
- for (size_t i = 0; i < mod->max_record; i++) {
56
- fprintf(stdout, "%f ", mod->Upi_1d[i]);
57
- }*/
58
- mod_free(mod);
59
- mod = NULL;
60
- }
61
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes