LCOV - code coverage report
Current view: top level - src/vectorpostprocessors - EulerAngleUpdaterCheck.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #31405 (292dce) with base fef103 Lines: 44 45 97.8 %
Date: 2025-09-04 07:55:36 Functions: 3 3 100.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 "EulerAngleUpdaterCheck.h"
      11             : #include "EulerAngleUpdater.h"
      12             : #include "EulerAngleProvider.h"
      13             : #include "GrainTrackerInterface.h"
      14             : #include "GrainForceAndTorqueInterface.h"
      15             : #include "RotationTensor.h"
      16             : 
      17             : registerMooseObject("PhaseFieldApp", EulerAngleUpdaterCheck);
      18             : 
      19             : InputParameters
      20          22 : EulerAngleUpdaterCheck::validParams()
      21             : {
      22          22 :   InputParameters params = GeneralVectorPostprocessor::validParams();
      23          22 :   params.addClassDescription(
      24             :       "Provide updated Euler angles after rigid body rotation of the grains.");
      25          44 :   params.addRequiredParam<UserObjectName>("grain_tracker_object",
      26             :                                           "The FeatureFloodCount UserObject to get values from.");
      27          44 :   params.addParam<UserObjectName>("euler_angle_updater",
      28             :                                   "Name of Euler angle provider user object");
      29          44 :   params.addRequiredParam<UserObjectName>("grain_torques_object",
      30             :                                           "Name of Euler angle provider user object");
      31          44 :   params.addRequiredParam<VectorPostprocessorName>("grain_volumes",
      32             :                                                    "The feature volume VectorPostprocessorValue.");
      33          44 :   params.addParam<Real>("rotation_constant", 1.0, "constant value characterizing grain rotation");
      34          22 :   return params;
      35           0 : }
      36             : 
      37          11 : EulerAngleUpdaterCheck::EulerAngleUpdaterCheck(const InputParameters & params)
      38             :   : GeneralVectorPostprocessor(params),
      39          11 :     _diff(declareVector("vec_diff")),
      40          11 :     _grain_tracker(getUserObject<GrainTrackerInterface>("grain_tracker_object")),
      41          11 :     _euler(getUserObject<EulerAngleUpdater>("euler_angle_updater")),
      42          11 :     _grain_torque(getUserObject<GrainForceAndTorqueInterface>("grain_torques_object")),
      43          11 :     _grain_volumes(getVectorPostprocessorValue("grain_volumes", "feature_volumes")),
      44          33 :     _mr(getParam<Real>("rotation_constant"))
      45             : {
      46          11 : }
      47             : 
      48             : void
      49          17 : EulerAngleUpdaterCheck::initialize()
      50             : {
      51          17 :   const auto grain_num = _grain_tracker.getTotalFeatureCount();
      52          17 :   _angles.resize(grain_num);
      53          17 :   _angles_old.resize(grain_num);
      54          17 :   _diff.assign(3 * grain_num, 0.0);
      55             : 
      56          34 :   for (unsigned int i = 0; i < grain_num; ++i)
      57             :   {
      58          17 :     _angles[i] = _euler.getEulerAngles(i);
      59          17 :     _angles_old[i] = _euler.getEulerAnglesOld(i);
      60          17 :     RealGradient torque = _grain_torque.getTorqueValues()[i];
      61             : 
      62             :     RealVectorValue a(1, 1, 1);
      63          17 :     RotationTensor R(_angles[i]);  // Final rotation tensor
      64          17 :     RealVectorValue a_rot = R * a; // final rotated vector
      65             : 
      66          17 :     RotationTensor R0(_angles_old[i]);        // RotationTensor as per old euler angles
      67          17 :     RealVectorValue torque_rot = R0 * torque; // Rotated torque
      68          17 :     RealVectorValue a_rot0 = R0 * a;          // Rotated unit vector as per old euler angles
      69             : 
      70             :     /**
      71             :      * Change in euler angles are obtained from the torque & angular velocities about the material
      72             :      * axes.
      73             :      * Change in phi1, Phi and phi2 are caused by rotation about z axis, x' axis & z'' axis,
      74             :      * respectively.
      75             :      * Components of the angular velocities across z, x' and z'' axes are obtained from the torque
      76             :      * values.
      77             :      * This yields change in euler angles due to grain rotation.
      78             :      */
      79             :     RealVectorValue torque_rot1;
      80             :     RealVectorValue angle_rot;
      81             :     torque_rot1(0) =
      82             :         torque_rot(2); // Tourque about z changed to torque responsible for chaneg in angle phi1
      83          17 :     angle_rot(0) = _mr / _grain_volumes[i] * torque_rot1(0) * _dt; // change in phi1
      84             :     // Tourque about x' changed to torque responsible for chaneg in angle Phi
      85             :     torque_rot1(1) =
      86          17 :         (torque_rot(0) * std::cos(angle_rot(0)) + torque_rot(1) * std::sin(angle_rot(0)));
      87          17 :     angle_rot(1) = _mr / _grain_volumes[i] * torque_rot1(1) * _dt; // change in Phi
      88             :     // Tourque about z'' changed to torque responsible for chaneg in angle phi2
      89          17 :     torque_rot1(2) = (torque_rot(0) * std::sin(angle_rot(0)) * std::sin(angle_rot(1)) -
      90          17 :                       torque_rot(1) * std::cos(angle_rot(0)) * std::sin(angle_rot(1)) +
      91          17 :                       torque_rot(2) * std::cos(angle_rot(1)));
      92          17 :     angle_rot(2) = _mr / _grain_volumes[i] * torque_rot1(2) * _dt; // change in phi2
      93             :     angle_rot *= (180.0 / libMesh::pi);
      94             : 
      95          17 :     RotationTensor R4(angle_rot);         // RotationTensor due to grain rotation
      96          17 :     RealVectorValue a_rot1 = R4 * a_rot0; // Final rotated vector obtained in two step rotation
      97             : 
      98             :     // Difference between the final positions of the rotated vector obtained in two different ways,
      99             :     // should be 0.0
     100          17 :     _diff[3 * i + 0] = a_rot(0) - a_rot1(0);
     101          17 :     _diff[3 * i + 1] = a_rot(1) - a_rot1(1);
     102          17 :     _diff[3 * i + 2] = a_rot(2) - a_rot1(2);
     103             :   }
     104          17 : }

Generated by: LCOV version 1.14