LCOV - code coverage report
Current view: top level - src/vectorpostprocessors - EulerAngleUpdaterCheck.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #32971 (54bef8) with base c6cf66 Lines: 44 45 97.8 %
Date: 2026-05-29 20:38:39 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          14 : EulerAngleUpdaterCheck::validParams()
      21             : {
      22          14 :   InputParameters params = GeneralVectorPostprocessor::validParams();
      23          14 :   params.addClassDescription(
      24             :       "Provide updated Euler angles after rigid body rotation of the grains.");
      25          28 :   params.addRequiredParam<UserObjectName>("grain_tracker_object",
      26             :                                           "The FeatureFloodCount UserObject to get values from.");
      27          28 :   params.addParam<UserObjectName>("euler_angle_updater",
      28             :                                   "Name of Euler angle provider user object");
      29          28 :   params.addRequiredParam<UserObjectName>("grain_torques_object",
      30             :                                           "Name of Euler angle provider user object");
      31          28 :   params.addRequiredParam<VectorPostprocessorName>("grain_volumes",
      32             :                                                    "The feature volume VectorPostprocessorValue.");
      33          28 :   params.addParam<Real>("rotation_constant", 1.0, "constant value characterizing grain rotation");
      34          14 :   return params;
      35           0 : }
      36             : 
      37           7 : EulerAngleUpdaterCheck::EulerAngleUpdaterCheck(const InputParameters & params)
      38             :   : GeneralVectorPostprocessor(params),
      39           7 :     _diff(declareVector("vec_diff")),
      40           7 :     _grain_tracker(getUserObject<GrainTrackerInterface>("grain_tracker_object")),
      41           7 :     _euler(getUserObject<EulerAngleUpdater>("euler_angle_updater")),
      42           7 :     _grain_torque(getUserObject<GrainForceAndTorqueInterface>("grain_torques_object")),
      43           7 :     _grain_volumes(getVectorPostprocessorValue("grain_volumes", "feature_volumes")),
      44          21 :     _mr(getParam<Real>("rotation_constant"))
      45             : {
      46           7 : }
      47             : 
      48             : void
      49          13 : EulerAngleUpdaterCheck::initialize()
      50             : {
      51          13 :   const auto grain_num = _grain_tracker.getTotalFeatureCount();
      52          13 :   _angles.resize(grain_num);
      53          13 :   _angles_old.resize(grain_num);
      54          13 :   _diff.assign(3 * grain_num, 0.0);
      55             : 
      56          26 :   for (unsigned int i = 0; i < grain_num; ++i)
      57             :   {
      58          13 :     _angles[i] = _euler.getEulerAngles(i);
      59          13 :     _angles_old[i] = _euler.getEulerAnglesOld(i);
      60          13 :     RealGradient torque = _grain_torque.getTorqueValues()[i];
      61             : 
      62             :     RealVectorValue a(1, 1, 1);
      63          13 :     RotationTensor R(_angles[i]);  // Final rotation tensor
      64          13 :     RealVectorValue a_rot = R * a; // final rotated vector
      65             : 
      66          13 :     RotationTensor R0(_angles_old[i]);        // RotationTensor as per old euler angles
      67          13 :     RealVectorValue torque_rot = R0 * torque; // Rotated torque
      68          13 :     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          13 :     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          13 :         (torque_rot(0) * std::cos(angle_rot(0)) + torque_rot(1) * std::sin(angle_rot(0)));
      87          13 :     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          13 :     torque_rot1(2) = (torque_rot(0) * std::sin(angle_rot(0)) * std::sin(angle_rot(1)) -
      90          13 :                       torque_rot(1) * std::cos(angle_rot(0)) * std::sin(angle_rot(1)) +
      91          13 :                       torque_rot(2) * std::cos(angle_rot(1)));
      92          13 :     angle_rot(2) = _mr / _grain_volumes[i] * torque_rot1(2) * _dt; // change in phi2
      93             :     angle_rot *= (180.0 / libMesh::pi);
      94             : 
      95          13 :     RotationTensor R4(angle_rot);         // RotationTensor due to grain rotation
      96          13 :     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          13 :     _diff[3 * i + 0] = a_rot(0) - a_rot1(0);
     101          13 :     _diff[3 * i + 1] = a_rot(1) - a_rot1(1);
     102          13 :     _diff[3 * i + 2] = a_rot(2) - a_rot1(2);
     103             :   }
     104          13 : }

Generated by: LCOV version 1.14