class kawin.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 

kawin.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 
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) 

kawin.StrainEnergy.setInterfacialEnergyMethod(self, method)

Sets method for calculating interfacial energy as a function of aspect ratio 
method : str 
    'eqradius' - interfacial energy is determined using the equivalent spherical radius 
    'thermo' - interfacial energy is determined using dG/dSA (default) 


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


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


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

kawin.StrainEnergy.setConstantElasticEnergy(self, energy)

If elastic strain energy is known to be a constant, this can be use to greatly 
simplify calculations 
energy - strain energy in J/m3 

kawin.StrainEnergy.setElasticTensor(self, tensor)

kawin.StrainEnergy.setElasticConstants(self, c11, c12, c44)

kawin.StrainEnergy.setModuli(self, E = None, nu = None, G = None, lam = None, K = None, M = None)

kawin.StrainEnergy.setElasticTensorPrecipitate(self, tensor)

kawin.StrainEnergy.setElasticConsantsPrecipitate(self, c11, c12, c44)

kawin.StrainEnergy.setModuliPrecipitate(self, E = None, nu = None, G = None, lam = None, K = None, M = None)

kawin.StrainEnergy._setElasticTensor(self, tensor)

Inputs 6x6 elastic matrix 
tensor : matrix of floats 
    Must be 6x6 

kawin.StrainEnergy._setElasticConstants(self, c11, c12, c44)

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

kawin.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 

kawin.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) 
rot : matrix 
    3x3 rotation matrix 

kawin.StrainEnergy.setRotationPrecipitate(self, rot)

kawin.StrainEnergy.setEigenstrain(self, strain)

Sets eigenstrain of precipitate 
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) 

kawin.StrainEnergy.setAppliedStress(self, stress)

Sets applied stress tensor 
Axes of stress tensor should be the same as the matrix 
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 


Calculates applied strain tensor from applied stress tensor and elastic tensor 


Sets up elastic constants 

kawin.StrainEnergy._convert2To4rankTensor(self, c)

Converts 2nd rank elastic tensor to 4th rank 
c : ndarray 
    2nd rank elastic tensor 
c4 : ndarray 
    4th rank elastic tensor 

kawin.StrainEnergy._convert4To2rankTensor(self, c4)

Converts 4th rank elastic tensor to 4nd rank 
c4 : ndarray 
    4th rank elastic tensor 
c : ndarray 
    2nd rank elastic tensor 

kawin.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 

kawin.StrainEnergy._convertVecTo2rankTensor(self, v)

Converts strain/stress vector to 2nd rank tensor 
v : 1d array 
    Strain/stress vector 
e : ndarray 
    2nd rank elastic tensor 

kawin.StrainEnergy._convert2rankToVec(self, c)

kawin.StrainEnergy._rotateRank2Tensor(self, rot, tensor)

Rotates a 2nd rank tensor 
T_ij = r_il * r_jk * T_lk 
tensor : ndarray 
    2nd rank tensor to rotate (3x3 array) 

kawin.StrainEnergy._rotateRank4Tensor(self, rot, tensor)

Rotates a 4th rank tensor 
T_ijkl = r_im * r_jn * r_ok * r_lp * T_mnop 
tensor : ndarray 
    4th rank tensor to rotate (3x3x3x3 array) 

kawin.StrainEnergy.setIntegrationIntervals(self, phiInt, thetaInt, assumeSymmetric=True)

Number of intervals to split domain along phi and theta for integration 
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 

kawin.StrainEnergy.lebedevIntegration(self, order = ‘high’)

Creates Lebedev quadrature points and nodes for integrating Eshebly's tensor 
This is preferred over discretizing phi and theta 
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) 

kawin.StrainEnergy._n(self, phi, theta)

Unit normal vector of sphere 
phi - azimuthal angle 
theta - polar angle 

kawin.StrainEnergy._beta(self, a, b, c, phi, theta)

Distance from center to surface of ellipsoid 
a, b, c - radii of ellipsoid along x,y,z axes 
phi, theta - azimuthal, polar angle 

kawin.StrainEnergy._OhmGeneral(self, n)

Ohm term for general system 
Ohm_ij = inverse(C_iklj * n_k * n_l) 


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


kawin.StrainEnergy.Sijmn(self, D)

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

kawin.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 

kawin.StrainEnergy._strainEnergy(self, stress, strain, V)

u = -0.5 * V * sigma_ij * strain_ij 






kawin.StrainEnergy._Khachaturyan(self, I1, I2)

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


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


Strain energy of perfect sphere (cubic factor = 1) 

kawin.StrainEnergy._strainEnergyCuboidal(self, eta = 1)

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


kawin.StrainEnergy._strainEnergySingle(self, rsingle)

Generic strain energy function 

kawin.StrainEnergy.strainEnergy(self, r)

kawin.StrainEnergy._OhmCubic(self, n)

Ohm term for cubic crystal symmetry 

kawin.StrainEnergy._D(self, n)

Needed for the Ohm term with cubic crystal symmetry 


kawin.StrainEnergy.eqAR_byGR(self, Rsph, gamma, shpFactor, a=1.001, b=100)

Golden ratio search 
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 

kawin.StrainEnergy._GRsearch(self, Rsph, gamma, interfacial, normR, a, b)

Golden ratio search for a single radius 

kawin.StrainEnergy.updateCache(self, normR)

Update cached calculations 


Clear cached calculations 

kawin.StrainEnergy.eqAR_bySearch(self, Rsph, gamma, shpFactor)

Cached search 
Rsph : float or array 
    Equivalent spherical radius 
gamma : float 
    Interfacial energy 
shpFactor : ShapeFactor object 

kawin.StrainEnergy._cachedSearch(self, Rsph, gamma, interfacial, normR)

Cached search for a single radius