ASCOT5
Loading...
Searching...
No Matches
wall_3d.c
Go to the documentation of this file.
1
12#include <stdio.h>
13#include <stdlib.h>
14#include <math.h>
15#include "../ascot5.h"
16#include "wall_3d.h"
17#include "../math.h"
18#include "../list.h"
19#include "../octree.h"
20#include "../print.h"
21
23
46int wall_3d_init(wall_3d_data* data, int nelements, real* x1x2x3, real* y1y2y3,
47 real* z1z2z3) {
48
49 /* The data is to be in the format
50 * [x1 y1 z1 x2 y2 z2 x3 y3 z3; ... ]
51 */
52 data->n = nelements;
53 data->wall_tris = (real*)malloc(9 * nelements * sizeof(real));
54 real xmin = x1x2x3[0], xmax = x1x2x3[0];
55 real ymin = y1y2y3[0], ymax = y1y2y3[0];
56 real zmin = z1z2z3[0], zmax = z1z2z3[0];
57 for(int i = 0; i < nelements; i++) {
58 for(int j = 0; j < 3; j++) {
59 data->wall_tris[i*9 + j*3 + 0] = x1x2x3[3*i+j];
60 data->wall_tris[i*9 + j*3 + 1] = y1y2y3[3*i+j];
61 data->wall_tris[i*9 + j*3 + 2] = z1z2z3[3*i+j];
62
63 /* Find min & max values of the volume occupied by the wall */
64 xmin = fmin( xmin, x1x2x3[3*i+j] );
65 xmax = fmax( xmax, x1x2x3[3*i+j] );
66 ymin = fmin( ymin, y1y2y3[3*i+j] );
67 ymax = fmax( ymax, y1y2y3[3*i+j] );
68 zmin = fmin( zmin, z1z2z3[3*i+j] );
69 zmax = fmax( zmax, z1z2z3[3*i+j] );
70 }
71 }
72
73 /* Add a little bit of padding so we don't need to worry about triangles
74 clipping the edges */
75 data->xmin = xmin - 0.1;
76 data->xmax = xmax + 0.1;
77 data->ymin = ymin - 0.1;
78 data->ymax = ymax + 0.1;
79 data->zmin = zmin - 0.1;
80 data->zmax = zmax + 0.1;
81
82 /* Depth of the octree in which the triangles are sorted */
84 int ngrid = 1;
85 for(int i = 0; i < data->depth - 1; i++) {
86 ngrid *= 2;
87 }
88 data->ngrid = ngrid;
89
90 data->xgrid = (data->xmax - data->xmin) / data->ngrid;
91 data->ygrid = (data->ymax - data->ymin) / data->ngrid;
92 data->zgrid = (data->zmax - data->zmin) / data->ngrid;
93
96
97 print_out(VERBOSE_IO, "\n3D wall model (wall_3D)\n");
99 "Number of wall elements %d\n"
100 "Spanning xmin = %2.3f m, xmax = %2.3f m\n"
101 " ymin = %2.3f m, ymax = %2.3f m\n"
102 " zmin = %2.3f m, zmax = %2.3f m\n",
103 data->n,
104 data->xmin, data->xmax, data->ymin,
105 data->ymax, data->zmin, data->zmax);
106
107 return 0;
108}
109
116 free(data->tree_array);
117 free(data->wall_tris);
118}
119
126 GPU_MAP_TO_DEVICE(
127 data->wall_tris[0:data->n*9],
128 data->tree_array[0:data->tree_array_size]
129 )
130}
131
143void wall_3d_init_tree(wall_3d_data* w, real* offload_array) {
144 /* create a list for holding the triangle ids in each cell */
145 int ncell = w->ngrid*w->ngrid*w->ngrid;
146 list_int_node** tri_list = (list_int_node**) malloc(ncell
147 *sizeof(list_int_node*));
148 int i;
149 for(i = 0; i < ncell; i++) {
150 list_int_create(&tri_list[i]);
151 }
152
153 /* iterate through all triangles and cells and fill the lists */
154 for(i = 0; i < w->n; i++) {
155 real t1[3], t2[3], t3[3];
156 t1[0] = offload_array[i*9];
157 t1[1] = offload_array[i*9+1];
158 t1[2] = offload_array[i*9+2];
159 t2[0] = offload_array[i*9+3];
160 t2[1] = offload_array[i*9+4];
161 t2[2] = offload_array[i*9+5];
162 t3[0] = offload_array[i*9+6];
163 t3[1] = offload_array[i*9+7];
164 t3[2] = offload_array[i*9+8];
165
166 int ix, iy, iz;
167 #pragma omp parallel for private(ix, iy, iz)
168 for(ix = 0; ix < w->ngrid; ix++) {
169 for(iy = 0; iy < w->ngrid; iy++) {
170 for(iz = 0; iz < w->ngrid; iz++) {
171 real c1[3], c2[3];
172 real epsilon = 1e-6;
173 c1[0] = w->xmin + ix * w->xgrid - epsilon;
174 c2[0] = w->xmin + (ix+1) * w->xgrid + epsilon;
175 c1[1] = w->ymin + iy * w->ygrid - epsilon;
176 c2[1] = w->ymin + (iy+1) * w->ygrid + epsilon;
177 c1[2] = w->zmin + iz * w->zgrid - epsilon;
178 c2[2] = w->zmin + (iz+1) * w->zgrid + epsilon;
179 int result = wall_3d_tri_in_cube(t1, t2, t3, c1, c2);
180 int cell_index = ix*w->ngrid*w->ngrid+iy*w->ngrid+iz;
181 if(result > 0) {
182 list_int_add(tri_list[cell_index], i);
183 }
184 }
185 }
186 }
187 }
188
189 /* construct an array from the triangle lists */
190 int list_size = 0;
191 for(i = 0; i < ncell; i++) {
192 list_size += list_int_size(tri_list[i]);
193 }
194
195 w->tree_array = (int*) malloc((2*ncell + list_size)*sizeof(int));
196 w->tree_array_size = 2*ncell + list_size;
197
198 int next_empty_list = ncell;
199 for(i = 0; i < ncell; i++) {
200 w->tree_array[i] = next_empty_list;
201 w->tree_array[next_empty_list] = list_int_size(tri_list[i]);
202 int j;
203 for(j = 0; j < w->tree_array[next_empty_list]; j++) {
204 w->tree_array[next_empty_list+j+1] = list_int_get(tri_list[i], j);
205 }
206 next_empty_list += w->tree_array[next_empty_list] + 1;
207 list_int_free(&tri_list[i]);
208 }
209 free(tri_list);
210}
211
224 if (w->n > 1000000){
226 "Starting to initialize 3D-wall octree with %d triangles.\n",
227 w->n);
228 }
229
230 /* Construct the octree and store triangles there */
231 octree_node* tree;
232 octree_create(&tree, w->xmin, w->xmax, w->ymin, w->ymax, w->zmin, w->zmax,
233 w->depth);
234 int i;
235 for(i = 0; i < w->n; i++) {
236 real t1[3], t2[3], t3[3];
237 t1[0] = w->wall_tris[i*9];
238 t1[1] = w->wall_tris[i*9+1];
239 t1[2] = w->wall_tris[i*9+2];
240 t2[0] = w->wall_tris[i*9+3];
241 t2[1] = w->wall_tris[i*9+4];
242 t2[2] = w->wall_tris[i*9+5];
243 t3[0] = w->wall_tris[i*9+6];
244 t3[1] = w->wall_tris[i*9+7];
245 t3[2] = w->wall_tris[i*9+8];
246 octree_add(tree, t1, t2, t3, i);
247 if (i%1000000==0 && i > 0){
248 print_out(VERBOSE_NORMAL, " Adding triangle %10d/%d.\n",i,w->n);
249 }
250 }
251
252 /* Create lists for triangles in each grid square and fill the lists
253 by querying the octree in each grid point */
254 int ncell = w->ngrid*w->ngrid*w->ngrid;
255 list_int_node** tri_list =
256 (list_int_node**) malloc(ncell * sizeof(list_int_node*));
257 int ix, iy, iz;
258 for(ix = 0; ix < w->ngrid; ix++) {
259 for(iy = 0; iy < w->ngrid; iy++) {
260 for(iz = 0; iz < w->ngrid; iz++) {
261 real p[3];
262 p[0] = w->xmin + ix * w->xgrid + 0.5*w->xgrid;
263 p[1] = w->ymin + iy * w->ygrid + 0.5*w->ygrid;
264 p[2] = w->zmin + iz * w->zgrid + 0.5*w->zgrid;
265
266 int cell_index = ix*w->ngrid*w->ngrid+iy*w->ngrid+iz;
267 tri_list[cell_index] = octree_get(tree, p);
268 }
269 }
270 }
271
272 /* construct an array from the triangle lists */
273 int list_size = 0;
274 for(i = 0; i < ncell; i++) {
275 list_size += list_int_size(tri_list[i]);
276 }
277 w->tree_array = (int*) malloc((2*ncell + list_size)*sizeof(int));
278
279 int next_empty_list = ncell;
280 for(i = 0; i < ncell; i++) {
281 /* First ncell elements store the position where the actual cell data
282 * begins in tree_array */
283 w->tree_array[i] = next_empty_list;
284
285 /* The first data point in the actual cell data is the number of
286 * triangles in this cell */
287 w->tree_array[next_empty_list] = list_int_size(tri_list[i]);
288
289 /* Store triangle IDs that are located in this cell */
290 for(int j = 0; j < w->tree_array[next_empty_list]; j++) {
291 w->tree_array[next_empty_list+j+1] = list_int_get(tri_list[i], j);
292 }
293 next_empty_list += w->tree_array[next_empty_list] + 1;
294 }
295 free(tri_list);
296 octree_free(&tree);
297}
298
315int wall_3d_hit_wall(real r1, real phi1, real z1, real r2, real phi2,
316 real z2, wall_3d_data* wdata, real* w_coll) {
317 real rpz1[3], rpz2[3];
318 rpz1[0] = r1;
319 rpz1[1] = phi1;
320 rpz1[2] = z1;
321 rpz2[0] = r2;
322 rpz2[1] = phi2;
323 rpz2[2] = z2;
324
325 real q1[3], q2[3];
326 math_rpz2xyz(rpz1, q1);
327 math_rpz2xyz(rpz2, q2);
328
329 int ix1 = (int) floor((q1[0] - wdata->xmin)
330 / ((wdata->xmax - wdata->xmin) / (wdata->ngrid)));
331 int iy1 = (int) floor((q1[1] - wdata->ymin)
332 / ((wdata->ymax - wdata->ymin) / (wdata->ngrid)));
333 int iz1 = (int) floor((q1[2] - wdata->zmin)
334 / ((wdata->zmax - wdata->zmin) / (wdata->ngrid)));
335
336 int ix2 = (int) floor((q2[0] - wdata->xmin)
337 / ((wdata->xmax - wdata->xmin) / (wdata->ngrid)));
338 int iy2 = (int) floor((q2[1] - wdata->ymin)
339 / ((wdata->ymax - wdata->ymin) / (wdata->ngrid)));
340 int iz2 = (int) floor((q2[2] - wdata->zmin)
341 / ((wdata->zmax - wdata->zmin) / (wdata->ngrid)));
342
343 int hit_tri = 0;
344 real smallest_w = 1.1;
345
346 for(int i = 0; i <= abs(ix2-ix1); i++) {
347 for(int j = 0; j <= abs(iy2-iy1); j++) {
348 for(int k = 0; k <= abs(iz2-iz1); k++) {
349 int ix = ix1 + i*((int) copysign(1, ix2-ix1));
350 int iy = iy1 + j*((int) copysign(1, iy2-iy1));
351 int iz = iz1 + k*((int) copysign(1, iz2-iz1));
352
353 if(ix >= 0 && ix < wdata->ngrid && iy >= 0 && iy < wdata->ngrid
354 && iz >= 0 && iz < wdata->ngrid) {
355
356 int ilist = wdata->tree_array[ix*wdata->ngrid*wdata->ngrid
357 + iy*wdata->ngrid + iz];
358
359 for(int l = 0; l < wdata->tree_array[ilist]; l++) {
360 int itri = wdata->tree_array[ilist+l+1];
362 q1, q2,
363 &wdata->wall_tris[9*itri],
364 &wdata->wall_tris[9*itri+3],
365 &wdata->wall_tris[9*itri+6]);
366 if(w >= 0 && w < smallest_w) {
367 smallest_w = w;
368 hit_tri = itri+1;
369 }
370 }
371 }
372 }
373 }
374 }
375 *w_coll = smallest_w;
376 return hit_tri;
377}
378
395int wall_3d_hit_wall_full(real r1, real phi1, real z1, real r2, real phi2,
396 real z2, wall_3d_data* wdata, real* w_coll) {
397 real rpz1[3], rpz2[3];
398 rpz1[0] = r1;
399 rpz1[1] = phi1;
400 rpz1[2] = z1;
401 rpz2[0] = r2;
402 rpz2[1] = phi2;
403 rpz2[2] = z2;
404
405 real q1[3], q2[3];
406 math_rpz2xyz(rpz1, q1);
407 math_rpz2xyz(rpz2, q2);
408
409 int hit_tri = 0;
410 real smallest_w = 1.1;
411 real w;
412 int j;
413
414 for(j = 0; j < wdata->n; j++) {
415 w = wall_3d_tri_collision(q1, q2, &wdata->wall_tris[9*j],
416 &wdata->wall_tris[9*j+3], &wdata->wall_tris[9*j+6]);
417 if(w > 0) {
418 if(w < smallest_w) {
419 smallest_w = w;
420 hit_tri = j+1;
421 }
422 }
423 }
424
425 *w_coll = smallest_w;
426 return hit_tri;
427}
428
440int wall_3d_tri_in_cube(real t1[3], real t2[3], real t3[3], real bb1[3],
441 real bb2[3]) {
442 /* check if any point is inside the cube */
443 if(bb1[0] <= t1[0] && t1[0] <= bb2[0]
444 && bb1[1] <= t1[1] && t1[1] <= bb2[1]
445 && bb1[2] <= t1[2] && t1[2] <= bb2[2])
446 return 1;
447 if(bb1[0] < t2[0] && t2[0] <= bb2[0]
448 && bb1[1] <= t2[1] && t2[1] <= bb2[1]
449 && bb1[2] <= t2[2] && t2[2] <= bb2[2])
450 return 1;
451 if(bb1[0] <= t3[0] && t3[0] <= bb2[0]
452 && bb1[1] <= t3[1] && t3[1] <= bb2[1]
453 && bb1[2] <= t3[2] && t3[2] <= bb2[2])
454 return 1;
455
456 /* no such luck; check if any of the cube edges intersects the triangle */
457 real c000[3]; c000[0] = bb1[0]; c000[1] = bb1[1]; c000[2] = bb1[2];
458 real c100[3]; c100[0] = bb2[0]; c100[1] = bb1[1]; c100[2] = bb1[2];
459 real c010[3]; c010[0] = bb1[0]; c010[1] = bb2[1]; c010[2] = bb1[2];
460 real c110[3]; c110[0] = bb2[0]; c110[1] = bb2[1]; c110[2] = bb1[2];
461 real c001[3]; c001[0] = bb1[0]; c001[1] = bb1[1]; c001[2] = bb2[2];
462 real c101[3]; c101[0] = bb2[0]; c101[1] = bb1[1]; c101[2] = bb2[2];
463 real c011[3]; c011[0] = bb1[0]; c011[1] = bb2[1]; c011[2] = bb2[2];
464 real c111[3]; c111[0] = bb2[0]; c111[1] = bb2[1]; c111[2] = bb2[2];
465
466 if( wall_3d_tri_collision(c000, c100, t1, t2, t3) >= 0
467 || wall_3d_tri_collision(c000, c010, t1, t2, t3) >= 0
468 || wall_3d_tri_collision(c110, c010, t1, t2, t3) >= 0
469 || wall_3d_tri_collision(c110, c100, t1, t2, t3) >= 0
470 || wall_3d_tri_collision(c000, c001, t1, t2, t3) >= 0
471 || wall_3d_tri_collision(c010, c011, t1, t2, t3) >= 0
472 || wall_3d_tri_collision(c100, c101, t1, t2, t3) >= 0
473 || wall_3d_tri_collision(c110, c111, t1, t2, t3) >= 0
474 || wall_3d_tri_collision(c001, c101, t1, t2, t3) >= 0
475 || wall_3d_tri_collision(c001, c011, t1, t2, t3) >= 0
476 || wall_3d_tri_collision(c111, c011, t1, t2, t3) >= 0
477 || wall_3d_tri_collision(c111, c101, t1, t2, t3) >= 0)
478 return 1;
479
480 /* check for triangle edges intersecting cube quads */
481 if( wall_3d_quad_collision(t1, t2, c000, c100, c110, c010) == 1
482 || wall_3d_quad_collision(t1, t2, c000, c010, c011, c001) == 1
483 || wall_3d_quad_collision(t1, t2, c000, c100, c101, c001) == 1
484 || wall_3d_quad_collision(t1, t2, c010, c110, c111, c011) == 1
485 || wall_3d_quad_collision(t1, t2, c100, c101, c111, c110) == 1
486 || wall_3d_quad_collision(t1, t2, c001, c101, c111, c011) == 1)
487 return 1;
488 if( wall_3d_quad_collision(t3, t2, c000, c100, c110, c010) == 1
489 || wall_3d_quad_collision(t3, t2, c000, c010, c011, c001) == 1
490 || wall_3d_quad_collision(t3, t2, c000, c100, c101, c001) == 1
491 || wall_3d_quad_collision(t3, t2, c010, c110, c111, c011) == 1
492 || wall_3d_quad_collision(t3, t2, c100, c101, c111, c110) == 1
493 || wall_3d_quad_collision(t3, t2, c001, c101, c111, c011) == 1)
494 return 1;
495 if( wall_3d_quad_collision(t1, t3, c000, c100, c110, c010) == 1
496 || wall_3d_quad_collision(t1, t3, c000, c010, c011, c001) == 1
497 || wall_3d_quad_collision(t1, t3, c000, c100, c101, c001) == 1
498 || wall_3d_quad_collision(t1, t3, c010, c110, c111, c011) == 1
499 || wall_3d_quad_collision(t1, t3, c100, c101, c111, c110) == 1
500 || wall_3d_quad_collision(t1, t3, c001, c101, c111, c011) == 1)
501 return 1;
502 return 0;
503}
504
520double wall_3d_tri_collision(real q1[3], real q2[3], real t1[3], real t2[3],
521 real t3[3]) {
522 real q12[3], Q12[3];
523 Q12[0] = q2[0] - q1[0];
524 Q12[1] = q2[1] - q1[1];
525 Q12[2] = q2[2] - q1[2];
526 math_unit(Q12, q12);
527
528 real edge12[3];
529 edge12[0] = t2[0] - t1[0];
530 edge12[1] = t2[1] - t1[1];
531 edge12[2] = t2[2] - t1[2];
532
533 real edge13[3];
534 edge13[0] = t3[0] - t1[0];
535 edge13[1] = t3[1] - t1[1];
536 edge13[2] = t3[2] - t1[2];
537
538 real h[3];
539 math_cross(q12, edge13, h);
540 real det = math_dot(h, edge12);
541
542 /* Check that the triangle has non-zero area */
543 real normal[3], area;
544 math_cross(edge12, edge13, normal);
545 area = math_norm(normal);
546
547 real w = -1.0;
548 if( area > WALL_EPSILON ) {
549 /* If ray is parallel to the triangle, nudge it a little bit so we don't
550 have to handle annoying special cases */
551 if( fabs(det) < WALL_EPSILON ) {
552 Q12[0] = q2[0] - q1[0] + 2 * WALL_EPSILON * normal[0] / area;
553 Q12[1] = q2[1] - q1[1] + 2 * WALL_EPSILON * normal[1] / area;
554 Q12[2] = q2[2] - q1[2] + 2 * WALL_EPSILON * normal[2] / area;
555 math_unit(Q12, q12);
556 math_cross(q12, edge13, h);
557 det = math_dot(h, edge12);
558 }
559
560 real tq11[3];
561 tq11[0] = q1[0] - t1[0];
562 tq11[1] = q1[1] - t1[1];
563 tq11[2] = q1[2] - t1[2];
564
565 real n[3];
566 math_cross(tq11, edge12, n);
567
568 real u = math_dot(h, tq11) / det;
569 real v = math_dot(q12, n) / det;
570
571 if( ( u >= 0.0 && u <= 1.0 ) && ( v >= 0.0 && u + v <= 1.0 ) ) {
572 w = ( math_dot(n, edge13) / det ) / math_norm(Q12);
573 if( w > 1.0 ) {
574 w = -1.0;
575 }
576 }
577 }
578
579 return w;
580
581}
582
595int wall_3d_quad_collision(real q1[3], real q2[3], real t1[3], real t2[3],
596 real t3[3], real t4[3]) {
597 if(wall_3d_tri_collision(q1, q2, t1, t2, t3) >= 0
598 || wall_3d_tri_collision(q1, q2, t1, t3, t4) >= 0)
599 return 1;
600 else
601 return 0;
602}
Main header file for ASCOT5.
double real
Definition ascot5.h:85
#define WALL_OCTREE_DEPTH
Default depth of octree struct.
Definition ascot5.h:134
int list_int_size(list_int_node *list)
Get list size.
Definition list.c:86
void list_int_create(list_int_node **list)
Create an empty list.
Definition list.c:16
void list_int_free(list_int_node **list)
Deallocate this list and all lists it is linked to.
Definition list.c:28
int list_int_get(list_int_node *list, int index)
Retrieve the data stored in a list node.
Definition list.c:69
void list_int_add(list_int_node *list, int data)
Add new node to the end of the chain.
Definition list.c:48
Header file for list.c.
Header file for math.c.
#define math_dot(a, b)
Calculate dot product a[3] dot b[3].
Definition math.h:28
#define math_unit(a, b)
Calculate unit vector b from a 3D vector a.
Definition math.h:70
#define math_rpz2xyz(rpz, xyz)
Convert cylindrical coordinates rpz to cartesian coordinates xyz.
Definition math.h:78
#define math_cross(a, b, c)
Calculate cross product for 3D vectors c = a x b.
Definition math.h:31
#define math_norm(a)
Calculate norm of 3D vector a.
Definition math.h:64
void octree_add(octree_node *node, real t1[3], real t2[3], real t3[3], int id)
Add triangle to the node(s) it belongs to.
Definition octree.c:123
void octree_free(octree_node **node)
Free octree node and all its child nodes.
Definition octree.c:91
void octree_create(octree_node **node, real x_min, real x_max, real y_min, real y_max, real z_min, real z_max, int depth)
Create octree of given depth.
Definition octree.c:46
list_int_node * octree_get(octree_node *node, real p[3])
Get that leaf node's linked list the given coordinate belongs to.
Definition octree.c:164
Header file for octree.c.
Macros for printing console output.
#define print_out(v,...)
Print to standard output.
Definition print.h:31
@ VERBOSE_NORMAL
Definition print.h:18
@ VERBOSE_IO
Definition print.h:20
Linked list node that stores int data.
Definition list.h:12
Struct representing single octree node.
Definition octree.h:17
3D wall data parameters
Definition wall_3d.h:16
real zgrid
Definition wall_3d.h:26
int * tree_array
Array storing information what triangles given octree cell stores.
Definition wall_3d.h:40
real zmax
Definition wall_3d.h:25
real xmax
Definition wall_3d.h:19
real zmin
Definition wall_3d.h:24
real ymin
Definition wall_3d.h:21
real xmin
Definition wall_3d.h:18
real * wall_tris
Definition wall_3d.h:30
real xgrid
Definition wall_3d.h:20
real ygrid
Definition wall_3d.h:23
real ymax
Definition wall_3d.h:22
int wall_3d_tri_in_cube(real t1[3], real t2[3], real t3[3], real bb1[3], real bb2[3])
Check if any part of a triangle is inside a box.
Definition wall_3d.c:440
void wall_3d_init_tree(wall_3d_data *w, real *offload_array)
Construct wall octree iteratively.
Definition wall_3d.c:143
int wall_3d_hit_wall_full(real r1, real phi1, real z1, real r2, real phi2, real z2, wall_3d_data *wdata, real *w_coll)
Check if trajectory from (r1, phi1, z1) to (r2, phi2, z2) intersects the wall against all triangles.
Definition wall_3d.c:395
double wall_3d_tri_collision(real q1[3], real q2[3], real t1[3], real t2[3], real t3[3])
Check if a line segment intersects a triangle.
Definition wall_3d.c:520
void wall_3d_free(wall_3d_data *data)
Free allocated resources.
Definition wall_3d.c:115
void wall_3d_offload(wall_3d_data *data)
Offload data to the accelerator.
Definition wall_3d.c:125
int wall_3d_hit_wall(real r1, real phi1, real z1, real r2, real phi2, real z2, wall_3d_data *wdata, real *w_coll)
Check if trajectory from (r1, phi1, z1) to (r2, phi2, z2) intersects the wall using the octree struct...
Definition wall_3d.c:315
int wall_3d_init(wall_3d_data *data, int nelements, real *x1x2x3, real *y1y2y3, real *z1z2z3)
Initialize 3D wall data and check inputs.
Definition wall_3d.c:46
int wall_3d_quad_collision(real q1[3], real q2[3], real t1[3], real t2[3], real t3[3], real t4[3])
Check if a line segment intersects a quad (assumed planar)
Definition wall_3d.c:595
void wall_3d_init_octree(wall_3d_data *w)
Construct wall octree recursively.
Definition wall_3d.c:223
Header file for wall_3d.c.
#define WALL_EPSILON
Definition wall_3d.h:11