https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ComputeBlockOrientationByRotation.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://www.mooseframework.org
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
11#include "MooseMesh.h"
12
13#include "libmesh/mesh_tools.h"
14
16
19{
21 params.addParam<unsigned int>("bins", 20, "Number of bins to segregate quaternions");
22 params.addParam<Real>("L_norm", 1, "Specifies the type of average the user intends to perform");
24 "This object determines the orientation of each grain (block) by identifying the most common "
25 "orientation direction among the material points within the grain.");
26 return params;
27}
28
30 const InputParameters & parameters)
31 : ComputeBlockOrientationBase(parameters),
32 _updated_rotation(getMaterialProperty<RankTwoTensor>("updated_rotation")),
33 _bins(getParam<unsigned int>("bins")),
34 _L_norm(getParam<Real>("L_norm"))
35{
36}
37
38void
46
47void
49{
50 RankTwoTensor rot;
52
53 for (unsigned int _qp = 0; _qp < _qrule->n_points(); _qp++)
54 rot += _JxW[_qp] * _coord[_qp] * _updated_rotation[_qp];
56
57 // transform RankTwoTensor to Eigen::Matrix
58 Eigen::Matrix<Real, 3, 3> rot_mat;
59
60 for (unsigned int i = 0; i < 3; ++i)
61 for (unsigned int j = 0; j < 3; ++j)
62 rot_mat(i, j) = rot(i, j);
63
64 // SVD-based projection to SO(3)
65 Eigen::JacobiSVD<Eigen::Matrix<Real, 3, 3>> svd(rot_mat,
66 Eigen::ComputeFullU | Eigen::ComputeFullV);
67
68 Eigen::Matrix<Real, 3, 3> U = svd.matrixU();
69 Eigen::Matrix<Real, 3, 3> V = svd.matrixV();
70
71 // Enforce proper rotation (det = +1)
72 Eigen::Matrix<Real, 3, 3> R = U * V.transpose();
73 if (R.determinant() < 0.0)
74 {
75 Eigen::Matrix<Real, 3, 3> D = Eigen::Matrix<Real, 3, 3>::Identity();
76 D(2, 2) = -1.0;
77 R = U * D * V.transpose();
78 }
79
80 // compute Quaternion from rotation matrix
81 Eigen::Quaternion<Real> q(R);
82 // store quaternion values for the current element
83 _quat[_current_elem->subdomain_id()].push_back(std::make_tuple(q.w(), q.x(), q.y(), q.z()));
84}
85
86void
88{
89 for (const auto & block : _fe_problem.mesh().meshSubdomains())
90 {
91 // Use allgather to sync data from all processors
94 }
95}
96
99{
100 // creating a map to store the quaternion count for each bin index
101 std::map<std::tuple<int, int, int, int>, unsigned int> feature_weights;
102
103 // precompute the scaling from the bins once and reuse
104 const Real bin_scale = 0.5 * _bins;
105
106 for (const auto & [w, x, y, z] : _quat[sid])
107 {
108 const auto bin = std::make_tuple<int, int, int, int>(std::floor(w * bin_scale),
109 std::floor(x * bin_scale),
110 std::floor(y * bin_scale),
111 std::floor(z * bin_scale));
112 feature_weights[bin]++;
113 }
114
115 // quaternion average matrix Q*w*Q^T
116 typedef Eigen::Matrix<Real, 4, 4> Matrix4x4;
117 Matrix4x4 quat_mat = Matrix4x4::Zero();
118 typedef Eigen::Matrix<Real, 4, 1> Vector4;
119
120 Real total_weight = 0.0;
121
122 for (const auto & [w, x, y, z] : _quat[sid])
123 {
124 Vector4 v(w, x, y, z);
125
126 const auto bin = std::make_tuple<int, int, int, int>(std::floor(w * bin_scale),
127 std::floor(x * bin_scale),
128 std::floor(y * bin_scale),
129 std::floor(z * bin_scale));
130 const auto bin_size = feature_weights[bin];
131 const auto weight = std::pow(bin_size, _L_norm);
132 total_weight += weight;
133
134 quat_mat += v * weight * v.transpose();
135 }
136
137 quat_mat *= 1.0 / total_weight;
138
139 // compute eigenvalues and eigenvectors
140 Eigen::EigenSolver<Matrix4x4> EigenSolver(quat_mat);
141 Vector4 eigen_values = EigenSolver.eigenvalues().real();
142 Matrix4x4 eigen_vectors = EigenSolver.eigenvectors().real();
143
144 // Selecting eigenvector corresponding to max eigenvalue to compute average Euler angle
145 Vector4::Index max_index = 0;
146 eigen_values.maxCoeff(&max_index);
147 const auto max_vec = eigen_vectors.col(max_index) / eigen_vectors.col(max_index).norm();
148 const Eigen::Quaternion<Real> q(max_vec(0), max_vec(1), max_vec(2), max_vec(3));
149
150 return EulerAngles(q);
151}
registerMooseObject("SolidMechanicsApp", ComputeBlockOrientationByRotation)
const std::vector< double > y
const std::vector< double > x
const double R
const double v
void ErrorVector unsigned int
Computes the average value of a variable on each block.
virtual void initialize() override
This is called before execute so you can reset any internal data.
std::map< SubdomainID, EulerAngles > _block_ea_values
Computes the average value of a variable on each block.
unsigned int _bins
number of bins for each quaternion component
Real _L_norm
parameter used to compute the weighting function for the average quaternion calculation
EulerAngles computeSubdomainEulerAngles(const SubdomainID &sid)
Compute Quaternion for each subdomain (block), following Markley, F.
virtual void execute() override
Compute the average of the rotation matrix in this element.
std::unordered_map< SubdomainID, std::vector< std::tuple< Real, Real, Real, Real > > > _quat
virtual void initialize() override
Clear internal Euler angle and misorientationdata.
const MaterialProperty< RankTwoTensor > & _updated_rotation
virtual void finalize() override
Gather all Euler angles from this block.
ComputeBlockOrientationByRotation(const InputParameters &parameters)
const QBase *const & _qrule
const Elem *const & _current_elem
const MooseArray< Real > & _coord
const MooseArray< Real > & _JxW
const Real & _current_elem_volume
Euler angle triplet.
Definition EulerAngles.h:25
virtual MooseMesh & mesh() override
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
const std::set< SubdomainID > & meshSubdomains() const
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
FEProblemBase & _fe_problem
const Parallel::Communicator & _communicator
void mooseSetToZero(T &v)