Skip to content

Commit c21459a

Browse files
Merge branch 'master' into new_cluster_interface
2 parents e4e93a5 + d1092d2 commit c21459a

6 files changed

Lines changed: 281 additions & 40 deletions

File tree

.github/workflows/python-testsuite.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,6 @@ jobs:
4949
run: |
5050
export OMP_NUM_THREADS=1
5151
cd tests
52+
rm -rf __pycache__
5253
# Test excluding very long running tests
5354
pytest -v -m "not release"

Modules/Cluster.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,12 @@ def __init__(self, hostname=None, pwd=None, extra_options="", workdir = "",
189189
self.n_together_def = 1
190190
self.use_multiple_submission = False
191191

192+
# If true, add the set -x option at the beggining of the script
193+
# This options makes the system print on stdout all executed commands.
194+
# Very usefull to debug if something goes wrong.
195+
# On some clusters may cause malfunctions.
196+
self.add_set_minus_x = True
197+
192198

193199
# This is a set of lines to be runned before the calculation
194200
# It can be used to load the needed modules in the cluster
@@ -228,6 +234,11 @@ def __init__(self, hostname=None, pwd=None, extra_options="", workdir = "",
228234
# Useful if the cluster has a limit for the maximum number of jobs allowed.
229235
self.batch_size = 1000
230236

237+
# This could be a function that generates for each input file additional
238+
# text in the submission file.
239+
# Usefull if you want to copy things in a different directory to run the calculation on the cluster.
240+
self.additional_script_parameters = None
241+
231242

232243
# Allow to setup additional custom extra parameters
233244
self.custom_params = {}
@@ -438,9 +449,11 @@ def batch_submission(self, list_of_structures, calc, indices,
438449
new_mpicmd = self.mpi_cmd.replace("NPROC", str(self.n_cpu))
439450
results = [None] * N_structs
440451
submitted = []
452+
submission_labels = []
441453
for i in range(N_structs):
442454
# Prepare a typical label
443455
lbl = label + "_" + str(indices[i])
456+
submission_labels.append(lbl)
444457

445458
atm = list_of_structures[i].get_ase_atoms()
446459
atm.set_calculator(calc)
@@ -530,17 +543,28 @@ def batch_submission(self, list_of_structures, calc, indices,
530543

531544

532545
# Add the set -x option
533-
submission += "set -x\n"
546+
if self.add_set_minus_x:
547+
submission += "set -x\n"
534548

535549
# Add the loading of the modules
536550
submission += self.load_modules + "\n"
537551

538552
# Go to the working directory
539553
submission += "cd " + self.workdir + "\n"
554+
555+
# If any, apply the extra text before and after the calculation
556+
other_input = ""
557+
other_output = ""
558+
if self.additional_script_parameters is not None:
559+
other_input, other_output = self.additional_script_parameters(submission_labels)
560+
561+
submission += other_input
540562

541563
# Use the xargs trick
542564
#submission += "xargs -d " + r"'\n'" + " -L1 -P%d -a %s -- bash -c\n" % (n_togheder,
543565
submission += app_list
566+
567+
submission += other_output
544568

545569
# Copy the submission script
546570
sub_fpath = "%s/%s.sh" % (self.local_workdir, label + "_" + str(indices[0]))

Modules/SchaMinimizer.py

Lines changed: 50 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ def __init__(self, ensemble = None, root_representation = "normal",
177177
self.precond_dyn = True
178178

179179
self.minim_struct = True
180+
self.minim_dyn = True
180181

181182
# This is a debugging flag
182183
# If true the preconditioning of the original ensemble
@@ -318,10 +319,14 @@ def minimization_step(self, custom_function_gradient = None):
318319
#dyn_grad, err = self.ensemble.get_free_energy_gradient_respect_to_dyn()
319320
#dyn_grad, err = self.ensemble.get_fc_from_self_consistency(True, True)
320321
#dyn_grad, err = self.ensemble.get_fc_from_self_consistency(True, True)
321-
if self.precond_dyn:
322-
dyn_grad, err = self.ensemble.get_preconditioned_gradient(True, True, preconditioned=1)
322+
if self.minim_dyn:
323+
if self.precond_dyn:
324+
dyn_grad, err = self.ensemble.get_preconditioned_gradient(True, True, preconditioned=1)
325+
else:
326+
dyn_grad, err = self.ensemble.get_preconditioned_gradient(True, True, preconditioned=0)
323327
else:
324-
dyn_grad, err = self.ensemble.get_preconditioned_gradient(True, True, preconditioned=0)
328+
dyn_grad = np.zeros( (len(self.dyn.q_tot), 3 * self.dyn.structure.N_atoms, 3 * self.dyn.structure.N_atoms), dtype = np.complex128)
329+
err = np.zeros_like(dyn_grad)
325330

326331

327332
# Perform the symmetrization
@@ -330,45 +335,46 @@ def minimization_step(self, custom_function_gradient = None):
330335
# qe_sym.ImposeSumRule(err)
331336
# qe_sym.SymmetrizeDynQ(err, np.array([0,0,0]))
332337
t1 = time.time()
333-
if not self.neglect_symmetries:
334-
# Check if the symmetries must be applied in the supercell
335-
if self.use_spglib:
336-
# Check if we have a supercell
337-
supercell = self.dyn.GetSupercell()
338-
n_cell = np.prod(supercell)
339-
if n_cell == 1:
340-
# Only gamma, apply the symmetries
341-
qe_sym.ApplySymmetriesToV2(dyn_grad[0, :, :])
342-
343-
#qe_sym.ApplySymmetriesToV2(err)
344-
#CC.symmetries.CustomASR(err)
338+
if self.minim_dyn:
339+
if not self.neglect_symmetries:
340+
# Check if the symmetries must be applied in the supercell
341+
if self.use_spglib:
342+
# Check if we have a supercell
343+
supercell = self.dyn.GetSupercell()
344+
n_cell = np.prod(supercell)
345+
if n_cell == 1:
346+
# Only gamma, apply the symmetries
347+
qe_sym.ApplySymmetriesToV2(dyn_grad[0, :, :])
348+
349+
#qe_sym.ApplySymmetriesToV2(err)
350+
#CC.symmetries.CustomASR(err)
351+
else:
352+
# We have a supercell, we must generate the dynamical matrix in the supercell
353+
super_structure = self.dyn.structure.generate_supercell(supercell)
354+
fc_supercell = CC.Phonons.GetSupercellFCFromDyn(dyn_grad, np.array(self.dyn.q_tot), \
355+
self.dyn.structure, super_structure)
356+
357+
# Lets generate a new symmetries for the supercell
358+
qe_sym_supcell = CC.symmetries.QE_Symmetry(super_structure)
359+
qe_sym_supcell.SetupFromSPGLIB()
360+
361+
# Apply the symmetries to the fc_supercell matrix
362+
qe_sym_supcell.ApplySymmetriesToV2(fc_supercell)
363+
364+
# Convert back to Q space
365+
dyn_grad = CC.Phonons.GetDynQFromFCSupercell(fc_supercell, np.array(self.dyn.q_tot), \
366+
self.dyn.structure, super_structure)
367+
368+
# Apply the sum rule at gamma
369+
CC.symmetries.CustomASR(dyn_grad[0,:,:])
345370
else:
346-
# We have a supercell, we must generate the dynamical matrix in the supercell
347-
super_structure = self.dyn.structure.generate_supercell(supercell)
348-
fc_supercell = CC.Phonons.GetSupercellFCFromDyn(dyn_grad, np.array(self.dyn.q_tot), \
349-
self.dyn.structure, super_structure)
350-
351-
# Lets generate a new symmetries for the supercell
352-
qe_sym_supcell = CC.symmetries.QE_Symmetry(super_structure)
353-
qe_sym_supcell.SetupFromSPGLIB()
354-
355-
# Apply the symmetries to the fc_supercell matrix
356-
qe_sym_supcell.ApplySymmetriesToV2(fc_supercell)
357-
358-
# Convert back to Q space
359-
dyn_grad = CC.Phonons.GetDynQFromFCSupercell(fc_supercell, np.array(self.dyn.q_tot), \
360-
self.dyn.structure, super_structure)
371+
qe_sym.SymmetrizeFCQ(dyn_grad, np.array(self.dyn.q_stars), asr = "custom")
372+
#qe_sym.SymmetrizeFCQ(err, np.array(self.dyn.q_stars), asr = "custom")
361373

362-
# Apply the sum rule at gamma
363-
CC.symmetries.CustomASR(dyn_grad[0,:,:])
374+
# Just divide the error by the square root the number of symmetries
375+
err /= np.sqrt(qe_sym.QE_nsym * np.prod(self.ensemble.supercell))
364376
else:
365-
qe_sym.SymmetrizeFCQ(dyn_grad, np.array(self.dyn.q_stars), asr = "custom")
366-
#qe_sym.SymmetrizeFCQ(err, np.array(self.dyn.q_stars), asr = "custom")
367-
368-
# Just divide the error by the square root the number of symmetries
369-
err /= np.sqrt(qe_sym.QE_nsym * np.prod(self.ensemble.supercell))
370-
else:
371-
CC.symmetries.CustomASR(dyn_grad[0, :,:])
377+
CC.symmetries.CustomASR(dyn_grad[0, :,:])
372378
t2 = time.time()
373379
print ("Time elapsed to symmetrize the gradient:", t2 - t1, "s")
374380

@@ -468,6 +474,8 @@ def minimization_step(self, custom_function_gradient = None):
468474
is_diag_ok = True
469475
self.minimizer.update_dyn(new_kl_ratio, dyn_grad, struct_grad)
470476

477+
478+
471479
# Get the new dynamical matrix and strucure after the step
472480
new_dyn, new_struct = self.minimizer.get_dyn_struct()
473481

@@ -892,6 +900,9 @@ def init(self, verbosity = False, delete_previous_data = True):
892900
delete_previous_data : bool
893901
If true, it will clean previous minimizations from the free energies, gradients...
894902
"""
903+
904+
if (not self.minim_dyn) and (not self.minim_struct):
905+
raise ValueError("Error, either one of minim_dyn or minim_struct should be True.")
895906

896907
# Check the ensemble size
897908
if not self.ensemble.structures:
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import print_function
3+
from __future__ import division
4+
5+
import sys, os
6+
import numpy as np
7+
import cellconstructor as CC
8+
import cellconstructor.Phonons
9+
10+
import sscha, sscha.Ensemble
11+
import sscha.SchaMinimizer
12+
13+
"""
14+
This test makes a simple relaxation of the sample ensemble
15+
provided within this distribution
16+
"""
17+
18+
def test_gradient_comparison(verbose = False):
19+
total_path = os.path.dirname(os.path.abspath(__file__))
20+
os.chdir(total_path)
21+
22+
DATA_PATH = "../../Examples/ensemble_data_test/"
23+
24+
dyn_start = CC.Phonons.Phonons(os.path.join(DATA_PATH, "dyn"))
25+
26+
27+
# Perform the minimization
28+
ens = sscha.Ensemble.Ensemble(dyn_start, 0, dyn_start.GetSupercell())
29+
ens.load(DATA_PATH, 2, 1000)
30+
31+
minim = sscha.SchaMinimizer.SSCHA_Minimizer(ens)
32+
minim.minim_struct = True
33+
minim.min_step_dyn = 0.5
34+
minim.min_step_struc = 0.5
35+
minim.meaningful_factor = 1e-10
36+
minim.max_ka = 5
37+
38+
class CG:
39+
def __init__(self):
40+
self.ka = 0
41+
def compare_gradients(self, dyn_grad, struct_grad):
42+
ka = self.ka
43+
44+
if not os.path.exists("grad_{}.dat".format(ka)):
45+
np.savetxt("grad_{}.dat".format(ka), dyn_grad[0,:,:])
46+
else:
47+
correct_grad = np.loadtxt("grad_{}.dat".format(ka))
48+
diff = np.max(np.abs(dyn_grad - correct_grad))
49+
print("KA = {} | difference = {}".format(ka, diff))
50+
self.ka += 1
51+
52+
cg = CG()
53+
54+
minim.init()
55+
minim.run(custom_function_gradient = cg.compare_gradients)
56+
minim.finalize()
57+
58+
59+
60+
if __name__ == "__main__":
61+
test_gradient_comparison(True)

tests/test_rho_update/rho.dat

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
4.539220355821488306e-01
2+
1.411526449794866522e+00
3+
2.104710325189953046e+00
4+
1.307973163516430670e+00
5+
9.698244944445526539e-01
6+
6.079171591146247389e-01
7+
8.638305258146310450e-01
8+
1.364249855976386483e+00
9+
1.150362638627647982e+00
10+
9.282376473677631523e-01
11+
7.481192048339360134e-01
12+
3.963286781380914725e-01
13+
8.697536941689273382e-01
14+
8.246715668237457608e-01
15+
3.994984794357198110e-01
16+
5.046320360558806950e-01
17+
9.329591782510011644e-01
18+
1.034134496933409197e+00
19+
1.261538977433160902e+00
20+
8.983074250578575448e-01
21+
1.016582863091882283e+00
22+
1.178658097285228301e+00
23+
5.400118861260385650e-01
24+
5.815053907267632161e-01
25+
1.672259771808280115e+00
26+
1.193477382384837915e+00
27+
1.139073730384374539e+00
28+
8.978012988414395545e-01
29+
8.891090775619920894e-01
30+
2.459552753806575343e+00
31+
9.824445587590747708e-01
32+
1.157391371610775321e+00
33+
1.359971082419375144e+00
34+
1.186643630233218172e+00
35+
7.227648865314558746e-01
36+
1.095252449457546851e+00
37+
5.454369201695307146e-01
38+
1.104938252792029285e+00
39+
7.482719193837685800e-01
40+
1.498463555239989420e+00
41+
5.572994625789204903e-01
42+
7.705556253595574612e-01
43+
6.986817913535011693e-01
44+
5.447730186037899047e-01
45+
1.141109810306783379e+00
46+
9.919214313253675863e-01
47+
8.552194270819423183e-01
48+
8.114897140621727401e-01
49+
7.490298145732271484e-01
50+
5.733037139914664015e-01
51+
7.814040834364547328e-01
52+
1.184479312351917502e+00
53+
1.431239307147331496e+00
54+
5.745975497809883148e-01
55+
6.852131914998749185e-01
56+
7.331097689064051126e-01
57+
4.424517778140502067e-01
58+
1.648708815350376167e+00
59+
6.498338247002786172e-01
60+
8.659896174386515488e-01
61+
6.691119551407023192e-01
62+
5.392713915162969940e-01
63+
1.251206844589672906e+00
64+
4.362932779004319306e-01
65+
5.922883410805960258e-01
66+
8.794036099552269281e-01
67+
9.019277098138261950e-01
68+
1.160878890503636240e+00
69+
1.105650006125480811e+00
70+
1.165694660516127801e+00
71+
9.486042209926186519e-01
72+
5.014128121316550057e-01
73+
1.082562669335646488e+00
74+
6.828508512622004645e-01
75+
6.216703952241426911e-01
76+
6.891275313437438266e-01
77+
9.977369856535546200e-01
78+
7.427079255525675938e-01
79+
7.694943795491897554e-01
80+
1.113645044986756760e+00
81+
1.560928717016897282e+00
82+
7.277430228963687187e-01
83+
5.139526369854987564e-01
84+
1.004312304546424173e+00
85+
3.358750079123379861e-01
86+
4.447819855182386095e-01
87+
1.216612868580458917e+00
88+
4.800835463817738069e-01
89+
6.242423793254461284e-01
90+
9.930756363113935059e-01
91+
4.709592911549231875e-01
92+
1.031033707302008828e+00
93+
1.234728079118472044e+00
94+
1.648877984075169723e+00
95+
1.387104853294882867e+00
96+
6.636840015273967053e-01
97+
7.958957361111163031e-01
98+
8.739496782321736212e-01
99+
8.012650880673536369e-01
100+
6.980785469953588729e-01

0 commit comments

Comments
 (0)