-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdomain.c
360 lines (303 loc) · 10.6 KB
/
domain.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
#include <stdlib.h>
#include "grid.h"
#include "domain.h"
#include "vector.h"
#include "error.h"
// Convention in ids etc
// Ids for vertices, triangles follow the matlab id convention - starting at 1
// Create one big domain
domain* build_cartesian_domain(grid* cartesian_grid, int subdomain_count_x)
{
int i,j;
domain* cartesian_domain;
#define CGN (cartesian_grid->N + 1)
cartesian_domain = calloc(1, sizeof(domain));
cartesian_domain->cartesian_grid = cartesian_grid;
cartesian_domain->subdomain_count_x = subdomain_count_x;
cartesian_domain->subdomain_vertex_map = calloc(subdomain_count_x, sizeof(int*));
#define CDM (cartesian_domain->subdomain_vertex_map)
for(i = 0; i < subdomain_count_x; i++)
{
cartesian_domain->subdomain_vertex_map[i] = calloc(CGN*CGN, sizeof(int));
for(j = 0; j < CGN*CGN; j++)
{
CDM[i][j] = -1;
}
}
#undef CGN
#undef CDM
return cartesian_domain;
}
// Create subdomains and add them to the domain object
int build_subdomains_in_domain(domain* cartesian_domain, int overlap)
{
int i;
#define CG (cartesian_domain->cartesian_grid)
#define CDN (cartesian_domain->cartesian_grid->N + 1)
#define CSD (cartesian_domain->subdomains)
#define CSDN (cartesian_domain->subdomain_count_x)
if(CDN % CSDN != 0)
{
error("The number of points in the grid is not divisible by the count of subdomains");
}
if(CDN/CSDN < 4*overlap)
{
warn("The size of overlap is approaching the size of subdomain. Things will break.");
}
cartesian_domain->subdomains = (subdomain*) calloc(CSDN, sizeof(subdomain));
for(i = 0; i < CSDN; i++)
{
CSD[i].id = i; // Start with 0 go to p-1
CSD[i].cartesian_grid = CG; // Global grid
CSD[i].overlap = 2*overlap; // Number of overlapping nodes with adjacent subdomains
if(i == 0)
{
CSD[i].bottom_left_x = 0; // Bottom left corner in global grid - x
CSD[i].bottom_left_y = 0; // Bottom left corner in global grid - y
CSD[i].top_right_x = CDN/CSDN + overlap - 1; // Bottom left corner in global grid - x
CSD[i].top_right_y = CDN - 1; // Bottom left corner in global grid - y
}
else if(i == CSDN - 1)
{
CSD[i].bottom_left_x = CDN - CDN/CSDN - overlap; // Bottom left corner in global grid - x
CSD[i].bottom_left_y = 0; // Bottom left corner in global grid - y
CSD[i].top_right_x = CDN - 1; // Bottom left corner in global grid - x
CSD[i].top_right_y = CDN - 1; // Bottom left corner in global grid - y
}
else
{
CSD[i].bottom_left_x = (CDN/CSDN) * i - overlap; // Bottom left corner in global grid - x
CSD[i].bottom_left_y = 0; // Bottom left corner in global grid - y
CSD[i].top_right_x = (CDN/CSDN) * (i + 1) + overlap - 1; // Bottom left corner in global grid - x
CSD[i].top_right_y = CDN - 1; // Bottom left corner in global grid - y
}
CSD[i].dimX = CSD[i].top_right_x - CSD[i].bottom_left_x + 1; // May include overlap if there are overlapping subdomains
CSD[i].dimY = CSD[i].top_right_y - CSD[i].bottom_left_y + 1; // May include overlap if there are overlapping subdomains
CSD[i].subdomain_vertices = calloc(CSD[i].dimX*CSD[i].dimY, sizeof(vertex*)); // Vertices belonging to the subdomain in the global grid vertex order
vector_init(&(CSD[i].subdomain_solution), CSD[i].dimX*CSD[i].dimY); // Solution in the subdomain in the global grid vertex order
if(i != 0)
{
vector_init(&(CSD[i].ghost_subdomain_left), 2*overlap*CSD[i].dimY); // Ghost cells into which neighboring threads will write info
}
if(i != CSDN - 1)
{
vector_init(&(CSD[i].ghost_subdomain_right), 2*overlap*CSD[i].dimY); // Ghost cells into which neighboring threads will write info
}
}
#undef CDN
#undef CSD
#undef CSDN
#undef CG
return 0;
}
// Create vertices in domain
int create_vertices_for_domain(domain* cartesian_domain)
{
int i, j, count;
#define CG (cartesian_domain->cartesian_grid)
#define CDN (cartesian_domain->cartesian_grid->N + 1)
cartesian_domain->vertices = (vertex*) calloc(CDN*CDN, sizeof(vertex));
#define CDV (cartesian_domain->vertices)
count = 0;
for(i = 0; i < CDN; i++) // Go one row after another
{
for(j = 0; j < CDN; j++) // Loop over columns
{
CDV[count].id = i * CDN + j;
CDV[count].x = CG->grid_nodes_x[j];
CDV[count].y = CG->grid_nodes_y[i];
count++;
}
}
#undef CDN
#undef CG
#undef CDV
return 0;
}
// Go over the list of vertices, add them to the subdomain vertex list.
int create_vertex_subdomain_mapping(domain* cartesian_domain, int idx)
{
int i, j, count;
#define CSD (cartesian_domain->subdomains)
#define CDV (cartesian_domain->vertices)
#define CDM (cartesian_domain->subdomain_vertex_map)
#define CDN (cartesian_domain->cartesian_grid->N + 1)
count = 0;
for(i = CSD[idx].bottom_left_y; i <= CSD[idx].top_right_y; i++)
{
for(j = CSD[idx].bottom_left_x; j <= CSD[idx].top_right_x; j++)
{
CSD[idx].subdomain_vertices[count] = &(CDV[i * CDN + j]);
CDM[idx][i * CDN + j] = count;
count++;
}
}
#undef CSD
#undef CDV
#undef CDN
#undef CDM
return 0;
}
// Copy the solution to the right, left, or both subdomains
int copy_overlap_to_adjacent_neighbours_ghost(domain* cartesian_domain, int idx, int direction)
{
int i, j;
int count;
#define CSD (cartesian_domain->subdomains)
#define CSDN (cartesian_domain->subdomain_count_x)
if(direction <= 0)
{
if(idx > 0) // copy left
{
count = 0;
for(i = 0; i < CSD[idx].dimY; i++)
{
for(j = 0; j < CSD[idx].overlap; j++)
{
CSD[idx - 1].ghost_subdomain_right.elements[count++] = CSD[idx].subdomain_solution.elements[i*CSD[idx].dimX + j];
}
}
}
}
if(direction >= 0)
{
if(idx < CSDN - 1) // copy right
{
count = 0;
for(i = 0; i < CSD[idx].dimY; i++)
{
for(j = CSD[idx].dimX - CSD[idx].overlap; j < CSD[idx].dimX; j++)
{
CSD[idx + 1].ghost_subdomain_left.elements[count++] = CSD[idx].subdomain_solution.elements[i*CSD[idx].dimX + j];
}
}
}
}
#undef CSD
#undef CSDN
return 0;
}
// Copy the solution from the left or right ghost cell of the same subdomain
int copy_from_my_ghost_cell(domain* cartesian_domain, int idx, int direction)
{
int i, j;
int count;
#define CSD (cartesian_domain->subdomains)
#define CSDN (cartesian_domain->subdomain_count_x)
if(direction <= 0)
{
if(idx > 0) // copy from left
{
count = 0;
for(i = 0; i < CSD[idx].dimY; i++)
{
for(j = 0; j < CSD[idx].overlap; j++)
{
CSD[idx].subdomain_solution.elements[i*CSD[idx].dimX + j] = CSD[idx].ghost_subdomain_left.elements[count++];
}
}
}
}
if(direction >= 0)
{
if(idx < CSDN - 1) // copy from right
{
count = 0;
for(i = 0; i < CSD[idx].dimY; i++)
{
for(j = CSD[idx].dimX - CSD[idx].overlap; j < CSD[idx].dimX; j++)
{
CSD[idx].subdomain_solution.elements[i*CSD[idx].dimX + j] = CSD[idx].ghost_subdomain_right.elements[count++];
}
}
}
}
#undef CSD
#undef CSDN
return 0;
}
// Boolean method returns true or false to write output for vertex. Each subdomain only writes the right overlap.
int write_output_for_vertex(domain* cartesian_domain, int subdomainIdx, vertex* v)
{
int ll, ul, global_vertex_i;
#define CSD (cartesian_domain->subdomains)
#define CDN (cartesian_domain->cartesian_grid->N + 1)
if(subdomainIdx == 0)
{
ll = 0;
}
else
{
ll = CSD[subdomainIdx].bottom_left_x + CSD[subdomainIdx].overlap;
}
ul = CSD[subdomainIdx].top_right_x;
global_vertex_i = (v->id % CDN);
#undef CSD
#undef CDN
// return 1;
return (ll <= global_vertex_i && global_vertex_i <= ul);
}
// Remove all vertex objects from heap
int cleanup_vertices(domain* cartesian_domain)
{
#define CDV (cartesian_domain->vertices)
if(CDV != NULL)
{
free(CDV);
}
#undef CDV
return 0;
}
// Remove all subdomain objects from heap
int cleanup_subdomains(domain* cartesian_domain)
{
int i;
#define CSD (cartesian_domain->subdomains)
#define CSDN (cartesian_domain->subdomain_count_x)
for(i = 0 ; i < CSDN; i++)
{
if(CSD[i].subdomain_vertices != NULL)
{
free(CSD[i].subdomain_vertices);
}
vector_free(&(CSD[i].subdomain_solution));
if(i != 0)
{
vector_free(&(CSD[i].ghost_subdomain_left));
}
if(i != CSDN - 1)
{
vector_free(&(CSD[i].ghost_subdomain_right));
}
if(CSD[i].elements != NULL)
{
free(CSD[i].elements);
}
}
#undef CSDN
#undef CSD
return 0;
}
// Remove domain object from heap
int cleanup_domain(domain* cartesian_domain)
{
int i;
#define CDM (cartesian_domain->subdomain_vertex_map)
#define CSD (cartesian_domain->subdomains)
#define CSDN (cartesian_domain->subdomain_count_x)
if(cartesian_domain != NULL)
{
cleanup_vertices(cartesian_domain);
for(i = 0; i < CSDN; i++)
{
free(CDM[i]);
}
free(CDM);
free(CSD);
free(cartesian_domain);
}
#undef CDM
#undef CSD
#undef CSDN
return 0;
}