Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
virtual.h
Go to the documentation of this file.
1/** @file virtual.h
2 */
3/**
4# Multi-dimensional arrays using virtual memory
5
6This implementation uses the Unix/Linux virtual memory subsystem to
7more efficiently store sparse multidimensional arrays.
8
9The `Memindex` structure defines multi-dimensional arrays. The
10interface is that used by [/src/grid/tree.h](). */
11
12#include <sys/mman.h>
13
14struct _Memindex {
15 int len;
16#if dimension == 1
17 char ** b;
18#elif dimension == 2
19 char *** b;
20#else // dimension == 3
21 char **** b;
22#endif
23};
24
25#define Memindex struct _Memindex *
26
27/**
28The `mem_data()` macros return the data stored at a specific
29(multidimensional) index. It assumes that the index is allocated. This
30can be checked with `mem_allocated()`. */
31
32#if dimension == 1
33inline static
34const bool mem_allocated (const Memindex m, const int i) {
35 return (i >= 0 && i < m->len && m->b[i]);
36}
37#define mem_data(m,i) ((m)->b[i])
38#elif dimension == 2
39inline static
40const bool mem_allocated (const Memindex m, const int i, const int j) {
41 return (i >= 0 && i < m->len && m->b[i] &&
42 j >= 0 && j < m->len && m->b[i][j]);
43}
44#define mem_data(m,i,j) ((m)->b[i][j])
45#else // dimension == 3
46inline static
47const bool mem_allocated (const Memindex m, const int i, const int j, const int k) {
48 return (i >= 0 && i < m->len && m->b[i] &&
49 j >= 0 && j < m->len && m->b[i][j] &&
50 k >= 0 && k < m->len && m->b[i][j][k]);
51}
52#define mem_data(m,i,j,k) ((m)->b[i][j][k])
53#endif // dimension == 3
54
55/**
56The `mem_new()` function returns a new (empty) `Memindex`. */
57
59{
60 Memindex m = calloc (1, sizeof (struct _Memindex));
61 return m;
62}
63
64/**
65The `mem_destroy()` function frees all the memory allocated by a given
66`Memindex`. */
67
68void mem_destroy (Memindex m, int len)
69{
70#if dimension > 1
71 for (int i = 0; i < len; i++)
72 if (m->b[i]) {
73 #if dimension > 2
74 for (int j = 0; j < len; j++)
75 if (m->b[i][j])
76 munmap (m->b[i][j], m->len*sizeof (char *));
77 #endif // dimension > 2
78 munmap (m->b[i], m->len*sizeof (char *));
79 }
80#endif // dimension > 1
81 if (m->b)
82 munmap (m->b, m->len*sizeof (char *));
83 free (m);
84}
85
86/**
87The `mem_assign()` function assigns a (pointer) value to a given index. */
88
89#define mymap(len) mmap (NULL, len*sizeof (char *), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
90
91#if dimension == 1
92void mem_assign (Memindex m, int i, int len, void * b)
93{
94 if (!m->b) {
95 m->b = mymap (len);
96 m->len = len;
97 }
98 mem_data(m,i) = b;
99}
100#elif dimension == 2
101void mem_assign (Memindex m, int i, int j, int len, void * b)
102{
103 assert (b != NULL);
104 if (!m->b) {
105 m->b = mymap (len);
106 m->len = len;
107 }
108 if (!m->b[i])
109 m->b[i] = mymap (len);
110 mem_data(m,i,j) = b;
111}
112#else // dimension == 3
113void mem_assign (Memindex m, int i, int j, int k, int len, void * b)
114{
115 if (!m->b) {
116 m->b = mymap (len);
117 m->len = len;
118 }
119 if (!m->b[i])
120 m->b[i] = mymap (len);
121 if (!m->b[i][j])
122 m->b[i][j] = mymap (len);
123 mem_data(m,i,j,k) = b;
124}
125#endif // dimension == 3
126
127/**
128The `mem_free()` function frees a given index. */
129
130static bool mem_free1d (char ** const b, const int i, int len)
131{
132 // Assumes 4k pages = 512*sizeof(char *) = 512*8 = 4096
133 char ** const start = b + (i/512)*512;
134 for (char ** j = start; j < start + min(len, 512); j++)
135 if (*j)
136 return false;
137 if (madvise (start, 4096, MADV_DONTNEED))
138 perror ("virtual.h: madvise: ");
139 return true;
140}
141
142#if dimension == 1
143void mem_free (Memindex m, int i, int len, void * b)
144{
145 if (m->b[i]) {
146 m->b[i] = NULL;
147 mem_free1d (m->b, i, len);
148 }
149}
150#elif dimension == 2
151void mem_free (Memindex m, int i, int j, int len, void * b)
152{
153 if (m->b[i][j]) {
154 m->b[i][j] = NULL;
155 if (mem_free1d (m->b[i], j, len))
156 mem_free1d ((char **)m->b, i, len);
157 }
158}
159#else // dimension == 3
160void mem_free (Memindex m, int i, int j, int k, int len, void * b)
161{
162 if (m->b[i][j][k]) {
163 m->b[i][j][k] = NULL;
164 if (mem_free1d (m->b[i][j], k, len))
165 if (mem_free1d ((char **)m->b[i], j, len))
166 mem_free1d ((char **)m->b, i, len);
167 }
168}
169#endif // dimension == 3
170
171/**
172The `foreach_mem()` macro traverses every `_i` allocated elements of
173array `_m` taking into account a periodicity of `_len` (and ghost
174cells). */
175
177 Memindex _m = index;
178 int _len = len;
179 Point point = {0};
180 for (point.i = max(Period.x*GHOSTS, 0);
181 point.i < min(_len - Period.x*GHOSTS, _len);
182 point.i += _i)
183 if (_m->b[point.i])
184#if dimension > 1
185 for (point.j = max(Period.y*GHOSTS, 0);
186 point.j < min(_len - Period.y*GHOSTS, _len);
187 point.j += _i)
188 if (_m->b[point.i][point.j])
189#if dimension > 2
190 for (point.k = max(Period.z*GHOSTS, 0);
191 point.k < min(_len - Period.z*GHOSTS, _len);
192 point.k += _i)
193 if (_m->b[point.i][point.j][point.k])
194#endif // dimension > 2
195#endif // dimension > 1
196 {...}
197}
int min
Definition balance.h:192
define k
define m((k)==0 &&(l)==0 &&(m)==0) macro2 foreach_point(double _x=0.
#define GHOSTS
Definition cartesian.h:13
free(list1)
int x
Definition common.h:76
struct @0 Period
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define line calloc(n, s) @ define prealloc(p
#define assert(a)
Definition config.h:107
Point point
Definition conserving.h:86
*cs[i, 0, 0] a *[i -1, 0, 0] j
Definition embed.h:88
scalar int i
Definition embed.h:74
macro
We also redefine the "per field" (inner) traversal.
Definition layers.h:18
size_t max
Definition mtrace.h:8
size *double * b
#define mem_allocated(m, i, j)
The mem_data() macros return the data stored at a specific (multidimensional) index.
Definition range.h:153
def _i
Definition stencils.h:405
Definition linear.h:21
int i
Definition linear.h:23
int len
Definition simple.h:16
char *** b
Definition range.h:134
define n sizeof(Cell))) @define fine(a
Array * index
struct _Memindex * mem_new(int len)
The mem_new() function returns a new (empty) Memindex.
Definition virtual.h:58
macro foreach_mem(struct _Memindex *index, int len, int _i)
The foreach_mem() macro traverses every _i allocated elements of array _m taking into account a perio...
Definition virtual.h:176
void mem_free(struct _Memindex *m, int i, int j, int len, void *b)
Definition virtual.h:151
#define mymap(len)
The mem_assign() function assigns a (pointer) value to a given index.
Definition virtual.h:89
static bool mem_free1d(char **const b, const int i, int len)
The mem_free() function frees a given index.
Definition virtual.h:130
#define Memindex
Definition virtual.h:25
void mem_assign(struct _Memindex *m, int i, int j, int len, void *b)
Definition virtual.h:101
#define mem_data(m, i, j)
Definition virtual.h:44
void mem_destroy(struct _Memindex *m, int len)
The mem_destroy() function frees all the memory allocated by a given Memindex.
Definition virtual.h:68