@@ -629,26 +629,35 @@ def _single_adsorption(
629
629
# 自动处理三种惯性矩方向
630
630
slabs_list = []
631
631
for inertia_mode in range (1 , 4 ): # 遍历第一、第二、第三惯性矩
632
+ atoms_copy = atoms .copy () # ✅ 每次都从原始结构复制
633
+ base_position = [0.0 , 0.0 , 0.0 ]
632
634
adsorption_vector = principal_axes [:, inertia_mode - 1 ]
633
- atoms .rotate (adsorption_vector , [0 , 0 , 1 ])
635
+ atoms_copy .rotate (adsorption_vector , [0 , 0 , 1 ])
634
636
635
637
if enable_rotate_xoy and rotation_mode == 'vnn' and rotation_args != {}:
636
- principle_axe = utils .solve_principle_axe_pca (atoms .get_positions ())
638
+ principle_axe = utils .solve_principle_axe_pca (atoms_copy .get_positions ())
637
639
if abs (rotation_args ['vec_to_neigh_imgsite' ][0 ]) < 1e-8 :
638
640
target_vec = [1 , 0 , 0 ]
639
641
elif abs (rotation_args ['vec_to_neigh_imgsite' ][1 ]) < 1e-8 :
640
642
target_vec = [0 , 1 , 0 ]
641
643
else :
642
644
target_vec = [- 1 / rotation_args ['vec_to_neigh_imgsite' ][0 ],
643
645
1 / rotation_args ['vec_to_neigh_imgsite' ][1 ], 0 ]
644
- atoms .rotate ([principle_axe [0 ], principle_axe [1 ], 0 ], target_vec )
646
+ atoms_copy .rotate ([principle_axe [0 ], principle_axe [1 ], 0 ], target_vec )
647
+ # =============== ✅ 关键部分:设置 Z 高度 ===============
648
+ z_coordinates = atoms_copy .get_positions ()[:, 2 ]
649
+ min_z = np .min (z_coordinates )
645
650
646
- # 【关键改动】确保每次都重新计算 `base_position[2]`
647
- z_coordinates = atoms .get_positions ()[:, 2 ]
648
- min_z = np .min (z_coordinates ) # 得到分子 z 轴最小值
649
- final_positions = slab .get_positions () # slab 坐标
650
- max_z = np .max (final_positions [:, 2 ]) # 获取 slab z 轴最大值
651
- base_position [2 ] = round (0 - min_z + 2.5 + max_z , 1 )
651
+ final_positions = slab .get_positions ()
652
+ max_z = np .max (final_positions [:, 2 ])
653
+
654
+
655
+ if abs (site_coord [2 ]) < 1e-6 : # 如果为 0 或非常接近 0
656
+ effective_distance = 2.5
657
+ else :
658
+ effective_distance = site_coord [2 ]
659
+
660
+ base_position [2 ] = round (max_z - min_z + effective_distance , 2 )
652
661
653
662
# xzq如果输入的 xy 为 [0, 0],则将分子放在 slab 的 xy 中心
654
663
if site_coord [0 ] == 0 and site_coord [1 ] == 0 :
@@ -660,15 +669,15 @@ def _single_adsorption(
660
669
base_position [0 ] = round (site_coord [0 ], 1 )
661
670
base_position [1 ] = round (site_coord [1 ], 1 )
662
671
663
- atoms .translate (base_position ) # 确保所有构型都以正确的 z 轴间距平移
672
+ atoms_copy .translate (base_position ) # 确保所有构型都以正确的 z 轴间距平移
664
673
665
674
# 将分子平移到指定的 site_coord 位置
666
- vec_tmp = site_coord - atoms .get_positions ()[bond ] # 计算平移量
667
- atoms .translate ([vec_tmp [0 ], vec_tmp [1 ], 0 ]) # 只平移 x-y,不改变 z
675
+ vec_tmp = site_coord - atoms_copy .get_positions ()[bond ] # 计算平移量
676
+ atoms_copy .translate ([vec_tmp [0 ], vec_tmp [1 ], 0 ]) # 只平移 x-y,不改变 z
668
677
669
678
670
679
slab_with_adsorbate = slab .copy ()
671
- slab_with_adsorbate += atoms
680
+ slab_with_adsorbate += atoms_copy
672
681
slabs_list .append (slab_with_adsorbate )
673
682
674
683
return slabs_list # 返回三种吸附构型的列表
@@ -727,11 +736,14 @@ def _single_adsorption(
727
736
n = len (slab )
728
737
slabs_list = []
729
738
score_configurations = [] # 各个吸附构型(slab)的“分数”
730
- for ia ,a in enumerate (atoms_list ):
739
+ for ia , a_orig in enumerate (atoms_list ):
731
740
slabs_list .append (copy .deepcopy (slab ))
741
+ a = copy .deepcopy (a_orig ) # 确保每次处理原始未改动的 adsorbate
732
742
dealt_positions = a .get_positions ()
733
743
min_z = np .min (dealt_positions [:,2 ]) #得到分子z轴最小值
734
- base_position [2 ] = round (max_z - min_z + 2.5 ,1 ) # 吸附物种最低原子处于slab以上?A,随后再尝试降低
744
+ # Step 1: Z 方向平移
745
+ z_translation = max_z - min_z + (2.5 if site_coord [2 ] == 0 else site_coord [2 ])
746
+ a .translate ([0 , 0 , z_translation ])
735
747
# 计算 slab 中心坐标
736
748
slab_positions = slab .get_positions ()
737
749
center_x , center_y = utils .center_slab (slab_positions )
0 commit comments