Grain boundaries (GBs) migrate to reduce the free energy of the system. One source of energy that can be reduced is the grain boundary energy, and the standard grain growth model accounts for this driving force (commonly called the curvature driving force). In addition, GBs can migrate to reduce the elastic energy stored in the system. To account for this driving force in the grain growth model, we couple to a mechanics solution.

In our model, $$$N_{gr}$$$ grains are represented by $$$N_{op}$$$ order parameters, where $$$N_{gr} \geq N_{op}$$$. Each grain has a unique ID $$$gr$$$ and is represented by a specific order parameter $$$op$$$, though the order parameter used for each grain can change throughout the simulation. The assignment of the order parameters to each grain is controlled by the grain tracker user object.

The crystal orientation of each grain is described by a set of three Euler angles $$$[\phi_1, \Phi, \phi_2]_{gr}$$$. The Euler angles define a rotation tensor $$$\mathbf{R}_{gr}$$$ used to rotate the elasticity tensor in the crystal frame of reference $$$\boldsymbol{\mathcal{C}}_0$$$ to the current frame. Thus, the elasticity tensor for each grain is fully defined by $$$$\boldsymbol{\mathcal{C}}_{gr} = (\mathbf{R}_{gr} \boxtimes \mathbf{R}_{gr}) \boldsymbol{\mathcal{C}}_0 (\mathbf{R}_{gr} \boxtimes \mathbf{R}_{gr})^T$$$$ where $$$\boxtimes$$$ is the fourth-order tensor product. In the phase field model, the grain boundaries are represented by a diffuse inteface in which multiple order parameters have non-zero values. Thus, the elasticity tensor at any point in space is a weighted average of the elasticity tensors from all grains with non-zero order parameters, i.e. $$$$\boldsymbol{\mathcal{C}}(\mathbf{r}) = \frac{\sum_{gr} h(\eta_{gr}(\mathbf{r})) \boldsymbol{\mathcal{C}}_{gr} }{\sum_{gr} h(\eta_{gr}(\mathbf{r}))},$$$$ Where the interpolation function $h$ is equal to 0 when $\eta_{gr} = 0$ and 1 when $\eta_{gr}=1$, i.e. $$$$h(\eta_{gr}) = \frac{1}{2}(1 + \sin(\pi((\eta_{gr} - 0.5))$$$$ The local stress is calculated from the local elasticity tensor according to $$$$\boldsymbol{\sigma}(\mathbf{r}) = \boldsymbol{\mathcal{C}}(\mathbf{r}) \boldsymbol{\epsilon}(\mathbf{r})$$$$ and the elastic energy density is calculated according to $$$$\begin{eqnarray} E_d &=& \frac{1}{2} \boldsymbol{\sigma}(\mathbf{r}) \cdot \boldsymbol{\epsilon}(\mathbf{r}) \\ &=& \frac{1}{2} \boldsymbol{\mathcal{C}}(\mathbf{r}) \boldsymbol{\epsilon}(\mathbf{r}) \cdot \boldsymbol{\epsilon} (\mathbf{r}) \end{eqnarray}$$$$

The elastic energy is added to the free energy of the system, as shown on the Developing Phase Field Models page. The Allen-Cahn equation defining the evolution of the order parameters becomes $$$$\frac{\partial \eta_{gr}}{\partial t} = - L \left( \frac{\partial f_{loc}}{\partial \eta_j} + \frac{\partial E_{d}}{\partial \eta_{gr}} - \kappa_j \nabla^2 \eta_j \right),$$$$ where $$$$\frac{\partial E_{d}}{\partial \eta_{gr}} = \frac{1}{2} \frac{\partial \boldsymbol{\mathcal{C}}}{\partial \eta_{gr}} \boldsymbol{\epsilon} \cdot \boldsymbol{\epsilon}.$$$$ The partial derivative of the elasticity tensor with respect to the order parameters is defined by $$$$\frac{\partial \boldsymbol{\mathcal{C}}}{\partial \eta_{gr}} = h'(\eta_{gr}) \frac{ \boldsymbol{\mathcal{C}}_{gr} }{\sum_{gr} h(\eta_{gr})} - h'(\eta_{gr}) \frac{\sum_{gr} h(\eta_{gr}) \boldsymbol{\mathcal{C}}_{gr} }{\left(\sum_{gr} h(\eta_{gr}) \right)^2}.$$$$

The additional contribution of elastic energy on the Allen-Cahn equation describing grain growth is implemented in the phase field module with the kernel ACGrGrElasticDrivingForce. It only adds the elastic energy contribution, so it must be used with the ACGrGrPoly kernel. The addition to the residual in weak form is $$$$L \left( \frac{\partial E_d}{\partial \eta_{gr}}, \psi_m \right),$$$$ and is implemented in the code according to

Real ACGrGrElasticDrivingForce::computeDFDOP(PFFunctionType type) { // Access the heterogeneous strain calculated by the Solid Mechanics kernels RankTwoTensor strain(_elastic_strain[_qp]); // Compute the partial derivative of the stress wrt the order parameter RankTwoTensor D_stress = _D_elastic_tensor[_qp] * strain; switch (type) { case Residual: return 0.5 * D_stress.doubleContraction(strain); // Compute the deformation energy driving force case Jacobian: return 0.0; } mooseError("Invalid type passed in"); }

The stress and strain are computed using kernels from the tensor mechanics module, but a material in the phase field module was created to compute the polycrystal elasticity tensor, ComputePolycrystalElasticityTensor. It also computes the derivatives of the elasticity tensor with respect to all of the order parameters. This material must be used with the GrainTracker user object.

As with the basic grain growth model, creating separate blocks in the input file for every order parameter would be burdensome. Thus, we have implemented an action that adds the elastic driving force kernel for each order parameter. The action is PolycrystalElasticDrivingForceAction and it must be used with the PolycrystalKernelAction.

This capability is tested in

`moose/modules/combined/tests/ACGrGrElasticDrivingForce`

and is demonstrated on larger problems in

`moose/modules/combined/examples/phase_field-mechanics/hex_grain_growth_2D_eldrforce.i`

`moose/modules/combined/examples/phase_field-mechanics/poly_grain_growth_2D_eldrforce.i`