1 /*-------------------------------------------------------------------
2 Copyright 2012 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<CoulombParams::ExchangeRegularization> exRegMethodMap
24 (	CoulombParams::None,                 "None",
25 	CoulombParams::AuxiliaryFunction,    "AuxiliaryFunction",
26 	CoulombParams::ProbeChargeEwald,     "ProbeChargeEwald",
27 	CoulombParams::SphericalTruncated,   "SphericalTruncated",
28 	CoulombParams::WignerSeitzTruncated, "WignerSeitzTruncated"
29 );
30 
31 EnumStringMap<CoulombParams::Geometry> truncationTypeMap
32 (	CoulombParams::Periodic,    "Periodic",
33 	CoulombParams::Slab,        "Slab",
34 	CoulombParams::Cylindrical, "Cylindrical",
35 	CoulombParams::Wire,        "Wire",
36 	CoulombParams::Isolated,    "Isolated",
37 	CoulombParams::Spherical,   "Spherical"
38 );
39 
40 EnumStringMap<int> truncationDirMap
41 (	0, "100",
42 	1, "010",
43 	2, "001"
44 );
45 
46 struct CommandCoulombInteraction : public Command
47 {
CommandCoulombInteractionCommandCoulombInteraction48 	CommandCoulombInteraction() : Command("coulomb-interaction", "jdftx/Coulomb interactions")
49 	{
50 		format = "<truncationType> [<args> ...]";
51 		comments =
52 			"Optionally truncate the coulomb interaction. The available <truncationType>'s\n"
53 			"and the corresponding arguments are:\n"
54 			"\n+ Periodic\n\n"
55 			"    Standard periodic (untruncated) coulomb interaction (Default)\n"
56 			"\n+ Slab <dir>=" + truncationDirMap.optionList() + "\n\n"
57 			"    Truncate coulomb interaction along the specified lattice direction.\n"
58 			"    The other two lattice directions must be orthogonal to this one.\n"
59 			"    Useful for slab-like geometries.\n"
60 			"\n+ Cylindrical <dir>=" + truncationDirMap.optionList() + " [<Rc>=0]\n\n"
61 			"    Truncate coulomb interaction on a cylinder of radius <Rc> bohrs\n"
62 			"    with axis along specified lattice direction. The other two lattice\n"
63 			"    directions must be orthogonal to this one. Rc=0 is understood to be\n"
64 			"    the in-radius of the 2D Wigner-Seitz cell perpendicular to <dir>.\n"
65 			"\n+ Wire <dir>=" + truncationDirMap.optionList() + "\n\n"
66 			"    Truncate coulomb interaction on the 2D Wigner-Seitz cell in the plane\n"
67 			"    perpendicular to <dir>. The other two lattice directions must be\n"
68 			"    orthogonal to this one. Useful for wire-like geometries.\n"
69 			"\n+ Isolated\n\n"
70 			"    Truncate coulomb interaction on the 3D Wigner-Seitz cell.\n"
71 			"\n+ Spherical [<Rc>=0]\n\n"
72 			"    Truncate coulomb interaction on a sphere of radius <Rc> bohrs.\n"
73 			"    Rc=0 is understood to be the in-radius of the Wigner-Seitz cell.\n"
74 			"\n"
75 			"For all the truncated modes, the charge density must be confined to a\n"
76 			"maximum separation of L/2 in each truncated direction, where L is the\n"
77 			"length of the unit cell in that direction or 2 Rc for Spherical and\n"
78 			"Cylindrical modes. The center of the charge density is not important\n"
79 			"and may cross unit cell boundaries.";
80 		hasDefault = true;
81 	}
82 
processCommandCoulombInteraction83 	void process(ParamList& pl, Everything& e)
84 	{	CoulombParams& cp = e.coulombParams;
85 		pl.get(cp.geometry, CoulombParams::Periodic, truncationTypeMap, "truncationType");
86 		if(cp.geometry==CoulombParams::Periodic) return; //no parameters
87 		//Get direction for the partially periodic modes:
88 		if(cp.geometry==CoulombParams::Slab
89 		|| cp.geometry==CoulombParams::Wire
90 		|| cp.geometry==CoulombParams::Cylindrical)
91 			pl.get(cp.iDir, 0, truncationDirMap, "dir", true);
92 		//Get optional radius for the cylindrical/spherical modes:
93 		if(cp.geometry==CoulombParams::Cylindrical
94 		|| cp.geometry==CoulombParams::Spherical)
95 			pl.get(cp.Rc, 0., "Rc");
96 	}
97 
printStatusCommandCoulombInteraction98 	void printStatus(Everything& e, int iRep)
99 	{	CoulombParams& cp = e.coulombParams;
100 		logPrintf("%s", truncationTypeMap.getString(cp.geometry));
101 		if(cp.geometry==CoulombParams::Periodic) return; //no parameters
102 		//Print direction for the partially periodic modes:
103 		if(cp.geometry==CoulombParams::Slab
104 		|| cp.geometry==CoulombParams::Wire
105 		|| cp.geometry==CoulombParams::Cylindrical)
106 			logPrintf(" %s", truncationDirMap.getString(cp.iDir));
107 		//Print optional radius for the cylindrical/spherical modes:
108 		if(cp.geometry==CoulombParams::Cylindrical
109 		|| cp.geometry==CoulombParams::Spherical)
110 			logPrintf(" %lg", cp.Rc);
111 	}
112 }
113 commandCoulombInteraction;
114 
115 
116 struct CommandCoulombTruncationEmbed : public Command
117 {
CommandCoulombTruncationEmbedCommandCoulombTruncationEmbed118 	CommandCoulombTruncationEmbed() : Command("coulomb-truncation-embed", "jdftx/Coulomb interactions")
119 	{
120 		format = "<c0> <c1> <c2>";
121 		comments =
122 			"Compute truncated Coulomb interaction in a double-sized box (doubled only\n"
123 			"along truncated directions). This relaxes the L/2 localization constraint\n"
124 			"otherwise required by truncated potentials (see command coulomb-interaction),\n"
125 			"but breaks translational invariance and requires the specification of a center.\n"
126 			"\n"
127 			"Coordinate system for center (<c0> <c1> <c2>) is as specified by coords-type.\n"
128 			"\n"
129 			"Default: not enabled; coulomb-interaction employs translationally invariant scheme";
130 
131 		hasDefault = false;
132 		require("coulomb-interaction");
133 		//Dependencies due to coordinate system option:
134 		require("latt-scale");
135 		require("coords-type");
136 	}
137 
processCommandCoulombTruncationEmbed138 	void process(ParamList& pl, Everything& e)
139 	{	e.coulombParams.embed = true;
140 		vector3<>& c = e.coulombParams.embedCenter;
141 		pl.get(c[0], 0., "c0", true);
142 		pl.get(c[1], 0., "c1", true);
143 		pl.get(c[2], 0., "c2", true);
144 		if(e.iInfo.coordsType==CoordsCartesian) c = inv(e.gInfo.R) * c; //Transform coordinates if necessary
145 		if(e.coulombParams.geometry==CoulombParams::Periodic)
146 			e.coulombParams.embed = false; //No embedding, just use to specify center
147 	}
148 
printStatusCommandCoulombTruncationEmbed149 	void printStatus(Everything& e, int iRep)
150 	{	vector3<> c = e.coulombParams.embedCenter;
151 		if(e.iInfo.coordsType==CoordsCartesian) c = e.gInfo.R * c; //Print in coordinate system chosen by user
152 		logPrintf("%lg %lg %lg", c[0], c[1], c[2]);
153 	}
154 }
155 commandCoulombTruncationEmbed;
156 
157 
158 struct CommandCoulombTruncationIonMargin : public Command
159 {
CommandCoulombTruncationIonMarginCommandCoulombTruncationIonMargin160 	CommandCoulombTruncationIonMargin() : Command("coulomb-truncation-ion-margin", "jdftx/Coulomb interactions")
161 	{
162 		format = "<margin>";
163 		comments =
164 			"Extra margin (in bohrs) around the ions, when checking localization constraints\n"
165 			"for truncated Coulomb potentials (see command coulomb-interaction). Set to a typical\n"
166 			"distance from nuclei where the electron density becomes negligible, so as to\n"
167 			"ensure the electron density satisfies those localization constraints.\n"
168 			"(Default: 5 bohrs, minimum allowed: 1 bohr)";
169 		hasDefault = false;
170 	}
171 
processCommandCoulombTruncationIonMargin172 	void process(ParamList& pl, Everything& e)
173 	{	pl.get(e.coulombParams.ionMargin, 0., "margin", true);
174 		if(e.coulombParams.ionMargin < 1.) throw string("<margin> must be at least 1 bohr.");
175 	}
176 
printStatusCommandCoulombTruncationIonMargin177 	void printStatus(Everything& e, int iRep)
178 	{	logPrintf("%lg", e.coulombParams.ionMargin);
179 	}
180 }
181 commandCoulombTruncationIonMargin;
182 
183 
184 struct CommandExchangeRegularization : public Command
185 {
CommandExchangeRegularizationCommandExchangeRegularization186 	CommandExchangeRegularization() : Command("exchange-regularization", "jdftx/Coulomb interactions")
187 	{
188 		format = "<method>=" + exRegMethodMap.optionList();
189 		comments =
190 			"Regularization / singularity correction method for exact exchange.\n"
191 			"The allowed methods and defaults depend on the setting of <geometry>\n"
192 			"in command coulomb-interaction\n"
193 			"\n+ None\n\n"
194 			"    No singularity correction: default and only option for non-periodic\n"
195 			"    systems with no G=0 singularity (<geometry> = Spherical / Isolated).\n"
196 			"    This is allowed for fully or partially periodic systems, but is not\n"
197 			"    recommended due to extremely poor convergence with number of k-points.\n"
198 			"\n+ AuxiliaryFunction\n\n"
199 			"    G=0 modification based on numerical integrals of an auxiliary\n"
200 			"    function, as described in Ref. \\cite AuxFunc-Carrier\n"
201 			"    Allowed for 3D/2D/1D periodic systems.\n"
202 			"\n+ ProbeChargeEwald\n\n"
203 			"    G=0 modification based on the Ewald sum of a single point charge\n"
204 			"    per k-point sampled supercell. Valid for 3D/2D/1D periodic systems.\n"
205 			"\n+ SphericalTruncated\n\n"
206 			"    Truncate exchange kernel on a sphere whose volume equals the k-point\n"
207 			"    sampled supercell, as in Ref. \\cite SphericalTruncation.\n"
208 			"    Allowed for any (partially) periodic <geometry>, but is recommended\n"
209 			"    only when the k-point sampled supercell is roughly isotropic.\n"
210 			"\n+ WignerSeitzTruncated\n\n"
211 			"    Truncate exchange kernel on the Wigner-Seitz cell of the k-point\n"
212 			"    sampled supercell, as in Ref. \\cite TruncatedEXX.\n"
213 			"    Default for any (partially) periodic <geometry>.";
214 		hasDefault = true;
215 		require("coulomb-interaction");
216 	};
217 
processCommandExchangeRegularization218 	void process(ParamList& pl, Everything& e)
219 	{	CoulombParams& cp = e.coulombParams;
220 		//Select default regularization based on geometry:
221 		bool isIsolated = cp.geometry==CoulombParams::Isolated
222 				|| cp.geometry==CoulombParams::Spherical;
223 		cp.exchangeRegularization = isIsolated
224 			? CoulombParams::None
225 			: CoulombParams::WignerSeitzTruncated;
226 		pl.get(cp.exchangeRegularization, cp.exchangeRegularization, exRegMethodMap, "method");
227 		//Check compatibility of regularization with geometry:
228 		if(isIsolated && cp.exchangeRegularization!=CoulombParams::None)
229 			throw string("exchange-regularization <method> must be None for non-periodic"
230 				" coulomb-interaction <geometry> = Spherical or Isolated");
231 	}
232 
printStatusCommandExchangeRegularization233 	void printStatus(Everything& e, int iRep)
234 	{	logPrintf("%s", exRegMethodMap.getString(e.coulombParams.exchangeRegularization));
235 	}
236 }
237 commandCoulombParams;
238