symfc 1.3.0__tar.gz → 1.3.2__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 (110) hide show
  1. {symfc-1.3.0/src/symfc.egg-info → symfc-1.3.2}/PKG-INFO +1 -1
  2. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/api_symfc.py +4 -2
  3. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/solvers/solver_O2O3.py +1 -0
  4. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/eig_tools.py +1 -241
  5. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/matrix_tools_O2.py +38 -39
  6. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/matrix_tools_O3.py +45 -59
  7. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/matrix_tools_O4.py +46 -55
  8. symfc-1.3.2/src/symfc/utils/rotation_dev/__init__.py +1 -0
  9. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/version.py +1 -1
  10. {symfc-1.3.0 → symfc-1.3.2/src/symfc.egg-info}/PKG-INFO +1 -1
  11. {symfc-1.3.0 → symfc-1.3.2}/src/symfc.egg-info/SOURCES.txt +4 -3
  12. {symfc-1.3.0 → symfc-1.3.2}/tests/basis_sets/test_basis_sets_O2.py +32 -0
  13. {symfc-1.3.0 → symfc-1.3.2}/tests/basis_sets/test_basis_sets_O3.py +2 -86
  14. {symfc-1.3.0 → symfc-1.3.2}/tests/conftest.py +87 -0
  15. {symfc-1.3.0 → symfc-1.3.2}/tests/utils/test_matrix_tools_O2.py +22 -0
  16. {symfc-1.3.0 → symfc-1.3.2}/tests/utils/test_matrix_tools_O3.py +1 -1
  17. {symfc-1.3.0 → symfc-1.3.2}/LICENSE +0 -0
  18. {symfc-1.3.0 → symfc-1.3.2}/MANIFEST.in +0 -0
  19. {symfc-1.3.0 → symfc-1.3.2}/README.md +0 -0
  20. {symfc-1.3.0 → symfc-1.3.2}/pyproject.toml +0 -0
  21. {symfc-1.3.0 → symfc-1.3.2}/setup.cfg +0 -0
  22. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/__init__.py +0 -0
  23. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/basis_sets/__init__.py +0 -0
  24. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/basis_sets/basis_sets_O1.py +0 -0
  25. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/basis_sets/basis_sets_O2.py +0 -0
  26. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/basis_sets/basis_sets_O3.py +0 -0
  27. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/basis_sets/basis_sets_O4.py +0 -0
  28. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/basis_sets/basis_sets_base.py +0 -0
  29. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/solvers/__init__.py +0 -0
  30. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/solvers/solver_O2.py +0 -0
  31. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/solvers/solver_O2O3O4.py +0 -0
  32. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/solvers/solver_O3.py +0 -0
  33. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/solvers/solver_O3O4.py +0 -0
  34. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/solvers/solver_O4.py +0 -0
  35. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/solvers/solver_base.py +0 -0
  36. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/spg_reps/__init__.py +0 -0
  37. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/spg_reps/spg_reps_O1.py +0 -0
  38. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/spg_reps/spg_reps_O2.py +0 -0
  39. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/spg_reps/spg_reps_O3.py +0 -0
  40. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/spg_reps/spg_reps_O4.py +0 -0
  41. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/spg_reps/spg_reps_base.py +0 -0
  42. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/__init__.py +0 -0
  43. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/cutoff_tools.py +0 -0
  44. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/matrix_tools.py +0 -0
  45. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/matrix_tools_O1.py +0 -0
  46. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/permutation_tools.py +0 -0
  47. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/permutation_tools_O2.py +0 -0
  48. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/permutation_tools_O3.py +0 -0
  49. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/permutation_tools_O4.py +0 -0
  50. {symfc-1.3.0/src/symfc/utils → symfc-1.3.2/src/symfc/utils/rotation_dev}/run_rotation_tools_O2.py +0 -0
  51. {symfc-1.3.0/src/symfc/utils → symfc-1.3.2/src/symfc/utils/rotation_dev}/run_rotation_tools_O3.py +0 -0
  52. {symfc-1.3.0/src/symfc/utils → symfc-1.3.2/src/symfc/utils/rotation_dev}/run_test_O2.py +0 -0
  53. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/rotation_tools_O2.py +0 -0
  54. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/solver_funcs.py +0 -0
  55. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/utils.py +0 -0
  56. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/utils_O1.py +0 -0
  57. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/utils_O2.py +0 -0
  58. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/utils_O3.py +0 -0
  59. {symfc-1.3.0 → symfc-1.3.2}/src/symfc/utils/utils_O4.py +0 -0
  60. {symfc-1.3.0 → symfc-1.3.2}/src/symfc.egg-info/dependency_links.txt +0 -0
  61. {symfc-1.3.0 → symfc-1.3.2}/src/symfc.egg-info/requires.txt +0 -0
  62. {symfc-1.3.0 → symfc-1.3.2}/src/symfc.egg-info/top_level.txt +0 -0
  63. {symfc-1.3.0 → symfc-1.3.2}/tests/NaCl-unitcell.yaml +0 -0
  64. {symfc-1.3.0 → symfc-1.3.2}/tests/basis_sets/test_basis_sets_O4.py +0 -0
  65. {symfc-1.3.0 → symfc-1.3.2}/tests/basis_sets/test_basis_sets_base.py +0 -0
  66. {symfc-1.3.0 → symfc-1.3.2}/tests/compact_fc_GaN_222.xz +0 -0
  67. {symfc-1.3.0 → symfc-1.3.2}/tests/compact_fc_GaN_442.xz +0 -0
  68. {symfc-1.3.0 → symfc-1.3.2}/tests/compact_fc_NaCl_222.xz +0 -0
  69. {symfc-1.3.0 → symfc-1.3.2}/tests/compact_fc_SiO2_221.xz +0 -0
  70. {symfc-1.3.0 → symfc-1.3.2}/tests/compact_fc_Si_111_fc3_2.xz +0 -0
  71. {symfc-1.3.0 → symfc-1.3.2}/tests/compact_fc_Si_111_fc3_3.xz +0 -0
  72. {symfc-1.3.0 → symfc-1.3.2}/tests/compact_fc_Si_111_fc4_2.xz +0 -0
  73. {symfc-1.3.0 → symfc-1.3.2}/tests/compact_fc_Si_111_fc4_3.xz +0 -0
  74. {symfc-1.3.0 → symfc-1.3.2}/tests/compact_fc_Si_111_fc4_4.xz +0 -0
  75. {symfc-1.3.0 → symfc-1.3.2}/tests/compact_fc_SnO2_223.xz +0 -0
  76. {symfc-1.3.0 → symfc-1.3.2}/tests/dfset_GaN_222_rd.xz +0 -0
  77. {symfc-1.3.0 → symfc-1.3.2}/tests/dfset_GaN_442_rd.xz +0 -0
  78. {symfc-1.3.0 → symfc-1.3.2}/tests/dfset_NaCl_222_rd.xz +0 -0
  79. {symfc-1.3.0 → symfc-1.3.2}/tests/dfset_SiO2_221_rd.xz +0 -0
  80. {symfc-1.3.0 → symfc-1.3.2}/tests/dfset_Si_111_fc3_rd.xz +0 -0
  81. {symfc-1.3.0 → symfc-1.3.2}/tests/dfset_SnO2_223_rd.xz +0 -0
  82. {symfc-1.3.0 → symfc-1.3.2}/tests/full_fc_NaCl_222.xz +0 -0
  83. {symfc-1.3.0 → symfc-1.3.2}/tests/full_fc_Si_111_fc3_2.xz +0 -0
  84. {symfc-1.3.0 → symfc-1.3.2}/tests/full_fc_Si_111_fc3_3.xz +0 -0
  85. {symfc-1.3.0 → symfc-1.3.2}/tests/full_fc_Si_111_fc4_2.xz +0 -0
  86. {symfc-1.3.0 → symfc-1.3.2}/tests/full_fc_Si_111_fc4_3.xz +0 -0
  87. {symfc-1.3.0 → symfc-1.3.2}/tests/full_fc_Si_111_fc4_4.xz +0 -0
  88. {symfc-1.3.0 → symfc-1.3.2}/tests/full_fc_Si_111_fc4_step_2.xz +0 -0
  89. {symfc-1.3.0 → symfc-1.3.2}/tests/full_fc_Si_111_fc4_step_3.xz +0 -0
  90. {symfc-1.3.0 → symfc-1.3.2}/tests/full_fc_Si_111_fc4_step_4.xz +0 -0
  91. {symfc-1.3.0 → symfc-1.3.2}/tests/full_fc_SnO2_223.xz +0 -0
  92. {symfc-1.3.0 → symfc-1.3.2}/tests/perms_super.dat +0 -0
  93. {symfc-1.3.0 → symfc-1.3.2}/tests/phonopy_to_python.py +0 -0
  94. {symfc-1.3.0 → symfc-1.3.2}/tests/solvers/test_solver_utils.py +0 -0
  95. {symfc-1.3.0 → symfc-1.3.2}/tests/spg_reps/test_spg_reps_O1.py +0 -0
  96. {symfc-1.3.0 → symfc-1.3.2}/tests/spg_reps/test_spg_reps_O2.py +0 -0
  97. {symfc-1.3.0 → symfc-1.3.2}/tests/spg_reps/test_spg_reps_O3.py +0 -0
  98. {symfc-1.3.0 → symfc-1.3.2}/tests/spg_reps/test_spg_reps_O4.py +0 -0
  99. {symfc-1.3.0 → symfc-1.3.2}/tests/spg_reps/test_spg_reps_base.py +0 -0
  100. {symfc-1.3.0 → symfc-1.3.2}/tests/test_api.py +0 -0
  101. {symfc-1.3.0 → symfc-1.3.2}/tests/utils/test_cutoff_tools.py +0 -0
  102. {symfc-1.3.0 → symfc-1.3.2}/tests/utils/test_eig_tools.py +0 -0
  103. {symfc-1.3.0 → symfc-1.3.2}/tests/utils/test_matrix_tools_O4.py +0 -0
  104. {symfc-1.3.0 → symfc-1.3.2}/tests/utils/test_solver_funcs.py +0 -0
  105. {symfc-1.3.0 → symfc-1.3.2}/tests/utils/test_utils.py +0 -0
  106. {symfc-1.3.0 → symfc-1.3.2}/tests/utils/test_utils_O1.py +0 -0
  107. {symfc-1.3.0 → symfc-1.3.2}/tests/utils/test_utils_O2.py +0 -0
  108. {symfc-1.3.0 → symfc-1.3.2}/tests/utils/test_utils_O2_2.py +0 -0
  109. {symfc-1.3.0 → symfc-1.3.2}/tests/utils/test_utils_O3.py +0 -0
  110. {symfc-1.3.0 → symfc-1.3.2}/tests/utils/test_utils_O4.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: symfc
3
- Version: 1.3.0
3
+ Version: 1.3.2
4
4
  Summary: This is the symfc module.
5
5
  Author-email: Atsuto Seko <seko@cms.mtl.kyoto-u.ac.jp>
6
6
  Maintainer-email: Atsushi Togo <atztogo@gmail.com>
@@ -286,6 +286,7 @@ class Symfc:
286
286
  basis_set_o2 = FCBasisSetO2(
287
287
  self._supercell,
288
288
  spacegroup_operations=self._spacegroup_operations,
289
+ cutoff=self._cutoff[2],
289
290
  use_mkl=self._use_mkl,
290
291
  log_level=self._log_level,
291
292
  ).run()
@@ -341,6 +342,7 @@ class Symfc:
341
342
  basis_size_estimates[order] = FCBasisSetO2(
342
343
  self._supercell,
343
344
  spacegroup_operations=self._spacegroup_operations,
345
+ cutoff=self._cutoff[2],
344
346
  use_mkl=self._use_mkl,
345
347
  log_level=self._log_level,
346
348
  ).estimate_basis_size()
@@ -409,9 +411,9 @@ class Symfc:
409
411
 
410
412
  def _prepare_cutoff(self, cutoff):
411
413
  if cutoff is None:
412
- self._cutoff = {3: None, 4: None}
414
+ self._cutoff = {2: None, 3: None, 4: None}
413
415
  else:
414
416
  self._cutoff = cutoff
415
- for order in (3, 4):
417
+ for order in (2, 3, 4):
416
418
  if order not in self._cutoff:
417
419
  self._cutoff[order] = None
@@ -308,6 +308,7 @@ def prepare_normal_equation_O2O3(
308
308
  if verbose:
309
309
  print("Solver_block:", end, "/", disps.shape[0], flush=True)
310
310
  print(" - Time:", "{:.3f}".format(t2 - t1), flush=True)
311
+ del X3
311
312
 
312
313
  if verbose:
313
314
  print("Solver:", "Calculate X.T @ X and X.T @ y", flush=True)
@@ -7,7 +7,7 @@ from typing import Optional
7
7
  import numpy as np
8
8
  import scipy
9
9
  from scipy.linalg import get_lapack_funcs
10
- from scipy.sparse import csr_array, hstack, lil_array
10
+ from scipy.sparse import csr_array
11
11
 
12
12
  from symfc.utils.solver_funcs import get_batch_slice
13
13
 
@@ -385,243 +385,3 @@ def eigsh_projector_sumrule_large(p: csr_array, verbose: bool = True) -> np.ndar
385
385
  eigvecs_full[ids, col_id:col_end] = eigvecs
386
386
  col_id = col_end
387
387
  return eigvecs_full[:, :col_id]
388
-
389
-
390
- def _find_smaller_block(p1: np.ndarray, target_size: int = 3000, random: bool = True):
391
- """Find a reasonable block in matrix p1."""
392
- if random:
393
- # algorithm 2 (random choice)
394
- total_size = p1.shape[0]
395
- ids = np.random.choice(
396
- range(total_size),
397
- min(target_size, total_size),
398
- replace=False,
399
- )
400
- bools = np.zeros(p1.shape[0], dtype=bool)
401
- bools[ids] = True
402
- return bools
403
-
404
- # algorithm 1
405
- n_data = np.count_nonzero(np.abs(p1) > 1e-15, axis=1)
406
- rep_id = np.abs(n_data - target_size).argmin()
407
- return np.abs(p1[rep_id]) > 1e-15
408
-
409
-
410
- def _iterative_eigsh_projector(
411
- p_block: np.ndarray,
412
- max_iter: int = 50,
413
- size_terminate: int = 2000,
414
- use_mkl: bool = False,
415
- verbose: bool = False,
416
- use_sparse: bool = True,
417
- ):
418
- if use_sparse:
419
- return _iterative_eigsh_projector_use_sparse(
420
- p_block=p_block,
421
- max_iter=max_iter,
422
- size_terminate=size_terminate,
423
- use_mkl=use_mkl,
424
- verbose=verbose,
425
- )
426
- return _iterative_eigsh_projector_use_dense(
427
- p_block=p_block,
428
- max_iter=max_iter,
429
- size_terminate=size_terminate,
430
- verbose=verbose,
431
- )
432
-
433
-
434
- def _iterative_eigsh_projector_use_dense(
435
- p_block: np.ndarray,
436
- max_iter: int = 50,
437
- size_terminate: int = 2000,
438
- verbose: bool = False,
439
- ):
440
- """Solve eigenvalue problem partially for matrix p."""
441
- if verbose:
442
- print(" - Use iterative projector solver.", flush=True)
443
-
444
- if p_block.shape[0] < size_terminate:
445
- return None, p_block, None
446
-
447
- eigvecs_block = np.zeros(p_block.shape, dtype="double")
448
- compr = None
449
- col_id = 0
450
-
451
- for j in range(max_iter):
452
- if verbose:
453
- print(" * iteration:", j + 1, flush=True)
454
- if p_block.shape[0] < size_terminate:
455
- if verbose:
456
- print(" iteration stopped. p.shape <", size_terminate, flush=True)
457
- break
458
-
459
- bool_small = _find_smaller_block(p_block, target_size=3000)
460
- bool_const = np.logical_not(bool_small)
461
- n_const = np.count_nonzero(bool_const)
462
- if verbose:
463
- print(
464
- " - Solving projector of size",
465
- np.count_nonzero(bool_small),
466
- flush=True,
467
- )
468
-
469
- if np.count_nonzero(bool_small) / p_block.shape[0] > 0.95:
470
- if verbose:
471
- print(" iteration stopped (> 0.95).", flush=True)
472
- break
473
-
474
- p_small = p_block[np.ix_(bool_small, bool_small)]
475
- rank = int(round(np.trace(p_small)))
476
- if rank == 0:
477
- break
478
-
479
- eigvecs, (cmplt_eigvals, cmplt_small) = eigh_projector(
480
- p_small,
481
- return_complement=True,
482
- verbose=verbose,
483
- )
484
- if eigvecs.shape[1] == 0:
485
- if verbose:
486
- print(" No eigenvectors are found.", flush=True)
487
- break
488
-
489
- compr_size = n_const + cmplt_small.shape[1]
490
- if verbose:
491
- print(" - Compressing matrix:", flush=True)
492
- print(" ", p_block.shape[0], "->", compr_size, flush=True)
493
-
494
- col_end = col_id + eigvecs.shape[1]
495
- if j == 0:
496
- compr = np.zeros((p_block.shape[0], compr_size))
497
- row_ids = np.where(bool_const)[0]
498
- compr[(row_ids, np.arange(n_const))] = 1.0
499
-
500
- row_ids = np.where(bool_small)[0]
501
- compr[row_ids, n_const:] = cmplt_small
502
- eigvecs_block[row_ids, col_id:col_end] = eigvecs
503
- else:
504
- compr_slice = compr[:, bool_small]
505
- prod = compr_slice @ cmplt_small
506
- eigvecs_block[:, col_id:col_end] = compr_slice @ eigvecs
507
- """Time consuming part."""
508
- compr = np.hstack([compr[:, bool_const], prod])
509
- col_id = col_end
510
-
511
- """
512
- cmplt_small.T @ p_small @ cmplt_small
513
- = (cmplt_small.T @ cmplt_small
514
- @ np.diag(cmplt_eigvals) @ cmplt_small.T @ cmplt_small)
515
- = np.diag(cmplt_eigvals)
516
- """
517
- mat12 = p_block[np.ix_(bool_const, bool_small)] @ cmplt_small
518
- p_block = np.block(
519
- [
520
- [p_block[np.ix_(bool_const, bool_const)], mat12],
521
- [mat12.T, np.diag(cmplt_eigvals)],
522
- ]
523
- )
524
-
525
- if col_id == 0:
526
- return None, p_block, None
527
- return eigvecs_block[:, :col_id], p_block, compr
528
-
529
-
530
- def _iterative_eigsh_projector_use_sparse(
531
- p_block: np.ndarray,
532
- max_iter: int = 50,
533
- size_terminate: int = 2000,
534
- use_mkl: bool = False,
535
- verbose: bool = True,
536
- ):
537
- """Solve eigenvalue problem partially for matrix p."""
538
- if p_block.shape[0] < size_terminate:
539
- return None, p_block, None
540
-
541
- if verbose:
542
- print(" - Use iterative projector solver.", flush=True)
543
-
544
- eigvecs_block = np.zeros(p_block.shape, dtype="double")
545
- compr = None
546
- col_id = 0
547
-
548
- for j in range(max_iter):
549
- if verbose:
550
- print(" * iteration:", j + 1, flush=True)
551
- if p_block.shape[0] < size_terminate:
552
- if verbose:
553
- print(" iteration stopped. p.shape <", size_terminate, flush=True)
554
- break
555
-
556
- bool_small = _find_smaller_block(p_block, target_size=3000)
557
- bool_const = np.logical_not(bool_small)
558
- n_const = np.count_nonzero(bool_const)
559
- if verbose:
560
- print(
561
- " - Solving projector of size",
562
- np.count_nonzero(bool_small),
563
- flush=True,
564
- )
565
-
566
- if np.count_nonzero(bool_small) / p_block.shape[0] > 0.95:
567
- if verbose:
568
- print(" iteration stopped (> 0.95).", flush=True)
569
- break
570
-
571
- p_small = p_block[np.ix_(bool_small, bool_small)]
572
- rank = int(round(np.trace(p_small)))
573
- if rank == 0:
574
- break
575
-
576
- eigvecs, (cmplt_eigvals, cmplt_small) = eigh_projector(
577
- p_small,
578
- return_complement=True,
579
- verbose=verbose,
580
- )
581
- cmplt_small_sp = csr_array(cmplt_small)
582
- if eigvecs.shape[1] == 0:
583
- if verbose:
584
- print(" No eigenvectors are found.", flush=True)
585
- break
586
-
587
- compr_size = n_const + cmplt_small.shape[1]
588
- if verbose:
589
- print(" - Compressing matrix:", flush=True)
590
- print(" ", p_block.shape[0], "->", compr_size, flush=True)
591
-
592
- col_end = col_id + eigvecs.shape[1]
593
- if j == 0:
594
- compr1 = csr_array(
595
- (np.ones(n_const), (np.where(bool_const)[0], np.arange(n_const))),
596
- shape=(p_block.shape[0], n_const),
597
- dtype="double",
598
- )
599
- compr2 = lil_array((p_block.shape[0], cmplt_small.shape[1]), dtype="double")
600
- row_ids = np.where(bool_small)[0]
601
- compr2[row_ids] = cmplt_small_sp.tolil()
602
- compr = hstack([compr1, compr2.tocsr()])
603
- eigvecs_block[row_ids, col_id:col_end] = eigvecs
604
- else:
605
- compr_slice = compr[:, bool_small]
606
- prod = dot_product_sparse(compr_slice, cmplt_small_sp, use_mkl=use_mkl)
607
- compr = hstack([compr[:, bool_const], prod])
608
- eigvecs_block[:, col_id:col_end] = compr_slice.toarray() @ eigvecs
609
- col_id = col_end
610
-
611
- """
612
- cmplt_small.T @ p_small @ cmplt_small
613
- = (cmplt_small.T @ cmplt_small
614
- @ np.diag(cmplt_eigvals) @ cmplt_small.T @ cmplt_small)
615
- = np.diag(cmplt_eigvals)
616
- """
617
- mat12 = p_block[np.ix_(bool_const, bool_small)] @ cmplt_small
618
- p_block = np.block(
619
- [
620
- [p_block[np.ix_(bool_const, bool_const)], mat12],
621
- [mat12.T, np.diag(cmplt_eigvals)],
622
- ]
623
- )
624
-
625
- if col_id == 0:
626
- return None, p_block, None
627
- return eigvecs_block[:, :col_id], p_block, compr.toarray()
@@ -95,7 +95,15 @@ def projector_permutation_lat_trans_O2(
95
95
  return proj_pt
96
96
 
97
97
 
98
- def compressed_projector_sum_rules_O2(
98
+ def optimize_batch_size_sum_rules_O2(natom: int, n_batch: Optional[int] = None):
99
+ """Calculate batch size for constructing projector for sum rules."""
100
+ if n_batch > natom:
101
+ raise ValueError("n_batch must be smaller than N.")
102
+ batch_size = natom * (natom // n_batch)
103
+ return batch_size
104
+
105
+
106
+ def compressed_projector_sum_rules_O2_index_atoms(
99
107
  trans_perms: np.ndarray,
100
108
  n_a_compress_mat: csr_array,
101
109
  atomic_decompr_idx: Optional[np.ndarray] = None,
@@ -123,23 +131,20 @@ def compressed_projector_sum_rules_O2(
123
131
  proj_size = n_a_compress_mat.shape[1]
124
132
  proj_cplmt = csr_array((proj_size, proj_size), dtype="double")
125
133
 
126
- if n_batch > natom:
127
- raise ValueError("n_batch must be smaller than N.")
128
- batch_size = natom * (natom // n_batch)
129
-
130
134
  if atomic_decompr_idx is None:
131
135
  atomic_decompr_idx = _get_atomic_lat_trans_decompr_indices(trans_perms)
132
136
 
133
137
  decompr_idx = atomic_decompr_idx.reshape((natom, natom)).T.reshape(-1) * 9
134
- nonzero = np.zeros((natom, natom), dtype=bool)
135
- indep_atoms = get_indep_atoms_by_lat_trans(trans_perms)
136
- nonzero[indep_atoms, :] = True
137
- nonzero = nonzero.reshape(-1)
138
- if fc_cutoff is not None:
139
- nonzero_cutoff = fc_cutoff.nonzero_atomic_indices_fc2()
140
- nonzero_cutoff = nonzero_cutoff.reshape((natom, natom)).T.reshape(-1)
141
- nonzero = nonzero & nonzero_cutoff
138
+ if fc_cutoff is None:
139
+ indep_atoms = get_indep_atoms_by_lat_trans(trans_perms)
140
+ nonzero = np.zeros((natom, natom), dtype=bool)
141
+ nonzero[indep_atoms, :] = True
142
+ nonzero = nonzero.reshape(-1)
143
+ else:
144
+ nonzero = fc_cutoff.nonzero_atomic_indices_fc2()
145
+ nonzero = nonzero.reshape((natom, natom)).T.reshape(-1)
142
146
 
147
+ batch_size = optimize_batch_size_sum_rules_O2(natom, n_batch=n_batch)
143
148
  ab = np.arange(9)
144
149
  for begin, end in zip(*get_batch_slice(NN, batch_size)):
145
150
  size = end - begin
@@ -148,31 +153,29 @@ def compressed_projector_sum_rules_O2(
148
153
 
149
154
  nonzero_b = nonzero[begin:end]
150
155
  size_data = np.count_nonzero(nonzero_b) * 9
151
- if size_data > 0:
152
- decompr_idx_b = decompr_idx[begin:end]
153
- c_sum_cplmt = csr_array(
156
+ if size_data == 0:
157
+ continue
158
+
159
+ decompr_idx_b = decompr_idx[begin:end][nonzero_b]
160
+ c_sum_cplmt = csr_array(
161
+ (
162
+ np.ones(size_data, dtype="double"),
154
163
  (
155
- np.ones(size_data, dtype="double"),
156
- (
157
- np.repeat(np.arange(size_row), natom)[np.tile(nonzero_b, 9)],
158
- (decompr_idx_b[nonzero_b][None, :] + ab[:, None]).reshape(-1),
159
- ),
164
+ np.repeat(np.arange(size_row), natom)[np.tile(nonzero_b, 9)],
165
+ (ab[:, None] + decompr_idx_b[None, :]).reshape(-1),
160
166
  ),
161
- shape=(size_row, NN9 // n_lp),
162
- dtype="double",
163
- )
164
- c_sum_cplmt = dot_product_sparse(
165
- c_sum_cplmt, n_a_compress_mat, use_mkl=use_mkl
166
- )
167
- proj_cplmt += dot_product_sparse(
168
- c_sum_cplmt.T, c_sum_cplmt, use_mkl=use_mkl
169
- )
167
+ ),
168
+ shape=(size_row, NN9 // n_lp),
169
+ dtype="double",
170
+ )
171
+ c_sum_cplmt = dot_product_sparse(c_sum_cplmt, n_a_compress_mat, use_mkl=use_mkl)
172
+ proj_cplmt += dot_product_sparse(c_sum_cplmt.T, c_sum_cplmt, use_mkl=use_mkl)
170
173
 
171
174
  proj_cplmt /= n_lp * natom
172
175
  return scipy.sparse.identity(proj_cplmt.shape[0]) - proj_cplmt
173
176
 
174
177
 
175
- def compressed_projector_sum_rules_O2_stable(
178
+ def compressed_projector_sum_rules_O2(
176
179
  trans_perms: np.ndarray,
177
180
  n_a_compress_mat: csr_array,
178
181
  atomic_decompr_idx: Optional[np.ndarray] = None,
@@ -200,10 +203,6 @@ def compressed_projector_sum_rules_O2_stable(
200
203
  proj_size = n_a_compress_mat.shape[1]
201
204
  proj_cplmt = csr_array((proj_size, proj_size), dtype="double")
202
205
 
203
- if n_batch > natom:
204
- raise ValueError("n_batch must be smaller than N.")
205
- batch_size = natom * (natom // n_batch)
206
-
207
206
  if atomic_decompr_idx is None:
208
207
  atomic_decompr_idx = _get_atomic_lat_trans_decompr_indices(trans_perms)
209
208
 
@@ -212,6 +211,7 @@ def compressed_projector_sum_rules_O2_stable(
212
211
  nonzero = fc_cutoff.nonzero_atomic_indices_fc2()
213
212
  nonzero = nonzero.reshape((natom, natom)).T.reshape(-1)
214
213
 
214
+ batch_size = optimize_batch_size_sum_rules_O2(natom, n_batch=n_batch)
215
215
  ab = np.arange(9)
216
216
  for begin, end in zip(*get_batch_slice(NN, batch_size)):
217
217
  size = end - begin
@@ -224,7 +224,7 @@ def compressed_projector_sum_rules_O2_stable(
224
224
  np.ones(size_vector, dtype="double"),
225
225
  (
226
226
  np.repeat(np.arange(size_row), natom),
227
- (decompr_idx[begin:end][None, :] + ab[:, None]).reshape(-1),
227
+ (ab[:, None] + decompr_idx[begin:end][None, :]).reshape(-1),
228
228
  ),
229
229
  ),
230
230
  shape=(size_row, NN9 // n_lp),
@@ -232,15 +232,14 @@ def compressed_projector_sum_rules_O2_stable(
232
232
  )
233
233
  else:
234
234
  nonzero_b = nonzero[begin:end]
235
+ decompr_idx_b = decompr_idx[begin:end][nonzero_b]
235
236
  size_data = np.count_nonzero(nonzero_b) * 9
236
237
  c_sum_cplmt = csr_array(
237
238
  (
238
239
  np.ones(size_data, dtype="double"),
239
240
  (
240
241
  np.repeat(np.arange(size_row), natom)[np.tile(nonzero_b, 9)],
241
- (
242
- decompr_idx[begin:end][nonzero_b][None, :] + ab[:, None]
243
- ).reshape(-1),
242
+ (ab[:, None] + decompr_idx_b[None, :]).reshape(-1),
244
243
  ),
245
244
  ),
246
245
  shape=(size_row, NN9 // n_lp),
@@ -294,7 +294,21 @@ def projector_permutation_lat_trans_O3(
294
294
  return proj_pt
295
295
 
296
296
 
297
- def compressed_projector_sum_rules_O3(
297
+ def optimize_batch_size_sum_rules_O3(natom: int, n_batch: Optional[int] = None):
298
+ """Calculate batch size for constructing projector for sum rules."""
299
+ if n_batch is None:
300
+ if natom < 256:
301
+ n_batch = natom // min(natom, 16)
302
+ else:
303
+ n_batch = natom // 4
304
+
305
+ if n_batch > natom:
306
+ raise ValueError("n_batch must be smaller than N.")
307
+ batch_size = natom**2 * (natom // n_batch)
308
+ return batch_size
309
+
310
+
311
+ def compressed_projector_sum_rules_O3_indep_atoms(
298
312
  trans_perms: np.ndarray,
299
313
  n_a_compress_mat: csr_array,
300
314
  atomic_decompr_idx: Optional[np.ndarray] = None,
@@ -324,31 +338,21 @@ def compressed_projector_sum_rules_O3(
324
338
  proj_size = n_a_compress_mat.shape[1]
325
339
  proj_cplmt = csr_array((proj_size, proj_size), dtype="double")
326
340
 
327
- if n_batch is None:
328
- if natom < 256:
329
- n_batch = natom // min(natom, 64)
330
- else:
331
- n_batch = natom // 4
332
-
333
- if n_batch > natom:
334
- raise ValueError("n_batch must be smaller than N.")
335
- batch_size = natom**2 * (natom // n_batch)
336
-
337
341
  if atomic_decompr_idx is None:
338
342
  atomic_decompr_idx = get_atomic_lat_trans_decompr_indices_O3(trans_perms)
339
343
 
340
- """Bottleneck part when using cutoff distance"""
341
344
  decompr_idx = atomic_decompr_idx.reshape((natom, NN)).T.reshape(-1) * 27
342
345
 
343
- indep_atoms = get_indep_atoms_by_lat_trans(trans_perms)
344
- nonzero = np.zeros((natom, natom, natom), dtype=bool)
345
- nonzero[indep_atoms, :, :] = True
346
- nonzero = nonzero.reshape(-1)
347
- if fc_cutoff is not None:
348
- nonzero_cutoff = fc_cutoff.nonzero_atomic_indices_fc3()
349
- nonzero_cutoff = nonzero_cutoff.reshape((natom, NN)).T.reshape(-1)
350
- nonzero = nonzero & nonzero_cutoff
346
+ if fc_cutoff is None:
347
+ indep_atoms = get_indep_atoms_by_lat_trans(trans_perms)
348
+ nonzero = np.zeros((natom, natom, natom), dtype=bool)
349
+ nonzero[indep_atoms, :, :] = True
350
+ nonzero = nonzero.reshape(-1)
351
+ else:
352
+ nonzero = fc_cutoff.nonzero_atomic_indices_fc3()
353
+ nonzero = nonzero.reshape((natom, NN)).T.reshape(-1)
351
354
 
355
+ batch_size = optimize_batch_size_sum_rules_O3(natom, n_batch=n_batch)
352
356
  abc = np.arange(27)
353
357
  for begin, end in zip(*get_batch_slice(NNN, batch_size)):
354
358
  size = end - begin
@@ -357,39 +361,31 @@ def compressed_projector_sum_rules_O3(
357
361
 
358
362
  nonzero_b = nonzero[begin:end]
359
363
  size_data = np.count_nonzero(nonzero_b) * 27
364
+ if size_data == 0:
365
+ continue
366
+
360
367
  if verbose:
361
- print(
362
- "Complementary P (Sum rule):",
363
- str(end) + "/" + str(NNN) + ",",
364
- "Non-zero:",
365
- size_data,
366
- flush=True,
367
- )
368
- if size_data > 0:
369
- decompr_idx_b = decompr_idx[begin:end]
370
- c_sum_cplmt = csr_array(
368
+ print("Complementary P (Sum rule):", str(end) + "/" + str(NNN), flush=True)
369
+ decompr_idx_b = decompr_idx[begin:end][nonzero_b]
370
+ c_sum_cplmt = csr_array(
371
+ (
372
+ np.ones(size_data, dtype="double"),
371
373
  (
372
- np.ones(size_data, dtype="double"),
373
- (
374
- np.repeat(np.arange(size_row), natom)[np.tile(nonzero_b, 27)],
375
- (decompr_idx_b[nonzero_b][None, :] + abc[:, None]).reshape(-1),
376
- ),
374
+ np.repeat(np.arange(size_row), natom)[np.tile(nonzero_b, 27)],
375
+ (abc[:, None] + decompr_idx_b[None, :]).reshape(-1),
377
376
  ),
378
- shape=(size_row, NNN27 // n_lp),
379
- dtype="double",
380
- )
381
- c_sum_cplmt = dot_product_sparse(
382
- c_sum_cplmt, n_a_compress_mat, use_mkl=use_mkl
383
- )
384
- proj_cplmt += dot_product_sparse(
385
- c_sum_cplmt.T, c_sum_cplmt, use_mkl=use_mkl
386
- )
377
+ ),
378
+ shape=(size_row, NNN27 // n_lp),
379
+ dtype="double",
380
+ )
381
+ c_sum_cplmt = dot_product_sparse(c_sum_cplmt, n_a_compress_mat, use_mkl=use_mkl)
382
+ proj_cplmt += dot_product_sparse(c_sum_cplmt.T, c_sum_cplmt, use_mkl=use_mkl)
387
383
 
388
384
  proj_cplmt /= n_lp * natom
389
385
  return scipy.sparse.identity(proj_cplmt.shape[0]) - proj_cplmt
390
386
 
391
387
 
392
- def compressed_projector_sum_rules_O3_stable(
388
+ def compressed_projector_sum_rules_O3(
393
389
  trans_perms: np.ndarray,
394
390
  n_a_compress_mat: csr_array,
395
391
  atomic_decompr_idx: Optional[np.ndarray] = None,
@@ -419,16 +415,6 @@ def compressed_projector_sum_rules_O3_stable(
419
415
  proj_size = n_a_compress_mat.shape[1]
420
416
  proj_cplmt = csr_array((proj_size, proj_size), dtype="double")
421
417
 
422
- if n_batch is None:
423
- if natom < 256:
424
- n_batch = natom // min(natom, 16)
425
- else:
426
- n_batch = natom // 4
427
-
428
- if n_batch > natom:
429
- raise ValueError("n_batch must be smaller than N.")
430
- batch_size = natom**2 * (natom // n_batch)
431
-
432
418
  if atomic_decompr_idx is None:
433
419
  atomic_decompr_idx = get_atomic_lat_trans_decompr_indices_O3(trans_perms)
434
420
 
@@ -437,6 +423,7 @@ def compressed_projector_sum_rules_O3_stable(
437
423
  nonzero = fc_cutoff.nonzero_atomic_indices_fc3()
438
424
  nonzero = nonzero.reshape((natom, NN)).T.reshape(-1)
439
425
 
426
+ batch_size = optimize_batch_size_sum_rules_O3(natom, n_batch=n_batch)
440
427
  abc = np.arange(27)
441
428
  for begin, end in zip(*get_batch_slice(NNN, batch_size)):
442
429
  if verbose:
@@ -451,7 +438,7 @@ def compressed_projector_sum_rules_O3_stable(
451
438
  np.ones(size_vector, dtype="double"),
452
439
  (
453
440
  np.repeat(np.arange(size_row), natom),
454
- (decompr_idx[begin:end][None, :] + abc[:, None]).reshape(-1),
441
+ (abc[:, None] + decompr_idx[begin:end][None, :]).reshape(-1),
455
442
  ),
456
443
  ),
457
444
  shape=(size_row, NNN27 // n_lp),
@@ -459,15 +446,14 @@ def compressed_projector_sum_rules_O3_stable(
459
446
  )
460
447
  else:
461
448
  nonzero_b = nonzero[begin:end]
449
+ decompr_idx_b = decompr_idx[begin:end][nonzero_b]
462
450
  size_data = np.count_nonzero(nonzero_b) * 27
463
451
  c_sum_cplmt = csr_array(
464
452
  (
465
453
  np.ones(size_data, dtype="double"),
466
454
  (
467
455
  np.repeat(np.arange(size_row), natom)[np.tile(nonzero_b, 27)],
468
- (
469
- decompr_idx[begin:end][nonzero_b][None, :] + abc[:, None]
470
- ).reshape(-1),
456
+ (abc[:, None] + decompr_idx_b[None, :]).reshape(-1),
471
457
  ),
472
458
  ),
473
459
  shape=(size_row, NNN27 // n_lp),