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 
24 EnumStringMap<ExCorrType> exCorrTypeMap(
25 	ExCorrLDA_PZ, "lda", //Default LDA is PZ
26 	ExCorrLDA_PZ, "lda-PZ",
27 	ExCorrLDA_PW, "lda-PW",
28 	ExCorrLDA_PW_prec, "lda-PW-prec",
29 	ExCorrLDA_VWN, "lda-VWN",
30 	ExCorrLDA_Teter, "lda-Teter",
31 	ExCorrGGA_PBE, "gga", //Default GGA is PBE
32 	ExCorrGGA_PBE, "gga-PBE",
33 	ExCorrGGA_PBEsol, "gga-PBEsol",
34 	ExCorrGGA_PW91, "gga-PW91",
35 	ExCorrMGGA_TPSS, "mgga-TPSS",
36 	ExCorrMGGA_revTPSS, "mgga-revTPSS",
37 	ExCorrORB_GLLBsc, "orb-GLLBsc",
38 	ExCorrPOT_LB94, "pot-LB94",
39 	ExCorrHYB_PBE0, "hyb-PBE0",
40 	ExCorrHYB_HSE06, "hyb-HSE06",
41 	ExCorrHYB_HSE12, "hyb-HSE12",
42 	ExCorrHYB_HSE12s, "hyb-HSE12s",
43 	ExCorrHF, "Hartree-Fock"
44 );
45 EnumStringMap<ExCorrType> exCorrDescriptionMap(
46 	ExCorrLDA_PZ, "Perdew-Zunger LDA",
47 	ExCorrLDA_PW, "Perdew-Wang LDA",
48 	ExCorrLDA_PW_prec, "Perdew-Wang LDA with extended precision (used by PBE)",
49 	ExCorrLDA_VWN, "Vosko-Wilk-Nusair LDA",
50 	ExCorrLDA_Teter, "Teter93 LSDA",
51 	ExCorrGGA_PBE, "Perdew-Burke-Ernzerhof GGA",
52 	ExCorrGGA_PBEsol, "Perdew-Burke-Ernzerhof GGA reparametrized for solids",
53 	ExCorrGGA_PW91, "Perdew-Wang GGA",
54 	ExCorrMGGA_TPSS, "Tao-Perdew-Staroverov-Scuseria meta GGA",
55 	ExCorrMGGA_revTPSS, "revised Tao-Perdew-Staroverov-Scuseria meta GGA",
56 	ExCorrORB_GLLBsc, "Orbital-dependent GLLB-sc potential (no total energy)",
57 	ExCorrPOT_LB94, "van Leeuwen-Baerends model potential (no total energy)",
58 	ExCorrHYB_PBE0, "Hybrid PBE with 1/4 exact exchange",
59 	ExCorrHYB_HSE06, "HSE06 'wPBEh' hybrid with 1/4 screened exact exchange",
60 	ExCorrHYB_HSE12, "Reparametrized screened exchange functional for accuracy (w=0.185 A^-1 and a=0.313)",
61 	ExCorrHYB_HSE12s, "Reparametrized screened exchange functional for k-point convergence (w=0.408 A^-1 and a=0.425)",
62 	ExCorrHF, "Full exact exchange with no correlation"
63 );
64 
65 EnumStringMap<KineticType> kineticTypeMap(
66 	KineticTF, "lda-TF",
67 	KineticVW, "gga-vW",
68 	KineticPW91, "gga-PW91k"
69 );
70 EnumStringMap<KineticType> kineticDescriptionMap(
71 	KineticTF, "Thomas-Fermi LDA kinetic energy",
72 	KineticVW, "von Weisacker correction to LDA kinetic energy",
73 	KineticPW91, "Perdew-Wang GGA kinetic energy parameterized by Lembarki and Chermette"
74 );
75 
76 
77 #ifdef LIBXC_ENABLED
78 #include <xc.h>
79 #include <xcMap.h> //autogenerated during cmake
80 
81 //Get description by temporarily initializing functional:
getLibXCdescription(const string & name,const EnumStringMap<int> & map)82 string getLibXCdescription(const string& name, const EnumStringMap<int>& map)
83 {	int xcCode = 0;
84 	bool xcFound = map.getEnum(name.c_str(), xcCode);
85 	assert(xcFound && xcCode);
86 	xc_func_type func;
87 	if(xc_func_init(&func, xcCode, XC_UNPOLARIZED) != 0)
88 		die("Error obtaining description for LibXC functional %s.\n", name.c_str());
89 	string desc(func.info->name);
90 	xc_func_end(&func);
91 	return desc;
92 }
getLibXCdescription_X(const string & name)93 string getLibXCdescription_X(const string& name) { return getLibXCdescription(name, xcMap_X); }
getLibXCdescription_C(const string & name)94 string getLibXCdescription_C(const string& name) { return getLibXCdescription(name, xcMap_C); }
getLibXCdescription_XC(const string & name)95 string getLibXCdescription_XC(const string& name) { return getLibXCdescription(name, xcMap_XC); }
getLibXCdescription_K(const string & name)96 string getLibXCdescription_K(const string& name) { return getLibXCdescription(name, xcMap_K); }
97 #endif //LIBXC_ENABLED
98 
99 
100 struct CommandElecExCorr : public Command
101 {
CommandElecExCorrCommandElecExCorr102 	CommandElecExCorr(const char* cmdName = "elec-ex-corr", string path="jdftx/Electronic/Functional") : Command(cmdName, path)
103 	{
104 		format = "<functional>";
105 		comments = "Specify the exchange-correlation functional, where <functional> is one of:"
106 			+ addDescriptions(exCorrTypeMap.optionList(), linkDescription(exCorrTypeMap, exCorrDescriptionMap))
107 			+ ".\n\nNote that lda is an alias for lda-pz, and gga for gga-pbe.\n\n";
108 		hasDefault = true;
109 		emptyParamError = "   eXchange/Correlation functional(s) must be specified.";
110 
111 		#ifdef LIBXC_ENABLED
112 		format += "\n\t| <funcX> <funcC>\n\t| <funcXC>";
113 		comments +=
114 			"The second and third lines use eXchange/Correlation functionals from libXC \\cite LibXC.\n"
115 			"The exact entries below will depend on the version of LibXC linked against.\n"
116 			"Here, <funcX> is one of:"
117 			+ addDescriptions(xcMap_X.optionList(), getLibXCdescription_X)
118 			+ ",\n\n<funcC> is one of:"
119 			+ addDescriptions(xcMap_C.optionList(), getLibXCdescription_C)
120 			+ ",\n\nand <funcXC> is one of:"
121 			+ addDescriptions(xcMap_XC.optionList(), getLibXCdescription_XC)
122 			+ ".";
123 		#else
124 		comments += "Additional functionals can be enabled by compiling with LibXC support \\cite LibXC.";
125 		#endif
126 	}
127 
processCommandElecExCorr128 	void process(ParamList& pl, Everything& e)
129 	{	process(pl, e.exCorr);
130 	}
131 
printStatusCommandElecExCorr132 	void printStatus(Everything& e, int iRep)
133 	{	printStatus(e.exCorr);
134 	}
135 
136 protected:
processCommandElecExCorr137 	void process(ParamList& pl, ExCorr& exCorr)
138 	{	string key;
139 		pl.get(key, string(), "functional");
140 		if(key.length()) //Otherwise default functional set by ExCorr constructor
141 		{	if(exCorrTypeMap.getEnum(key.c_str(), exCorr.exCorrType)) //Found internal ExCorr functional
142 			{	//Set the functional name:
143 				exCorr.xcName = string(exCorrTypeMap.getString(exCorr.exCorrType));
144 			}
145 			#ifdef LIBXC_ENABLED
146 			else if(xcMap_X.getEnum(key.c_str(), exCorr.xcExchange)) {} //Found LibXC Exchange functional
147 			else if(xcMap_XC.getEnum(key.c_str(), exCorr.xcExcorr)) {} //Found LibXC ExCorr functional
148 			#endif
149 			else throw key + " is not a recognized exchange or exchange-correlation functional";
150 		}
151 		#ifdef LIBXC_ENABLED
152 		if((exCorr.xcExchange || exCorr.xcExcorr) && !exCorr.xcCorr)
153 		{	//LibXC will be used:
154 			exCorr.exCorrType = ExCorrLibXC;
155 			if(exCorr.xcExchange)
156 				pl.get(exCorr.xcCorr, 0, xcMap_C, "funcC", true); //required correlation functional
157 			//Set the short name:
158 			if(exCorr.xcExcorr)
159 				exCorr.xcName = string(xcMap_XC.getString(exCorr.xcExcorr));
160 			else
161 				exCorr.xcName = string(xcMap_X.getString(exCorr.xcExchange))
162 					+ ':' + string(xcMap_C.getString(exCorr.xcCorr));
163 		}
164 		#endif
165 	}
166 
printStatusCommandElecExCorr167 	void printStatus(const ExCorr& exCorr)
168 	{	switch(exCorr.exCorrType)
169 		{
170 			#ifdef LIBXC_ENABLED
171 			case ExCorrLibXC:
172 			{	if(exCorr.xcExcorr)
173 					logPrintf("%s", xcMap_XC.getString(exCorr.xcExcorr));
174 				else
175 					logPrintf("%s %s", xcMap_X.getString(exCorr.xcExchange), xcMap_C.getString(exCorr.xcCorr));
176 				break;
177 			}
178 			#endif
179 			default:
180 				logPrintf("%s", exCorrTypeMap.getString(exCorr.exCorrType));
181 		}
182 	}
183 }
184 commandElecExCorr;
185 
186 
187 struct CommandElecExCorrCompare : public CommandElecExCorr
188 {
CommandElecExCorrCompareCommandElecExCorrCompare189 	CommandElecExCorrCompare() : CommandElecExCorr("elec-ex-corr-compare")
190 	{
191 		format = "<functional>";
192 		comments =
193 			"Compute total energies for other functionals at the final state for comparison.\n"
194 			"The available options for each parameter are identical to elec-ex-corr.\n"
195 			"\n"
196 			"This command may be specified multiple times. It invokes 'dump End ExcCompare'\n"
197 			"automatically, but the compute frequency can be controlled using dump explicitly.";
198 		hasDefault = false;
199 		allowMultiple = true;
200 		emptyParamError = "   eXchange/Correlation functional(s) must be specified.";
201 
202 		#ifdef LIBXC_ENABLED
203 		format += "\n\t| <funcX> <funcC>\n\t| <funcXC>";
204 		#endif
205 		forbid("fix-electron-density");
206 		forbid("fix-electron-potential");
207 	}
208 
processCommandElecExCorrCompare209 	void process(ParamList& pl, Everything& e)
210 	{	e.exCorrDiff.push_back(std::shared_ptr<ExCorr>(new ExCorr));
211 		CommandElecExCorr::process(pl, *e.exCorrDiff.back());
212 		e.dump.insert(std::make_pair(DumpFreq_End, DumpExcCompare));
213 	}
214 
printStatusCommandElecExCorrCompare215 	void printStatus(Everything& e, int iRep)
216 	{	CommandElecExCorr::printStatus(*e.exCorrDiff[iRep]);
217 	}
218 }
219 commandElecExCorrCompare;
220 
221 
222 struct CommandFluidExCorr : public CommandElecExCorr
223 {
CommandFluidExCorrCommandFluidExCorr224 	CommandFluidExCorr() : CommandElecExCorr("fluid-ex-corr", "jdftx/Fluid/Parameters")
225 	{
226 		format = "<kinetic> [<exchange-correlation>]";
227 		comments =
228 			"Kinetic energy functional for fluid convolution coupling where <kinetic> is one of:"
229 			+ addDescriptions(kineticTypeMap.optionList(), linkDescription(kineticTypeMap, kineticDescriptionMap)) +
230 			#ifdef LIBXC_ENABLED
231 			addDescriptions(xcMap_K.optionList(), getLibXCdescription_K) +
232 			#endif
233 			".\n\nThe available options for <exchange-correlation> are identical to elec-ex-corr\n"
234 			"and defaults to lda-pz.";
235 		hasDefault = true;
236 		emptyParamError = "   A kinetic energy functional must be specified.";
237 		require("elec-ex-corr");
238 	}
239 
processCommandFluidExCorr240 	void process(ParamList& pl, Everything& e)
241 	{	ExCorr& fluidExCorr = e.eVars.fluidParams.exCorr;
242 		//Get kinetic energy functional:
243 		string key; pl.get(key, string(), "kinetic");
244 		if(!key.length()) fluidExCorr.kineticType = KineticTF; //default: Thomas-Fermi
245 		else
246 		{	if(kineticTypeMap.getEnum(key.c_str(), fluidExCorr.kineticType)) {} //Found internal kinetic functional
247 			#ifdef LIBXC_ENABLED
248 			else if(xcMap_K.getEnum(key.c_str(), fluidExCorr.xcKinetic)) { fluidExCorr.kineticType = KineticLibXC; } //Found LibXC kinetic functional
249 			#endif
250 			else throw key + " is not a recognized kinetic energy functional";
251 		}
252 		//Set default exchange-correlation to be LDA
253 		fluidExCorr.exCorrType =  ExCorrLDA_PZ;
254 		fluidExCorr.xcName = exCorrTypeMap.getString(ExCorrLDA_PZ);
255 
256 		CommandElecExCorr::process(pl, fluidExCorr);
257 	}
258 
printStatusCommandFluidExCorr259 	void printStatus(Everything& e, int iRep)
260 	{	const ExCorr& fluidExCorr = e.eVars.fluidParams.exCorr;
261 		switch(fluidExCorr.exCorrType)
262 		{
263 			#ifdef LIBXC_ENABLED
264 			case KineticLibXC: logPrintf("%s ", xcMap_K.getString(fluidExCorr.xcKinetic)); break;
265 			#endif
266 			default: logPrintf("%s ", kineticTypeMap.getString(fluidExCorr.kineticType));
267 		}
268 		CommandElecExCorr::printStatus(fluidExCorr);
269 	}
270 }
271 commandFluidExCorr;
272 
273 
274 struct CommandVanDerWaals : public Command
275 {
CommandVanDerWaalsCommandVanDerWaals276 	CommandVanDerWaals() : Command("van-der-waals", "jdftx/Electronic/Functional")
277 	{
278 		format = "[<scaleOverride>=0]";
279 		comments =
280 			"DFT+D2 pair-potential corrections for the long range Van der Waals\n"
281 			"interaction [S. Grimme, J. Comput. Chem. 27: 1787–1799 (2006)].\n"
282 			"\n"
283 			"Default scale factors are available for the gga-PBE, hyb-gga-xc-b3lyp\n"
284 			"and mgga-TPSS exchange-correlation functionals (see elec-ex-corr).\n"
285 			"Manually specify <scaleOverride> to use with other functionals";
286 	}
287 
processCommandVanDerWaals288 	void process(ParamList& pl, Everything& e)
289 	{	e.iInfo.vdWenable = true;
290 		pl.get(e.iInfo.vdWscale, 0., "scaleOverride");
291 	}
292 
printStatusCommandVanDerWaals293 	void printStatus(Everything& e, int iRep)
294 	{	if(e.iInfo.vdWscale) logPrintf("%lg", e.iInfo.vdWscale);
295 	}
296 }
297 commandVanDerWaals;
298 
299 
300 struct CommandExchangeParameters : public Command
301 {
CommandExchangeParametersCommandExchangeParameters302 	CommandExchangeParameters() : Command("exchange-parameters", "jdftx/Electronic/Functional")
303 	{
304 		format = "<exxScale> [<exxOmega>=0]";
305 		comments =
306 			"Override exact-exchange parameters in a hybrid functional.\n"
307 			"Here <exxScale> is the scale fraction of exact exchange,\n"
308 			"and <exxOmega> is the screening parameter.\n"
309 			"This is only supported for internal hybrid functionals PBE0\n"
310 			"and HSExx, and not for the LibXC hybrid functionals.";
311 	}
312 
processCommandExchangeParameters313 	void process(ParamList& pl, Everything& e)
314 	{	pl.get(e.exCorr.exxScaleOverride, 0., "exxScale", true);
315 		pl.get(e.exCorr.exxOmegaOverride, 0., "exxOmega");
316 		if(e.exCorr.exxScaleOverride <= 0.) throw string("<exxScale> must be >= 0");
317 	}
318 
printStatusCommandExchangeParameters319 	void printStatus(Everything& e, int iRep)
320 	{	logPrintf(" %lg", e.exCorr.exxScaleOverride);
321 		if(e.exCorr.exxOmegaOverride) logPrintf(" %lg", e.exCorr.exxOmegaOverride);
322 	}
323 }
324 commandExchangeParameters;
325 
326 
327 struct CommandExchangeBlockSize : public Command
328 {
CommandExchangeBlockSizeCommandExchangeBlockSize329 	CommandExchangeBlockSize() : Command("exchange-block-size", "jdftx/Electronic/Functional")
330 	{
331 		format = "<blockSize>";
332 		comments =
333 			"Number of bands in blocks of FFTs used in exact-exchange calculation.\n"
334 			"Larger values should improve performance, at the expense of greater\n"
335 			"memory requirements. (Default: 16)";
336 	}
337 
processCommandExchangeBlockSize338 	void process(ParamList& pl, Everything& e)
339 	{	pl.get(e.cntrl.exxBlockSize, 0, "blockSize", true);
340 		if(e.cntrl.exxBlockSize < 1) throw string("<blockSize> must be >= 1");
341 	}
342 
printStatusCommandExchangeBlockSize343 	void printStatus(Everything& e, int iRep)
344 	{	logPrintf(" %d", e.cntrl.exxBlockSize);
345 	}
346 }
347 commandExchangeBlockSize;
348