Beispiel #1
0
// Returns true if the edgept supplied as input is an inside angle.  This
// is determined by the angular change of the vectors from point to point.
bool Wordrec::is_inside_angle(EDGEPT *pt) {
  return angle_change(pt->prev, pt, pt->next) < chop_inside_angle;
}
Beispiel #2
0
void
EulerAngleUpdater::initialize()
{
  const auto grain_num = _grain_tracker.getTotalFeatureCount();

  if (_first_time)
  {
    _angles.resize(grain_num);
    _angles_old.resize(grain_num);
    for (unsigned int i = 0; i < grain_num; ++i)
      _angles[i] = _euler.getEulerAngles(i); // Read initial euler angles
  }

  unsigned int angle_size = _angles.size();
  for (unsigned int i = angle_size; i < grain_num; ++i) // if new grains are created
    _angles.push_back(_euler.getEulerAngles(i));        // Assign initial euler angles

  for (unsigned int i = 0; i < grain_num; ++i)
  {
    if (!_first_time && !_fe_problem.converged())
      _angles[i] = _angles_old[i];

    RealGradient torque = _grain_torque.getTorqueValues()[i];

    if (i <= angle_size) // if new grains are created
      _angles_old[i] = _angles[i];
    else
      _angles_old.push_back(_angles[i]);

    RotationTensor R0(_angles_old[i]); // RotationTensor as per old euler angles
    RealVectorValue torque_rotated =
        R0 * torque; // Applied torque is rotated to allign with old grain axes
    RealVectorValue omega =
        _mr / _grain_volumes[i] * torque_rotated; // Angular velocity as per old grain axes
    /**
     * Change in euler angles are obtained from the torque & angular velocities about the material
     * axes.
     * Change in phi1, Phi and phi2 are caused by rotation about z axis, x' axis & z'' axis,
     * respectively.
     * Components of the angular velocities across z, x' and z'' axes are obtained from the torque
     * values.
     * This yields change in euler angles due to grain rotation.
     */
    RealVectorValue angle_change;
    angle_change(0) = omega(2) * _dt;
    angle_change(1) =
        (omega(0) * std::cos(angle_change(0)) + omega(1) * std::sin(angle_change(0))) * _dt;
    angle_change(2) = (omega(0) * std::sin(angle_change(0)) * std::sin(angle_change(1)) -
                       omega(1) * std::cos(angle_change(0)) * std::sin(angle_change(1)) +
                       omega(2) * std::cos(angle_change(1))) *
                      _dt;
    angle_change *= (180.0 / libMesh::pi);

    RotationTensor R1(angle_change); // Rotation matrix due to torque
    /**
     * Final RotationMatrix = RotationMatrix due to applied torque X old RotationMatrix
     * Updated Euler angles are obtained by back-tracking the angles from the rotation matrix
     * For details about the componenets of the rotation matrix please refer to RotationTensor.C
     * Phi = acos(R33); phi1 = atan2(R31,-R32); phi2 = atan2(R13,R23) for phi != 0.0 por 180.0
     */
    RealTensorValue R = R1 * R0;

    if (R(2, 2) != 1.0 && R(2, 2) != -1.0) // checks if cos(Phi) = 1 or -1
    {
      _angles[i].phi1 = std::atan2(R(2, 0), -R(2, 1)) * (180.0 / libMesh::pi);
      _angles[i].Phi = std::acos(R(2, 2)) * (180.0 / libMesh::pi);
      _angles[i].phi2 = std::atan2(R(0, 2), R(1, 2)) * (180.0 / libMesh::pi);
    }
    else if (R(2, 2) == 1.0) // special case for Phi = 0.0
    {
      if (R0(2, 2) == 1.0)
        // when Phi_old = 0.0; all the rotations are about z axis and angles accumulates after each
        // rotation
        _angles[i].phi1 = _angles_old[i].phi1 + _angles_old[i].phi2 + angle_change(0);
      else
        _angles[i].phi1 = angle_change(0);
      // Comply with bunge euler angle definitions, 0.0 <= phi1 <= 360.0
      if (std::abs(_angles[i].phi1) > 360.0)
      {
        int laps = _angles[i].phi1 / 360.0;
        _angles[i].phi1 -= laps * 360.0;
      }
      _angles[i].Phi = 0.0;
      _angles[i].phi2 = -_angles[i].phi1 + std::atan2(R(0, 1), R(1, 1)) * (180.0 / libMesh::pi);
    }
    else
    {
      if (R0(2, 2) == 1.0)
        _angles[i].phi1 = _angles_old[i].phi1 + _angles_old[i].phi2 + angle_change(0);
      else
        _angles[i].phi1 = angle_change(0);
      // Comply with bunge euler angle definitions, 0.0 <= phi1 <= 360.0
      if (std::abs(_angles[i].phi1) > 360.0)
      {
        int laps = _angles[i].phi1 / 360.0;
        _angles[i].phi1 -= laps * 360.0;
      }
      _angles[i].Phi = 180.0;
      _angles[i].phi2 = _angles[i].phi1 - std::atan2(-R(0, 1), -R(1, 1)) * (180.0 / libMesh::pi);
    }

    // Following checks and updates are done only to comply with bunge euler angle definitions, 0.0
    // <= phi1/phi2 <= 360.0
    if (_angles[i].phi1 < 0.0)
      _angles[i].phi1 += 360.0;
    if (_angles[i].phi2 < 0.0)
      _angles[i].phi2 += 360.0;
    if (_angles[i].Phi < 0.0)
      mooseError("Euler angle out of range.");
  }

  _first_time = false;
}
Beispiel #3
0
/**
 * @name point_priority
 *
 * Assign a priority to and edge point that might be used as part of a
 * split. The argument should be of type EDGEPT.
 */
PRIORITY Wordrec::point_priority(EDGEPT *point) {
  return static_cast<PRIORITY>(angle_change(point->prev, point, point->next));
}
Beispiel #4
0
/**
 * @name point_priority
 *
 * Assign a priority to and edge point that might be used as part of a
 * split. The argument should be of type EDGEPT.
 */
PRIORITY Wordrec::point_priority(EDGEPT *point) {
  return (PRIORITY)angle_change(point->prev, point, point->next);
}