Skip to content

Commit f84adfb

Browse files
committed
Closer to symmetrized NBO input
1 parent 96b1e5b commit f84adfb

5 files changed

Lines changed: 249 additions & 78 deletions

File tree

exatomic/core/basis.py

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,59 @@ def primitives(self, spherical):
162162
#self.gaussian = gaussian
163163

164164

165+
def deduplicate_basis_sets(sets, sp=False):
166+
"""Deduplicate identical basis sets on different centers.
167+
168+
Args:
169+
sets (pd.DataFrame): non-unique basis sets
170+
sp (bool): Whether or not to call _expand_sp (gaussian program only)
171+
172+
Returns:
173+
tup (tuple): deduplicated basis sets and basis set map for atom table
174+
"""
175+
unique, setmap, cnt = [], {}, 0
176+
sets = sets.groupby('center')
177+
chk = ['alpha', 'd']
178+
for center, seht in sets:
179+
for i, other in enumerate(unique):
180+
if other.shape != seht.shape: continue
181+
if np.allclose(other[chk], seht[chk]):
182+
setmap[center] = i
183+
break
184+
else:
185+
unique.append(seht)
186+
setmap[center] = cnt
187+
cnt += 1
188+
if sp: unique = _expand_sp(unique)
189+
sets = pd.concat(unique).reset_index(drop=True)
190+
try: sets.drop([2, 3], axis=1, inplace=True)
191+
except ValueError: pass
192+
sets.rename(columns={'center': 'set'}, inplace=True)
193+
sets['set'] = sets['set'].map(setmap)
194+
sets['frame'] = 0
195+
return sets, setmap
196+
197+
def _expand_sp(unique):
198+
"""Currently only used when 'program' == 'gaussian'."""
199+
expand = []
200+
for seht in unique:
201+
if np.isnan(seht[2]).sum() == seht.shape[0]:
202+
expand.append(seht)
203+
continue
204+
sps = seht[2][~np.isnan(seht[2])].index
205+
shls = len(seht.ix[sps]['shell'].unique())
206+
dupl = seht.ix[sps[0]:sps[-1]].copy()
207+
dupl[1] = dupl[2]
208+
dupl['L'] = 1
209+
dupl['shell'] += shls
210+
last = seht.ix[sps[-1] + 1:].copy()
211+
last['shell'] += shls
212+
expand.append(pd.concat([seht.ix[:sps[0] - 1],
213+
seht.ix[sps[0]:sps[-1]],
214+
dupl, last]))
215+
return expand
216+
217+
165218
class BasisSetOrder(DataFrame):
166219
"""
167220
BasisSetOrder uniquely determines the basis function ordering scheme for
@@ -223,22 +276,38 @@ class Overlap(DataFrame):
223276
_columns = ['chi0', 'chi1', 'coef', 'frame']
224277
_index = 'index'
225278

226-
#@property
227-
#def _constructor(self):
228-
# return Overlap
229279

230-
def square(self, frame=0, column='coef', mocoefs=None):
280+
def square(self, frame=0, column='coef', mocoefs=None, irrep=None):
231281
"""Return a 'square' matrix DataFrame of the Overlap.
232282
233283
Args:
234284
column (str): column of coefficients to reshape
235285
mocoefs (str): alias for `column`
236286
frame (int): default 0
287+
irrep (int): irreducible representation if symmetrized
237288
"""
238289
if mocoefs is not None: column = mocoefs
290+
if 'irrep' in self.columns:
291+
if irrep is None:
292+
irreps, i, j = self.groupby('irrep'), 0, 0
293+
norb = (irreps.chi0.max() + 1).sum()
294+
nchi = (irreps.chi1.max() + 1).sum()
295+
cmat = np.zeros((nchi, norb))
296+
for irrep, grp in irreps:
297+
piv = grp.pivot('chi0', 'chi1', column)
298+
ii, jj = piv.shape
299+
cmat[i : i + ii, j : j + jj] = piv.values
300+
i += ii
301+
j += jj
302+
idx = pd.Index(range(nchi), name='chi0')
303+
orb = pd.Index(range(norb), name='chi1')
304+
return pd.DataFrame(cmat, index=idx, columns=orb)
305+
return self.groupby('irrep').get_group(irrep
306+
).pivot('chi', 'orbital', column)
239307
sq = _square(self[column].values)
240-
return pd.DataFrame(sq, index=pd.Index(range(sq.shape[0]), name='chi0'),
241-
columns=pd.Index(range(sq.shape[1]), name='chi1'))
308+
idx = pd.Index(range(sq.shape[0]), name='chi0')
309+
orb = pd.Index(range(sq.shape[1]), name='chi1')
310+
return pd.DataFrame(sq, index=idx, columns=orb)
242311

243312
@classmethod
244313
def from_column(cls, source):

exatomic/gaussian/output.py

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
from exatomic.core.frame import compute_frame_from_atom
2222
from exatomic.core.frame import Frame
2323
from exatomic.core.atom import Atom, Frequency
24-
from exatomic.core.basis import BasisSet, BasisSetOrder, Overlap
24+
from exatomic.core.basis import (BasisSet, BasisSetOrder, Overlap,
25+
deduplicate_basis_sets)
2526
from exatomic.core.orbital import Orbital, MOMatrix, Excitation
2627
from exatomic.algorithms.basis import lmap, lorder
2728
from numba import jit
@@ -159,8 +160,11 @@ def _padx(srs): return [0] + srs.tolist() + [df.shape[0]]
159160
except TypeError:
160161
df[2] = df[2].str.replace('D', 'E').astype(np.float64)
161162
sp = True
163+
df.rename(columns={0: 'alpha', 1: 'd'}, inplace=True)
162164
# Deduplicate basis sets and expand 'SP' shells if present
163-
df, setmap = _dedup(df, sp=sp)
165+
df, setmap = deduplicate_basis_sets(df, sp=sp)
166+
try: df.drop([2, 3], axis=1, inplace=True)
167+
except ValueError: pass
164168
spherical = '5D' in self[found[_rebas03][0]]
165169
if df['L'].max() < 2:
166170
spherical = True
@@ -531,7 +535,9 @@ def parse_basis_set(self):
531535
shldx[1] += 1
532536
ptr += nprim
533537
sp = False
534-
sets, setmap = _dedup(pd.DataFrame.from_dict(ddict))
538+
df = pd.DataFrame.from_dict(ddict)
539+
df.rename(columns={0: 'alpha', 1: 'd'}, inplace=True)
540+
sets, setmap = deduplicate_basis_sets(df)
535541
self.basis_set = sets
536542
self.meta['spherical'] = True
537543
self.atom['set'] = self.atom['set'].map(setmap)
@@ -623,48 +629,48 @@ def __init__(self, *args, **kwargs):
623629
super(Fchk, self).__init__(*args, **kwargs)
624630

625631

626-
def _dedup(sets, sp=False):
627-
unique, setmap, cnt = [], {}, 0
628-
sets = sets.groupby('center')
629-
chk = [0, 1]
630-
for center, seht in sets:
631-
for i, other in enumerate(unique):
632-
if other.shape != seht.shape: continue
633-
if np.allclose(other[chk], seht[chk]):
634-
setmap[center] = i
635-
break
636-
else:
637-
unique.append(seht)
638-
setmap[center] = cnt
639-
cnt += 1
640-
if sp: unique = _expand_sp(unique)
641-
sets = pd.concat(unique).reset_index(drop=True)
642-
try: sets.drop([2, 3], axis=1, inplace=True)
643-
except ValueError: pass
644-
sets.rename(columns={'center': 'set', 0: 'alpha', 1: 'd'}, inplace=True)
645-
sets['set'] = sets['set'].map(setmap)
646-
sets['frame'] = 0
647-
return sets, setmap
648-
649-
650-
def _expand_sp(unique):
651-
expand = []
652-
for seht in unique:
653-
if np.isnan(seht[2]).sum() == seht.shape[0]:
654-
expand.append(seht)
655-
continue
656-
sps = seht[2][~np.isnan(seht[2])].index
657-
shls = len(seht.ix[sps]['shell'].unique())
658-
dupl = seht.ix[sps[0]:sps[-1]].copy()
659-
dupl[1] = dupl[2]
660-
dupl['L'] = 1
661-
dupl['shell'] += shls
662-
last = seht.ix[sps[-1] + 1:].copy()
663-
last['shell'] += shls
664-
expand.append(pd.concat([seht.ix[:sps[0] - 1],
665-
seht.ix[sps[0]:sps[-1]],
666-
dupl, last]))
667-
return expand
632+
# def _dedup(sets, sp=False):
633+
# unique, setmap, cnt = [], {}, 0
634+
# sets = sets.groupby('center')
635+
# chk = [0, 1]
636+
# for center, seht in sets:
637+
# for i, other in enumerate(unique):
638+
# if other.shape != seht.shape: continue
639+
# if np.allclose(other[chk], seht[chk]):
640+
# setmap[center] = i
641+
# break
642+
# else:
643+
# unique.append(seht)
644+
# setmap[center] = cnt
645+
# cnt += 1
646+
# if sp: unique = _expand_sp(unique)
647+
# sets = pd.concat(unique).reset_index(drop=True)
648+
# try: sets.drop([2, 3], axis=1, inplace=True)
649+
# except ValueError: pass
650+
# sets.rename(columns={'center': 'set', 0: 'alpha', 1: 'd'}, inplace=True)
651+
# sets['set'] = sets['set'].map(setmap)
652+
# sets['frame'] = 0
653+
# return sets, setmap
654+
#
655+
#
656+
# def _expand_sp(unique):
657+
# expand = []
658+
# for seht in unique:
659+
# if np.isnan(seht[2]).sum() == seht.shape[0]:
660+
# expand.append(seht)
661+
# continue
662+
# sps = seht[2][~np.isnan(seht[2])].index
663+
# shls = len(seht.ix[sps]['shell'].unique())
664+
# dupl = seht.ix[sps[0]:sps[-1]].copy()
665+
# dupl[1] = dupl[2]
666+
# dupl['L'] = 1
667+
# dupl['shell'] += shls
668+
# last = seht.ix[sps[-1] + 1:].copy()
669+
# last['shell'] += shls
670+
# expand.append(pd.concat([seht.ix[:sps[0] - 1],
671+
# seht.ix[sps[0]:sps[-1]],
672+
# dupl, last]))
673+
# return expand
668674

669675

670676
def _basis_set_order(chunk, mapr, sets):

0 commit comments

Comments
 (0)