kawin.precipitation.non_ideal

ElasticFactors module

StrainEnergy

class kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy(self):

Defines class for calculating strain energy of a precipitate

Ellipsoidal precipitates will use the Eshelby's tensor
Spherical and Cuboidal precipitates will use the Khachaturyan's approximation

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setOhmInverseFunction(self, method = ‘quick’):

Sets method to invert the ohm term in calculating eshelby's tensor

Parameters
----------
method : str
    'numpy' - uses np.linalg.inv, which can be slower for batch, but runs through
                multiple checks for whether values are real/complex or if inverse exists
    'quick' - quick inverse using Cramer's rule assuming that values are real and inverse exists - recommended method

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setAspectRatioResolution(self, resolution = 0.01, cachedRange = 5):

Sets resolution to which equilibrium aspect ratios are calculated

Equilibrium aspect ratios are found by calculated strain energy for a range of aspect ratios
and finding the aspect ratio giving the minimum energy (strain + interfacial energy)

If aspect ratio does not vary much in a given system, then the default parameters may lead to poor
prediction of the aspect ratios

Parameters
----------
resolution : float (optional)
    Minimum distance between aspect ratios when calculating cache (default at 0.01)
cachedRange : float (optional)
    Range of aspect ratio to calculate strain energy when updated cache (default at 5)

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setInterfacialEnergyMethod(self, method):

Sets method for calculating interfacial energy as a function of aspect ratio

Parameters
----------
method : str
    'eqradius' - interfacial energy is determined using the equivalent spherical radius
    'thermo' - interfacial energy is determined using dG/dSA (default)

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setSpherical(self):

Assumes spherical geometry for strain energy calculation
Uses Khachaturyan's approximation

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setCuboidal(self):

Assumes cuboidal geometry for strain energy calculation
Uses Khachaturyan's approximation

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setEllipsoidal(self):

Assumes ellipsoidal geometry for strain energy calculation
Uses Eshelby's tensor

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setConstantElasticEnergy(self, energy):

If elastic strain energy is known to be a constant, this can be use to greatly
simplify calculations

Parameters
----------
energy - strain energy in J/m3

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setElasticTensor(self, tensor):

Sets elastic tensor of matrix using 2nd rank tensor

Parameters
----------
tensor : 6x6 array
    2nd rank elastic tensor

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setElasticConstants(self, c11, c12, c44):

Sets elastic tensor of matrix by elastic constants, assuming cubic symmetry

Parameters
----------
c11 : float
    Modulus for compression
    c11 = E(1-nu) / (1+nu)(1-2nu)
c12 : float
    Modulus for dilation (accounts for compression and Poisson's ratio)
    c12 = E nu / (1+nu)(1-2nu)
c44 : float
    Modulus for shear
    c44 = (c11-c12)/2

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setModuli(self, E = None, nu = None, G = None, lam = None, K = None, M = None):

Sets elastic tensor of matrix by 2 moduli

Parameters (only 2 has to be defined)
----------
E : float
    Elastic modulus
nu : float
    Poisson's ratio
G : float
    Shear modulus
lam : float
    Lame's first parameter
K : float
    Bulk modulus
M : float
    P-wave modulus

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setElasticTensorPrecipitate(self, tensor):

Sets elastic tensor of precipitate using 2nd rank tensor

Parameters
----------
tensor : 6x6 array
    2nd rank elastic tensor

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setElasticConsantsPrecipitate(self, c11, c12, c44):

Sets elastic tensor of precipitate by elastic constants, assuming cubic symmetry

Parameters
----------
c11 : float
    Modulus for compression
    c11 = E(1-nu) / (1+nu)(1-2nu)
c12 : float
    Modulus for dilation (accounts for compression and Poisson's ratio)
    c12 = E nu / (1+nu)(1-2nu)
c44 : float
    Modulus for shear
    c44 = (c11-c12)/2

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setModuliPrecipitate(self, E = None, nu = None, G = None, lam = None, K = None, M = None):

Sets elastic tensor of precipitate by 2 moduli

Parameters (only 2 has to be defined)
----------
E : float
    Elastic modulus
nu : float
    Poisson's ratio
G : float
    Shear modulus
lam : float
    Lame's first parameter
K : float
    Bulk modulus
M : float
    P-wave modulus

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._setElasticTensor(self, tensor):

Inputs 6x6 elastic matrix

Parameters
----------
tensor : matrix of floats
    Must be 6x6

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._setElasticConstants(self, c11, c12, c44):

Creates elastic tensor from c11, c12 and c44 constants assuming isotropic system

Parameters
----------
c11 : float
c12 : float
c44 : float

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._setModuli(self, E = None, nu = None, G = None, lam = None, K = None, M = None):

Set elastic tensor by defining at least two of the moduli
Everything will be converted to E, nu and G
If more than two parameters are defined, then the following priority will be used:
E - Youngs modulus
nu - Poisson's ratio
G - shear modulus
lam - Lame's first parameter
K - bulk modulus
M - P-wave modulus

NOTE: There's gotta be a better way to implement the conversions

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setRotationMatrix(self, rot):

Sets rotation matrix to be applied to the matrix

This is for cases where the axes of the precipitate does not align with the axes of the matrix
(e.g., the long/short axes of the precipitate is not parallel to the <100> directions of the matrix)

Parameters
----------
rot : matrix
    3x3 rotation matrix

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setRotationPrecipitate(self, rot):

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setEigenstrain(self, strain):

Sets eigenstrain of precipitate

Parameters
----------
strain : float, array or matrix
    float - assume strain is the same along all 3 axis
    array - each index corresponds to strain in a given axis
    matrix - full 2nd rank strain tensor

NOTE: when using in conjunction with ShapeFactors, the axis are order specific
    For needle-like precipitates, x1, x2 and x3 correspond to (short axis, short axis, long axis)
    For plate-like precipitates, x1, x2 and x3 correspond to (long axis, long axis, short axis)

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setAppliedStress(self, stress):

Sets applied stress tensor
Axes of stress tensor should be the same as the matrix

Parameters
----------
stress : float, array or matrix
    float - assume stress is the same along all 3 axis
    array - each index corresponds to stress in a given axis
    matrix - full 2nd rank stress tensor

NOTE: The applied stress is in reference to the coordinate axes of the precipitates
Thus, this is only valid if the following conditions are met:
    The matrix phase has a single orientation (either as a single crystal or highly textured)
    Precipitates will form only in a single orientation with respect to the matrix

TODO: It will be nice to expand on this.
    For polycrystalline matrix and randomly oriented precipitates, it should be possible
    to average the strain energy contributions over all matrix/precipitate orientations

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.getAppliedStrain(self):

Calculates applied strain tensor from applied stress tensor and elastic tensor

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setup(self):

Sets up elastic constants

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._convert2To4rankTensor(self, c):

Converts 2nd rank elastic tensor to 4th rank

Parameters
----------
c : ndarray
    2nd rank elastic tensor

Returns
-------
c4 : ndarray
    4th rank elastic tensor

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._convert4To2rankTensor(self, c4):

Converts 4th rank elastic tensor to 4nd rank

Parameters
----------
c4 : ndarray
    4th rank elastic tensor

Returns
-------
c : ndarray
    2nd rank elastic tensor

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._invert4rankTensor(self, c4):

Inverts 4th rank tensor to give stiffness tensor

This is done by converting to 2nd rank, inverting, then converting back to 4th rank

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._convertVecTo2rankTensor(self, v):

Converts strain/stress vector to 2nd rank tensor

Parameters
----------
v : 1d array
    Strain/stress vector

Returns
-------
e : ndarray
    2nd rank elastic tensor

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._convert2rankToVec(self, c):

Converts 2nd rank tensor to vector

Parameter
---------
c : ndarray
    3x3 tensor

Returns
-------
v : 1darray
    Strain/stress vector

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._rotateRank2Tensor(self, rot, tensor):

Rotates a 2nd rank tensor
T_ij = r_il * r_jk * T_lk

Parameters
----------
tensor : ndarray
    2nd rank tensor to rotate (3x3 array)

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._rotateRank4Tensor(self, rot, tensor):

Rotates a 4th rank tensor
T_ijkl = r_im * r_jn * r_ok * r_lp * T_mnop

Parameters
----------
tensor : ndarray
    4th rank tensor to rotate (3x3x3x3 array)

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.setIntegrationIntervals(self, phiInt, thetaInt, assumeSymmetric=True):

Number of intervals to split domain along phi and theta for integration

Parameters
----------
phiInt : int
    Number of intervals to divide along phi
thetaInt : int
    Number of intervals to divide along theta
assumeSymmetric : bool (optional)
    If True (default), will only integrate Eshelby's tensor on a single quadrant and
    multiply the results by 8

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.lebedevIntegration(self, order = ‘high’):

Creates Lebedev quadrature points and nodes for integrating Eshebly's tensor
This is preferred over discretizing phi and theta

Parameters
----------
order : str
    'low' - uses quadrature order or 53 (974 points)
    'mid' - uses quadrature order or 83 (2354 points)
    'high' (default) - uses quadrature order or 131 (5810 points)

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._n(self, phi, theta):

Unit normal vector of sphere

Parameters
----------
phi - azimuthal angle
theta - polar angle

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._beta(self, a, b, c, phi, theta):

Distance from center to surface of ellipsoid

Parameters
----------
a, b, c - radii of ellipsoid along x,y,z axes
phi, theta - azimuthal, polar angle

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._OhmGeneral(self, n):

Ohm term for general system

Ohm_ij = inverse(C_iklj * n_k * n_l)

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._ohm_quickInverse(self, m):

Hard coded inverse of m which is of shape (3,3,n)

numpy inv is more optimized for larger matrices, but can be slower for small
matrices such as a 2x2 or 3x3. We can take advantage of 3x3 matrices having a computable
inverse to make it faster

NOTE: this only works since we know that m has a shape of (3,3,n) and is only composed of real numbers

This function can probably be a bit more efficient, but quick 
profiling on sphInt gives around a 35x speedup compared to doing 
np.transpose(np.linalg.inv(np.transpose(m, (2,0,1))), (1,2,0)) 
where the slowdown was in np.linalg.inv

For matrix:
    |  a  b  c  |
    |  d  e  f  |
    |  g  h  i  |

Inverse is defined as:
    |  ei-fh  fg-di  dh-eg  |          |  A  B  C  |
    |  ch-bi  ai-cg  bg-ah  | / det -> |  D  E  F  | / det
    |  bf-ce  cd-af  ae-bd  |          |  G  H  I  |
    Where det = aA + bB + cC

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._ohm_npinv(self, m):

Inverts ohm term using np.linalg.inv

numpy inverse function takes in an array of shape (m,n,n) and inverts each nxn matrix
    So we have to transpose m from (3,3,n) -> (n,3,3), then invert, then transpose (n,3,3) ->(3,3,n)

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.sphInt(self):

Faster version of calculating the Dijkl, which avoids
using a for loop to iterate across phi and theta

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.Dijkl(self):

Dijkl term for Eshelby's theory

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.Sijmn(self, D):

S_ijmn = -0.5 * C_lkmn * (D_iklj + D_jkli)

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._multiply(self, a, b):

Multiplies 2 tensors
4th x 2nd -> c_ij = a_ijkl * b_kl
4th x 4th -> c_ijkl = a_ijmn * b_mnkl

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._strainEnergy(self, stress, strain, V):

u = -0.5 * V * sigma_ij * strain_ij

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._strainEnergyEllipsoidWithStress(self):

Strain energy of ellipsoidal particle with applied stress

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._strainEnergyEllipsoid(self):

Strain energy of ellipsoidal particle

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._strainEnergyEllipsoid2(self):

Alternative method of strain energy on ellipsoidal particle using 2nd rank tensors

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._strainEnergyBohm(self):

Strain energy of particle for when matrix and precipitate phases have different elastic tensors

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._strainEnergyBohm2(self):

Strain energy of particle for when matrix and precipitate phases have different elastic tensors using 2nd rank tensors

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._Khachaturyan(self, I1, I2):

Khachaturyan's approximation for strain energy of spherical and cuboidal precipitates

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._strainEnergyCube(self):

Strain energy of perfect cube (cubic factor = sqrt(2))

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._strainEnergySphere(self):

Strain energy of perfect sphere (cubic factor = 1)

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._strainEnergyCuboidal(self, eta = 1):

For cuboidal preciptitates, strain energy can be approximated
as a linear interpolation between a perfect cube and sphere

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._strainEnergyConstant(self):

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._strainEnergySingle(self, rsingle):

Generic strain energy function

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.strainEnergy(self, r):

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._OhmCubic(self, n):

Ohm term for cubic crystal symmetry

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._D(self, n):

Needed for the Ohm term with cubic crystal symmetry

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._xi(self):

Needed for the Ohm term with cubic crystal symmetry

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.eqAR_byGR(self, Rsph, gamma, shpFactor, a=1.001, b=100):

Equilibrium aspect ratio using golden ratio search

Parameters
----------
Rsph : float or array
    Equivalent spherical radius
gamma : float
    Interfacial energy
shpFactor : ShapeFactor object
a, b : float
    Min and max bounds
    Default is 1.001 and 100

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._GRsearch(self, Rsph, gamma, interfacial, normR, a, b):

Golden ratio search for a single radius

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.updateCache(self, normR):

Update cached calculations

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.clearCache(self):

Clear cached calculations

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy.eqAR_bySearch(self, Rsph, gamma, shpFactor):

Equilibrium aspect ratio by cached search

Parameters
----------
Rsph : float or array
    Equivalent spherical radius
gamma : float
    Interfacial energy
shpFactor : ShapeFactor object

def kawin.precipitation.non_ideal.ElasticFactors.StrainEnergy._cachedSearch(self, Rsph, gamma, interfacial, normR):

Cached search for a single radius

LebedevNodes module

def kawin.precipitation.non_ideal.LebedevNodes.loadPoints(order):

Load lebedov nodes of specific order

Parameters
----------
order : int
    Can be 53, 83 or 131
    Determines the order of polynomial at which an exact integral solution can be found

Returns
-------
phi coordinates, theta coordinates, weights

ShapeFactors module

ShapeFactor

class kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor(self):

Defines functions for shape factors of needle, plate and cuboidal precipitates
Shape factors involve the following:
    Aspect Ratio - ratio of long axis to short axis
    Eccentricity - characteristic value of the precipitate shape that depends on the aspect ratio
    Equivalent radius factor - correction factor to the radius to give the radius of a sphere with equivalent volume
    Kinetic factor - correction factor for the growth rate of the particle
    Thermodynamic factor / Area factor - correction factor for the critical driving force/radius for nucleation
    
    For a sphere (or needle and plate precipitates with aspect ratio of 1):
        Eccentricity = 0
        Equivalent radius factor = 1
        Kinetic factor = 1
        Thermodynamic factor = 1

NOTE:
normalRadaii, eqRadiusFactor, kineticFactor and thermoFactor 
    take in R and output the corresponding factors

_normalRadaiiEquation, __eqRadiusEquation, _kineticEquation and _thermoEquation
    take in aspect ratio and output the corresponding factors

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor.setAspectRatio(self, ar):

Sets aspect ratio as a function of R (equivalent spherical radius)

Parameters
----------
ar : float or function
    Aspect ratio
    If function, must take in radius and return aspect ratio

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._scalarAspectRatioEquation(self, R):

Aspect ratio as a function of radius if the aspect ratio is set as a scalar

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor.setPrecipitateShape(self, precipitateShape, ar = 1):

General shape setting function

Defualts to spherical

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor.setSpherical(self, ar = 1):

Sets factors for spherical precipitates

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor.setNeedleShape(self, ar = 1):

Factors for needle shaped precipitates

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor.setPlateShape(self, ar = 1):

Factors for plate shaped precipitates

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor.setCuboidalShape(self, ar = 1):

Factors for cuboidal shaped precipitates

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor.normalRadii(self, R):

Radius along the 3 axis to give a spherical volume of 1

Parameters
----------
R : float or array
    Equivalent spherical radius

Returns
-------
3 length array for each axis if R is scalar
n x 3 array if R is an array

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor.eqRadiusFactor(self, R):

Equivalent spherical radius factor for generic precipitates

Parameters
----------
R : float or array
    Equivalent spherical radius

Returns
-------
Eq. radius factor with same shape as R

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor.kineticFactor(self, R):

Kinetic factor for generic precipitates

Parameters
----------
R : float or array
    Equivalent spherical radius

Returns
-------
Kinetic factor with same shape as R

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor.thermoFactor(self, R):

Thermodynamic factor for generic precipitates

Parameters
----------
R : float or array
    Equivalent spherical radius

Returns
-------
Thermodynamic factor with same shape as R

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor.eccentricity(self, ar):

Eccentricity given the aspect ratio (for needle and plate shaped precipitates)

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._eqRadiusFactorSphere(self, ar):

Equivalent radius for a sphere (returns 1)

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._eqRadiusFactorNeedle(self, ar):

Equivalent radius for needle shaped precipitate

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._eqRadiusFactorPlate(self, ar):

Equivalent radius for plate shaped precipitate

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._eqRadiusFactorCuboidal(self, ar):

Equivalent radius for cuboidal shaped precipitate

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._normalRadiiSphere(self, ar):

Returns radius along the 3-axis for a volume of 1

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._normalRadiiNeedle(self, ar):

Returns radius along the 3-axis for a volume of 1

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._normalRadiiPlate(self, ar):

Returns radius along the 3-axis for a volume of 1

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._normalRadiiCuboidal(self, ar):

Returns radius along the 3-axis for a volume of 1

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._kineticFactorSphere(self, ar):

Kinetic factor for a sphere (returns 1)

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._kineticFactorEquationNeedle(self, ar):

Kinetic factor for needle shaped precipitate

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._kineticFactorEquationPlate(self, ar):

Kinetic factor for plate shaped precipitate

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._kineticFactorEquationCuboidal(self, ar):

Kinetic factor for cuboidal shaped precipitate

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._thermoFactorSphere(self, ar):

Thermodynamic factor for a sphere (returns 1)

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._thermoFactorEquationNeedle(self, ar):

Thermodynamic factor for needle shaped precipitate

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._thermoFactorEquationPlate(self, ar):

Thermodynamic factor for plate shaped precipitate

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._thermoFactorEquationCuboidal(self, ar):

Thermodynamic factor for cuboidal shaped precipitate

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._findRcritScalar(self, RcritSphere, Rmax):

Critical radius given a scalar aspect ratio

def kawin.precipitation.non_ideal.ShapeFactors.ShapeFactor._findRcrit(self, RcritSphere, Rmax):

Critical radius given aspect ratio as a function of radius
Found by bisection method

GrainBoundaries module

GBFactors

class kawin.precipitation.non_ideal.GrainBoundaries.GBFactors(self):

Defines nucleation factors for bulk, dislocation, 
surface, edge and corner nucleation

This includes: surface area, volume, GB area removal, Rcrit and Gcrit

Attributes
----------
gbRemoval - factor to multiply by r**2 to get area of grain boundary removed
areaFactor - factor to multiply by r**2 to get surface area of precipitate
volumeFactor - factor to multiply by r**3 to get volume of precipitate

def kawin.precipitation.non_ideal.GrainBoundaries.GBFactors.setNucleationType(self, site):

Sets nucleation site type

Parameters
----------
site - int
    Index for site type based off list on top of this file

def kawin.precipitation.non_ideal.GrainBoundaries.GBFactors.setFactors(self, gbEnergy, gamma):

Calculated area, volume and GB removal factors

Parameters
----------
gbEnergy - float
    Grain boundary energy
gamma - float
    Interfacial energy between precipitate and bulk

def kawin.precipitation.non_ideal.GrainBoundaries.GBFactors.Rcrit(self, dG):

Critical radius for nucleation
This is only done for GB nucleation
    Bulk and dislocation nucleation needs to account for shape factors

R* = 2 * (b * \gamma_{\alpha \alpha} - a * \gamma_{\alpha \beta}) / (3 * c * dG)

Parameters
----------
dG - float
    Volumetric driving force

def kawin.precipitation.non_ideal.GrainBoundaries.GBFactors.Gcrit(self, dG, Rcrit):

Critical driving force for nucleation

G* = 4/27 * (b * \gamma_{\alpha \alpha} - a * \gamma_{\alpha \beta})^3 / (c * dG)^2

or in terms of R*
G* = -R*^2 * (b * \gamma_{\alpha \alpha} - a * \gamma_{\alpha \beta} + c * r* * dG)

This is calculated in terms of R* since there is a check in the nucleation calculation that will
increase R* to minimum radius if R* is too small (very low nucleation barriers)

Parameters
----------
dG - float
    Volumetric driving force
Rcrit - float
    Critical radius for nucleation

EffectiveDiffusion module

EffectiveDiffusionFunctions

class kawin.precipitation.non_ideal.EffectiveDiffusion.EffectiveDiffusionFunctions(self):

Stores variables and functions to calculate effective diffusion distance

def kawin.precipitation.non_ideal.EffectiveDiffusion.EffectiveDiffusionFunctions.setupInterpolation(self, n = 250, lmin = -5, lmax = 1):

Sets up interpolation points for effective diffusion distance

Parameters
----------
n : int
    Number of points to interpolate between, two endpoints will be added
    at supersaturation of 0 and 1
lmin : float
    Minimum lambda value in log scale
lmax : float
    Maximum lambda value in log scale

def kawin.precipitation.non_ideal.EffectiveDiffusion.EffectiveDiffusionFunctions.effectiveDiffusionDistance(self, supersaturation):

Effective diffusion distance given supersaturation
This gives a constant to be multiplied by the particle radius

The effective diffusion distance is given by
eps = Q/2*lambda

Where Q is the super saturation and lambda is given by
Q = 2*lambda^2 - 2*lambda^3 * sqrt(pi) * exp(lambda^2) * (1 - erf(lambda))

Parameters
----------
supersaturation : float or array of floats
    (x - x_P) / (x_M - x_P) where x is matrix composition, x_M is parent composition and x_P is precipitate composition

Returns
-------
Effective diffusion distance (eps) to be used as (eps*R) in the growth rate equation

def kawin.precipitation.non_ideal.EffectiveDiffusion.EffectiveDiffusionFunctions.lambdaLow(self, supersaturation):

Lambda when Q approaches 0
This is done to prevent precision errors when multiplying exp*(1-erf)

def kawin.precipitation.non_ideal.EffectiveDiffusion.EffectiveDiffusionFunctions.lambdaHigh(self, supersaturation):

Lambda when Q approaches 1
This is done to prevent precision errors when multiplying exp*(1-erf)

def kawin.precipitation.non_ideal.EffectiveDiffusion.EffectiveDiffusionFunctions.effectiveDiffusionDistanceApprox(self, supersaturation):

Effective diffusion distance given supersaturation
This gives a constant to be multiplied by the particle radius

When Q approaches 1, this equation oscillates due to floating point errors
Therefore, interpolation is performed between the two limits (Q -> 0 and Q -> 1)

This may be removed in later versions

Parameters
----------
supersaturation : float or array of floats
    (x - x_P) / (x_M - x_P) where x is matrix composition, x_M is parent composition and x_P is precipitate composition

Returns
-------
Effective diffusion distance (eps) to be used as (eps*R) in the growth rate equation

def kawin.precipitation.non_ideal.EffectiveDiffusion.EffectiveDiffusionFunctions.noDiffusionDistance(self, supersaturation):

If neglecting the effective diffusion distance, return 1

Parameters
----------
supersaturation : float or array of floats
    (x - x_P) / (x_M - x_P) where x is matrix composition, x_M is parent composition and x_P is precipitate composition

Returns
-------
1 or array of 1s