surface-construct 0.12.3__tar.gz → 0.12.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {surface_construct-0.12.3/surface_construct.egg-info → surface_construct-0.12.5}/PKG-INFO +1 -1
  2. {surface_construct-0.12.3 → surface_construct-0.12.5}/setup.py +1 -1
  3. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/sg_sampler.py +8 -0
  4. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/structures/adsorbate.py +5 -4
  5. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/structures/surface_grid.py +13 -6
  6. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/tasks/__init__.py +2 -1
  7. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/tasks/sitesampling.py +3 -5
  8. surface_construct-0.12.5/surface_construct/tasks/vipsitetask.py +77 -0
  9. {surface_construct-0.12.3 → surface_construct-0.12.5/surface_construct.egg-info}/PKG-INFO +1 -1
  10. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct.egg-info/SOURCES.txt +1 -0
  11. {surface_construct-0.12.3 → surface_construct-0.12.5}/tests/test_task.py +66 -4
  12. {surface_construct-0.12.3 → surface_construct-0.12.5}/LICENSE +0 -0
  13. {surface_construct-0.12.3 → surface_construct-0.12.5}/README.md +0 -0
  14. {surface_construct-0.12.3 → surface_construct-0.12.5}/setup.cfg +0 -0
  15. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/__init__.py +0 -0
  16. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/db.py +0 -0
  17. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/default_parameter.py +0 -0
  18. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/structures/__init__.py +0 -0
  19. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/structures/combiner.py +0 -0
  20. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/structures/pymsym_test.py +0 -0
  21. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/structures/surface.py +0 -0
  22. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/tasks/afm.py +0 -0
  23. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/tasks/taskbase.py +0 -0
  24. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/tasks/terminations.py +0 -0
  25. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/utils/__init__.py +0 -0
  26. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/utils/atoms.py +0 -0
  27. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/utils/geometry.py +0 -0
  28. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/utils/pymsym_wrapper.py +0 -0
  29. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/utils/spglib_wrapper.py +0 -0
  30. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct/utils/weight_functions.py +0 -0
  31. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct.egg-info/dependency_links.txt +0 -0
  32. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct.egg-info/requires.txt +0 -0
  33. {surface_construct-0.12.3 → surface_construct-0.12.5}/surface_construct.egg-info/top_level.txt +0 -0
  34. {surface_construct-0.12.3 → surface_construct-0.12.5}/tests/test_adsorbate.py +0 -0
  35. {surface_construct-0.12.3 → surface_construct-0.12.5}/tests/test_combiner.py +0 -0
  36. {surface_construct-0.12.3 → surface_construct-0.12.5}/tests/test_sampling1.py +0 -0
  37. {surface_construct-0.12.3 → surface_construct-0.12.5}/tests/test_sampling2.py +0 -0
  38. {surface_construct-0.12.3 → surface_construct-0.12.5}/tests/test_simple_surface.py +0 -0
  39. {surface_construct-0.12.3 → surface_construct-0.12.5}/tests/test_surface_grid.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: surface_construct
3
- Version: 0.12.3
3
+ Version: 0.12.5
4
4
  Summary: Surface construction and surface reaction sampling tools.
5
5
  Home-page: https://gitee.com/pjren/surface_construct/
6
6
  Author: ren
@@ -15,7 +15,7 @@ install_requires = [
15
15
 
16
16
  setup(
17
17
  name='surface_construct',
18
- version='0.12.3',
18
+ version='0.12.5',
19
19
  packages=find_packages(),
20
20
  url='https://gitee.com/pjren/surface_construct/',
21
21
  license='GPL',
@@ -145,6 +145,14 @@ class RandomSGSampler(SGSamplerBase):
145
145
  else:
146
146
  self.seed = None
147
147
 
148
+ @property
149
+ def _population(self):
150
+ """
151
+ 排除已经采过的 index
152
+ :return:
153
+ """
154
+ return [i for i in range(self._pop_size) if i not in self.sg_obj.sample_idx]
155
+
148
156
  def _samples(self, size, **kwargs):
149
157
  idx = random.sample(self._population, size)
150
158
  return idx
@@ -139,9 +139,10 @@ class Adsorbate:
139
139
  for ids in self.dock_point_indices for i in ids])
140
140
  return self._rads
141
141
 
142
+ atoms = self.atoms.copy()
142
143
  if not self.is_regulated:
143
- self.regulate()
144
- positions = self.atoms.positions
144
+ atoms_regulate(atoms)
145
+ positions = atoms.positions
145
146
  dim_length = np.array([
146
147
  max(positions[:,0]) - min(positions[:,0]),
147
148
  max(positions[:,1]) - min(positions[:,1]),
@@ -150,8 +151,8 @@ class Adsorbate:
150
151
  shortest_dim = np.argmin(dim_length)
151
152
  idx0 =np.argmin(positions[:,shortest_dim])
152
153
  idx1 =np.argmax(positions[:,shortest_dim])
153
- num0 = self.atoms.numbers[idx0]
154
- num1 = self.atoms.numbers[idx1]
154
+ num0 = atoms.numbers[idx0]
155
+ num1 = atoms.numbers[idx1]
155
156
  self._rads = (dim_length[shortest_dim] + radii[num0] + radii[num1]) / 2
156
157
  return self._rads
157
158
 
@@ -899,6 +899,11 @@ class SurfaceGrid:
899
899
  self.sample_dct[idx]['calculated'] = True
900
900
 
901
901
  def fit(self, key='energy'):
902
+ if len(self.points) == len(self.calculated_sample):
903
+ self.grid_property[key] = [self.sample_dct[idx][key] for idx in range(len(self.points))]
904
+ self.grid_property_sigma[key] = [0.] * len(self.points)
905
+ return
906
+
902
907
  from sklearn.gaussian_process import GaussianProcessRegressor
903
908
  from sklearn.gaussian_process.kernels import RBF, ConstantKernel, WhiteKernel
904
909
  from sklearn.preprocessing import StandardScaler
@@ -909,12 +914,14 @@ class SurfaceGrid:
909
914
  scaler.fit(y)
910
915
  y_scaled = scaler.transform(y).T[0]
911
916
  # RBF Kernel
912
- length_scale_grid = 1.0 # 实空间的length scale, 1 angstrom
913
- length_scale_vector = length_scale_grid * self.vector_interval
914
- length_scale_bounds = (length_scale_vector/2.0, length_scale_vector*2.0)
915
- # length_scale_bounds = 'fixed'
916
- # length_scale = [length_scale_vector] * self._vector_dim # 向量空间的 length_scale, anisotropic
917
- length_scale = length_scale_vector # 向量空间的 length_scale, isotropic
917
+ try:
918
+ length_scale_grid = 1.0 # 实空间的length scale, 1 angstrom
919
+ length_scale_vector = length_scale_grid * self.vector_interval
920
+ length_scale_bounds = (length_scale_vector/2.0, length_scale_vector*2.0)
921
+ length_scale = length_scale_vector # 向量空间的 length_scale, isotropic
922
+ except IndexError:
923
+ length_scale = 1.0
924
+ length_scale_bounds = (1e-5, 1e5)
918
925
  rbf_kernel = RBF(length_scale=length_scale, length_scale_bounds=length_scale_bounds)
919
926
  # noise kernel
920
927
  noise_level_dict = {
@@ -12,4 +12,5 @@
12
12
  4. 分析和作图
13
13
  """
14
14
  from .sitesampling import SurfaceSiteSampleTask
15
- from .afm import AFMTask
15
+ from .afm import AFMTask
16
+ from .vipsitetask import VIPSiteTask
@@ -53,7 +53,6 @@ class SurfaceSiteSampleTask(TaskBase):
53
53
  self.sg_obj = combiner.sg_obj
54
54
  if self.sg_obj.points is None:
55
55
  self.sg_obj.initialize()
56
- self.to_pkl() # 保存当前状态
57
56
 
58
57
  if self.sampler is None:
59
58
  self.sampler = [{'surface':'KeyPointSGSampler'}] # 默认关键点采样
@@ -63,8 +62,6 @@ class SurfaceSiteSampleTask(TaskBase):
63
62
  self.grid_idx = None
64
63
  self.stime = datetime.datetime.now()
65
64
 
66
- self.print_task_info()
67
-
68
65
  def print_task_info(self):
69
66
  msg = [f"Starting task {self.__class__.__name__} at "
70
67
  f"{datetime.datetime.ctime(self.stime)}.\n",
@@ -192,8 +189,9 @@ class SurfaceSiteSampleTask(TaskBase):
192
189
  self.irun(grid_idx, fit=False)
193
190
  else:
194
191
  for i in range(size):
195
- grid_idx = sg_sampler_obj(self.sg_obj).samples(size=1)
196
- self.irun(grid_idx, fit=True)
192
+ grid_idx = sg_sampler_obj(self.sg_obj).samples(size=1)[0]
193
+ self.irun(grid_idx)
194
+ self.sg_obj.fit()
197
195
  elif type(sg_sampler) in (tuple, list):
198
196
  msg = f" Appending sampling with {size} points."
199
197
  self.log(msg+'\n')
@@ -0,0 +1,77 @@
1
+ import random
2
+
3
+ import ase.data
4
+ import numpy as np
5
+ from matplotlib import pyplot as plt
6
+ from matplotlib.patches import Circle
7
+
8
+ from .sitesampling import SurfaceSiteSampleTask
9
+
10
+ class VIPSiteTask(SurfaceSiteSampleTask):
11
+ def __init__(self, exclude=None, include=None, **kwargs):
12
+ super().__init__(**kwargs)
13
+
14
+ vip_id = self.sg_obj.vip_id
15
+ grid_site_type, site_type_dict = self.sg_obj.get_grid_site_type()
16
+ if exclude is None and include is None:
17
+ msg = [f"Either exclude or include must be specified"]
18
+ msg += [f"Possible site types are {len(site_type_dict)} in total:"]
19
+ msg += [f"{k}: {v}" for k,v in site_type_dict.items() if type(k) in (int,)]
20
+ raise ValueError('\n'.join(msg))
21
+ elif exclude is not None and include is not None:
22
+ raise ValueError("Can not specified exclude and include at the same time")
23
+ elif exclude is not None and include is None:
24
+ filtered = [i for i in vip_id if site_type_dict[grid_site_type[i]] not in exclude]
25
+ else:
26
+ filtered = [i for i in vip_id if site_type_dict[grid_site_type[i]] in include]
27
+
28
+ points = self.sg_obj.points[filtered]
29
+ vector = self.sg_obj.vector[filtered]
30
+ raw_vector = self.sg_obj._raw_vector[filtered]
31
+ self.sg_obj.points = points
32
+ self.sg_obj.vector = vector
33
+ self.sg_obj._raw_vector = raw_vector
34
+ self.sg_obj.vectorgen = None
35
+
36
+ sampler_size = 0
37
+ new_sampler = []
38
+ for isampler in self.sampler: # 不需要初始采样和key 点采样
39
+ if isampler['surface'] not in ('InitialSGSampler', 'KeyPointSGSampler'):
40
+ sampler_size += isampler.get('size', 0)
41
+ new_sampler.append(isampler)
42
+
43
+ # 如果 filter 之后的点小于等于 self.sampler['size'], 重新定义sampler
44
+ if sampler_size >= len(points):
45
+ self.sampler = [{
46
+ 'size': len(points), # 采样大小
47
+ 'surface': "RandomSGSampler", # 表面采样方法
48
+ }]
49
+ else:
50
+ self.sampler = new_sampler
51
+
52
+ def plot(self, figname='vip_site_heatmap.png'):
53
+ fig, ax = plt.subplots()
54
+ ax.set_aspect('equal')
55
+ # 画晶格
56
+ fpts = [[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], [0, 0, 0]] # 得到max_z处表面的分数坐标
57
+ pts = self.sg_obj.atoms.cell.cartesian_positions(fpts)[:, :2] # 转为直角坐标,并取xy 两列
58
+ ax.plot(pts[:, 0], pts[:, 1], 'k-', linewidth=2)
59
+ # 画原子
60
+ cmap = plt.cm.jet
61
+ energies = self.sg_obj.grid_property['energy']
62
+ norm = plt.Normalize(vmin=min(energies), vmax=max(energies))
63
+ radius = 0.5
64
+ cell = self.sg_obj.atoms.cell
65
+ for point,e in zip(self.sg_obj.points,energies):
66
+ color = cmap(norm(e))
67
+ fx, fy = cell.scaled_positions(point)[:2]
68
+ px, py = cell.cartesian_positions([fx, fy, 0.])[:2] # 适用于非正交盒子,将其平移到 xy 平面
69
+ circle = Circle((px, py), radius, facecolor=color,edgecolor='k', linewidth=1, alpha=0.8)
70
+ ax.add_patch(circle)
71
+ # 添加 colorbar
72
+ sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
73
+ sm.set_array([]) # 需要调用 set_array 但不传数据
74
+ cbar = plt.colorbar(sm, ax=ax)
75
+ cbar.set_label('E/eV', fontsize=12)
76
+ plt.tight_layout()
77
+ fig.savefig(figname, bbox_inches='tight')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: surface_construct
3
- Version: 0.12.3
3
+ Version: 0.12.5
4
4
  Summary: Surface construction and surface reaction sampling tools.
5
5
  Home-page: https://gitee.com/pjren/surface_construct/
6
6
  Author: ren
@@ -21,6 +21,7 @@ surface_construct/tasks/afm.py
21
21
  surface_construct/tasks/sitesampling.py
22
22
  surface_construct/tasks/taskbase.py
23
23
  surface_construct/tasks/terminations.py
24
+ surface_construct/tasks/vipsitetask.py
24
25
  surface_construct/utils/__init__.py
25
26
  surface_construct/utils/atoms.py
26
27
  surface_construct/utils/geometry.py
@@ -11,7 +11,7 @@ from lasp_ase.lasp import Lasp
11
11
  from surface_construct import SurfaceGrid
12
12
  from surface_construct import AdsGridCombiner
13
13
  from surface_construct import Adsorbate
14
- from surface_construct.tasks import SurfaceSiteSampleTask, AFMTask
14
+ from surface_construct.tasks import SurfaceSiteSampleTask, AFMTask, VIPSiteTask
15
15
  from ase.optimize import LBFGS, BFGS
16
16
 
17
17
 
@@ -54,7 +54,8 @@ class TestTask:
54
54
  'weight': (0.1, 0.45, 0.45), # 表面采样方法的权重
55
55
  } # 第二步采样
56
56
  ]
57
- task_obj = SurfaceSiteSampleTask(combiner=ads_grid_comb, sampler=sampler, optimizer=BFGS)
57
+ task_obj = SurfaceSiteSampleTask(combiner=ads_grid_comb, sampler=sampler, optimizer=None)
58
+ task_obj.print_task_info()
58
59
  task_obj.run()
59
60
  print('Done')
60
61
 
@@ -81,7 +82,37 @@ class TestTask:
81
82
  'weight': (0.4, 0.3, 0.3), # 表面采样方法的权重
82
83
  } # 第二步采样
83
84
  ]
84
- task_obj = SurfaceSiteSampleTask(combiner=ads_grid_comb, sampler=sampler, optimizer=LBFGS)
85
+ task_obj = SurfaceSiteSampleTask(combiner=ads_grid_comb, sampler=sampler, optimizer=None)
86
+
87
+ task_obj.print_task_info()
88
+ task_obj.run()
89
+ print('Done')
90
+
91
+ def test_H2O_CuO_Cu(self):
92
+ """
93
+ Water on CuO/Cu surface
94
+ :return:
95
+ """
96
+ shutil.copyfile('../atoms_files/CuCHO_lasp.in', 'lasp.in')
97
+ shutil.copyfile('../atoms_files/CuCHO.pot', 'CuCHO.pot')
98
+ atoms = ase.io.read('../atoms_files/CuOx-Cu100-CONTCAR')
99
+ atoms.calc = Lasp()
100
+ ads_atoms = ase.Atoms('H2O',[[0.,0.,-1.],[0.,0.86,0.5],[0.,0.,0.]])
101
+ ads_obj = Adsorbate(ads_atoms,rtype='vdw_radii')
102
+ sg_obj = SurfaceGrid(atoms,rsub='vdw_radii',rads=ads_obj.rads)
103
+ ads_grid_comb = AdsGridCombiner(sg_obj, ads_obj)
104
+ sampler =[
105
+ {
106
+ 'surface': "KeyPointSGSampler", # 表面采样方法
107
+ }, # 第一步采样
108
+ {
109
+ 'size': 3, # 采样大小
110
+ 'surface': ("MaxDiversitySGSampler", "MinEnergySGSampler", "MaxSigmaSGSampler"), # 表面采样方法
111
+ 'weight': (0.4, 0.3, 0.3), # 表面采样方法的权重
112
+ } # 第二步采样
113
+ ]
114
+ task_obj = SurfaceSiteSampleTask(combiner=ads_grid_comb, sampler=sampler, optimizer=None)
115
+ task_obj.print_task_info()
85
116
  task_obj.run()
86
117
  print('Done')
87
118
 
@@ -145,5 +176,36 @@ class TestTask:
145
176
  } # 第二步采样
146
177
  ]
147
178
  task_obj = AFMTask(combiner=com_obj, sampler=sampler, optimizer=LBFGS, nz=10) # nz 定义 z方向采多少样
179
+ task_obj.print_task_info()
148
180
  task_obj.run()
149
- print('Done')
181
+ print('Done')
182
+
183
+ def test_vipsite(self):
184
+ """
185
+ Water on CuO/Cu surface, only O top site
186
+ :return:
187
+ """
188
+ shutil.copyfile('../atoms_files/CuCHO_lasp.in', 'lasp.in')
189
+ shutil.copyfile('../atoms_files/CuCHO.pot', 'CuCHO.pot')
190
+ atoms = ase.io.read('../atoms_files/CuOx-Cu100-CONTCAR')
191
+ atoms.calc = Lasp()
192
+ ads_atoms = ase.Atoms('H2O',[[0.,0.,-1.],[0.,0.86,0.5],[0.,0.,0.]])
193
+ ads_obj = Adsorbate(ads_atoms,rtype='vdw_radii')
194
+ sg_obj = SurfaceGrid(atoms,rads=ads_obj.rads)
195
+ ads_grid_comb = AdsGridCombiner(sg_obj, ads_obj)
196
+ sampler =[
197
+ {
198
+ 'size': 2, # 采样大小
199
+ 'surface': "RandomSGSampler", # 表面采样方法
200
+ },
201
+ {
202
+ 'size': 4, # 采样大小
203
+ 'surface': ("MaxDiversitySGSampler", "MinEnergySGSampler", "MaxSigmaSGSampler"), # 表面采样方法
204
+ 'weight': (0.4, 0.3, 0.3), # 表面采样方法的权重
205
+ } # 第二步采样
206
+ ]
207
+ task_obj = VIPSiteTask(combiner=ads_grid_comb, sampler=sampler, optimizer=None, include=[(8,)])
208
+ task_obj.print_task_info()
209
+ task_obj.run()
210
+ task_obj.plot()
211
+ print('Done')