![]() |
ESPResSo 3.2.0-11-g9950804-git
Extensible Simulation Package for Soft Matter Research
|
00001 /* 00002 Copyright (C) 2010,2011,2012,2013 The ESPResSo project 00003 Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 00004 Max-Planck-Institute for Polymer Research, Theory Group 00005 00006 This file is part of ESPResSo. 00007 00008 ESPResSo is free software: you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation, either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 ESPResSo is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program. If not, see <http://www.gnu.org/licenses/>. 00020 */ 00021 #include "parser.h" 00022 00023 #ifdef P3M 00024 #include "p3m_tcl.h" 00025 #include "p3m.h" 00026 00027 int tclcommand_inter_coulomb_parse_p3m_tune(Tcl_Interp * interp, int argc, char ** argv, int adaptive) 00028 { 00029 int mesh = -1, cao = -1, n_interpol = -1; 00030 double r_cut = -1, accuracy = -1; 00031 00032 while(argc > 0) { 00033 if(ARG0_IS_S("r_cut")) { 00034 if (! (argc > 1 && ARG1_IS_D(r_cut) && r_cut >= -1)) { 00035 Tcl_AppendResult(interp, "r_cut expects a positive double", 00036 (char *) NULL); 00037 return TCL_ERROR; 00038 } 00039 00040 } else if(ARG0_IS_S("mesh")) { 00041 if(! (argc > 1 && ARG1_IS_I(mesh) && mesh >= -1)) { 00042 Tcl_AppendResult(interp, "mesh expects an integer >= -1", 00043 (char *) NULL); 00044 return TCL_ERROR; 00045 } 00046 00047 } else if(ARG0_IS_S("cao")) { 00048 if(! (argc > 1 && ARG1_IS_I(cao) && cao >= -1 && cao <= 7)) { 00049 Tcl_AppendResult(interp, "cao expects an integer between -1 and 7", 00050 (char *) NULL); 00051 return TCL_ERROR; 00052 } 00053 00054 } else if(ARG0_IS_S("accuracy")) { 00055 if(! (argc > 1 && ARG1_IS_D(accuracy) && accuracy > 0)) { 00056 Tcl_AppendResult(interp, "accuracy expects a positive double", 00057 (char *) NULL); 00058 return TCL_ERROR; 00059 } 00060 00061 } else if (ARG0_IS_S("n_interpol")) { 00062 if (! (argc > 1 && ARG1_IS_I(n_interpol) && n_interpol >= 0)) { 00063 Tcl_AppendResult(interp, "n_interpol expects an nonnegative integer", (char *) NULL); 00064 return TCL_ERROR; 00065 } 00066 } 00067 /* unknown parameter. Probably one of the optionals */ 00068 else break; 00069 00070 argc -= 2; 00071 argv += 2; 00072 } 00073 p3m_set_tune_params(r_cut, mesh, cao, -1.0, accuracy, n_interpol); 00074 00075 /* check for optional parameters */ 00076 if (argc > 0) { 00077 if (tclcommand_inter_coulomb_parse_p3m_opt_params(interp, argc, argv) == TCL_ERROR) 00078 return TCL_ERROR; 00079 } 00080 00081 /* do the tuning */ 00082 char *log = NULL; 00083 if (p3m_adaptive_tune(&log) == ES_ERROR) { 00084 Tcl_AppendResult(interp, log, "\nfailed to tune P3M parameters to required accuracy", (char *) NULL); 00085 if (log) 00086 free(log); 00087 return TCL_ERROR; 00088 } 00089 00090 /* Tell the user about the tuning outcome */ 00091 Tcl_AppendResult(interp, log, (char *) NULL); 00092 00093 if (log) 00094 free(log); 00095 00096 return TCL_OK; 00097 } 00098 00099 int tclcommand_inter_coulomb_parse_p3m(Tcl_Interp * interp, int argc, char ** argv) 00100 { 00101 double r_cut, alpha, accuracy = -1.0; 00102 int mesh[3], cao, i; 00103 IntList il; 00104 init_intlist(&il); 00105 00106 if (argc < 1) { 00107 Tcl_AppendResult(interp, "expected: inter coulomb <bjerrum> p3m tune | <r_cut> { <mesh> | \\{ <mesh_x> <mesh_y> <mesh_z> \\} } <cao> [<alpha> [<accuracy>]]", 00108 (char *) NULL); 00109 return TCL_ERROR; 00110 } 00111 00112 if (ARG0_IS_S("tune")) 00113 return tclcommand_inter_coulomb_parse_p3m_tune(interp, argc-1, argv+1, 0); 00114 00115 if (ARG0_IS_S("tunev2")) 00116 return tclcommand_inter_coulomb_parse_p3m_tune(interp, argc-1, argv+1, 1); 00117 00118 if(! ARG0_IS_D(r_cut)) 00119 return TCL_ERROR; 00120 00121 if(argc < 3 || argc > 5) { 00122 Tcl_AppendResult(interp, "wrong # arguments: inter coulomb <bjerrum> p3m <r_cut> { <mesh> | \\{ <mesh_x> <mesh_y> <mesh_z> \\} } <cao> [<alpha> [<accuracy>]]", 00123 (char *) NULL); 00124 return TCL_ERROR; 00125 } 00126 00127 if(! ARG_IS_I(1, mesh[0])) { 00128 if( ! ARG_IS_INTLIST(1, il) || !(il.n == 3) ) { 00129 Tcl_AppendResult(interp, "integer or interger list of length 3 expected", (char *) NULL); 00130 return TCL_ERROR; 00131 } else { 00132 mesh[0] = il.e[0]; 00133 mesh[1] = il.e[1]; 00134 mesh[2] = il.e[2]; 00135 } 00136 } else { 00137 mesh[1] = mesh[2] = mesh[0]; 00138 } 00139 00140 if(! ARG_IS_I(2, cao)) { 00141 Tcl_AppendResult(interp, "integer expected", (char *) NULL); 00142 return TCL_ERROR; 00143 } 00144 00145 if(argc > 3) { 00146 if(! ARG_IS_D(3, alpha)) 00147 return TCL_ERROR; 00148 } 00149 else { 00150 Tcl_AppendResult(interp, "Automatic p3m tuning not implemented.", 00151 (char *) NULL); 00152 return TCL_ERROR; 00153 } 00154 00155 if(argc > 4) { 00156 if(! ARG_IS_D(4, accuracy)) { 00157 Tcl_AppendResult(interp, "double expected", (char *) NULL); 00158 return TCL_ERROR; 00159 } 00160 } 00161 00162 if ((i = p3m_set_params(r_cut, mesh, cao, alpha, accuracy)) < 0) { 00163 switch (i) { 00164 case -1: 00165 Tcl_AppendResult(interp, "r_cut must be positive", (char *) NULL); 00166 break; 00167 case -2: 00168 Tcl_AppendResult(interp, "mesh must be positive", (char *) NULL); 00169 break; 00170 case -3: 00171 Tcl_AppendResult(interp, "cao must be between 1 and 7 and less than mesh", 00172 (char *) NULL); 00173 break; 00174 case -4: 00175 Tcl_AppendResult(interp, "alpha must be positive", (char *) NULL); 00176 break; 00177 case -5: 00178 Tcl_AppendResult(interp, "accuracy must be positive", (char *) NULL); 00179 break; 00180 default:; 00181 Tcl_AppendResult(interp, "unspecified error", (char *) NULL); 00182 } 00183 00184 return TCL_ERROR; 00185 } 00186 00187 return TCL_OK; 00188 } 00189 00190 00191 int tclcommand_inter_coulomb_parse_p3m_opt_params(Tcl_Interp * interp, int argc, char ** argv) 00192 { 00193 int i; double d1, d2, d3; 00194 00195 Tcl_ResetResult(interp); 00196 00197 while (argc > 0) { 00198 /* p3m parameter: inter */ 00199 if (ARG0_IS_S("n_interpol")) { 00200 00201 if(argc < 2) { 00202 Tcl_AppendResult(interp, argv[0], " needs 1 parameter", 00203 (char *) NULL); 00204 return TCL_ERROR; 00205 } 00206 00207 if (! ARG1_IS_I(i)) { 00208 Tcl_AppendResult(interp, argv[0], " needs 1 INTEGER parameter", 00209 (char *) NULL); 00210 return TCL_ERROR; 00211 } 00212 00213 if (p3m_set_ninterpol(i) == TCL_ERROR) { 00214 Tcl_AppendResult(interp, argv[0], " argument must be positive", 00215 (char *) NULL); 00216 return TCL_ERROR; 00217 } 00218 00219 argc -= 2; 00220 argv += 2; 00221 } 00222 00223 /* p3m parameter: mesh_off */ 00224 else if (ARG0_IS_S("mesh_off")) { 00225 00226 if(argc < 4) { 00227 Tcl_AppendResult(interp, argv[0], " needs 3 parameters", 00228 (char *) NULL); 00229 return TCL_ERROR; 00230 } 00231 00232 if ((! ARG_IS_D(1, d1)) || 00233 (! ARG_IS_D(2, d2)) || 00234 (! ARG_IS_D(3, d3))) 00235 { 00236 Tcl_AppendResult(interp, argv[0], " needs 3 DOUBLE parameters", 00237 (char *) NULL); 00238 return TCL_ERROR; 00239 } 00240 00241 if (p3m_set_mesh_offset(d1, d2 ,d3) == TCL_ERROR) 00242 { 00243 Tcl_AppendResult(interp, argv[0], " parameters have to be between 0.0 an 1.0", 00244 (char *) NULL); 00245 return TCL_ERROR; 00246 } 00247 00248 argc -= 4; 00249 argv += 4; 00250 } 00251 00252 /* p3m parameter: epsilon */ 00253 else if(ARG0_IS_S( "epsilon")) { 00254 00255 if(argc < 2) { 00256 Tcl_AppendResult(interp, argv[0], " needs 1 parameter", 00257 (char *) NULL); 00258 return TCL_ERROR; 00259 } 00260 00261 if (ARG1_IS_S("metallic")) { 00262 d1 = P3M_EPSILON_METALLIC; 00263 } 00264 else if (! ARG1_IS_D(d1)) { 00265 Tcl_AppendResult(interp, argv[0], " needs 1 DOUBLE parameter or \"metallic\"", 00266 (char *) NULL); 00267 return TCL_ERROR; 00268 } 00269 00270 if (p3m_set_eps(d1) == TCL_ERROR) { 00271 Tcl_AppendResult(interp, argv[0], " There is no error msg yet!", 00272 (char *) NULL); 00273 return TCL_ERROR; 00274 } 00275 00276 argc -= 2; 00277 argv += 2; 00278 } 00279 else { 00280 Tcl_AppendResult(interp, "Unknown coulomb p3m parameter: \"",argv[0],"\"",(char *) NULL); 00281 return TCL_ERROR; 00282 } 00283 } 00284 00285 return TCL_OK; 00286 } 00287 00288 /*********************** miscelanea of functions *************************************/ 00289 00290 int tclprint_to_result_p3m(Tcl_Interp *interp) 00291 { 00292 char buffer[TCL_DOUBLE_SPACE]; 00293 00294 Tcl_PrintDouble(interp, p3m.params.r_cut, buffer); 00295 Tcl_AppendResult(interp, "p3m ", buffer, " ", (char *) NULL); 00296 sprintf(buffer,"%d",p3m.params.mesh[0]); 00297 Tcl_AppendResult(interp, buffer, " ", (char *) NULL); 00298 sprintf(buffer,"%d",p3m.params.cao); 00299 Tcl_AppendResult(interp, buffer, " ", (char *) NULL); 00300 Tcl_PrintDouble(interp, p3m.params.alpha, buffer); 00301 Tcl_AppendResult(interp, buffer, " ", (char *) NULL); 00302 Tcl_PrintDouble(interp, p3m.params.accuracy, buffer); 00303 Tcl_AppendResult(interp, buffer, (char *) NULL); 00304 00305 Tcl_AppendResult(interp, "} {coulomb epsilon ", (char *) NULL); 00306 if (p3m.params.epsilon == P3M_EPSILON_METALLIC) 00307 Tcl_AppendResult(interp, " metallic ", (char *) NULL); 00308 else { 00309 Tcl_PrintDouble(interp, p3m.params.epsilon, buffer); 00310 Tcl_AppendResult(interp, buffer, " ", (char *) NULL); 00311 } 00312 sprintf(buffer,"%d",p3m.params.inter); 00313 Tcl_AppendResult(interp, "n_interpol ", buffer, " ", (char *) NULL); 00314 Tcl_PrintDouble(interp, p3m.params.mesh_off[0], buffer); 00315 Tcl_AppendResult(interp, "mesh_off ", buffer, " ", (char *) NULL); 00316 Tcl_PrintDouble(interp, p3m.params.mesh_off[1], buffer); 00317 Tcl_AppendResult(interp, buffer, " ", (char *) NULL); 00318 Tcl_PrintDouble(interp, p3m.params.mesh_off[2], buffer); 00319 Tcl_AppendResult(interp, buffer, (char *) NULL); 00320 00321 return TCL_OK; 00322 } 00323 00324 /************************************************ 00325 * Debug functions printing p3m structures 00326 ************************************************/ 00327 00328 #endif /* of P3M */ 00329
1.7.5.1