Source code for GSASIIstrMath

# -*- coding: utf-8 -*-
########### SVN repository information ###################
# $Date: 2023-12-12 12:48:03 -0600 (Tue, 12 Dec 2023) $
# $Author: vondreele $
# $Revision: 5706 $
# $URL: https://subversion.xray.aps.anl.gov/pyGSAS/trunk/GSASIIstrMath.py $
# $Id: GSASIIstrMath.py 5706 2023-12-12 18:48:03Z vondreele $
########### SVN repository information ###################
'''
:mod:`GSASIIstrMath` routines, used for refinement computations 
are found below.
'''
from __future__ import division, print_function
import time
import copy
import numpy as np
import numpy.ma as ma
import numpy.linalg as nl
import scipy.stats as st
import scipy.special as sp
import multiprocessing as mp
import pickle
import GSASIIpath
GSASIIpath.SetVersionNumber("$Revision: 5706 $")
import GSASIIElem as G2el
import GSASIIlattice as G2lat
import GSASIIspc as G2spc
import GSASIIpwd as G2pwd
import GSASIImapvars as G2mv
import GSASIImath as G2mth
import GSASIIobj as G2obj
import GSASIImpsubs as G2mp
#G2mp.InitMP(False)  # This disables multiprocessing 

sind = lambda x: np.sin(x*np.pi/180.)
cosd = lambda x: np.cos(x*np.pi/180.)
tand = lambda x: np.tan(x*np.pi/180.)
asind = lambda x: 180.*np.arcsin(x)/np.pi
acosd = lambda x: 180.*np.arccos(x)/np.pi
atan2d = lambda y,x: 180.*np.arctan2(y,x)/np.pi
    
try:  # fails on doc build
    ateln2 = 8.0*np.log(2.0)
    twopi = 2.0*np.pi
    twopisq = 2.0*np.pi**2
except TypeError:
    pass
nxs = np.newaxis
keV = 12.397639

################################################################################
##### Rigid Body Models
################################################################################
        
[docs] def ApplyRBModels(parmDict,Phases,rigidbodyDict,Update=False): ''' Takes RB info from RBModels in Phase and RB data in rigidbodyDict along with current RB values in parmDict & modifies atom contents (fxyz & Uij) of parmDict ''' atxIds = ['Ax:','Ay:','Az:'] atuIds = ['AU11:','AU22:','AU33:','AU12:','AU13:','AU23:'] RBIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[],'Spin':[]}) #these are lists of rbIds RBIds['Spin'] = RBIds.get('Spin',[]) #patch if not RBIds['Vector'] and not RBIds['Residue'] and not RBIds['Spin']: return VRBIds = RBIds['Vector'] RRBIds = RBIds['Residue'] SRBIds = RBIds['Spin'] if Update: RBData = rigidbodyDict else: RBData = copy.deepcopy(rigidbodyDict) # don't mess with original! if RBIds['Vector']: # first update the vector magnitudes VRBData = RBData['Vector'] for i,rbId in enumerate(VRBIds): if VRBData[rbId]['useCount']: for j in range(len(VRBData[rbId]['VectMag'])): name = '::RBV;'+str(j)+':'+str(i) VRBData[rbId]['VectMag'][j] = parmDict[name] for phase in Phases: Phase = Phases[phase] General = Phase['General'] cx,ct,cs,cia = General['AtomPtrs'] cell = General['Cell'][1:7] Amat,Bmat = G2lat.cell2AB(cell) AtLookup = G2mth.FillAtomLookUp(Phase['Atoms'],cia+8) pfx = str(Phase['pId'])+'::' if Update: RBModels = Phase['RBModels'] else: RBModels = copy.deepcopy(Phase['RBModels']) # again don't mess with original! for irb,RBObj in enumerate(RBModels.get('Vector',[])): jrb = VRBIds.index(RBObj['RBId']) rbsx = str(irb)+':'+str(jrb) for i,px in enumerate(['RBVPx:','RBVPy:','RBVPz:']): RBObj['Orig'][0][i] = parmDict[pfx+px+rbsx] for i,po in enumerate(['RBVOa:','RBVOi:','RBVOj:','RBVOk:']): RBObj['Orient'][0][i] = parmDict[pfx+po+rbsx] RBObj['Orient'][0] = G2mth.normQ(RBObj['Orient'][0]) RBObj['AtomFrac'][0] = parmDict[pfx+'RBVf:'+rbsx] TLS = RBObj['ThermalMotion'] if 'T' in TLS[0]: for i,pt in enumerate(['RBVT11:','RBVT22:','RBVT33:','RBVT12:','RBVT13:','RBVT23:']): TLS[1][i] = parmDict[pfx+pt+rbsx] if 'L' in TLS[0]: for i,pt in enumerate(['RBVL11:','RBVL22:','RBVL33:','RBVL12:','RBVL13:','RBVL23:']): TLS[1][i+6] = parmDict[pfx+pt+rbsx] if 'S' in TLS[0]: for i,pt in enumerate(['RBVS12:','RBVS13:','RBVS21:','RBVS23:','RBVS31:','RBVS32:','RBVSAA:','RBVSBB:']): TLS[1][i+12] = parmDict[pfx+pt+rbsx] if 'U' in TLS[0]: TLS[1][0] = parmDict[pfx+'RBVU:'+rbsx] XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Vector') UIJ = G2mth.UpdateRBUIJ(Bmat,Cart,RBObj) for i,x in enumerate(XYZ): atId = RBObj['Ids'][i] if parmDict[pfx+'Afrac:'+str(AtLookup[atId])]: parmDict[pfx+'Afrac:'+str(AtLookup[atId])] = RBObj['AtomFrac'][0] for j in [0,1,2]: parmDict[pfx+atxIds[j]+str(AtLookup[atId])] = x[j] if UIJ[i][0] == 'A': for j in range(6): parmDict[pfx+atuIds[j]+str(AtLookup[atId])] = UIJ[i][j+2] elif UIJ[i][0] == 'I': parmDict[pfx+'AUiso:'+str(AtLookup[atId])] = UIJ[i][1] for irb,RBObj in enumerate(RBModels.get('Residue',[])): jrb = RRBIds.index(RBObj['RBId']) rbsx = str(irb)+':'+str(jrb) for i,px in enumerate(['RBRPx:','RBRPy:','RBRPz:']): RBObj['Orig'][0][i] = parmDict[pfx+px+rbsx] for i,po in enumerate(['RBROa:','RBROi:','RBROj:','RBROk:']): RBObj['Orient'][0][i] = parmDict[pfx+po+rbsx] RBObj['Orient'][0] = G2mth.normQ(RBObj['Orient'][0]) RBObj['AtomFrac'][0] = parmDict[pfx+'RBRf:'+rbsx] TLS = RBObj['ThermalMotion'] if 'T' in TLS[0]: for i,pt in enumerate(['RBRT11:','RBRT22:','RBRT33:','RBRT12:','RBRT13:','RBRT23:']): RBObj['ThermalMotion'][1][i] = parmDict[pfx+pt+rbsx] if 'L' in TLS[0]: for i,pt in enumerate(['RBRL11:','RBRL22:','RBRL33:','RBRL12:','RBRL13:','RBRL23:']): RBObj['ThermalMotion'][1][i+6] = parmDict[pfx+pt+rbsx] if 'S' in TLS[0]: for i,pt in enumerate(['RBRS12:','RBRS13:','RBRS21:','RBRS23:','RBRS31:','RBRS32:','RBRSAA:','RBRSBB:']): RBObj['ThermalMotion'][1][i+12] = parmDict[pfx+pt+rbsx] if 'U' in TLS[0]: RBObj['ThermalMotion'][1][0] = parmDict[pfx+'RBRU:'+rbsx] for itors,tors in enumerate(RBObj['Torsions']): tors[0] = parmDict[pfx+'RBRTr;'+str(itors)+':'+rbsx] XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Residue') UIJ = G2mth.UpdateRBUIJ(Bmat,Cart,RBObj) for i,x in enumerate(XYZ): atId = RBObj['Ids'][i] if parmDict[pfx+'Afrac:'+str(AtLookup[atId])]: parmDict[pfx+'Afrac:'+str(AtLookup[atId])] = RBObj['AtomFrac'][0] for j in [0,1,2]: parmDict[pfx+atxIds[j]+str(AtLookup[atId])] = x[j] if UIJ[i][0] == 'A': for j in range(6): parmDict[pfx+atuIds[j]+str(AtLookup[atId])] = UIJ[i][j+2] elif UIJ[i][0] == 'I': parmDict[pfx+'AUiso:'+str(AtLookup[atId])] = UIJ[i][1] for irb,RBObj in enumerate(RBModels.get('Spin',[])): iAt = AtLookup[RBObj['Ids'][0]] jrb = SRBIds.index(RBObj['RBId'][0]) name = pfx+'RBSOa:%d:%d'%(iAt,jrb) for i,po in enumerate(['RBSOa:','RBSOi:','RBSOj:','RBSOk:']): name = pfx+'%s%d:%d'%(po,iAt,jrb) RBObj['Orient'][0][i] = parmDict[name] for ish in range(len(RBObj['RBId'])): jrb = SRBIds.index(RBObj['RBId'][ish]) if 'Q' not in RBObj['atType']: name = pfx+'RBSSh;%d;Radius:%d:%d'%(ish,iAt,jrb) RBObj['Radius'][ish][0] = parmDict[name] for item in RBObj['SHC'][ish]: name = pfx+'RBSSh;%d;%s:%d:%d'%(ish,item,iAt,jrb) RBObj['SHC'][ish][item][0] = parmDict[name]
[docs] def ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase): 'Computes rigid body derivatives; there are none for Spin RBs' atxIds = ['dAx:','dAy:','dAz:'] atuIds = ['AU11:','AU22:','AU33:','AU12:','AU13:','AU23:'] OIds = ['Oa:','Oi:','Oj:','Ok:'] RBIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]}) #these are lists of rbIds if not RBIds['Vector'] and not RBIds['Residue']: return VRBIds = RBIds['Vector'] RRBIds = RBIds['Residue'] RBData = rigidbodyDict for item in parmDict: if 'RBV' in item or 'RBR' in item: dFdvDict[item] = 0. #NB: this is a vector which is no. refl. long & must be filled! General = Phase['General'] cx,ct,cs,cia = General['AtomPtrs'] cell = General['Cell'][1:7] Amat,Bmat = G2lat.cell2AB(cell) rpd = np.pi/180. rpd2 = rpd**2 g = nl.inv(np.inner(Bmat,Bmat)) gvec = np.sqrt(np.array([g[0][0]**2,g[1][1]**2,g[2][2]**2, g[0][0]*g[1][1],g[0][0]*g[2][2],g[1][1]*g[2][2]])) AtLookup = G2mth.FillAtomLookUp(Phase['Atoms'],cia+8) pfx = str(Phase['pId'])+'::' RBModels = Phase['RBModels'] for irb,RBObj in enumerate(RBModels.get('Vector',[])): symAxis = RBObj.get('symAxis') VModel = RBData['Vector'][RBObj['RBId']] Q = RBObj['Orient'][0] jrb = VRBIds.index(RBObj['RBId']) rbsx = str(irb)+':'+str(jrb) dXdv = [] for iv in range(len(VModel['VectMag'])): dCdv = [] for vec in VModel['rbVect'][iv]: dCdv.append(G2mth.prodQVQ(Q,vec)) dXdv.append(np.inner(Bmat,np.array(dCdv)).T) XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Vector') for ia,atId in enumerate(RBObj['Ids']): atNum = AtLookup[atId] if parmDict[pfx+'Afrac:'+str(AtLookup[atId])]: dFdvDict[pfx+'RBVf:'+rbsx] += dFdvDict[pfx+'Afrac:'+str(atNum)] dx = 0.00001 for iv in range(len(VModel['VectMag'])): for ix in [0,1,2]: dFdvDict['::RBV;'+str(iv)+':'+str(jrb)] += dXdv[iv][ia][ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)] for i,name in enumerate(['RBVPx:','RBVPy:','RBVPz:']): dFdvDict[pfx+name+rbsx] += dFdvDict[pfx+atxIds[i]+str(atNum)] for iv in range(4): Q[iv] -= dx XYZ1 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q),symAxis) Q[iv] += 2.*dx XYZ2 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q),symAxis) Q[iv] -= dx dXdO = (XYZ2[ia]-XYZ1[ia])/(2.*dx) for ix in [0,1,2]: dFdvDict[pfx+'RBV'+OIds[iv]+rbsx] += dXdO[ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)] X = G2mth.prodQVQ(Q,Cart[ia]) dFdu = np.array([dFdvDict[pfx+Uid+str(AtLookup[atId])] for Uid in atuIds]).T/gvec dFdu = G2lat.U6toUij(dFdu.T) dFdu = np.tensordot(Amat,np.tensordot(Amat,dFdu,([1,0])),([0,1])) dFdu = G2lat.UijtoU6(dFdu) atNum = AtLookup[atId] if 'T' in RBObj['ThermalMotion'][0]: for i,name in enumerate(['RBVT11:','RBVT22:','RBVT33:','RBVT12:','RBVT13:','RBVT23:']): dFdvDict[pfx+name+rbsx] += dFdu[i] if 'L' in RBObj['ThermalMotion'][0]: dFdvDict[pfx+'RBVL11:'+rbsx] += rpd2*(dFdu[1]*X[2]**2+dFdu[2]*X[1]**2-dFdu[5]*X[1]*X[2]) dFdvDict[pfx+'RBVL22:'+rbsx] += rpd2*(dFdu[0]*X[2]**2+dFdu[2]*X[0]**2-dFdu[4]*X[0]*X[2]) dFdvDict[pfx+'RBVL33:'+rbsx] += rpd2*(dFdu[0]*X[1]**2+dFdu[1]*X[0]**2-dFdu[3]*X[0]*X[1]) dFdvDict[pfx+'RBVL12:'+rbsx] += rpd2*(-dFdu[3]*X[2]**2-2.*dFdu[2]*X[0]*X[1]+ dFdu[4]*X[1]*X[2]+dFdu[5]*X[0]*X[2]) dFdvDict[pfx+'RBVL13:'+rbsx] += rpd2*(-dFdu[4]*X[1]**2-2.*dFdu[1]*X[0]*X[2]+ dFdu[3]*X[1]*X[2]+dFdu[5]*X[0]*X[1]) dFdvDict[pfx+'RBVL23:'+rbsx] += rpd2*(-dFdu[5]*X[0]**2-2.*dFdu[0]*X[1]*X[2]+ dFdu[3]*X[0]*X[2]+dFdu[4]*X[0]*X[1]) if 'S' in RBObj['ThermalMotion'][0]: dFdvDict[pfx+'RBVS12:'+rbsx] += rpd*(dFdu[5]*X[1]-2.*dFdu[1]*X[2]) dFdvDict[pfx+'RBVS13:'+rbsx] += rpd*(-dFdu[5]*X[2]+2.*dFdu[2]*X[1]) dFdvDict[pfx+'RBVS21:'+rbsx] += rpd*(-dFdu[4]*X[0]+2.*dFdu[0]*X[2]) dFdvDict[pfx+'RBVS23:'+rbsx] += rpd*(dFdu[4]*X[2]-2.*dFdu[2]*X[0]) dFdvDict[pfx+'RBVS31:'+rbsx] += rpd*(dFdu[3]*X[0]-2.*dFdu[0]*X[1]) dFdvDict[pfx+'RBVS32:'+rbsx] += rpd*(-dFdu[3]*X[1]+2.*dFdu[1]*X[0]) dFdvDict[pfx+'RBVSAA:'+rbsx] += rpd*(dFdu[4]*X[1]-dFdu[3]*X[2]) dFdvDict[pfx+'RBVSBB:'+rbsx] += rpd*(dFdu[5]*X[0]-dFdu[3]*X[2]) if 'U' in RBObj['ThermalMotion'][0]: dFdvDict[pfx+'RBVU:'+rbsx] += dFdvDict[pfx+'AUiso:'+str(AtLookup[atId])] for irb,RBObj in enumerate(RBModels.get('Residue',[])): symAxis = RBObj.get('symAxis') Q = RBObj['Orient'][0] jrb = RRBIds.index(RBObj['RBId']) torData = RBData['Residue'][RBObj['RBId']]['rbSeq'] rbsx = str(irb)+':'+str(jrb) XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Residue') for itors,tors in enumerate(RBObj['Torsions']): #derivative error? tname = pfx+'RBRTr;'+str(itors)+':'+rbsx orId,pvId = torData[itors][:2] pivotVec = Cart[orId]-Cart[pvId] QA = G2mth.AVdeg2Q(-0.001,pivotVec) QB = G2mth.AVdeg2Q(0.001,pivotVec) for ir in torData[itors][3]: atNum = AtLookup[RBObj['Ids'][ir]] rVec = Cart[ir]-Cart[pvId] dR = G2mth.prodQVQ(QB,rVec)-G2mth.prodQVQ(QA,rVec) dRdT = np.inner(Bmat,G2mth.prodQVQ(Q,dR))/.002 for ix in [0,1,2]: dFdvDict[tname] += dRdT[ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)] for ia,atId in enumerate(RBObj['Ids']): atNum = AtLookup[atId] if parmDict[pfx+'Afrac:'+str(AtLookup[atId])]: dFdvDict[pfx+'RBRf:'+rbsx] += dFdvDict[pfx+'Afrac:'+str(atNum)] dx = 0.00001 for i,name in enumerate(['RBRPx:','RBRPy:','RBRPz:']): dFdvDict[pfx+name+rbsx] += dFdvDict[pfx+atxIds[i]+str(atNum)] for iv in range(4): Q[iv] -= dx XYZ1 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q),symAxis) Q[iv] += 2.*dx XYZ2 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q),symAxis) Q[iv] -= dx dXdO = (XYZ2[ia]-XYZ1[ia])/(2.*dx) for ix in [0,1,2]: dFdvDict[pfx+'RBR'+OIds[iv]+rbsx] += dXdO[ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)] X = G2mth.prodQVQ(Q,Cart[ia]) dFdu = np.array([dFdvDict[pfx+Uid+str(AtLookup[atId])] for Uid in atuIds]).T/gvec dFdu = G2lat.U6toUij(dFdu.T) dFdu = np.tensordot(Amat.T,np.tensordot(Amat,dFdu,([1,0])),([0,1])) dFdu = G2lat.UijtoU6(dFdu) atNum = AtLookup[atId] if 'T' in RBObj['ThermalMotion'][0]: for i,name in enumerate(['RBRT11:','RBRT22:','RBRT33:','RBRT12:','RBRT13:','RBRT23:']): dFdvDict[pfx+name+rbsx] += dFdu[i] if 'L' in RBObj['ThermalMotion'][0]: dFdvDict[pfx+'RBRL11:'+rbsx] += rpd2*(dFdu[1]*X[2]**2+dFdu[2]*X[1]**2-dFdu[5]*X[1]*X[2]) dFdvDict[pfx+'RBRL22:'+rbsx] += rpd2*(dFdu[0]*X[2]**2+dFdu[2]*X[0]**2-dFdu[4]*X[0]*X[2]) dFdvDict[pfx+'RBRL33:'+rbsx] += rpd2*(dFdu[0]*X[1]**2+dFdu[1]*X[0]**2-dFdu[3]*X[0]*X[1]) dFdvDict[pfx+'RBRL12:'+rbsx] += rpd2*(-dFdu[3]*X[2]**2-2.*dFdu[2]*X[0]*X[1]+ dFdu[4]*X[1]*X[2]+dFdu[5]*X[0]*X[2]) dFdvDict[pfx+'RBRL13:'+rbsx] += rpd2*(dFdu[4]*X[1]**2-2.*dFdu[1]*X[0]*X[2]+ dFdu[3]*X[1]*X[2]+dFdu[5]*X[0]*X[1]) dFdvDict[pfx+'RBRL23:'+rbsx] += rpd2*(dFdu[5]*X[0]**2-2.*dFdu[0]*X[1]*X[2]+ dFdu[3]*X[0]*X[2]+dFdu[4]*X[0]*X[1]) if 'S' in RBObj['ThermalMotion'][0]: dFdvDict[pfx+'RBRS12:'+rbsx] += rpd*(dFdu[5]*X[1]-2.*dFdu[1]*X[2]) dFdvDict[pfx+'RBRS13:'+rbsx] += rpd*(-dFdu[5]*X[2]+2.*dFdu[2]*X[1]) dFdvDict[pfx+'RBRS21:'+rbsx] += rpd*(-dFdu[4]*X[0]+2.*dFdu[0]*X[2]) dFdvDict[pfx+'RBRS23:'+rbsx] += rpd*(dFdu[4]*X[2]-2.*dFdu[2]*X[0]) dFdvDict[pfx+'RBRS31:'+rbsx] += rpd*(dFdu[3]*X[0]-2.*dFdu[0]*X[1]) dFdvDict[pfx+'RBRS32:'+rbsx] += rpd*(-dFdu[3]*X[1]+2.*dFdu[1]*X[0]) dFdvDict[pfx+'RBRSAA:'+rbsx] += rpd*(dFdu[4]*X[1]-dFdu[3]*X[2]) dFdvDict[pfx+'RBRSBB:'+rbsx] += rpd*(dFdu[5]*X[0]-dFdu[3]*X[2]) if 'U' in RBObj['ThermalMotion'][0]: dFdvDict[pfx+'RBRU:'+rbsx] += dFdvDict[pfx+'AUiso:'+str(AtLookup[atId])]
[docs] def MakeSpHarmFF(HKL,Bmat,SHCdict,Tdata,hType,FFtables,ORBtables,BLtables,FF,SQ,ifDeriv=False): ''' Computes hkl dependent form factors & derivatives from spinning rigid bodies :param array HKL: reflection hkl set to be considered :param array Bmat: inv crystal to Cartesian transfomation matrix :param dict SHCdict: RB spin/deformation data :param array Tdata: atom type info :param str hType: histogram type :param dict FFtables: x-ray form factor tables :param dict ORBtables: x-ray orbital form factor tables :param dict BLtables: neutron scattering lenghts :param array FF: form factors - will be modified by adding the spin/deformation RB spherical harmonics terms :param array SQ: 1/4d^2 for the HKL set :param bool ifDeriv: True if dFF/dcoff to be returned :returns: dict dFFdS of derivatives if ifDeriv = True ''' def MakePolar(Orient,QB): QA = G2mth.invQ(Orient) #rotates about chosen axis Q = G2mth.prodQQ(QB,QA) #might be switched? QB,QA is order for plotting return G2lat.H2ThPh(np.reshape(HKL,(-1,3)),Bmat,Q) dFFdS = {} atFlg = [] Th,Ph = G2lat.H2ThPh(np.reshape(HKL,(-1,3)),Bmat,[1.,0.,0.,1.]) SQR = np.repeat(SQ,HKL.shape[1]) for iAt,Atype in enumerate(Tdata): if 'Q' in Atype: Th,Ph = G2lat.H2ThPh(np.reshape(HKL,(-1,3)),Bmat,[1.,0.,0.,1.]) atFlg.append(1.0) SHdat = SHCdict[iAt] symAxis = np.array(SHdat['symAxis']) QB = G2mth.make2Quat(np.array([0,0,1.]),symAxis)[0] #position obj polar axis Th,Ph = MakePolar([SHdat['Oa'],SHdat['Oi'],SHdat['Oj'],SHdat['Ok']],QB) ThP,PhP = MakePolar([SHdat['Oa']+.0001,SHdat['Oi'],SHdat['Oj'],SHdat['Ok']],QB) dp = 0.00001 ThPi,PhPi = MakePolar([SHdat['Oa'],SHdat['Oi']+dp,SHdat['Oj'],SHdat['Ok']],QB) ThPj,PhPj = MakePolar([SHdat['Oa'],SHdat['Oi'],SHdat['Oj']+dp,SHdat['Ok']],QB) ThPk,PhPk = MakePolar([SHdat['Oa'],SHdat['Oi'],SHdat['Oj'],SHdat['Ok']+dp],QB) ThM,PhM = MakePolar([SHdat['Oa']-.0001,SHdat['Oi'],SHdat['Oj'],SHdat['Ok']],QB) ThMi,PhMi = MakePolar([SHdat['Oa'],SHdat['Oi']-dp,SHdat['Oj'],SHdat['Ok']],QB) ThMj,PhMj = MakePolar([SHdat['Oa'],SHdat['Oi'],SHdat['Oj']-dp,SHdat['Ok']],QB) ThMk,PhMk = MakePolar([SHdat['Oa'],SHdat['Oi'],SHdat['Oj'],SHdat['Ok']-dp],QB) QR = np.repeat(twopi*np.sqrt(4.*SQ),HKL.shape[1]) #refl Q for Bessel fxn FF[:,iAt] = 0. ishl = 0 dSHdO = np.zeros(HKL.shape[0]*HKL.shape[1]) dSHdOi = np.zeros(HKL.shape[0]*HKL.shape[1]) dSHdOj = np.zeros(HKL.shape[0]*HKL.shape[1]) dSHdOk = np.zeros(HKL.shape[0]*HKL.shape[1]) if '0' not in SHdat: #no spin RB for atom Q?? break Shell = SHdat['0'] Irb = Shell['ShR'] Oname = 'Oa:%d:%s'%(iAt,Irb) Oiname = 'Oi:%d:%s'%(iAt,Irb) Ojname = 'Oj:%d:%s'%(iAt,Irb) Okname = 'Ok:%d:%s'%(iAt,Irb) while True: shl = '%d'%ishl if shl not in SHdat: break Shell = SHdat[shl] Atm = Shell['AtType'] Nat = Shell['Natoms'] Irb = Shell['ShR'] if 'X' in hType: if 'Q' in Atm: SFF = 0.0 else: SFF = G2el.ScatFac(FFtables[Atm],SQR) elif 'N' in hType: SFF = G2el.getBLvalues(BLtables)[Atm] Rname = 'Sh;%s;Radius:%d:%s'%(shl,iAt,Irb) if 'Q' in Atm: dBSdR= 0.0 FF[:,iAt] = 0.0 else: R = Shell['Radius'] R0 = sp.spherical_jn(0,QR*R)/(4.*np.pi) R0P = sp.spherical_jn(0,QR*(R+0.01))/(4.*np.pi) R0M = sp.spherical_jn(0,QR*(R-0.01))/(4.*np.pi) dBSdR = Nat*SFF*(R0P-R0M)/0.02 FF[:,iAt] += Nat*SFF*R0 #Bessel function; L=0 term for item in Shell: if 'C(' in item: l,m = eval(item.strip('C').strip('c')) SH = G2lat.KslCalc(item,Th,Ph) SHP = G2lat.KslCalc(item,ThP,PhP) SHPi = G2lat.KslCalc(item,ThPi,PhPi) SHPj = G2lat.KslCalc(item,ThPj,PhPj) SHPk = G2lat.KslCalc(item,ThPk,PhPk) SHM = G2lat.KslCalc(item,ThM,PhM) SHMi = G2lat.KslCalc(item,ThMi,PhMi) SHMj = G2lat.KslCalc(item,ThMj,PhMj) SHMk = G2lat.KslCalc(item,ThMk,PhMk) BS = 1.0 if 'Q' in Atm: BS = sp.spherical_jn(l,1.0) #Slater term here? else: BS = sp.spherical_jn(l,QR*R)/(4.*np.pi) #Bessel function BSP = sp.spherical_jn(l,QR*(R+0.01))/(4.*np.pi) BSM = sp.spherical_jn(l,QR*(R-0.01))/(4.*np.pi) dBSdR += Nat*SFF*SH*Shell[item]*(BSP-BSM)/0.02 dSHdO += Nat*SFF*BS*Shell[item]*(SHP-SHM)/0.0002 dSHdOi += Nat*SFF*BS*Shell[item]*(SHPi-SHMi)/(2.*dp) dSHdOj += Nat*SFF*BS*Shell[item]*(SHPj-SHMj)/(2.*dp) dSHdOk += Nat*SFF*BS*Shell[item]*(SHPk-SHMk)/(2.*dp) FF[:,iAt] += Nat*SFF*BS*SH*Shell[item] name = 'Sh;%s;%s:%d:%s'%(shl,item,iAt,Irb) dFFdS[name] = Nat*SFF*BS*SH if 'Q' not in Atm: dFFdS[Rname] = dBSdR ishl += 1 dFFdS[Oname] = dSHdO dFFdS[Oiname] = dSHdOi dFFdS[Ojname] = dSHdOj dFFdS[Okname] = dSHdOk elif iAt in SHCdict and 'X' in hType: orKeys = [item for item in ORBtables[Atype] if item not in ['ZSlater','NSlater','SZE','popCore','popVal']] orbs = SHCdict[iAt] UVmat = np.inner(nl.inv(SHCdict[-iAt]['UVmat']),Bmat) Th,Ph = G2lat.H2ThPh(np.reshape(HKL,(-1,3)),UVmat,[1.,0.,0.,1.]) atFlg.append(1.0) orbTable = ORBtables[Atype][orKeys[0]] ffOrb = {item:orbTable[item] for item in orbTable if item not in ['ZSlater','NSlater','SZE','popCore','popVal']} FFcore = G2el.ScatFac(ffOrb,SQR) #core FFtot = np.zeros_like(FFcore) for orb in orbs: if 'UVmat' in orb: continue Ne = orbs[orb].get('Ne',1.0) # not there for non <j0> orbs if 'kappa' in orbs[orb]: kappa = orbs[orb]['kappa'] SQk = SQR/kappa**2 korb = orb orbTable = ORBtables[Atype][orKeys[int(orb)+1]] ffOrb = {item:orbTable[item] for item in orbTable if item not in ['ZSlater','NSlater','SZE','popCore','popVal']} ff = Ne*G2el.ScatFac(ffOrb,SQk) dffdk = G2el.ScatFacDer(ffOrb,SQk) dSH = 0.0 if '<j0>' in orKeys[int(orb)+1]: dSH = 1.0 for term in orbs[orb]: if 'D(' in term: item = term.replace('D','C') SH = G2lat.KslCalc(item,Th,Ph) FFtot += SH*orbs[orb][term]*ff name = 'A%s%s:%d'%(term,orb,iAt) dFFdS[name] = SH*ff dSH += SH*orbs[orb][term] elif 'Ne' in term: name = 'ANe%s:%d'%(orb,iAt) dFFdS[name] = ff/Ne if 'j0' in orKeys[int(orb)+1]: FFtot += ff name = 'Akappa%s:%d'%(korb,iAt) if name in dFFdS: dFFdS[name] += -2.0*Ne*SQk*dSH*dffdk/kappa else: dFFdS[name] = -2.0*Ne*SQk*dSH*dffdk/kappa FF[:,iAt] = FFcore+FFtot else: atFlg.append(0.) if ifDeriv: return dFFdS,atFlg
def GetSHC(pfx,parmDict): SHCdict = {} for parm in parmDict: if pfx+'RBS' in parm and 'RBS;' not in parm: #skips radii parms items = parm.split(':') atid = int(items[-2]) name = items[2][3:] #strip 'RBS' if atid not in SHCdict: SHCdict[atid] = {} if ';' not in name: # will get Oa, Oi ,Oj, Ok if name not in ['AtNo','Px','Py','Pz','SytSym']: SHCdict[atid][name] = parmDict[parm] continue bits = name.split(';') shno = bits[1] if shno not in SHCdict[atid]: SHCdict[atid][shno] = {} if 'AtType' in bits[0] or 'Natoms' in bits[0] or 'ShR' in bits[0]: SHCdict[atid][shno][bits[0]] = parmDict[parm] elif 'Sh' in name: cof = bits[2] SHCdict[atid][shno][cof] = parmDict[parm] if pfx+'AD(' in parm or pfx+'Akappa' in parm or pfx+'ANe' in parm: #atom deformation parms items = parm.split(':') atid = int(items[-1]) name = items[2][1:] #strip 'A' if atid not in SHCdict: SHCdict[atid] = {} orb = name[-1] if orb not in SHCdict[atid]: SHCdict[atid][orb] = {} SHCdict[atid][orb][name[:-1]] = parmDict[parm] #[atom id][orb no.][deform. coef] if pfx+'UVmat' in parm: items = parm.split(':') atid = int(items[-1]) if -atid not in SHCdict: SHCdict[-atid] = {} SHCdict[-atid]['UVmat'] = parmDict[parm] if len(SHCdict): return {pfx:SHCdict,} else: return {} ################################################################################ ##### Penalty & restraint functions ################################################################################
[docs] def penaltyFxn(HistoPhases,calcControls,parmDict,varyList): 'Compute user-supplied and built-in restraint functions' Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases pNames = [] pVals = [] pWt = [] negWt = {} pWsum = {} pWnum = {} for phase in Phases: pId = Phases[phase]['pId'] negWt[pId] = Phases[phase]['General']['Pawley neg wt'] General = Phases[phase]['General'] cx,ct,cs,cia = General['AtomPtrs'] textureData = General['SH Texture'] SGData = General['SGData'] Atoms = Phases[phase]['Atoms'] AtLookup = G2mth.FillAtomLookUp(Phases[phase]['Atoms'],cia+8) cell = General['Cell'][1:7] Amat,Bmat = G2lat.cell2AB(cell) if phase not in restraintDict: continue phaseRest = restraintDict[phase] names = [['Bond','Bonds'],['Angle','Angles'],['Plane','Planes'], ['Chiral','Volumes'],['Torsion','Torsions'],['Rama','Ramas'], ['ChemComp','Sites'],['Texture','HKLs'],['General','General'], ['Moments','Moments']] for name,rest in names: pWsum[name] = 0. pWnum[name] = 0 if name not in phaseRest: continue itemRest = phaseRest[name] if itemRest[rest] and itemRest['Use']: wt = itemRest.get('wtFactor',1.) if name in ['Bond','Angle','Plane','Chiral']: for i,[indx,ops,obs,esd] in enumerate(itemRest[rest]): pNames.append(str(pId)+':'+name+':'+str(i)) XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx)) XYZ = G2mth.getSyXYZ(XYZ,ops,SGData) if name == 'Bond': calc = G2mth.getRestDist(XYZ,Amat) elif name == 'Angle': calc = G2mth.getRestAngle(XYZ,Amat) elif name == 'Plane': calc = G2mth.getRestPlane(XYZ,Amat) elif name == 'Chiral': calc = G2mth.getRestChiral(XYZ,Amat) pVals.append(obs-calc) pWt.append(wt/esd**2) pWsum[name] += wt*((obs-calc)/esd)**2 pWnum[name] += 1 elif name in ['Torsion','Rama']: coeffDict = itemRest['Coeff'] for i,[indx,ops,cofName,esd] in enumerate(itemRest[rest]): pNames.append(str(pId)+':'+name+':'+str(i)) XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx)) XYZ = G2mth.getSyXYZ(XYZ,ops,SGData) if name == 'Torsion': tor = G2mth.getRestTorsion(XYZ,Amat) restr,calc = G2mth.calcTorsionEnergy(tor,coeffDict[cofName]) else: phi,psi = G2mth.getRestRama(XYZ,Amat) restr,calc = G2mth.calcRamaEnergy(phi,psi,coeffDict[cofName]) pVals.append(restr) pWt.append(wt/esd**2) pWsum[name] += wt*(restr/esd)**2 pWnum[name] += 1 elif name == 'ChemComp': for i,[indx,factors,obs,esd] in enumerate(itemRest[rest]): pNames.append(str(pId)+':'+name+':'+str(i)) mul = np.array(G2mth.GetAtomItemsById(Atoms,AtLookup,indx,cs+1)) frac = np.array(G2mth.GetAtomFracByID(pId,parmDict,AtLookup,indx)) calc = np.sum(mul*frac*factors) pVals.append(obs-calc) pWt.append(wt/esd**2) pWsum[name] += wt*((obs-calc)/esd)**2 pWnum[name] += 1 elif name == 'Moments': for i,[indx,obs,esd] in enumerate(itemRest[rest]): pNames.append(str(pId)+':'+name+':'+str(i)) moms = G2mth.GetAtomMomsByID(pId,parmDict,AtLookup,indx) obs = 0. calcs = [] for i,mom in enumerate(moms): calcs.append(G2mth.GetMag(mom,cell)) obs += calcs[-1] obs /= len(indx) for calc in calcs: pVals.append(obs-calc) pWt.append(wt/esd**2) pWsum[name] += wt*((obs-calc)/esd)**2 pWnum[name] += 1 elif name == 'Texture': SHkeys = list(textureData['SH Coeff'][1].keys()) SHCoef = G2mth.GetSHCoeff(pId,parmDict,SHkeys) shModels = ['cylindrical','none','shear - 2/m','rolling - mmm'] SamSym = dict(zip(shModels,['0','-1','2/m','mmm'])) for i,[hkl,grid,esd1,ifesd2,esd2] in enumerate(itemRest[rest]): PH = np.array(hkl) phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData) ODFln = G2lat.Flnh(SHCoef,phi,beta,SGData) R,P,Z = G2mth.getRestPolefig(ODFln,SamSym[textureData['Model']],grid) Z1 = ma.masked_greater(Z,0.0) #is this + or -? IndZ1 = np.array(ma.nonzero(Z1)) for ind in IndZ1.T: pNames.append('%d:%s:%d:%.2f:%.2f'%(pId,name,i,R[ind[0],ind[1]],P[ind[0],ind[1]])) pVals.append(Z1[ind[0]][ind[1]]) pWt.append(wt/esd1**2) pWsum[name] += wt*(-Z1[ind[0]][ind[1]]/esd1)**2 pWnum[name] += 1 if ifesd2: Z2 = 1.-Z for ind in np.ndindex(grid,grid): pNames.append('%d:%s:%d:%.2f:%.2f'%(pId,name+'-unit',i,R[ind[0],ind[1]],P[ind[0],ind[1]])) pVals.append(Z2[ind[0]][ind[1]]) pWt.append(wt/esd2**2) pWsum[name] += wt*(Z2/esd2)**2 pWnum[name] += 1 elif name == 'General': for i,(eq,obs,esd) in enumerate(itemRest[rest]): calcobj = G2obj.ExpressionCalcObj(eq) calcobj.SetupCalc(parmDict) calc = calcobj.EvalExpression() try: pVals.append(obs-calc) pWt.append(wt/esd**2) pWsum[name] += wt*((obs-calc)/esd)**2 pWnum[name] += 1 pNames.append(str(pId)+':'+name+':'+str(i)) except: print('Error computing General restraint #{}'.format(i+1)) for phase in Phases: name = 'SH-Pref.Ori.' pId = Phases[phase]['pId'] General = Phases[phase]['General'] SGData = General['SGData'] cell = General['Cell'][1:7] pWsum[name] = 0.0 pWnum[name] = 0 for hist in Phases[phase]['Histograms']: if not Phases[phase]['Histograms'][hist]['Use']: continue if hist in Histograms and 'PWDR' in hist: hId = Histograms[hist]['hId'] phfx = '%d:%d:'%(pId,hId) if calcControls.get(phfx+'poType','') == 'SH': toler = calcControls[phfx+'SHtoler'] wt = 1./toler**2 HKLs = np.array(calcControls[phfx+'SHhkl']) SHnames = calcControls[phfx+'SHnames'] SHcof = dict(zip(SHnames,[parmDict[phfx+cof] for cof in SHnames])) for i,PH in enumerate(HKLs): phi,beta = G2lat.CrsAng(PH,cell,SGData) SH3Coef = {} for item in SHcof: L,N = eval(item.strip('C')) SH3Coef['C%d,0,%d'%(L,N)] = SHcof[item] ODFln = G2lat.Flnh(SH3Coef,phi,beta,SGData) X = np.linspace(0,90.0,26) Y = ma.masked_greater(G2lat.polfcal(ODFln,'0',X,0.0),0.0) #+ or -? IndY = ma.nonzero(Y) for ind in IndY[0]: pNames.append('%d:%d:%s:%d:%.2f'%(pId,hId,name,i,X[ind])) pVals.append(Y[ind]) pWt.append(wt) pWsum[name] += wt*(Y[ind])**2 pWnum[name] += 1 pWsum['PWLref'] = 0. pWnum['PWLref'] = 0 for item in varyList: if 'PWLref' in item and parmDict[item] < 0.: pId = int(item.split(':')[0]) if negWt[pId]: pNames.append(item) pVals.append(parmDict[item]) pWt.append(negWt[pId]) pWsum['PWLref'] += negWt[pId]*(parmDict[item])**2 pWnum['PWLref'] += 1 pVals = np.array(pVals) pWt = np.array(pWt) #should this be np.sqrt? return pNames,pVals,pWt,pWsum,pWnum
[docs] def penaltyDeriv(pNames,pVal,HistoPhases,calcControls,parmDict,varyList): '''Compute derivatives on user-supplied and built-in restraint (penalty) functions where pNames is list of restraint labels :returns: array pDerv: partial derivatives by variable# in varList and restraint# in pNames (pDerv[variable#][restraint#]) ''' Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases pDerv = np.zeros((len(varyList),len(pVal))) for pName in pNames: # loop over restraints if 'General' == pName.split(':')[1]: # initialize for General restraint(s) here parmDict0 = parmDict.copy() # setup steps for each parameter stepDict = {} for parm in varyList: stepDict[parm] = G2obj.getVarStep(parm,parmDict) break for phase in Phases: # if phase not in restraintDict: # continue pId = Phases[phase]['pId'] General = Phases[phase]['General'] cx,ct,cs,cia = General['AtomPtrs'] SGData = General['SGData'] Atoms = Phases[phase]['Atoms'] AtLookup = G2mth.FillAtomLookUp(Phases[phase]['Atoms'],cia+8) cell = General['Cell'][1:7] Amat,Bmat = G2lat.cell2AB(cell) textureData = General['SH Texture'] SHkeys = list(textureData['SH Coeff'][1].keys()) SHCoef = G2mth.GetSHCoeff(pId,parmDict,SHkeys) shModels = ['cylindrical','none','shear - 2/m','rolling - mmm'] SamSym = dict(zip(shModels,['0','-1','2/m','mmm'])) sam = SamSym[textureData['Model']] phaseRest = restraintDict.get(phase,{}) names = {'Bond':'Bonds','Angle':'Angles','Plane':'Planes', 'Chiral':'Volumes','Torsion':'Torsions','Rama':'Ramas', 'ChemComp':'Sites','Texture':'HKLs','Moments':'Moments'} lasthkl = np.array([0,0,0]) for ip,pName in enumerate(pNames): # loop over restraints pnames = pName.split(':') if pId == int(pnames[0]): name = pnames[1] if 'PWL' in pName: pDerv[varyList.index(pName)][ip] += 1. continue elif 'SH-' in pName: continue Id = int(pnames[2]) itemRest = phaseRest[name] if name in ['Bond','Angle','Plane','Chiral']: indx,ops,obs,esd = itemRest[names[name]][Id] dNames = [] for ind in indx: dNames += [str(pId)+'::dA'+Xname+':'+str(AtLookup[ind]) for Xname in ['x','y','z']] XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx)) if name == 'Bond': deriv = G2mth.getRestDeriv(G2mth.getRestDist,XYZ,Amat,ops,SGData) elif name == 'Angle': deriv = G2mth.getRestDeriv(G2mth.getRestAngle,XYZ,Amat,ops,SGData) elif name == 'Plane': deriv = G2mth.getRestDeriv(G2mth.getRestPlane,XYZ,Amat,ops,SGData) elif name == 'Chiral': deriv = G2mth.getRestDeriv(G2mth.getRestChiral,XYZ,Amat,ops,SGData) elif name in ['Torsion','Rama']: coffDict = itemRest['Coeff'] indx,ops,cofName,esd = itemRest[names[name]][Id] dNames = [] for ind in indx: dNames += [str(pId)+'::dA'+Xname+':'+str(AtLookup[ind]) for Xname in ['x','y','z']] XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx)) if name == 'Torsion': deriv = G2mth.getTorsionDeriv(XYZ,Amat,coffDict[cofName]) else: deriv = G2mth.getRamaDeriv(XYZ,Amat,coffDict[cofName]) elif name == 'ChemComp': indx,factors,obs,esd = itemRest[names[name]][Id] dNames = [] for ind in indx: dNames += [str(pId)+'::Afrac:'+str(AtLookup[ind])] mul = np.array(G2mth.GetAtomItemsById(Atoms,AtLookup,indx,cs+1)) deriv = mul*factors elif name == 'Moments': indx,obs,esd = itemRest[names[name]][Id] dNames = [] deriv = [] moms = G2mth.GetAtomMomsByID(pId,parmDict,AtLookup,indx) for i,ind in enumerate(indx): calc = G2mth.GetMag(moms[i],cell) dNames += [str(pId)+'::'+Xname+':'+str(AtLookup[ind]) for Xname in ['AMx','AMy','AMz']] deriv += list(G2mth.GetMagDerv(moms[i],cell)*np.sign((obs-calc))) elif 'Texture' in name: deriv = [] dNames = [] hkl,grid,esd1,ifesd2,esd2 = itemRest[names[name]][Id] hkl = np.array(hkl) if np.any(lasthkl-hkl): phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData) ODFln = G2lat.Flnh(SHCoef,phi,beta,SGData) lasthkl = copy.copy(hkl) if 'unit' in name: pass else: gam = float(pnames[3]) psi = float(pnames[4]) for SHname in ODFln: l,m,n = eval(SHname[1:]) Ksl = G2lat.GetKsl(l,m,sam,psi,gam)[0] dNames += [str(pId)+'::'+SHname] deriv.append(-ODFln[SHname][0]*Ksl/SHCoef[SHname]) elif name == 'General': deriv = [] dNames = [] eq,obs,esd = itemRest[name][Id] calcobj = G2obj.ExpressionCalcObj(eq) parmlist = list(eq.assgnVars.values()) # parameters used in this expression for parm in parmlist: # expand list if any parms are determined by constraints if parm in G2mv.GetDependentVars(): parmlist += G2mv.GetIndependentVars() break for ind,var in enumerate(varyList): drv = 0 if var in parmlist: step = stepDict.get(var,1e-5) calc = [] # apply step to parameter oneparm = True for s in -step,2*step: parmDict[var] += s # extend shift if needed to other parameters if var in G2mv.independentVars: G2mv.Dict2Map(parmDict) oneparm = False elif var in G2mv.dependentVars: G2mv.Map2Dict(parmDict,[]) oneparm = False if 'RB' in var: ApplyRBModels(parmDict,Phases,rigidbodyDict) # test oneparm = False calcobj.SetupCalc(parmDict) calc.append(calcobj.EvalExpression()) drv = (calc[1]-calc[0])*.5/step # restore the dict if oneparm: parmDict[var] = parmDict0[var] else: parmDict = parmDict0.copy() else: drv = 0 pDerv[ind][ip] = drv # Add derivatives into matrix, if needed for dName,drv in zip(dNames,deriv): try: ind = varyList.index(dName) pDerv[ind][ip] += drv except ValueError: pass lasthkl = np.array([0,0,0]) for ip,pName in enumerate(pNames): deriv = [] dNames = [] pnames = pName.split(':') if 'SH-' in pName and pId == int(pnames[0]): hId = int(pnames[1]) phfx = '%d:%d:'%(pId,hId) psi = float(pnames[4]) HKLs = calcControls[phfx+'SHhkl'] SHnames = calcControls[phfx+'SHnames'] SHcof = dict(zip(SHnames,[parmDict[phfx+cof] for cof in SHnames])) hkl = np.array(HKLs[int(pnames[3])]) if np.any(lasthkl-hkl): phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData) SH3Coef = {} for item in SHcof: L,N = eval(item.strip('C')) SH3Coef['C%d,0,%d'%(L,N)] = SHcof[item] ODFln = G2lat.Flnh(SH3Coef,phi,beta,SGData) lasthkl = copy.copy(hkl) for SHname in SHnames: l,n = eval(SHname[1:]) SH3name = 'C%d,0,%d'%(l,n) Ksl = G2lat.GetKsl(l,0,'0',psi,0.0)[0] dNames += [phfx+SHname] deriv.append(ODFln[SH3name][0]*Ksl/SHcof[SHname]) for dName,drv in zip(dNames,deriv): try: ind = varyList.index(dName) pDerv[ind][ip] += drv except ValueError: pass return pDerv
################################################################################ ##### Function & derivative calculations ################################################################################
[docs] def GetAtomFXU(pfx,calcControls,parmDict): 'Needs a doc string' Natoms = calcControls['Natoms'][pfx] Tdata = Natoms*[' ',] Mdata = np.zeros(Natoms) IAdata = Natoms*[' ',] Fdata = np.zeros(Natoms) Xdata = np.zeros((3,Natoms)) dXdata = np.zeros((3,Natoms)) Uisodata = np.zeros(Natoms) Uijdata = np.zeros((6,Natoms)) Gdata = np.zeros((3,Natoms)) keys = {'Atype:':Tdata,'Amul:':Mdata,'Afrac:':Fdata,'AI/A:':IAdata, 'dAx:':dXdata[0],'dAy:':dXdata[1],'dAz:':dXdata[2], 'Ax:':Xdata[0],'Ay:':Xdata[1],'Az:':Xdata[2],'AUiso:':Uisodata, 'AU11:':Uijdata[0],'AU22:':Uijdata[1],'AU33:':Uijdata[2], 'AU12:':Uijdata[3],'AU13:':Uijdata[4],'AU23:':Uijdata[5], 'AMx:':Gdata[0],'AMy:':Gdata[1],'AMz:':Gdata[2],} for iatm in range(Natoms): for key in keys: parm = pfx+key+str(iatm) if parm in parmDict: keys[key][iatm] = parmDict[parm] Fdata = np.where(Fdata,Fdata,1.e-8) #avoid divide by zero in derivative calc. Gdata = np.where(Gdata,Gdata,1.e-8) #avoid divide by zero in derivative calc. return Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata,Gdata
[docs] def GetAtomSSFXU(pfx,calcControls,parmDict): 'Needs a doc string' Natoms = calcControls['Natoms'][pfx] maxSSwave = calcControls['maxSSwave'][pfx] Nwave = {'F':maxSSwave['Sfrac'],'X':maxSSwave['Spos'],'Y':maxSSwave['Spos'],'Z':maxSSwave['Spos'], 'U':maxSSwave['Sadp'],'M':maxSSwave['Smag'],'T':maxSSwave['Spos']} XSSdata = np.zeros((6,maxSSwave['Spos'],Natoms)) FSSdata = np.zeros((2,maxSSwave['Sfrac'],Natoms)) USSdata = np.zeros((12,maxSSwave['Sadp'],Natoms)) MSSdata = np.zeros((6,maxSSwave['Smag'],Natoms)) waveTypes = [] keys = {'Fsin:':FSSdata[0],'Fcos:':FSSdata[1],'Fzero:':FSSdata[0],'Fwid:':FSSdata[1], 'Tmin:':XSSdata[0],'Tmax:':XSSdata[1],'Xmax:':XSSdata[2],'Ymax:':XSSdata[3],'Zmax:':XSSdata[4], 'Xsin:':XSSdata[0],'Ysin:':XSSdata[1],'Zsin:':XSSdata[2],'Xcos:':XSSdata[3],'Ycos:':XSSdata[4],'Zcos:':XSSdata[5], 'U11sin:':USSdata[0],'U22sin:':USSdata[1],'U33sin:':USSdata[2],'U12sin:':USSdata[3],'U13sin:':USSdata[4],'U23sin:':USSdata[5], 'U11cos:':USSdata[6],'U22cos:':USSdata[7],'U33cos:':USSdata[8],'U12cos:':USSdata[9],'U13cos:':USSdata[10],'U23cos:':USSdata[11], 'MXsin:':MSSdata[0],'MYsin:':MSSdata[1],'MZsin:':MSSdata[2],'MXcos:':MSSdata[3],'MYcos:':MSSdata[4],'MZcos:':MSSdata[5]} for iatm in range(Natoms): wavetype = [parmDict.get(pfx+kind+'waveType:'+str(iatm),'') for kind in ['F','P','A','M']] waveTypes.append(wavetype) for key in keys: for m in range(Nwave[key[0]]): parm = pfx+key+str(iatm)+':%d'%(m) if parm in parmDict: keys[key][m][iatm] = parmDict[parm] return waveTypes,FSSdata,XSSdata,USSdata,MSSdata
[docs] def StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict): ''' Compute structure factors for all h,k,l for phase puts the result, F^2, in each ref[8] in refList operates on blocks of 100 reflections for speed input: :param dict refDict: where 'RefList' list where each ref = h,k,l,it,d,... 'FF' dict of form factors - filed in below :param np.array G: reciprocal metric tensor :param str pfx: phase id string :param dict SGData: space group info. dictionary output from SpcGroup :param dict calcControls: :param dict ParmDict: ''' phfx = pfx.split(':')[0]+hfx ast = np.sqrt(np.diag(G)) Mast = twopisq*np.multiply.outer(ast,ast) SGMT = np.array([ops[0].T for ops in SGData['SGOps']]) # must be ops[0].T SGT = np.array([ops[1] for ops in SGData['SGOps']]) FFtables = calcControls['FFtables'] EFtables = calcControls['EFtables'] BLtables = calcControls['BLtables'] ORBtables = calcControls['ORBtables'] Amat,Bmat = G2lat.Gmat2AB(G) Flack = 1.0 if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict: Flack = 1.-2.*parmDict[phfx+'Flack'] TwinLaw = np.array([[[1,0,0],[0,1,0],[0,0,1]],]) TwDict = refDict.get('TwDict',{}) hType = calcControls[hfx+'histType'] if 'S' in hType: NTL = calcControls[phfx+'NTL'] NM = calcControls[phfx+'TwinNMN']+1 TwinLaw = calcControls[phfx+'TwinLaw'] TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))]) TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1)) Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata,Gdata = \ GetAtomFXU(pfx,calcControls,parmDict) if not Xdata.size: #no atoms in phase! return if 'NC' in hType or 'NB' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam']) elif 'X' in hType: FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata]) FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata]) elif 'SEC' in hType: FP = np.zeros(len(Tdata)) FPP = np.zeros(len(Tdata)) Uij = np.array(G2lat.U6toUij(Uijdata)) bij = Mast*Uij.T blkSize = 100 #no. of reflections in a block - size seems optimal nRef = refDict['RefList'].shape[0] SQ = 1./(2.*refDict['RefList'].T[4])**2 if 'N' in hType: dat = G2el.getBLvalues(BLtables) refDict['FF']['El'] = list(dat.keys()) refDict['FF']['FF'] = np.ones((nRef,len(dat)))*list(dat.values()) elif 'SEC' in hType: dat = G2el.getFFvalues(EFtables,0.) refDict['FF']['El'] = list(dat.keys()) refDict['FF']['FF'] = np.zeros((nRef,len(dat))) for iel,El in enumerate(refDict['FF']['El']): refDict['FF']['FF'].T[iel] = G2el.ScatFac(EFtables[El],SQ) else: #'X' dat = G2el.getFFvalues(FFtables,0.) refDict['FF']['El'] = list(dat.keys()) refDict['FF']['FF'] = np.zeros((nRef,len(dat))) for iel,El in enumerate(refDict['FF']['El']): refDict['FF']['FF'].T[iel] = G2el.ScatFac(FFtables[El],SQ) SHCdict = GetSHC(pfx,parmDict) #this is pfx keyed dict! #reflection processing begins here - big arrays! iBeg = 0 while iBeg < nRef: iFin = min(iBeg+blkSize,nRef) refl = refDict['RefList'][iBeg:iFin] #array(blkSize,nItems) H = refl.T[:3] #array(blkSize,3) H = np.squeeze(np.inner(H.T,TwinLaw)) #maybe array(blkSize,nTwins,3) or (blkSize,3) TwMask = np.any(H,axis=-1) if TwinLaw.shape[0] > 1 and TwDict: #need np.inner(TwinLaw[?],TwDict[iref][i])*TwinInv[i] for ir in range(blkSize): iref = ir+iBeg if iref in TwDict: for i in TwDict[iref]: for n in range(NTL): H[ir][i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM]) TwMask = np.any(H,axis=-1) SQ = 1./(2.*refl.T[4])**2 #array(blkSize) SQfactor = 4.0*SQ*twopisq #ditto prev. if 'T' in hType: if 'P' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14]) else: FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12]) FP = np.repeat(FP.T,len(SGT)*len(TwinLaw),axis=0) FPP = np.repeat(FPP.T,len(SGT)*len(TwinLaw),axis=0) Uniq = np.inner(H,SGMT) Phi = np.inner(H,SGT) phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T sinp = np.sin(phase) cosp = np.cos(phase) biso = -SQfactor*Uisodata[:,nxs] Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT)*len(TwinLaw),axis=1).T HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1) # HbH = -np.sum(np.inner(Uniq,bij)*Uniq[:,:,nxs,:],axis=-1).T #doesn't work, but should! Tuij = np.where(HbH<1.,np.exp(HbH),1.0).T Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/len(SGMT) Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata]) FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,len(SGT)*len(TwinLaw),axis=0) #FF has to have the Bessel*Sph.Har.*atm form factor for each refletion in Uniq for Q atoms; otherwise just normal FF #this must be done here. NB: same place for non-spherical atoms; same math except no Bessel part. if pfx in SHCdict: MakeSpHarmFF(Uniq,Bmat,SHCdict[pfx],Tdata,hType,FFtables,ORBtables,BLtables,FF,SQ) #Not Amat! Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),len(SGT)*len(TwinLaw)) if 'T' in calcControls[hfx+'histType']: #fa,fb are 2 X blkSize X nTwin X nOps x nAtoms fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-np.reshape(Flack*FPP,sinp.shape)*sinp*Tcorr]) fb = np.array([np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr,np.reshape(Flack*FPP,cosp.shape)*cosp*Tcorr]) else: fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-Flack*FPP*sinp*Tcorr]) fb = np.array([np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr,Flack*FPP*cosp*Tcorr]) fas = np.sum(np.sum(fa,axis=-1),axis=-1) #real 2 x blkSize x nTwin; sum over atoms & uniq hkl fbs = np.sum(np.sum(fb,axis=-1),axis=-1) #imag if SGData['SGInv']: #centrosymmetric; B=0 fbs[0] *= 0. fas[1] *= 0. if 'P' in hType: #PXC, PNC & PNT: F^2 = A[0]^2 + A[1]^2 + B[0]^2 + B[1]^2 refl.T[9] = np.sum(fas**2,axis=0)+np.sum(fbs**2,axis=0) refl.T[10] = atan2d(fbs[0],fas[0]) #ignore f' & f" else: #HKLF: F^2 = (A[0]+A[1])^2 + (B[0]+B[1])^2 if len(TwinLaw) > 1: refl.T[9] = np.sum(fas[:,:,0],axis=0)**2+np.sum(fbs[:,:,0],axis=0)**2 #FcT from primary twin element refl.T[7] = np.sum(TwinFr*TwMask*np.sum(fas,axis=0)**2,axis=-1)+ \ np.sum(TwinFr*TwMask*np.sum(fbs,axis=0)**2,axis=-1) #Fc sum over twins refl.T[10] = atan2d(fbs[0].T[0],fas[0].T[0]) #ignore f' & f" & use primary twin else: # checked correct!! refl.T[9] = np.sum(fas,axis=0)**2+np.sum(fbs,axis=0)**2 refl.T[7] = np.copy(refl.T[9]) refl.T[10] = atan2d(fbs[0],fas[0]) #ignore f' & f" # refl.T[10] = atan2d(np.sum(fbs,axis=0),np.sum(fas,axis=0)) #include f' & f" iBeg += blkSize
# print 'sf time %.4f, nref %d, blkSize %d'%(time.time()-time0,nRef,blkSize)
[docs] def StructureFactorDerv2(refDict,G,hfx,pfx,SGData,calcControls,parmDict): '''Compute structure factor derivatives on blocks of reflections - for powders/nontwins only faster than StructureFactorDerv - correct for powders/nontwins!! input: :param dict refDict: where 'RefList' list where each ref = h,k,l,it,d,... 'FF' dict of form factors - filled in below :param np.array G: reciprocal metric tensor :param str hfx: histogram id string :param str pfx: phase id string :param dict SGData: space group info. dictionary output from SpcGroup :param dict calcControls: :param dict parmDict: :returns: dict dFdvDict: dictionary of derivatives ''' phfx = pfx.split(':')[0]+hfx ast = np.sqrt(np.diag(G)) Mast = twopisq*np.multiply.outer(ast,ast) SGMT = np.array([ops[0].T for ops in SGData['SGOps']]) # must be ops[0].T SGT = np.array([ops[1] for ops in SGData['SGOps']]) FFtables = calcControls['FFtables'] ORBtables = calcControls['ORBtables'] BLtables = calcControls['BLtables'] hType = calcControls[hfx+'histType'] Amat,Bmat = G2lat.Gmat2AB(G) nRef = len(refDict['RefList']) Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata,Gdata = \ GetAtomFXU(pfx,calcControls,parmDict) atFlg = np.zeros(len(Tdata)) #non zero for Q type atoms - see below if not Xdata.size: #no atoms in phase! return {} mSize = len(Mdata) nOps = len(SGMT) FF = np.zeros(len(Tdata)) if 'NC' in calcControls[hfx+'histType'] or 'NB' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam']) elif 'X' in calcControls[hfx+'histType']: FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata]) FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata]) elif 'SEC' in calcControls[hfx+'histType']: FP = np.zeros(len(Tdata)) FPP = np.zeros(len(Tdata)) Uij = np.array(G2lat.U6toUij(Uijdata)) bij = Mast*Uij.T dFdvDict = {} dFdfr = np.zeros((nRef,mSize)) dFdff = np.zeros((nRef,nOps,mSize)) dFdx = np.zeros((nRef,mSize,3)) dFdui = np.zeros((nRef,mSize)) dFdua = np.zeros((nRef,mSize,6)) dFdbab = np.zeros((nRef,2)) dFdfl = np.zeros((nRef)) Flack = 1.0 if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict: Flack = 1.-2.*parmDict[phfx+'Flack'] SHCdict = GetSHC(pfx,parmDict) #this is dict with pf as key dffdSH = {} #reflection processing begins here - big arrays! iBeg = 0 blkSize = 32 #no. of reflections in a block - optimized for speed while iBeg < nRef: iFin = min(iBeg+blkSize,nRef) refl = refDict['RefList'][iBeg:iFin] #array(blkSize,nItems) H = refl.T[:3].T SQ = 1./(2.*refl.T[4])**2 # or (sin(theta)/lambda)**2 SQfactor = 8.0*SQ*np.pi**2 if 'T' in calcControls[hfx+'histType']: if 'P' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14]) else: FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12]) FP = np.repeat(FP.T,len(SGT),axis=0) FPP = np.repeat(FPP.T,len(SGT),axis=0) dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor) Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),len(SGT)) Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata]) FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,len(SGT),axis=0) Uniq = np.inner(H,SGMT) # array(nSGOp,3,3) Phi = np.inner(H,SGT) phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T sinp = np.sin(phase) #refBlk x nOps x nAtoms cosp = np.cos(phase) occ = Mdata*Fdata/len(SGT) biso = -SQfactor*Uisodata[:,nxs] Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT),axis=1).T HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1) #Natm,Nops,Nref Tuij = np.where(HbH<1.,np.exp(HbH),1.0).T #Nref,Nops,Natm Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/len(SGMT) Hij = np.array([Mast*np.multiply.outer(U,U) for U in np.reshape(Uniq,(-1,3))]) #Nref*Nops,3,3 Hij = np.reshape(np.array([G2lat.UijtoU6(uij) for uij in Hij]),(-1,len(SGT),6)) #Nref,Nops,6 if pfx in SHCdict: dffdsh,atFlg = MakeSpHarmFF(Uniq,Bmat,SHCdict[pfx],Tdata,hType,FFtables,ORBtables,BLtables,FF,SQ,True) if len(dffdSH): for item in dffdSH: dffdSH[item] = np.concatenate((dffdSH[item],dffdsh[item])) else: dffdSH.update(dffdsh) fot = np.reshape(((FF+FP).T-Bab).T,cosp.shape)*Tcorr if len(FPP.shape) > 1: fotp = np.reshape(FPP,cosp.shape)*Tcorr else: fotp = FPP*Tcorr if 'T' in calcControls[hfx+'histType']: fa = np.array([fot*cosp,-np.reshape(Flack*FPP,sinp.shape)*sinp*Tcorr]) fb = np.array([fot*sinp,np.reshape(Flack*FPP,cosp.shape)*cosp*Tcorr]) else: fa = np.array([fot*cosp,-Flack*FPP*sinp*Tcorr]) fb = np.array([fot*sinp,Flack*FPP*cosp*Tcorr]) fas = np.sum(np.sum(fa,axis=-1),axis=-1) #real sum over atoms & unique hkl array(2,refBlk,nTwins) fbs = np.sum(np.sum(fb,axis=-1),axis=-1) #imag sum over atoms & uniq hkl fax = np.array([-fot*sinp,-fotp*cosp]) #positions array(2,refBlk,nEqv,nAtoms) fbx = np.array([fot*cosp,-fotp*sinp]) #sum below is over Uniq dfadfr = np.sum(fa/occ,axis=-2) #array(2,refBlk,nAtom) Fdata != 0 avoids /0. problem dfadff = fa[0]*Tcorr*atFlg/fot #ignores resonant scattering? no sum on Uniq; array(refBlk,nEqv,nAtom) dfadba = np.sum(-cosp*Tcorr,axis=-2) #array(refBlk,nAtom) dfadx = np.sum(twopi*Uniq[nxs,:,nxs,:,:]*np.swapaxes(fax,-2,-1)[:,:,:,:,nxs],axis=-2) dfadui = np.sum(-SQfactor[nxs,:,nxs,nxs]*fa,axis=-2) #array(Ops,refBlk,nAtoms) dfadua = np.sum(-Hij[nxs,:,nxs,:,:]*np.swapaxes(fa,-2,-1)[:,:,:,:,nxs],axis=-2) if not SGData['SGInv']: dfbdfr = np.sum(fb/occ,axis=-2) #Fdata != 0 avoids /0. problem dfbdff = fb[0]*Tcorr*atFlg/fot #ignores resonant scattering? no sum on Uniq; array(refBlk,nEqv,nAtom) dfbdba = np.sum(-sinp*Tcorr,axis=-2) dfadfl = np.sum(np.sum(-fotp*sinp,axis=-1),axis=-1) dfbdfl = np.sum(np.sum(fotp*cosp,axis=-1),axis=-1) dfbdx = np.sum(twopi*Uniq[nxs,:,nxs,:,:]*np.swapaxes(fbx,-2,-1)[:,:,:,:,nxs],axis=-2) dfbdui = np.sum(-SQfactor[nxs,:,nxs,nxs]*fb,axis=-2) dfbdua = np.sum(-Hij[nxs,:,nxs,:,:]*np.swapaxes(fb,-2,-1)[:,:,:,:,nxs],axis=-2) else: dfbdfr = np.zeros_like(dfadfr) dfbdff = np.zeros_like(dfadff) dfbdx = np.zeros_like(dfadx) dfbdui = np.zeros_like(dfadui) dfbdua = np.zeros_like(dfadua) dfbdba = np.zeros_like(dfadba) dfadfl = 0.0 dfbdfl = 0.0 #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for Al2O3! SA = fas[0]+fas[1] SB = fbs[0]+fbs[1] if 'P' in calcControls[hfx+'histType']: #checked perfect for centro & noncentro dFdfr[iBeg:iFin] = 2.*np.sum(fas[:,:,nxs]*dfadfr+fbs[:,:,nxs]*dfbdfr,axis=0)*Mdata/len(SGMT) dFdff[iBeg:iFin] = 2.*np.sum(fas[:,:,nxs,nxs]*dfadff[nxs,:,:,:]+fbs[:,:,nxs,nxs]*dfbdff[nxs,:,:,:],axis=0) #not summed on Uniq yet dFdx[iBeg:iFin] = 2.*np.sum(fas[:,:,nxs,nxs]*dfadx+fbs[:,:,nxs,nxs]*dfbdx,axis=0) dFdui[iBeg:iFin] = 2.*np.sum(fas[:,:,nxs]*dfadui+fbs[:,:,nxs]*dfbdui,axis=0) dFdua[iBeg:iFin] = 2.*np.sum(fas[:,:,nxs,nxs]*dfadua+fbs[:,:,nxs,nxs]*dfbdua,axis=0) else: dFdfr[iBeg:iFin] = (2.*SA[:,nxs]*(dfadfr[0]+dfadfr[1])+2.*SB[:,nxs]*(dfbdfr[0]+dfbdfr[1]))*Mdata/len(SGMT) dFdff[iBeg:iFin] = (2.*SA[:,nxs,nxs]*dfadff+2.*SB[:,nxs,nxs]*dfbdff) #not summed on Uniq yet array(Nref,nEqv,nAtom) dFdx[iBeg:iFin] = 2.*SA[:,nxs,nxs]*(dfadx[0]+dfadx[1])+2.*SB[:,nxs,nxs]*(dfbdx[0]+dfbdx[1]) dFdui[iBeg:iFin] = 2.*SA[:,nxs]*(dfadui[0]+dfadui[1])+2.*SB[:,nxs]*(dfbdui[0]+dfbdui[1]) dFdua[iBeg:iFin] = 2.*SA[:,nxs,nxs]*(dfadua[0]+dfadua[1])+2.*SB[:,nxs,nxs]*(dfbdua[0]+dfbdua[1]) dFdfl[iBeg:iFin] = -SA*dfadfl-SB*dfbdfl #array(nRef,) dFdbab[iBeg:iFin] = 2.*(fas[0,nxs]*np.array([np.sum(dfadba.T*dBabdA,axis=0),np.sum(-dfadba.T*parmDict[phfx+'BabA']*SQfactor*dBabdA,axis=0)])+ \ fbs[0,nxs]*np.array([np.sum(dfbdba.T*dBabdA,axis=0),np.sum(-dfbdba.T*parmDict[phfx+'BabA']*SQfactor*dBabdA,axis=0)])).T iBeg += blkSize # print 'derv time %.4f, nref %d, blkSize %d'%(time.time()-time0,nRef,blkSize) #loop over atoms - each dict entry is list of derivatives for all the reflections for i in range(len(Tdata)): #loop over atoms dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i] dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i] dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i] dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i] dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i] dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i] dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i] dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i] dFdvDict[pfx+'AU12:'+str(i)] = dFdua.T[3][i] dFdvDict[pfx+'AU13:'+str(i)] = dFdua.T[4][i] dFdvDict[pfx+'AU23:'+str(i)] = dFdua.T[5][i] for item in dffdSH: if 'SH' in item or 'O' in item: if i == int(item.split(':')[1]): dFdvDict[pfx+'RBS'+item] = np.sum(dFdff[:,:,i]*np.reshape(dffdSH[item],(nRef,-1)),axis=1) else: if i == int(item.split(':')[1]): dFdvDict[pfx+item] = np.sum(dFdff[:,:,i]*np.reshape(dffdSH[item],(nRef,-1)),axis=1) dFdvDict[phfx+'Flack'] = 4.*dFdfl.T dFdvDict[phfx+'BabA'] = dFdbab.T[0] dFdvDict[phfx+'BabU'] = dFdbab.T[1] return dFdvDict
[docs] def MagStructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict): ''' Compute neutron magnetic structure factors for all h,k,l for phase puts the result, F^2, in each ref[8] in refList operates on blocks of 100 reflections for speed input: :param dict refDict: where 'RefList' list where each ref = h,k,l,it,d,... 'FF' dict of form factors - filed in below :param np.array G: reciprocal metric tensor :param str pfx: phase id string :param dict SGData: space group info. dictionary output from SpcGroup :param dict calcControls: :param dict ParmDict: :returns: copy of new refList - used in calculating numerical derivatives ''' g = nl.inv(G) ast = np.sqrt(np.diag(G)) ainv = np.sqrt(np.diag(g)) GS = G/np.outer(ast,ast) Ginv = g/np.outer(ainv,ainv) uAmat = G2lat.Gmat2AB(GS)[0] Bmat = G2lat.Gmat2AB(G)[1] Mast = twopisq*np.multiply.outer(ast,ast) SGMT = np.array([ops[0].T for ops in SGData['SGOps']]) SGT = np.array([ops[1] for ops in SGData['SGOps']]) Ncen = len(SGData['SGCen']) Nops = len(SGMT)*Ncen if not SGData['SGFixed']: Nops *= (1+SGData['SGInv']) MFtables = calcControls['MFtables'] TwinLaw = np.ones(1) # TwinLaw = np.array([[[1,0,0],[0,1,0],[0,0,1]],]) # TwDict = refDict.get('TwDict',{}) # if 'S' in calcControls[hfx+'histType']: # NTL = calcControls[phfx+'NTL'] # NM = calcControls[phfx+'TwinNMN']+1 # TwinLaw = calcControls[phfx+'TwinLaw'] # TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))]) # TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1)) Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata,Gdata = \ GetAtomFXU(pfx,calcControls,parmDict) if not Xdata.size: #no atoms in phase! return Mag = np.array([np.sqrt(np.inner(mag,np.inner(mag,Ginv))) for mag in Gdata.T]) Gdata = np.inner(Gdata.T,np.swapaxes(SGMT,1,2)).T #apply sym. ops. if SGData['SGInv'] and not SGData['SGFixed']: Gdata = np.hstack((Gdata,-Gdata)) #inversion if any Gdata = np.hstack([Gdata for icen in range(Ncen)]) #dup over cell centering--> [Mxyz,nops,natms] Gdata = SGData['MagMom'][nxs,:,nxs]*Gdata #flip vectors according to spin flip * det(opM) Mag = np.tile(Mag[:,nxs],Nops).T #make Mag same length as Gdata Kdata = np.inner(Gdata.T,uAmat).T Kmean = np.mean(np.sqrt(np.sum(Kdata**2,axis=0)),axis=0) Kdata /= Kmean #Cartesian unit vectors Uij = np.array(G2lat.U6toUij(Uijdata)) bij = Mast*Uij.T blkSize = 100 #no. of reflections in a block - size seems optimal nRef = refDict['RefList'].shape[0] SQ = 1./(2.*refDict['RefList'].T[4])**2 refDict['FF']['El'] = list(MFtables.keys()) refDict['FF']['MF'] = np.zeros((nRef,len(MFtables))) for iel,El in enumerate(refDict['FF']['El']): refDict['FF']['MF'].T[iel] = G2el.MagScatFac(MFtables[El],SQ) #reflection processing begins here - big arrays! iBeg = 0 while iBeg < nRef: iFin = min(iBeg+blkSize,nRef) refl = refDict['RefList'][iBeg:iFin] #array(blkSize,nItems) H = refl.T[:3].T #array(blkSize,3) # H = np.squeeze(np.inner(H.T,TwinLaw)) #maybe array(blkSize,nTwins,3) or (blkSize,3) # TwMask = np.any(H,axis=-1) # if TwinLaw.shape[0] > 1 and TwDict: #need np.inner(TwinLaw[?],TwDict[iref][i])*TwinInv[i] # for ir in range(blkSize): # iref = ir+iBeg # if iref in TwDict: # for i in TwDict[iref]: # for n in range(NTL): # H[ir][i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM]) # TwMask = np.any(H,axis=-1) SQ = 1./(2.*refl.T[4])**2 #array(blkSize) SQfactor = 4.0*SQ*twopisq #ditto prev. Uniq = np.inner(H,SGMT) Phi = np.inner(H,SGT) phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T biso = -SQfactor*Uisodata[:,nxs] Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT)*len(TwinLaw),axis=1).T HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1) Tuij = np.where(HbH<1.,np.exp(HbH),1.0).T Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata]) MF = refDict['FF']['MF'][iBeg:iFin].T[Tindx].T #Nref,Natm TMcorr = 0.539*(np.reshape(Tiso,Tuij.shape)*Tuij)[:,0,:]*Fdata*Mdata*MF/(2*Nops) #Nref,Natm if SGData['SGInv']: if not SGData['SGFixed']: mphase = np.hstack((phase,-phase)) #OK else: mphase = phase else: mphase = phase # mphase = np.array([mphase+twopi*np.inner(cen,H)[:,nxs,nxs] for cen in SGData['SGCen']]) mphase = np.concatenate(mphase,axis=1) #Nref,full Nop,Natm sinm = np.sin(mphase) #ditto - match magstrfc.for cosm = np.cos(mphase) #ditto HM = np.inner(Bmat,H) #put into cartesian space HM = HM/np.sqrt(np.sum(HM**2,axis=0)) #Kdata = MAGS & HM = UVEC in magstrfc.for both OK eDotK = np.sum(HM[:,:,nxs,nxs]*Kdata[:,nxs,:,:],axis=0) Q = HM[:,:,nxs,nxs]*eDotK[nxs,:,:,:]-Kdata[:,nxs,:,:] #xyz,Nref,Nop,Natm = BPM in magstrfc.for OK fam = Q*TMcorr[nxs,:,nxs,:]*cosm[nxs,:,:,:]*Mag[nxs,nxs,:,:] #ditto fbm = Q*TMcorr[nxs,:,nxs,:]*sinm[nxs,:,:,:]*Mag[nxs,nxs,:,:] #ditto fams = np.sum(np.sum(fam,axis=-1),axis=-1) #Mxyz,Nref Sum(sum(fam,atoms),ops) fbms = np.sum(np.sum(fbm,axis=-1),axis=-1) #ditto refl.T[9] = np.sum(fams**2,axis=0)+np.sum(fbms**2,axis=0) #Sum(fams**2,Mxyz) Re + Im refl.T[7] = np.copy(refl.T[9]) refl.T[10] = atan2d(fbms[0],fams[0]) #- what is phase for mag refl? # if 'P' in calcControls[hfx+'histType']: #PXC, PNC & PNT: F^2 = A[0]^2 + A[1]^2 + B[0]^2 + B[1]^2 # refl.T[9] = np.sum(fas**2,axis=0)+np.sum(fbs**2,axis=0) #add fam**2 & fbm**2 here # refl.T[10] = atan2d(fbs[0],fas[0]) #ignore f' & f" # else: #HKLF: F^2 = (A[0]+A[1])^2 + (B[0]+B[1])^2 # if len(TwinLaw) > 1: # refl.T[9] = np.sum(fas[:,:,0],axis=0)**2+np.sum(fbs[:,:,0],axis=0)**2 #FcT from primary twin element # refl.T[7] = np.sum(TwinFr*TwMask*np.sum(fas,axis=0)**2,axis=-1)+ \ # np.sum(TwinFr*TwMask*np.sum(fbs,axis=0)**2,axis=-1) #Fc sum over twins # refl.T[10] = atan2d(fbs[0].T[0],fas[0].T[0]) #ignore f' & f" & use primary twin # else: # checked correct!! # refl.T[9] = np.sum(fas,axis=0)**2+np.sum(fbs,axis=0)**2 # refl.T[7] = np.copy(refl.T[9]) # refl.T[10] = atan2d(fbs[0],fas[0]) #ignore f' & f" ## refl.T[10] = atan2d(np.sum(fbs,axis=0),np.sum(fas,axis=0)) #include f' & f" iBeg += blkSize # print 'sf time %.4f, nref %d, blkSize %d'%(time.time()-time0,nRef,blkSize) return copy.deepcopy(refDict['RefList'])
[docs] def MagStructureFactorDerv2(refDict,G,hfx,pfx,SGData,calcControls,parmDict): '''Compute magnetic structure factor derivatives numerically - for powders/nontwins only input: :param dict refDict: where 'RefList' list where each ref = h,k,l,it,d,... 'FF' dict of form factors - filled in below :param np.array G: reciprocal metric tensor :param str hfx: histogram id string :param str pfx: phase id string :param dict SGData: space group info. dictionary output from SpcGroup :param dict calcControls: :param dict parmDict: :returns: dict dFdvDict: dictionary of magnetic derivatives ''' trefDict = copy.deepcopy(refDict) dM = 1.e-6 dFdvDict = {} for parm in parmDict: if 'AM' in parm: parmDict[parm] += dM prefList = MagStructureFactor2(trefDict,G,hfx,pfx,SGData,calcControls,parmDict) parmDict[parm] -= 2*dM mrefList = MagStructureFactor2(trefDict,G,hfx,pfx,SGData,calcControls,parmDict) parmDict[parm] += dM dFdvDict[parm] = (prefList[:,9]-mrefList[:,9])/(2.*dM) return dFdvDict
[docs] def MagStructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict): '''Compute nonmagnetic structure factor derivatives on blocks of reflections in magnetic structures - for powders/nontwins only input: :param dict refDict: where 'RefList' list where each ref = h,k,l,it,d,... 'FF' dict of form factors - filled in below :param np.array G: reciprocal metric tensor :param str hfx: histogram id string :param str pfx: phase id string :param dict SGData: space group info. dictionary output from SpcGroup :param dict calcControls: :param dict parmDict: :returns: dict dFdvDict: dictionary of derivatives ''' g = nl.inv(G) ast = np.sqrt(np.diag(G)) ainv = np.sqrt(np.diag(g)) GS = G/np.outer(ast,ast) Ginv = g/np.outer(ainv,ainv) uAmat = G2lat.Gmat2AB(GS)[0] Mast = twopisq*np.multiply.outer(ast,ast) SGMT = np.array([ops[0].T for ops in SGData['SGOps']]) SGT = np.array([ops[1] for ops in SGData['SGOps']]) Ncen = len(SGData['SGCen']) Nops = len(SGMT)*Ncen if not SGData['SGFixed']: Nops *= (1+SGData['SGInv']) Bmat = G2lat.Gmat2AB(G)[1] nRef = len(refDict['RefList']) Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata,Gdata = \ GetAtomFXU(pfx,calcControls,parmDict) if not Xdata.size: #no atoms in phase! return {} mSize = len(Mdata) Mag = np.array([np.sqrt(np.inner(mag,np.inner(mag,Ginv))) for mag in Gdata.T]) Gones = np.ones_like(Gdata) Gdata = np.inner(Gdata.T,np.swapaxes(SGMT,1,2)).T #apply sym. ops. Gones = np.inner(Gones.T,SGMT).T if SGData['SGInv'] and not SGData['SGFixed']: Gdata = np.hstack((Gdata,-Gdata)) #inversion if any Gones = np.hstack((Gones,-Gones)) #inversion if any Gdata = np.hstack([Gdata for icen in range(Ncen)]) #dup over cell centering Gones = np.hstack([Gones for icen in range(Ncen)]) #dup over cell centering Gdata = SGData['MagMom'][nxs,:,nxs]*Gdata #flip vectors according to spin flip Gones = SGData['MagMom'][nxs,:,nxs]*Gones #flip vectors according to spin flip Mag = np.tile(Mag[:,nxs],Nops).T #make Mag same length as Gdata Kdata = np.inner(Gdata.T,uAmat).T #Cartesian unit vectors Kmean = np.mean(np.sqrt(np.sum(Kdata**2,axis=0)),axis=0) Kdata /= Kmean Uij = np.array(G2lat.U6toUij(Uijdata)) bij = Mast*Uij.T dFdvDict = {} dFdfr = np.zeros((nRef,mSize)) dFdx = np.zeros((nRef,mSize,3)) dFdui = np.zeros((nRef,mSize)) dFdua = np.zeros((nRef,mSize,6)) time0 = time.time() #reflection processing begins here - big arrays! iBeg = 0 blkSize = 5 #no. of reflections in a block - optimized for speed while iBeg < nRef: iFin = min(iBeg+blkSize,nRef) refl = refDict['RefList'][iBeg:iFin] #array(blkSize,nItems) H = refl.T[:3].T SQ = 1./(2.*refl.T[4])**2 # or (sin(theta)/lambda)**2 SQfactor = 8.0*SQ*np.pi**2 Uniq = np.inner(H,SGMT) # array(nSGOp,3) Phi = np.inner(H,SGT) phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T occ = Mdata*Fdata/Nops biso = -SQfactor*Uisodata[:,nxs] Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT),axis=1).T HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1) Tuij = np.where(HbH<1.,np.exp(HbH),1.0).T Hij = np.array([Mast*np.multiply.outer(U,U) for U in np.reshape(Uniq,(-1,3))]) Hij = np.reshape(np.array([G2lat.UijtoU6(uij) for uij in Hij]),(-1,len(SGT),6)) Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata]) MF = refDict['FF']['MF'][iBeg:iFin].T[Tindx].T #Nref,Natm TMcorr = 0.539*(np.reshape(Tiso,Tuij.shape)*Tuij)[:,0,:]*Fdata*Mdata*MF/(2*Nops) #Nref,Natm if SGData['SGInv']: if not SGData['SGFixed']: mphase = np.hstack((phase,-phase)) #OK Uniq = np.hstack((Uniq,-Uniq)) #Nref,Nops,hkl Hij = np.hstack((Hij,Hij)) else: mphase = phase else: mphase = phase # Hij = np.concatenate(np.array([Hij for cen in SGData['SGCen']]),axis=1) Uniq = np.hstack([Uniq for cen in SGData['SGCen']]) mphase = np.array([mphase+twopi*np.inner(cen,H)[:,nxs,nxs] for cen in SGData['SGCen']]) mphase = np.concatenate(mphase,axis=1) #Nref,Nop,Natm sinm = np.sin(mphase) #ditto - match magstrfc.for cosm = np.cos(mphase) #ditto HM = np.inner(Bmat.T,H) #put into cartesian space HM = HM/np.sqrt(np.sum(HM**2,axis=0)) #unit cartesian vector for H eDotK = np.sum(HM[:,:,nxs,nxs]*Kdata[:,nxs,:,:],axis=0) Q = HM[:,:,nxs,nxs]*eDotK[nxs,:,:,:]-Kdata[:,nxs,:,:] #Mxyz,Nref,Nop,Natm = BPM in magstrfc.for OK fam = Q*TMcorr[nxs,:,nxs,:]*cosm[nxs,:,:,:]*Mag[nxs,nxs,:,:] #Mxyz,Nref,Nop,Natm fbm = Q*TMcorr[nxs,:,nxs,:]*sinm[nxs,:,:,:]*Mag[nxs,nxs,:,:] fams = np.sum(np.sum(fam,axis=-1),axis=-1) #Mxyz,Nref fbms = np.sum(np.sum(fbm,axis=-1),axis=-1) famx = -Q*TMcorr[nxs,:,nxs,:]*Mag[nxs,nxs,:,:]*sinm[nxs,:,:,:] #Mxyz,Nref,Nops,Natom fbmx = Q*TMcorr[nxs,:,nxs,:]*Mag[nxs,nxs,:,:]*cosm[nxs,:,:,:] #sums below are over Nops - real part dfadfr = np.sum(fam/occ,axis=2) #array(Mxyz,refBlk,nAtom) Fdata != 0 avoids /0. problem deriv OK dfadx = np.sum(twopi*Uniq[nxs,:,:,nxs,:]*famx[:,:,:,:,nxs],axis=2) #deriv OK dfadui = np.sum(-SQfactor[:,nxs,nxs]*fam,axis=2) #array(Ops,refBlk,nAtoms) deriv OK dfadua = np.sum(-Hij[nxs,:,:,nxs,:]*fam[:,:,:,:,nxs],axis=2) #deriv OK # imaginary part; array(3,refBlk,nAtom,3) & array(3,refBlk,nAtom,6) dfbdfr = np.sum(fbm/occ,axis=2) #array(mxyz,refBlk,nAtom) Fdata != 0 avoids /0. problem dfbdx = np.sum(twopi*Uniq[nxs,:,:,nxs,:]*fbmx[:,:,:,:,nxs],axis=2) dfbdui = np.sum(-SQfactor[:,nxs,nxs]*fbm,axis=2) #array(Ops,refBlk,nAtoms) dfbdua = np.sum(-Hij[nxs,:,:,nxs,:]*fbm[:,:,:,:,nxs],axis=2) #accumulate derivatives dFdfr[iBeg:iFin] = 2.*np.sum((fams[:,:,nxs]*dfadfr+fbms[:,:,nxs]*dfbdfr)*Mdata/Nops,axis=0) #ok dFdx[iBeg:iFin] = 2.*np.sum(fams[:,:,nxs,nxs]*dfadx+fbms[:,:,nxs,nxs]*dfbdx,axis=0) #ok dFdui[iBeg:iFin] = 2.*np.sum(fams[:,:,nxs]*dfadui+fbms[:,:,nxs]*dfbdui,axis=0) #ok dFdua[iBeg:iFin] = 2.*np.sum(fams[:,:,nxs,nxs]*dfadua+fbms[:,:,nxs,nxs]*dfbdua,axis=0) #ok iBeg += blkSize print (' %d derivative time %.4f\r'%(nRef,time.time()-time0)) #loop over atoms - each dict entry is list of derivatives for all the reflections for i in range(len(Mdata)): dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i] dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i] dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i] dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i] dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i] dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i] dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i] dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i] dFdvDict[pfx+'AU12:'+str(i)] = dFdua.T[3][i] dFdvDict[pfx+'AU13:'+str(i)] = dFdua.T[4][i] dFdvDict[pfx+'AU23:'+str(i)] = dFdua.T[5][i] return dFdvDict
[docs] def StructureFactorDervTw2(refDict,G,hfx,pfx,SGData,calcControls,parmDict): '''Compute structure factor derivatives on blocks of reflections - for twins only faster than StructureFactorDervTw input: :param dict refDict: where 'RefList' list where each ref = h,k,l,it,d,... 'FF' dict of form factors - filled in below :param np.array G: reciprocal metric tensor :param str hfx: histogram id string :param str pfx: phase id string :param dict SGData: space group info. dictionary output from SpcGroup :param dict calcControls: :param dict parmDict: :returns: dict dFdvDict: dictionary of derivatives ''' phfx = pfx.split(':')[0]+hfx ast = np.sqrt(np.diag(G)) Mast = twopisq*np.multiply.outer(ast,ast) SGMT = np.array([ops[0].T for ops in SGData['SGOps']]) SGT = np.array([ops[1] for ops in SGData['SGOps']]) FFtables = calcControls['FFtables'] BLtables = calcControls['BLtables'] TwDict = refDict.get('TwDict',{}) NTL = calcControls[phfx+'NTL'] NM = calcControls[phfx+'TwinNMN']+1 TwinLaw = calcControls[phfx+'TwinLaw'] TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))]) TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1)) nTwin = len(TwinLaw) nRef = len(refDict['RefList']) Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata,Gdata = \ GetAtomFXU(pfx,calcControls,parmDict) if not Xdata.size: #no atoms in phase! return {} mSize = len(Mdata) FF = np.zeros(len(Tdata)) if 'NC' in calcControls[hfx+'histType'] or 'NB' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam']) elif 'X' in calcControls[hfx+'histType']: FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata]) FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata]) elif 'SEC' in calcControls[hfx+'histType']: FP = np.zeros(len(Tdata)) FPP = np.zeros(len(Tdata)) Uij = np.array(G2lat.U6toUij(Uijdata)) bij = Mast*Uij.T dFdvDict = {} dFdfr = np.zeros((nRef,nTwin,mSize)) dFdx = np.zeros((nRef,nTwin,mSize,3)) dFdui = np.zeros((nRef,nTwin,mSize)) dFdua = np.zeros((nRef,nTwin,mSize,6)) dFdbab = np.zeros((nRef,nTwin,2)) dFdtw = np.zeros((nRef,nTwin)) time0 = time.time() #reflection processing begins here - big arrays! iBeg = 0 blkSize = 16 #no. of reflections in a block - optimized for speed while iBeg < nRef: iFin = min(iBeg+blkSize,nRef) refl = refDict['RefList'][iBeg:iFin] #array(blkSize,nItems) H = refl.T[:3] H = np.inner(H.T,TwinLaw) #array(3,nTwins) TwMask = np.any(H,axis=-1) for ir in range(blkSize): iref = ir+iBeg if iref in TwDict: for i in TwDict[iref]: for n in range(NTL): H[ir][i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM]) TwMask = np.any(H,axis=-1) SQ = 1./(2.*refl.T[4])**2 # or (sin(theta)/lambda)**2 SQfactor = 8.0*SQ*np.pi**2 if 'T' in calcControls[hfx+'histType']: if 'P' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14]) else: FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12]) FP = np.repeat(FP.T,len(SGT)*len(TwinLaw),axis=0) FPP = np.repeat(FPP.T,len(SGT)*len(TwinLaw),axis=0) dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor) Bab = np.repeat(parmDict[phfx+'BabA']*dBabdA,len(SGT)*nTwin) Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata]) FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,len(SGT)*len(TwinLaw),axis=0) Uniq = np.inner(H,SGMT) # (nTwin,nSGOp,3) Phi = np.inner(H,SGT) phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T sinp = np.sin(phase) cosp = np.cos(phase) occ = Mdata*Fdata/len(SGT) biso = -SQfactor*Uisodata[:,nxs] Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT)*nTwin,axis=1) HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1) Hij = np.array([Mast*np.multiply.outer(U,U) for U in np.reshape(Uniq,(-1,3))]) Hij = np.reshape(np.array([G2lat.UijtoU6(uij) for uij in Hij]),(-1,nTwin,len(SGT),6)) Tuij = np.where(HbH<1.,np.exp(HbH),1.0) Tcorr = (np.reshape(Tiso,Tuij.shape)*Tuij).T*Mdata*Fdata/len(SGMT) fot = np.reshape(((FF+FP).T-Bab).T,cosp.shape)*Tcorr fotp = FPP*Tcorr if 'T' in calcControls[hfx+'histType']: #fa,fb are 2 X blkSize X nTwin X nOps x nAtoms fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-np.reshape(FPP,sinp.shape)*sinp*Tcorr]) fb = np.array([np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr,np.reshape(FPP,cosp.shape)*cosp*Tcorr]) else: fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-FPP*sinp*Tcorr]) fb = np.array([np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr,FPP*cosp*Tcorr]) fas = np.sum(np.sum(fa,axis=-1),axis=-1) #real sum over atoms & unique hkl array(2,nTwins) fbs = np.sum(np.sum(fb,axis=-1),axis=-1) #imag sum over atoms & uniq hkl if SGData['SGInv']: #centrosymmetric; B=0 fbs[0] *= 0. fas[1] *= 0. fax = np.array([-fot*sinp,-fotp*cosp]) #positions array(2,nRef,ntwi,nEqv,nAtoms) fbx = np.array([fot*cosp,-fotp*sinp]) #sum below is over Uniq dfadfr = np.sum(np.sum(fa/occ,axis=-2),axis=0) #array(2,nRef,ntwin,nAtom) Fdata != 0 avoids /0. problem dfadba = np.sum(-cosp*Tcorr[:,nxs],axis=1) dfadui = np.sum(np.sum(-SQfactor[nxs,:,nxs,nxs,nxs]*fa,axis=-2),axis=0) dfadx = np.sum(np.sum(twopi*Uniq[nxs,:,:,:,nxs,:]*fax[:,:,:,:,:,nxs],axis=-3),axis=0) # nRef x nTwin x nAtoms x xyz; sum on ops & A,A' dfadua = np.sum(np.sum(-Hij[nxs,:,:,:,nxs,:]*fa[:,:,:,:,:,nxs],axis=-3),axis=0) if not SGData['SGInv']: dfbdfr = np.sum(np.sum(fb/occ,axis=-2),axis=0) #Fdata != 0 avoids /0. problem dfadba /= 2. # dfbdba = np.sum(-sinp*Tcorr[:,nxs],axis=1)/2. dfbdui = np.sum(np.sum(-SQfactor[nxs,:,nxs,nxs,nxs]*fb,axis=-2),axis=0) dfbdx = np.sum(np.sum(twopi*Uniq[nxs,:,:,:,nxs,:]*fbx[:,:,:,:,:,nxs],axis=-3),axis=0) dfbdua = np.sum(np.sum(-Hij[nxs,:,:,:,nxs,:]*fb[:,:,:,:,:,nxs],axis=-3),axis=0) else: dfbdfr = np.zeros_like(dfadfr) dfbdx = np.zeros_like(dfadx) dfbdui = np.zeros_like(dfadui) dfbdua = np.zeros_like(dfadua) # dfbdba = np.zeros_like(dfadba) SA = fas[0]+fas[1] SB = fbs[0]+fbs[1] dFdfr[iBeg:iFin] = ((2.*TwMask*SA)[:,:,nxs]*dfadfr+(2.*TwMask*SB)[:,:,nxs]*dfbdfr)*Mdata[nxs,nxs,:]/len(SGMT) dFdx[iBeg:iFin] = (2.*TwMask*SA)[:,:,nxs,nxs]*dfadx+(2.*TwMask*SB)[:,:,nxs,nxs]*dfbdx dFdui[iBeg:iFin] = (2.*TwMask*SA)[:,:,nxs]*dfadui+(2.*TwMask*SB)[:,:,nxs]*dfbdui dFdua[iBeg:iFin] = (2.*TwMask*SA)[:,:,nxs,nxs]*dfadua+(2.*TwMask*SB)[:,:,nxs,nxs]*dfbdua if SGData['SGInv']: #centrosymmetric; B=0 dFdtw[iBeg:iFin] = np.sum(TwMask[nxs,:]*fas,axis=0)**2 else: dFdtw[iBeg:iFin] = np.sum(TwMask[nxs,:]*fas,axis=0)**2+np.sum(TwMask[nxs,:]*fbs,axis=0)**2 # dFdbab[iBeg:iFin] = fas[0,:,nxs]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T+ \ # fbs[0,:,nxs]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T iBeg += blkSize print (' %d derivative time %.4f\r'%(len(refDict['RefList']),time.time()-time0)) #loop over atoms - each dict entry is list of derivatives for all the reflections for i in range(len(Mdata)): #these all OK dFdvDict[pfx+'Afrac:'+str(i)] = np.sum(dFdfr.T[i]*TwinFr[:,nxs],axis=0) dFdvDict[pfx+'dAx:'+str(i)] = np.sum(dFdx.T[0][i]*TwinFr[:,nxs],axis=0) dFdvDict[pfx+'dAy:'+str(i)] = np.sum(dFdx.T[1][i]*TwinFr[:,nxs],axis=0) dFdvDict[pfx+'dAz:'+str(i)] = np.sum(dFdx.T[2][i]*TwinFr[:,nxs],axis=0) dFdvDict[pfx+'AUiso:'+str(i)] = np.sum(dFdui.T[i]*TwinFr[:,nxs],axis=0) dFdvDict[pfx+'AU11:'+str(i)] = np.sum(dFdua.T[0][i]*TwinFr[:,nxs],axis=0) dFdvDict[pfx+'AU22:'+str(i)] = np.sum(dFdua.T[1][i]*TwinFr[:,nxs],axis=0) dFdvDict[pfx+'AU33:'+str(i)] = np.sum(dFdua.T[2][i]*TwinFr[:,nxs],axis=0) dFdvDict[pfx+'AU12:'+str(i)] = np.sum(dFdua.T[3][i]*TwinFr[:,nxs],axis=0) dFdvDict[pfx+'AU13:'+str(i)] = np.sum(dFdua.T[4][i]*TwinFr[:,nxs],axis=0) dFdvDict[pfx+'AU23:'+str(i)] = np.sum(dFdua.T[5][i]*TwinFr[:,nxs],axis=0) dFdvDict[phfx+'BabA'] = dFdbab.T[0] dFdvDict[phfx+'BabU'] = dFdbab.T[1] for i in range(nTwin): dFdvDict[phfx+'TwinFr:'+str(i)] = dFdtw.T[i] return dFdvDict
[docs] def SStructureFactor(refDict,G,hfx,pfx,SGData,SSGData,calcControls,parmDict): ''' Compute super structure factors for all h,k,l,m for phase - no twins puts the result, F^2, in each ref[9] in refList works on blocks of 32 reflections for speed input: :param dict refDict: where 'RefList' list where each ref = h,k,l,m,it,d,... 'FF' dict of form factors - filed in below :param np.array G: reciprocal metric tensor :param str pfx: phase id string :param dict SGData: space group info. dictionary output from SpcGroup :param dict calcControls: :param dict ParmDict: ''' phfx = pfx.split(':')[0]+hfx ast = np.sqrt(np.diag(G)) GS = G/np.outer(ast,ast) uAmat,uBmat = G2lat.Gmat2AB(GS) Amat,Bmat = G2lat.Gmat2AB(G) Mast = twopisq*np.multiply.outer(ast,ast) SGInv = SGData['SGInv'] SGMT = np.array([ops[0].T for ops in SGData['SGOps']]) Nops = len(SGMT)*(1+SGData['SGInv']) if SGData['SGGray']: Nops *= 2 SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']]) GamI = np.array([ops[0][3,3] for ops in SSGData['SSGOps']]) if SGData['SGInv']: GamI = np.hstack((GamI,-GamI)) GamI = np.hstack([GamI for cen in SGData['SGCen']]) if SGData['SGGray']: GamI = np.hstack((GamI,GamI)) SSGT = np.array([ops[1] for ops in SSGData['SSGOps']]) SSCen = SSGData['SSGCen'] FFtables = calcControls['FFtables'] EFtables = calcControls['EFtables'] BLtables = calcControls['BLtables'] MFtables = calcControls['MFtables'] Flack = 1.0 if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict: Flack = 1.-2.*parmDict[phfx+'Flack'] Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata,Gdata = \ GetAtomFXU(pfx,calcControls,parmDict) if not Xdata.size: #no atoms in phase! return waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict) ngl,nWaves,Fmod,Xmod,Umod,Mmod,glTau,glWt = G2mth.makeWaves(waveTypes,FSSdata,XSSdata,USSdata,MSSdata,Mast) #NB: Mmod is ReIm,Mxyz,Ntau,Natm modQ = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']]) if parmDict[pfx+'isMag']: #This part correct for making modulated mag moments on equiv atoms - Mmod matched drawing & Bilbao drawings # mXYZ = np.array([[XYZ[0] for XYZ in list(G2spc.GenAtom(xyz,SGData,All=True,Move=True))] for xyz in (Xdata+dXdata).T]) #Natn,Nop,xyz # if SGData['SGGray']: # mXYZ = np.hstack((mXYZ,mXYZ)) # MmodAR,MmodBR,MmodAI,MmodBI = G2mth.MagMod(glTau,mXYZ,modQ,MSSdata,SGData,SSGData) #Ntau,Nops,Natm,Mxyz cos,sin parts sum matches drawing mXYZ,MmodAR,MmodBR,MmodAI,MmodBI = G2mth.MagMod2(glTau,Xdata+dXdata,modQ,MSSdata,SGData,SSGData) #Ntau,Nops,Natm,Mxyz cos,sin parts sum matches drawing #expand Mmod over mag symm ops. --> GSSdata if not SGData['SGGray']: #for fixed Mx,My,Mz GSdata = np.inner(Gdata.T,np.swapaxes(SGMT,1,2)) #apply sym. ops.--> Natm,Nops,Nxyz if SGData['SGInv'] and not SGData['SGFixed']: #inversion if any GSdata = np.hstack((GSdata,-GSdata)) GSdata = np.hstack([GSdata for cen in SSCen]) #dup over cell centering - Natm,Nops,Mxyz GSdata = SGData['MagMom'][nxs,:,nxs]*GSdata #flip vectors according to spin flip * det(opM) GSdata = np.swapaxes(GSdata,0,1) #Nop,Natm,Mxyz FF = np.zeros(len(Tdata)) if 'NC' in calcControls[hfx+'histType'] or 'NB' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam']) elif 'X' in calcControls[hfx+'histType']: FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata]) FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata]) elif 'SEC' in calcControls[hfx+'histType']: FP = np.zeros(len(Tdata)) FPP = np.zeros(len(Tdata)) Uij = np.array(G2lat.U6toUij(Uijdata)).T bij = Mast*Uij blkSize = 48 #no. of reflections in a block nRef = refDict['RefList'].shape[0] SQ = 1./(2.*refDict['RefList'].T[5])**2 if 'N' in calcControls[hfx+'histType']: dat = G2el.getBLvalues(BLtables) refDict['FF']['El'] = list(dat.keys()) refDict['FF']['FF'] = np.ones((nRef,len(dat)))*list(dat.values()) refDict['FF']['MF'] = np.zeros((nRef,len(dat))) for iel,El in enumerate(refDict['FF']['El']): if El in MFtables: refDict['FF']['MF'].T[iel] = G2el.MagScatFac(MFtables[El],SQ) elif 'SEC' in calcControls[hfx+'histType']: dat = G2el.getFFvalues(EFtables,0.) refDict['FF']['El'] = list(dat.keys()) refDict['FF']['FF'] = np.zeros((nRef,len(dat))) for iel,El in enumerate(refDict['FF']['El']): refDict['FF']['FF'].T[iel] = G2el.ScatFac(EFtables[El],SQ) else: dat = G2el.getFFvalues(FFtables,0.) refDict['FF']['El'] = list(dat.keys()) refDict['FF']['FF'] = np.zeros((nRef,len(dat))) for iel,El in enumerate(refDict['FF']['El']): refDict['FF']['FF'].T[iel] = G2el.ScatFac(FFtables[El],SQ) #reflection processing begins here - big arrays! iBeg = 0 while iBeg < nRef: iFin = min(iBeg+blkSize,nRef) mRef= iFin-iBeg refl = refDict['RefList'][iBeg:iFin] #array(blkSize,nItems) H = refl.T[:4] #array(blkSize,4) HP = H[:3]+modQ[:,nxs]*H[3:] #projected hklm to hkl SQ = 1./(2.*refl.T[5])**2 #array(blkSize) SQfactor = 4.0*SQ*twopisq #ditto prev. Uniq = np.inner(H.T,SSGMT) UniqP = np.inner(HP.T,SGMT) Phi = np.inner(H.T,SSGT) if SGInv and not SGData['SGFixed']: #if centro - expand HKL sets Uniq = np.hstack((Uniq,-Uniq)) Phi = np.hstack((Phi,-Phi)) UniqP = np.hstack((UniqP,-UniqP)) if 'T' in calcControls[hfx+'histType']: if 'P' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14]) else: FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12]) FP = np.repeat(FP.T,Uniq.shape[1],axis=0) FPP = np.repeat(FPP.T,Uniq.shape[1],axis=0) Bab = 0. if phfx+'BabA' in parmDict: Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),Uniq.shape[1]) Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata]) FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,Uniq.shape[1],axis=0) phase = twopi*(np.inner(Uniq[:,:,:3],(dXdata.T+Xdata.T))-Phi[:,:,nxs]) sinp = np.sin(phase) cosp = np.cos(phase) biso = -SQfactor*Uisodata[:,nxs] Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),Uniq.shape[1],axis=1).T HbH = -np.sum(UniqP[:,:,nxs,:]*np.inner(UniqP[:,:,:],bij),axis=-1) #use hklt proj to hkl Tuij = np.where(HbH<1.,np.exp(HbH),1.0) Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/Uniq.shape[1] #refBlk x ops x atoms if 'N' in calcControls[hfx+'histType'] and parmDict[pfx+'isMag']: phasem = twopi*np.inner(mXYZ,HP.T).T #2pi(Q.r) cosm = np.cos(phasem) #Nref,nops,natm sinm = np.sin(phasem) MF = refDict['FF']['MF'][iBeg:iFin].T[Tindx].T #Nref,Natm TMcorr = 0.539*(np.reshape(Tiso,Tuij.shape)*Tuij)[:,0,:]*Mdata*Fdata*MF/(2*Nops) #Nref,Natm HM = np.inner(Bmat,HP.T) #put into cartesian space X||H,Z||H*L; Bmat.T correct Cart coordinates eM = (HM*refl.T[5]).T # normalize HP by d* Nref,hkl=Unit vectors || Q if not SGData['SGGray']: #correct -fixed Mx,My,Mz contribution fam0 = TMcorr[:,nxs,:,nxs]*GSdata[nxs,:,:,:]*cosm[:,:,:,nxs] #Nref,Nops,Natm,Mxyz fbm0 = TMcorr[:,nxs,:,nxs]*GSdata[nxs,:,:,:]*sinm[:,:,:,nxs] # calc mag. structure factors; Nref,Ntau,Nops,Natm,Mxyz fams = TMcorr[:,nxs,nxs,:,nxs]*SGData['MagMom'][nxs,nxs,:,nxs,nxs]*np.array([np.where(H[3,i]!=0,( (-MmodAR+H[3,i]*MmodBR)*cosm[i,nxs,:,:,nxs]+ GamI[nxs,:,nxs,nxs]*(MmodAI-H[3,i]*MmodBI)*sinm[i,nxs,:,:,nxs]), 0.) for i in range(mRef)])/2. #Nref,Ntau,Nops,Natm,Mxyz fbms = TMcorr[:,nxs,nxs,:,nxs]*SGData['MagMom'][nxs,nxs,:,nxs,nxs]*np.array([np.where(H[3,i]!=0,( (MmodAR-H[3,i]*MmodBR)*sinm[i,nxs,:,:,nxs]+ GamI[nxs,:,nxs,nxs]*(-MmodAI+H[3,i]*MmodBI)*cosm[i,nxs,:,:,nxs]), 0.) for i in range(mRef)])/2. #Nref,Ntau,Nops,Natm,Mxyz if not SGData['SGGray']: fams += fam0[:,nxs,:,:,:] fbms += fbm0[:,nxs,:,:,:] #sum ops & atms fasm = np.sum(np.sum(fams,axis=-2),axis=-2) #Nref,Ntau,Mxyz; sum ops & atoms fbsm = np.sum(np.sum(fbms,axis=-2),axis=-2) # #put into cartesian space facm = np.inner(fasm,uBmat) #uBmat best fit for DyMnGe; +,- & -,+ fams, fbms; Nref, Ntau, Mxyz fbcm = np.inner(fbsm,uBmat) #Nref,Ntau,Mxyz #form e.F dot product eDotFa = np.sum(eM[:,nxs,:]*facm,axis=-1) #Nref,Ntau eDotFb = np.sum(eM[:,nxs,:]*fbcm,axis=-1) #intensity Halpern & Johnson fass = np.sum((facm-eM[:,nxs,:]*eDotFa[:,:,nxs])**2,axis=-1) #Nref,Ntau fbss = np.sum((fbcm-eM[:,nxs,:]*eDotFb[:,:,nxs])**2,axis=-1) # gray *2 if SGData['SGGray']: fass *= 2. fbss *= 2. ## #do integration fas = np.sum(fass*glWt[nxs,:],axis=1) fbs = np.sum(fbss*glWt[nxs,:],axis=1) refl.T[10] = fas+fbs #Sum(fams**2,Mxyz) Re + Im refl.T[11] = atan2d(fbs,fas) else: GfpuA = G2mth.Modulation(Uniq,UniqP,nWaves,Fmod,Xmod,Umod,glTau,glWt) #2 x refBlk x sym X atoms if 'T' in calcControls[hfx+'histType']: fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-np.reshape(Flack*FPP,sinp.shape)*sinp*Tcorr]) fb = np.array([np.reshape(Flack*FPP,cosp.shape)*cosp*Tcorr,np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr]) else: fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-Flack*FPP*sinp*Tcorr]) fb = np.array([Flack*FPP*cosp*Tcorr,np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr]) fag = fa*GfpuA[0]-fb*GfpuA[1] #real; 2 x refBlk x sym x atoms fbg = fb*GfpuA[0]+fa*GfpuA[1] fas = np.sum(np.sum(fag,axis=-1),axis=-1) #2 x refBlk; sum sym & atoms fbs = np.sum(np.sum(fbg,axis=-1),axis=-1) refl.T[10] = np.sum(fas,axis=0)**2+np.sum(fbs,axis=0)**2 #square of sums refl.T[11] = atan2d(fbs[0],fas[0]) #use only tau=0; ignore f' & f" if 'P' not in calcControls[hfx+'histType']: refl.T[8] = np.copy(refl.T[10]) iBeg += blkSize return copy.deepcopy(refDict['RefList'])
[docs] def SStructureFactorTw(refDict,G,hfx,pfx,SGData,SSGData,calcControls,parmDict): ''' Compute super structure factors for all h,k,l,m for phase - twins only puts the result, F^2, in each ref[8+im] in refList works on blocks of 32 reflections for speed input: :param dict refDict: where 'RefList' list where each ref = h,k,l,m,it,d,... 'FF' dict of form factors - filed in below :param np.array G: reciprocal metric tensor :param str pfx: phase id string :param dict SGData: space group info. dictionary output from SpcGroup :param dict calcControls: :param dict ParmDict: ''' phfx = pfx.split(':')[0]+hfx ast = np.sqrt(np.diag(G)) Mast = twopisq*np.multiply.outer(ast,ast) SGInv = SGData['SGInv'] SGMT = np.array([ops[0].T for ops in SGData['SGOps']]) SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']]) SSGT = np.array([ops[1] for ops in SSGData['SSGOps']]) FFtables = calcControls['FFtables'] EFtables = calcControls['EFtables'] BLtables = calcControls['BLtables'] MFtables = calcControls['MFtables'] Flack = 1.0 if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict: Flack = 1.-2.*parmDict[phfx+'Flack'] TwinLaw = np.array([[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],]) #4D? TwDict = refDict.get('TwDict',{}) if 'S' in calcControls[hfx+'histType']: NTL = calcControls[phfx+'NTL'] NM = calcControls[phfx+'TwinNMN']+1 TwinLaw = calcControls[phfx+'TwinLaw'] #this'll have to be 4D also... TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))]) TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1)) Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata,Gdata = \ GetAtomFXU(pfx,calcControls,parmDict) if not Xdata.size: #no atoms in phase! return waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict) ngl,nWaves,Fmod,Xmod,Umod,Mmod,glTau,glWt = G2mth.makeWaves(waveTypes,FSSdata,XSSdata,USSdata,Mast) modQ = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']]) FF = np.zeros(len(Tdata)) if 'NC' in calcControls[hfx+'histType'] or 'NB' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam']) elif 'X' in calcControls[hfx+'histType']: FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata]) FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata]) elif 'SEC' in calcControls[hfx+'histType']: FP = np.zeros(len(Tdata)) FPP = np.zeros(len(Tdata)) Uij = np.array(G2lat.U6toUij(Uijdata)).T bij = Mast*Uij blkSize = 32 #no. of reflections in a block nRef = refDict['RefList'].shape[0] if not len(refDict['FF']): #no form factors - 1st time thru StructureFactor SQ = 1./(2.*refDict['RefList'].T[5])**2 if 'N' in calcControls[hfx+'histType']: dat = G2el.getBLvalues(BLtables) refDict['FF']['El'] = list(dat.keys()) refDict['FF']['FF'] = np.ones((nRef,len(dat)))*list(dat.values()) refDict['FF']['MF'] = np.zeros((nRef,len(dat))) for iel,El in enumerate(refDict['FF']['El']): if El in MFtables: refDict['FF']['MF'].T[iel] = G2el.MagScatFac(MFtables[El],SQ) elif 'SEC' in calcControls[hfx+'histType']: dat = G2el.getFFvalues(EFtables,0.) refDict['FF']['El'] = list(dat.keys()) refDict['FF']['FF'] = np.zeros((nRef,len(dat))) for iel,El in enumerate(refDict['FF']['El']): refDict['FF']['FF'].T[iel] = G2el.ScatFac(EFtables[El],SQ) else: dat = G2el.getFFvalues(FFtables,0.) refDict['FF']['El'] = list(dat.keys()) refDict['FF']['FF'] = np.zeros((nRef,len(dat))) for iel,El in enumerate(refDict['FF']['El']): refDict['FF']['FF'].T[iel] = G2el.ScatFac(FFtables[El],SQ) # time0 = time.time() #reflection processing begins here - big arrays! iBeg = 0 while iBeg < nRef: iFin = min(iBeg+blkSize,nRef) refl = refDict['RefList'][iBeg:iFin] #array(blkSize,nItems) H = refl[:,:4] #array(blkSize,4) H3 = refl[:,:3] HP = H[:,:3]+modQ[nxs,:]*H[:,3:] #projected hklm to hkl HP = np.inner(HP,TwinLaw) #array(blkSize,nTwins,4) H3 = np.inner(H3,TwinLaw) TwMask = np.any(HP,axis=-1) if TwinLaw.shape[0] > 1 and TwDict: #need np.inner(TwinLaw[?],TwDict[iref][i])*TwinInv[i] for ir in range(blkSize): iref = ir+iBeg if iref in TwDict: for i in TwDict[iref]: for n in range(NTL): HP[ir][i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM]) H3[ir][i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM]) TwMask = np.any(HP,axis=-1) SQ = 1./(2.*refl.T[5])**2 #array(blkSize) SQfactor = 4.0*SQ*twopisq #ditto prev. Uniq = np.inner(H,SSGMT) Uniq3 = np.inner(H3,SGMT) UniqP = np.inner(HP,SGMT) Phi = np.inner(H,SSGT) if SGInv: #if centro - expand HKL sets Uniq = np.hstack((Uniq,-Uniq)) Uniq3 = np.hstack((Uniq3,-Uniq3)) Phi = np.hstack((Phi,-Phi)) UniqP = np.hstack((UniqP,-UniqP)) if 'T' in calcControls[hfx+'histType']: if 'P' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14]) else: FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12]) FP = np.repeat(FP.T,Uniq.shape[1]*len(TwinLaw),axis=0) FPP = np.repeat(FPP.T,Uniq.shape[1]*len(TwinLaw),axis=0) Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),Uniq.shape[1]*len(TwinLaw)) Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata]) FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,Uniq.shape[1]*len(TwinLaw),axis=0) phase = twopi*(np.inner(Uniq3,(dXdata.T+Xdata.T))-Phi[:,nxs,:,nxs]) sinp = np.sin(phase) cosp = np.cos(phase) biso = -SQfactor*Uisodata[:,nxs] Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),Uniq.shape[1]*len(TwinLaw),axis=1).T HbH = -np.sum(UniqP[:,:,:,nxs]*np.inner(UniqP[:,:,:],bij),axis=-1) #use hklt proj to hkl Tuij = np.where(HbH<1.,np.exp(HbH),1.0) Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/Uniq.shape[1] #refBlk x ops x atoms if 'T' in calcControls[hfx+'histType']: fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-np.reshape(Flack*FPP,sinp.shape)*sinp*Tcorr]) fb = np.array([np.reshape(Flack*FPP,cosp.shape)*cosp*Tcorr,np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr]) else: fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-Flack*FPP*sinp*Tcorr]) fb = np.array([Flack*FPP*cosp*Tcorr,np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr]) GfpuA = G2mth.ModulationTw(Uniq,UniqP,nWaves,Fmod,Xmod,Umod,glTau,glWt) #2 x refBlk x sym X atoms fag = fa*GfpuA[0]-fb*GfpuA[1] #real; 2 x refBlk x sym x atoms fbg = fb*GfpuA[0]+fa*GfpuA[1] fas = np.sum(np.sum(fag,axis=-1),axis=-1) #2 x refBlk; sum sym & atoms fbs = np.sum(np.sum(fbg,axis=-1),axis=-1) refl.T[10] = np.sum(fas[:,:,0],axis=0)**2+np.sum(fbs[:,:,0],axis=0)**2 #FcT from primary twin element refl.T[8] = np.sum(TwinFr*np.sum(TwMask[nxs,:,:]*fas,axis=0)**2,axis=-1)+ \ np.sum(TwinFr*np.sum(TwMask[nxs,:,:]*fbs,axis=0)**2,axis=-1) #Fc sum over twins refl.T[11] = atan2d(fbs[0].T[0],fas[0].T[0]) #ignore f' & f" iBeg += blkSize
# print ('nRef %d time %.4f\r'%(nRef,time.time()-time0))
[docs] def SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict): ''' Compute super structure factor derivatives for all h,k,l,m for phase - no twins Only Fourier component are done analytically here input: :param dict refDict: where 'RefList' list where each ref = h,k,l,m,it,d,... 'FF' dict of form factors - filled in below :param int im: = 1 (could be eliminated) :param np.array G: reciprocal metric tensor :param str hfx: histogram id string :param str pfx: phase id string :param dict SGData: space group info. dictionary output from SpcGroup :param dict SSGData: super space group info. :param dict calcControls: :param dict ParmDict: :returns: dict dFdvDict: dictionary of derivatives ''' phfx = pfx.split(':')[0]+hfx ast = np.sqrt(np.diag(G)) Mast = twopisq*np.multiply.outer(ast,ast) SGInv = SGData['SGInv'] SGMT = np.array([ops[0].T for ops in SGData['SGOps']]) SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']]) SSGT = np.array([ops[1] for ops in SSGData['SSGOps']]) FFtables = calcControls['FFtables'] EFtables = calcControls['EFtables'] BLtables = calcControls['BLtables'] nRef = len(refDict['RefList']) Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata,Gdata = \ GetAtomFXU(pfx,calcControls,parmDict) if not Xdata.size: #no atoms in phase! return {} mSize = len(Mdata) #no. atoms waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict) ngl,nWaves,Fmod,Xmod,Umod,Mmod,glTau,glWt = G2mth.makeWaves(waveTypes,FSSdata,XSSdata,USSdata,MSSdata,Mast) waveShapes,SCtauF,SCtauX,SCtauU,UmodAB = G2mth.makeWavesDerv(ngl,waveTypes,FSSdata,XSSdata,USSdata,Mast) modQ = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']]) FF = np.zeros(len(Tdata)) if 'NC' in calcControls[hfx+'histType'] or 'NB' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam']) elif 'X' in calcControls[hfx+'histType']: FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata]) FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata]) elif 'SEC' in calcControls[hfx+'histType']: FP = np.zeros(len(Tdata)) FPP = np.zeros(len(Tdata)) Uij = np.array(G2lat.U6toUij(Uijdata)).T bij = Mast*Uij if not len(refDict['FF']): if 'N' in calcControls[hfx+'histType']: dat = G2el.getBLvalues(BLtables) #will need wave here for anom. neutron b's elif 'SEC' in calcControls[hfx+'histType']: dat = G2el.getFFvalues(EFtables,0.) else: dat = G2el.getFFvalues(FFtables,0.) refDict['FF']['El'] = list(dat.keys()) refDict['FF']['FF'] = np.zeros((len(refDict['RefList']),len(dat))) dFdvDict = {} dFdfr = np.zeros((nRef,mSize)) dFdx = np.zeros((nRef,mSize,3)) dFdui = np.zeros((nRef,mSize)) dFdua = np.zeros((nRef,mSize,6)) dFdbab = np.zeros((nRef,2)) dFdfl = np.zeros((nRef)) dFdGf = np.zeros((nRef,mSize,FSSdata.shape[1],2)) dFdGx = np.zeros((nRef,mSize,XSSdata.shape[1],6)) dFdGu = np.zeros((nRef,mSize,USSdata.shape[1],12)) Flack = 1.0 if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict: Flack = 1.-2.*parmDict[phfx+'Flack'] time0 = time.time() nRef = len(refDict['RefList'])/100 for iref,refl in enumerate(refDict['RefList']): if 'T' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl.T[12+im]) H = np.array(refl[:4]) HP = H[:3]+modQ*H[3:] #projected hklm to hkl SQ = 1./(2.*refl[4+im])**2 # or (sin(theta)/lambda)**2 SQfactor = 8.0*SQ*np.pi**2 Bab = 0.0 if phfx+'BabA' in parmDict: dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor) Bab = parmDict[phfx+'BabA']*dBabdA Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata]) FF = refDict['FF']['FF'][iref].T[Tindx] Uniq = np.inner(H,SSGMT) Phi = np.inner(H,SSGT) UniqP = np.inner(HP,SGMT) if SGInv: #if centro - expand HKL sets Uniq = np.vstack((Uniq,-Uniq)) Phi = np.hstack((Phi,-Phi)) UniqP = np.vstack((UniqP,-UniqP)) phase = twopi*(np.inner(Uniq[:,:3],(dXdata+Xdata).T)+Phi[:,nxs]) sinp = np.sin(phase) cosp = np.cos(phase) occ = Mdata*Fdata/Uniq.shape[0] biso = -SQfactor*Uisodata[:,nxs] Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),Uniq.shape[0],axis=1).T #ops x atoms HbH = -np.sum(UniqP[:,nxs,:3]*np.inner(UniqP[:,:3],bij),axis=-1) #ops x atoms Hij = np.array([Mast*np.multiply.outer(U[:3],U[:3]) for U in UniqP]) #atoms x 3x3 Hij = np.array([G2lat.UijtoU6(uij) for uij in Hij]) #atoms x 6 Tuij = np.where(HbH<1.,np.exp(HbH),1.0) #ops x atoms Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/Uniq.shape[0] #ops x atoms fot = (FF+FP-Bab)*Tcorr #ops x atoms fotp = FPP*Tcorr #ops x atoms GfpuA = G2mth.Modulation(Uniq,UniqP,nWaves,Fmod,Xmod,Umod,glTau,glWt) #2 x sym X atoms dGdf,dGdx,dGdu = G2mth.ModulationDerv(Uniq,UniqP,Hij,nWaves,waveShapes,Fmod,Xmod,UmodAB,SCtauF,SCtauX,SCtauU,glTau,glWt) # GfpuA is 2 x ops x atoms # derivs are: ops x atoms x waves x 2,6,12, or 5 parms as [real,imag] parts fa = np.array([((FF+FP).T-Bab).T*cosp*Tcorr,-Flack*FPP*sinp*Tcorr]) # array(2,nEqv,nAtoms) fb = np.array([((FF+FP).T-Bab).T*sinp*Tcorr,Flack*FPP*cosp*Tcorr]) #or array(2,nEqv,nAtoms) fag = fa*GfpuA[0]-fb*GfpuA[1] fbg = fb*GfpuA[0]+fa*GfpuA[1] fas = np.sum(np.sum(fag,axis=1),axis=1) # 2 x twin fbs = np.sum(np.sum(fbg,axis=1),axis=1) fax = np.array([-fot*sinp,-fotp*cosp]) #positions; 2 x ops x atoms fbx = np.array([fot*cosp,-fotp*sinp]) fax = fax*GfpuA[0]-fbx*GfpuA[1] fbx = fbx*GfpuA[0]+fax*GfpuA[1] #sum below is over Uniq dfadfr = np.sum(fag/occ,axis=1) #Fdata != 0 ever avoids /0. problem dfbdfr = np.sum(fbg/occ,axis=1) #Fdata != 0 avoids /0. problem dfadba = np.sum(-cosp*Tcorr[:,nxs],axis=1) dfbdba = np.sum(-sinp*Tcorr[:,nxs],axis=1) dfadui = np.sum(-SQfactor*fag,axis=1) dfbdui = np.sum(-SQfactor*fbg,axis=1) dfadx = np.sum(twopi*Uniq[:,:3]*np.swapaxes(fax,-2,-1)[:,:,:,nxs],axis=-2) #2 x nAtom x 3xyz; sum nOps dfbdx = np.sum(twopi*Uniq[:,:3]*np.swapaxes(fbx,-2,-1)[:,:,:,nxs],axis=-2) dfadua = np.sum(-Hij*np.swapaxes(fag,-2,-1)[:,:,:,nxs],axis=-2) #2 x nAtom x 6Uij; sum nOps dfbdua = np.sum(-Hij*np.swapaxes(fbg,-2,-1)[:,:,:,nxs],axis=-2) #these are correct also for twins above # array(2,nAtom,nWave,2) & array(2,nAtom,nWave,6) & array(2,nAtom,nWave,12); sum on nOps dfadGf = np.sum(fa[:,:,:,nxs,nxs]*dGdf[0][nxs,:,:,:,:]-fb[:,:,:,nxs,nxs]*dGdf[1][nxs,:,:,:,:],axis=1) dfbdGf = np.sum(fb[:,:,:,nxs,nxs]*dGdf[0][nxs,:,:,:,:]+fa[:,:,:,nxs,nxs]*dGdf[1][nxs,:,:,:,:],axis=1) dfadGx = np.sum(fa[:,:,:,nxs,nxs]*dGdx[0][nxs,:,:,:,:]-fb[:,:,:,nxs,nxs]*dGdx[1][nxs,:,:,:,:],axis=1) dfbdGx = np.sum(fb[:,:,:,nxs,nxs]*dGdx[0][nxs,:,:,:,:]+fa[:,:,:,nxs,nxs]*dGdx[1][nxs,:,:,:,:],axis=1) dfadGu = np.sum(fa[:,:,:,nxs,nxs]*dGdu[0][nxs,:,:,:,:]-fb[:,:,:,nxs,nxs]*dGdu[1][nxs,:,:,:,:],axis=1) dfbdGu = np.sum(fb[:,:,:,nxs,nxs]*dGdu[0][nxs,:,:,:,:]+fa[:,:,:,nxs,nxs]*dGdu[1][nxs,:,:,:,:],axis=1) if not SGData['SGInv']: #Flack derivative dfadfl = np.sum(-FPP*Tcorr*sinp) dfbdfl = np.sum(FPP*Tcorr*cosp) else: dfadfl = 1.0 dfbdfl = 1.0 SA = fas[0]+fas[1] #float = A+A' SB = fbs[0]+fbs[1] #float = B+B' if 'P' in calcControls[hfx+'histType']: #checked perfect for centro & noncentro? dFdfl[iref] = -SA*dfadfl-SB*dfbdfl #array(nRef,) dFdfr[iref] = 2.*(fas[0]*dfadfr[0]+fas[1]*dfadfr[1])*Mdata/len(Uniq)+ \ 2.*(fbs[0]*dfbdfr[0]-fbs[1]*dfbdfr[1])*Mdata/len(Uniq) dFdx[iref] = 2.*(fas[0]*dfadx[0]+fas[1]*dfadx[1])+ \ 2.*(fbs[0]*dfbdx[0]+fbs[1]*dfbdx[1]) dFdui[iref] = 2.*(fas[0]*dfadui[0]+fas[1]*dfadui[1])+ \ 2.*(fbs[0]*dfbdui[0]-fbs[1]*dfbdui[1]) dFdua[iref] = 2.*(fas[0]*dfadua[0]+fas[1]*dfadua[1])+ \ 2.*(fbs[0]*dfbdua[0]+fbs[1]*dfbdua[1]) dFdGf[iref] = 2.*(fas[0]*dfadGf[0]+fas[1]*dfadGf[1])+ \ 2.*(fbs[0]*dfbdGf[0]+fbs[1]*dfbdGf[1]) dFdGx[iref] = 2.*(fas[0]*dfadGx[0]+fas[1]*dfadGx[1])+ \ 2.*(fbs[0]*dfbdGx[0]-fbs[1]*dfbdGx[1]) dFdGu[iref] = 2.*(fas[0]*dfadGu[0]+fas[1]*dfadGu[1])+ \ 2.*(fbs[0]*dfbdGu[0]+fbs[1]*dfbdGu[1]) else: #OK, I think dFdfr[iref] = 2.*(SA*dfadfr[0]+SA*dfadfr[1]+SB*dfbdfr[0]+SB*dfbdfr[1])*Mdata/len(Uniq) #array(nRef,nAtom) dFdx[iref] = 2.*(SA*dfadx[0]+SA*dfadx[1]+SB*dfbdx[0]+SB*dfbdx[1]) #array(nRef,nAtom,3) dFdui[iref] = 2.*(SA*dfadui[0]+SA*dfadui[1]+SB*dfbdui[0]+SB*dfbdui[1]) #array(nRef,nAtom) dFdua[iref] = 2.*(SA*dfadua[0]+SA*dfadua[1]+SB*dfbdua[0]+SB*dfbdua[1]) #array(nRef,nAtom,6) dFdfl[iref] = -SA*dfadfl-SB*dfbdfl #array(nRef,) dFdGf[iref] = 2.*(SA*dfadGf[0]+SB*dfbdGf[1]) #array(nRef,natom,nwave,2) dFdGx[iref] = 2.*(SA*dfadGx[0]+SB*dfbdGx[1]) #array(nRef,natom,nwave,6) dFdGu[iref] = 2.*(SA*dfadGu[0]+SB*dfbdGu[1]) #array(nRef,natom,nwave,12) if phfx+'BabA' in parmDict: dFdbab[iref] = 2.*fas[0]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T+ \ 2.*fbs[0]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T #loop over atoms - each dict entry is list of derivatives for all the reflections if not iref%100 : print (' %d derivative time %.4f\r'%(iref,time.time()-time0),end='') for i in range(len(Mdata)): #loop over atoms dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i] dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i] dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i] dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i] dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i] dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i] dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i] dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i] dFdvDict[pfx+'AU12:'+str(i)] = dFdua.T[3][i] dFdvDict[pfx+'AU13:'+str(i)] = dFdua.T[4][i] dFdvDict[pfx+'AU23:'+str(i)] = dFdua.T[5][i] for j in range(FSSdata.shape[1]): #loop over waves Fzero & Fwid? dFdvDict[pfx+'Fsin:'+str(i)+':'+str(j)] = dFdGf.T[0][j][i] dFdvDict[pfx+'Fcos:'+str(i)+':'+str(j)] = dFdGf.T[1][j][i] nx = 0 if waveTypes[i] in ['Block','ZigZag']: nx = 1 for j in range(XSSdata.shape[1]-nx): #loop over waves dFdvDict[pfx+'Xsin:'+str(i)+':'+str(j+nx)] = dFdGx.T[0][j][i] dFdvDict[pfx+'Ysin:'+str(i)+':'+str(j+nx)] = dFdGx.T[1][j][i] dFdvDict[pfx+'Zsin:'+str(i)+':'+str(j+nx)] = dFdGx.T[2][j][i] dFdvDict[pfx+'Xcos:'+str(i)+':'+str(j+nx)] = dFdGx.T[3][j][i] dFdvDict[pfx+'Ycos:'+str(i)+':'+str(j+nx)] = dFdGx.T[4][j][i] dFdvDict[pfx+'Zcos:'+str(i)+':'+str(j+nx)] = dFdGx.T[5][j][i] for j in range(USSdata.shape[1]): #loop over waves dFdvDict[pfx+'U11sin:'+str(i)+':'+str(j)] = dFdGu.T[0][j][i] dFdvDict[pfx+'U22sin:'+str(i)+':'+str(j)] = dFdGu.T[1][j][i] dFdvDict[pfx+'U33sin:'+str(i)+':'+str(j)] = dFdGu.T[2][j][i] dFdvDict[pfx+'U12sin:'+str(i)+':'+str(j)] = dFdGu.T[3][j][i] dFdvDict[pfx+'U13sin:'+str(i)+':'+str(j)] = dFdGu.T[4][j][i] dFdvDict[pfx+'U23sin:'+str(i)+':'+str(j)] = dFdGu.T[5][j][i] dFdvDict[pfx+'U11cos:'+str(i)+':'+str(j)] = dFdGu.T[6][j][i] dFdvDict[pfx+'U22cos:'+str(i)+':'+str(j)] = dFdGu.T[7][j][i] dFdvDict[pfx+'U33cos:'+str(i)+':'+str(j)] = dFdGu.T[8][j][i] dFdvDict[pfx+'U12cos:'+str(i)+':'+str(j)] = dFdGu.T[9][j][i] dFdvDict[pfx+'U13cos:'+str(i)+':'+str(j)] = dFdGu.T[10][j][i] dFdvDict[pfx+'U23cos:'+str(i)+':'+str(j)] = dFdGu.T[11][j][i] dFdvDict[phfx+'Flack'] = 4.*dFdfl.T dFdvDict[phfx+'BabA'] = dFdbab.T[0] dFdvDict[phfx+'BabU'] = dFdbab.T[1] return dFdvDict
[docs] def SStructureFactorDerv2(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict): ''' Compute super structure factor derivatives for all h,k,l,m for phase - no twins input: :param dict refDict: where 'RefList' list where each ref = h,k,l,m,it,d,... 'FF' dict of form factors - filled in below :param int im: = 1 (could be eliminated) :param np.array G: reciprocal metric tensor :param str hfx: histogram id string :param str pfx: phase id string :param dict SGData: space group info. dictionary output from SpcGroup :param dict SSGData: super space group info. :param dict calcControls: :param dict ParmDict: :returns: dict dFdvDict: dictionary of derivatives ''' trefDict = copy.deepcopy(refDict) dM = 1.e-4 dFdvDict = {} for parm in parmDict: if ':' not in parm: continue if parm.split(':')[2] in ['Tmin','Tmax','Xmax','Ymax','Zmax','Fzero','Fwid', 'MXsin','MXcos','MYsin','MYcos','MZsin','MZcos','AMx','AMy','AMz',]: parmDict[parm] += dM prefList = SStructureFactor(trefDict,G,hfx,pfx,SGData,SSGData,calcControls,parmDict) parmDict[parm] -= 2*dM mrefList = SStructureFactor(trefDict,G,hfx,pfx,SGData,SSGData,calcControls,parmDict) parmDict[parm] += dM dFdvDict[parm] = (prefList[:,9+im]-mrefList[:,9+im])/(2.*dM) return dFdvDict
[docs] def SStructureFactorDervTw(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict): 'Needs a doc string' phfx = pfx.split(':')[0]+hfx ast = np.sqrt(np.diag(G)) Mast = twopisq*np.multiply.outer(ast,ast) SGInv = SGData['SGInv'] SGMT = np.array([ops[0].T for ops in SGData['SGOps']]) SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']]) SSGT = np.array([ops[1] for ops in SSGData['SSGOps']]) FFtables = calcControls['FFtables'] EFtables = calcControls['EFtables'] BLtables = calcControls['BLtables'] TwinLaw = np.array([[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],]) TwDict = refDict.get('TwDict',{}) if 'S' in calcControls[hfx+'histType']: NTL = calcControls[phfx+'NTL'] NM = calcControls[phfx+'TwinNMN']+1 TwinLaw = calcControls[phfx+'TwinLaw'] TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1)) nTwin = len(TwinLaw) nRef = len(refDict['RefList']) Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata,Gdata = \ GetAtomFXU(pfx,calcControls,parmDict) if not Xdata.size: #no atoms in phase! return {} mSize = len(Mdata) #no. atoms waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict) ngl,nWaves,Fmod,Xmod,Umod,Mmod,glTau,glWt = G2mth.makeWaves(waveTypes,FSSdata,XSSdata,USSdata,MSSdata,Mast) #NB: Mmod is ReIm,Mxyz,Ntau,Natm waveShapes,SCtauF,SCtauX,SCtauU,UmodAB = G2mth.makeWavesDerv(ngl,waveTypes,FSSdata,XSSdata,USSdata,Mast) modQ = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']]) FF = np.zeros(len(Tdata)) if 'NC' in calcControls[hfx+'histType'] or 'NB' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam']) elif 'X' in calcControls[hfx+'histType']: FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata]) FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata]) elif 'SEC' in calcControls[hfx+'histType']: FP = np.zeros(len(Tdata)) FPP = np.zeros(len(Tdata)) Uij = np.array(G2lat.U6toUij(Uijdata)).T bij = Mast*Uij if not len(refDict['FF']): if 'N' in calcControls[hfx+'histType']: dat = G2el.getBLvalues(BLtables) #will need wave here for anom. neutron b's elif 'SEC' in calcControls[hfx+'histType']: dat = G2el.getFFvalues(EFtables,0.) else: dat = G2el.getFFvalues(FFtables,0.) refDict['FF']['El'] = list(dat.keys()) refDict['FF']['FF'] = np.zeros((len(refDict['RefList']),len(dat))) dFdvDict = {} dFdfr = np.zeros((nRef,nTwin,mSize)) dFdx = np.zeros((nRef,nTwin,mSize,3)) dFdui = np.zeros((nRef,nTwin,mSize)) dFdua = np.zeros((nRef,nTwin,mSize,6)) dFdbab = np.zeros((nRef,nTwin,2)) dFdtw = np.zeros((nRef,nTwin)) dFdGf = np.zeros((nRef,nTwin,mSize,FSSdata.shape[1])) dFdGx = np.zeros((nRef,nTwin,mSize,XSSdata.shape[1],3)) dFdGz = np.zeros((nRef,nTwin,mSize,5)) dFdGu = np.zeros((nRef,nTwin,mSize,USSdata.shape[1],6)) Flack = 1.0 if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict: Flack = 1.-2.*parmDict[phfx+'Flack'] time0 = time.time() nRef = len(refDict['RefList'])/100 for iref,refl in enumerate(refDict['RefList']): if 'T' in calcControls[hfx+'histType']: FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl.T[12+im]) H = np.array(refl[:4]) HP = H[:3]+modQ*H[3:] #projected hklm to hkl H = np.inner(H.T,TwinLaw) #maybe array(4,nTwins) or (4) TwMask = np.any(H,axis=-1) if TwinLaw.shape[0] > 1 and TwDict: if iref in TwDict: for i in TwDict[iref]: for n in range(NTL): H[i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM]) TwMask = np.any(H,axis=-1) SQ = 1./(2.*refl[4+im])**2 # or (sin(theta)/lambda)**2 SQfactor = 8.0*SQ*np.pi**2 dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor) Bab = parmDict[phfx+'BabA']*dBabdA Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata]) FF = refDict['FF']['FF'][iref].T[Tindx] Uniq = np.inner(H,SSGMT) Phi = np.inner(H,SSGT) UniqP = np.inner(HP,SGMT) if SGInv: #if centro - expand HKL sets Uniq = np.vstack((Uniq,-Uniq)) Phi = np.hstack((Phi,-Phi)) UniqP = np.vstack((UniqP,-UniqP)) phase = twopi*(np.inner(Uniq[:,:3],(dXdata+Xdata).T)+Phi[:,nxs]) sinp = np.sin(phase) cosp = np.cos(phase) occ = Mdata*Fdata/Uniq.shape[0] biso = -SQfactor*Uisodata[:,nxs] Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),Uniq.shape[0]*len(TwinLaw),axis=1).T #ops x atoms HbH = -np.sum(UniqP[:,nxs,:3]*np.inner(UniqP[:,:3],bij),axis=-1) #ops x atoms Hij = np.array([Mast*np.multiply.outer(U[:3],U[:3]) for U in UniqP]) #atoms x 3x3 Hij = np.squeeze(np.reshape(np.array([G2lat.UijtoU6(uij) for uij in Hij]),(nTwin,-1,6))) Tuij = np.where(HbH<1.,np.exp(HbH),1.0) #ops x atoms Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/Uniq.shape[0] #ops x atoms fot = (FF+FP-Bab)*Tcorr #ops x atoms fotp = FPP*Tcorr #ops x atoms GfpuA = G2mth.Modulation(Uniq,UniqP,nWaves,Fmod,Xmod,Umod,glTau,glWt) #2 x sym X atoms dGdf,dGdx,dGdu,dGdz = G2mth.ModulationDerv(Uniq,UniqP,Hij,nWaves,waveShapes,Fmod,Xmod,UmodAB,SCtauF,SCtauX,SCtauU,glTau,glWt) # GfpuA is 2 x ops x atoms # derivs are: ops x atoms x waves x 2,6,12, or 5 parms as [real,imag] parts fa = np.array([((FF+FP).T-Bab).T*cosp*Tcorr,-Flack*FPP*sinp*Tcorr]) # array(2,nTwin,nEqv,nAtoms) fb = np.array([((FF+FP).T-Bab).T*sinp*Tcorr,Flack*FPP*cosp*Tcorr]) #or array(2,nEqv,nAtoms) fag = fa*GfpuA[0]-fb*GfpuA[1] fbg = fb*GfpuA[0]+fa*GfpuA[1] fas = np.sum(np.sum(fag,axis=1),axis=1) # 2 x twin fbs = np.sum(np.sum(fbg,axis=1),axis=1) fax = np.array([-fot*sinp,-fotp*cosp]) #positions; 2 x twin x ops x atoms fbx = np.array([fot*cosp,-fotp*sinp]) fax = fax*GfpuA[0]-fbx*GfpuA[1] fbx = fbx*GfpuA[0]+fax*GfpuA[1] #sum below is over Uniq dfadfr = np.sum(fag/occ,axis=1) #Fdata != 0 ever avoids /0. problem dfbdfr = np.sum(fbg/occ,axis=1) #Fdata != 0 avoids /0. problem dfadba = np.sum(-cosp*Tcorr[:,nxs],axis=1) dfbdba = np.sum(-sinp*Tcorr[:,nxs],axis=1) dfadui = np.sum(-SQfactor*fag,axis=1) dfbdui = np.sum(-SQfactor*fbg,axis=1) dfadx = np.array([np.sum(twopi*Uniq[it,:,:3]*np.swapaxes(fax,-2,-1)[:,it,:,:,nxs],axis=-2) for it in range(nTwin)]) dfbdx = np.array([np.sum(twopi*Uniq[it,:,:3]*np.swapaxes(fbx,-2,-1)[:,it,:,:,nxs],axis=-2) for it in range(nTwin)]) dfadua = np.array([np.sum(-Hij[it]*np.swapaxes(fag,-2,-1)[:,it,:,:,nxs],axis=-2) for it in range(nTwin)]) dfbdua = np.array([np.sum(-Hij[it]*np.swapaxes(fbg,-2,-1)[:,it,:,:,nxs],axis=-2) for it in range(nTwin)]) # array(2,nTwin,nAtom,3) & array(2,nTwin,nAtom,6) & array(2,nTwin,nAtom,12) dfadGf = np.sum(fa[:,it,:,:,nxs,nxs]*dGdf[0][nxs,nxs,:,:,:,:]-fb[:,it,:,:,nxs,nxs]*dGdf[1][nxs,nxs,:,:,:,:],axis=1) dfbdGf = np.sum(fb[:,it,:,:,nxs,nxs]*dGdf[0][nxs,nxs,:,:,:,:]+fa[:,it,:,:,nxs,nxs]*dGdf[1][nxs,nxs,:,:,:,:],axis=1) dfadGx = np.sum(fa[:,it,:,:,nxs,nxs]*dGdx[0][nxs,nxs,:,:,:,:]-fb[:,it,:,:,nxs,nxs]*dGdx[1][nxs,nxs,:,:,:,:],axis=1) dfbdGx = np.sum(fb[:,it,:,:,nxs,nxs]*dGdx[0][nxs,nxs,:,:,:,:]+fa[:,it,:,:,nxs,nxs]*dGdx[1][nxs,nxs,:,:,:,:],axis=1) dfadGz = np.sum(fa[:,it,:,0,nxs,nxs]*dGdz[0][nxs,nxs,:,:,:]-fb[:,it,:,0,nxs,nxs]*dGdz[1][nxs,nxs,:,:,:],axis=1) dfbdGz = np.sum(fb[:,it,:,0,nxs,nxs]*dGdz[0][nxs,nxs,:,:,:]+fa[:,it,:,0,nxs,nxs]*dGdz[1][nxs,nxs,:,:,:],axis=1) dfadGu = np.sum(fa[:,it,:,:,nxs,nxs]*dGdu[0][nxs,nxs,:,:,:,:]-fb[:,it,:,:,nxs,nxs]*dGdu[1][nxs,nxs,:,:,:,:],axis=1) dfbdGu = np.sum(fb[:,it,:,:,nxs,nxs]*dGdu[0][nxs,nxs,:,:,:,:]+fa[:,it,:,:,nxs,nxs]*dGdu[1][nxs,nxs,:,:,:,:],axis=1) # GSASIIpath.IPyBreak() #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for Al2O3! SA = fas[0]+fas[1] #float = A+A' (might be array[nTwin]) SB = fbs[0]+fbs[1] #float = B+B' (might be array[nTwin]) dFdfr[iref] = [2.*TwMask[it]*(SA[it]*dfadfr[0][it]+SA[it]*dfadfr[1][it]+SB[it]*dfbdfr[0][it]+SB[it]*dfbdfr[1][it])*Mdata/len(Uniq[it]) for it in range(nTwin)] dFdx[iref] = [2.*TwMask[it]*(SA[it]*dfadx[it][0]+SA[it]*dfadx[it][1]+SB[it]*dfbdx[it][0]+SB[it]*dfbdx[it][1]) for it in range(nTwin)] dFdui[iref] = [2.*TwMask[it]*(SA[it]*dfadui[it][0]+SA[it]*dfadui[it][1]+SB[it]*dfbdui[it][0]+SB[it]*dfbdui[it][1]) for it in range(nTwin)] dFdua[iref] = [2.*TwMask[it]*(SA[it]*dfadua[it][0]+SA[it]*dfadua[it][1]+SB[it]*dfbdua[it][0]+SB[it]*dfbdua[it][1]) for it in range(nTwin)] dFdtw[iref] = np.sum(TwMask*fas,axis=0)**2+np.sum(TwMask*fbs,axis=0)**2 dFdGf[iref] = [2.*TwMask[it]*(SA[it]*dfadGf[1]+SB[it]*dfbdGf[1]) for it in range(nTwin)] dFdGx[iref] = [2.*TwMask[it]*(SA[it]*dfadGx[1]+SB[it]*dfbdGx[1]) for it in range(nTwin)] dFdGz[iref] = [2.*TwMask[it]*(SA[it]*dfadGz[1]+SB[it]*dfbdGz[1]) for it in range(nTwin)] dFdGu[iref] = [2.*TwMask[it]*(SA[it]*dfadGu[1]+SB[it]*dfbdGu[1]) for it in range(nTwin)] # GSASIIpath.IPyBreak() dFdbab[iref] = 2.*fas[0]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T+ \ 2.*fbs[0]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T #loop over atoms - each dict entry is list of derivatives for all the reflections if not iref%100 : print (' %d derivative time %.4f\r'%(iref,time.time()-time0),end='') for i in range(len(Mdata)): #loop over atoms dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i] dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i] dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i] dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i] dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i] dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i] dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i] dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i] dFdvDict[pfx+'AU12:'+str(i)] = dFdua.T[3][i] dFdvDict[pfx+'AU13:'+str(i)] = dFdua.T[4][i] dFdvDict[pfx+'AU23:'+str(i)] = dFdua.T[5][i] for j in range(FSSdata.shape[1]): #loop over waves Fzero & Fwid? dFdvDict[pfx+'Fsin:'+str(i)+':'+str(j)] = dFdGf.T[0][j][i] dFdvDict[pfx+'Fcos:'+str(i)+':'+str(j)] = dFdGf.T[1][j][i] nx = 0 if waveTypes[i] in ['Block','ZigZag']: nx = 1 dFdvDict[pfx+'Tmin:'+str(i)+':0'] = dFdGz.T[0][i] #ZigZag/Block waves (if any) dFdvDict[pfx+'Tmax:'+str(i)+':0'] = dFdGz.T[1][i] dFdvDict[pfx+'Xmax:'+str(i)+':0'] = dFdGz.T[2][i] dFdvDict[pfx+'Ymax:'+str(i)+':0'] = dFdGz.T[3][i] dFdvDict[pfx+'Zmax:'+str(i)+':0'] = dFdGz.T[4][i] for j in range(XSSdata.shape[1]-nx): #loop over waves dFdvDict[pfx+'Xsin:'+str(i)+':'+str(j+nx)] = dFdGx.T[0][j][i] dFdvDict[pfx+'Ysin:'+str(i)+':'+str(j+nx)] = dFdGx.T[1][j][i] dFdvDict[pfx+'Zsin:'+str(i)+':'+str(j+nx)] = dFdGx.T[2][j][i] dFdvDict[pfx+'Xcos:'+str(i)+':'+str(j+nx)] = dFdGx.T[3][j][i] dFdvDict[pfx+'Ycos:'+str(i)+':'+str(j+nx)] = dFdGx.T[4][j][i] dFdvDict[pfx+'Zcos:'+str(i)+':'+str(j+nx)] = dFdGx.T[5][j][i] for j in range(USSdata.shape[1]): #loop over waves dFdvDict[pfx+'U11sin:'+str(i)+':'+str(j)] = dFdGu.T[0][j][i] dFdvDict[pfx+'U22sin:'+str(i)+':'+str(j)] = dFdGu.T[1][j][i] dFdvDict[pfx+'U33sin:'+str(i)+':'+str(j)] = dFdGu.T[2][j][i] dFdvDict[pfx+'U12sin:'+str(i)+':'+str(j)] = dFdGu.T[3][j][i] dFdvDict[pfx+'U13sin:'+str(i)+':'+str(j)] = dFdGu.T[4][j][i] dFdvDict[pfx+'U23sin:'+str(i)+':'+str(j)] = dFdGu.T[5][j][i] dFdvDict[pfx+'U11cos:'+str(i)+':'+str(j)] = dFdGu.T[6][j][i] dFdvDict[pfx+'U22cos:'+str(i)+':'+str(j)] = dFdGu.T[7][j][i] dFdvDict[pfx+'U33cos:'+str(i)+':'+str(j)] = dFdGu.T[8][j][i] dFdvDict[pfx+'U12cos:'+str(i)+':'+str(j)] = dFdGu.T[9][j][i] dFdvDict[pfx+'U13cos:'+str(i)+':'+str(j)] = dFdGu.T[10][j][i] dFdvDict[pfx+'U23cos:'+str(i)+':'+str(j)] = dFdGu.T[11][j][i] # GSASIIpath.IPyBreak() dFdvDict[phfx+'BabA'] = dFdbab.T[0] dFdvDict[phfx+'BabU'] = dFdbab.T[1] return dFdvDict
[docs] def SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varyList): ''' Single crystal extinction function; returns extinction & derivative ''' extCor = 1.0 dervDict = {} dervCor = 1.0 if calcControls[phfx+'EType'] != 'None': SQ = 1/(4.*ref[4+im]**2) if 'C' in parmDict[hfx+'Type']: cos2T = 1.0-2.*SQ*parmDict[hfx+'Lam']**2 #cos(2theta) else: #'T' cos2T = 1.0-2.*SQ*ref[12+im]**2 #cos(2theta) if 'SXC' in parmDict[hfx+'Type'] or 'SEC' in parmDict[hfx+'Type']: AV = 7.9406e5/parmDict[pfx+'Vol']**2 #is 7.9406e5 constant right for electroms? PL = np.sqrt(1.0-cos2T**2)/parmDict[hfx+'Lam'] P12 = (calcControls[phfx+'Cos2TM']+cos2T**4)/(calcControls[phfx+'Cos2TM']+cos2T**2) PLZ = AV*P12*ref[9+im]*parmDict[hfx+'Lam']**2 elif 'SNT' in parmDict[hfx+'Type']: AV = 1.e7/parmDict[pfx+'Vol']**2 PL = SQ PLZ = AV*ref[9+im]*ref[12+im]**2 elif 'SNC' in parmDict[hfx+'Type']: AV = 1.e7/parmDict[pfx+'Vol']**2 PL = np.sqrt(1.0-cos2T**2)/parmDict[hfx+'Lam'] PLZ = AV*ref[9+im]*parmDict[hfx+'Lam']**2 if 'Primary' in calcControls[phfx+'EType']: PLZ *= 1.5 else: if 'C' in parmDict[hfx+'Type']: PLZ *= calcControls[phfx+'Tbar'] else: #'T' PLZ *= ref[13+im] #t-bar if 'Primary' in calcControls[phfx+'EType']: PLZ *= 1.5 PSIG = parmDict[phfx+'Ep'] elif 'I & II' in calcControls[phfx+'EType']: PSIG = parmDict[phfx+'Eg']/np.sqrt(1.+(parmDict[phfx+'Es']*PL/parmDict[phfx+'Eg'])**2) elif 'Type II' in calcControls[phfx+'EType']: PSIG = parmDict[phfx+'Es'] else: # 'Secondary Type I' PSIG = parmDict[phfx+'Eg']/PL AG = 0.58+0.48*cos2T+0.24*cos2T**2 AL = 0.025+0.285*cos2T BG = 0.02-0.025*cos2T BL = 0.15-0.2*(0.75-cos2T)**2 if cos2T < 0.: BL = -0.45*cos2T CG = 2. CL = 2. PF = PLZ*PSIG if 'Gaussian' in calcControls[phfx+'EApprox']: PF4 = 1.+CG*PF+AG*PF**2/(1.+BG*PF) extCor = np.sqrt(PF4) PF3 = 0.5*(CG+2.*AG*PF/(1.+BG*PF)-AG*PF**2*BG/(1.+BG*PF)**2)/(PF4*extCor) else: PF4 = 1.+CL*PF+AL*PF**2/(1.+BL*PF) extCor = np.sqrt(PF4) PF3 = 0.5*(CL+2.*AL*PF/(1.+BL*PF)-AL*PF**2*BL/(1.+BL*PF)**2)/(PF4*extCor) dervCor = (1.+PF)*PF3 #extinction corr for other derivatives if 'Primary' in calcControls[phfx+'EType'] and phfx+'Ep' in varyList: dervDict[phfx+'Ep'] = -ref[7+im]*PLZ*PF3 if 'II' in calcControls[phfx+'EType'] and phfx+'Es' in varyList: dervDict[phfx+'Es'] = -ref[7+im]*PLZ*PF3*(PSIG/parmDict[phfx+'Es'])**3 if 'I' in calcControls[phfx+'EType'] and phfx+'Eg' in varyList: dervDict[phfx+'Eg'] = -ref[7+im]*PLZ*PF3*(PSIG/parmDict[phfx+'Eg'])**3*PL**2 return 1./extCor,dervDict,dervCor
[docs] def Dict2Values(parmdict, varylist): '''Use before call to leastsq to setup list of values for the parameters in parmdict, as selected by key in varylist''' return [parmdict[key] for key in varylist]
[docs] def Values2Dict(parmdict, varylist, values): ''' Use after call to leastsq to update the parameter dictionary with values corresponding to keys in varylist''' parmdict.update(zip(varylist,values))
[docs] def GetNewCellParms(parmDict,varyList): '''Compute unit cell tensor terms from varied Aij and Dij values. Terms are included in the dict only if Aij or Dij is varied. ''' newCellDict = {} Anames = ['A'+str(i) for i in range(6)] Ddict = dict(zip(['D11','D22','D33','D12','D13','D23'],Anames)) for item in varyList: keys = item.split(':') if keys[2] in Ddict: key = keys[0]+'::'+Ddict[keys[2]] #key is e.g. '0::A0' parm = keys[0]+'::'+keys[2] #parm is e.g. '0::D11' newCellDict[parm] = [key,parmDict[key]+parmDict[item]] return newCellDict # is e.g. {'0::D11':A0-D11}
[docs] def ApplyXYZshifts(parmDict,varyList): ''' takes atom x,y,z shift and applies it to corresponding atom x,y,z value :param dict parmDict: parameter dictionary :param list varyList: list of variables (not used!) :returns: newAtomDict - dictionary of new atomic coordinate names & values; key is parameter shift name ''' newAtomDict = {} for item in parmDict: if 'dA' in item: parm = ''.join(item.split('d')) parmDict[parm] += parmDict[item] newAtomDict[item] = [parm,parmDict[parm]] return newAtomDict
[docs] def SHTXcal(refl,im,g,pfx,hfx,SGData,calcControls,parmDict): 'Spherical harmonics texture' IFCoup = 'Bragg' in calcControls[hfx+'instType'] if 'T' in calcControls[hfx+'histType']: tth = parmDict[hfx+'2-theta'] else: tth = refl[5+im] odfCor = 1.0 H = refl[:3] cell = G2lat.Gmat2cell(g) Sangls = [parmDict[pfx+'SH omega'],parmDict[pfx+'SH chi'],parmDict[pfx+'SH phi']] Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']] phi,beta = G2lat.CrsAng(H,cell,SGData) psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs. SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],parmDict[pfx+'SHmodel'],parmDict[pfx+'SHorder']) for item in SHnames: L,M,N = eval(item.strip('C')) Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta) Ksl,x,x = G2lat.GetKsl(L,M,parmDict[pfx+'SHmodel'],psi,gam) Lnorm = G2lat.Lnorm(L) odfCor += parmDict[pfx+item]*Lnorm*Kcl*Ksl return odfCor
[docs] def SHTXcalDerv(refl,im,g,pfx,hfx,SGData,calcControls,parmDict): 'Spherical harmonics texture derivatives' if 'T' in calcControls[hfx+'histType']: tth = parmDict[hfx+'2-theta'] else: tth = refl[5+im] IFCoup = 'Bragg' in calcControls[hfx+'instType'] odfCor = 1.0 dFdODF = {} dFdSA = [0,0,0] H = refl[:3] cell = G2lat.Gmat2cell(g) Sangls = [parmDict[pfx+'SH omega'],parmDict[pfx+'SH chi'],parmDict[pfx+'SH phi']] Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']] phi,beta = G2lat.CrsAng(H,cell,SGData) psi,gam,dPSdA,dGMdA = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],parmDict[pfx+'SHmodel'],parmDict[pfx+'SHorder']) for item in SHnames: L,M,N = eval(item.strip('C')) Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta) Ksl,dKsdp,dKsdg = G2lat.GetKsl(L,M,parmDict[pfx+'SHmodel'],psi,gam) Lnorm = G2lat.Lnorm(L) odfCor += parmDict[pfx+item]*Lnorm*Kcl*Ksl dFdODF[pfx+item] = Lnorm*Kcl*Ksl for i in range(3): dFdSA[i] += parmDict[pfx+item]*Lnorm*Kcl*(dKsdp*dPSdA[i]+dKsdg*dGMdA[i]) return odfCor,dFdODF,dFdSA
[docs] def SHPOcal(refl,im,g,phfx,hfx,SGData,calcControls,parmDict): 'spherical harmonics preferred orientation (cylindrical symmetry only)' if 'T' in calcControls[hfx+'histType']: tth = parmDict[hfx+'2-theta'] else: tth = refl[5+im] odfCor = 1.0 H = refl[:3] cell = G2lat.Gmat2cell(g) Sangls = [0.,0.,0.] if 'Bragg' in calcControls[hfx+'instType']: Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']] IFCoup = True else: Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']] IFCoup = False phi,beta = G2lat.CrsAng(H,cell,SGData) psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs. SHnames = calcControls[phfx+'SHnames'] for item in SHnames: L,N = eval(item.strip('C')) Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta) Ksl,x,x = G2lat.GetKsl(L,0,'0',psi,gam) Lnorm = G2lat.Lnorm(L) odfCor += parmDict[phfx+item]*Lnorm*Kcl*Ksl return np.squeeze(odfCor)
[docs] def SHPOcalDerv(refl,im,g,phfx,hfx,SGData,calcControls,parmDict): 'spherical harmonics preferred orientation derivatives (cylindrical symmetry only)' if 'T' in calcControls[hfx+'histType']: tth = parmDict[hfx+'2-theta'] else: tth = refl[5+im] odfCor = 1.0 dFdODF = {} H = refl[:3] cell = G2lat.Gmat2cell(g) Sangls = [0.,0.,0.] if 'Bragg' in calcControls[hfx+'instType']: Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']] IFCoup = True else: Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']] IFCoup = False phi,beta = G2lat.CrsAng(H,cell,SGData) psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs. SHnames = calcControls[phfx+'SHnames'] for item in SHnames: L,N = eval(item.strip('C')) Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta) Ksl,x,x = G2lat.GetKsl(L,0,'0',psi,gam) Lnorm = G2lat.Lnorm(L) odfCor += parmDict[phfx+item]*Lnorm*Kcl*Ksl dFdODF[phfx+item] = Kcl*Ksl*Lnorm return odfCor,dFdODF
[docs] def GetPrefOri(uniq,G,g,phfx,hfx,SGData,calcControls,parmDict): 'March-Dollase preferred orientation correction' POcorr = 1.0 MD = parmDict[phfx+'MD'] if MD != 1.0: MDAxis = calcControls[phfx+'MDAxis'] sumMD = 0 for H in uniq: cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G) A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD) sumMD += A**3 POcorr = sumMD/len(uniq) return POcorr
[docs] def GetPrefOriDerv(refl,im,uniq,G,g,phfx,hfx,SGData,calcControls,parmDict): 'Needs a doc string' POcorr = 1.0 POderv = {} if calcControls[phfx+'poType'] == 'MD': MD = parmDict[phfx+'MD'] MDAxis = calcControls[phfx+'MDAxis'] sumMD = 0 sumdMD = 0 for H in uniq: cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G) A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD) sumMD += A**3 sumdMD -= (1.5*A**5)*(2.0*MD*cosP**2-(sinP/MD)**2) POcorr = sumMD/len(uniq) POderv[phfx+'MD'] = sumdMD/len(uniq) else: #spherical harmonics if calcControls[phfx+'SHord']: POcorr,POderv = SHPOcalDerv(refl,im,g,phfx,hfx,SGData,calcControls,parmDict) return POcorr,POderv
[docs] def GetAbsorb(refl,im,hfx,calcControls,parmDict): 'Needs a doc string' if 'Debye' in calcControls[hfx+'instType']: if 'T' in calcControls[hfx+'histType']: return G2pwd.Absorb('Cylinder',parmDict[hfx+'Absorption']*refl[14+im],abs(parmDict[hfx+'2-theta']),0,0) else: return G2pwd.Absorb('Cylinder',parmDict[hfx+'Absorption'],refl[5+im],0,0) else: return G2pwd.SurfaceRough(parmDict[hfx+'SurfRoughA'],parmDict[hfx+'SurfRoughB'],refl[5+im])
[docs] def GetAbsorbDerv(refl,im,hfx,calcControls,parmDict): 'Needs a doc string' if 'Debye' in calcControls[hfx+'instType']: if 'T' in calcControls[hfx+'histType']: return G2pwd.AbsorbDerv('Cylinder',parmDict[hfx+'Absorption']*refl[14+im],abs(parmDict[hfx+'2-theta']),0,0) else: return G2pwd.AbsorbDerv('Cylinder',parmDict[hfx+'Absorption'],refl[5+im],0,0) else: return np.array(G2pwd.SurfaceRoughDerv(parmDict[hfx+'SurfRoughA'],parmDict[hfx+'SurfRoughB'],refl[5+im]))
[docs] def GetPwdrExt(refl,im,pfx,phfx,hfx,calcControls,parmDict): 'Needs a doc string' coef = np.array([-0.5,0.25,-0.10416667,0.036458333,-0.0109375,2.8497409E-3]) pi2 = np.sqrt(2./np.pi) if 'T' in calcControls[hfx+'histType']: sth2 = sind(abs(parmDict[hfx+'2-theta'])/2.)**2 wave = refl[14+im] else: #'C'W sth2 = sind(refl[5+im]/2.)**2 wave = parmDict.get(hfx+'Lam',parmDict.get(hfx+'Lam1',1.0)) c2th = 1.-2.0*sth2 flv2 = refl[9+im]*(wave/parmDict[pfx+'Vol'])**2 if 'X' in calcControls[hfx+'histType']: flv2 *= 0.079411*(1.0+c2th**2)/2.0 xfac = flv2*parmDict[phfx+'Extinction'] exb = 1.0 if xfac > -1.: exb = 1./np.sqrt(1.+xfac) exl = 1.0 if 0 < xfac <= 1.: xn = np.array([xfac**(i+1) for i in range(6)]) exl += np.sum(xn*coef) elif xfac > 1.: xfac2 = 1./np.sqrt(xfac) exl = pi2*(1.-0.125/xfac)*xfac2 return exb*sth2+exl*(1.-sth2)
[docs] def GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict): 'Needs a doc string' coef = np.array([-0.5,0.25,-0.10416667,0.036458333,-0.0109375,2.8497409E-3]) pi2 = np.sqrt(2./np.pi) if 'T' in calcControls[hfx+'histType']: sth2 = sind(abs(parmDict[hfx+'2-theta'])/2.)**2 wave = refl[14+im] else: #'C'W sth2 = sind(refl[5+im]/2.)**2 wave = parmDict.get(hfx+'Lam',parmDict.get(hfx+'Lam1',1.0)) c2th = 1.-2.0*sth2 flv2 = refl[9+im]*(wave/parmDict[pfx+'Vol'])**2 if 'X' in calcControls[hfx+'histType']: flv2 *= 0.079411*(1.0+c2th**2)/2.0 xfac = flv2*parmDict[phfx+'Extinction'] dbde = -500.*flv2 if xfac > -1.: dbde = -0.5*flv2/np.sqrt(1.+xfac)**3 dlde = 0. if 0 < xfac <= 1.: xn = np.array([i*flv2*xfac**i for i in [1,2,3,4,5,6]]) dlde = np.sum(xn*coef)/xfac elif xfac > 1.: xfac2 = 1./np.sqrt(xfac) dlde = 0.5*flv2*pi2*xfac2*(-1./xfac+0.375/xfac**2) return dbde*sth2+dlde*(1.-sth2)
[docs] def GetIntensityCorr(refl,im,uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict): 'Needs a doc string' #need powder extinction! parmDict[phfx+'Scale'] = max(1.e-12,parmDict[phfx+'Scale']) #put floor on phase fraction scale parmDict[hfx+'Scale'] = max(1.e-12,parmDict[hfx+'Scale']) #put floor on histogram scale Icorr = parmDict[phfx+'Scale']*parmDict[hfx+'Scale']*refl[3+im] #scale*multiplicity if 'XC' in parmDict[hfx+'Type']: Icorr *= G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5+im],parmDict[hfx+'Azimuth'])[0] POcorr = 1.0 if pfx+'SHorder' in parmDict: #generalized spherical harmonics texture - takes precidence POcorr = SHTXcal(refl,im,g,pfx,hfx,SGData,calcControls,parmDict) elif calcControls[phfx+'poType'] == 'MD': #March-Dollase POcorr = GetPrefOri(uniq,G,g,phfx,hfx,SGData,calcControls,parmDict) elif calcControls[phfx+'SHord']: #cylindrical spherical harmonics POcorr = SHPOcal(refl,im,g,phfx,hfx,SGData,calcControls,parmDict) Icorr *= POcorr AbsCorr = 1.0 AbsCorr = GetAbsorb(refl,im,hfx,calcControls,parmDict) Icorr *= AbsCorr ExtCorr = GetPwdrExt(refl,im,pfx,phfx,hfx,calcControls,parmDict) Icorr *= ExtCorr return Icorr,POcorr,AbsCorr,ExtCorr
[docs] def GetIntensityDerv(refl,im,wave,uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict): 'Needs a doc string' #need powder extinction derivs! dIdsh = 1./parmDict[hfx+'Scale'] dIdsp = 1./parmDict[phfx+'Scale'] if 'XC' in parmDict[hfx+'Type']: pola,dIdPola = G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5+im],parmDict[hfx+'Azimuth']) dIdPola /= pola else: #'N' dIdPola = 0.0 dFdODF = {} dFdSA = [0,0,0] dIdPO = {} if pfx+'SHorder' in parmDict: odfCor,dFdODF,dFdSA = SHTXcalDerv(refl,im,g,pfx,hfx,SGData,calcControls,parmDict) for iSH in dFdODF: dFdODF[iSH] /= odfCor for i in range(3): dFdSA[i] /= odfCor elif calcControls[phfx+'poType'] == 'MD' or calcControls[phfx+'SHord']: POcorr,dIdPO = GetPrefOriDerv(refl,im,uniq,G,g,phfx,hfx,SGData,calcControls,parmDict) for iPO in dIdPO: dIdPO[iPO] /= POcorr if 'T' in parmDict[hfx+'Type']: dFdAb = GetAbsorbDerv(refl,im,hfx,calcControls,parmDict)*wave/refl[16+im] #wave/abs corr dFdEx = GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict)/refl[17+im] #/ext corr else: dFdAb = GetAbsorbDerv(refl,im,hfx,calcControls,parmDict)*wave/refl[13+im] #wave/abs corr dFdEx = GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict)/refl[14+im] #/ext corr return dIdsh,dIdsp,dIdPola,dIdPO,dFdODF,dFdSA,dFdAb,dFdEx
[docs] def GetSampleSigGam(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict): '''Computes the sample-dependent Lorentzian & Gaussian peak width contributions from size & microstrain parameters :param float wave: wavelength for CW data, 2-theta for EDX data ''' if 'C' in calcControls[hfx+'histType'] or 'B' in calcControls[hfx+'histType']: #All checked & OK costh = cosd(refl[5+im]/2.) #crystallite size if calcControls[phfx+'SizeType'] == 'isotropic': Sgam = 1.8*wave/(np.pi*parmDict[phfx+'Size;i']*costh) elif calcControls[phfx+'SizeType'] == 'uniaxial': H = np.array(refl[:3]) P = np.array(calcControls[phfx+'SizeAxis']) cosP,sinP = G2lat.CosSinAngle(H,P,G) Sgam = (1.8*wave/np.pi)/(parmDict[phfx+'Size;i']*parmDict[phfx+'Size;a']*costh) Sgam *= np.sqrt((sinP*parmDict[phfx+'Size;a'])**2+(cosP*parmDict[phfx+'Size;i'])**2) else: #ellipsoidal crystallites Sij =[parmDict[phfx+'Size;%d'%(i)] for i in range(6)] H = np.array(refl[:3]) lenR = G2pwd.ellipseSize(H,Sij,GB) Sgam = 1.8*wave/(np.pi*costh*lenR) #microstrain if calcControls[phfx+'MustrainType'] == 'isotropic': Mgam = 0.018*parmDict[phfx+'Mustrain;i']*tand(refl[5+im]/2.)/np.pi elif calcControls[phfx+'MustrainType'] == 'uniaxial': H = np.array(refl[:3]) P = np.array(calcControls[phfx+'MustrainAxis']) cosP,sinP = G2lat.CosSinAngle(H,P,G) Si = parmDict[phfx+'Mustrain;i'] Sa = parmDict[phfx+'Mustrain;a'] Mgam = 0.018*Si*Sa*tand(refl[5+im]/2.)/(np.pi*np.sqrt((Si*cosP)**2+(Sa*sinP)**2)) else: #generalized - P.W. Stephens model Strms = G2spc.MustrainCoeff(refl[:3],SGData) Sum = 0 for i,strm in enumerate(Strms): Sum += parmDict[phfx+'Mustrain;'+str(i)]*strm Mgam = 0.018*refl[4+im]**2*tand(refl[5+im]/2.)*np.sqrt(Sum)/np.pi elif 'E' in calcControls[hfx+'histType']: #crystallite size sinth = sind(wave/2.0) #"wave" = 2-theta for EDX if calcControls[phfx+'SizeType'] == 'isotropic': Sgam = 1.e-4*keV/(2.*parmDict[phfx+'Size;i']*sinth) elif calcControls[phfx+'SizeType'] == 'uniaxial': H = np.array(refl[:3]) P = np.array(calcControls[phfx+'SizeAxis']) cosP,sinP = G2lat.CosSinAngle(H,P,G) Sgam = 1.e-4*keV/(2.*parmDict[phfx+'Size;i']*parmDict[phfx+'Size;a']*sinth) Sgam *= np.sqrt((sinP*parmDict[phfx+'Size;a'])**2+(cosP*parmDict[phfx+'Size;i'])**2) else: #ellipsoidal crystallites Sij =[parmDict[phfx+'Size;%d'%(i)] for i in range(6)] H = np.array(refl[:3]) lenR = G2pwd.ellipseSize(H,Sij,GB) Sgam = 1.e-4*keV/(2.*sinth*lenR) #microstrain if calcControls[phfx+'MustrainType'] == 'isotropic': Mgam = 1.e-4*parmDict[phfx+'Mustrain;i'] elif calcControls[phfx+'MustrainType'] == 'uniaxial': H = np.array(refl[:3]) P = np.array(calcControls[phfx+'MustrainAxis']) cosP,sinP = G2lat.CosSinAngle(H,P,G) Si = parmDict[phfx+'Mustrain;i'] Sa = parmDict[phfx+'Mustrain;a'] Mgam = 1.e-4*Si*Sa/(np.sqrt((Si*cosP)**2+(Sa*sinP)**2)) else: #generalized - P.W. Stephens model Strms = G2spc.MustrainCoeff(refl[:3],SGData) Sum = 0 for i,strm in enumerate(Strms): Sum += parmDict[phfx+'Mustrain;'+str(i)]*strm Mgam = 1.e-4*refl[4+im]**2*np.sqrt(Sum) elif 'T' in calcControls[hfx+'histType']: #All checked & OK #crystallite size if calcControls[phfx+'SizeType'] == 'isotropic': #OK Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/parmDict[phfx+'Size;i'] elif calcControls[phfx+'SizeType'] == 'uniaxial': #OK H = np.array(refl[:3]) P = np.array(calcControls[phfx+'SizeAxis']) cosP,sinP = G2lat.CosSinAngle(H,P,G) Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/(parmDict[phfx+'Size;i']*parmDict[phfx+'Size;a']) Sgam *= np.sqrt((sinP*parmDict[phfx+'Size;a'])**2+(cosP*parmDict[phfx+'Size;i'])**2) else: #ellipsoidal crystallites #OK Sij =[parmDict[phfx+'Size;%d'%(i)] for i in range(6)] H = np.array(refl[:3]) lenR = G2pwd.ellipseSize(H,Sij,GB) Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/lenR #microstrain if calcControls[phfx+'MustrainType'] == 'isotropic': #OK Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*parmDict[phfx+'Mustrain;i'] elif calcControls[phfx+'MustrainType'] == 'uniaxial': #OK H = np.array(refl[:3]) P = np.array(calcControls[phfx+'MustrainAxis']) cosP,sinP = G2lat.CosSinAngle(H,P,G) Si = parmDict[phfx+'Mustrain;i'] Sa = parmDict[phfx+'Mustrain;a'] Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*Si*Sa/np.sqrt((Si*cosP)**2+(Sa*sinP)**2) else: #generalized - P.W. Stephens model OK Strms = G2spc.MustrainCoeff(refl[:3],SGData) Sum = 0 for i,strm in enumerate(Strms): Sum += parmDict[phfx+'Mustrain;'+str(i)]*strm Mgam = 1.e-6*parmDict[hfx+'difC']*np.sqrt(Sum)*refl[4+im]**3 gam = Sgam*parmDict[phfx+'Size;mx']+Mgam*parmDict[phfx+'Mustrain;mx'] sig = (Sgam*(1.-parmDict[phfx+'Size;mx']))**2+(Mgam*(1.-parmDict[phfx+'Mustrain;mx']))**2 sig /= ateln2 return sig,gam
[docs] def GetSampleSigGamDerv(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict): '''Computes the derivatives on sample-dependent Lorentzian & Gaussian peak widths contributions from size & microstrain parameters :param float wave: wavelength for CW data, 2-theta for EDX data ''' gamDict = {} sigDict = {} if 'C' in calcControls[hfx+'histType'] or 'B' in calcControls[hfx+'histType']: #All checked & OK costh = cosd(refl[5+im]/2.) tanth = tand(refl[5+im]/2.) #crystallite size derivatives if calcControls[phfx+'SizeType'] == 'isotropic': Sgam = 1.8*wave/(np.pi*costh*parmDict[phfx+'Size;i']) gamDict[phfx+'Size;i'] = -1.8*wave*parmDict[phfx+'Size;mx']/(np.pi*costh*parmDict[phfx+'Size;i']**2) sigDict[phfx+'Size;i'] = -3.6*Sgam*wave*(1.-parmDict[phfx+'Size;mx'])**2/(np.pi*costh*ateln2) elif calcControls[phfx+'SizeType'] == 'uniaxial': H = np.array(refl[:3]) P = np.array(calcControls[phfx+'SizeAxis']) cosP,sinP = G2lat.CosSinAngle(H,P,G) Si = parmDict[phfx+'Size;i'] Sa = parmDict[phfx+'Size;a'] gami = 1.8*wave/(costh*np.pi*Si*Sa) sqtrm = np.sqrt((sinP*Sa)**2+(cosP*Si)**2) Sgam = gami*sqtrm dsi = gami*Si*cosP**2/sqtrm-Sgam/Si dsa = gami*Sa*sinP**2/sqtrm-Sgam/Sa gamDict[phfx+'Size;i'] = dsi*parmDict[phfx+'Size;mx'] gamDict[phfx+'Size;a'] = dsa*parmDict[phfx+'Size;mx'] sigDict[phfx+'Size;i'] = 2.*dsi*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2 sigDict[phfx+'Size;a'] = 2.*dsa*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2 else: #ellipsoidal crystallites const = 1.8*wave/(np.pi*costh) Sij =[parmDict[phfx+'Size;%d'%(i)] for i in range(6)] H = np.array(refl[:3]) lenR,dRdS = G2pwd.ellipseSizeDerv(H,Sij,GB) Sgam = const/lenR for i,item in enumerate([phfx+'Size;%d'%(j) for j in range(6)]): gamDict[item] = -(const/lenR**2)*dRdS[i]*parmDict[phfx+'Size;mx'] sigDict[item] = -2.*Sgam*(const/lenR**2)*dRdS[i]*(1.-parmDict[phfx+'Size;mx'])**2/ateln2 gamDict[phfx+'Size;mx'] = Sgam sigDict[phfx+'Size;mx'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])/ateln2 #microstrain derivatives if calcControls[phfx+'MustrainType'] == 'isotropic': Mgam = 0.018*parmDict[phfx+'Mustrain;i']*tand(refl[5+im]/2.)/np.pi gamDict[phfx+'Mustrain;i'] = 0.018*tanth*parmDict[phfx+'Mustrain;mx']/np.pi sigDict[phfx+'Mustrain;i'] = 0.036*Mgam*tanth*(1.-parmDict[phfx+'Mustrain;mx'])**2/(np.pi*ateln2) elif calcControls[phfx+'MustrainType'] == 'uniaxial': H = np.array(refl[:3]) P = np.array(calcControls[phfx+'MustrainAxis']) cosP,sinP = G2lat.CosSinAngle(H,P,G) Si = parmDict[phfx+'Mustrain;i'] Sa = parmDict[phfx+'Mustrain;a'] gami = 0.018*Si*Sa*tanth/np.pi sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2) Mgam = gami/sqtrm dsi = -gami*Si*cosP**2/sqtrm**3 dsa = -gami*Sa*sinP**2/sqtrm**3 gamDict[phfx+'Mustrain;i'] = (Mgam/Si+dsi)*parmDict[phfx+'Mustrain;mx'] gamDict[phfx+'Mustrain;a'] = (Mgam/Sa+dsa)*parmDict[phfx+'Mustrain;mx'] sigDict[phfx+'Mustrain;i'] = 2*(Mgam/Si+dsi)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2 sigDict[phfx+'Mustrain;a'] = 2*(Mgam/Sa+dsa)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2 else: #generalized - P.W. Stephens model const = 0.018*refl[4+im]**2*tanth/np.pi Strms = G2spc.MustrainCoeff(refl[:3],SGData) Sum = 0 for i,strm in enumerate(Strms): Sum += parmDict[phfx+'Mustrain;'+str(i)]*strm gamDict[phfx+'Mustrain;'+str(i)] = strm*parmDict[phfx+'Mustrain;mx']/2. sigDict[phfx+'Mustrain;'+str(i)] = strm*(1.-parmDict[phfx+'Mustrain;mx'])**2 Mgam = const*np.sqrt(Sum) for i in range(len(Strms)): gamDict[phfx+'Mustrain;'+str(i)] *= Mgam/Sum sigDict[phfx+'Mustrain;'+str(i)] *= const**2/ateln2 gamDict[phfx+'Mustrain;mx'] = Mgam sigDict[phfx+'Mustrain;mx'] = -2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])/ateln2 elif 'E' in calcControls[hfx+'histType']: sinth = sind(wave/2.0) #"wave" = 2-theta for EDX #crystallite size derivatives if calcControls[phfx+'SizeType'] == 'isotropic': Sgam = 1.e-4*keV/(2.*parmDict[phfx+'Size;i']*sinth) gamDict[phfx+'Size;i'] = -1.e-4*keV*parmDict[phfx+'Size;mx']/(2.*sinth*parmDict[phfx+'Size;i']**2) sigDict[phfx+'Size;i'] = -2.0*Sgam*wave*(1.-parmDict[phfx+'Size;mx'])**2/(2.*sinth*ateln2) elif calcControls[phfx+'SizeType'] == 'uniaxial': H = np.array(refl[:3]) P = np.array(calcControls[phfx+'SizeAxis']) cosP,sinP = G2lat.CosSinAngle(H,P,G) Si = parmDict[phfx+'Size;i'] Sa = parmDict[phfx+'Size;a'] gami = 1.e-4*keV/(2.*sinth*Si*Sa) sqtrm = np.sqrt((sinP*Sa)**2+(cosP*Si)**2) Sgam = gami*sqtrm dsi = gami*Si*cosP**2/sqtrm-Sgam/Si dsa = gami*Sa*sinP**2/sqtrm-Sgam/Sa gamDict[phfx+'Size;i'] = dsi*parmDict[phfx+'Size;mx'] gamDict[phfx+'Size;a'] = dsa*parmDict[phfx+'Size;mx'] sigDict[phfx+'Size;i'] = 2.*dsi*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2 sigDict[phfx+'Size;a'] = 2.*dsa*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2 else: #ellipsoidal crystallites const = 1.e-4*keV/(2.*sinth) Sij =[parmDict[phfx+'Size;%d'%(i)] for i in range(6)] H = np.array(refl[:3]) lenR,dRdS = G2pwd.ellipseSizeDerv(H,Sij,GB) Sgam = const/lenR for i,item in enumerate([phfx+'Size;%d'%(j) for j in range(6)]): gamDict[item] = -(const/lenR**2)*dRdS[i]*parmDict[phfx+'Size;mx'] sigDict[item] = -2.*Sgam*(const/lenR**2)*dRdS[i]*(1.-parmDict[phfx+'Size;mx'])**2/ateln2 gamDict[phfx+'Size;mx'] = Sgam sigDict[phfx+'Size;mx'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])/ateln2 #microstrain derivatives if calcControls[phfx+'MustrainType'] == 'isotropic': Mgam = 1.e-4*parmDict[phfx+'Mustrain;i'] gamDict[phfx+'Mustrain;i'] = 1.e-4*parmDict[phfx+'Mustrain;mx'] sigDict[phfx+'Mustrain;i'] = 2.e-4*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/(ateln2) elif calcControls[phfx+'MustrainType'] == 'uniaxial': H = np.array(refl[:3]) P = np.array(calcControls[phfx+'MustrainAxis']) cosP,sinP = G2lat.CosSinAngle(H,P,G) Si = parmDict[phfx+'Mustrain;i'] Sa = parmDict[phfx+'Mustrain;a'] gami = 1.e-4*Si*Sa*tanth sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2) Mgam = gami/sqtrm dsi = -gami*Si*cosP**2/sqtrm**3 dsa = -gami*Sa*sinP**2/sqtrm**3 gamDict[phfx+'Mustrain;i'] = (Mgam/Si+dsi)*parmDict[phfx+'Mustrain;mx'] gamDict[phfx+'Mustrain;a'] = (Mgam/Sa+dsa)*parmDict[phfx+'Mustrain;mx'] sigDict[phfx+'Mustrain;i'] = 2*(Mgam/Si+dsi)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2 sigDict[phfx+'Mustrain;a'] = 2*(Mgam/Sa+dsa)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2 else: #generalized - P.W. Stephens model const = 1.e-4*refl[4+im]**2 Strms = G2spc.MustrainCoeff(refl[:3],SGData) Sum = 0 for i,strm in enumerate(Strms): Sum += parmDict[phfx+'Mustrain;'+str(i)]*strm gamDict[phfx+'Mustrain;'+str(i)] = strm*parmDict[phfx+'Mustrain;mx']/2. sigDict[phfx+'Mustrain;'+str(i)] = strm*(1.-parmDict[phfx+'Mustrain;mx'])**2 Mgam = const*np.sqrt(Sum) for i in range(len(Strms)): gamDict[phfx+'Mustrain;'+str(i)] *= Mgam/Sum sigDict[phfx+'Mustrain;'+str(i)] *= const**2/ateln2 gamDict[phfx+'Mustrain;mx'] = Mgam sigDict[phfx+'Mustrain;mx'] = -2.e-4*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])/ateln2 else: #'T'OF - All checked & OK if calcControls[phfx+'SizeType'] == 'isotropic': #OK Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/parmDict[phfx+'Size;i'] gamDict[phfx+'Size;i'] = -Sgam*parmDict[phfx+'Size;mx']/parmDict[phfx+'Size;i'] sigDict[phfx+'Size;i'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])**2/(ateln2*parmDict[phfx+'Size;i']) elif calcControls[phfx+'SizeType'] == 'uniaxial': #OK const = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2 H = np.array(refl[:3]) P = np.array(calcControls[phfx+'SizeAxis']) cosP,sinP = G2lat.CosSinAngle(H,P,G) Si = parmDict[phfx+'Size;i'] Sa = parmDict[phfx+'Size;a'] gami = const/(Si*Sa) sqtrm = np.sqrt((sinP*Sa)**2+(cosP*Si)**2) Sgam = gami*sqtrm dsi = gami*Si*cosP**2/sqtrm-Sgam/Si dsa = gami*Sa*sinP**2/sqtrm-Sgam/Sa gamDict[phfx+'Size;i'] = dsi*parmDict[phfx+'Size;mx'] gamDict[phfx+'Size;a'] = dsa*parmDict[phfx+'Size;mx'] sigDict[phfx+'Size;i'] = 2.*dsi*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2 sigDict[phfx+'Size;a'] = 2.*dsa*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2 else: #OK ellipsoidal crystallites const = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2 Sij =[parmDict[phfx+'Size;%d'%(i)] for i in range(6)] H = np.array(refl[:3]) lenR,dRdS = G2pwd.ellipseSizeDerv(H,Sij,GB) Sgam = const/lenR for i,item in enumerate([phfx+'Size;%d'%(j) for j in range(6)]): gamDict[item] = -(const/lenR**2)*dRdS[i]*parmDict[phfx+'Size;mx'] sigDict[item] = -2.*Sgam*(const/lenR**2)*dRdS[i]*(1.-parmDict[phfx+'Size;mx'])**2/ateln2 gamDict[phfx+'Size;mx'] = Sgam #OK sigDict[phfx+'Size;mx'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])/ateln2 #OK #microstrain derivatives if calcControls[phfx+'MustrainType'] == 'isotropic': Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*parmDict[phfx+'Mustrain;i'] gamDict[phfx+'Mustrain;i'] = 1.e-6*refl[4+im]*parmDict[hfx+'difC']*parmDict[phfx+'Mustrain;mx'] #OK sigDict[phfx+'Mustrain;i'] = 2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])**2/(ateln2*parmDict[phfx+'Mustrain;i']) elif calcControls[phfx+'MustrainType'] == 'uniaxial': H = np.array(refl[:3]) P = np.array(calcControls[phfx+'MustrainAxis']) cosP,sinP = G2lat.CosSinAngle(H,P,G) Si = parmDict[phfx+'Mustrain;i'] Sa = parmDict[phfx+'Mustrain;a'] gami = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*Si*Sa sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2) Mgam = gami/sqtrm dsi = -gami*Si*cosP**2/sqtrm**3 dsa = -gami*Sa*sinP**2/sqtrm**3 gamDict[phfx+'Mustrain;i'] = (Mgam/Si+dsi)*parmDict[phfx+'Mustrain;mx'] gamDict[phfx+'Mustrain;a'] = (Mgam/Sa+dsa)*parmDict[phfx+'Mustrain;mx'] sigDict[phfx+'Mustrain;i'] = 2*(Mgam/Si+dsi)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2 sigDict[phfx+'Mustrain;a'] = 2*(Mgam/Sa+dsa)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2 else: #generalized - P.W. Stephens model OK Strms = G2spc.MustrainCoeff(refl[:3],SGData) const = 1.e-6*parmDict[hfx+'difC']*refl[4+im]**3 Sum = 0 for i,strm in enumerate(Strms): Sum += parmDict[phfx+'Mustrain;'+str(i)]*strm gamDict[phfx+'Mustrain;'+str(i)] = strm*parmDict[phfx+'Mustrain;mx']/2. sigDict[phfx+'Mustrain;'+str(i)] = strm*(1.-parmDict[phfx+'Mustrain;mx'])**2 Mgam = const*np.sqrt(Sum) for i in range(len(Strms)): gamDict[phfx+'Mustrain;'+str(i)] *= Mgam/Sum sigDict[phfx+'Mustrain;'+str(i)] *= const**2/ateln2 gamDict[phfx+'Mustrain;mx'] = Mgam sigDict[phfx+'Mustrain;mx'] = -2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])/ateln2 return sigDict,gamDict
[docs] def GetReflPos(refl,im,wave,A,pfx,hfx,phfx,calcControls,parmDict): 'Needs a doc string' if im: h,k,l,m = refl[:4] vec = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']]) d = 1./np.sqrt(G2lat.calc_rDsqSS(np.array([h,k,l,m]),A,vec)) else: h,k,l = refl[:3] d = 1./np.sqrt(G2lat.calc_rDsq(np.array([h,k,l]),A)) refl[4+im] = d if 'C' in calcControls[hfx+'histType'] or 'B' in calcControls[hfx+'histType']: pos = 2.0*asind(wave/(2.0*d))+parmDict[hfx+'Zero'] const = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius']) #shifts in microns if 'Bragg' in calcControls[hfx+'instType']: pos -= const*(4.*parmDict[hfx+'Shift']*cosd(pos/2.0)+ \ parmDict[hfx+'Transparency']*sind(pos)*100.0) #trans(=1/mueff) in cm else: #Debye-Scherrer - simple but maybe not right pos -= const*(parmDict[hfx+'DisplaceX']*cosd(pos)+(parmDict[hfx+'DisplaceY']+parmDict[phfx+'LayerDisp'])*sind(pos)) elif 'E' in calcControls[hfx+'histType']: pos = 12.397639/(2.0*d*sind(parmDict[hfx+'2-theta']/2.0))+parmDict[hfx+'ZE']+parmDict[hfx+'YE']*d+parmDict[hfx+'XE']*d**2 elif 'T' in calcControls[hfx+'histType']: pos = parmDict[hfx+'difC']*d+parmDict[hfx+'difA']*d**2+parmDict[hfx+'difB']/d+parmDict[hfx+'Zero'] #do I need sample position effects - maybe? return pos
[docs] def GetReflPosDerv(refl,im,wave,A,pfx,hfx,phfx,calcControls,parmDict): 'Needs a doc string' dpr = 180./np.pi if im: h,k,l,m = refl[:4] vec = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']]) dstsq = G2lat.calc_rDsqSS(np.array([h,k,l,m]),A,vec) h,k,l = [h+m*vec[0],k+m*vec[1],l+m*vec[2]] #do proj of hklm to hkl so dPdA & dPdV come out right else: m = 0 h,k,l = refl[:3] dstsq = G2lat.calc_rDsq(np.array([h,k,l]),A) dst = np.sqrt(dstsq) dsp = 1./dst if 'C' in calcControls[hfx+'histType'] or 'B' in calcControls[hfx+'histType']: pos = refl[5+im]-parmDict[hfx+'Zero'] const = dpr/np.sqrt(1.0-wave**2*dstsq/4.0) dpdw = const*dst dpdA = np.array([h**2,k**2,l**2,h*k,h*l,k*l])*const*wave/(2.0*dst) dpdZ = 1.0 dpdV = np.array([2.*h*A[0]+k*A[3]+l*A[4],2*k*A[1]+h*A[3]+l*A[5], 2*l*A[2]+h*A[4]+k*A[5]])*m*const*wave/(2.0*dst) shft = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius']) #shifts in microns if 'Bragg' in calcControls[hfx+'instType']: dpdSh = -4.*shft*cosd(pos/2.0) dpdTr = -shft*sind(pos)*100.0 return dpdA,dpdw,dpdZ,dpdSh,dpdTr,0.,0.,dpdV else: #Debye-Scherrer - simple but maybe not right dpdXd = -shft*cosd(pos) dpdYd = -shft*sind(pos) return dpdA,dpdw,dpdZ,0.,0.,dpdXd,dpdYd,dpdV elif 'E' in calcControls[hfx+'histType']: tth = parmDict[hfx+'2-theta']/2.0 dpdZE = 1.0 dpdYE = dsp dpdXE = dsp**2 dpdA = np.array([h**2,k**2,l**2,h*k,h*l,k*l])*refl[5+im]*dsp**2/2. dpdTTh = -12.397639*cosd(tth)/(dsp*sind(tth)**2) return dpdA,dpdTTh,dpdXE,dpdYE,dpdZE elif 'T' in calcControls[hfx+'histType']: dpdA = -np.array([h**2,k**2,l**2,h*k,h*l,k*l])*parmDict[hfx+'difC']*dsp**3/2. dpdZ = 1.0 dpdDC = dsp dpdDA = dsp**2 dpdDB = 1./dsp dpdV = np.array([2.*h*A[0]+k*A[3]+l*A[4],2*k*A[1]+h*A[3]+l*A[5], 2*l*A[2]+h*A[4]+k*A[5]])*m*parmDict[hfx+'difC']*dsp**3/2. return dpdA,dpdZ,dpdDC,dpdDA,dpdDB,dpdV
[docs] def GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict): '''Computes the shifts in peak position due to the Hydrostatic strain (HStrain, Dij terms). This routine is not used anywhere ''' laue = SGData['SGLaue'] uniq = SGData['SGUniq'] h,k,l = refl[:3] if laue in ['m3','m3m']: hkl1 = (h**2+k**2+l**2) hkl2 = ((h*k)**2+(h*l)**2+(k*l)**2)/hkl1**2 Dij = parmDict[phfx+'D11']*hkl1+parmDict[phfx+'eA']*hkl2 elif laue in ['6/m','6/mmm','3m1','31m','3']: Dij = parmDict[phfx+'D11']*(h**2+k**2+h*k)+parmDict[phfx+'D33']*l**2 elif laue in ['3R','3mR']: Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)+parmDict[phfx+'D12']*(h*k+h*l+k*l) elif laue in ['4/m','4/mmm']: Dij = parmDict[phfx+'D11']*(h**2+k**2)+parmDict[phfx+'D33']*l**2 elif laue in ['mmm']: Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2 elif laue in ['2/m']: Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2 if uniq == 'a': Dij += parmDict[phfx+'D23']*k*l elif uniq == 'b': Dij += parmDict[phfx+'D13']*h*l elif uniq == 'c': Dij += parmDict[phfx+'D12']*h*k else: Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2+ \ parmDict[phfx+'D12']*h*k+parmDict[phfx+'D13']*h*l+parmDict[phfx+'D23']*k*l if 'C' in calcControls[hfx+'histType'] or 'B' in calcControls[hfx+'histType']: return -180.*Dij*refl[4+im]**2*tand(refl[5+im]/2.0)/np.pi elif 'E' in calcControls[hfx+'histType']: return Dij*refl[5+im]/refl[4+im]**2 else: return -Dij*parmDict[hfx+'difC']*0.5*refl[4+im]**2
[docs] def GetHStrainShiftDerv(refl,im,SGData,phfx,hfx,calcControls,parmDict): '''Computes the derivatives due to the shifts in peak position from Hydrostatic strain (HStrain, Dij terms). ''' laue = SGData['SGLaue'] uniq = SGData['SGUniq'] h,k,l = refl[:3] if laue in ['m3','m3m']: dDijDict = {phfx+'D11':h**2+k**2+l**2, phfx+'eA':((h*k)**2+(h*l)**2+(k*l)**2)/(h**2+k**2+l**2)**2} elif laue in ['6/m','6/mmm','3m1','31m','3']: dDijDict = {phfx+'D11':h**2+k**2+h*k,phfx+'D33':l**2} elif laue in ['3R','3mR']: dDijDict = {phfx+'D11':h**2+k**2+l**2,phfx+'D12':h*k+h*l+k*l} elif laue in ['4/m','4/mmm']: dDijDict = {phfx+'D11':h**2+k**2,phfx+'D33':l**2} elif laue in ['mmm']: dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2} elif laue in ['2/m']: dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2} if uniq == 'a': dDijDict[phfx+'D23'] = k*l elif uniq == 'b': dDijDict[phfx+'D13'] = h*l elif uniq == 'c': dDijDict[phfx+'D12'] = h*k else: dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2, phfx+'D12':h*k,phfx+'D13':h*l,phfx+'D23':k*l} if 'C' in calcControls[hfx+'histType'] or 'B' in calcControls[hfx+'histType']: for item in dDijDict: dDijDict[item] *= 180.0*refl[4+im]**2*tand(refl[5+im]/2.0)/np.pi elif 'E' in calcControls[hfx+'histType']: for item in dDijDict: dDijDict[item] *= refl[5+im]/refl[4+im]**2 else: for item in dDijDict: dDijDict[item] *= -parmDict[hfx+'difC']*refl[4+im]**3/2. return dDijDict
def GetDij(phfx,SGData,parmDict): HSvals = [parmDict[phfx+name] for name in G2spc.HStrainNames(SGData)] return G2spc.HStrainVals(HSvals,SGData)
[docs] def GetFobsSq(Histograms,Phases,parmDict,calcControls): '''Compute the observed structure factors for Powder histograms and store in reflection array Multiprocessing support added ''' if GSASIIpath.GetConfigValue('Show_timing',False): starttime = time.time() #; print 'start GetFobsSq' histoList = list(Histograms.keys()) histoList.sort() Ka2 = shl = lamRatio = kRatio = None for histogram in histoList: if 'PWDR' in histogram[:4]: Histogram = Histograms[histogram] hId = Histogram['hId'] hfx = ':%d:'%(hId) Limits = calcControls[hfx+'Limits'] if 'C' in calcControls[hfx+'histType']: shl = max(parmDict[hfx+'SH/L'],0.0005) Ka2 = False kRatio = 0.0 if hfx+'Lam1' in list(parmDict.keys()): Ka2 = True lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1']) kRatio = parmDict[hfx+'I(L2)/I(L1)'] x,y,w,yc,yb,yd = Histogram['Data'] xMask = ma.getmaskarray(x) xB = np.searchsorted(x,Limits[0]) xF = np.searchsorted(x,Limits[1]) ymb = np.array(y-yb) ymb = np.where(ymb,ymb,1.0) ycmb = np.array(yc-yb) ratio = 1./np.where(ycmb,ycmb/ymb,1.e10) refLists = Histogram['Reflection Lists'] for phase in refLists: if phase not in Phases: #skips deleted or renamed phases silently! continue Phase = Phases[phase] if histogram not in Phase['Histograms']: continue im = 0 if Phase['General'].get('Modulated',False): im = 1 pId = Phase['pId'] phfx = '%d:%d:'%(pId,hId) refDict = refLists[phase] sumFo = 0.0 sumdF = 0.0 sumFosq = 0.0 sumdFsq = 0.0 sumInt = 0.0 nExcl = 0 # test to see if we are using multiprocessing below useMP,ncores = G2mp.InitMP() if len(refDict['RefList']) < 100: useMP = False if useMP: # multiprocessing: create a set of initialized Python processes MPpool = mp.Pool(G2mp.ncores,G2mp.InitFobsSqGlobals, [x,ratio,shl,xB,xF,im,lamRatio,kRatio,xMask,Ka2]) profArgs = [[] for i in range(G2mp.ncores)] else: G2mp.InitFobsSqGlobals(x,ratio,shl,xB,xF,im,lamRatio,kRatio,xMask,Ka2) if 'C' in calcControls[hfx+'histType']: # are we multiprocessing? for iref,refl in enumerate(refDict['RefList']): if useMP: profArgs[iref%G2mp.ncores].append((refl,iref)) else: icod = G2mp.ComputeFobsSqCW(refl,iref) if type(icod) is tuple: refl[8+im] = icod[0] sumInt += icod[1] if parmDict.get(phfx+'LeBail'): refl[9+im] = refl[8+im] elif icod == -1: refl[3+im] *= -1 nExcl += 1 elif icod == -2: break if useMP: for sInt,resList in MPpool.imap_unordered(G2mp.ComputeFobsSqCWbatch,profArgs): sumInt += sInt for refl8im,irefl in resList: if refl8im is None: refDict['RefList'][irefl][3+im] *= -1 nExcl += 1 else: refDict['RefList'][irefl][8+im] = refl8im if parmDict.get(phfx+'LeBail'): refDict['RefList'][irefl][9+im] = refDict['RefList'][irefl][8+im] elif 'T' in calcControls[hfx+'histType']: for iref,refl in enumerate(refDict['RefList']): if useMP: profArgs[iref%G2mp.ncores].append((refl,iref)) else: icod = G2mp.ComputeFobsSqTOF(refl,iref) if type(icod) is tuple: refl[8+im] = icod[0] sumInt += icod[1] if parmDict.get(phfx+'LeBail'): refl[9+im] = refl[8+im] elif icod == -1: refl[3+im] *= -1 nExcl += 1 elif icod == -2: break if useMP: for sInt,resList in MPpool.imap_unordered(G2mp.ComputeFobsSqTOFbatch,profArgs): sumInt += sInt for refl8im,irefl in resList: if refl8im is None: refDict['RefList'][irefl][3+im] *= -1 nExcl += 1 else: refDict['RefList'][irefl][8+im] = refl8im if parmDict.get(phfx+'LeBail'): refDict['RefList'][irefl][9+im] = refDict['RefList'][irefl][8+im] elif 'E' in calcControls[hfx+'histType']: for iref,refl in enumerate(refDict['RefList']): if useMP: profArgs[iref%G2mp.ncores].append((refl,iref)) else: icod = G2mp.ComputeFobsSqED(refl,iref) if type(icod) is tuple: refl[8+im] = icod[0] sumInt += icod[1] if parmDict.get(phfx+'LeBail'): refl[9+im] = refl[8+im] elif icod == -1: refl[3+im] *= -1 nExcl += 1 elif icod == -2: break if useMP: for sInt,resList in MPpool.imap_unordered(G2mp.ComputeFobsSqEDbatch,profArgs): sumInt += sInt for refl8im,irefl in resList: if refl8im is None: refDict['RefList'][irefl][3+im] *= -1 nExcl += 1 else: refDict['RefList'][irefl][8+im] = refl8im if parmDict.get(phfx+'LeBail'): refDict['RefList'][irefl][9+im] = refDict['RefList'][irefl][8+im] elif 'B' in calcControls[hfx+'histType']: for iref,refl in enumerate(refDict['RefList']): if useMP: profArgs[iref%G2mp.ncores].append((refl,iref)) else: icod = G2mp.ComputeFobsSqPink(refl,iref) if type(icod) is tuple: refl[8+im] = icod[0] sumInt += icod[1] if parmDict.get(phfx+'LeBail'): refl[9+im] = refl[8+im] elif icod == -1: refl[3+im] *= -1 nExcl += 1 elif icod == -2: break if useMP: for sInt,resList in MPpool.imap_unordered(G2mp.ComputeFobsSqPinkbatch,profArgs): sumInt += sInt for refl8im,irefl in resList: if refl8im is None: refDict['RefList'][irefl][3+im] *= -1 nExcl += 1 else: refDict['RefList'][irefl][8+im] = refl8im if parmDict.get(phfx+'LeBail'): refDict['RefList'][irefl][9+im] = refDict['RefList'][irefl][8+im] if useMP: MPpool.terminate() sumFo = 0.0 sumdF = 0.0 sumFosq = 0.0 sumdFsq = 0.0 for iref,refl in enumerate(refDict['RefList']): Fo = np.sqrt(np.abs(refl[8+im])) Fc = np.sqrt(np.abs(refl[9+im])) sumFo += Fo sumFosq += refl[8+im]**2 sumdF += np.abs(Fo-Fc) sumdFsq += (refl[8+im]-refl[9+im])**2 if sumFo: Histogram['Residuals'][phfx+'Rf'] = min(100.,(sumdF/sumFo)*100.) Histogram['Residuals'][phfx+'Rf^2'] = min(100.,np.sqrt(sumdFsq/sumFosq)*100.) else: Histogram['Residuals'][phfx+'Rf'] = 100. Histogram['Residuals'][phfx+'Rf^2'] = 100. Histogram['Residuals'][phfx+'sumInt'] = sumInt Histogram['Residuals'][phfx+'Nref'] = len(refDict['RefList'])-nExcl Histogram['Residuals']['hId'] = hId elif 'HKLF' in histogram[:4]: Histogram = Histograms[histogram] Histogram['Residuals']['hId'] = Histograms[histogram]['hId'] if GSASIIpath.GetConfigValue('Show_timing',False): print ('GetFobsSq t=',time.time()-starttime)
[docs] def getPowderProfile(parmDict,x,varylist,Histogram,Phases,calcControls,pawleyLookup,histogram=None): 'Computes the powder pattern for a histogram based on contributions from all used phases' if GSASIIpath.GetConfigValue('Show_timing',False): starttime = time.time() def GetReflSigGamCW(refl,im,wave,G,GB,phfx,calcControls,parmDict): U = parmDict[hfx+'U'] V = parmDict[hfx+'V'] W = parmDict[hfx+'W'] X = parmDict[hfx+'X'] Y = parmDict[hfx+'Y'] Z = parmDict[hfx+'Z'] tanPos = tand(refl[5+im]/2.0) Ssig,Sgam = GetSampleSigGam(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict) sig = U*tanPos**2+V*tanPos+W+Ssig #save peak sigma sig = max(0.001,sig) gam = X/cosd(refl[5+im]/2.0)+Y*tanPos+Sgam+Z #save peak gamma gam = max(0.001,gam) return sig,gam def GetReflSigGamTOF(refl,im,G,GB,phfx,calcControls,parmDict): sig = parmDict[hfx+'sig-0']+parmDict[hfx+'sig-1']*refl[4+im]**2+ \ parmDict[hfx+'sig-2']*refl[4+im]**4+parmDict[hfx+'sig-q']*refl[4+im] gam = parmDict[hfx+'X']*refl[4+im]+parmDict[hfx+'Y']*refl[4+im]**2+parmDict[hfx+'Z'] Ssig,Sgam = GetSampleSigGam(refl,im,0.0,G,GB,SGData,hfx,phfx,calcControls,parmDict) sig += Ssig gam += Sgam return sig,gam def GetReflSigGamED(refl,im,G,GB,phfx,calcControls,parmDict): sig = parmDict[hfx+'A']*refl[5+im]**2+parmDict[hfx+'B']*refl[5+im]+parmDict[hfx+'C'] gam = parmDict[hfx+'X']*refl[5+im]**2+parmDict[hfx+'Y']*refl[5+im]+parmDict[hfx+'Z'] Ssig,Sgam = GetSampleSigGam(refl,im,parmDict[hfx+'2-theta'],G,GB,SGData,hfx,phfx,calcControls,parmDict) sig += Ssig gam += Sgam return sig,gam def GetReflAlpBet(refl,im,hfx,parmDict): alp = parmDict[hfx+'alpha']/refl[4+im] bet = parmDict[hfx+'beta-0']+parmDict[hfx+'beta-1']/refl[4+im]**4+parmDict[hfx+'beta-q']/refl[4+im]**2 return alp,bet def GetPinkReflAlpBet(refl,im,hfx,parmDict): sinPos = sind(refl[5+im]/2.0) alp = max(0.1,parmDict[hfx+'alpha-0']+parmDict[hfx+'alpha-1']*sinPos) bet = max(0.001,parmDict[hfx+'beta-0']+parmDict[hfx+'beta-1']*sinPos) return alp,bet def SavePartial(phase,y): phPartialFP = open(phasePartials,'ab') # append to file pickle.dump(phase,phPartialFP) pickle.dump(y,phPartialFP) phPartialFP.close() hId = Histogram['hId'] hfx = ':%d:'%(hId) bakType = calcControls[hfx+'bakType'] fixback = Histogram['Background'][1].get('fixback',None) yb,Histogram['sumBk'] = G2pwd.getBackground(hfx,parmDict,bakType,calcControls[hfx+'histType'],x,fixback) yc = np.zeros_like(yb) cw = np.diff(ma.getdata(x)) cw = np.append(cw,cw[-1]) # set up for save of phase partials if triggered in GSASIIdataGUI.OnRefinePartials phasePartials = calcControls.get('PhasePartials',None) Nphase = len(Histogram['Reflection Lists']) #partials made ony if Nphase > 1 if phasePartials: phPartialFP = open(phasePartials,'ab') # create histogram header pickle.dump(None,phPartialFP) pickle.dump(hId,phPartialFP) if Nphase > 1: pickle.dump(x,phPartialFP) pickle.dump(yb,phPartialFP) else: pickle.dump(None,phPartialFP) pickle.dump(None,phPartialFP) phPartialFP.close() if 'C' in calcControls[hfx+'histType']: shl = max(parmDict[hfx+'SH/L'],0.002) Ka2 = False if hfx+'Lam1' in (parmDict.keys()): wave = parmDict[hfx+'Lam1'] Ka2 = True lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1']) kRatio = parmDict[hfx+'I(L2)/I(L1)'] else: wave = parmDict[hfx+'Lam'] elif 'B' in calcControls[hfx+'histType']: wave = parmDict[hfx+'Lam'] else: shl = 0. for phase in Histogram['Reflection Lists']: refDict = Histogram['Reflection Lists'][phase] if phase not in Phases: #skips deleted or renamed phases silently! continue Phase = Phases[phase] if histogram and not histogram in Phase['Histograms']: continue pId = Phase['pId'] pfx = '%d::'%(pId) phfx = '%d:%d:'%(pId,hId) hfx = ':%d:'%(hId) SGData = Phase['General']['SGData'] SGMT = np.array([ops[0].T for ops in SGData['SGOps']]) im = 0 if Phase['General'].get('Modulated',False): SSGData = Phase['General']['SSGData'] im = 1 #offset in SS reflection list Dij = GetDij(phfx,SGData,parmDict) A = [parmDict[pfx+'A%d'%(i)]+Dij[i] for i in range(6)] #TODO: need to do something if Dij << 0. G,g = G2lat.A2Gmat(A) #recip & real metric tensors if np.any(np.diag(G)<0.): msg = 'Invalid metric tensor for phase #{}\n ({})'.format( pId,Phase['General']['Name']) elif np.any(np.isnan(A)): msg = 'Infinite metric tensor for phase #{}\n ({})'.format( pId,Phase['General']['Name']) else: msg = None if msg: print('\nInvalid cell metric tensor for phase #{} ({})\n'.format( pId,Phase['General']['Name']),'values (A): {:.3f} {:.3f} {:.3f} {:.3f} {:.3f} {:.3f}\n'.format(*A)) raise G2obj.G2Exception('Error: '+msg+' See console.\nCheck for refinement of conflicting variables') GA,GB = G2lat.Gmat2AB(G) #Orthogonalization matrices Vst = np.sqrt(nl.det(G)) #V* if not Phase['General'].get('doPawley') and not parmDict.get(phfx+'LeBail'): if 'E' in calcControls[hfx+'histType']: print('\n\n**** Error: EDX data not suitable for Rietveld refinement ****\n\n') else: if im: SStructureFactor(refDict,G,hfx,pfx,SGData,SSGData,calcControls,parmDict) elif parmDict[pfx+'isMag'] and 'N' in calcControls[hfx+'histType']: MagStructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict) else: StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict) badPeak = False # test to see if we are using multiprocessing here useMP,ncores = G2mp.InitMP() if len(refDict['RefList']) < 100: useMP = False if phasePartials: useMP = False ypartial = np.zeros_like(yb) if useMP: # multiprocessing: create a set of initialized Python processes MPpool = mp.Pool(ncores,G2mp.InitPwdrProfGlobals,[im,shl,x]) profArgs = [[] for i in range(ncores)] if 'C' in calcControls[hfx+'histType']: for iref,refl in enumerate(refDict['RefList']): if im: h,k,l,m = refl[:4] else: h,k,l = refl[:3] Uniq = np.inner(refl[:3],SGMT) refl[5+im] = GetReflPos(refl,im,wave,A,pfx,hfx,phfx,calcControls,parmDict) #corrected reflection position # refl[5+im] += GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict) #apply hydrostatic strain shift Lorenz = 1./(2.*sind(refl[5+im]/2.)**2*cosd(refl[5+im]/2.)) #Lorentz correction refl[6+im:8+im] = GetReflSigGamCW(refl,im,wave,G,GB,phfx,calcControls,parmDict) #peak sig & gam refl[11+im:15+im] = GetIntensityCorr(refl,im,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict) refl[11+im] *= Vst*Lorenz if Phase['General'].get('doPawley'): try: if im: pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)]) else: pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)]) refl[9+im] = parmDict[pInd] except KeyError: # print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l) continue Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl) iBeg = np.searchsorted(x,refl[5+im]-fmin) iFin = np.searchsorted(x,refl[5+im]+fmax) if not iBeg+iFin: #peak below low limit - skip peak continue elif not iBeg-iFin: #peak above high limit - done break elif iBeg > iFin: #bad peak coeff - skip badPeak = True continue if useMP: profArgs[iref%ncores].append((refl[5+im],refl,iBeg,iFin,1.)) else: fp = G2pwd.getFCJVoigt3(refl[5+im],refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg:iFin]))[0] yc[iBeg:iFin] += refl[11+im]*refl[9+im]*fp #>90% of time spent here if phasePartials: ypartial[iBeg:iFin] += refl[11+im]*refl[9+im]*fp if Ka2: pos2 = refl[5+im]+lamRatio*tand(refl[5+im]/2.0) # + 360/pi * Dlam/lam * tan(th) Wd,fmin,fmax = G2pwd.getWidthsCW(pos2,refl[6+im],refl[7+im],shl) iBeg = np.searchsorted(x,pos2-fmin) iFin = np.searchsorted(x,pos2+fmax) if not iBeg+iFin: #peak below low limit - skip peak continue elif not iBeg-iFin: #peak above high limit - done return yc,yb elif iBeg > iFin: #bad peak coeff - skip continue if useMP: profArgs[iref%ncores].append((pos2,refl,iBeg,iFin,kRatio)) else: fp2 = G2pwd.getFCJVoigt3(pos2,refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg:iFin]))[0] yc[iBeg:iFin] += refl[11+im]*refl[9+im]*kRatio*fp2 #and here if phasePartials: ypartial[iBeg:iFin] += refl[11+im]*refl[9+im]*kRatio*fp2 elif 'E' in calcControls[hfx+'histType']: for iref,refl in enumerate(refDict['RefList']): if im: h,k,l,m = refl[:4] else: h,k,l = refl[:3] Uniq = np.inner(refl[:3],SGMT) refl[5+im] = GetReflPos(refl,im,0.0,A,pfx,hfx,phfx,calcControls,parmDict) #corrected reflection position # refl[5+im] += GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict) #apply hydrostatic strain shift refl[6+im:8+im] = GetReflSigGamED(refl,im,G,GB,phfx,calcControls,parmDict) #peak sig & gam refl[11+im] = 1.0 #no intensity corrections; default = 1.0 if Phase['General'].get('doPawley'): try: if im: pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)]) else: pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)]) refl[9+im] = parmDict[pInd] except KeyError: continue Wd,fmin,fmax = G2pwd.getWidthsED(refl[5+im],refl[6+im],refl[7+im]) iBeg = np.searchsorted(x,refl[5+im]-fmin) iFin = np.searchsorted(x,refl[5+im]+fmax) if not iBeg+iFin: #peak below low limit - skip peak continue elif not iBeg-iFin: #peak above high limit - done break elif iBeg > iFin: #bad peak coeff - skip badPeak = True continue if useMP: profArgs[iref%ncores].append((refl[5+im],refl,iBeg,iFin,1.)) else: fp = G2pwd.getPsVoigt(refl[5+im],refl[6+im]*1.e4,refl[7+im]*100.,ma.getdata(x[iBeg:iFin]))[0] yc[iBeg:iFin] += refl[9+im]*fp if phasePartials: ypartial[iBeg:iFin] += refl[11+im]*refl[9+im]*fp elif 'B' in calcControls[hfx+'histType']: for iref,refl in enumerate(refDict['RefList']): if im: h,k,l,m = refl[:4] else: h,k,l = refl[:3] Uniq = np.inner(refl[:3],SGMT) refl[5+im] = GetReflPos(refl,im,wave,A,pfx,hfx,phfx,calcControls,parmDict) #corrected reflection position # refl[5+im] += GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict) #apply hydrostatic strain shift Lorenz = 1./(2.*sind(refl[5+im]/2.)**2*cosd(refl[5+im]/2.)) #Lorentz correction refl[6+im:8+im] = GetReflSigGamCW(refl,im,wave,G,GB,phfx,calcControls,parmDict) #peak sig & gam refl[12+im:14+im] = GetPinkReflAlpBet(refl,im,hfx,parmDict) refl[11+im],refl[14+im],refl[15+im],refl[16+im] = GetIntensityCorr(refl,im,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict) refl[11+im] *= Vst*Lorenz if Phase['General'].get('doPawley'): try: if im: pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)]) else: pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)]) refl[9+im] = parmDict[pInd] except KeyError: continue Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im]/1.e4,refl[7+im]/100.) iBeg = np.searchsorted(x,refl[5+im]-fmin) iFin = np.searchsorted(x,refl[5+im]+fmax) if not iBeg+iFin: #peak below low limit - skip peak continue elif not iBeg-iFin: #peak above high limit - done break elif iBeg > iFin: #bad peak coeff - skip badPeak = True continue if useMP: profArgs[iref%ncores].append((refl[5+im],refl,iBeg,iFin,1.)) else: fp = G2pwd.getEpsVoigt(refl[5+im],refl[12+im],refl[13+im],refl[6+im]/1.e4,refl[7+im]/100.,ma.getdata(x[iBeg:iFin]))[0] # if 'NB' in calcControls[hfx+'histType']: # yc[iBeg:iFin] += refl[11+im]*refl[9+im]*fp*.001/cw[iBeg:iFin] # else: # yc[iBeg:iFin] += refl[11+im]*refl[9+im]*fp yc[iBeg:iFin] += refl[11+im]*refl[9+im]*fp if phasePartials: ypartial[iBeg:iFin] += refl[11+im]*refl[9+im]*fp elif 'T' in calcControls[hfx+'histType']: for iref,refl in enumerate(refDict['RefList']): if im: h,k,l,m = refl[:4] else: h,k,l = refl[:3] Uniq = np.inner(refl[:3],SGMT) refl[5+im] = GetReflPos(refl,im,0.0,A,pfx,hfx,phfx,calcControls,parmDict) #corrected reflection position - #TODO - what about tabluated offset? Lorenz = sind(abs(parmDict[hfx+'2-theta'])/2)*refl[4+im]**4 #TOF Lorentz correction # refl[5+im] += GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict) #apply hydrostatic strain shift refl[6+im:8+im] = GetReflSigGamTOF(refl,im,G,GB,phfx,calcControls,parmDict) #peak sig & gam refl[12+im:14+im] = GetReflAlpBet(refl,im,hfx,parmDict) #TODO - skip if alp, bet tabulated? refl[11+im],refl[15+im],refl[16+im],refl[17+im] = GetIntensityCorr(refl,im,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict) refl[11+im] *= Vst*Lorenz if Phase['General'].get('doPawley'): try: if im: pInd =pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)]) else: pInd =pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)]) refl[9+im] = parmDict[pInd] except KeyError: continue Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im]) iBeg = np.searchsorted(x,refl[5+im]-fmin) iFin = np.searchsorted(x,refl[5+im]+fmax) if not iBeg+iFin: #peak below low limit - skip peak continue elif not iBeg-iFin: #peak above high limit - done break elif iBeg > iFin: #bad peak coeff - skip badPeak = True continue if useMP: profArgs[iref%ncores].append((refl[5+im],refl,iBeg,iFin)) else: fp = G2pwd.getEpsVoigt(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im],ma.getdata(x[iBeg:iFin]))[0] yc[iBeg:iFin] += refl[11+im]*refl[9+im]*fp if phasePartials: ypartial[iBeg:iFin] += refl[11+im]*refl[9+im]*fp if phasePartials: #for all flavors of PWDR if Nphase > 1: SavePartial(phase,ypartial) else: SavePartial(phase,[]) # print 'profile calc time: %.3fs'%(time.time()-time0) if useMP and 'C' in calcControls[hfx+'histType']: for y in MPpool.imap_unordered(G2mp.ComputePwdrProfCW,profArgs): yc += y MPpool.terminate() elif useMP and 'T' in calcControls[hfx+'histType']: for y in MPpool.imap_unordered(G2mp.ComputePwdrProfTOF,profArgs): yc += y MPpool.terminate() elif useMP and 'B' in calcControls[hfx+'histType']: for y in MPpool.imap_unordered(G2mp.ComputePwdrProfPink,profArgs): yc += y MPpool.terminate() elif useMP and 'E' in calcControls[hfx+'histType']: for y in MPpool.imap_unordered(G2mp.ComputePwdrProfED,profArgs): yc += y MPpool.terminate() if badPeak: print ('ouch #7 bad profile coefficients yield negative peak width; some reflections skipped') if GSASIIpath.GetConfigValue('Show_timing',False): print ('getPowderProfile t=%.3f'%(time.time()-starttime)) return yc,yb
[docs] def getPowderProfileDerv(args): '''Computes the derivatives of the computed powder pattern with respect to all refined parameters. Used for single processor & Multiprocessor versions ''' import pytexture as ptx ptx.pyqlmninit() #initialize fortran arrays for spherical harmonics for each processor parmDict,x,varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup,dependentVars = args[:9] prc,tprc,histogram = 0,1,None if len(args) >= 10: prc=args[9] if len(args) >= 11: tprc=args[10] if len(args) >= 12: histogram=args[11] def cellVaryDerv(pfx,SGData,dpdA): if SGData['SGLaue'] in ['-1',]: return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]], [pfx+'A3',dpdA[3]],[pfx+'A4',dpdA[4]],[pfx+'A5',dpdA[5]]] elif SGData['SGLaue'] in ['2/m',]: if SGData['SGUniq'] == 'a': return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A5',dpdA[5]]] elif SGData['SGUniq'] == 'b': return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A4',dpdA[4]]] else: return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A3',dpdA[3]]] elif SGData['SGLaue'] in ['mmm',]: return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]]] elif SGData['SGLaue'] in ['4/m','4/mmm']: return [[pfx+'A0',dpdA[0]],[pfx+'A2',dpdA[2]]] elif SGData['SGLaue'] in ['6/m','6/mmm','3m1', '31m', '3']: return [[pfx+'A0',dpdA[0]],[pfx+'A2',dpdA[2]]] elif SGData['SGLaue'] in ['3R', '3mR']: return [[pfx+'A0',dpdA[0]+dpdA[1]+dpdA[2]],[pfx+'A3',dpdA[3]+dpdA[4]+dpdA[5]]] elif SGData['SGLaue'] in ['m3m','m3']: return [[pfx+'A0',dpdA[0]]] # create a list of dependent variables and set up a dictionary to hold their derivatives # dependentVars = G2mv.GetDependentVars() depDerivDict = {} for j in dependentVars: depDerivDict[j] = np.zeros(shape=(len(x))) # print ('dependent vars',dependentVars) hId = Histogram['hId'] hfx = ':%d:'%(hId) bakType = calcControls[hfx+'bakType'] dMdv = np.zeros(shape=(len(varylist),len(x))) fixback = Histogram['Background'][1].get('fixback',None) dMdb,dMddb,dMdpk,dMdfb = G2pwd.getBackgroundDerv(hfx,parmDict,bakType,calcControls[hfx+'histType'],x,fixback) if prc == 0 and hfx+'Back;0' in varylist: # for now assume that Back;x vars do not appear in constraints bBpos = varylist.index(hfx+'Back;0') dMdv[bBpos:bBpos+len(dMdb)] += dMdb #TODO crash if bck parms tossed names = [hfx+'DebyeA',hfx+'DebyeR',hfx+'DebyeU'] for name in varylist: if prc == 0 and 'Debye' in name: Id = int(name.split(';')[-1]) parm = name[:int(name.rindex(';'))] if parm in names: #skips if bkg fxn not in current histogram ip = names.index(parm) dMdv[varylist.index(name)] += dMddb[3*Id+ip] names = [hfx+'BkPkpos',hfx+'BkPkint',hfx+'BkPksig',hfx+'BkPkgam'] for name in varylist: if prc == 0 and 'BkPk' in name: parm,Id = name.split(';') Id = int(Id) if parm in names: #skips if bkg fxn not in current histogram ip = names.index(parm) dMdv[varylist.index(name)] += dMdpk[4*Id+ip] if hfx+'BF mult' in varylist: dMdv[varylist.index(hfx+'BF mult')] += dMdfb cw = np.diff(ma.getdata(x)) cw = np.append(cw,cw[-1]) Ka2 = False #also for TOF! if 'C' in calcControls[hfx+'histType']: shl = max(parmDict[hfx+'SH/L'],0.002) if hfx+'Lam1' in (parmDict.keys()): wave = parmDict[hfx+'Lam1'] Ka2 = True lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1']) kRatio = parmDict[hfx+'I(L2)/I(L1)'] else: wave = parmDict[hfx+'Lam'] elif 'B' in calcControls[hfx+'histType']: wave = parmDict[hfx+'Lam'] for phase in Histogram['Reflection Lists']: refDict = Histogram['Reflection Lists'][phase] if phase not in Phases: #skips deleted or renamed phases silently! continue Phase = Phases[phase] if histogram and histogram not in Phase['Histograms']: continue SGData = Phase['General']['SGData'] SGMT = np.array([ops[0].T for ops in SGData['SGOps']]) im = 0 if Phase['General'].get('Modulated',False): SSGData = Phase['General']['SSGData'] im = 1 #offset in SS reflection list #?? pId = Phase['pId'] pfx = '%d::'%(pId) phfx = '%d:%d:'%(pId,hId) Dij = GetDij(phfx,SGData,parmDict) A = [parmDict[pfx+'A%d'%(i)]+Dij[i] for i in range(6)] G,g = G2lat.A2Gmat(A) #recip & real metric tensors GA,GB = G2lat.Gmat2AB(G) #Orthogonalization matricies if not Phase['General'].get('doPawley') and not parmDict.get(phfx+'LeBail') and 'E' not in calcControls[hfx+'histType']: if im: dFdvDict = SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict) dFdvDict.update(SStructureFactorDerv2(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)) else: if Phase['General']['Type'] == 'magnetic': dFdvDict = MagStructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict) dFdvDict.update(MagStructureFactorDerv2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)) else: dFdvDict = StructureFactorDerv2(refDict,G,hfx,pfx,SGData,calcControls,parmDict) ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase) # determine the parameters that will have derivatives computed only at end nonatomvarylist = [] for name in varylist: if '::RBV;' not in name and '::RBS;' not in name: try: aname = name.split(pfx)[1][:2] if aname not in ['Af','dA','AU','RB','AM','Xs','Xc','Ys','Yc','Zs','Zc', \ 'Tm','Xm','Ym','Zm','U1','U2','U3','MX','MY','MZ','AN','Ak','AD']: continue # skip anything not an atom or rigid body param except IndexError: continue nonatomvarylist.append(name) nonatomdependentVars = [] for name in dependentVars: if '::RBV;' not in name and '::RBS;' not in name: try: aname = name.split(pfx)[1][:2] if aname not in ['Af','dA','AU','RB','AM','Xs','Xc','Ys','Yc','Zs','Zc', \ 'Tm','Xm','Ym','Zm','U1','U2','U3','MX','MY','MZ','AN','Ak','AD']: continue # skip anything not an atom or rigid body param except IndexError: continue nonatomdependentVars.append(name) #========================================================================================== #========================================================================================== for iref in range(prc,len(refDict['RefList']),tprc): refl = refDict['RefList'][iref] if im: h,k,l,m = refl[:4] else: h,k,l = refl[:3] Uniq = np.inner(refl[:3],SGMT) if 'T' in calcControls[hfx+'histType']: wave = refl[14+im] if 'E' in calcControls[hfx+'histType']: dIdsh,dIdsp,dIdpola,dIdPO,dFdODF,dFdSA,dFdAb,dFdEx = [[],[],[],[],[],[],[],[]] else: dIdsh,dIdsp,dIdpola,dIdPO,dFdODF,dFdSA,dFdAb,dFdEx = GetIntensityDerv(refl,im,wave,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict) if 'C' in calcControls[hfx+'histType']: #CW powder Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl) elif 'T' in calcControls[hfx+'histType']: Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im]) elif 'B' in calcControls[hfx+'histType']: Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im]/1.e4,refl[7+im]/100.) elif 'E' in calcControls[hfx+'histType']: Wd,fmin,fmax = G2pwd.getWidthsED(refl[5+im],refl[6+im],refl[7+im]) iBeg = np.searchsorted(x,refl[5+im]-fmin) iFin = np.searchsorted(x,refl[5+im]+fmax) if not iBeg+iFin: #peak below low limit - skip peak continue elif not iBeg-iFin: #peak above high limit - done break pos = refl[5+im] if 'C' in calcControls[hfx+'histType']: tanth = tand(pos/2.0) costh = cosd(pos/2.0) lenBF = iFin-iBeg dMdpk = np.zeros(shape=(6,lenBF)) dMdipk = G2pwd.getdFCJVoigt3(refl[5+im],refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg:iFin])) for i in range(5): dMdpk[i] += refl[11+im]*refl[9+im]*dMdipk[i] dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'sig':dMdpk[2],'gam':dMdpk[3],'shl':dMdpk[4],'L1/L2':np.zeros_like(dMdpk[0])} if Ka2: pos2 = refl[5+im]+lamRatio*tanth # + 360/pi * Dlam/lam * tan(th) iBeg2 = np.searchsorted(x,pos2-fmin) iFin2 = np.searchsorted(x,pos2+fmax) if iBeg2-iFin2: lenBF2 = iFin2-iBeg2 dMdpk2 = np.zeros(shape=(6,lenBF2)) dMdipk2 = G2pwd.getdFCJVoigt3(pos2,refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg2:iFin2])) for i in range(5): dMdpk2[i] = refl[11+im]*refl[9+im]*kRatio*dMdipk2[i] dMdpk2[5] = refl[11+im]*dMdipk2[0] dervDict2 = {'int':dMdpk2[0],'pos':dMdpk2[1],'sig':dMdpk2[2],'gam':dMdpk2[3],'shl':dMdpk2[4],'L1/L2':dMdpk2[5]*refl[9]} elif 'T' in calcControls[hfx+'histType']: lenBF = iFin-iBeg if lenBF < 0: #bad peak coeff break dMdpk = np.zeros(shape=(6,lenBF)) dMdipk = G2pwd.getdEpsVoigt(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im],ma.getdata(x[iBeg:iFin])) for i in range(6): dMdpk[i] += refl[11+im]*refl[9+im]*dMdipk[i] dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'alp':dMdpk[2],'bet':dMdpk[3],'sig':dMdpk[4],'gam':dMdpk[5]} elif 'B' in calcControls[hfx+'histType']: sinth = tand(pos/2.0) tanth = tand(pos/2.0) costh = cosd(pos/2.0) lenBF = iFin-iBeg if lenBF < 0: #bad peak coeff break dMdpk = np.zeros(shape=(6,lenBF)) dMdipk = G2pwd.getdEpsVoigt(refl[5+im],refl[12+im],refl[13+im],refl[6+im]/1.e4,refl[7+im]/100.,ma.getdata(x[iBeg:iFin])) for i in range(6): dMdpk[i] = refl[11+im]*refl[9+im]*dMdipk[i] dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'alp':dMdpk[2],'bet':dMdpk[3],'sig':dMdpk[4]/1.e4,'gam':dMdpk[5]/100.} elif 'E' in calcControls[hfx+'histType']: lenBF = iFin-iBeg if lenBF < 0: #bad peak coeff break dMdpk = np.zeros(shape=(4,lenBF)) dMdipk = G2pwd.getdPsVoigt(refl[5+im],refl[6+im]*10**4,refl[7+im]*100.,ma.getdata(x[iBeg:iFin])) for i in range(4): dMdpk[i] = refl[9+im]*dMdipk[i] dervDict = {'int':dMdpk[0],'pos':-dMdpk[1],'sig':dMdpk[2]*1.e4,'gam':dMdpk[3]*100.} if Phase['General'].get('doPawley'): dMdpw = np.zeros(len(x)) try: if im: pIdx = pfx+'PWLref:'+str(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)]) else: pIdx = pfx+'PWLref:'+str(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)]) idx = varylist.index(pIdx) dMdpw[iBeg:iFin] = dervDict['int']/refl[9+im] if Ka2: #not for TOF either dMdpw[iBeg2:iFin2] += dervDict2['int']/refl[9+im] dMdv[idx] = dMdpw except: # ValueError: pass if 'C' in calcControls[hfx+'histType']: dpdA,dpdw,dpdZ,dpdSh,dpdTr,dpdX,dpdY,dpdV = GetReflPosDerv(refl,im,wave,A,pfx,hfx,phfx,calcControls,parmDict) names = {hfx+'Scale':[dIdsh,'int'],hfx+'Polariz.':[dIdpola,'int'],phfx+'Scale':[dIdsp,'int'], hfx+'U':[tanth**2,'sig'],hfx+'V':[tanth,'sig'],hfx+'W':[1.0,'sig'], hfx+'X':[1.0/costh,'gam'],hfx+'Y':[tanth,'gam'],hfx+'Z':[1.0,'gam'],hfx+'SH/L':[1.0,'shl'], hfx+'I(L2)/I(L1)':[1.0,'L1/L2'],hfx+'Zero':[dpdZ,'pos'],hfx+'Lam':[dpdw,'pos'], hfx+'Shift':[dpdSh,'pos'],hfx+'Transparency':[dpdTr,'pos'],hfx+'DisplaceX':[dpdX,'pos'], hfx+'DisplaceY':[dpdY,'pos'],phfx+'Extinction':[dFdEx,'int'],phfx+'LayerDisp':[dpdY,'pos']} if 'Bragg' in calcControls[hfx+'instType']: names.update({hfx+'SurfRoughA':[dFdAb[0],'int'], hfx+'SurfRoughB':[dFdAb[1],'int'],}) else: names.update({hfx+'Absorption':[dFdAb,'int'],}) elif 'T' in calcControls[hfx+'histType']: #'T'OF dpdA,dpdZ,dpdDC,dpdDA,dpdDB,dpdV = GetReflPosDerv(refl,im,0.0,A,pfx,hfx,phfx,calcControls,parmDict) names = {hfx+'Scale':[dIdsh,'int'],phfx+'Scale':[dIdsp,'int'], hfx+'difC':[dpdDC,'pos'],hfx+'difA':[dpdDA,'pos'],hfx+'difB':[dpdDB,'pos'], hfx+'Zero':[dpdZ,'pos'],hfx+'X':[refl[4+im],'gam'],hfx+'Y':[refl[4+im]**2,'gam'],hfx+'Z':[1.0,'gam'], hfx+'alpha':[1./refl[4+im],'alp'],hfx+'beta-0':[1.0,'bet'],hfx+'beta-1':[1./refl[4+im]**4,'bet'], hfx+'beta-q':[1./refl[4+im]**2,'bet'],hfx+'sig-0':[1.0,'sig'],hfx+'sig-1':[refl[4+im]**2,'sig'], hfx+'sig-2':[refl[4+im]**4,'sig'],hfx+'sig-q':[refl[4+im],'sig'], hfx+'Absorption':[dFdAb,'int'],phfx+'Extinction':[dFdEx,'int'],} elif 'B' in calcControls[hfx+'histType']: dpdA,dpdw,dpdZ,dpdSh,dpdTr,dpdX,dpdY,dpdV = GetReflPosDerv(refl,im,wave,A,pfx,hfx,phfx,calcControls,parmDict) names = {hfx+'Scale':[dIdsh,'int'],phfx+'Scale':[dIdsp,'int'],hfx+'Lam':[dpdw,'pos'], hfx+'Zero':[dpdZ,'pos'],hfx+'X':[1.0/costh,'gam'],hfx+'Y':[tanth,'gam'],hfx+'Z':[1.0,'gam'], hfx+'U':[tanth**2,'sig'],hfx+'V':[tanth,'sig'],hfx+'W':[1.0,'sig'],hfx+'Polariz.':[dIdpola,'int'], # hfx+'alpha-0':[1.0,'alp'],hfx+'alpha-1':[tanth,'alp'],hfx+'beta-0':[1.0,'bet'],hfx+'beta-1':[tanth,'bet'], hfx+'alpha-0':[1.0,'alp'],hfx+'alpha-1':[sinth,'alp'],hfx+'beta-0':[1.0,'bet'],hfx+'beta-1':[sinth,'bet'], hfx+'Absorption':[dFdAb,'int'],phfx+'Extinction':[dFdEx,'int'],hfx+'DisplaceX':[dpdX,'pos'],hfx+'DisplaceY':[dpdY,'pos']} if 'X' in calcControls[hfx+'histType']: names[hfx+'alpha-1'] = [tanth,'alp'] #preserve pink x-ray definitions names[hfx+'beta-1'] = [tanth,'bet'] elif 'E' in calcControls[hfx+'histType']: dpdA,dpdTTh,dpdXE,dpdYE,dpdZE = GetReflPosDerv(refl,im,0.0,A,pfx,hfx,phfx,calcControls,parmDict) names = {hfx+'Scale':[dIdsh,'int'],hfx+'2-theta':[dpdTTh,'pos'], hfx+'A':[refl[5+im]**2,'sig'],hfx+'B':[refl[5+im],'sig'],hfx+'C':[1.0,'sig'], hfx+'X':[refl[5+im]**2,'gam'],hfx+'Y':[refl[5+im],'gam'],hfx+'Z':[1.0,'sig'], hfx+'XE':[dpdXE,'pos'],hfx+'YE':[dpdYE,'pos'],hfx+'ZE':[dpdZE,'pos'] } for name in names: item = names[name] if name in varylist: dMdv[varylist.index(name)][iBeg:iFin] += item[0]*dervDict[item[1]] if Ka2 and iFin2-iBeg2: dMdv[varylist.index(name)][iBeg2:iFin2] += item[0]*dervDict2[item[1]] elif name in dependentVars: depDerivDict[name][iBeg:iFin] += item[0]*dervDict[item[1]] if Ka2 and iFin2-iBeg2: depDerivDict[name][iBeg2:iFin2] += item[0]*dervDict2[item[1]] for iPO in dIdPO: if iPO in varylist: dMdv[varylist.index(iPO)][iBeg:iFin] += dIdPO[iPO]*dervDict['int'] if Ka2 and iFin2-iBeg2: dMdv[varylist.index(iPO)][iBeg2:iFin2] += dIdPO[iPO]*dervDict2['int'] elif iPO in dependentVars: depDerivDict[iPO][iBeg:iFin] += dIdPO[iPO]*dervDict['int'] if Ka2 and iFin2-iBeg2: depDerivDict[iPO][iBeg2:iFin2] += dIdPO[iPO]*dervDict2['int'] for i,name in enumerate(['omega','chi','phi']): aname = pfx+'SH '+name if aname in varylist: dMdv[varylist.index(aname)][iBeg:iFin] += dFdSA[i]*dervDict['int'] if Ka2 and iFin2-iBeg2: dMdv[varylist.index(aname)][iBeg2:iFin2] += dFdSA[i]*dervDict2['int'] elif aname in dependentVars: depDerivDict[aname][iBeg:iFin] += dFdSA[i]*dervDict['int'] if Ka2 and iFin2-iBeg2: depDerivDict[aname][iBeg2:iFin2] += dFdSA[i]*dervDict2['int'] for iSH in dFdODF: if iSH in varylist: dMdv[varylist.index(iSH)][iBeg:iFin] += dFdODF[iSH]*dervDict['int'] if Ka2 and iFin2-iBeg2: dMdv[varylist.index(iSH)][iBeg2:iFin2] += dFdODF[iSH]*dervDict2['int'] elif iSH in dependentVars: depDerivDict[iSH][iBeg:iFin] += dFdODF[iSH]*dervDict['int'] if Ka2 and iFin2-iBeg2: depDerivDict[iSH][iBeg2:iFin2] += dFdODF[iSH]*dervDict2['int'] cellDervNames = cellVaryDerv(pfx,SGData,dpdA) for name,dpdA in cellDervNames: if name in varylist: dMdv[varylist.index(name)][iBeg:iFin] += dpdA*dervDict['pos'] if Ka2 and iFin2-iBeg2: dMdv[varylist.index(name)][iBeg2:iFin2] += dpdA*dervDict2['pos'] elif name in dependentVars: #need to scale for mixed phase constraints? depDerivDict[name][iBeg:iFin] += dpdA*dervDict['pos'] if Ka2 and iFin2-iBeg2: depDerivDict[name][iBeg2:iFin2] += dpdA*dervDict2['pos'] dDijDict = GetHStrainShiftDerv(refl,im,SGData,phfx,hfx,calcControls,parmDict) for name in dDijDict: if name in varylist: dMdv[varylist.index(name)][iBeg:iFin] += dDijDict[name]*dervDict['pos'] if Ka2 and iFin2-iBeg2: dMdv[varylist.index(name)][iBeg2:iFin2] += dDijDict[name]*dervDict2['pos'] elif name in dependentVars: depDerivDict[name][iBeg:iFin] += dDijDict[name]*dervDict['pos'] if Ka2 and iFin2-iBeg2: depDerivDict[name][iBeg2:iFin2] += dDijDict[name]*dervDict2['pos'] #TODO: need Layer Disp deriv here for i,name in enumerate([pfx+'mV0',pfx+'mV1',pfx+'mV2']): if name in varylist: dMdv[varylist.index(name)][iBeg:iFin] += dpdV[i]*dervDict['pos'] if Ka2 and iFin2-iBeg2: dMdv[varylist.index(name)][iBeg2:iFin2] += dpdV[i]*dervDict2['pos'] elif name in dependentVars: depDerivDict[name][iBeg:iFin] += dpdV[i]*dervDict['pos'] if Ka2 and iFin2-iBeg2: depDerivDict[name][iBeg2:iFin2] += dpdV[i]*dervDict2['pos'] if 'C' in calcControls[hfx+'histType'] or 'B' in calcControls[hfx+'histType']: sigDict,gamDict = GetSampleSigGamDerv(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict) elif 'T' in calcControls[hfx+'histType']: #'T'OF sigDict,gamDict = GetSampleSigGamDerv(refl,im,0.0,G,GB,SGData,hfx,phfx,calcControls,parmDict) else: #'E' sigDict,gamDict = GetSampleSigGamDerv(refl,im,parmDict[hfx+'2-theta'],G,GB,SGData,hfx,phfx,calcControls,parmDict) for name in gamDict: if name in varylist: dMdv[varylist.index(name)][iBeg:iFin] += gamDict[name]*dervDict['gam'] if Ka2 and iFin2-iBeg2: dMdv[varylist.index(name)][iBeg2:iFin2] += gamDict[name]*dervDict2['gam'] elif name in dependentVars: depDerivDict[name][iBeg:iFin] += gamDict[name]*dervDict['gam'] if Ka2 and iFin2-iBeg2: depDerivDict[name][iBeg2:iFin2] += gamDict[name]*dervDict2['gam'] for name in sigDict: if name in varylist: dMdv[varylist.index(name)][iBeg:iFin] += sigDict[name]*dervDict['sig'] if Ka2 and iFin2-iBeg2: dMdv[varylist.index(name)][iBeg2:iFin2] += sigDict[name]*dervDict2['sig'] elif name in dependentVars: depDerivDict[name][iBeg:iFin] += sigDict[name]*dervDict['sig'] if Ka2 and iFin2-iBeg2: depDerivDict[name][iBeg2:iFin2] += sigDict[name]*dervDict2['sig'] for name in ['BabA','BabU']: if refl[9+im]: if phfx+name in varylist: dMdv[varylist.index(phfx+name)][iBeg:iFin] += parmDict[phfx+'Scale']*dFdvDict[phfx+name][iref]*dervDict['int']/refl[9+im] if Ka2 and iFin2-iBeg2: dMdv[varylist.index(phfx+name)][iBeg2:iFin2] += parmDict[phfx+'Scale']*dFdvDict[phfx+name][iref]*dervDict2['int']/refl[9+im] elif phfx+name in dependentVars: depDerivDict[phfx+name][iBeg:iFin] += parmDict[phfx+'Scale']*dFdvDict[phfx+name][iref]*dervDict['int']/refl[9+im] if Ka2 and iFin2-iBeg2: depDerivDict[phfx+name][iBeg2:iFin2] += parmDict[phfx+'Scale']*dFdvDict[phfx+name][iref]*dervDict2['int']/refl[9+im] if not Phase['General'].get('doPawley') and not parmDict.get(phfx+'LeBail') and 'E' not in calcControls[hfx+'histType']: #do atom derivatives - for RB,F,X & U so far - how do I scale mixed phase constraints? corr = 0. corr2 = 0. if refl[9+im]: corr = dervDict['int']/refl[9+im] if Ka2 and iFin2-iBeg2: corr2 = dervDict2['int']/refl[9+im] for name in nonatomvarylist: dMdv[varylist.index(name)][iBeg:iFin] += dFdvDict[name][iref]*corr if Ka2 and iFin2-iBeg2: dMdv[varylist.index(name)][iBeg2:iFin2] += dFdvDict[name][iref]*corr2 for name in nonatomdependentVars: depDerivDict[name][iBeg:iFin] += dFdvDict[name][iref]*corr if Ka2 and iFin2-iBeg2: depDerivDict[name][iBeg2:iFin2] += dFdvDict[name][iref]*corr2 # now process derivatives in constraints dMdv[:,ma.getmaskarray(x)] = 0. # instead of masking, zero out masked values #G2mv.Dict2Deriv(varylist,depDerivDict,dMdv) return dMdv,depDerivDict
def UserRejectHKL(ref,im,userReject): if ref[5+im]/ref[6+im] < userReject['minF/sig']: return False elif userReject['MaxD'] < ref[4+im] > userReject['MinD']: return False elif ref[11+im] < userReject['MinExt']: return False elif abs(ref[5+im]-ref[7+im])/ref[6+im] > userReject['MaxDF/F']: return False return True
[docs] def dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict): '''Loop over reflections in a HKLF histogram and compute derivatives of the fitting model (M) with respect to all parameters. Independent and dependant dM/dp arrays are returned to either dervRefine or HessRefine. :returns: ''' hId = Histogram['hId'] hfx = ':%d:'%(hId) pfx = '%d::'%(Phase['pId']) phfx = '%d:%d:'%(Phase['pId'],hId) SGData = Phase['General']['SGData'] im = 0 if Phase['General'].get('Modulated',False): SSGData = Phase['General']['SSGData'] im = 1 #offset in SS reflection list A = [parmDict[pfx+'A%d'%(i)] for i in range(6)] G,g = G2lat.A2Gmat(A) #recip & real metric tensors TwinLaw = calcControls[phfx+'TwinLaw'] refDict = Histogram['Data'] if parmDict[phfx+'Scale'] < 0.: parmDict[phfx+'Scale'] = .001 if im: # split to nontwin/twin versions if len(TwinLaw) > 1: dFdvDict = SStructureFactorDervTw(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict) #not ok else: dFdvDict = SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict) #OK dFdvDict.update(SStructureFactorDerv2(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)) else: if len(TwinLaw) > 1: dFdvDict = StructureFactorDervTw2(refDict,G,hfx,pfx,SGData,calcControls,parmDict) else: #correct!! if Phase['General']['Type'] == 'magnetic': dFdvDict = MagStructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict) dFdvDict.update(MagStructureFactorDerv2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)) else: dFdvDict = StructureFactorDerv2(refDict,G,hfx,pfx,SGData,calcControls,parmDict) ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase) dMdvh = np.zeros((len(varylist),len(refDict['RefList']))) dependentVars = G2mv.GetDependentVars() depDerivDict = {} for j in dependentVars: depDerivDict[j] = np.zeros(shape=(len(refDict['RefList']))) wdf = np.zeros(len(refDict['RefList'])) if calcControls['F**2']: for iref,ref in enumerate(refDict['RefList']): if ref[6+im] > 0: dervDict,dervCor = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist+dependentVars)[1:] w = 1.0/ref[6+im] if ref[3+im] > 0: wdf[iref] = w*(ref[5+im]-ref[7+im]) for j,var in enumerate(varylist): if var in dFdvDict: dMdvh[j][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im] for var in dependentVars: if var in dFdvDict: depDerivDict[var][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im] if phfx+'Scale' in varylist: dMdvh[varylist.index(phfx+'Scale')][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale'] #OK elif phfx+'Scale' in dependentVars: depDerivDict[phfx+'Scale'][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale'] #OK for item in ['Ep','Es','Eg']: if phfx+item in varylist and phfx+item in dervDict: dMdvh[varylist.index(phfx+item)][iref] = w*dervDict[phfx+item]/ref[11+im] #OK elif phfx+item in dependentVars and phfx+item in dervDict: depDerivDict[phfx+item][iref] = w*dervDict[phfx+item]/ref[11+im] #OK for item in ['BabA','BabU']: if phfx+item in varylist: dMdvh[varylist.index(phfx+item)][iref] = w*dFdvDict[phfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im] elif phfx+item in dependentVars: depDerivDict[phfx+item][iref] = w*dFdvDict[phfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im] else: #F refinement for iref,ref in enumerate(refDict['RefList']): if ref[5+im] > 0.: dervDict,dervCor = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist+dependentVars)[1:] Fo = np.sqrt(ref[5+im]) Fc = np.sqrt(ref[7+im]) w = 1.0/ref[6+im] if ref[3+im] > 0: wdf[iref] = 2.0*Fc*w*(Fo-Fc) for j,var in enumerate(varylist): if var in dFdvDict: dMdvh[j][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im] for var in dependentVars: if var in dFdvDict: depDerivDict[var][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im] if phfx+'Scale' in varylist: dMdvh[varylist.index(phfx+'Scale')][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale'] #OK elif phfx+'Scale' in dependentVars: depDerivDict[phfx+'Scale'][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale'] #OK for item in ['Ep','Es','Eg']: #OK! if phfx+item in varylist and phfx+item in dervDict: dMdvh[varylist.index(phfx+item)][iref] = w*dervDict[phfx+item]/ref[11+im] elif phfx+item in dependentVars and phfx+item in dervDict: depDerivDict[phfx+item][iref] = w*dervDict[phfx+item]/ref[11+im] for item in ['BabA','BabU']: if phfx+item in varylist: dMdvh[varylist.index(phfx+item)][iref] = w*dFdvDict[phfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im] elif phfx+item in dependentVars: depDerivDict[phfx+item][iref] = w*dFdvDict[phfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im] return dMdvh,depDerivDict,wdf
[docs] def dervRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg): '''Loop over histograms and compute derivatives of the fitting model (M) with respect to all parameters. Results are returned in a Jacobian matrix (aka design matrix) of dimensions (n by m) where n is the number of parameters and m is the number of data points. This can exceed memory when m gets large. This routine is used when refinement derivatives are selected as "analtytic Jacobian" in Controls. :returns: Jacobian numpy.array dMdv for all histograms concatinated ''' parmDict.update(zip(varylist,values)) G2mv.Dict2Map(parmDict) Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases dependentVars = G2mv.GetDependentVars() histoList = list(Histograms.keys()) histoList.sort() First = True for histogram in histoList: if 'PWDR' in histogram[:4]: Histogram = Histograms[histogram] hId = Histogram['hId'] hfx = ':%d:'%(hId) wtFactor = calcControls[hfx+'wtFactor'] Limits = calcControls[hfx+'Limits'] x,y,w,yc,yb,yd = Histogram['Data'] xB = np.searchsorted(x,Limits[0]) xF = np.searchsorted(x,Limits[1])+1 dMdv,depDerivDict = getPowderProfileDerv([parmDict,x[xB:xF],varylist,Histogram,Phases,rigidbodyDict, calcControls,pawleyLookup,dependentVars]) G2mv.Dict2Deriv(varylist,depDerivDict,dMdv) dMdvh = np.sqrt(w[xB:xF])*dMdv elif 'HKLF' in histogram[:4]: Histogram = Histograms[histogram] phase = Histogram['Reflection Lists'] Phase = Phases[phase] dMdvh,depDerivDict,wdf = dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict) hfx = ':%d:'%(Histogram['hId']) wtFactor = calcControls[hfx+'wtFactor'] # now process derivatives in constraints G2mv.Dict2Deriv(varylist,depDerivDict,dMdvh) else: continue #skip non-histogram entries if First: dMdV = np.sqrt(wtFactor)*dMdvh First = False else: dMdV = np.concatenate((dMdV.T,np.sqrt(wtFactor)*dMdvh.T)).T GetFobsSq(Histograms,Phases,parmDict,calcControls) pNames,pVals,pWt,pWsum,pWnum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist) if np.any(pVals): dpdv = penaltyDeriv(pNames,pVals,HistoPhases,calcControls,parmDict,varylist) dMdV = np.concatenate((dMdV.T,(np.sqrt(pWt)*dpdv).T)).T return dMdV
[docs] def HessRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg): '''Loop over histograms and compute derivatives of the fitting model (M) with respect to all parameters. For each histogram, the Jacobian matrix, dMdv, with dimensions (n by m) where n is the number of parameters and m is the number of data points *in the histogram*. The (n by n) Hessian is computed from each Jacobian and it is returned. This routine is used when refinement derivatives are selected as "analtytic Hessian" in Controls. :returns: Vec,Hess where Vec is the least-squares vector and Hess is the Hessian ''' parmDict.update(zip(varylist,values)) G2mv.Dict2Map(parmDict) Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases dependentVars = G2mv.GetDependentVars() #fixup H atom positions here? ApplyRBModels(parmDict,Phases,rigidbodyDict) #,Update=True?? Hess = np.empty(0) Vec = np.empty(0) histoList = list(Histograms.keys()) histoList.sort() for histogram in histoList: if 'PWDR' in histogram[:4]: if hasattr(dlg,'SetHistogram'): dlg.SetHistogram(None,'Computing derivatives for '+histogram) Histogram = Histograms[histogram] hId = Histogram['hId'] hfx = ':%d:'%(hId) wtFactor = calcControls[hfx+'wtFactor'] Limits = calcControls[hfx+'Limits'] x,y,w,yc,yb,yd = Histogram['Data'] W = wtFactor*w dy = y-yc xB = np.searchsorted(x,Limits[0]) xF = np.searchsorted(x,Limits[1])+1 useMP,ncores = G2mp.InitMP() if GSASIIpath.GetConfigValue('Show_timing',False): starttime = time.time() if useMP: MPpool = mp.Pool(ncores) dMdvh = None depDerivDict = None # old approach, create all args prior to use # profArgs = [ # (parmDict,x[xB:xF],varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup,dependentVars, # i,ncores,histogram) for i in range(ncores)] # for dmdv,depDerivs in MPpool.imap_unordered(getPowderProfileDerv,profArgs): # better, use a generator so arg is created as used profGenArgs = ( (parmDict,x[xB:xF],varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup,dependentVars, i,ncores,histogram) for i in range(ncores)) for dmdv,depDerivs in MPpool.imap_unordered(getPowderProfileDerv,profGenArgs): if dMdvh is None: dMdvh = dmdv depDerivDict = depDerivs else: dMdvh += dmdv for key in depDerivs.keys(): depDerivDict[key] += depDerivs[key] MPpool.terminate() else: dMdvh,depDerivDict = getPowderProfileDerv([parmDict,x[xB:xF], varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup,dependentVars,0,1,histogram]) #dMdvh = getPowderProfileDerv(parmDict,x[xB:xF], # varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup,dependentVars) G2mv.Dict2Deriv(varylist,depDerivDict,dMdvh) if GSASIIpath.GetConfigValue('Show_timing',False): print ('getPowderProfileDerv t=%.3f'%(time.time()-starttime)) Wt = ma.sqrt(W[xB:xF])[nxs,:] Dy = dy[xB:xF][nxs,:] dMdvh *= Wt if dlg: if 'G2' in str(type(dlg)): GoOn = dlg.Update(Histogram['Residuals']['wR'],newmsg='Hessian for histogram %d\nAll data Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%')) else: GoOn = dlg.Update(int(Histogram['Residuals']['wR']),newmsg='Hessian for histogram %d\nAll data Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%')) if type(GoOn) is tuple: if not GoOn[0]: raise G2obj.G2RefineCancel('Cancel pressed') elif not GoOn: raise G2obj.G2RefineCancel('Cancel pressed') #dlg.Raise() if len(Hess): Hess += np.inner(dMdvh,dMdvh) dMdvh *= Wt*Dy Vec += np.sum(dMdvh,axis=1) else: Hess = np.inner(dMdvh,dMdvh) dMdvh *= Wt*Dy Vec = np.sum(dMdvh,axis=1) elif 'HKLF' in histogram[:4]: if hasattr(dlg,'SetHistogram'): dlg.SetHistogram(None,'Computing derivatives for '+histogram) Histogram = Histograms[histogram] phase = Histogram['Reflection Lists'] Phase = Phases[phase] dMdvh,depDerivDict,wdf = dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict) hId = Histogram['hId'] hfx = ':%d:'%(Histogram['hId']) wtFactor = calcControls[hfx+'wtFactor'] # now process derivatives in constraints G2mv.Dict2Deriv(varylist,depDerivDict,dMdvh) # print 'matrix build time: %.3f'%(time.time()-time0) if dlg: if 'G2' in str(type(dlg)): GoOn = dlg.Update(Histogram['Residuals']['wR'],newmsg='Hessian for histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%')) else: GoOn = dlg.Update(int(Histogram['Residuals']['wR']),newmsg='Hessian for histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%')) if type(GoOn) is tuple: if not GoOn[0]: raise G2obj.G2RefineCancel('Cancel pressed') elif not GoOn: raise G2obj.G2RefineCancel('Cancel pressed') #dlg.Raise() if len(Hess): Vec += wtFactor*np.sum(dMdvh*wdf,axis=1) Hess += wtFactor*np.inner(dMdvh,dMdvh) else: Vec = wtFactor*np.sum(dMdvh*wdf,axis=1) Hess = wtFactor*np.inner(dMdvh,dMdvh) else: continue #skip non-histogram entries GetFobsSq(Histograms,Phases,parmDict,calcControls) pNames,pVals,pWt,pWsum,pWnum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist) if np.any(pVals): dpdv = penaltyDeriv(pNames,pVals,HistoPhases,calcControls,parmDict,varylist) Vec -= np.sum(dpdv*pWt*pVals,axis=1) Hess += np.inner(dpdv*pWt,dpdv) return Vec,Hess
[docs] def errRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg=None): '''Computes the point-by-point discrepancies between every data point in every histogram and the observed value. Used in the Jacobian, Hessian & numeric least-squares to compute function :returns: an np array of differences between observed and computed diffraction values. ''' Values2Dict(parmDict, varylist, values) if len(varylist): #skip if no variables; e.g. in a zero cycle LeBail refinement G2mv.Dict2Map(parmDict) Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases M = np.empty(0) SumwYo = 0 Nobs = 0 Nrej = 0 Next = 0 ApplyRBModels(parmDict,Phases,rigidbodyDict) #fixup Hatom positions here.... histoList = list(Histograms.keys()) histoList.sort() phasePartials = calcControls.get('PhasePartials',None) if phasePartials: print('Storing intensity by phase in',phasePartials) phPartialFP = open(phasePartials,'wb') # create/clear partials file phPartialFP.close() for histogram in histoList: if 'PWDR' in histogram[:4]: Histogram = Histograms[histogram] hId = Histogram['hId'] if hasattr(dlg,'SetHistogram'): dlg.SetHistogram(hId,histogram) hfx = ':%d:'%(hId) wtFactor = calcControls[hfx+'wtFactor'] Limits = calcControls[hfx+'Limits'] x,y,w,yc,yb,yd = Histogram['Data'] yc *= 0.0 #zero full calcd profiles yb *= 0.0 yd *= 0.0 xB = np.searchsorted(x,Limits[0]) xF = np.searchsorted(x,Limits[1])+1 yc[xB:xF],yb[xB:xF] = getPowderProfile(parmDict,x[xB:xF], varylist,Histogram,Phases,calcControls,pawleyLookup,histogram) yc[xB:xF] += yb[xB:xF] if not np.any(y): #fill dummy data try: rv = st.poisson(yc[xB:xF]) y[xB:xF] = rv.rvs() except ValueError: y[xB:xF] = yc[xB:xF] Z = np.ones_like(yc[xB:xF]) Z[1::2] *= -1 y[xB:xF] = yc[xB:xF]+np.abs(y[xB:xF]-yc[xB:xF])*Z w[xB:xF] = np.where(y[xB:xF]>0.,1./y[xB:xF],1.0) yd[xB:xF] = y[xB:xF]-yc[xB:xF] W = wtFactor*w wdy = -ma.sqrt(w[xB:xF])*(yd[xB:xF]) Histogram['Residuals']['Durbin-Watson'] = ma.sum(ma.diff(wdy)**2)/ma.sum(wdy**2) wdy *= np.sqrt(wtFactor) Histogram['Residuals']['Nobs'] = ma.count(x[xB:xF]) Nobs += Histogram['Residuals']['Nobs'] Histogram['Residuals']['sumwYo'] = ma.sum(W[xB:xF]*y[xB:xF]**2) SumwYo += Histogram['Residuals']['sumwYo'] Histogram['Residuals']['R'] = min(100.,ma.sum(ma.abs(yd[xB:xF]))/ma.sum(y[xB:xF])*100.) Histogram['Residuals']['wR'] = min(100.,ma.sqrt(ma.sum(wdy**2)/Histogram['Residuals']['sumwYo'])*100.) sumYmB = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],ma.abs(y[xB:xF]-yb[xB:xF]),0.)) sumwYmB2 = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],W[xB:xF]*(y[xB:xF]-yb[xB:xF])**2,0.)) sumYB = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],ma.abs(y[xB:xF]-yc[xB:xF])*ma.abs(y[xB:xF]-yb[xB:xF])/y[xB:xF],0.)) sumwYB2 = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],W[xB:xF]*(ma.abs(y[xB:xF]-yc[xB:xF])*ma.abs(y[xB:xF]-yb[xB:xF])/y[xB:xF])**2,0.)) Histogram['Residuals']['Rb'] = min(100.,100.*sumYB/sumYmB) Histogram['Residuals']['wRb'] = min(100.,100.*ma.sqrt(sumwYB2/sumwYmB2)) Histogram['Residuals']['wRmin'] = min(100.,100.*ma.sqrt(Histogram['Residuals']['Nobs']/Histogram['Residuals']['sumwYo'])) if dlg: if 'G2' in str(type(dlg)): GoOn = dlg.Update(Histogram['Residuals']['wR'],newmsg='For histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%')) else: GoOn = dlg.Update(int(Histogram['Residuals']['wR']),newmsg='For histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%')) if type(GoOn) is tuple: if not GoOn[0]: raise G2obj.G2RefineCancel('Cancel pressed') elif not GoOn: raise G2obj.G2RefineCancel('Cancel pressed') #dlg.Raise() M = np.concatenate((M,wdy)) #end of PWDR processing elif 'HKLF' in histogram[:4]: Histogram = Histograms[histogram] hId = Histogram['hId'] if hasattr(dlg,'SetHistogram'): dlg.SetHistogram(hId,histogram) Histogram['Residuals'] = {} phase = Histogram['Reflection Lists'] Phase = Phases[phase] hfx = ':%d:'%(hId) wtFactor = calcControls[hfx+'wtFactor'] pfx = '%d::'%(Phase['pId']) phfx = '%d:%d:'%(Phase['pId'],hId) SGData = Phase['General']['SGData'] TwinLaw = calcControls[phfx+'TwinLaw'] im = 0 if parmDict[phfx+'Scale'] < 0.: parmDict[phfx+'Scale'] = .001 if Phase['General'].get('Modulated',False): SSGData = Phase['General']['SSGData'] im = 1 #offset in SS reflection list A = [parmDict[pfx+'A%d'%(i)] for i in range(6)] G,g = G2lat.A2Gmat(A) #recip & real metric tensors refDict = Histogram['Data'] if im: if len(TwinLaw) > 1: SStructureFactorTw(refDict,G,hfx,pfx,SGData,SSGData,calcControls,parmDict) else: SStructureFactor(refDict,G,hfx,pfx,SGData,SSGData,calcControls,parmDict) else: StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict) # print 'sf-calc time: %.3f'%(time.time()-time0) df = np.zeros(len(refDict['RefList'])) sumwYo = 0 sumFo = 0 sumFo2 = 0 sumFc2 = 0 sumdF = 0 sumdF2 = 0 if im: sumSSFo = np.zeros(10) sumSSFo2 = np.zeros(10) sumSSdF = np.zeros(10) sumSSdF2 = np.zeros(10) sumSSwYo = np.zeros(10) sumSSwdf2 = np.zeros(10) SSnobs = np.zeros(10) nobs = 0 nrej = 0 Nexti = 0 maxH = 0 if calcControls['F**2']: for i,ref in enumerate(refDict['RefList']): if ref[6+im] > 0: ref[11+im] = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist)[0] w = 1.0/ref[6+im] # 1/sig(F^2) ref[7+im] *= parmDict[phfx+'Scale']*ref[11+im] #correct Fc^2 for extinction ref[8+im] = ref[5+im]/(parmDict[phfx+'Scale']*ref[11+im]) if UserRejectHKL(ref,im,calcControls['UsrReject']) and ref[3+im]: #skip sp.gp. absences (mul=0) ref[3+im] = abs(ref[3+im]) #mark as allowed Fo = np.sqrt(ref[5+im]) sumFo += Fo sumFo2 += ref[5+im] sumFc2 += ref[7+im] sumdF += abs(Fo-np.sqrt(ref[7+im])) sumdF2 += abs(ref[5+im]-ref[7+im]) nobs += 1 df[i] = -w*(ref[5+im]-ref[7+im]) sumwYo += (w*ref[5+im])**2 #w*Fo^2 if im: #accumulate super lattice sums ind = int(abs(ref[3])) sumSSFo[ind] += Fo sumSSFo2[ind] += ref[5+im] sumSSdF[ind] += abs(Fo-np.sqrt(ref[7+im])) sumSSdF2[ind] += abs(ref[5+im]-ref[7+im]) sumSSwYo[ind] += (w*ref[5+im])**2 #w*Fo^2 sumSSwdf2[ind] += df[i]**2 SSnobs[ind] += 1 maxH = max(maxH,ind) else: if ref[3+im]: ref[3+im] = -abs(ref[3+im]) #mark as rejected nrej += 1 else: #sp.gp.extinct Nexti += 1 else: for i,ref in enumerate(refDict['RefList']): if ref[5+im] > 0.: ref[11+im] = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist)[0] ref[7+im] *= parmDict[phfx+'Scale']*ref[11+im] #correct Fc^2 for extinction ref[8+im] = ref[5+im]/(parmDict[phfx+'Scale']*ref[11+im]) Fo = np.sqrt(ref[5+im]) Fc = np.sqrt(ref[7+im]) w = 2.0*Fo/ref[6+im] # 1/sig(F)? if UserRejectHKL(ref,im,calcControls['UsrReject']) and ref[3+im]: #skip sp.gp. absences (mul=0) ref[3+im] = abs(ref[3+im]) #mark as allowed sumFo += Fo sumFo2 += ref[5+im] sumFc2 += ref[7+im] sumdF += abs(Fo-Fc) sumdF2 += abs(ref[5+im]-ref[7+im]) nobs += 1 df[i] = -w*(Fo-Fc) sumwYo += (w*Fo)**2 if im: ind = int(abs(ref[3])) sumSSFo[ind] += Fo sumSSFo2[ind] += ref[5+im] sumSSdF[ind] += abs(Fo-Fc) sumSSdF2[ind] += abs(ref[5+im]-ref[7+im]) sumSSwYo[ind] += (w*Fo)**2 sumSSwdf2[ind] += df[i]**2 SSnobs[ind] += 1 maxH = max(maxH,ind) else: if ref[3+im]: ref[3+im] = -abs(ref[3+im]) #mark as rejected nrej += 1 else: #sp.gp.extinct Nexti += 1 Scale = sumFo2/sumFc2 if (Scale < 0.8 or Scale > 1.2) and phfx+'Scale' in varylist: print ('New scale: %.4f'%(Scale*parmDict[phfx+'Scale'])) indx = varylist.index(phfx+'Scale') values[indx] = Scale*parmDict[phfx+'Scale'] Histogram['Residuals']['Nobs'] = nobs Histogram['Residuals']['sumwYo'] = sumwYo SumwYo += sumwYo Histogram['Residuals']['wR'] = min(100.,np.sqrt(np.sum(df**2)/sumwYo)*100.) Histogram['Residuals'][phfx+'Rf'] = 100.*sumdF/sumFo Histogram['Residuals'][phfx+'Rf^2'] = 100.*sumdF2/sumFo2 Histogram['Residuals'][phfx+'Nref'] = nobs Histogram['Residuals'][phfx+'Nrej'] = nrej Histogram['Residuals'][phfx+'Next'] = Nexti if im: Histogram['Residuals'][phfx+'SSRf'] = 100.*sumSSdF[:maxH+1]/sumSSFo[:maxH+1] Histogram['Residuals'][phfx+'SSRf^2'] = 100.*sumSSdF2[:maxH+1]/sumSSFo2[:maxH+1] Histogram['Residuals'][phfx+'SSNref'] = SSnobs[:maxH+1] Histogram['Residuals']['SSwR'] = np.sqrt(sumSSwdf2[:maxH+1]/sumSSwYo[:maxH+1])*100. Nobs += nobs Nrej += nrej Next += Nexti if dlg: if 'G2' in str(type(dlg)): GoOn = dlg.Update(Histogram['Residuals']['wR'],newmsg='For histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%')) else: GoOn = dlg.Update(int(Histogram['Residuals']['wR']),newmsg='For histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%')) if type(GoOn) is tuple: if not GoOn[0]: raise G2obj.G2RefineCancel('Cancel pressed') elif not GoOn: raise G2obj.G2RefineCancel('Cancel pressed') #dlg.Raise() M = np.concatenate((M,wtFactor*df)) # end of HKLF processing # GetFobsSq(Histograms,Phases,parmDict,calcControls) Histograms['sumwYo'] = SumwYo Histograms['Nobs'] = Nobs Histograms['Nrej'] = Nrej Histograms['Next'] = Next Rw = min(100.,np.sqrt(np.sum(M**2)/SumwYo)*100.) if dlg: if hasattr(dlg,'SetHistogram'): dlg.SetHistogram(-1,'overall') GoOn = dlg.Update(int(Rw),newmsg='%s%8.3f%s'%('All data Rw =',Rw,'%')) if type(GoOn) is tuple: if not GoOn[0]: parmDict['saved values'] = values raise G2obj.G2RefineCancel('Cancel pressed') elif not GoOn: parmDict['saved values'] = values raise G2obj.G2RefineCancel('Cancel pressed') #dlg.Raise() pDict,pVals,pWt,pWsum,pWnum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist) pSum = 0 if len(pVals): pSum = np.sum(pWt*pVals**2) if len(pVals) and dlg: for name in pWsum: if pWsum[name]: print (' Penalty function for %5d %8ss = %12.5g'%(pWnum[name],name,pWsum[name])) print ('Total restraint contribution to Chi**2: %12.5g on %d terms'%(pSum,len(pVals))) if hasattr(dlg,'SetHistogram'): dlg.SetHistogram(-2,'Restraints') Nobs += len(pVals) M = np.concatenate((M,np.sqrt(pWt)*pVals)) GoOn = dlg.Update(int(100.*pSum/np.sum(M**2)),newmsg='Restraints') Histograms['RestraintSum'] = pSum Histograms['RestraintTerms'] = len(pVals) return M
[docs] def calcMassFracs(varyList,covMatrix,Phases,hist,hId): '''Compute mass fractions and their uncertainties for all phases in a histogram. Computed using the covariance matrix, along with the derivatives for the mass fraction equations. :param list varyList: list of varied parameters :param np.array covMatrix: covariance matrix, order of rows and columns must match varyList :param dict Phases: data structure (from tree or .gpx) with all phase information :param str hist: name of selected histogram :param int hId: number of current histogram :returns: valDict,sigDict which contain the mass fraction values and sigmas, keyed by "ph:h:WgtFrac" ''' # Compute mass normalizer & assemble list of refined PF terms wtSum = 0.0 mass = {} phFr = {} used = {} for phase in Phases: if Phases[phase]['General']['Type'] == 'magnetic': continue if Phases[phase]['General']['doPawley']: continue if hist not in Phases[phase]['Histograms']: continue if not Phases[phase]['Histograms'][hist]['Use']: continue pId = Phases[phase]['pId'] mass[pId] = Phases[phase]['General']['Mass'] phFr[pId] = Phases[phase]['Histograms'][hist]['Scale'][0] wtSum += mass[pId]*phFr[pId] # Is this PF refined? var = "{}:{}:Scale".format(pId,hId) if var in varyList: # yes, save it used[varyList.index(var)] = pId elif var in G2mv.GetDependentVars(): for v,m in zip(*G2mv.getInvConstraintEq(var,varyList)): if v not in varyList: continue i = varyList.index(v) if i not in used: used[i] = {} used[i][pId] = m valDict = {} sigDict = {} for phasej in Phases: if Phases[phasej]['General']['Type'] == 'magnetic': continue if Phases[phase]['General']['doPawley']: continue if hist not in Phases[phasej]['Histograms']: continue if not Phases[phasej]['Histograms'][hist]['Use']: continue if wtSum < 1.0: continue #no atoms; probable LeBail pId_j = Phases[phasej]['pId'] var = "{}:{}:WgtFrac".format(pId_j,hId) valDict[var] = mass[pId_j] * phFr[pId_j] / wtSum Avec = np.zeros(len(varyList)) for i in used: if type(used[i]) is dict: for pId_i in used[i]: if pId_i == pId_j: deriv = (mass[pId_j]/wtSum) - (mass[pId_j]**2 * phFr[pId_j]/wtSum**2) else: deriv = -mass[pId_j]* mass[pId_i] * phFr[pId_j]/wtSum**2 Avec[i] += used[i][pId_i] * deriv # dot product else: pId_i = used[i] if pId_i == pId_j: Avec[i] = (mass[pId_j]/wtSum) - (mass[pId_j]**2 * phFr[pId_j]/wtSum**2) else: Avec[i] = -mass[pId_j]* mass[pId_i] * phFr[pId_j]/wtSum**2 sigDict[var] = np.sqrt(np.inner(Avec.T,np.inner(covMatrix,Avec))) if len(valDict) == 1: return {},{} # don't add where only a single phase is present return valDict,sigDict