1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package ffx.potential.commands;
39
40 import ffx.crystal.Crystal;
41 import ffx.crystal.LatticeSystem;
42 import ffx.potential.bonded.Atom;
43 import ffx.potential.cli.PotentialCommand;
44 import ffx.utilities.FFXBinding;
45 import picocli.CommandLine.Command;
46 import picocli.CommandLine.Option;
47 import picocli.CommandLine.Parameters;
48
49 import java.io.BufferedWriter;
50 import java.io.File;
51 import java.io.FileWriter;
52 import java.io.IOException;
53 import java.util.HashMap;
54 import java.util.Iterator;
55 import java.util.Map;
56
57 import static java.lang.String.format;
58 import static org.apache.commons.io.FilenameUtils.getName;
59 import static org.apache.commons.io.FilenameUtils.removeExtension;
60 import static org.apache.commons.math3.util.FastMath.cos;
61
62
63
64
65
66
67
68 @Command(name = "XYZtoQE", description = "Generate QE input from a XYZ file.")
69 public class ExportQE extends PotentialCommand {
70
71
72
73
74 @Option(names = {"--ns", "--nstep"}, paramLabel = "500", defaultValue = "500",
75 description = "Number of structural optimization steps performed in this run.")
76 private int nStep;
77
78
79
80
81 @Option(names = {"--ec", "--etot_conv_thr"}, paramLabel = "1.0e-6", defaultValue = "1.0e-6",
82 description = "Convergence threshold on total energy (a.u) for ionic minimization.")
83 private double etotConvThr;
84
85
86
87
88 @Option(names = {"--ef", "--forc_conv_thr"}, paramLabel = "1.0e-4", defaultValue = "1.0e-4",
89 description = "Convergence threshold on forces (a.u) for ionic minimization.")
90 private double forcConvThr;
91
92
93
94
95 @Option(names = {"--ke", "--ecutwfc"}, paramLabel = "50.0", defaultValue = "50.0",
96 description = "Kinetic energy cutoff (Ry) for wavefunctions.")
97 private double ecutwfc;
98
99
100
101
102 @Option(names = {"--rho", "--ecutrho"}, paramLabel = "500.0", defaultValue = "500.0",
103 description = "Kinetic energy cutoff (Ry) for charge density and potential.")
104 private double ecutrho;
105
106
107
108
109 @Option(names = {"--em", "--electron_maxstep"}, paramLabel = "1500", defaultValue = "1500",
110 description = "Maximum number of iterations in a scf step.")
111 private int electronMaxstep;
112
113
114
115
116 @Option(names = {"--ct", "--conv_thr"}, paramLabel = "1.0e-8", defaultValue = "1.0e-8",
117 description = "Convergence threshold for self consistency.")
118 private double convThr;
119
120
121
122
123 @Option(names = {"--mb", "--mixing_beta"}, paramLabel = "0.5", defaultValue = "0.5",
124 description = "Mixing factor for self-consistency.")
125 private double mixingBeta;
126
127
128
129
130 @Option(names = {"--hx", "--hexagonal"}, paramLabel = "true", defaultValue = "true",
131 description = "Perform QE on hexagonal system.")
132 private boolean hexagonal;
133
134
135
136
137 @Parameters(arity = "1", paramLabel = "file",
138 description = "XYZ file to be converted.")
139 private String filename = null;
140
141 public ExportQE() {
142 super();
143 }
144
145 public ExportQE(FFXBinding binding) {
146 super(binding);
147 }
148
149 public ExportQE(String[] args) {
150 super(args);
151 }
152
153 @Override
154 public ExportQE run() {
155
156 if (!init()) {
157 return this;
158 }
159
160
161 activeAssembly = getActiveAssembly(filename);
162 if (activeAssembly == null) {
163 logger.info(helpString());
164 return this;
165 }
166
167
168 filename = activeAssembly.getFile().getAbsolutePath();
169 logger.info(format("\n Converting %s to QE format\n", filename));
170
171 String dirString = getBaseDirString(filename);
172 String name = removeExtension(getName(filename));
173 File modelFile = new File(dirString + name + ".in");
174
175 Crystal crystal = activeAssembly.getCrystal().getUnitCell();
176 double xtalA = crystal.a;
177 double xtalB = crystal.b;
178 double xtalC = crystal.c;
179
180 HashMap<String, Double> atomTypes = new HashMap<>();
181 StringBuilder atomicPositions = new StringBuilder();
182
183 Atom[] atoms = activeAssembly.getAtomArray();
184 for (Atom atom : atoms) {
185 if (!atomTypes.containsKey(atom.getName())) {
186 atomTypes.put(atom.getName(), atom.getAtomType().atomicWeight);
187 }
188 double[] xyz = atom.getXYZ(null);
189 crystal.toFractionalCoordinates(xyz, xyz);
190 atomicPositions.append(format("%2s %16.12f %16.12f %16.12f%n", atom.getName(), xyz[0], xyz[1], xyz[2]));
191 }
192
193 try (BufferedWriter bwQE = new BufferedWriter(new FileWriter(modelFile))) {
194
195 bwQE.write(format("&CONTROL%n" +
196 "\tcalculation = 'vc-relax',%n" +
197 "\trestart_mode = 'from_scratch',%n" +
198 "\tprefix = '%s',%n" +
199 "\tetot_conv_thr = %6.4E,%n" +
200 "\tforc_conv_thr = %6.4E,%n" +
201 "\tnstep = %d,%n" +
202 "/%n", name, etotConvThr, forcConvThr, nStep));
203
204
205 bwQE.write(format("&SYSTEM%n" +
206 "\tspace_group = %d,%n" +
207 "\tnat = %d,%n" +
208 "\tntyp = %d,%n" +
209 "\ta = %16.12f%n" +
210 "\tb = %16.12f%n" +
211 "\tc = %16.12f%n" +
212 "\tcosAB = %16.12f%n" +
213 "\tcosAC = %16.12f%n" +
214 "\tcosBC = %16.12f%n" +
215 "\tecutwfc = %6.4f,%n" +
216 "\tecutrho = %6.4f,%n" +
217 "\tvdw_corr = 'XDM',%n",
218 crystal.spaceGroup.number,
219 activeAssembly.getAtomList().size(),
220 atomTypes.size(),
221 xtalA, xtalB, xtalC,
222 cos(crystal.gamma), cos(crystal.beta), cos(crystal.alpha),
223 ecutwfc, ecutrho));
224 if (crystal.spaceGroup.latticeSystem == LatticeSystem.HEXAGONAL_LATTICE) {
225 bwQE.write("\trhombohedral = .FALSE.,\n");
226 }
227 bwQE.write("/\n");
228
229
230 bwQE.write(format("&ELECTRONS%n" +
231 "\telectron_maxstep = %d,%n" +
232 "\tconv_thr = %6.4E,%n" +
233 "\tscf_must_converge = .TRUE.,%n" +
234 "\tmixing_beta = %5.3f,%n" +
235 "/%n", electronMaxstep, convThr, mixingBeta));
236
237
238 bwQE.write("&IONS\n" +
239 "\tion_dynamics = 'bfgs',\n" +
240 "/\n");
241
242
243 bwQE.write("&CELL\n" +
244 "\tcell_dynamics = 'bfgs',\n" +
245 "/\n");
246
247
248 StringBuilder line = new StringBuilder();
249 Iterator<Map.Entry<String, Double>> it = atomTypes.entrySet().iterator();
250 while (it.hasNext()) {
251 Map.Entry<String, Double> pair = it.next();
252 line.append(" ").append(pair.getKey()).append(" ").append(pair.getValue())
253 .append(" ").append(pair.getKey()).append(".b86bpbe.UPF\n");
254 }
255 bwQE.write("ATOMIC_SPECIES\n" + line + "\n");
256
257
258 bwQE.write("ATOMIC_POSITIONS crystal_sg\n" + atomicPositions + "\n");
259
260
261 int k1;
262 int k2;
263 int k3;
264 if (xtalA < 5) {
265 k1 = 8;
266 } else if (xtalA <= 7) {
267 k1 = 6;
268 } else if (xtalA <= 12) {
269 k1 = 4;
270 } else {
271 k1 = 2;
272 }
273 if (xtalB < 5) {
274 k2 = 8;
275 } else if (xtalB <= 7) {
276 k2 = 6;
277 } else if (xtalB <= 12) {
278 k2 = 4;
279 } else {
280 k2 = 2;
281 }
282 if (xtalC < 5) {
283 k3 = 8;
284 } else if (xtalC <= 7) {
285 k3 = 6;
286 } else if (xtalC <= 12) {
287 k3 = 4;
288 } else {
289 k3 = 2;
290 }
291 bwQE.write("K_POINTS automatic\n" + k1 + " " + k2 + " " + k3 + " 1 1 1\n");
292 } catch (IOException e) {
293 logger.severe(" Error writing QE input file: " + e.getMessage());
294 }
295
296 logger.info(format(" Saved QE file: %s", modelFile));
297 return this;
298 }
299 }