Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_fluids.c
Go to the documentation of this file.
1
8#include <math.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <stdint.h>
12#include <stdbool.h>
13#include <strings.h>
14#include "nilorea/n_fluids.h"
15#include "nilorea/n_common.h"
17
19#define N_FLUID_U_FIELD 0
21#define N_FLUID_V_FIELD 1
23#define N_FLUID_S_FIELD 2
24
32void n_memset(void* dst, void* val, size_t size, size_t count) {
33 void* ptr = dst;
34 while (count-- > 0) {
35 memcpy(ptr, val, size);
36 ptr += size;
37 }
38}
39
46 __n_assert((*fluid), return FALSE);
47
48 FreeNoLog((*fluid)->u);
49 FreeNoLog((*fluid)->newU);
50 FreeNoLog((*fluid)->v);
51 FreeNoLog((*fluid)->newV);
52 FreeNoLog((*fluid)->p);
53 FreeNoLog((*fluid)->s);
54 FreeNoLog((*fluid)->m);
55 FreeNoLog((*fluid)->newM);
56 FreeNoLog((*fluid));
57
58 return TRUE;
59}
60
72N_FLUID* new_n_fluid(double density, double gravity, size_t numIters, double dt, double overRelaxation, size_t sx, size_t sy) {
73 N_FLUID* fluid = NULL;
74
75 Malloc(fluid, N_FLUID, 1);
76 __n_assert(fluid, return NULL);
77
78 fluid->density = density;
79 fluid->gravity = gravity;
80 fluid->numIters = numIters;
81 fluid->dt = dt;
82 fluid->h = 1.0 / 100.0;
83 fluid->overRelaxation = overRelaxation;
84 fluid->numX = sx + 2;
85 fluid->numY = sy + 2;
86 fluid->numZ = 1; // TODO: expand Z
87 fluid->numCells = fluid->numX * fluid->numY * fluid->numZ;
88
89 Malloc(fluid->u, double, fluid->numCells);
90 Malloc(fluid->newU, double, fluid->numCells);
91 Malloc(fluid->v, double, fluid->numCells);
92 Malloc(fluid->newV, double, fluid->numCells);
93 Malloc(fluid->p, double, fluid->numCells);
94 Malloc(fluid->s, double, fluid->numCells);
95 Malloc(fluid->m, double, fluid->numCells);
96 Malloc(fluid->newM, double, fluid->numCells);
97
98 fluid->showSmoke = 1;
99 fluid->showPressure = 0;
100 fluid->showPaint = 0;
101 fluid->fluid_production_percentage = 0.1;
102 fluid->cScale = 16.0;
103 // double precision. Taking 'value', if( fabs( value ) < float_tolerance ) value is considered as zero
104 fluid->negative_float_tolerance = -0.00001;
105 fluid->positive_float_tolerance = 0.00001;
106
107 double d_val = 1.0;
108 n_memset(fluid->m, &d_val, sizeof(d_val), fluid->numCells);
109
110 // precalculate and allocated N_PROC_PARAMS lists for threaded computing
115
116 int nb_cores = get_nb_cpu_cores();
117 if (nb_cores == -1) {
118 nb_cores = 1;
119 }
120 size_t steps = fluid->numX / nb_cores;
121
122 N_FLUID_THREAD_PARAMS* params = NULL;
123 // integrate
124 for (size_t i = 1; i < fluid->numX; i += steps) {
125 Malloc(params, N_FLUID_THREAD_PARAMS, 1);
126 params->ptr = fluid;
127 params->x_start = i;
128 params->x_end = i + steps;
129 params->y_start = 1;
130 params->y_end = fluid->numY - 1;
131 list_push(fluid->integrate_chunk_list, params, &free);
132 }
133 // set the last batch at the end of the range
135 params->x_end = fluid->numX;
136
137 // solveIncompressibility
138 for (size_t i = 1; i < fluid->numX - 1; i += steps) {
139 Malloc(params, N_FLUID_THREAD_PARAMS, 1);
140 params->ptr = fluid;
141 params->x_start = i;
142 params->x_end = i + steps;
143 params->y_start = 1;
144 params->y_end = fluid->numY - 1;
145 list_push(fluid->solveIncompressibility_chunk_list, params, &free);
146 }
147 // set the last batch at the end of the range
149 params->x_end = fluid->numX - 1;
150
151 // advectVel
152 for (size_t i = 1; i < fluid->numX; i += steps) {
153 Malloc(params, N_FLUID_THREAD_PARAMS, 1);
154 params->ptr = fluid;
155 params->x_start = i;
156 params->x_end = i + steps;
157 params->y_start = 1;
158 params->y_end = fluid->numY;
159 list_push(fluid->advectVel_chunk_list, params, &free);
160 }
161 // set the last batch at the end of the range
163 params->x_end = fluid->numX;
164
165 // adVectSmoke
166 for (size_t i = 1; i < fluid->numX - 1; i += steps) {
167 Malloc(params, N_FLUID_THREAD_PARAMS, 1);
168 params->ptr = fluid;
169 params->x_start = i;
170 params->x_end = i + steps;
171 params->y_start = 1;
172 params->y_end = fluid->numY - 1;
173 list_push(fluid->advectSmoke_chunk_list, params, &free);
174 }
175 // set the last batch at the end of the range
177 params->x_end = fluid->numX - 1;
178
179 return fluid;
180} /* new_n_fluid */
181
187void* n_fluid_integrate_proc(void* ptr) {
189 N_FLUID* fluid = (N_FLUID*)params->ptr;
190
191 size_t n = fluid->numY;
192 for (size_t i = params->x_start; i < params->x_end; i++) {
193 for (size_t j = params->y_start; j < params->y_end; j++) {
194 if (!_z(fluid, s[i * n + j]) && !_z(fluid, s[i * n + j - 1]))
195 fluid->v[i * n + j] += fluid->gravity * fluid->dt;
196 }
197 }
198 return NULL;
199}
200
207 __n_assert(fluid, return FALSE);
208
209 size_t n = fluid->numY;
210 for (size_t i = 1; i < fluid->numX; i++) {
211 for (size_t j = 1; j < fluid->numY - 1; j++) {
212 if (!_z(fluid, s[i * n + j]) && !_z(fluid, s[i * n + j - 1]))
213 fluid->v[i * n + j] += fluid->gravity * fluid->dt;
214 }
215 }
216 return TRUE;
217}
218
226 N_FLUID* fluid = (N_FLUID*)params->ptr;
227
228 double cp = (fluid->density * fluid->h) / fluid->dt;
229
230 size_t n = fluid->numY;
231 for (size_t i = params->x_start; i < params->x_end; i++) {
232 for (size_t j = params->y_start; j < params->y_end; j++) {
233 if (_z(fluid, s[i * n + j]))
234 continue;
235
236 double sx0 = fluid->s[(i - 1) * n + j];
237 double sx1 = fluid->s[(i + 1) * n + j];
238 double sy0 = fluid->s[i * n + j - 1];
239 double sy1 = fluid->s[i * n + j + 1];
240 double s = sx0 + sx1 + sy0 + sy1;
241 if (_zd(fluid, s))
242 continue;
243
244 double div = fluid->u[(i + 1) * n + j] - fluid->u[i * n + j] + fluid->v[i * n + j + 1] - fluid->v[i * n + j];
245 double p = (-div * fluid->overRelaxation) / s;
246 fluid->p[i * n + j] += cp * p;
247 fluid->u[i * n + j] -= sx0 * p;
248 fluid->u[(i + 1) * n + j] += sx1 * p;
249 fluid->v[i * n + j] -= sy0 * p;
250 fluid->v[i * n + j + 1] += sy1 * p;
251 }
252 }
253 return NULL;
254}
255
262 __n_assert(fluid, return FALSE);
263 size_t n = fluid->numY;
264
265 double cp = (fluid->density * fluid->h) / fluid->dt;
266
267 for (size_t iter = 0; iter < fluid->numIters; iter++) {
268 for (size_t i = 1; i < fluid->numX - 1; i++) {
269 for (size_t j = 1; j < fluid->numY - 1; j++) {
270 if (_z(fluid, s[i * n + j]))
271 continue;
272
273 double sx0 = fluid->s[(i - 1) * n + j];
274 double sx1 = fluid->s[(i + 1) * n + j];
275 double sy0 = fluid->s[i * n + j - 1];
276 double sy1 = fluid->s[i * n + j + 1];
277 double s = sx0 + sx1 + sy0 + sy1;
278 if (_zd(fluid, s))
279 continue;
280
281 double div = fluid->u[(i + 1) * n + j] - fluid->u[i * n + j] + fluid->v[i * n + j + 1] - fluid->v[i * n + j];
282 double p = (-div * fluid->overRelaxation) / s;
283 fluid->p[i * n + j] += cp * p;
284 fluid->u[i * n + j] -= sx0 * p;
285 fluid->u[(i + 1) * n + j] += sx1 * p;
286 fluid->v[i * n + j] -= sy0 * p;
287 fluid->v[i * n + j + 1] += sy1 * p;
288 }
289 }
290 }
291 return TRUE;
292}
293
300 __n_assert(fluid, return FALSE);
301 size_t n = fluid->numY;
302 for (size_t i = 0; i < fluid->numX; i++) {
303 fluid->u[i * n + 0] = fluid->u[i * n + 1];
304 fluid->u[i * n + fluid->numY - 1] = fluid->u[i * n + fluid->numY - 2];
305 }
306 for (size_t j = 0; j < fluid->numY; j++) {
307 fluid->v[0 * n + j] = fluid->v[1 * n + j];
308 fluid->v[(fluid->numX - 1) * n + j] = fluid->v[(fluid->numX - 2) * n + j];
309 }
310 return TRUE;
311}
312
321double n_fluid_sampleField(N_FLUID* fluid, double x, double y, uint32_t field) {
322 __n_assert(fluid, return FALSE);
323 size_t n = fluid->numY;
324 double h1 = 1.0 / fluid->h;
325 double h2 = 0.5 * fluid->h;
326
327 x = MAX(MIN(x, fluid->numX * fluid->h), fluid->h);
328 y = MAX(MIN(y, fluid->numY * fluid->h), fluid->h);
329
330 double dx = 0.0;
331 double dy = 0.0;
332
333 double* f = NULL;
334 switch (field) {
335 case N_FLUID_U_FIELD:
336 f = fluid->u;
337 dy = h2;
338 break;
339 case N_FLUID_V_FIELD:
340 f = fluid->v;
341 dx = h2;
342 break;
343 case N_FLUID_S_FIELD:
344 f = fluid->m;
345 dx = h2;
346 dy = h2;
347 break;
348 }
349
350 double x0 = MIN(floor((x - dx) * h1), fluid->numX - 1);
351 double tx = ((x - dx) - x0 * fluid->h) * h1;
352 double x1 = MIN(x0 + 1, fluid->numX - 1);
353
354 double y0 = MIN(floor((y - dy) * h1), fluid->numY - 1);
355 double ty = ((y - dy) - y0 * fluid->h) * h1;
356 double y1 = MIN(y0 + 1, fluid->numY - 1);
357
358 double sx = 1.0 - tx;
359 double sy = 1.0 - ty;
360
361 double val = sx * sy * f[(size_t)(x0 * n + y0)] +
362 tx * sy * f[(size_t)(x1 * n + y0)] +
363 tx * ty * f[(size_t)(x1 * n + y1)] +
364 sx * ty * f[(size_t)(x0 * n + y1)];
365
366 return val;
367}
368
376double n_fluid_avgU(N_FLUID* fluid, size_t i, size_t j) {
377 __n_assert(fluid, return FALSE);
378 size_t n = fluid->numY;
379 double u = (fluid->u[i * n + j - 1] + fluid->u[i * n + j] +
380 fluid->u[(i + 1) * n + j - 1] + fluid->u[(i + 1) * n + j]) *
381 0.25;
382
383 return u;
384}
385
393double n_fluid_avgV(N_FLUID* fluid, size_t i, size_t j) {
394 __n_assert(fluid, return FALSE);
395 size_t n = fluid->numY;
396 double v = (fluid->v[(i - 1) * n + j] + fluid->v[i * n + j] +
397 fluid->v[(i - 1) * n + j + 1] + fluid->v[i * n + j + 1]) *
398 0.25;
399 return v;
400}
401
407void* n_fluid_advectVel_proc(void* ptr) {
409 N_FLUID* fluid = (N_FLUID*)params->ptr;
410
411 size_t n = fluid->numY;
412 double h2 = 0.5 * fluid->h;
413 for (size_t i = params->x_start; i < params->x_end; i++) {
414 for (size_t j = params->y_start; j < params->y_end; j++) {
415 size_t index = i * n + j;
416 // u component
417 if (!_z(fluid, s[index]) && !_z(fluid, s[(i - 1) * n + j]) && j < fluid->numY - 1) {
418 double x = i * fluid->h;
419 double y = j * fluid->h + h2;
420 double u = fluid->u[index];
421 double v = n_fluid_avgV(fluid, i, j);
422 // double v = n_fluid_sampleField( fluid , x , y , N_FLUID_V_FIELD );
423 x = x - fluid->dt * u;
424 y = y - fluid->dt * v;
425 u = n_fluid_sampleField(fluid, x, y, N_FLUID_U_FIELD);
426 fluid->newU[index] = u;
427 }
428 // v component
429 if (!_z(fluid, s[index]) && !_z(fluid, s[index - 1]) && i < fluid->numX - 1) {
430 double x = i * fluid->h + h2;
431 double y = j * fluid->h;
432 double u = n_fluid_avgU(fluid, i, j);
433 // double u = n_fluid_sampleField( fluid , x , y , N_FLUID_U_FIELD );
434 double v = fluid->v[index];
435 x = x - fluid->dt * u;
436 y = y - fluid->dt * v;
437 v = n_fluid_sampleField(fluid, x, y, N_FLUID_V_FIELD);
438 fluid->newV[index] = v;
439 }
440 }
441 }
442 return NULL;
443}
444
451 __n_assert(fluid, return FALSE);
452
453 memcpy(fluid->newU, fluid->u, fluid->numCells * sizeof(double));
454 memcpy(fluid->newV, fluid->v, fluid->numCells * sizeof(double));
455
456 size_t n = fluid->numY;
457 double h2 = 0.5 * fluid->h;
458 for (size_t i = 1; i < fluid->numX; i++) {
459 for (size_t j = 1; j < fluid->numY; j++) {
460 size_t index = i * n + j;
461 // u component
462 if (!_z(fluid, s[index]) && !_z(fluid, s[(i - 1) * n + j]) && j < fluid->numY - 1) {
463 double x = i * fluid->h;
464 double y = j * fluid->h + h2;
465 double u = fluid->u[index];
466 double v = n_fluid_avgV(fluid, i, j);
467 // double v = n_fluid_sampleField( fluid , x , y , N_FLUID_V_FIELD );
468 x = x - fluid->dt * u;
469 y = y - fluid->dt * v;
470 u = n_fluid_sampleField(fluid, x, y, N_FLUID_U_FIELD);
471 fluid->newU[index] = u;
472 }
473 // v component
474 if (!_z(fluid, s[index]) && !_z(fluid, s[index - 1]) && i < fluid->numX - 1) {
475 double x = i * fluid->h + h2;
476 double y = j * fluid->h;
477 double u = n_fluid_avgU(fluid, i, j);
478 // double u = n_fluid_sampleField( fluid , x , y , N_FLUID_U_FIELD );
479 double v = fluid->v[index];
480 x = x - fluid->dt * u;
481 y = y - fluid->dt * v;
482 v = n_fluid_sampleField(fluid, x, y, N_FLUID_V_FIELD);
483 fluid->newV[index] = v;
484 }
485 }
486 }
487 double* ptr = fluid->u;
488 fluid->u = fluid->newU;
489 fluid->newU = ptr;
490
491 ptr = fluid->v;
492 fluid->v = fluid->newV;
493 fluid->newV = ptr;
494
495 return TRUE;
496}
497
503void* n_fluid_advectSmoke_proc(void* ptr) {
505 N_FLUID* fluid = (N_FLUID*)params->ptr;
506
507 size_t n = fluid->numY;
508 double h2 = 0.5 * fluid->h;
509 for (size_t i = params->x_start; i < params->x_end; i++) {
510 for (size_t j = params->y_start; j < params->y_end; j++) {
511 size_t index = i * n + j;
512 if (!_z(fluid, s[index])) {
513 double u = (fluid->u[index] + fluid->u[(i + 1) * n + j]) * 0.5;
514 double v = (fluid->v[index] + fluid->v[index + 1]) * 0.5;
515 double x = i * fluid->h + h2 - fluid->dt * u;
516 double y = j * fluid->h + h2 - fluid->dt * v;
517
518 fluid->newM[index] = n_fluid_sampleField(fluid, x, y, N_FLUID_S_FIELD);
519 }
520 }
521 }
522 return NULL;
523}
524
531 __n_assert(fluid, return FALSE);
532
533 size_t n = fluid->numY;
534 double h2 = 0.5 * fluid->h;
535
536 memcpy(fluid->newM, fluid->m, fluid->numCells * sizeof(double));
537
538 for (size_t i = 1; i < fluid->numX - 1; i++) {
539 for (size_t j = 1; j < fluid->numY - 1; j++) {
540 size_t index = i * n + j;
541 if (!_z(fluid, s[index])) {
542 double u = (fluid->u[index] + fluid->u[(i + 1) * n + j]) * 0.5;
543 double v = (fluid->v[index] + fluid->v[index + 1]) * 0.5;
544 double x = i * fluid->h + h2 - fluid->dt * u;
545 double y = j * fluid->h + h2 - fluid->dt * v;
546
547 fluid->newM[index] = n_fluid_sampleField(fluid, x, y, N_FLUID_S_FIELD);
548 }
549 }
550 }
551 double* ptr = fluid->m;
552 fluid->m = fluid->newM;
553 fluid->newM = ptr;
554
555 return TRUE;
556}
557
564 __n_assert(fluid, return FALSE);
565 n_fluid_integrate(fluid);
566 memset(fluid->p, 0, fluid->numCells * sizeof(double));
568 n_fluid_extrapolate(fluid);
569 n_fluid_advectVel(fluid);
570 n_fluid_advectSmoke(fluid);
571 return TRUE;
572}
573
581 __n_assert(fluid, return FALSE);
582
583 // n_fluid_integrate( fluid );
584 list_foreach(node, fluid->integrate_chunk_list) {
586 }
590
591 // set pressure to 0
592 memset(fluid->p, 0, fluid->numCells * sizeof(double));
593
594 // n_fluid_solveIncompressibility( fluid );
595 for (size_t iter = 0; iter < fluid->numIters; iter++) {
598 }
602 }
603
604 // extrapolate
605 n_fluid_extrapolate(fluid);
606
607 // n_fluid_advectVel( fluid );
608 memcpy(fluid->newU, fluid->u, fluid->numCells * sizeof(double));
609 memcpy(fluid->newV, fluid->v, fluid->numCells * sizeof(double));
610
611 list_foreach(node, fluid->advectVel_chunk_list) {
613 }
617
618 double* ptr = fluid->u;
619 fluid->u = fluid->newU;
620 fluid->newU = ptr;
621
622 ptr = fluid->v;
623 fluid->v = fluid->newV;
624 fluid->newV = ptr;
625
626 // n_fluid_advectSmoke( fluid );
627 memcpy(fluid->newM, fluid->m, fluid->numCells * sizeof(double));
630 }
634
635 ptr = fluid->m;
636 fluid->m = fluid->newM;
637 fluid->newM = ptr;
638
639 return TRUE;
640}
641
652int n_fluid_setObstacle(N_FLUID* fluid, double x, double y, double vx, double vy, double r) {
653 __n_assert(fluid, return FALSE);
654
655 size_t n = fluid->numY;
656 for (size_t i = 1; i < fluid->numX - 2; i++) {
657 for (size_t j = 1; j < fluid->numY - 2; j++) {
658 double dx = (i + 0.5) - x;
659 double dy = (j + 0.5) - y;
660
661 if (i > 7 && (dx * dx + dy * dy < r * r)) {
662 fluid->s[i * n + j] = 0.0;
663 fluid->m[i * n + j] = 1.0;
664 fluid->u[i * n + j] = vx;
665 fluid->u[(i + 1) * n + j] = vx;
666 fluid->v[i * n + j] = vy;
667 fluid->v[i * n + j + 1] = vy;
668 }
669 }
670 }
671 return TRUE;
672}
673
680 __n_assert(fluid, return FALSE);
681
682 size_t n = fluid->numY;
683 for (size_t i = 1; i < fluid->numX - 2; i++) {
684 for (size_t j = 1; j < fluid->numY - 2; j++) {
685 fluid->s[i * n + j] = 1.0;
686 }
687 }
688
689 return TRUE;
690}
691
703int n_fluid_setObstacleFromBitmap(N_FLUID* fluid, ALLEGRO_BITMAP* bitmap, double x, double y, double vx, double vy, double r) {
704 __n_assert(fluid, return FALSE);
705
706 al_lock_bitmap(bitmap, al_get_bitmap_format(bitmap), ALLEGRO_LOCK_READONLY);
707
708 size_t n = fluid->numY;
709 for (size_t i = 1; i < fluid->numX - 2; i++) {
710 for (size_t j = 1; j < fluid->numY - 2; j++) {
711 double dx = (i + 0.5) - x;
712 double dy = (j + 0.5) - y;
713
714 if (i > 7 && (dx * dx + dy * dy < r * r)) {
715 fluid->s[i * n + j] = 0.0;
716 fluid->m[i * n + j] = 1.0;
717 fluid->u[i * n + j] = vx;
718 fluid->v[i * n + j] = vy;
719
720 fluid->u[(i + 1) * n + j] = vx;
721 fluid->v[i * n + j + 1] = vy;
722 }
723 }
724 }
725
726 al_unlock_bitmap(bitmap);
727
728 return TRUE;
729}
730
739ALLEGRO_COLOR n_fluid_getSciColor(N_FLUID* fluid, double val, double minVal, double maxVal) {
740 val = MIN(MAX(val, minVal), maxVal - 0.0001);
741 double d = maxVal - minVal;
742 if (_zd(fluid, d)) {
743 val = 0.5;
744 } else {
745 val = (val - minVal) / d;
746 }
747 double m = 0.25;
748 size_t num = floor(val / m);
749 double s = (val - num * m) / m;
750 double r = 0.0, g = 0.0, b = 0.0;
751 switch (num) {
752 case 0:
753 r = 0.0;
754 g = s;
755 b = 1.0;
756 break;
757 case 1:
758 r = 0.0;
759 g = 1.0;
760 b = 1.0 - s;
761 break;
762 case 2:
763 r = s;
764 g = 1.0;
765 b = 0.0;
766 break;
767 case 3:
768 r = 1.0;
769 g = 1.0 - s;
770 b = 0.0;
771 break;
772 }
773 // return[255*r,255*g,255*b, 255]
774 return al_map_rgb_f(r, g, b);
775}
776
783 __n_assert(fluid, return FALSE);
784
785 size_t n = fluid->numY;
786
787 double minP = fluid->p[0];
788 double maxP = fluid->p[0];
789
790 if (fluid->showPressure) {
791 for (size_t i = 0; i < fluid->numCells; i++) {
792 minP = MIN(minP, fluid->p[i]);
793 maxP = MAX(maxP, fluid->p[i]);
794 }
795 }
796
797 ALLEGRO_COLOR color;
798 double cScale = fluid->cScale;
799
800 for (size_t i = 0; i < fluid->numX; i++) {
801 for (size_t j = 0; j < fluid->numY; j++) {
802 int64_t x = i * cScale;
803 int64_t y = j * cScale;
804 int64_t cx = x + cScale;
805 int64_t cy = y + cScale;
806
807 double s = fluid->m[i * n + j];
808
809 if (fluid->showPaint) {
810 color = n_fluid_getSciColor(fluid, s, 0.0, 1.0);
811 } else if (fluid->showPressure) {
812 float color_vec_f[3] = {0.0, 0.0, 0.0};
813 double p = fluid->p[i * n + j];
814 color = n_fluid_getSciColor(fluid, p, minP, maxP);
815 if (fluid->showSmoke) {
816 al_unmap_rgb_f(color, color_vec_f, color_vec_f + 1, color_vec_f + 2);
817 color = al_map_rgb_f(MAX(0.0, color_vec_f[0] - s), MAX(0.0, color_vec_f[1] - s), MAX(0.0, color_vec_f[2] - s));
818 }
819 } else if (fluid->showSmoke) {
820 color = al_map_rgb_f(1.0 - s, 0.0, 0.0);
821 } else {
822 color = al_map_rgb_f(s, s, s);
823 }
824 al_draw_filled_rectangle(x, y, cx, cy, color);
825 }
826 }
827 return TRUE;
828}
THREAD_POOL * thread_pool
Definition ex_fluid.c:59
#define FreeNoLog(__ptr)
Free Handler without log.
Definition n_common.h:249
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:185
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:256
LIST_NODE * end
pointer to the end of the list
Definition n_list.h:49
void * ptr
void pointer to store
Definition n_list.h:27
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
Definition n_list.c:200
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper.
Definition n_list.h:66
LIST * new_generic_list(size_t max_items)
Initialiaze a generic list container to max_items pointers.
Definition n_list.c:19
#define MAX_LIST_ITEMS
flag to pass to new_generic_list for the maximum possible number of item in a list
Definition n_list.h:56
double h
Definition n_fluids.h:67
double * newU
holder for newU arrays
Definition n_fluids.h:92
size_t numY
number of cells in Y
Definition n_fluids.h:55
size_t y_start
y start point
Definition n_fluids.h:45
double fluid_production_percentage
size of the produced fluid
Definition n_fluids.h:85
bool showSmoke
display fluid as a colored cloud instead of black and white, can be combined with showPressure
Definition n_fluids.h:73
size_t numX
number of cells in X
Definition n_fluids.h:53
LIST * advectSmoke_chunk_list
preprocessed list of threaded procs parameters, for n_fluid_advectSmoke
Definition n_fluids.h:116
double overRelaxation
over relaxation
Definition n_fluids.h:71
bool showPressure
display fluids pressures as color variations, can be combined with showSmoke
Definition n_fluids.h:77
void * ptr
pointer to data which will be used in the proc
Definition n_fluids.h:39
double positive_float_tolerance
fluid double positive precision setting
Definition n_fluids.h:82
LIST * solveIncompressibility_chunk_list
preprocessed list of threaded procs parameters, for n_fluid_solveIncompressibility
Definition n_fluids.h:112
size_t x_end
x end point
Definition n_fluids.h:43
bool showPaint
activate a fonky palette, override smoke and pressure display
Definition n_fluids.h:75
double * u
holder for u arrays
Definition n_fluids.h:90
LIST * integrate_chunk_list
preprocessed list of threaded procs parameters, for n_fluid_integrate
Definition n_fluids.h:110
double * newV
holder for newV arrays
Definition n_fluids.h:97
double dt
time between frames
Definition n_fluids.h:65
double * s
holder for s arrays
Definition n_fluids.h:102
double * v
holder for v arrays
Definition n_fluids.h:95
size_t numCells
total number of cells
Definition n_fluids.h:59
size_t numIters
number of fluid processing iterations for each frame
Definition n_fluids.h:61
double density
density of the fluid (not working ?)
Definition n_fluids.h:63
LIST * advectVel_chunk_list
preprocessed list of threaded procs parameters, for n_fluid_advectVel
Definition n_fluids.h:114
double * m
holder for m arrays
Definition n_fluids.h:105
double cScale
scale used to deduce cellX and cellY from screen/window width and height
Definition n_fluids.h:87
double * newM
holder for newM arrays
Definition n_fluids.h:107
size_t numZ
number of cells in Z
Definition n_fluids.h:57
double * p
holder for p arrays
Definition n_fluids.h:100
size_t x_start
x start point
Definition n_fluids.h:41
double gravity
gravity on Y
Definition n_fluids.h:69
size_t y_end
y end point
Definition n_fluids.h:47
double negative_float_tolerance
fluid double negative precision setting
Definition n_fluids.h:80
double n_fluid_avgV(N_FLUID *fluid, size_t i, size_t j)
compute the average V value at a fluid position using it's surrounding
Definition n_fluids.c:393
int n_fluid_draw(N_FLUID *fluid)
draw a N_FLUID on screen / targert bitmap
Definition n_fluids.c:782
#define _z(__fluid, __component)
test if component is near zero, according to fluid's precision
Definition n_fluids.h:28
int n_fluid_simulate_threaded(N_FLUID *fluid, THREAD_POOL *thread_pool)
a threaded version of N_FLUID global processing function
Definition n_fluids.c:580
int n_fluid_simulate(N_FLUID *fluid)
non threaded version of N_FLUID global processing function
Definition n_fluids.c:563
double n_fluid_avgU(N_FLUID *fluid, size_t i, size_t j)
compute the average U value at a fluid position using it's surrounding
Definition n_fluids.c:376
double n_fluid_sampleField(N_FLUID *fluid, double x, double y, uint32_t field)
compute a sample value at a field position
Definition n_fluids.c:321
ALLEGRO_COLOR n_fluid_getSciColor(N_FLUID *fluid, double val, double minVal, double maxVal)
get fonky colors for the fluid
Definition n_fluids.c:739
int n_fluid_extrapolate(N_FLUID *fluid)
non threaded extrapolation function
Definition n_fluids.c:299
int n_fluid_advectSmoke(N_FLUID *fluid)
non threaded version of add smoke function
Definition n_fluids.c:530
int n_fluid_solveIncompressibility(N_FLUID *fluid)
non threaded version of incompressibility solving function
Definition n_fluids.c:261
int n_fluid_resetObstacles(N_FLUID *fluid)
reset the obstacles set in a N_FLUID
Definition n_fluids.c:679
#define _zd(__fluid, __value)
test if value is near zero, according to fluid's precision
Definition n_fluids.h:33
int n_fluid_integrate(N_FLUID *fluid)
non threaded version of integration function
Definition n_fluids.c:206
int n_fluid_setObstacle(N_FLUID *fluid, double x, double y, double vx, double vy, double r)
set an obstacle in the fluid grid
Definition n_fluids.c:652
int destroy_n_fluid(N_FLUID **fluid)
ddestroy a fluid structure
Definition n_fluids.c:45
int n_fluid_advectVel(N_FLUID *fluid)
non threaded version of add velocities function
Definition n_fluids.c:450
N_FLUID * new_n_fluid(double density, double gravity, size_t numIters, double dt, double overRelaxation, size_t sx, size_t sy)
return a newly allocated fluid
Definition n_fluids.c:72
structure of a fluid
Definition n_fluids.h:51
structure passed to a threaded fluid process
Definition n_fluids.h:37
int start_threaded_pool(THREAD_POOL *thread_pool)
Launch the process waiting for execution in the thread pool.
#define SYNCED_PROC
processing mode for added func, synced start, not queued
int add_threaded_process(THREAD_POOL *thread_pool, void *(*func_ptr)(void *param), void *param, int mode)
add a function and params to a thread pool
int refresh_thread_pool(THREAD_POOL *thread_pool)
try to add some waiting DIRECT_PROCs on some free thread slots, else do nothing
int wait_for_synced_threaded_pool(THREAD_POOL *thread_pool)
wait for all the launched process, blocking but light on the CPU as there is no polling
long int get_nb_cpu_cores()
get number of core of current system
Structure of a trhead pool.
Common headers and low-level functions & define.
void n_memset(void *dst, void *val, size_t size, size_t count)
memset bytes to a custom value
Definition n_fluids.c:32
#define N_FLUID_S_FIELD
array number for s
Definition n_fluids.c:23
#define N_FLUID_U_FIELD
array number for u
Definition n_fluids.c:19
void * n_fluid_integrate_proc(void *ptr)
ready to be threaded integration function
Definition n_fluids.c:187
void * n_fluid_advectVel_proc(void *ptr)
ready to be threaded add velocities function
Definition n_fluids.c:407
void * n_fluid_advectSmoke_proc(void *ptr)
ready to be threaded add smoke function
Definition n_fluids.c:503
int n_fluid_setObstacleFromBitmap(N_FLUID *fluid, ALLEGRO_BITMAP *bitmap, double x, double y, double vx, double vy, double r)
set an obstacle in the fluid grid from a bitmap mask
Definition n_fluids.c:703
#define N_FLUID_V_FIELD
array number for v
Definition n_fluids.c:21
void * n_fluid_solveIncompressibility_proc(void *ptr)
ready to be threaded incompressibility solving function
Definition n_fluids.c:224
Fluid management port from "How to write an Eulerian fluid simulator with 200 lines of code",...
Thread pool declaration.