diff --git a/data_analysis/mechanics.py b/data_analysis/mechanics.py new file mode 100644 index 0000000000000000000000000000000000000000..b21495ab458f27138e87795e77712db31afe477d --- /dev/null +++ b/data_analysis/mechanics.py @@ -0,0 +1,378 @@ +# -*- coding: utf-8 -*- +""" +Created on Thu Apr 3 10:42:13 2025 + +@author: nroisin +""" +import numpy as np + +def stress_from_strain(strain_tensor,c11= 165.77,c12= 63.93,c44 = 79.62): + strain_voigt=np.zeros((1,6)) + strain_shape=np.shape(strain_tensor) + + if len(strain_shape)==2: + if strain_shape[0]==3 and strain_shape[1]==3: + strain_voigt[0]=strain_tensor[0,0] + strain_voigt[1]=strain_tensor[1,1] + strain_voigt[2]=strain_tensor[2,2] + strain_voigt[3]=strain_tensor[1,2] + strain_voigt[4]=strain_tensor[0,2] + strain_voigt[5]=strain_tensor[0,1] + if strain_shape[0]==1 and strain_shape[1]==6: + strain_voigt=strain_tensor + else: + strain_voigt=np.array([strain_tensor]) + + compliance_tensor=np.array([[c11,c12,c12,0,0,0], + [c12,c11,c12,0,0,0], + [c12,c12,c11,0,0,0], + [0,0,0,c44,0,0], + [0,0,0,0,c44,0], + [0,0,0,0,0,c44]]) + return compliance_tensor @ strain_tensor + +def strain_from_stress(stress_tensor,c11= 165.77,c12= 63.93,c44 = 79.62): + stress_voigt=np.zeros((1,6)) + stress_shape=np.shape(stress_tensor) + + if len(stress_shape)==2: + if stress_shape[0]==3 and stress_shape[1]==3: + stress_voigt[0]=stress_tensor[0,0] + stress_voigt[1]=stress_tensor[1,1] + stress_voigt[2]=stress_tensor[2,2] + stress_voigt[3]=stress_tensor[1,2] + stress_voigt[4]=stress_tensor[0,2] + stress_voigt[5]=stress_tensor[0,1] + if stress_shape[0]==1 and stress_shape[1]==6: + stress_voigt=stress_tensor + else: + stress_voigt=np.array([stress_tensor]) + + compliance_tensor=np.array([[c11,c12,c12,0,0,0], + [c12,c11,c12,0,0,0], + [c12,c12,c11,0,0,0], + [0,0,0,c44,0,0], + [0,0,0,0,c44,0], + [0,0,0,0,0,c44]]) + return np.linalg.inv(compliance_tensor) @ stress_tensor + +def straintensor(direction,cristal_plane,N=11,emin=-0.05,emax=0.05,C11=165.77,C12=63.93,C44=79.62, poisson=True) : + # Constants + retour=np.zeros((3,3,N)) + + eps=np.linspace(emin,emax,N) + + # Initiation + uniepsilon001=np.zeros((3,3,N)) + uniepsilon110=np.zeros((3,3,N)) + uniepsilon111=np.zeros((3,3,N)) + biepsilon001=np.zeros((3,3,N)) + biepsilon110=np.zeros((3,3,N)) + biepsilon111=np.zeros((3,3,N)) + shear001=np.zeros((3,3,N)) + shear110=np.zeros((3,3,N)) + shear111=np.zeros((3,3,N)) + hydro=np.zeros((3,3,N)) + # Matrix computation + # Uniaxial + if poisson: + uniepar001=-C12/(C11+C12)*eps + else: + uniepar001=0 + + uniepsilon001[0][0]=uniepar001 + uniepsilon001[0][1]=np.zeros(N) + uniepsilon001[0][2]=np.zeros(N) + uniepsilon001[1][0]=np.zeros(N) + uniepsilon001[1][1]=uniepar001 + uniepsilon001[1][2]=np.zeros(N) + uniepsilon001[2][0]=np.zeros(N) + uniepsilon001[2][1]=np.zeros(N) + uniepsilon001[2][2]=eps + + if poisson: + uniepar110=- ( 4*C12*C44 ) / ( 2*C11*C44+(C11+2*C12)*(C11-C12) )*eps + else: + uniepar110=0 + + uniepsilon110[0][0]=0.5*(eps+uniepar110) + uniepsilon110[0][1]=0.5*(eps-uniepar110) + uniepsilon110[0][2]=np.zeros(N) + uniepsilon110[1][0]=0.5*(eps-uniepar110) + uniepsilon110[1][1]=0.5*(eps+uniepar110) + uniepsilon110[1][2]=np.zeros(N) + uniepsilon110[2][0]=np.zeros(N) + uniepsilon110[2][1]=np.zeros(N) + uniepsilon110[2][2]=uniepar110 + + if poisson: + uniepar111 = - (C11 + 2*C12 - 2*C44) / (C11 + 2*C12 + 2*C44)*eps + else: + uniepar111 = 0 + + uniepsilon111[0][0] = (eps + 2*uniepar111) / 3 + uniepsilon111[0][1] = (eps - uniepar111) / 3 + uniepsilon111[0][2] = (eps - uniepar111) / 3 + uniepsilon111[1][0] = (eps - uniepar111) / 3 + uniepsilon111[1][1] = (eps + 2*uniepar111) / 3 + uniepsilon111[1][2] = (eps - uniepar111) / 3 + uniepsilon111[2][0] = (eps - uniepar111) / 3 + uniepsilon111[2][1] = (eps - uniepar111) / 3 + uniepsilon111[2][2] = (eps + 2*uniepar111) / 3 + + # Biaxial + if poisson: + bieper001 = -2 * C12 / C11 * eps + else: + bieper001=0 + + biepsilon001[0][0] = eps + biepsilon001[0][1] = np.zeros(N) + biepsilon001[0][2] = np.zeros(N) + biepsilon001[1][0] = np.zeros(N) + biepsilon001[1][1] = eps + biepsilon001[1][2] = np.zeros(N) + biepsilon001[2][0] = np.zeros(N) + biepsilon001[2][1] = np.zeros(N) + biepsilon001[2][2] = bieper001 + + if poisson: + bieper110 = -(C11+3*C12-2*C44)/(C11+C12+2*C44)*eps + else: + bieper110 = 0 + + biepsilon110[0][0] = 0.5*(bieper110+eps) + biepsilon110[0][1] = 0.5*(bieper110-eps) + biepsilon110[0][2] = np.zeros(N) + biepsilon110[1][2] = np.zeros(N) + biepsilon110[1][1] = 0.5*(bieper110+eps) + biepsilon110[1][0] = 0.5*(bieper110-eps) + biepsilon110[2][0] = np.zeros(N) + biepsilon110[2][1] = np.zeros(N) + biepsilon110[2][2] = eps + + if poisson: + bieper111 = -2*(C11+2*C12-2*C44)/(C11+2*C12+4*C44)* eps + else: + bieper111=0 + biepsilon111[0][0] = (bieper111+2*eps)/3 + biepsilon111[0][1] = (bieper111-eps)/3 + biepsilon111[0][2] = (bieper111-eps)/3 + biepsilon111[1][0] = (bieper111-eps)/3 + biepsilon111[1][1] = (bieper111+2*eps)/3 + biepsilon111[1][2] = (bieper111-eps)/3 + biepsilon111[2][0] = (bieper111-eps)/3 + biepsilon111[2][1] = (bieper111-eps)/3 + biepsilon111[2][2] = (bieper111+2*eps)/3 + + # Shear + + shear001[0][2] = eps + shear001[2][0] = eps + + shear110[0][2] = eps/np.sqrt(2) + shear110[2][0] = eps/np.sqrt(2) + shear110[1][2] = eps/np.sqrt(2) + shear110[2][2] = eps/np.sqrt(2) + + shear111[0][1] = eps/np.sqrt(3) + shear111[0][2] = eps/np.sqrt(3) + shear111[1][0] = eps/np.sqrt(3) + shear111[1][2] = eps/np.sqrt(3) + shear111[2][0] = eps/np.sqrt(3) + shear111[2][1] = eps/np.sqrt(3) + + # hydro + + hydro[0][0] = eps/3 + hydro[1][1] = eps/3 + hydro[2][2] = eps/3 + if direction == "uniaxial": + if cristal_plane == "001": + retour=uniepsilon001 + elif cristal_plane == "110": + retour=uniepsilon110 + elif cristal_plane == "111": + retour=uniepsilon111 + elif direction == "biaxial": + if cristal_plane == "001": + retour=biepsilon001 + elif cristal_plane == "110": + retour=biepsilon110 + elif cristal_plane == "111": + retour=biepsilon111 + elif direction == "shear": + if cristal_plane == "001": + retour=shear001 + elif cristal_plane == "110": + retour=shear110 + elif cristal_plane == "111": + retour=shear111 + elif direction =="hydro" : + retour = hydro + + + return retour + +def straintensor_scalar(direction,cristal_plane,eps=0,C11=16.577,C12=6.393,C44=7.962,poisson=True) : + # Constants + retour=np.zeros((3,3)) + + + # Initiation + uniepsilon001=np.zeros((3,3)) + uniepsilon110=np.zeros((3,3)) + uniepsilon111=np.zeros((3,3)) + biepsilon001=np.zeros((3,3)) + biepsilon110=np.zeros((3,3)) + biepsilon111=np.zeros((3,3)) + shear001=np.zeros((3,3)) + shear110=np.zeros((3,3)) + shear111=np.zeros((3,3)) + hydro=np.zeros((3,3)) + # Matrix computation + # Uniaxial + if poisson: + uniepar001=-C12/(C11+C12)*eps + else: + uniepar001=0 + + uniepsilon001[0][0]=uniepar001 + uniepsilon001[0][1]=0 + uniepsilon001[0][2]=0 + uniepsilon001[1][0]=0 + uniepsilon001[1][1]=uniepar001 + uniepsilon001[1][2]=0 + uniepsilon001[2][0]=0 + uniepsilon001[2][1]=0 + uniepsilon001[2][2]=eps + + if poisson: + uniepar110=- ( 4*C12*C44 ) / ( 2*C11*C44+(C11+2*C12)*(C11-C12) )*eps + else: + uniepar110=0 + + + uniepsilon110[0][0]=0.5*(eps+uniepar110) + uniepsilon110[0][1]=0.5*(eps-uniepar110) + uniepsilon110[0][2]=0 + uniepsilon110[1][0]=0.5*(eps-uniepar110) + uniepsilon110[1][1]=0.5*(eps+uniepar110) + uniepsilon110[1][2]=0 + uniepsilon110[2][0]=0 + uniepsilon110[2][1]=0 + uniepsilon110[2][2]=uniepar110 + + if poisson: + uniepar111 = - (C11 + 2*C12 - 2*C44) / (C11 + 2*C12 + 2*C44)*eps + else: + uniepar111=0 + + uniepsilon111[0][0] = (eps + 2*uniepar111) / 3 + uniepsilon111[0][1] = (eps - uniepar111) / 3 + uniepsilon111[0][2] = (eps - uniepar111) / 3 + uniepsilon111[1][0] = (eps - uniepar111) / 3 + uniepsilon111[1][1] = (eps + 2*uniepar111) / 3 + uniepsilon111[1][2] = (eps - uniepar111) / 3 + uniepsilon111[2][0] = (eps - uniepar111) / 3 + uniepsilon111[2][1] = (eps - uniepar111) / 3 + uniepsilon111[2][2] = (eps + 2*uniepar111) / 3 + + # Biaxial + if poisson: + bieper001 = -2 * C12 / C11 * eps + else: + bieper001=0 + + + + biepsilon001[0][0] = eps + biepsilon001[0][1] = 0 + biepsilon001[0][2] = 0 + biepsilon001[1][0] = 0 + biepsilon001[1][1] = eps + biepsilon001[1][2] = 0 + biepsilon001[2][0] = 0 + biepsilon001[2][1] = 0 + biepsilon001[2][2] = bieper001 + + if poisson: + bieper110 = -(C11+3*C12-2*C44)/(C11+C12+2*C44)*eps + else: + bieper110=0 + + + biepsilon110[0][0] = 0.5*(bieper110+eps) + biepsilon110[0][1] = 0.5*(bieper110-eps) + biepsilon110[0][2] = 0 + biepsilon110[1][2] = 0 + biepsilon110[1][1] = 0.5*(bieper110+eps) + biepsilon110[1][0] = 0.5*(bieper110-eps) + biepsilon110[2][0] = 0 + biepsilon110[2][1] = 0 + biepsilon110[2][2] = eps + + if poisson: + bieper111 = -2*(C11+2*C12-2*C44)/(C11+2*C12+4*C44)* eps + else: + bieper111=0 + + + biepsilon111[0][0] = (bieper111+2*eps)/3 + biepsilon111[0][1] = (bieper111-eps)/3 + biepsilon111[0][2] = (bieper111-eps)/3 + biepsilon111[1][0] = (bieper111-eps)/3 + biepsilon111[1][1] = (bieper111+2*eps)/3 + biepsilon111[1][2] = (bieper111-eps)/3 + biepsilon111[2][0] = (bieper111-eps)/3 + biepsilon111[2][1] = (bieper111-eps)/3 + biepsilon111[2][2] = (bieper111+2*eps)/3 + + # Shear + + shear001[0][2] = eps + shear001[2][0] = eps + + shear110[0][2] = eps/np.sqrt(2) + shear110[2][0] = eps/np.sqrt(2) + shear110[1][2] = eps/np.sqrt(2) + shear110[2][2] = eps/np.sqrt(2) + + shear111[0][1] = eps/np.sqrt(3) + shear111[0][2] = eps/np.sqrt(3) + shear111[1][0] = eps/np.sqrt(3) + shear111[1][2] = eps/np.sqrt(3) + shear111[2][0] = eps/np.sqrt(3) + shear111[2][1] = eps/np.sqrt(3) + + # hydro + + hydro[0][0] = eps/3 + hydro[1][1] = eps/3 + hydro[2][2] = eps/3 + if direction == "uni": + if cristal_plane == "001": + retour=uniepsilon001 + elif cristal_plane == "110": + retour=uniepsilon110 + elif cristal_plane == "111": + retour=uniepsilon111 + elif direction == "bi": + if cristal_plane == "001": + retour=biepsilon001 + elif cristal_plane == "110": + retour=biepsilon110 + elif cristal_plane == "111": + retour=biepsilon111 + elif direction == "shear": + if cristal_plane == "001": + retour=shear001 + elif cristal_plane == "110": + retour=shear110 + elif cristal_plane == "111": + retour=shear111 + elif direction =="hydro" : + retour = hydro + + + return retour \ No newline at end of file diff --git a/data_analysis/raman.py b/data_analysis/raman.py index aca71de80535f88590fba2c28a8b097d8ce396bb..6dfa8e4871fd1470b370b30a2ff328f7eb977a0e 100644 --- a/data_analysis/raman.py +++ b/data_analysis/raman.py @@ -95,6 +95,7 @@ def plot_with_peaks(x,y,ax=None,height=None, threshold=None, distance=None, widt ax.text(position[i],1.2*height[i],"%.2f cm$^{-1}$"%position[i],ha="center",va="bottom",rotation="vertical") if ax==None: return fig, ax + def plot_from_file(file_path,ax=None,with_peaks=False,height=None, threshold=None, distance=None, width=None,*ax_kwargs,**plot_kwargs): """ Function to plot the Raman spectrum with the peaks indicated diff --git a/data_analysis/semiconductor.py b/data_analysis/semiconductor.py index db73e45d37f389e7ba1b933e2c30cf939f25deda..0df22c543303f8feb176f56ec95b84a5a6cb6f0d 100644 --- a/data_analysis/semiconductor.py +++ b/data_analysis/semiconductor.py @@ -1,9 +1,44 @@ import numpy as np import matplotlib.pyplot as plt -def mobility_extraction: +def mos_parameter_extraction: + # linear fit -def transistor_current: +def threshold_voltage_extraction: -def mobility_strain_silicon(strain_tensor, pi11, pi12, pi44): +def bjt_transistor_current: + +def mos_transistor_current: + +def diode_current: + +def schottky_current: + +def photodiode_current: + +def piezoresitivity_semiconductor(stress_tensor, pi11, pi12, pi44): + stress_voigt=np.zeros((1,6)) + stress_shape=np.shape(stress_tensor) + + if len(stress_shape)==2: + if stress_shape[0]==3 and stress_shape[1]==3: + stress_voigt[0]=stress_tensor[0,0] + stress_voigt[1]=stress_tensor[1,1] + stress_voigt[2]=stress_tensor[2,2] + stress_voigt[3]=stress_tensor[1,2] + stress_voigt[4]=stress_tensor[0,2] + stress_voigt[5]=stress_tensor[0,1] + if stress_shape[0]==1 and stress_shape[1]==6: + stress_voigt=stress_tensor + else: + stress_voigt=np.array([stress_tensor]) + + piezo_tensor=np.array([[pi11,pi12,pi12,0,0,0], + [pi12,pi11,pi12,0,0,0], + [pi12,pi12,pi11,0,0,0], + [0,0,0,pi44,0,0], + [0,0,0,0,pi44,0], + [0,0,0,0,0,pi44]]) + + return piezo_tensor @ stress_tensor \ No newline at end of file