66#include " openmc/constants.h"
77#include " openmc/error.h"
88#include " openmc/mesh.h"
9+ #include " openmc/position.h"
910#include " openmc/xml_interface.h"
1011
1112namespace openmc {
@@ -30,6 +31,10 @@ void MeshFilter::from_xml(pugi::xml_node node)
3031 if (check_for_node (node, " translation" )) {
3132 set_translation (get_node_array<double >(node, " translation" ));
3233 }
34+ // Read the rotation transform.
35+ if (check_for_node (node, " rotation" )) {
36+ set_rotation (get_node_array<double >(node, " rotation" ));
37+ }
3338}
3439
3540void MeshFilter::get_all_bins (
@@ -45,6 +50,12 @@ void MeshFilter::get_all_bins(
4550 last_r -= translation ();
4651 r -= translation ();
4752 }
53+ // apply rotation if present
54+ if (!rotation_.empty ()) {
55+ last_r = last_r.rotate (rotation_);
56+ r = r.rotate (rotation_);
57+ u = u.rotate (rotation_);
58+ }
4859
4960 if (estimator != TallyEstimator::TRACKLENGTH) {
5061 auto bin = model::meshes[mesh_]->get_bin (r);
@@ -65,6 +76,9 @@ void MeshFilter::to_statepoint(hid_t filter_group) const
6576 if (translated_) {
6677 write_dataset (filter_group, " translation" , translation_);
6778 }
79+ if (rotated_) {
80+ write_dataset (filter_group, " rotation" , rotation_);
81+ }
6882}
6983
7084std::string MeshFilter::text_label (int bin) const
@@ -93,6 +107,40 @@ void MeshFilter::set_translation(const double translation[3])
93107 this ->set_translation ({translation[0 ], translation[1 ], translation[2 ]});
94108}
95109
110+ void MeshFilter::set_rotation (const vector<double >& rot)
111+ {
112+ rotated_ = true ;
113+
114+ // Compute and store the inverse rotation matrix for the angles given.
115+ rotation_.clear ();
116+ rotation_.reserve (rot.size () == 9 ? 9 : 12 );
117+ if (rot.size () == 3 ) {
118+ double phi = -rot[0 ] * PI / 180.0 ;
119+ double theta = -rot[1 ] * PI / 180.0 ;
120+ double psi = -rot[2 ] * PI / 180.0 ;
121+ rotation_.push_back (std::cos (theta) * std::cos (psi));
122+ rotation_.push_back (-std::cos (phi) * std::sin (psi) +
123+ std::sin (phi) * std::sin (theta) * std::cos (psi));
124+ rotation_.push_back (std::sin (phi) * std::sin (psi) +
125+ std::cos (phi) * std::sin (theta) * std::cos (psi));
126+ rotation_.push_back (std::cos (theta) * std::sin (psi));
127+ rotation_.push_back (std::cos (phi) * std::cos (psi) +
128+ std::sin (phi) * std::sin (theta) * std::sin (psi));
129+ rotation_.push_back (-std::sin (phi) * std::cos (psi) +
130+ std::cos (phi) * std::sin (theta) * std::sin (psi));
131+ rotation_.push_back (-std::sin (theta));
132+ rotation_.push_back (std::sin (phi) * std::cos (theta));
133+ rotation_.push_back (std::cos (phi) * std::cos (theta));
134+
135+ // When user specifies angles, write them at end of vector
136+ rotation_.push_back (rot[0 ]);
137+ rotation_.push_back (rot[1 ]);
138+ rotation_.push_back (rot[2 ]);
139+ } else {
140+ std::copy (rot.begin (), rot.end (), std::back_inserter (rotation_));
141+ }
142+ }
143+
96144// ==============================================================================
97145// C-API functions
98146// ==============================================================================
@@ -201,4 +249,48 @@ extern "C" int openmc_mesh_filter_set_translation(
201249 return 0 ;
202250}
203251
252+ // ! Return the rotation matrix of a mesh filter
253+ extern " C" int openmc_mesh_filter_get_rotation (
254+ int32_t index, double rot[], size_t * n)
255+ {
256+ // Make sure this is a valid index to an allocated filter
257+ if (int err = verify_filter (index))
258+ return err;
259+
260+ // Check the filter type
261+ const auto & filter = model::tally_filters[index];
262+ if (filter->type () != FilterType::MESH) {
263+ set_errmsg (" Tried to get a rotation from a non-mesh filter." );
264+ return OPENMC_E_INVALID_TYPE;
265+ }
266+ // Get rotation from the mesh filter and set value
267+ auto mesh_filter = dynamic_cast <MeshFilter*>(filter.get ());
268+ *n = mesh_filter->rotation ().size ();
269+ std::memcpy (rot, mesh_filter->rotation ().data (),
270+ *n * sizeof (mesh_filter->rotation ()[0 ]));
271+ return 0 ;
272+ }
273+
274+ // ! Set the flattened rotation matrix of a mesh filter
275+ extern " C" int openmc_mesh_filter_set_rotation (
276+ int32_t index, const double rot[], size_t rot_len)
277+ {
278+ // Make sure this is a valid index to an allocated filter
279+ if (int err = verify_filter (index))
280+ return err;
281+
282+ const auto & filter = model::tally_filters[index];
283+ // Check the filter type
284+ if (filter->type () != FilterType::MESH) {
285+ set_errmsg (" Tried to set a rotation from a non-mesh filter." );
286+ return OPENMC_E_INVALID_TYPE;
287+ }
288+
289+ // Get a pointer to the filter and downcast
290+ auto mesh_filter = dynamic_cast <MeshFilter*>(filter.get ());
291+ std::vector<double > vec_rot (rot, rot + rot_len);
292+ mesh_filter->set_rotation (vec_rot);
293+ return 0 ;
294+ }
295+
204296} // namespace openmc
0 commit comments