Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize cython find_points_in _spheres #3015

Merged
merged 29 commits into from
May 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6419cd2
pip install cython to fix "clang: error: no such file or directory: '…
janosh Nov 9, 2022
e8bf8cc
Move VolumetricData to io/common and merge cube support
nwinner Sep 27, 2022
1c1a090
Module level import
nwinner Oct 19, 2022
691f7f9
Delete sphere
nwinner Nov 22, 2022
7d3bb1b
Accidentally deleted
nwinner Nov 23, 2022
db77172
Added methods to compute and compare DOS fingerprints (#2772)
naik-aakash Dec 24, 2022
3af2040
Cp2k 2.0 (#2672)
nwinner Jan 3, 2023
781ad5e
sprinkle nogils
lbluque May 16, 2023
85d3005
remove python for loop
lbluque May 16, 2023
23d5426
avoid python overhead in get_cube_neighbors
lbluque May 16, 2023
6cd975b
back to c malloc/free
lbluque May 17, 2023
8bb3bf2
pass pbc as int array
lbluque May 17, 2023
c8656ed
STY: use cdef context for improved readability
lbluque May 17, 2023
216bb17
MAINT: use int type for index/count vars
lbluque May 17, 2023
a60a1b0
STY: organize cdef's
lbluque May 17, 2023
d3b6954
MAINT: use array instead of pointers in signatures
lbluque May 17, 2023
43b4dd2
MAINT: pass array in get_cube_neighbors
lbluque May 17, 2023
e7b402d
MAINT: compute_offset not python interaction
lbluque May 18, 2023
6195f1e
MAINT: call realloc directly in loops and check failures afterwards
lbluque May 18, 2023
65c6024
MAINT: remove num_threads arg for now
lbluque May 18, 2023
7ceb6bf
MAINT: sprinkle const to arrays and memviews that should not be modified
lbluque May 18, 2023
5688173
MAINT: adapt structure/lattice to use updated find_points_in_spheres
lbluque May 18, 2023
ccdf88c
STY: clean up readability
lbluque May 23, 2023
6fe69e3
BUG: set cdivision=False to avoid bug #2226
lbluque May 24, 2023
784cd65
MAINT: declare missing ints
lbluque May 24, 2023
02bf53b
DEV: remove cython compiler options
lbluque May 25, 2023
3a6b448
DEV: add comment about cdivision
lbluque May 25, 2023
bbe428f
STY: fix lint issues
lbluque May 25, 2023
b680359
pre-commit auto-fixes
pre-commit-ci[bot] May 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions pymatgen/cli/pmg_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,95 @@ def setup_cp2k_data(cp2k_data_dirs: list[str]) -> None:
print("\n Start a new terminal to ensure that your environment variables are properly set.")


def setup_cp2k_data(cp2k_data_dirs: list[str]) -> None:
"""Setup CP2K basis and potential data directory"""
data_dir, target_dir = (os.path.abspath(dir) for dir in cp2k_data_dirs)
try:
os.mkdir(target_dir)
except OSError:
reply = input("Destination directory exists. Continue (y/n)?")
if reply != "y":
print("Exiting ...")
raise SystemExit(0)
print("Generating pymatgen resource directory for CP2K...")

import glob

from monty.json import jsanitize
from ruamel import yaml

from pymatgen.core import Element
from pymatgen.io.cp2k.inputs import GaussianTypeOrbitalBasisSet, GthPotential
from pymatgen.io.cp2k.utils import chunk

basis_files = glob.glob(os.path.join(data_dir, "*BASIS*"))
potential_files = glob.glob(os.path.join(data_dir, "*POTENTIAL*"))

settings: dict[str, dict] = {str(el): {"potentials": {}, "basis_sets": {}} for el in Element}

for potential_file in potential_files:
print(f"Processing... {potential_file}")
with open(potential_file) as file:
try:
chunks = chunk(file.read())
except IndexError:
continue
for chk in chunks:
try:
potential = GthPotential.from_string(chk)
potential.filename = os.path.basename(potential_file)
potential.version = None
settings[potential.element.symbol]["potentials"][potential.get_hash()] = jsanitize(
potential, strict=True
)
except ValueError:
# Chunk was readable, but the element is not pmg recognized
continue
except IndexError:
# Chunk was readable, but invalid. Mostly likely "N/A" for this potential
continue

for basis_file in basis_files:
print(f"Processing... {basis_file}")
with open(basis_file) as file:
try:
chunks = chunk(file.read())
except IndexError:
continue
for chk in chunks:
try:
basis = GaussianTypeOrbitalBasisSet.from_string(chk)
basis.filename = os.path.basename(basis_file)
settings[basis.element.symbol]["basis_sets"][basis.get_hash()] = jsanitize( # type: ignore
basis, strict=True
)
except ValueError:
# Chunk was readable, but the element is not pmg recognized
continue
except IndexError:
# Chunk was readable, but invalid. Mostly likely "N/A" for this potential
continue

print("Done processing cp2k data files")

for el in settings:
print(f"Writing {el} settings file")
with open(os.path.join(target_dir, el), "w") as file:
yaml.dump(settings.get(el), file, default_flow_style=False)

print(
"\n CP2K resource directory generated. It is recommended that you run:"
f"\n 'pmg config --add PMG_CP2K_DATA_DIR {os.path.abspath(target_dir)}' "
)
print(
"\n It is also recommended that you set the following (with example values):"
"\n 'pmg config --add PMG_DEFAULT_CP2K_FUNCTIONAL PBE' "
"\n 'pmg config --add PMG_DEFAULT_CP2K_BASIS_TYPE TZVP-MOLOPT' "
"\n 'pmg config --add PMG_DEFAULT_CP2K_AUX_BASIS_TYPE pFIT' "
)
print("\n Start a new terminal to ensure that your environment variables are properly set.")


def setup_potcars(potcar_dirs: list[str]):
"""Setup POTCAR directories."""
psp_dir, target_dir = (os.path.abspath(d) for d in potcar_dirs)
Expand Down
10 changes: 5 additions & 5 deletions pymatgen/core/lattice.py
Original file line number Diff line number Diff line change
Expand Up @@ -1482,16 +1482,16 @@ def get_points_in_sphere(
except ImportError:
return self.get_points_in_sphere_py(frac_points=frac_points, center=center, r=r, zip_results=zip_results)
else:
frac_points = np.ascontiguousarray(frac_points, dtype=np.float_)
frac_points = np.ascontiguousarray(frac_points, dtype=float)
lattice_matrix = np.ascontiguousarray(self.matrix, dtype=float)
cart_coords = np.ascontiguousarray(self.get_cartesian_coords(frac_points), dtype=float)
pbc = np.ascontiguousarray(self.pbc, dtype=int)
r = float(r)
lattice_matrix = np.array(self.matrix)
lattice_matrix = np.ascontiguousarray(lattice_matrix)
cart_coords = self.get_cartesian_coords(frac_points)
_, indices, images, distances = find_points_in_spheres(
all_coords=cart_coords,
center_coords=np.ascontiguousarray([center], dtype=float),
r=r,
pbc=np.array(self.pbc, dtype=int),
pbc=pbc,
lattice=lattice_matrix,
tol=1e-8,
)
Expand Down
3 changes: 2 additions & 1 deletion pymatgen/core/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -1380,12 +1380,13 @@ def get_neighbor_list(
site_coords = np.array([site.coords for site in sites], dtype=float)
cart_coords = np.ascontiguousarray(np.array(self.cart_coords), dtype=float)
lattice_matrix = np.ascontiguousarray(np.array(self.lattice.matrix), dtype=float)
pbc = np.ascontiguousarray(self.pbc, dtype=int)
r = float(r)
center_indices, points_indices, images, distances = find_points_in_spheres(
cart_coords,
site_coords,
r=r,
pbc=np.array(self.pbc, dtype=int),
pbc=pbc,
lattice=lattice_matrix,
tol=numerical_tol,
)
Expand Down
46 changes: 46 additions & 0 deletions pymatgen/electronic_structure/tests/test_dos.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,52 @@ def test_dos_fp_exceptions(self):
"projections unavailable in input DOS or there's a typo in type."
)

def test_get_dos_fp(self):
# normalize=True
dos_fp = self.dos.get_dos_fp(type="s", min_e=-10, max_e=0, n_bins=56, normalize=True)
bin_width = np.diff(dos_fp.energies)[0][0]
assert max(dos_fp.energies[0]) <= 0
assert min(dos_fp.energies[0]) >= -10
assert len(dos_fp.energies[0]) == 56
assert dos_fp.type == "s"
self.assertAlmostEqual(sum(dos_fp.densities * bin_width), 1, delta=0.001)
# normalize=False
dos_fp2 = self.dos.get_dos_fp(type="s", min_e=-10, max_e=0, n_bins=56, normalize=False)
bin_width2 = np.diff(dos_fp2.energies)[0][0]
self.assertAlmostEqual(sum(dos_fp2.densities * bin_width2), 7.279303571428509, delta=0.001)
self.assertAlmostEqual(dos_fp2.bin_width, bin_width2, delta=0.001)
# binning=False
dos_fp = self.dos.get_dos_fp(type="s", min_e=None, max_e=None, n_bins=56, normalize=True, binning=False)
assert dos_fp.n_bins == len(self.dos.energies)

def test_get_dos_fp_similarity(self):
dos_fp = self.dos.get_dos_fp(type="s", min_e=-10, max_e=0, n_bins=56, normalize=True)
dos_fp2 = self.dos.get_dos_fp(type="tdos", min_e=-10, max_e=0, n_bins=56, normalize=True)
similarity_index = self.dos.get_dos_fp_similarity(dos_fp, dos_fp2, col=1, tanimoto=True)
self.assertAlmostEqual(similarity_index, 0.3342481451042263, delta=0.0001)

dos_fp = self.dos.get_dos_fp(type="s", min_e=-10, max_e=0, n_bins=56, normalize=True)
dos_fp2 = self.dos.get_dos_fp(type="s", min_e=-10, max_e=0, n_bins=56, normalize=True)
similarity_index = self.dos.get_dos_fp_similarity(dos_fp, dos_fp2, col=1, tanimoto=True)
assert similarity_index == 1

def test_dos_fp_exceptions(self):
dos_fp = self.dos.get_dos_fp(type="s", min_e=-10, max_e=0, n_bins=56, normalize=True)
dos_fp2 = self.dos.get_dos_fp(type="tdos", min_e=-10, max_e=0, n_bins=56, normalize=True)
# test exceptions
with self.assertRaises(ValueError) as err:
self.dos.get_dos_fp_similarity(dos_fp, dos_fp2, col=1, tanimoto=True, normalize=True)
assert (
err.exception.__str__()
== "Cannot compute similarity index. Please set either normalize=True or tanimoto=True or both to False."
)
with self.assertRaises(ValueError) as err:
self.dos.get_dos_fp(type="k", min_e=-10, max_e=0, n_bins=56, normalize=True)
assert (
err.exception.__str__()
== "Please recheck type requested, either the orbital projections unavailable in input DOS or there's a typo in type."
)


class DOSTest(PymatgenTest):
def setUp(self):
Expand Down
Loading