1 /*-------------------------------------------------------------------
2 Copyright 2011 Ravishankar Sundararaman
3 
4 This file is part of JDFTx.
5 
6 JDFTx is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 JDFTx is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with JDFTx.  If not, see <http://www.gnu.org/licenses/>.
18 -------------------------------------------------------------------*/
19 
20 #include <commands/command.h>
21 #include <electronic/Everything.h>
22 
23 EnumStringMap<GridInfo::LatticeType> lattTypeMap
24 (	GridInfo::Triclinic, "Triclinic",
25 	GridInfo::Monoclinic, "Monoclinic",
26 	GridInfo::Orthorhombic, "Orthorhombic",
27 	GridInfo::Tetragonal, "Tetragonal",
28 	GridInfo::Rhombohedral, "Rhombohedral",
29 	GridInfo::Hexagonal, "Hexagonal",
30 	GridInfo::Cubic, "Cubic"
31 );
32 
33 EnumStringMap<GridInfo::LatticeModification> lattModMap
34 (	GridInfo::BodyCentered, "Body-Centered",
35 	GridInfo::BaseCentered, "Base-Centered",
36 	GridInfo::FaceCentered, "Face-Centered"
37 );
38 
39 struct CommandLattice : public Command
40 {
CommandLatticeCommandLattice41 	CommandLattice() : Command("lattice", "jdftx/Ionic/Geometry")
42 	{
43 		format = " [<modification>] <lattice> <parameters...>\n"
44 			"\t| \\\n\t<R00> <R01> <R02> \\\n\t<R10> <R11> <R12> \\\n\t<R20> <R21> <R22>";
45 		comments = "Specify lattice by name and parameters, or explicitly using lattice vectors.\n"
46 			"\n"
47 			"The options for the first syntax ([<modification>] <lattice> <parameters...> scheme) are:\n"
48 			"+ Triclinic <a> <b> <c> <alpha> <beta> <gamma>\n"
49 			"+ [Base-Centered] Monoclinic <a> <b> <c> <beta>\n"
50 			"+ [Base|Body|Face-Centered] Orthorhombic <a> <b> <c>\n"
51 			"+ [Body-Centered] Tetragonal <a> <c>\n"
52 			"+ Rhombohedral <a> <alpha>\n"
53 			"+ Hexagonal <a> <c>\n"
54 			"+ [Body|Face-Centered] Cubic <a>\n"
55 			"where lengths <a>,<b>,<c> are in bohrs and angles <alpha>,<beta,<gamma> are in degrees.\n"
56 			"\n"
57 			"Alternately, the second syntax directly specifies the transformation\n"
58 			"matrix from lattice to Cartesian coordinates. Therefore, the columns\n"
59 			"of this 3x3 matrix are the lattice vectors in bohrs.\n"
60 			"\n"
61 			"NOTE: other DFT codes may specify lattice vectors in rows;\n"
62 			"confirm that you switch them to columns if porting an input file to JDFTx.";
63 	}
64 
processCommandLattice65 	void process(ParamList& pl, Everything& e)
66 	{	GridInfo& g = e.gInfo;
67 		//Check for named lattice specification:
68 		try { pl.get(g.latticeModification, GridInfo::Simple, lattModMap, "modification", true); } catch(string) { pl.rewind(); } //no modification
69 		try { pl.get(g.latticeType, GridInfo::Manual, lattTypeMap, "type", true); } catch(string) { pl.rewind(); } //Not a named lattice
70 		//Read parameters:
71 		g.alpha = 90.;
72 		g.beta  = 90.;
73 		g.gamma = 90.;
74 		switch(g.latticeType)
75 		{
76 			case GridInfo::Manual:
77 			{	for(int j=0; j<3; j++) for(int k=0; k<3; k++)
78 				{	ostringstream oss; oss << "R" << j << k;
79 					try
80 					{	pl.get(g.R(j,k), 0.0, oss.str(), true);
81 					}
82 					catch(string)
83 					{	if(j==0 && k<2) throw string("First two parameters match neither <R00> <R01> ..., nor valid [<modification>] <lattice> ...");
84 						else throw; //propagate Rjk parse error
85 					}
86 				}
87 				break;
88 			}
89 			case GridInfo::Triclinic:
90 			{	pl.get(g.a, 0., "a", true);
91 				pl.get(g.b, 0., "b", true);
92 				pl.get(g.c, 0., "c", true);
93 				pl.get(g.alpha, 0., "alpha", true);
94 				pl.get(g.beta,  0., "beta", true);
95 				pl.get(g.gamma, 0., "gamma", true);
96 				break;
97 			}
98 			case GridInfo::Monoclinic:
99 			{	pl.get(g.a, 0., "a", true);
100 				pl.get(g.b, 0., "b", true);
101 				pl.get(g.c, 0., "c", true);
102 				pl.get(g.beta,  0., "beta", true);
103 				break;
104 			}
105 			case GridInfo::Orthorhombic:
106 			{	pl.get(g.a, 0., "a", true);
107 				pl.get(g.b, 0., "b", true);
108 				pl.get(g.c, 0., "c", true);
109 				break;
110 			}
111 			case GridInfo::Tetragonal:
112 			{	pl.get(g.a, 0., "a", true);
113 				g.b = g.a;
114 				pl.get(g.c, 0., "c", true);
115 				break;
116 			}
117 			case GridInfo::Rhombohedral:
118 			{	pl.get(g.a, 0., "a", true);
119 				g.b = g.a;
120 				g.c = g.a;
121 				pl.get(g.alpha, 0., "alpha", true);
122 				g.beta  = g.alpha;
123 				g.gamma = g.alpha;
124 				break;
125 			}
126 			case GridInfo::Hexagonal:
127 			{	pl.get(g.a, 0., "a", true);
128 				g.b = g.a;
129 				pl.get(g.c, 0., "c", true);
130 				g.gamma = 120.;
131 				break;
132 			}
133 			case GridInfo::Cubic:
134 			{	pl.get(g.a, 0., "a", true);
135 				g.b = g.a;
136 				g.c = g.a;
137 				break;
138 			}
139 		}
140 		//Check parameters and compute the lattice vectors:
141 		if(g.latticeType != GridInfo::Manual)
142 			g.setLatticeVectors();
143 	}
144 
printStatusCommandLattice145 	void printStatus(Everything& e, int iRep)
146 	{	const GridInfo& g = e.gInfo;
147 		if(g.latticeType == GridInfo::Manual)
148 		{	matrix3<> Runscaled;
149 			for(int k=0; k<3; k++)
150 				Runscaled.set_col(k, (1./g.lattScale[k]) * g.R.column(k));
151 			for(int j=0; j<3; j++)
152 			{	logPrintf(" \\\n\t");
153 				for(int k=0; k<3; k++)
154 					logPrintf("%20.15lf ", Runscaled(j,k));
155 			}
156 		}
157 		else
158 		{	if(g.latticeModification != GridInfo::Simple)
159 				logPrintf("%s ", lattModMap.getString(g.latticeModification));
160 			logPrintf("%s ", lattTypeMap.getString(g.latticeType));
161 			switch(g.latticeType)
162 			{	case GridInfo::Manual: break; //never encountered
163 				case GridInfo::Triclinic: logPrintf("%lg %lg %lg %lg %lg %lg", g.a, g.b, g.c, g.alpha, g.beta, g.gamma); break;
164 				case GridInfo::Monoclinic: logPrintf("%lg %lg %lg %lg", g.a, g.b, g.c, g.beta); break;
165 				case GridInfo::Orthorhombic: logPrintf("%lg %lg %lg", g.a, g.b, g.c); break;
166 				case GridInfo::Tetragonal: logPrintf("%lg %lg", g.a, g.c); break;
167 				case GridInfo::Rhombohedral: logPrintf("%lg %lg", g.a, g.alpha); break;
168 				case GridInfo::Hexagonal: logPrintf("%lg %lg", g.a, g.c); break;
169 				case GridInfo::Cubic: logPrintf("%lg", g.a); break;
170 			}
171 		}
172 	}
173 }
174 commandLattice;
175 
176 
177 struct CommandLattScale : public Command
178 {
CommandLattScaleCommandLattScale179 	CommandLattScale() : Command("latt-scale", "jdftx/Ionic/Geometry")
180 	{
181 		format = "<s0> <s1> <s2>";
182 		comments = "Scale lattice vector i by factor <si>. This may be convenient\n"
183 			"for unit conversions, or specifying lattice vectors of supercells.";
184 		hasDefault = true;
185 
186 		require("lattice");
187 	}
188 
processCommandLattScale189 	void process(ParamList& pl, Everything& e)
190 	{	//check if any parameters have been specified:
191 		string key; pl.get(key, string(), ""); pl.rewind();
192 		if(!key.length()) { e.gInfo.lattScale = vector3<>(1.,1.,1.); return; }
193 		//Read parameters:
194 		for(int k=0; k<3; k++)
195 		{	ostringstream oss; oss << "s" << k;
196 			pl.get(e.gInfo.lattScale[k], 1., oss.str(), true);
197 			e.gInfo.R.set_col(k, e.gInfo.lattScale[k] * e.gInfo.R.column(k));
198 		}
199 	}
200 
printStatusCommandLattScale201 	void printStatus(Everything& e, int iRep)
202 	{	for(int k=0; k<3; k++) logPrintf("%lg ", e.gInfo.lattScale[k]);
203 	}
204 }
205 commandLattScale;
206 
207 
208 struct CommandLattMoveScale : public Command
209 {
CommandLattMoveScaleCommandLattMoveScale210 	CommandLattMoveScale() : Command("latt-move-scale", "jdftx/Ionic/Optimization")
211 	{
212 		format = "<s0> <s1> <s2>";
213 		comments = "Preconditioning factor for each lattice vector (must be commensurate with symmetries).\n"
214 			"Note that setting the factor for a direction to zero prevents it from being optimized,\n"
215 			"which could especially be useful for lattice optimization of 1D and 2D systems.";
216 		hasDefault = true;
217 	}
218 
processCommandLattMoveScale219 	void process(ParamList& pl, Everything& e)
220 	{	vector3<>& s = e.cntrl.lattMoveScale;
221 		pl.get(s[0], 1., "s0");
222 		pl.get(s[1], 1., "s1");
223 		pl.get(s[2], 1., "s2");
224 	}
225 
printStatusCommandLattMoveScale226 	void printStatus(Everything& e, int iRep)
227 	{	const vector3<>& s = e.cntrl.lattMoveScale;
228 		logPrintf("%lg %lg %lg", s[0], s[1], s[2]);
229 	}
230 }
231 commandLattMoveScale;
232 
233 EnumStringMap<CoordsType> coordsMap(
234 	CoordsLattice, "Lattice",
235 	CoordsCartesian, "Cartesian" );
236 
237 struct CommandCoordsType : public Command
238 {
CommandCoordsTypeCommandCoordsType239 	CommandCoordsType() : Command("coords-type", "jdftx/Ionic/Geometry")
240 	{
241 		format = "<coords>=" + coordsMap.optionList();
242 		comments = "Coordinate system used in specifying ion positions (default: Lattice).\n"
243 			"+ Lattice coordinates correspond to fractional coordinates in terms of the\n"
244 			"  lattice vectors, which is usually more convenient for periodic systems.\n"
245 			"+ Cartesian coordinates specify absolute atom positions in bohr units,\n"
246 			"  which is usually more convenient for non-periodic systems like molecules.\n"
247 			"\n"
248 			"NOTE: other DFT codes may specify Cartesian coordinates in Angstroms;\n"
249 			"confirm that you switch them to bohrs if porting an input file to JDFTx.";
250 		hasDefault = true;
251 	}
252 
processCommandCoordsType253 	void process(ParamList& pl, Everything& e)
254 	{	pl.get(e.iInfo.coordsType, CoordsLattice, coordsMap, "coords");
255 	}
256 
printStatusCommandCoordsType257 	void printStatus(Everything& e, int iRep)
258 	{	fputs(coordsMap.getString(e.iInfo.coordsType), globalLog);
259 	}
260 }
261 commandCoordsType;
262