piegy 2.3.5__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.
- {piegy-2.3.5 → piegy-2.3.7}/MANIFEST.in +1 -0
- {piegy-2.3.5/src/piegy.egg-info → piegy-2.3.7}/PKG-INFO +1 -1
- {piegy-2.3.5 → piegy-2.3.7}/pyproject.toml +1 -1
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/C_core/Makefile +0 -1
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/C_core/patch.c +8 -4
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/C_core/patch.h +5 -5
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/C_core/sim_funcs.c +116 -108
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/C_core/sim_funcs.h +25 -21
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/__version__.py +3 -1
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/data_tools.py +29 -41
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/figures.py +3 -3
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/simulation.py +9 -4
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/test_var.py +19 -13
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/tools/figure_tools.py +1 -1
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/tools/find_C.py +3 -4
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/videos.py +14 -11
- {piegy-2.3.5 → piegy-2.3.7/src/piegy.egg-info}/PKG-INFO +1 -1
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy.egg-info/SOURCES.txt +0 -1
- piegy-2.3.5/src/piegy/C_core/runner.c +0 -61
- {piegy-2.3.5 → piegy-2.3.7}/LICENSE.txt +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/README.md +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/setup.cfg +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/setup.py +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/C_core/model.c +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/C_core/model.h +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/__init__.py +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/analysis.py +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/build_info.py +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/simulation_py.py +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/tools/__init__.py +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy/tools/file_tools.py +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy.egg-info/dependency_links.txt +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy.egg-info/requires.txt +0 -0
- {piegy-2.3.5 → piegy-2.3.7}/src/piegy.egg-info/top_level.txt +0 -0
@@ -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
|
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->
|
11
|
-
p->
|
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
|
18
|
-
size_t
|
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
|
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
|
|
@@ -68,75 +68,68 @@ static void find_nb_periodical(size_t* restrict nb, size_t i, size_t j, size_t N
|
|
68
68
|
|
69
69
|
|
70
70
|
// single_init function: initializes world, runs 1 event, returns updated variables
|
71
|
-
static double single_init(const model_t* mod, patch_t* world, size_t* nb_indices,
|
72
|
-
double* patch_rates, double* sum_rates_by_row, double* sum_rates_p,
|
71
|
+
static double single_init(const model_t* restrict mod, patch_t* restrict world, size_t* restrict nb_indices,
|
72
|
+
double* restrict patch_rates, double* restrict sum_rates_by_row, double* restrict sum_rates_p,
|
73
|
+
signal_t* restrict sig_p, patch_picked_t* restrict picked_p) {
|
73
74
|
|
74
75
|
size_t N = mod->N;
|
75
76
|
size_t M = mod->M;
|
76
77
|
size_t NM = N * M;
|
77
78
|
size_t max_record = mod->max_record;
|
78
|
-
size_t
|
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
|
79
80
|
|
80
81
|
// init world
|
81
82
|
for (size_t i = 0; i < N; i++) {
|
82
83
|
for (size_t j = 0; j < M; j++) {
|
83
|
-
patch_init(&world[
|
84
|
-
|
84
|
+
patch_init(&world[ij_out], mod->I[ij_out * 2], mod->I[ij_out * 2 + 1], i, j);
|
85
|
+
ij_out++;
|
85
86
|
}
|
86
87
|
}
|
87
88
|
|
88
89
|
// init nb_indices
|
89
|
-
|
90
|
+
ij_out = 0;
|
90
91
|
if (mod->boundary) {
|
91
92
|
for (size_t i = 0; i < N; i++) {
|
92
93
|
for (size_t j = 0; j < M; j++) {
|
93
|
-
find_nb_zero_flux(&nb_indices[
|
94
|
-
|
94
|
+
find_nb_zero_flux(&nb_indices[ij_out * 4], i, j, N, M, NM);
|
95
|
+
ij_out++;
|
95
96
|
}
|
96
97
|
}
|
97
98
|
} else {
|
98
99
|
for (size_t i = 0; i < N; i++) {
|
99
100
|
for (size_t j = 0; j < M; j++) {
|
100
|
-
find_nb_periodical(&nb_indices[
|
101
|
-
|
101
|
+
find_nb_periodical(&nb_indices[ij_out * 4], i, j, N, M, NM);
|
102
|
+
ij_out++;
|
102
103
|
}
|
103
104
|
}
|
104
105
|
}
|
105
106
|
|
106
107
|
|
107
108
|
// set nb pointers for patches
|
108
|
-
ij = 0;
|
109
|
-
|
110
|
-
for (size_t j = 0; j < M; j++) {
|
111
|
-
set_nb(world, &nb_indices[ij * 4], ij, NM);
|
112
|
-
ij++;
|
113
|
-
}
|
109
|
+
for (size_t ij = 0; ij < NM; ij++) {
|
110
|
+
set_nb(world, &(mod->P[ij * 6]), &nb_indices[ij * 4], ij, NM);
|
114
111
|
}
|
115
112
|
|
116
113
|
//////// Begin Running ////////
|
117
114
|
|
118
115
|
// init payoff & natural death rates
|
119
|
-
ij = 0;
|
120
|
-
|
121
|
-
for (size_t j = 0; j < M; j++) {
|
122
|
-
update_pi_k(&world[ij], &(mod->X[ij * 4]), &(mod->P[ij * 6]));
|
123
|
-
ij++;
|
124
|
-
}
|
116
|
+
for (size_t ij = 0; ij < N; ij++) {
|
117
|
+
update_pi_k(&world[ij], &(mod->X[ij * 4]), &(mod->P[ij * 6]));
|
125
118
|
}
|
126
119
|
|
127
120
|
// init migration rates & store patch rates
|
128
|
-
|
121
|
+
ij_out = 0;
|
129
122
|
for (size_t i = 0; i < N; i++) {
|
130
123
|
for (size_t j = 0; j < M; j++) {
|
131
|
-
uint8_t mig_result = init_mig(&world[
|
124
|
+
uint8_t mig_result = init_mig(&world[ij_out], &(mod->P[ij_out * 6])); // init mig rates for all 4 directions
|
132
125
|
if (mig_result == SIM_OVERFLOW) {
|
133
126
|
return -1 * SIM_OVERFLOW;
|
134
127
|
}
|
135
|
-
double ij_rates = world[
|
136
|
-
patch_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;
|
137
130
|
sum_rates_by_row[i] += ij_rates;
|
138
131
|
*sum_rates_p = *sum_rates_p + ij_rates; // can't do *sum_rates_p += ij_rates
|
139
|
-
|
132
|
+
ij_out++;
|
140
133
|
}
|
141
134
|
}
|
142
135
|
|
@@ -145,6 +138,9 @@ static double single_init(const model_t* mod, patch_t* world, size_t* nb_indices
|
|
145
138
|
find_patch(picked_p, expected_sum, patch_rates, sum_rates_by_row, *sum_rates_p, N, M);
|
146
139
|
size_t picked_idx = picked_p->i * M + picked_p->j;
|
147
140
|
size_t e0 = find_event(&world[picked_idx], expected_sum - picked_p->current_sum);
|
141
|
+
if (picked_idx >= NM || e0 >= 12) {
|
142
|
+
return -1 * ACCURACY_ERROR;
|
143
|
+
}
|
148
144
|
|
149
145
|
// make signal
|
150
146
|
if (mod->boundary) {
|
@@ -172,18 +168,16 @@ static double single_init(const model_t* mod, patch_t* world, size_t* nb_indices
|
|
172
168
|
// store data
|
173
169
|
if (time > mod->record_itv) {
|
174
170
|
size_t recod_idx = (size_t) (time / mod->record_itv);
|
175
|
-
|
176
|
-
for (size_t
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
}
|
184
|
-
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;
|
185
179
|
}
|
186
|
-
}
|
180
|
+
}
|
187
181
|
}
|
188
182
|
|
189
183
|
return time;
|
@@ -200,10 +194,15 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
|
|
200
194
|
size_t max_record = mod->max_record;
|
201
195
|
double record_itv = mod->record_itv;
|
202
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;
|
203
203
|
|
204
204
|
// print progress
|
205
205
|
double one_progress = 0.0;
|
206
|
-
double current_progress = one_progress;
|
207
206
|
if (mod->print_pct != -1) {
|
208
207
|
one_progress = maxtime * mod->print_pct / 100.0;
|
209
208
|
fprintf(stdout, "\r ");
|
@@ -212,12 +211,13 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
|
|
212
211
|
} else {
|
213
212
|
one_progress = 2.0 * maxtime;
|
214
213
|
}
|
214
|
+
double current_progress = one_progress;
|
215
215
|
|
216
216
|
// update sum of rates every 1e5 rounds
|
217
217
|
// many rates are updated each time, rather than re-calculated.
|
218
|
-
// So need to re-calculate from scratch every some
|
218
|
+
// So need to re-calculate from scratch every some rounds to reduce numerical errors
|
219
219
|
size_t curr_update_sum_round = 0; // current round
|
220
|
-
size_t update_sum_freq =
|
220
|
+
size_t update_sum_freq = UPDATE_SUM_ROUNDS_SM; // recalculate sum every this many rounds
|
221
221
|
|
222
222
|
// Initialize simulation
|
223
223
|
patch_t* world = (patch_t*) calloc(NM, sizeof(patch_t));
|
@@ -242,57 +242,59 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
|
|
242
242
|
fflush(stdout);
|
243
243
|
single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
|
244
244
|
return SIM_OVERFLOW;
|
245
|
+
} else if (time == -1 * ACCURACY_ERROR) {
|
246
|
+
fprintf(stdout, "\nError: accuracy too low at t = 0, simulation stopped\n");
|
247
|
+
fflush(stdout);
|
248
|
+
single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
|
249
|
+
return ACCURACY_ERROR;
|
245
250
|
}
|
246
|
-
size_t record_index = time / mod->record_itv;
|
251
|
+
size_t record_index = (size_t) (time / mod->record_itv);
|
247
252
|
double record_time = time - record_index * record_itv;
|
248
253
|
|
249
254
|
|
250
255
|
while (time < maxtime) {
|
251
|
-
|
252
|
-
// Print progress
|
253
|
-
if (time > current_progress) {
|
254
|
-
uint8_t curr_prog = (uint8_t)(time * 100 / maxtime);
|
255
|
-
if (curr_prog < 10) {
|
256
|
-
fprintf(stdout, "\r%s: %d %%", message, (int)(time * 100 / maxtime));
|
257
|
-
} else {
|
258
|
-
fprintf(stdout, "\r%s: %d%%", message, (int)(time * 100 / maxtime));
|
259
|
-
}
|
260
|
-
fflush(stdout);
|
261
|
-
//fflush(stdout); // Make sure it prints immediately
|
262
|
-
current_progress += one_progress;
|
263
|
-
}
|
264
256
|
|
265
|
-
// update sums
|
257
|
+
// update sums and print progress
|
266
258
|
curr_update_sum_round++;
|
267
259
|
if (curr_update_sum_round > update_sum_freq) {
|
268
260
|
curr_update_sum_round = 0;
|
269
|
-
update_sum_freq = UPDATE_SUM_FREQ_LG; // assume can make it larger
|
270
|
-
size_t ij = 0;
|
271
261
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
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
|
277
|
+
for (size_t ij = 0; ij < NM; ij++) {
|
278
|
+
double sum_U_weight = 0;
|
279
|
+
double sum_V_weight = 0;
|
280
|
+
for (size_t k = 0; k < 4; k++) {
|
281
|
+
sum_U_weight += world[ij].U_weight[k];
|
282
|
+
sum_V_weight += world[ij].V_weight[k];
|
287
283
|
}
|
284
|
+
if (sum_U_weight > ACCURATE_BOUND || sum_V_weight > ACCURATE_BOUND) {
|
285
|
+
update_sum_freq = UPDATE_SUM_ROUNDS_SM; // values too large, put back the small update frequency
|
286
|
+
}
|
287
|
+
world[ij].sum_U_weight = sum_U_weight;
|
288
|
+
world[ij].sum_V_weight = sum_V_weight;
|
289
|
+
// patch_rates are updated every time a patch is changed
|
288
290
|
}
|
289
|
-
|
291
|
+
size_t ij_out = 0;
|
290
292
|
sum_rates = 0;
|
291
293
|
for (size_t i = 0; i < N; i++) {
|
292
294
|
double sum_rates_by_row_i = 0;
|
293
295
|
for (size_t j = 0; j < M; j++) {
|
294
|
-
sum_rates_by_row_i += patch_rates[
|
295
|
-
|
296
|
+
sum_rates_by_row_i += patch_rates[ij_out];
|
297
|
+
ij_out++;
|
296
298
|
}
|
297
299
|
sum_rates_by_row[i] = sum_rates_by_row_i;
|
298
300
|
sum_rates += sum_rates_by_row_i;
|
@@ -307,13 +309,14 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
|
|
307
309
|
size_t sij1 = signal.ij1;
|
308
310
|
size_t sij2 = signal.ij2;
|
309
311
|
uint8_t rela_loc = signal.rela_loc;
|
312
|
+
|
310
313
|
if (rela_loc == NO_MIG) {
|
311
314
|
// if only one
|
312
315
|
sum_rates_by_row[si1] -= patch_rates[sij1];
|
313
316
|
sum_rates -= patch_rates[sij1];
|
314
317
|
|
315
|
-
update_pi_k(&world[sij1], &(
|
316
|
-
update_mig_just_rate(&world[sij1], &(
|
318
|
+
update_pi_k(&world[sij1], &(X[sij1 * 4]), &(P[sij1 * 6]));
|
319
|
+
update_mig_just_rate(&world[sij1], &(P[sij1 * 6]));
|
317
320
|
|
318
321
|
patch_rates[sij1] = world[sij1].sum_pi_death_rates + world[sij1].sum_mig_rates;
|
319
322
|
sum_rates_by_row[si1] += patch_rates[sij1];
|
@@ -325,11 +328,11 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
|
|
325
328
|
sum_rates -= patch_rates[sij1];
|
326
329
|
sum_rates -= patch_rates[sij2];
|
327
330
|
|
328
|
-
update_pi_k(&world[sij1], &(
|
329
|
-
update_pi_k(&world[sij2], &(
|
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]));
|
330
333
|
|
331
|
-
if (update_mig_weight_rate(&world[sij1], &(
|
332
|
-
update_mig_weight_rate(&world[sij2], &(
|
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) {
|
333
336
|
|
334
337
|
fprintf(stdout, "\nError: overflow at t = %f\n", time);
|
335
338
|
fflush(stdout);
|
@@ -351,7 +354,7 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
|
|
351
354
|
size_t nb_idx = nb_indices[sij1 * 4 + k];
|
352
355
|
if (nb_idx == NM) { continue; } // invalid neighbor
|
353
356
|
// all neighbors, as long as exists, need to change
|
354
|
-
if (update_mig_weight_rate(&world[nb_idx], &(
|
357
|
+
if (update_mig_weight_rate(&world[nb_idx], &(P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
|
355
358
|
fprintf(stdout, "\nError: overflow at t = %f\n", time);
|
356
359
|
fflush(stdout);
|
357
360
|
single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
|
@@ -366,7 +369,7 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
|
|
366
369
|
if (nb_idx == NM) { continue; }
|
367
370
|
if (k != rela_loc) {
|
368
371
|
// nb_idx isn't the second last-changed patch
|
369
|
-
if (update_mig_weight_rate(&world[nb_idx], &(
|
372
|
+
if (update_mig_weight_rate(&world[nb_idx], &(P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
|
370
373
|
fprintf(stdout, "\nError: overflow at t = %f\n", time);
|
371
374
|
fflush(stdout);
|
372
375
|
single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
|
@@ -380,7 +383,7 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
|
|
380
383
|
if (nb_idx == NM) { continue; }
|
381
384
|
if (k != (rela_loc ^ 1)) {
|
382
385
|
// nb_idx isn't the first last-changed patch
|
383
|
-
if (update_mig_weight_rate(&world[nb_idx], &(
|
386
|
+
if (update_mig_weight_rate(&world[nb_idx], &(P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
|
384
387
|
fprintf(stdout, "\nError: overflow at t = %f\n", time);
|
385
388
|
fflush(stdout);
|
386
389
|
single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
|
@@ -396,6 +399,12 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
|
|
396
399
|
find_patch(&picked, expected_sum, patch_rates, sum_rates_by_row, sum_rates, N, M);
|
397
400
|
size_t picked_idx = picked.i * M + picked.j;
|
398
401
|
uint8_t e0 = find_event(&world[picked_idx], expected_sum - picked.current_sum);
|
402
|
+
if (picked_idx >= NM || e0 >= 12) {
|
403
|
+
fprintf(stdout, "\nError: accuracy too low at t = %f, simulation stopped\n", time);
|
404
|
+
fflush(stdout);
|
405
|
+
single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
|
406
|
+
return ACCURACY_ERROR;
|
407
|
+
}
|
399
408
|
|
400
409
|
// make signal
|
401
410
|
if (boundary) {
|
@@ -424,16 +433,13 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
|
|
424
433
|
record_time -= multi_records * record_itv;
|
425
434
|
size_t upper = record_index + multi_records;
|
426
435
|
|
427
|
-
size_t ij = 0;
|
428
|
-
|
429
|
-
for (size_t
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
mod->Vpi_1d[ij * max_record + k] += world[ij].V_pi;
|
435
|
-
}
|
436
|
-
ij++;
|
436
|
+
for (size_t ij = 0; ij < NM; ij++) {
|
437
|
+
size_t ij_max_record = ij * max_record;
|
438
|
+
for (size_t k = record_index; k < upper; k++) {
|
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;
|
437
443
|
}
|
438
444
|
}
|
439
445
|
record_index += multi_records;
|
@@ -441,16 +447,13 @@ static uint8_t single_test(model_t* restrict mod, char* message) {
|
|
441
447
|
|
442
448
|
} else {
|
443
449
|
// if already exceeds maxtime
|
444
|
-
size_t ij = 0;
|
445
|
-
|
446
|
-
for (size_t
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
mod->Vpi_1d[ij * max_record + k] += world[ij].V_pi;
|
452
|
-
}
|
453
|
-
ij++;
|
450
|
+
for (size_t ij = 0; ij < NM; ij++) {
|
451
|
+
size_t ij_max_record = ij * max_record;
|
452
|
+
for (size_t k = record_index; k < max_record; k++) {
|
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;
|
454
457
|
}
|
455
458
|
}
|
456
459
|
}
|
@@ -483,7 +486,7 @@ static void single_test_free(patch_t** world, size_t** nb_indices, double** patc
|
|
483
486
|
|
484
487
|
|
485
488
|
|
486
|
-
uint8_t run(model_t* mod, char* message, size_t msg_len) {
|
489
|
+
uint8_t run(model_t* restrict mod, char* message, size_t msg_len) {
|
487
490
|
if (!mod->data_empty) {
|
488
491
|
// this won't happen if called from python, the ``simulation.run`` caller has checked it.
|
489
492
|
fprintf(stdout, "Error: mod has non-empty data\n");
|
@@ -538,6 +541,9 @@ uint8_t run(model_t* mod, char* message, size_t msg_len) {
|
|
538
541
|
case SIM_OVERFLOW:
|
539
542
|
// error message is handled by single_test
|
540
543
|
return SIM_OVERFLOW;
|
544
|
+
case ACCURACY_ERROR:
|
545
|
+
// error message is handled by single_test
|
546
|
+
return ACCURACY_ERROR;
|
541
547
|
}
|
542
548
|
}
|
543
549
|
|
@@ -545,8 +551,10 @@ uint8_t run(model_t* mod, char* message, size_t msg_len) {
|
|
545
551
|
|
546
552
|
double stop = clock();
|
547
553
|
|
548
|
-
|
549
|
-
|
554
|
+
if (mod->print_pct != -1) {
|
555
|
+
fprintf(stdout, "\r%sruntime: %.3fs \n", message, (double)(stop - start) / CLOCKS_PER_SEC);
|
556
|
+
fflush(stdout);
|
557
|
+
}
|
550
558
|
return SUCCESS;
|
551
559
|
}
|
552
560
|
|
@@ -18,8 +18,8 @@
|
|
18
18
|
|
19
19
|
|
20
20
|
|
21
|
-
// upper bound for RNG is 2^
|
22
|
-
#define RAND_UPPER_PLUS_2 (double) (
|
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
|
@@ -35,19 +35,25 @@
|
|
35
35
|
#define DATA_NOT_EMPTY 1
|
36
36
|
#define SMALL_MAXTIME 2
|
37
37
|
#define SIM_OVERFLOW 3
|
38
|
+
#define ACCURACY_ERROR 4
|
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
|
+
*/
|
38
46
|
|
39
47
|
// where exp(x) is considered overflow
|
40
|
-
// below the actual bound (709)
|
48
|
+
// below the actual bound (709) to preserve accuracy
|
41
49
|
#define EXP_OVERFLOW_BOUND 500
|
42
|
-
#define ACCURATE_BOUND 10000000000LL
|
43
|
-
|
44
|
-
// how frequent to update rates & sum of rates in single test (recalculate)
|
45
|
-
#define UPDATE_SUM_FREQ_SM 100
|
46
|
-
#define UPDATE_SUM_FREQ_LG 10000
|
47
50
|
|
51
|
+
// Compare current rates with this bound
|
52
|
+
#define ACCURATE_BOUND 1LL << 33 // about 8.6 * 10^9
|
48
53
|
|
49
|
-
|
50
|
-
|
54
|
+
// how frequent to update rates & sum of rates in single test (recalculate)
|
55
|
+
#define UPDATE_SUM_ROUNDS_SM 100 // small, more frequent if some rate is larger than ACCURATE_BOUND
|
56
|
+
#define UPDATE_SUM_ROUNDS_LG 10000
|
51
57
|
|
52
58
|
|
53
59
|
|
@@ -90,11 +96,12 @@ typedef struct signal_t {
|
|
90
96
|
*/
|
91
97
|
static void find_nb_zero_flux(size_t* restrict nb, size_t i, size_t j, size_t N, size_t M, size_t NM);
|
92
98
|
static void find_nb_periodical(size_t* restrict nb, size_t i, size_t j, size_t N, size_t M, size_t NM);
|
93
|
-
static double single_init(const model_t* mod, patch_t* world, size_t* nb_indices,
|
94
|
-
double* patch_rates, double* sum_rates_by_row, double*
|
99
|
+
static double single_init(const model_t* restrict mod, patch_t* restrict world, size_t* restrict nb_indices,
|
100
|
+
double* restrict patch_rates, double* restrict sum_rates_by_row, double* restrict sum_rates_p,
|
101
|
+
signal_t* restrict sig_p, patch_picked_t* restrict picked_p);
|
95
102
|
static uint8_t single_test(model_t* restrict mod, char* message);
|
96
103
|
static void single_test_free(patch_t** world, size_t** nb_indices, double** patch_rates, double** sum_rates_by_row);
|
97
|
-
uint8_t run(model_t* mod, char* message, size_t msg_len);
|
104
|
+
uint8_t run(model_t* restrict mod, char* message, size_t msg_len);
|
98
105
|
|
99
106
|
|
100
107
|
|
@@ -107,7 +114,7 @@ static inline double random01() {
|
|
107
114
|
uint32_t r1 = rand() & 0x7fff; // RAND_MAX is different across machines, ensure 15 bits
|
108
115
|
uint32_t r2 = rand() & 0x7fff;
|
109
116
|
|
110
|
-
double r_combined = (r1 << 15) + r2;
|
117
|
+
double r_combined = (r1 << 15) + r2;
|
111
118
|
return (r_combined + 1) / RAND_UPPER_PLUS_2;
|
112
119
|
}
|
113
120
|
|
@@ -119,8 +126,8 @@ static inline void update_pi_k(patch_t* restrict p, const double* restrict M_sta
|
|
119
126
|
// M_start: start index of patch (i, j)'s matrix
|
120
127
|
// P_start: start index of p's patch variables, i.e., ij * 6
|
121
128
|
|
122
|
-
|
123
|
-
|
129
|
+
uint32_t U = p->U;
|
130
|
+
uint32_t V = p->V;
|
124
131
|
double sum = U + V;
|
125
132
|
double U_ratio = U / sum;
|
126
133
|
double V_ratio = V / sum;
|
@@ -163,8 +170,8 @@ static inline void update_mig_just_rate(patch_t* restrict p, const double* restr
|
|
163
170
|
double* p_U_weight = p->U_weight;
|
164
171
|
double* p_V_weight = p->V_weight;
|
165
172
|
|
166
|
-
double mu1_U = P_start[0] *
|
167
|
-
double mu2_V = P_start[1] *
|
173
|
+
double mu1_U = P_start[0] * p->U;
|
174
|
+
double mu2_V = P_start[1] * p->V;
|
168
175
|
|
169
176
|
double mu1_U_divide_sum = mu1_U / p->sum_U_weight;
|
170
177
|
double mu2_V_divide_sum = mu2_V / p->sum_V_weight;
|
@@ -347,9 +354,6 @@ static inline void change_popu(patch_t* restrict p, uint8_t s) {
|
|
347
354
|
p->V -= 1;
|
348
355
|
}
|
349
356
|
return;
|
350
|
-
//default:
|
351
|
-
// fprintf(stderr, "Bug: invalid event number in change_popu: %hhu\n", s);
|
352
|
-
// return;
|
353
357
|
}
|
354
358
|
}
|
355
359
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
__version__ = '2.3.
|
1
|
+
__version__ = '2.3.7'
|
2
2
|
|
3
3
|
'''
|
4
4
|
version history:
|
@@ -42,4 +42,6 @@ version history:
|
|
42
42
|
2.3.3: fix error in calculation of migration rates.
|
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
|
+
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.
|
45
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
|
-
|
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
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
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(
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
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
|
-
|
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(
|
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(
|
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
|
|
@@ -25,7 +25,7 @@ from numpy.ctypeslib import ndpointer
|
|
25
25
|
# check whether overflow / too large values might be encountered
|
26
26
|
# these values are considered as exponents in exp()
|
27
27
|
EXP_OVERFLOW_BOUND = 709 # where exp(x) almost reaches overflow bound
|
28
|
-
EXP_TOO_LARGE_BOUND =
|
28
|
+
EXP_TOO_LARGE_BOUND = 30 # where exp(x) reaches ~10e13 and accuracy goes below 10^-3 (10^-3 isn't accurate any more)
|
29
29
|
|
30
30
|
|
31
31
|
# read the C core into LIB
|
@@ -36,6 +36,7 @@ SIM_SUCCESS = 0
|
|
36
36
|
SIM_DATA_EMPTY = 1
|
37
37
|
SIM_SMALL_MAXTIME = 2
|
38
38
|
SIM_OVERFLOW = 3
|
39
|
+
ACCURACY_ERROR = 4
|
39
40
|
|
40
41
|
|
41
42
|
'''
|
@@ -449,7 +450,11 @@ def run(mod, message = ""):
|
|
449
450
|
elif result == SIM_OVERFLOW:
|
450
451
|
LIB.mod_free_py(ctypes.byref(mod_c))
|
451
452
|
del mod_c
|
452
|
-
raise OverflowError('Overflow in simulation')
|
453
|
+
raise OverflowError('Overflow in simulation. Possibly due to too large w1, w2, or payoff.')
|
454
|
+
elif result == ACCURACY_ERROR:
|
455
|
+
LIB.mod_free_py(ctypes.byref(mod_c))
|
456
|
+
del mod_c
|
457
|
+
raise RuntimeError('Accuracy dropped catastrophically during simulation. Possibly due to too large w1, w2, or payoff.')
|
453
458
|
else:
|
454
459
|
LIB.mod_free_py(ctypes.byref(mod_c))
|
455
460
|
del mod_c
|
@@ -524,9 +529,9 @@ def check_overflow_func(mod):
|
|
524
529
|
w1_pi = pi_expected[i][j] * mod.P[i][j][2] # w1 * U_pi
|
525
530
|
w2_pi = pi_expected[i][j] * mod.P[i][j][3] # w2 * V_pi
|
526
531
|
if ((w1_pi > EXP_OVERFLOW_BOUND) or (w2_pi > EXP_OVERFLOW_BOUND)):
|
527
|
-
print("Warning: might cause overflow.
|
532
|
+
print("Warning: might cause overflow in simulation. w1, w2, or payoff matrix values too large")
|
528
533
|
return
|
529
534
|
if ((w1_pi > EXP_TOO_LARGE_BOUND) or (w2_pi > EXP_TOO_LARGE_BOUND)):
|
530
|
-
print("Warning: might
|
535
|
+
print("Warning: might have low accuracy in simulation. w1, w2, or payoff matrix values too large")
|
531
536
|
return
|
532
537
|
|
@@ -92,8 +92,9 @@ 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
|
-
|
96
|
-
|
95
|
+
del sim2
|
96
|
+
except (OverflowError, RuntimeError):
|
97
|
+
print(current_var_str + ' raised error, skipped')
|
97
98
|
continue
|
98
99
|
|
99
100
|
return var_dirs
|
@@ -139,8 +140,9 @@ 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)
|
142
|
-
|
143
|
-
|
143
|
+
del sim2
|
144
|
+
except (OverflowError, RuntimeError):
|
145
|
+
print(current_var_str + ' raised error, skipped')
|
144
146
|
continue
|
145
147
|
|
146
148
|
return var_dirs
|
@@ -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
|
512
|
+
for k in range(len(var_dirs)):
|
513
|
+
dirs = var_dirs[k]
|
511
514
|
try:
|
512
|
-
|
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(
|
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
|
581
|
+
for k in range(len(sublist)):
|
582
|
+
dirs = sublist[k]
|
578
583
|
try:
|
579
|
-
|
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(
|
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
|
|
@@ -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
|
-
|
14
|
-
|
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
|
-
|
210
|
-
|
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
|
240
|
-
|
241
|
-
|
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
|
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)
|
281
|
-
fig_V, ax_V = plt.subplots(figsize = figsize)
|
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,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, 100, 100, 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
|
File without changes
|
File without changes
|
File without changes
|