LCOV - code coverage report
Current view: top level - src/utils - EulerAngles.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #32971 (54bef8) with base c6cf66 Lines: 22 47 46.8 %
Date: 2026-05-29 20:40:07 Functions: 3 6 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "libmesh/ignore_warnings.h"
      11             : #include "EulerAngles.h"
      12             : #include "MooseRandom.h"
      13             : 
      14         498 : EulerAngles::EulerAngles()
      15             : {
      16         498 :   phi1 = 0.0;
      17         498 :   Phi = 0.0;
      18         498 :   phi2 = 0.0;
      19         498 : }
      20             : 
      21      169016 : EulerAngles::EulerAngles(const Eigen::Quaternion<Real> & q)
      22             : {
      23      169016 :   phi1 = std::atan2((q.x() * q.z() + q.w() * q.y()), -(-q.w() * q.x() + q.y() * q.z())) *
      24             :          (180.0 / libMesh::pi);
      25             : 
      26             :   // avoid NAN value from sqrt(val) while computing Phi
      27      169016 :   auto val = 1.0 - std::pow(q.w() * q.w() - q.x() * q.x() - q.y() * q.y() + q.z() * q.z(), 2.0);
      28      169016 :   if (val < 0.0 && !MooseUtils::absoluteFuzzyEqual(val, 0.0))
      29           0 :     mooseError("Euler angle conversion is not successful due to invalid quaternion value.");
      30             : 
      31      169016 :   Phi = std::atan2(std::sqrt(std::abs(val)),
      32      169016 :                    q.w() * q.w() - q.x() * q.x() - q.y() * q.y() + q.z() * q.z()) *
      33             :         (180.0 / libMesh::pi);
      34      169016 :   phi2 = std::atan2((q.x() * q.z() - q.w() * q.y()), (q.w() * q.x() + q.y() * q.z())) *
      35             :          (180.0 / libMesh::pi);
      36             : 
      37             :   // Following checks and updates are done only to comply with bunge euler angle definitions, 0.0
      38             :   // <= phi1/phi2 <= 360.0
      39      169016 :   if (phi1 < 0.0)
      40       37410 :     phi1 += 360.0;
      41      169016 :   if (phi2 < 0.0)
      42           0 :     phi2 += 360.0;
      43      169016 :   if (Phi < 0.0)
      44           0 :     mooseError("Euler angle out of range.");
      45      169016 : }
      46             : 
      47         377 : EulerAngles::EulerAngles(const Real & v0, const Real & v1, const Real & v2)
      48             : {
      49         377 :   phi1 = v0;
      50         377 :   Phi = v1;
      51         377 :   phi2 = v2;
      52         377 : }
      53             : 
      54             : Eigen::Quaternion<Real>
      55           0 : EulerAngles::toQuaternion()
      56             : {
      57             :   Eigen::Quaternion<Real> q;
      58             : 
      59             :   Real cPhi1PlusPhi2, cphi, cPhi1MinusPhi2;
      60             :   Real sPhi1PlusPhi2, sphi, sPhi1MinusPhi2;
      61             : 
      62             :   /**
      63             :    * "NASA Mission Planning and Analysis Division.
      64             :    * "Euler Angles, Quaternions, and Transformation Matrices". NASA.
      65             :    */
      66             : 
      67           0 :   cPhi1PlusPhi2 = std::cos((phi1 * libMesh::pi / 180.0 + phi2 * libMesh::pi / 180.0) / 2.0);
      68           0 :   cphi = std::cos(Phi * libMesh::pi / 360.0);
      69           0 :   cPhi1MinusPhi2 = std::cos((phi1 * libMesh::pi / 180.0 - phi2 * libMesh::pi / 180.0) / 2.0);
      70             : 
      71           0 :   sPhi1PlusPhi2 = std::sin((phi1 * libMesh::pi / 180.0 + phi2 * libMesh::pi / 180.0) / 2.0);
      72           0 :   sphi = std::sin(Phi * libMesh::pi / 360.0);
      73           0 :   sPhi1MinusPhi2 = std::sin((phi1 * libMesh::pi / 180.0 - phi2 * libMesh::pi / 180.0) / 2.0);
      74             : 
      75           0 :   q.w() = cphi * cPhi1PlusPhi2;
      76           0 :   q.x() = sphi * cPhi1MinusPhi2;
      77           0 :   q.y() = sphi * sPhi1MinusPhi2;
      78           0 :   q.z() = cphi * sPhi1PlusPhi2;
      79             : 
      80           0 :   return q;
      81             : }
      82             : 
      83             : void
      84           0 : EulerAngles::random()
      85             : {
      86           0 :   phi1 = MooseRandom::rand() * 360.0;
      87           0 :   Phi = std::acos(1.0 - 2.0 * MooseRandom::rand()) / libMesh::pi * 180.0;
      88           0 :   phi2 = MooseRandom::rand() * 360;
      89           0 : }
      90             : 
      91             : void
      92           0 : EulerAngles::random(MooseRandom & random)
      93             : {
      94           0 :   phi1 = random.rand(0) * 360.0;
      95           0 :   Phi = std::acos(1.0 - 2.0 * random.rand(0)) / libMesh::pi * 180.0;
      96           0 :   phi2 = random.rand(0) * 360;
      97           0 : }
      98             : #include "libmesh/restore_warnings.h"

Generated by: LCOV version 1.14