返回列表 发布新帖
查看: 360|回复: 1

[X射线类] 单晶衍射仪系列3-衍射过程仿真

118

帖子

310

积分

36

金币

初级会员

积分
310
发表于 2025-3-27 19:41:51 | 查看全部 |阅读模式
本帖最后由 casjxm 于 2025-3-27 19:56 编辑

单晶衍射仪主要部件包括X射线源,测角仪,探测器。X射线源一般是固定的,有时需要根据实际需求选择测角仪与探测器的合理配置,这时就需要对衍射过程进行仿真,输入测角仪,探测器以及样品的参数进行模拟测试,再看看测试数据是否满足需求。前面已经在相关帖子中说明了衍射原理以及晶体学的基本计算公式。


直接上代码(matlab):
1. 计算面间距
参考:https://www.matstr.com/forum.php?mod=viewthread&tid=564&extra=
https://www.matstr.com/forum.php?mod=viewthread&tid=383&extra=

function result=hkldist(hkl, cellpara)
%hkl: row vector
        h=hkl(1);
        k=hkl(2);
        l=hkl(3);
        a=cellpara(1);
        b=cellpara(2);
        c=cellpara(3);
        d=cellpara(4)/180*pi;
        e=cellpara(5)/180*pi;
        f=cellpara(6)/180*pi;
                v=a*b*c*sqrt(1-cos(d)*cos(d)-cos(e)*cos(e)-cos(f)*cos(f)+2*cos(d)*cos(e)*cos(f));
                s11=b*b*c*c*sin(d)*sin(d);
                s22=a*a*c*c*sin(e)*sin(e);
                s33=a*a*b*b*sin(f)*sin(f);
                s12=a*b*c*c*(cos(d)*cos(e)-cos(f));
                s23=a*a*b*c*(cos(e)*cos(f)-cos(d));
                s13=a*b*b*c*(cos(f)*cos(d)-cos(e));
                dist=v/sqrt(s11*h*h+s22*k*k+s33*l*l+2*s12*h*k+2*s23*k*l+2*s13*l*h);
result=dist;

2. 测角仪(晶体)旋转
参考:https://www.matstr.com/forum.php?mod=viewthread&tid=491&extra=

function result=rot_all_mat(w,k,p,ok)
res=rot_phi_mat(w,k,p,ok)*rot_kap_mat(w,k,ok)*rot_omega_mat(w);
result=res;


3. 直空间与倒空间单胞参数的转换
参考:https://www.matstr.com/forum.php?mod=viewthread&tid=382&extra=

function result=realcellpara2recicellpara(realcellpara)
%realcellpara[6]
a=realcellpara(1);
b=realcellpara(2);
c=realcellpara(3);
alpha=realcellpara(4)/180*pi;
beta=realcellpara(5)/180*pi;
gama=realcellpara(6)/180*pi;
v=a*b*c*sqrt(1-cos(alpha)^2-cos(beta)^2-cos(gama)^2+2*cos(alpha)*cos(beta)*cos(gama));
a2=b*c*sin(alpha)/v;
b2=a*c*sin(beta)/v;
c2=a*b*sin(gama)/v;
alpha2=asin(v/(a*b*c*sin(beta)*sin(gama)))/pi*180;
beta2=asin(v/(a*b*c*sin(alpha)*sin(gama)))/pi*180;
gama2=asin(v/(a*b*c*sin(alpha)*sin(beta)))/pi*180;
v2=1/v;
res=[a2 b2 c2 alpha2 beta2 gama2 v2];

result=res;


4. 晶体学坐标系到直角坐标系转换
参考: https://www.matstr.com/forum.php?mod=viewthread&tid=381&extra=
function result=abc2xyz_mat(cellpara)

%x: row [x1,x2,x3]
%cellpara:row
%res: row [res1,res2,res3]
a=cellpara(1);
b=cellpara(2);
c=cellpara(3);
alpha=cellpara(4)/180*pi;
beta=cellpara(5)/180*pi;
gama=cellpara(6)/180*pi;

m=[a 0 0;
b*cos(gama) b*sin(gama) 0;
c*cos(beta) c*(cos(alpha)-cos(gama)*cos(beta))/sin(gama) c*sqrt(sin(gama)^2+2*cos(alpha)*cos(beta)*cos(gama)-cos(beta)^2-cos(alpha)^2)/sin(gama)];
% res=x*m
result=m;

5. 衍射点在直角坐标系中的位置

function result=hkl2xyz(hkl,omega,kappa,phi,phiok,reci_orien_mat)
%hkl: row vector
%res: row vector
%reci_orien_mat=[da*/dx db*/dx dc*/dx; da*/dy db*/dy dc*/dy;da*/dz db*/dz dc*/dz;]
rotmat=rot_all_mat(omega,kappa,phi,phiok);
res=hkl*reci_orien_mat'*rotmat';
result=res;

6. 衍射点直角坐标对应的球坐标角度
参考:https://blog.csdn.net/qq_35097289/article/details/94003524

function result=xyz2phisita(xyz)
r=norm(xyz);
phi=acos(xyz(3)/r);
sita=acos(xyz(1)/r/sin(phi));
res=[phi/pi*180,sita/pi*180];
result=res;

7. 生成单张衍射照片中的hkl

function result=creatframehkl(reci_orien_mat,peakposierr,lamda,resol,cellpara,omega,kappa,phi,phiok,phiSitaRange)
%reci_orien_mat=[da*/dx db*/dx dc*/dx; da*/dy db*/dy dc*/dy;da*/dz db*/dz dc*/dz;]
hkl=creatspherehkl(resol,cellpara);
rotmat=rot_all_mat(omega/180*pi,kappa/180*pi,phi/180*pi,phiok/180*pi);
n=size(hkl);
xyz=hkl*reci_orien_mat'*rotmat';

r2=(1/lamda)^2;
ewalda=1/lamda;
xyz2=xyz(:,1)-ewalda;
xyz3=[xyz2,xyz(:,2:3)];
xyz4=xyz3.^2;
xyz5=abs(sum(xyz4')'-r2);

xyz6=[];
hkl2=[];
for i=1:n(1)
        if(xyz5(i)<peakposierr)
                xyz6=[xyz6;xyz(i,:)];
                hkl2=[hkl2;hkl(i,:)];
        end
end

m=size(hkl2);
hkl3=[];
for i=1:m(1)
        phiSita=xyz2phisita(xyz6(i,:));
        if((phiSita(1)>phiSitaRange(1))&&(phiSita(1)<phiSitaRange(2))&&(phiSita(2)>phiSitaRange(3))&&(phiSita(2)<phiSitaRange(4)))
        hkl3=[hkl3;hkl2(i,:)];
        end
end        

result=hkl3;


8. 生成全ewald球衍射点

function result=creatspherehkl(resol,cellpara)
        res=[];
        for i=1:100
                for j=1:100
                        for k=1:100
                        hkl=[i,j,k];
                        if(hkldist(hkl,cellpara)>resol)
                                res=[res;hkl];
                        end
                        end
                end                        
        end

result=res;


9. 倒空间与直空间取向矩阵的变换
参考:https://www.matstr.com/forum.php?mod=viewthread&tid=563&extra=

function result=reciorienmat2realorienmat(reci_orien_mat)
%reci_orien_mat=[da*/dx db*/dx dc*/dx; da*/dy db*/dy dc*/dy;da*/dz db*/dz dc*/dz;]
recicellpara=orienmat2cellpara(reci_orien_mat);
va2=reci_orien_mat(:,1)';
vb2=reci_orien_mat(:,2)';
vc2=reci_orien_mat(:,3)';
va=cross(vb2,vc2)/recicellpara(7);
vb=cross(vc2,va2)/recicellpara(7);
vc=cross(va2,vb2)/recicellpara(7);
real_orien_mat=[va' vb' vc'];

result=real_orien_mat;



10. 取向矩阵与单胞参数的转换

function result=orienmat2cellpara(orien_mat)
%reci_orien_mat=[da*/dx db*/dx dc*/dx; da*/dy db*/dy dc*/dy;da*/dz db*/dz dc*/dz;]
%real_orien_mat=[da/dx db/dx dc/dx; da/dy db/dy dc/dy;da/dz db/dz dc/dz;]

va=orien_mat(:,1)';
vb=orien_mat(:,2)';
vc=orien_mat(:,3)';
a=norm(va);
b=norm(vb);
c=norm(vc);
alpha=acos(dot(vb,vc)/b/c)/pi*180;
beta=acos(dot(vc,va)/c/a)/pi*180;
gama=acos(dot(va,vb)/a/b)/pi*180;
v=a*b*c*sqrt(1-cos(alpha/180*pi)^2-cos(beta/180*pi)^2-cos(gama/180*pi)^2+2*cos(alpha/180*pi)*cos(beta/180*pi)*cos(gama/180*pi));

res=[a b c alpha beta gama v];
result=res;


11. 探测器测试范围


function result=detectorrange(width,height,sita2,distance,centery,centerz)
s_phi1=90-atan((height/2+centerz)/distance)/pi*180;
s_phi2=90+atan((height/2-centerz)/distance)/pi*180;
s_sita1=180-atan((width/2+centery)/distance)/pi*180-sita2;
s_sita2=180+atan((width/2-centery)/distance)/pi*180-sita2;
res=[s_phi1,s_phi2,s_sita1,s_sita2];
result=res;

12. omega扫描测试
function result=scan_omega(reci_orien_mat,peakposierr,lamda,resol,cellpara,stepangle,anglerange,phiok)
%anglerange=omegamin,omegamax,kappa,phi

%Eiger4M: 155mmX163mm
%pilatus2M: 254mmX289mm(HxV)
width=254;
height=289;
sita2=0;
distance=70;
centery=0;
centerz=0;

phiSitaRange=detectorrange(width,height,sita2,distance,centery,centerz);
m=size(anglerange);
nrun=m(1);
m=(anglerange(:,2)-anglerange(:,1))/stepangle;
nframe=floor(m)+1;
hkl=[];
multiple=[];
for i=1:nrun
        runhkl=[];
        for j=1:nframe(i)
                omega=anglerange(i,1)+(j-1)*stepangle;
                kappa=anglerange(i,3);
                phi=anglerange(i,4);
                framehkl=creatframehkl(reci_orien_mat,peakposierr,lamda,resol,cellpara,omega,kappa,phi,phiok,phiSitaRange);
                n=size(framehkl);
                if(n(1)>=1)
                        plot3(framehkl(:,1),framehkl(:,2),framehkl(:,3),'b*');
                end
                pause(2);
                runhkl=[runhkl;framehkl];
        end
        [uniqueRows, ~, rowIndices] = unique(runhkl, 'rows');
        rowCounts = accumarray(rowIndices, 1);
        hkl=[hkl;uniqueRows];
        multiple=[multiple;rowCounts];
                        n=size(hkl);
                if(n(1)>=1)
                         plot3(hkl(:,1),hkl(:,2),hkl(:,3),'r*');
                 end
                 pause(2);
        
end
        
        [uniqueRows, ~, rowIndices] = unique(hkl, 'rows');
        rowCounts = accumarray(rowIndices, 1);
        m=size(hkl);
        n=size(uniqueRows);
        for i=1:n(1)
                for j=1:m(1)
                        if(rowIndices(j)==i)
                                rowCounts(i)=rowCounts(i)+multiple(j)-1;
                        end
                end
        end

        hklm3=[];
        for i=1:n(1)
                if(rowCounts(i)>=3)
                        hklm3=[hklm3;uniqueRows(i)];
                end
        end
        n3=size(hklm3);
        
        spherehkl=creatspherehkl(resol,cellpara);
        p=size(spherehkl);
        complete=n(1)/p(1);
        complete3=n3(1)/p(1);
res=[complete,complete3];

result=res;


13. 初始化并进行测试
function result=initiallzation()
realcellpara=[6 7 8 90 106.5 90 1000];
stepangle=0.5;
%anglerange=omegamin,omegamax,kappa,phi
anglerange=[20 50 45 60;30 60 45 60;70 90 45 80];
phiok=45;
resol=0.83;
lamda=0.71073;
peakposierr=3;
recicellpara=realcellpara2recicellpara(realcellpara);
%reci_orien_mat=[da*/dx db*/dx dc*/dx; da*/dy db*/dy dc*/dy;da*/dz db*/dz dc*/dz;]
%real_orien_mat=[da/dx db/dx dc/dx; da/dy db/dy dc/dy;da/dz db/dz dc/dz;]
abctoxyzmat=abc2xyz_mat(realcellpara);
real_orien_mat=abctoxyzmat';
reci_orien_mat=reciorienmat2realorienmat(real_orien_mat);

complete=scan_omega(reci_orien_mat,peakposierr,lamda,resol,realcellpara,stepangle,anglerange,phiok)
result=complete;

%%%%%%%%%%%%%%%%%%%%%%%%
测试过程,在matlab中运行initiallzation:
complete =
    0.8655    0.8480






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

93

帖子

227

积分

115

金币

版主

积分
227
QQ
发表于 2025-4-19 15:47:16 | 查看全部
有意思
您需要登录后才可以回帖 登录 | 注册

本版积分规则

  • 微信小程序
  • 公众号
  • 微信客服

关于我们|Archiver|APP客户端|小黑屋|物质结构社区 ( 闽ICP备2024081439号-1 )

GMT+8, 2025-5-29 05:09 , Processed in 0.016680 second(s), 7 queries , Redis On.

Powered by Discuz! X5.0

© 2001-2025 Discuz! Team.

在本版发帖
科研需求联系客服
添加微信客服
返回顶部
快速回复 返回顶部 返回列表