Skip to content

Commit be0db9f

Browse files
committed
Add full HORTON partitioning options support
1 parent 508fbb9 commit be0db9f

2 files changed

Lines changed: 74 additions & 24 deletions

File tree

pyxdm/core/session.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,16 +127,32 @@ def setup_calculator(self) -> None:
127127
self.calculator = XDMCalculator(self.mol)
128128
logger.debug("XDM calculator initialized")
129129

130-
def setup_partition_schemes(self, schemes: list[str], proatomdb: Optional[str] = None) -> dict:
130+
def setup_partition_schemes(self, schemes, proatomdb: Optional[str] = None) -> dict:
131131
"""
132132
Setup partitioning schemes for the session.
133133
134134
Parameters
135135
----------
136-
schemes : list of str
137-
List of partitioning scheme names to use
136+
schemes : list of str or dict
137+
List of partitioning scheme names to use, or a dictionary mapping
138+
scheme names to their configuration options.
139+
140+
If dict, keys are scheme names and values are dicts of kwargs:
141+
- mbis: lmax (int, default=3), maxiter (int, default=500), threshold (float, default=1e-6)
142+
- becke: lmax (int, default=3), k (int, default=3)
143+
- hirshfeld: lmax (int, default=3)
144+
- hirshfeld-i: lmax (int, default=3), maxiter (int, default=500), threshold (float, default=1e-6)
145+
- iterative-stockholder: lmax (int, default=3), maxiter (int, default=500), threshold (float, default=1e-6)
146+
147+
Example:
148+
schemes = {
149+
"mbis": {"lmax": 4, "maxiter": 500, "threshold": 1e-6},
150+
"hirshfeld-i": {"lmax": 3, "maxiter": 1000, "threshold": 1e-5},
151+
"becke": {"lmax": 3, "k": 3}
152+
}
153+
138154
proatomdb : str, optional
139-
Path to proatom database for Hirshfeld schemes
155+
Path to proatom database for Hirshfeld-based schemes (hirshfeld, hirshfeld-i)
140156
141157
Returns
142158
-------
@@ -146,9 +162,14 @@ def setup_partition_schemes(self, schemes: list[str], proatomdb: Optional[str] =
146162
self.partitions = {}
147163
self.partition_schemes = {}
148164

149-
for scheme in schemes:
165+
if isinstance(schemes, dict):
166+
scheme_configs = schemes
167+
else:
168+
scheme_configs = {scheme: {} for scheme in schemes}
169+
170+
for scheme, config in scheme_configs.items():
150171
try:
151-
scheme_kwargs = {}
172+
scheme_kwargs = config.copy() if config else {}
152173
if proatomdb:
153174
scheme_kwargs["proatom_db"] = proatomdb
154175

pyxdm/partitioning/partitioning.py

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,24 @@ class BeckePartitioning(PartitioningScheme):
138138

139139
NAME: str = "becke"
140140

141-
def __init__(self) -> None:
141+
def __init__(self, lmax: int = 3, k: int = 3) -> None:
142142
"""
143143
Initialize Becke partitioning.
144144
145+
Parameters
146+
----------
147+
lmax : int, default=3
148+
Maximum angular momentum for multipole expansion
149+
k : int, default=3
150+
Order of the polynomials used in the Becke switching function
151+
145152
Returns
146153
-------
147154
None
148155
"""
149156
super().__init__()
157+
self.lmax = lmax
158+
self.k = k
150159

151160
def compute_weights(self, mol: Any, grid: Union[CustomGrid, Any]) -> None:
152161
"""
@@ -178,6 +187,8 @@ def compute_weights(self, mol: Any, grid: Union[CustomGrid, Any]) -> None:
178187
grid,
179188
rho_total,
180189
local=False,
190+
lmax=self.lmax,
191+
k=self.k,
181192
)
182193
becke.do_all()
183194

@@ -195,21 +206,24 @@ class HirshfeldPartitioning(PartitioningScheme):
195206

196207
NAME: str = "hirshfeld"
197208

198-
def __init__(self, proatom_db: Optional[str] = None) -> None:
209+
def __init__(self, proatom_db: Optional[str] = None, lmax: int = 3) -> None:
199210
"""
200211
Initialize Hirshfeld partitioning.
201212
202213
Parameters
203214
----------
204215
proatom_db : Optional[str], default=None
205216
Path to pro-atom database. If None, uses default database.
217+
lmax : int, default=3
218+
Maximum angular momentum for multipole expansion
206219
207220
Returns
208221
-------
209222
None
210223
"""
211224
super().__init__()
212225
self.proatom_db = proatom_db
226+
self.lmax = lmax
213227

214228
def compute_weights(self, mol: Any, grid: Union[CustomGrid, Any]) -> None:
215229
"""
@@ -249,6 +263,7 @@ def compute_weights(self, mol: Any, grid: Union[CustomGrid, Any]) -> None:
249263
rho_total,
250264
proatomdb,
251265
local=False,
266+
lmax=self.lmax,
252267
)
253268
hirshfeld.do_all()
254269

@@ -272,6 +287,7 @@ def __init__(
272287
proatom_db: Optional[str] = None,
273288
maxiter: int = 500,
274289
threshold: float = 1e-6,
290+
lmax: int = 3,
275291
) -> None:
276292
"""
277293
Initialize Hirshfeld-I partitioning.
@@ -284,6 +300,8 @@ def __init__(
284300
Maximum number of iterations for convergence
285301
threshold : float, default=1e-6
286302
Convergence threshold for iterative process
303+
lmax : int, default=3
304+
Maximum angular momentum for multipole expansion
287305
288306
Returns
289307
-------
@@ -293,6 +311,7 @@ def __init__(
293311
self.proatom_db = proatom_db
294312
self.maxiter = maxiter
295313
self.threshold = threshold
314+
self.lmax = lmax
296315

297316
def compute_weights(self, mol: Any, grid: Union[CustomGrid, Any]) -> None:
298317
"""
@@ -328,6 +347,7 @@ def compute_weights(self, mol: Any, grid: Union[CustomGrid, Any]) -> None:
328347
rho_total,
329348
proatomdb,
330349
local=False,
350+
lmax=self.lmax,
331351
maxiter=self.maxiter,
332352
threshold=self.threshold,
333353
)
@@ -364,6 +384,7 @@ def __init__(
364384
self,
365385
maxiter: int = 500,
366386
threshold: float = 1e-6,
387+
lmax: int = 3,
367388
) -> None:
368389
"""
369390
Initialize Iterative Stockholder partitioning.
@@ -374,10 +395,13 @@ def __init__(
374395
Maximum number of iterations for self-consistent procedure
375396
threshold : float, default=1e-6
376397
Convergence threshold for density changes between iterations
398+
lmax : int, default=3
399+
Maximum angular momentum for multipole expansion
377400
"""
378401
super().__init__()
379402
self.maxiter = maxiter
380403
self.threshold = threshold
404+
self.lmax = lmax
381405

382406
def compute_weights(self, mol: Any, grid: Union[CustomGrid, Any]) -> None:
383407
"""
@@ -404,6 +428,7 @@ def compute_weights(self, mol: Any, grid: Union[CustomGrid, Any]) -> None:
404428
mol.pseudo_numbers,
405429
grid,
406430
rho_total,
431+
lmax=self.lmax,
407432
maxiter=self.maxiter,
408433
threshold=self.threshold,
409434
)
@@ -425,7 +450,7 @@ class MBISPartitioning(PartitioningScheme):
425450

426451
NAME: str = "mbis"
427452

428-
def __init__(self, maxiter: int = 500, threshold: float = 1e-6) -> None:
453+
def __init__(self, maxiter: int = 500, threshold: float = 1e-6, lmax: int = 3) -> None:
429454
"""Initialize MBIS partitioning.
430455
431456
Parameters
@@ -434,10 +459,13 @@ def __init__(self, maxiter: int = 500, threshold: float = 1e-6) -> None:
434459
Maximum number of iterations for convergence
435460
threshold : float, default=1e-6
436461
Convergence threshold for iterative process
462+
lmax : int, default=3
463+
Maximum angular momentum for multipole expansion
437464
"""
438465
super().__init__()
439466
self.maxiter = maxiter
440467
self.threshold = threshold
468+
self.lmax = lmax
441469

442470
def compute_weights(self, mol: Any, grid: Union[CustomGrid, Any]) -> None:
443471
"""Create MBIS partition object for grid projection.
@@ -463,6 +491,7 @@ def compute_weights(self, mol: Any, grid: Union[CustomGrid, Any]) -> None:
463491
mol.pseudo_numbers,
464492
grid,
465493
rho_total,
494+
lmax=self.lmax,
466495
maxiter=self.maxiter,
467496
threshold=self.threshold,
468497
)
@@ -504,11 +533,11 @@ def create_scheme(cls, scheme_name: str, **kwargs: Any) -> "PartitioningScheme":
504533
**kwargs
505534
Additional keyword arguments passed to the scheme constructor.
506535
Different schemes accept different parameters:
507-
- mbis: maxiter, threshold, agspec
508-
- becke: (no parameters)
509-
- hirshfeld: proatom_db
510-
- hirshfeld-i: proatom_db, maxiter, threshold
511-
- iterstock/iterative-stockholder/is: maxiter, threshold
536+
- mbis: lmax, maxiter, threshold
537+
- becke: lmax, k
538+
- hirshfeld: proatom_db, lmax
539+
- hirshfeld-i: proatom_db, lmax, maxiter, threshold
540+
- iterative-stockholder: lmax, maxiter, threshold
512541
513542
Returns
514543
-------
@@ -526,20 +555,20 @@ def create_scheme(cls, scheme_name: str, **kwargs: Any) -> "PartitioningScheme":
526555

527556
# Filter kwargs based on scheme requirements
528557
if scheme_name in [BeckePartitioning.NAME]:
529-
# Becke doesn't accept any special parameters
530-
filtered_kwargs = {}
558+
# Becke accepts lmax, k
559+
filtered_kwargs = {k: v for k, v in kwargs.items() if k in ["lmax", "k"]}
531560
elif scheme_name in [HirshfeldPartitioning.NAME]:
532-
# Hirshfeld only accepts 'proatom_db'
533-
filtered_kwargs = {k: v for k, v in kwargs.items() if k in ["proatom_db"]}
561+
# Hirshfeld accepts proatom_db, lmax
562+
filtered_kwargs = {k: v for k, v in kwargs.items() if k in ["proatom_db", "lmax"]}
534563
elif scheme_name in [HirshfeldIPartitioning.NAME]:
535-
# Hirshfeld-I accepts proatom_db, maxiter, threshold
536-
filtered_kwargs = {k: v for k, v in kwargs.items() if k in ["proatom_db", "maxiter", "threshold"]}
564+
# Hirshfeld-I accepts proatom_db, lmax, maxiter, threshold
565+
filtered_kwargs = {k: v for k, v in kwargs.items() if k in ["proatom_db", "lmax", "maxiter", "threshold"]}
537566
elif scheme_name in [IterativeStockholderPartitioning.NAME, "iterstock", "is"]:
538-
# Iterative Stockholder accepts maxiter, threshold
539-
filtered_kwargs = {k: v for k, v in kwargs.items() if k in ["maxiter", "threshold"]}
567+
# Iterative Stockholder accepts lmax, maxiter, threshold
568+
filtered_kwargs = {k: v for k, v in kwargs.items() if k in ["lmax", "maxiter", "threshold"]}
540569
else:
541-
# MBIS accepts maxiter, threshold, agspec
542-
filtered_kwargs = {k: v for k, v in kwargs.items() if k in ["maxiter", "threshold"]}
570+
# MBIS accepts lmax, maxiter, threshold
571+
filtered_kwargs = {k: v for k, v in kwargs.items() if k in ["lmax", "maxiter", "threshold"]}
543572

544573
scheme_class = cls._schemes[scheme_name]
545574
result = scheme_class(**filtered_kwargs)

0 commit comments

Comments
 (0)