piegy 2.3.4__tar.gz → 2.3.6__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.4/src/piegy.egg-info → piegy-2.3.6}/PKG-INFO +1 -1
- {piegy-2.3.4 → piegy-2.3.6}/pyproject.toml +1 -1
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/C_core/Makefile +0 -1
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/C_core/runner.c +4 -5
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/C_core/sim_funcs.c +88 -73
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/C_core/sim_funcs.h +13 -21
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/__version__.py +3 -1
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/figures.py +4 -4
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/simulation.py +12 -11
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/test_var.py +4 -4
- {piegy-2.3.4 → piegy-2.3.6/src/piegy.egg-info}/PKG-INFO +1 -1
- {piegy-2.3.4 → piegy-2.3.6}/LICENSE.txt +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/MANIFEST.in +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/README.md +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/setup.cfg +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/setup.py +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/C_core/model.c +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/C_core/model.h +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/C_core/patch.c +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/C_core/patch.h +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/__init__.py +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/analysis.py +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/build_info.py +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/data_tools.py +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/simulation_py.py +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/tools/__init__.py +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/tools/figure_tools.py +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/tools/file_tools.py +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/tools/find_C.py +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy/videos.py +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy.egg-info/SOURCES.txt +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy.egg-info/dependency_links.txt +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy.egg-info/requires.txt +0 -0
- {piegy-2.3.4 → piegy-2.3.6}/src/piegy.egg-info/top_level.txt +0 -0
@@ -11,13 +11,13 @@
|
|
11
11
|
int main() {
|
12
12
|
size_t N = 1;
|
13
13
|
size_t M = 100;
|
14
|
-
double maxtime =
|
14
|
+
double maxtime = 300;
|
15
15
|
double record_itv = 0.1;
|
16
16
|
size_t sim_time = 1;
|
17
17
|
bool boundary = true;
|
18
|
-
uint32_t I_single[2] = {
|
18
|
+
uint32_t I_single[2] = {3, 3};
|
19
19
|
double X_single[4] = {-1, 4, 0, 2};
|
20
|
-
double P_single[6] = {0.5, 0.5,
|
20
|
+
double P_single[6] = {0.5, 0.5, 80, 80, 0.001, 0.001};
|
21
21
|
int32_t print_pct = 1;
|
22
22
|
int32_t seed = 36; // -1 for None
|
23
23
|
|
@@ -46,8 +46,7 @@ int main() {
|
|
46
46
|
mod_init(mod, N, M, maxtime, record_itv, sim_time, boundary, I, X, P, print_pct, seed);
|
47
47
|
|
48
48
|
char message[20] = ""; // writable buffer with enough space
|
49
|
-
|
50
|
-
uint8_t result = run(mod, message, 20, update_sum_freq);
|
49
|
+
uint8_t result = run(mod, message, 20);
|
51
50
|
|
52
51
|
/*for (size_t i = 0; i < mod->max_record; i++) {
|
53
52
|
fprintf(stdout, "%f ", mod->U1d[i]);
|
@@ -68,8 +68,9 @@ 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;
|
@@ -145,6 +146,9 @@ static double single_init(const model_t* mod, patch_t* world, size_t* nb_indices
|
|
145
146
|
find_patch(picked_p, expected_sum, patch_rates, sum_rates_by_row, *sum_rates_p, N, M);
|
146
147
|
size_t picked_idx = picked_p->i * M + picked_p->j;
|
147
148
|
size_t e0 = find_event(&world[picked_idx], expected_sum - picked_p->current_sum);
|
149
|
+
if (picked_idx >= NM || e0 >= 12) {
|
150
|
+
return -1 * ACCURACY_ERROR;
|
151
|
+
}
|
148
152
|
|
149
153
|
// make signal
|
150
154
|
if (mod->boundary) {
|
@@ -191,7 +195,7 @@ static double single_init(const model_t* mod, patch_t* world, size_t* nb_indices
|
|
191
195
|
|
192
196
|
|
193
197
|
|
194
|
-
static uint8_t single_test(model_t* restrict mod,
|
198
|
+
static uint8_t single_test(model_t* restrict mod, char* message) {
|
195
199
|
// bring some dimensions to the front
|
196
200
|
size_t N = mod->N;
|
197
201
|
size_t M = mod->M;
|
@@ -201,9 +205,9 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
|
|
201
205
|
double record_itv = mod->record_itv;
|
202
206
|
bool boundary = mod->boundary;
|
203
207
|
|
204
|
-
|
208
|
+
// print progress
|
205
209
|
double one_progress = 0.0;
|
206
|
-
|
210
|
+
double current_progress = one_progress;
|
207
211
|
if (mod->print_pct != -1) {
|
208
212
|
one_progress = maxtime * mod->print_pct / 100.0;
|
209
213
|
fprintf(stdout, "\r ");
|
@@ -213,11 +217,11 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
|
|
213
217
|
one_progress = 2.0 * maxtime;
|
214
218
|
}
|
215
219
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
220
|
+
// update sum of rates every 1e5 rounds
|
221
|
+
// many rates are updated each time, rather than re-calculated.
|
222
|
+
// So need to re-calculate from scratch every some rounds to reduce numerical errors
|
223
|
+
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
|
221
225
|
|
222
226
|
// Initialize simulation
|
223
227
|
patch_t* world = (patch_t*) calloc(NM, sizeof(patch_t));
|
@@ -242,54 +246,61 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
|
|
242
246
|
fflush(stdout);
|
243
247
|
single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
|
244
248
|
return SIM_OVERFLOW;
|
245
|
-
}
|
249
|
+
} else if (time == -1 * ACCURACY_ERROR) {
|
250
|
+
fprintf(stdout, "\nError: accuracy too low at t = 0, simulation stopped\n");
|
251
|
+
fflush(stdout);
|
252
|
+
single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
|
253
|
+
return ACCURACY_ERROR;
|
254
|
+
}
|
246
255
|
size_t record_index = time / mod->record_itv;
|
247
256
|
double record_time = time - record_index * record_itv;
|
248
257
|
|
249
258
|
|
250
259
|
while (time < maxtime) {
|
251
260
|
|
252
|
-
// Print progress
|
253
|
-
if (time >
|
254
|
-
|
255
|
-
if (
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
} else {
|
260
|
-
fprintf(stdout, "\r%s: %d%%", message, (int)(time * 100 / maxtime));
|
261
|
-
}
|
262
|
-
fflush(stdout);
|
263
|
-
//fflush(stdout); // Make sure it prints immediately
|
264
|
-
current_progress += one_progress;
|
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));
|
265
268
|
}
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
269
|
+
fflush(stdout);
|
270
|
+
//fflush(stdout); // Make sure it prints immediately
|
271
|
+
current_progress += one_progress;
|
272
|
+
}
|
273
|
+
|
274
|
+
// update sums
|
275
|
+
curr_update_sum_round++;
|
276
|
+
if (curr_update_sum_round > update_sum_rounds) {
|
277
|
+
curr_update_sum_round = 0;
|
278
|
+
|
279
|
+
update_sum_rounds = UPDATE_SUM_ROUNDS_LG; // assume can make it larger
|
280
|
+
for (size_t ij = 0; ij < NM; ij++) {
|
281
|
+
double sum_U_weight = 0;
|
282
|
+
double sum_V_weight = 0;
|
283
|
+
for (size_t k = 0; k < 4; k++) {
|
284
|
+
sum_U_weight += world[ij].U_weight[k];
|
285
|
+
sum_V_weight += world[ij].V_weight[k];
|
280
286
|
}
|
281
|
-
|
282
|
-
|
283
|
-
sum_rates_by_row[i] = 0;
|
284
|
-
for (size_t j = 0; j < M; j++) {
|
285
|
-
sum_rates_by_row[i] += patch_rates[ij];
|
286
|
-
ij++;
|
287
|
-
}
|
287
|
+
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
|
288
289
|
}
|
289
|
-
|
290
|
-
|
291
|
-
|
290
|
+
world[ij].sum_U_weight = sum_U_weight;
|
291
|
+
world[ij].sum_V_weight = sum_V_weight;
|
292
|
+
// patch_rates are updated every time a patch is changed
|
293
|
+
}
|
294
|
+
size_t ij = 0;
|
295
|
+
sum_rates = 0;
|
296
|
+
for (size_t i = 0; i < N; i++) {
|
297
|
+
double sum_rates_by_row_i = 0;
|
298
|
+
for (size_t j = 0; j < M; j++) {
|
299
|
+
sum_rates_by_row_i += patch_rates[ij];
|
300
|
+
ij++;
|
292
301
|
}
|
302
|
+
sum_rates_by_row[i] = sum_rates_by_row_i;
|
303
|
+
sum_rates += sum_rates_by_row_i;
|
293
304
|
}
|
294
305
|
}
|
295
306
|
|
@@ -301,13 +312,14 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
|
|
301
312
|
size_t sij1 = signal.ij1;
|
302
313
|
size_t sij2 = signal.ij2;
|
303
314
|
uint8_t rela_loc = signal.rela_loc;
|
315
|
+
|
304
316
|
if (rela_loc == NO_MIG) {
|
305
317
|
// if only one
|
306
318
|
sum_rates_by_row[si1] -= patch_rates[sij1];
|
307
319
|
sum_rates -= patch_rates[sij1];
|
308
320
|
|
309
321
|
update_pi_k(&world[sij1], &(mod->X[sij1 * 4]), &(mod->P[sij1 * 6]));
|
310
|
-
|
322
|
+
update_mig_just_rate(&world[sij1], &(mod->P[sij1 * 6]));
|
311
323
|
|
312
324
|
patch_rates[sij1] = world[sij1].sum_pi_death_rates + world[sij1].sum_mig_rates;
|
313
325
|
sum_rates_by_row[si1] += patch_rates[sij1];
|
@@ -358,7 +370,8 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
|
|
358
370
|
for (uint8_t k = 0; k < 4; k++) {
|
359
371
|
size_t nb_idx = nb_indices[sij1 * 4 + k];
|
360
372
|
if (nb_idx == NM) { continue; }
|
361
|
-
if (
|
373
|
+
if (k != rela_loc) {
|
374
|
+
// nb_idx isn't the second last-changed patch
|
362
375
|
if (update_mig_weight_rate(&world[nb_idx], &(mod->P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
|
363
376
|
fprintf(stdout, "\nError: overflow at t = %f\n", time);
|
364
377
|
fflush(stdout);
|
@@ -371,7 +384,8 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
|
|
371
384
|
for (uint8_t k = 0; k < 4; k++) {
|
372
385
|
size_t nb_idx = nb_indices[sij2 * 4 + k];
|
373
386
|
if (nb_idx == NM) { continue; }
|
374
|
-
if (
|
387
|
+
if (k != (rela_loc ^ 1)) {
|
388
|
+
// nb_idx isn't the first last-changed patch
|
375
389
|
if (update_mig_weight_rate(&world[nb_idx], &(mod->P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
|
376
390
|
fprintf(stdout, "\nError: overflow at t = %f\n", time);
|
377
391
|
fflush(stdout);
|
@@ -388,6 +402,12 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
|
|
388
402
|
find_patch(&picked, expected_sum, patch_rates, sum_rates_by_row, sum_rates, N, M);
|
389
403
|
size_t picked_idx = picked.i * M + picked.j;
|
390
404
|
uint8_t e0 = find_event(&world[picked_idx], expected_sum - picked.current_sum);
|
405
|
+
if (picked_idx >= NM || e0 >= 12) {
|
406
|
+
fprintf(stdout, "\nError: accuracy too low at t = %f, simulation stopped\n", time);
|
407
|
+
fflush(stdout);
|
408
|
+
single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
|
409
|
+
return ACCURACY_ERROR;
|
410
|
+
}
|
391
411
|
|
392
412
|
// make signal
|
393
413
|
if (boundary) {
|
@@ -416,16 +436,12 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
|
|
416
436
|
record_time -= multi_records * record_itv;
|
417
437
|
size_t upper = record_index + multi_records;
|
418
438
|
|
419
|
-
size_t ij = 0;
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
mod->Upi_1d[ij * max_record + k] += world[ij].U_pi;
|
426
|
-
mod->Vpi_1d[ij * max_record + k] += world[ij].V_pi;
|
427
|
-
}
|
428
|
-
ij++;
|
439
|
+
for (size_t ij = 0; ij < NM; ij++) {
|
440
|
+
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;
|
429
445
|
}
|
430
446
|
}
|
431
447
|
record_index += multi_records;
|
@@ -433,16 +449,12 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
|
|
433
449
|
|
434
450
|
} else {
|
435
451
|
// if already exceeds maxtime
|
436
|
-
size_t ij = 0;
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
mod->Upi_1d[ij * max_record + k] += world[ij].U_pi;
|
443
|
-
mod->Vpi_1d[ij * max_record + k] += world[ij].V_pi;
|
444
|
-
}
|
445
|
-
ij++;
|
452
|
+
for (size_t ij = 0; ij < NM; ij++) {
|
453
|
+
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;
|
446
458
|
}
|
447
459
|
}
|
448
460
|
}
|
@@ -475,7 +487,7 @@ static void single_test_free(patch_t** world, size_t** nb_indices, double** patc
|
|
475
487
|
|
476
488
|
|
477
489
|
|
478
|
-
uint8_t run(model_t* mod, char* message, size_t msg_len
|
490
|
+
uint8_t run(model_t* restrict mod, char* message, size_t msg_len) {
|
479
491
|
if (!mod->data_empty) {
|
480
492
|
// this won't happen if called from python, the ``simulation.run`` caller has checked it.
|
481
493
|
fprintf(stdout, "Error: mod has non-empty data\n");
|
@@ -518,7 +530,7 @@ uint8_t run(model_t* mod, char* message, size_t msg_len, uint32_t update_sum_fre
|
|
518
530
|
snprintf(end_info, sizeof(end_info), ", ~%.2fs left", pred_runtime);
|
519
531
|
}*/
|
520
532
|
|
521
|
-
uint8_t result = single_test(mod,
|
533
|
+
uint8_t result = single_test(mod, curr_msg);
|
522
534
|
|
523
535
|
switch (result) {
|
524
536
|
case SUCCESS:
|
@@ -530,6 +542,9 @@ uint8_t run(model_t* mod, char* message, size_t msg_len, uint32_t update_sum_fre
|
|
530
542
|
case SIM_OVERFLOW:
|
531
543
|
// error message is handled by single_test
|
532
544
|
return SIM_OVERFLOW;
|
545
|
+
case ACCURACY_ERROR:
|
546
|
+
// error message is handled by single_test
|
547
|
+
return ACCURACY_ERROR;
|
533
548
|
}
|
534
549
|
}
|
535
550
|
|
@@ -35,10 +35,16 @@
|
|
35
35
|
#define DATA_NOT_EMPTY 1
|
36
36
|
#define SMALL_MAXTIME 2
|
37
37
|
#define SIM_OVERFLOW 3
|
38
|
+
#define ACCURACY_ERROR 4
|
38
39
|
|
39
40
|
// where exp(x) is considered overflow
|
40
|
-
// below the actual bound (709)
|
41
|
+
// below the actual bound (709) to preserve accuracy
|
41
42
|
#define EXP_OVERFLOW_BOUND 500
|
43
|
+
#define ACCURATE_BOUND 10000000000LL
|
44
|
+
|
45
|
+
// how frequent to update rates & sum of rates in single test (recalculate)
|
46
|
+
#define UPDATE_SUM_ROUNDS_SM 100
|
47
|
+
#define UPDATE_SUM_ROUNDS_LG 10000
|
42
48
|
|
43
49
|
|
44
50
|
static uint64_t pcg_state = 0;
|
@@ -85,11 +91,12 @@ typedef struct signal_t {
|
|
85
91
|
*/
|
86
92
|
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);
|
87
93
|
static void find_nb_periodical(size_t* restrict nb, size_t i, size_t j, size_t N, size_t M, size_t NM);
|
88
|
-
static double single_init(const model_t* mod, patch_t* world, size_t* nb_indices,
|
89
|
-
double* patch_rates, double* sum_rates_by_row, double*
|
90
|
-
|
94
|
+
static double single_init(const model_t* restrict mod, patch_t* restrict world, size_t* restrict nb_indices,
|
95
|
+
double* restrict patch_rates, double* restrict sum_rates_by_row, double* restrict sum_rates_p,
|
96
|
+
signal_t* restrict sig_p, patch_picked_t* restrict picked_p);
|
97
|
+
static uint8_t single_test(model_t* restrict mod, char* message);
|
91
98
|
static void single_test_free(patch_t** world, size_t** nb_indices, double** patch_rates, double** sum_rates_by_row);
|
92
|
-
uint8_t run(model_t* mod, char* message, size_t msg_len
|
99
|
+
uint8_t run(model_t* restrict mod, char* message, size_t msg_len);
|
93
100
|
|
94
101
|
|
95
102
|
|
@@ -153,7 +160,6 @@ static inline void update_pi_k(patch_t* restrict p, const double* restrict M_sta
|
|
153
160
|
|
154
161
|
|
155
162
|
static inline void update_mig_just_rate(patch_t* restrict p, const double* restrict P_start) {
|
156
|
-
// BUGGY - not using
|
157
163
|
// update migration weight for patch p, in location loc. Only rate is updated
|
158
164
|
// used by last-changed patch, when there is only one last-changed patch
|
159
165
|
double* p_U_weight = p->U_weight;
|
@@ -161,7 +167,6 @@ static inline void update_mig_just_rate(patch_t* restrict p, const double* restr
|
|
161
167
|
|
162
168
|
double mu1_U = P_start[0] * (double)p->U;
|
163
169
|
double mu2_V = P_start[1] * (double)p->V;
|
164
|
-
p->sum_mig_rates = mu1_U + mu2_V;
|
165
170
|
|
166
171
|
double mu1_U_divide_sum = mu1_U / p->sum_U_weight;
|
167
172
|
double mu2_V_divide_sum = mu2_V / p->sum_V_weight;
|
@@ -170,6 +175,7 @@ static inline void update_mig_just_rate(patch_t* restrict p, const double* restr
|
|
170
175
|
p->mig_rates[i] = mu1_U_divide_sum * p_U_weight[i];
|
171
176
|
p->mig_rates[i + 4] = mu2_V_divide_sum * p_V_weight[i];
|
172
177
|
}
|
178
|
+
p->sum_mig_rates = mu1_U + mu2_V;
|
173
179
|
}
|
174
180
|
|
175
181
|
|
@@ -245,7 +251,6 @@ static inline uint8_t init_mig(patch_t* restrict p, const double* restrict P_sta
|
|
245
251
|
|
246
252
|
for (uint8_t i = 0; i < 4; i++) {
|
247
253
|
patch_t* nbi = p->nb[i];
|
248
|
-
|
249
254
|
if (nbi) {
|
250
255
|
// not NULL
|
251
256
|
double w1_Upi = w1 * nbi->U_pi;
|
@@ -264,7 +269,6 @@ static inline uint8_t init_mig(patch_t* restrict p, const double* restrict P_sta
|
|
264
269
|
}
|
265
270
|
}
|
266
271
|
|
267
|
-
|
268
272
|
double mu1_U = P_start[0] * (double)p->U;
|
269
273
|
double mu2_V = P_start[1] * (double)p->V;
|
270
274
|
double mu1_U_divide_sum = mu1_U / p->sum_U_weight;
|
@@ -583,16 +587,4 @@ static inline void make_signal_periodical(size_t N, size_t M, size_t i, size_t j
|
|
583
587
|
}
|
584
588
|
|
585
589
|
|
586
|
-
static inline bool nb_need_change(size_t nb_idx, size_t sij1, size_t sij2) {
|
587
|
-
// a nb doesn't need change only if two patches are updated
|
588
|
-
|
589
|
-
// or, can try this 1-line version
|
590
|
-
// return (nb_idx != sij1) && (nb_idx != sij2);
|
591
|
-
if ((nb_idx == sij1) || (nb_idx == sij2)) {
|
592
|
-
return false;
|
593
|
-
}
|
594
|
-
return true; // need to change
|
595
|
-
}
|
596
|
-
|
597
|
-
|
598
590
|
#endif
|
@@ -1,4 +1,4 @@
|
|
1
|
-
__version__ = '2.3.
|
1
|
+
__version__ = '2.3.6'
|
2
2
|
|
3
3
|
'''
|
4
4
|
version history:
|
@@ -41,4 +41,6 @@ version history:
|
|
41
41
|
Simplified update-migration functions, improve speed by ~10%. Add -march=native flag to Makefile.
|
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
|
+
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.
|
44
46
|
'''
|
@@ -530,19 +530,19 @@ def video_fig(mod, ax_list = None, num_grid = 100, U_color = 'Purples', V_color
|
|
530
530
|
|
531
531
|
|
532
532
|
im = ax_list[0, 0].imshow(ave_U, cmap = U_color)
|
533
|
-
ax_list[0, 0].get_figure().colorbar(im, ax = ax_list[0, 0])
|
533
|
+
ax_list[0, 0].get_figure().colorbar(im, ax = ax_list[0, 0], extent = [0, mod.N * mod.M, 0, mod.maxtime], origin='lower', aspect = 'auto')
|
534
534
|
ax_list[0, 0].set_title('Population U over time')
|
535
535
|
|
536
536
|
im = ax_list[0, 1].imshow(ave_V, cmap = V_color)
|
537
|
-
ax_list[0, 1].get_figure().colorbar(im, ax = ax_list[0, 1])
|
537
|
+
ax_list[0, 1].get_figure().colorbar(im, ax = ax_list[0, 1], extent = [0, mod.N * mod.M, 0, mod.maxtime], origin='lower', aspect = 'auto')
|
538
538
|
ax_list[0, 1].set_title('Population V over time')
|
539
539
|
|
540
540
|
im = ax_list[1, 0].imshow(ave_Upi, cmap = U_color)
|
541
|
-
ax_list[1, 0].get_figure().colorbar(im, ax = ax_list[1, 0])
|
541
|
+
ax_list[1, 0].get_figure().colorbar(im, ax = ax_list[1, 0], extent = [0, mod.N * mod.M, 0, mod.maxtime], origin='lower', aspect = 'auto')
|
542
542
|
ax_list[1, 0].set_title('Payoff ' + r'$p_H$' + ' over time')
|
543
543
|
|
544
544
|
im = ax_list[1, 1].imshow(ave_Vpi, cmap = V_color)
|
545
|
-
ax_list[1, 1].get_figure().colorbar(im, ax = ax_list[1, 1])
|
545
|
+
ax_list[1, 1].get_figure().colorbar(im, ax = ax_list[1, 1], extent = [0, mod.N * mod.M, 0, mod.maxtime], origin='lower', aspect = 'auto')
|
546
546
|
ax_list[1, 1].set_title('Payoff ' + r'$p_D$' + ' over time')
|
547
547
|
|
548
548
|
return ax_list
|
@@ -25,11 +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 =
|
29
|
-
|
30
|
-
# how frequent to update sum in simulation, i.e., accuracy
|
31
|
-
# the defuault value is 64, increase to 4 times if encounter error
|
32
|
-
UPDATE_SUM_FREQ = 64
|
28
|
+
EXP_TOO_LARGE_BOUND = 30 # where exp(x) reaches ~10e13 and accuracy goes below 10^-3 (10^-3 isn't accurate any more)
|
33
29
|
|
34
30
|
|
35
31
|
# read the C core into LIB
|
@@ -40,6 +36,7 @@ SIM_SUCCESS = 0
|
|
40
36
|
SIM_DATA_EMPTY = 1
|
41
37
|
SIM_SMALL_MAXTIME = 2
|
42
38
|
SIM_OVERFLOW = 3
|
39
|
+
ACCURACY_ERROR = 4
|
43
40
|
|
44
41
|
|
45
42
|
'''
|
@@ -101,7 +98,7 @@ def read_lib():
|
|
101
98
|
LIB.mod_free_py.argtypes = [ctypes.POINTER(model_c)]
|
102
99
|
LIB.mod_free_py.restype = None
|
103
100
|
|
104
|
-
LIB.run.argtypes = [ctypes.POINTER(model_c), ctypes.POINTER(c_char), c_size_t
|
101
|
+
LIB.run.argtypes = [ctypes.POINTER(model_c), ctypes.POINTER(c_char), c_size_t]
|
105
102
|
LIB.run.restype = c_ubyte # which is uint8
|
106
103
|
|
107
104
|
|
@@ -410,7 +407,7 @@ class model:
|
|
410
407
|
|
411
408
|
|
412
409
|
|
413
|
-
def run(mod, message = ""
|
410
|
+
def run(mod, message = ""):
|
414
411
|
'''
|
415
412
|
C-cored simulation
|
416
413
|
'''
|
@@ -437,7 +434,7 @@ def run(mod, message = "", update_sum_freq = UPDATE_SUM_FREQ):
|
|
437
434
|
del mod_c
|
438
435
|
raise RuntimeError('Model initialization failed')
|
439
436
|
|
440
|
-
result = LIB.run(ctypes.byref(mod_c), msg_buffer, msg_len
|
437
|
+
result = LIB.run(ctypes.byref(mod_c), msg_buffer, msg_len)
|
441
438
|
|
442
439
|
if result == SIM_SUCCESS:
|
443
440
|
mod.set_data(False, mod.max_record, 1, mod_c.get_array('U1d').reshape(mod.N, mod.M, mod.max_record),
|
@@ -453,7 +450,11 @@ def run(mod, message = "", update_sum_freq = UPDATE_SUM_FREQ):
|
|
453
450
|
elif result == SIM_OVERFLOW:
|
454
451
|
LIB.mod_free_py(ctypes.byref(mod_c))
|
455
452
|
del mod_c
|
456
|
-
raise OverflowError('Overflow in simulation')
|
453
|
+
raise OverflowError('Overflow in simulation. Possibly due to too large w1, w2, or payoff matrix values.')
|
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 matrix values.')
|
457
458
|
else:
|
458
459
|
LIB.mod_free_py(ctypes.byref(mod_c))
|
459
460
|
del mod_c
|
@@ -528,9 +529,9 @@ def check_overflow_func(mod):
|
|
528
529
|
w1_pi = pi_expected[i][j] * mod.P[i][j][2] # w1 * U_pi
|
529
530
|
w2_pi = pi_expected[i][j] * mod.P[i][j][3] # w2 * V_pi
|
530
531
|
if ((w1_pi > EXP_OVERFLOW_BOUND) or (w2_pi > EXP_OVERFLOW_BOUND)):
|
531
|
-
print("Warning: might cause overflow. \n\t w1, w2, or payoff matrix values too large")
|
532
|
+
print("Warning: might cause overflow in simulation. \n\t w1, w2, or payoff matrix values too large")
|
532
533
|
return
|
533
534
|
if ((w1_pi > EXP_TOO_LARGE_BOUND) or (w2_pi > EXP_TOO_LARGE_BOUND)):
|
534
|
-
print("Warning: might
|
535
|
+
print("Warning: might have low accuracy in simulation. \n\t w1, w2, or payoff matrix values too large")
|
535
536
|
return
|
536
537
|
|
@@ -92,8 +92,8 @@ 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
|
-
except OverflowError:
|
96
|
-
print(current_var_str + ' raised
|
95
|
+
except (OverflowError, RuntimeError):
|
96
|
+
print(current_var_str + ' raised error, skipped')
|
97
97
|
continue
|
98
98
|
|
99
99
|
return var_dirs
|
@@ -139,8 +139,8 @@ def test_var2(mod, var1, var2, values1, values2, dirs, compress_itv = None):
|
|
139
139
|
if compress_itv != None:
|
140
140
|
sim2.compress_data(compress_itv)
|
141
141
|
data_t.save_data(sim2, var_dirs[k1][k2], print_msg = False)
|
142
|
-
except OverflowError:
|
143
|
-
print(current_var_str + ' raised
|
142
|
+
except (OverflowError, RuntimeError):
|
143
|
+
print(current_var_str + ' raised error, skipped')
|
144
144
|
continue
|
145
145
|
|
146
146
|
return var_dirs
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|