piegy 2.1.0__cp38-cp38-win32.whl → 2.1.9__cp38-cp38-win32.whl

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.
@@ -0,0 +1,547 @@
1
+ /**
2
+ * This .h defines the simulation functions in piegy.simulation
3
+ */
4
+
5
+ #ifndef SIM_FUNCS
6
+ #define SIM_FUNCS
7
+
8
+ #include <stdlib.h>
9
+ #include <stdint.h>
10
+ #include <stdio.h>
11
+ #include <stdbool.h>
12
+ #include <string.h>
13
+ #include <time.h>
14
+ #include <math.h>
15
+
16
+ #include "patch.h"
17
+ #include "model.h"
18
+
19
+
20
+
21
+ // upper bound for RNG is 2^24 + 1
22
+ #define RAND_UPPER_PLUS_2 (double) (0xffffffu + 2)
23
+
24
+ // directions of migration
25
+ // so that 3 - mig_dir = reflection of it. Used to track neighbors
26
+ // the actual implementation of signals still uses this order: up, down, left, right
27
+ #define MIG_UP 0
28
+ #define MIG_DOWN 1
29
+ #define MIG_LEFT 2
30
+ #define MIG_RIGHT 3
31
+
32
+ // results of single_test
33
+ #define SUCCESS 0
34
+ #define GENERAL_FAILURE 1
35
+ #define SMALL_MAXTIME 2
36
+ #define OVERFLOW 3
37
+
38
+ // where exp(x) reaches overflow bound (just below it)
39
+ #define EXP_OVERFLOW_BOUND 700
40
+
41
+
42
+ static uint64_t pcg_state = 0;
43
+ static uint64_t pcg_inc = 0;
44
+
45
+
46
+
47
+
48
+ /**
49
+ * index of patch in find_patch
50
+ */
51
+ typedef struct patch_picked_t {
52
+ size_t i;
53
+ size_t j;
54
+ double current_sum;
55
+ } patch_picked_t;
56
+
57
+ /**
58
+ * index & event number in make_signal_*
59
+ */
60
+ typedef struct signal_t {
61
+ // does the signal only have the first patch?
62
+ bool only_first;
63
+
64
+ // the first patch
65
+ size_t i1;
66
+ size_t j1;
67
+ size_t ij1; // i1 * M + j1
68
+ uint8_t e1;
69
+
70
+ // the second patch
71
+ size_t i2;
72
+ size_t j2;
73
+ size_t ij2;
74
+ uint8_t e2;
75
+ } signal_t;
76
+
77
+
78
+
79
+ /**
80
+ * Defined in .c
81
+ */
82
+ 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);
83
+ static void find_nb_periodical(size_t* restrict nb, size_t i, size_t j, size_t N, size_t M, size_t NM);
84
+ static double single_init(const model_t* mod, patch_t* world, size_t* nb_indices,
85
+ double* patch_rates, double* sum_rates_by_row, double* sum_rates, signal_t* sig_p, patch_picked_t* picked_p) ;
86
+ static void single_test(model_t* restrict mod, uint32_t update_sum_frequency, uint32_t* result, char* message);
87
+ static void single_test_free(patch_t* world, size_t* nb_indices, double* patch_rates, double* sum_rates_by_row);
88
+ void run(model_t* mod, char* message, size_t msg_len);
89
+
90
+
91
+ /**
92
+ * Inline Functions
93
+ */
94
+
95
+ static inline double random01() {
96
+ // generate a 24 bit random int, then convert to a (0, 1) ranged double
97
+ uint32_t r1 = rand() & 0x7fff; // RAND_MAX is different across machines, ensure 15 bits
98
+ uint32_t r2 = rand() & 0x7fff;
99
+
100
+ double r_combined = ((r1 >> 3) << 12) + (r2 >> 3); // discard the lower 3 bits, which are unstable
101
+ return (r_combined + 1) / RAND_UPPER_PLUS_2;
102
+ }
103
+
104
+ /**
105
+ * patch functions
106
+ */
107
+
108
+ static inline void update_pi_k(patch_t* restrict p, const double* restrict M_start, const double* restrict P_kappa_start) {
109
+ // M_start: start index of patch (i, j)'s matrix
110
+ // P_kappa_start: start index of patch (i, j)'s kappa values (the 4th and 5th, 0-indexed)
111
+
112
+ double U = (double) p->U;
113
+ double V = (double) p->V;
114
+ double sum_minus_1 = U + V - 1.0;
115
+
116
+ if (sum_minus_1 > 0) {
117
+ if (U != 0) {
118
+ p->U_pi = ((U - 1) / sum_minus_1) * M_start[0] +
119
+ (V / sum_minus_1) * M_start[1];
120
+ } else {
121
+ p->U_pi = 0.0;
122
+ }
123
+
124
+ if (V != 0) {
125
+ p->V_pi = (U / sum_minus_1) * M_start[2] +
126
+ ((V - 1) / sum_minus_1) * M_start[3];
127
+ } else {
128
+ p->V_pi = 0.0;
129
+ }
130
+
131
+ } else {
132
+ p->U_pi = 0.0;
133
+ p->V_pi = 0.0;
134
+ }
135
+
136
+ p->pi_death_rates[0] = fabs(U * p->U_pi);
137
+ p->pi_death_rates[1] = fabs(V * p->V_pi);
138
+
139
+ p->pi_death_rates[2] = P_kappa_start[0] * U * (sum_minus_1 + 1.0);
140
+ p->pi_death_rates[3] = P_kappa_start[1] * V * (sum_minus_1 + 1.0);
141
+
142
+ p->sum_pi_death_rates = 0.0;
143
+ for (size_t i = 0; i < 4; i++) {
144
+ p->sum_pi_death_rates += p->pi_death_rates[i];
145
+ }
146
+ }
147
+
148
+
149
+ static inline void update_mig_one(patch_t* restrict p, const double* restrict P_start, uint8_t nb_loc) {
150
+ // update mig rate for one direction
151
+ // P_start: start index of p's patch variables, i.e., ij * 6
152
+ // nb_loc: location of neighbor, up, down, left, right
153
+
154
+ double mu1_U = P_start[0] * (double)p->U;
155
+ double mu2_V = P_start[1] * (double)p->V;
156
+ double* p_U_weight = p->U_weight;
157
+ double* p_V_weight = p->V_weight;
158
+
159
+ patch_t* nbi = p->nb[nb_loc];
160
+ p->sum_U_weight -= p_U_weight[nb_loc];
161
+ p->sum_V_weight -= p_V_weight[nb_loc];
162
+
163
+ switch(nb_loc) {
164
+ case MIG_UP:
165
+ p_U_weight[MIG_UP] = 1.0 + exp(P_start[2] * nbi->U_pi);
166
+ p_V_weight[MIG_UP] = 1.0 + exp(P_start[3] * nbi->V_pi);
167
+ break;
168
+ case MIG_DOWN:
169
+ p_U_weight[MIG_DOWN] = 1.0 + exp(P_start[2] * nbi->U_pi);
170
+ p_V_weight[MIG_DOWN] = 1.0 + exp(P_start[3] * nbi->V_pi);
171
+ break;
172
+ case MIG_LEFT:
173
+ p_U_weight[MIG_LEFT] = 1.0 + exp(P_start[2] * nbi->U_pi);
174
+ p_V_weight[MIG_LEFT] = 1.0 + exp(P_start[3] * nbi->V_pi);
175
+ break;
176
+ default:
177
+ p_U_weight[MIG_RIGHT] = 1.0 + exp(P_start[2] * nbi->U_pi);
178
+ p_V_weight[MIG_RIGHT] = 1.0 + exp(P_start[3] * nbi->V_pi);
179
+ break;
180
+ }
181
+ p->sum_U_weight += p_U_weight[nb_loc];
182
+ p->sum_V_weight += p_V_weight[nb_loc];
183
+
184
+ double mu1_U_divide_sum = mu1_U / p->sum_U_weight;
185
+ double mu2_V_divide_sum = mu2_V / p->sum_V_weight;
186
+
187
+ for (size_t i = 0; i < 4; i++) {
188
+ p->mig_rates[i] = mu1_U_divide_sum * p_U_weight[i];
189
+ p->mig_rates[i + 4] = mu2_V_divide_sum * p_V_weight[i];
190
+ }
191
+
192
+ }
193
+
194
+
195
+
196
+ static inline void update_mig_all(patch_t* restrict p, const double* restrict P_start) {
197
+ // update migration rate for all directions
198
+ double mu1_U = P_start[0] * (double)p->U;
199
+ double mu2_V = P_start[1] * (double)p->V;
200
+
201
+ double* p_U_weight = p->U_weight;
202
+ double* p_V_weight = p->V_weight;
203
+
204
+ p->sum_U_weight = 0.0;
205
+ p->sum_V_weight = 0.0;
206
+
207
+ double w1 = P_start[2];
208
+ double w2 = P_start[3];
209
+
210
+ for (uint8_t i = 0; i < 4; i++) {
211
+ patch_t* nbi = p->nb[i];
212
+
213
+ if (nbi) {
214
+ // not NULL
215
+ p_U_weight[i] = 1.0 + exp(w1 * nbi->U_pi);
216
+ p_V_weight[i] = 1.0 + exp(w2 * nbi->V_pi);
217
+
218
+ p->sum_U_weight += p_U_weight[i];
219
+ p->sum_V_weight += p_V_weight[i];
220
+ }
221
+ }
222
+
223
+ double mu1_U_divide_sum = mu1_U / p->sum_U_weight;
224
+ double mu2_V_divide_sum = mu2_V / p->sum_V_weight;
225
+
226
+ for (uint8_t i = 0; i < 4; i++) {
227
+ p->mig_rates[i] = mu1_U_divide_sum * p_U_weight[i];
228
+ p->mig_rates[i + 4] = mu2_V_divide_sum * p_V_weight[i];
229
+ }
230
+
231
+ p->sum_mig_rates = mu1_U + mu2_V;
232
+ }
233
+
234
+
235
+
236
+ static inline size_t find_event(const patch_t* restrict p, double expected_sum) {
237
+ size_t event = 0;
238
+ double current_sum;
239
+
240
+ //if (expected_sum > (p->sum_pi_death_rates + p->sum_mig_rates)) {
241
+ // fprintf(stderr, "Bug: patch rate not enough in find_event.\n");
242
+ //}
243
+
244
+ if (expected_sum < p->sum_pi_death_rates) {
245
+ // First 4 events (payoff and death)
246
+ current_sum = 0.0;
247
+ while (current_sum < expected_sum) {
248
+ current_sum += p->pi_death_rates[event];
249
+ event++;
250
+ }
251
+ event--; // step back to correct event index
252
+ } else {
253
+ // Last 8 events (migration)2
254
+ current_sum = p->sum_pi_death_rates;
255
+ while (current_sum < expected_sum) {
256
+ current_sum += p->mig_rates[event];
257
+ event++;
258
+ }
259
+ event += 3; // -1 and then +4
260
+ }
261
+
262
+ return event;
263
+ }
264
+
265
+
266
+ static inline void change_popu(patch_t* restrict p, uint8_t s) {
267
+ switch (s) {
268
+ case 0:
269
+ // Migration IN for U
270
+ p->U += 1;
271
+ return;
272
+ case 1:
273
+ // Migration OUT / death due to carrying capacity for U
274
+ p->U -= (p->U > 0);
275
+ return;
276
+ case 2:
277
+ // Natural birth/death for U due to payoff
278
+ if (p->U_pi > 0.0) {
279
+ p->U += 1;
280
+ } else if (p->U > 0) {
281
+ p->U -= 1;
282
+ }
283
+ return;
284
+ case 3:
285
+ // Migration IN for V
286
+ p->V += 1;
287
+ return;
288
+ case 4:
289
+ // Migration OUT / death due to carrying capacity for V
290
+ p->V -= (p->V > 0);
291
+ return;
292
+ default:
293
+ // Natural birth/death for V due to payoff
294
+ if (p->V_pi > 0.0) {
295
+ p->V += 1;
296
+ } else if (p->V > 0) {
297
+ p->V -= 1;
298
+ }
299
+ return;
300
+ //default:
301
+ // fprintf(stderr, "Bug: invalid event number in change_popu: %hhu\n", s);
302
+ // return;
303
+ }
304
+ }
305
+
306
+
307
+ /**
308
+ * Main Simulation Functions
309
+ */
310
+
311
+ static inline void find_patch(patch_picked_t* restrict picked, double expected_sum, const double* restrict patch_rates, const double* restrict sum_rates_by_row, double sum_rates, size_t N, size_t M) {
312
+ double current_sum = 0;
313
+ size_t row = 0;
314
+ size_t col = 0;
315
+
316
+ // Find row
317
+ if (expected_sum < sum_rates * 0.5) {
318
+ current_sum = 0.0;
319
+ row = 0;
320
+ while (current_sum < expected_sum) {
321
+ current_sum += sum_rates_by_row[row];
322
+ row++;
323
+ }
324
+ row--;
325
+ current_sum -= sum_rates_by_row[row];
326
+ } else {
327
+ current_sum = sum_rates;
328
+ row = N - 1;
329
+ while (current_sum > expected_sum) {
330
+ current_sum -= sum_rates_by_row[row];
331
+ row--;
332
+ }
333
+ row++;
334
+ }
335
+
336
+ size_t row_M = row * M;
337
+
338
+ // Find col in that row
339
+ if ((expected_sum - current_sum) < sum_rates_by_row[row] * 0.5) {
340
+ col = 0;
341
+ while (current_sum < expected_sum) {
342
+ current_sum += patch_rates[row_M + col];
343
+ col++;
344
+ }
345
+ col--;
346
+ current_sum -= patch_rates[row_M + col];
347
+ } else {
348
+ current_sum += sum_rates_by_row[row];
349
+ col = M - 1;
350
+ while (current_sum > expected_sum) {
351
+ current_sum -= patch_rates[row_M + col];
352
+ col--;
353
+ }
354
+ col++;
355
+ }
356
+
357
+ picked->i = row;
358
+ picked->j = col;
359
+ picked->current_sum = current_sum;
360
+ }
361
+
362
+
363
+
364
+ static inline void make_signal_zero_flux(size_t i, size_t j, uint8_t e, signal_t* restrict signal) {
365
+ // this is always the case for the first one
366
+ signal->i1 = i;
367
+ signal->j1 = j;
368
+
369
+ switch (e) {
370
+ case 0:
371
+ signal->e1 = 2;
372
+ signal->only_first = true;
373
+ return;
374
+ case 1:
375
+ signal->e1 = 5;
376
+ signal->only_first = true;
377
+ return;
378
+ case 2:
379
+ signal->e1 = 1;
380
+ signal->only_first = true;
381
+ return;
382
+ case 3:
383
+ signal->e1 = 4;
384
+ signal->only_first = true;
385
+ return;
386
+ case 4:
387
+ signal->e1 = 1;
388
+ signal->i2 = i - 1;
389
+ signal->j2 = j;
390
+ signal->e2 = 0;
391
+ signal->only_first = false;
392
+ return;
393
+ case 5:
394
+ signal->e1 = 1;
395
+ signal->i2 = i + 1;
396
+ signal->j2 = j;
397
+ signal->e2 = 0;
398
+ signal->only_first = false;
399
+ return;
400
+ case 6:
401
+ signal->e1 = 1;
402
+ signal->i2 = i;
403
+ signal->j2 = j - 1;
404
+ signal->e2 = 0;
405
+ signal->only_first = false;
406
+ return;
407
+ case 7:
408
+ signal->e1 = 1;
409
+ signal->i2 = i;
410
+ signal->j2 = j + 1;
411
+ signal->e2 = 0;
412
+ signal->only_first = false;
413
+ return;
414
+ case 8:
415
+ signal->e1 = 4;
416
+ signal->i2 = i - 1;
417
+ signal->j2 = j;
418
+ signal->e2 = 3;
419
+ signal->only_first = false;
420
+ return;
421
+ case 9:
422
+ signal->e1 = 4;
423
+ signal->i2 = i + 1;
424
+ signal->j2 = j;
425
+ signal->e2 = 3;
426
+ signal->only_first = false;
427
+ return;
428
+ case 10:
429
+ signal->e1 = 4;
430
+ signal->i2 = i;
431
+ signal->j2 = j - 1;
432
+ signal->e2 = 3;
433
+ signal->only_first = false;
434
+ return;
435
+ default:
436
+ signal->e1 = 4;
437
+ signal->i2 = i;
438
+ signal->j2 = j + 1;
439
+ signal->e2 = 3;
440
+ signal->only_first = false;
441
+ return;
442
+ //default:
443
+ // fprintf(stderr, "Bug: invalid case in make_signal_zf, i, j, e: %zu, %zu, %hhu\n", i, j, e);
444
+ // return;
445
+ }
446
+ }
447
+
448
+
449
+
450
+ static inline void make_signal_periodical(size_t N, size_t M, size_t i, size_t j, uint8_t e, signal_t* restrict signal) {
451
+ // this is always the case for the first one
452
+ signal->i1 = i;
453
+ signal->j1 = j;
454
+
455
+ switch (e) {
456
+ case 0:
457
+ signal->e1 = 2;
458
+ signal->only_first = true;
459
+ return;
460
+ case 1:
461
+ signal->e1 = 5;
462
+ signal->only_first = true;
463
+ return;
464
+ case 2:
465
+ signal->e1 = 1;
466
+ signal->only_first = true;
467
+ return;
468
+ case 3:
469
+ signal->e1 = 4;
470
+ signal->only_first = true;
471
+ return;
472
+ case 4:
473
+ signal->e1 = 1;
474
+ signal->i2 = i != 0 ? i - 1 : N - 1;
475
+ signal->j2 = j;
476
+ signal->e2 = 0;
477
+ signal->only_first = false;
478
+ return;
479
+ case 5:
480
+ signal->e1 = 1;
481
+ signal->i2 = i != N - 1 ? i + 1 : 0;
482
+ signal->j2 = j;
483
+ signal->e2 = 0;
484
+ signal->only_first = false;
485
+ return;
486
+ case 6:
487
+ signal->e1 = 1;
488
+ signal->i2 = i;
489
+ signal->j2 = j != 0 ? j - 1 : M - 1;
490
+ signal->e2 = 0;
491
+ signal->only_first = false;
492
+ return;
493
+ case 7:
494
+ signal->e1 = 1;
495
+ signal->i2 = i;
496
+ signal->j2 = j != M - 1 ? j + 1 : 0;
497
+ signal->e2 = 0;
498
+ signal->only_first = false;
499
+ return;
500
+ case 8:
501
+ signal->e1 = 4;
502
+ signal->i2 = i != 0 ? i - 1 : N - 1;
503
+ signal->j2 = j;
504
+ signal->e2 = 3;
505
+ signal->only_first = false;
506
+ return;
507
+ case 9:
508
+ signal->e1 = 4;
509
+ signal->i2 = i != N - 1 ? i + 1 : 0;
510
+ signal->j2 = j;
511
+ signal->e2 = 3;
512
+ signal->only_first = false;
513
+ return;
514
+ case 10:
515
+ signal->e1 = 4;
516
+ signal->i2 = i;
517
+ signal->j2 = j != 0 ? j - 1 : M - 1;
518
+ signal->e2 = 3;
519
+ signal->only_first = false;
520
+ return;
521
+ default:
522
+ signal->e1 = 4;
523
+ signal->i2 = i;
524
+ signal->j2 = j != M - 1 ? j + 1 : 0;
525
+ signal->e2 = 3;
526
+ signal->only_first = false;
527
+ return;
528
+ //default:
529
+ // fprintf(stderr, "Bug: invalid case in make_signal_pr, i, j, e: %zu, %zu, %hhu\n", i, j, e);
530
+ // return;
531
+ }
532
+ }
533
+
534
+
535
+ static inline bool nb_need_change(size_t nb_idx, size_t sij1, size_t sij2) {
536
+ // a nb doesn't need change only if two patches are updated
537
+
538
+ // or, can try this 1-line version
539
+ // return (nb_idx != sij1) && (nb_idx != sij2);
540
+ if ((nb_idx == sij1) || (nb_idx == sij2)) {
541
+ return false;
542
+ }
543
+ return true; // need to change
544
+ }
545
+
546
+
547
+ #endif
piegy/__init__.py CHANGED
@@ -19,6 +19,7 @@ Last update: May 12, 2025
19
19
  '''
20
20
 
21
21
  from .__version__ import __version__
22
+ from .build_info import build_info
22
23
 
23
24
  from .simulation import model, run, demo_model, UV_expected_val, check_overflow_func
24
25
  from .videos import make_video, SUPPORTED_FIGURES
piegy/__version__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = '2.1.0'
1
+ __version__ = '2.1.9'
2
2
 
3
3
  '''
4
4
  version history:
@@ -28,4 +28,6 @@ version history:
28
28
  2.0.4: minor debuggings.
29
29
  2.0.5: fix error in random number generator.
30
30
  2.1.0: redo random number generator. Update package upload so that more compatible across platforms.
31
+ 2.1.1: fix import bug for the C core.
32
+ 2.1.2 ~ 2.1.9: updating & fixing wheel.
31
33
  '''
piegy/build_info.py ADDED
@@ -0,0 +1,12 @@
1
+ """
2
+ Contains build info, whether it's local built, or a pre-compiled wheel.
3
+ Auto-generated at compile time.
4
+ """
5
+
6
+ build_info = {
7
+ "version": "2.1.9",
8
+ "built from": "local machine",
9
+ "build date": "2025-06-28 09:00:03",
10
+ "python version": "3.8.10",
11
+ "platform": "win32"
12
+ }
piegy/find_C.py ADDED
@@ -0,0 +1,17 @@
1
+ '''
2
+ This module is used to find the C core
3
+ '''
4
+
5
+ import os
6
+
7
+
8
+ def find_C():
9
+ C_core_path = os.path.join(os.path.dirname(__file__), 'C_core')
10
+ C_list = os.listdir(C_core_path)
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
16
+
17
+ raise FileNotFoundError('C computation core not found. You can either compile manully or use the Python core instead. Please see docs.')
piegy/simulation.py CHANGED
@@ -12,6 +12,7 @@ Class & Functions:
12
12
  - check_overflow_func: check whether an overflow might happen in simulation. This is usually done automatically when init-ing a model.
13
13
  '''
14
14
 
15
+ from . import find_C
15
16
 
16
17
  import numpy as np
17
18
  import os
@@ -21,14 +22,15 @@ import numpy as np
21
22
  from numpy.ctypeslib import ndpointer
22
23
 
23
24
 
24
- # path to the C shared libary
25
- C_LIB_PATH = os.path.join(os.path.dirname(__file__), 'C_core', 'piegyc.so')
26
-
27
25
  # check whether overflow / too large values might be encountered
28
26
  # these values are considered as exponents in exp()
29
27
  EXP_OVERFLOW_BOUND = 709 # where exp(x) reaches overflow bound
30
28
  EXP_TOO_LARGE_BOUND = 88 # where exp(x) reaches 1e20
31
29
 
30
+ # read the C core into LIB
31
+ # initialized upon first run
32
+ LIB = None
33
+
32
34
 
33
35
  '''
34
36
  The C core
@@ -69,23 +71,28 @@ class model_c(ctypes.Structure):
69
71
  ptr = getattr(self, name)
70
72
  return np.ctypeslib.as_array(ptr, shape=(self.arr_size,))
71
73
 
72
- lib = ctypes.CDLL(C_LIB_PATH, winmode = 0)
73
- lib.mod_init.argtypes = [
74
- ctypes.POINTER(model_c), c_size_t, c_size_t,
75
- c_double, c_double, c_size_t, c_bool,
76
- ndpointer(dtype=np.uint32, flags="C_CONTIGUOUS"),
77
- ndpointer(dtype=np.float64, flags="C_CONTIGUOUS"),
78
- ndpointer(dtype=np.float64, flags="C_CONTIGUOUS"),
79
- c_int32, c_int32
80
- ]
81
- lib.mod_init.restype = c_bool
82
74
 
83
- lib.mod_free_py.argtypes = [ctypes.POINTER(model_c)]
84
- lib.mod_free_py.restype = None
75
+ def read_lib():
76
+ global LIB
77
+ if LIB != None:
78
+ return
79
+
80
+ LIB = ctypes.CDLL(find_C.find_C(), winmode = 0)
81
+ LIB.mod_init.argtypes = [
82
+ ctypes.POINTER(model_c), c_size_t, c_size_t,
83
+ c_double, c_double, c_size_t, c_bool,
84
+ ndpointer(dtype=np.uint32, flags="C_CONTIGUOUS"),
85
+ ndpointer(dtype=np.float64, flags="C_CONTIGUOUS"),
86
+ ndpointer(dtype=np.float64, flags="C_CONTIGUOUS"),
87
+ c_int32, c_int32
88
+ ]
89
+ LIB.mod_init.restype = c_bool
85
90
 
86
- lib.run.argtypes = [ctypes.POINTER(model_c), ctypes.POINTER(c_char), c_size_t]
87
- lib.run.restype = None
91
+ LIB.mod_free_py.argtypes = [ctypes.POINTER(model_c)]
92
+ LIB.mod_free_py.restype = None
88
93
 
94
+ LIB.run.argtypes = [ctypes.POINTER(model_c), ctypes.POINTER(c_char), c_size_t]
95
+ LIB.run.restype = None
89
96
 
90
97
 
91
98
 
@@ -396,6 +403,8 @@ def run(mod, message = ""):
396
403
  C-cored simulation
397
404
  '''
398
405
 
406
+ read_lib()
407
+
399
408
  if not mod.data_empty:
400
409
  raise ValueError('mod has non-empty data.')
401
410
 
@@ -408,20 +417,20 @@ def run(mod, message = ""):
408
417
  P = np.ascontiguousarray(mod.P.flatten(), dtype = np.float64)
409
418
 
410
419
  mod_c = model_c()
411
- success = lib.mod_init(ctypes.byref(mod_c),
420
+ success = LIB.mod_init(ctypes.byref(mod_c),
412
421
  mod.N, mod.M, mod.maxtime, mod.record_itv, mod.sim_time, mod.boundary,
413
422
  I, X, P, mod.print_pct, mod.seed)
414
423
  if not success:
415
424
  raise RuntimeError('mod_init failed')
416
425
 
417
- lib.run(ctypes.byref(mod_c), msg_buffer, msg_len)
426
+ LIB.run(ctypes.byref(mod_c), msg_buffer, msg_len)
418
427
 
419
428
  mod.set_data(False, mod.max_record, 1, mod_c.get_array('U1d').reshape(mod.N, mod.M, mod.max_record),
420
429
  mod_c.get_array('V1d').reshape(mod.N, mod.M, mod.max_record),
421
430
  mod_c.get_array('Upi_1d').reshape(mod.N, mod.M, mod.max_record),
422
431
  mod_c.get_array('Vpi_1d').reshape(mod.N, mod.M, mod.max_record))
423
432
 
424
- lib.mod_free_py(ctypes.byref(mod_c))
433
+ LIB.mod_free_py(ctypes.byref(mod_c))
425
434
  del mod_c
426
435
 
427
436
 
piegy/simulation_py.py CHANGED
@@ -5,8 +5,7 @@ But you can still run them by calling:
5
5
  >>> run_py(mod)
6
6
  '''
7
7
 
8
- from . import simulation
9
- model = simulation.model
8
+ from .simulation import model
10
9
 
11
10
  import math
12
11
  import numpy as np