@@ -158,56 +158,46 @@ void TranslationalPeriodicBC::handle_particle(
158158// RotationalPeriodicBC implementation
159159// ==============================================================================
160160
161- RotationalPeriodicBC::RotationalPeriodicBC (int i_surf, int j_surf)
161+ RotationalPeriodicBC::RotationalPeriodicBC (int i_surf, int j_surf, PeriodicAxis axis )
162162 : PeriodicBC(i_surf, j_surf)
163163{
164164 Surface& surf1 {*model::surfaces[i_surf_]};
165165 Surface& surf2 {*model::surfaces[j_surf_]};
166166
167- // Check the type of the first surface
168- bool surf1_is_xyplane;
169- if (const auto * ptr = dynamic_cast <const SurfaceXPlane*>(&surf1)) {
170- surf1_is_xyplane = true ;
171- } else if (const auto * ptr = dynamic_cast <const SurfaceYPlane*>(&surf1)) {
172- surf1_is_xyplane = true ;
173- } else if (const auto * ptr = dynamic_cast <const SurfacePlane*>(&surf1)) {
174- surf1_is_xyplane = false ;
175- } else {
176- throw std::invalid_argument (fmt::format (
177- " Surface {} is an invalid type for "
178- " rotational periodic BCs. Only x-planes, y-planes, or general planes "
179- " (that are perpendicular to z) are supported for these BCs." ,
180- surf1.id_ ));
167+ // below convention for right handed coordinate system
168+ switch (axis) {
169+ case x:
170+ zero_axis_idx = 0 ; // x component of plane must be zero
171+ axis_1_idx_ = 1 ; // y component independent
172+ axis_2_idx_ = 2 ; // z component dependent
173+ break ;
174+ case y:
175+ zero_axis_idx = 1 ; // y component of plane must be zero
176+ axis_1_idx_ = 2 ; // z component independent
177+ axis_2_idx_ = 0 ; // x component dependent
178+ break ;
179+ case z:
180+ zero_axis_idx = 2 ; // z component of plane must be zero
181+ axis_1_idx_ = 0 ; // x component independent
182+ axis_2_idx_ = 1 ; // y component dependent
183+ break ;
184+ default :
185+ throw std::invalid_argument (fmt::format (" You've specified an axis {} that is not x, y, or z." ),axis)
181186 }
182187
183- // Check the type of the second surface
184- bool surf2_is_xyplane;
185- if (const auto * ptr = dynamic_cast <const SurfaceXPlane*>(&surf2)) {
186- surf2_is_xyplane = true ;
187- } else if (const auto * ptr = dynamic_cast <const SurfaceYPlane*>(&surf2)) {
188- surf2_is_xyplane = true ;
189- } else if (const auto * ptr = dynamic_cast <const SurfacePlane*>(&surf2)) {
190- surf2_is_xyplane = false ;
191- } else {
192- throw std::invalid_argument (fmt::format (
193- " Surface {} is an invalid type for "
194- " rotational periodic BCs. Only x-planes, y-planes, or general planes "
195- " (that are perpendicular to z) are supported for these BCs." ,
196- surf2.id_ ));
197- }
198188
199189 // Compute the surface normal vectors and make sure they are perpendicular
200- // to the z- axis
190+ // to the correct axis
201191 Direction norm1 = surf1.normal ({0 , 0 , 0 });
202192 Direction norm2 = surf2.normal ({0 , 0 , 0 });
203- if (std::abs (norm1. z ) > FP_PRECISION) {
193+ if (std::abs (norm1[zero_axis_idx] ) > FP_PRECISION) {
204194 throw std::invalid_argument (fmt::format (
205195 " Rotational periodic BCs are only "
206196 " supported for rotations about the z-axis, but surface {} is not "
207197 " perpendicular to the z-axis." ,
208198 surf1.id_ ));
209199 }
210- if (std::abs (norm2. z ) > FP_PRECISION) {
200+ if (std::abs (norm2[zero_axis_idx] ) > FP_PRECISION) {
211201 throw std::invalid_argument (fmt::format (
212202 " Rotational periodic BCs are only "
213203 " supported for rotations about the z-axis, but surface {} is not "
@@ -231,15 +221,7 @@ RotationalPeriodicBC::RotationalPeriodicBC(int i_surf, int j_surf)
231221 surf2.id_ ));
232222 }
233223
234- // Compute the BC rotation angle. Here it is assumed that both surface
235- // normal vectors point inwards---towards the valid geometry region.
236- // Consequently, the rotation angle is not the difference between the two
237- // normals, but is instead the difference between one normal and one
238- // anti-normal. (An incident ray on one surface must be an outgoing ray on
239- // the other surface after rotation hence the anti-normal.)
240- double theta1 = std::atan2 (norm1.y , norm1.x );
241- double theta2 = std::atan2 (norm2.y , norm2.x ) + PI;
242- angle_ = theta2 - theta1;
224+ angle_ = compute_periodic_rotation (norm1[axis_2_idx_], norm1[axis_1_idx_], norm2[axis_2_idx_], norm2[axis_1_idx_])
243225
244226 // Warn the user if the angle does not evenly divide a circle
245227 double rem = std::abs (std::remainder ((2 * PI / angle_), 1.0 ));
@@ -251,6 +233,20 @@ RotationalPeriodicBC::RotationalPeriodicBC(int i_surf, int j_surf)
251233 }
252234}
253235
236+ float RotationalPeriodicBC::compute_periodic_rotation (
237+ float rise_1, float run_1, float rise_2, float run_2) const
238+ {
239+ // Compute the BC rotation angle. Here it is assumed that both surface
240+ // normal vectors point inwards---towards the valid geometry region.
241+ // Consequently, the rotation angle is not the difference between the two
242+ // normals, but is instead the difference between one normal and one
243+ // anti-normal. (An incident ray on one surface must be an outgoing ray on
244+ // the other surface after rotation hence the anti-normal.)
245+ double theta1 = std::atan2 (rise_1, run_1);
246+ double theta2 = std::atan2 (rise_2, run_2) + PI;
247+ return theta2 - theta1;
248+ }
249+
254250void RotationalPeriodicBC::handle_particle (
255251 Particle& p, const Surface& surf) const
256252{
@@ -279,9 +275,9 @@ void RotationalPeriodicBC::handle_particle(
279275 double cos_theta = std::cos (theta);
280276 double sin_theta = std::sin (theta);
281277 Position new_r = {
282- cos_theta * r. x - sin_theta * r. y , sin_theta * r. x + cos_theta * r. y , r. z };
278+ cos_theta * r[axis_1_idx_] - sin_theta * r[axis_2_idx_] , sin_theta * r[axis_1_idx_] + cos_theta * r[axis_2_idx_] , r[zero_axis_idx] };
283279 Direction new_u = {
284- cos_theta * u. x - sin_theta * u. y , sin_theta * u. x + cos_theta * u. y , u. z };
280+ cos_theta * u[axis_1_idx_] - sin_theta * u[axis_2_idx_] , sin_theta * u[axis_1_idx_] + cos_theta * u[axis_2_idx_] , u[zero_axis_idx] };
285281
286282 // Handle the effects of the surface albedo on the particle's weight.
287283 BoundaryCondition::handle_albedo (p, surf);
0 commit comments