1#[cfg(test)]
2mod test;
3use crate::math::Projection;
4
5use crate::{
6 fem::block::element::{
7 ElementNodalReferenceCoordinates, FiniteElement, GradientVectors, IntegrationWeights,
8 ParametricCoordinate, ParametricCoordinates, ParametricReference, ShapeFunctions,
9 ShapeFunctionsAtIntegrationPoints, ShapeFunctionsGradients, StandardGradientOperators,
10 StandardGradientOperatorsTransposed,
11 composite::{
12 CompositeElement, NormalizedProjectionMatrix, ParametricGradientOperators,
13 ProjectionMatrix, ShapeFunctionIntegrals, ShapeFunctionIntegralsProducts,
14 },
15 linear::Tetrahedron as LinearTetrahedron,
16 quadratic::Tetrahedron as QuadraticTetrahedron,
17 },
18 math::{Quantity, Scalar, ScalarList, Tensor, TensorRank1},
19 units::Volume,
20};
21
22const G: usize = 4;
23const M: usize = 3;
24const N: usize = 10;
25const P: usize = 4;
26const Q: usize = 12;
27
28pub type Tetrahedron = CompositeElement<G, N>;
29
30impl From<ElementNodalReferenceCoordinates<N>> for Tetrahedron {
31 fn from(reference_nodal_coordinates: ElementNodalReferenceCoordinates<N>) -> Self {
32 let gradient_vectors = Self::projected_gradient_vectors(&reference_nodal_coordinates);
33 let integration_weights = Self::reference_jacobians(&reference_nodal_coordinates)
34 * Quantity::<Volume>::new(Self::integration_weight());
35 Self {
36 gradient_vectors,
37 integration_weights,
38 }
39 }
40}
41
42impl FiniteElement<G, M, N, P> for Tetrahedron {
43 fn integration_points() -> ParametricCoordinates<G, M> {
44 QuadraticTetrahedron::integration_points() }
46 fn integration_weights(&self) -> &IntegrationWeights<G, Volume> {
47 &self.integration_weights
48 }
49 fn parametric_reference() -> ParametricReference<M, N> {
50 [
51 [0.0, 0.0, 0.0],
52 [1.0, 0.0, 0.0],
53 [0.0, 1.0, 0.0],
54 [0.0, 0.0, 1.0],
55 [0.5, 0.0, 0.0],
56 [0.5, 0.5, 0.0],
57 [0.0, 0.5, 0.0],
58 [0.0, 0.0, 0.5],
59 [0.5, 0.0, 0.5],
60 [0.0, 0.5, 0.5],
61 ]
62 .into()
63 }
64 fn parametric_weights() -> ScalarList<G> {
65 [1.0 / 24.0; G].into()
66 }
67 fn shape_functions(parametric_coordinate: ParametricCoordinate<M>) -> ShapeFunctions<P> {
68 LinearTetrahedron::shape_functions(parametric_coordinate) }
70 fn shape_functions_gradients(
71 parametric_coordinate: ParametricCoordinate<M>,
72 ) -> ShapeFunctionsGradients<M, P> {
73 LinearTetrahedron::shape_functions_gradients(parametric_coordinate) }
75}
76
77impl Tetrahedron {
78 const fn integration_weight() -> Scalar {
79 1.0 / 24.0
80 }
81 fn inverse_normalized_projection_matrix() -> NormalizedProjectionMatrix<P> {
82 const DIAG: Scalar = 4.0 / 640.0;
83 const OFF: Scalar = -1.0 / 640.0;
84 [
85 [DIAG, OFF, OFF, OFF],
86 [OFF, DIAG, OFF, OFF],
87 [OFF, OFF, DIAG, OFF],
88 [OFF, OFF, OFF, DIAG],
89 ]
90 .into()
91 }
92 fn inverse_projection_matrix(
93 reference_jacobians_subelements: &ScalarList<Q>,
94 ) -> NormalizedProjectionMatrix<P> {
95 Self::shape_function_integrals_products()
96 .iter()
97 .zip(reference_jacobians_subelements)
98 .map(
99 |(shape_function_integrals_products, reference_jacobian_subelement)| {
100 shape_function_integrals_products * reference_jacobian_subelement
101 },
102 )
103 .sum::<ProjectionMatrix<P>>()
104 .inverse()
105 }
106 fn projected_gradient_vectors(
107 reference_nodal_coordinates: &ElementNodalReferenceCoordinates<N>,
108 ) -> GradientVectors<3, G, N> {
109 let parametric_gradient_operators = Self::shape_functions_gradients_at_integration_points()
110 .iter()
111 .map(|standard_gradient_operator| {
112 reference_nodal_coordinates * standard_gradient_operator
113 })
114 .collect::<ParametricGradientOperators<Q>>();
115 let reference_jacobians_subelements =
116 Self::reference_jacobians_subelements(reference_nodal_coordinates);
117 let inverse_projection_matrix =
118 Self::inverse_projection_matrix(&reference_jacobians_subelements);
119 Self::shape_functions_at_integration_points()
120 .iter()
121 .map(|shape_functions_at_integration_point| {
122 Self::standard_gradient_operators_transposed()
123 .iter()
124 .map(|standard_gradient_operators_a| {
125 Self::shape_function_integrals()
126 .iter()
127 .zip(
128 standard_gradient_operators_a.iter().zip(
129 parametric_gradient_operators
130 .iter()
131 .zip(reference_jacobians_subelements.iter()),
132 ),
133 )
134 .map(
135 |(
136 shape_function_integral,
137 (
138 standard_gradient_operator,
139 (
140 parametric_gradient_operator,
141 reference_jacobian_subelement,
142 ),
143 ),
144 )| {
145 (parametric_gradient_operator.inverse_transpose()
146 * standard_gradient_operator)
147 * reference_jacobian_subelement
148 * (shape_functions_at_integration_point
149 * (&inverse_projection_matrix
150 * shape_function_integral))
151 },
152 )
153 .sum()
154 })
155 .collect()
156 })
157 .collect()
158 }
159 fn reference_jacobians(
160 reference_nodal_coordinates: &ElementNodalReferenceCoordinates<N>,
161 ) -> ScalarList<G> {
162 let vector = Self::inverse_normalized_projection_matrix()
163 * Self::shape_function_integrals()
164 .iter()
165 .zip(Self::reference_jacobians_subelements(
166 reference_nodal_coordinates,
167 ))
168 .map(|(shape_function_integral, reference_jacobian_subelement)| {
169 shape_function_integral * reference_jacobian_subelement
170 })
171 .sum::<TensorRank1<P, Projection>>();
172 Self::shape_functions_at_integration_points()
173 .iter()
174 .map(|shape_functions_at_integration_point| {
175 (shape_functions_at_integration_point * &vector).value()
176 })
177 .collect()
178 }
179 fn reference_jacobians_subelements(
180 reference_nodal_coordinates: &ElementNodalReferenceCoordinates<N>,
181 ) -> ScalarList<Q> {
182 Self::shape_functions_gradients_at_integration_points()
183 .iter()
184 .map(|standard_gradient_operator| {
185 reference_nodal_coordinates * standard_gradient_operator
186 })
187 .collect::<ParametricGradientOperators<Q>>()
188 .iter()
189 .map(|parametric_gradient_operator| parametric_gradient_operator.determinant())
190 .collect()
191 }
192 fn shape_functions_at_integration_points() -> ShapeFunctionsAtIntegrationPoints<G, P> {
193 const DIAG: Scalar = 0.585_410_196_624_968_5;
194 const OFF: Scalar = 0.138_196_601_125_010_5;
195 [
196 [DIAG, OFF, OFF, OFF],
197 [OFF, DIAG, OFF, OFF],
198 [OFF, OFF, DIAG, OFF],
199 [OFF, OFF, OFF, DIAG],
200 ]
201 .into()
202 }
203 fn shape_function_integrals() -> ShapeFunctionIntegrals<Q, P> {
204 [
205 [200.0, 40.0, 40.0, 40.0],
206 [40.0, 200.0, 40.0, 40.0],
207 [40.0, 40.0, 200.0, 40.0],
208 [40.0, 40.0, 40.0, 200.0],
209 [30.0, 70.0, 30.0, 30.0],
210 [10.0, 50.0, 50.0, 50.0],
211 [30.0, 30.0, 30.0, 70.0],
212 [50.0, 50.0, 10.0, 50.0],
213 [50.0, 50.0, 50.0, 10.0],
214 [30.0, 30.0, 70.0, 30.0],
215 [50.0, 10.0, 50.0, 50.0],
216 [70.0, 30.0, 30.0, 30.0],
217 ]
218 .into()
219 }
220 fn shape_function_integrals_products() -> ShapeFunctionIntegralsProducts<Q, P> {
221 [
222 [
223 [128.0, 24.0, 24.0, 24.0],
224 [24.0, 8.0, 4.0, 4.0],
225 [24.0, 4.0, 8.0, 4.0],
226 [24.0, 4.0, 4.0, 8.0],
227 ],
228 [
229 [8.0, 24.0, 4.0, 4.0],
230 [24.0, 128.0, 24.0, 24.0],
231 [4.0, 24.0, 8.0, 4.0],
232 [4.0, 24.0, 4.0, 8.0],
233 ],
234 [
235 [8.0, 4.0, 24.0, 4.0],
236 [4.0, 8.0, 24.0, 4.0],
237 [24.0, 24.0, 128.0, 24.0],
238 [4.0, 4.0, 24.0, 8.0],
239 ],
240 [
241 [8.0, 4.0, 4.0, 24.0],
242 [4.0, 8.0, 4.0, 24.0],
243 [4.0, 4.0, 8.0, 24.0],
244 [24.0, 24.0, 24.0, 128.0],
245 ],
246 [
247 [7.0, 13.0, 5.0, 5.0],
248 [13.0, 31.0, 13.0, 13.0],
249 [5.0, 13.0, 7.0, 5.0],
250 [5.0, 13.0, 5.0, 7.0],
251 ],
252 [
253 [1.0, 3.0, 3.0, 3.0],
254 [3.0, 17.0, 15.0, 15.0],
255 [3.0, 15.0, 17.0, 15.0],
256 [3.0, 15.0, 15.0, 17.0],
257 ],
258 [
259 [7.0, 5.0, 5.0, 13.0],
260 [5.0, 7.0, 5.0, 13.0],
261 [5.0, 5.0, 7.0, 13.0],
262 [13.0, 13.0, 13.0, 31.0],
263 ],
264 [
265 [17.0, 15.0, 3.0, 15.0],
266 [15.0, 17.0, 3.0, 15.0],
267 [3.0, 3.0, 1.0, 3.0],
268 [15.0, 15.0, 3.0, 17.0],
269 ],
270 [
271 [17.0, 15.0, 15.0, 3.0],
272 [15.0, 17.0, 15.0, 3.0],
273 [15.0, 15.0, 17.0, 3.0],
274 [3.0, 3.0, 3.0, 1.0],
275 ],
276 [
277 [7.0, 5.0, 13.0, 5.0],
278 [5.0, 7.0, 13.0, 5.0],
279 [13.0, 13.0, 31.0, 13.0],
280 [5.0, 5.0, 13.0, 7.0],
281 ],
282 [
283 [17.0, 3.0, 15.0, 15.0],
284 [3.0, 1.0, 3.0, 3.0],
285 [15.0, 3.0, 17.0, 15.0],
286 [15.0, 3.0, 15.0, 17.0],
287 ],
288 [
289 [31.0, 13.0, 13.0, 13.0],
290 [13.0, 7.0, 5.0, 5.0],
291 [13.0, 5.0, 7.0, 5.0],
292 [13.0, 5.0, 5.0, 7.0],
293 ],
294 ]
295 .into()
296 }
297 fn shape_functions_gradients_at_integration_points() -> StandardGradientOperators<M, N, Q> {
298 [
299 [
300 [-2.0, -2.0, -2.0],
301 [0.0, 0.0, 0.0],
302 [0.0, 0.0, 0.0],
303 [0.0, 0.0, 0.0],
304 [2.0, 0.0, 0.0],
305 [0.0, 0.0, 0.0],
306 [0.0, 2.0, 0.0],
307 [0.0, 0.0, 2.0],
308 [0.0, 0.0, 0.0],
309 [0.0, 0.0, 0.0],
310 ],
311 [
312 [0.0, 0.0, 0.0],
313 [2.0, 0.0, 0.0],
314 [0.0, 0.0, 0.0],
315 [0.0, 0.0, 0.0],
316 [-2.0, -2.0, -2.0],
317 [0.0, 2.0, 0.0],
318 [0.0, 0.0, 0.0],
319 [0.0, 0.0, 0.0],
320 [0.0, 0.0, 2.0],
321 [0.0, 0.0, 0.0],
322 ],
323 [
324 [0.0, 0.0, 0.0],
325 [0.0, 0.0, 0.0],
326 [0.0, 2.0, 0.0],
327 [0.0, 0.0, 0.0],
328 [0.0, 0.0, 0.0],
329 [2.0, 0.0, 0.0],
330 [-2.0, -2.0, -2.0],
331 [0.0, 0.0, 0.0],
332 [0.0, 0.0, 0.0],
333 [0.0, 0.0, 2.0],
334 ],
335 [
336 [0.0, 0.0, 0.0],
337 [0.0, 0.0, 0.0],
338 [0.0, 0.0, 0.0],
339 [0.0, 0.0, 2.0],
340 [0.0, 0.0, 0.0],
341 [0.0, 0.0, 0.0],
342 [0.0, 0.0, 0.0],
343 [-2.0, -2.0, -2.0],
344 [2.0, 0.0, 0.0],
345 [0.0, 2.0, 0.0],
346 ],
347 [
348 [0.0, 0.0, 0.0],
349 [0.0, 0.0, 0.0],
350 [0.0, 0.0, 0.0],
351 [0.0, 0.0, 0.0],
352 [-2.0 / 3.0, -2.0, -2.0],
353 [4.0 / 3.0, 2.0, 0.0],
354 [-2.0 / 3.0, 0.0, 0.0],
355 [-2.0 / 3.0, 0.0, 0.0],
356 [4.0 / 3.0, 0.0, 2.0],
357 [-2.0 / 3.0, 0.0, 0.0],
358 ],
359 [
360 [0.0, 0.0, 0.0],
361 [0.0, 0.0, 0.0],
362 [0.0, 0.0, 0.0],
363 [0.0, 0.0, 0.0],
364 [-2.0 / 3.0, -2.0 / 3.0, -2.0 / 3.0],
365 [4.0 / 3.0, 4.0 / 3.0, -2.0 / 3.0],
366 [-2.0 / 3.0, -2.0 / 3.0, -2.0 / 3.0],
367 [-2.0 / 3.0, -2.0 / 3.0, -2.0 / 3.0],
368 [4.0 / 3.0, -2.0 / 3.0, 4.0 / 3.0],
369 [-2.0 / 3.0, 4.0 / 3.0, 4.0 / 3.0],
370 ],
371 [
372 [0.0, 0.0, 0.0],
373 [0.0, 0.0, 0.0],
374 [0.0, 0.0, 0.0],
375 [0.0, 0.0, 0.0],
376 [0.0, 0.0, -2.0 / 3.0],
377 [0.0, 0.0, -2.0 / 3.0],
378 [0.0, 0.0, -2.0 / 3.0],
379 [-2.0, -2.0, -2.0 / 3.0],
380 [2.0, 0.0, 4.0 / 3.0],
381 [0.0, 2.0, 4.0 / 3.0],
382 ],
383 [
384 [0.0, 0.0, 0.0],
385 [0.0, 0.0, 0.0],
386 [0.0, 0.0, 0.0],
387 [0.0, 0.0, 0.0],
388 [0.0, -4.0 / 3.0, -2.0],
389 [0.0, 2.0 / 3.0, 0.0],
390 [0.0, 2.0 / 3.0, 0.0],
391 [-2.0, -4.0 / 3.0, 0.0],
392 [2.0, 2.0 / 3.0, 2.0],
393 [0.0, 2.0 / 3.0, 0.0],
394 ],
395 [
396 [0.0, 0.0, 0.0],
397 [0.0, 0.0, 0.0],
398 [0.0, 0.0, 0.0],
399 [0.0, 0.0, 0.0],
400 [0.0, -2.0, -4.0 / 3.0],
401 [2.0, 2.0, 2.0 / 3.0],
402 [-2.0, 0.0, -4.0 / 3.0],
403 [0.0, 0.0, 2.0 / 3.0],
404 [0.0, 0.0, 2.0 / 3.0],
405 [0.0, 0.0, 2.0 / 3.0],
406 ],
407 [
408 [0.0, 0.0, 0.0],
409 [0.0, 0.0, 0.0],
410 [0.0, 0.0, 0.0],
411 [0.0, 0.0, 0.0],
412 [0.0, -2.0 / 3.0, 0.0],
413 [2.0, 4.0 / 3.0, 0.0],
414 [-2.0, -2.0 / 3.0, -2.0],
415 [0.0, -2.0 / 3.0, 0.0],
416 [0.0, -2.0 / 3.0, 0.0],
417 [0.0, 4.0 / 3.0, 2.0],
418 ],
419 [
420 [0.0, 0.0, 0.0],
421 [0.0, 0.0, 0.0],
422 [0.0, 0.0, 0.0],
423 [0.0, 0.0, 0.0],
424 [2.0 / 3.0, 0.0, 0.0],
425 [2.0 / 3.0, 0.0, 0.0],
426 [-4.0 / 3.0, 0.0, -2.0],
427 [-4.0 / 3.0, -2.0, 0.0],
428 [2.0 / 3.0, 0.0, 0.0],
429 [2.0 / 3.0, 2.0, 2.0],
430 ],
431 [
432 [0.0, 0.0, 0.0],
433 [0.0, 0.0, 0.0],
434 [0.0, 0.0, 0.0],
435 [0.0, 0.0, 0.0],
436 [2.0 / 3.0, -4.0 / 3.0, -4.0 / 3.0],
437 [2.0 / 3.0, 2.0 / 3.0, 2.0 / 3.0],
438 [-4.0 / 3.0, 2.0 / 3.0, -4.0 / 3.0],
439 [-4.0 / 3.0, -4.0 / 3.0, 2.0 / 3.0],
440 [2.0 / 3.0, 2.0 / 3.0, 2.0 / 3.0],
441 [2.0 / 3.0, 2.0 / 3.0, 2.0 / 3.0],
442 ],
443 ]
444 .into()
445 }
446 fn standard_gradient_operators_transposed() -> StandardGradientOperatorsTransposed<M, N, Q> {
447 [
448 [
449 [-2.0, -2.0, -2.0],
450 [0.0, 0.0, 0.0],
451 [0.0, 0.0, 0.0],
452 [0.0, 0.0, 0.0],
453 [0.0, 0.0, 0.0],
454 [0.0, 0.0, 0.0],
455 [0.0, 0.0, 0.0],
456 [0.0, 0.0, 0.0],
457 [0.0, 0.0, 0.0],
458 [0.0, 0.0, 0.0],
459 [0.0, 0.0, 0.0],
460 [0.0, 0.0, 0.0],
461 ],
462 [
463 [0.0, 0.0, 0.0],
464 [2.0, 0.0, 0.0],
465 [0.0, 0.0, 0.0],
466 [0.0, 0.0, 0.0],
467 [0.0, 0.0, 0.0],
468 [0.0, 0.0, 0.0],
469 [0.0, 0.0, 0.0],
470 [0.0, 0.0, 0.0],
471 [0.0, 0.0, 0.0],
472 [0.0, 0.0, 0.0],
473 [0.0, 0.0, 0.0],
474 [0.0, 0.0, 0.0],
475 ],
476 [
477 [0.0, 0.0, 0.0],
478 [0.0, 0.0, 0.0],
479 [0.0, 2.0, 0.0],
480 [0.0, 0.0, 0.0],
481 [0.0, 0.0, 0.0],
482 [0.0, 0.0, 0.0],
483 [0.0, 0.0, 0.0],
484 [0.0, 0.0, 0.0],
485 [0.0, 0.0, 0.0],
486 [0.0, 0.0, 0.0],
487 [0.0, 0.0, 0.0],
488 [0.0, 0.0, 0.0],
489 ],
490 [
491 [0.0, 0.0, 0.0],
492 [0.0, 0.0, 0.0],
493 [0.0, 0.0, 0.0],
494 [0.0, 0.0, 2.0],
495 [0.0, 0.0, 0.0],
496 [0.0, 0.0, 0.0],
497 [0.0, 0.0, 0.0],
498 [0.0, 0.0, 0.0],
499 [0.0, 0.0, 0.0],
500 [0.0, 0.0, 0.0],
501 [0.0, 0.0, 0.0],
502 [0.0, 0.0, 0.0],
503 ],
504 [
505 [2.0, 0.0, 0.0],
506 [-2.0, -2.0, -2.0],
507 [0.0, 0.0, 0.0],
508 [0.0, 0.0, 0.0],
509 [-2.0 / 3.0, -2.0, -2.0],
510 [-2.0 / 3.0, -2.0 / 3.0, -2.0 / 3.0],
511 [0.0, 0.0, -2.0 / 3.0],
512 [0.0, -4.0 / 3.0, -2.0],
513 [0.0, -2.0, -4.0 / 3.0],
514 [0.0, -2.0 / 3.0, 0.0],
515 [2.0 / 3.0, 0.0, 0.0],
516 [2.0 / 3.0, -4.0 / 3.0, -4.0 / 3.0],
517 ],
518 [
519 [0.0, 0.0, 0.0],
520 [0.0, 2.0, 0.0],
521 [2.0, 0.0, 0.0],
522 [0.0, 0.0, 0.0],
523 [4.0 / 3.0, 2.0, 0.0],
524 [4.0 / 3.0, 4.0 / 3.0, -2.0 / 3.0],
525 [0.0, 0.0, -2.0 / 3.0],
526 [0.0, 2.0 / 3.0, 0.0],
527 [2.0, 2.0, 2.0 / 3.0],
528 [2.0, 4.0 / 3.0, 0.0],
529 [2.0 / 3.0, 0.0, 0.0],
530 [2.0 / 3.0, 2.0 / 3.0, 2.0 / 3.0],
531 ],
532 [
533 [0.0, 2.0, 0.0],
534 [0.0, 0.0, 0.0],
535 [-2.0, -2.0, -2.0],
536 [0.0, 0.0, 0.0],
537 [-2.0 / 3.0, 0.0, 0.0],
538 [-2.0 / 3.0, -2.0 / 3.0, -2.0 / 3.0],
539 [0.0, 0.0, -2.0 / 3.0],
540 [0.0, 2.0 / 3.0, 0.0],
541 [-2.0, 0.0, -4.0 / 3.0],
542 [-2.0, -2.0 / 3.0, -2.0],
543 [-4.0 / 3.0, 0.0, -2.0],
544 [-4.0 / 3.0, 2.0 / 3.0, -4.0 / 3.0],
545 ],
546 [
547 [0.0, 0.0, 2.0],
548 [0.0, 0.0, 0.0],
549 [0.0, 0.0, 0.0],
550 [-2.0, -2.0, -2.0],
551 [-2.0 / 3.0, 0.0, 0.0],
552 [-2.0 / 3.0, -2.0 / 3.0, -2.0 / 3.0],
553 [-2.0, -2.0, -2.0 / 3.0],
554 [-2.0, -4.0 / 3.0, 0.0],
555 [0.0, 0.0, 2.0 / 3.0],
556 [0.0, -2.0 / 3.0, 0.0],
557 [-4.0 / 3.0, -2.0, 0.0],
558 [-4.0 / 3.0, -4.0 / 3.0, 2.0 / 3.0],
559 ],
560 [
561 [0.0, 0.0, 0.0],
562 [0.0, 0.0, 2.0],
563 [0.0, 0.0, 0.0],
564 [2.0, 0.0, 0.0],
565 [4.0 / 3.0, 0.0, 2.0],
566 [4.0 / 3.0, -2.0 / 3.0, 4.0 / 3.0],
567 [2.0, 0.0, 4.0 / 3.0],
568 [2.0, 2.0 / 3.0, 2.0],
569 [0.0, 0.0, 2.0 / 3.0],
570 [0.0, -2.0 / 3.0, 0.0],
571 [2.0 / 3.0, 0.0, 0.0],
572 [2.0 / 3.0, 2.0 / 3.0, 2.0 / 3.0],
573 ],
574 [
575 [0.0, 0.0, 0.0],
576 [0.0, 0.0, 0.0],
577 [0.0, 0.0, 2.0],
578 [0.0, 2.0, 0.0],
579 [-2.0 / 3.0, 0.0, 0.0],
580 [-2.0 / 3.0, 4.0 / 3.0, 4.0 / 3.0],
581 [0.0, 2.0, 4.0 / 3.0],
582 [0.0, 2.0 / 3.0, 0.0],
583 [0.0, 0.0, 2.0 / 3.0],
584 [0.0, 4.0 / 3.0, 2.0],
585 [2.0 / 3.0, 2.0, 2.0],
586 [2.0 / 3.0, 2.0 / 3.0, 2.0 / 3.0],
587 ],
588 ]
589 .into()
590 }
591}