structure.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Wed Aug 15 23:42:12 2018
  4. @author: USER
  5. """
  6. # Codes are free to use. Do whatever you want
  7. from __future__ import absolute_import
  8. """Read raw data"""
  9. ####################### LIBRARY #############################
  10. # exceptions library
  11. # Python stdlib imports
  12. # data processing library
  13. import numpy as np
  14. # pyrod library
  15. from tool.properties import roughness
  16. import tool.control as tc
  17. import read.read_parameters as rp
  18. ####################### CONSTANT ############################
  19. # constant
  20. ####################### FUNCTIONS ###########################
  21. def atomic_form_factor(ei_list,square_q,mode = 'factor'):
  22. """atomic form factors"""
  23. rp.check_ions(ei_list)
  24. if mode == 'factor':
  25. # atomic form factor
  26. af = rp.IONS_TABLE
  27. f = np.mat(np.zeros([np.size(square_q,0),len(ei_list)]))
  28. num = 0
  29. for ei in ei_list:
  30. f[:,num] = np.mat(af.at[ei,'a1']*np.exp(-af.at[ei,'b1']*square_q/4) +\
  31. af.at[ei,'a2']*np.exp(-af.at[ei,'b2']*square_q/4) +\
  32. af.at[ei,'a3']*np.exp(-af.at[ei,'b3']*square_q/4) +\
  33. af.at[ei,'a4']*np.exp(-af.at[ei,'b4']*square_q/4) +\
  34. af.at[ei,'c']).T
  35. num = num + 1
  36. elif mode == 'electron':
  37. # atomic form factor
  38. af = rp.IONS_TABLE
  39. f = np.mat(np.ones([np.size(square_q,0),len(ei_list)]))
  40. num = 0
  41. for ei in ei_list:
  42. f[:,num] = f[:,num]*(af.at[ei,'a1'] + af.at[ei,'a2'] + af.at[ei,'a3'] + af.at[ei,'a4'] + af.at[ei,'c'])
  43. num = num + 1
  44. return f
  45. def debye_waller_factor(dw,q,u,v):
  46. """
  47. ______________________________________________________
  48. debye waller factors
  49. """
  50. # debye waller factor obtained from parameters.xlsx
  51. # actually its thermal vibration distance of atoms
  52. # default setting is 0.1 A
  53. # dw = slab['dw']
  54. num = 0
  55. # debye waller factor matrix--sampling number x atoms number
  56. d = np.mat(np.zeros([len(q),np.size(dw,1)]))
  57. for ei in dw.columns:
  58. ds = np.exp(-np.square(2*np.pi)*(\
  59. (dw.at['dw_x',ei]*u)**2+\
  60. (dw.at['dw_y',ei]*v)**2+\
  61. (dw.at['dw_z',ei]*q)**2)/2)
  62. d[:,num] = np.mat(ds).T
  63. num = num + 1
  64. return d
  65. def substrate_ctr(var_list, iq,
  66. sub_ubr,
  67. sub_index,
  68. beta = 0, u = 0, v = 0, scale = 1e-4,
  69. key_list = ['absorption',
  70. 'pos',
  71. 'roughness',
  72. 'dw',
  73. 'scale']):
  74. """
  75. calculate the ctr rods of substrate
  76. """
  77. square_q = iq**2
  78. # sn for sampling number
  79. sn = len(iq)
  80. atoms = var_list['substrate']['pos']
  81. ions = (np.array(var_list['substrate']['ions']).tolist())[0]
  82. p = atoms.as_matrix()
  83. # thermal vibration distance
  84. dw = var_list['substrate']['dw']
  85. # r-- crystal surface roughness
  86. r = np.mat(np.ones([sn,1]))
  87. "---------------------------------------------------------"
  88. # introduce the contral variable list
  89. # indicator to indicate the variable postion in ubr list
  90. for key in key_list:
  91. if key == 'absorption':
  92. # aor-- absorption indicator
  93. aor = tc.indicator_contral_vars(sub_ubr,sub_index,'substrate','absorption')
  94. beta = beta + (1-sub_ubr[aor[0]:aor[1]][0])
  95. elif key == 'roughness':
  96. # ror--roughness indicator
  97. ror = tc.indicator_contral_vars(sub_ubr,sub_index,'substrate','roughness')
  98. # beta_r- roughness beta distinguish with absorption beta
  99. beta_r = sub_ubr[ror[0]:ror[1]][0]-1
  100. cr = roughness(iq)
  101. r = np.mat(cr.robinson_roughness(beta_r)).T
  102. elif key == 'scale':
  103. # sor-- scale indicator
  104. sor = tc.indicator_contral_vars(sub_ubr,sub_index,'substrate','scale')
  105. scale = scale + sub_ubr[sor[0]:sor[1]][0]
  106. elif key == 'pos':
  107. # por-- pos indicator
  108. por = tc.indicator_contral_vars(sub_ubr,sub_index,'substrate','pos')
  109. # get pos ubr and reshape it into 3x5 matrix p.shape
  110. p_ubr = np.reshape(np.array(sub_ubr[por[0]:por[1]]),p.shape)
  111. p = np.multiply(p, p_ubr)
  112. elif key == 'dw':
  113. # dor-- debye waller factor indicator
  114. dor = tc.indicator_contral_vars(sub_ubr,sub_index,'substrate','dw')
  115. d_ubr = np.reshape(np.array(sub_ubr[dor[0]:dor[1]]),dw.shape)
  116. dw = np.multiply(dw, d_ubr)
  117. "---------------------------------------------------------"
  118. # a--atomic form factor
  119. a = atomic_form_factor(ions,square_q)
  120. # d--debye waller factor
  121. d = debye_waller_factor(dw,iq,u,v)
  122. # q--construct 3d qs space
  123. q = np.mat(np.zeros([sn,3]))
  124. q[:,0] = np.mat(np.ones([sn,1]))*u # qx
  125. q[:,1] = np.mat(np.ones([sn,1]))*v # qy
  126. q[:,2] = np.mat(iq).T
  127. # f--structure form factor
  128. f = np.multiply(np.multiply(a,d),
  129. np.exp(1j*2*np.pi*(np.dot(q,p))))
  130. # s--shape function
  131. s = 1/(1 - np.exp(-1*1j*2*np.pi*np.dot(q,np.mat([0,0,1]).T))*\
  132. np.exp(-beta) +\
  133. scale)
  134. #sctr--structure form factor for crystal turncation rod
  135. sctr = np.multiply(f,s)
  136. return np.multiply(np.sum(sctr,1), r)
  137. def film_ctr(varl,vart,subr,sindex, iq, u, v,key_list = ['lattice_abc','dw','pos']):
  138. "--------------------------------------------------------------------------"
  139. for key in key_list:
  140. # lattice abc modulation
  141. if key == 'lattice_abc':
  142. # lattice contral variable
  143. pos_ctable = []
  144. # layer loop
  145. for l in vart['slab_list']:
  146. # the indicator of the lattice constant contral variable for each layer
  147. pos_indicator = tc.indicator_contral_vars(subr,sindex,l,key)
  148. pos_contral = subr[pos_indicator[0]:pos_indicator[1]]
  149. pos_ctable.append(pos_contral)
  150. # debye_waller_factor modultion
  151. elif key == 'dw':
  152. # dw contral table
  153. dw_ctable = []
  154. # dw contral variable
  155. for l in vart['slab_list']:
  156. # indicator of debye waller factor for each layer
  157. dw_indicator = tc.indicator_contral_vars(subr,sindex,l,key)
  158. dw_contral = subr[dw_indicator[0]:dw_indicator[1]]
  159. dw_ctable.append(np.reshape(dw_contral,(3,varl[l]['atoms_num'])))
  160. # posz--modulate lattice c, modualte it indivual
  161. "--------------------------------------------------------------------------"
  162. m,n = vart['posz_table'].shape
  163. u,v = 0,0
  164. sn = len(iq)
  165. # Note! data type = complex!
  166. # ComplexWarning: Casting complex values to real discards the imaginary part
  167. slab_ctr = np.mat(np.zeros([sn,1],dtype = complex))
  168. # q--construct 3d qs space
  169. q = np.mat(np.zeros([sn,3]))
  170. q[:,0] = np.mat(np.ones([sn,1]))*u # qx
  171. q[:,1] = np.mat(np.ones([sn,1]))*v # qy
  172. q[:,2] = np.mat(iq).T
  173. square_q = np.square(iq)
  174. # loop for layer
  175. tot_layer = 0
  176. for layeri in range(m):
  177. # debye waller factor
  178. if 'dw' in key_list:
  179. dw_factor = np.multiply(vart['dw_table'][layeri],dw_ctable[layeri])
  180. else:
  181. dw_factor = vart['dw_table'][layeri]
  182. dw_layeri = debye_waller_factor(dw_factor,iq,u,v)
  183. # lattice constant modulation
  184. slabi = vart['slab_list'][layeri]
  185. if 'lattice_abc' in key_list:
  186. lattice_abc = pos_ctable[layeri]
  187. else:
  188. lattice_abc = [1,1,1]
  189. sub_c = varl['substrate']['lattice'].at['constant','c']
  190. # multivarible optimization of postion
  191. if 'pos' in key_list:
  192. slab_c = varl[slabi]['lattice'].at['constant','c']*lattice_abc[2]*subr[layeri]
  193. else:
  194. slab_c = varl[slabi]['lattice'].at['constant','c']*lattice_abc[2]
  195. tot_layer = tot_layer + slab_c/sub_c
  196. # loop for atom
  197. for atomi in range(n):
  198. posi = [vart['posx_table'][layeri,atomi]*lattice_abc[0],
  199. vart['posy_table'][layeri,atomi]*lattice_abc[1],
  200. tot_layer + varl[slabi]['pos'].as_matrix()[2,atomi] - \
  201. varl['substrate']['layers_num']*1]
  202. # the ocupany, contral vancany
  203. ocui = vart['ocu_table'][layeri,atomi]
  204. # ion name
  205. ion = vart['ion_table'][layeri][atomi]
  206. #
  207. a = ocui*atomic_form_factor([ion],square_q)
  208. d = dw_layeri[:,atomi]
  209. f = np.multiply(np.multiply(a,d),
  210. np.exp(1j*2*np.pi*(np.dot(q,np.mat(posi).T))))
  211. slab_ctr = slab_ctr + f
  212. return slab_ctr
  213. ######################## CLASSS #############################