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<PCMVariant> pcmVariantMap
24 (	PCM_CANDLE,  "CANDLE",
25 	PCM_SGA13,   "SGA13",
26 	PCM_GLSSA13, "GLSSA13",
27 	PCM_LA12,    "LA12",
28 	PCM_SoftSphere, "SoftSphere",
29 	PCM_FixedCavity, "FixedCavity",
30 	PCM_SCCS_g09,      "SCCS_g09",
31 	PCM_SCCS_g03,      "SCCS_g03",
32 	PCM_SCCS_g03p,     "SCCS_g03p",
33 	PCM_SCCS_g09beta,  "SCCS_g09beta",
34 	PCM_SCCS_g03beta,  "SCCS_g03beta",
35 	PCM_SCCS_g03pbeta, "SCCS_g03pbeta",
36 	PCM_SCCS_cation,   "SCCS_cation",
37 	PCM_SCCS_anion,    "SCCS_anion"
38 );
39 EnumStringMap<PCMVariant> pcmVariantDescMap
40 (	PCM_CANDLE,  "Charge-asymmetry corrected, local-response, nonlocal-cavity solvation model \\cite CANDLE",
41 	PCM_SGA13,   "PCM with weighted-density cavitation and dispersion \\cite CavityWDA",
42 	PCM_GLSSA13, "PCM with empirical cavity tension \\cite NonlinearPCM",
43 	PCM_LA12,    "PCM with no cavitation/dispersion contributions \\cite PCM-Kendra",
44 	PCM_SoftSphere, "Soft-sphere continuum solvation model \\cite PCM-SoftSphere",
45 	PCM_FixedCavity, "Use a cavity read in using cavityFile in pcm-params and only calculate electrostatic solvation",
46 	PCM_SCCS_g09,      "g09 parametrization of SCCS local linear model for water \\cite PCM-SCCS",
47 	PCM_SCCS_g03,      "g03 parametrization of SCCS local linear model for water \\cite PCM-SCCS",
48 	PCM_SCCS_g03p,     "g03' parametrization of SCCS local linear model for water \\cite PCM-SCCS",
49 	PCM_SCCS_g09beta,  "g09+beta parametrization of SCCS local linear model for water \\cite PCM-SCCS",
50 	PCM_SCCS_g03beta,  "g03+beta parametrization of SCCS local linear model for water \\cite PCM-SCCS",
51 	PCM_SCCS_g03pbeta, "g03'+beta parametrization of SCCS local linear model for water \\cite PCM-SCCS",
52 	PCM_SCCS_cation,   "cations-only parametrization of SCCS local linear model for water \\cite PCM-SCCS-charged",
53 	PCM_SCCS_anion,    "anions-only parametrization of SCCS local linear model for water \\cite PCM-SCCS-charged"
54 );
55 
56 struct CommandPcmVariant : public Command
57 {
CommandPcmVariantCommandPcmVariant58 	CommandPcmVariant() : Command("pcm-variant", "jdftx/Fluid/Parameters")
59 	{
60 		format = "[<variant>=GLSSA13]";
61 		comments = "Select <variant> of LinearPCM or NonlinearPCM that determines\n"
62 			"the cavity and related energies (cavitation, dispersion etc.).\n"
63 			"CANDLE and SCCS variants are only supported for LinearPCM.\n"
64 			"Here, <variant> must be one of:"
65 			+ addDescriptions(pcmVariantMap.optionList(), linkDescription(pcmVariantMap, pcmVariantDescMap));
66 		hasDefault = true;
67 		require("fluid");
68 	}
69 
processCommandPcmVariant70 	void process(ParamList& pl, Everything& e)
71 	{	FluidSolverParams& fsp = e.eVars.fluidParams;
72 		pl.get(fsp.pcmVariant, PCM_GLSSA13, pcmVariantMap, "variant");
73 		if(fsp.fluidType==FluidSaLSA)
74 			 fsp.pcmVariant = PCM_SaLSA; //only option for SaLSA
75 		//Check variant compatibility with fluidType
76 		if(fsp.fluidType!=FluidNone)
77 		{	//check only when fluid is not None, so that you can switch any
78 			//fluid input file to vacuum simply by commenting out fluid line
79 			if(fsp.fluidType!=FluidLinearPCM && ( fsp.pcmVariant==PCM_CANDLE || isPCM_SCCS(fsp.pcmVariant) ) )
80 				throw string("CANDLE and SCCS variants can only be used with fluid LinearPCM");
81 		}
82 	}
83 
printStatusCommandPcmVariant84 	void printStatus(Everything& e, int iRep)
85 	{	const FluidSolverParams& fsp = e.eVars.fluidParams;
86 		if(fsp.fluidType==FluidSaLSA) logPrintf("SaLSA"); //only option for SaLSA
87 		else logPrintf("%s", pcmVariantMap.getString(fsp.pcmVariant));
88 	}
89 }
90 commandPcmVariant;
91 
92 enum PCMparameter
93 {	PCMp_lMax, //!< angular momentum truncation in SaLSA
94 	PCMp_nc, //!< critical density for the PCM cavity shape function
95 	PCMp_sigma, //!< smoothing factor for the PCM cavity shape function
96 	PCMp_cavityTension, //!< effective surface tension (including dispersion etc.) of the cavity (hartree per bohr^2)
97 	PCMp_cavityPressure, //!< effective pressure on the cavity (hartree per bohr^3) for SCCS and SoftSphere models
98 	PCMp_cavityScale, //!< atomic radius scale factor for soft sphere solvation model
99 	PCMp_ionSpacing, //!< extra spacing from dielectric to ionic cavity in bohrs for soft sphere model
100 	PCMp_cavityFile, //!< filename for fixed cavity model
101 	PCMp_zMask0, //z center in lattice coordinates for cavity mask
102 	PCMp_zMaskH, //half-width in z lattice coordinates for cavity mask
103 	PCMp_zMaskIonH, //half-width in z lattice coordinates for ion cavity mask
104 	PCMp_zMaskSigma, //smoothness of z-mask in bohrs
105 	PCMp_rhoMin, //!< min electron density (bohr^-3) for SCCS cavity switching function
106 	PCMp_rhoMax, //!< max electron density (bohr^-3) for SCCS cavity switching function
107 	PCMp_rhoDelta, //!< electron density change (bohr^-3) for SCCS cavity area calculation
108 	PCMp_eta_wDiel, //!< fit parameter for dielectric cavity in CANDLE
109 	PCMp_sqrtC6eff, //!< sqrt(effective molecule C6 coefficient) for CANDLE
110 	PCMp_pCavity, //!< sensitivity of cavity to surface electric fields [e-a0/Eh] in CANDLE
111 	PCMp_Ztot, //! Total valence charge on the solvent, used by CANDLE
112 	PCMp_screenOverride, //! Overrides screening length
113 	PCMp_Delim //!< Delimiter used in parsing
114 };
115 EnumStringMap<PCMparameter> pcmParamMap
116 (	PCMp_lMax,          "lMax",
117 	PCMp_nc,            "nc",
118 	PCMp_sigma,         "sigma",
119 	PCMp_cavityTension, "cavityTension",
120 	PCMp_cavityPressure, "cavityPressure",
121 	PCMp_cavityScale, "cavityScale",
122 	PCMp_ionSpacing, "ionSpacing",
123 	PCMp_cavityFile, "cavityFile",
124 	PCMp_zMask0, "zMask0",
125 	PCMp_zMaskH, "zMaskH",
126 	PCMp_zMaskIonH, "zMaskIonH",
127 	PCMp_zMaskSigma, "zMaskSigma",
128 	PCMp_rhoMin, "rhoMin",
129 	PCMp_rhoMax, "rhoMax",
130 	PCMp_rhoDelta, "rhoDelta",
131 	PCMp_eta_wDiel, "eta_wDiel",
132 	PCMp_sqrtC6eff, "sqrtC6eff",
133 	PCMp_pCavity, "pCavity",
134 	PCMp_Ztot, "Ztot",
135 	PCMp_screenOverride, "screenOverride"
136 );
137 EnumStringMap<PCMparameter> pcmParamDescMap
138 (	PCMp_lMax, "angular momentum truncation in SaLSA",
139 	PCMp_nc, "critical density for the PCM cavity shape function",
140 	PCMp_sigma, "smoothing factor for the PCM cavity shape function",
141 	PCMp_cavityTension, "effective surface tension (including dispersion etc.) of the cavity (hartree per bohr^2)",
142 	PCMp_cavityPressure, "effective pressure on the cavity (hartree per bohr^3) for SCCS and soft sphere models",
143 	PCMp_cavityScale, "atomic radius scale factor for soft sphere model",
144 	PCMp_ionSpacing, "extra spacing from dielectric to ionic cavity in bohrs for soft sphere model",
145 	PCMp_cavityFile, "filename for fixed cavity model (should be on double-sized box when using Coulomb truncation)",
146 	PCMp_zMask0, "center in z lattice coordinates for cavity mask (default: 0)",
147 	PCMp_zMaskIonH, "half-width in z lattice coordinates for ion cavity mask (default: 0 => disabled)",
148 	PCMp_zMaskH, "half-width in z lattice coordinates for cavity mask (default: 0 => disabled)",
149 	PCMp_zMaskSigma, "smoothness of z-mask in bohrs (default: 0.5)",
150 	PCMp_rhoMin, "min electron density (bohr^-3) for SCCS cavity switching function",
151 	PCMp_rhoMax, "max electron density (bohr^-3) for SCCS cavity switching function",
152 	PCMp_rhoDelta, "electron density change (bohr^-3) for SCCS cavity area calculation",
153 	PCMp_eta_wDiel, "fit parameter for dielectric cavity in CANDLE",
154 	PCMp_sqrtC6eff, "sqrt(effective molecule C6 coefficient) for CANDLE",
155 	PCMp_pCavity, "sensitivity of cavity to surface electric fields [a.u.] in CANDLE",
156 	PCMp_Ztot, "total valence charge on the solvent, used by CANDLE",
157 	PCMp_screenOverride, "overrides the screening length calculated from fluid-components"
158 );
159 
160 struct CommandPcmParams : public Command
161 {
CommandPcmParamsCommandPcmParams162 	CommandPcmParams() : Command("pcm-params", "jdftx/Fluid/Parameters")
163 	{
164 		format = "<key1> <value1> <key2> <value2> ...";
165 		comments = "Adjust PCM solvent parameters. Possible keys and value types are:"
166 			+ addDescriptions(pcmParamMap.optionList(), linkDescription(pcmParamMap, pcmParamDescMap))
167 			+ "\n\nAny number of these key-value pairs may be specified in any order.";
168 
169 		require("fluid-solvent");
170 	}
171 
processCommandPcmParams172 	void process(ParamList& pl, Everything& e)
173 	{	FluidSolverParams& fsp = e.eVars.fluidParams;
174 		while(true)
175 		{	PCMparameter key;
176 			pl.get(key, PCMp_Delim, pcmParamMap, "key");
177 			#define READ_AND_CHECK(param, op, val) \
178 				case PCMp_##param: \
179 					pl.get(fsp.param, val, #param, true); \
180 					if(!(fsp.param op val)) throw string(#param " must be " #op " " #val); \
181 					break;
182 			switch(key)
183 			{	READ_AND_CHECK(lMax, >=, 0)
184 				READ_AND_CHECK(nc, >, 0.)
185 				READ_AND_CHECK(sigma, >, 0.)
186 				READ_AND_CHECK(cavityTension, <, DBL_MAX)
187 				READ_AND_CHECK(cavityPressure, <, DBL_MAX)
188 				READ_AND_CHECK(cavityScale, >, 0.)
189 				READ_AND_CHECK(ionSpacing, >=, 0.)
190 				case PCMp_cavityFile:
191 					pl.get(fsp.cavityFile, string(), "filename", true);
192 					break;
193 				READ_AND_CHECK(zMask0, <, DBL_MAX)
194 				READ_AND_CHECK(zMaskH, >=, 0.)
195 				READ_AND_CHECK(zMaskIonH, >=, 0.)
196 				READ_AND_CHECK(zMaskSigma, >, 0.)
197 				READ_AND_CHECK(rhoMin, >, 0.)
198 				READ_AND_CHECK(rhoMax, >, 0.)
199 				READ_AND_CHECK(rhoDelta, >, 0.)
200 				READ_AND_CHECK(eta_wDiel, >=, 0.)
201 				READ_AND_CHECK(sqrtC6eff, >=, 0.)
202 				READ_AND_CHECK(pCavity, <, DBL_MAX)
203 				READ_AND_CHECK(Ztot, >, 0.)
204 				READ_AND_CHECK(screenOverride, >, 0.)
205 				case PCMp_Delim: return; //end of input
206 			}
207 			#undef READ_AND_CHECK
208 		}
209 	}
210 
printStatusCommandPcmParams211 	void printStatus(Everything& e, int iRep)
212 	{	const FluidSolverParams& fsp = e.eVars.fluidParams;
213 		#define PRINT(param) logPrintf(" \\\n\t" #param " %lg", fsp.param);
214 		logPrintf(" \\\n\tlMax %d", fsp.lMax);
215 		PRINT(nc)
216 		PRINT(sigma)
217 		PRINT(cavityTension)
218 		PRINT(cavityPressure)
219 		PRINT(cavityScale)
220 		PRINT(ionSpacing)
221 		logPrintf(" \\\n\tcavityFile %s", fsp.cavityFile.c_str());
222 		PRINT(zMask0)
223 		PRINT(zMaskH)
224 		PRINT(zMaskIonH)
225 		PRINT(zMaskSigma)
226 		PRINT(rhoMin)
227 		PRINT(rhoMax)
228 		PRINT(rhoDelta)
229 		PRINT(eta_wDiel)
230 		PRINT(sqrtC6eff)
231 		PRINT(pCavity)
232 		PRINT(Ztot)
233 		PRINT(screenOverride)
234 		#undef PRINT
235 	}
236 }
237 commandPcmParams;
238 
239 
240 struct CommandPcmNonlinearDebug : public Command
241 {
CommandPcmNonlinearDebugCommandPcmNonlinearDebug242     CommandPcmNonlinearDebug() : Command("pcm-nonlinear-debug", "jdftx/Fluid/Parameters")
243 	{
244 		format = "<linearDielectric>=" + boolMap.optionList() + " <linearScreening>=" + boolMap.optionList();
245 		comments = "Emulate linear response of the dielectric or screening within NonlinearPCM (for debugging purposes only)";
246 	}
247 
processCommandPcmNonlinearDebug248 	void process(ParamList& pl, Everything& e)
249 	{	FluidSolverParams& fsp = e.eVars.fluidParams;
250 		pl.get(fsp.linearDielectric, false, boolMap, "linearDielectric", true);
251 		pl.get(fsp.linearScreening, false, boolMap, "linearScreening", true);
252 	}
253 
printStatusCommandPcmNonlinearDebug254 	void printStatus(Everything& e, int iRep)
255 	{	const FluidSolverParams& fsp = e.eVars.fluidParams;
256 		logPrintf("%s %s", boolMap.getString(fsp.linearDielectric), boolMap.getString(fsp.linearScreening));
257 	}
258 }
259 commandPcmNonlinearDebug;
260 
261 
262 
263 struct CommandIonWidth : public Command
264 {
CommandIonWidthCommandIonWidth265 	CommandIonWidth() : Command("ion-width", "jdftx/Fluid/Parameters")
266 	{
267 		format = "Ecut | fftbox | <width>";
268 		comments = "Manually specify width of gaussian representations of nuclear charge in bohr\n"
269 			"or set automatically based on either energy cut-off (Ecut) or grid spacing (fftbox).\n"
270 			"The widened charges are only used in the interaction with fluids, and does not\n"
271 			"affect the energy of the electronic system. Default is Ecut-based selection\n"
272 			"for LinearPCM/NonlinearPCM and 0 (no widening) for all other fluid types.";
273 		hasDefault = true;
274 		require("fluid");
275 	}
276 
processCommandIonWidth277 	void process(ParamList& pl, Everything& e)
278 	{	string key; pl.get(key, string(), "width");
279 		if(!key.length()) //default
280 		{	switch(e.eVars.fluidParams.fluidType)
281 			{	case FluidLinearPCM:
282 				case FluidNonlinearPCM:
283 					e.iInfo.ionWidthMethod = IonInfo::IonWidthEcut;
284 					break;
285 				default:
286 					e.iInfo.ionWidthMethod = IonInfo::IonWidthManual;
287 					e.iInfo.ionWidth = 0.;
288 			}
289 		}
290 		else if(key=="Ecut") e.iInfo.ionWidthMethod = IonInfo::IonWidthEcut;
291 		else if(key=="fftbox") e.iInfo.ionWidthMethod = IonInfo::IonWidthFFTbox;
292 		else
293 		{	istringstream iss(key);
294 			iss >> e.iInfo.ionWidth;
295 			if(iss.fail()) throw string("<width> must be Ecut, fftbox or a value in bohrs");
296 			e.iInfo.ionWidthMethod = IonInfo::IonWidthManual;
297 		}
298 	}
299 
printStatusCommandIonWidth300 	void printStatus(Everything& e, int iRep)
301 	{	switch(e.iInfo.ionWidthMethod)
302 		{	case IonInfo::IonWidthFFTbox: logPrintf("fftbox"); break;
303 			case IonInfo::IonWidthEcut: logPrintf("Ecut"); break;
304 			case IonInfo::IonWidthManual: logPrintf("%lg", e.iInfo.ionWidth); break;
305 		}
306 	}
307 }
308 commandIonWidth;
309