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 //! @file elec_misc.cpp Commands controlling electronic fillings algorithms
24 
25 EnumStringMap<ElecInfo::SmearingType> smearingTypeMap(
26 	ElecInfo::SmearingFermi, "Fermi",
27 	ElecInfo::SmearingGauss, "Gauss",
28 	ElecInfo::SmearingMP1, "MP1",
29 	ElecInfo::SmearingCold, "Cold" );
30 
31 EnumStringMap<ElecInfo::SmearingType> smearingTypeDescMap(
32 	ElecInfo::SmearingFermi, "Use a Fermi-Dirac function for fillings",
33 	ElecInfo::SmearingGauss, "Use a gaussian-based (erfc) function for fillings",
34 	ElecInfo::SmearingMP1, "Use an order-1 Methfessel-Paxton \\cite MP1 function for fillings",
35 	ElecInfo::SmearingCold, "Use the cold smearing function \\cite ColdSmearing to approximate zero temperature" );
36 
37 struct CommandElecSmearing : public Command
38 {
CommandElecSmearingCommandElecSmearing39 	CommandElecSmearing() : Command("elec-smearing", "jdftx/Electronic/Parameters")
40 	{
41 		format = "<smearingType>="+smearingTypeMap.optionList()+" <smearingWidth>";
42 		comments =
43 			"Use variable electronic fillings using a smearing function selected by <smearingType>:"
44 			+ addDescriptions(smearingTypeMap.optionList(), linkDescription(smearingTypeMap, smearingTypeDescMap))
45 			+ "\n\nwith width set by <smearingWidth> in Hartrees.\n"
46 			"The width corresponds to kT (electronic temperature) for Fermi smearing,\n"
47 			"and sigma/2 for the remaining gaussian-based options: this convention\n"
48 			"results in roughly the same rate of k-point convergence for all smearing\n"
49 			"methods using the same width. However, the entropy contribution at the\n"
50 			"same width will follow the order Fermi > Gauss >> (Cold, MP1).";
51 
52 		require("lcao-params");
53 	}
54 
processCommandElecSmearing55 	void process(ParamList& pl, Everything& e)
56 	{	ElecInfo& eInfo = e.eInfo;
57 		pl.get(eInfo.smearingType, ElecInfo::SmearingFermi, smearingTypeMap, "smearingType", true);
58 		pl.get(eInfo.smearingWidth, 0.0, "smearingWidth", true);
59 		if(e.eInfo.smearingWidth<=0) throw string("<smearingWidth> must be positive.\n");
60 		eInfo.fillingsUpdate = ElecInfo::FillingsHsub;
61 	}
62 
printStatusCommandElecSmearing63 	void printStatus(Everything& e, int iRep)
64 	{	const ElecInfo& eInfo = e.eInfo;
65 		logPrintf("%s %lg", smearingTypeMap.getString(eInfo.smearingType), eInfo.smearingWidth);
66 	}
67 }
68 commandElecFermiFillings;
69 
70 struct DeprecatedCommandElecFermiFillings : public DeprecatedCommand
DeprecatedCommandElecFermiFillingsDeprecatedCommandElecFermiFillings71 {	DeprecatedCommandElecFermiFillings() : DeprecatedCommand("elec-fermi-fillings") { }
72 
73 	std::pair<string,string> replace(ParamList& pl) const
74 	{	string unusedParam; double kT;
75 		pl.get(unusedParam, string(), "unusedParam", true);
76 		pl.get(kT, 0.0, "kT", true);
77 		ostringstream oss; oss << " Fermi " << kT;
78 		return std::make_pair(string("elec-smearing"), oss.str());
79 	}
80 }
81 deprecatedCommandElecFermiFillings;
82 
83 //-------------------------------------------------------------------------------------------------
84 
85 struct CommandTargetMu : public Command
86 {
CommandTargetMuCommandTargetMu87 	CommandTargetMu() : Command("target-mu", "jdftx/Electronic/Parameters")
88 	{
89 		format = "<mu> [<outerLoop>=no]";
90 		comments =
91 			"Fixed chemical potential <mu> (instead of fixed charge).\n"
92 			"Note that <mu> is absolute (relative to vacuum level) and in Hartrees.\n"
93 			"For example, potential V (in Volts) relative to SHE corresponds to\n"
94 			"mu = -(Vref + V)/27.2114, where Vref is the absolute SHE potential\n"
95 			"in Volts below vacuum; you could set Vref = 4.44 based on experiment\n"
96 			"or use the value calibrated using potentials of zero charge with\n"
97 			"the solvation model in use.\n"
98 			"\n"
99 			"The default setting <outerLoop>=no directly performs variational minimization\n"
100 			"or SCF in the grand canonical ensemble: keeping mu fixed throughout, letting\n"
101 			"the number of electrons adjust continuously \\cite GC-DFT.\n"
102 			"\n"
103 			"Setting <outerLoop>=yes instead performs a sequence of conventional fixed-charge\n"
104 			"optimizations, adjusting mu in an outer loop using the secant method.\n"
105 			"This is usually much slower, and is only recommended if the default\n"
106 			"direct grand canonical method fails.";
107 
108 		require("fluid-cation");
109 		require("fluid-anion");
110 		require("elec-smearing");
111 		forbid("elec-initial-charge");
112 		forbid("fix-electron-density");
113 		forbid("fix-electron-potential");
114 	}
115 
processCommandTargetMu116 	void process(ParamList& pl, Everything& e)
117 	{	pl.get(e.eInfo.mu, 0.0, "mu", true);
118 		pl.get(e.eInfo.muLoop, false, boolMap, "outerLoop");
119 	}
120 
printStatusCommandTargetMu121 	void printStatus(Everything& e, int iRep)
122 	{	logPrintf("%lg %s\n", e.eInfo.mu, boolMap.getString(e.eInfo.muLoop));
123 	}
124 }
125 commandTargetMu;
126 
127 //-------------------------------------------------------------------------------------------------
128 
129 struct CommandTargetBz : public Command
130 {
CommandTargetBzCommandTargetBz131 	CommandTargetBz() : Command("target-Bz", "jdftx/Electronic/Parameters")
132 	{
133 		format = "<Bz>";
134 		comments =
135 			"Fixed magnetic field <Bz> (instead of magnetization).\n"
136 			"Note that <Bz> is in atomic units (1 T is approximately 4.26E-6 a.u.)\n"
137 			"and in an electron-is-positive convention (Bz > 0 favors up spins).\n"
138 			"Requires smearing and is only valid for spintype z-spin.";
139 
140 		require("elec-smearing");
141 		require("elec-initial-magnetization");
142 		forbid("fix-electron-density");
143 		forbid("fix-electron-potential");
144 	}
145 
processCommandTargetBz146 	void process(ParamList& pl, Everything& e)
147 	{	pl.get(e.eInfo.Bz, 0., "Bz", true);
148 	}
149 
printStatusCommandTargetBz150 	void printStatus(Everything& e, int iRep)
151 	{	logPrintf("%lg\n", e.eInfo.Bz);
152 	}
153 }
154 commandTargetBz;
155 
156 //-------------------------------------------------------------------------------------------------
157 
158 struct CommandElecInitialCharge : public Command
159 {
CommandElecInitialChargeCommandElecInitialCharge160     CommandElecInitialCharge() : Command("elec-initial-charge", "jdftx/Initialization")
161 	{
162 		format = "<QNet>";
163 		comments =
164 			"Initialize a system with <QNet> excess electrons compared to a neutral system.";
165 
166 		forbid("target-mu");
167 	}
168 
processCommandElecInitialCharge169 	void process(ParamList& pl, Everything& e)
170 	{	pl.get(e.eInfo.Qinitial, 0., "QNet", true);
171 	}
172 
printStatusCommandElecInitialCharge173 	void printStatus(Everything& e, int iRep)
174 	{	logPrintf("%lf", e.eInfo.Qinitial);
175 	}
176 }
177 CommandElecInitialCharge;
178 
179 //-------------------------------------------------------------------------------------------------
180 
181 struct CommandElecInitialMagnetization : public Command
182 {
CommandElecInitialMagnetizationCommandElecInitialMagnetization183     CommandElecInitialMagnetization() : Command("elec-initial-magnetization", "jdftx/Initialization")
184 	{
185 		format = "<M> <constrain>=yes|no";
186 		comments =
187 			"Initialize system with total magnetization <M> (= Nup - Ndn).\n"
188 			"With Fermi fillings, the magnetization will be constrained if <constrain>=yes,\n"
189 			"and will equilibriate otherwise. Without Fermi fillings, the magnetization will\n"
190 			"remain constrained regardless. Note: target-Bz will override <constrain> to no.\n"
191 			"Only valid for spintype z-spin.";
192 
193 		require("spintype");
194 	}
195 
processCommandElecInitialMagnetization196 	void process(ParamList& pl, Everything& e)
197 	{	if(e.eInfo.spinType != SpinZ)
198 			throw(string("Total magnetization can only be specified for spintype z-spin"));
199 		pl.get(e.eInfo.Minitial, 0., "M", true);
200 		//Constraint parameter:
201 		bool Mconstrain = true;
202 		pl.get(Mconstrain, true, boolMap, "constrain", true);
203 		e.eInfo.Bz = Mconstrain ? NAN : 0.; //nan B signifies M constrained, M free otherwise
204 	}
205 
printStatusCommandElecInitialMagnetization206 	void printStatus(Everything& e, int iRep)
207 	{	logPrintf("%lf %s", e.eInfo.Minitial, boolMap.getString(std::isnan(e.eInfo.Bz)));
208 	}
209 }
210 CommandElecInitialMagnetization;
211 
212 //-------------------------------------------------------------------------------------------------
213 
214 struct CommandElecInitialFillings : public Command
215 {
CommandElecInitialFillingsCommandElecInitialFillings216 	CommandElecInitialFillings() : Command("elec-initial-fillings", "jdftx/Initialization")
217 	{
218 		format = "read <filename> [<nBandsOld>]";
219 		comments =
220 			"Initial electronic fillings are read from <filename> instead of computed automatically (default).\n"
221 			"+ <nBandsOld> specifies the number of bands in the file being read, if different from current nBands.\n"
222 			"  Extra new bands are filled with 0s, fillings of extra old bands are accumulated into other bands.\n"
223 			"  Default: 0 => fillings file has same number of bands as this run.";
224 
225 		forbid("initial-state");
226 	}
227 
processCommandElecInitialFillings228 	void process(ParamList& pl, Everything& e)
229 	{	string key; pl.get(key, string(), "read", true);
230 		if(key!=string("read")) throw "First parameter must be 'read', encountered " + key;
231 		pl.get(e.eInfo.initialFillingsFilename, string(), "filename", true);
232 		pl.get(e.eInfo.nBandsOld, 0, "nBandsOld");
233 	}
234 
printStatusCommandElecInitialFillings235 	void printStatus(Everything& e, int iRep)
236 	{	logPrintf("read %s %d", e.eInfo.initialFillingsFilename.c_str(), e.eInfo.nBandsOld);
237 	}
238 }
239 commandElecInitialFillings;
240 
241 //-------------------------------------------------------------------------------------------------
242 
243 struct CommandElecInitialEigenvals : public Command
244 {
CommandElecInitialEigenvalsCommandElecInitialEigenvals245 	CommandElecInitialEigenvals() : Command("elec-initial-eigenvals", "jdftx/Initialization")
246 	{
247 		format = "<filename>";
248 		comments = "Read the initial eigenvalues for variable fillings (default: derive from subspace hamiltonian)\n";
249 
250 		forbid("initial-state");
251 	}
252 
processCommandElecInitialEigenvals253 	void process(ParamList& pl, Everything& e)
254 	{	pl.get(e.eVars.eigsFilename, string(), "filename", true);
255 	}
256 
printStatusCommandElecInitialEigenvals257 	void printStatus(Everything& e, int iRep)
258 	{	logPrintf("%s", e.eVars.eigsFilename.c_str());
259 	}
260 }
261 commandElecInitialEigenvals;
262 
263 //-------------------------------------------------------------------------------------------------
264 
265 struct CommandSubspaceRotationFactor : public Command
266 {
CommandSubspaceRotationFactorCommandSubspaceRotationFactor267 	CommandSubspaceRotationFactor() : Command("subspace-rotation-factor", "jdftx/Electronic/Optimization")
268 	{	format = "<factor> <adjust>=yes|no";
269 		comments =
270 			"Preconditioning factor for subspace rotations generated by the\n"
271 			"auxiliary Hamiltonian used for minimization with variable fillings.\n"
272 			"With <adjust> = yes (default), the factor is heuristically adjusted\n"
273 			"during the minimization to optimize convergence.";
274 		hasDefault = true;
275 	}
276 
processCommandSubspaceRotationFactor277 	void process(ParamList& pl, Everything& e)
278 	{	pl.get(e.cntrl.subspaceRotationFactor, 1., "factor");
279 		pl.get(e.cntrl.subspaceRotationAdjust, true, boolMap, "adjust");
280 	}
281 
printStatusCommandSubspaceRotationFactor282 	void printStatus(Everything& e, int iRep)
283 	{	logPrintf("%lg %s", e.cntrl.subspaceRotationFactor, boolMap.getString(e.cntrl.subspaceRotationAdjust));
284 	}
285 }
286 commandSubspaceRotationFactor;
287