Skip to content

Commit 73734e3

Browse files
committed
THe problem of deducing the next layer's coefficient given the previous layer can be written as an affine transformation in linear algebra (y = Ax+b). The method _get_propagation_matrix_and_offset_vec returns A and b. num_coef_pairs is no longer needed so is deleted.
1 parent 055109c commit 73734e3

File tree

1 file changed

+64
-27
lines changed

1 file changed

+64
-27
lines changed

process/neutronics.py

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -152,22 +152,6 @@ class Coefficients:
152152
c: Iterable[float]
153153
s: Iterable[float]
154154

155-
@property
156-
def num_coef_pairs(self) -> int:
157-
"""
158-
The length of .c and .s, which should be the same.
159-
Raises
160-
------
161-
ValueError:
162-
If .c and .s do not match in length, then we have a problem.
163-
"""
164-
if len(self.c)!=len(self.s):
165-
raise ValueError(
166-
"Mismatched lengths between "
167-
f"c ({len(self.c)}) and s ({len(self.s)})"
168-
)
169-
return len(self.c)
170-
171155
def validate_length(self, exp_len: int, parent_name: str):
172156
"""Validate that all fields has the correct length."""
173157
for const_name, const_value in asdict(self).items():
@@ -545,7 +529,7 @@ def _calculate_mean_energy_and_incident_bin(
545529

546530
def _groupwise_cs_values_in_layer(
547531
self, n: int, num_layer: int, x: float | npt.NDArray
548-
) -> tuple[float, float] | tuple[npt.NDArray, npt.NDArray]:
532+
) -> npt.NDArray:
549533
"""
550534
Calculate the num_layer-th layer n-th basis function at the specified
551535
x position(s).
@@ -557,7 +541,7 @@ def _groupwise_cs_values_in_layer(
557541
else:
558542
l = np.sqrt(-self.l2[num_layer, n])
559543
c, s = np.cos, np.sin
560-
return c(abs_x / l), s(abs_x / l)
544+
return np.array([c(abs_x / l), s(abs_x / l)])
561545

562546
def _groupwise_cs_differential_in_layer(
563547
self, n: int, num_layer: int, x: float | npt.NDArray
@@ -569,9 +553,9 @@ def _groupwise_cs_differential_in_layer(
569553
abs_x = abs(x)
570554
if self.l2[num_layer, n] > 0:
571555
l = np.sqrt(self.l2[num_layer, n])
572-
return np.sinh(abs_x / l) / l, np.cosh(abs_x / l) / l
556+
return np.array([np.sinh(abs_x / l) / l, np.cosh(abs_x / l) / l])
573557
l = np.sqrt(-self.l2[num_layer, n])
574-
return -np.sin(abs_x / l) / l, np.cos(abs_x / l) / l
558+
return np.array([-np.sin(abs_x / l) / l, np.cos(abs_x / l) / l])
575559

576560
def _groupwise_cs_definite_integral_in_layer(
577561
self, n: int, num_layer: int, x_lower: float | npt.NDArray, x_upper
@@ -582,15 +566,15 @@ def _groupwise_cs_definite_integral_in_layer(
582566
"""
583567
if self.l2[num_layer, n] > 0:
584568
l = np.sqrt(self.l2[num_layer, n])
585-
return (
569+
return np.array([
586570
l * (np.sinh(x_upper / l) - np.sinh(x_lower / l)),
587571
l * (np.cosh(x_upper / l) - np.cosh(x_lower / l))
588-
)
572+
])
589573
l = np.sqrt(-self.l2[num_layer, n])
590-
return (
574+
return np.array([
591575
l * (np.sin(x_upper / l) - np.sin(x_lower / l)),
592576
l * (np.cos(x_lower / l) - np.cos(x_upper / l)) # reverse sign
593-
)
577+
])
594578

595579
def solve_lowest_group(self) -> None:
596580
"""
@@ -666,9 +650,62 @@ def solve_lowest_group(self) -> None:
666650
[bz_c_factor], [bz_s_factor]
667651
)
668652
else:
669-
raise NotImplementedError("Only implemented 2 groups so far.")
653+
return NotImplemented
670654
return
671655

656+
def _get_propagation_matrix_and_offset_vec(n: int, num_layer: int):
657+
"""
658+
Infer this layer's main basis functions' coefficients (.c[n] and .s[n])
659+
using using the previous layer's basis functions.
660+
"""
661+
x_j = self.interface_x[num_layer]
662+
coefs_in = np.array(astuple(self.coefficients[num_layer - 1, n])).T
663+
coefs_jn = np.array(astuple(self.coefficients[num_layer, n])).T
664+
d_in = self.diffusion_const[num_layer-1, n]
665+
d_jn = self.diffusion_const[num_layer, n]
666+
l_in = self.l2[num_layer-1, n]
667+
l_jn = self.l2[num_layer, n]
668+
669+
diff_residual_flux = (sum(
670+
cs_coef_pair @ self._groupwise_cs_values_in_layer(
671+
g, num_layer - 1, x_j
672+
)
673+
for g, cs_coef_pair in enumerate(coefs_in) if g!=n
674+
) - sum(
675+
cs_coef_pair @ self._groupwise_cs_values_in_layer(
676+
g, num_layer, x_j
677+
)
678+
for g, cs_coef_pair in enumerate(coefs_jn) if g!=n
679+
)
680+
)
681+
diff_residual_current = l_jn * (
682+
- d_in/d_jn * sum(
683+
cs_coef_pair @ self._groupwise_cs_differential_in_layer(
684+
g, num_layer - 1, x_j
685+
)
686+
for g, cs_coef_pair in enumerate(coefs_in) if g!=n
687+
)
688+
+ sum(
689+
cs_coef_pair @ self._groupwise_cs_differential_in_layer(
690+
g, num_layer, x_j
691+
)
692+
for g, cs_coef_pair in enumerate(coefs_jn) if g!=n
693+
)
694+
)
695+
shift_vector = np.array([diff_residual_flux, diff_residual_current])
696+
697+
transformation_matrix = np.array([
698+
self._groupwise_cs_values_in_layer(n, num_layer - 1, x_j),
699+
-l_jn / d_jn * d_in / l_in * (
700+
self._groupwise_cs_differential_in_layer(n, num_layer - 1, x_j)
701+
),
702+
])
703+
A = np.array([
704+
self._groupwise_cs_values_in_layer(n, num_layer, x_j),
705+
-self._groupwise_cs_differential_in_layer(n, num_layer, x_j),
706+
])
707+
return A @ transformation_matrix, A @ shift_vector
708+
672709
def solve_group_n(self, n: int) -> None:
673710
"""
674711
Solve the n-th group of neutron's diffusion equation, where n <=
@@ -761,8 +798,8 @@ def solve_group_n(self, n: int) -> None:
761798
)
762799
* scale_factor
763800
)
764-
_coefs[num_layer, n].c[n] = sum(skipped_c_coefs)
765-
_coefs[num_layer, n].s[n] = sum(skipped_s_coefs)
801+
_coefs[num_layer, n].c[n] = ... - sum(skipped_c_coefs)
802+
_coefs[num_layer, n].s[n] = ... - sum(skipped_s_coefs)
766803

767804
self.coefficients[num_layer, n] = _coefs
768805

0 commit comments

Comments
 (0)