32
32
device = "cpu"
33
33
if torch .cuda .is_available ():
34
34
device = torch .device ("cuda" )
35
+ device = "cpu"
35
36
except Exception :
36
37
pass
37
38
amu_gm = 1.66054e-24
@@ -638,11 +639,14 @@ def from_xyz(self, filename="dsgdb9nsd_057387.xyz", box_size=40):
638
639
return atoms
639
640
640
641
@classmethod
641
- def from_poscar (self , filename = "POSCAR" ):
642
+ def from_poscar (self , filename = "POSCAR" , string = "" ):
642
643
"""Read POSCAR/CONTCAR file from to make Atoms object."""
643
644
from jarvis .io .vasp .inputs import Poscar
644
645
645
- return Poscar .from_file (filename ).atoms
646
+ if string != "" :
647
+ return Poscar .from_string (string ).atoms
648
+ else :
649
+ return Poscar .from_file (filename ).atoms
646
650
647
651
@property
648
652
def check_polar (self ):
@@ -1376,7 +1380,7 @@ def get_mineral_prototype_name(
1376
1380
# name+="_"+str(com_positions)
1377
1381
return name
1378
1382
1379
- def get_basic_polyhdra_motif (self , thresh = 0.5 , cutoff = 4 ):
1383
+ def get_basic_polyhdra_motif (self , thresh = 0.5 , cutoff = 4 , extra_cutoff = 4 ):
1380
1384
"""Get chemical environment around atoms."""
1381
1385
1382
1386
def classify_coordination_environment (num_neighbors ):
@@ -1404,22 +1408,22 @@ def classify_coordination_environment(num_neighbors):
1404
1408
return "Other"
1405
1409
1406
1410
nbr_env = []
1407
- for ii , i in enumerate (self .get_all_neighbors (r = cutoff + 2 )):
1408
- counter = Counter ([round (j [2 ], 3 ) for j in i ])
1409
- counter = dict (
1410
- sorted (
1411
- counter .items (), key = lambda item : item [0 ], reverse = False
1412
- )
1413
- )
1414
- asc_bonds = list (counter .keys ())
1415
- # print('asc_bonds',asc_bonds)
1416
- min_bond = asc_bonds [0 ] # min(list(counter.keys()))
1417
- num_neighbors = counter [min_bond ]
1418
- # Add second neighbors if too close
1419
- if min_bond + thresh >= asc_bonds [1 ]:
1420
- num_neighbors += counter [asc_bonds [1 ]]
1411
+ for ii , i in enumerate (
1412
+ self .get_all_neighbors (r = cutoff + extra_cutoff )
1413
+ ):
1414
+ sorted_i = sorted (i , key = lambda x : x [2 ])
1415
+ num_neighbors = 0
1416
+ min_bond = sorted_i [0 ][2 ]
1417
+ info = []
1418
+ for j in sorted_i :
1419
+ if j [2 ] <= min_bond + thresh :
1420
+ info .append (self .elements [j [1 ]])
1421
+ num_neighbors = len (info )
1422
+ info_els = Counter (info )
1423
+ tmp = Composition .from_dict (info_els ).formula
1421
1424
env = classify_coordination_environment (num_neighbors )
1422
- rep = self .elements [ii ] + "X" + str (num_neighbors )
1425
+ rep = self .elements [ii ] + tmp
1426
+ # rep = self.elements[ii] + "X" + str(num_neighbors)
1423
1427
info = [self .elements [ii ], env , num_neighbors , rep ]
1424
1428
if info not in nbr_env and env != "Other" :
1425
1429
nbr_env .append (info )
@@ -1514,6 +1518,8 @@ def describe(
1514
1518
model = "" ,
1515
1519
polyhedra_thresh = 0.5 ,
1516
1520
add_crystal_info = False ,
1521
+ add_wyck_descs = False ,
1522
+ add_same_el_bonds = False ,
1517
1523
):
1518
1524
"""Describe for NLP applications."""
1519
1525
from jarvis .analysis .diffraction .xrd import XRD
@@ -1583,6 +1589,18 @@ def describe(
1583
1589
}
1584
1590
wyck_descs = ""
1585
1591
if include_spg :
1592
+ polar_point_groups = [
1593
+ "1" ,
1594
+ "2" ,
1595
+ "3" ,
1596
+ "4" ,
1597
+ "6" ,
1598
+ "m" ,
1599
+ "mm2" ,
1600
+ "3m" ,
1601
+ "4mm" ,
1602
+ "6mm" ,
1603
+ ]
1586
1604
from jarvis .analysis .structure .spacegroup import (
1587
1605
get_wyckoff_position_operators ,
1588
1606
)
@@ -1593,13 +1611,17 @@ def describe(
1593
1611
struct_info ["spg_symbol" ] = spg .space_group_symbol
1594
1612
struct_info ["crystal_system" ] = spg .crystal_system
1595
1613
struct_info ["point_group" ] = spg .point_group_symbol
1614
+ if spg .point_group_symbol in polar_point_groups :
1615
+ struct_info ["polar" ] = True
1616
+ else :
1617
+ struct_info ["polar" ] = False
1596
1618
struct_info ["wyckoff" ] = ", " .join (
1597
1619
list (set (spg ._dataset ["wyckoffs" ]))
1598
1620
)
1599
1621
struct_info ["natoms_primitive" ] = spg .primitive_atoms .num_atoms
1600
- struct_info [
1601
- "natoms_conventional"
1602
- ] = spg . conventional_standard_structure . num_atoms
1622
+ struct_info ["natoms_conventional" ] = (
1623
+ spg . conventional_standard_structure . num_atoms
1624
+ )
1603
1625
p = inflect .engine ()
1604
1626
# Multiplicity
1605
1627
wyck_mult = get_wyckoff_position_operators (
@@ -1670,6 +1692,9 @@ def describe(
1670
1692
1671
1693
p = struct_info ["bond_distances" ]
1672
1694
for ii , (kk , vv ) in enumerate (p .items ()):
1695
+ elements_in_bond = kk .split ("-" )
1696
+ # if add_same_el_bonds and elements_in_bond[0]!=elements_in_bond[1]:
1697
+ # print('kk,vv',kk,vv)
1673
1698
if ii == len (p ) - 1 :
1674
1699
punc = " Å."
1675
1700
else :
@@ -1701,7 +1726,14 @@ def describe(
1701
1726
+ str (max (bnd ))
1702
1727
+ " Å."
1703
1728
)
1704
- bond_desc += txt
1729
+ if elements_in_bond [0 ] != elements_in_bond [1 ]:
1730
+ bond_desc += txt
1731
+ if (
1732
+ add_same_el_bonds
1733
+ and elements_in_bond [0 ] == elements_in_bond [1 ]
1734
+ ):
1735
+
1736
+ bond_desc += txt
1705
1737
line2 = (
1706
1738
chem_info ["atomic_formula" ]
1707
1739
+ " crystallizes in the "
@@ -1739,7 +1771,7 @@ def describe(
1739
1771
cutoff = cutoff , thresh = polyhedra_thresh
1740
1772
)
1741
1773
info ["motifs" ] = motifs
1742
- motif_desc = ""
1774
+ motif_desc = " "
1743
1775
for ii , i in enumerate (motifs ):
1744
1776
if ii != len (motifs ) - 1 :
1745
1777
motif_desc += (
@@ -1770,7 +1802,7 @@ def describe(
1770
1802
+ " "
1771
1803
+ str (struct_info ["spg_symbol" ])
1772
1804
+ " spacegroup."
1773
- + wyck_descs
1805
+ # + wyck_descs
1774
1806
+ bond_desc
1775
1807
+ motif_desc
1776
1808
)
@@ -1782,7 +1814,7 @@ def describe(
1782
1814
+ " "
1783
1815
+ str (struct_info ["spg_symbol" ])
1784
1816
+ " spacegroup."
1785
- + wyck_descs
1817
+ # + wyck_descs
1786
1818
+ bond_desc
1787
1819
+ motif_desc
1788
1820
)
@@ -1810,6 +1842,8 @@ def describe(
1810
1842
line3 = line3 .replace (" " , " " )
1811
1843
if add_crystal_info :
1812
1844
line3 += crystal_str
1845
+ if add_wyck_descs :
1846
+ line3 += wyck_descs
1813
1847
info ["crystal_str" ] = crystal_str
1814
1848
info ["desc_1" ] = line1
1815
1849
info ["desc_2" ] = line2
@@ -2477,18 +2511,18 @@ def to_optimade(
2477
2511
info_at ["cartesian_site_positions" ] = atoms .cart_coords [order ].tolist ()
2478
2512
info_at ["nperiodic_dimensions" ] = 3
2479
2513
# info_at["species"] = atoms.elements
2480
- info_at [
2481
- "species"
2482
- ] = self . get_optimade_species ( ) # dict(atoms.composition.to_dict())
2514
+ info_at ["species" ] = (
2515
+ self . get_optimade_species ()
2516
+ ) # dict(atoms.composition.to_dict())
2483
2517
info_at ["elements_ratios" ] = list (
2484
2518
atoms .composition .atomic_fraction .values ()
2485
2519
)
2486
2520
info_at ["structure_features" ] = []
2487
2521
info_at ["last_modified" ] = str (now )
2488
2522
# info_at["more_data_available"] = True
2489
- info_at [
2490
- "chemical_formula_descriptive"
2491
- ] = atoms . composition . reduced_formula
2523
+ info_at ["chemical_formula_descriptive" ] = (
2524
+ atoms . composition . reduced_formula
2525
+ )
2492
2526
info_at ["dimension_types" ] = [1 , 1 , 1 ]
2493
2527
info ["attributes" ] = info_at
2494
2528
return info
@@ -2586,6 +2620,23 @@ def build_xanes_poscar(
2586
2620
return atoms
2587
2621
2588
2622
2623
+ if __name__ == "__main__" :
2624
+ pos = """MgB2
2625
+ 1.0
2626
+ 1.5367454354207384 -2.661721209337192 0.0
2627
+ 1.5367454354207384 2.661721209337192 0.0
2628
+ 0.0 0.0 3.5146401326518166
2629
+ Mg B
2630
+ 1 2
2631
+ Cartesian
2632
+ 0.0 0.0 0.0
2633
+ 1.53675 -0.8872417744799828 1.75732
2634
+ 1.53675 0.8872417744799828 1.75732
2635
+ """
2636
+ atoms = Atoms .from_poscar (string = pos )
2637
+ import pprint
2638
+
2639
+ pprint .pprint (atoms .describe ())
2589
2640
# ['Mn ', 'Mn ', 'Ru ', 'U ']
2590
2641
#
2591
2642
# def clear_elements(atoms=None):
0 commit comments