1use std::collections::HashMap;
2
3#[derive(Clone, Debug)]
4pub struct Block {
5 pub imax: usize,
6 pub jmax: usize,
7 pub kmax: usize, pub x: Vec<f64>, pub y: Vec<f64>,
10 pub z: Vec<f64>,
11}
12
13#[derive(Clone, Debug)]
15pub struct FaceData {
16 pub x: Vec<f64>,
17 pub y: Vec<f64>,
18 pub z: Vec<f64>,
19 pub dims: (usize, usize),
21}
22
23impl Block {
24 pub fn new(
25 imax: usize,
26 jmax: usize,
27 kmax: usize,
28 x: Vec<f64>,
29 y: Vec<f64>,
30 z: Vec<f64>,
31 ) -> Self {
32 let n = imax * jmax * kmax;
33 assert_eq!(x.len(), n);
34 assert_eq!(y.len(), n);
35 assert_eq!(z.len(), n);
36 Self {
37 imax,
38 jmax,
39 kmax,
40 x,
41 y,
42 z,
43 }
44 }
45
46 #[inline]
47 pub fn npoints(&self) -> usize {
48 self.imax * self.jmax * self.kmax
49 }
50
51 #[inline]
52 pub fn idx(&self, i: usize, j: usize, k: usize) -> usize {
53 debug_assert!(i < self.imax && j < self.jmax && k < self.kmax);
55 (k * self.jmax + j) * self.imax + i
56 }
57
58 #[inline]
59 pub fn xyz(&self, i: usize, j: usize, k: usize) -> (f64, f64, f64) {
60 let idx = self.idx(i, j, k);
61 (self.x[idx], self.y[idx], self.z[idx])
62 }
63
64 #[inline]
65 pub fn x_at(&self, i: usize, j: usize, k: usize) -> f64 {
66 self.x[self.idx(i, j, k)]
67 }
68
69 #[inline]
70 pub fn y_at(&self, i: usize, j: usize, k: usize) -> f64 {
71 self.y[self.idx(i, j, k)]
72 }
73
74 #[inline]
75 pub fn z_at(&self, i: usize, j: usize, k: usize) -> f64 {
76 self.z[self.idx(i, j, k)]
77 }
78
79 #[inline]
80 pub fn x_slice(&self) -> &[f64] {
81 &self.x
82 }
83
84 #[inline]
85 pub fn y_slice(&self) -> &[f64] {
86 &self.y
87 }
88
89 #[inline]
90 pub fn z_slice(&self) -> &[f64] {
91 &self.z
92 }
93
94 #[inline]
95 pub fn centroid(&self) -> (f64, f64, f64) {
96 let n = self.npoints() as f64;
97 let sum_x: f64 = self.x.iter().sum();
98 let sum_y: f64 = self.y.iter().sum();
99 let sum_z: f64 = self.z.iter().sum();
100 (sum_x / n, sum_y / n, sum_z / n)
101 }
102
103 pub fn print_xyz(&self, i: usize, j: usize, k: usize) {
105 let (x, y, z) = self.xyz(i, j, k);
106 println!("XYZ at (i={i}, j={j}, k={k}) is ({x:.6}, {y:.6}, {z:.6})");
107 }
108
109 pub fn shifted(&self, amount: f64, axis: char) -> Block {
110 let mut new = self.clone();
111 new.shift_in_place(amount, axis);
112 new
113 }
114
115 pub fn shift_in_place(&mut self, amount: f64, axis: char) {
116 if amount == 0.0 {
117 return;
118 }
119 match axis.to_ascii_lowercase() {
120 'x' => {
121 for v in &mut self.x {
122 *v += amount;
123 }
124 }
125 'y' => {
126 for v in &mut self.y {
127 *v += amount;
128 }
129 }
130 'z' => {
131 for v in &mut self.z {
132 *v += amount;
133 }
134 }
135 _ => {}
136 }
137 }
138
139 #[inline]
141 pub fn size(&self) -> usize {
142 self.npoints()
143 }
144
145 pub fn scale(&mut self, factor: f64) {
147 for v in &mut self.x {
148 *v *= factor;
149 }
150 for v in &mut self.y {
151 *v *= factor;
152 }
153 for v in &mut self.z {
154 *v *= factor;
155 }
156 }
157
158 pub fn scaled(&self, factor: f64) -> Block {
160 let mut new = self.clone();
161 new.scale(factor);
162 new
163 }
164
165 pub fn cylindrical(&self) -> (Vec<f64>, Vec<f64>) {
170 let n = self.npoints();
171 let mut r = Vec::with_capacity(n);
172 let mut theta = Vec::with_capacity(n);
173 for idx in 0..n {
174 let yi = self.y[idx];
175 let zi = self.z[idx];
176 r.push((zi * zi + yi * yi).sqrt());
177 theta.push(yi.atan2(zi));
178 }
179 (r, theta)
180 }
181
182 pub fn cell_volumes(&self) -> Vec<f64> {
190 let (ni, nj, nk) = (self.imax, self.jmax, self.kmax);
191 let n = ni * nj * nk;
192 let idx = |i: usize, j: usize, k: usize| -> usize { (k * nj + j) * ni + i };
193
194 let mut a = vec![vec![0.0f64; n]; 9];
196
197 for k in 1..nk {
199 for j in 1..nj {
200 for i in 0..ni {
201 let dx1 = self.x[idx(i, j, k - 1)] - self.x[idx(i, j - 1, k)];
202 let dy1 = self.y[idx(i, j, k - 1)] - self.y[idx(i, j - 1, k)];
203 let dz1 = self.z[idx(i, j, k - 1)] - self.z[idx(i, j - 1, k)];
204
205 let dx2 = self.x[idx(i, j, k)] - self.x[idx(i, j - 1, k - 1)];
206 let dy2 = self.y[idx(i, j, k)] - self.y[idx(i, j - 1, k - 1)];
207 let dz2 = self.z[idx(i, j, k)] - self.z[idx(i, j - 1, k - 1)];
208
209 let id = idx(i, j, k);
210 a[0][id] = (dy1 * dz2 - dz1 * dy2) * 0.5;
211 a[1][id] = (dz1 * dx2 - dx1 * dz2) * 0.5;
212 a[2][id] = (dx1 * dy2 - dy1 * dx2) * 0.5;
213 }
214 }
215 }
216
217 for k in 1..nk {
219 for j in 0..nj {
220 for i in 1..ni {
221 let dx1 = self.x[idx(i, j, k)] - self.x[idx(i - 1, j, k - 1)];
222 let dy1 = self.y[idx(i, j, k)] - self.y[idx(i - 1, j, k - 1)];
223 let dz1 = self.z[idx(i, j, k)] - self.z[idx(i - 1, j, k - 1)];
224
225 let dx2 = self.x[idx(i, j, k - 1)] - self.x[idx(i - 1, j, k)];
226 let dy2 = self.y[idx(i, j, k - 1)] - self.y[idx(i - 1, j, k)];
227 let dz2 = self.z[idx(i, j, k - 1)] - self.z[idx(i - 1, j, k)];
228
229 let id = idx(i, j, k);
230 a[3][id] = (dy1 * dz2 - dz1 * dy2) * 0.5;
231 a[4][id] = (dz1 * dx2 - dx1 * dz2) * 0.5;
232 a[5][id] = (dx1 * dy2 - dy1 * dx2) * 0.5;
233 }
234 }
235 }
236
237 for k in 0..nk {
239 for j in 1..nj {
240 for i in 1..ni {
241 let dx1 = self.x[idx(i, j, k)] - self.x[idx(i - 1, j - 1, k)];
242 let dy1 = self.y[idx(i, j, k)] - self.y[idx(i - 1, j - 1, k)];
243 let dz1 = self.z[idx(i, j, k)] - self.z[idx(i - 1, j - 1, k)];
244
245 let dx2 = self.x[idx(i - 1, j, k)] - self.x[idx(i, j - 1, k)];
246 let dy2 = self.y[idx(i - 1, j, k)] - self.y[idx(i, j - 1, k)];
247 let dz2 = self.z[idx(i - 1, j, k)] - self.z[idx(i, j - 1, k)];
248
249 let id = idx(i, j, k);
250 a[6][id] = (dy1 * dz2 - dz1 * dy2) * 0.5;
251 a[7][id] = (dz1 * dx2 - dx1 * dz2) * 0.5;
252 a[8][id] = (dx1 * dy2 - dy1 * dx2) * 0.5;
253 }
254 }
255 }
256
257 let mut v = vec![0.0f64; n];
259 for k in 1..nk {
260 for j in 1..nj {
261 for i in 1..ni {
262 let mut cf = [[0.0f64; 3]; 6];
264 cf[0][0] = self.x[idx(i - 1, j - 1, k - 1)] + self.x[idx(i - 1, j - 1, k)]
266 + self.x[idx(i - 1, j, k - 1)]
267 + self.x[idx(i - 1, j, k)];
268 cf[0][1] = self.y[idx(i - 1, j - 1, k - 1)] + self.y[idx(i - 1, j - 1, k)]
269 + self.y[idx(i - 1, j, k - 1)]
270 + self.y[idx(i - 1, j, k)];
271 cf[0][2] = self.z[idx(i - 1, j - 1, k - 1)] + self.z[idx(i - 1, j - 1, k)]
272 + self.z[idx(i - 1, j, k - 1)]
273 + self.z[idx(i - 1, j, k)];
274 cf[1][0] = self.x[idx(i, j - 1, k - 1)] + self.x[idx(i, j - 1, k)]
276 + self.x[idx(i, j, k - 1)]
277 + self.x[idx(i, j, k)];
278 cf[1][1] = self.y[idx(i, j - 1, k - 1)] + self.y[idx(i, j - 1, k)]
279 + self.y[idx(i, j, k - 1)]
280 + self.y[idx(i, j, k)];
281 cf[1][2] = self.z[idx(i, j - 1, k - 1)] + self.z[idx(i, j - 1, k)]
282 + self.z[idx(i, j, k - 1)]
283 + self.z[idx(i, j, k)];
284 cf[2][0] = self.x[idx(i - 1, j - 1, k - 1)] + self.x[idx(i - 1, j - 1, k)]
286 + self.x[idx(i, j - 1, k - 1)]
287 + self.x[idx(i, j - 1, k)];
288 cf[2][1] = self.y[idx(i - 1, j - 1, k - 1)] + self.y[idx(i - 1, j - 1, k)]
289 + self.y[idx(i, j - 1, k - 1)]
290 + self.y[idx(i, j - 1, k)];
291 cf[2][2] = self.z[idx(i - 1, j - 1, k - 1)] + self.z[idx(i - 1, j - 1, k)]
292 + self.z[idx(i, j - 1, k - 1)]
293 + self.z[idx(i, j - 1, k)];
294 cf[3][0] = self.x[idx(i - 1, j, k - 1)] + self.x[idx(i - 1, j, k)]
296 + self.x[idx(i, j, k - 1)]
297 + self.x[idx(i, j, k)];
298 cf[3][1] = self.y[idx(i - 1, j, k - 1)] + self.y[idx(i - 1, j, k)]
299 + self.y[idx(i, j, k - 1)]
300 + self.y[idx(i, j, k)];
301 cf[3][2] = self.z[idx(i - 1, j, k - 1)] + self.z[idx(i - 1, j, k)]
302 + self.z[idx(i, j, k - 1)]
303 + self.z[idx(i, j, k)];
304 cf[4][0] = self.x[idx(i - 1, j - 1, k - 1)] + self.x[idx(i - 1, j, k - 1)]
306 + self.x[idx(i, j - 1, k - 1)]
307 + self.x[idx(i, j, k - 1)];
308 cf[4][1] = self.y[idx(i - 1, j - 1, k - 1)] + self.y[idx(i - 1, j, k - 1)]
309 + self.y[idx(i, j - 1, k - 1)]
310 + self.y[idx(i, j, k - 1)];
311 cf[4][2] = self.z[idx(i - 1, j - 1, k - 1)] + self.z[idx(i - 1, j, k - 1)]
312 + self.z[idx(i, j - 1, k - 1)]
313 + self.z[idx(i, j, k - 1)];
314 cf[5][0] = self.x[idx(i - 1, j - 1, k)] + self.x[idx(i - 1, j, k)]
316 + self.x[idx(i, j - 1, k)]
317 + self.x[idx(i, j, k)];
318 cf[5][1] = self.y[idx(i - 1, j - 1, k)] + self.y[idx(i - 1, j, k)]
319 + self.y[idx(i, j - 1, k)]
320 + self.y[idx(i, j, k)];
321 cf[5][2] = self.z[idx(i - 1, j - 1, k)] + self.z[idx(i - 1, j, k)]
322 + self.z[idx(i, j - 1, k)]
323 + self.z[idx(i, j, k)];
324
325 let mut vol12 = 0.0f64;
326 for nn in 0..2usize {
327 let sign = if nn == 0 { -1.0 } else { 1.0 };
328 for l in 0..3usize {
329 vol12 += sign
331 * (cf[nn][l] * a[l][idx(i - 1 + nn, j, k)]
332 + cf[2 + nn][l] * a[3 + l][idx(i, j - 1 + nn, k)]
333 + cf[4 + nn][l] * a[6 + l][idx(i, j, k - 1 + nn)]);
334 }
335 }
336 v[idx(i, j, k)] = vol12 / 12.0;
337 }
338 }
339 }
340 v
341 }
342
343 pub fn get_faces(&self) -> HashMap<&'static str, FaceData> {
349 let mut map = HashMap::with_capacity(6);
350
351 let extract =
353 |fix_axis: usize, fix_val: usize| -> FaceData {
354 let (nu, nv) = match fix_axis {
355 0 => (self.jmax, self.kmax), 1 => (self.imax, self.kmax), _ => (self.imax, self.jmax), };
359 let cap = nu * nv;
360 let mut xf = Vec::with_capacity(cap);
361 let mut yf = Vec::with_capacity(cap);
362 let mut zf = Vec::with_capacity(cap);
363 for v in 0..nv {
364 for u in 0..nu {
365 let (i, j, k) = match fix_axis {
366 0 => (fix_val, u, v),
367 1 => (u, fix_val, v),
368 _ => (u, v, fix_val),
369 };
370 let id = self.idx(i, j, k);
371 xf.push(self.x[id]);
372 yf.push(self.y[id]);
373 zf.push(self.z[id]);
374 }
375 }
376 FaceData { x: xf, y: yf, z: zf, dims: (nu, nv) }
377 };
378
379 map.insert("imin", extract(0, 0));
380 map.insert("imax", extract(0, self.imax - 1));
381 map.insert("jmin", extract(1, 0));
382 map.insert("jmax", extract(1, self.jmax - 1));
383 map.insert("kmin", extract(2, 0));
384 map.insert("kmax", extract(2, self.kmax - 1));
385 map
386 }
387
388 pub fn sub_block(
390 &self,
391 i_range: std::ops::RangeInclusive<usize>,
392 j_range: std::ops::RangeInclusive<usize>,
393 k_range: std::ops::RangeInclusive<usize>,
394 ) -> Block {
395 let ni = i_range.end() - i_range.start() + 1;
396 let nj = j_range.end() - j_range.start() + 1;
397 let nk = k_range.end() - k_range.start() + 1;
398 let cap = ni * nj * nk;
399 let mut x = Vec::with_capacity(cap);
400 let mut y = Vec::with_capacity(cap);
401 let mut z = Vec::with_capacity(cap);
402 for k in k_range {
403 for j in j_range.clone() {
404 for i in i_range.clone() {
405 let id = self.idx(i, j, k);
406 x.push(self.x[id]);
407 y.push(self.y[id]);
408 z.push(self.z[id]);
409 }
410 }
411 }
412 Block::new(ni, nj, nk, x, y, z)
413 }
414}