Changes in / [986c80:edcda5]
- Files:
-
- 6 deleted
- 43 edited
Legend:
- Unmodified
- Added
- Removed
-
ChangeLog
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
Makefile.am
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
configure.ac
-
Property mode
changed from
100755
to100644
r986c80 redcda5 14 14 AC_PROG_CC 15 15 AM_MISSING_PROG([DOXYGEN], [doxygen]) 16 17 AC_ARG_ENABLE([debug],AS_HELP_STRING([--enable-debug],[debugging level of compiler. Argument is yes or debugging level. (default is no)]), 18 [enable_debugging=$enableval], [enable_debugging=no]) 19 AC_ARG_ENABLE([optimization],AS_HELP_STRING([--enable-optimization],[Optimization level of compiler. Argument is yes or optimization. (default is 2)]), 20 [enable_optimization=$enableval], [enable_optimization=2]) 21 AC_ARG_ENABLE([warnings], AS_HELP_STRING([--enable-warnings],[Output compiler warnings, argument is none, some or full (default is some).]), 22 [enable_warnings=$enableval], [enable_warnings=some]) 23 AC_SET_COMPILER_FLAGS([$enable_optimization], [$enable_debugging], [$enable_warnings]) 16 24 17 25 # Checks for libraries. -
Property mode
changed from
-
doc/Doxyfile
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
doc/Makefile.am
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
m4/ac_doxygen.m4
-
Property mode
changed from
100644
to120000
r986c80 redcda5 1 # This file is part of Autoconf. -*- Autoconf -*- 2 3 # Copyright (C) 2004 Oren Ben-Kiki 4 # This file is distributed under the same terms as the Autoconf macro files. 5 6 # Generate automatic documentation using Doxygen. Works in concert with the 7 # aminclude.m4 file and a compatible doxygen configuration file. Defines the 8 # following public macros: 9 # 10 # DX_???_FEATURE(ON|OFF) - control the default setting fo a Doxygen feature. 11 # Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics, 12 # 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI' 13 # for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF', 14 # 'XML', 'PDF' and 'PS' for the appropriate output formats. The environment 15 # variable DOXYGEN_PAPER_SIZE may be specified to override the default 'a4wide' 16 # paper size. 17 # 18 # By default, HTML, PDF and PS documentation is generated as this seems to be 19 # the most popular and portable combination. MAN pages created by Doxygen are 20 # usually problematic, though by picking an appropriate subset and doing some 21 # massaging they might be better than nothing. CHM and RTF are specific for MS 22 # (note that you can't generate both HTML and CHM at the same time). The XML is 23 # rather useless unless you apply specialized post-processing to it. 24 # 25 # The macro mainly controls the default state of the feature. The use can 26 # override the default by specifying --enable or --disable. The macros ensure 27 # that contradictory flags are not given (e.g., --enable-doxygen-html and 28 # --enable-doxygen-chm, --enable-doxygen-anything with --disable-doxygen, etc.) 29 # Finally, each feature will be automatically disabled (with a warning) if the 30 # required programs are missing. 31 # 32 # Once all the feature defaults have been specified, call DX_INIT_DOXYGEN with 33 # the following parameters: a one-word name for the project for use as a 34 # filename base etc., an optional configuration file name (the default is 35 # 'Doxyfile', the same as Doxygen's default), and an optional output directory 36 # name (the default is 'doxygen-doc'). 37 38 ## ----------## 39 ## Defaults. ## 40 ## ----------## 41 42 DX_ENV="" 43 AC_DEFUN([DX_FEATURE_doc], ON) 44 AC_DEFUN([DX_FEATURE_dot], ON) 45 AC_DEFUN([DX_FEATURE_man], OFF) 46 AC_DEFUN([DX_FEATURE_html], ON) 47 AC_DEFUN([DX_FEATURE_chm], OFF) 48 AC_DEFUN([DX_FEATURE_chi], OFF) 49 AC_DEFUN([DX_FEATURE_rtf], OFF) 50 AC_DEFUN([DX_FEATURE_xml], OFF) 51 AC_DEFUN([DX_FEATURE_pdf], ON) 52 AC_DEFUN([DX_FEATURE_ps], ON) 53 54 ## --------------- ## 55 ## Private macros. ## 56 ## --------------- ## 57 58 # DX_ENV_APPEND(VARIABLE, VALUE) 59 # ------------------------------ 60 # Append VARIABLE="VALUE" to DX_ENV for invoking doxygen. 61 AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])]) 62 63 # DX_DIRNAME_EXPR 64 # --------------- 65 # Expand into a shell expression prints the directory part of a path. 66 AC_DEFUN([DX_DIRNAME_EXPR], 67 [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']]) 68 69 # DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF) 70 # ------------------------------------- 71 # Expands according to the M4 (static) status of the feature. 72 AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])]) 73 74 # DX_REQUIRE_PROG(VARIABLE, PROGRAM) 75 # ---------------------------------- 76 # Require the specified program to be found for the DX_CURRENT_FEATURE to work. 77 AC_DEFUN([DX_REQUIRE_PROG], [ 78 AC_PATH_TOOL([$1], [$2]) 79 if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then 80 AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION]) 81 AC_SUBST([DX_FLAG_[]DX_CURRENT_FEATURE], 0) 82 fi 83 ]) 84 85 # DX_TEST_FEATURE(FEATURE) 86 # ------------------------ 87 # Expand to a shell expression testing whether the feature is active. 88 AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1]) 89 90 # DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE) 91 # ------------------------------------------------- 92 # Verify that a required features has the right state before trying to turn on 93 # the DX_CURRENT_FEATURE. 94 AC_DEFUN([DX_CHECK_DEPEND], [ 95 test "$DX_FLAG_$1" = "$2" \ 96 || AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1, 97 requires, contradicts) doxygen-DX_CURRENT_FEATURE]) 98 ]) 99 100 # DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE) 101 # ---------------------------------------------------------- 102 # Turn off the DX_CURRENT_FEATURE if the required feature is off. 103 AC_DEFUN([DX_CLEAR_DEPEND], [ 104 test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_[]DX_CURRENT_FEATURE], 0) 105 ]) 106 107 # DX_FEATURE_ARG(FEATURE, DESCRIPTION, 108 # CHECK_DEPEND, CLEAR_DEPEND, 109 # REQUIRE, DO-IF-ON, DO-IF-OFF) 110 # -------------------------------------------- 111 # Parse the command-line option controlling a feature. CHECK_DEPEND is called 112 # if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND), 113 # otherwise CLEAR_DEPEND is called to turn off the default state if a required 114 # feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional 115 # requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and 116 # DO-IF-ON or DO-IF-OFF are called according to the final state of the feature. 117 AC_DEFUN([DX_ARG_ABLE], [ 118 AC_DEFUN([DX_CURRENT_FEATURE], [$1]) 119 AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2]) 120 AC_ARG_ENABLE(doxygen-$1, 121 [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1], 122 [--enable-doxygen-$1]), 123 DX_IF_FEATURE([$1], [don't $2], [$2]))], 124 [ 125 case "$enableval" in 126 #( 127 y|Y|yes|Yes|YES) 128 AC_SUBST([DX_FLAG_$1], 1) 129 $3 130 ;; #( 131 n|N|no|No|NO) 132 AC_SUBST([DX_FLAG_$1], 0) 133 ;; #( 134 *) 135 AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1]) 136 ;; 137 esac 138 ], [ 139 AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)]) 140 $4 141 ]) 142 if DX_TEST_FEATURE([$1]); then 143 $5 144 : 145 fi 146 if DX_TEST_FEATURE([$1]); then 147 AM_CONDITIONAL(DX_COND_$1, :) 148 $6 149 : 150 else 151 AM_CONDITIONAL(DX_COND_$1, false) 152 $7 153 : 154 fi 155 ]) 156 157 ## -------------- ## 158 ## Public macros. ## 159 ## -------------- ## 160 161 # DX_XXX_FEATURE(DEFAULT_STATE) 162 # ----------------------------- 163 AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])]) 164 AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])]) 165 AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])]) 166 AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])]) 167 AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])]) 168 AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])]) 169 AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) 170 AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) 171 AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])]) 172 AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])]) 173 174 # DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR]) 175 # --------------------------------------------------------- 176 # PROJECT also serves as the base name for the documentation files. 177 # The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc". 178 AC_DEFUN([DX_INIT_DOXYGEN], [ 179 180 # Files: 181 AC_SUBST([DX_PROJECT], [$1]) 182 AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])]) 183 AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])]) 184 185 # Environment variables used inside doxygen.cfg: 186 DX_ENV_APPEND(SRCDIR, $srcdir) 187 DX_ENV_APPEND(PROJECT, $DX_PROJECT) 188 DX_ENV_APPEND(DOCDIR, $DX_DOCDIR) 189 DX_ENV_APPEND(VERSION, $PACKAGE_VERSION) 190 191 # Doxygen itself: 192 DX_ARG_ABLE(doc, [generate any doxygen documentation], 193 [], 194 [], 195 [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen) 196 DX_REQUIRE_PROG([DX_PERL], perl)], 197 [DX_ENV_APPEND(PERL_PATH, $DX_PERL)]) 198 199 # Dot for graphics: 200 DX_ARG_ABLE(dot, [generate graphics for doxygen documentation], 201 [DX_CHECK_DEPEND(doc, 1)], 202 [DX_CLEAR_DEPEND(doc, 1)], 203 [DX_REQUIRE_PROG([DX_DOT], dot)], 204 [DX_ENV_APPEND(HAVE_DOT, YES) 205 DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])], 206 [DX_ENV_APPEND(HAVE_DOT, NO)]) 207 208 # Man pages generation: 209 DX_ARG_ABLE(man, [generate doxygen manual pages], 210 [DX_CHECK_DEPEND(doc, 1)], 211 [DX_CLEAR_DEPEND(doc, 1)], 212 [], 213 [DX_ENV_APPEND(GENERATE_MAN, YES)], 214 [DX_ENV_APPEND(GENERATE_MAN, NO)]) 215 216 # RTF file generation: 217 DX_ARG_ABLE(rtf, [generate doxygen RTF documentation], 218 [DX_CHECK_DEPEND(doc, 1)], 219 [DX_CLEAR_DEPEND(doc, 1)], 220 [], 221 [DX_ENV_APPEND(GENERATE_RTF, YES)], 222 [DX_ENV_APPEND(GENERATE_RTF, NO)]) 223 224 # XML file generation: 225 DX_ARG_ABLE(xml, [generate doxygen XML documentation], 226 [DX_CHECK_DEPEND(doc, 1)], 227 [DX_CLEAR_DEPEND(doc, 1)], 228 [], 229 [DX_ENV_APPEND(GENERATE_XML, YES)], 230 [DX_ENV_APPEND(GENERATE_XML, NO)]) 231 232 # (Compressed) HTML help generation: 233 DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation], 234 [DX_CHECK_DEPEND(doc, 1)], 235 [DX_CLEAR_DEPEND(doc, 1)], 236 [DX_REQUIRE_PROG([DX_HHC], hhc)], 237 [DX_ENV_APPEND(HHC_PATH, $DX_HHC) 238 DX_ENV_APPEND(GENERATE_HTML, YES) 239 DX_ENV_APPEND(GENERATE_HTMLHELP, YES)], 240 [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)]) 241 242 # Seperate CHI file generation. 243 DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file], 244 [DX_CHECK_DEPEND(chm, 1)], 245 [DX_CLEAR_DEPEND(chm, 1)], 246 [], 247 [DX_ENV_APPEND(GENERATE_CHI, YES)], 248 [DX_ENV_APPEND(GENERATE_CHI, NO)]) 249 250 # Plain HTML pages generation: 251 DX_ARG_ABLE(html, [generate doxygen plain HTML documentation], 252 [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)], 253 [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)], 254 [], 255 [DX_ENV_APPEND(GENERATE_HTML, YES)], 256 [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)]) 257 258 # PostScript file generation: 259 DX_ARG_ABLE(ps, [generate doxygen PostScript documentation], 260 [DX_CHECK_DEPEND(doc, 1)], 261 [DX_CLEAR_DEPEND(doc, 1)], 262 [DX_REQUIRE_PROG([DX_LATEX], latex) 263 DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) 264 DX_REQUIRE_PROG([DX_DVIPS], dvips) 265 DX_REQUIRE_PROG([DX_EGREP], egrep)]) 266 267 # PDF file generation: 268 DX_ARG_ABLE(pdf, [generate doxygen PDF documentation], 269 [DX_CHECK_DEPEND(doc, 1)], 270 [DX_CLEAR_DEPEND(doc, 1)], 271 [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex) 272 DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) 273 DX_REQUIRE_PROG([DX_EGREP], egrep)]) 274 275 # LaTeX generation for PS and/or PDF: 276 if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then 277 AM_CONDITIONAL(DX_COND_latex, :) 278 DX_ENV_APPEND(GENERATE_LATEX, YES) 279 else 280 AM_CONDITIONAL(DX_COND_latex, false) 281 DX_ENV_APPEND(GENERATE_LATEX, NO) 282 fi 283 284 # Paper size for PS and/or PDF: 285 AC_ARG_VAR(DOXYGEN_PAPER_SIZE, 286 [a4wide (default), a4, letter, legal or executive]) 287 case "$DOXYGEN_PAPER_SIZE" in 288 #( 289 "") 290 AC_SUBST(DOXYGEN_PAPER_SIZE, "") 291 ;; #( 292 a4wide|a4|letter|legal|executive) 293 DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE) 294 ;; #( 295 *) 296 AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE']) 297 ;; 298 esac 299 300 #For debugging: 301 #echo DX_FLAG_doc=$DX_FLAG_doc 302 #echo DX_FLAG_dot=$DX_FLAG_dot 303 #echo DX_FLAG_man=$DX_FLAG_man 304 #echo DX_FLAG_html=$DX_FLAG_html 305 #echo DX_FLAG_chm=$DX_FLAG_chm 306 #echo DX_FLAG_chi=$DX_FLAG_chi 307 #echo DX_FLAG_rtf=$DX_FLAG_rtf 308 #echo DX_FLAG_xml=$DX_FLAG_xml 309 #echo DX_FLAG_pdf=$DX_FLAG_pdf 310 #echo DX_FLAG_ps=$DX_FLAG_ps 311 #echo DX_ENV=$DX_ENV 312 ]) 1 ../../m4/ac_doxygen.m4 -
Property mode
changed from
-
m4/acx_compilerflags.m4
-
Property mode
changed from
100644
to120000
r986c80 redcda5 1 # AC_SET_COMPILER_FLAGS(optimization, debugging, warnings) 2 #---------------------------------------------------------------- 3 AC_DEFUN([AC_SET_COMPILER_FLAGS],[ 4 AC_MSG_NOTICE([Using AC@&t@_SET_COMPILER_FLAGS macro]) 5 6 dnl optimization 7 if test ! x"$1" = xno; then 8 if test x"$2" = xno; then 9 if test x"$1" = xyes; then 10 optimization="-O2" 11 else 12 optimization="-O$1" 13 fi 14 fi 15 fi 16 dnl debugging info 17 if ! test x"$2" = xno; then 18 if test x"$2" = xyes; then 19 debugging="-g3" 20 else 21 debugging="-g$2" 22 fi 23 AC_DEFINE(HAVE_DEBUG,1, ["Output debugging info"]) 24 AC_SUBST(HAVE_DEBUG) 25 fi 26 27 dnl enable all warnings 28 if test x"$3" = xsome; then 29 dnl even without debugging we want some minimal info of something's utterly wrong 30 Cwarnings="-Wall" 31 CXXwarnings="-Wall" 32 fi 33 if test x"$3" = xfull; then 34 Cwarnings="-Wall -W -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wshadow -Wpointer-arith -Wcast-align -Wcast-qual -Wwrite-strings -Wredundant-decls -Wnested-externs -Wmissing-noreturn -Wformat-security -Wmissing-format-attribute -Winit-self" 35 CXXwarnings="-Wall -W -Wshadow -Wpointer-arith -Wcast-align -Wcast-qual -Wwrite-strings -Wredundant-decls -Wmissing-noreturn -Wformat-security -Wmissing-format-attribute -Winit-self" 36 fi 37 if test x"$3" = xnone; then 38 unset Cwarnings 39 unset CXXwarnings 40 else 41 AC_DEFINE(HAVE_WARNINGS,$enable_warnings, ["Output compiler warnings"]) 42 fi 43 44 # finally, apply whatever was set 45 CFLAGS="$CFLAGS $debugging $optimization $Cwarnings" 46 CXXFLAGS="$CXXFLAGS $debugging $optimization $CXXwarnings" 47 48 ]) 1 ../../m4/acx_compilerflags.m4 -
Property mode
changed from
-
src/Hbondangle.db
-
Property mode
changed from
100755
to100644
r986c80 redcda5 4 4 7 180 110 106.67 5 5 8 180 104.5 -1 6 14 180 120 109. 476 14 180 120 109.5 7 7 15 180 -1 -1 8 8 16 180 -1 -1 9 9 17 180 -1 -1 10 20 180 120 109.4711 10 34 180 -1 -1 12 11 35 180 -1 -1 -
Property mode
changed from
-
src/Hbonddistance.db
-
Property mode
changed from
100755
to100644
r986c80 redcda5 9 9 16 1.35 -1 -1 10 10 17 1.29 -1 -1 11 20 1.09 1.09 -112 11 34 1.47 -1 -1 13 12 35 1.44 -1 -1 -
Property mode
changed from
-
src/Makefile.am
-
Property mode
changed from
100755
to100644
r986c80 redcda5 10 10 11 11 12 EXTRA_DIST = ${molecuilder_DATA}12 #EXTRA_DIST = ${molecuilder_DATA} -
Property mode
changed from
-
src/analyzer.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 25 25 periodentafel *periode = NULL; // and a period table of all elements 26 26 EnergyMatrix Energy; 27 EnergyMatrix EnergyFragments;27 EnergyMatrix Hcorrection; 28 28 ForceMatrix Force; 29 ForceMatrix ForceFragments;30 HessianMatrix Hessian;31 HessianMatrix HessianFragments;32 EnergyMatrix Hcorrection;33 EnergyMatrix HcorrectionFragments;34 29 ForceMatrix Shielding; 35 30 ForceMatrix ShieldingPAS; 36 ForceMatrix Chi;37 ForceMatrix ChiPAS;38 31 EnergyMatrix Time; 32 EnergyMatrix EnergyFragments; 33 EnergyMatrix HcorrectionFragments; 34 ForceMatrix ForceFragments; 39 35 ForceMatrix ShieldingFragments; 40 36 ForceMatrix ShieldingPASFragments; 41 ForceMatrix ChiFragments;42 ForceMatrix ChiPASFragments;43 37 KeySetsContainer KeySet; 44 38 ofstream output; … … 55 49 stringstream yrange; 56 50 char *dir = NULL; 57 bool NoHCorrection = false; 58 bool NoHessian = false; 59 bool NoTime = false; 51 bool Hcorrected = true; 52 double norm; 60 53 int counter; 61 54 … … 91 84 // ------------- Parse through all Fragment subdirs -------- 92 85 if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix,0,0)) return 1; 93 if (!Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX,0,0)) { 94 NoHCorrection = true; 95 cout << "No HCorrection file found, skipping these." << endl; 96 } 97 86 Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX,0,0); 98 87 if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix,0,0)) return 1; 99 if (!Hessian.ParseFragmentMatrix(argv[1], dir, HessianSuffix,0,0)) { 100 NoHessian = true; 101 cout << "No Hessian file found, skipping these." << endl; 102 } 103 if (!Time.ParseFragmentMatrix(argv[1], dir, TimeSuffix, 10,1)) { 104 NoTime = true; 105 cout << "No speed file found, skipping these." << endl; 106 } 88 if (!Time.ParseFragmentMatrix(argv[1], dir, TimeSuffix, 10,1)) return 1; 107 89 if (periode != NULL) { // also look for PAS values 108 90 if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1; 109 91 if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1; 110 if (!Chi.ParseFragmentMatrix(argv[1], dir, ChiSuffix, 1, 0)) return 1;111 if (!ChiPAS.ParseFragmentMatrix(argv[1], dir, ChiPASSuffix, 1, 0)) return 1;112 92 } 113 93 114 94 // ---------- Parse the TE Factors into an array ----------------- 115 if (!Energy.InitialiseIndices()) return 1; 116 if (!NoHCorrection) 117 Hcorrection.InitialiseIndices(); 95 if (!Energy.ParseIndices()) return 1; 96 if (Hcorrected) Hcorrection.ParseIndices(); 118 97 119 98 // ---------- Parse the Force indices into an array --------------- 120 99 if (!Force.ParseIndices(argv[1])) return 1; 121 100 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1; 122 if (!ForceFragments.InitialiseIndices((class MatrixContainer *)&Force)) return 1; 123 124 // ---------- Parse hessian indices into an array ----------------- 125 if (!NoHessian) { 126 if (!Hessian.InitialiseIndices((class MatrixContainer *)&Force)) return 1; 127 if (!HessianFragments.AllocateMatrix(Hessian.Header, Hessian.MatrixCounter, Hessian.RowCounter, Hessian.ColumnCounter)) return 1; 128 if (!HessianFragments.InitialiseIndices((class MatrixContainer *)&Force)) return 1; 129 } 101 if (!ForceFragments.ParseIndices(argv[1])) return 1; 130 102 131 103 // ---------- Parse the shielding indices into an array --------------- … … 133 105 if(!Shielding.ParseIndices(argv[1])) return 1; 134 106 if(!ShieldingPAS.ParseIndices(argv[1])) return 1; 135 if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1;136 if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1;137 if(!ShieldingFragments.ParseIndices(argv[1])) return 1;138 if(!ShieldingPASFragments.ParseIndices(argv[1])) return 1;139 if(!Chi.ParseIndices(argv[1])) return 1;140 if(!ChiPAS.ParseIndices(argv[1])) return 1;141 if (!ChiFragments.AllocateMatrix(Chi.Header, Chi.MatrixCounter, Chi.RowCounter, Chi.ColumnCounter)) return 1;142 if (!ChiPASFragments.AllocateMatrix(ChiPAS.Header, ChiPAS.MatrixCounter, ChiPAS.RowCounter, ChiPAS.ColumnCounter)) return 1;143 if(!ChiFragments.ParseIndices(argv[1])) return 1;144 if(!ChiPASFragments.ParseIndices(argv[1])) return 1;145 107 } 146 108 … … 151 113 // ---------- Parse fragment files created by 'joiner' into an array ------------- 152 114 if (!EnergyFragments.ParseFragmentMatrix(argv[1], dir, EnergyFragmentSuffix,0,0)) return 1; 153 if (!NoHCorrection) 154 HcorrectionFragments.ParseFragmentMatrix(argv[1], dir, HcorrectionFragmentSuffix,0,0); 115 if (Hcorrected) HcorrectionFragments.ParseFragmentMatrix(argv[1], dir, HcorrectionFragmentSuffix,0,0); 155 116 if (!ForceFragments.ParseFragmentMatrix(argv[1], dir, ForceFragmentSuffix,0,0)) return 1; 156 if (!NoHessian)157 if (!HessianFragments.ParseFragmentMatrix(argv[1], dir, HessianFragmentSuffix,0,0)) return 1;158 117 if (periode != NULL) { // also look for PAS values 159 if (!ShieldingFragments.ParseFragmentMatrix(argv[1], dir, ShieldingFragmentSuffix, 1, 0)) return 1; 160 if (!ShieldingPASFragments.ParseFragmentMatrix(argv[1], dir, ShieldingPASFragmentSuffix, 1, 0)) return 1; 161 if (!ChiFragments.ParseFragmentMatrix(argv[1], dir, ChiFragmentSuffix, 1, 0)) return 1; 162 if (!ChiPASFragments.ParseFragmentMatrix(argv[1], dir, ChiPASFragmentSuffix, 1, 0)) return 1; 118 if (!ShieldingFragments.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1; 119 if (!ShieldingPASFragments.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1; 163 120 } 164 121 … … 169 126 filename << argv[3] << "/" << "energy-forces.all"; 170 127 output.open(filename.str().c_str(), ios::out); 171 output << endl << "Total Energy" << endl << "==============" << endl << Energy.Header [Energy.MatrixCounter]<< endl;128 output << endl << "Total Energy" << endl << "==============" << endl << Energy.Header << endl; 172 129 for(int j=0;j<Energy.RowCounter[Energy.MatrixCounter];j++) { 173 for(int k=0;k<Energy.ColumnCounter [Energy.MatrixCounter];k++)130 for(int k=0;k<Energy.ColumnCounter;k++) 174 131 output << scientific << Energy.Matrix[ Energy.MatrixCounter ][j][k] << "\t"; 175 132 output << endl; … … 177 134 output << endl; 178 135 179 output << endl << "Total Forces" << endl << "===============" << endl << Force.Header [Force.MatrixCounter]<< endl;136 output << endl << "Total Forces" << endl << "===============" << endl << Force.Header << endl; 180 137 for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) { 181 for(int k=0;k<Force.ColumnCounter [Force.MatrixCounter];k++)138 for(int k=0;k<Force.ColumnCounter;k++) 182 139 output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t"; 183 140 output << endl; … … 185 142 output << endl; 186 143 187 if (!NoHessian) {188 output << endl << "Total Hessian" << endl << "===============" << endl << Hessian.Header[Hessian.MatrixCounter] << endl;189 for(int j=0;j<Hessian.RowCounter[Hessian.MatrixCounter];j++) {190 for(int k=0;k<Hessian.ColumnCounter[Hessian.MatrixCounter];k++)191 output << scientific << Hessian.Matrix[ Hessian.MatrixCounter ][j][k] << "\t";192 output << endl;193 }194 output << endl;195 }196 197 144 if (periode != NULL) { // also look for PAS values 198 output << endl << "Total Shieldings" << endl << "===============" << endl << Shielding.Header [Hessian.MatrixCounter]<< endl;145 output << endl << "Total Shieldings" << endl << "===============" << endl << Shielding.Header << endl; 199 146 for(int j=0;j<Shielding.RowCounter[Shielding.MatrixCounter];j++) { 200 for(int k=0;k<Shielding.ColumnCounter [Shielding.MatrixCounter];k++)147 for(int k=0;k<Shielding.ColumnCounter;k++) 201 148 output << scientific << Shielding.Matrix[ Shielding.MatrixCounter ][j][k] << "\t"; 202 149 output << endl; … … 204 151 output << endl; 205 152 206 output << endl << "Total Shieldings PAS" << endl << "===============" << endl << ShieldingPAS.Header [ShieldingPAS.MatrixCounter]<< endl;153 output << endl << "Total Shieldings PAS" << endl << "===============" << endl << ShieldingPAS.Header << endl; 207 154 for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) { 208 for(int k=0;k<ShieldingPAS.ColumnCounter [ShieldingPAS.MatrixCounter];k++)155 for(int k=0;k<ShieldingPAS.ColumnCounter;k++) 209 156 output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; 210 157 output << endl; 211 158 } 212 159 output << endl; 213 214 output << endl << "Total Chis" << endl << "===============" << endl << Chi.Header[Chi.MatrixCounter] << endl; 215 for(int j=0;j<Chi.RowCounter[Chi.MatrixCounter];j++) { 216 for(int k=0;k<Chi.ColumnCounter[Chi.MatrixCounter];k++) 217 output << scientific << Chi.Matrix[ Chi.MatrixCounter ][j][k] << "\t"; 218 output << endl; 219 } 220 output << endl; 221 222 output << endl << "Total Chis PAS" << endl << "===============" << endl << ChiPAS.Header[ChiPAS.MatrixCounter] << endl; 223 for(int j=0;j<ChiPAS.RowCounter[ChiPAS.MatrixCounter];j++) { 224 for(int k=0;k<ChiPAS.ColumnCounter[ChiPAS.MatrixCounter];k++) 225 output << scientific << ChiPAS.Matrix[ ChiPAS.MatrixCounter ][j][k] << "\t"; 226 output << endl; 227 } 228 output << endl; 229 } 230 231 if (!NoTime) { 232 output << endl << "Total Times" << endl << "===============" << endl << Time.Header[Time.MatrixCounter] << endl; 233 for(int j=0;j<Time.RowCounter[Time.MatrixCounter];j++) { 234 for(int k=0;k<Time.ColumnCounter[Time.MatrixCounter];k++) { 235 output << scientific << Time.Matrix[ Time.MatrixCounter ][j][k] << "\t"; 236 } 237 output << endl; 238 } 239 output << endl; 240 } 160 } 161 162 output << endl << "Total Times" << endl << "===============" << endl << Time.Header << endl; 163 for(int j=0;j<Time.RowCounter[Time.MatrixCounter];j++) { 164 for(int k=0;k<Time.ColumnCounter;k++) { 165 output << scientific << Time.Matrix[ Time.MatrixCounter ][j][k] << "\t"; 166 } 167 output << endl; 168 } 169 output << endl; 241 170 output.close(); 242 if (!NoTime) 243 for(int k=0;k<Time.ColumnCounter[Time.MatrixCounter];k++) 244 Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k] = Time.Matrix[ Time.MatrixCounter ][Time.RowCounter[Time.MatrixCounter]-1][k]; 171 for(int k=0;k<Time.ColumnCounter;k++) 172 Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k] = Time.Matrix[ Time.MatrixCounter ][Time.RowCounter[Time.MatrixCounter]-1][k]; 245 173 246 174 // +++++++++++++++ ANALYZING ++++++++++++++++++++++++++++++ … … 252 180 // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order 253 181 // +++++++++++++++++++++++++++++++++++++++ Plotting Delta Simtime vs Bond Order 254 if (!NoTime) { 255 if (!OpenOutputFile(output, argv[3], "SimTime-Order.dat" )) return false; 256 if (!OpenOutputFile(output2, argv[3], "DeltaSimTime-Order.dat" )) return false; 257 for(int j=Time.RowCounter[Time.MatrixCounter];j--;) 258 for(int k=Time.ColumnCounter[Time.MatrixCounter];k--;) { 259 Time.Matrix[ Time.MatrixCounter ][j][k] = 0.; 260 } 261 counter = 0; 262 output << "#Order\tFrag.No.\t" << Time.Header[Time.MatrixCounter] << endl; 263 output2 << "#Order\tFrag.No.\t" << Time.Header[Time.MatrixCounter] << endl; 264 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 265 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) 266 for(int j=Time.RowCounter[Time.MatrixCounter];j--;) 267 for(int k=Time.ColumnCounter[Time.MatrixCounter];k--;) { 268 Time.Matrix[ Time.MatrixCounter ][j][k] += Time.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 269 } 270 counter += KeySet.FragmentsPerOrder[BondOrder]; 271 output << BondOrder+1 << "\t" << counter; 272 output2 << BondOrder+1 << "\t" << counter; 273 for(int k=0;k<Time.ColumnCounter[Time.MatrixCounter];k++) { 274 output << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k]; 275 if (fabs(Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]) > MYEPSILON) 276 output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k] / Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]; 277 else 278 output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k]; 279 } 280 output << endl; 281 output2 << endl; 282 } 283 output.close(); 284 output2.close(); 285 } 286 287 if (!NoHessian) { 288 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in hessian to full QM 289 if (!CreateDataDeltaHessianOrderPerAtom(Hessian, HessianFragments, KeySet, argv[3], "DeltaHessian_xx-Order", "Plot of error between approximated hessian and full hessian versus the Bond Order", datum)) return 1; 290 291 if (!CreateDataDeltaFrobeniusOrderPerAtom(Hessian, HessianFragments, KeySet, argv[3], "DeltaFrobeniusHessian_xx-Order", "Plot of error between approximated hessian and full hessian in the frobenius norm versus the Bond Order", datum)) return 1; 292 293 // ++++++++++++++++++++++++++++++++++++++Plotting Hessian vs. Order 294 if (!CreateDataHessianOrderPerAtom(HessianFragments, KeySet, argv[3], "Hessian_xx-Order", "Plot of approximated hessian versus the Bond Order", datum)) return 1; 295 if (!AppendOutputFile(output, argv[3], "Hessian_xx-Order.dat" )) return false; 296 output << endl << "# Full" << endl; 297 for(int j=0;j<Hessian.RowCounter[Hessian.MatrixCounter];j++) { 298 output << j << "\t"; 299 for(int k=0;k<Hessian.ColumnCounter[Force.MatrixCounter];k++) 300 output << scientific << Hessian.Matrix[ Hessian.MatrixCounter ][j][k] << "\t"; 301 output << endl; 302 } 303 output.close(); 304 } 305 306 // +++++++++++++++++++++++++++++++++++++++ Plotting shieldings 307 if (periode != NULL) { // also look for PAS values 308 if (!CreateDataDeltaForcesOrderPerAtom(ShieldingPAS, ShieldingPASFragments, KeySet, argv[3], "DeltaShieldingsPAS-Order", "Plot of error between approximated shieldings and full shieldings versus the Bond Order", datum)) return 1; 309 if (!CreateDataForcesOrderPerAtom(ShieldingPASFragments, KeySet, argv[3], "ShieldingsPAS-Order", "Plot of approximated shieldings versus the Bond Order", datum)) return 1; 310 if (!AppendOutputFile(output, argv[3], "ShieldingsPAS-Order.dat" )) return false; 311 output << endl << "# Full" << endl; 312 for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) { 313 output << j << "\t"; 314 for(int k=0;k<ShieldingPAS.ColumnCounter[ShieldingPAS.MatrixCounter];k++) 315 output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; //*(((k>1) && (k<6))? 1.e6 : 1.) << "\t"; 316 output << endl; 317 } 318 output.close(); 319 if (!CreateDataDeltaForcesOrderPerAtom(ChiPAS, ChiPASFragments, KeySet, argv[3], "DeltaChisPAS-Order", "Plot of error between approximated Chis and full Chis versus the Bond Order", datum)) return 1; 320 if (!CreateDataForcesOrderPerAtom(ChiPASFragments, KeySet, argv[3], "ChisPAS-Order", "Plot of approximated Chis versus the Bond Order", datum)) return 1; 321 if (!AppendOutputFile(output, argv[3], "ChisPAS-Order.dat" )) return false; 322 output << endl << "# Full" << endl; 323 for(int j=0;j<ChiPAS.RowCounter[ChiPAS.MatrixCounter];j++) { 324 output << j << "\t"; 325 for(int k=0;k<ChiPAS.ColumnCounter[ChiPAS.MatrixCounter];k++) 326 output << scientific << ChiPAS.Matrix[ ChiPAS.MatrixCounter ][j][k] << "\t"; //*(((k>1) && (k<6))? 1.e6 : 1.) << "\t"; 327 output << endl; 328 } 329 output.close(); 330 } 331 332 182 if (!OpenOutputFile(output, argv[3], "SimTime-Order.dat" )) return false; 183 if (!OpenOutputFile(output2, argv[3], "DeltaSimTime-Order.dat" )) return false; 184 for(int j=Time.RowCounter[Time.MatrixCounter];j--;) 185 for(int k=Time.ColumnCounter;k--;) { 186 Time.Matrix[ Time.MatrixCounter ][j][k] = 0.; 187 } 188 counter = 0; 189 output << "#Order\tFrag.No.\t" << Time.Header << endl; 190 output2 << "#Order\tFrag.No.\t" << Time.Header << endl; 191 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 192 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) 193 for(int j=Time.RowCounter[Time.MatrixCounter];j--;) 194 for(int k=Time.ColumnCounter;k--;) { 195 Time.Matrix[ Time.MatrixCounter ][j][k] += Time.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 196 } 197 counter += KeySet.FragmentsPerOrder[BondOrder]; 198 output << BondOrder+1 << "\t" << counter; 199 output2 << BondOrder+1 << "\t" << counter; 200 for(int k=0;k<Time.ColumnCounter;k++) { 201 output << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k]; 202 if (fabs(Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]) > MYEPSILON) 203 output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k] / Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]; 204 else 205 output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k]; 206 } 207 output << endl; 208 output2 << endl; 209 } 210 output.close(); 211 output2.close(); 212 213 333 214 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM 334 215 if (!CreateDataDeltaEnergyOrder(Energy, EnergyFragments, KeySet, argv[3], "DeltaEnergies-Order", "Plot of error between approximated and full energies energies versus the Bond Order", datum)) return 1; … … 351 232 // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order 352 233 if (!CreateDataForcesOrderPerAtom(ForceFragments, KeySet, argv[3], "Forces-Order", "Plot of approximated forces versus the Bond Order", datum)) return 1; 353 if (!AppendOutputFile(output, argv[3], "Forces-Order.dat" )) return false; 354 output << endl << "# Full" << endl; 355 for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) { 356 output << j << "\t"; 357 for(int k=0;k<Force.ColumnCounter[Force.MatrixCounter];k++) 358 output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t"; 359 output << endl; 360 } 361 output.close(); 234 362 235 // min force 363 236 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MinForces-Order", "Plot of min approximated forces versus the Bond Order", datum, CreateMinimumForce)) return 1; … … 404 277 yrange.str("[1e-8:1e+1]"); 405 278 406 if (!NoTime) { 407 // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order 408 if (!CreatePlotOrder(Time, KeySet, argv[3], "SimTime-Order", 1, "below", "y", "", 1, 1, "bond order k", "Evaluation time [s]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1; 409 } 279 // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order 280 if (!CreatePlotOrder(Time, KeySet, argv[3], "SimTime-Order", 1, "below", "y", "", 1, 1, "bond order k", "Evaluation time [s]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1; 410 281 411 282 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM … … 488 359 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "maximum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; 489 360 490 // +++++++++++++++++++++++++++++++=Ploting approximated and true shielding for each atom491 if (periode != NULL) { // also look for PAS values492 if(!OpenOutputFile(output, argv[3], "ShieldingsPAS-Order.pyx")) return 1;493 if(!OpenOutputFile(output2, argv[3], "DeltaShieldingsPAS-Order.pyx")) return 1;494 CreatePlotHeader(output, "ShieldingsPAS-Order", 1, "top right", NULL, NULL, 1, 5, "nuclei index", "iso chemical shielding value [ppm]");495 CreatePlotHeader(output2, "DeltaShieldingsPAS-Order", 1, "top right", NULL, NULL, 1, 5, "nuclei index", "iso chemical shielding value [ppm]");496 double step=0.8/KeySet.Order;497 output << "set boxwidth " << step << endl;498 output << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl;499 output2 << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl;500 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {501 output << "'ShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1+" << step*(double)BondOrder << "):7 with boxes, \\" << endl;502 output2 << "'DeltaShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1):7 with linespoints";503 if (BondOrder-1 != KeySet.Order)504 output2 << ", \\" << endl;505 }506 output << "'ShieldingsPAS-Order.dat' index " << KeySet.Order << " title 'Full' using ($1+" << step*(double)KeySet.Order << "):7 with boxes" << endl;507 output2.close();508 509 if(!OpenOutputFile(output, argv[3], "ChisPAS-Order.pyx")) return 1;510 if(!OpenOutputFile(output2, argv[3], "DeltaChisPAS-Order.pyx")) return 1;511 CreatePlotHeader(output, "ChisPAS-Order", 1, "top right", NULL, NULL, 1, 5, "nuclei index", "iso chemical Chi value [ppm]");512 CreatePlotHeader(output2, "DeltaChisPAS-Order", 1, "top right", NULL, NULL, 1, 5, "nuclei index", "iso chemical Chi value [ppm]");513 output << "set boxwidth " << step << endl;514 output << "plot [0:" << ChiPAS.RowCounter[ChiPAS.MatrixCounter]+10 << "]\\" << endl;515 output2 << "plot [0:" << ChiPAS.RowCounter[ChiPAS.MatrixCounter]+10 << "]\\" << endl;516 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {517 output << "'ChisPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1+" << step*(double)BondOrder << "):7 with boxes, \\" << endl;518 output2 << "'DeltaChisPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1):7 with linespoints";519 if (BondOrder-1 != KeySet.Order)520 output2 << ", \\" << endl;521 }522 output << "'ChisPAS-Order.dat' index " << KeySet.Order << " title 'Full' using ($1+" << step*(double)KeySet.Order << "):7 with boxes" << endl;523 output.close();524 output2.close();525 526 if(!OpenOutputFile(output, argv[3], "ChisPAS-Order.pyx")) return 1;527 if(!OpenOutputFile(output2, argv[3], "DeltaChisPAS-Order.pyx")) return 1;528 CreatePlotHeader(output, "ChisPAS-Order", 1, "top right", NULL, NULL, 1, 5, "nuclei index", "iso chemical Chi value [ppm]");529 CreatePlotHeader(output2, "DeltaChisPAS-Order", 1, "top right", NULL, NULL, 1, 5, "nuclei index", "iso chemical Chi value [ppm]");530 output << "set boxwidth " << step << endl;531 output << "plot [0:" << ChiPAS.RowCounter[ChiPAS.MatrixCounter]+10 << "]\\" << endl;532 output2 << "plot [0:" << ChiPAS.RowCounter[ChiPAS.MatrixCounter]+10 << "]\\" << endl;533 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {534 output << "'ChisPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1+" << step*(double)BondOrder << "):7 with boxes, \\" << endl;535 output2 << "'DeltaChisPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1):7 with linespoints";536 if (BondOrder-1 != KeySet.Order)537 output2 << ", \\" << endl;538 }539 output << "'ChisPAS-Order.dat' index " << KeySet.Order << " title 'Full' using ($1+" << step*(double)KeySet.Order << "):7 with boxes" << endl;540 output.close();541 output2.close();542 }543 544 361 // create Makefile 545 362 if(!OpenOutputFile(output, argv[3], "Makefile")) return 1; -
Property mode
changed from
-
src/atom.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 85 85 }; 86 86 87 ostream & operator << (ostream &ost, constatom &a)87 ostream & operator << (ostream &ost, atom &a) 88 88 { 89 89 ost << "[" << a.Name << "|" << &a << "]"; -
Property mode
changed from
-
src/bond.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 82 82 }; 83 83 84 ostream & operator << (ostream &ost, constbond &b)84 ostream & operator << (ostream &ost, bond &b) 85 85 { 86 86 ost << "[" << b.leftatom->Name << " <" << b.BondDegree << "(H" << b.HydrogenBond << ")>" << b.rightatom->Name << "]"; … … 98 98 if(rightatom == Atom) 99 99 return leftatom; 100 cerr << "Bond " << *this << " does not contain atom " << *Atom << "!" << endl;101 100 return NULL; 102 101 }; -
Property mode
changed from
-
src/boundary.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 2 2 #include "boundary.hpp" 3 3 4 #define DEBUG 15 #define DoTecplotOutput 06 #define DoRaster3DOutput 17 #define TecplotSuffix ".dat"8 #define Raster3DSuffix ".r3d"9 10 4 // ======================================== Points on Boundary ================================= 11 5 … … 14 8 LinesCount = 0; 15 9 Nr = -1; 16 } 17 ; 10 }; 18 11 19 12 BoundaryPointSet::BoundaryPointSet(atom *Walker) … … 22 15 LinesCount = 0; 23 16 Nr = Walker->nr; 24 } 25 ; 17 }; 26 18 27 19 BoundaryPointSet::~BoundaryPointSet() … … 29 21 cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl; 30 22 node = NULL; 31 lines.clear(); 32 } 33 ; 34 35 void 36 BoundaryPointSet::AddLine(class BoundaryLineSet *line) 37 { 38 cout << Verbose(6) << "Adding " << *this << " to line " << *line << "." 39 << endl; 40 if (line->endpoints[0] == this) 41 { 42 lines.insert(LinePair(line->endpoints[1]->Nr, line)); 43 } 44 else 45 { 46 lines.insert(LinePair(line->endpoints[0]->Nr, line)); 47 } 23 }; 24 25 void BoundaryPointSet::AddLine(class BoundaryLineSet *line) 26 { 27 cout << Verbose(6) << "Adding line " << *line << " to " << *this << "." << endl; 28 if (line->endpoints[0] == this) { 29 lines.insert ( LinePair( line->endpoints[1]->Nr, line) ); 30 } else { 31 lines.insert ( LinePair( line->endpoints[0]->Nr, line) ); 32 } 48 33 LinesCount++; 49 } 50 ; 51 52 ostream & 53 operator <<(ostream &ost, BoundaryPointSet &a) 34 }; 35 36 ostream & operator << (ostream &ost, BoundaryPointSet &a) 54 37 { 55 38 ost << "[" << a.Nr << "|" << a.node->Name << "]"; 56 39 return ost; 57 } 58 ; 40 }; 59 41 60 42 // ======================================== Lines on Boundary ================================= … … 62 44 BoundaryLineSet::BoundaryLineSet() 63 45 { 64 for (int i = 0; i < 2;i++)46 for (int i=0;i<2;i++) 65 47 endpoints[i] = NULL; 66 48 TrianglesCount = 0; 67 49 Nr = -1; 68 } 69 ; 50 }; 70 51 71 52 BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number) … … 76 57 SetEndpointsOrdered(endpoints, Point[0], Point[1]); 77 58 // add this line to the hash maps of both endpoints 78 Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding.79 Point[1]->AddLine(this); //59 Point[0]->AddLine(this); 60 Point[1]->AddLine(this); 80 61 // clear triangles list 81 62 TrianglesCount = 0; 82 63 cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl; 83 } 84 ; 64 }; 85 65 86 66 BoundaryLineSet::~BoundaryLineSet() 87 67 { 88 for (int i = 0; i < 2; i++) { 89 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 90 endpoints[i]->lines.erase(Nr); 91 LineMap::iterator tester = endpoints[i]->lines.begin(); 92 tester++; 93 if (tester == endpoints[i]->lines.end()) { 94 cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl; 95 if (endpoints[i] != NULL) { 96 delete(endpoints[i]); 97 endpoints[i] = NULL; 98 } else 99 cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl; 100 } else 101 cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl; 102 } 103 } 104 ; 105 106 void 107 BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 108 { 109 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." 110 << endl; 111 triangles.insert(TrianglePair(TrianglesCount, triangle)); 68 for (int i=0;i<2;i++) { 69 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 70 endpoints[i]->lines.erase(Nr); 71 LineMap::iterator tester = endpoints[i]->lines.begin(); 72 tester++; 73 if (tester == endpoints[i]->lines.end()) { 74 cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl; 75 delete(endpoints[i]); 76 } else 77 cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl; 78 } 79 }; 80 81 void BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 82 { 83 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." << endl; 84 triangles.insert ( TrianglePair( TrianglesCount, triangle) ); 112 85 TrianglesCount++; 113 } 114 ; 115 116 ostream & 117 operator <<(ostream &ost, BoundaryLineSet &a) 118 { 119 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 120 << a.endpoints[1]->node->Name << "]"; 86 }; 87 88 ostream & operator << (ostream &ost, BoundaryLineSet &a) 89 { 90 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "]"; 121 91 return ost; 122 } 123 ; 92 }; 124 93 125 94 // ======================================== Triangles on Boundary ================================= … … 128 97 BoundaryTriangleSet::BoundaryTriangleSet() 129 98 { 130 for (int i = 0; i < 3; i++) 131 { 132 endpoints[i] = NULL; 133 lines[i] = NULL; 134 } 99 for (int i=0;i<3;i++) { 100 endpoints[i] = NULL; 101 lines[i] = NULL; 102 } 135 103 Nr = -1; 136 } 137 ; 138 139 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], 140 int number) 104 }; 105 106 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], int number) 141 107 { 142 108 // set number … … 144 110 // set lines 145 111 cout << Verbose(5) << "New triangle " << Nr << ":" << endl; 146 for (int i = 0; i < 3; i++) 147 { 148 lines[i] = line[i]; 149 lines[i]->AddTriangle(this); 112 for (int i=0;i<3;i++) { 113 lines[i] = line[i]; 114 lines[i]->AddTriangle(this); 115 } 116 // get ascending order of endpoints 117 map <int, class BoundaryPointSet * > OrderMap; 118 for(int i=0;i<3;i++) // for all three lines 119 for (int j=0;j<2;j++) { // for both endpoints 120 OrderMap.insert ( pair <int, class BoundaryPointSet * >( line[i]->endpoints[j]->Nr, line[i]->endpoints[j]) ); 121 // and we don't care whether insertion fails 150 122 } 151 // get ascending order of endpoints152 map<int, class BoundaryPointSet *> OrderMap;153 for (int i = 0; i < 3; i++)154 // for all three lines155 for (int j = 0; j < 2; j++)156 { // for both endpoints157 OrderMap.insert(pair<int, class BoundaryPointSet *> (158 line[i]->endpoints[j]->Nr, line[i]->endpoints[j]));159 // and we don't care whether insertion fails160 }161 123 // set endpoints 162 124 int Counter = 0; 163 125 cout << Verbose(6) << " with end points "; 164 for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner 165 != OrderMap.end(); runner++) 166 { 167 endpoints[Counter] = runner->second; 168 cout << " " << *endpoints[Counter]; 169 Counter++; 170 } 171 if (Counter < 3) 172 { 173 cerr << "ERROR! We have a triangle with only two distinct endpoints!" 174 << endl; 175 //exit(1); 176 } 126 for (map <int, class BoundaryPointSet * >::iterator runner = OrderMap.begin(); runner != OrderMap.end(); runner++) { 127 endpoints[Counter] = runner->second; 128 cout << " " << *endpoints[Counter]; 129 Counter++; 130 } 131 if (Counter < 3) { 132 cerr << "ERROR! We have a triangle with only two distinct endpoints!" << endl; 133 //exit(1); 134 } 177 135 cout << "." << endl; 178 } 179 ; 136 }; 180 137 181 138 BoundaryTriangleSet::~BoundaryTriangleSet() 182 139 { 183 for (int i = 0; i < 3; i++) { 184 cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl; 185 lines[i]->triangles.erase(Nr); 186 if (lines[i]->triangles.empty()) { 187 cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl; 188 if (lines[i] != NULL) { 189 delete (lines[i]); 190 lines[i] = NULL; 191 } else 192 cerr << "ERROR: This line " << i << " has already been free'd." << endl; 193 } else 194 cout << Verbose(5) << *lines[i] << " is still attached to a triangle." << endl; 195 } 196 } 197 ; 198 199 void 200 BoundaryTriangleSet::GetNormalVector(Vector &OtherVector) 140 for (int i=0;i<3;i++) { 141 cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl; 142 lines[i]->triangles.erase(Nr); 143 TriangleMap::iterator tester = lines[i]->triangles.begin(); 144 tester++; 145 if (tester == lines[i]->triangles.end()) { 146 cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl; 147 delete(lines[i]); 148 } else 149 cout << Verbose(5) << *lines[i] << " is still attached to a triangle." << endl; 150 } 151 }; 152 153 void BoundaryTriangleSet::GetNormalVector(Vector &NormalVector) 201 154 { 202 155 // get normal vector 203 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, 204 &endpoints[2]->node->x); 205 156 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, &endpoints[2]->node->x); 157 206 158 // make it always point inward (any offset vector onto plane projected onto normal vector suffices) 207 if (endpoints[0]->node->x.Projection(& OtherVector) > 0)159 if (endpoints[0]->node->x.Projection(&NormalVector) > 0) 208 160 NormalVector.Scale(-1.); 209 } 210 ; 211 212 ostream & 213 operator <<(ostream &ost, BoundaryTriangleSet &a) 214 { 215 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 216 << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]"; 161 }; 162 163 ostream & operator << (ostream &ost, BoundaryTriangleSet &a) 164 { 165 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]"; 217 166 return ost; 218 } 219 ; 167 }; 220 168 221 169 // ========================================== F U N C T I O N S ================================= … … 226 174 * \return point which is shared or NULL if none 227 175 */ 228 class BoundaryPointSet * 229 GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2) 230 { 231 class BoundaryLineSet * lines[2] = 232 { line1, line2 }; 176 class BoundaryPointSet * GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2) 177 { 178 class BoundaryLineSet * lines[2] = {line1, line2}; 233 179 class BoundaryPointSet *node = NULL; 234 map<int, class BoundaryPointSet *> OrderMap; 235 pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest; 236 for (int i = 0; i < 2; i++) 237 // for both lines 238 for (int j = 0; j < 2; j++) 239 { // for both endpoints 240 OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> ( 241 lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j])); 242 if (!OrderTest.second) 243 { // if insertion fails, we have common endpoint 244 node = OrderTest.first->second; 245 cout << Verbose(5) << "Common endpoint of lines " << *line1 246 << " and " << *line2 << " is: " << *node << "." << endl; 247 j = 2; 248 i = 2; 249 break; 250 } 180 map <int, class BoundaryPointSet * > OrderMap; 181 pair < map <int, class BoundaryPointSet * >::iterator, bool > OrderTest; 182 for(int i=0;i<2;i++) // for both lines 183 for (int j=0;j<2;j++) { // for both endpoints 184 OrderTest = OrderMap.insert ( pair <int, class BoundaryPointSet * >( lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]) ); 185 if (!OrderTest.second) { // if insertion fails, we have common endpoint 186 node = OrderTest.first->second; 187 cout << Verbose(5) << "Common endpoint of lines " << *line1 << " and " << *line2 << " is: " << *node << "." << endl; 188 j=2; 189 i=2; 190 break; 251 191 } 192 } 252 193 return node; 253 } 254 ; 194 }; 255 195 256 196 /** Determines the boundary points of a cluster. … … 261 201 * \param *mol molecule structure representing the cluster 262 202 */ 263 Boundaries * 264 GetBoundaryPoints(ofstream *out, molecule *mol) 203 Boundaries * GetBoundaryPoints(ofstream *out, molecule *mol) 265 204 { 266 205 atom *Walker = NULL; … … 268 207 LineMap LinesOnBoundary; 269 208 TriangleMap TrianglesOnBoundary; 270 209 271 210 *out << Verbose(1) << "Finding all boundary points." << endl; 272 Boundaries *BoundaryPoints = new Boundaries [NDIM];// first is alpha, second is (r, nr)211 Boundaries *BoundaryPoints = new Boundaries [NDIM]; // first is alpha, second is (r, nr) 273 212 BoundariesTestPair BoundaryTestPair; 274 213 Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector; 275 214 double radius, angle; 276 215 // 3a. Go through every axis 277 for (int axis = 0; axis < NDIM; axis++) 278 { 279 AxisVector.Zero(); 280 AngleReferenceVector.Zero(); 281 AngleReferenceNormalVector.Zero(); 282 AxisVector.x[axis] = 1.; 283 AngleReferenceVector.x[(axis + 1) % NDIM] = 1.; 284 AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.; 285 // *out << Verbose(1) << "Axisvector is "; 286 // AxisVector.Output(out); 287 // *out << " and AngleReferenceVector is "; 288 // AngleReferenceVector.Output(out); 289 // *out << "." << endl; 290 // *out << " and AngleReferenceNormalVector is "; 291 // AngleReferenceNormalVector.Output(out); 292 // *out << "." << endl; 293 // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours 294 Walker = mol->start; 295 while (Walker->next != mol->end) 216 for (int axis=0; axis<NDIM; axis++) { 217 AxisVector.Zero(); 218 AngleReferenceVector.Zero(); 219 AngleReferenceNormalVector.Zero(); 220 AxisVector.x[axis] = 1.; 221 AngleReferenceVector.x[(axis+1)%NDIM] = 1.; 222 AngleReferenceNormalVector.x[(axis+2)%NDIM] = 1.; 223 // *out << Verbose(1) << "Axisvector is "; 224 // AxisVector.Output(out); 225 // *out << " and AngleReferenceVector is "; 226 // AngleReferenceVector.Output(out); 227 // *out << "." << endl; 228 // *out << " and AngleReferenceNormalVector is "; 229 // AngleReferenceNormalVector.Output(out); 230 // *out << "." << endl; 231 // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours 232 Walker = mol->start; 233 while (Walker->next != mol->end) { 234 Walker = Walker->next; 235 Vector ProjectedVector; 236 ProjectedVector.CopyVector(&Walker->x); 237 ProjectedVector.ProjectOntoPlane(&AxisVector); 238 // correct for negative side 239 //if (Projection(y) < 0) 240 //angle = 2.*M_PI - angle; 241 radius = ProjectedVector.Norm(); 242 if (fabs(radius) > MYEPSILON) 243 angle = ProjectedVector.Angle(&AngleReferenceVector); 244 else 245 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues 246 247 //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl; 248 if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) { 249 angle = 2.*M_PI - angle; 250 } 251 //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): "; 252 //ProjectedVector.Output(out); 253 //*out << endl; 254 BoundaryTestPair = BoundaryPoints[axis].insert( BoundariesPair (angle, DistancePair (radius, Walker) ) ); 255 if (BoundaryTestPair.second) { // successfully inserted 256 } else { // same point exists, check first r, then distance of original vectors to center of gravity 257 *out << Verbose(2) << "Encountered two vectors whose projection onto axis " << axis << " is equal: " << endl; 258 *out << Verbose(2) << "Present vector: "; 259 BoundaryTestPair.first->second.second->x.Output(out); 260 *out << endl; 261 *out << Verbose(2) << "New vector: "; 262 Walker->x.Output(out); 263 *out << endl; 264 double tmp = ProjectedVector.Norm(); 265 if (tmp > BoundaryTestPair.first->second.first) { 266 BoundaryTestPair.first->second.first = tmp; 267 BoundaryTestPair.first->second.second = Walker; 268 *out << Verbose(2) << "Keeping new vector." << endl; 269 } else if (tmp == BoundaryTestPair.first->second.first) { 270 if (BoundaryTestPair.first->second.second->x.ScalarProduct(&BoundaryTestPair.first->second.second->x) < Walker->x.ScalarProduct(&Walker->x)) { // Norm() does a sqrt, which makes it a lot slower 271 BoundaryTestPair.first->second.second = Walker; 272 *out << Verbose(2) << "Keeping new vector." << endl; 273 } else { 274 *out << Verbose(2) << "Keeping present vector." << endl; 275 } 276 } else { 277 *out << Verbose(2) << "Keeping present vector." << endl; 278 } 279 } 280 } 281 // printing all inserted for debugging 282 // { 283 // *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl; 284 // int i=0; 285 // for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 286 // if (runner != BoundaryPoints[axis].begin()) 287 // *out << ", " << i << ": " << *runner->second.second; 288 // else 289 // *out << i << ": " << *runner->second.second; 290 // i++; 291 // } 292 // *out << endl; 293 // } 294 // 3c. throw out points whose distance is less than the mean of left and right neighbours 295 bool flag = false; 296 do { // do as long as we still throw one out per round 297 *out << Verbose(1) << "Looking for candidates to kick out by convex condition ... " << endl; 298 flag = false; 299 Boundaries::iterator left = BoundaryPoints[axis].end(); 300 Boundaries::iterator right = BoundaryPoints[axis].end(); 301 for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 302 // set neighbours correctly 303 if (runner == BoundaryPoints[axis].begin()) { 304 left = BoundaryPoints[axis].end(); 305 } else { 306 left = runner; 307 } 308 left--; 309 right = runner; 310 right++; 311 if (right == BoundaryPoints[axis].end()) { 312 right = BoundaryPoints[axis].begin(); 313 } 314 // check distance 315 316 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector) 296 317 { 297 Walker = Walker->next; 298 Vector ProjectedVector; 299 ProjectedVector.CopyVector(&Walker->x); 300 ProjectedVector.ProjectOntoPlane(&AxisVector); 301 // correct for negative side 302 //if (Projection(y) < 0) 303 //angle = 2.*M_PI - angle; 304 radius = ProjectedVector.Norm(); 305 if (fabs(radius) > MYEPSILON) 306 angle = ProjectedVector.Angle(&AngleReferenceVector); 307 else 308 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues 309 310 //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl; 311 if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) 312 { 313 angle = 2. * M_PI - angle; 314 } 315 //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): "; 316 //ProjectedVector.Output(out); 317 //*out << endl; 318 BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle, 319 DistancePair (radius, Walker))); 320 if (BoundaryTestPair.second) 321 { // successfully inserted 322 } 323 else 324 { // same point exists, check first r, then distance of original vectors to center of gravity 325 *out << Verbose(2) 326 << "Encountered two vectors whose projection onto axis " 327 << axis << " is equal: " << endl; 328 *out << Verbose(2) << "Present vector: "; 329 BoundaryTestPair.first->second.second->x.Output(out); 330 *out << endl; 331 *out << Verbose(2) << "New vector: "; 332 Walker->x.Output(out); 333 *out << endl; 334 double tmp = ProjectedVector.Norm(); 335 if (tmp > BoundaryTestPair.first->second.first) 336 { 337 BoundaryTestPair.first->second.first = tmp; 338 BoundaryTestPair.first->second.second = Walker; 339 *out << Verbose(2) << "Keeping new vector." << endl; 340 } 341 else if (tmp == BoundaryTestPair.first->second.first) 342 { 343 if (BoundaryTestPair.first->second.second->x.ScalarProduct( 344 &BoundaryTestPair.first->second.second->x) 345 < Walker->x.ScalarProduct(&Walker->x)) 346 { // Norm() does a sqrt, which makes it a lot slower 347 BoundaryTestPair.first->second.second = Walker; 348 *out << Verbose(2) << "Keeping new vector." << endl; 349 } 350 else 351 { 352 *out << Verbose(2) << "Keeping present vector." << endl; 353 } 354 } 355 else 356 { 357 *out << Verbose(2) << "Keeping present vector." << endl; 358 } 359 } 318 Vector SideA, SideB, SideC, SideH; 319 SideA.CopyVector(&left->second.second->x); 320 SideA.ProjectOntoPlane(&AxisVector); 321 // *out << "SideA: "; 322 // SideA.Output(out); 323 // *out << endl; 324 325 SideB.CopyVector(&right->second.second->x); 326 SideB.ProjectOntoPlane(&AxisVector); 327 // *out << "SideB: "; 328 // SideB.Output(out); 329 // *out << endl; 330 331 SideC.CopyVector(&left->second.second->x); 332 SideC.SubtractVector(&right->second.second->x); 333 SideC.ProjectOntoPlane(&AxisVector); 334 // *out << "SideC: "; 335 // SideC.Output(out); 336 // *out << endl; 337 338 SideH.CopyVector(&runner->second.second->x); 339 SideH.ProjectOntoPlane(&AxisVector); 340 // *out << "SideH: "; 341 // SideH.Output(out); 342 // *out << endl; 343 344 // calculate each length 345 double a = SideA.Norm(); 346 //double b = SideB.Norm(); 347 //double c = SideC.Norm(); 348 double h = SideH.Norm(); 349 // calculate the angles 350 double alpha = SideA.Angle(&SideH); 351 double beta = SideA.Angle(&SideC); 352 double gamma = SideB.Angle(&SideH); 353 double delta = SideC.Angle(&SideH); 354 double MinDistance = a * sin(beta)/(sin(delta)) * (((alpha < M_PI/2.) || (gamma < M_PI/2.)) ? 1. : -1.); 355 // *out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl; 356 //*out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl; 357 if ((fabs(h/fabs(h) - MinDistance/fabs(MinDistance)) < MYEPSILON) && (h < MinDistance)) { 358 // throw out point 359 //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl; 360 BoundaryPoints[axis].erase(runner); 361 flag = true; 362 } 360 363 } 361 // printing all inserted for debugging 362 // { 363 // *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl; 364 // int i=0; 365 // for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 366 // if (runner != BoundaryPoints[axis].begin()) 367 // *out << ", " << i << ": " << *runner->second.second; 368 // else 369 // *out << i << ": " << *runner->second.second; 370 // i++; 371 // } 372 // *out << endl; 373 // } 374 // 3c. throw out points whose distance is less than the mean of left and right neighbours 375 bool flag = false; 376 do 377 { // do as long as we still throw one out per round 378 *out << Verbose(1) 379 << "Looking for candidates to kick out by convex condition ... " 380 << endl; 381 flag = false; 382 Boundaries::iterator left = BoundaryPoints[axis].end(); 383 Boundaries::iterator right = BoundaryPoints[axis].end(); 384 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 385 != BoundaryPoints[axis].end(); runner++) 386 { 387 // set neighbours correctly 388 if (runner == BoundaryPoints[axis].begin()) 389 { 390 left = BoundaryPoints[axis].end(); 391 } 392 else 393 { 394 left = runner; 395 } 396 left--; 397 right = runner; 398 right++; 399 if (right == BoundaryPoints[axis].end()) 400 { 401 right = BoundaryPoints[axis].begin(); 402 } 403 // check distance 404 405 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector) 406 { 407 Vector SideA, SideB, SideC, SideH; 408 SideA.CopyVector(&left->second.second->x); 409 SideA.ProjectOntoPlane(&AxisVector); 410 // *out << "SideA: "; 411 // SideA.Output(out); 412 // *out << endl; 413 414 SideB.CopyVector(&right->second.second->x); 415 SideB.ProjectOntoPlane(&AxisVector); 416 // *out << "SideB: "; 417 // SideB.Output(out); 418 // *out << endl; 419 420 SideC.CopyVector(&left->second.second->x); 421 SideC.SubtractVector(&right->second.second->x); 422 SideC.ProjectOntoPlane(&AxisVector); 423 // *out << "SideC: "; 424 // SideC.Output(out); 425 // *out << endl; 426 427 SideH.CopyVector(&runner->second.second->x); 428 SideH.ProjectOntoPlane(&AxisVector); 429 // *out << "SideH: "; 430 // SideH.Output(out); 431 // *out << endl; 432 433 // calculate each length 434 double a = SideA.Norm(); 435 //double b = SideB.Norm(); 436 //double c = SideC.Norm(); 437 double h = SideH.Norm(); 438 // calculate the angles 439 double alpha = SideA.Angle(&SideH); 440 double beta = SideA.Angle(&SideC); 441 double gamma = SideB.Angle(&SideH); 442 double delta = SideC.Angle(&SideH); 443 double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha 444 < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.); 445 // *out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl; 446 //*out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl; 447 if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance)) 448 < MYEPSILON) && (h < MinDistance)) 449 { 450 // throw out point 451 //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl; 452 BoundaryPoints[axis].erase(runner); 453 flag = true; 454 } 455 } 456 } 457 } 458 while (flag); 459 } 364 } 365 } while (flag); 366 } 460 367 return BoundaryPoints; 461 } 462 ; 368 }; 463 369 464 370 /** Determines greatest diameters of a cluster defined by its convex envelope. … … 469 375 * \param IsAngstroem whether we have angstroem or atomic units 470 376 * \return NDIM array of the diameters 471 */ 472 double * 473 GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, 474 bool IsAngstroem) 377 */ 378 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem) 475 379 { 476 380 // get points on boundary of NULL was given as parameter 477 381 bool BoundaryFreeFlag = false; 478 382 Boundaries *BoundaryPoints = BoundaryPtr; 479 if (BoundaryPoints == NULL) 480 { 481 BoundaryFreeFlag = true; 482 BoundaryPoints = GetBoundaryPoints(out, mol); 483 } 484 else 485 { 486 *out << Verbose(1) << "Using given boundary points set." << endl; 487 } 383 if (BoundaryPoints == NULL) { 384 BoundaryFreeFlag = true; 385 BoundaryPoints = GetBoundaryPoints(out, mol); 386 } else { 387 *out << Verbose(1) << "Using given boundary points set." << endl; 388 } 389 488 390 // determine biggest "diameter" of cluster for each axis 489 391 Boundaries::iterator Neighbour, OtherNeighbour; 490 392 double *GreatestDiameter = new double[NDIM]; 491 for (int i = 0; i < NDIM;i++)393 for(int i=0;i<NDIM;i++) 492 394 GreatestDiameter[i] = 0.; 493 395 double OldComponent, tmp, w1, w2; 494 396 Vector DistanceVector, OtherVector; 495 397 int component, Othercomponent; 496 for (int axis = 0; axis < NDIM; axis++) 497 { // regard each projected plane 498 //*out << Verbose(1) << "Current axis is " << axis << "." << endl; 499 for (int j = 0; j < 2; j++) 500 { // and for both axis on the current plane 501 component = (axis + j + 1) % NDIM; 502 Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM; 503 //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl; 504 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 505 != BoundaryPoints[axis].end(); runner++) 506 { 507 //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl; 508 // seek for the neighbours pair where the Othercomponent sign flips 509 Neighbour = runner; 510 Neighbour++; 511 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 512 Neighbour = BoundaryPoints[axis].begin(); 513 DistanceVector.CopyVector(&runner->second.second->x); 514 DistanceVector.SubtractVector(&Neighbour->second.second->x); 515 do 516 { // seek for neighbour pair where it flips 517 OldComponent = DistanceVector.x[Othercomponent]; 518 Neighbour++; 519 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 520 Neighbour = BoundaryPoints[axis].begin(); 521 DistanceVector.CopyVector(&runner->second.second->x); 522 DistanceVector.SubtractVector(&Neighbour->second.second->x); 523 //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl; 524 } 525 while ((runner != Neighbour) && (fabs(OldComponent / fabs( 526 OldComponent) - DistanceVector.x[Othercomponent] / fabs( 527 DistanceVector.x[Othercomponent])) < MYEPSILON)); // as long as sign does not flip 528 if (runner != Neighbour) 529 { 530 OtherNeighbour = Neighbour; 531 if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around 532 OtherNeighbour = BoundaryPoints[axis].end(); 533 OtherNeighbour--; 534 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl; 535 // now we have found the pair: Neighbour and OtherNeighbour 536 OtherVector.CopyVector(&runner->second.second->x); 537 OtherVector.SubtractVector(&OtherNeighbour->second.second->x); 538 //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl; 539 //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl; 540 // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour 541 w1 = fabs(OtherVector.x[Othercomponent]); 542 w2 = fabs(DistanceVector.x[Othercomponent]); 543 tmp = fabs((w1 * DistanceVector.x[component] + w2 544 * OtherVector.x[component]) / (w1 + w2)); 545 // mark if it has greater diameter 546 //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl; 547 GreatestDiameter[component] = (GreatestDiameter[component] 548 > tmp) ? GreatestDiameter[component] : tmp; 549 } //else 550 //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl; 551 } 552 } 398 for(int axis=0;axis<NDIM;axis++) { // regard each projected plane 399 //*out << Verbose(1) << "Current axis is " << axis << "." << endl; 400 for (int j=0;j<2;j++) { // and for both axis on the current plane 401 component = (axis+j+1)%NDIM; 402 Othercomponent = (axis+1+((j+1) & 1))%NDIM; 403 //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl; 404 for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 405 //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl; 406 // seek for the neighbours pair where the Othercomponent sign flips 407 Neighbour = runner; 408 Neighbour++; 409 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 410 Neighbour = BoundaryPoints[axis].begin(); 411 DistanceVector.CopyVector(&runner->second.second->x); 412 DistanceVector.SubtractVector(&Neighbour->second.second->x); 413 do { // seek for neighbour pair where it flips 414 OldComponent = DistanceVector.x[Othercomponent]; 415 Neighbour++; 416 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 417 Neighbour = BoundaryPoints[axis].begin(); 418 DistanceVector.CopyVector(&runner->second.second->x); 419 DistanceVector.SubtractVector(&Neighbour->second.second->x); 420 //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl; 421 } while ((runner != Neighbour) && ( fabs( OldComponent/fabs(OldComponent) - DistanceVector.x[Othercomponent]/fabs(DistanceVector.x[Othercomponent]) ) < MYEPSILON)); // as long as sign does not flip 422 if (runner != Neighbour) { 423 OtherNeighbour = Neighbour; 424 if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around 425 OtherNeighbour = BoundaryPoints[axis].end(); 426 OtherNeighbour--; 427 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl; 428 // now we have found the pair: Neighbour and OtherNeighbour 429 OtherVector.CopyVector(&runner->second.second->x); 430 OtherVector.SubtractVector(&OtherNeighbour->second.second->x); 431 //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl; 432 //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl; 433 // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour 434 w1 = fabs(OtherVector.x[Othercomponent]); 435 w2 = fabs(DistanceVector.x[Othercomponent]); 436 tmp = fabs((w1*DistanceVector.x[component] + w2*OtherVector.x[component])/(w1+w2)); 437 // mark if it has greater diameter 438 //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl; 439 GreatestDiameter[component] = (GreatestDiameter[component] > tmp) ? GreatestDiameter[component] : tmp; 440 } //else 441 //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl; 442 } 553 443 } 554 *out << Verbose(0) << "RESULT: The biggest diameters are " 555 << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and " 556 << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom" 557 : "atomiclength") << "." << endl; 444 } 445 *out << Verbose(0) << "RESULT: The biggest diameters are " << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and " << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "." << endl; 558 446 559 447 // free reference lists 560 448 if (BoundaryFreeFlag) 561 delete[] 449 delete[](BoundaryPoints); 562 450 563 451 return GreatestDiameter; 564 } 565 ; 566 567 /** Creates the objects in a raster3d file (renderable with a header.r3d) 568 * \param *out output stream for debugging 569 * \param *tecplot output stream for tecplot data 570 * \param *Tess Tesselation structure with constructed triangles 571 * \param *mol molecule structure with atom positions 572 */ 573 void write_raster3d_file(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, class molecule *mol) 574 { 575 atom *Walker = mol->start; 576 bond *Binder = mol->first; 577 int i; 578 Vector *center = mol->DetermineCenterOfAll(out); 579 if (rasterfile != NULL) { 580 //cout << Verbose(1) << "Writing Raster3D file ... "; 581 *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl; 582 *rasterfile << "@header.r3d" << endl; 583 *rasterfile << "# All atoms as spheres" << endl; 584 while (Walker->next != mol->end) { 585 Walker = Walker->next; 586 *rasterfile << "2" << endl << " "; // 2 is sphere type 587 for (i=0;i<NDIM;i++) 588 *rasterfile << Walker->x.x[i]+center->x[i] << " "; 589 *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour 590 } 591 592 *rasterfile << "# All bonds as vertices" << endl; 593 while (Binder->next != mol->last) { 594 Binder = Binder->next; 595 *rasterfile << "3" << endl << " "; // 2 is round-ended cylinder type 596 for (i=0;i<NDIM;i++) 597 *rasterfile << Binder->leftatom->x.x[i]+center->x[i] << " "; 598 *rasterfile << "\t0.03\t"; 599 for (i=0;i<NDIM;i++) 600 *rasterfile << Binder->rightatom->x.x[i]+center->x[i] << " "; 601 *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour 602 } 603 604 *rasterfile << "# All tesselation triangles" << endl; 605 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) { 606 *rasterfile << "1" << endl << " "; // 1 is triangle type 607 for (i=0;i<3;i++) { // print each node 608 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates 609 *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " "; 610 *rasterfile << "\t"; 611 } 612 *rasterfile << "1. 0. 0." << endl; // red as colour 613 *rasterfile << "18" << endl << " 0.5 0.5 0.5" << endl; // 18 is transparency type for previous object 614 } 615 } else { 616 cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl; 617 } 618 delete(center); 619 }; 620 621 /** This function creates the tecplot file, displaying the tesselation of the hull. 622 * \param *out output stream for debugging 623 * \param *tecplot output stream for tecplot data 624 * \param N arbitrary number to differentiate various zones in the tecplot format 625 */ 626 void 627 write_tecplot_file(ofstream *out, ofstream *tecplot, 628 class Tesselation *TesselStruct, class molecule *mol, int N) 629 { 630 if (tecplot != NULL) 631 { 632 *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl; 633 *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl; 634 *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N=" 635 << TesselStruct->PointsOnBoundaryCount << ", E=" 636 << TesselStruct->TrianglesOnBoundaryCount 637 << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl; 638 int *LookupList = new int[mol->AtomCount]; 639 for (int i = 0; i < mol->AtomCount; i++) 640 LookupList[i] = -1; 641 642 // print atom coordinates 643 *out << Verbose(2) << "The following triangles were created:"; 644 int Counter = 1; 645 atom *Walker = NULL; 646 for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target 647 != TesselStruct->PointsOnBoundary.end(); target++) 648 { 649 Walker = target->second->node; 650 LookupList[Walker->nr] = Counter++; 651 *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " " 652 << Walker->x.x[2] << " " << endl; 653 } 654 *tecplot << endl; 655 // print connectivity 656 for (TriangleMap::iterator runner = 657 TesselStruct->TrianglesOnBoundary.begin(); runner 658 != TesselStruct->TrianglesOnBoundary.end(); runner++) 659 { 660 *out << " " << runner->second->endpoints[0]->node->Name << "<->" 661 << runner->second->endpoints[1]->node->Name << "<->" 662 << runner->second->endpoints[2]->node->Name; 663 *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " 664 << LookupList[runner->second->endpoints[1]->node->nr] << " " 665 << LookupList[runner->second->endpoints[2]->node->nr] << endl; 666 } 667 delete[] (LookupList); 668 *out << endl; 669 } 670 } 452 }; 453 671 454 672 455 /** Determines the volume of a cluster. 673 456 * Determines first the convex envelope, then tesselates it and calculates its volume. 674 457 * \param *out output stream for debugging 675 * \param *tecplot output stream for tecplot data676 458 * \param *configuration needed for path to store convex envelope file 677 459 * \param *BoundaryPoints NDIM set of boundary points on the projected plane per axis, on return if desired 678 460 * \param *mol molecule structure representing the cluster 679 * \return determined volume of the cluster in cubed config:GetIsAngstroem()680 461 */ 681 double 682 VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, 683 Boundaries *BoundaryPtr, molecule *mol) 462 double VolumeOfConvexEnvelope(ofstream *out, config *configuration, Boundaries *BoundaryPtr, molecule *mol) 684 463 { 685 464 bool IsAngstroem = configuration->GetIsAngstroem(); … … 690 469 double volume = 0.; 691 470 double PyramidVolume = 0.; 692 double G, h; 693 Vector x, y; 694 double a, b, c; 695 696 //Find_non_convex_border(out, tecplot, *TesselStruct, mol); // Is now called from command line. 471 double G,h; 472 Vector x,y; 473 double a,b,c; 697 474 698 475 // 1. calculate center of gravity 699 476 *out << endl; 700 477 Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out); 701 478 702 479 // 2. translate all points into CoG 703 480 *out << Verbose(1) << "Translating system to Center of Gravity." << endl; 704 481 Walker = mol->start; 705 while (Walker->next != mol->end) 706 { 707 Walker = Walker->next; 708 Walker->x.Translate(CenterOfGravity); 482 while (Walker->next != mol->end) { 483 Walker = Walker->next; 484 Walker->x.Translate(CenterOfGravity); 485 } 486 487 // 3. Find all points on the boundary 488 if (BoundaryPoints == NULL) { 489 BoundaryFreeFlag = true; 490 BoundaryPoints = GetBoundaryPoints(out, mol); 491 } else { 492 *out << Verbose(1) << "Using given boundary points set." << endl; 493 } 494 495 // 4. fill the boundary point list 496 for (int axis=0;axis<NDIM;axis++) 497 for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 498 TesselStruct->AddPoint(runner->second.second); 709 499 } 710 500 711 // 3. Find all points on the boundary 712 if (BoundaryPoints == NULL) 713 { 714 BoundaryFreeFlag = true; 715 BoundaryPoints = GetBoundaryPoints(out, mol); 716 } 717 else 718 { 719 *out << Verbose(1) << "Using given boundary points set." << endl; 720 } 721 722 // 4. fill the boundary point list 723 for (int axis = 0; axis < NDIM; axis++) 724 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 725 != BoundaryPoints[axis].end(); runner++) 726 { 727 TesselStruct->AddPoint(runner->second.second); 728 } 729 730 *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount 731 << " points on the convex boundary." << endl; 501 *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount << " points on the convex boundary." << endl; 732 502 // now we have the whole set of edge points in the BoundaryList 733 503 504 734 505 // listing for debugging 735 736 737 738 739 740 506 // *out << Verbose(1) << "Listing PointsOnBoundary:"; 507 // for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) { 508 // *out << " " << *runner->second; 509 // } 510 // *out << endl; 511 741 512 // 5a. guess starting triangle 742 513 TesselStruct->GuessStartingTriangle(out); 743 514 744 515 // 5b. go through all lines, that are not yet part of two triangles (only of one so far) 745 516 TesselStruct->TesselateOnBoundary(out, configuration, mol); 746 517 747 *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount 748 << " triangles with " << TesselStruct->LinesOnBoundaryCount 749 << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." 750 << endl; 518 *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount << " triangles with " << TesselStruct->LinesOnBoundaryCount << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." << endl; 751 519 752 520 // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes 753 *out << Verbose(1) 754 << "Calculating the volume of the pyramids formed out of triangles and center of gravity." 755 << endl; 756 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner 757 != TesselStruct->TrianglesOnBoundary.end(); runner++) 758 { // go through every triangle, calculate volume of its pyramid with CoG as peak 759 x.CopyVector(&runner->second->endpoints[0]->node->x); 760 x.SubtractVector(&runner->second->endpoints[1]->node->x); 761 y.CopyVector(&runner->second->endpoints[0]->node->x); 762 y.SubtractVector(&runner->second->endpoints[2]->node->x); 763 a = sqrt(runner->second->endpoints[0]->node->x.Distance( 764 &runner->second->endpoints[1]->node->x)); 765 b = sqrt(runner->second->endpoints[0]->node->x.Distance( 766 &runner->second->endpoints[2]->node->x)); 767 c = sqrt(runner->second->endpoints[2]->node->x.Distance( 768 &runner->second->endpoints[1]->node->x)); 769 G = sqrt(((a * a + b * b + c * c) * (a * a + b * b + c * c) - 2 * (a * a 770 * a * a + b * b * b * b + c * c * c * c)) / 16.); // area of tesselated triangle 771 x.MakeNormalVector(&runner->second->endpoints[0]->node->x, 772 &runner->second->endpoints[1]->node->x, 773 &runner->second->endpoints[2]->node->x); 774 x.Scale(runner->second->endpoints[1]->node->x.Projection(&x)); 775 h = x.Norm(); // distance of CoG to triangle 776 PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak) 777 *out << Verbose(2) << "Area of triangle is " << G << " " 778 << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is " 779 << h << " and the volume is " << PyramidVolume << " " 780 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 781 volume += PyramidVolume; 782 } 783 *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10) 784 << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." 785 << endl; 521 *out << Verbose(1) << "Calculating the volume of the pyramids formed out of triangles and center of gravity." << endl; 522 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) { // go through every triangle, calculate volume of its pyramid with CoG as peak 523 x.CopyVector(&runner->second->endpoints[0]->node->x); 524 x.SubtractVector(&runner->second->endpoints[1]->node->x); 525 y.CopyVector(&runner->second->endpoints[0]->node->x); 526 y.SubtractVector(&runner->second->endpoints[2]->node->x); 527 a = sqrt(runner->second->endpoints[0]->node->x.Distance(&runner->second->endpoints[1]->node->x)); 528 b = sqrt(runner->second->endpoints[0]->node->x.Distance(&runner->second->endpoints[2]->node->x)); 529 c = sqrt(runner->second->endpoints[2]->node->x.Distance(&runner->second->endpoints[1]->node->x)); 530 G = sqrt( ( (a*a+b*b+c*c)*(a*a+b*b+c*c) - 2*(a*a*a*a + b*b*b*b + c*c*c*c) )/16.); // area of tesselated triangle 531 x.MakeNormalVector(&runner->second->endpoints[0]->node->x, &runner->second->endpoints[1]->node->x, &runner->second->endpoints[2]->node->x); 532 x.Scale(runner->second->endpoints[1]->node->x.Projection(&x)); 533 h = x.Norm(); // distance of CoG to triangle 534 PyramidVolume = (1./3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak) 535 *out << Verbose(2) << "Area of triangle is " << G << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is " << h << " and the volume is " << PyramidVolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 536 volume += PyramidVolume; 537 } 538 *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10) << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 539 786 540 787 541 // 7. translate all points back from CoG 788 *out << Verbose(1) << "Translating system back from Center of Gravity." 789 << endl; 542 *out << Verbose(1) << "Translating system back from Center of Gravity." << endl; 790 543 CenterOfGravity->Scale(-1); 791 544 Walker = mol->start; 792 while (Walker->next != mol->end) 793 { 794 Walker = Walker->next; 795 Walker->x.Translate(CenterOfGravity); 796 } 797 798 // 8. Store triangles in tecplot file 799 write_tecplot_file(out, tecplot, TesselStruct, mol, 0); 545 while (Walker->next != mol->end) { 546 Walker = Walker->next; 547 Walker->x.Translate(CenterOfGravity); 548 } 800 549 801 550 // free reference lists 802 551 if (BoundaryFreeFlag) 803 delete[] 804 552 delete[](BoundaryPoints); 553 805 554 return volume; 806 } 807 ; 555 }; 556 808 557 809 558 /** Creates multiples of the by \a *mol given cluster and suspends them in water with a given final density. … … 815 564 * \param celldensity desired average density in final cell 816 565 */ 817 void 818 PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, 819 double ClusterVolume, double celldensity) 566 void PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, double ClusterVolume, double celldensity) 820 567 { 821 568 // transform to PAS 822 569 mol->PrincipalAxisSystem(out, true); 823 570 824 571 // some preparations beforehand 825 572 bool IsAngstroem = configuration->GetIsAngstroem(); … … 827 574 double clustervolume; 828 575 if (ClusterVolume == 0) 829 clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration, 830 BoundaryPoints, mol); 831 else 576 clustervolume = VolumeOfConvexEnvelope(out, configuration, BoundaryPoints, mol); 577 else 832 578 clustervolume = ClusterVolume; 833 double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, 834 IsAngstroem); 579 double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, IsAngstroem); 835 580 Vector BoxLengths; 836 int repetition[NDIM] = 837 { 1, 1, 1 }; 581 int repetition[NDIM] = {1, 1, 1}; 838 582 int TotalNoClusters = 1; 839 for (int i = 0; i < NDIM;i++)583 for (int i=0;i<NDIM;i++) 840 584 TotalNoClusters *= repetition[i]; 841 585 … … 843 587 double totalmass = 0.; 844 588 atom *Walker = mol->start; 845 while (Walker->next != mol->end) 846 { 847 Walker = Walker->next; 848 totalmass += Walker->type->mass; 849 } 850 *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10) 851 << totalmass << " atomicmassunit." << endl; 852 853 *out << Verbose(0) << "RESULT: The average density is " << setprecision(10) 854 << totalmass / clustervolume << " atomicmassunit/" 855 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 856 589 while (Walker->next != mol->end) { 590 Walker = Walker->next; 591 totalmass += Walker->type->mass; 592 } 593 *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10) << totalmass << " atomicmassunit." << endl; 594 595 *out << Verbose(0) << "RESULT: The average density is " << setprecision(10) << totalmass/clustervolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 596 857 597 // solve cubic polynomial 858 *out << Verbose(1) << "Solving equidistant suspension in water problem ..." 859 << endl; 598 *out << Verbose(1) << "Solving equidistant suspension in water problem ..." << endl; 860 599 double cellvolume; 861 600 if (IsAngstroem) 862 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass 863 / clustervolume)) / (celldensity - 1); 601 cellvolume = (TotalNoClusters*totalmass/SOLVENTDENSITY_A - (totalmass/clustervolume))/(celldensity-1); 864 602 else 865 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass866 / clustervolume)) / (celldensity - 1);867 *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity868 << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom"869 870 871 double minimumvolume = TotalNoClusters * (GreatestDiameter[0]872 * GreatestDiameter[1] * GreatestDiameter[2]);873 *out << Verbose(1)874 << "Minimum volume of the convex envelope contained in a rectangular box is "875 << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom"876 : "atomiclength") << "^3." << endl;877 if (minimumvolume > cellvolume)878 {879 cerr << Verbose(0)880 << "ERROR: the containing box already has a greater volume than the envisaged cell volume!"881 << endl;882 cout << Verbose(0)883 << "Setting Box dimensions to minimum possible, the greatest diameters."884 885 for (int i = 0; i < NDIM; i++)886 BoxLengths.x[i] = GreatestDiameter[i];887 mol->CenterEdge(out, &BoxLengths);603 cellvolume = (TotalNoClusters*totalmass/SOLVENTDENSITY_a0 - (totalmass/clustervolume))/(celldensity-1); 604 *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 605 606 double minimumvolume = TotalNoClusters*(GreatestDiameter[0]*GreatestDiameter[1]*GreatestDiameter[2]); 607 *out << Verbose(1) << "Minimum volume of the convex envelope contained in a rectangular box is " << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 608 if (minimumvolume > cellvolume) { 609 cerr << Verbose(0) << "ERROR: the containing box already has a greater volume than the envisaged cell volume!" << endl; 610 cout << Verbose(0) << "Setting Box dimensions to minimum possible, the greatest diameters." << endl; 611 for(int i=0;i<NDIM;i++) 612 BoxLengths.x[i] = GreatestDiameter[i]; 613 mol->CenterEdge(out, &BoxLengths); 614 } else { 615 BoxLengths.x[0] = (repetition[0]*GreatestDiameter[0] + repetition[1]*GreatestDiameter[1] + repetition[2]*GreatestDiameter[2]); 616 BoxLengths.x[1] = (repetition[0]*repetition[1]*GreatestDiameter[0]*GreatestDiameter[1] 617 + repetition[0]*repetition[2]*GreatestDiameter[0]*GreatestDiameter[2] 618 + repetition[1]*repetition[2]*GreatestDiameter[1]*GreatestDiameter[2]); 619 BoxLengths.x[2] = minimumvolume - cellvolume; 620 double x0 = 0.,x1 = 0.,x2 = 0.; 621 if (gsl_poly_solve_cubic(BoxLengths.x[0],BoxLengths.x[1],BoxLengths.x[2],&x0,&x1,&x2) == 1) // either 1 or 3 on return 622 *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0 << " ." << endl; 623 else { 624 *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0 << " and " << x1 << " and " << x2 << " ." << endl; 625 x0 = x2; // sorted in ascending order 888 626 } 889 else 890 { 891 BoxLengths.x[0] = (repetition[0] * GreatestDiameter[0] + repetition[1] 892 * GreatestDiameter[1] + repetition[2] * GreatestDiameter[2]); 893 BoxLengths.x[1] = (repetition[0] * repetition[1] * GreatestDiameter[0] 894 * GreatestDiameter[1] + repetition[0] * repetition[2] 895 * GreatestDiameter[0] * GreatestDiameter[2] + repetition[1] 896 * repetition[2] * GreatestDiameter[1] * GreatestDiameter[2]); 897 BoxLengths.x[2] = minimumvolume - cellvolume; 898 double x0 = 0., x1 = 0., x2 = 0.; 899 if (gsl_poly_solve_cubic(BoxLengths.x[0], BoxLengths.x[1], 900 BoxLengths.x[2], &x0, &x1, &x2) == 1) // either 1 or 3 on return 901 *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0 902 << " ." << endl; 903 else 904 { 905 *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0 906 << " and " << x1 << " and " << x2 << " ." << endl; 907 x0 = x2; // sorted in ascending order 908 } 909 910 cellvolume = 1; 911 for (int i = 0; i < NDIM; i++) 912 { 913 BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]); 914 cellvolume *= BoxLengths.x[i]; 915 } 916 917 // set new box dimensions 918 *out << Verbose(0) << "Translating to box with these boundaries." << endl; 919 mol->CenterInBox((ofstream *) &cout, &BoxLengths); 627 628 cellvolume = 1; 629 for(int i=0;i<NDIM;i++) { 630 BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]); 631 cellvolume *= BoxLengths.x[i]; 920 632 } 633 634 // set new box dimensions 635 *out << Verbose(0) << "Translating to box with these boundaries." << endl; 636 mol->CenterInBox((ofstream *)&cout, &BoxLengths); 637 } 921 638 // update Box of atoms by boundary 922 639 mol->SetBoxDimension(&BoxLengths); 923 *out << Verbose(0) << "RESULT: The resulting cell dimensions are: " 924 << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and " 925 << BoxLengths.x[2] << " with total volume of " << cellvolume << " " 926 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 927 } 928 ; 640 *out << Verbose(0) << "RESULT: The resulting cell dimensions are: " << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and " << BoxLengths.x[2] << " with total volume of " << cellvolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 641 }; 642 929 643 930 644 // =========================================================== class TESSELATION =========================================== … … 934 648 Tesselation::Tesselation() 935 649 { 936 PointsOnBoundaryCount = 0; 937 LinesOnBoundaryCount = 0; 650 PointsOnBoundaryCount = 0; 651 LinesOnBoundaryCount = 0; 938 652 TrianglesOnBoundaryCount = 0; 939 TriangleFilesWritten = 0; 940 } 941 ; 653 }; 942 654 943 655 /** Constructor of class Tesselation. … … 946 658 Tesselation::~Tesselation() 947 659 { 948 cout << Verbose(1) << "Free'ing TesselStruct ... " << endl; 949 for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) { 950 if (runner->second != NULL) { 951 delete (runner->second); 952 runner->second = NULL; 953 } else 954 cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl; 955 } 956 for (LineMap::iterator runner = LinesOnBoundary.begin(); runner != LinesOnBoundary.end(); runner++) { 957 if (runner->second != NULL) { 958 delete (runner->second); 959 runner->second = NULL; 960 } else 961 cerr << "ERROR: The line " << runner->first << " has already been free'd." << endl; 962 } 963 for (PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) { 964 if (runner->second != NULL) { 965 delete (runner->second); 966 runner->second = NULL; 967 } else 968 cerr << "ERROR: The point " << runner->first << " has already been free'd." << endl; 969 } 970 } 971 ; 660 for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) { 661 delete(runner->second); 662 } 663 }; 972 664 973 665 /** Gueses first starting triangle of the convex envelope. … … 975 667 * \param *out output stream for debugging 976 668 * \param PointsOnBoundary set of boundary points defining the convex envelope of the cluster 977 */ 978 void 979 Tesselation::GuessStartingTriangle(ofstream *out) 669 */ 670 void Tesselation::GuessStartingTriangle(ofstream *out) 980 671 { 981 672 // 4b. create a starting triangle 982 673 // 4b1. create all distances 983 674 DistanceMultiMap DistanceMMap; 984 double distance, tmp; 985 Vector PlaneVector, TrialVector; 986 PointMap::iterator A, B, C; // three nodes of the first triangle 987 A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily 988 989 // with A chosen, take each pair B,C and sort 990 if (A != PointsOnBoundary.end()) 991 { 992 B = A; 993 B++; 994 for (; B != PointsOnBoundary.end(); B++) 995 { 996 C = B; 997 C++; 998 for (; C != PointsOnBoundary.end(); C++) 999 { 1000 tmp = A->second->node->x.Distance(&B->second->node->x); 1001 distance = tmp * tmp; 1002 tmp = A->second->node->x.Distance(&C->second->node->x); 1003 distance += tmp * tmp; 1004 tmp = B->second->node->x.Distance(&C->second->node->x); 1005 distance += tmp * tmp; 1006 DistanceMMap.insert(DistanceMultiMapPair(distance, pair< 1007 PointMap::iterator, PointMap::iterator> (B, C))); 1008 } 1009 } 675 double distance; 676 for (PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) { 677 for(PointMap::iterator sprinter = PointsOnBoundary.begin(); sprinter != PointsOnBoundary.end(); sprinter++) { 678 if (runner->first < sprinter->first) { 679 distance = runner->second->node->x.Distance(&sprinter->second->node->x); 680 DistanceMMap.insert( DistanceMultiMapPair(distance, pair<PointMap::iterator, PointMap::iterator>(runner,sprinter) ) ); 681 } 1010 682 } 1011 // // listing distances 1012 // *out << Verbose(1) << "Listing DistanceMMap:"; 1013 // for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) { 1014 // *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")"; 1015 // } 1016 // *out << endl; 1017 // 4b2. pick three baselines forming a triangle 1018 // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate 683 } 684 685 // // listing distances 686 // *out << Verbose(1) << "Listing DistanceMMap:"; 687 // for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) { 688 // *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")"; 689 // } 690 // *out << endl; 691 692 // 4b2. take three smallest distance that form a triangle 693 // we take the smallest distance as the base line 1019 694 DistanceMultiMap::iterator baseline = DistanceMMap.begin(); 1020 for (; baseline != DistanceMMap.end(); baseline++) 1021 { 1022 // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate 1023 // 2. next, we have to check whether all points reside on only one side of the triangle 1024 // 3. construct plane vector 1025 PlaneVector.MakeNormalVector(&A->second->node->x, 1026 &baseline->second.first->second->node->x, 1027 &baseline->second.second->second->node->x); 1028 *out << Verbose(2) << "Plane vector of candidate triangle is "; 1029 PlaneVector.Output(out); 1030 *out << endl; 1031 // 4. loop over all points 1032 double sign = 0.; 1033 PointMap::iterator checker = PointsOnBoundary.begin(); 1034 for (; checker != PointsOnBoundary.end(); checker++) 1035 { 1036 // (neglecting A,B,C) 1037 if ((checker == A) || (checker == baseline->second.first) || (checker 1038 == baseline->second.second)) 1039 continue; 1040 // 4a. project onto plane vector 1041 TrialVector.CopyVector(&checker->second->node->x); 1042 TrialVector.SubtractVector(&A->second->node->x); 1043 distance = TrialVector.Projection(&PlaneVector); 1044 if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok 1045 continue; 1046 *out << Verbose(3) << "Projection of " << checker->second->node->Name 1047 << " yields distance of " << distance << "." << endl; 1048 tmp = distance / fabs(distance); 1049 // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle) 1050 if ((sign != 0) && (tmp != sign)) 1051 { 1052 // 4c. If so, break 4. loop and continue with next candidate in 1. loop 1053 *out << Verbose(2) << "Current candidates: " 1054 << A->second->node->Name << "," 1055 << baseline->second.first->second->node->Name << "," 1056 << baseline->second.second->second->node->Name << " leave " 1057 << checker->second->node->Name << " outside the convex hull." 1058 << endl; 1059 break; 1060 } 1061 else 1062 { // note the sign for later 1063 *out << Verbose(2) << "Current candidates: " 1064 << A->second->node->Name << "," 1065 << baseline->second.first->second->node->Name << "," 1066 << baseline->second.second->second->node->Name << " leave " 1067 << checker->second->node->Name << " inside the convex hull." 1068 << endl; 1069 sign = tmp; 1070 } 1071 // 4d. Check whether the point is inside the triangle (check distance to each node 1072 tmp = checker->second->node->x.Distance(&A->second->node->x); 1073 int innerpoint = 0; 1074 if ((tmp < A->second->node->x.Distance( 1075 &baseline->second.first->second->node->x)) && (tmp 1076 < A->second->node->x.Distance( 1077 &baseline->second.second->second->node->x))) 1078 innerpoint++; 1079 tmp = checker->second->node->x.Distance( 1080 &baseline->second.first->second->node->x); 1081 if ((tmp < baseline->second.first->second->node->x.Distance( 1082 &A->second->node->x)) && (tmp 1083 < baseline->second.first->second->node->x.Distance( 1084 &baseline->second.second->second->node->x))) 1085 innerpoint++; 1086 tmp = checker->second->node->x.Distance( 1087 &baseline->second.second->second->node->x); 1088 if ((tmp < baseline->second.second->second->node->x.Distance( 1089 &baseline->second.first->second->node->x)) && (tmp 1090 < baseline->second.second->second->node->x.Distance( 1091 &A->second->node->x))) 1092 innerpoint++; 1093 // 4e. If so, break 4. loop and continue with next candidate in 1. loop 1094 if (innerpoint == 3) 1095 break; 1096 } 1097 // 5. come this far, all on same side? Then break 1. loop and construct triangle 1098 if (checker == PointsOnBoundary.end()) 1099 { 1100 *out << "Looks like we have a candidate!" << endl; 1101 break; 1102 } 1103 } 1104 if (baseline != DistanceMMap.end()) 1105 { 1106 BPS[0] = baseline->second.first->second; 1107 BPS[1] = baseline->second.second->second; 1108 BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1109 BPS[0] = A->second; 1110 BPS[1] = baseline->second.second->second; 1111 BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1112 BPS[0] = baseline->second.first->second; 1113 BPS[1] = A->second; 1114 BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1115 1116 // 4b3. insert created triangle 1117 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 1118 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1119 TrianglesOnBoundaryCount++; 1120 for (int i = 0; i < NDIM; i++) 1121 { 1122 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i])); 1123 LinesOnBoundaryCount++; 1124 } 1125 1126 *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl; 1127 } 1128 else 1129 { 1130 *out << Verbose(1) << "No starting triangle found." << endl; 1131 exit(255); 1132 } 1133 } 1134 ; 695 BPS[0] = baseline->second.first->second; 696 BPS[1] = baseline->second.second->second; 697 BLS[0] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 698 699 // take the second smallest as the second base line 700 DistanceMultiMap::iterator secondline = DistanceMMap.begin(); 701 do { 702 secondline++; 703 } while (!( 704 ((BPS[0] == secondline->second.first->second) && (BPS[1] != secondline->second.second->second)) || 705 ((BPS[0] == secondline->second.second->second) && (BPS[1] != secondline->second.first->second)) || 706 ((BPS[1] == secondline->second.first->second) && (BPS[0] != secondline->second.second->second)) || 707 ((BPS[1] == secondline->second.second->second) && (BPS[0] != secondline->second.first->second)) 708 )); 709 BPS[0] = secondline->second.first->second; 710 BPS[1] = secondline->second.second->second; 711 BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 712 713 // connection yields the third line (note: first and second endpoint are sorted!) 714 if (baseline->second.first->second == secondline->second.first->second) { 715 SetEndpointsOrdered(BPS, baseline->second.second->second, secondline->second.second->second); 716 } else if (baseline->second.first->second == secondline->second.second->second) { 717 SetEndpointsOrdered(BPS, baseline->second.second->second, secondline->second.first->second); 718 } else if (baseline->second.second->second == secondline->second.first->second) { 719 SetEndpointsOrdered(BPS, baseline->second.first->second, baseline->second.second->second); 720 } else if (baseline->second.second->second == secondline->second.second->second) { 721 SetEndpointsOrdered(BPS, baseline->second.first->second, baseline->second.first->second); 722 } 723 BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 724 725 // 4b3. insert created triangle 726 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 727 TrianglesOnBoundary.insert( TrianglePair(TrianglesOnBoundaryCount, BTS) ); 728 TrianglesOnBoundaryCount++; 729 for(int i=0;i<NDIM;i++) { 730 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]) ); 731 LinesOnBoundaryCount++; 732 } 733 734 *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl; 735 }; 736 1135 737 1136 738 /** Tesselates the convex envelope of a cluster from a single starting triangle. … … 1147 749 * \param *mol the cluster as a molecule structure 1148 750 */ 1149 void 1150 Tesselation::TesselateOnBoundary(ofstream *out, config *configuration, 1151 molecule *mol) 751 void Tesselation::TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol) 1152 752 { 1153 753 bool flag; … … 1155 755 class BoundaryPointSet *peak = NULL; 1156 756 double SmallestAngle, TempAngle; 1157 Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, 1158 PropagationVector; 757 Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, PropagationVector; 1159 758 LineMap::iterator LineChecker[2]; 1160 do 1161 { 1162 flag = false; 1163 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline 1164 != LinesOnBoundary.end(); baseline++) 1165 if (baseline->second->TrianglesCount == 1) 1166 { 1167 *out << Verbose(2) << "Current baseline is between " 1168 << *(baseline->second) << "." << endl; 1169 // 5a. go through each boundary point if not _both_ edges between either endpoint of the current line and this point exist (and belong to 2 triangles) 1170 SmallestAngle = M_PI; 1171 BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far 1172 // get peak point with respect to this base line's only triangle 1173 for (int i = 0; i < 3; i++) 1174 if ((BTS->endpoints[i] != baseline->second->endpoints[0]) 1175 && (BTS->endpoints[i] != baseline->second->endpoints[1])) 1176 peak = BTS->endpoints[i]; 1177 *out << Verbose(3) << " and has peak " << *peak << "." << endl; 1178 // normal vector of triangle 1179 BTS->GetNormalVector(NormalVector); 1180 *out << Verbose(4) << "NormalVector of base triangle is "; 1181 NormalVector.Output(out); 1182 *out << endl; 1183 // offset to center of triangle 1184 CenterVector.Zero(); 1185 for (int i = 0; i < 3; i++) 1186 CenterVector.AddVector(&BTS->endpoints[i]->node->x); 1187 CenterVector.Scale(1. / 3.); 1188 *out << Verbose(4) << "CenterVector of base triangle is "; 1189 CenterVector.Output(out); 1190 *out << endl; 1191 // vector in propagation direction (out of triangle) 1192 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection) 1193 TempVector.CopyVector(&baseline->second->endpoints[0]->node->x); 1194 TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x); 1195 PropagationVector.MakeNormalVector(&TempVector, &NormalVector); 1196 TempVector.CopyVector(&CenterVector); 1197 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center! 1198 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl; 1199 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline 1200 PropagationVector.Scale(-1.); 1201 *out << Verbose(4) << "PropagationVector of base triangle is "; 1202 PropagationVector.Output(out); 1203 *out << endl; 1204 winner = PointsOnBoundary.end(); 1205 for (PointMap::iterator target = PointsOnBoundary.begin(); target 1206 != PointsOnBoundary.end(); target++) 1207 if ((target->second != baseline->second->endpoints[0]) 1208 && (target->second != baseline->second->endpoints[1])) 1209 { // don't take the same endpoints 1210 *out << Verbose(3) << "Target point is " << *(target->second) 1211 << ":"; 1212 bool continueflag = true; 1213 1214 VirtualNormalVector.CopyVector( 1215 &baseline->second->endpoints[0]->node->x); 1216 VirtualNormalVector.AddVector( 1217 &baseline->second->endpoints[0]->node->x); 1218 VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line 1219 VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target 1220 TempAngle = VirtualNormalVector.Angle(&PropagationVector); 1221 continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees) 1222 if (!continueflag) 1223 { 1224 *out << Verbose(4) 1225 << "Angle between propagation direction and base line to " 1226 << *(target->second) << " is " << TempAngle 1227 << ", bad direction!" << endl; 1228 continue; 1229 } 1230 else 1231 *out << Verbose(4) 1232 << "Angle between propagation direction and base line to " 1233 << *(target->second) << " is " << TempAngle 1234 << ", good direction!" << endl; 1235 LineChecker[0] = baseline->second->endpoints[0]->lines.find( 1236 target->first); 1237 LineChecker[1] = baseline->second->endpoints[1]->lines.find( 1238 target->first); 1239 // if (LineChecker[0] != baseline->second->endpoints[0]->lines.end()) 1240 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl; 1241 // else 1242 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl; 1243 // if (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 1244 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl; 1245 // else 1246 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl; 1247 // check first endpoint (if any connecting line goes to target or at least not more than 1) 1248 continueflag = continueflag && (((LineChecker[0] 1249 == baseline->second->endpoints[0]->lines.end()) 1250 || (LineChecker[0]->second->TrianglesCount == 1))); 1251 if (!continueflag) 1252 { 1253 *out << Verbose(4) << *(baseline->second->endpoints[0]) 1254 << " has line " << *(LineChecker[0]->second) 1255 << " to " << *(target->second) 1256 << " as endpoint with " 1257 << LineChecker[0]->second->TrianglesCount 1258 << " triangles." << endl; 1259 continue; 1260 } 1261 // check second endpoint (if any connecting line goes to target or at least not more than 1) 1262 continueflag = continueflag && (((LineChecker[1] 1263 == baseline->second->endpoints[1]->lines.end()) 1264 || (LineChecker[1]->second->TrianglesCount == 1))); 1265 if (!continueflag) 1266 { 1267 *out << Verbose(4) << *(baseline->second->endpoints[1]) 1268 << " has line " << *(LineChecker[1]->second) 1269 << " to " << *(target->second) 1270 << " as endpoint with " 1271 << LineChecker[1]->second->TrianglesCount 1272 << " triangles." << endl; 1273 continue; 1274 } 1275 // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint) 1276 continueflag = continueflag && (!(((LineChecker[0] 1277 != baseline->second->endpoints[0]->lines.end()) 1278 && (LineChecker[1] 1279 != baseline->second->endpoints[1]->lines.end()) 1280 && (GetCommonEndpoint(LineChecker[0]->second, 1281 LineChecker[1]->second) == peak)))); 1282 if (!continueflag) 1283 { 1284 *out << Verbose(4) << "Current target is peak!" << endl; 1285 continue; 1286 } 1287 // in case NOT both were found 1288 if (continueflag) 1289 { // create virtually this triangle, get its normal vector, calculate angle 1290 flag = true; 1291 VirtualNormalVector.MakeNormalVector( 1292 &baseline->second->endpoints[0]->node->x, 1293 &baseline->second->endpoints[1]->node->x, 1294 &target->second->node->x); 1295 // make it always point inward 1296 if (baseline->second->endpoints[0]->node->x.Projection( 1297 &VirtualNormalVector) > 0) 1298 VirtualNormalVector.Scale(-1.); 1299 // calculate angle 1300 TempAngle = NormalVector.Angle(&VirtualNormalVector); 1301 *out << Verbose(4) << "NormalVector is "; 1302 VirtualNormalVector.Output(out); 1303 *out << " and the angle is " << TempAngle << "." << endl; 1304 if (SmallestAngle > TempAngle) 1305 { // set to new possible winner 1306 SmallestAngle = TempAngle; 1307 winner = target; 1308 } 1309 } 1310 } 1311 // 5b. The point of the above whose triangle has the greatest angle with the triangle the current line belongs to (it only belongs to one, remember!): New triangle 1312 if (winner != PointsOnBoundary.end()) 1313 { 1314 *out << Verbose(2) << "Winning target point is " 1315 << *(winner->second) << " with angle " << SmallestAngle 1316 << "." << endl; 1317 // create the lins of not yet present 1318 BLS[0] = baseline->second; 1319 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles) 1320 LineChecker[0] = baseline->second->endpoints[0]->lines.find( 1321 winner->first); 1322 LineChecker[1] = baseline->second->endpoints[1]->lines.find( 1323 winner->first); 1324 if (LineChecker[0] 1325 == baseline->second->endpoints[0]->lines.end()) 1326 { // create 1327 BPS[0] = baseline->second->endpoints[0]; 1328 BPS[1] = winner->second; 1329 BLS[1] = new class BoundaryLineSet(BPS, 1330 LinesOnBoundaryCount); 1331 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, 1332 BLS[1])); 1333 LinesOnBoundaryCount++; 1334 } 1335 else 1336 BLS[1] = LineChecker[0]->second; 1337 if (LineChecker[1] 1338 == baseline->second->endpoints[1]->lines.end()) 1339 { // create 1340 BPS[0] = baseline->second->endpoints[1]; 1341 BPS[1] = winner->second; 1342 BLS[2] = new class BoundaryLineSet(BPS, 1343 LinesOnBoundaryCount); 1344 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, 1345 BLS[2])); 1346 LinesOnBoundaryCount++; 1347 } 1348 else 1349 BLS[2] = LineChecker[1]->second; 1350 BTS = new class BoundaryTriangleSet(BLS, 1351 TrianglesOnBoundaryCount); 1352 TrianglesOnBoundary.insert(TrianglePair( 1353 TrianglesOnBoundaryCount, BTS)); 1354 TrianglesOnBoundaryCount++; 759 do { 760 flag = false; 761 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++) 762 if (baseline->second->TrianglesCount == 1) { 763 *out << Verbose(2) << "Current baseline is between " << *(baseline->second) << "." << endl; 764 // 5a. go through each boundary point if not _both_ edges between either endpoint of the current line and this point exist (and belong to 2 triangles) 765 SmallestAngle = M_PI; 766 BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far 767 // get peak point with respect to this base line's only triangle 768 for(int i=0;i<3;i++) 769 if ((BTS->endpoints[i] != baseline->second->endpoints[0]) && (BTS->endpoints[i] != baseline->second->endpoints[1])) 770 peak = BTS->endpoints[i]; 771 *out << Verbose(3) << " and has peak " << *peak << "." << endl; 772 // normal vector of triangle 773 BTS->GetNormalVector(NormalVector); 774 *out << Verbose(4) << "NormalVector of base triangle is "; 775 NormalVector.Output(out); 776 *out << endl; 777 // offset to center of triangle 778 CenterVector.Zero(); 779 for(int i=0;i<3;i++) 780 CenterVector.AddVector(&BTS->endpoints[i]->node->x); 781 CenterVector.Scale(1./3.); 782 *out << Verbose(4) << "CenterVector of base triangle is "; 783 CenterVector.Output(out); 784 *out << endl; 785 // vector in propagation direction (out of triangle) 786 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection) 787 TempVector.CopyVector(&baseline->second->endpoints[0]->node->x); 788 TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x); 789 PropagationVector.MakeNormalVector(&TempVector, &NormalVector); 790 TempVector.CopyVector(&CenterVector); 791 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center! 792 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl; 793 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline 794 PropagationVector.Scale(-1.); 795 *out << Verbose(4) << "PropagationVector of base triangle is "; 796 PropagationVector.Output(out); 797 *out << endl; 798 winner = PointsOnBoundary.end(); 799 for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++) 800 if ((target->second != baseline->second->endpoints[0]) && (target->second != baseline->second->endpoints[1])) { // don't take the same endpoints 801 *out << Verbose(3) << "Target point is " << *(target->second) << ":"; 802 bool continueflag = true; 803 804 VirtualNormalVector.CopyVector(&baseline->second->endpoints[0]->node->x); 805 VirtualNormalVector.AddVector(&baseline->second->endpoints[0]->node->x); 806 VirtualNormalVector.Scale(-1./2.); // points now to center of base line 807 VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target 808 TempAngle = VirtualNormalVector.Angle(&PropagationVector); 809 continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees) 810 if (!continueflag) { 811 *out << Verbose(4) << "Angle between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", bad direction!" << endl; 812 continue; 813 } else 814 *out << Verbose(4) << "Angle between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", good direction!" << endl; 815 LineChecker[0] = baseline->second->endpoints[0]->lines.find(target->first); 816 LineChecker[1] = baseline->second->endpoints[1]->lines.find(target->first); 817 // if (LineChecker[0] != baseline->second->endpoints[0]->lines.end()) 818 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl; 819 // else 820 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl; 821 // if (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 822 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl; 823 // else 824 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl; 825 // check first endpoint (if any connecting line goes to target or at least not more than 1) 826 continueflag = continueflag && (( (LineChecker[0] == baseline->second->endpoints[0]->lines.end()) || (LineChecker[0]->second->TrianglesCount == 1))); 827 if (!continueflag) { 828 *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl; 829 continue; 830 } 831 // check second endpoint (if any connecting line goes to target or at least not more than 1) 832 continueflag = continueflag && (( (LineChecker[1] == baseline->second->endpoints[1]->lines.end()) || (LineChecker[1]->second->TrianglesCount == 1))); 833 if (!continueflag) { 834 *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl; 835 continue; 836 } 837 // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint) 838 continueflag = continueflag && (!( 839 ((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 840 && (GetCommonEndpoint(LineChecker[0]->second, LineChecker[1]->second) == peak)) 841 )); 842 if (!continueflag) { 843 *out << Verbose(4) << "Current target is peak!" << endl; 844 continue; 845 } 846 // in case NOT both were found 847 if (continueflag) { // create virtually this triangle, get its normal vector, calculate angle 848 flag = true; 849 VirtualNormalVector.MakeNormalVector(&baseline->second->endpoints[0]->node->x, &baseline->second->endpoints[1]->node->x, &target->second->node->x); 850 // make it always point inward 851 if (baseline->second->endpoints[0]->node->x.Projection(&VirtualNormalVector) > 0) 852 VirtualNormalVector.Scale(-1.); 853 // calculate angle 854 TempAngle = NormalVector.Angle(&VirtualNormalVector); 855 *out << Verbose(4) << "NormalVector is "; 856 VirtualNormalVector.Output(out); 857 *out << " and the angle is " << TempAngle << "." << endl; 858 if (SmallestAngle > TempAngle) { // set to new possible winner 859 SmallestAngle = TempAngle; 860 winner = target; 1355 861 } 1356 else 1357 { 1358 *out << Verbose(1) 1359 << "I could not determine a winner for this baseline " 1360 << *(baseline->second) << "." << endl; 1361 } 1362 1363 // 5d. If the set of lines is not yet empty, go to 5. and continue 862 } 1364 863 } 1365 else 1366 *out << Verbose(2) << "Baseline candidate " << *(baseline->second) 1367 << " has a triangle count of " 1368 << baseline->second->TrianglesCount << "." << endl; 1369 } 1370 while (flag); 1371 1372 } 1373 ; 864 // 5b. The point of the above whose triangle has the greatest angle with the triangle the current line belongs to (it only belongs to one, remember!): New triangle 865 if (winner != PointsOnBoundary.end()) { 866 *out << Verbose(2) << "Winning target point is " << *(winner->second) << " with angle " << SmallestAngle << "." << endl; 867 // create the lins of not yet present 868 BLS[0] = baseline->second; 869 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles) 870 LineChecker[0] = baseline->second->endpoints[0]->lines.find(winner->first); 871 LineChecker[1] = baseline->second->endpoints[1]->lines.find(winner->first); 872 if (LineChecker[0] == baseline->second->endpoints[0]->lines.end()) { // create 873 BPS[0] = baseline->second->endpoints[0]; 874 BPS[1] = winner->second; 875 BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 876 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BLS[1]) ); 877 LinesOnBoundaryCount++; 878 } else 879 BLS[1] = LineChecker[0]->second; 880 if (LineChecker[1] == baseline->second->endpoints[1]->lines.end()) { // create 881 BPS[0] = baseline->second->endpoints[1]; 882 BPS[1] = winner->second; 883 BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 884 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BLS[2]) ); 885 LinesOnBoundaryCount++; 886 } else 887 BLS[2] = LineChecker[1]->second; 888 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 889 TrianglesOnBoundary.insert( TrianglePair(TrianglesOnBoundaryCount, BTS) ); 890 TrianglesOnBoundaryCount++; 891 } else { 892 *out << Verbose(1) << "I could not determine a winner for this baseline " << *(baseline->second) << "." << endl; 893 } 894 895 // 5d. If the set of lines is not yet empty, go to 5. and continue 896 } else 897 *out << Verbose(2) << "Baseline candidate " << *(baseline->second) << " has a triangle count of " << baseline->second->TrianglesCount << "." << endl; 898 } while (flag); 899 900 stringstream line; 901 line << configuration->configpath << "/" << CONVEXENVELOPE; 902 *out << Verbose(1) << "Storing convex envelope in tecplot data file " << line.str() << "." << endl; 903 ofstream output(line.str().c_str()); 904 output << "TITLE = \"3D CONVEX SHELL\"" << endl; 905 output << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl; 906 output << "ZONE T=\"TRIANGLES\", N=" << PointsOnBoundaryCount << ", E=" << TrianglesOnBoundaryCount << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl; 907 int *LookupList = new int[mol->AtomCount]; 908 for (int i=0;i<mol->AtomCount;i++) 909 LookupList[i] = -1; 910 911 // print atom coordinates 912 *out << Verbose(2) << "The following triangles were created:"; 913 int Counter = 1; 914 atom *Walker = NULL; 915 for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++) { 916 Walker = target->second->node; 917 LookupList[Walker->nr] = Counter++; 918 output << Walker->x.x[0] << " " << Walker->x.x[1] << " " << Walker->x.x[2] << " " << endl; 919 } 920 output << endl; 921 // print connectivity 922 for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) { 923 *out << " " << runner->second->endpoints[0]->node->Name << "<->" << runner->second->endpoints[1]->node->Name << "<->" << runner->second->endpoints[2]->node->Name; 924 output << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl; 925 } 926 output.close(); 927 delete[](LookupList); 928 *out << endl; 929 }; 1374 930 1375 931 /** Adds an atom to the tesselation::PointsOnBoundary list. 1376 932 * \param *Walker atom to add 1377 933 */ 1378 void 1379 Tesselation::AddPoint(atom *Walker) 1380 { 1381 PointTestPair InsertUnique; 934 void Tesselation::AddPoint(atom *Walker) 935 { 1382 936 BPS[0] = new class BoundaryPointSet(Walker); 1383 InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0])); 1384 if (InsertUnique.second) // if new point was not present before, increase counter 1385 PointsOnBoundaryCount++; 1386 } 1387 ; 1388 1389 /** Adds point to Tesselation::PointsOnBoundary if not yet present. 1390 * Tesselation::TPS is set to either this new BoundaryPointSet or to the existing one of not unique. 1391 * @param Candidate point to add 1392 * @param n index for this point in Tesselation::TPS array 1393 */ 1394 void 1395 Tesselation::AddTrianglePoint(atom* Candidate, int n) 1396 { 1397 PointTestPair InsertUnique; 1398 TPS[n] = new class BoundaryPointSet(Candidate); 1399 InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n])); 1400 if (InsertUnique.second) // if new point was not present before, increase counter 1401 { 1402 PointsOnBoundaryCount++; 1403 } 1404 else 1405 { 1406 delete TPS[n]; 1407 cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node) 1408 << " gibt's schon in der PointMap." << endl; 1409 TPS[n] = (InsertUnique.first)->second; 1410 } 1411 } 1412 ; 1413 1414 /** Function tries to add line from current Points in BPS to BoundaryLineSet. 1415 * If succesful it raises the line count and inserts the new line into the BLS, 1416 * if unsuccesful, it writes the line which had been present into the BLS, deleting the new constructed one. 1417 * @param *a first endpoint 1418 * @param *b second endpoint 1419 * @param n index of Tesselation::BLS giving the line with both endpoints 1420 */ 1421 void 1422 Tesselation::AddTriangleLine(class BoundaryPointSet *a, 1423 class BoundaryPointSet *b, int n) 1424 { 1425 LineMap::iterator LineWalker; 1426 //cout << "Manually checking endpoints for line." << endl; 1427 if ((a->lines.find(b->node->nr)) != a->lines.end()) // ->first == b->node->nr) 1428 //If a line is there, how do I recognize that beyond a shadow of a doubt? 1429 { 1430 //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl; 1431 1432 LineWalker = LinesOnBoundary.end(); 1433 LineWalker--; 1434 1435 while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr, 1436 b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max( 1437 a->node->nr, b->node->nr)) 1438 { 1439 //cout << Verbose(1) << "Looking for line which already exists"<< endl; 1440 LineWalker--; 1441 } 1442 BPS[0] = LineWalker->second->endpoints[0]; 1443 BPS[1] = LineWalker->second->endpoints[1]; 1444 BLS[n] = LineWalker->second; 1445 1446 } 1447 else 1448 { 1449 cout << Verbose(2) 1450 << "Adding line which has not been used before between " 1451 << *(a->node) << " and " << *(b->node) << "." << endl; 1452 BPS[0] = a; 1453 BPS[1] = b; 1454 BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1455 1456 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n])); 1457 LinesOnBoundaryCount++; 1458 1459 } 1460 } 1461 ; 1462 1463 /** Function tries to add Triangle just created to Triangle and remarks if already existent (Failure of algorithm). 1464 * Furthermore it adds the triangle to all of its lines, in order to recognize those which are saturated later. 1465 */ 1466 void 1467 Tesselation::AddTriangleToLines() 1468 { 1469 1470 cout << Verbose(1) << "Adding triangle to its lines" << endl; 1471 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1472 TrianglesOnBoundaryCount++; 1473 1474 /* 1475 * this is apparently done when constructing triangle 1476 1477 for (int i=0; i<3; i++) 1478 { 1479 BLS[i]->AddTriangle(BTS); 1480 } 1481 */ 1482 } 1483 ; 1484 1485 /** 1486 * Function returns center of sphere with RADIUS, which rests on points a, b, c 1487 * @param Center this vector will be used for return 1488 * @param a vector first point of triangle 1489 * @param b vector second point of triangle 1490 * @param c vector third point of triangle 1491 * @param *Umkreismittelpunkt new cneter point of circumference 1492 * @param Direction vector indicates up/down 1493 * @param AlternativeDirection vecotr, needed in case the triangles have 90 deg angle 1494 * @param Halfplaneindicator double indicates whether Direction is up or down 1495 * @param AlternativeIndicator doube indicates in case of orthogonal triangles which direction of AlternativeDirection is suitable 1496 * @param alpha double angle at a 1497 * @param beta double, angle at b 1498 * @param gamma, double, angle at c 1499 * @param Radius, double 1500 * @param Umkreisradius double radius of circumscribing circle 1501 */ 1502 1503 void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection, 1504 double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius) 1505 { 1506 Vector TempNormal, helper; 1507 double Restradius; 1508 cout << Verbose(3) << "Begin of Get_center_of_sphere.\n"; 1509 Center->Zero(); 1510 helper.CopyVector(&a); 1511 helper.Scale(sin(2.*alpha)); 1512 Center->AddVector(&helper); 1513 helper.CopyVector(&b); 1514 helper.Scale(sin(2.*beta)); 1515 Center->AddVector(&helper); 1516 helper.CopyVector(&c); 1517 helper.Scale(sin(2.*gamma)); 1518 Center->AddVector(&helper); 1519 //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ; 1520 Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma))); 1521 NewUmkreismittelpunkt->CopyVector(Center); 1522 cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n"; 1523 // Here we calculated center of circumscribing circle, using barycentric coordinates 1524 cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n"; 1525 1526 TempNormal.CopyVector(&a); 1527 TempNormal.SubtractVector(&b); 1528 helper.CopyVector(&a); 1529 helper.SubtractVector(&c); 1530 TempNormal.VectorProduct(&helper); 1531 if (fabs(HalfplaneIndicator) < MYEPSILON) 1532 { 1533 if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0)) 1534 { 1535 TempNormal.Scale(-1); 1536 } 1537 } 1538 else 1539 { 1540 if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0) 1541 { 1542 TempNormal.Scale(-1); 1543 } 1544 } 1545 1546 TempNormal.Normalize(); 1547 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius); 1548 cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n"; 1549 TempNormal.Scale(Restradius); 1550 cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n"; 1551 1552 Center->AddVector(&TempNormal); 1553 cout << Verbose(4) << "Center of sphere of circumference is " << *Center << ".\n"; 1554 cout << Verbose(3) << "End of Get_center_of_sphere.\n"; 1555 } 1556 ; 1557 1558 1559 /** This recursive function finds a third point, to form a triangle with two given ones. 1560 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \ 1561 * supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \ 1562 * upon which we operate. 1563 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \ 1564 * direction and angle into Storage. 1565 * We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \ 1566 * with all neighbours of the candidate. 1567 * @param a first point 1568 * @param b second point 1569 * *param c atom old third point of old triangle 1570 * @param Candidate base point along whose bonds to start looking from 1571 * @param Parent point to avoid during search as its wrong direction 1572 * @param RecursionLevel contains current recursion depth 1573 * @param Chord baseline vector of first and second point 1574 * @param direction1 second in plane vector (along with \a Chord) of the triangle the baseline belongs to 1575 * @param OldNormal normal of the triangle which the baseline belongs to 1576 * @param ReferencePoint Vector of center of circumscribing circle from which we look towards center of sphere 1577 * @param Opt_Candidate candidate reference to return 1578 * @param Storage array containing two angles of current Opt_Candidate 1579 * @param RADIUS radius of ball 1580 * @param mol molecule structure with atoms and bonds 1581 */ 1582 1583 void Tesselation::Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent, 1584 int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint, 1585 atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol) 1586 { 1587 cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n"; 1588 cout << Verbose(3) << "Candidate is "<< *Candidate << endl; 1589 cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl; 1590 cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl; 1591 cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl; 1592 cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl; 1593 /* OldNormal is normal vector on the old triangle 1594 * direction1 is normal on the triangle line, from which we come, as well as on OldNormal. 1595 * Chord points from b to a!!! 1596 */ 1597 Vector dif_a; //Vector from a to candidate 1598 Vector dif_b; //Vector from b to candidate 1599 Vector AngleCheck; 1600 Vector TempNormal, Umkreismittelpunkt; 1601 Vector Mittelpunkt; 1602 1603 double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius; 1604 double BallAngle, AlternativeSign; 1605 atom *Walker; // variable atom point 1606 1607 Vector NewUmkreismittelpunkt; 1608 1609 if (a != Candidate and b != Candidate and c != Candidate) { 1610 cout << Verbose(3) << "We have a unique candidate!" << endl; 1611 dif_a.CopyVector(&(a->x)); 1612 dif_a.SubtractVector(&(Candidate->x)); 1613 dif_b.CopyVector(&(b->x)); 1614 dif_b.SubtractVector(&(Candidate->x)); 1615 AngleCheck.CopyVector(&(Candidate->x)); 1616 AngleCheck.SubtractVector(&(a->x)); 1617 AngleCheck.ProjectOntoPlane(Chord); 1618 1619 SideA = dif_b.Norm(); 1620 SideB = dif_a.Norm(); 1621 SideC = Chord->Norm(); 1622 //Chord->Scale(-1); 1623 1624 alpha = Chord->Angle(&dif_a); 1625 beta = M_PI - Chord->Angle(&dif_b); 1626 gamma = dif_a.Angle(&dif_b); 1627 1628 cout << Verbose(2) << "Base triangle has sides " << dif_a << ", " << dif_b << ", " << *Chord << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl; 1629 1630 if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) { 1631 cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n"; 1632 cout << Verbose(1) << "Base triangle has sides " << dif_a << ", " << dif_b << ", " << *Chord << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl; 1633 } 1634 1635 if ((M_PI*4. > alpha*5.) && (M_PI*4. > beta*5.) && (M_PI*4 > gamma*5.)) { 1636 Umkreisradius = SideA / 2.0 / sin(alpha); 1637 //cout << Umkreisradius << endl; 1638 //cout << SideB / 2.0 / sin(beta) << endl; 1639 //cout << SideC / 2.0 / sin(gamma) << endl; 1640 1641 if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points. 1642 cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl; 1643 cout << Verbose(2) << "Candidate is "<< *Candidate << endl; 1644 sign = AngleCheck.ScalarProduct(direction1); 1645 if (fabs(sign)<MYEPSILON) { 1646 if (AngleCheck.ScalarProduct(OldNormal)<0) { 1647 sign =0; 1648 AlternativeSign=1; 1649 } else { 1650 sign =0; 1651 AlternativeSign=-1; 1652 } 1653 } else { 1654 sign /= fabs(sign); 1655 cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl; 1656 } 1657 1658 Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius); 1659 1660 AngleCheck.CopyVector(&ReferencePoint); 1661 AngleCheck.Scale(-1); 1662 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl; 1663 AngleCheck.AddVector(&Mittelpunkt); 1664 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl; 1665 cout << Verbose(4) << "Reference vector to sphere's center is " << AngleCheck << "." << endl; 1666 1667 BallAngle = AngleCheck.Angle(OldNormal); 1668 cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl; 1669 1670 //cout << "direction1 is " << direction1->x[0] <<" "<< direction1->x[1] <<" "<< direction1->x[2] <<" " << endl; 1671 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl; 1672 1673 cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl; 1674 1675 NewUmkreismittelpunkt.SubtractVector(&ReferencePoint); 1676 1677 if ((AngleCheck.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) { 1678 if (Storage[0]< -1.5) { // first Candidate at all 1679 if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) { 1680 cout << Verbose(2) << "First good candidate is " << *Candidate << " with "; 1681 Opt_Candidate = Candidate; 1682 Storage[0] = sign; 1683 Storage[1] = AlternativeSign; 1684 Storage[2] = BallAngle; 1685 cout << " angle " << Storage[2] << " and Up/Down " 1686 << Storage[0] << endl; 1687 } else 1688 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl; 1689 } else { 1690 if ( Storage[2] > BallAngle) { 1691 if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) { 1692 cout << Verbose(2) << "Next better candidate is " << *Candidate << " with "; 1693 Opt_Candidate = Candidate; 1694 Storage[0] = sign; 1695 Storage[1] = AlternativeSign; 1696 Storage[2] = BallAngle; 1697 cout << " angle " << Storage[2] << " and Up/Down " 1698 << Storage[0] << endl; 1699 } else 1700 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl; 1701 } else { 1702 if (DEBUG) { 1703 cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl; 1704 } 1705 } 1706 } 1707 } else { 1708 if (DEBUG) { 1709 cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl; 1710 } 1711 } 1712 } else { 1713 if (DEBUG) { 1714 cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl; 1715 } 1716 } 1717 } else { 1718 if (DEBUG) { 1719 cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl; 1720 } 1721 } 1722 } else { 1723 if (DEBUG) { 1724 cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl; 1725 } 1726 } 1727 1728 if (RecursionLevel < 5) { // Seven is the recursion level threshold. 1729 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond 1730 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate); 1731 if (Walker == Parent) { // don't go back the same bond 1732 continue; 1733 } else { 1734 Find_next_suitable_point_via_Angle_of_Sphere(a, b, c, Walker, Candidate, RecursionLevel+1, Chord, direction1, OldNormal, ReferencePoint, Opt_Candidate, Storage, RADIUS, mol); //call function again 1735 } 1736 } 1737 } 1738 cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n"; 1739 } 1740 ; 1741 1742 1743 /** This recursive function finds a third point, to form a triangle with two given ones. 1744 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \ 1745 * supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \ 1746 * upon which we operate. 1747 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \ 1748 * direction and angle into Storage. 1749 * We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \ 1750 * with all neighbours of the candidate. 1751 * @param a first point 1752 * @param b second point 1753 * @param Candidate base point along whose bonds to start looking from 1754 * @param Parent point to avoid during search as its wrong direction 1755 * @param RecursionLevel contains current recursion depth 1756 * @param Chord baseline vector of first and second point 1757 * @param d1 second in plane vector (along with \a Chord) of the triangle the baseline belongs to 1758 * @param OldNormal normal of the triangle which the baseline belongs to 1759 * @param Opt_Candidate candidate reference to return 1760 * @param Opt_Mittelpunkt Centerpoint of ball, when resting on Opt_Candidate 1761 * @param Storage array containing two angles of current Opt_Candidate 1762 * @param RADIUS radius of ball 1763 * @param mol molecule structure with atoms and bonds 1764 */ 1765 void Find_next_suitable_point(atom* a, atom* b, atom* Candidate, atom* Parent, 1766 int RecursionLevel, Vector *Chord, Vector *d1, Vector *OldNormal, 1767 atom*& Opt_Candidate, Vector *Opt_Mittelpunkt, double *Storage, const double RADIUS, molecule* mol) 1768 { 1769 /* OldNormal is normal vector on the old triangle 1770 * d1 is normal on the triangle line, from which we come, as well as on OldNormal. 1771 * Chord points from b to a!!! 1772 */ 1773 Vector dif_a; //Vector from a to candidate 1774 Vector dif_b; //Vector from b to candidate 1775 Vector AngleCheck, AngleCheckReference, DirectionCheckPoint; 1776 Vector TempNormal, Umkreismittelpunkt, Mittelpunkt, helper; 1777 1778 double CurrentEpsilon = 0.1; 1779 double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius; 1780 double BallAngle; 1781 atom *Walker; // variable atom point 1782 1783 1784 dif_a.CopyVector(&(a->x)); 1785 dif_a.SubtractVector(&(Candidate->x)); 1786 dif_b.CopyVector(&(b->x)); 1787 dif_b.SubtractVector(&(Candidate->x)); 1788 DirectionCheckPoint.CopyVector(&dif_a); 1789 DirectionCheckPoint.Scale(-1); 1790 DirectionCheckPoint.ProjectOntoPlane(Chord); 1791 1792 SideA = dif_b.Norm(); 1793 SideB = dif_a.Norm(); 1794 SideC = Chord->Norm(); 1795 //Chord->Scale(-1); 1796 1797 alpha = Chord->Angle(&dif_a); 1798 beta = M_PI - Chord->Angle(&dif_b); 1799 gamma = dif_a.Angle(&dif_b); 1800 1801 1802 if (DEBUG) { 1803 cout << "Atom number" << Candidate->nr << endl; 1804 Candidate->x.Output((ofstream *) &cout); 1805 cout << "number of bonds " << mol->NumberOfBondsPerAtom[Candidate->nr] << endl; 1806 } 1807 1808 if (a != Candidate and b != Candidate) { 1809 // alpha = dif_a.Angle(&dif_b) / 2.; 1810 // SideA = Chord->Norm() / 2.;// (Chord->Norm()/2.) / sin(0.5*alpha); 1811 // SideB = dif_a.Norm(); 1812 // centerline = SideA * SideA + SideB * SideB - 2. * SideA * SideB * cos( 1813 // alpha); // note this is squared of center line length 1814 // centerline = (Chord->Norm()/2.) / sin(0.5*alpha); 1815 // Those are remains from Freddie. Needed? 1816 1817 Umkreisradius = SideA / 2.0 / sin(alpha); 1818 //cout << Umkreisradius << endl; 1819 //cout << SideB / 2.0 / sin(beta) << endl; 1820 //cout << SideC / 2.0 / sin(gamma) << endl; 1821 1822 if (Umkreisradius < RADIUS && DirectionCheckPoint.ScalarProduct(&(Candidate->x))>0) { //Checking whether ball will at least rest o points. 1823 // intermediate calculations to aquire centre of sphere, called Mittelpunkt: 1824 Umkreismittelpunkt.Zero(); 1825 helper.CopyVector(&a->x); 1826 helper.Scale(sin(2.*alpha)); 1827 Umkreismittelpunkt.AddVector(&helper); 1828 helper.CopyVector(&b->x); 1829 helper.Scale(sin(2.*beta)); 1830 Umkreismittelpunkt.AddVector(&helper); 1831 helper.CopyVector(&Candidate->x); 1832 helper.Scale(sin(2.*gamma)); 1833 Umkreismittelpunkt.AddVector(&helper); 1834 //Umkreismittelpunkt = (a->x) * sin(2.*alpha) + b->x * sin(2.*beta) + (Candidate->x) * sin(2.*gamma) ; 1835 Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma))); 1836 1837 TempNormal.CopyVector(&dif_a); 1838 TempNormal.VectorProduct(&dif_b); 1839 if (TempNormal.ScalarProduct(OldNormal)<0 && sign>0 || TempNormal.ScalarProduct(OldNormal)>0 && sign<0) { 1840 TempNormal.Scale(-1); 1841 } 1842 TempNormal.Normalize(); 1843 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius); 1844 TempNormal.Scale(Restradius); 1845 1846 Mittelpunkt.CopyVector(&Umkreismittelpunkt); 1847 Mittelpunkt.AddVector(&TempNormal); //this is center of sphere supported by a, b and Candidate 1848 1849 AngleCheck.CopyVector(Chord); 1850 AngleCheck.Scale(-0.5); 1851 AngleCheck.SubtractVector(&(b->x)); 1852 AngleCheckReference.CopyVector(&AngleCheck); 1853 AngleCheckReference.AddVector(Opt_Mittelpunkt); 1854 AngleCheck.AddVector(&Mittelpunkt); 1855 1856 BallAngle = AngleCheck.Angle(&AngleCheckReference); 1857 1858 d1->ProjectOntoPlane(&AngleCheckReference); 1859 sign = AngleCheck.ScalarProduct(d1); 1860 if (fabs(sign) < MYEPSILON) 1861 sign = 0; 1862 else 1863 sign /= fabs(sign); // +1 if in direction of triangle plane, -1 if in other direction... 1864 1865 1866 if (Storage[0]< -1.5) { // first Candidate at all 1867 cout << "Next better candidate is " << *Candidate << " with "; 1868 Opt_Candidate = Candidate; 1869 Storage[0] = sign; 1870 Storage[1] = BallAngle; 1871 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1872 cout << "Angle is " << Storage[1] << ", Halbraum ist " << Storage[0] << endl; 1873 } else { 1874 /* 1875 * removed due to change in criterium, now checking angle of ball to old normal. 1876 //We will now check for non interference, that is if the new candidate would have the Opt_Candidate 1877 //within the ball. 1878 1879 Distance = Opt_Candidate->x.Distance(&Mittelpunkt); 1880 //cout << "Opt_Candidate " << Opt_Candidate << " has distance " << Distance << " to Center of Candidate " << endl; 1881 1882 1883 if (Distance >RADIUS) { // We have no interference and may now check whether the new point is better. 1884 */ 1885 //cout << "Atom " << Candidate << " has distance " << Candidate->x.Distance(Opt_Mittelpunkt) << " to Center of Candidate " << endl; 1886 1887 if (((Storage[0] < 0 && fabs(sign - Storage[0]) > CurrentEpsilon))) { //This will give absolute preference to those in "right-hand" quadrants 1888 //(Candidate->x.Distance(Opt_Mittelpunkt) < RADIUS)) //and those where Candidate would be within old Sphere. 1889 cout << "Next better candidate is " << *Candidate << " with "; 1890 Opt_Candidate = Candidate; 1891 Storage[0] = sign; 1892 Storage[1] = BallAngle; 1893 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1894 cout << "Angle is " << Storage[1] << ", Halbraum ist " << Storage[0] << endl; 1895 } else { 1896 if ((fabs(sign - Storage[0]) < CurrentEpsilon && sign > 0 && Storage[1] > BallAngle) || (fabs(sign - Storage[0]) < CurrentEpsilon && sign < 0 && Storage[1] < BallAngle)) { 1897 //Depending on quadrant we prefer higher or lower atom with respect to Triangle normal first. 1898 cout << "Next better candidate is " << *Candidate << " with "; 1899 Opt_Candidate = Candidate; 1900 Storage[0] = sign; 1901 Storage[1] = BallAngle; 1902 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1903 cout << "Angle is " << Storage[1] << ", Halbraum ist " << Storage[0] << endl; 1904 } 1905 } 1906 } 1907 /* 1908 * This is for checking point-angle and presence of Candidates in Ball, currently we are checking the ball Angle. 1909 * 1910 else 1911 { 1912 if (sign>0 && BallAngle>0 && Storage[0]<0) 1913 { 1914 cout << "Next better candidate is " << *Candidate << " with "; 1915 Opt_Candidate = Candidate; 1916 Storage[0] = sign; 1917 Storage[1] = BallAngle; 1918 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1919 cout << "Angle is " << Storage[1] << ", Halbraum ist " 1920 << Storage[0] << endl; 1921 1922 //Debugging purposes only 1923 cout << "Umkreismittelpunkt has coordinates" << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] <<" "<<Umkreismittelpunkt.x[2] << endl; 1924 cout << "Candidate has coordinates" << Candidate->x.x[0]<< " " << Candidate->x.x[1] << " " << Candidate->x.x[2] << endl; 1925 cout << "a has coordinates" << a->x.x[0]<< " " << a->x.x[1] << " " << a->x.x[2] << endl; 1926 cout << "b has coordinates" << b->x.x[0]<< " " << b->x.x[1] << " " << b->x.x[2] << endl; 1927 cout << "Mittelpunkt has coordinates" << Mittelpunkt.x[0] << " " << Mittelpunkt.x[1]<< " " <<Mittelpunkt.x[2] << endl; 1928 cout << "Umkreisradius ist " << Umkreisradius << endl; 1929 cout << "Restradius ist " << Restradius << endl; 1930 cout << "TempNormal has coordinates " << TempNormal.x[0] << " " << TempNormal.x[1] << " " << TempNormal.x[2] << " " << endl; 1931 cout << "OldNormal has coordinates " << OldNormal->x[0] << " " << OldNormal->x[1] << " " << OldNormal->x[2] << " " << endl; 1932 cout << "Dist a to UmkreisMittelpunkt " << a->x.Distance(&Umkreismittelpunkt) << endl; 1933 cout << "Dist b to UmkreisMittelpunkt " << b->x.Distance(&Umkreismittelpunkt) << endl; 1934 cout << "Dist Candidate to UmkreisMittelpunkt " << Candidate->x.Distance(&Umkreismittelpunkt) << endl; 1935 cout << "Dist a to Mittelpunkt " << a->x.Distance(&Mittelpunkt) << endl; 1936 cout << "Dist b to Mittelpunkt " << b->x.Distance(&Mittelpunkt) << endl; 1937 cout << "Dist Candidate to Mittelpunkt " << Candidate->x.Distance(&Mittelpunkt) << endl; 1938 1939 1940 1941 } 1942 else 1943 { 1944 if (DEBUG) 1945 cout << "Looses to better candidate" << endl; 1946 } 1947 } 1948 */ 1949 } else { 1950 if (DEBUG) { 1951 cout << "Doesn't satisfy requirements for circumscribing circle" << endl; 1952 } 1953 } 1954 } else { 1955 if (DEBUG) { 1956 cout << "identisch mit Ursprungslinie" << endl; 1957 } 1958 } 1959 1960 if (RecursionLevel < 9) { // Five is the recursion level threshold. 1961 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond 1962 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate); 1963 if (Walker == Parent) { // don't go back the same bond 1964 continue; 1965 } else { 1966 Find_next_suitable_point(a, b, Walker, Candidate, RecursionLevel+1, Chord, d1, OldNormal, Opt_Candidate, Opt_Mittelpunkt, Storage, RADIUS, mol); //call function again 1967 } 1968 } 1969 } 1970 }; 1971 1972 /** This function finds a triangle to a line, adjacent to an existing one. 1973 * @param out output stream for debugging 1974 * @param tecplot output stream for writing found triangles in TecPlot format 1975 * @param mol molecule structure with all atoms and bonds 1976 * @param Line current baseline to search from 1977 * @param T current triangle which \a Line is edge of 1978 * @param RADIUS radius of the rolling ball 1979 * @param N number of found triangles 1980 * @param *filename filename base for intermediate envelopes 1981 */ 1982 bool Tesselation::Find_next_suitable_triangle(ofstream *out, ofstream *tecplot, 1983 molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, 1984 const double& RADIUS, int N, const char *tempbasename) 1985 { 1986 cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n"; 1987 Vector direction1; 1988 Vector helper; 1989 Vector Chord; 1990 ofstream *tempstream = NULL; 1991 char NumberName[255]; 1992 double tmp; 1993 //atom* Walker; 1994 atom* OldThirdPoint; 1995 1996 double Storage[3]; 1997 Storage[0] = -2.; // This direction is either +1 or -1 one, so any result will take precedence over initial values 1998 Storage[1] = -2.; // This is also lower then any value produced by an eligible atom, which are all positive 1999 Storage[2] = 9999999.; 2000 atom* Opt_Candidate = NULL; 2001 Vector Opt_Mittelpunkt; 2002 2003 cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl; 2004 2005 helper.CopyVector(&(Line.endpoints[0]->node->x)); 2006 for (int i = 0; i < 3; i++) { 2007 if (T.endpoints[i]->node->nr != Line.endpoints[0]->node->nr && T.endpoints[i]->node->nr != Line.endpoints[1]->node->nr) { 2008 OldThirdPoint = T.endpoints[i]->node; 2009 helper.SubtractVector(&T.endpoints[i]->node->x); 2010 break; 2011 } 2012 } 2013 2014 direction1.CopyVector(&Line.endpoints[0]->node->x); 2015 direction1.SubtractVector(&Line.endpoints[1]->node->x); 2016 direction1.VectorProduct(&(T.NormalVector)); 2017 2018 if (direction1.ScalarProduct(&helper) < 0) { 2019 direction1.Scale(-1); 2020 } 2021 cout << Verbose(2) << "Looking in direction " << direction1 << " for candidates.\n"; 2022 2023 Chord.CopyVector(&(Line.endpoints[0]->node->x)); // bring into calling function 2024 Chord.SubtractVector(&(Line.endpoints[1]->node->x)); 2025 cout << Verbose(2) << "Baseline vector is " << Chord << ".\n"; 2026 2027 2028 Vector Umkreismittelpunkt, a, b, c; 2029 double alpha, beta, gamma; 2030 a.CopyVector(&(T.endpoints[0]->node->x)); 2031 b.CopyVector(&(T.endpoints[1]->node->x)); 2032 c.CopyVector(&(T.endpoints[2]->node->x)); 2033 a.SubtractVector(&(T.endpoints[1]->node->x)); 2034 b.SubtractVector(&(T.endpoints[2]->node->x)); 2035 c.SubtractVector(&(T.endpoints[0]->node->x)); 2036 2037 alpha = M_PI - a.Angle(&c); 2038 beta = M_PI - b.Angle(&a); 2039 gamma = M_PI - c.Angle(&b); 2040 if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) 2041 cerr << Verbose(0) << "WARNING: sum of angles for candidate triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n"; 2042 2043 Umkreismittelpunkt.Zero(); 2044 helper.CopyVector(&T.endpoints[0]->node->x); 2045 helper.Scale(sin(2.*alpha)); 2046 Umkreismittelpunkt.AddVector(&helper); 2047 helper.CopyVector(&T.endpoints[1]->node->x); 2048 helper.Scale(sin(2.*beta)); 2049 Umkreismittelpunkt.AddVector(&helper); 2050 helper.CopyVector(&T.endpoints[2]->node->x); 2051 helper.Scale(sin(2.*gamma)); 2052 Umkreismittelpunkt.AddVector(&helper); 2053 //Umkreismittelpunkt = (T.endpoints[0]->node->x) * sin(2.*alpha) + T.endpoints[1]->node->x * sin(2.*beta) + (T.endpoints[2]->node->x) * sin(2.*gamma) ; 2054 //cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl; 2055 Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma))); 2056 //cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl; 2057 cout << " We look over line " << Line << " in direction " << direction1.x[0] << " " << direction1.x[1] << " " << direction1.x[2] << " " << endl; 2058 cout << " Old Normal is " << (T.NormalVector.x)[0] << " " << T.NormalVector.x[1] << " " << (T.NormalVector.x)[2] << " " << endl; 2059 2060 cout << Verbose(2) << "Base triangle has sides " << a << ", " << b << ", " << c << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl; 2061 cout << Verbose(2) << "Center of circumference is " << Umkreismittelpunkt << "." << endl; 2062 if (DEBUG) 2063 cout << Verbose(3) << "Check of relative endpoints (same distance, equally spreaded): "<< endl; 2064 tmp = 0; 2065 for (int i=0;i<NDIM;i++) { 2066 helper.CopyVector(&T.endpoints[i]->node->x); 2067 helper.SubtractVector(&Umkreismittelpunkt); 2068 if (DEBUG) 2069 cout << Verbose(3) << "Endpoint[" << i << "]: " << helper << " with length " << helper.Norm() << "." << endl; 2070 if (tmp == 0) // set on first time for comparison against next ones 2071 tmp = helper.Norm(); 2072 if (fabs(helper.Norm() - tmp) > MYEPSILON) 2073 cerr << Verbose(1) << "WARNING: center of circumference is wrong!" << endl; 2074 } 2075 2076 cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl; 2077 2078 Find_next_suitable_point_via_Angle_of_Sphere(Line.endpoints[0]->node, Line.endpoints[1]->node, OldThirdPoint, Line.endpoints[0]->node, Line.endpoints[1]->node, 0, &Chord, &direction1, &(T.NormalVector), Umkreismittelpunkt, Opt_Candidate, Storage, RADIUS, mol); 2079 Find_next_suitable_point_via_Angle_of_Sphere(Line.endpoints[0]->node, Line.endpoints[1]->node, OldThirdPoint, Line.endpoints[1]->node, Line.endpoints[0]->node, 0, &Chord, &direction1, &(T.NormalVector), Umkreismittelpunkt, Opt_Candidate, Storage, RADIUS, mol); 2080 if (Opt_Candidate == NULL) { 2081 cerr << "WARNING: Could not find a suitable candidate." << endl; 2082 return false; 2083 } 2084 cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << endl; 2085 2086 // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2) 2087 bool flag = CheckPresenceOfTriangle(out, Opt_Candidate, Line.endpoints[0]->node, Line.endpoints[1]->node); 2088 2089 if (flag) { // if so, add 2090 AddTrianglePoint(Opt_Candidate, 0); 2091 AddTrianglePoint(Line.endpoints[0]->node, 1); 2092 AddTrianglePoint(Line.endpoints[1]->node, 2); 2093 2094 AddTriangleLine(TPS[0], TPS[1], 0); 2095 AddTriangleLine(TPS[0], TPS[2], 1); 2096 AddTriangleLine(TPS[1], TPS[2], 2); 2097 2098 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 2099 AddTriangleToLines(); 2100 2101 BTS->GetNormalVector(BTS->NormalVector); 2102 2103 if ((BTS->NormalVector.ScalarProduct(&(T.NormalVector)) < 0 && Storage[0] > 0) || (BTS->NormalVector.ScalarProduct(&(T.NormalVector)) > 0 && Storage[0] < 0) || (fabs(Storage[0]) < MYEPSILON && Storage[1]*BTS->NormalVector.ScalarProduct(&direction1) < 0) ) { 2104 BTS->NormalVector.Scale(-1); 2105 }; 2106 cout << Verbose(1) << "New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl; 2107 cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl; 2108 } else { // else, yell and do nothing 2109 cout << Verbose(1) << "This triangle consisting of "; 2110 cout << *Opt_Candidate << ", "; 2111 cout << *Line.endpoints[0]->node << " and "; 2112 cout << *Line.endpoints[1]->node << " "; 2113 cout << "is invalid!" << endl; 2114 return false; 2115 } 2116 2117 if ((TrianglesOnBoundaryCount % 10) == 0) { 2118 sprintf(NumberName, "-%d", TriangleFilesWritten); 2119 if (DoTecplotOutput) { 2120 string NameofTempFile(tempbasename); 2121 NameofTempFile.append(NumberName); 2122 NameofTempFile.append(TecplotSuffix); 2123 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2124 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2125 write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten); 2126 tempstream->close(); 2127 tempstream->flush(); 2128 delete(tempstream); 2129 } 2130 2131 if (DoRaster3DOutput) { 2132 string NameofTempFile(tempbasename); 2133 NameofTempFile.append(NumberName); 2134 NameofTempFile.append(Raster3DSuffix); 2135 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2136 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2137 write_raster3d_file(out, tempstream, this, mol); 2138 tempstream->close(); 2139 tempstream->flush(); 2140 delete(tempstream); 2141 } 2142 if (DoTecplotOutput || DoRaster3DOutput) 2143 TriangleFilesWritten++; 2144 } 2145 2146 cout << Verbose(1) << "End of Find_next_suitable_triangle\n"; 2147 return true; 2148 }; 2149 2150 /** Checks whether the triangle consisting of the three atoms is already present. 2151 * Searches for the points in Tesselation::PointsOnBoundary and checks their 2152 * lines. If any of the three edges already has two triangles attached, false is 2153 * returned. 2154 * \param *out output stream for debugging 2155 * \param *a first endpoint 2156 * \param *b second endpoint 2157 * \param *c third endpoint 2158 * \return false - triangle invalid due to edge criteria, true - triangle may be added. 2159 */ 2160 bool Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *a, atom *b, atom *c) { 2161 LineMap::iterator TryAndError; 2162 PointTestPair InsertPoint; 2163 bool Present[3]; 2164 2165 *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl; 2166 TPS[0] = new class BoundaryPointSet(a); 2167 TPS[1] = new class BoundaryPointSet(b); 2168 TPS[2] = new class BoundaryPointSet(c); 2169 for (int i=0;i<3;i++) { // check through all endpoints 2170 InsertPoint = PointsOnBoundary.insert(PointPair(TPS[i]->node->nr, TPS[i])); 2171 Present[i] = !InsertPoint.second; 2172 if (Present[i]) { // if new point was not present before, increase counter 2173 delete TPS[i]; 2174 *out << Verbose(2) << "Atom " << *((InsertPoint.first)->second->node) << " gibt's schon in der PointMap." << endl; 2175 TPS[i] = (InsertPoint.first)->second; 2176 } 2177 } 2178 2179 // check lines 2180 for (int i=0;i<3;i++) 2181 if (Present[i]) 2182 for (int j=i;j<3;j++) 2183 if (Present[j]) { 2184 TryAndError = TPS[i]->lines.find(TPS[j]->node->nr); 2185 if ((TryAndError != TPS[i]->lines.end()) && (TryAndError->second->TrianglesCount > 1)) { 2186 *out << "WARNING: Line " << *TryAndError->second << " already present with " << TryAndError->second->TrianglesCount << " triangles attached." << endl; 2187 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl; 2188 return false; 2189 } 2190 } 2191 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl; 2192 return true; 2193 }; 2194 2195 2196 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, atom* Parent, 2197 int RecursionLevel, Vector Oben, atom*& Opt_Candidate, double Storage[3], 2198 molecule* mol, double RADIUS) 2199 { 2200 cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation, recursive level " << RecursionLevel << endl; 2201 int i; 2202 Vector AngleCheck; 2203 atom* Walker; 2204 double norm = -1., angle; 2205 2206 // check if we only have one unique point yet ... 2207 if (a != Candidate) { 2208 cout << Verbose(3) << "Current candidate is " << *Candidate << ": "; 2209 AngleCheck.CopyVector(&(Candidate->x)); 2210 AngleCheck.SubtractVector(&(a->x)); 2211 norm = AngleCheck.Norm(); 2212 // second point shall have smallest angle with respect to Oben vector 2213 if (norm < RADIUS) { 2214 angle = AngleCheck.Angle(&Oben); 2215 if (angle < Storage[0]) { 2216 //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]); 2217 cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n"; 2218 Opt_Candidate = Candidate; 2219 Storage[0] = AngleCheck.Angle(&Oben); 2220 //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]); 2221 } else { 2222 cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl; 2223 } 2224 } else { 2225 cout << "Refused due to Radius " << norm << endl; 2226 } 2227 } 2228 2229 // if not recursed to deeply, look at all its bonds 2230 if (RecursionLevel < 7) { 2231 for (i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { 2232 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate); 2233 if (Walker == Parent) // don't go back along the bond we came from 2234 continue; 2235 else 2236 Find_second_point_for_Tesselation(a, Walker, Candidate, RecursionLevel + 1, Oben, Opt_Candidate, Storage, mol, RADIUS); 2237 } 2238 } 2239 cout << Verbose(2) << "End of Find_second_point_for_Tesselation, recursive level " << RecursionLevel << endl; 2240 }; 2241 2242 void Tesselation::Find_starting_triangle(molecule* mol, const double RADIUS) 2243 { 2244 cout << Verbose(1) << "Begin of Find_starting_triangle\n"; 2245 int i = 0; 2246 atom* Walker; 2247 atom* FirstPoint; 2248 atom* SecondPoint; 2249 atom* max_index[NDIM]; 2250 double max_coordinate[NDIM]; 2251 Vector Oben; 2252 Vector helper; 2253 Vector Chord; 2254 Vector CenterOfFirstLine; 2255 2256 Oben.Zero(); 2257 2258 for (i = 0; i < 3; i++) { 2259 max_index[i] = NULL; 2260 max_coordinate[i] = -1; 2261 } 2262 cout << Verbose(2) << "Molecule mol is there and has " << mol->AtomCount << " Atoms \n"; 2263 2264 // 1. searching topmost atom with respect to each axis 2265 Walker = mol->start; 2266 while (Walker->next != mol->end) { 2267 Walker = Walker->next; 2268 for (i = 0; i < 3; i++) { 2269 if (Walker->x.x[i] > max_coordinate[i]) { 2270 max_coordinate[i] = Walker->x.x[i]; 2271 max_index[i] = Walker; 2272 } 2273 } 2274 } 2275 2276 cout << Verbose(2) << "Found maximum coordinates: "; 2277 for (int i=0;i<NDIM;i++) 2278 cout << i << ": " << *max_index[i] << "\t"; 2279 cout << endl; 2280 //Koennen dies fuer alle Richtungen, legen hier erstmal Richtung auf k=0 2281 const int k = 1; 2282 Oben.x[k] = 1.; 2283 FirstPoint = max_index[k]; 2284 2285 cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << " with " << mol->NumberOfBondsPerAtom[FirstPoint->nr] << " bonds." << endl; 2286 double Storage[3]; 2287 atom* Opt_Candidate = NULL; 2288 Storage[0] = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant. 2289 Storage[1] = 999999.; // This will be an angle looking for the third point. 2290 Storage[2] = 999999.; 2291 2292 Find_second_point_for_Tesselation(FirstPoint, FirstPoint, FirstPoint, 0, Oben, Opt_Candidate, Storage, mol, RADIUS); // we give same point as next candidate as its bonds are looked into in find_second_... 2293 SecondPoint = Opt_Candidate; 2294 cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n"; 2295 2296 helper.CopyVector(&(FirstPoint->x)); 2297 helper.SubtractVector(&(SecondPoint->x)); 2298 helper.Normalize(); 2299 Oben.ProjectOntoPlane(&helper); 2300 Oben.Normalize(); 2301 helper.VectorProduct(&Oben); 2302 Storage[0] = -2.; // This will indicate the quadrant. 2303 Storage[1] = 9999999.; // This will be an angle looking for the third point. 2304 Storage[2] = 9999999.; 2305 2306 Chord.CopyVector(&(FirstPoint->x)); // bring into calling function 2307 Chord.SubtractVector(&(SecondPoint->x)); 2308 // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized) 2309 2310 cout << Verbose(2) << "Looking for third point candidates \n"; 2311 // look in one direction of baseline for initial candidate 2312 Opt_Candidate = NULL; 2313 CenterOfFirstLine.CopyVector(&Chord); 2314 CenterOfFirstLine.Scale(0.5); 2315 CenterOfFirstLine.AddVector(&(SecondPoint->x)); 2316 2317 cout << Verbose(1) << "Looking for third point candidates from " << *FirstPoint << " onward ...\n"; 2318 Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, SecondPoint, FirstPoint, 0, &Chord, &helper, &Oben, CenterOfFirstLine, Opt_Candidate, Storage, RADIUS, mol); 2319 // look in other direction of baseline for possible better candidate 2320 cout << Verbose(1) << "Looking for third point candidates from " << *SecondPoint << " onward ...\n"; 2321 Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, FirstPoint, SecondPoint, 0, &Chord, &helper, &Oben, CenterOfFirstLine, Opt_Candidate, Storage, RADIUS, mol); 2322 cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl; 2323 2324 // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate 2325 2326 // Finally, we only have to add the found points 2327 AddTrianglePoint(FirstPoint, 0); 2328 AddTrianglePoint(SecondPoint, 1); 2329 AddTrianglePoint(Opt_Candidate, 2); 2330 // ... and respective lines 2331 AddTriangleLine(TPS[0], TPS[1], 0); 2332 AddTriangleLine(TPS[1], TPS[2], 1); 2333 AddTriangleLine(TPS[0], TPS[2], 2); 2334 // ... and triangles to the Maps of the Tesselation class 2335 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 2336 AddTriangleToLines(); 2337 // ... and calculate its normal vector (with correct orientation) 2338 Oben.Scale(-1.); 2339 BTS->GetNormalVector(Oben); 2340 cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n"; 2341 cout << Verbose(1) << "End of Find_starting_triangle\n"; 2342 }; 2343 2344 void Find_non_convex_border(ofstream *out, ofstream *tecplot, molecule* mol, const char *filename, const double RADIUS) 2345 { 2346 int N = 0; 2347 struct Tesselation *Tess = new Tesselation; 2348 cout << Verbose(1) << "Entering search for non convex hull. " << endl; 2349 cout << flush; 2350 LineMap::iterator baseline; 2351 cout << Verbose(0) << "Begin of Find_non_convex_border\n"; 2352 bool flag = false; // marks whether we went once through all baselines without finding any without two triangles 2353 bool failflag = false; 2354 if ((mol->first->next == mol->last) || (mol->last->previous == mol->first)) 2355 mol->CreateAdjacencyList((ofstream *)&cout, 1.6, true); 2356 2357 Tess->Find_starting_triangle(mol, RADIUS); 2358 2359 baseline = Tess->LinesOnBoundary.begin(); 2360 while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) { 2361 if (baseline->second->TrianglesCount == 1) { 2362 failflag = Tess->Find_next_suitable_triangle(out, tecplot, mol, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename); //the line is there, so there is a triangle, but only one. 2363 flag = flag || failflag; 2364 if (!failflag) 2365 cerr << "WARNING: Find_next_suitable_triangle failed." << endl; 2366 } else { 2367 cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl; 2368 } 2369 N++; 2370 baseline++; 2371 if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) { 2372 baseline = Tess->LinesOnBoundary.begin(); // restart if we reach end due to newly inserted lines 2373 flag = false; 2374 } 2375 } 2376 if (failflag) { 2377 cout << Verbose(1) << "Writing final tecplot file\n"; 2378 if (DoTecplotOutput) 2379 write_tecplot_file(out, tecplot, Tess, mol, -1); 2380 if (DoRaster3DOutput) 2381 write_raster3d_file(out, tecplot, Tess, mol); 2382 } else { 2383 cerr << "ERROR: Could definately not find all necessary triangles!" << endl; 2384 } 2385 2386 cout << Verbose(0) << "End of Find_non_convex_border\n"; 2387 delete(Tess); 2388 }; 2389 937 PointsOnBoundary.insert( PointPair(Walker->nr, BPS[0]) ); 938 PointsOnBoundaryCount++; 939 }; -
Property mode
changed from
-
src/boundary.hpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 36 36 BoundaryPointSet(atom *Walker); 37 37 ~BoundaryPointSet(); 38 38 39 39 void AddLine(class BoundaryLineSet *line); 40 40 41 41 LineMap lines; 42 42 int LinesCount; … … 64 64 BoundaryTriangleSet(class BoundaryLineSet *line[3], int number); 65 65 ~BoundaryTriangleSet(); 66 66 67 67 void GetNormalVector(Vector &NormalVector); 68 68 69 69 class BoundaryPointSet *endpoints[3]; 70 70 class BoundaryLineSet *lines[3]; 71 Vector NormalVector;72 71 int Nr; 73 72 }; … … 75 74 class Tesselation { 76 75 public: 77 76 78 77 Tesselation(); 79 78 ~Tesselation(); 80 79 81 80 void TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol); 82 81 void GuessStartingTriangle(ofstream *out); 83 82 void AddPoint(atom * Walker); 84 void AddTrianglePoint(atom* Candidate, int n); 85 void AddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n); 86 void AddTriangleToLines(); 87 void Find_starting_triangle(molecule* mol, const double RADIUS); 88 bool Find_next_suitable_triangle(ofstream *out, ofstream *tecplot, molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, const char *filename); 89 bool CheckPresenceOfTriangle(ofstream *out, atom *a, atom *b, atom *c); 90 void Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent, int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint, atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol); 91 83 92 84 PointMap PointsOnBoundary; 93 85 LineMap LinesOnBoundary; 94 86 TriangleMap TrianglesOnBoundary; 95 class BoundaryPointSet *TPS[3]; //this is a Storage for pointers to triangle points, this and BPS[2] needed due to AddLine restrictions96 87 class BoundaryPointSet *BPS[2]; 97 88 class BoundaryLineSet *BLS[3]; … … 100 91 int LinesOnBoundaryCount; 101 92 int TrianglesOnBoundaryCount; 102 int TriangleFilesWritten;103 93 }; 104 94 … … 109 99 110 100 111 double VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot,config *configuration, Boundaries *BoundaryPoints, molecule *mol);101 double VolumeOfConvexEnvelope(ofstream *out, config *configuration, Boundaries *BoundaryPoints, molecule *mol); 112 102 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem); 113 103 void PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, double ClusterVolume, double celldensity); 114 void Find_non_convex_border(ofstream *out, ofstream *tecplot, molecule* mol, const char *tempbasename, const double RADIUS);115 void Find_next_suitable_point(atom a, atom b, atom Candidate, int n, Vector *d1, Vector *d2, atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule *mol, bool problem);116 104 117 105 -
Property mode
changed from
-
src/builder.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 1 1 /** \file builder.cpp 2 * 2 * 3 3 * By stating absolute positions or binding angles and distances atomic positions of a molecule can be constructed. 4 4 * The output is the complete configuration file for PCP for direct use. … … 6 6 * -# Atomic data is retrieved from a file, if not found requested and stored there for later re-use 7 7 * -# step-by-step construction of the molecule beginning either at a centre of with a certain atom 8 * 8 * 9 9 */ 10 10 11 11 /*! \mainpage Molecuilder - a molecular set builder 12 * 12 * 13 13 * This introductory shall briefly make aquainted with the program, helping in installing and a first run. 14 * 14 * 15 15 * \section about About the Program 16 * 16 * 17 17 * Molecuilder is a short program, written in C++, that enables the construction of a coordinate set for the 18 18 * atoms making up an molecule by the successive statement of binding angles and distances and referencing to 19 19 * already constructed atoms. 20 * 20 * 21 21 * A configuration file may be written that is compatible to the format used by PCP - a parallel Car-Parrinello 22 22 * molecular dynamics implementation. 23 * 23 * 24 24 * \section install Installation 25 * 25 * 26 26 * Installation should without problems succeed as follows: 27 27 * -# ./configure (or: mkdir build;mkdir run;cd build; ../configure --bindir=../run) 28 28 * -# make 29 29 * -# make install 30 * 30 * 31 31 * Further useful commands are 32 32 * -# make clean uninstall: deletes .o-files and removes executable from the given binary directory\n 33 * -# make doxygen-doc: Creates these html pages out of the documented source 34 * 33 * -# make doxygen-doc: Creates these html pages out of the documented source 34 * 35 35 * \section run Running 36 * 36 * 37 37 * The program can be executed by running: ./molecuilder 38 * 38 * 39 39 * Note, that it uses a database, called "elements.db", in the executable's directory. If the file is not found, 40 40 * it is created and any given data on elements of the periodic table will be stored therein and re-used on 41 * later re-execution. 42 * 41 * later re-execution. 42 * 43 43 * \section ref References 44 * 44 * 45 45 * For the special configuration file format, see the documentation of pcp. 46 * 46 * 47 47 */ 48 48 … … 80 80 cout << Verbose(0) << "INPUT: "; 81 81 cin >> choice; 82 82 83 83 switch (choice) { 84 84 case 'a': // absolute coordinates of atom … … 89 89 mol->AddAtom(first); // add to molecule 90 90 break; 91 91 92 92 case 'b': // relative coordinates of atom wrt to reference point 93 93 first = new atom; … … 105 105 mol->AddAtom(first); // add to molecule 106 106 break; 107 107 108 108 case 'c': // relative coordinates of atom wrt to already placed atom 109 109 first = new atom; … … 111 111 do { 112 112 if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl; 113 second = mol->AskAtom("Enter atom number: "); 113 second = mol->AskAtom("Enter atom number: "); 114 114 cout << Verbose(0) << "Enter relative coordinates." << endl; 115 115 first->x.AskPosition(mol->cell_size, false); … … 121 121 mol->AddAtom(first); // add to molecule 122 122 break; 123 123 124 124 case 'd': // two atoms, two angles and a distance 125 125 first = new atom; … … 152 152 x.Copyvector(&fourth->x); 153 153 x.SubtractVector(&third->x); 154 154 155 155 if (!z.SolveSystem(&x,&y,&n, b, c, a)) { 156 156 cout << Verbose(0) << "Failure solving self-dependent linear system!" << endl; … … 167 167 cout << "x: ", 168 168 x.Output((ofstream *)&cout); 169 cout << endl; 169 cout << endl; 170 170 z.MakeNormalVector(&second->x,&third->x,&fourth->x); 171 171 cout << "z: ", 172 172 z.Output((ofstream *)&cout); 173 cout << endl; 173 cout << endl; 174 174 y.MakeNormalVector(&x,&z); 175 175 cout << "y: ", 176 176 y.Output((ofstream *)&cout); 177 cout << endl; 178 177 cout << endl; 178 179 179 // rotate vector around first angle 180 180 first->x.CopyVector(&x); … … 182 182 cout << "Rotated vector: ", 183 183 first->x.Output((ofstream *)&cout); 184 cout << endl; 184 cout << endl; 185 185 // remove the projection onto the rotation plane of the second angle 186 186 n.CopyVector(&y); … … 188 188 cout << "N1: ", 189 189 n.Output((ofstream *)&cout); 190 cout << endl; 190 cout << endl; 191 191 first->x.SubtractVector(&n); 192 192 cout << "Subtracted vector: ", 193 193 first->x.Output((ofstream *)&cout); 194 cout << endl; 194 cout << endl; 195 195 n.CopyVector(&z); 196 196 n.Scale(first->x.Projection(&z)); 197 197 cout << "N2: ", 198 198 n.Output((ofstream *)&cout); 199 cout << endl; 199 cout << endl; 200 200 first->x.SubtractVector(&n); 201 201 cout << "2nd subtracted vector: ", 202 202 first->x.Output((ofstream *)&cout); 203 cout << endl; 204 203 cout << endl; 204 205 205 // rotate another vector around second angle 206 206 n.CopyVector(&y); … … 208 208 cout << "2nd Rotated vector: ", 209 209 n.Output((ofstream *)&cout); 210 cout << endl; 211 210 cout << endl; 211 212 212 // add the two linear independent vectors 213 213 first->x.AddVector(&n); 214 first->x.Normalize(); 214 first->x.Normalize(); 215 215 first->x.Scale(a); 216 216 first->x.AddVector(&second->x); 217 217 218 218 cout << Verbose(0) << "resulting coordinates: "; 219 219 first->x.Output((ofstream *)&cout); … … 241 241 } while ((j != -1) && (i<128)); 242 242 if (i >= 2) { 243 first->x.LSQdistance(atoms, i); 243 first->x.LSQdistance(atoms, i); 244 244 245 245 first->x.Output((ofstream *)&cout); … … 259 259 static void CenterAtoms(molecule *mol) 260 260 { 261 Vector x, y , helper;261 Vector x, y; 262 262 char choice; // menu choice char 263 263 264 264 cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl; 265 265 cout << Verbose(0) << " a - on origin" << endl; … … 271 271 cout << Verbose(0) << "INPUT: "; 272 272 cin >> choice; 273 273 274 274 switch (choice) { 275 275 default: … … 292 292 mol->CenterEdge((ofstream *)&cout, &x); // make every coordinate positive 293 293 mol->Translate(&y); // translate by boundary 294 helper.CopyVector(&y); 295 helper.Scale(2.); 296 helper.AddVector(&x); 297 mol->SetBoxDimension(&helper); // update Box of atoms by boundary 294 mol->SetBoxDimension(&(x+y*2)); // update Box of atoms by boundary 298 295 break; 299 296 case 'd': … … 330 327 cout << Verbose(0) << "INPUT: "; 331 328 cin >> choice; 332 329 333 330 switch (choice) { 334 331 default: … … 349 346 second = mol->AskAtom("Enter second atom: "); 350 347 351 n.CopyVector((const Vector *)&first->x); 352 n.SubtractVector((const Vector *)&second->x); 348 n.CopyVector((const Vector *)&first->x); 349 n.SubtractVector((const Vector *)&second->x); 353 350 n.Normalize(); 354 break; 351 break; 355 352 case 'd': 356 353 char shorthand[4]; … … 366 363 x.x[i] = gsl_vector_get(param.x,i); 367 364 n.x[i] = gsl_vector_get(param.x,i+NDIM); 368 } 365 } 369 366 gsl_vector_free(param.x); 370 367 cout << Verbose(0) << "Offset vector: "; … … 372 369 cout << Verbose(0) << endl; 373 370 n.Normalize(); 374 break; 371 break; 375 372 }; 376 373 cout << Verbose(0) << "Alignment vector: "; … … 388 385 Vector n; 389 386 char choice; // menu choice char 390 387 391 388 cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl; 392 389 cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl; … … 397 394 cout << Verbose(0) << "INPUT: "; 398 395 cin >> choice; 399 396 400 397 switch (choice) { 401 398 default: … … 416 413 second = mol->AskAtom("Enter second atom: "); 417 414 418 n.CopyVector((const Vector *)&first->x); 419 n.SubtractVector((const Vector *)&second->x); 415 n.CopyVector((const Vector *)&first->x); 416 n.SubtractVector((const Vector *)&second->x); 420 417 n.Normalize(); 421 break; 418 break; 422 419 }; 423 420 cout << Verbose(0) << "Normal vector: "; … … 436 433 double tmp1, tmp2; 437 434 char choice; // menu choice char 438 435 439 436 cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl; 440 437 cout << Verbose(0) << " a - state atom for removal by number" << endl; … … 445 442 cout << Verbose(0) << "INPUT: "; 446 443 cin >> choice; 447 444 448 445 switch (choice) { 449 446 default: … … 478 475 mol->RemoveAtom(first); 479 476 } 480 break; 477 break; 481 478 }; 482 479 //mol->Output((ofstream *)&cout); … … 495 492 int Z; 496 493 char choice; // menu choice char 497 494 498 495 cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl; 499 496 cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl; … … 517 514 for (int i=MAX_ELEMENTS;i--;) 518 515 min[i] = 0.; 519 520 second = mol->start; 516 517 second = mol->start; 521 518 while ((second->next != mol->end)) { 522 519 second = second->next; // advance … … 529 526 } 530 527 if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1; 531 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl; 528 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl; 532 529 } 533 530 for (int i=MAX_ELEMENTS;i--;) 534 531 if (min[i] != 0.) cout << Verbose(0) << "Minimum Bond length between " << first->type->name << " Atom " << first->nr << " and next Ion of type " << (periode->FindElement(i))->name << ": " << min[i] << " a.u." << endl; 535 532 break; 536 533 537 534 case 'b': 538 535 first = mol->AskAtom("Enter first atom: "); … … 559 556 y.SubtractVector((const Vector *)&second->x); 560 557 cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": "; 561 cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl; 558 cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl; 562 559 break; 563 560 case 'd': … … 572 569 case 'e': 573 570 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 574 VolumeOfConvexEnvelope((ofstream *)&cout, NULL,configuration, NULL, mol);571 VolumeOfConvexEnvelope((ofstream *)&cout, configuration, NULL, mol); 575 572 break; 576 573 case 'f': … … 603 600 int Order1; 604 601 clock_t start, end; 605 602 606 603 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl; 607 604 cout << Verbose(0) << "What's the desired bond order: "; … … 612 609 end = clock(); 613 610 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 614 } else 611 } else 615 612 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl; 616 613 }; … … 626 623 atom *Walker = mol->start; 627 624 int i, comp, counter=0; 628 625 629 626 // generate some KeySets 630 627 cout << "Generating KeySets." << endl; … … 640 637 cout << "Testing insertion of already present item in KeySets." << endl; 641 638 KeySetTestPair test; 642 test = TestSets[mol->AtomCount-1].insert(Walker->nr); 639 test = TestSets[mol->AtomCount-1].insert(Walker->nr); 643 640 if (test.second) { 644 641 cout << Verbose(1) << "Insertion worked?!" << endl; … … 649 646 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr); 650 647 651 // constructing Graph structure 648 // constructing Graph structure 652 649 cout << "Generating Subgraph class." << endl; 653 650 Graph Subgraphs; … … 660 657 cout << "Testing insertion of already present item in Subgraph." << endl; 661 658 GraphTestPair test2; 662 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.))); 659 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.))); 663 660 if (test2.second) { 664 661 cout << Verbose(1) << "Insertion worked?!" << endl; … … 666 663 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl; 667 664 } 668 665 669 666 // show graphs 670 667 cout << "Showing Subgraph's contents, checking that it's sorted." << endl; … … 677 674 if ((*key) > comp) 678 675 cout << (*key) << " "; 679 else 676 else 680 677 cout << (*key) << "! "; 681 678 comp = (*key); … … 697 694 char filename[MAXSTRINGSIZE]; 698 695 ofstream output; 699 string basis("3-21G");700 696 701 697 cout << Verbose(0) << "Storing configuration ... " << endl; … … 703 699 mol->CalculateOrbitals(*configuration); 704 700 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble; 705 strcpy(filename, ConfigFileName); 706 if (ConfigFileName != NULL) { // test the file name 701 if (ConfigFileName != NULL) { 707 702 output.open(ConfigFileName, ios::trunc); 708 703 } else if (strlen(configuration->configname) != 0) { 709 strcpy(filename, configuration->configname);710 704 output.open(configuration->configname, ios::trunc); 711 705 } else { 712 strcpy(filename, DEFAULTCONFIG);713 706 output.open(DEFAULTCONFIG, ios::trunc); 714 707 } 715 output.close();716 output.clear();717 708 cout << Verbose(0) << "Saving of config file "; 718 if (configuration->Save( filename, periode, mol))709 if (configuration->Save(&output, periode, mol)) 719 710 cout << "successful." << endl; 720 711 else 721 712 cout << "failed." << endl; 722 713 output.close(); 714 output.clear(); 715 723 716 // and save to xyz file 724 717 if (ConfigFileName != NULL) { … … 731 724 strcat(filename, ".xyz"); 732 725 output.open(filename, ios::trunc); 733 } 726 } 734 727 cout << Verbose(0) << "Saving of XYZ file "; 735 728 if (mol->MDSteps <= 1) { … … 746 739 output.close(); 747 740 output.clear(); 748 741 749 742 // and save as MPQC configuration 750 if (ConfigFileName != NULL) 743 if (ConfigFileName != NULL) { 751 744 strcpy(filename, ConfigFileName); 752 if (output == NULL) 745 strcat(filename, ".in"); 746 output.open(filename, ios::trunc); 747 } 748 if (output == NULL) { 753 749 strcpy(filename,"main_pcp_linux"); 750 strcat(filename, ".in"); 751 output.open(filename, ios::trunc); 752 } 754 753 cout << Verbose(0) << "Saving as mpqc input "; 755 if (configuration->SaveMPQC( filename, mol))754 if (configuration->SaveMPQC(&output, mol)) 756 755 cout << "done." << endl; 757 756 else 758 757 cout << "failed." << endl; 759 758 output.close(); 759 output.clear(); 760 760 761 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) { 761 762 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl; … … 789 790 int argptr; 790 791 PathToDatabases = LocalPath; 791 792 792 793 if (argc > 1) { // config file specified as option 793 794 // 1. : Parse options that just set variables or print help … … 802 803 case '?': 803 804 cout << "MoleCuilder suite" << endl << "==================" << endl << endl; 804 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl; 805 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl; 805 806 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl; 806 807 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl; 807 cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl;808 808 cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl; 809 cout << "\t-B <basis>\tgive gaussian basis for MPQC output." << endl;810 809 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl; 811 810 cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl; … … 818 817 cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl; 819 818 cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl; 820 cout << "\t-N\tGet non-convex-envelope." << endl; 821 cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl; 819 cout << "\t-o\tGet volume of the convex envelope (and store to tecplot file)." << endl; 822 820 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl; 823 821 cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl; … … 825 823 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl; 826 824 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl; 827 cout << "\t-T <file> Store temperatures from the config file in <file>." << endl; 825 cout << "\t-T <file> Store temperatures from the config file in <file>." << endl; 828 826 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl; 829 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl; 827 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl; 830 828 cout << "\t-v/-V\t\tGives version information." << endl; 831 829 cout << "Note: config files must not begin with '-' !" << endl; … … 843 841 break; 844 842 case 'e': 845 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 846 cerr << "Not enough or invalid arguments for specifying element db: -e <db file>" << endl; 847 } else { 848 cout << "Using " << argv[argptr] << " as elements database." << endl; 849 PathToDatabases = argv[argptr]; 850 argptr+=1; 851 } 843 cout << "Using " << argv[argptr] << " as elements database." << endl; 844 PathToDatabases = argv[argptr]; 845 argptr+=1; 852 846 break; 853 847 case 'n': … … 862 856 argptr++; 863 857 } while (argptr < argc); 864 858 865 859 // 2. Parse the element database 866 860 if (periode->LoadPeriodentafel(PathToDatabases)) { … … 871 865 return 1; 872 866 } 873 867 874 868 // 3. Find config file name and parse if possible 875 869 if (argv[1][0] != '-') { … … 910 904 } else 911 905 config_present = absent; 912 906 913 907 // 4. parse again through options, now for those depending on elements db and config presence 914 908 argptr = 1; … … 921 915 case 'p': 922 916 ExitFlag = 1; 923 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 924 ExitFlag = 255; 925 cerr << "Not enough arguments for parsing: -p <xyz file>" << endl; 926 } else { 927 SaveFlag = true; 928 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl; 929 if (!mol->AddXYZFile(argv[argptr])) 930 cout << Verbose(2) << "File not found." << endl; 931 else { 932 cout << Verbose(2) << "File found and parsed." << endl; 917 SaveFlag = true; 918 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl; 919 if (!mol->AddXYZFile(argv[argptr])) 920 cout << Verbose(2) << "File not found." << endl; 921 else { 922 cout << Verbose(2) << "File found and parsed." << endl; 923 config_present = present; 924 } 925 break; 926 case 'a': 927 ExitFlag = 1; 928 SaveFlag = true; 929 cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), "; 930 first = new atom; 931 first->type = periode->FindElement(atoi(argv[argptr])); 932 if (first->type != NULL) 933 cout << Verbose(2) << "found element " << first->type->name << endl; 934 for (int i=NDIM;i--;) 935 first->x.x[i] = atof(argv[argptr+1+i]); 936 if (first->type != NULL) { 937 mol->AddAtom(first); // add to molecule 938 if ((config_present == empty) && (mol->AtomCount != 0)) 933 939 config_present = present; 934 } 935 } 936 break; 937 case 'a': 938 ExitFlag = 1; 939 if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) { 940 ExitFlag = 255; 941 cerr << "Not enough or invalid arguments for adding atom: -a <element> <x> <y> <z>" << endl; 942 } else { 943 SaveFlag = true; 944 cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), "; 945 first = new atom; 946 first->type = periode->FindElement(atoi(argv[argptr])); 947 if (first->type != NULL) 948 cout << Verbose(2) << "found element " << first->type->name << endl; 949 for (int i=NDIM;i--;) 950 first->x.x[i] = atof(argv[argptr+1+i]); 951 if (first->type != NULL) { 952 mol->AddAtom(first); // add to molecule 953 if ((config_present == empty) && (mol->AtomCount != 0)) 954 config_present = present; 955 } else 956 cerr << Verbose(1) << "Could not find the specified element." << endl; 957 argptr+=4; 958 } 940 } else 941 cerr << Verbose(1) << "Could not find the specified element." << endl; 942 argptr+=4; 959 943 break; 960 944 default: // no match? Don't step on (this is done in next switch's default) … … 964 948 if (config_present == present) { 965 949 switch(argv[argptr-1][1]) { 966 case 'B': 967 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr][0] == '-')) { 968 ExitFlag = 255; 969 cerr << "Not enough or invalid arguments given for giving gaussian basis: -B <basis>" << endl; 970 } else { 971 cout << Verbose(1) << "Setting gaussian basis to " << argv[argptr] << "." << endl; 972 configuration.basis.copy(argv[argptr],strlen(argv[argptr])); 973 argptr+=1; 974 } 975 break; 976 case 'D': 950 case 'D': 977 951 ExitFlag = 1; 978 952 { … … 1005 979 delete[](MinimumRingSize); 1006 980 } 1007 //argptr+=1;981 argptr+=1; 1008 982 break; 1009 983 case 'E': 1010 984 ExitFlag = 1; 1011 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) { 1012 ExitFlag = 255; 1013 cerr << "Not enough or invalid arguments given for changing element: -E <atom nr.> <element>" << endl; 1014 } else { 1015 SaveFlag = true; 1016 cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl; 1017 first = mol->FindAtom(atoi(argv[argptr])); 1018 first->type = periode->FindElement(atoi(argv[argptr+1])); 1019 argptr+=2; 1020 } 1021 break; 1022 case 'A': 1023 ExitFlag = 1; 1024 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr][0] == '-')) { 1025 ExitFlag =255; 1026 cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl; 1027 } else { 1028 cout << "Parsing bonds from " << argv[argptr] << "." << endl; 1029 ifstream *input = new ifstream(argv[argptr]); 1030 mol->CreateAdjacencyList2((ofstream *)&cout, input); 1031 input->close(); 1032 } 1033 break; 1034 case 'N': 1035 ExitFlag = 1; 1036 if ((argptr+1 >= argc) || (argv[argptr+1][0] == '-')){ 1037 ExitFlag = 255; 1038 cerr << "Not enough or invalid arguments given for non-convex envelope: -o <radius> <tecplot output file>" << endl; 1039 } else { 1040 cout << Verbose(0) << "Evaluating npn-convex envelope."; 1041 string TempName(argv[argptr+1]); 1042 TempName.append(".r3d"); 1043 ofstream *output = new ofstream(TempName.c_str(), ios::trunc); 1044 cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl; 1045 Find_non_convex_border((ofstream *)&cout, output, mol, argv[argptr+1], atof(argv[argptr])); 1046 output->close(); 1047 delete(output); 1048 argptr+=2; 1049 } 1050 break; 985 SaveFlag = true; 986 cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl; 987 first = mol->FindAtom(atoi(argv[argptr])); 988 first->type = periode->FindElement(atoi(argv[argptr+1])); 989 argptr+=2; 990 break; 1051 991 case 'T': 1052 992 ExitFlag = 1; 1053 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1054 ExitFlag = 255; 1055 cerr << "Not enough or invalid arguments given for storing tempature: -T <temperature file>" << endl; 1056 } else { 993 { 1057 994 cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl; 1058 995 ofstream *output = new ofstream(argv[argptr], ios::trunc); … … 1063 1000 output->close(); 1064 1001 delete(output); 1065 argptr+=1;1066 1002 } 1003 argptr+=1; 1067 1004 break; 1068 1005 case 'L': … … 1078 1015 case 'P': 1079 1016 ExitFlag = 1; 1080 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1081 ExitFlag = 255; 1082 cerr << "Not enough or invalid arguments given for parsing and integrating forces: -P <forces file>" << endl; 1083 } else { 1084 SaveFlag = true; 1085 cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl; 1086 if (!mol->VerletForceIntegration((ofstream *)&cout, argv[argptr], configuration)) 1087 cout << Verbose(2) << "File not found." << endl; 1088 else 1089 cout << Verbose(2) << "File found and parsed." << endl; 1090 argptr+=1; 1017 SaveFlag = true; 1018 cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl; 1019 if (!mol->VerletForceIntegration((ofstream *)&cout, argv[argptr], configuration.Deltat, configuration.GetIsAngstroem(), configuration.DoConstrainedMD)) 1020 cout << Verbose(2) << "File not found." << endl; 1021 else { 1022 cout << Verbose(2) << "File found and parsed." << endl; 1023 if (configuration.DoConstrainedMD) 1024 // increase source step in expectancy of a new step in the config 1025 configuration.DoConstrainedMD++; 1091 1026 } 1027 argptr+=1; 1092 1028 break; 1093 1029 case 't': 1094 1030 ExitFlag = 1; 1095 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1096 ExitFlag = 255; 1097 cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl; 1098 } else { 1099 ExitFlag = 1; 1100 SaveFlag = true; 1101 cout << Verbose(1) << "Translating all ions to new origin." << endl; 1102 for (int i=NDIM;i--;) 1103 x.x[i] = atof(argv[argptr+i]); 1104 mol->Translate((const Vector *)&x); 1105 argptr+=3; 1031 SaveFlag = true; 1032 cout << Verbose(1) << "Translating all ions to new origin." << endl; 1033 for (int i=NDIM;i--;) 1034 x.x[i] = atof(argv[argptr+i]); 1035 mol->Translate((const Vector *)&x); 1036 argptr+=3; 1037 break; 1038 case 's': 1039 ExitFlag = 1; 1040 SaveFlag = true; 1041 j = -1; 1042 cout << Verbose(1) << "Scaling all ion positions by factor." << endl; 1043 factor = new double[NDIM]; 1044 factor[0] = atof(argv[argptr]); 1045 if (argc > argptr+1) 1046 argptr++; 1047 factor[1] = atof(argv[argptr]); 1048 if (argc > argptr+1) 1049 argptr++; 1050 factor[2] = atof(argv[argptr]); 1051 mol->Scale(&factor); 1052 for (int i=0;i<NDIM;i++) { 1053 j += i+1; 1054 x.x[i] = atof(argv[NDIM+i]); 1055 mol->cell_size[j]*=factor[i]; 1106 1056 } 1107 break; 1108 case 's': 1109 ExitFlag = 1; 1110 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) { 1111 ExitFlag = 255; 1112 cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl; 1113 } else { 1114 SaveFlag = true; 1115 j = -1; 1116 cout << Verbose(1) << "Scaling all ion positions by factor." << endl; 1117 factor = new double[NDIM]; 1118 factor[0] = atof(argv[argptr]); 1119 if ((argptr < argc) && (IsValidNumber(argv[argptr]))) 1120 argptr++; 1121 factor[1] = atof(argv[argptr]); 1122 if ((argptr < argc) && (IsValidNumber(argv[argptr]))) 1123 argptr++; 1124 factor[2] = atof(argv[argptr]); 1125 mol->Scale(&factor); 1126 for (int i=0;i<NDIM;i++) { 1127 j += i+1; 1128 x.x[i] = atof(argv[NDIM+i]); 1129 mol->cell_size[j]*=factor[i]; 1130 } 1131 delete[](factor); 1132 argptr+=1; 1057 delete[](factor); 1058 argptr+=1; 1059 break; 1060 case 'b': 1061 ExitFlag = 1; 1062 SaveFlag = true; 1063 j = -1; 1064 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl; 1065 j=-1; 1066 for (int i=0;i<NDIM;i++) { 1067 j += i+1; 1068 x.x[i] = atof(argv[argptr++]); 1069 mol->cell_size[j] += x.x[i]*2.; 1133 1070 } 1134 break;1135 case 'b':1136 ExitFlag = 1;1137 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {1138 ExitFlag = 255;1139 cerr << "Not enough or invalid arguments given for centering in box: -b <length_x> <length_y> <length_z>" << endl;1140 } else {1141 1142 1143 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;1144 j=-1;1145 for (int i=0;i<NDIM;i++) {1146 j += i+1;1147 x.x[i] = atof(argv[argptr++]);1148 mol->cell_size[j] += x.x[i]*2.;1149 }1150 // center1151 mol->CenterInBox((ofstream *)&cout, &x);1152 // update Box of atoms by boundary1153 mol-> SetBoxDimension(&x);1071 // center 1072 mol->CenterInBox((ofstream *)&cout, &x); 1073 // update Box of atoms by boundary 1074 mol->SetBoxDimension(&x); 1075 break; 1076 case 'c': 1077 ExitFlag = 1; 1078 SaveFlag = true; 1079 j = -1; 1080 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl; 1081 // make every coordinate positive 1082 mol->CenterEdge((ofstream *)&cout, &x); 1083 // update Box of atoms by boundary 1084 mol->SetBoxDimension(&x); 1085 // translate each coordinate by boundary 1086 j=-1; 1087 for (int i=0;i<NDIM;i++) { 1088 j += i+1; 1089 x.x[i] = atof(argv[argptr++]); 1090 mol->cell_size[j] += x.x[i]*2.; 1154 1091 } 1155 break; 1156 case 'c': 1157 ExitFlag = 1; 1158 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1159 ExitFlag = 255; 1160 cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl; 1161 } else { 1162 SaveFlag = true; 1163 j = -1; 1164 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl; 1165 // make every coordinate positive 1166 mol->CenterEdge((ofstream *)&cout, &x); 1167 // update Box of atoms by boundary 1168 mol->SetBoxDimension(&x); 1169 // translate each coordinate by boundary 1170 j=-1; 1171 for (int i=0;i<NDIM;i++) { 1172 j += i+1; 1173 x.x[i] = atof(argv[argptr++]); 1174 mol->cell_size[j] += x.x[i]*2.; 1175 } 1176 mol->Translate((const Vector *)&x); 1177 } 1092 mol->Translate((const Vector *)&x); 1178 1093 break; 1179 1094 case 'O': … … 1192 1107 case 'f': 1193 1108 ExitFlag = 1; 1194 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) { 1195 ExitFlag = 255; 1196 cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl; 1197 } else { 1198 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl; 1109 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl; 1110 if (argc >= argptr+2) { 1199 1111 cout << Verbose(0) << "Creating connection matrix..." << endl; 1200 1112 start = clock(); … … 1206 1118 end = clock(); 1207 1119 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 1208 argptr+=2; 1120 argptr+=1; 1121 } else { 1122 cerr << "Not enough arguments for fragmentation: -f <max. bond distance> <bond order>" << endl; 1209 1123 } 1210 1124 break; … … 1225 1139 case 'o': 1226 1140 ExitFlag = 1; 1227 if ((argptr >= argc) || (argv[argptr][0] == '-')){ 1228 ExitFlag = 255; 1229 cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl; 1230 } else { 1231 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 1232 ofstream *output = new ofstream(argv[argptr], ios::trunc); 1233 //$$$ 1234 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl; 1235 VolumeOfConvexEnvelope((ofstream *)&cout, output, &configuration, NULL, mol); 1236 output->close(); 1237 delete(output); 1238 argptr+=1; 1239 } 1141 SaveFlag = true; 1142 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 1143 VolumeOfConvexEnvelope((ofstream *)&cout, &configuration, NULL, mol); 1240 1144 break; 1241 1145 case 'U': 1242 1146 ExitFlag = 1; 1243 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) { 1244 ExitFlag = 255; 1245 cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl; 1246 volume = -1; // for case 'u': don't print error again 1247 } else { 1248 volume = atof(argv[argptr++]); 1249 cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl; 1250 } 1147 volume = atof(argv[argptr++]); 1148 cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl; 1251 1149 case 'u': 1252 1150 ExitFlag = 1; 1253 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) { 1254 if (volume != -1) 1255 ExitFlag = 255; 1256 cerr << "Not enough arguments given for suspension: -u <density>" << endl; 1257 } else { 1151 { 1258 1152 double density; 1259 1153 SaveFlag = true; … … 1270 1164 // repetition[i] = 1; 1271 1165 // } 1272 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density); // if volume == 0, will calculate from ConvexEnvelope1166 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density); 1273 1167 } 1274 1168 break; 1275 1169 case 'd': 1276 1170 ExitFlag = 1; 1277 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1278 ExitFlag = 255; 1279 cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl; 1280 } else { 1281 SaveFlag = true; 1282 for (int axis = 1; axis <= NDIM; axis++) { 1283 int faktor = atoi(argv[argptr++]); 1284 int count; 1285 element ** Elements; 1286 Vector ** vectors; 1287 if (faktor < 1) { 1288 cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl; 1289 faktor = 1; 1171 SaveFlag = true; 1172 for (int axis = 1; axis <= NDIM; axis++) { 1173 int faktor = atoi(argv[argptr++]); 1174 int count; 1175 element ** Elements; 1176 Vector ** vectors; 1177 if (faktor < 1) { 1178 cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl; 1179 faktor = 1; 1180 } 1181 mol->CountAtoms((ofstream *)&cout); // recount atoms 1182 if (mol->AtomCount != 0) { // if there is more than none 1183 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand 1184 Elements = new element *[count]; 1185 vectors = new Vector *[count]; 1186 j = 0; 1187 first = mol->start; 1188 while (first->next != mol->end) { // make a list of all atoms with coordinates and element 1189 first = first->next; 1190 Elements[j] = first->type; 1191 vectors[j] = &first->x; 1192 j++; 1290 1193 } 1291 mol->CountAtoms((ofstream *)&cout); // recount atoms 1292 if (mol->AtomCount != 0) { // if there is more than none 1293 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand 1294 Elements = new element *[count]; 1295 vectors = new Vector *[count]; 1296 j = 0; 1297 first = mol->start; 1298 while (first->next != mol->end) { // make a list of all atoms with coordinates and element 1299 first = first->next; 1300 Elements[j] = first->type; 1301 vectors[j] = &first->x; 1302 j++; 1194 if (count != j) 1195 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl; 1196 x.Zero(); 1197 y.Zero(); 1198 y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude 1199 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times 1200 x.AddVector(&y); // per factor one cell width further 1201 for (int k=count;k--;) { // go through every atom of the original cell 1202 first = new atom(); // create a new body 1203 first->x.CopyVector(vectors[k]); // use coordinate of original atom 1204 first->x.AddVector(&x); // translate the coordinates 1205 first->type = Elements[k]; // insert original element 1206 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...) 1303 1207 } 1304 if (count != j) 1305 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl; 1208 } 1209 // free memory 1210 delete[](Elements); 1211 delete[](vectors); 1212 // correct cell size 1213 if (axis < 0) { // if sign was negative, we have to translate everything 1306 1214 x.Zero(); 1307 y.Zero(); 1308 y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude 1309 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times 1310 x.AddVector(&y); // per factor one cell width further 1311 for (int k=count;k--;) { // go through every atom of the original cell 1312 first = new atom(); // create a new body 1313 first->x.CopyVector(vectors[k]); // use coordinate of original atom 1314 first->x.AddVector(&x); // translate the coordinates 1315 first->type = Elements[k]; // insert original element 1316 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...) 1317 } 1318 } 1319 // free memory 1320 delete[](Elements); 1321 delete[](vectors); 1322 // correct cell size 1323 if (axis < 0) { // if sign was negative, we have to translate everything 1324 x.Zero(); 1325 x.AddVector(&y); 1326 x.Scale(-(faktor-1)); 1327 mol->Translate(&x); 1328 } 1329 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1215 x.AddVector(&y); 1216 x.Scale(-(faktor-1)); 1217 mol->Translate(&x); 1330 1218 } 1219 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1331 1220 } 1332 1221 } … … 1390 1279 if (j == 1) return 0; // just for -v and -h options 1391 1280 if (j) return j; // something went wrong 1392 1281 1393 1282 // General stuff 1394 1283 if (mol->cell_size[0] == 0.) { … … 1404 1293 // now the main construction loop 1405 1294 cout << Verbose(0) << endl << "Now comes the real construction..." << endl; 1406 do { 1295 do { 1407 1296 cout << Verbose(0) << endl << endl; 1408 1297 cout << Verbose(0) << "============Element list=======================" << endl; … … 1423 1312 cout << Verbose(0) << "-----------------------------------------------" << endl; 1424 1313 cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl; 1425 cout << Verbose(0) << "i - realign molecule" << endl; 1426 cout << Verbose(0) << "m - mirror all molecules" << endl; 1314 cout << Verbose(0) << "i - realign molecule" << endl; 1315 cout << Verbose(0) << "m - mirror all molecules" << endl; 1427 1316 cout << Verbose(0) << "t - translate molecule by vector" << endl; 1428 1317 cout << Verbose(0) << "c - scale by unit transformation" << endl; … … 1435 1324 cout << Verbose(0) << "Input: "; 1436 1325 cin >> choice; 1437 1326 1438 1327 switch (choice) { 1439 1328 default: 1440 1329 case 'a': // add atom 1441 1330 AddAtoms(periode, mol); 1442 choice = 'a'; 1443 break; 1444 1331 choice = 'a'; 1332 break; 1333 1445 1334 case 'b': // scale a bond 1446 1335 cout << Verbose(0) << "Scaling bond length between two atoms." << endl; … … 1458 1347 } 1459 1348 //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: "; 1460 //second->Output(second->type->No, 1, (ofstream *)&cout); 1461 break; 1462 1463 case 'c': // unit scaling of the metric 1349 //second->Output(second->type->No, 1, (ofstream *)&cout); 1350 break; 1351 1352 case 'c': // unit scaling of the metric 1464 1353 cout << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl; 1465 1354 cout << Verbose(0) << "Enter three factors: "; … … 1472 1361 delete[](factor); 1473 1362 break; 1474 1363 1475 1364 case 'd': // duplicate the periodic cell along a given axis, given times 1476 1365 cout << Verbose(0) << "State the axis [(+-)123]: "; … … 1478 1367 cout << Verbose(0) << "State the factor: "; 1479 1368 cin >> faktor; 1480 1369 1481 1370 mol->CountAtoms((ofstream *)&cout); // recount atoms 1482 1371 if (mol->AtomCount != 0) { // if there is more than none … … 1519 1408 mol->Translate(&x); 1520 1409 } 1521 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1410 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1522 1411 } 1523 1412 break; 1524 1413 1525 1414 case 'e': // edit each field of the configuration 1526 1415 configuration.Edit(mol); 1527 1416 break; 1528 1417 1529 1418 case 'f': 1530 1419 FragmentAtoms(mol, &configuration); 1531 1420 break; 1532 1421 1533 1422 case 'g': // center the atoms 1534 1423 CenterAtoms(mol); 1535 1424 break; 1536 1537 case 'i': // align all atoms 1425 1426 case 'i': // align all atoms 1538 1427 AlignAtoms(periode, mol); 1539 1428 break; … … 1546 1435 MirrorAtoms(mol); 1547 1436 break; 1548 1437 1549 1438 case 'o': // create the connection matrix 1550 1439 { … … 1567 1456 } 1568 1457 break; 1569 1458 1570 1459 case 'p': // parse and XYZ file 1571 1460 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl; … … 1576 1465 break; 1577 1466 1578 case 'q': // quit 1579 break; 1580 1467 case 'q': // quit 1468 break; 1469 1581 1470 case 'r': // remove atom 1582 RemoveAtoms(mol); 1583 break; 1584 1471 RemoveAtoms(mol); 1472 break; 1473 1585 1474 case 's': // save to config file 1586 1475 SaveConfig(ConfigFileName, &configuration, periode, mol); … … 1588 1477 1589 1478 case 't': // translate all atoms 1590 cout << Verbose(0) << "Enter translation vector." << endl; 1479 cout << Verbose(0) << "Enter translation vector." << endl; 1591 1480 x.AskPosition(mol->cell_size,0); 1592 1481 mol->Translate((const Vector *)&x); 1593 1482 break; 1594 1483 1595 1484 case 'T': 1596 1485 testroutine(mol); 1597 1486 break; 1598 1487 1599 1488 case 'u': // change an atom's element 1600 1489 first = NULL; … … 1603 1492 cin >> Z; 1604 1493 } while ((first = mol->FindAtom(Z)) == NULL); 1605 cout << Verbose(0) << "New element by atomic number Z: "; 1494 cout << Verbose(0) << "New element by atomic number Z: "; 1606 1495 cin >> Z; 1607 1496 first->type = periode->FindElement(Z); 1608 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl; 1497 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl; 1609 1498 break; 1610 1499 }; 1611 1500 } while (choice != 'q'); 1612 1501 1613 1502 // save element data base 1614 1503 if (periode->StorePeriodentafel(ElementsFileName)) //ElementsFileName -
Property mode
changed from
-
src/config.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 18 18 configpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname"); 19 19 configname = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname"); 20 ThermostatImplemented = (int *) Malloc((MaxThermostats)*(sizeof(int)), "IonsInitRead: *ThermostatImplemented");21 ThermostatNames = (char **) Malloc((MaxThermostats)*(sizeof(char *)), "IonsInitRead: *ThermostatNames");22 for (int j=0;j<MaxThermostats;j++)23 ThermostatNames[j] = (char *) MallocString(12*(sizeof(char)), "IonsInitRead: ThermostatNames[]");24 Thermostat = 4;25 alpha = 0.;26 ScaleTempStep = 25;27 TempFrequency = 2.5;28 20 strcpy(mainname,"pcp"); 29 21 strcpy(defaultpath,"not specified"); … … 31 23 configpath[0]='\0'; 32 24 configname[0]='\0'; 33 basis="3-21G"; 34 35 36 strcpy(ThermostatNames[0],"None"); 37 ThermostatImplemented[0] = 1; 38 strcpy(ThermostatNames[1],"Woodcock"); 39 ThermostatImplemented[1] = 1; 40 strcpy(ThermostatNames[2],"Gaussian"); 41 ThermostatImplemented[2] = 1; 42 strcpy(ThermostatNames[3],"Langevin"); 43 ThermostatImplemented[3] = 1; 44 strcpy(ThermostatNames[4],"Berendsen"); 45 ThermostatImplemented[4] = 1; 46 strcpy(ThermostatNames[5],"NoseHoover"); 47 ThermostatImplemented[5] = 1; 48 25 49 26 FastParsing = false; 50 27 ProcPEGamma=8; … … 65 42 UseAddGramSch=1; 66 43 Seed=1; 44 67 45 MaxOuterStep=0; 68 Deltat= 0.01;46 Deltat=1; 69 47 OutVisStep=10; 70 48 OutSrcStep=5; … … 118 96 Free((void **)&configname, "config::~config: *configname"); 119 97 }; 120 121 /** Readin of Thermostat related values from parameter file.122 * \param *source parameter file123 */124 void config::InitThermostats(ifstream *source)125 {126 char *thermo = MallocString(12, "IonsInitRead: thermo");127 int verbose = 0;128 129 // read desired Thermostat from file along with needed additional parameters130 if (ParseForParameter(verbose,source,"Thermostat", 0, 1, 1, string_type, thermo, 1, optional)) {131 if (strcmp(thermo, ThermostatNames[0]) == 0) { // None132 if (ThermostatImplemented[0] == 1) {133 Thermostat = None;134 } else {135 cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl;136 Thermostat = None;137 }138 } else if (strcmp(thermo, ThermostatNames[1]) == 0) { // Woodcock139 if (ThermostatImplemented[1] == 1) {140 Thermostat = Woodcock;141 ParseForParameter(verbose,source,"Thermostat", 0, 2, 1, int_type, &ScaleTempStep, 1, critical); // read scaling frequency142 } else {143 cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl;144 Thermostat = None;145 }146 } else if (strcmp(thermo, ThermostatNames[2]) == 0) { // Gaussian147 if (ThermostatImplemented[2] == 1) {148 Thermostat = Gaussian;149 ParseForParameter(verbose,source,"Thermostat", 0, 2, 1, int_type, &ScaleTempStep, 1, critical); // read collision rate150 } else {151 cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl;152 Thermostat = None;153 }154 } else if (strcmp(thermo, ThermostatNames[3]) == 0) { // Langevin155 if (ThermostatImplemented[3] == 1) {156 Thermostat = Langevin;157 ParseForParameter(verbose,source,"Thermostat", 0, 2, 1, double_type, &TempFrequency, 1, critical); // read gamma158 if (ParseForParameter(verbose,source,"Thermostat", 0, 3, 1, double_type, &alpha, 1, optional)) {159 cout << Verbose(2) << "Extended Stochastic Thermostat detected with interpolation coefficient " << alpha << "." << endl;160 } else {161 alpha = 1.;162 }163 } else {164 cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl;165 Thermostat = None;166 }167 } else if (strcmp(thermo, ThermostatNames[4]) == 0) { // Berendsen168 if (ThermostatImplemented[4] == 1) {169 Thermostat = Berendsen;170 ParseForParameter(verbose,source,"Thermostat", 0, 2, 1, double_type, &TempFrequency, 1, critical); // read \tau_T171 } else {172 cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl;173 Thermostat = None;174 }175 } else if (strcmp(thermo, ThermostatNames[5]) == 0) { // Nose-Hoover176 if (ThermostatImplemented[5] == 1) {177 Thermostat = NoseHoover;178 ParseForParameter(verbose,source,"Thermostat", 0, 2, 1, double_type, &HooverMass, 1, critical); // read Hoovermass179 alpha = 0.;180 } else {181 cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl;182 Thermostat = None;183 }184 } else {185 cout << Verbose(1) << " Warning: thermostat name was not understood!" << endl;186 Thermostat = None;187 }188 } else {189 if ((MaxOuterStep > 0) && (TargetTemp != 0))190 cout << Verbose(2) << "No thermostat chosen despite finite temperature MD, falling back to None." << endl;191 Thermostat = None;192 }193 Free((void **)&thermo, "InitThermostats: thermo");194 };195 196 98 197 99 /** Displays menu for editing each entry of the config file. … … 563 465 double value[3]; 564 466 565 InitThermostats(file);566 567 467 /* Namen einlesen */ 568 468 … … 1075 975 1076 976 /** Stores all elements of config structure from which they can be re-read. 1077 * \param *filename name of file977 * \param output open output *file stream to write to 1078 978 * \param *periode pointer to a periodentafel class with all elements 1079 979 * \param *mol pointer to molecule containing all atoms of the molecule 1080 980 */ 1081 bool config::Save( const char *filename, periodentafel *periode, molecule *mol) const981 bool config::Save(ofstream *output, periodentafel *periode, molecule *mol) const 1082 982 { 1083 983 bool result = true; 1084 984 // bring MaxTypes up to date 1085 985 mol->CountElements(); 1086 ofstream *output = NULL;1087 output = new ofstream(filename, ios::out);1088 986 if (output != NULL) { 1089 987 *output << "# ParallelCarParinello - main configuration file - created with molecuilder" << endl; … … 1103 1001 *output << "DoFullCurrent\t" << config::DoFullCurrent << "\t# Do full perturbation" << endl; 1104 1002 *output << "DoConstrainedMD\t" << config::DoConstrainedMD << "\t# Do perform a constrained (>0, relating to current MD step) instead of unconstrained (0) MD" << endl; 1105 *output << "Thermostat\t" << ThermostatNames[Thermostat] << "\t";1106 switch(Thermostat) {1107 default:1108 case None:1109 break;1110 case Woodcock:1111 *output << ScaleTempStep;1112 break;1113 case Gaussian:1114 *output << ScaleTempStep;1115 break;1116 case Langevin:1117 *output << TempFrequency << "\t" << alpha;1118 break;1119 case Berendsen:1120 *output << TempFrequency;1121 break;1122 case NoseHoover:1123 *output << HooverMass;1124 break;1125 };1126 *output << "\t# Which Thermostat and its parameters to use in MD case." << endl;1127 1003 *output << "CommonWannier\t" << config::CommonWannier << "\t# Put virtual centers at indivual orbits, all common, merged by variance, to grid point, to cell center" << endl; 1128 1004 *output << "SawtoothStart\t" << config::SawtoothStart << "\t# Absolute value for smooth transition at cell border " << endl; … … 1196 1072 else 1197 1073 result = result && mol->OutputTrajectories(output); 1198 output->close();1199 output->clear();1200 delete(output);1201 1074 return result; 1202 1075 } else … … 1206 1079 /** Stores all elements in a MPQC input file. 1207 1080 * Note that this format cannot be parsed again. 1208 * \param *filename name of file (without ".in" suffix!)1081 * \param output open output *file stream to write to 1209 1082 * \param *mol pointer to molecule containing all atoms of the molecule 1210 1083 */ 1211 bool config::SaveMPQC( const char *filename, molecule *mol) const1084 bool config::SaveMPQC(ofstream *output, molecule *mol) const 1212 1085 { 1213 1086 int ElementNo = 0; 1214 1087 int AtomNo; 1215 1088 atom *Walker = NULL; 1216 element *runner = NULL;1089 element *runner = mol->elemente->start; 1217 1090 Vector *center = NULL; 1218 ofstream *output = NULL; 1219 stringstream *fname = NULL; 1220 1221 // first without hessian 1222 fname = new stringstream; 1223 *fname << filename << ".in"; 1224 output = new ofstream(fname->str().c_str(), ios::out); 1091 1225 1092 *output << "% Created by MoleCuilder" << endl; 1226 1093 *output << "mpqc: (" << endl; … … 1228 1095 *output << "\tdo_gradient = yes" << endl; 1229 1096 *output << "\tmole<CLHF>: (" << endl; 1230 *output << "\t\tmaxiter = 200" << endl; 1231 *output << "\t\tbasis = $:basis" << endl; 1232 *output << "\t\tmolecule = $:molecule" << endl; 1233 *output << "\t)" << endl; 1234 *output << ")" << endl; 1235 *output << "molecule<Molecule>: (" << endl; 1236 *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl; 1237 *output << "\t{ atoms geometry } = {" << endl; 1097 *output << "\t\tmolecule<Molecule>: (" << endl; 1098 *output << "\t\t\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl; 1099 *output << "\t\t\t{ atoms geometry } = {" << endl; 1238 1100 center = mol->DetermineCenterOfAll(output); 1239 1101 // output of atoms 1240 runner = mol->elemente->start;1241 1102 while (runner->next != mol->elemente->end) { // go through every element 1242 1103 runner = runner->next; … … 1249 1110 if (Walker->type == runner) { // if this atom fits to element 1250 1111 AtomNo++; 1251 *output << "\t\t " << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl;1112 *output << "\t\t\t\t" << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl; 1252 1113 } 1253 1114 } … … 1255 1116 } 1256 1117 delete(center); 1257 *output << "\t}" << endl; 1258 *output << ")" << endl; 1259 *output << "basis<GaussianBasisSet>: (" << endl; 1260 *output << "\tname = \"" << basis << "\"" << endl; 1261 *output << "\tmolecule = $:molecule" << endl; 1262 *output << ")" << endl; 1263 output->close(); 1264 delete(output); 1265 delete(fname); 1266 1267 // second with hessian 1268 fname = new stringstream; 1269 *fname << filename << ".hess.in"; 1270 output = new ofstream(fname->str().c_str(), ios::out); 1271 *output << "% Created by MoleCuilder" << endl; 1272 *output << "mpqc: (" << endl; 1273 *output << "\tsavestate = no" << endl; 1274 *output << "\tdo_gradient = yes" << endl; 1275 *output << "\tmole<CLHF>: (" << endl; 1276 *output << "\t\tmaxiter = 200" << endl; 1277 *output << "\t\tbasis = $:basis" << endl; 1278 *output << "\t\tmolecule = $:molecule" << endl; 1279 *output << "\t)" << endl; 1280 *output << "\tfreq<MolecularFrequencies>: (" << endl; 1281 *output << "\t\tmolecule=$:molecule" << endl; 1118 *output << "\t\t\t}" << endl; 1119 *output << "\t\t)" << endl; 1120 *output << "\t\tbasis<GaussianBasisSet>: (" << endl; 1121 *output << "\t\t\tname = \"STO-3G\"" << endl; 1122 *output << "\t\t\tmolecule = $:mpqc:mole:molecule" << endl; 1123 *output << "\t\t)" << endl; 1282 1124 *output << "\t)" << endl; 1283 1125 *output << ")" << endl; 1284 *output << "molecule<Molecule>: (" << endl;1285 *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl;1286 *output << "\t{ atoms geometry } = {" << endl;1287 center = mol->DetermineCenterOfAll(output);1288 // output of atoms1289 runner = mol->elemente->start;1290 while (runner->next != mol->elemente->end) { // go through every element1291 runner = runner->next;1292 if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms1293 ElementNo++;1294 AtomNo = 0;1295 Walker = mol->start;1296 while (Walker->next != mol->end) { // go through every atom of this element1297 Walker = Walker->next;1298 if (Walker->type == runner) { // if this atom fits to element1299 AtomNo++;1300 *output << "\t\t" << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl;1301 }1302 }1303 }1304 }1305 delete(center);1306 *output << "\t}" << endl;1307 *output << ")" << endl;1308 *output << "basis<GaussianBasisSet>: (" << endl;1309 *output << "\tname = \"3-21G\"" << endl;1310 *output << "\tmolecule = $:molecule" << endl;1311 *output << ")" << endl;1312 output->close();1313 delete(output);1314 delete(fname);1315 1316 1126 return true; 1317 1127 }; -
Property mode
changed from
-
src/datacreator.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 29 29 }; 30 30 31 /** Opens a file for appending with \a *filename in \a *dir.32 * \param output file handle on return33 * \param *dir directory34 * \param *filename name of file35 * \return true if file has been opened36 */37 bool AppendOutputFile(ofstream &output, const char *dir, const char *filename)38 {39 stringstream name;40 name << dir << "/" << filename;41 output.open(name.str().c_str(), ios::app);42 if (output == NULL) {43 cout << "Unable to open " << name.str() << " for writing, is directory correct?" << endl;44 return false;45 }46 return true;47 };48 49 31 /** Plots an energy vs. order. 50 32 * \param &Fragments EnergyMatrix class containing matrix values … … 63 45 cout << msg << endl; 64 46 output << "# " << msg << ", created on " << datum; 65 output << "#Order\tFrag.No.\t" << Fragments.Header [Fragments.MatrixCounter]<< endl;47 output << "#Order\tFrag.No.\t" << Fragments.Header << endl; 66 48 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 67 49 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) { 68 50 for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;) 69 for(int k=Fragments.ColumnCounter [ KeySet.OrderSet[BondOrder][i] ];k--;)51 for(int k=Fragments.ColumnCounter;k--;) 70 52 Fragments.Matrix[Fragments.MatrixCounter][j][k] += Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 71 53 } 72 54 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 73 for (int l=0;l<Fragments.ColumnCounter [Fragments.MatrixCounter];l++)55 for (int l=0;l<Fragments.ColumnCounter;l++) 74 56 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l]; 75 57 output << endl; … … 96 78 cout << msg << endl; 97 79 output << "# " << msg << ", created on " << datum; 98 output << "#Order\tFrag.No.\t" << Fragments.Header [Fragments.MatrixCounter]<< endl;80 output << "#Order\tFrag.No.\t" << Fragments.Header << endl; 99 81 Fragments.SetLastMatrix(Energy.Matrix[Energy.MatrixCounter],0); 100 82 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 101 83 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) { 102 84 for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;) 103 for(int k=Fragments.ColumnCounter [ KeySet.OrderSet[BondOrder][i] ];k--;)85 for(int k=Fragments.ColumnCounter;k--;) 104 86 Fragments.Matrix[Fragments.MatrixCounter][j][k] -= Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 105 87 } 106 88 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 107 for (int l=0;l<Fragments.ColumnCounter [Energy.MatrixCounter];l++)89 for (int l=0;l<Fragments.ColumnCounter;l++) 108 90 if (fabs(Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]) < MYEPSILON) 109 91 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l]; … … 133 115 cout << msg << endl; 134 116 output << "# " << msg << ", created on " << datum; 135 output << "# Order\tFrag.No.\t" << Fragments.Header [Fragments.MatrixCounter]<< endl;117 output << "# Order\tFrag.No.\t" << Fragments.Header << endl; 136 118 Fragments.SetLastMatrix(0.,0); 137 119 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { … … 139 121 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 140 122 CreateForce(Fragments, Fragments.MatrixCounter); 141 for (int l=0;l<Fragments.ColumnCounter [Fragments.MatrixCounter];l++)123 for (int l=0;l<Fragments.ColumnCounter;l++) 142 124 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l]; 143 125 output << endl; … … 165 147 cout << msg << endl; 166 148 output << "# " << msg << ", created on " << datum; 167 output << "# Order\tFrag.No.\t" << Fragments.Header [Fragments.MatrixCounter]<< endl;149 output << "# Order\tFrag.No.\t" << Fragments.Header << endl; 168 150 Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter],0); 169 151 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { … … 171 153 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 172 154 CreateForce(Fragments, Fragments.MatrixCounter); 173 for (int l=0;l<Fragments.ColumnCounter [Fragments.MatrixCounter];l++)155 for (int l=0;l<Fragments.ColumnCounter;l++) 174 156 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l]; 175 157 output << endl; … … 198 180 cout << msg << endl; 199 181 output << "# " << msg << ", created on " << datum; 200 output << "# AtomNo\t" << Fragments.Header [Fragments.MatrixCounter]<< endl;182 output << "# AtomNo\t" << Fragments.Header << endl; 201 183 Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter], 0); 202 184 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { … … 204 186 Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.); 205 187 // errors per atom 206 output << endl <<"#Order\t" << BondOrder+1 << endl;188 output << "#Order\t" << BondOrder+1 << endl; 207 189 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 208 190 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t"; 209 for (int l=0;l<Fragments.ColumnCounter [ Fragments.MatrixCounter ];l++) {191 for (int l=0;l<Fragments.ColumnCounter;l++) { 210 192 if (((l+1) % 3) == 0) { 211 193 norm = 0.; … … 244 226 cout << msg << endl; 245 227 output << "# " << msg << ", created on " << datum; 246 output << "# AtomNo\t" << Fragments.Header [Fragments.MatrixCounter]<< endl;228 output << "# AtomNo\t" << Fragments.Header << endl; 247 229 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 248 230 //cout << "Current order is " << BondOrder << "." << endl; 249 231 Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.); 250 232 // errors per atom 251 output << endl <<"#Order\t" << BondOrder+1 << endl;233 output << "#Order\t" << BondOrder+1 << endl; 252 234 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 253 235 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t"; 254 for (int l=0;l<Fragments.ColumnCounter [ Fragments.MatrixCounter ];l++)236 for (int l=0;l<Fragments.ColumnCounter;l++) 255 237 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t"; 256 238 output << endl; … … 262 244 }; 263 245 264 265 /** Plot hessian error vs. vs atom vs. order.266 * \param &Hessian HessianMatrix containing reference values (in MatrixCounter matrix)267 * \param &Fragments HessianMatrix class containing matrix values268 * \param KeySet KeySetContainer class holding bond KeySetContainer::Order269 * \param *prefix prefix in filename (without ending)270 * \param *msg message to be place in first line as a comment271 * \param *datum current date and time272 * \return true if file was written successfully273 */274 bool CreateDataDeltaHessianOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)275 {276 stringstream filename;277 ofstream output;278 279 filename << prefix << ".dat";280 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;281 cout << msg << endl;282 output << "# " << msg << ", created on " << datum;283 output << "# AtomNo\t" << Fragments.Header[Fragments.MatrixCounter] << endl;284 Fragments.SetLastMatrix(Hessian.Matrix[Hessian.MatrixCounter], 0);285 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {286 //cout << "Current order is " << BondOrder << "." << endl;287 Fragments.SumSubHessians(Fragments, KeySet, BondOrder, -1.);288 // errors per atom289 output << endl << "#Order\t" << BondOrder+1 << endl;290 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {291 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";292 for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++) {293 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";294 }295 output << endl;296 }297 output << endl;298 }299 output.close();300 return true;301 };302 303 /** Plot hessian error vs. vs atom vs. order in the frobenius norm.304 * \param &Hessian HessianMatrix containing reference values (in MatrixCounter matrix)305 * \param &Fragments HessianMatrix class containing matrix values306 * \param KeySet KeySetContainer class holding bond KeySetContainer::Order307 * \param *prefix prefix in filename (without ending)308 * \param *msg message to be place in first line as a comment309 * \param *datum current date and time310 * \return true if file was written successfully311 */312 bool CreateDataDeltaFrobeniusOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)313 {314 stringstream filename;315 ofstream output;316 double norm = 0;317 double tmp;318 319 filename << prefix << ".dat";320 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;321 cout << msg << endl;322 output << "# " << msg << ", created on " << datum;323 output << "# AtomNo\t";324 Fragments.SetLastMatrix(Hessian.Matrix[Hessian.MatrixCounter], 0);325 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {326 output << "Order" << BondOrder+1 << "\t";327 }328 output << endl;329 output << Fragments.RowCounter[ Fragments.MatrixCounter ] << "\t";330 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {331 //cout << "Current order is " << BondOrder << "." << endl;332 Fragments.SumSubHessians(Fragments, KeySet, BondOrder, -1.);333 // frobenius norm of errors per atom334 norm = 0.;335 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {336 for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++) {337 tmp = Fragments.Matrix[Fragments.MatrixCounter][ j ][l];338 norm += tmp*tmp;339 }340 }341 output << scientific << sqrt(norm)/(Fragments.RowCounter[ Fragments.MatrixCounter ]*Fragments.ColumnCounter[ Fragments.MatrixCounter] ) << "\t";342 }343 output << endl;344 output.close();345 return true;346 };347 348 /** Plot hessian error vs. vs atom vs. order.349 * \param &Fragments HessianMatrix class containing matrix values350 * \param KeySet KeySetContainer class holding bond KeySetContainer::Order351 * \param *prefix prefix in filename (without ending)352 * \param *msg message to be place in first line as a comment353 * \param *datum current date and time354 * \return true if file was written successfully355 */356 bool CreateDataHessianOrderPerAtom(class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum)357 {358 stringstream filename;359 ofstream output;360 361 filename << prefix << ".dat";362 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;363 cout << msg << endl;364 output << "# " << msg << ", created on " << datum;365 output << "# AtomNo\t" << Fragments.Header[ Fragments.MatrixCounter ] << endl;366 Fragments.SetLastMatrix(0., 0);367 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {368 //cout << "Current order is " << BondOrder << "." << endl;369 Fragments.SumSubHessians(Fragments, KeySet, BondOrder, 1.);370 // errors per atom371 output << endl << "#Order\t" << BondOrder+1 << endl;372 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {373 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";374 for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++)375 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";376 output << endl;377 }378 output << endl;379 }380 output.close();381 return true;382 };383 384 246 /** Plot matrix vs. fragment. 385 247 */ … … 393 255 cout << msg << endl; 394 256 output << "# " << msg << ", created on " << datum << endl; 395 output << "#Order\tFrag.No.\t" << Fragment.Header [ Fragment.MatrixCounter ]<< endl;257 output << "#Order\tFrag.No.\t" << Fragment.Header << endl; 396 258 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 397 259 for(int i=0;i<KeySet.FragmentsPerOrder[BondOrder];i++) { 398 260 output << BondOrder+1 << "\t" << KeySet.OrderSet[BondOrder][i]+1; 399 261 CreateFragment(Fragment, KeySet.OrderSet[BondOrder][i]); 400 for (int l=0;l<Fragment.ColumnCounter [ KeySet.OrderSet[BondOrder][i] ];l++)262 for (int l=0;l<Fragment.ColumnCounter;l++) 401 263 output << scientific << "\t" << Fragment.Matrix[ KeySet.OrderSet[BondOrder][i] ][ Fragment.RowCounter[ KeySet.OrderSet[BondOrder][i] ] ][l]; 402 264 output << endl; … … 417 279 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) { 418 280 if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) { 419 for (int k=Fragments.ColumnCounter [ Fragments.MatrixCounter ];k--;)281 for (int k=Fragments.ColumnCounter;k--;) 420 282 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 421 283 } … … 434 296 int i=0; 435 297 do { // first get a minimum value unequal to 0 436 for (int k=Fragments.ColumnCounter [ Fragments.MatrixCounter ];k--;)298 for (int k=Fragments.ColumnCounter;k--;) 437 299 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 438 300 i++; … … 440 302 for(;i<KeySet.FragmentsPerOrder[BondOrder];i++) { // then find lowest 441 303 if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) > fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) { 442 for (int k=Fragments.ColumnCounter [ Fragments.MatrixCounter ];k--;)304 for (int k=Fragments.ColumnCounter;k--;) 443 305 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 444 306 } … … 458 320 cout << msg << endl; 459 321 output << "# " << msg << ", created on " << datum; 460 output << "#Order\tFrag.No.\t" << Fragment.Header [ Fragment.MatrixCounter ]<< endl;322 output << "#Order\tFrag.No.\t" << Fragment.Header << endl; 461 323 // max 462 324 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { … … 464 326 CreateFragmentOrder(Fragment, KeySet, BondOrder); 465 327 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 466 for (int l=0;l<Fragment.ColumnCounter [ Fragment.MatrixCounter ];l++)328 for (int l=0;l<Fragment.ColumnCounter;l++) 467 329 output << scientific << "\t" << Fragment.Matrix[ Fragment.MatrixCounter ][ Fragment.RowCounter[ Fragment.MatrixCounter ]-1 ][l]; 468 330 output << endl; … … 478 340 void CreateEnergy(class MatrixContainer &Energy, int MatrixNumber) 479 341 { 480 for(int k=0;k<Energy.ColumnCounter [MatrixNumber];k++)342 for(int k=0;k<Energy.ColumnCounter;k++) 481 343 Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber] ] [k] = Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber]-1 ] [k]; 482 344 }; … … 489 351 void CreateMinimumForce(class MatrixContainer &Force, int MatrixNumber) 490 352 { 491 for (int l=Force.ColumnCounter [MatrixNumber];l--;)353 for (int l=Force.ColumnCounter;l--;) 492 354 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.; 493 for (int l=5;l<Force.ColumnCounter [MatrixNumber];l+=3) {355 for (int l=5;l<Force.ColumnCounter;l+=3) { 494 356 double stored = 0; 495 357 int k=0; … … 524 386 { 525 387 int divisor = 0; 526 for (int l=Force.ColumnCounter [MatrixNumber];l--;)388 for (int l=Force.ColumnCounter;l--;) 527 389 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.; 528 for (int l=5;l<Force.ColumnCounter [MatrixNumber];l+=3) {390 for (int l=5;l<Force.ColumnCounter;l+=3) { 529 391 double tmp = 0; 530 392 for (int k=Force.RowCounter[MatrixNumber];k--;) { … … 548 410 void CreateMaximumForce(class MatrixContainer &Force, int MatrixNumber) 549 411 { 550 for (int l=5;l<Force.ColumnCounter [MatrixNumber];l+=3) {412 for (int l=5;l<Force.ColumnCounter;l+=3) { 551 413 double stored = 0; 552 414 for (int k=Force.RowCounter[MatrixNumber];k--;) { … … 580 442 void CreateVectorSumForce(class MatrixContainer &Force, int MatrixNumber) 581 443 { 582 for (int l=Force.ColumnCounter [MatrixNumber];l--;)444 for (int l=Force.ColumnCounter;l--;) 583 445 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.; 584 for (int l=0;l<Force.ColumnCounter [MatrixNumber];l++) {446 for (int l=0;l<Force.ColumnCounter;l++) { 585 447 for (int k=Force.RowCounter[MatrixNumber];k--;) 586 448 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] += Force.Matrix[MatrixNumber][k][l]; … … 658 520 void AbsEnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses) 659 521 { 660 stringstream line(Energy.Header [ Energy.MatrixCounter ]);522 stringstream line(Energy.Header); 661 523 string token; 662 524 663 525 getline(line, token, '\t'); 664 for (int i=2; i<= Energy.ColumnCounter [Energy.MatrixCounter];i++) {526 for (int i=2; i<= Energy.ColumnCounter;i++) { 665 527 getline(line, token, '\t'); 666 528 while (token[0] == ' ') // remove leading white spaces 667 529 token.erase(0,1); 668 530 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+2 << ")) " << uses; 669 if (i != (Energy.ColumnCounter [Energy.MatrixCounter]))531 if (i != (Energy.ColumnCounter)) 670 532 output << ", \\"; 671 533 output << endl; … … 682 544 void EnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses) 683 545 { 684 stringstream line(Energy.Header [Energy.MatrixCounter]);546 stringstream line(Energy.Header); 685 547 string token; 686 548 687 549 getline(line, token, '\t'); 688 for (int i=1; i<= Energy.ColumnCounter [Energy.MatrixCounter];i++) {550 for (int i=1; i<= Energy.ColumnCounter;i++) { 689 551 getline(line, token, '\t'); 690 552 while (token[0] == ' ') // remove leading white spaces 691 553 token.erase(0,1); 692 554 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":" << i+2 << " " << uses; 693 if (i != (Energy.ColumnCounter [Energy.MatrixCounter]))555 if (i != (Energy.ColumnCounter)) 694 556 output << ", \\"; 695 557 output << endl; … … 706 568 void ForceMagnitudePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 707 569 { 708 stringstream line(Force.Header [Force.MatrixCounter]);570 stringstream line(Force.Header); 709 571 string token; 710 572 … … 714 576 getline(line, token, '\t'); 715 577 getline(line, token, '\t'); 716 for (int i=7; i< Force.ColumnCounter [Force.MatrixCounter];i+=NDIM) {578 for (int i=7; i< Force.ColumnCounter;i+=NDIM) { 717 579 getline(line, token, '\t'); 718 580 while (token[0] == ' ') // remove leading white spaces … … 720 582 token.erase(token.length(), 1); // kill residual index char (the '0') 721 583 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses; 722 if (i != (Force.ColumnCounter [Force.MatrixCounter]-1))584 if (i != (Force.ColumnCounter-1)) 723 585 output << ", \\"; 724 586 output << endl; … … 737 599 void AbsFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 738 600 { 739 stringstream line(Force.Header [Force.MatrixCounter]);601 stringstream line(Force.Header); 740 602 string token; 741 603 … … 745 607 getline(line, token, '\t'); 746 608 getline(line, token, '\t'); 747 for (int i=7; i< Force.ColumnCounter [Force.MatrixCounter];i+=NDIM) {609 for (int i=7; i< Force.ColumnCounter;i+=NDIM) { 748 610 getline(line, token, '\t'); 749 611 while (token[0] == ' ') // remove leading white spaces … … 751 613 token.erase(token.length(), 1); // kill residual index char (the '0') 752 614 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+1 << ")) " << uses; 753 if (i != (Force.ColumnCounter [Force.MatrixCounter]-1))615 if (i != (Force.ColumnCounter-1)) 754 616 output << ", \\"; 755 617 output << endl; … … 768 630 void BoxesForcePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 769 631 { 770 stringstream line(Force.Header [Force.MatrixCounter]);632 stringstream line(Force.Header); 771 633 char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"}; 772 634 string token; … … 777 639 getline(line, token, '\t'); 778 640 getline(line, token, '\t'); 779 for (int i=7; i< Force.ColumnCounter [Force.MatrixCounter];i+=NDIM) {641 for (int i=7; i< Force.ColumnCounter;i+=NDIM) { 780 642 getline(line, token, '\t'); 781 643 while (token[0] == ' ') // remove leading white spaces … … 783 645 token.erase(token.length(), 1); // kill residual index char (the '0') 784 646 output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses << " " << fillcolor[(i-7)/3]; 785 if (i != (Force.ColumnCounter [Force.MatrixCounter]-1))647 if (i != (Force.ColumnCounter-1)) 786 648 output << ", \\"; 787 649 output << endl; … … 800 662 void BoxesFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 801 663 { 802 stringstream line(Force.Header [Force.MatrixCounter]);664 stringstream line(Force.Header); 803 665 char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"}; 804 666 string token; … … 809 671 getline(line, token, '\t'); 810 672 getline(line, token, '\t'); 811 for (int i=7; i< Force.ColumnCounter [Force.MatrixCounter];i+=NDIM) {673 for (int i=7; i< Force.ColumnCounter;i+=NDIM) { 812 674 getline(line, token, '\t'); 813 675 while (token[0] == ' ') // remove leading white spaces … … 815 677 token.erase(token.length(), 1); // kill residual index char (the '0') 816 678 output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):" << i+1 << " " << uses << " " << fillcolor[(i-7)/3]; 817 if (i != (Force.ColumnCounter [Force.MatrixCounter]-1))679 if (i != (Force.ColumnCounter-1)) 818 680 output << ", \\"; 819 681 output << endl; -
Property mode
changed from
-
src/datacreator.hpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 18 18 19 19 bool OpenOutputFile(ofstream &output, const char *dir, const char *filename); 20 bool AppendOutputFile(ofstream &output, const char *dir, const char *filename);21 20 22 21 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); … … 26 25 bool CreateDataDeltaForcesOrder(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)); 27 26 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 28 bool CreateDataHessianOrderPerAtom(class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);29 bool CreateDataDeltaHessianOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);30 bool CreateDataDeltaFrobeniusOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum);31 27 bool CreateDataFragment(class MatrixContainer &ForceFragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)); 32 28 bool CreateDataFragmentOrder(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragmentOrder)(class MatrixContainer &, class KeySetsContainer &, int)); -
Property mode
changed from
-
src/defs.hpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 16 16 #define BONDTHRESHOLD 0.5 //!< CSD threshold in bond check which is the width of the interval whose center is the sum of the covalent radii 17 17 #define AtomicEnergyToKelvin 315774.67 //!< conversion factor from atomic energy to kelvin via boltzmann factor 18 #define KelvinToAtomicTemperature 3.1668152e-06 //!< conversion factor for Kelvin to atomic temperature (Hartree over k_B)19 #define KelvinToeV 8.6173422e-05 //!< conversion factor for Kelvin to Ht (k_B * T = energy), thus Boltzmann constant in eV/K20 #define AtomicMassUnitsToeV 931494088. //!< conversion factor for atomic weight in units to mass in eV21 #define AtomicMassUnitsToHt 34480864. //!< conversion factor for atomic weight in units to mass in Ht (protonmass/electronmass * electron_mass_in_Ht22 #define ElectronMass_Ht 18778.865 //!< electron mass in Ht23 #define ElectronMass_eV 510998.903 //!< electron mass in eV24 #define Units2Electronmass (AtomicMassUnitsToeV/ElectronMass_eV) //!< atomic mass unit in eV/ electron mass in eV = 1 822.8886325 #define Atomictime2Femtoseconds 0.024188843 //!< Atomictime in fs26 27 18 #define VERSIONSTRING "v1.0" 28 19 -
Property mode
changed from
-
src/element.cpp
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
src/elements.db
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
src/graph.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 7 7 using namespace std; 8 8 9 #include "graph.hpp"10 9 11 /***************************************** Implementations for graph classes ********************************/ 10 #include <iostream> 11 #include <list> 12 #include <vector> 12 13 13 /** Constructor of class Graph. 14 */ 15 Graph::Graph() 16 { 17 }; 14 /***************************************** Functions for class graph ********************************/ 18 15 19 /** Destructor of class Graph.20 * Destructor does release memory for nodes and edges contained in its lists as well.21 */22 Graph::~Graph()23 {24 };25 16 26 /** Constructor of class SubGraph. 27 */ 28 SubGraph::SubGraph() 29 { 30 }; 31 32 /** Destructor of class SubGraph. 33 * Note that destructor does not deallocate either nodes or edges! (this is done by its subgraph!) 34 */ 35 SubGraph::~SubGraph() 36 { 37 }; 38 39 /** Constructor of class Node. 40 */ 41 Node::Node() 42 { 43 }; 44 45 /** Destructor of class Node. 46 */ 47 Node::~Node() 48 { 49 }; 50 51 /** Constructor of class Edge. 52 */ 53 Edge::Edge() 54 { 55 }; 56 57 /** Destructor of class Edge. 58 */ 59 Edge::~Edge() 60 { 61 }; 62 17 -
Property mode
changed from
-
src/helpers.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 182 182 }; 183 183 184 /** Tests whether a given string contains a valid number or not.185 * \param *string186 * \return true - is a number, false - is not a valid number187 */188 bool IsValidNumber( const char *string)189 {190 int ptr = 0;191 if ((string[ptr] == '.') || (string[ptr] == '-')) // number may be negative or start with dot192 ptr++;193 if ((string[ptr] >= '0') && (string[ptr] <= '9'))194 return true;195 return false;196 };197 198 -
Property mode
changed from
-
src/helpers.hpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 59 59 void Free(void ** buffer, const char* output); 60 60 char *FixedDigitNumber(const int FragmentNumber, const int digits); 61 bool IsValidNumber( const char *string);62 61 63 62 /********************************************** helpful template functions *********************************/ -
Property mode
changed from
-
src/joiner.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 19 19 periodentafel *periode = NULL; // and a period table of all elements 20 20 EnergyMatrix Energy; 21 EnergyMatrix Hcorrection; 22 ForceMatrix Force; 21 23 EnergyMatrix EnergyFragments; 22 23 EnergyMatrix Hcorrection;24 24 EnergyMatrix HcorrectionFragments; 25 26 ForceMatrix Force;27 25 ForceMatrix ForceFragments; 28 29 HessianMatrix Hessian;30 HessianMatrix HessianFragments;31 32 26 ForceMatrix Shielding; 33 27 ForceMatrix ShieldingPAS; 34 28 ForceMatrix ShieldingFragments; 35 29 ForceMatrix ShieldingPASFragments; 36 ForceMatrix Chi;37 ForceMatrix ChiPAS;38 ForceMatrix ChiFragments;39 ForceMatrix ChiPASFragments;40 30 KeySetsContainer KeySet; 41 31 stringstream prefix; 42 32 char *dir = NULL; 43 bool NoHCorrection = false; 44 bool NoHessian = false; 33 bool Hcorrected = true; 45 34 46 35 cout << "Joiner" << endl; … … 72 61 // ------------- Parse through all Fragment subdirs -------- 73 62 if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix, 0,0)) return 1; 74 if (!Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX, 0,0)) { 75 NoHCorrection = true; 76 cout << "No HCorrection matrices found, skipping these." << endl; 77 } 63 Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX, 0,0); 78 64 if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix, 0,0)) return 1; 79 if (!Hessian.ParseFragmentMatrix(argv[1], dir, HessianSuffix, 0,0)) {80 NoHessian = true;81 cout << "No hessian matrices found, skipping these." << endl;82 }83 65 if (periode != NULL) { // also look for PAS values 84 66 if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1; 85 67 if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1; 86 if (!Chi.ParseFragmentMatrix(argv[1], dir, ChiSuffix, 1, 0)) return 1;87 if (!ChiPAS.ParseFragmentMatrix(argv[1], dir, ChiPASSuffix, 1, 0)) return 1;88 68 } 89 69 90 70 // ---------- Parse the TE Factors into an array ----------------- 91 if (!Energy.InitialiseIndices()) return 1; 92 if (!NoHCorrection) 93 Hcorrection.InitialiseIndices(); 71 if (!Energy.ParseIndices()) return 1; 72 if (Hcorrected) Hcorrection.ParseIndices(); 94 73 95 74 // ---------- Parse the Force indices into an array --------------- 96 75 if (!Force.ParseIndices(argv[1])) return 1; 97 98 // ---------- Parse the Hessian (=force) indices into an array ---------------99 if (!NoHessian)100 if (!Hessian.InitialiseIndices((class MatrixContainer *)&Force)) return 1;101 76 102 77 // ---------- Parse the shielding indices into an array --------------- … … 104 79 if(!Shielding.ParseIndices(argv[1])) return 1; 105 80 if(!ShieldingPAS.ParseIndices(argv[1])) return 1; 106 if(!Chi.ParseIndices(argv[1])) return 1;107 if(!ChiPAS.ParseIndices(argv[1])) return 1;108 81 } 109 82 110 83 // ---------- Parse the KeySets into an array --------------- 111 84 if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1; 85 112 86 if (!KeySet.ParseManyBodyTerms()) return 1; 113 114 87 if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return 1; 115 if (!NoHCorrection) 116 HcorrectionFragments.AllocateMatrix(Hcorrection.Header, Hcorrection.MatrixCounter, Hcorrection.RowCounter, Hcorrection.ColumnCounter); 88 if (Hcorrected) HcorrectionFragments.AllocateMatrix(Hcorrection.Header, Hcorrection.MatrixCounter, Hcorrection.RowCounter, Hcorrection.ColumnCounter); 117 89 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1; 118 if (!NoHessian)119 if (!HessianFragments.AllocateMatrix(Hessian.Header, Hessian.MatrixCounter, Hessian.RowCounter, Hessian.ColumnCounter)) return 1;120 90 if (periode != NULL) { // also look for PAS values 121 91 if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1; 122 92 if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1; 123 if (!ChiFragments.AllocateMatrix(Chi.Header, Chi.MatrixCounter, Chi.RowCounter, Chi.ColumnCounter)) return 1;124 if (!ChiPASFragments.AllocateMatrix(ChiPAS.Header, ChiPAS.MatrixCounter, ChiPAS.RowCounter, ChiPAS.ColumnCounter)) return 1;125 93 } 126 94 … … 128 96 if(!Energy.SetLastMatrix(0., 0)) return 1; 129 97 if(!Force.SetLastMatrix(0., 2)) return 1; 130 if (!NoHessian)131 if (!Hessian.SetLastMatrix(0., 0)) return 1;132 98 if (periode != NULL) { // also look for PAS values 133 99 if(!Shielding.SetLastMatrix(0., 2)) return 1; 134 100 if(!ShieldingPAS.SetLastMatrix(0., 2)) return 1; 135 if(!Chi.SetLastMatrix(0., 2)) return 1;136 if(!ChiPAS.SetLastMatrix(0., 2)) return 1;137 101 } 138 102 … … 144 108 cout << "Summing energy of order " << BondOrder+1 << " ..." << endl; 145 109 if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return 1; 146 if ( !NoHCorrection) {110 if (Hcorrected) { 147 111 HcorrectionFragments.SumSubManyBodyTerms(Hcorrection, KeySet, BondOrder); 148 112 if (!Energy.SumSubEnergy(EnergyFragments, &HcorrectionFragments, KeySet, BondOrder, 1.)) return 1; 149 Hcorrection.SumSubEnergy(HcorrectionFragments, NULL, KeySet, BondOrder, 1.);113 if (Hcorrected) Hcorrection.SumSubEnergy(HcorrectionFragments, NULL, KeySet, BondOrder, 1.); 150 114 } else 151 115 if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return 1; … … 154 118 if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return 1; 155 119 if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return 1; 156 // --------- sum up Hessian --------------------157 if (!NoHessian) {158 cout << "Summing Hessian of order " << BondOrder+1 << " ..." << endl;159 if (!HessianFragments.SumSubManyBodyTerms(Hessian, KeySet, BondOrder)) return 1;160 if (!Hessian.SumSubHessians(HessianFragments, KeySet, BondOrder, 1.)) return 1;161 }162 120 if (periode != NULL) { // also look for PAS values 163 cout << "Summing shieldings and susceptibilitiesof order " << BondOrder+1 << " ..." << endl;121 cout << "Summing shieldings of order " << BondOrder+1 << " ..." << endl; 164 122 if (!ShieldingFragments.SumSubManyBodyTerms(Shielding, KeySet, BondOrder)) return 1; 165 123 if (!Shielding.SumSubForces(ShieldingFragments, KeySet, BondOrder, 1.)) return 1; 166 124 if (!ShieldingPASFragments.SumSubManyBodyTerms(ShieldingPAS, KeySet, BondOrder)) return 1; 167 125 if (!ShieldingPAS.SumSubForces(ShieldingPASFragments, KeySet, BondOrder, 1.)) return 1; 168 if (!ChiFragments.SumSubManyBodyTerms(Chi, KeySet, BondOrder)) return 1;169 if (!Chi.SumSubForces(ChiFragments, KeySet, BondOrder, 1.)) return 1;170 if (!ChiPASFragments.SumSubManyBodyTerms(ChiPAS, KeySet, BondOrder)) return 1;171 if (!ChiPAS.SumSubForces(ChiPASFragments, KeySet, BondOrder, 1.)) return 1;172 126 } 173 127 … … 180 134 // forces 181 135 if (!Force.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ForcesSuffix)) return 1; 182 // hessian183 if (!NoHessian)184 if (!Hessian.WriteLastMatrix(argv[1], (prefix.str()).c_str(), HessianSuffix)) return 1;185 136 // shieldings 186 137 if (periode != NULL) { // also look for PAS values 187 138 if (!Shielding.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingSuffix)) return 1; 188 139 if (!ShieldingPAS.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingPASSuffix)) return 1; 189 if (!Chi.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ChiSuffix)) return 1;190 if (!ChiPAS.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ChiPASSuffix)) return 1;191 140 } 192 141 } … … 195 144 prefix << dir << EnergyFragmentSuffix; 196 145 if (!EnergyFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 197 if ( !NoHCorrection) {146 if (Hcorrected) { 198 147 prefix.str(" "); 199 148 prefix << dir << HcorrectionFragmentSuffix; … … 204 153 if (!ForceFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 205 154 if (!CreateDataFragment(EnergyFragments, KeySet, argv[1], FRAGMENTPREFIX ENERGYPERFRAGMENT, "fragment energy versus the Fragment No", "today", CreateEnergy)) return 1; 206 if (!NoHessian) {207 prefix.str(" ");208 prefix << dir << HessianFragmentSuffix;209 if (!HessianFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;210 }211 155 if (periode != NULL) { // also look for PAS values 212 156 prefix.str(" "); … … 216 160 prefix << dir << ShieldingPASFragmentSuffix; 217 161 if (!ShieldingPASFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 218 prefix.str(" ");219 prefix << dir << ChiFragmentSuffix;220 if (!ChiFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;221 prefix.str(" ");222 prefix << dir << ChiPASFragmentSuffix;223 if (!ChiPASFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1;224 162 } 225 163 226 164 // write last matrices as fragments into central dir (not subdir as above), for analyzer to know index bounds 227 165 if (!Energy.WriteLastMatrix(argv[1], dir, EnergyFragmentSuffix)) return 1; 228 if ( !NoHCorrection) Hcorrection.WriteLastMatrix(argv[1], dir, HcorrectionFragmentSuffix);166 if (Hcorrected) Hcorrection.WriteLastMatrix(argv[1], dir, HcorrectionFragmentSuffix); 229 167 if (!Force.WriteLastMatrix(argv[1], dir, ForceFragmentSuffix)) return 1; 230 if (!NoHessian)231 if (!Hessian.WriteLastMatrix(argv[1], dir, HessianFragmentSuffix)) return 1;232 168 if (periode != NULL) { // also look for PAS values 233 169 if (!Shielding.WriteLastMatrix(argv[1], dir, ShieldingFragmentSuffix)) return 1; 234 170 if (!ShieldingPAS.WriteLastMatrix(argv[1], dir, ShieldingPASFragmentSuffix)) return 1; 235 if (!Chi.WriteLastMatrix(argv[1], dir, ChiFragmentSuffix)) return 1;236 if (!ChiPAS.WriteLastMatrix(argv[1], dir, ChiPASFragmentSuffix)) return 1;237 171 } 238 172 -
Property mode
changed from
-
src/moleculelist.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 395 395 int FragmentCounter = 0; 396 396 ofstream output; 397 string basis("3-21G");398 397 399 398 // store the fragments as config and as xyz … … 456 455 // and save as config 457 456 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, fragmentprefix, FragmentNumber); 457 outputFragment.open(FragmentName, ios::out); 458 458 *out << Verbose(2) << "Saving " << fragmentprefix << " No. " << FragmentNumber << "/" << FragmentCounter-1 << " as config ..."; 459 if ((intermediateResult = configuration->Save( FragmentName, ListOfMolecules[i]->elemente, ListOfMolecules[i])))459 if ((intermediateResult = configuration->Save(&outputFragment, ListOfMolecules[i]->elemente, ListOfMolecules[i]))) 460 460 *out << " done." << endl; 461 461 else 462 462 *out << " failed." << endl; 463 result = result && intermediateResult;464 463 465 464 // restore old config 466 465 configuration->SetDefaultPath(PathBackup); 467 466 467 result = result && intermediateResult; 468 outputFragment.close(); 469 outputFragment.clear(); 468 470 469 471 // and save as mpqc input file 470 472 sprintf(FragmentName, "%s/%s%s.in", configuration->configpath, fragmentprefix, FragmentNumber); 473 outputFragment.open(FragmentName, ios::out); 471 474 *out << Verbose(2) << "Saving " << fragmentprefix << " No. " << FragmentNumber << "/" << FragmentCounter-1 << " as mpqc input ..."; 472 if ((intermediateResult = configuration->SaveMPQC( FragmentName, ListOfMolecules[i])))475 if ((intermediateResult = configuration->SaveMPQC(&outputFragment, ListOfMolecules[i]))) 473 476 *out << " done." << endl; 474 477 else … … 476 479 477 480 result = result && intermediateResult; 478 //outputFragment.close();479 //outputFragment.clear();481 outputFragment.close(); 482 outputFragment.clear(); 480 483 delete(FragmentNumber); 481 484 //Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber"); -
Property mode
changed from
-
src/molecules.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 1 1 /** \file molecules.cpp 2 * 2 * 3 3 * Functions for the class molecule. 4 * 4 * 5 5 */ 6 6 … … 25 25 sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]); 26 26 } 27 27 28 28 return sum; 29 29 }; … … 34 34 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero. 35 35 */ 36 molecule::molecule(periodentafel *teil) 37 { 36 molecule::molecule(periodentafel *teil) 37 { 38 38 // init atom chain list 39 start = new atom; 39 start = new atom; 40 40 end = new atom; 41 start->father = NULL; 41 start->father = NULL; 42 42 end->father = NULL; 43 43 link(start,end); … … 46 46 last = new bond(start, end, 1, -1); 47 47 link(first,last); 48 // other stuff 48 // other stuff 49 49 MDSteps = 0; 50 last_atom = 0; 50 last_atom = 0; 51 51 elemente = teil; 52 52 AtomCount = 0; … … 67 67 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero. 68 68 */ 69 molecule::~molecule() 69 molecule::~molecule() 70 70 { 71 71 if (ListOfBondsPerAtom != NULL) … … 78 78 delete(last); 79 79 delete(end); 80 delete(start); 80 delete(start); 81 81 }; 82 82 83 83 /** Adds given atom \a *pointer from molecule list. 84 * Increases molecule::last_atom and gives last number to added atom and names it according to its element::abbrev and molecule::AtomCount 84 * Increases molecule::last_atom and gives last number to added atom and names it according to its element::abbrev and molecule::AtomCount 85 85 * \param *pointer allocated and set atom 86 86 * \return true - succeeded, false - atom not found in list 87 87 */ 88 88 bool molecule::AddAtom(atom *pointer) 89 { 89 { 90 90 if (pointer != NULL) { 91 pointer->sort = &pointer->nr; 91 pointer->sort = &pointer->nr; 92 92 pointer->nr = last_atom++; // increase number within molecule 93 93 AtomCount++; … … 106 106 return add(pointer, end); 107 107 } else 108 return false; 108 return false; 109 109 }; 110 110 … … 115 115 */ 116 116 atom * molecule::AddCopyAtom(atom *pointer) 117 { 117 { 118 118 if (pointer != NULL) { 119 119 atom *walker = new atom(); … … 122 122 walker->v.CopyVector(&pointer->v); // copy velocity 123 123 walker->FixedIon = pointer->FixedIon; 124 walker->sort = &walker->nr; 124 walker->sort = &walker->nr; 125 125 walker->nr = last_atom++; // increase number within molecule 126 126 walker->father = pointer; //->GetTrueFather(); … … 133 133 return walker; 134 134 } else 135 return NULL; 135 return NULL; 136 136 }; 137 137 … … 156 156 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that 157 157 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1. 158 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 158 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 159 159 * \f] 160 * as the coordination of all three atoms in the coordinate system of these three vectors: 160 * as the coordination of all three atoms in the coordinate system of these three vectors: 161 161 * \f$\pmatrix{d & f & 0}\f$, \f$\pmatrix{d & -0.5 \cdot f & g}\f$ and \f$\pmatrix{d & -0.5 \cdot f & -g}\f$. 162 * 162 * 163 163 * \param *out output stream for debugging 164 * \param *Bond pointer to bond between \a *origin and \a *replacement 165 * \param *TopOrigin son of \a *origin of upper level molecule (the atom added to this molecule as a copy of \a *origin) 164 * \param *Bond pointer to bond between \a *origin and \a *replacement 165 * \param *TopOrigin son of \a *origin of upper level molecule (the atom added to this molecule as a copy of \a *origin) 166 166 * \param *origin pointer to atom which acts as the origin for scaling the added hydrogen to correct bond length 167 167 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule … … 191 191 InBondvector.SubtractVector(&TopOrigin->x); 192 192 bondlength = InBondvector.Norm(); 193 193 194 194 // is greater than typical bond distance? Then we have to correct periodically 195 195 // the problem is not the H being out of the box, but InBondvector have the wrong direction 196 // due to TopReplacement or Origin being on the wrong side! 197 if (bondlength > BondDistance) { 196 // due to TopReplacement or Origin being on the wrong side! 197 if (bondlength > BondDistance) { 198 198 // *out << Verbose(4) << "InBondvector is: "; 199 199 // InBondvector.Output(out); … … 215 215 // *out << endl; 216 216 } // periodic correction finished 217 217 218 218 InBondvector.Normalize(); 219 219 // get typical bond length and store as scale factor for later 220 220 BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1]; 221 221 if (BondRescale == -1) { 222 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 223 return false; 224 BondRescale = bondlength; 222 cerr << Verbose(3) << "WARNING: There is no typical bond distance for bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 223 BondRescale = bondlength; 225 224 } else { 226 225 if (!IsAngstroem) … … 273 272 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 274 273 // *out << Verbose(3) << "Regarding the double bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") to be constructed: Taking " << FirstOtherAtom->Name << " and " << SecondOtherAtom->Name << " along with " << TopOrigin->Name << " to determine orthogonal plane." << endl; 275 274 276 275 // determine the plane of these two with the *origin 277 276 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x); … … 286 285 Orthovector1.Normalize(); 287 286 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl; 288 287 289 288 // create the two Hydrogens ... 290 289 FirstOtherAtom = new atom(); … … 300 299 bondangle = TopOrigin->type->HBondAngle[1]; 301 300 if (bondangle == -1) { 302 *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 303 return false; 301 *out << Verbose(3) << "WARNING: There is no typical bond angle for bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 304 302 bondangle = 0; 305 303 } … … 318 316 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle)); 319 317 } 320 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 318 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 321 319 SecondOtherAtom->x.Scale(&BondRescale); 322 320 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl; 323 321 for(int i=NDIM;i--;) { // and make relative to origin atom 324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 322 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 325 323 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i]; 326 324 } … … 365 363 // *out << endl; 366 364 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1); 367 // *out << Verbose(3) << "Orthovector2: "; 365 // *out << Verbose(3) << "Orthovector2: "; 368 366 // Orthovector2.Output(out); 369 367 // *out << endl; 370 368 371 369 // create correct coordination for the three atoms 372 370 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.; // retrieve triple bond angle from database … … 380 378 factors[0] = d; 381 379 factors[1] = f; 382 factors[2] = 0.; 380 factors[2] = 0.; 383 381 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 384 382 factors[1] = -0.5*f; 385 factors[2] = g; 383 factors[2] = g; 386 384 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 387 factors[2] = -g; 385 factors[2] = -g; 388 386 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 389 387 … … 437 435 */ 438 436 bool molecule::AddXYZFile(string filename) 439 { 437 { 440 438 istringstream *input = NULL; 441 439 int NumberOfAtoms = 0; // atom number in xyz read … … 446 444 string line; // currently parsed line 447 445 double x[3]; // atom coordinates 448 446 449 447 xyzfile.open(filename.c_str()); 450 448 if (!xyzfile) … … 454 452 input = new istringstream(line); 455 453 *input >> NumberOfAtoms; 456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 454 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 457 455 getline(xyzfile,line,'\n'); // Read comment 458 456 cout << Verbose(1) << "Comment: " << line << endl; 459 457 460 458 if (MDSteps == 0) // no atoms yet present 461 459 MDSteps++; … … 491 489 xyzfile.close(); 492 490 delete(input); 493 return true; 491 return true; 494 492 }; 495 493 … … 503 501 atom *LeftAtom = NULL, *RightAtom = NULL; 504 502 atom *Walker = NULL; 505 503 506 504 // copy all atoms 507 505 Walker = start; … … 510 508 CurrentAtom = copy->AddCopyAtom(Walker); 511 509 } 512 510 513 511 // copy all bonds 514 512 bond *Binder = first; … … 534 532 copy->NoCyclicBonds++; 535 533 NewBond->Type = Binder->Type; 536 } 534 } 537 535 // correct fathers 538 536 Walker = copy->start; … … 551 549 copy->CreateListOfBondsPerAtom((ofstream *)&cout); 552 550 } 553 551 554 552 return copy; 555 553 }; … … 576 574 577 575 /** Remove bond from bond chain list. 578 * \todo Function not implemented yet 576 * \todo Function not implemented yet 579 577 * \param *pointer bond pointer 580 578 * \return true - bound found and removed, false - bond not found/removed … … 588 586 589 587 /** Remove every bond from bond chain list that atom \a *BondPartner is a constituent of. 590 * \todo Function not implemented yet 588 * \todo Function not implemented yet 591 589 * \param *BondPartner atom to be removed 592 590 * \return true - bounds found and removed, false - bonds not found/removed … … 621 619 Vector *min = new Vector; 622 620 Vector *max = new Vector; 623 621 624 622 // gather min and max for each axis 625 623 ptr = start->next; // start at first in list … … 667 665 { 668 666 Vector *min = new Vector; 669 667 670 668 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 671 669 atom *ptr = start->next; // start at first in list … … 683 681 } 684 682 } 685 // *out << Verbose(4) << "Maximum is "; 683 // *out << Verbose(4) << "Maximum is "; 686 684 // max->Output(out); 687 685 // *out << ", Minimum is "; … … 691 689 max->AddVector(min); 692 690 Translate(min); 693 } 691 } 694 692 delete(min); 695 693 // *out << Verbose(3) << "End of CenterEdge." << endl; 696 }; 694 }; 697 695 698 696 /** Centers the center of the atoms at (0,0,0). … … 704 702 int Num = 0; 705 703 atom *ptr = start->next; // start at first in list 706 704 707 705 for(int i=NDIM;i--;) // zero center vector 708 706 center->x[i] = 0.; 709 707 710 708 if (ptr != end) { //list not empty? 711 709 while (ptr->next != end) { // continue with second if present 712 710 ptr = ptr->next; 713 711 Num++; 714 center->AddVector(&ptr->x); 712 center->AddVector(&ptr->x); 715 713 } 716 714 center->Scale(-1./Num); // divide through total number (and sign for direction) 717 715 Translate(center); 718 716 } 719 }; 717 }; 720 718 721 719 /** Returns vector pointing to center of gravity. … … 729 727 Vector tmp; 730 728 double Num = 0; 731 729 732 730 a->Zero(); 733 731 … … 737 735 Num += 1.; 738 736 tmp.CopyVector(&ptr->x); 739 a->AddVector(&tmp); 737 a->AddVector(&tmp); 740 738 } 741 739 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 757 755 Vector tmp; 758 756 double Num = 0; 759 757 760 758 a->Zero(); 761 759 … … 766 764 tmp.CopyVector(&ptr->x); 767 765 tmp.Scale(ptr->type->mass); // scale by mass 768 a->AddVector(&tmp); 766 a->AddVector(&tmp); 769 767 } 770 768 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 789 787 Translate(center); 790 788 } 791 }; 789 }; 792 790 793 791 /** Scales all atoms by \a *factor. … … 803 801 Trajectories[ptr].R.at(j).Scale(factor); 804 802 ptr->x.Scale(factor); 805 } 806 }; 807 808 /** Translate all atoms by given vector. 803 } 804 }; 805 806 /** Translate all atoms by given vector. 809 807 * \param trans[] translation vector. 810 808 */ … … 818 816 Trajectories[ptr].R.at(j).Translate(trans); 819 817 ptr->x.Translate(trans); 820 } 821 }; 822 823 /** Mirrors all atoms against a given plane. 818 } 819 }; 820 821 /** Mirrors all atoms against a given plane. 824 822 * \param n[] normal vector of mirror plane. 825 823 */ … … 833 831 Trajectories[ptr].R.at(j).Mirror(n); 834 832 ptr->x.Mirror(n); 835 } 833 } 836 834 }; 837 835 … … 847 845 bool flag; 848 846 Vector Testvector, Translationvector; 849 847 850 848 do { 851 849 Center.Zero(); … … 863 861 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 864 862 for (int j=0;j<NDIM;j++) { 865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 863 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 866 864 if ((fabs(tmp)) > BondDistance) { 867 865 flag = false; … … 879 877 cout << Verbose(1) << "vector is: "; 880 878 Testvector.Output((ofstream *)&cout); 881 cout << endl; 879 cout << endl; 882 880 #ifdef ADDHYDROGEN 883 881 // now also change all hydrogens … … 892 890 cout << Verbose(1) << "Hydrogen vector is: "; 893 891 Testvector.Output((ofstream *)&cout); 894 cout << endl; 892 cout << endl; 895 893 } 896 894 } … … 914 912 915 913 CenterGravity(out, CenterOfGravity); 916 917 // reset inertia tensor 914 915 // reset inertia tensor 918 916 for(int i=0;i<NDIM*NDIM;i++) 919 917 InertiaTensor[i] = 0.; 920 918 921 919 // sum up inertia tensor 922 920 while (ptr->next != end) { … … 943 941 } 944 942 *out << endl; 945 943 946 944 // diagonalize to determine principal axis system 947 945 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM); … … 952 950 gsl_eigen_symmv_free(T); 953 951 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); 954 952 955 953 for(int i=0;i<NDIM;i++) { 956 954 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i); 957 955 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl; 958 956 } 959 957 960 958 // check whether we rotate or not 961 959 if (DoRotate) { 962 *out << Verbose(1) << "Transforming molecule into PAS ... "; 960 *out << Verbose(1) << "Transforming molecule into PAS ... "; 963 961 // the eigenvectors specify the transformation matrix 964 962 ptr = start; … … 972 970 973 971 // summing anew for debugging (resulting matrix has to be diagonal!) 974 // reset inertia tensor 972 // reset inertia tensor 975 973 for(int i=0;i<NDIM*NDIM;i++) 976 974 InertiaTensor[i] = 0.; 977 975 978 976 // sum up inertia tensor 979 977 ptr = start; … … 1002 1000 *out << endl; 1003 1001 } 1004 1002 1005 1003 // free everything 1006 1004 delete(CenterOfGravity); … … 1019 1017 * \sa molecule::MinimiseConstrainedPotential(), molecule::VerletForceIntegration() 1020 1018 * \param *out output stream for debugging 1021 * \param *PermutationMap gives target ptr for each atom, array of size molecule::AtomCount (this is "x" in \f$ V^{con}(x) \f$)1019 * \param *PermutationMap gives target ptr for each atom, array of size molecule::AtomCount (this is "x" in \f$V^{con}(x)\f$) 1022 1020 * \param startstep start configuration (MDStep in molecule::trajectories) 1023 1021 * \param endstep end configuration (MDStep in molecule::trajectories) … … 1481 1479 * \param *out output stream for debugging 1482 1480 * \param *file filename 1483 * \param config structure with config::Deltat, config::IsAngstroem, config::DoConstrained1484 1481 * \param delta_t time step width in atomic units 1485 1482 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false) … … 1488 1485 * \todo This is not yet checked if it is correctly working with DoConstrained set to true. 1489 1486 */ 1490 bool molecule::VerletForceIntegration(ofstream *out, char *file, config &configuration) 1491 { 1487 bool molecule::VerletForceIntegration(ofstream *out, char *file, double delta_t, bool IsAngstroem, int DoConstrained) 1488 { 1489 element *runner = elemente->start; 1492 1490 atom *walker = NULL; 1491 int AtomNo; 1493 1492 ifstream input(file); 1494 1493 string token; 1495 1494 stringstream item; 1496 double IonMass, Vector[NDIM], ConstrainedPotentialEnergy, ActualTemp;1495 double a, IonMass, Vector[NDIM], ConstrainedPotentialEnergy; 1497 1496 ForceMatrix Force; 1498 1497 1499 1498 CountElements(); // make sure ElementsInMolecule is up to date 1500 1499 1501 1500 // check file 1502 1501 if (input == NULL) { … … 1524 1523 } 1525 1524 // solve a constrained potential if we are meant to 1526 if ( configuration.DoConstrainedMD) {1525 if (DoConstrained) { 1527 1526 // calculate forces and potential 1528 1527 atom **PermutationMap = NULL; 1529 ConstrainedPotentialEnergy = MinimiseConstrainedPotential(out, PermutationMap, configuration.DoConstrainedMD, 0, configuration.GetIsAngstroem());1530 EvaluateConstrainedForces(out, configuration.DoConstrainedMD, 0, PermutationMap, &Force);1528 ConstrainedPotentialEnergy = MinimiseConstrainedPotential(out, PermutationMap, DoConstrained, 0, IsAngstroem); 1529 EvaluateConstrainedForces(out, DoConstrained, 0, PermutationMap, &Force); 1531 1530 Free((void **)&PermutationMap, "molecule::MinimiseConstrainedPotential: *PermutationMap"); 1532 1531 } 1533 1532 1534 1533 // and perform Verlet integration for each atom with position, velocity and force vector 1535 walker = start; 1536 while (walker->next != end) { // go through every atom of this element 1537 walker = walker->next; 1538 //a = configuration.Deltat*0.5/walker->type->mass; // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a 1539 // check size of vectors 1540 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) { 1541 //out << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl; 1542 Trajectories[walker].R.resize(MDSteps+10); 1543 Trajectories[walker].U.resize(MDSteps+10); 1544 Trajectories[walker].F.resize(MDSteps+10); 1545 } 1546 1547 // Update R (and F) 1548 for (int d=0; d<NDIM; d++) { 1549 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][walker->nr][d+5]*(configuration.GetIsAngstroem() ? AtomicLengthToAngstroem : 1.); 1550 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d]; 1551 Trajectories[walker].R.at(MDSteps).x[d] += configuration.Deltat*(Trajectories[walker].U.at(MDSteps-1).x[d]); // s(t) = s(0) + v * deltat + 1/2 a * deltat^2 1552 Trajectories[walker].R.at(MDSteps).x[d] += 0.5*configuration.Deltat*configuration.Deltat*(Trajectories[walker].F.at(MDSteps).x[d]/walker->type->mass); // F = m * a and s = 0.5 * F/m * t^2 = F * a * t 1553 } 1554 // Update U 1555 for (int d=0; d<NDIM; d++) { 1556 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d]; 1557 Trajectories[walker].U.at(MDSteps).x[d] += configuration.Deltat * (Trajectories[walker].F.at(MDSteps).x[d]+Trajectories[walker].F.at(MDSteps-1).x[d]/walker->type->mass); // v = F/m * t 1558 } 1559 // out << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1560 // for (int d=0;d<NDIM;d++) 1561 // out << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step 1562 // out << ")\t("; 1563 // for (int d=0;d<NDIM;d++) 1564 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " "; // next step 1565 // out << ")" << endl; 1566 // next atom 1567 } 1568 } 1569 // correct velocities (rather momenta) so that center of mass remains motionless 1570 for(int d=0;d<NDIM;d++) 1571 Vector[d] = 0.; 1572 IonMass = 0.; 1573 walker = start; 1574 while (walker->next != end) { // go through every atom 1575 walker = walker->next; 1576 IonMass += walker->type->mass; // sum up total mass 1577 for(int d=0;d<NDIM;d++) { 1578 Vector[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass; 1579 } 1580 } 1581 // correct velocities (rather momenta) so that center of mass remains motionless 1582 for(int d=0;d<NDIM;d++) 1583 Vector[d] /= IonMass; 1584 ActualTemp = 0.; 1585 walker = start; 1586 while (walker->next != end) { // go through every atom of this element 1587 walker = walker->next; 1588 for(int d=0;d<NDIM;d++) { 1589 Trajectories[walker].U.at(MDSteps).x[d] -= Vector[d]; 1590 ActualTemp += 0.5 * walker->type->mass * Trajectories[walker].U.at(MDSteps).x[d] * Trajectories[walker].U.at(MDSteps).x[d]; 1591 } 1592 } 1593 Thermostats(configuration, ActualTemp, Berendsen); 1594 MDSteps++; 1595 1596 1597 // exit 1598 return true; 1599 }; 1600 1601 /** Implementation of various thermostats. 1602 * All these thermostats apply an additional force which has the following forms: 1603 * -# Woodcock 1604 * \f$p_i \rightarrow \sqrt{\frac{T_0}{T}} \cdot p_i\f$ 1605 * -# Gaussian 1606 * \f$ \frac{ \sum_i \frac{p_i}{m_i} \frac{\partial V}{\partial q_i}} {\sum_i \frac{p^2_i}{m_i}} \cdot p_i\f$ 1607 * -# Langevin 1608 * \f$p_{i,n} \rightarrow \sqrt{1-\alpha^2} p_{i,0} + \alpha p_r\f$ 1609 * -# Berendsen 1610 * \f$p_i \rightarrow \left [ 1+ \frac{\delta t}{\tau_T} \left ( \frac{T_0}{T} \right ) \right ]^{\frac{1}{2}} \cdot p_i\f$ 1611 * -# Nose-Hoover 1612 * \f$\zeta p_i \f$ with \f$\frac{\partial \zeta}{\partial t} = \frac{1}{M_s} \left ( \sum^N_{i=1} \frac{p_i^2}{m_i} - g k_B T \right )\f$ 1613 * These Thermostats either simply rescale the velocities, thus this function should be called after ion velocities have been updated, and/or 1614 * have a constraint force acting additionally on the ions. In the latter case, the ion speeds have to be modified 1615 * belatedly and the constraint force set. 1616 * \param *P Problem at hand 1617 * \param i which of the thermostats to take: 0 - none, 1 - Woodcock, 2 - Gaussian, 3 - Langevin, 4 - Berendsen, 5 - Nose-Hoover 1618 * \sa InitThermostat() 1619 */ 1620 void molecule::Thermostats(config &configuration, double ActualTemp, int Thermostat) 1621 { 1622 double ekin = 0.; 1623 double E = 0., G = 0.; 1624 double delta_alpha = 0.; 1625 double ScaleTempFactor; 1626 double sigma; 1627 double IonMass; 1628 int d; 1629 gsl_rng * r; 1630 const gsl_rng_type * T; 1631 double *U = NULL, *F = NULL, FConstraint[NDIM]; 1632 atom *walker = NULL; 1633 1634 // calculate scale configuration 1635 ScaleTempFactor = configuration.TargetTemp/ActualTemp; 1636 1637 // differentating between the various thermostats 1638 switch(Thermostat) { 1639 case None: 1640 cout << Verbose(2) << "Applying no thermostat..." << endl; 1641 break; 1642 case Woodcock: 1643 if ((configuration.ScaleTempStep > 0) && ((MDSteps-1) % configuration.ScaleTempStep == 0)) { 1644 cout << Verbose(2) << "Applying Woodcock thermostat..." << endl; 1534 runner = elemente->start; 1535 while (runner->next != elemente->end) { // go through every element 1536 runner = runner->next; 1537 IonMass = runner->mass; 1538 a = delta_t*0.5/IonMass; // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a 1539 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1540 AtomNo = 0; 1645 1541 walker = start; 1646 1542 while (walker->next != end) { // go through every atom of this element 1647 1543 walker = walker->next; 1648 IonMass = walker->type->mass; 1649 U = Trajectories[walker].U.at(MDSteps).x; 1650 if (walker->FixedIon == 0) // even FixedIon moves, only not by other's forces 1651 for (d=0; d<NDIM; d++) { 1652 U[d] *= sqrt(ScaleTempFactor); 1653 ekin += 0.5*IonMass * U[d]*U[d]; 1544 if (walker->type == runner) { // if this atom fits to element 1545 // check size of vectors 1546 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) { 1547 //out << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl; 1548 Trajectories[walker].R.resize(MDSteps+10); 1549 Trajectories[walker].U.resize(MDSteps+10); 1550 Trajectories[walker].F.resize(MDSteps+10); 1654 1551 } 1655 } 1656 } 1657 break; 1658 case Gaussian: 1659 cout << Verbose(2) << "Applying Gaussian thermostat..." << endl; 1660 walker = start; 1661 while (walker->next != end) { // go through every atom of this element 1662 walker = walker->next; 1663 IonMass = walker->type->mass; 1664 U = Trajectories[walker].U.at(MDSteps).x; 1665 F = Trajectories[walker].F.at(MDSteps).x; 1666 if (walker->FixedIon == 0) // even FixedIon moves, only not by other's forces 1667 for (d=0; d<NDIM; d++) { 1668 G += U[d] * F[d]; 1669 E += U[d]*U[d]*IonMass; 1670 } 1671 } 1672 cout << Verbose(1) << "Gaussian Least Constraint constant is " << G/E << "." << endl; 1673 walker = start; 1674 while (walker->next != end) { // go through every atom of this element 1675 walker = walker->next; 1676 IonMass = walker->type->mass; 1677 U = Trajectories[walker].U.at(MDSteps).x; 1678 F = Trajectories[walker].F.at(MDSteps).x; 1679 if (walker->FixedIon == 0) // even FixedIon moves, only not by other's forces 1680 for (d=0; d<NDIM; d++) { 1681 FConstraint[d] = (G/E) * (U[d]*IonMass); 1682 U[d] += configuration.Deltat/IonMass * (FConstraint[d]); 1683 ekin += IonMass * U[d]*U[d]; 1684 } 1685 } 1686 break; 1687 case Langevin: 1688 cout << Verbose(2) << "Applying Langevin thermostat..." << endl; 1689 // init random number generator 1690 gsl_rng_env_setup(); 1691 T = gsl_rng_default; 1692 r = gsl_rng_alloc (T); 1693 // Go through each ion 1694 walker = start; 1695 while (walker->next != end) { // go through every atom of this element 1696 walker = walker->next; 1697 IonMass = walker->type->mass; 1698 sigma = sqrt(configuration.TargetTemp/IonMass); // sigma = (k_b T)/m (Hartree/atomicmass = atomiclength/atomictime) 1699 U = Trajectories[walker].U.at(MDSteps).x; 1700 F = Trajectories[walker].F.at(MDSteps).x; 1701 if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces 1702 // throw a dice to determine whether it gets hit by a heat bath particle 1703 if (((((rand()/(double)RAND_MAX))*configuration.TempFrequency) < 1.)) { 1704 cout << Verbose(3) << "Particle " << *walker << " was hit (sigma " << sigma << "): " << sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]) << " -> "; 1705 // pick three random numbers from a Boltzmann distribution around the desired temperature T for each momenta axis 1706 for (d=0; d<NDIM; d++) { 1707 U[d] = gsl_ran_gaussian (r, sigma); 1552 1553 // Update R (and F) 1554 for (int d=0; d<NDIM; d++) { 1555 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5]*(IsAngstroem ? AtomicLengthToAngstroem : 1.); 1556 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d]; 1557 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]); 1558 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*a*(Trajectories[walker].F.at(MDSteps).x[d]); // F = m * a and s = 0.5 * F/m * t^2 = F * a * t 1708 1559 } 1709 cout << sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]) << endl; 1710 } 1711 for (d=0; d<NDIM; d++) 1712 ekin += 0.5*IonMass * U[d]*U[d]; 1713 } 1714 } 1715 break; 1716 case Berendsen: 1717 cout << Verbose(2) << "Applying Berendsen-VanGunsteren thermostat..." << endl; 1718 walker = start; 1719 while (walker->next != end) { // go through every atom of this element 1720 walker = walker->next; 1721 IonMass = walker->type->mass; 1722 U = Trajectories[walker].U.at(MDSteps).x; 1723 F = Trajectories[walker].F.at(MDSteps).x; 1724 if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces 1725 for (d=0; d<NDIM; d++) { 1726 U[d] *= sqrt(1+(configuration.Deltat/configuration.TempFrequency)*(ScaleTempFactor-1)); 1727 ekin += 0.5*IonMass * U[d]*U[d]; 1560 // Update U 1561 for (int d=0; d<NDIM; d++) { 1562 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d]; 1563 Trajectories[walker].U.at(MDSteps).x[d] += a * (Trajectories[walker].F.at(MDSteps).x[d]+Trajectories[walker].F.at(MDSteps-1).x[d]); 1564 } 1565 // out << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1566 // for (int d=0;d<NDIM;d++) 1567 // out << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step 1568 // out << ")\t("; 1569 // for (int d=0;d<NDIM;d++) 1570 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " "; // next step 1571 // out << ")" << endl; 1572 // next atom 1573 AtomNo++; 1728 1574 } 1729 1575 } 1730 1576 } 1731 break; 1732 case NoseHoover: 1733 cout << Verbose(2) << "Applying Nose-Hoover thermostat..." << endl; 1734 // dynamically evolve alpha (the additional degree of freedom) 1735 delta_alpha = 0.; 1736 walker = start; 1737 while (walker->next != end) { // go through every atom of this element 1738 walker = walker->next; 1739 IonMass = walker->type->mass; 1740 U = Trajectories[walker].U.at(MDSteps).x; 1741 if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces 1742 for (d=0; d<NDIM; d++) { 1743 delta_alpha += U[d]*U[d]*IonMass; 1744 } 1745 } 1746 } 1747 delta_alpha = (delta_alpha - (3.*AtomCount+1.) * configuration.TargetTemp)/(configuration.HooverMass*Units2Electronmass); 1748 configuration.alpha += delta_alpha*configuration.Deltat; 1749 cout << Verbose(3) << "alpha = " << delta_alpha << " * " << configuration.Deltat << " = " << configuration.alpha << "." << endl; 1750 // apply updated alpha as additional force 1751 walker = start; 1752 while (walker->next != end) { // go through every atom of this element 1753 walker = walker->next; 1754 IonMass = walker->type->mass; 1755 U = Trajectories[walker].U.at(MDSteps).x; 1756 if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces 1757 for (d=0; d<NDIM; d++) { 1758 FConstraint[d] = - configuration.alpha * (U[d] * IonMass); 1759 U[d] += configuration.Deltat/IonMass * (FConstraint[d]); 1760 ekin += (0.5*IonMass) * U[d]*U[d]; 1761 } 1762 } 1763 } 1764 break; 1765 } 1766 cout << Verbose(1) << "Kinetic energy is " << ekin << "." << endl; 1577 } 1578 } 1579 // // correct velocities (rather momenta) so that center of mass remains motionless 1580 // for(int d=0;d<NDIM;d++) 1581 // Vector[d] = 0.; 1582 // IonMass = 0.; 1583 // walker = start; 1584 // while (walker->next != end) { // go through every atom 1585 // walker = walker->next; 1586 // IonMass += walker->type->mass; // sum up total mass 1587 // for(int d=0;d<NDIM;d++) { 1588 // Vector[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass; 1589 // } 1590 // } 1591 // walker = start; 1592 // while (walker->next != end) { // go through every atom of this element 1593 // walker = walker->next; 1594 // for(int d=0;d<NDIM;d++) { 1595 // Trajectories[walker].U.at(MDSteps).x[d] -= Vector[d]*walker->type->mass/IonMass; 1596 // } 1597 // } 1598 MDSteps++; 1599 1600 1601 // exit 1602 return true; 1767 1603 }; 1768 1604 … … 1786 1622 ptr = ptr->next; 1787 1623 tmp = ptr->x.x[0]; 1788 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1624 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1789 1625 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1790 1626 for (int j=0;j<MDSteps;j++) { 1791 1627 tmp = Trajectories[ptr].R.at(j).x[0]; 1792 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1628 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1793 1629 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1794 1630 } 1795 } 1631 } 1796 1632 // rotate n vector 1797 1633 tmp = n->x[0]; … … 1801 1637 n->Output((ofstream *)&cout); 1802 1638 cout << endl; 1803 1639 1804 1640 // rotate on z-y plane 1805 1641 ptr = start; … … 1809 1645 ptr = ptr->next; 1810 1646 tmp = ptr->x.x[1]; 1811 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1647 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1812 1648 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1813 1649 for (int j=0;j<MDSteps;j++) { 1814 1650 tmp = Trajectories[ptr].R.at(j).x[1]; 1815 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1651 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1816 1652 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1817 1653 } 1818 } 1654 } 1819 1655 // rotate n vector (for consistency check) 1820 1656 tmp = n->x[1]; 1821 1657 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1822 1658 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1823 1659 1824 1660 cout << Verbose(1) << "alignment vector after second rotation: "; 1825 1661 n->Output((ofstream *)&cout); … … 1832 1668 * \return true - succeeded, false - atom not found in list 1833 1669 */ 1834 bool molecule::RemoveAtom(atom *pointer) 1835 { 1670 bool molecule::RemoveAtom(atom *pointer) 1671 { 1836 1672 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1837 1673 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1838 1674 else 1839 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1675 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1840 1676 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1841 1677 ElementCount--; … … 1847 1683 * \return true - succeeded, false - atom not found in list 1848 1684 */ 1849 bool molecule::CleanupMolecule() 1850 { 1851 return (cleanup(start,end) && cleanup(first,last)); 1685 bool molecule::CleanupMolecule() 1686 { 1687 return (cleanup(start,end) && cleanup(first,last)); 1852 1688 }; 1853 1689 … … 1863 1699 } else { 1864 1700 cout << Verbose(0) << "Atom not found in list." << endl; 1865 return NULL; 1701 return NULL; 1866 1702 } 1867 1703 }; … … 1912 1748 struct lsq_params *par = (struct lsq_params *)params; 1913 1749 atom *ptr = par->mol->start; 1914 1750 1915 1751 // initialize vectors 1916 1752 a.x[0] = gsl_vector_get(x,0); … … 1942 1778 { 1943 1779 int np = 6; 1944 1780 1945 1781 const gsl_multimin_fminimizer_type *T = 1946 1782 gsl_multimin_fminimizer_nmsimplex; … … 1948 1784 gsl_vector *ss; 1949 1785 gsl_multimin_function minex_func; 1950 1786 1951 1787 size_t iter = 0, i; 1952 1788 int status; 1953 1789 double size; 1954 1790 1955 1791 /* Initial vertex size vector */ 1956 1792 ss = gsl_vector_alloc (np); 1957 1793 1958 1794 /* Set all step sizes to 1 */ 1959 1795 gsl_vector_set_all (ss, 1.0); 1960 1796 1961 1797 /* Starting point */ 1962 1798 par->x = gsl_vector_alloc (np); 1963 1799 par->mol = this; 1964 1800 1965 1801 gsl_vector_set (par->x, 0, 0.0); // offset 1966 1802 gsl_vector_set (par->x, 1, 0.0); … … 1969 1805 gsl_vector_set (par->x, 4, 0.0); 1970 1806 gsl_vector_set (par->x, 5, 1.0); 1971 1807 1972 1808 /* Initialize method and iterate */ 1973 1809 minex_func.f = &LeastSquareDistance; 1974 1810 minex_func.n = np; 1975 1811 minex_func.params = (void *)par; 1976 1812 1977 1813 s = gsl_multimin_fminimizer_alloc (T, np); 1978 1814 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1979 1815 1980 1816 do 1981 1817 { 1982 1818 iter++; 1983 1819 status = gsl_multimin_fminimizer_iterate(s); 1984 1820 1985 1821 if (status) 1986 1822 break; 1987 1823 1988 1824 size = gsl_multimin_fminimizer_size (s); 1989 1825 status = gsl_multimin_test_size (size, 1e-2); 1990 1826 1991 1827 if (status == GSL_SUCCESS) 1992 1828 { 1993 1829 printf ("converged to minimum at\n"); 1994 1830 } 1995 1831 1996 1832 printf ("%5d ", (int)iter); 1997 1833 for (i = 0; i < (size_t)np; i++) … … 2002 1838 } 2003 1839 while (status == GSL_CONTINUE && iter < 100); 2004 1840 2005 1841 for (i=0;i<(size_t)np;i++) 2006 1842 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); … … 2019 1855 int ElementNo, AtomNo; 2020 1856 CountElements(); 2021 1857 2022 1858 if (out == NULL) { 2023 1859 return false; … … 2054 1890 int ElementNo, AtomNo; 2055 1891 CountElements(); 2056 1892 2057 1893 if (out == NULL) { 2058 1894 return false; … … 2101 1937 atom *Walker = start; 2102 1938 while (Walker->next != end) { 2103 Walker = Walker->next; 1939 Walker = Walker->next; 2104 1940 #ifdef ADDHYDROGEN 2105 1941 if (Walker->type->Z != 1) { // regard only non-hydrogen … … 2132 1968 int No = 0; 2133 1969 time_t now; 2134 1970 2135 1971 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 2136 1972 walker = start; … … 2159 1995 { 2160 1996 atom *walker = NULL; 2161 int AtomNo = 0, ElementNo;1997 int No = 0; 2162 1998 time_t now; 2163 element *runner = NULL; 2164 1999 2165 2000 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 2166 2001 walker = start; 2167 2002 while (walker->next != end) { // go through every atom and count 2168 2003 walker = walker->next; 2169 AtomNo++;2004 No++; 2170 2005 } 2171 2006 if (out != NULL) { 2172 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now); 2173 ElementNo = 0; 2174 runner = elemente->start; 2175 while (runner->next != elemente->end) { // go through every element 2176 runner = runner->next; 2177 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 2178 ElementNo++; 2179 walker = start; 2180 while (walker->next != end) { // go through every atom of this element 2181 walker = walker->next; 2182 if (walker->type == runner) { // if this atom fits to element 2183 walker->OutputXYZLine(out); 2184 } 2185 } 2186 } 2007 *out << No << "\n\tCreated by molecuilder on " << ctime(&now); 2008 walker = start; 2009 while (walker->next != end) { // go through every atom of this element 2010 walker = walker->next; 2011 walker->OutputXYZLine(out); 2187 2012 } 2188 2013 return true; … … 2215 2040 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 2216 2041 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 2217 NoNonHydrogen++; 2042 NoNonHydrogen++; 2218 2043 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 2219 2044 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); … … 2223 2048 } 2224 2049 } else 2225 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 2050 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 2226 2051 } 2227 2052 }; … … 2235 2060 ElementsInMolecule[i] = 0; 2236 2061 ElementCount = 0; 2237 2062 2238 2063 atom *walker = start; 2239 2064 while (walker->next != end) { … … 2271 2096 Binder = Binder->next; 2272 2097 if (Binder->Cyclic) 2273 No++; 2098 No++; 2274 2099 } 2275 2100 delete(BackEdgeStack); … … 2329 2154 2330 2155 /** Creates an adjacency list of the molecule. 2331 * We obtain an outside file with the indices of atoms which are bondmembers.2332 */2333 void molecule::CreateAdjacencyList2(ofstream *out, ifstream *input)2334 {2335 2336 // 1 We will parse bonds out of the dbond file created by tremolo.2337 int atom1, atom2, temp;2338 atom *Walker, *OtherWalker;2339 2340 if (!input)2341 {2342 cout << Verbose(1) << "Opening silica failed \n";2343 };2344 2345 *input >> ws >> atom1;2346 *input >> ws >> atom2;2347 cout << Verbose(1) << "Scanning file\n";2348 while (!input->eof()) // Check whether we read everything already2349 {2350 *input >> ws >> atom1;2351 *input >> ws >> atom2;2352 if(atom2<atom1) //Sort indices of atoms in order2353 {2354 temp=atom1;2355 atom1=atom2;2356 atom2=temp;2357 };2358 2359 Walker=start;2360 while(Walker-> nr != atom1) // Find atom corresponding to first index2361 {2362 Walker = Walker->next;2363 };2364 OtherWalker = Walker->next;2365 while(OtherWalker->nr != atom2) // Find atom corresponding to second index2366 {2367 OtherWalker= OtherWalker->next;2368 };2369 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.2370 2371 }2372 2373 CreateListOfBondsPerAtom(out);2374 2375 };2376 2377 2378 /** Creates an adjacency list of the molecule.2379 2156 * Generally, we use the CSD approach to bond recognition, that is the the distance 2380 2157 * between two atoms A and B must be within [Rcov(A)+Rcov(B)-t,Rcov(A)+Rcov(B)+t] with 2381 * a threshold t = 0.4 Angstroem. 2158 * a threshold t = 0.4 Angstroem. 2382 2159 * To make it O(N log N) the function uses the linked-cell technique as follows: 2383 2160 * The procedure is step-wise: … … 2396 2173 void molecule::CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem) 2397 2174 { 2398 2399 2175 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 2400 2176 int No, NoBonds, CandidateBondNo; … … 2412 2188 cleanup(first,last); 2413 2189 } 2414 2190 2415 2191 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 2416 2192 CountAtoms(out); … … 2431 2207 for (int i=NumberCells;i--;) 2432 2208 CellList[i] = NULL; 2433 2209 2434 2210 // 2b. put all atoms into its corresponding list 2435 2211 Walker = start; … … 2452 2228 if (CellList[index] == NULL) // allocate molecule if not done 2453 2229 CellList[index] = new molecule(elemente); 2454 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 2455 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 2230 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 2231 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 2456 2232 } 2457 2233 //for (int i=0;i<NumberCells;i++) 2458 2234 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 2459 2460 2235 2461 2236 // 3a. go through every cell 2462 2237 for (N[0]=divisor[0];N[0]--;) … … 2471 2246 Walker = Walker->next; 2472 2247 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 2473 // 3c. check for possible bond between each atom in this and every one in the 27 cells 2248 // 3c. check for possible bond between each atom in this and every one in the 27 cells 2474 2249 for (n[0]=-1;n[0]<=1;n[0]++) 2475 2250 for (n[1]=-1;n[1]<=1;n[1]++) … … 2503 2278 } 2504 2279 } 2505 2506 2507 2508 2280 // 4. free the cell again 2509 2281 for (int i=NumberCells;i--;) … … 2512 2284 } 2513 2285 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 2514 2286 2515 2287 // create the adjacency list per atom 2516 2288 CreateListOfBondsPerAtom(out); 2517 2289 2518 2290 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 2519 2291 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene … … 2574 2346 *out << endl; 2575 2347 } else 2576 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 2348 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 2577 2349 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 2578 2350 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 2579 2580 }; 2581 2582 2351 }; 2583 2352 2584 2353 /** Performs a Depth-First search on this molecule. … … 2601 2370 bond *Binder = NULL; 2602 2371 bool BackStepping = false; 2603 2372 2604 2373 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 2605 2374 2606 2375 ResetAllBondsToUnused(); 2607 2376 ResetAllAtomNumbers(); … … 2616 2385 LeafWalker->Leaf = new molecule(elemente); 2617 2386 LeafWalker->Leaf->AddCopyAtom(Root); 2618 2387 2619 2388 OldGraphNr = CurrentGraphNr; 2620 2389 Walker = Root; … … 2627 2396 AtomStack->Push(Walker); 2628 2397 CurrentGraphNr++; 2629 } 2398 } 2630 2399 do { // (3) if Walker has no unused egdes, go to (5) 2631 2400 BackStepping = false; // reset backstepping flag for (8) … … 2661 2430 Binder = NULL; 2662 2431 } while (1); // (2) 2663 2432 2664 2433 // if we came from backstepping, yet there were no more unused bonds, we end up here with no Ancestor, because Walker is Root! Then we are finished! 2665 2434 if ((Walker == Root) && (Binder == NULL)) 2666 2435 break; 2667 2668 // (5) if Ancestor of Walker is ... 2436 2437 // (5) if Ancestor of Walker is ... 2669 2438 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 2670 2439 if (Walker->Ancestor->GraphNr != Root->GraphNr) { … … 2709 2478 } while (OtherAtom != Walker); 2710 2479 ComponentNumber++; 2711 2480 2712 2481 // (11) Root is separation vertex, set Walker to Root and go to (4) 2713 2482 Walker = Root; … … 2722 2491 2723 2492 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2724 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2493 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2725 2494 LeafWalker->Leaf->Output(out); 2726 2495 *out << endl; … … 2730 2499 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2731 2500 if (Root->GraphNr != -1) // if already discovered, step on 2732 Root = Root->next; 2501 Root = Root->next; 2733 2502 } 2734 2503 } … … 2752 2521 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2753 2522 } 2754 2523 2755 2524 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2756 2525 Binder = first; … … 2763 2532 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2764 2533 OutputComponentNumber(out, Binder->rightatom); 2765 *out << ">." << endl; 2534 *out << ">." << endl; 2766 2535 if (Binder->Cyclic) // cyclic ?? 2767 2536 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; … … 2778 2547 * the other our initial Walker - and do a Breadth First Search for the Root. We mark down each Predecessor and as soon as 2779 2548 * we have found the Root via BFS, we may climb back the closed cycle via the Predecessors. Thereby we mark atoms and bonds 2780 * as cyclic and print out the cycles. 2549 * as cyclic and print out the cycles. 2781 2550 * \param *out output stream for debugging 2782 2551 * \param *BackEdgeStack stack with all back edges found during DFS scan. Beware: This stack contains the bonds from the total molecule, not from the subgraph! … … 2789 2558 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2790 2559 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2791 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2560 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2792 2561 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2793 2562 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; … … 2804 2573 *out << Verbose(1) << "Back edge list - "; 2805 2574 BackEdgeStack->Output(out); 2806 2575 2807 2576 *out << Verbose(1) << "Analysing cycles ... " << endl; 2808 2577 NumCycles = 0; … … 2810 2579 BackEdge = BackEdgeStack->PopFirst(); 2811 2580 // this is the target 2812 Root = BackEdge->leftatom; 2581 Root = BackEdge->leftatom; 2813 2582 // this is the source point 2814 Walker = BackEdge->rightatom; 2583 Walker = BackEdge->rightatom; 2815 2584 ShortestPathList[Walker->nr] = 0; 2816 2585 BFSStack->ClearStack(); // start with empty BFS stack … … 2826 2595 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2827 2596 OtherAtom = Binder->GetOtherAtom(Walker); 2828 #ifdef ADDHYDROGEN 2597 #ifdef ADDHYDROGEN 2829 2598 if (OtherAtom->type->Z != 1) { 2830 2599 #endif … … 2835 2604 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2836 2605 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2837 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 2606 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 2838 2607 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2839 2608 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; … … 2845 2614 if (OtherAtom == Root) 2846 2615 break; 2847 #ifdef ADDHYDROGEN 2616 #ifdef ADDHYDROGEN 2848 2617 } else { 2849 2618 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; … … 2883 2652 } 2884 2653 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2885 2654 2886 2655 if (OtherAtom == Root) { 2887 2656 // now climb back the predecessor list and thus find the cycle members … … 2911 2680 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2912 2681 } 2913 2682 2914 2683 // now clean the lists 2915 2684 while (!TouchedStack->IsEmpty()){ … … 2921 2690 } 2922 2691 if (MinRingSize != -1) { 2923 // go over all atoms 2692 // go over all atoms 2924 2693 Root = start; 2925 2694 while(Root->next != end) { 2926 2695 Root = Root->next; 2927 2696 2928 2697 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2929 2698 Walker = Root; … … 2962 2731 } 2963 2732 ColorList[Walker->nr] = black; 2964 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2733 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2965 2734 } 2966 2735 2967 2736 // now clean the lists 2968 2737 while (!TouchedStack->IsEmpty()){ … … 3013 2782 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 3014 2783 { 3015 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2784 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 3016 2785 *out << vertex->ComponentNr[i] << " "; 3017 2786 }; … … 3091 2860 { 3092 2861 int c = 0; 3093 int FragmentCount; 2862 int FragmentCount; 3094 2863 // get maximum bond degree 3095 2864 atom *Walker = start; … … 3101 2870 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 3102 2871 return FragmentCount; 3103 }; 2872 }; 3104 2873 3105 2874 /** Scans a single line for number and puts them into \a KeySet. 3106 2875 * \param *out output stream for debugging 3107 2876 * \param *buffer buffer to scan 3108 * \param &CurrentSet filled KeySet on return 2877 * \param &CurrentSet filled KeySet on return 3109 2878 * \return true - at least one valid atom id parsed, false - CurrentSet is empty 3110 2879 */ … … 3114 2883 int AtomNr; 3115 2884 int status = 0; 3116 2885 3117 2886 line.str(buffer); 3118 2887 while (!line.eof()) { … … 3150 2919 double TEFactor; 3151 2920 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 3152 2921 3153 2922 if (FragmentList == NULL) { // check list pointer 3154 2923 FragmentList = new Graph; 3155 2924 } 3156 2925 3157 2926 // 1st pass: open file and read 3158 2927 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; … … 3183 2952 status = false; 3184 2953 } 3185 2954 3186 2955 // 2nd pass: open TEFactors file and read 3187 2956 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; … … 3195 2964 InputFile >> TEFactor; 3196 2965 (*runner).second.second = TEFactor; 3197 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2966 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 3198 2967 } else { 3199 2968 status = false; … … 3236 3005 if(output != NULL) { 3237 3006 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 3238 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 3007 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 3239 3008 if (sprinter != (*runner).first.begin()) 3240 3009 output << "\t"; … … 3302 3071 status = false; 3303 3072 } 3304 3073 3305 3074 return status; 3306 3075 }; … … 3311 3080 * \param **ListOfAtoms allocated (molecule::AtomCount) and filled lookup table for ids (Atom::nr) to *Atom 3312 3081 * \return true - structure is equal, false - not equivalence 3313 */ 3082 */ 3314 3083 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 3315 3084 { … … 3318 3087 bool status = true; 3319 3088 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 3320 3089 3321 3090 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 3322 3091 File.open(filename.str().c_str(), ios::out); … … 3377 3146 *out << endl; 3378 3147 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 3379 3148 3380 3149 return status; 3381 3150 }; … … 3399 3168 for(int i=AtomCount;i--;) 3400 3169 AtomMask[i] = false; 3401 3170 3402 3171 if (Order < 0) { // adaptive increase of BondOrder per site 3403 3172 if (AtomMask[AtomCount] == true) // break after one step … … 3439 3208 line >> ws >> Value; // skip time entry 3440 3209 line >> ws >> Value; 3441 No -= 1; // indices start at 1 in file, not 0 3210 No -= 1; // indices start at 1 in file, not 0 3442 3211 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 3443 3212 … … 3448 3217 // as the smallest number in each set has always been the root (we use global id to keep the doubles away), seek smallest and insert into AtomMask 3449 3218 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 3450 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 3219 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 3451 3220 if (!InsertedElement.second) { // this root is already present 3452 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 3453 //if ((*PresentItem).second.first < (*runner).first) // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase) 3221 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 3222 //if ((*PresentItem).second.first < (*runner).first) // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase) 3454 3223 { // if value is smaller, update value and order 3455 3224 (*PresentItem).second.first = fabs(Value); … … 3489 3258 Walker = FindAtom(No); 3490 3259 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 3491 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 3260 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 3492 3261 AtomMask[No] = true; 3493 3262 status = true; 3494 3263 //} else 3495 //*out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->nr] << " does not allow further adaptive increase." << endl; 3264 //*out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->nr] << " does not allow further adaptive increase." << endl; 3496 3265 } 3497 3266 // close and done … … 3527 3296 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 3528 3297 status = true; 3529 3298 3530 3299 if (!status) { 3531 3300 if (Order == 0) … … 3535 3304 } 3536 3305 } 3537 3306 3538 3307 // print atom mask for debugging 3539 3308 *out << " "; … … 3544 3313 *out << (AtomMask[i] ? "t" : "f"); 3545 3314 *out << endl; 3546 3315 3547 3316 return status; 3548 3317 }; … … 3558 3327 int AtomNo = 0; 3559 3328 atom *Walker = NULL; 3560 3329 3561 3330 if (SortIndex != NULL) { 3562 3331 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; … … 3616 3385 atom **ListOfAtoms = NULL; 3617 3386 atom ***ListOfLocalAtoms = NULL; 3618 bool *AtomMask = NULL; 3619 3387 bool *AtomMask = NULL; 3388 3620 3389 *out << endl; 3621 3390 #ifdef ADDHYDROGEN … … 3626 3395 3627 3396 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 3628 3397 3629 3398 // ===== 1. Check whether bond structure is same as stored in files ==== 3630 3399 3631 3400 // fill the adjacency list 3632 3401 CreateListOfBondsPerAtom(out); … … 3634 3403 // create lookup table for Atom::nr 3635 3404 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 3636 3405 3637 3406 // === compare it with adjacency file === 3638 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 3407 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 3639 3408 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 3640 3409 … … 3659 3428 // else 3660 3429 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name; 3661 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3662 3430 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 3663 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3664 3431 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize); 3665 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3666 3432 delete(LocalBackEdgeStack); 3667 3433 } … … 3685 3451 FragmentationToDo = FragmentationToDo || CheckOrder; 3686 3452 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 3687 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3453 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3688 3454 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 3689 3455 … … 3694 3460 MolecularWalker = MolecularWalker->next; 3695 3461 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl; 3696 //MolecularWalker->Leaf->OutputListOfBonds(out); // output ListOfBondsPerAtom for debugging 3462 // output ListOfBondsPerAtom for debugging 3463 MolecularWalker->Leaf->OutputListOfBonds(out); 3697 3464 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) { 3465 3698 3466 // call BOSSANOVA method 3699 3467 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl; … … 3715 3483 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3716 3484 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3717 3485 3718 3486 // free subgraph memory again 3719 3487 FragmentCounter = 0; … … 3740 3508 } 3741 3509 *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl; 3742 3510 3743 3511 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3744 3512 if (BondFragments->NumberOfMolecules != 0) { 3745 3513 // create the SortIndex from BFS labels to order in the config file 3746 3514 CreateMappingLabelsToConfigSequence(out, SortIndex); 3747 3515 3748 3516 *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl; 3749 3517 if (BondFragments->OutputConfigForListOfFragments(out, FRAGMENTPREFIX, configuration, SortIndex, true, true)) … … 3751 3519 else 3752 3520 *out << Verbose(1) << "Some config writing failed." << endl; 3753 3521 3754 3522 // store force index reference file 3755 3523 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3756 3757 // store keysets file 3524 3525 // store keysets file 3758 3526 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3759 3760 // store Adjacency file 3527 3528 // store Adjacency file 3761 3529 StoreAdjacencyToFile(out, configuration->configpath); 3762 3530 3763 3531 // store Hydrogen saturation correction file 3764 3532 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3765 3533 3766 3534 // store adaptive orders into file 3767 3535 StoreOrderAtSiteFile(out, configuration->configpath); 3768 3536 3769 3537 // restore orbital and Stop values 3770 3538 CalculateOrbitals(*configuration); 3771 3539 3772 3540 // free memory for bond part 3773 3541 *out << Verbose(1) << "Freeing bond memory" << endl; 3774 3542 delete(FragmentList); // remove bond molecule from memory 3775 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3543 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3776 3544 } else 3777 3545 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3778 //} else 3546 //} else 3779 3547 // *out << Verbose(1) << "No fragments to store." << endl; 3780 3548 *out << Verbose(0) << "End of bond fragmentation." << endl; … … 3805 3573 do { // go through all bonds and push local ones 3806 3574 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3807 if (Walker != NULL) // if this Walker exists in the subgraph ...3808 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds3809 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);3810 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond 3811 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);3812 *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl;3813 3814 3815 3575 if (Walker == NULL) // if this Walker exists in the subgraph ... 3576 continue; 3577 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds 3578 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3579 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond 3580 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]); 3581 break; 3582 } 3583 } 3816 3584 Binder = ReferenceStack->PopFirst(); // loop the stack for next item 3817 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl;3818 3585 ReferenceStack->Push(Binder); 3819 3586 } while (FirstBond != Binder); … … 3894 3661 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3895 3662 Walker->MaxOrder = MaxArray[Walker->nr]; 3896 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3663 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3897 3664 } 3898 3665 file.close(); … … 3905 3672 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3906 3673 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3907 3674 3908 3675 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3909 3676 return status; … … 3971 3738 } 3972 3739 *out << " -- TotalDegree: " << TotalDegree << endl; 3973 } 3740 } 3974 3741 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3975 3742 }; … … 3977 3744 /** Adds atoms up to \a BondCount distance from \a *Root and notes them down in \a **AddedAtomList. 3978 3745 * Gray vertices are always enqueued in an StackClass<atom *> FIFO queue, the rest is usual BFS with adding vertices found was 3979 * white and putting into queue. 3746 * white and putting into queue. 3980 3747 * \param *out output stream for debugging 3981 3748 * \param *Mol Molecule class to add atoms to … … 3986 3753 * \param BondOrder maximum distance for vertices to add 3987 3754 * \param IsAngstroem lengths are in angstroem or bohrradii 3988 */ 3755 */ 3989 3756 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3990 3757 { … … 4012 3779 } 4013 3780 ShortestPathList[Root->nr] = 0; 4014 3781 4015 3782 // and go on ... Queue always contains all lightgray vertices 4016 3783 while (!AtomStack->IsEmpty()) { … … 4020 3787 // followed by n+1 till top of stack. 4021 3788 Walker = AtomStack->PopFirst(); // pop oldest added 4022 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3789 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 4023 3790 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 4024 3791 Binder = ListOfBondsPerAtom[Walker->nr][i]; … … 4027 3794 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 4028 3795 if (ColorList[OtherAtom->nr] == white) { 4029 if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem) 3796 if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem) 4030 3797 ColorList[OtherAtom->nr] = lightgray; 4031 3798 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 4032 3799 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 4033 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 3800 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 4034 3801 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 4035 3802 *out << Verbose(3); … … 4069 3836 } else { 4070 3837 #ifdef ADDHYDROGEN 4071 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 4072 exit(1); 3838 Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem); 4073 3839 #endif 4074 3840 } … … 4079 3845 // This has to be a cyclic bond, check whether it's present ... 4080 3846 if (AddedBondList[Binder->nr] == NULL) { 4081 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3847 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 4082 3848 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 4083 3849 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; … … 4085 3851 } else { // if it's root bond it has to broken (otherwise we would not create the fragments) 4086 3852 #ifdef ADDHYDROGEN 4087 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 4088 exit(1); 3853 Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem); 4089 3854 #endif 4090 3855 } … … 4094 3859 } 4095 3860 ColorList[Walker->nr] = black; 4096 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3861 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 4097 3862 } 4098 3863 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); … … 4118 3883 4119 3884 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 4120 3885 4121 3886 // reset parent list 4122 3887 *out << Verbose(3) << "Resetting ParentList." << endl; 4123 3888 for (int i=Father->AtomCount;i--;) 4124 3889 ParentList[i] = NULL; 4125 3890 4126 3891 // fill parent list with sons 4127 3892 *out << Verbose(3) << "Filling Parent List." << endl; … … 4164 3929 * \param *&Leaf KeySet to look through 4165 3930 * \param *&ShortestPathList list of the shortest path to decide which atom to suggest as removal candidate in the end 4166 * \param index of the atom suggested for removal 3931 * \param index of the atom suggested for removal 4167 3932 */ 4168 3933 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) … … 4170 3935 atom *Runner = NULL; 4171 3936 int SP, Removal; 4172 3937 4173 3938 *out << Verbose(2) << "Looking for removal candidate." << endl; 4174 3939 SP = -1; //0; // not -1, so that Root is never removed … … 4188 3953 /** Stores a fragment from \a KeySet into \a molecule. 4189 3954 * First creates the minimal set of atoms from the KeySet, then creates the bond structure from the complete 4190 * molecule and adds missing hydrogen where bonds were cut. 3955 * molecule and adds missing hydrogen where bonds were cut. 4191 3956 * \param *out output stream for debugging messages 4192 * \param &Leaflet pointer to KeySet structure 3957 * \param &Leaflet pointer to KeySet structure 4193 3958 * \param IsAngstroem whether we have Ansgtroem or bohrradius 4194 3959 * \return pointer to constructed molecule … … 4201 3966 bool LonelyFlag = false; 4202 3967 int size; 4203 3968 4204 3969 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 4205 3970 4206 3971 Leaf->BondDistance = BondDistance; 4207 3972 for(int i=NDIM*2;i--;) 4208 Leaf->cell_size[i] = cell_size[i]; 3973 Leaf->cell_size[i] = cell_size[i]; 4209 3974 4210 3975 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) … … 4219 3984 size++; 4220 3985 } 4221 3986 4222 3987 // create the bonds between all: Make it an induced subgraph and add hydrogen 4223 3988 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; … … 4229 3994 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 4230 3995 // create all bonds 4231 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3996 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 4232 3997 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 4233 3998 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 4234 3999 if (SonList[OtherFather->nr] != NULL) { 4235 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 4000 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 4236 4001 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 4237 4002 // *out << Verbose(3) << "Adding Bond: "; 4238 // *out << 4003 // *out << 4239 4004 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 4240 4005 // *out << "." << endl; 4241 4006 //NumBonds[Runner->nr]++; 4242 } else { 4007 } else { 4243 4008 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 4244 4009 } 4245 4010 LonelyFlag = false; 4246 4011 } else { 4247 // *out << ", who has no son in this fragment molecule." << endl; 4012 // *out << ", who has no son in this fragment molecule." << endl; 4248 4013 #ifdef ADDHYDROGEN 4249 4014 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; 4250 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem)) 4251 exit(1); 4015 Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem); 4252 4016 #endif 4253 4017 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree; … … 4263 4027 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 4264 4028 Runner = Runner->next; 4265 #endif 4029 #endif 4266 4030 } 4267 4031 Leaf->CreateListOfBondsPerAtom(out); … … 4296 4060 StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself 4297 4061 StackClass<atom *> *SnakeStack = new StackClass<atom *>(Order+1); // equal to Order is not possible, as then the StackClass<atom *> cannot discern between full and empty stack! 4298 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 4062 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 4299 4063 MoleculeListClass *FragmentList = NULL; 4300 4064 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL; … … 4346 4110 // clear snake stack 4347 4111 SnakeStack->ClearStack(); 4348 //SnakeStack->TestImplementation(out, start->next); 4112 //SnakeStack->TestImplementation(out, start->next); 4349 4113 4350 4114 ///// INNER LOOP //////////// … … 4367 4131 } 4368 4132 if (ShortestPathList[Walker->nr] == -1) { 4369 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 4133 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 4370 4134 TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed 4371 4135 } … … 4405 4169 OtherAtom = Binder->GetOtherAtom(Walker); 4406 4170 if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us 4407 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 4171 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 4408 4172 //ColorVertexList[OtherAtom->nr] = lightgray; // mark as explored 4409 4173 } else { // otherwise check its colour and element 4410 4174 if ( 4411 4175 #ifdef ADDHYDROGEN 4412 (OtherAtom->type->Z != 1) && 4176 (OtherAtom->type->Z != 1) && 4413 4177 #endif 4414 4178 (ColorEdgeList[Binder->nr] == white)) { // skip hydrogen, look for unexplored vertices … … 4420 4184 //} else { 4421 4185 // *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl; 4422 //} 4186 //} 4423 4187 Walker = OtherAtom; 4424 4188 break; 4425 4189 } else { 4426 if (OtherAtom->type->Z == 1) 4190 if (OtherAtom->type->Z == 1) 4427 4191 *out << "Links to a hydrogen atom." << endl; 4428 else 4192 else 4429 4193 *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl; 4430 4194 } … … 4436 4200 *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl; 4437 4201 } 4438 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 4202 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 4439 4203 *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl; 4440 4204 ColorVertexList[Walker->nr] = black; … … 4443 4207 } 4444 4208 } while ((Walker != Root) || (ColorVertexList[Root->nr] != black)); 4445 *out << Verbose(2) << "Inner Looping is finished." << endl; 4209 *out << Verbose(2) << "Inner Looping is finished." << endl; 4446 4210 4447 4211 // if we reset all AtomCount atoms, we have again technically O(N^2) ... … … 4459 4223 } 4460 4224 } 4461 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 4225 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 4462 4226 4463 4227 // copy together 4464 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 4228 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 4465 4229 FragmentList = new MoleculeListClass(FragmentCounter, AtomCount); 4466 4230 RunningIndex = 0; … … 4533 4297 4534 4298 NumCombinations = 1 << SetDimension; 4535 4299 4536 4300 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 4537 4301 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 4538 4302 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 4539 4303 4540 4304 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 4541 4305 *out << Verbose(1+verbosity) << "We are " << RootDistance << " away from Root, which is " << *FragmentSearch->Root << ", SubOrder is " << SubOrder << ", SetDimension is " << SetDimension << " and this means " << NumCombinations-1 << " combination(s)." << endl; 4542 4306 4543 // initialised touched list (stores added atoms on this level) 4307 // initialised touched list (stores added atoms on this level) 4544 4308 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 4545 4309 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 4546 4310 TouchedList[TouchedIndex] = -1; 4547 4311 TouchedIndex = 0; 4548 4312 4549 4313 // create every possible combination of the endpieces 4550 4314 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; … … 4554 4318 for (int j=SetDimension;j--;) 4555 4319 bits += (i & (1 << j)) >> j; 4556 4320 4557 4321 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 4558 4322 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue … … 4562 4326 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 4563 4327 if (bit) { // if bit is set, we add this bond partner 4564 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 4328 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 4565 4329 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 4566 4330 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 4567 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 4331 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 4568 4332 if (TestKeySetInsert.second) { 4569 4333 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added … … 4578 4342 } 4579 4343 } 4580 4581 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 4344 4345 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 4582 4346 if (SpaceLeft > 0) { 4583 4347 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; … … 4607 4371 } 4608 4372 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 4609 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 4373 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 4610 4374 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 4611 4375 } … … 4616 4380 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 4617 4381 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 4618 *out << (*runner) << " "; 4382 *out << (*runner) << " "; 4619 4383 *out << endl; 4620 4384 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) … … 4624 4388 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 4625 4389 } 4626 4390 4627 4391 // --3-- remove all added items in this level from snake stack 4628 4392 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; … … 4635 4399 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 4636 4400 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 4637 *out << (*runner) << " "; 4401 *out << (*runner) << " "; 4638 4402 *out << endl; 4639 4403 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level … … 4642 4406 } 4643 4407 } 4644 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 4408 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 4645 4409 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 4646 4410 }; … … 4651 4415 * \return true - connected, false - disconnected 4652 4416 * \note this is O(n^2) for it's just a bug checker not meant for permanent use! 4653 */ 4417 */ 4654 4418 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 4655 4419 { … … 4657 4421 bool BondStatus = false; 4658 4422 int size; 4659 4423 4660 4424 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 4661 4425 *out << Verbose(2) << "Disconnected atom: "; 4662 4426 4663 4427 // count number of atoms in graph 4664 4428 size = 0; … … 4706 4470 * \param *out output stream for debugging 4707 4471 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation 4708 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4472 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4709 4473 * \param RestrictedKeySet Restricted vertex set to use in context of molecule 4710 4474 * \return number of inserted fragments 4711 4475 * \note ShortestPathList in FragmentSearch structure is probably due to NumberOfAtomsSPLevel and SP not needed anymore 4712 4476 */ 4713 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4477 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4714 4478 { 4715 4479 int SP, AtomKeyNr; … … 4732 4496 FragmentSearch.BondsPerSPCount[i] = 0; 4733 4497 FragmentSearch.BondsPerSPCount[0] = 1; 4734 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4498 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4735 4499 add(Binder, FragmentSearch.BondsPerSPList[1]); 4736 4500 4737 4501 // do a BFS search to fill the SP lists and label the found vertices 4738 4502 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 4739 4503 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 4740 4504 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 4741 // (EdgeinSPLevel) of this tree ... 4505 // (EdgeinSPLevel) of this tree ... 4742 4506 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 4743 4507 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. … … 4792 4556 } 4793 4557 } 4794 4558 4795 4559 // outputting all list for debugging 4796 4560 *out << Verbose(0) << "Printing all found lists." << endl; … … 4801 4565 Binder = Binder->next; 4802 4566 *out << Verbose(2) << *Binder << endl; 4803 } 4804 } 4805 4567 } 4568 } 4569 4806 4570 // creating fragments with the found edge sets (may be done in reverse order, faster) 4807 4571 SP = -1; // the Root <-> Root edge must be subtracted! … … 4810 4574 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4811 4575 Binder = Binder->next; 4812 SP ++; 4576 SP ++; 4813 4577 } 4814 4578 } … … 4817 4581 // start with root (push on fragment stack) 4818 4582 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4819 FragmentSearch.FragmentSet->clear(); 4583 FragmentSearch.FragmentSet->clear(); 4820 4584 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4821 4585 // prepare the subset and call the generator 4822 4586 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4823 4587 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4824 4588 4825 4589 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4826 4590 4827 4591 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4828 4592 } else { … … 4833 4597 // remove root from stack 4834 4598 *out << Verbose(0) << "Removing root again from stack." << endl; 4835 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4599 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4836 4600 4837 4601 // free'ing the bonds lists … … 4852 4616 } 4853 4617 4854 // return list 4618 // return list 4855 4619 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4856 4620 return (FragmentSearch.FragmentCounter - Counter); … … 4883 4647 // remove bonds that are beyond bonddistance 4884 4648 for(int i=NDIM;i--;) 4885 Translationvector.x[i] = 0.; 4649 Translationvector.x[i] = 0.; 4886 4650 // scan all bonds 4887 4651 Binder = first; … … 4930 4694 } 4931 4695 } 4932 // re-add bond 4696 // re-add bond 4933 4697 link(Binder, OtherBinder); 4934 4698 } else { … … 4984 4748 IteratorB++; 4985 4749 } // end of while loop 4986 }// end of check in case of equal sizes 4750 }// end of check in case of equal sizes 4987 4751 } 4988 4752 return false; // if we reach this point, they are equal … … 5028 4792 * \param graph1 first (dest) graph 5029 4793 * \param graph2 second (source) graph 5030 * \param *counter keyset counter that gets increased 4794 * \param *counter keyset counter that gets increased 5031 4795 */ 5032 4796 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) … … 5073 4837 int RootKeyNr, RootNr; 5074 4838 struct UniqueFragments FragmentSearch; 5075 4839 5076 4840 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 5077 4841 … … 5096 4860 Walker = Walker->next; 5097 4861 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 5098 } 4862 } 5099 4863 5100 4864 // this can easily be seen: if Order is 5, then the number of levels for each lower order is the total sum of the number of levels above, as … … 5110 4874 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 5111 4875 // *out << Verbose(0) << "Bond order " << Walker->GetTrueFather()->AdaptiveOrder << " of Root " << *Walker << " greater than or equal to Minimum Ring size of " << MinimumRingSize << " found is not allowed." << endl; 5112 //} else 4876 //} else 5113 4877 { 5114 4878 // increase adaptive order by one 5115 4879 Walker->GetTrueFather()->AdaptiveOrder++; 5116 4880 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 5117 4881 5118 4882 // initialise Order-dependent entries of UniqueFragments structure 5119 4883 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); … … 5122 4886 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 5123 4887 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 5124 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4888 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 5125 4889 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 5126 4890 FragmentSearch.BondsPerSPCount[i] = 0; 5127 } 5128 4891 } 4892 5129 4893 // allocate memory for all lower level orders in this 1D-array of ptrs 5130 4894 NumLevels = 1 << (Order-1); // (int)pow(2,Order); … … 5132 4896 for (int i=0;i<NumLevels;i++) 5133 4897 FragmentLowerOrdersList[RootNr][i] = NULL; 5134 4898 5135 4899 // create top order where nothing is reduced 5136 4900 *out << Verbose(0) << "==============================================================================================================" << endl; 5137 4901 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 5138 4902 5139 4903 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 5140 4904 FragmentLowerOrdersList[RootNr][0] = new Graph; … … 5149 4913 // we don't have to dive into suborders! These keysets are all already created on lower orders! 5150 4914 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 5151 4915 5152 4916 // if ((NumLevels >> 1) > 0) { 5153 4917 // // create lower order fragments … … 5156 4920 // for (int source=0;source<(NumLevels >> 1);source++) { // 1-terms don't need any more splitting, that's why only half is gone through (shift again) 5157 4921 // // step down to next order at (virtual) boundary of powers of 2 in array 5158 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4922 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 5159 4923 // Order--; 5160 4924 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; … … 5163 4927 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 5164 4928 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 5165 // 4929 // 5166 4930 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 5167 4931 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; … … 5194 4958 RootStack.push_back(RootKeyNr); // put back on stack 5195 4959 RootNr++; 5196 4960 5197 4961 // free Order-dependent entries of UniqueFragments structure for next loop cycle 5198 4962 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); … … 5200 4964 delete(FragmentSearch.BondsPerSPList[2*i]); 5201 4965 delete(FragmentSearch.BondsPerSPList[2*i+1]); 5202 } 4966 } 5203 4967 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 5204 4968 } … … 5211 4975 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 5212 4976 delete(FragmentSearch.FragmentSet); 5213 5214 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4977 4978 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 5215 4979 // 5433222211111111 5216 4980 // 43221111 … … 5232 4996 RootKeyNr = RootStack.front(); 5233 4997 RootStack.pop_front(); 5234 Walker = FindAtom(RootKeyNr); 4998 Walker = FindAtom(RootKeyNr); 5235 4999 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 5236 5000 for(int i=0;i<NumLevels;i++) { … … 5245 5009 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 5246 5010 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 5247 5011 5248 5012 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 5249 5013 }; … … 5279 5043 atom *Walker = NULL; 5280 5044 bool result = true; // status of comparison 5281 5282 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 5045 5046 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 5283 5047 /// first count both their atoms and elements and update lists thereby ... 5284 5048 //*out << Verbose(0) << "Counting atoms, updating list" << endl; … … 5327 5091 if (CenterOfGravity.Distance(&OtherCenterOfGravity) > threshold) { 5328 5092 *out << Verbose(4) << "Centers of gravity don't match." << endl; 5329 result = false; 5330 } 5331 } 5332 5093 result = false; 5094 } 5095 } 5096 5333 5097 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 5334 5098 if (result) { … … 5346 5110 OtherDistances[Walker->nr] = OtherCenterOfGravity.Distance(&Walker->x); 5347 5111 } 5348 5112 5349 5113 /// ... sort each list (using heapsort (o(N log N)) from GSL) 5350 5114 *out << Verbose(5) << "Sorting distances" << endl; … … 5357 5121 for(int i=AtomCount;i--;) 5358 5122 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 5359 5123 5360 5124 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 5361 5125 *out << Verbose(4) << "Comparing distances" << endl; … … 5368 5132 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 5369 5133 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 5370 5134 5371 5135 /// free memory 5372 5136 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); … … 5376 5140 result = false; 5377 5141 } 5378 } 5142 } 5379 5143 /// return pointer to map if all distances were below \a threshold 5380 5144 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; … … 5385 5149 *out << Verbose(3) << "Result: Not equal." << endl; 5386 5150 return NULL; 5387 } 5151 } 5388 5152 }; 5389 5153 … … 5440 5204 * \param *output output stream of temperature file 5441 5205 * \return file written (true), failure on writing file (false) 5442 */ 5206 */ 5443 5207 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 5444 5208 { … … 5448 5212 if (output == NULL) 5449 5213 return false; 5450 else 5214 else 5451 5215 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 5452 5216 for (int step=startstep;step < endstep; step++) { // loop over all time steps -
Property mode
changed from
-
src/molecules.hpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 1 1 /** \file molecules.hpp 2 2 * 3 * Class definitions of atom and molecule, element and periodentafel 3 * Class definitions of atom and molecule, element and periodentafel 4 4 */ 5 5 … … 16 16 #include <gsl/gsl_multimin.h> 17 17 #include <gsl/gsl_vector.h> 18 #include <gsl/gsl_randist.h>19 18 20 19 // STL headers … … 56 55 #define BoundariesTestPair pair< Boundaries::iterator, bool> 57 56 58 #define PointMap map < int, class BoundaryPointSet * > 59 #define PointPair pair < int, class BoundaryPointSet * > 60 #define PointTestPair pair < PointMap::iterator, bool > 61 62 #define LineMap map < int, class BoundaryLineSet * > 63 #define LinePair pair < int, class BoundaryLineSet * > 64 #define LineTestPair pair < Line Map::iterator, bool >65 66 #define TriangleMap map < int, class BoundaryTriangleSet * > 67 #define TrianglePair pair < int, class BoundaryTriangleSet * > 68 #define TriangleTestPair pair < TrianglePair::iterator, bool > 57 #define PointMap map < int, class BoundaryPointSet * > 58 #define PointPair pair < int, class BoundaryPointSet * > 59 #define PointTestPair pair < PointMap::iterator, bool > 60 61 #define LineMap map < int, class BoundaryLineSet * > 62 #define LinePair pair < int, class BoundaryLineSet * > 63 #define LineTestPair pair < LinePair::iterator, bool > 64 65 #define TriangleMap map < int, class BoundaryTriangleSet * > 66 #define TrianglePair pair < int, class BoundaryTriangleSet * > 67 #define TriangleTestPair pair < TrianglePair::iterator, bool > 69 68 70 69 #define DistanceMultiMap multimap <double, pair < PointMap::iterator, PointMap::iterator> > … … 88 87 //bool operator < (KeySet SubgraphA, KeySet SubgraphB); //note: this declaration is important, otherwise normal < is used (producing wrong order) 89 88 inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment); // Insert a KeySet into a Graph 90 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter); // Insert all KeySet's in a Graph into another Graph 89 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter); // Insert all KeySet's in a Graph into another Graph 91 90 int CompareDoubles (const void * a, const void * b); 92 91 … … 142 141 unsigned char AdaptiveOrder; //!< current present bond order at site (0 means "not set") 143 142 bool MaxOrder; //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not 144 143 145 144 atom(); 146 145 ~atom(); 147 146 148 147 bool Output(int ElementNo, int AtomNo, ofstream *out) const; 149 148 bool OutputXYZLine(ofstream *out) const; 150 149 atom *GetTrueFather(); 151 150 bool Compare(atom &ptr); 152 151 153 152 private: 154 153 }; 155 154 156 ostream & operator << (ostream &ost, constatom &a);155 ostream & operator << (ostream &ost, atom &a); 157 156 158 157 /** Bonds between atoms. … … 171 170 int nr; //!< unique number in a molecule, updated by molecule::CreateAdjacencyList() 172 171 bool Cyclic; //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis() 173 enum EdgeType Type;//!< whether this is a tree or back edge 174 172 enum EdgeType Type;//!< whether this is a tree or back edge 173 175 174 atom * GetOtherAtom(atom *Atom) const; 176 175 bond * GetFirstBond(); 177 176 bond * GetLastBond(); 178 177 179 178 bool MarkUsed(enum Shading color); 180 179 enum Shading IsUsed(); … … 182 181 bool Contains(const atom *ptr); 183 182 bool Contains(const int nr); 184 183 185 184 bond(); 186 185 bond(atom *left, atom *right); … … 188 187 bond(atom *left, atom *right, int degree, int number); 189 188 ~bond(); 190 191 private: 189 190 private: 192 191 enum Shading Used; //!< marker in depth-first search, DepthFirstSearchAnalysis() 193 192 }; 194 193 195 196 ostream & operator << (ostream &ost, const bond &b); 194 ostream & operator << (ostream &ost, bond &b); 197 195 198 196 class MoleculeLeafClass; 199 200 201 #define MaxThermostats 6 //!< maximum number of thermostat entries in Ions#ThermostatNames and Ions#ThermostatImplemented202 enum thermostats { None, Woodcock, Gaussian, Langevin, Berendsen, NoseHoover }; //!< Thermostat names for output203 204 197 205 198 /** The complete molecule. … … 226 219 int NoCyclicBonds; //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis() 227 220 double BondDistance; //!< typical bond distance used in CreateAdjacencyList() and furtheron 228 221 229 222 molecule(periodentafel *teil); 230 223 ~molecule(); 231 224 232 225 /// remove atoms from molecule. 233 226 bool AddAtom(atom *pointer); … … 238 231 atom * AddCopyAtom(atom *pointer); 239 232 bool AddXYZFile(string filename); 240 bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem); 233 bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem); 241 234 bond * AddBond(atom *first, atom *second, int degree); 242 235 bool RemoveBond(bond *pointer); 243 236 bool RemoveBonds(atom *BondPartner); 244 237 245 238 /// Find atoms. 246 atom * FindAtom(int Nr) const; 239 atom * FindAtom(int Nr) const; 247 240 atom * AskAtom(string text); 248 241 … … 252 245 void CalculateOrbitals(class config &configuration); 253 246 bool CenterInBox(ofstream *out, Vector *BoxLengths); 254 void CenterEdge(ofstream *out, Vector *max); 255 void CenterOrigin(ofstream *out, Vector *max); 247 void CenterEdge(ofstream *out, Vector *max); 248 void CenterOrigin(ofstream *out, Vector *max); 256 249 void CenterGravity(ofstream *out, Vector *max); 257 250 void Translate(const Vector *x); … … 267 260 void PrincipalAxisSystem(ofstream *out, bool DoRotate); 268 261 double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem); 269 270 bool VerletForceIntegration(ofstream *out, char *file, config &configuration); 271 void Thermostats(config &configuration, double ActualTemp, int Thermostat); 272 273 double ConstrainedPotential(ofstream *out, atom **permutation, int start, int end, double *constants, bool IsAngstroem); 274 double MinimiseConstrainedPotential(ofstream *out, atom **&permutation, int startstep, int endstep, bool IsAngstroem); 275 void EvaluateConstrainedForces(ofstream *out, int startstep, int endstep, atom **PermutationMap, ForceMatrix *Force); 276 bool LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration); 262 bool VerletForceIntegration(ofstream *out, char *file, double delta_t, bool IsAngstroem, int DoConstrained); 263 double ConstrainedPotential(ofstream *out, atom **permutation, int start, int end, double *constants, bool IsAngstroem); 264 double MinimiseConstrainedPotential(ofstream *out, atom **&permutation, int startstep, int endstep, bool IsAngstroem); 265 void EvaluateConstrainedForces(ofstream *out, int startstep, int endstep, atom **PermutationMap, ForceMatrix *Force); 266 bool LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration); 277 267 278 268 bool CheckBounds(const Vector *x) const; 279 269 void GetAlignvector(struct lsq_params * par) const; 280 270 281 /// Initialising routines in fragmentation 282 void CreateAdjacencyList2(ofstream *out, ifstream *output); 271 /// Initialising routines in fragmentation 283 272 void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem); 284 273 void CreateListOfBondsPerAtom(ofstream *out); 285 274 286 275 // Graph analysis 287 276 MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack); … … 299 288 300 289 molecule *CopyMolecule(); 301 290 302 291 /// Fragment molecule by two different approaches: 303 292 int FragmentMolecule(ofstream *out, int Order, config *configuration); … … 321 310 int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList); 322 311 int GuesstimateFragmentCount(ofstream *out, int order); 323 324 // Recognize doubly appearing molecules in a list of them 312 313 // Recognize doubly appearing molecules in a list of them 325 314 int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold); 326 315 int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule); 327 316 328 317 // Output routines. 329 318 bool Output(ofstream *out); … … 346 335 int NumberOfMolecules; //!< Number of entries in \a **FragmentList and of to be returned one. 347 336 int NumberOfTopAtoms; //!< Number of atoms in the molecule from which all fragments originate 348 337 349 338 MoleculeListClass(); 350 339 MoleculeListClass(int Num, int NumAtoms); … … 356 345 bool OutputConfigForListOfFragments(ofstream *out, const char *fragmentprefix, config *configuration, int *SortIndex, bool DoPeriodic, bool DoCentering); 357 346 void Output(ofstream *out); 358 347 359 348 private: 360 349 }; … … 366 355 class MoleculeLeafClass { 367 356 public: 368 molecule *Leaf; //!< molecule of this leaf 357 molecule *Leaf; //!< molecule of this leaf 369 358 //MoleculeLeafClass *UpLeaf; //!< Leaf one level up 370 359 //MoleculeLeafClass *DownLeaf; //!< First leaf one level down … … 402 391 bool FastParsing; 403 392 double Deltat; 404 string basis;405 406 393 int DoConstrainedMD; 407 394 int MaxOuterStep; 408 int Thermostat;409 int *ThermostatImplemented;410 char **ThermostatNames;411 double TempFrequency;412 double alpha;413 double HooverMass;414 double TargetTemp;415 int ScaleTempStep;416 395 417 396 private: … … 419 398 char *defaultpath; 420 399 char *pseudopotpath; 421 400 422 401 int DoOutVis; 423 402 int DoOutMes; … … 434 413 int UseAddGramSch; 435 414 int Seed; 436 415 437 416 int OutVisStep; 438 417 int OutSrcStep; 418 double TargetTemp; 419 int ScaleTempStep; 439 420 int MaxPsiStep; 440 421 double EpsWannier; 441 422 442 423 int MaxMinStep; 443 424 double RelEpsTotalEnergy; … … 448 429 double InitRelEpsKineticEnergy; 449 430 int InitMaxMinGapStopStep; 450 431 451 432 //double BoxLength[NDIM*NDIM]; 452 433 453 434 double ECut; 454 435 int MaxLevel; … … 459 440 int RTActualUse; 460 441 int AddPsis; 461 442 462 443 double RCut; 463 444 int StructOpt; … … 466 447 int MaxTypes; 467 448 468 449 469 450 int ParseForParameter(int verbose, ifstream *file, const char *name, int sequential, int const xth, int const yth, int type, void *value, int repetition, int critical); 470 451 471 452 public: 472 453 config(); … … 477 458 void LoadOld(char *filename, periodentafel *periode, molecule *mol); 478 459 void RetrieveConfigPathAndName(string filename); 479 bool Save( const char *filename, periodentafel *periode, molecule *mol) const;480 bool SaveMPQC( const char *filename, molecule *mol) const;460 bool Save(ofstream *file, periodentafel *periode, molecule *mol) const; 461 bool SaveMPQC(ofstream *file, molecule *mol) const; 481 462 void Edit(molecule *mol); 482 463 bool GetIsAngstroem() const; 483 464 char *GetDefaultPath() const; 484 465 void SetDefaultPath(const char *path); 485 void InitThermostats(ifstream *source);486 466 }; 487 467 -
Property mode
changed from
-
src/orbitals.db
-
Property mode
changed from
100755
to100644
r986c80 redcda5 18 18 18 0 19 19 19 1 20 20 420 20 2 21 21 21 3 22 22 22 4 -
Property mode
changed from
-
src/parser.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 56 56 MatrixContainer::MatrixContainer() { 57 57 Indices = NULL; 58 Header = (char * *) Malloc(sizeof(char)*1, "MatrixContainer::MatrixContainer: **Header");58 Header = (char *) Malloc(sizeof(char)*1023, "MatrixContainer::MatrixContainer: *Header"); 59 59 Matrix = (double ***) Malloc(sizeof(double **)*(1), "MatrixContainer::MatrixContainer: ***Matrix"); // one more each for the total molecule 60 60 RowCounter = (int *) Malloc(sizeof(int)*(1), "MatrixContainer::MatrixContainer: *RowCounter"); 61 ColumnCounter = (int *) Malloc(sizeof(int)*(1), "MatrixContainer::MatrixContainer: *ColumnCounter");62 Header[0] = NULL;63 61 Matrix[0] = NULL; 64 62 RowCounter[0] = -1; 65 63 MatrixCounter = 0; 66 ColumnCounter [0] = -1;64 ColumnCounter = 0; 67 65 }; 68 66 … … 72 70 if (Matrix != NULL) { 73 71 for(int i=MatrixCounter;i--;) { 74 if ( (ColumnCounter != NULL) && (RowCounter != NULL)) {72 if (RowCounter != NULL) { 75 73 for(int j=RowCounter[i]+1;j--;) 76 74 Free((void **)&Matrix[i][j], "MatrixContainer::~MatrixContainer: *Matrix[][]"); … … 78 76 } 79 77 } 80 if (( ColumnCounter != NULL) && (RowCounter != NULL) && (Matrix[MatrixCounter] != NULL))78 if ((RowCounter != NULL) && (Matrix[MatrixCounter] != NULL)) 81 79 for(int j=RowCounter[MatrixCounter]+1;j--;) 82 80 Free((void **)&Matrix[MatrixCounter][j], "MatrixContainer::~MatrixContainer: *Matrix[MatrixCounter][]"); … … 91 89 Free((void **)&Indices, "MatrixContainer::~MatrixContainer: **Indices"); 92 90 93 if (Header != NULL) 94 for(int i=MatrixCounter+1;i--;) 95 Free((void **)&Header[i], "MatrixContainer::~MatrixContainer: *Header[]"); 96 Free((void **)&Header, "MatrixContainer::~MatrixContainer: **Header"); 91 Free((void **)&Header, "MatrixContainer::~MatrixContainer: *Header"); 97 92 Free((void **)&RowCounter, "MatrixContainer::~MatrixContainer: *RowCounter"); 98 Free((void **)&ColumnCounter, "MatrixContainer::~MatrixContainer: *RowCounter"); 99 }; 100 101 /** Either copies index matrix from another MatrixContainer or initialises with trivial mapping if NULL. 102 * This either copies the index matrix or just maps 1 to 1, 2 to 2 and so on for all fragments. 103 * \param *Matrix pointer to other MatrixContainer 104 * \return true - copy/initialisation sucessful, false - dimension false for copying 105 */ 106 bool MatrixContainer::InitialiseIndices(class MatrixContainer *Matrix) 107 { 108 cout << "Initialising indices"; 109 if (Matrix == NULL) { 110 cout << " with trivial mapping." << endl; 111 Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "MatrixContainer::InitialiseIndices: **Indices"); 112 for(int i=MatrixCounter+1;i--;) { 113 Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "MatrixContainer::InitialiseIndices: *Indices[]"); 114 for(int j=RowCounter[i];j--;) 115 Indices[i][j] = j; 116 } 117 } else { 118 cout << " from other MatrixContainer." << endl; 119 if (MatrixCounter != Matrix->MatrixCounter) 120 return false; 121 Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "MatrixContainer::InitialiseIndices: **Indices"); 122 for(int i=MatrixCounter+1;i--;) { 123 if (RowCounter[i] != Matrix->RowCounter[i]) 124 return false; 125 Indices[i] = (int *) Malloc(sizeof(int)*Matrix->RowCounter[i], "MatrixContainer::InitialiseIndices: *Indices[]"); 126 for(int j=Matrix->RowCounter[i];j--;) { 127 Indices[i][j] = Matrix->Indices[i][j]; 128 //cout << Indices[i][j] << "\t"; 129 } 130 //cout << endl; 131 } 132 } 133 return true; 134 }; 93 }; 94 135 95 136 96 /** Parsing a number of matrices. … … 160 120 return false; 161 121 } 162 163 // parse header 164 Header[MatrixNr] = (char *) Malloc(sizeof(char)*1024, "MatrixContainer::ParseMatrix: *Header[]"); 122 123 // skip some initial lines 165 124 for (int m=skiplines+1;m--;) 166 input.getline(Header [MatrixNr], 1023);125 input.getline(Header, 1023); 167 126 168 127 // scan header for number of columns 169 line.str(Header [MatrixNr]);128 line.str(Header); 170 129 for(int k=skipcolumns;k--;) 171 line >> Header [MatrixNr];130 line >> Header; 172 131 //cout << line.str() << endl; 173 ColumnCounter [MatrixNr]=0;132 ColumnCounter=0; 174 133 while ( getline(line,token, '\t') ) { 175 134 if (token.length() > 0) 176 ColumnCounter [MatrixNr]++;135 ColumnCounter++; 177 136 } 178 137 //cout << line.str() << endl; 179 //cout << "ColumnCounter [" << MatrixNr << "]: " << ColumnCounter[MatrixNr]<< "." << endl;180 if (ColumnCounter [MatrixNr]== 0)181 cerr << "ColumnCounter [" << MatrixNr << "]: " << ColumnCounter[MatrixNr]<< " from file " << name << ", this is probably an error!" << endl;138 //cout << "ColumnCounter: " << ColumnCounter << "." << endl; 139 if (ColumnCounter == 0) 140 cerr << "ColumnCounter: " << ColumnCounter << " from file " << name << ", this is probably an error!" << endl; 182 141 183 142 // scan rest for number of rows/lines … … 196 155 197 156 // allocate matrix if it's not zero dimension in one direction 198 if ((ColumnCounter [MatrixNr]> 0) && (RowCounter[MatrixNr] > -1)) {199 Matrix[MatrixNr] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixNr]+1), "MatrixContainer::Parse Matrix: **Matrix[]");157 if ((ColumnCounter > 0) && (RowCounter[MatrixNr] > -1)) { 158 Matrix[MatrixNr] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixNr]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 200 159 201 160 // parse in each entry for this matrix … … 203 162 input.seekg(ios::beg); 204 163 for (int m=skiplines+1;m--;) 205 input.getline(Header [MatrixNr], 1023); // skip header206 line.str(Header [MatrixNr]);164 input.getline(Header, 1023); // skip header 165 line.str(Header); 207 166 for(int k=skipcolumns;k--;) // skip columns in header too 208 167 line >> filename; 209 strncpy(Header [MatrixNr], line.str().c_str(), 1023);168 strncpy(Header, line.str().c_str(), 1023); 210 169 for(int j=0;j<RowCounter[MatrixNr];j++) { 211 Matrix[MatrixNr][j] = (double *) Malloc(sizeof(double)*ColumnCounter [MatrixNr], "MatrixContainer::ParseMatrix: *Matrix[][]");170 Matrix[MatrixNr][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]"); 212 171 input.getline(filename, 1023); 213 172 stringstream lines(filename); … … 215 174 for(int k=skipcolumns;k--;) 216 175 lines >> filename; 217 for(int k=0;(k<ColumnCounter [MatrixNr]) && (!lines.eof());k++) {176 for(int k=0;(k<ColumnCounter) && (!lines.eof());k++) { 218 177 lines >> Matrix[MatrixNr][j][k]; 219 178 //cout << " " << setprecision(2) << Matrix[MatrixNr][j][k];; 220 179 } 221 180 //cout << endl; 222 Matrix[MatrixNr][ RowCounter[MatrixNr] ] = (double *) Malloc(sizeof(double)*ColumnCounter [MatrixNr], "MatrixContainer::ParseMatrix: *Matrix[RowCounter[MatrixNr]][]");223 for(int j=ColumnCounter [MatrixNr];j--;)181 Matrix[MatrixNr][ RowCounter[MatrixNr] ] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[RowCounter[MatrixNr]][]"); 182 for(int j=ColumnCounter;j--;) 224 183 Matrix[MatrixNr][ RowCounter[MatrixNr] ][j] = 0.; 225 184 } 226 185 } else { 227 cerr << "ERROR: Matrix nr. " << MatrixNr << " has column and row count of (" << ColumnCounter [MatrixNr]<< "," << RowCounter[MatrixNr] << "), could not allocate nor parse!" << endl;186 cerr << "ERROR: Matrix nr. " << MatrixNr << " has column and row count of (" << ColumnCounter << "," << RowCounter[MatrixNr] << "), could not allocate nor parse!" << endl; 228 187 } 229 188 input.close(); … … 274 233 275 234 cout << "Parsing through each fragment and retrieving " << prefix << suffix << "." << endl; 276 Header = (char **) ReAlloc(Header, sizeof(char *)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: **Header"); // one more each for the total molecule277 235 Matrix = (double ***) ReAlloc(Matrix, sizeof(double **)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: ***Matrix"); // one more each for the total molecule 278 236 RowCounter = (int *) ReAlloc(RowCounter, sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *RowCounter"); 279 ColumnCounter = (int *) ReAlloc(ColumnCounter, sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *ColumnCounter");280 237 for(int i=MatrixCounter+1;i--;) { 281 238 Matrix[i] = NULL; 282 Header[i] = NULL;283 239 RowCounter[i] = -1; 284 ColumnCounter[i] = -1;285 240 } 286 241 for(int i=0; i < MatrixCounter;i++) { … … 297 252 298 253 /** Allocates and resets the memory for a number \a MCounter of matrices. 299 * \param * *GivenHeader Header line for each matrix254 * \param *GivenHeader Header line 300 255 * \param MCounter number of matrices 301 256 * \param *RCounter number of rows for each matrix 302 * \param *CCounter number of columns for each matrix257 * \param CCounter number of columns for all matrices 303 258 * \return Allocation successful 304 259 */ 305 bool MatrixContainer::AllocateMatrix(char **GivenHeader, int MCounter, int *RCounter, int *CCounter) 306 { 260 bool MatrixContainer::AllocateMatrix(char *GivenHeader, int MCounter, int *RCounter, int CCounter) 261 { 262 Header = (char *) Malloc(sizeof(char)*1024, "MatrixContainer::ParseFragmentMatrix: *EnergyHeader"); 263 strncpy(Header, GivenHeader, 1023); 264 307 265 MatrixCounter = MCounter; 308 Header = (char **) Malloc(sizeof(char *)*(MatrixCounter+1), "MatrixContainer::AllocateMatrix: *Header"); 309 Matrix = (double ***) Malloc(sizeof(double **)*(MatrixCounter+1), "MatrixContainer::AllocateMatrix: ***Matrix"); // one more each for the total molecule 310 RowCounter = (int *) Malloc(sizeof(int)*(MatrixCounter+1), "MatrixContainer::AllocateMatrix: *RowCounter"); 311 ColumnCounter = (int *) Malloc(sizeof(int)*(MatrixCounter+1), "MatrixContainer::AllocateMatrix: *ColumnCounter"); 266 ColumnCounter = CCounter; 267 Matrix = (double ***) Malloc(sizeof(double **)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: ***Matrix"); // one more each for the total molecule 268 RowCounter = (int *) Malloc(sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *RowCounter"); 312 269 for(int i=MatrixCounter+1;i--;) { 313 Header[i] = (char *) Malloc(sizeof(char)*1024, "MatrixContainer::AllocateMatrix: *Header[i]");314 strncpy(Header[i], GivenHeader[i], 1023);315 270 RowCounter[i] = RCounter[i]; 316 ColumnCounter[i] = CCounter[i]; 317 Matrix[i] = (double **) Malloc(sizeof(double *)*(RowCounter[i]+1), "MatrixContainer::AllocateMatrix: **Matrix[]"); 271 Matrix[i] = (double **) Malloc(sizeof(double *)*(RowCounter[i]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 318 272 for(int j=RowCounter[i]+1;j--;) { 319 Matrix[i][j] = (double *) Malloc(sizeof(double)*ColumnCounter [i], "MatrixContainer::AllocateMatrix: *Matrix[][]");320 for(int k=ColumnCounter [i];k--;)273 Matrix[i][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]"); 274 for(int k=ColumnCounter;k--;) 321 275 Matrix[i][j][k] = 0.; 322 276 } … … 332 286 for(int i=MatrixCounter+1;i--;) 333 287 for(int j=RowCounter[i]+1;j--;) 334 for(int k=ColumnCounter [i];k--;)288 for(int k=ColumnCounter;k--;) 335 289 Matrix[i][j][k] = 0.; 336 290 return true; … … 345 299 for(int i=MatrixCounter+1;i--;) 346 300 for(int j=RowCounter[i]+1;j--;) 347 for(int k=ColumnCounter [i];k--;)301 for(int k=ColumnCounter;k--;) 348 302 if (fabs(Matrix[i][j][k]) > max) 349 303 max = fabs(Matrix[i][j][k]); … … 361 315 for(int i=MatrixCounter+1;i--;) 362 316 for(int j=RowCounter[i]+1;j--;) 363 for(int k=ColumnCounter [i];k--;)317 for(int k=ColumnCounter;k--;) 364 318 if (fabs(Matrix[i][j][k]) < min) 365 319 min = fabs(Matrix[i][j][k]); … … 377 331 { 378 332 for(int j=RowCounter[MatrixCounter]+1;j--;) 379 for(int k=skipcolumns;k<ColumnCounter [MatrixCounter];k++)333 for(int k=skipcolumns;k<ColumnCounter;k++) 380 334 Matrix[MatrixCounter][j][k] = value; 381 335 return true; … … 390 344 { 391 345 for(int j=RowCounter[MatrixCounter]+1;j--;) 392 for(int k=skipcolumns;k<ColumnCounter [MatrixCounter];k++)346 for(int k=skipcolumns;k<ColumnCounter;k++) 393 347 Matrix[MatrixCounter][j][k] = values[j][k]; 394 348 return true; 395 349 }; 396 350 397 /** Sums the en tries with each factor and put into last element of \a ***Matrix.351 /** Sums the energy with each factor and put into last element of \a ***Energies. 398 352 * Sums over "E"-terms to create the "F"-terms 399 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.353 * \param Matrix MatrixContainer with matrices (LevelCounter by ColumnCounter) with all the energies. 400 354 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order 401 355 * \param Order bond order … … 430 384 } 431 385 if (Order == SubOrder) { // equal order is always copy from Energies 432 for(int l=ColumnCounter [ KeySet.OrderSet[SubOrder][j] ];l--;) // then adds/subtract each column386 for(int l=ColumnCounter;l--;) // then adds/subtract each column 433 387 Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] += MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l]; 434 388 } else { 435 for(int l=ColumnCounter [ KeySet.OrderSet[SubOrder][j] ];l--;)389 for(int l=ColumnCounter;l--;) 436 390 Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] -= Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l]; 437 391 } 438 392 } 439 //if ((ColumnCounter [ KeySet.OrderSet[SubOrder][j] ]>1) && (RowCounter[0]-1 >= 1))393 //if ((ColumnCounter>1) && (RowCounter[0]-1 >= 1)) 440 394 //cout << "Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " << Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl; 441 395 } … … 472 426 return false; 473 427 } 474 output << Header [i]<< endl;428 output << Header << endl; 475 429 for(int j=0;j<RowCounter[i];j++) { 476 for(int k=0;k<ColumnCounter [i];k++)430 for(int k=0;k<ColumnCounter;k++) 477 431 output << scientific << Matrix[i][j][k] << "\t"; 478 432 output << endl; … … 501 455 return false; 502 456 } 503 output << Header [MatrixCounter]<< endl;457 output << Header << endl; 504 458 for(int j=0;j<RowCounter[MatrixCounter];j++) { 505 for(int k=0;k<ColumnCounter [MatrixCounter];k++)459 for(int k=0;k<ColumnCounter;k++) 506 460 output << scientific << Matrix[MatrixCounter][j][k] << "\t"; 507 461 output << endl; … … 513 467 // ======================================= CLASS EnergyMatrix ============================= 514 468 469 /** Create a trivial energy index mapping. 470 * This just maps 1 to 1, 2 to 2 and so on for all fragments. 471 * \return creation sucessful 472 */ 473 bool EnergyMatrix::ParseIndices() 474 { 475 cout << "Parsing energy indices." << endl; 476 Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "EnergyMatrix::ParseIndices: **Indices"); 477 for(int i=MatrixCounter+1;i--;) { 478 Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "EnergyMatrix::ParseIndices: *Indices[]"); 479 for(int j=RowCounter[i];j--;) 480 Indices[i][j] = j; 481 } 482 return true; 483 }; 484 515 485 /** Sums the energy with each factor and put into last element of \a EnergyMatrix::Matrix. 516 486 * Sums over the "F"-terms in ANOVA decomposition. 517 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.487 * \param Matrix MatrixContainer with matrices (LevelCounter by ColumnCounter) with all the energies. 518 488 * \param CorrectionFragments MatrixContainer with hydrogen saturation correction per fragments 519 489 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order … … 528 498 for(int i=KeySet.FragmentsPerOrder[Order];i--;) 529 499 for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;) 530 for(int k=ColumnCounter [ KeySet.OrderSet[Order][i] ];k--;)500 for(int k=ColumnCounter;k--;) 531 501 Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k]; 532 502 else 533 503 for(int i=KeySet.FragmentsPerOrder[Order];i--;) 534 504 for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;) 535 for(int k=ColumnCounter [ KeySet.OrderSet[Order][i] ];k--;)505 for(int k=ColumnCounter;k--;) 536 506 Matrix[MatrixCounter][j][k] += sign*(Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k] + CorrectionFragments->Matrix[ KeySet.OrderSet[Order][i] ][j][k]); 537 507 return true; … … 554 524 // count maximum of columns 555 525 RowCounter[MatrixCounter] = 0; 556 ColumnCounter[MatrixCounter] = 0; 557 for(int j=0; j < MatrixCounter;j++) { // (energy matrix might be bigger than number of atoms in terms of rows) 526 for(int j=0; j < MatrixCounter;j++) // (energy matrix might be bigger than number of atoms in terms of rows) 558 527 if (RowCounter[j] > RowCounter[MatrixCounter]) 559 528 RowCounter[MatrixCounter] = RowCounter[j]; 560 if (ColumnCounter[j] > ColumnCounter[MatrixCounter]) // take maximum of all for last matrix561 ColumnCounter[MatrixCounter] = ColumnCounter[j];562 }563 529 // allocate last plus one matrix 564 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter [MatrixCounter]<< " columns." << endl;530 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter << " columns." << endl; 565 531 Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 566 532 for(int j=0;j<=RowCounter[MatrixCounter];j++) 567 Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter [MatrixCounter], "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");533 Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]"); 568 534 569 535 // try independently to parse global energysuffix file if present … … 623 589 624 590 /** Sums the forces and puts into last element of \a ForceMatrix::Matrix. 625 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.591 * \param Matrix MatrixContainer with matrices (LevelCounter by ColumnCounter) with all the energies. 626 592 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order 627 593 * \param Order bond order … … 643 609 if (j != -1) { 644 610 //if (j == 0) cout << "Summing onto ion 0, type 0 from fragment " << FragmentNr << ", ion " << l << "." << endl; 645 for(int k=2;k<ColumnCounter [MatrixCounter];k++)611 for(int k=2;k<ColumnCounter;k++) 646 612 Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ FragmentNr ][l][k]; 647 613 } … … 689 655 RowCounter[MatrixCounter]++; // nr start at 0, count starts at 1 690 656 input.close(); 691 692 ColumnCounter[MatrixCounter] = 0;693 for(int j=0; j < MatrixCounter;j++) { // (energy matrix might be bigger than number of atoms in terms of rows)694 if (ColumnCounter[j] > ColumnCounter[MatrixCounter]) // take maximum of all for last matrix695 ColumnCounter[MatrixCounter] = ColumnCounter[j];696 }697 657 698 658 // allocate last plus one matrix 699 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter [MatrixCounter]<< " columns." << endl;659 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter << " columns." << endl; 700 660 Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 701 661 for(int j=0;j<=RowCounter[MatrixCounter];j++) 702 Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter[MatrixCounter], "MatrixContainer::ParseFragmentMatrix: *Matrix[][]"); 703 704 // try independently to parse global forcesuffix file if present 705 strncpy(filename, name, 1023); 706 strncat(filename, prefix, 1023-strlen(filename)); 707 strncat(filename, suffix.c_str(), 1023-strlen(filename)); 708 ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter); 709 } 710 711 712 return status; 713 }; 714 715 // ======================================= CLASS HessianMatrix ============================= 716 717 /** Parsing force Indices of each fragment 718 * \param *name directory with \a ForcesFile 719 * \return parsing successful 720 */ 721 bool HessianMatrix::ParseIndices(char *name) 722 { 723 ifstream input; 724 char *FragmentNumber = NULL; 725 char filename[1023]; 726 stringstream line; 727 728 cout << "Parsing hessian indices for " << MatrixCounter << " matrices." << endl; 729 Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "HessianMatrix::ParseIndices: **Indices"); 730 line << name << FRAGMENTPREFIX << FORCESFILE; 731 input.open(line.str().c_str(), ios::in); 732 //cout << "Opening " << line.str() << " ... " << input << endl; 733 if (input == NULL) { 734 cout << endl << "Unable to open " << line.str() << ", is the directory correct?" << endl; 735 return false; 736 } 737 for (int i=0;(i<MatrixCounter) && (!input.eof());i++) { 738 // get the number of atoms for this fragment 739 input.getline(filename, 1023); 740 line.str(filename); 741 // parse the values 742 Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "HessianMatrix::ParseIndices: *Indices[]"); 743 FragmentNumber = FixedDigitNumber(MatrixCounter, i); 744 //cout << FRAGMENTPREFIX << FragmentNumber << "[" << RowCounter[i] << "]:"; 745 Free((void **)&FragmentNumber, "HessianMatrix::ParseIndices: *FragmentNumber"); 746 for(int j=0;(j<RowCounter[i]) && (!line.eof());j++) { 747 line >> Indices[i][j]; 748 //cout << " " << Indices[i][j]; 749 } 750 //cout << endl; 751 } 752 Indices[MatrixCounter] = (int *) Malloc(sizeof(int)*RowCounter[MatrixCounter], "HessianMatrix::ParseIndices: *Indices[]"); 753 for(int j=RowCounter[MatrixCounter];j--;) { 754 Indices[MatrixCounter][j] = j; 755 } 756 input.close(); 757 return true; 758 }; 759 760 761 /** Sums the hessian entries and puts into last element of \a HessianMatrix::Matrix. 762 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies. 763 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order 764 * \param Order bond order 765 * \param sign +1 or -1 766 * \return true if summing was successful 767 */ 768 bool HessianMatrix::SumSubHessians(class HessianMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign) 769 { 770 int FragmentNr; 771 // sum forces 772 for(int i=0;i<KeySet.FragmentsPerOrder[Order];i++) { 773 FragmentNr = KeySet.OrderSet[Order][i]; 774 for(int l=0;l<RowCounter[ FragmentNr ];l++) { 775 int j = Indices[ FragmentNr ][l]; 776 if (j > RowCounter[MatrixCounter]) { 777 cerr << "Current hessian index " << j << " is greater than " << RowCounter[MatrixCounter] << ", where i=" << i << ", Order=" << Order << ", l=" << l << " and FragmentNr=" << FragmentNr << "!" << endl; 778 return false; 779 } 780 if (j != -1) { 781 for(int m=0;m<ColumnCounter[ FragmentNr ];m++) { 782 int k = Indices[ FragmentNr ][m]; 783 if (k > ColumnCounter[MatrixCounter]) { 784 cerr << "Current hessian index " << k << " is greater than " << ColumnCounter[MatrixCounter] << ", where m=" << m << ", j=" << j << ", i=" << i << ", Order=" << Order << ", l=" << l << " and FragmentNr=" << FragmentNr << "!" << endl; 785 return false; 786 } 787 if (k != -1) { 788 //cout << "Adding " << sign*Fragments.Matrix[ FragmentNr ][l][m] << " from [" << l << "][" << m << "] onto [" << j << "][" << k << "]." << endl; 789 Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ FragmentNr ][l][m]; 790 } 791 } 792 } 793 } 794 } 795 return true; 796 }; 797 798 /** Constructor for class HessianMatrix. 799 */ 800 HessianMatrix::HessianMatrix() : MatrixContainer() 801 { 802 IsSymmetric = true; 803 } 804 805 /** Sums the hessian entries with each factor and put into last element of \a ***Matrix. 806 * Sums over "E"-terms to create the "F"-terms 807 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies. 808 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order 809 * \param Order bond order 810 * \return true if summing was successful 811 */ 812 bool HessianMatrix::SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySet, int Order) 813 { 814 // go through each order 815 for (int CurrentFragment=0;CurrentFragment<KeySet.FragmentsPerOrder[Order];CurrentFragment++) { 816 //cout << "Current Fragment is " << CurrentFragment << "/" << KeySet.OrderSet[Order][CurrentFragment] << "." << endl; 817 // then go per order through each suborder and pick together all the terms that contain this fragment 818 for(int SubOrder=0;SubOrder<=Order;SubOrder++) { // go through all suborders up to the desired order 819 for (int j=0;j<KeySet.FragmentsPerOrder[SubOrder];j++) { // go through all possible fragments of size suborder 820 if (KeySet.Contains(KeySet.OrderSet[Order][CurrentFragment], KeySet.OrderSet[SubOrder][j])) { 821 //cout << "Current other fragment is " << j << "/" << KeySet.OrderSet[SubOrder][j] << "." << endl; 822 // if the fragment's indices are all in the current fragment 823 for(int k=0;k<RowCounter[ KeySet.OrderSet[SubOrder][j] ];k++) { // go through all atoms in this fragment 824 int m = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][k]; 825 //cout << "Current row index is " << k << "/" << m << "." << endl; 826 if (m != -1) { // if it's not an added hydrogen 827 for (int l=0;l<RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ];l++) { // look for the corresponding index in the current fragment 828 //cout << "Comparing " << m << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l] << "." << endl; 829 if (m == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l]) { 830 m = l; 831 break; 832 } 833 } 834 //cout << "Corresponding row index for " << k << " in CurrentFragment is " << m << "." << endl; 835 if (m > RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) { 836 cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment] << " current row index " << m << " is greater than " << RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl; 837 return false; 838 } 839 840 for(int l=0;l<ColumnCounter[ KeySet.OrderSet[SubOrder][j] ];l++) { 841 int n = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][l]; 842 //cout << "Current column index is " << l << "/" << n << "." << endl; 843 if (n != -1) { // if it's not an added hydrogen 844 for (int p=0;p<ColumnCounter[ KeySet.OrderSet[Order][CurrentFragment] ];p++) { // look for the corresponding index in the current fragment 845 //cout << "Comparing " << n << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][p] << "." << endl; 846 if (n == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][p]) { 847 n = p; 848 break; 849 } 850 } 851 //cout << "Corresponding column index for " << l << " in CurrentFragment is " << n << "." << endl; 852 if (n > ColumnCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) { 853 cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment] << " current column index " << n << " is greater than " << ColumnCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl; 854 return false; 855 } 856 if (Order == SubOrder) { // equal order is always copy from Energies 857 //cout << "Adding " << MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l] << " from [" << k << "][" << l << "] onto [" << m << "][" << n << "]." << endl; 858 Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][n] += MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l]; 859 } else { 860 //cout << "Subtracting " << Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l] << " from [" << k << "][" << l << "] onto [" << m << "][" << n << "]." << endl; 861 Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][n] -= Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l]; 862 } 863 } 864 } 865 } 866 //if ((ColumnCounter[ KeySet.OrderSet[SubOrder][j] ]>1) && (RowCounter[0]-1 >= 1)) 867 //cout << "Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " << Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl; 868 } 869 } else { 870 //cout << "Fragment " << KeySet.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySet.OrderSet[Order][CurrentFragment] << "." << endl; 871 } 872 } 873 } 874 //cout << "Final Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << KeySet.AtomCounter[0]-1 << "][" << 1 << "] = " << Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][KeySet.AtomCounter[0]-1][1] << endl; 875 } 876 877 return true; 878 }; 879 880 /** Calls MatrixContainer::ParseFragmentMatrix() and additionally allocates last plus one matrix. 881 * \param *name directory with files 882 * \param *prefix prefix of each matrix file 883 * \param *suffix suffix of each matrix file 884 * \param skiplines number of inital lines to skip 885 * \param skiplines number of inital columns to skip 886 * \return parsing successful 887 */ 888 bool HessianMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) 889 { 890 char filename[1023]; 891 ifstream input; 892 stringstream file; 893 int nr; 894 bool status = MatrixContainer::ParseFragmentMatrix(name, prefix, suffix, skiplines, skipcolumns); 895 896 if (status) { 897 // count number of atoms for last plus one matrix 898 file << name << FRAGMENTPREFIX << KEYSETFILE; 899 input.open(file.str().c_str(), ios::in); 900 if (input == NULL) { 901 cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl; 902 return false; 903 } 904 RowCounter[MatrixCounter] = 0; 905 ColumnCounter[MatrixCounter] = 0; 906 while (!input.eof()) { 907 input.getline(filename, 1023); 908 stringstream zeile(filename); 909 while (!zeile.eof()) { 910 zeile >> nr; 911 //cout << "Current index: " << nr << "." << endl; 912 if (nr > RowCounter[MatrixCounter]) { 913 RowCounter[MatrixCounter] = nr; 914 ColumnCounter[MatrixCounter] = nr; 915 } 916 } 917 } 918 RowCounter[MatrixCounter]++; // nr start at 0, count starts at 1 919 ColumnCounter[MatrixCounter]++; // nr start at 0, count starts at 1 920 input.close(); 921 922 // allocate last plus one matrix 923 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter[MatrixCounter] << " columns." << endl; 924 Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 925 for(int j=0;j<=RowCounter[MatrixCounter];j++) 926 Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter[MatrixCounter], "MatrixContainer::ParseFragmentMatrix: *Matrix[][]"); 662 Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]"); 927 663 928 664 // try independently to parse global forcesuffix file if present -
Property mode
changed from
-
src/parser.hpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 19 19 20 20 #define EnergySuffix ".energy.all" 21 #define EnergyFragmentSuffix ".energyfragment.all"21 #define HcorrectionSuffix ".Hcorrection.all" 22 22 #define ForcesSuffix ".forces.all" 23 #define ForceFragmentSuffix ".forcefragment.all"24 #define HcorrectionSuffix ".Hcorrection.all"25 #define HcorrectionFragmentSuffix ".Hcorrectionfragment.all"26 #define HessianSuffix ".hessian_xx.all"27 #define HessianFragmentSuffix ".hessianfragment_xx.all"28 #define OrderSuffix ".Order"29 23 #define ShieldingSuffix ".sigma_all.csv" 30 24 #define ShieldingPASSuffix ".sigma_all_PAS.csv" 31 25 #define ShieldingFragmentSuffix ".sigma_all_fragment.all" 32 26 #define ShieldingPASFragmentSuffix ".sigma_all_PAS_fragment.all" 33 #define ChiSuffix ".chi_all.csv"34 #define ChiPASSuffix ".chi_all_PAS.csv"35 #define ChiFragmentSuffix ".chi_all_fragment.all"36 #define ChiPASFragmentSuffix ".chi_all_PAS_fragment.all"37 27 #define TimeSuffix ".speed" 28 #define EnergyFragmentSuffix ".energyfragment.all" 29 #define HcorrectionFragmentSuffix ".Hcorrectionfragment.all" 30 #define ForceFragmentSuffix ".forcefragment.all" 31 #define OrderSuffix ".Order" 38 32 39 33 // ======================================= FUNCTIONS ========================================== … … 49 43 double ***Matrix; 50 44 int **Indices; 51 char * *Header;45 char *Header; 52 46 int MatrixCounter; 53 47 int *RowCounter; 54 int *ColumnCounter;48 int ColumnCounter; 55 49 56 50 MatrixContainer(); 57 51 ~MatrixContainer(); 58 52 59 bool InitialiseIndices(class MatrixContainer *Matrix = NULL);60 53 bool ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr); 61 54 virtual bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns); 62 bool AllocateMatrix(char * *GivenHeader, int MCounter, int *RCounter, int *CCounter);55 bool AllocateMatrix(char *GivenHeader, int MCounter, int *RCounter, int CCounter); 63 56 bool ResetMatrix(); 64 57 double FindMinValue(); … … 77 70 class EnergyMatrix : public MatrixContainer { 78 71 public: 72 bool ParseIndices(); 79 73 bool SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign); 80 74 bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns); … … 88 82 bool SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign); 89 83 bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns); 90 };91 92 // ======================================= CLASS HessianMatrix =============================93 94 class HessianMatrix : public MatrixContainer {95 public:96 HessianMatrix();97 //~HessianMatrix();98 bool ParseIndices(char *name);99 bool SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySet, int Order);100 bool SumSubHessians(class HessianMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign);101 bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);102 private:103 bool IsSymmetric;104 84 }; 105 85 -
Property mode
changed from
-
src/periodentafel.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 1 1 /** \file periodentafel.cpp 2 * 2 * 3 3 * Function implementations for the class periodentafel. 4 * 4 * 5 5 */ 6 6 … … 14 14 * Initialises start and end of list and resets periodentafel::checkliste to false. 15 15 */ 16 periodentafel::periodentafel() 17 { 18 start = new element; 19 end = new element; 20 start->previous = NULL; 21 start->next = end; 22 end->previous = start; 16 periodentafel::periodentafel() 17 { 18 start = new element; 19 end = new element; 20 start->previous = NULL; 21 start->next = end; 22 end->previous = start; 23 23 end->next = NULL; 24 24 }; … … 27 27 * Removes every element and afterwards deletes start and end of list. 28 28 */ 29 periodentafel::~periodentafel() 30 { 31 CleanupPeriodtable(); 32 delete(end); 33 delete(start); 34 }; 29 periodentafel::~periodentafel() 30 { 31 CleanupPeriodtable(); 32 delete(end); 33 delete(start); 34 }; 35 35 36 36 /** Adds element to period table list … … 38 38 * \return true - succeeded, false - does not occur 39 39 */ 40 bool periodentafel::AddElement(element *pointer) 41 { 40 bool periodentafel::AddElement(element *pointer) 41 { 42 42 pointer->sort = &pointer->Z; 43 43 if (pointer->Z < 1 && pointer->Z >= MAX_ELEMENTS) 44 44 cout << Verbose(0) << "Invalid Z number!\n"; 45 return add(pointer, end); 45 return add(pointer, end); 46 46 }; 47 47 … … 50 50 * \return true - succeeded, false - element not found 51 51 */ 52 bool periodentafel::RemoveElement(element *pointer) 53 { 54 return remove(pointer, start, end); 52 bool periodentafel::RemoveElement(element *pointer) 53 { 54 return remove(pointer, start, end); 55 55 }; 56 56 … … 58 58 * \return true - succeeded, false - does not occur 59 59 */ 60 bool periodentafel::CleanupPeriodtable() 61 { 62 return cleanup(start,end); 60 bool periodentafel::CleanupPeriodtable() 61 { 62 return cleanup(start,end); 63 63 }; 64 64 … … 76 76 cout << Verbose(0) << "Mass: " << endl; 77 77 cin >> walker->mass; 78 walker->Z = Z; 79 cout << Verbose(0) << "Atomic number: " << walker->Z << endl; 78 walker->Z = Z; 79 cout << Verbose(0) << "Atomic number: " << walker->Z << endl; 80 80 cout << Verbose(0) << "Name [max 64 chars]: " << endl; 81 81 cin >> walker->name; … … 105 105 /** Asks for element number and returns pointer to element 106 106 */ 107 element * periodentafel::AskElement() 107 element * periodentafel::AskElement() 108 108 { 109 109 element *walker = NULL; … … 117 117 }; 118 118 119 119 120 /** Prints period table to given stream. 120 121 * \param output stream 121 */ 122 */ 122 123 bool periodentafel::Output(ofstream *output) const 123 124 { … … 130 131 } 131 132 return result; 132 } else 133 } else 133 134 return false; 134 135 }; … … 137 138 * \param *output output stream 138 139 * \param *checkliste elements table for this molecule 139 */ 140 */ 140 141 bool periodentafel::Checkout(ofstream *output, const int *checkliste) const 141 142 { … … 151 152 if ((walker != NULL) && (walker->Z > 0) && (walker->Z < MAX_ELEMENTS) && (checkliste[walker->Z])) { 152 153 walker->No = No; 153 result = result && walker->Checkout(output, No++, checkliste[walker->Z]); 154 result = result && walker->Checkout(output, No++, checkliste[walker->Z]); 154 155 } 155 156 } 156 157 return result; 157 } else 158 } else 158 159 return false; 159 160 }; 161 160 162 161 163 /** Loads element list from file. … … 169 171 bool status = true; 170 172 bool otherstatus = true; 171 char filename[255];172 173 char *filename = new char[MAXSTRINGSIZE]; 174 173 175 // fill elements DB 174 176 strncpy(filename, path, MAXSTRINGSIZE); … … 223 225 if (infile != NULL) { 224 226 while (!infile.eof()) { 227 infile >> tmp; 228 infile >> ws; 229 infile >> FindElement((int)tmp)->Valence; 230 infile >> ws; 231 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->Valence << " valence electrons." << endl; 232 } 233 infile.close(); 234 infile.clear(); 235 } else 236 otherstatus = false; 237 238 // fill valence DB per element 239 strncpy(filename, path, MAXSTRINGSIZE); 240 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename)); 241 strncat(filename, STANDARDORBITALDB, MAXSTRINGSIZE-strlen(filename)); 242 infile.open(filename); 243 if (infile != NULL) { 244 while (!infile.eof()) { 225 245 infile >> tmp; 226 246 infile >> ws; 227 infile >> FindElement((int)tmp)-> Valence;228 infile >> ws; 229 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)-> Valence << " valence electrons." << endl;247 infile >> FindElement((int)tmp)->NoValenceOrbitals; 248 infile >> ws; 249 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->NoValenceOrbitals << " number of singly occupied valence orbitals." << endl; 230 250 } 231 251 infile.close(); … … 233 253 } else 234 254 otherstatus = false; 235 236 // fill valence DB per element 237 strncpy(filename, path, MAXSTRINGSIZE); 238 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename)); 239 strncat(filename, STANDARDORBITALDB, MAXSTRINGSIZE-strlen(filename)); 240 infile.open(filename); 241 if (infile != NULL) { 242 while (!infile.eof()) { 243 infile >> tmp; 244 infile >> ws; 245 infile >> FindElement((int)tmp)->NoValenceOrbitals; 246 infile >> ws; 247 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->NoValenceOrbitals << " number of singly occupied valence orbitals." << endl; 248 } 249 infile.close(); 250 infile.clear(); 251 } else 252 otherstatus = false; 253 255 254 256 // fill H-BondDistance DB per element 255 257 strncpy(filename, path, MAXSTRINGSIZE); … … 259 261 if (infile != NULL) { 260 262 while (!infile.eof()) { 261 263 infile >> tmp; 262 264 ptr = FindElement((int)tmp); 263 265 infile >> ws; 264 266 infile >> ptr->HBondDistance[0]; 265 267 infile >> ptr->HBondDistance[1]; 266 268 infile >> ptr->HBondDistance[2]; 267 269 infile >> ws; 268 270 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->HBondDistance[0] << " Angstrom typical distance to hydrogen." << endl; 269 271 } … … 272 274 } else 273 275 otherstatus = false; 274 276 275 277 // fill H-BondAngle DB per element 276 278 strncpy(filename, path, MAXSTRINGSIZE); … … 292 294 } else 293 295 otherstatus = false; 294 296 295 297 if (!otherstatus) 296 cerr << " WARNING: Something went wrong while parsing the otherdatabases!" << endl;297 298 cerr << "ERROR: Something went wrong while parsing the databases!" << endl; 299 298 300 return status; 299 301 }; … … 306 308 ofstream f; 307 309 char filename[MAXSTRINGSIZE]; 308 310 309 311 strncpy(filename, path, MAXSTRINGSIZE); 310 312 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename)); -
Property mode
changed from
-
src/periodentafel.hpp
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
src/stackclass.hpp
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
src/valence.db
-
Property mode
changed from
100755
to100644
r986c80 redcda5 18 18 18 0.80000000000000E+01 19 19 19 0.30000000000000E+01 20 20 0. 40000000000000E+0120 20 0.20000000000000E+01 21 21 21 0.30000000000000E+01 22 22 22 0.40000000000000E+01 -
Property mode
changed from
-
src/vector.cpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 1 1 /** \file vector.cpp 2 * 2 * 3 3 * Function implementations for the class vector. 4 * 5 */ 6 4 * 5 */ 6 7 7 #include "molecules.hpp" 8 8 9 9 10 10 /************************************ Functions for class vector ************************************/ … … 22 22 Vector::~Vector() {}; 23 23 24 /** Calculates square ofdistance between this and another vector.24 /** Calculates distance between this and another vector. 25 25 * \param *y array to second vector 26 26 * \return \f$| x - y |^2\f$ 27 27 */ 28 double Vector::Distance Squared(const Vector *y) const28 double Vector::Distance(const Vector *y) const 29 29 { 30 30 double res = 0.; 31 31 for (int i=NDIM;i--;) 32 32 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 33 return (res); 34 }; 35 36 /** Calculates distance between this and another vector. 37 * \param *y array to second vector 38 * \return \f$| x - y |\f$ 39 */ 40 double Vector::Distance(const Vector *y) const 41 { 42 double res = 0.; 43 for (int i=NDIM;i--;) 44 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 45 return (sqrt(res)); 33 return (res); 46 34 }; 47 35 … … 81 69 if (tmp < res) res = tmp; 82 70 } 83 return (res); 71 return (res); 84 72 }; 85 73 … … 124 112 for (int i=NDIM;i--;) 125 113 res += x[i]*y->x[i]; 126 return (res); 127 }; 128 129 130 /** Calculates VectorProduct between this and another vector. 131 * -# returns the Product in place of vector from which it was initiated 132 * -# ATTENTION: Only three dim. 133 * \param *y array to vector with which to calculate crossproduct 134 * \return \f$ x \times y \f& 135 */ 136 void Vector::VectorProduct(const Vector *y) 137 { 138 Vector tmp; 139 tmp.x[0] = x[1]* (y->x[2]) - x[2]* (y->x[1]); 140 tmp.x[1] = x[2]* (y->x[0]) - x[0]* (y->x[2]); 141 tmp.x[2] = x[0]* (y->x[1]) - x[1]* (y->x[0]); 142 this->CopyVector(&tmp); 143 144 }; 145 114 return (res); 115 }; 146 116 147 117 /** projects this vector onto plane defined by \a *y. 148 * \param *y normal vector of plane118 * \param *y array to normal vector of plane 149 119 * \return \f$\langle x, y \rangle\f$ 150 120 */ … … 153 123 Vector tmp; 154 124 tmp.CopyVector(y); 155 tmp.Normalize(); 156 tmp.Scale(ScalarProduct(&tmp)); 125 tmp.Scale(Projection(y)); 157 126 this->SubtractVector(&tmp); 158 127 }; … … 175 144 for (int i=NDIM;i--;) 176 145 res += this->x[i]*this->x[i]; 177 return (sqrt(res)); 146 return (sqrt(res)); 178 147 }; 179 148 … … 209 178 */ 210 179 void Vector::Init(double x1, double x2, double x3) 211 { 180 { 212 181 x[0] = x1; 213 182 x[1] = x2; … … 219 188 * \return \f$\acos\bigl(frac{\langle x, y \rangle}{|x||y|}\bigr)\f$ 220 189 */ 221 double Vector::Angle( constVector *y) const222 { 223 return acos(this->ScalarProduct(y)/Norm()/y->Norm()); 190 double Vector::Angle(Vector *y) const 191 { 192 return acos(this->ScalarProduct(y)/Norm()/y->Norm()); 224 193 }; 225 194 … … 269 238 270 239 /** Sums two vectors \a and \b component-wise. 271 * \param a first vector 240 * \param a first vector 272 241 * \param b second vector 273 242 * \return a + b … … 282 251 283 252 /** Factors given vector \a a times \a m. 284 * \param a vector 253 * \param a vector 285 254 * \param m factor 286 255 * \return a + b … … 313 282 }; 314 283 315 /** Prints a 3dim vector to a stream. 316 * \param ost output stream 317 * \param v Vector to be printed 318 * \return output stream 319 */ 320 ostream& operator<<(ostream& ost,Vector& m) 321 { 322 ost << "("; 323 for (int i=0;i<NDIM;i++) { 324 ost << m.x[i]; 325 if (i != 2) 326 ost << ","; 327 } 328 ost << ")"; 284 ofstream& operator<<(ofstream& ost,Vector& m) 285 { 286 m.Output(&ost); 329 287 return ost; 330 288 }; … … 351 309 }; 352 310 353 /** Translate atom by given vector. 311 /** Translate atom by given vector. 354 312 * \param trans[] translation vector. 355 313 */ … … 358 316 for (int i=NDIM;i--;) 359 317 x[i] += trans->x[i]; 360 }; 318 }; 361 319 362 320 /** Do a matrix multiplication. … … 397 355 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]); // A_32 398 356 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]); // A_33 399 357 400 358 // do the matrix multiplication 401 359 C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2]; … … 421 379 { 422 380 for(int i=NDIM;i--;) 423 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i]; 424 }; 425 426 /** Mirrors atom against a given plane. 381 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i]; 382 }; 383 384 /** Mirrors atom against a given plane. 427 385 * \param n[] normal vector of mirror plane. 428 386 */ … … 440 398 Output((ofstream *)&cout); 441 399 cout << endl; 442 }; 400 }; 443 401 444 402 /** Calculates normal vector for three given vectors (being three points in space). … … 472 430 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]); 473 431 Normalize(); 474 432 475 433 return true; 476 434 }; … … 530 488 /** Creates this vector as one of the possible orthonormal ones to the given one. 531 489 * Just scan how many components of given *vector are unequal to zero and 532 * try to get the skp of both to be zero accordingly. 490 * try to get the skp of both to be zero accordingly. 533 491 * \param *vector given vector 534 492 * \return true - success, false - failure (null vector given) … … 551 509 Components[Last++] = j; 552 510 cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl; 553 511 554 512 switch(Last) { 555 513 case 3: // threecomponent system … … 564 522 case 1: // one component system 565 523 // set sole non-zero component to 0, and one of the other zero component pendants to 1 566 x[(Components[0]+2)%NDIM] = 0.; 567 x[(Components[0]+1)%NDIM] = 1.; 568 x[Components[0]] = 0.; 524 x[(Components[0]+2)%NDIM] = 0.; 525 x[(Components[0]+1)%NDIM] = 1.; 526 x[Components[0]] = 0.; 569 527 return true; 570 528 break; … … 583 541 { 584 542 // cout << Verbose(3) << "For comparison: "; 585 // cout << "A " << A->Projection(this) << "\t"; 586 // cout << "B " << B->Projection(this) << "\t"; 587 // cout << "C " << C->Projection(this) << "\t"; 543 // cout << "A " << A->Projection(this) << "\t"; 544 // cout << "B " << B->Projection(this) << "\t"; 545 // cout << "C " << C->Projection(this) << "\t"; 588 546 // cout << endl; 589 547 return A->Projection(this); … … 595 553 * \return true if success, false if failed due to linear dependency 596 554 */ 597 bool Vector::LSQdistance(Vector **vectors, int num) 555 bool Vector::LSQdistance(Vector **vectors, int num) 598 556 { 599 557 int j; 600 558 601 559 for (j=0;j<num;j++) { 602 560 cout << Verbose(1) << j << "th atom's vector: "; … … 607 565 int np = 3; 608 566 struct LSQ_params par; 609 567 610 568 const gsl_multimin_fminimizer_type *T = 611 569 gsl_multimin_fminimizer_nmsimplex; … … 613 571 gsl_vector *ss, *y; 614 572 gsl_multimin_function minex_func; 615 573 616 574 size_t iter = 0, i; 617 575 int status; 618 576 double size; 619 577 620 578 /* Initial vertex size vector */ 621 579 ss = gsl_vector_alloc (np); 622 580 y = gsl_vector_alloc (np); 623 581 624 582 /* Set all step sizes to 1 */ 625 583 gsl_vector_set_all (ss, 1.0); 626 584 627 585 /* Starting point */ 628 586 par.vectors = vectors; 629 587 par.num = num; 630 588 631 589 for (i=NDIM;i--;) 632 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.); 633 590 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.); 591 634 592 /* Initialize method and iterate */ 635 593 minex_func.f = &LSQ; 636 594 minex_func.n = np; 637 595 minex_func.params = (void *)∥ 638 596 639 597 s = gsl_multimin_fminimizer_alloc (T, np); 640 598 gsl_multimin_fminimizer_set (s, &minex_func, y, ss); 641 599 642 600 do 643 601 { 644 602 iter++; 645 603 status = gsl_multimin_fminimizer_iterate(s); 646 604 647 605 if (status) 648 606 break; 649 607 650 608 size = gsl_multimin_fminimizer_size (s); 651 609 status = gsl_multimin_test_size (size, 1e-2); 652 610 653 611 if (status == GSL_SUCCESS) 654 612 { 655 613 printf ("converged to minimum at\n"); 656 614 } 657 615 658 616 printf ("%5d ", (int)iter); 659 617 for (i = 0; i < (size_t)np; i++) … … 664 622 } 665 623 while (status == GSL_CONTINUE && iter < 100); 666 624 667 625 for (i=(size_t)np;i--;) 668 626 this->x[i] = gsl_vector_get(s->x, i); … … 730 688 * \param alpha first angle 731 689 * \param beta second angle 732 * \param c norm of final vector 690 * \param c norm of final vector 733 691 * \return a vector with \f$\langle x1,x2 \rangle=A\f$, \f$\langle x1,y \rangle = B\f$ and with norm \a c. 734 * \bug this is not yet working properly 692 * \bug this is not yet working properly 735 693 */ 736 694 bool Vector::SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c) … … 748 706 if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping 749 707 if (fabs(x1->x[1]) > MYEPSILON) { 750 flag = 1; 708 flag = 1; 751 709 } else if (fabs(x1->x[2]) > MYEPSILON) { 752 710 flag = 2; … … 781 739 // now comes the case system 782 740 D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1]; 783 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2]; 741 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2]; 784 742 D3 = y->x[0]/x1->x[0]*A-B1; 785 743 cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n"; 786 744 if (fabs(D1) < MYEPSILON) { 787 cout << Verbose(2) << "D1 == 0!\n"; 745 cout << Verbose(2) << "D1 == 0!\n"; 788 746 if (fabs(D2) > MYEPSILON) { 789 cout << Verbose(3) << "D2 != 0!\n"; 747 cout << Verbose(3) << "D2 != 0!\n"; 790 748 x[2] = -D3/D2; 791 749 E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2; … … 797 755 cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 798 756 if (fabs(F1) < MYEPSILON) { 799 cout << Verbose(4) << "F1 == 0!\n"; 757 cout << Verbose(4) << "F1 == 0!\n"; 800 758 cout << Verbose(4) << "Gleichungssystem linear\n"; 801 x[1] = F3/(2.*F2); 759 x[1] = F3/(2.*F2); 802 760 } else { 803 761 p = F2/F1; 804 762 q = p*p - F3/F1; 805 cout << Verbose(4) << "p " << p << "\tq " << q << endl; 763 cout << Verbose(4) << "p " << p << "\tq " << q << endl; 806 764 if (q < 0) { 807 765 cout << Verbose(4) << "q < 0" << endl; … … 824 782 cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 825 783 if (fabs(F1) < MYEPSILON) { 826 cout << Verbose(3) << "F1 == 0!\n"; 784 cout << Verbose(3) << "F1 == 0!\n"; 827 785 cout << Verbose(3) << "Gleichungssystem linear\n"; 828 x[2] = F3/(2.*F2); 786 x[2] = F3/(2.*F2); 829 787 } else { 830 788 p = F2/F1; 831 789 q = p*p - F3/F1; 832 cout << Verbose(3) << "p " << p << "\tq " << q << endl; 790 cout << Verbose(3) << "p " << p << "\tq " << q << endl; 833 791 if (q < 0) { 834 792 cout << Verbose(3) << "q < 0" << endl; … … 874 832 } 875 833 cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n"; 876 // apply sign matrix 834 // apply sign matrix 877 835 for (j=NDIM;j--;) 878 836 x[j] *= sign[j]; … … 880 838 ang = x2->Angle (this); 881 839 cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t"; 882 if (fabs(ang - cos(beta)) < MYEPSILON) { 840 if (fabs(ang - cos(beta)) < MYEPSILON) { 883 841 break; 884 842 } -
Property mode
changed from
-
src/vector.hpp
-
Property mode
changed from
100755
to100644
r986c80 redcda5 7 7 * basically, just a x[3] but with helpful functions 8 8 */ 9 class Vector { 9 class Vector { 10 10 public: 11 11 double x[NDIM]; … … 16 16 17 17 double Distance(const Vector *y) const; 18 double DistanceSquared(const Vector *y) const;19 18 double PeriodicDistance(const Vector *y, const double *cell_size) const; 20 19 double ScalarProduct(const Vector *y) const; 21 20 double Projection(const Vector *y) const; 22 21 double Norm() const ; 23 double Angle( constVector *y) const;22 double Angle(Vector *y) const; 24 23 25 24 void AddVector(const Vector *y); … … 27 26 void CopyVector(const Vector *y); 28 27 void RotateVector(const Vector *y, const double alpha); 29 void VectorProduct(const Vector *y);30 28 void ProjectOntoPlane(const Vector *y); 31 void Zero(); 29 void Zero(); 32 30 void One(double one); 33 31 void Init(double x1, double x2, double x3); … … 42 40 void KeepPeriodic(ofstream *out, double *matrix); 43 41 void LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors); 44 42 45 43 double CutsPlaneAt(Vector *A, Vector *B, Vector *C); 46 44 bool GetOneNormalVector(const Vector *x1); … … 55 53 }; 56 54 57 o stream & operator << (ostream& ost, Vector &m);58 //Vector& operator+=(Vector& a, const Vector& b);59 //Vector& operator*=(Vector& a, const double m);60 //Vector& operator*(const Vector& a, const double m);61 //Vector& operator+(const Vector& a, const Vector& b);55 ofstream& operator<<(ofstream& ost, Vector& m); 56 Vector& operator+=(Vector& a, const Vector& b); 57 Vector& operator*=(Vector& a, const double m); 58 Vector& operator*(const Vector& a, const double m); 59 Vector& operator+(const Vector& a, const Vector& b); 62 60 63 61 #endif /*VECTOR_HPP_*/ -
Property mode
changed from
-
src/verbose.cpp
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
tests/Makefile.am
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
tests/atlocal.in
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
tests/molecuilder.in
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
tests/testsuite.at
-
Property mode
changed from
100755
to100644
r986c80 redcda5 12 12 AT_CHECK([../../molecuilder -h], 0, [stdout], [ignore]) 13 13 AT_CHECK([fgrep "Give this help screen" stdout], 0, [ignore], [ignore]) 14 AT_CHECK([../../molecuilder -e], 0, [ignore], [stderr])15 AT_CHECK([fgrep "Not enough or invalid arguments" stderr], 0, [ignore], [ignore])16 AT_CHECK([../../molecuilder test.conf], 0, [stdout], [stderr])17 AT_CHECK([fgrep "Element list loading failed" stdout], 0, [ignore], [ignore])18 14 AT_CLEANUP 19 15 … … 42 38 AT_CHECK([../../molecuilder -e ./ <input], 0, [ignore], [ignore]) 43 39 AT_CHECK([diff main_pcp_linux test.conf], 0, [ignore], [ignore]) 44 # 4. test some more configuration45 AT_CHECK([../../molecuilder test.conf -e ./ -t -s -b -F -E -c -b -a -U -T -u], 0, [ignore], [stderr])46 AT_CHECK([fgrep -c "Not enough or invalid" stderr], 0, [1047 ], [ignore])48 40 AT_CLEANUP 49 41 -
Property mode
changed from
Note:
See TracChangeset
for help on using the changeset viewer.