{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Basic one-dimensional phase-field model (Allen-Cahn equation)\n",
"This python code was developed by Yamanaka research group of Tokyo University of Agriculture and Technology in August 2019."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Problem\n",
"Let us consider an example: growth of phase B in phase A. \n",
"This notebook shows one-dimensional phase-field simulation of the growth of phase B using Allen-Cahn equation. \n",
"\n",
"For details of the model, please see reference (*S. M. Allen and J. W. Cahn, \"A Microscopic Theory for Antiphase Boundary Motion and Its Application to Antiphase Domain Coarsening,\" Acta Metallurgica, Vol. 27 (1979), pp. 1085–1095.*).\n",
"## Formulation\n",
"### 1. Order parameter\n",
"An non-conserved order parameter $\\phi$ (hereafter, we call it as \"phase-field variable\".) is used. The phase-field variable $\\phi$ is defined as $\\phi = 0$ in phase A and $\\phi = 1$ in phase B. The phase-field variable $\\phi$ smoothly changes from 0 to 1 in an \"diffuse\" interfacial region. \n",
"### 2. Total free energy\n",
"The total Gibbs free energy of the system is defined by\n",
"$$\n",
"G = \\int_{V} (g_{chem}(\\phi) + g_{doub}(\\phi) + g_{grad}(\\nabla\\phi)) dV\n",
"$$\n",
"where, $g_{chem}$, $g_{doub}$, and $g_{grad}$ are the chemical free energy, the double-well potential energy and the gradient energy densities, respectively. In this source code, these energy densities are defined as follows: \n",
"$$\n",
"g_{chem} = p(\\phi)g_{B} + (1-p(\\phi))g_{A}\n",
"$$\n",
"$$\n",
"g_{doub} = Wq(\\phi)\n",
"$$\n",
"$$\n",
"g_{grad} = \\frac{a^{2}}{2}|\\nabla\\phi|^{2}\n",
"$$\n",
"where $g_{A}$ and $g_{B}$ are Gibbs free energy densities of pure phase A and pure phase B, respectively. Here, $g_{A}$ and $g_{B}$ are assumed to be constant. \n",
"\n",
"$p(\\phi)$ and $q(\\phi)$ are an interpolation function and the double-well potential function. These functions are often defined as follows: \n",
"$$\n",
"p(\\phi) = \\phi^{2}(3-2\\phi)\n",
"$$\n",
"$$\n",
"q(\\phi) = \\phi^{2}(1-\\phi)^{2}\n",
"$$\n",
"\n",
"$W$ and $a$ are the height of double-well potential energy and the gradient energy coefficient, respectively, which are given by\n",
"$$\n",
"W = \\frac{6\\sigma\\delta}{b}\n",
"$$\n",
"$$\n",
"a = \\sqrt{\\frac{3\\sigma b}{\\delta}}\n",
"$$\n",
"where $\\sigma$ is the interfacial energy of an interface between phase A and B. $\\delta$ is the thickness (length in one-dimension) of the diffuse interface. $b$ is given as $b = 2\\tanh^{-1}(1-2\\lambda)$ where $\\lambda$ is a constant which is used for determining the thickness of interfacial region. In this source code, we use $\\lambda$ = 0.1 and then $b$ = 2.2. \n",
"\n",
"### 3. Time evolution equation (Allen-Cahn equation)\n",
"The time evolution of the phase-field variable (that describes the migration of the interface) is given by Allen-Cahn equation by assuming that the total free energy of the system, $G$, decreases monotonically with time (i.e. The second law of thermodynamics): \n",
"$$\n",
"\\frac{\\partial \\phi}{\\partial t} = -M_{\\phi}\\frac{\\delta G}{\\delta \\phi}=-M_{\\phi}\\left(\\frac{\\partial p(\\phi)}{\\partial \\phi}(g_{B}-g_{A})+W\\frac{\\partial q(\\phi)}{\\partial\\phi}-a^{2}\\nabla^{2}\\phi\\right)\n",
"$$\n",
"where $M_{\\phi}$ is the mobility of phase-field variable and is given by: \n",
"$$\n",
"M_{\\phi} = \\frac{\\sqrt{2W}}{6a}M\n",
"$$\n",
"Here, $M$ is a \"physical\" mobility of interface between phase A and B. \n",
"The term $g_{B}-g_{A}$ in the Allen-Cahn equation corresponds to the driving force of the growth of phase B. \n",
"\n",
"Note that the Euler-Lagrange equation given by the following equation is used to calculate the functional derivative of $G$ with respect to the phase-field variable as:\n",
"$$\n",
"\\frac{\\delta G}{\\delta \\phi}=\\frac{\\partial g}{\\partial \\phi}-\\nabla\\cdot\\frac{\\partial g}{\\partial (\\nabla \\phi)}\n",
"$$\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Programming "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### import libraries\n",
"In this notebook, you use NumPy, Matplotlib and Math libraries. \n",
"\n",
"Numpy is a fundamental package for scientific computing in Python that provides a multidimensional array object.
\n",
"Matplotlib is a Python library used for plotting the beautiful and attractive graphs and animations.
\n",
"Math is a library for accessing to some common math functions and constants in Python"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib nbagg\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from matplotlib import animation\n",
"import math"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### set parameters and physical values "
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"nx = 64 # number of computational grids\n",
"dx = 0.5e-6 # spacing of computational grid [m]\n",
"eee = 5.e+5 # magnitude of driving force of growth of phase B: g_A - g_B [J/m3] = [Pa]\n",
"sigma = 1.0 # ineterfacial energy [J/m2]\n",
"delta = 4.*dx # interfacial thickness [m]\n",
"amobi = 4.e-14 # interfacial mobilitiy [m4/(Js)]\n",
"ram = 0.1 # paraneter which deternines the interfacial area\n",
"bbb = 2.*np.log((1.+(1.-2.*ram))/(1.-(1.-2.*ram)))/2. # The constant b = 2.1972 (please see the handout)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### calculate phase-field parameters ($a, W$ and $M_{\\phi}$)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"aaa = np.sqrt(3.*delta*sigma/bbb) # gradient energy coefficient \"a\"[(J/m)^(1/2)]\n",
"www = 6.*sigma*bbb/delta # potential height W [J/m3]\n",
"pmobi = amobi*math.sqrt(2.*www)/(6.*aaa) # mobility of phase-field [m3/(Js)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### define time increment and total number of time steps"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"dt = dx*dx/(5.*pmobi*aaa*aaa)/2 # time increment for a time step [s]\n",
"nsteps = 500 # total number of time step"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### declare arrays for phase field variable and others"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"p = np.zeros((nsteps,nx)) # phase-field variable for all time steps\n",
"driv = np.zeros((nsteps,nx)) # array for saving driving force term (only for visualization)\n",
"grad = np.zeros((nsteps,nx)) # array for saving gradient force term (only for visualization)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### set initial distribution of phase-field variable (initial nuclei of phase B)\n",
"The initial nuclei of the phase B (region of $\\phi = 1$) is located at the origin of the computational domain. \n",
"\n",
"The initial profile of the phase-field variable along $x$-direction is calculated using the equilibrium profile (see Appendix in the handout for the derivation): \n",
"$$\n",
"\\phi = \\frac{1}{2}\\left(1-\\tanh \\frac{\\sqrt{2W}}{2a}(x-r_{0}) \\right)\n",
"$$\n",
"where $r_{0}$ denotes the initial position of the interface. "
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"r_nuclei = 10.*dx # length of the initial B phase\n",
"for i in range(0,nx):\n",
" r = i*dx - r_nuclei\n",
" p[0,i] = 0.5*(1.-np.tanh(np.sqrt(2.*www)/(2.*aaa)*r))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### define function for solving Allen-Cahn equation\n",
"Allen-Cahn equation is discretized by simple finite difference method in this program. \n",
"\n",
"The 1st-order foward Euler method is used for the time-integration. The 2nd-order central finite difference method is used for the spatial derivatives. The discretized Allen-Cahn equation is given as: \n",
"$$\n",
"\\phi^{t+\\Delta t}_{i} = \\phi^{t}_{i} + M_{\\phi}\n",
"\\left[ 4W\\phi^{t}_{i}\\left(1-\\phi^{t}_{i}\\right)\\left(\\phi^{t}_{i}-\\frac{1}{2}+\\frac{3}{2W}(g_{A}-g_{B})\\right)\n",
"+a^{2}\\left(\\frac{\\phi^{t}_{i+1}-2\\phi^{t}_{i}+\\phi^{t}_{i-1}}{(\\Delta x)^{2}}\\right)\n",
"\\right]\\Delta t\n",
"$$\n",
"\n",
"For visuallization, arrays \"driv\" and \"grad\" are saved. "
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def do_timestep(p,driv,grad):\n",
" for t in range(nsteps-1):\n",
" for i in range(nx):\n",
" ip = i + 1\n",
" im = i - 1\n",
" if ip > nx - 1:\n",
" ip = nx -1\n",
" if im < 0:\n",
" im = 0\n",
" p[t+1,i] = p[t,i] + pmobi * ( 4.*www*p[t,i]*(1.-p[t,i])*(p[t,i]-0.5+3./(2.*www)*eee) + aaa*aaa*((p[t,ip] - 2*p[t,i] + p[t,im])/dx/dx) ) * dt\n",
" driv[t+1,i] = pmobi*(4.*www*p[t,i]*(1.-p[t,i])*(p[t,i]-0.5+3./(2.*www)*eee))\n",
" grad[t+1,i] = pmobi*(aaa*aaa*(p[t,ip] - 2*p[t,i] + p[t,im])/dx/dx)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Time integration of Allen-Cahn equation and real-time visualization\n",
"Check the role of driving force and gradient terms in Allen-Cahn equation. \n",
"\n",
"The driving force tem: \n",
"$$\n",
"M_{\\phi}\\left[ 4W\\phi^{t}_{i}\\left(1-\\phi^{t}_{i}\\right)\\left(\\phi^{t}_{i}-\\frac{1}{2}+\\frac{3}{2W}(g_{A}-g_{B})\\right) \\right]\n",
"$$\n",
"The gradient (or diffusion) term:\n",
"$$\n",
"M_{\\phi}\\left[ a^{2}\\left(\\frac{\\phi^{t}_{i+1}-2\\phi^{t}_{i}+\\phi^{t}_{i-1}}{(\\Delta x)^{2}}\\right) \\right]\n",
"$$\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('