1<br> 2 3<i>This program was contributed by Yaqi Wang and Wolfgang 4Bangerth. Results from this program are used and discussed in the publication 5"Three-dimensional h-adaptivity for the multigroup neutron diffusion 6equations" by Yaqi Wang, Wolfgang Bangerth and Jean Ragusa. The paper's full 7bibliographic details are as follows: 8@code 9@Article{WBR09, 10 author = {Yaqi Wang and Wolfgang Bangerth and Jean Ragusa}, 11 title = {Three-dimensional h-adaptivity for the multigroup 12 neutron diffusion equations}, 13 journal = {Progr. Nucl. Energy}, 14 year = 2009, 15 volume = 51, 16 pages = {543--555} 17} 18@endcode 19The paper is available <a target="_top" 20href="https://www.semanticscholar.org/paper/Three-dimensional-h-adaptivity-for-the-multigroup-Wang-Bangerth/900592e8e891d9b888d59a69ec58bf2bbda56b4b">here</a>. 21</i> 22 23<br> 24 25 26<a name="Intro"></a> <h1>Introduction</h1> 27In this example, we intend to solve the multigroup diffusion approximation of 28the neutron transport equation. Essentially, the way to view this is as follows: In a 29nuclear reactor, neutrons are speeding around at different energies, get 30absorbed or scattered, or start a new fission 31event. If viewed at long enough length scales, the movement of neutrons can be 32considered a diffusion process. 33 34A mathematical description of this would group neutrons into energy bins, and 35consider the balance equations for the neutron fluxes in each of these 36bins, or energy groups. The scattering, absorption, and fission events would 37then be operators within the diffusion equation describing the neutron 38fluxes. Assume we have energy groups $g=1,\ldots,G$, where by convention we 39assume that the neutrons with the highest energy are in group 1 and those with 40the lowest energy in group $G$. Then the neutron flux of each group satisfies the 41following equations: 42@f{eqnarray*} 43\frac 1{v_g}\frac{\partial \phi_g(x,t)}{\partial t} 44&=& 45\nabla \cdot(D_g(x) \nabla \phi_g(x,t)) 46- 47\Sigma_{r,g}(x)\phi_g(x,t) 48\\ 49&& \qquad 50+ 51\chi_g\sum_{g'=1}^G\nu\Sigma_{f,g'}(x)\phi_{g'}(x,t) 52+ 53\sum_{g'\ne g}\Sigma_{s,g'\to g}(x)\phi_{g'}(x,t) 54+ 55s_{\mathrm{ext},g}(x,t) 56@f} 57augmented by appropriate boundary conditions. Here, $v_g$ is the velocity of 58neutrons within group $g$. In other words, the change in 59time in flux of neutrons in group $g$ is governed by the following 60processes: 61<ul> 62<li> Diffusion $\nabla \cdot(D_g(x) \nabla \phi_g(x,t))$. Here, $D_g$ is the 63 (spatially variable) diffusion coefficient. 64<li> Absorption $\Sigma_{r,g}(x)\phi_g(x,t)$ (note the 65 negative sign). The coefficient $\Sigma_{r,g}$ is called the <i>removal 66 cross section</i>. 67<li> Nuclear fission $\chi_g\sum_{g'=1}^G\nu\Sigma_{f,g'}(x)\phi_{g'}(x,t)$. 68 The production of neutrons of energy $g$ is 69 proportional to the flux of neutrons of energy $g'$ times the 70 probability $\Sigma_{f,g'}$ that neutrons of energy $g'$ cause a fission 71 event times the number $\nu$ of neutrons produced in each fission event 72 times the probability that a neutron produced in this event has energy 73 $g$. $\nu\Sigma_{f,g'}$ is called the <i>fission cross section</i> and 74 $\chi_g$ the <i>fission spectrum</i>. We will denote the term 75 $\chi_g\nu\Sigma_{f,g'}$ as the <i>fission distribution cross 76 section</i> in the program. 77<li> Scattering $\sum_{g'\ne g}\Sigma_{s,g'\to g}(x)\phi_{g'}(x,t)$ 78 of neutrons of energy $g'$ producing neutrons 79 of energy $g$. $\Sigma_{s,g'\to g}$ is called the <i>scattering cross 80 section</i>. The case of elastic, in-group scattering $g'=g$ exists, too, but 81 we subsume this into the removal cross section. The case $g'<g$ is called 82 down-scattering, since a neutron loses energy in such an event. On the 83 other hand, $g'>g$ corresponds to up-scattering: a neutron gains energy in 84 a scattering event from the thermal motion of the atoms surrounding it; 85 up-scattering is therefore only an important process for neutrons with 86 kinetic energies that are already on the same order as the thermal kinetic 87 energy (i.e. in the sub $eV$ range). 88<li> An extraneous source $s_{\mathrm{ext},g}$. 89</ul> 90 91For realistic simulations in reactor analysis, one may want to split the 92continuous spectrum of neutron energies into many energy groups, often up to 100. 93However, if neutron energy spectra are known well enough for some type of 94reactor (for example Pressurized Water Reactors, PWR), it is possible to obtain 95satisfactory results with only 2 energy groups. 96 97In the program shown in this tutorial program, we provide the structure to 98compute with as many energy groups as desired. However, to keep computing 99times moderate and in order to avoid tabulating hundreds of coefficients, we 100only provide the coefficients for above equations for a two-group simulation, 101i.e. $g=1,2$. We do, however, consider a realistic situation by assuming that 102the coefficients are not constant, but rather depend on the materials that are 103assembled into reactor fuel assemblies in rather complicated ways (see 104below). 105 106 107<h3>The eigenvalue problem</h3> 108 109If we consider all energy groups at once, we may write above equations in the 110following operator form: 111@f{eqnarray*} 112\frac 1v \frac{\partial \phi}{\partial t} 113= 114-L\phi 115+ 116F\phi 117+ 118X\phi 119+ 120s_{\mathrm{ext}}, 121@f} 122where $L,F,X$ are sinking, fission, and scattering operators, 123respectively. $L$ here includes both the diffusion and removal terms. Note 124that $L$ is symmetric, whereas $F$ and $X$ are not. 125 126It is well known that this equation admits a stable solution if all 127eigenvalues of the operator $-L+F+X$ are negative. This can be readily seen by 128multiplying the equation by $\phi$ and integrating over the domain, leading to 129@f{eqnarray*} 130 \frac 1{2v} \frac{\partial}{\partial t} \|\phi\|^2 = ((-L+F+X)\phi,\phi). 131@f} 132Stability means that the solution does not grow, i.e. we want the left hand 133side to be less than zero, which is the case if the eigenvalues of the 134operator on the right are all negative. For obvious reasons, it is 135not very desirable if a nuclear reactor produces neutron fluxes that grow 136exponentially, so eigenvalue analyses are the bread-and-butter of nuclear 137engineers. The main point of the program is therefore to consider the 138eigenvalue problem 139@f{eqnarray*} 140 (L-F-X) \phi = \lambda \phi, 141@f} 142where we want to make sure that all eigenvalues are positive. Note that $L$, 143being the diffusion operator plus the absorption (removal), is positive 144definite; the condition that all eigenvalues are positive therefore means that 145we want to make sure that fission and inter-group scattering are weak enough 146to not shift the spectrum into the negative. 147 148In nuclear engineering, one typically looks at a slightly different 149formulation of the eigenvalue problem. To this end, we do not just multiply 150with $\phi$ and integrate, but rather multiply with $\phi(L-X)^{-1}$. We then 151get the following evolution equation: 152@f{eqnarray*} 153 \frac 1{2v} \frac{\partial}{\partial t} \|\phi\|^2_{(L-X)^{-1}} = ((L-X)^{-1}(-L+F+X)\phi,\phi). 154@f} 155Stability is then guaranteed if the eigenvalues of the following problem are 156all negative: 157@f{eqnarray*} 158 (L-X)^{-1}(-L+F+X)\phi = \lambda_F \phi, 159@f} 160which is equivalent to the eigenvalue problem 161@f{eqnarray*} 162 (L-X)\phi = \frac 1{\lambda_F+1} F \phi. 163@f} 164The typical formulation in nuclear engineering is to write this as 165@f{eqnarray*} 166 (L-X) \phi = \frac 1{k_{\mathrm{eff}}} F \phi, 167@f} 168where $k_{\mathrm{eff}}=\frac 1{\lambda^F+1}$. 169Intuitively, $k_{\mathrm{eff}}$ is something like the multiplication 170factor for neutrons per typical time scale and should be less than or equal to 171one for stable operation of a reactor: if it is less than one, the chain reaction will 172die down, whereas nuclear bombs for example have a $k$-eigenvalue larger than 173one. A stable reactor should have $k_{\mathrm{eff}}=1$. 174 175For those who wonder how this can be achieved in practice without 176inadvertently getting slightly larger than one and triggering a nuclear bomb: 177first, fission processes happen on different time scales. While most neutrons 178are released very quickly after a fission event, a small number of neutrons 179are only released by daughter nuclei after several further decays, up to 10-60 180seconds after the fission was initiated. If one is therefore slightly beyond 181$k_{\mathrm{eff}}=1$, one therefore has many seconds to react until all the 182neutrons created in fission re-enter the fission cycle. Nevertheless, control 183rods in nuclear reactors absorbing neutrons -- and therefore reducing 184$k_{\mathrm{eff}}$ -- are designed in such a way that they are all the way in 185the reactor in at most 2 seconds. 186 187One therefore has on the order of 10-60 seconds to regulate the nuclear reaction 188if $k_{\mathrm{eff}}$ should be larger than one for some time, as indicated by 189a growing neutron flux. Regulation can be achieved by continuously monitoring 190the neutron flux, and if necessary increase or reduce neutron flux by moving 191neutron-absorbing control rods a few millimeters into or out of the 192reactor. On a longer scale, the water cooling the reactor contains boron, a 193good neutron absorber. Every few hours, boron concentrations are adjusted by 194adding boron or diluting the coolant. 195 196Finally, some of the absorption and scattering reactions have some 197stability built in; for example, higher neutron fluxes result in locally 198higher temperatures, which lowers the density of water and therefore reduces 199the number of scatterers that are necessary to moderate neutrons from high to 200low energies before they can start fission events themselves. 201 202In this tutorial program, we solve above $k$-eigenvalue problem for two energy 203groups, and we are looking for the largest multiplication factor 204$k_{\mathrm{eff}}$, which is proportional to the inverse of the minimum 205eigenvalue plus one. To solve the eigenvalue problem, we generally 206use a modified version of the <i>inverse power method</i>. The algorithm looks 207like this: 208 209<ol> 210<li> Initialize $\phi_g$ and $k_{\mathrm{eff}}$ with $\phi_g^{(0)}$ 211 and $k_{\mathrm{eff}}^{(0)}$ and let $n=1$. 212 213<li> Define the so-called <i>fission source</i> by 214 @f{eqnarray*} 215 s_f^{(n-1)}(x) 216 = 217 \frac{1}{k_{\mathrm{eff}}^{(n-1)}} 218 \sum_{g'=1}^G\nu\Sigma_{f,g'}(x)\phi_{g'}^{(n-1)}(x). 219 @f} 220 221<li> Solve for all group fluxes $\phi_g,g=1,\ldots,G$ using 222 @f{eqnarray*} 223 -\nabla \cdot D_g\nabla \phi_g^{(n)} 224 + 225 \Sigma_{r,g}\phi_g^{(n)} 226 = 227 \chi_g s_f^{(n-1)} 228 + 229 \sum_{g'< g} \Sigma_{s,g'\to g} \phi_{g'}^{(n)} 230 + 231 \sum_{g'> g}\Sigma_{s,g'\to g}\phi_{g'}^{(n-1)}. 232 @f} 233 234<li> Update 235 @f{eqnarray*} 236 k_{\mathrm{eff}}^{(n)} 237 = 238 \sum_{g'=1}^G 239 \int_{\Omega}\nu\Sigma_{f,g'}(x) 240 \phi_{g'}^{(n)}(x)dx. 241 @f} 242 243<li> Compare $k_{\mathrm{eff}}^{(n)}$ with $k_{\mathrm{eff}}^{(n-1)}$. 244 If the change greater than a prescribed tolerance then set $n=n+1$ repeat 245 the iteration starting at step 2, otherwise end the iteration. 246</ol> 247 248Note that in this scheme, we do not solve group fluxes exactly in each power 249iteration, but rather consider previously compute $\phi_{g'}^{(n)}$ only for 250down-scattering events $g'<g$. Up-scattering is only treated by using old 251iterators $\phi_{g'}^{(n-1)}$, in essence assuming that the scattering 252operator is triangular. This is physically motivated since up-scattering does 253not play a too important role in neutron scattering. In addition, practices 254shows that the inverse power iteration is stable even using this 255simplification. 256 257Note also that one can use lots of extrapolation techniques to accelerate the 258power iteration laid out above. However, none of these are implemented in this 259example. 260 261 262<h3>Meshes and mesh refinement</h3> 263 264One may wonder whether it is appropriate to solve for the solutions of the 265individual energy group equations on the same meshes. The question boils down 266to this: will $\phi_g$ and $\phi_{g'}$ have similar smoothness properties? If 267this is the case, then it is appropriate to use the same mesh for the two; a 268typical application could be chemical combustion, where typically the 269concentrations of all or most chemical species change rapidly within the flame 270front. As it turns out, and as will be apparent by looking at the 271graphs shown in the results section of this tutorial program, this isn't the 272case here, however: since the diffusion coefficient is different for different 273energy groups, fast neutrons (in bins with a small group number $g$) have a very 274smooth flux function, whereas slow neutrons (in bins with a large group 275number) are much more affected by the local material properties and have a 276correspondingly rough solution if the coefficient are rough as in the case we 277compute here. Consequently, we will want to use different meshes to compute 278each energy group. 279 280This has two implications that we will have to consider: First, we need to 281find a way to refine the meshes individually. Second, assembling the source 282terms for the inverse power iteration, where we have to integrate solution 283$\phi_{g'}^{(n)}$ defined on mesh $g'$ against the shape functions defined on 284mesh $g$, becomes a much more complicated task. 285 286 287<h4>Mesh refinement</h4> 288 289We use the usual paradigm: solve on a given mesh, then evaluate an error 290indicator for each cell of each mesh we have. Because it is so convenient, we 291again use the a posteriori error estimator by Kelly, Gago, Zienkiewicz 292and Babuska which approximates the error per cell by integrating the jump of 293the gradient of the solution along the faces of each cell. Using this, we 294obtain indicators 295@f{eqnarray*} 296\eta_{g,K}, \qquad g=1,2,\ldots,G,\qquad K\in{\cal T}_g, 297@f} 298where ${\cal T}_g$ is the triangulation used in the solution of 299$\phi_g$. The question is what to do with this. For one, it is clear that 300refining only those cells with the highest error indicators might lead to bad 301results. To understand this, it is important to realize that $\eta_{g,K}$ 302scales with the second derivative of $\phi_g$. In other words, if we have two 303energy groups $g=1,2$ whose solutions are equally smooth but where one is 304larger by a factor of 10,000, for example, then only the cells of that mesh 305will be refined, whereas the mesh for the solution of small magnitude will 306remain coarse. This is probably not what one wants, since we can consider both 307components of the solution equally important. 308 309In essence, we would therefore have to scale $\eta_{g,K}$ by an importance 310factor $z_g$ that says how important it is to resolve $\phi_g$ to any given 311accuracy. Such important factors can be computed using duality techniques 312(see, for example, the step-14 tutorial program, and the 313reference to the book by Bangerth and Rannacher cited there). We won't go 314there, however, and simply assume that all energy groups are equally 315important, and will therefore normalize the error indicators $\eta_{g,K}$ for 316group $g$ by the maximum of the solution $\phi_g$. We then refine the cells 317whose errors satisfy 318@f{eqnarray*} 319 \frac{\eta_{g,K}}{\|\phi_g\|_\infty} 320 > 321 \alpha_1 322 \displaystyle{\max_{\begin{matrix}1\le g\le G \\ K\in {\cal T}_g\end{matrix}} 323 \frac{\eta_{g,K}}{\|\phi_g\|_\infty}} 324@f} 325and coarsen the cells where 326@f{eqnarray*} 327 \frac{\eta_{g,K}}{\|\phi_g\|_\infty} 328 < 329 \alpha_2 330 \displaystyle{\max_{\begin{matrix}1\le g\le G \\ K\in {\cal T}_g\end{matrix}} 331 \frac{\eta_{g,K}}{\|\phi_g\|_\infty}}. 332@f} 333We chose $\alpha_1=0.3$ and $\alpha_2=0.01$ in the code. Note that this will, 334of course, lead to different meshes for the different energy groups. 335 336The strategy above essentially means the following: If for energy group $g$ 337there are many cells $K\in {\cal T}_g$ on which the error is large, for 338example because the solution is globally very rough, then many cells will be 339above the threshold. On the other hand, if there are a few cells with large 340and many with small errors, for example because the solution is overall rather 341smooth except at a few places, then only the few cells with large errors will 342be refined. Consequently, the strategy allows for meshes that track the global 343smoothness properties of the corresponding solutions rather well. 344 345 346<h4>Assembling terms on different meshes</h4> 347 348As pointed out above, the multigroup refinement strategy results in 349different meshes for the different solutions $\phi_g$. So what's the problem? 350In essence it goes like this: in step 3 of the eigenvalue iteration, we have 351form the weak form for the equation to compute $\phi_g^{(n)}$ as usual by 352multiplication with test functions $\varphi_g^i$ defined on the mesh for 353energy group $g$; in the process, we have to 354compute the right hand side vector that contains terms of the following form: 355@f{eqnarray*} 356 F_i = \int_\Omega f(x) \varphi_g^i(x) \phi_{g'}(x) \ dx, 357@f} 358where $f(x)$ is one of the coefficient functions $\Sigma_{s,g'\to g}$ or 359$\nu\chi_g\Sigma_{f,g'}$ used in the right hand side 360of eigenvalue equation. The difficulty now is that $\phi_{g'}$ is defined on 361the mesh for energy group $g'$, i.e. it can be expanded as 362$\phi_{g'}(x)=\sum_j\phi_{g'}^j \varphi_{g'}^j(x)$, with basis functions 363$\varphi_{g'}^j(x)$ defined on mesh $g'$. The contribution to the right hand 364side can therefore be written as 365@f{eqnarray*} 366 F_i = \sum_j \left\{\int_\Omega f(x) \varphi_g^i(x) \varphi_{g'}^j(x) 367 \ dx \right\} \phi_{g'}^j , 368@f} 369On the other hand, the test functions $\varphi_g^i(x)$ are defined on mesh 370$g$. This means that we can't just split the integral $\Omega$ into integrals 371over the cells of either mesh $g$ or $g'$, since the respectively other basis 372functions may not be defined on these cells. 373 374The solution to this problem lies in the fact that both the meshes for $g$ and 375$g'$ are derived by adaptive refinement from a common coarse mesh. We can 376therefore always find a set of cells, which we denote by ${\cal T}_g \cap 377{\cal T}_{g'}$, that satisfy the following conditions: 378<ul> 379<li> the union of the cells covers the entire domain, and 380<li> a cell $K \in {\cal T}_g \cap {\cal T}_{g'}$ is active on at least 381 one of the two meshes. 382</ul> 383A way to construct this set is to take each cell of coarse mesh and do the 384following steps: (i) if the cell is active on either ${\cal T}_g$ or 385${\cal T}_{g'}$, then add this cell to the set; (ii) otherwise, i.e. if 386this cell has children on both meshes, then do step (i) for each of the 387children of this cell. In fact, deal.II has a function 388GridTools::get_finest_common_cells that computes exactly this set 389of cells that are active on at least one of two meshes. 390 391With this, we can write above integral as follows: 392@f{eqnarray*} 393 F_i 394 = 395 \sum_{K \in {\cal T}_g \cap {\cal T}_{g'}} 396 \sum_j \left\{\int_K f(x) \varphi_g^i(x) \varphi_{g'}^j(x) 397 \ dx \right\} \phi_{g'}^j. 398@f} 399 In the code, we 400compute the right hand side in the function 401<code>NeutronDiffusionProblem::assemble_rhs</code>, where (among other things) we 402loop over the set of common most refined cells, calling the function 403<code>NeutronDiffusionProblem::assemble_common_cell</code> on each pair of 404these cells. 405 406By construction, there are now three cases to be considered: 407<ol> 408<li> The cell $K$ is active on both meshes, i.e. both the basis 409 functions $\varphi_g^i$ as well as $\varphi_{g'}^j$ are defined on $K$. 410<li> The cell $K$ is active on mesh $g$, but not $g'$, i.e. the 411 $\varphi_g^i$ are defined on $K$, whereas the $\varphi_{g'}^j$ are defined 412 on children of $K$. 413<li> The cell $K$ is active on mesh $g'$, but not $g$, with opposite 414 conclusions than in (ii). 415</ol> 416 417To compute the right hand side above, we then need to have different code for 418these three cases, as follows: 419<ol> 420<li> If the cell $K$ is active on both meshes, then we can directly 421 evaluate the integral. In fact, we don't even have to bother with the basis 422 functions $\varphi_{g'}$, since all we need is the values of $\phi_{g'}$ at 423 the quadrature points. We can do this using the 424 FEValues::get_function_values function. This is done directly in 425 the <code>NeutronDiffusionProblem::assemble_common_cell</code> function. 426 427<li> If the cell $K$ is active on mesh $g$, but not $g'$, then the 428 basis functions $\varphi_{g'}^j$ are only defined either on the children 429 $K_c,0\le c<2^{\texttt{dim}}$, or on children of these children if cell $K$ 430 is refined more than once on mesh $g'$. 431 432 Let us assume for a second that $K$ is only once more refined on mesh $g'$ 433 than on mesh $g$. Using the fact that we use embedded finite element spaces 434 where each basis function on one mesh can be written as a linear combination 435 of basis functions on the next refined mesh, we can expand the restriction 436 of $\phi_g^i$ to child cell $K_c$ into the basis functions defined on that 437 child cell (i.e. on cells on which the basis functions $\varphi_{g'}^l$ are 438 defined): 439 @f{eqnarray*} 440 \phi_g^i|_{K_c} = B_c^{il} \varphi_{g'}^l|_{K_c}. 441 @f} 442 Here, and in the following, summation over indices appearing twice is 443 implied. The matrix $B_c$ is the matrix that interpolated data from a cell 444 to its $c$-th child. 445 446 Then we can write the contribution of cell $K$ to the right hand side 447 component $F_i$ as 448 @f{eqnarray*} 449 F_i|_K 450 &=& 451 \left\{ \int_K f(x) \varphi_g^i(x) \varphi_{g'}^j(x) 452 \ dx \right\} \phi_{g'}^j 453 \\ 454 &=& 455 \left\{ 456 \sum_{0\le c<2^{\texttt{dim}}} 457 B_c^{il} \int_{K_c} f(x) \varphi_{g'}^l(x) \varphi_{g'}^j(x) 458 \ dx \right\} \phi_{g'}^j. 459 @f} 460 In matrix notation, this can be written as 461 @f{eqnarray*} 462 F_i|_K 463 = 464 \sum_{0\le c<2^{\texttt{dim}}} 465 F_i|_{K_c}, 466 \qquad 467 \qquad 468 F_i|_{K_c} = B_c^{il} M_{K_c}^{lj} \phi_{g'}^j 469 = (B_c M_{K_c})^{ij} \phi_{g'}^j, 470 @f} 471 where $M_{K_c}^{lj}=\int_{K_c} f(x) \varphi_{g'}^l(x) \varphi_{g'}^j(x)$ is 472 the weighted mass matrix on child $c$ of cell $K$. 473 474 The next question is what happens if a child $K_c$ of $K$ is not 475 active. Then, we have to apply the process recursively, i.e. we have to 476 interpolate the basis functions $\varphi_g^i$ onto child $K_c$ of $K$, then 477 onto child $K_{cc'}$ of that cell, onto child $K_{cc'c''}$ of that one, etc, 478 until we find an active cell. We then have to sum up all the contributions 479 from all the children, grandchildren, etc, of cell $K$, with contributions 480 of the form 481 @f{eqnarray*} 482 F_i|_{K_{cc'}} = (B_cB_{c'} M_{K_{cc'}})^{ij} \phi_{g'}^j, 483 @f} 484 or 485 @f{eqnarray*} 486 F_i|_{K_{cc'c''}} = (B_c B_{c'} B_{c''}M_{K_{cc'c''}})^{ij} 487 \phi_{g'}^j, 488 @f} 489 etc. We do this process recursively, i.e. if we sit on cell $K$ and see that 490 it has children on grid $g'$, then we call a function 491 <code>assemble_case_2</code> with an identity matrix; the function will 492 multiply it's argument from the left with the prolongation matrix; if the 493 cell has further children, it will call itself with this new matrix, 494 otherwise it will perform the integration. 495 496<li> The last case is where $K$ is active on mesh $g'$ but not mesh 497 $g$. In that case, we have to express basis function $\varphi_{g'}^j$ in 498 terms of the basis functions defined on the children of cell $K$, rather 499 than $\varphi_g^i$ as before. This of course works in exactly the same 500 way. If the children of $K$ are active on mesh $g$, then 501 leading to the expression 502 @f{eqnarray*} 503 F_i|_K 504 &=& 505 \left\{ \int_K f(x) \varphi_g^i(x) \varphi_{g'}^j(x) 506 \ dx \right\} \phi_{g'}^j 507 \\ 508 &=& 509 \left\{ 510 \sum_{0\le c<2^{\texttt{dim}}} 511 \int_{K_c} f(x) \varphi_g^i(x) B_c^{jl} \varphi_{g}^l(x) 512 \ dx \right\} \phi_{g'}^j. 513 @f} 514 In matrix notation, this expression now reads as 515 @f{eqnarray*} 516 F_i|_K 517 = 518 \sum_{0\le c<2^{\texttt{dim}}} 519 F_i|_{K_c}, 520 \qquad 521 \qquad 522 F_i|_{K_c} = M_{K_c}^{il} B_c^{jl} \phi_{g'}^j 523 = 524 (M_{K_c} B_c^T)^{ij} \phi_{g'}^j, 525 @f} 526 and correspondingly for cases where cell $K$ is refined more than once on 527 mesh $g$: 528 @f{eqnarray*} 529 F_i|_{K_{cc'}} = (M_{K_{cc'}} B_{c'}^T B_c^T)^{ij} \phi_{g'}^j, 530 @f} 531 or 532 @f{eqnarray*} 533 F_i|_{K_{cc'c''}} = (M_{K_{cc'c''}} B_{c''}^T B_{c'}^T B_c^T)^{ij} 534 \phi_{g'}^j, 535 @f} 536 etc. In other words, the process works in exactly the same way as before, 537 except that we have to take the transpose of the prolongation matrices and 538 need to multiply it to the mass matrix from the other side. 539</ol> 540 541 542The expressions for cases (ii) and (iii) can be understood as repeatedly 543interpolating either the left or right basis functions in the scalar product 544$(f \varphi_g^i, \varphi_{g'}^j)_K$ onto child cells, and then finally 545forming the inner product (the mass matrix) on the final cell. To make the 546symmetry in these cases more obvious, we can write them like this: for case 547(ii), we have 548@f{eqnarray*} 549 F_i|_{K_{cc'\cdots c^{(k)}}} 550 = [B_c B_{c'} \cdots B_{c^{(k)}} M_{K_{cc'\cdots c^{(k)}}}]^{ij} 551 \phi_{g'}^j, 552@f} 553whereas for case (iii) we get 554@f{eqnarray*} 555 F_i|_{K_{cc'\cdots c^{(k)}}} 556 = [(B_c B_{c'} \cdots B_{c^{(k)}} M_{K_{cc'\cdots c^{(k)}}})^T]^{ij} 557 \phi_{g'}^j, 558@f} 559 560 561 562<h3>Description of the test case</h3> 563 564A nuclear reactor core is composed of different types of assemblies. An 565assembly is essentially the smallest unit that can be moved in and out of a 566reactor, and is usually rectangular or square. However, assemblies are not 567fixed units, as they are assembled from a complex lattice of different fuel 568rods, control rods, and instrumentation elements that are held in place 569relative to each other by spacers that are permanently attached to the rods. 570To make things more complicated, there are different kinds of assemblies that 571are used at the same time in a reactor, where assemblies differ in the type 572and arrangement of rods they are made up of. 573 574Obviously, the arrangement of assemblies as well as the arrangement of rods 575inside them affect the distribution of neutron fluxes in the reactor (a fact 576that will be obvious by looking at the solution shown below in the results 577sections of this program). Fuel rods, for example, differ from each other in 578the enrichment of U-235 or Pu-239. Control rods, on the other hand, have zero 579fission, but nonzero scattering and absorption cross sections. 580 581This whole arrangement would make the description or spatially dependent 582material parameters very complicated. It will not become much simpler, but we 583will make one approximation: we merge the volume inhabited by each cylindrical 584rod and the surrounding water into volumes of quadratic cross section into 585so-called `pin cells' for which homogenized material data are obtained with 586nuclear database and knowledge of neutron spectrum. The homogenization makes 587all material data piecewise constant on the solution domain for a reactor with 588fresh fuel. Spatially dependent material parameters are then looked up for the 589quadratic assembly in which a point is located, and then for the quadratic pin 590cell within this assembly. 591 592In this tutorial program, we simulate a quarter of a reactor consisting of $4 593\times 4$ assemblies. We use symmetry (Neumann) boundary conditions to reduce 594the problem to one quarter of the domain, and consequently only simulate a 595$2\times 2$ set of assemblies. Two of them will be UO${}_2$ fuel, the other 596two of them MOX fuel. Each of these assemblies consists of $17\times 17$ rods 597of different compositions. In total, we therefore create a $34\times 34$ 598lattice of rods. To make things simpler later on, we reflect this fact by 599creating a coarse mesh of $34\times 34$ cells (even though the domain is a 600square, for which we would usually use a single cell). In deal.II, each cell 601has a <code>material_id</code> which one may use to associated each cell with a 602particular number identifying the material from which this cell's volume is 603made of; we will use this material ID to identify which of the 8 different 604kinds of rods that are used in this testcase make up a particular cell. Note 605that upon mesh refinement, the children of a cell inherit the material ID, 606making it simple to track the material even after mesh refinement. 607 608The arrangement of the rods will be clearly visible in the images shown in 609the results section. The cross sections for materials and for both energy 610groups are taken from a OECD/NEA benchmark problem. The detailed configuration 611and material data is given in the code. 612 613 614<h3>What the program does (and how it does that)</h3> 615 616As a coarse overview of what exactly the program does, here is the basic 617layout: starting on a coarse mesh that is the same for each energy group, we 618compute inverse eigenvalue iterations to compute the $k$-eigenvalue on a given 619set of meshes. We stop these iterations when the change in the eigenvalue 620drops below a certain tolerance, and then write out the meshes and solutions 621for each energy group for inspection by a graphics program. Because the meshes 622for the solutions are different, we have to generate a separate output file 623for each energy group, rather than being able to add all energy group 624solutions into the same file. 625 626After this, we evaluate the error indicators as explained in one of the sections 627above for each of the meshes, and refine and coarsen the cells of each mesh 628independently. Since the eigenvalue iterations are fairly expensive, we don't 629want to start all over on the new mesh; rather, we use the SolutionTransfer 630class to interpolate the solution on the previous mesh to the next one upon 631mesh refinement. A simple experiment will convince you that this is a lot 632cheaper than if we omitted this step. After doing so, we resume our eigenvalue 633iterations on the next set of meshes. 634 635The program is controlled by a parameter file, using the ParameterHandler 636class. We will show a 637parameter file in the results section of this tutorial. For the moment suffice 638it to say that it controls the polynomial degree of the finite elements used, 639the number of energy groups (even though all that is presently implemented are 640the coefficients for a 2-group problem), the tolerance where to stop the 641inverse eigenvalue iteration, and the number of refinement cycles we will do. 642