|
4 | 4 |
|
5 | 5 | #include <fmt/core.h> |
6 | 6 |
|
| 7 | +#include "openmc/constants.h" |
7 | 8 | #include "openmc/surface.h" |
8 | 9 |
|
9 | 10 | namespace openmc { |
@@ -104,32 +105,58 @@ TranslationalPeriodicBC::handle_particle(Particle& p, const Surface& surf) const |
104 | 105 | RotationalPeriodicBC::RotationalPeriodicBC(int i_surf, int j_surf) |
105 | 106 | : PeriodicBC(i_surf, j_surf) |
106 | 107 | { |
| 108 | + Surface& surf1 {*model::surfaces[i_surf_]}; |
| 109 | + Surface& surf2 {*model::surfaces[j_surf_]}; |
| 110 | + |
| 111 | + // The following blocks will resolve the type of each surface and compute the |
| 112 | + // appropriate rotation angle |
| 113 | + |
| 114 | + if (const auto* xplane = dynamic_cast<const SurfaceXPlane*>(&surf1)) { |
| 115 | + if (const auto* yplane = dynamic_cast<const SurfaceYPlane*>(&surf2)) { |
| 116 | + angle_ = 0.5 * PI; |
| 117 | + } |
| 118 | + } else if (const auto* yplane = dynamic_cast<const SurfaceYPlane*>(&surf1)) { |
| 119 | + if (const auto* xplane = dynamic_cast<const SurfaceXPlane*>(&surf2)) { |
| 120 | + angle_ = -0.5 * PI; |
| 121 | + } |
| 122 | + } |
107 | 123 | } |
108 | 124 |
|
109 | 125 | void |
110 | 126 | RotationalPeriodicBC::handle_particle(Particle& p, const Surface& surf) const |
111 | 127 | { |
112 | | - // Get a pointer of the first surface downcast to PeriodicSurface |
113 | | - auto surf_p = dynamic_cast<const PeriodicSurface*>(&surf); |
114 | | - |
115 | | - // Get a pointer to the partner PeriodicSurface |
116 | | - auto other = |
117 | | - surf.id_ == model::surfaces[i_surf_]->id_ ? |
118 | | - dynamic_cast<const PeriodicSurface*>(model::surfaces[j_surf_].get()) : |
119 | | - dynamic_cast<const PeriodicSurface*>(model::surfaces[i_surf_].get()); |
120 | | - |
121 | | - // Compute the new particle location and direction |
122 | | - Position r {p.r()}; |
123 | | - Direction u {p.u()}; |
124 | | - bool rotational = other->periodic_translate(surf_p, r, u); |
125 | | - |
126 | | - // Pick the particle's new surface |
127 | | - // TODO: off-by-one |
128 | | - int new_surface = rotational ? |
129 | | - surf_p->i_periodic_ + 1 : |
130 | | - ((p.surface_ > 0) ? surf_p->i_periodic_ + 1 : -(surf_p->i_periodic_ + 1)); |
131 | | - |
132 | | - p.cross_periodic_bc(surf, r, u, new_surface); |
| 128 | + // TODO: off-by-one on surface indices throughout this function. |
| 129 | + int i_particle_surf = std::abs(p.surface_) - 1; |
| 130 | + |
| 131 | + // Figure out which of the two BC surfaces were struck to figure out if a |
| 132 | + // forward or backward rotation is required. Also specify the new surface. |
| 133 | + double theta; |
| 134 | + int new_surface; |
| 135 | + if (i_particle_surf == i_surf_) { |
| 136 | + theta = -angle_; |
| 137 | + new_surface = p.surface_ > 0 ? -(j_surf_ + 1) : j_surf_ + 1; |
| 138 | + } else if (i_particle_surf == j_surf_) { |
| 139 | + theta = angle_; |
| 140 | + new_surface = p.surface_ > 0 ? -(i_surf_ + 1) : i_surf_ + 1; |
| 141 | + } else { |
| 142 | + throw std::runtime_error("Called BoundaryCondition::handle_particle after " |
| 143 | + "hitting a surface, but that surface is not recognized by the BC."); |
| 144 | + } |
| 145 | + |
| 146 | + // Rotate the particle's position and direction about the z-axis. |
| 147 | + Position r = p.r(); |
| 148 | + Direction u = p.u(); |
| 149 | + Position new_r = { |
| 150 | + std::cos(theta)*r[0] - std::sin(theta)*r[1], |
| 151 | + std::sin(theta)*r[0] + std::cos(theta)*r[1], |
| 152 | + r[2]}; |
| 153 | + Direction new_u = { |
| 154 | + std::cos(theta)*u[0] - std::sin(theta)*u[1], |
| 155 | + std::sin(theta)*u[0] + std::cos(theta)*u[1], |
| 156 | + u[2]}; |
| 157 | + |
| 158 | + // Pass the new location, direction, and surface to the particle. |
| 159 | + p.cross_periodic_bc(surf, new_r, new_u, new_surface); |
133 | 160 | } |
134 | 161 |
|
135 | 162 | } // namespace openmc |
0 commit comments