Changes in / [fcbfc8:631dcb]
- Files:
-
- 6 added
- 43 edited
Legend:
- Unmodified
- Added
- Removed
-
ChangeLog
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
Makefile.am
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
configure.ac
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 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])24 16 25 17 # Checks for libraries. -
Property mode
changed from
-
doc/Doxyfile
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
doc/Makefile.am
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
m4/ac_doxygen.m4
-
Property mode
changed from
120000
to100644
rfcbfc8 r631dcb 1 ../../m4/ac_doxygen.m4 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 ]) -
Property mode
changed from
-
m4/acx_compilerflags.m4
-
Property mode
changed from
120000
to100644
rfcbfc8 r631dcb 1 ../../m4/acx_compilerflags.m4 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 ]) -
Property mode
changed from
-
src/Hbondangle.db
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 4 4 7 180 110 106.67 5 5 8 180 104.5 -1 6 14 180 120 109. 56 14 180 120 109.47 7 7 15 180 -1 -1 8 8 16 180 -1 -1 9 9 17 180 -1 -1 10 20 180 120 109.47 10 11 34 180 -1 -1 11 12 35 180 -1 -1 -
Property mode
changed from
-
src/Hbonddistance.db
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 9 9 16 1.35 -1 -1 10 10 17 1.29 -1 -1 11 20 1.09 1.09 -1 11 12 34 1.47 -1 -1 12 13 35 1.44 -1 -1 -
Property mode
changed from
-
src/Makefile.am
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/analyzer.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 25 25 periodentafel *periode = NULL; // and a period table of all elements 26 26 EnergyMatrix Energy; 27 EnergyMatrix EnergyFragments; 28 ForceMatrix Force; 29 ForceMatrix ForceFragments; 30 HessianMatrix Hessian; 31 HessianMatrix HessianFragments; 27 32 EnergyMatrix Hcorrection; 28 ForceMatrix Force;33 EnergyMatrix HcorrectionFragments; 29 34 ForceMatrix Shielding; 30 35 ForceMatrix ShieldingPAS; 36 ForceMatrix Chi; 37 ForceMatrix ChiPAS; 31 38 EnergyMatrix Time; 32 EnergyMatrix EnergyFragments;33 EnergyMatrix HcorrectionFragments;34 ForceMatrix ForceFragments;35 39 ForceMatrix ShieldingFragments; 36 40 ForceMatrix ShieldingPASFragments; 41 ForceMatrix ChiFragments; 42 ForceMatrix ChiPASFragments; 37 43 KeySetsContainer KeySet; 38 44 ofstream output; … … 49 55 stringstream yrange; 50 56 char *dir = NULL; 51 bool Hcorrected = true; 52 double norm; 57 bool NoHCorrection = false; 58 bool NoHessian = false; 59 bool NoTime = false; 53 60 int counter; 54 61 … … 84 91 // ------------- Parse through all Fragment subdirs -------- 85 92 if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix,0,0)) return 1; 86 Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX,0,0); 93 if (!Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX,0,0)) { 94 NoHCorrection = true; 95 cout << "No HCorrection file found, skipping these." << endl; 96 } 97 87 98 if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix,0,0)) return 1; 88 if (!Time.ParseFragmentMatrix(argv[1], dir, TimeSuffix, 10,1)) 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 } 89 107 if (periode != NULL) { // also look for PAS values 90 108 if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1; 91 109 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; 92 112 } 93 113 94 114 // ---------- Parse the TE Factors into an array ----------------- 95 if (!Energy.ParseIndices()) return 1; 96 if (Hcorrected) Hcorrection.ParseIndices(); 115 if (!Energy.InitialiseIndices()) return 1; 116 if (!NoHCorrection) 117 Hcorrection.InitialiseIndices(); 97 118 98 119 // ---------- Parse the Force indices into an array --------------- 99 120 if (!Force.ParseIndices(argv[1])) return 1; 100 121 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1; 101 if (!ForceFragments.ParseIndices(argv[1])) 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 } 102 130 103 131 // ---------- Parse the shielding indices into an array --------------- … … 105 133 if(!Shielding.ParseIndices(argv[1])) return 1; 106 134 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; 107 145 } 108 146 … … 113 151 // ---------- Parse fragment files created by 'joiner' into an array ------------- 114 152 if (!EnergyFragments.ParseFragmentMatrix(argv[1], dir, EnergyFragmentSuffix,0,0)) return 1; 115 if (Hcorrected) HcorrectionFragments.ParseFragmentMatrix(argv[1], dir, HcorrectionFragmentSuffix,0,0); 153 if (!NoHCorrection) 154 HcorrectionFragments.ParseFragmentMatrix(argv[1], dir, HcorrectionFragmentSuffix,0,0); 116 155 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; 117 158 if (periode != NULL) { // also look for PAS values 118 159 if (!ShieldingFragments.ParseFragmentMatrix(argv[1], dir, ShieldingFragmentSuffix, 1, 0)) return 1; 119 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; 120 163 } 121 164 … … 126 169 filename << argv[3] << "/" << "energy-forces.all"; 127 170 output.open(filename.str().c_str(), ios::out); 128 output << endl << "Total Energy" << endl << "==============" << endl << Energy.Header << endl;171 output << endl << "Total Energy" << endl << "==============" << endl << Energy.Header[Energy.MatrixCounter] << endl; 129 172 for(int j=0;j<Energy.RowCounter[Energy.MatrixCounter];j++) { 130 for(int k=0;k<Energy.ColumnCounter ;k++)173 for(int k=0;k<Energy.ColumnCounter[Energy.MatrixCounter];k++) 131 174 output << scientific << Energy.Matrix[ Energy.MatrixCounter ][j][k] << "\t"; 132 175 output << endl; … … 134 177 output << endl; 135 178 136 output << endl << "Total Forces" << endl << "===============" << endl << Force.Header << endl;179 output << endl << "Total Forces" << endl << "===============" << endl << Force.Header[Force.MatrixCounter] << endl; 137 180 for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) { 138 for(int k=0;k<Force.ColumnCounter ;k++)181 for(int k=0;k<Force.ColumnCounter[Force.MatrixCounter];k++) 139 182 output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t"; 140 183 output << endl; … … 142 185 output << endl; 143 186 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 144 197 if (periode != NULL) { // also look for PAS values 145 output << endl << "Total Shieldings" << endl << "===============" << endl << Shielding.Header << endl;198 output << endl << "Total Shieldings" << endl << "===============" << endl << Shielding.Header[Hessian.MatrixCounter] << endl; 146 199 for(int j=0;j<Shielding.RowCounter[Shielding.MatrixCounter];j++) { 147 for(int k=0;k<Shielding.ColumnCounter ;k++)200 for(int k=0;k<Shielding.ColumnCounter[Shielding.MatrixCounter];k++) 148 201 output << scientific << Shielding.Matrix[ Shielding.MatrixCounter ][j][k] << "\t"; 149 202 output << endl; … … 151 204 output << endl; 152 205 153 output << endl << "Total Shieldings PAS" << endl << "===============" << endl << ShieldingPAS.Header << endl;206 output << endl << "Total Shieldings PAS" << endl << "===============" << endl << ShieldingPAS.Header[ShieldingPAS.MatrixCounter] << endl; 154 207 for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) { 155 for(int k=0;k<ShieldingPAS.ColumnCounter ;k++)208 for(int k=0;k<ShieldingPAS.ColumnCounter[ShieldingPAS.MatrixCounter];k++) 156 209 output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; 157 210 output << endl; 158 211 } 159 212 output << endl; 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; 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[Chi.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 } 170 241 output.close(); 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]; 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]; 173 245 174 246 // +++++++++++++++ ANALYZING ++++++++++++++++++++++++++++++ … … 180 252 // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order 181 253 // +++++++++++++++++++++++++++++++++++++++ Plotting Delta Simtime vs Bond Order 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(); 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 } 212 305 213 306 // +++++++++++++++++++++++++++++++++++++++ Plotting shieldings 214 307 if (periode != NULL) { // also look for PAS values 215 if (!OpenOutputFile(output, argv[3], "ShieldingPAS-Atom.dat" )) return false; 216 output << "#" << ShieldingPAS.Header << endl; 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; 217 312 for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) { 218 for(int k=0;k<ShieldingPAS.ColumnCounter;k++) 219 output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k]*(((k>1) && (k<6))? 1.e6 : 1.) << "\t"; 220 output << endl; 221 } 222 output << endl << endl; // another two newlines to partition the data 223 for(int j=0;j<ShieldingPASFragments.RowCounter[ShieldingPASFragments.MatrixCounter];j++) { 224 for(int k=0;k<ShieldingPASFragments.ColumnCounter;k++) 225 output << scientific << ShieldingPASFragments.Matrix[ ShieldingPASFragments.MatrixCounter ][j][k]*(((k>1) && (k<6))? 1.e6 : 1.) << "\t"; 226 output << endl; 227 } 228 output << endl; 229 } 230 output.close(); 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 } 231 331 232 332 … … 251 351 // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order 252 352 if (!CreateDataForcesOrderPerAtom(ForceFragments, KeySet, argv[3], "Forces-Order", "Plot of approximated forces versus the Bond Order", datum)) return 1; 253 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(); 254 362 // min force 255 363 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MinForces-Order", "Plot of min approximated forces versus the Bond Order", datum, CreateMinimumForce)) return 1; … … 296 404 yrange.str("[1e-8:1e+1]"); 297 405 298 // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order 299 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; 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 } 300 410 301 411 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM … … 380 490 // +++++++++++++++++++++++++++++++=Ploting approximated and true shielding for each atom 381 491 if (periode != NULL) { // also look for PAS values 382 if(!OpenOutputFile(output, argv[3], "ShieldingPAS-Atom.pyx")) return 1; 383 CreatePlotHeader(output, "ShieldingPAS-Atom", 1, "top right", NULL, NULL, 1, 5, "nuclei index", "chemical shielding value [ppm]"); 384 output << "plot \\" << endl; 385 output << "'ShieldingPAS-Atom.dat' index 0 title 'DFT' using 2:6 with linespoints, \\" << endl; 386 output << "'ShieldingPAS-Atom.dat' index 1 title 'BOSSANOVA' using 2:6 with linespoints" << endl; 492 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; 387 523 output.close(); 524 output2.close(); 388 525 } 389 526 -
Property mode
changed from
-
src/atom.cpp
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/bond.cpp
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/boundary.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 2 2 #include "boundary.hpp" 3 3 4 #define DEBUG 1 5 #define DoTecplotOutput 0 6 #define DoRaster3DOutput 1 7 #define TecplotSuffix ".dat" 8 #define Raster3DSuffix ".r3d" 9 4 10 // ======================================== Points on Boundary ================================= 5 11 … … 8 14 LinesCount = 0; 9 15 Nr = -1; 10 }; 16 } 17 ; 11 18 12 19 BoundaryPointSet::BoundaryPointSet(atom *Walker) … … 15 22 LinesCount = 0; 16 23 Nr = Walker->nr; 17 }; 24 } 25 ; 18 26 19 27 BoundaryPointSet::~BoundaryPointSet() … … 21 29 cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl; 22 30 node = NULL; 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 } 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 } 33 48 LinesCount++; 34 }; 35 36 ostream & operator << (ostream &ost, BoundaryPointSet &a) 49 } 50 ; 51 52 ostream & 53 operator <<(ostream &ost, BoundaryPointSet &a) 37 54 { 38 55 ost << "[" << a.Nr << "|" << a.node->Name << "]"; 39 56 return ost; 40 }; 57 } 58 ; 41 59 42 60 // ======================================== Lines on Boundary ================================= … … 44 62 BoundaryLineSet::BoundaryLineSet() 45 63 { 46 for (int i =0;i<2;i++)64 for (int i = 0; i < 2; i++) 47 65 endpoints[i] = NULL; 48 66 TrianglesCount = 0; 49 67 Nr = -1; 50 }; 68 } 69 ; 51 70 52 71 BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number) … … 57 76 SetEndpointsOrdered(endpoints, Point[0], Point[1]); 58 77 // add this line to the hash maps of both endpoints 59 Point[0]->AddLine(this); 60 Point[1]->AddLine(this); 78 Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding. 79 Point[1]->AddLine(this); // 61 80 // clear triangles list 62 81 TrianglesCount = 0; 63 82 cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl; 64 }; 83 } 84 ; 65 85 66 86 BoundaryLineSet::~BoundaryLineSet() 67 87 { 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) ); 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)); 85 112 TrianglesCount++; 86 }; 87 88 ostream & operator << (ostream &ost, BoundaryLineSet &a) 89 { 90 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "]"; 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 << "]"; 91 121 return ost; 92 }; 122 } 123 ; 93 124 94 125 // ======================================== Triangles on Boundary ================================= … … 97 128 BoundaryTriangleSet::BoundaryTriangleSet() 98 129 { 99 for (int i=0;i<3;i++) { 100 endpoints[i] = NULL; 101 lines[i] = NULL; 102 } 130 for (int i = 0; i < 3; i++) 131 { 132 endpoints[i] = NULL; 133 lines[i] = NULL; 134 } 103 135 Nr = -1; 104 }; 105 106 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], int number) 136 } 137 ; 138 139 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], 140 int number) 107 141 { 108 142 // set number … … 110 144 // set lines 111 145 cout << Verbose(5) << "New triangle " << Nr << ":" << endl; 112 for (int i=0;i<3;i++) { 113 lines[i] = line[i]; 114 lines[i]->AddTriangle(this); 115 } 146 for (int i = 0; i < 3; i++) 147 { 148 lines[i] = line[i]; 149 lines[i]->AddTriangle(this); 150 } 116 151 // 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 122 } 152 map<int, class BoundaryPointSet *> OrderMap; 153 for (int i = 0; i < 3; i++) 154 // for all three lines 155 for (int j = 0; j < 2; j++) 156 { // for both endpoints 157 OrderMap.insert(pair<int, class BoundaryPointSet *> ( 158 line[i]->endpoints[j]->Nr, line[i]->endpoints[j])); 159 // and we don't care whether insertion fails 160 } 123 161 // set endpoints 124 162 int Counter = 0; 125 163 cout << Verbose(6) << " with end points "; 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 } 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 } 135 177 cout << "." << endl; 136 }; 178 } 179 ; 137 180 138 181 BoundaryTriangleSet::~BoundaryTriangleSet() 139 182 { 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) 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) 154 201 { 155 202 // get normal vector 156 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, &endpoints[2]->node->x); 157 203 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, 204 &endpoints[2]->node->x); 205 158 206 // make it always point inward (any offset vector onto plane projected onto normal vector suffices) 159 if (endpoints[0]->node->x.Projection(& NormalVector) > 0)207 if (endpoints[0]->node->x.Projection(&OtherVector) > 0) 160 208 NormalVector.Scale(-1.); 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 << "]"; 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 << "]"; 166 217 return ost; 167 }; 218 } 219 ; 168 220 169 221 // ========================================== F U N C T I O N S ================================= … … 174 226 * \return point which is shared or NULL if none 175 227 */ 176 class BoundaryPointSet * GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2) 177 { 178 class BoundaryLineSet * lines[2] = {line1, line2}; 228 class BoundaryPointSet * 229 GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2) 230 { 231 class BoundaryLineSet * lines[2] = 232 { line1, line2 }; 179 233 class BoundaryPointSet *node = NULL; 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; 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 } 191 251 } 192 }193 252 return node; 194 }; 253 } 254 ; 195 255 196 256 /** Determines the boundary points of a cluster. … … 201 261 * \param *mol molecule structure representing the cluster 202 262 */ 203 Boundaries * GetBoundaryPoints(ofstream *out, molecule *mol) 263 Boundaries * 264 GetBoundaryPoints(ofstream *out, molecule *mol) 204 265 { 205 266 atom *Walker = NULL; … … 207 268 LineMap LinesOnBoundary; 208 269 TriangleMap TrianglesOnBoundary; 209 270 210 271 *out << Verbose(1) << "Finding all boundary points." << endl; 211 Boundaries *BoundaryPoints = new Boundaries [NDIM];// first is alpha, second is (r, nr)272 Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr) 212 273 BoundariesTestPair BoundaryTestPair; 213 274 Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector; 214 275 double radius, angle; 215 276 // 3a. Go through every axis 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; 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) 296 { 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 } 278 360 } 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; 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 } 307 457 } 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) 317 { 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 } 363 } 364 } 365 } while (flag); 366 } 458 while (flag); 459 } 367 460 return BoundaryPoints; 368 }; 461 } 462 ; 369 463 370 464 /** Determines greatest diameters of a cluster defined by its convex envelope. … … 375 469 * \param IsAngstroem whether we have angstroem or atomic units 376 470 * \return NDIM array of the diameters 377 */ 378 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem) 471 */ 472 double * 473 GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, 474 bool IsAngstroem) 379 475 { 380 476 // get points on boundary of NULL was given as parameter 381 477 bool BoundaryFreeFlag = false; 382 478 Boundaries *BoundaryPoints = BoundaryPtr; 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 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 } 390 488 // determine biggest "diameter" of cluster for each axis 391 489 Boundaries::iterator Neighbour, OtherNeighbour; 392 490 double *GreatestDiameter = new double[NDIM]; 393 for (int i=0;i<NDIM;i++)491 for (int i = 0; i < NDIM; i++) 394 492 GreatestDiameter[i] = 0.; 395 493 double OldComponent, tmp, w1, w2; 396 494 Vector DistanceVector, OtherVector; 397 495 int component, Othercomponent; 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 } 443 } 444 } 445 *out << Verbose(0) << "RESULT: The biggest diameters are " << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and " << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "." << endl; 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 } 553 } 554 *out << Verbose(0) << "RESULT: The biggest diameters are " 555 << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and " 556 << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom" 557 : "atomiclength") << "." << endl; 446 558 447 559 // free reference lists 448 560 if (BoundaryFreeFlag) 449 delete[] (BoundaryPoints);561 delete[] (BoundaryPoints); 450 562 451 563 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); 452 619 }; 453 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 } 454 671 455 672 /** Determines the volume of a cluster. 456 673 * Determines first the convex envelope, then tesselates it and calculates its volume. 457 674 * \param *out output stream for debugging 675 * \param *tecplot output stream for tecplot data 458 676 * \param *configuration needed for path to store convex envelope file 459 677 * \param *BoundaryPoints NDIM set of boundary points on the projected plane per axis, on return if desired 460 678 * \param *mol molecule structure representing the cluster 679 * \return determined volume of the cluster in cubed config:GetIsAngstroem() 461 680 */ 462 double VolumeOfConvexEnvelope(ofstream *out, config *configuration, Boundaries *BoundaryPtr, molecule *mol) 681 double 682 VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, 683 Boundaries *BoundaryPtr, molecule *mol) 463 684 { 464 685 bool IsAngstroem = configuration->GetIsAngstroem(); … … 469 690 double volume = 0.; 470 691 double PyramidVolume = 0.; 471 double G,h; 472 Vector x,y; 473 double a,b,c; 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. 474 697 475 698 // 1. calculate center of gravity 476 699 *out << endl; 477 700 Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out); 478 701 479 702 // 2. translate all points into CoG 480 703 *out << Verbose(1) << "Translating system to Center of Gravity." << endl; 481 704 Walker = mol->start; 482 while (Walker->next != mol->end) { 483 Walker = Walker->next; 484 Walker->x.Translate(CenterOfGravity); 485 } 486 705 while (Walker->next != mol->end) 706 { 707 Walker = Walker->next; 708 Walker->x.Translate(CenterOfGravity); 709 } 710 487 711 // 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 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 495 722 // 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); 499 } 500 501 *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount << " points on the convex boundary." << endl; 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; 502 732 // now we have the whole set of edge points in the BoundaryList 503 733 504 505 734 // listing for debugging 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 735 // *out << Verbose(1) << "Listing PointsOnBoundary:"; 736 // for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) { 737 // *out << " " << *runner->second; 738 // } 739 // *out << endl; 740 512 741 // 5a. guess starting triangle 513 742 TesselStruct->GuessStartingTriangle(out); 514 743 515 744 // 5b. go through all lines, that are not yet part of two triangles (only of one so far) 516 745 TesselStruct->TesselateOnBoundary(out, configuration, mol); 517 746 518 *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount << " triangles with " << TesselStruct->LinesOnBoundaryCount << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." << endl; 747 *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount 748 << " triangles with " << TesselStruct->LinesOnBoundaryCount 749 << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." 750 << endl; 519 751 520 752 // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes 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 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; 540 786 541 787 // 7. translate all points back from CoG 542 *out << Verbose(1) << "Translating system back from Center of Gravity." << endl; 788 *out << Verbose(1) << "Translating system back from Center of Gravity." 789 << endl; 543 790 CenterOfGravity->Scale(-1); 544 791 Walker = mol->start; 545 while (Walker->next != mol->end) { 546 Walker = Walker->next; 547 Walker->x.Translate(CenterOfGravity); 548 } 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); 549 800 550 801 // free reference lists 551 802 if (BoundaryFreeFlag) 552 delete[] (BoundaryPoints);553 803 delete[] (BoundaryPoints); 804 554 805 return volume; 555 } ;556 806 } 807 ; 557 808 558 809 /** Creates multiples of the by \a *mol given cluster and suspends them in water with a given final density. … … 564 815 * \param celldensity desired average density in final cell 565 816 */ 566 void PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, double ClusterVolume, double celldensity) 817 void 818 PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, 819 double ClusterVolume, double celldensity) 567 820 { 568 821 // transform to PAS 569 822 mol->PrincipalAxisSystem(out, true); 570 823 571 824 // some preparations beforehand 572 825 bool IsAngstroem = configuration->GetIsAngstroem(); … … 574 827 double clustervolume; 575 828 if (ClusterVolume == 0) 576 clustervolume = VolumeOfConvexEnvelope(out, configuration, BoundaryPoints, mol); 577 else 829 clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration, 830 BoundaryPoints, mol); 831 else 578 832 clustervolume = ClusterVolume; 579 double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, IsAngstroem); 833 double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, 834 IsAngstroem); 580 835 Vector BoxLengths; 581 int repetition[NDIM] = {1, 1, 1}; 836 int repetition[NDIM] = 837 { 1, 1, 1 }; 582 838 int TotalNoClusters = 1; 583 for (int i =0;i<NDIM;i++)839 for (int i = 0; i < NDIM; i++) 584 840 TotalNoClusters *= repetition[i]; 585 841 … … 587 843 double totalmass = 0.; 588 844 atom *Walker = mol->start; 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 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 597 857 // solve cubic polynomial 598 *out << Verbose(1) << "Solving equidistant suspension in water problem ..." << endl; 858 *out << Verbose(1) << "Solving equidistant suspension in water problem ..." 859 << endl; 599 860 double cellvolume; 600 861 if (IsAngstroem) 601 cellvolume = (TotalNoClusters*totalmass/SOLVENTDENSITY_A - (totalmass/clustervolume))/(celldensity-1); 862 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass 863 / clustervolume)) / (celldensity - 1); 602 864 else 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 626 } 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]; 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 } 865 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass 866 / clustervolume)) / (celldensity - 1); 867 *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity 868 << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom" 869 : "atomiclength") << "^3." << endl; 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 << endl; 885 for (int i = 0; i < NDIM; i++) 886 BoxLengths.x[i] = GreatestDiameter[i]; 887 mol->CenterEdge(out, &BoxLengths); 888 } 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); 920 } 638 921 // update Box of atoms by boundary 639 922 mol->SetBoxDimension(&BoxLengths); 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 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 ; 643 929 644 930 // =========================================================== class TESSELATION =========================================== … … 648 934 Tesselation::Tesselation() 649 935 { 650 PointsOnBoundaryCount = 0; 651 LinesOnBoundaryCount = 0; 936 PointsOnBoundaryCount = 0; 937 LinesOnBoundaryCount = 0; 652 938 TrianglesOnBoundaryCount = 0; 653 }; 939 TriangleFilesWritten = 0; 940 } 941 ; 654 942 655 943 /** Constructor of class Tesselation. … … 658 946 Tesselation::~Tesselation() 659 947 { 660 for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) { 661 delete(runner->second); 662 } 663 }; 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 ; 664 972 665 973 /** Gueses first starting triangle of the convex envelope. … … 667 975 * \param *out output stream for debugging 668 976 * \param PointsOnBoundary set of boundary points defining the convex envelope of the cluster 669 */ 670 void Tesselation::GuessStartingTriangle(ofstream *out) 977 */ 978 void 979 Tesselation::GuessStartingTriangle(ofstream *out) 671 980 { 672 981 // 4b. create a starting triangle 673 982 // 4b1. create all distances 674 983 DistanceMultiMap DistanceMMap; 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 } 682 } 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 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 } 1010 } 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 694 1019 DistanceMultiMap::iterator baseline = DistanceMMap.begin(); 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 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 ; 737 1135 738 1136 /** Tesselates the convex envelope of a cluster from a single starting triangle. … … 749 1147 * \param *mol the cluster as a molecule structure 750 1148 */ 751 void Tesselation::TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol) 1149 void 1150 Tesselation::TesselateOnBoundary(ofstream *out, config *configuration, 1151 molecule *mol) 752 1152 { 753 1153 bool flag; … … 755 1155 class BoundaryPointSet *peak = NULL; 756 1156 double SmallestAngle, TempAngle; 757 Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, PropagationVector; 1157 Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, 1158 PropagationVector; 758 1159 LineMap::iterator LineChecker[2]; 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; 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++; 861 1355 } 862 } 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 863 1364 } 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 }; 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 ; 930 1374 931 1375 /** Adds an atom to the tesselation::PointsOnBoundary list. 932 1376 * \param *Walker atom to add 933 1377 */ 934 void Tesselation::AddPoint(atom *Walker) 935 { 1378 void 1379 Tesselation::AddPoint(atom *Walker) 1380 { 1381 PointTestPair InsertUnique; 936 1382 BPS[0] = new class BoundaryPointSet(Walker); 937 PointsOnBoundary.insert( PointPair(Walker->nr, BPS[0]) ); 938 PointsOnBoundaryCount++; 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 } 939 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 -
Property mode
changed from
-
src/boundary.hpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 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; 71 72 int Nr; 72 73 }; … … 74 75 class Tesselation { 75 76 public: 76 77 77 78 Tesselation(); 78 79 ~Tesselation(); 79 80 80 81 void TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol); 81 82 void GuessStartingTriangle(ofstream *out); 82 83 void AddPoint(atom * Walker); 83 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 84 92 PointMap PointsOnBoundary; 85 93 LineMap LinesOnBoundary; 86 94 TriangleMap TrianglesOnBoundary; 95 class BoundaryPointSet *TPS[3]; //this is a Storage for pointers to triangle points, this and BPS[2] needed due to AddLine restrictions 87 96 class BoundaryPointSet *BPS[2]; 88 97 class BoundaryLineSet *BLS[3]; … … 91 100 int LinesOnBoundaryCount; 92 101 int TrianglesOnBoundaryCount; 102 int TriangleFilesWritten; 93 103 }; 94 104 … … 99 109 100 110 101 double VolumeOfConvexEnvelope(ofstream *out, config *configuration, Boundaries *BoundaryPoints, molecule *mol);111 double VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, Boundaries *BoundaryPoints, molecule *mol); 102 112 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem); 103 113 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); 104 116 105 117 -
Property mode
changed from
-
src/builder.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 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 ;261 Vector x, y, helper; 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 mol->SetBoxDimension(&(x+y*2)); // update Box of atoms by boundary 294 helper.CopyVector(&y); 295 helper.Scale(2.); 296 helper.AddVector(&x); 297 mol->SetBoxDimension(&helper); // update Box of atoms by boundary 295 298 break; 296 299 case 'd': … … 327 330 cout << Verbose(0) << "INPUT: "; 328 331 cin >> choice; 329 332 330 333 switch (choice) { 331 334 default: … … 346 349 second = mol->AskAtom("Enter second atom: "); 347 350 348 n.CopyVector((const Vector *)&first->x); 349 n.SubtractVector((const Vector *)&second->x); 351 n.CopyVector((const Vector *)&first->x); 352 n.SubtractVector((const Vector *)&second->x); 350 353 n.Normalize(); 351 break; 354 break; 352 355 case 'd': 353 356 char shorthand[4]; … … 363 366 x.x[i] = gsl_vector_get(param.x,i); 364 367 n.x[i] = gsl_vector_get(param.x,i+NDIM); 365 } 368 } 366 369 gsl_vector_free(param.x); 367 370 cout << Verbose(0) << "Offset vector: "; … … 369 372 cout << Verbose(0) << endl; 370 373 n.Normalize(); 371 break; 374 break; 372 375 }; 373 376 cout << Verbose(0) << "Alignment vector: "; … … 385 388 Vector n; 386 389 char choice; // menu choice char 387 390 388 391 cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl; 389 392 cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl; … … 394 397 cout << Verbose(0) << "INPUT: "; 395 398 cin >> choice; 396 399 397 400 switch (choice) { 398 401 default: … … 413 416 second = mol->AskAtom("Enter second atom: "); 414 417 415 n.CopyVector((const Vector *)&first->x); 416 n.SubtractVector((const Vector *)&second->x); 418 n.CopyVector((const Vector *)&first->x); 419 n.SubtractVector((const Vector *)&second->x); 417 420 n.Normalize(); 418 break; 421 break; 419 422 }; 420 423 cout << Verbose(0) << "Normal vector: "; … … 433 436 double tmp1, tmp2; 434 437 char choice; // menu choice char 435 438 436 439 cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl; 437 440 cout << Verbose(0) << " a - state atom for removal by number" << endl; … … 442 445 cout << Verbose(0) << "INPUT: "; 443 446 cin >> choice; 444 447 445 448 switch (choice) { 446 449 default: … … 475 478 mol->RemoveAtom(first); 476 479 } 477 break; 480 break; 478 481 }; 479 482 //mol->Output((ofstream *)&cout); … … 492 495 int Z; 493 496 char choice; // menu choice char 494 497 495 498 cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl; 496 499 cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl; … … 514 517 for (int i=MAX_ELEMENTS;i--;) 515 518 min[i] = 0.; 516 517 second = mol->start; 519 520 second = mol->start; 518 521 while ((second->next != mol->end)) { 519 522 second = second->next; // advance … … 526 529 } 527 530 if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1; 528 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl; 531 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl; 529 532 } 530 533 for (int i=MAX_ELEMENTS;i--;) 531 534 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; 532 535 break; 533 536 534 537 case 'b': 535 538 first = mol->AskAtom("Enter first atom: "); … … 556 559 y.SubtractVector((const Vector *)&second->x); 557 560 cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": "; 558 cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl; 561 cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl; 559 562 break; 560 563 case 'd': … … 569 572 case 'e': 570 573 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 571 VolumeOfConvexEnvelope((ofstream *)&cout, configuration, NULL, mol);574 VolumeOfConvexEnvelope((ofstream *)&cout, NULL, configuration, NULL, mol); 572 575 break; 573 576 case 'f': … … 600 603 int Order1; 601 604 clock_t start, end; 602 605 603 606 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl; 604 607 cout << Verbose(0) << "What's the desired bond order: "; … … 609 612 end = clock(); 610 613 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 611 } else 614 } else 612 615 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl; 613 616 }; … … 623 626 atom *Walker = mol->start; 624 627 int i, comp, counter=0; 625 628 626 629 // generate some KeySets 627 630 cout << "Generating KeySets." << endl; … … 637 640 cout << "Testing insertion of already present item in KeySets." << endl; 638 641 KeySetTestPair test; 639 test = TestSets[mol->AtomCount-1].insert(Walker->nr); 642 test = TestSets[mol->AtomCount-1].insert(Walker->nr); 640 643 if (test.second) { 641 644 cout << Verbose(1) << "Insertion worked?!" << endl; … … 646 649 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr); 647 650 648 // constructing Graph structure 651 // constructing Graph structure 649 652 cout << "Generating Subgraph class." << endl; 650 653 Graph Subgraphs; … … 657 660 cout << "Testing insertion of already present item in Subgraph." << endl; 658 661 GraphTestPair test2; 659 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.))); 662 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.))); 660 663 if (test2.second) { 661 664 cout << Verbose(1) << "Insertion worked?!" << endl; … … 663 666 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl; 664 667 } 665 668 666 669 // show graphs 667 670 cout << "Showing Subgraph's contents, checking that it's sorted." << endl; … … 674 677 if ((*key) > comp) 675 678 cout << (*key) << " "; 676 else 679 else 677 680 cout << (*key) << "! "; 678 681 comp = (*key); … … 694 697 char filename[MAXSTRINGSIZE]; 695 698 ofstream output; 699 string basis("3-21G"); 696 700 697 701 cout << Verbose(0) << "Storing configuration ... " << endl; … … 699 703 mol->CalculateOrbitals(*configuration); 700 704 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble; 701 if (ConfigFileName != NULL) { 705 strcpy(filename, ConfigFileName); 706 if (ConfigFileName != NULL) { // test the file name 702 707 output.open(ConfigFileName, ios::trunc); 703 708 } else if (strlen(configuration->configname) != 0) { 709 strcpy(filename, configuration->configname); 704 710 output.open(configuration->configname, ios::trunc); 705 711 } else { 712 strcpy(filename, DEFAULTCONFIG); 706 713 output.open(DEFAULTCONFIG, ios::trunc); 707 714 } 715 output.close(); 716 output.clear(); 708 717 cout << Verbose(0) << "Saving of config file "; 709 if (configuration->Save( &output, periode, mol))718 if (configuration->Save(filename, periode, mol)) 710 719 cout << "successful." << endl; 711 720 else 712 721 cout << "failed." << endl; 713 output.close(); 714 output.clear(); 715 722 716 723 // and save to xyz file 717 724 if (ConfigFileName != NULL) { … … 724 731 strcat(filename, ".xyz"); 725 732 output.open(filename, ios::trunc); 726 } 733 } 727 734 cout << Verbose(0) << "Saving of XYZ file "; 728 735 if (mol->MDSteps <= 1) { … … 739 746 output.close(); 740 747 output.clear(); 741 748 742 749 // and save as MPQC configuration 743 if (ConfigFileName != NULL) {750 if (ConfigFileName != NULL) 744 751 strcpy(filename, ConfigFileName); 745 strcat(filename, ".in"); 746 output.open(filename, ios::trunc); 747 } 748 if (output == NULL) { 752 if (output == NULL) 749 753 strcpy(filename,"main_pcp_linux"); 750 strcat(filename, ".in");751 output.open(filename, ios::trunc);752 }753 754 cout << Verbose(0) << "Saving as mpqc input "; 754 if (configuration->SaveMPQC( &output, mol))755 if (configuration->SaveMPQC(filename, mol)) 755 756 cout << "done." << endl; 756 757 else 757 758 cout << "failed." << endl; 758 output.close(); 759 output.clear(); 760 759 761 760 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) { 762 761 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl; … … 790 789 int argptr; 791 790 PathToDatabases = LocalPath; 792 791 793 792 if (argc > 1) { // config file specified as option 794 793 // 1. : Parse options that just set variables or print help … … 803 802 case '?': 804 803 cout << "MoleCuilder suite" << endl << "==================" << endl << endl; 805 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl; 804 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl; 806 805 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl; 807 806 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; 809 810 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl; 810 811 cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl; … … 817 818 cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl; 818 819 cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl; 819 cout << "\t-o\tGet volume of the convex envelope (and store to tecplot file)." << 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; 820 822 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl; 821 823 cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl; … … 823 825 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl; 824 826 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl; 825 cout << "\t-T <file> Store temperatures from the config file in <file>." << endl; 827 cout << "\t-T <file> Store temperatures from the config file in <file>." << endl; 826 828 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl; 827 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl; 829 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl; 828 830 cout << "\t-v/-V\t\tGives version information." << endl; 829 831 cout << "Note: config files must not begin with '-' !" << endl; … … 841 843 break; 842 844 case 'e': 843 cout << "Using " << argv[argptr] << " as elements database." << endl; 844 PathToDatabases = argv[argptr]; 845 argptr+=1; 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 } 846 852 break; 847 853 case 'n': … … 856 862 argptr++; 857 863 } while (argptr < argc); 858 864 859 865 // 2. Parse the element database 860 866 if (periode->LoadPeriodentafel(PathToDatabases)) { … … 865 871 return 1; 866 872 } 867 873 868 874 // 3. Find config file name and parse if possible 869 875 if (argv[1][0] != '-') { … … 904 910 } else 905 911 config_present = absent; 906 912 907 913 // 4. parse again through options, now for those depending on elements db and config presence 908 914 argptr = 1; … … 915 921 case 'p': 916 922 ExitFlag = 1; 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; 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; 933 config_present = present; 934 } 924 935 } 925 936 break; 926 937 case 'a': 927 938 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)) 939 config_present = present; 940 } else 941 cerr << Verbose(1) << "Could not find the specified element." << endl; 942 argptr+=4; 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 } 943 959 break; 944 960 default: // no match? Don't step on (this is done in next switch's default) … … 948 964 if (config_present == present) { 949 965 switch(argv[argptr-1][1]) { 950 case 'D': 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': 951 977 ExitFlag = 1; 952 978 { … … 979 1005 delete[](MinimumRingSize); 980 1006 } 981 argptr+=1;1007 //argptr+=1; 982 1008 break; 983 1009 case 'E': 984 1010 ExitFlag = 1; 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; 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; 991 1051 case 'T': 992 1052 ExitFlag = 1; 993 { 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 { 994 1057 cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl; 995 1058 ofstream *output = new ofstream(argv[argptr], ios::trunc); … … 1000 1063 output->close(); 1001 1064 delete(output); 1065 argptr+=1; 1002 1066 } 1003 argptr+=1;1004 1067 break; 1005 1068 case 'L': … … 1015 1078 case 'P': 1016 1079 ExitFlag = 1; 1017 SaveFlag = true; 1018 cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl; 1019 if (!mol->VerletForceIntegration((ofstream *)&cout, argv[argptr], configuration)) 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++; 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; 1026 1091 } 1027 argptr+=1;1028 1092 break; 1029 1093 case 't': 1030 1094 ExitFlag = 1; 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; 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; 1106 } 1037 1107 break; 1038 1108 case 's': 1039 1109 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]; 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; 1056 1133 } 1057 delete[](factor);1058 argptr+=1;1059 1134 break; 1060 1135 case 'b': 1061 1136 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.; 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 SaveFlag = true; 1142 j = -1; 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 // center 1151 mol->CenterInBox((ofstream *)&cout, &x); 1152 // update Box of atoms by boundary 1153 mol->SetBoxDimension(&x); 1070 1154 } 1071 // center1072 mol->CenterInBox((ofstream *)&cout, &x);1073 // update Box of atoms by boundary1074 mol->SetBoxDimension(&x);1075 1155 break; 1076 1156 case 'c': 1077 1157 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.; 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); 1091 1177 } 1092 mol->Translate((const Vector *)&x);1093 1178 break; 1094 1179 case 'O': … … 1107 1192 case 'f': 1108 1193 ExitFlag = 1; 1109 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl; 1110 if (argc >= argptr+2) { 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; 1111 1199 cout << Verbose(0) << "Creating connection matrix..." << endl; 1112 1200 start = clock(); … … 1118 1206 end = clock(); 1119 1207 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 1120 argptr+=1; 1121 } else { 1122 cerr << "Not enough arguments for fragmentation: -f <max. bond distance> <bond order>" << endl; 1208 argptr+=2; 1123 1209 } 1124 1210 break; … … 1139 1225 case 'o': 1140 1226 ExitFlag = 1; 1141 SaveFlag = true; 1142 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 1143 VolumeOfConvexEnvelope((ofstream *)&cout, &configuration, NULL, mol); 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 } 1144 1240 break; 1145 1241 case 'U': 1146 1242 ExitFlag = 1; 1147 volume = atof(argv[argptr++]); 1148 cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl; 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 } 1149 1251 case 'u': 1150 1252 ExitFlag = 1; 1151 { 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 { 1152 1258 double density; 1153 1259 SaveFlag = true; … … 1164 1270 // repetition[i] = 1; 1165 1271 // } 1166 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density); 1272 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density); // if volume == 0, will calculate from ConvexEnvelope 1167 1273 } 1168 1274 break; 1169 1275 case 'd': 1170 1276 ExitFlag = 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++; 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; 1193 1290 } 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, ...) 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++; 1207 1303 } 1304 if (count != j) 1305 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl; 1306 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; 1208 1330 } 1209 // free memory1210 delete[](Elements);1211 delete[](vectors);1212 // correct cell size1213 if (axis < 0) { // if sign was negative, we have to translate everything1214 x.Zero();1215 x.AddVector(&y);1216 x.Scale(-(faktor-1));1217 mol->Translate(&x);1218 }1219 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;1220 1331 } 1221 1332 } … … 1279 1390 if (j == 1) return 0; // just for -v and -h options 1280 1391 if (j) return j; // something went wrong 1281 1392 1282 1393 // General stuff 1283 1394 if (mol->cell_size[0] == 0.) { … … 1293 1404 // now the main construction loop 1294 1405 cout << Verbose(0) << endl << "Now comes the real construction..." << endl; 1295 do { 1406 do { 1296 1407 cout << Verbose(0) << endl << endl; 1297 1408 cout << Verbose(0) << "============Element list=======================" << endl; … … 1312 1423 cout << Verbose(0) << "-----------------------------------------------" << endl; 1313 1424 cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl; 1314 cout << Verbose(0) << "i - realign molecule" << endl; 1315 cout << Verbose(0) << "m - mirror all molecules" << endl; 1425 cout << Verbose(0) << "i - realign molecule" << endl; 1426 cout << Verbose(0) << "m - mirror all molecules" << endl; 1316 1427 cout << Verbose(0) << "t - translate molecule by vector" << endl; 1317 1428 cout << Verbose(0) << "c - scale by unit transformation" << endl; … … 1324 1435 cout << Verbose(0) << "Input: "; 1325 1436 cin >> choice; 1326 1437 1327 1438 switch (choice) { 1328 1439 default: 1329 1440 case 'a': // add atom 1330 1441 AddAtoms(periode, mol); 1331 choice = 'a'; 1332 break; 1333 1442 choice = 'a'; 1443 break; 1444 1334 1445 case 'b': // scale a bond 1335 1446 cout << Verbose(0) << "Scaling bond length between two atoms." << endl; … … 1347 1458 } 1348 1459 //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: "; 1349 //second->Output(second->type->No, 1, (ofstream *)&cout); 1350 break; 1351 1352 case 'c': // unit scaling of the metric 1460 //second->Output(second->type->No, 1, (ofstream *)&cout); 1461 break; 1462 1463 case 'c': // unit scaling of the metric 1353 1464 cout << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl; 1354 1465 cout << Verbose(0) << "Enter three factors: "; … … 1361 1472 delete[](factor); 1362 1473 break; 1363 1474 1364 1475 case 'd': // duplicate the periodic cell along a given axis, given times 1365 1476 cout << Verbose(0) << "State the axis [(+-)123]: "; … … 1367 1478 cout << Verbose(0) << "State the factor: "; 1368 1479 cin >> faktor; 1369 1480 1370 1481 mol->CountAtoms((ofstream *)&cout); // recount atoms 1371 1482 if (mol->AtomCount != 0) { // if there is more than none … … 1408 1519 mol->Translate(&x); 1409 1520 } 1410 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1521 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1411 1522 } 1412 1523 break; 1413 1524 1414 1525 case 'e': // edit each field of the configuration 1415 1526 configuration.Edit(mol); 1416 1527 break; 1417 1528 1418 1529 case 'f': 1419 1530 FragmentAtoms(mol, &configuration); 1420 1531 break; 1421 1532 1422 1533 case 'g': // center the atoms 1423 1534 CenterAtoms(mol); 1424 1535 break; 1425 1426 case 'i': // align all atoms 1536 1537 case 'i': // align all atoms 1427 1538 AlignAtoms(periode, mol); 1428 1539 break; … … 1435 1546 MirrorAtoms(mol); 1436 1547 break; 1437 1548 1438 1549 case 'o': // create the connection matrix 1439 1550 { … … 1456 1567 } 1457 1568 break; 1458 1569 1459 1570 case 'p': // parse and XYZ file 1460 1571 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl; … … 1465 1576 break; 1466 1577 1467 case 'q': // quit 1468 break; 1469 1578 case 'q': // quit 1579 break; 1580 1470 1581 case 'r': // remove atom 1471 RemoveAtoms(mol); 1472 break; 1473 1582 RemoveAtoms(mol); 1583 break; 1584 1474 1585 case 's': // save to config file 1475 1586 SaveConfig(ConfigFileName, &configuration, periode, mol); … … 1477 1588 1478 1589 case 't': // translate all atoms 1479 cout << Verbose(0) << "Enter translation vector." << endl; 1590 cout << Verbose(0) << "Enter translation vector." << endl; 1480 1591 x.AskPosition(mol->cell_size,0); 1481 1592 mol->Translate((const Vector *)&x); 1482 1593 break; 1483 1594 1484 1595 case 'T': 1485 1596 testroutine(mol); 1486 1597 break; 1487 1598 1488 1599 case 'u': // change an atom's element 1489 1600 first = NULL; … … 1492 1603 cin >> Z; 1493 1604 } while ((first = mol->FindAtom(Z)) == NULL); 1494 cout << Verbose(0) << "New element by atomic number Z: "; 1605 cout << Verbose(0) << "New element by atomic number Z: "; 1495 1606 cin >> Z; 1496 1607 first->type = periode->FindElement(Z); 1497 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl; 1608 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl; 1498 1609 break; 1499 1610 }; 1500 1611 } while (choice != 'q'); 1501 1612 1502 1613 // save element data base 1503 1614 if (periode->StorePeriodentafel(ElementsFileName)) //ElementsFileName -
Property mode
changed from
-
src/config.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 31 31 configpath[0]='\0'; 32 32 configname[0]='\0'; 33 basis="3-21G"; 34 33 35 34 36 strcpy(ThermostatNames[0],"None"); … … 1073 1075 1074 1076 /** Stores all elements of config structure from which they can be re-read. 1075 * \param output open output *file stream to write to1077 * \param *filename name of file 1076 1078 * \param *periode pointer to a periodentafel class with all elements 1077 1079 * \param *mol pointer to molecule containing all atoms of the molecule 1078 1080 */ 1079 bool config::Save( ofstream *output, periodentafel *periode, molecule *mol) const1081 bool config::Save(const char *filename, periodentafel *periode, molecule *mol) const 1080 1082 { 1081 1083 bool result = true; 1082 1084 // bring MaxTypes up to date 1083 1085 mol->CountElements(); 1086 ofstream *output = NULL; 1087 output = new ofstream(filename, ios::out); 1084 1088 if (output != NULL) { 1085 1089 *output << "# ParallelCarParinello - main configuration file - created with molecuilder" << endl; … … 1192 1196 else 1193 1197 result = result && mol->OutputTrajectories(output); 1198 output->close(); 1199 output->clear(); 1200 delete(output); 1194 1201 return result; 1195 1202 } else … … 1199 1206 /** Stores all elements in a MPQC input file. 1200 1207 * Note that this format cannot be parsed again. 1201 * \param output open output *file stream to write to1208 * \param *filename name of file (without ".in" suffix!) 1202 1209 * \param *mol pointer to molecule containing all atoms of the molecule 1203 1210 */ 1204 bool config::SaveMPQC( ofstream *output, molecule *mol) const1211 bool config::SaveMPQC(const char *filename, molecule *mol) const 1205 1212 { 1206 1213 int ElementNo = 0; 1207 1214 int AtomNo; 1208 1215 atom *Walker = NULL; 1209 element *runner = mol->elemente->start;1216 element *runner = NULL; 1210 1217 Vector *center = NULL; 1211 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); 1212 1225 *output << "% Created by MoleCuilder" << endl; 1213 1226 *output << "mpqc: (" << endl; … … 1215 1228 *output << "\tdo_gradient = yes" << endl; 1216 1229 *output << "\tmole<CLHF>: (" << endl; 1217 *output << "\t\tmolecule<Molecule>: (" << endl; 1218 *output << "\t\t\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl; 1219 *output << "\t\t\t{ atoms geometry } = {" << 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; 1220 1238 center = mol->DetermineCenterOfAll(output); 1221 1239 // output of atoms 1240 runner = mol->elemente->start; 1222 1241 while (runner->next != mol->elemente->end) { // go through every element 1223 1242 runner = runner->next; … … 1230 1249 if (Walker->type == runner) { // if this atom fits to element 1231 1250 AtomNo++; 1232 *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;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; 1233 1252 } 1234 1253 } … … 1236 1255 } 1237 1256 delete(center); 1238 *output << "\t\t\t}" << endl; 1239 *output << "\t\t)" << endl; 1240 *output << "\t\tbasis<GaussianBasisSet>: (" << endl; 1241 *output << "\t\t\tname = \"STO-3G\"" << endl; 1242 *output << "\t\t\tmolecule = $:mpqc:mole:molecule" << endl; 1243 *output << "\t\t)" << endl; 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; 1244 1282 *output << "\t)" << endl; 1245 1283 *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 atoms 1289 runner = mol->elemente->start; 1290 while (runner->next != mol->elemente->end) { // go through every element 1291 runner = runner->next; 1292 if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms 1293 ElementNo++; 1294 AtomNo = 0; 1295 Walker = mol->start; 1296 while (Walker->next != mol->end) { // go through every atom of this element 1297 Walker = Walker->next; 1298 if (Walker->type == runner) { // if this atom fits to element 1299 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 1246 1316 return true; 1247 1317 }; -
Property mode
changed from
-
src/datacreator.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 29 29 }; 30 30 31 /** Opens a file for appending with \a *filename in \a *dir. 32 * \param output file handle on return 33 * \param *dir directory 34 * \param *filename name of file 35 * \return true if file has been opened 36 */ 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 31 49 /** Plots an energy vs. order. 32 50 * \param &Fragments EnergyMatrix class containing matrix values … … 45 63 cout << msg << endl; 46 64 output << "# " << msg << ", created on " << datum; 47 output << "#Order\tFrag.No.\t" << Fragments.Header << endl;65 output << "#Order\tFrag.No.\t" << Fragments.Header[Fragments.MatrixCounter] << endl; 48 66 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 49 67 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) { 50 68 for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;) 51 for(int k=Fragments.ColumnCounter ;k--;)69 for(int k=Fragments.ColumnCounter[ KeySet.OrderSet[BondOrder][i] ];k--;) 52 70 Fragments.Matrix[Fragments.MatrixCounter][j][k] += Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 53 71 } 54 72 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 55 for (int l=0;l<Fragments.ColumnCounter ;l++)73 for (int l=0;l<Fragments.ColumnCounter[Fragments.MatrixCounter];l++) 56 74 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l]; 57 75 output << endl; … … 78 96 cout << msg << endl; 79 97 output << "# " << msg << ", created on " << datum; 80 output << "#Order\tFrag.No.\t" << Fragments.Header << endl;98 output << "#Order\tFrag.No.\t" << Fragments.Header[Fragments.MatrixCounter] << endl; 81 99 Fragments.SetLastMatrix(Energy.Matrix[Energy.MatrixCounter],0); 82 100 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 83 101 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) { 84 102 for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;) 85 for(int k=Fragments.ColumnCounter ;k--;)103 for(int k=Fragments.ColumnCounter[ KeySet.OrderSet[BondOrder][i] ];k--;) 86 104 Fragments.Matrix[Fragments.MatrixCounter][j][k] -= Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 87 105 } 88 106 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 89 for (int l=0;l<Fragments.ColumnCounter ;l++)107 for (int l=0;l<Fragments.ColumnCounter[Energy.MatrixCounter];l++) 90 108 if (fabs(Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]) < MYEPSILON) 91 109 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l]; … … 115 133 cout << msg << endl; 116 134 output << "# " << msg << ", created on " << datum; 117 output << "# Order\tFrag.No.\t" << Fragments.Header << endl;135 output << "# Order\tFrag.No.\t" << Fragments.Header[Fragments.MatrixCounter] << endl; 118 136 Fragments.SetLastMatrix(0.,0); 119 137 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { … … 121 139 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 122 140 CreateForce(Fragments, Fragments.MatrixCounter); 123 for (int l=0;l<Fragments.ColumnCounter ;l++)141 for (int l=0;l<Fragments.ColumnCounter[Fragments.MatrixCounter];l++) 124 142 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l]; 125 143 output << endl; … … 147 165 cout << msg << endl; 148 166 output << "# " << msg << ", created on " << datum; 149 output << "# Order\tFrag.No.\t" << Fragments.Header << endl;167 output << "# Order\tFrag.No.\t" << Fragments.Header[Fragments.MatrixCounter] << endl; 150 168 Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter],0); 151 169 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { … … 153 171 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 154 172 CreateForce(Fragments, Fragments.MatrixCounter); 155 for (int l=0;l<Fragments.ColumnCounter ;l++)173 for (int l=0;l<Fragments.ColumnCounter[Fragments.MatrixCounter];l++) 156 174 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l]; 157 175 output << endl; … … 180 198 cout << msg << endl; 181 199 output << "# " << msg << ", created on " << datum; 182 output << "# AtomNo\t" << Fragments.Header << endl;200 output << "# AtomNo\t" << Fragments.Header[Fragments.MatrixCounter] << endl; 183 201 Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter], 0); 184 202 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { … … 186 204 Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.); 187 205 // errors per atom 188 output << "#Order\t" << BondOrder+1 << endl;206 output << endl << "#Order\t" << BondOrder+1 << endl; 189 207 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 190 208 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t"; 191 for (int l=0;l<Fragments.ColumnCounter ;l++) {209 for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++) { 192 210 if (((l+1) % 3) == 0) { 193 211 norm = 0.; … … 226 244 cout << msg << endl; 227 245 output << "# " << msg << ", created on " << datum; 228 output << "# AtomNo\t" << Fragments.Header << endl;246 output << "# AtomNo\t" << Fragments.Header[Fragments.MatrixCounter] << endl; 229 247 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 230 248 //cout << "Current order is " << BondOrder << "." << endl; 231 249 Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.); 232 250 // errors per atom 233 output << "#Order\t" << BondOrder+1 << endl;251 output << endl << "#Order\t" << BondOrder+1 << endl; 234 252 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 235 253 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t"; 236 for (int l=0;l<Fragments.ColumnCounter ;l++)254 for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++) 237 255 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t"; 238 256 output << endl; … … 244 262 }; 245 263 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 values 268 * \param KeySet KeySetContainer class holding bond KeySetContainer::Order 269 * \param *prefix prefix in filename (without ending) 270 * \param *msg message to be place in first line as a comment 271 * \param *datum current date and time 272 * \return true if file was written successfully 273 */ 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 atom 289 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 values 306 * \param KeySet KeySetContainer class holding bond KeySetContainer::Order 307 * \param *prefix prefix in filename (without ending) 308 * \param *msg message to be place in first line as a comment 309 * \param *datum current date and time 310 * \return true if file was written successfully 311 */ 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 atom 334 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 values 350 * \param KeySet KeySetContainer class holding bond KeySetContainer::Order 351 * \param *prefix prefix in filename (without ending) 352 * \param *msg message to be place in first line as a comment 353 * \param *datum current date and time 354 * \return true if file was written successfully 355 */ 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 atom 371 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 246 384 /** Plot matrix vs. fragment. 247 385 */ … … 255 393 cout << msg << endl; 256 394 output << "# " << msg << ", created on " << datum << endl; 257 output << "#Order\tFrag.No.\t" << Fragment.Header << endl;395 output << "#Order\tFrag.No.\t" << Fragment.Header[ Fragment.MatrixCounter ] << endl; 258 396 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 259 397 for(int i=0;i<KeySet.FragmentsPerOrder[BondOrder];i++) { 260 398 output << BondOrder+1 << "\t" << KeySet.OrderSet[BondOrder][i]+1; 261 399 CreateFragment(Fragment, KeySet.OrderSet[BondOrder][i]); 262 for (int l=0;l<Fragment.ColumnCounter ;l++)400 for (int l=0;l<Fragment.ColumnCounter[ KeySet.OrderSet[BondOrder][i] ];l++) 263 401 output << scientific << "\t" << Fragment.Matrix[ KeySet.OrderSet[BondOrder][i] ][ Fragment.RowCounter[ KeySet.OrderSet[BondOrder][i] ] ][l]; 264 402 output << endl; … … 279 417 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) { 280 418 if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) { 281 for (int k=Fragments.ColumnCounter ;k--;)419 for (int k=Fragments.ColumnCounter[ Fragments.MatrixCounter ];k--;) 282 420 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 283 421 } … … 296 434 int i=0; 297 435 do { // first get a minimum value unequal to 0 298 for (int k=Fragments.ColumnCounter ;k--;)436 for (int k=Fragments.ColumnCounter[ Fragments.MatrixCounter ];k--;) 299 437 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 300 438 i++; … … 302 440 for(;i<KeySet.FragmentsPerOrder[BondOrder];i++) { // then find lowest 303 441 if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) > fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) { 304 for (int k=Fragments.ColumnCounter ;k--;)442 for (int k=Fragments.ColumnCounter[ Fragments.MatrixCounter ];k--;) 305 443 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 306 444 } … … 320 458 cout << msg << endl; 321 459 output << "# " << msg << ", created on " << datum; 322 output << "#Order\tFrag.No.\t" << Fragment.Header << endl;460 output << "#Order\tFrag.No.\t" << Fragment.Header[ Fragment.MatrixCounter ] << endl; 323 461 // max 324 462 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { … … 326 464 CreateFragmentOrder(Fragment, KeySet, BondOrder); 327 465 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 328 for (int l=0;l<Fragment.ColumnCounter ;l++)466 for (int l=0;l<Fragment.ColumnCounter[ Fragment.MatrixCounter ];l++) 329 467 output << scientific << "\t" << Fragment.Matrix[ Fragment.MatrixCounter ][ Fragment.RowCounter[ Fragment.MatrixCounter ]-1 ][l]; 330 468 output << endl; … … 340 478 void CreateEnergy(class MatrixContainer &Energy, int MatrixNumber) 341 479 { 342 for(int k=0;k<Energy.ColumnCounter ;k++)480 for(int k=0;k<Energy.ColumnCounter[MatrixNumber];k++) 343 481 Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber] ] [k] = Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber]-1 ] [k]; 344 482 }; … … 351 489 void CreateMinimumForce(class MatrixContainer &Force, int MatrixNumber) 352 490 { 353 for (int l=Force.ColumnCounter ;l--;)491 for (int l=Force.ColumnCounter[MatrixNumber];l--;) 354 492 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.; 355 for (int l=5;l<Force.ColumnCounter ;l+=3) {493 for (int l=5;l<Force.ColumnCounter[MatrixNumber];l+=3) { 356 494 double stored = 0; 357 495 int k=0; … … 386 524 { 387 525 int divisor = 0; 388 for (int l=Force.ColumnCounter ;l--;)526 for (int l=Force.ColumnCounter[MatrixNumber];l--;) 389 527 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.; 390 for (int l=5;l<Force.ColumnCounter ;l+=3) {528 for (int l=5;l<Force.ColumnCounter[MatrixNumber];l+=3) { 391 529 double tmp = 0; 392 530 for (int k=Force.RowCounter[MatrixNumber];k--;) { … … 410 548 void CreateMaximumForce(class MatrixContainer &Force, int MatrixNumber) 411 549 { 412 for (int l=5;l<Force.ColumnCounter ;l+=3) {550 for (int l=5;l<Force.ColumnCounter[MatrixNumber];l+=3) { 413 551 double stored = 0; 414 552 for (int k=Force.RowCounter[MatrixNumber];k--;) { … … 442 580 void CreateVectorSumForce(class MatrixContainer &Force, int MatrixNumber) 443 581 { 444 for (int l=Force.ColumnCounter ;l--;)582 for (int l=Force.ColumnCounter[MatrixNumber];l--;) 445 583 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.; 446 for (int l=0;l<Force.ColumnCounter ;l++) {584 for (int l=0;l<Force.ColumnCounter[MatrixNumber];l++) { 447 585 for (int k=Force.RowCounter[MatrixNumber];k--;) 448 586 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] += Force.Matrix[MatrixNumber][k][l]; … … 520 658 void AbsEnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses) 521 659 { 522 stringstream line(Energy.Header );660 stringstream line(Energy.Header[ Energy.MatrixCounter ]); 523 661 string token; 524 662 525 663 getline(line, token, '\t'); 526 for (int i=2; i<= Energy.ColumnCounter ;i++) {664 for (int i=2; i<= Energy.ColumnCounter[Energy.MatrixCounter];i++) { 527 665 getline(line, token, '\t'); 528 666 while (token[0] == ' ') // remove leading white spaces 529 667 token.erase(0,1); 530 668 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+2 << ")) " << uses; 531 if (i != (Energy.ColumnCounter ))669 if (i != (Energy.ColumnCounter[Energy.MatrixCounter])) 532 670 output << ", \\"; 533 671 output << endl; … … 544 682 void EnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses) 545 683 { 546 stringstream line(Energy.Header );684 stringstream line(Energy.Header[Energy.MatrixCounter]); 547 685 string token; 548 686 549 687 getline(line, token, '\t'); 550 for (int i=1; i<= Energy.ColumnCounter ;i++) {688 for (int i=1; i<= Energy.ColumnCounter[Energy.MatrixCounter];i++) { 551 689 getline(line, token, '\t'); 552 690 while (token[0] == ' ') // remove leading white spaces 553 691 token.erase(0,1); 554 692 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":" << i+2 << " " << uses; 555 if (i != (Energy.ColumnCounter ))693 if (i != (Energy.ColumnCounter[Energy.MatrixCounter])) 556 694 output << ", \\"; 557 695 output << endl; … … 568 706 void ForceMagnitudePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 569 707 { 570 stringstream line(Force.Header );708 stringstream line(Force.Header[Force.MatrixCounter]); 571 709 string token; 572 710 … … 576 714 getline(line, token, '\t'); 577 715 getline(line, token, '\t'); 578 for (int i=7; i< Force.ColumnCounter ;i+=NDIM) {716 for (int i=7; i< Force.ColumnCounter[Force.MatrixCounter];i+=NDIM) { 579 717 getline(line, token, '\t'); 580 718 while (token[0] == ' ') // remove leading white spaces … … 582 720 token.erase(token.length(), 1); // kill residual index char (the '0') 583 721 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses; 584 if (i != (Force.ColumnCounter -1))722 if (i != (Force.ColumnCounter[Force.MatrixCounter]-1)) 585 723 output << ", \\"; 586 724 output << endl; … … 599 737 void AbsFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 600 738 { 601 stringstream line(Force.Header );739 stringstream line(Force.Header[Force.MatrixCounter]); 602 740 string token; 603 741 … … 607 745 getline(line, token, '\t'); 608 746 getline(line, token, '\t'); 609 for (int i=7; i< Force.ColumnCounter ;i+=NDIM) {747 for (int i=7; i< Force.ColumnCounter[Force.MatrixCounter];i+=NDIM) { 610 748 getline(line, token, '\t'); 611 749 while (token[0] == ' ') // remove leading white spaces … … 613 751 token.erase(token.length(), 1); // kill residual index char (the '0') 614 752 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+1 << ")) " << uses; 615 if (i != (Force.ColumnCounter -1))753 if (i != (Force.ColumnCounter[Force.MatrixCounter]-1)) 616 754 output << ", \\"; 617 755 output << endl; … … 630 768 void BoxesForcePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 631 769 { 632 stringstream line(Force.Header );770 stringstream line(Force.Header[Force.MatrixCounter]); 633 771 char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"}; 634 772 string token; … … 639 777 getline(line, token, '\t'); 640 778 getline(line, token, '\t'); 641 for (int i=7; i< Force.ColumnCounter ;i+=NDIM) {779 for (int i=7; i< Force.ColumnCounter[Force.MatrixCounter];i+=NDIM) { 642 780 getline(line, token, '\t'); 643 781 while (token[0] == ' ') // remove leading white spaces … … 645 783 token.erase(token.length(), 1); // kill residual index char (the '0') 646 784 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]; 647 if (i != (Force.ColumnCounter -1))785 if (i != (Force.ColumnCounter[Force.MatrixCounter]-1)) 648 786 output << ", \\"; 649 787 output << endl; … … 662 800 void BoxesFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 663 801 { 664 stringstream line(Force.Header );802 stringstream line(Force.Header[Force.MatrixCounter]); 665 803 char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"}; 666 804 string token; … … 671 809 getline(line, token, '\t'); 672 810 getline(line, token, '\t'); 673 for (int i=7; i< Force.ColumnCounter ;i+=NDIM) {811 for (int i=7; i< Force.ColumnCounter[Force.MatrixCounter];i+=NDIM) { 674 812 getline(line, token, '\t'); 675 813 while (token[0] == ' ') // remove leading white spaces … … 677 815 token.erase(token.length(), 1); // kill residual index char (the '0') 678 816 output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):" << i+1 << " " << uses << " " << fillcolor[(i-7)/3]; 679 if (i != (Force.ColumnCounter -1))817 if (i != (Force.ColumnCounter[Force.MatrixCounter]-1)) 680 818 output << ", \\"; 681 819 output << endl; -
Property mode
changed from
-
src/datacreator.hpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 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); 20 21 21 22 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); … … 25 26 bool CreateDataDeltaForcesOrder(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)); 26 27 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); 27 31 bool CreateDataFragment(class MatrixContainer &ForceFragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)); 28 32 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
100644
to100755
-
Property mode
changed from
-
src/element.cpp
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/elements.db
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/graph.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 7 7 using namespace std; 8 8 9 #include "graph.hpp" 9 10 10 #include <iostream> 11 #include <list> 12 #include <vector> 11 /***************************************** Implementations for graph classes ********************************/ 13 12 14 /***************************************** Functions for class graph ********************************/ 13 /** Constructor of class Graph. 14 */ 15 Graph::Graph() 16 { 17 }; 15 18 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 }; 16 25 17 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 -
Property mode
changed from
-
src/helpers.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 182 182 }; 183 183 184 /** Tests whether a given string contains a valid number or not. 185 * \param *string 186 * \return true - is a number, false - is not a valid number 187 */ 188 bool IsValidNumber( const char *string) 189 { 190 int ptr = 0; 191 if ((string[ptr] == '.') || (string[ptr] == '-')) // number may be negative or start with dot 192 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
100644
to100755
rfcbfc8 r631dcb 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); 61 62 62 63 /********************************************** helpful template functions *********************************/ -
Property mode
changed from
-
src/joiner.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 19 19 periodentafel *periode = NULL; // and a period table of all elements 20 20 EnergyMatrix Energy; 21 EnergyMatrix EnergyFragments; 22 21 23 EnergyMatrix Hcorrection; 24 EnergyMatrix HcorrectionFragments; 25 22 26 ForceMatrix Force; 23 EnergyMatrix EnergyFragments;24 EnergyMatrix HcorrectionFragments;25 27 ForceMatrix ForceFragments; 28 29 HessianMatrix Hessian; 30 HessianMatrix HessianFragments; 31 26 32 ForceMatrix Shielding; 27 33 ForceMatrix ShieldingPAS; 28 34 ForceMatrix ShieldingFragments; 29 35 ForceMatrix ShieldingPASFragments; 36 EnergyMatrix Chi; 37 EnergyMatrix ChiPAS; 38 EnergyMatrix ChiFragments; 39 EnergyMatrix ChiPASFragments; 30 40 KeySetsContainer KeySet; 31 41 stringstream prefix; 32 42 char *dir = NULL; 33 bool Hcorrected = true; 43 bool NoHCorrection = false; 44 bool NoHessian = false; 34 45 35 46 cout << "Joiner" << endl; … … 61 72 // ------------- Parse through all Fragment subdirs -------- 62 73 if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix, 0,0)) return 1; 63 Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX, 0,0); 74 if (!Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX, 0,0)) { 75 NoHCorrection = true; 76 cout << "No HCorrection matrices found, skipping these." << endl; 77 } 64 78 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 } 65 83 if (periode != NULL) { // also look for PAS values 66 84 if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1; 67 85 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; 68 88 } 69 89 70 90 // ---------- Parse the TE Factors into an array ----------------- 71 if (!Energy.ParseIndices()) return 1; 72 if (Hcorrected) Hcorrection.ParseIndices(); 91 if (!Energy.InitialiseIndices()) return 1; 92 if (!NoHCorrection) 93 Hcorrection.InitialiseIndices(); 73 94 74 95 // ---------- Parse the Force indices into an array --------------- 75 96 if (!Force.ParseIndices(argv[1])) return 1; 76 97 98 // ---------- Parse the Hessian (=force) indices into an array --------------- 99 if (!NoHessian) 100 if (!Hessian.InitialiseIndices((class MatrixContainer *)&Force)) return 1; 101 77 102 // ---------- Parse the shielding indices into an array --------------- 78 103 if (periode != NULL) { // also look for PAS values 79 104 if(!Shielding.ParseIndices(argv[1])) return 1; 80 105 if(!ShieldingPAS.ParseIndices(argv[1])) return 1; 106 //if(!Chi.ParseIndices()) return 1; 107 //if(!ChiPAS.ParseIndices()) return 1; 81 108 } 82 109 83 110 // ---------- Parse the KeySets into an array --------------- 84 111 if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1; 85 86 112 if (!KeySet.ParseManyBodyTerms()) return 1; 113 87 114 if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return 1; 88 if (Hcorrected) HcorrectionFragments.AllocateMatrix(Hcorrection.Header, Hcorrection.MatrixCounter, Hcorrection.RowCounter, Hcorrection.ColumnCounter); 115 if (!NoHCorrection) 116 HcorrectionFragments.AllocateMatrix(Hcorrection.Header, Hcorrection.MatrixCounter, Hcorrection.RowCounter, Hcorrection.ColumnCounter); 89 117 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; 90 120 if (periode != NULL) { // also look for PAS values 91 121 if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1; 92 122 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; 93 125 } 94 126 … … 96 128 if(!Energy.SetLastMatrix(0., 0)) return 1; 97 129 if(!Force.SetLastMatrix(0., 2)) return 1; 130 if (!NoHessian) 131 if (!Hessian.SetLastMatrix(0., 0)) return 1; 98 132 if (periode != NULL) { // also look for PAS values 99 133 if(!Shielding.SetLastMatrix(0., 2)) return 1; 100 134 if(!ShieldingPAS.SetLastMatrix(0., 2)) return 1; 135 if(!Chi.SetLastMatrix(0., 2)) return 1; 136 if(!ChiPAS.SetLastMatrix(0., 2)) return 1; 101 137 } 102 138 … … 108 144 cout << "Summing energy of order " << BondOrder+1 << " ..." << endl; 109 145 if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return 1; 110 if ( Hcorrected) {146 if (!NoHCorrection) { 111 147 HcorrectionFragments.SumSubManyBodyTerms(Hcorrection, KeySet, BondOrder); 112 148 if (!Energy.SumSubEnergy(EnergyFragments, &HcorrectionFragments, KeySet, BondOrder, 1.)) return 1; 113 if (Hcorrected)Hcorrection.SumSubEnergy(HcorrectionFragments, NULL, KeySet, BondOrder, 1.);149 Hcorrection.SumSubEnergy(HcorrectionFragments, NULL, KeySet, BondOrder, 1.); 114 150 } else 115 151 if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return 1; … … 118 154 if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return 1; 119 155 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 } 120 162 if (periode != NULL) { // also look for PAS values 121 cout << "Summing shieldings of order " << BondOrder+1 << " ..." << endl;163 cout << "Summing shieldings and susceptibilities of order " << BondOrder+1 << " ..." << endl; 122 164 if (!ShieldingFragments.SumSubManyBodyTerms(Shielding, KeySet, BondOrder)) return 1; 123 165 if (!Shielding.SumSubForces(ShieldingFragments, KeySet, BondOrder, 1.)) return 1; 124 166 if (!ShieldingPASFragments.SumSubManyBodyTerms(ShieldingPAS, KeySet, BondOrder)) return 1; 125 167 if (!ShieldingPAS.SumSubForces(ShieldingPASFragments, KeySet, BondOrder, 1.)) return 1; 168 if (!ChiFragments.SumSubManyBodyTerms(Chi, KeySet, BondOrder)) return 1; 169 if (!Chi.SumSubEnergy(ChiFragments, NULL, KeySet, BondOrder, 1.)) return 1; 170 if (!ChiPASFragments.SumSubManyBodyTerms(ChiPAS, KeySet, BondOrder)) return 1; 171 if (!ChiPAS.SumSubEnergy(ChiPASFragments, NULL,KeySet, BondOrder, 1.)) return 1; 126 172 } 127 173 … … 134 180 // forces 135 181 if (!Force.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ForcesSuffix)) return 1; 182 // hessian 183 if (!NoHessian) 184 if (!Hessian.WriteLastMatrix(argv[1], (prefix.str()).c_str(), HessianSuffix)) return 1; 136 185 // shieldings 137 186 if (periode != NULL) { // also look for PAS values 138 187 if (!Shielding.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingSuffix)) return 1; 139 188 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; 140 191 } 141 192 } … … 144 195 prefix << dir << EnergyFragmentSuffix; 145 196 if (!EnergyFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 146 if ( Hcorrected) {197 if (!NoHCorrection) { 147 198 prefix.str(" "); 148 199 prefix << dir << HcorrectionFragmentSuffix; … … 153 204 if (!ForceFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 154 205 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 } 155 211 if (periode != NULL) { // also look for PAS values 156 212 prefix.str(" "); … … 160 216 prefix << dir << ShieldingPASFragmentSuffix; 161 217 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; 162 224 } 163 225 164 226 // write last matrices as fragments into central dir (not subdir as above), for analyzer to know index bounds 165 227 if (!Energy.WriteLastMatrix(argv[1], dir, EnergyFragmentSuffix)) return 1; 166 if ( Hcorrected) Hcorrection.WriteLastMatrix(argv[1], dir, HcorrectionFragmentSuffix);228 if (!NoHCorrection) Hcorrection.WriteLastMatrix(argv[1], dir, HcorrectionFragmentSuffix); 167 229 if (!Force.WriteLastMatrix(argv[1], dir, ForceFragmentSuffix)) return 1; 230 if (!NoHessian) 231 if (!Hessian.WriteLastMatrix(argv[1], dir, HessianFragmentSuffix)) return 1; 168 232 if (periode != NULL) { // also look for PAS values 169 233 if (!Shielding.WriteLastMatrix(argv[1], dir, ShieldingFragmentSuffix)) return 1; 170 234 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; 171 237 } 172 238 -
Property mode
changed from
-
src/moleculelist.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 395 395 int FragmentCounter = 0; 396 396 ofstream output; 397 string basis("3-21G"); 397 398 398 399 // store the fragments as config and as xyz … … 455 456 // and save as config 456 457 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( &outputFragment, ListOfMolecules[i]->elemente, ListOfMolecules[i])))459 if ((intermediateResult = configuration->Save(FragmentName, ListOfMolecules[i]->elemente, ListOfMolecules[i]))) 460 460 *out << " done." << endl; 461 461 else 462 462 *out << " failed." << endl; 463 result = result && intermediateResult; 463 464 464 465 // restore old config 465 466 configuration->SetDefaultPath(PathBackup); 466 467 467 result = result && intermediateResult;468 outputFragment.close();469 outputFragment.clear();470 468 471 469 // and save as mpqc input file 472 470 sprintf(FragmentName, "%s/%s%s.in", configuration->configpath, fragmentprefix, FragmentNumber); 473 outputFragment.open(FragmentName, ios::out);474 471 *out << Verbose(2) << "Saving " << fragmentprefix << " No. " << FragmentNumber << "/" << FragmentCounter-1 << " as mpqc input ..."; 475 if ((intermediateResult = configuration->SaveMPQC( &outputFragment, ListOfMolecules[i])))472 if ((intermediateResult = configuration->SaveMPQC(FragmentName, ListOfMolecules[i]))) 476 473 *out << " done." << endl; 477 474 else … … 479 476 480 477 result = result && intermediateResult; 481 outputFragment.close();482 outputFragment.clear();478 //outputFragment.close(); 479 //outputFragment.clear(); 483 480 delete(FragmentNumber); 484 481 //Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber"); -
Property mode
changed from
-
src/molecules.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 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) << "WARNING: There is no typical bond distance for bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 223 BondRescale = bondlength; 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; 224 225 } else { 225 226 if (!IsAngstroem) … … 272 273 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 273 274 // *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; 274 275 275 276 // determine the plane of these two with the *origin 276 277 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x); … … 285 286 Orthovector1.Normalize(); 286 287 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl; 287 288 288 289 // create the two Hydrogens ... 289 290 FirstOtherAtom = new atom(); … … 299 300 bondangle = TopOrigin->type->HBondAngle[1]; 300 301 if (bondangle == -1) { 301 *out << Verbose(3) << "WARNING: There is no typical bond angle for bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 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; 302 304 bondangle = 0; 303 305 } … … 316 318 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle)); 317 319 } 318 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 320 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 319 321 SecondOtherAtom->x.Scale(&BondRescale); 320 322 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl; 321 323 for(int i=NDIM;i--;) { // and make relative to origin atom 322 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 323 325 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i]; 324 326 } … … 363 365 // *out << endl; 364 366 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1); 365 // *out << Verbose(3) << "Orthovector2: "; 367 // *out << Verbose(3) << "Orthovector2: "; 366 368 // Orthovector2.Output(out); 367 369 // *out << endl; 368 370 369 371 // create correct coordination for the three atoms 370 372 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.; // retrieve triple bond angle from database … … 378 380 factors[0] = d; 379 381 factors[1] = f; 380 factors[2] = 0.; 382 factors[2] = 0.; 381 383 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 382 384 factors[1] = -0.5*f; 383 factors[2] = g; 385 factors[2] = g; 384 386 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 385 factors[2] = -g; 387 factors[2] = -g; 386 388 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 387 389 … … 435 437 */ 436 438 bool molecule::AddXYZFile(string filename) 437 { 439 { 438 440 istringstream *input = NULL; 439 441 int NumberOfAtoms = 0; // atom number in xyz read … … 444 446 string line; // currently parsed line 445 447 double x[3]; // atom coordinates 446 448 447 449 xyzfile.open(filename.c_str()); 448 450 if (!xyzfile) … … 452 454 input = new istringstream(line); 453 455 *input >> NumberOfAtoms; 454 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 455 457 getline(xyzfile,line,'\n'); // Read comment 456 458 cout << Verbose(1) << "Comment: " << line << endl; 457 459 458 460 if (MDSteps == 0) // no atoms yet present 459 461 MDSteps++; … … 489 491 xyzfile.close(); 490 492 delete(input); 491 return true; 493 return true; 492 494 }; 493 495 … … 501 503 atom *LeftAtom = NULL, *RightAtom = NULL; 502 504 atom *Walker = NULL; 503 505 504 506 // copy all atoms 505 507 Walker = start; … … 508 510 CurrentAtom = copy->AddCopyAtom(Walker); 509 511 } 510 512 511 513 // copy all bonds 512 514 bond *Binder = first; … … 532 534 copy->NoCyclicBonds++; 533 535 NewBond->Type = Binder->Type; 534 } 536 } 535 537 // correct fathers 536 538 Walker = copy->start; … … 549 551 copy->CreateListOfBondsPerAtom((ofstream *)&cout); 550 552 } 551 553 552 554 return copy; 553 555 }; … … 574 576 575 577 /** Remove bond from bond chain list. 576 * \todo Function not implemented yet 578 * \todo Function not implemented yet 577 579 * \param *pointer bond pointer 578 580 * \return true - bound found and removed, false - bond not found/removed … … 586 588 587 589 /** Remove every bond from bond chain list that atom \a *BondPartner is a constituent of. 588 * \todo Function not implemented yet 590 * \todo Function not implemented yet 589 591 * \param *BondPartner atom to be removed 590 592 * \return true - bounds found and removed, false - bonds not found/removed … … 619 621 Vector *min = new Vector; 620 622 Vector *max = new Vector; 621 623 622 624 // gather min and max for each axis 623 625 ptr = start->next; // start at first in list … … 665 667 { 666 668 Vector *min = new Vector; 667 669 668 670 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 669 671 atom *ptr = start->next; // start at first in list … … 681 683 } 682 684 } 683 // *out << Verbose(4) << "Maximum is "; 685 // *out << Verbose(4) << "Maximum is "; 684 686 // max->Output(out); 685 687 // *out << ", Minimum is "; … … 689 691 max->AddVector(min); 690 692 Translate(min); 691 } 693 } 692 694 delete(min); 693 695 // *out << Verbose(3) << "End of CenterEdge." << endl; 694 }; 696 }; 695 697 696 698 /** Centers the center of the atoms at (0,0,0). … … 702 704 int Num = 0; 703 705 atom *ptr = start->next; // start at first in list 704 706 705 707 for(int i=NDIM;i--;) // zero center vector 706 708 center->x[i] = 0.; 707 709 708 710 if (ptr != end) { //list not empty? 709 711 while (ptr->next != end) { // continue with second if present 710 712 ptr = ptr->next; 711 713 Num++; 712 center->AddVector(&ptr->x); 714 center->AddVector(&ptr->x); 713 715 } 714 716 center->Scale(-1./Num); // divide through total number (and sign for direction) 715 717 Translate(center); 716 718 } 717 }; 719 }; 718 720 719 721 /** Returns vector pointing to center of gravity. … … 727 729 Vector tmp; 728 730 double Num = 0; 729 731 730 732 a->Zero(); 731 733 … … 735 737 Num += 1.; 736 738 tmp.CopyVector(&ptr->x); 737 a->AddVector(&tmp); 739 a->AddVector(&tmp); 738 740 } 739 741 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 755 757 Vector tmp; 756 758 double Num = 0; 757 759 758 760 a->Zero(); 759 761 … … 764 766 tmp.CopyVector(&ptr->x); 765 767 tmp.Scale(ptr->type->mass); // scale by mass 766 a->AddVector(&tmp); 768 a->AddVector(&tmp); 767 769 } 768 770 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 787 789 Translate(center); 788 790 } 789 }; 791 }; 790 792 791 793 /** Scales all atoms by \a *factor. … … 801 803 Trajectories[ptr].R.at(j).Scale(factor); 802 804 ptr->x.Scale(factor); 803 } 804 }; 805 806 /** Translate all atoms by given vector. 805 } 806 }; 807 808 /** Translate all atoms by given vector. 807 809 * \param trans[] translation vector. 808 810 */ … … 816 818 Trajectories[ptr].R.at(j).Translate(trans); 817 819 ptr->x.Translate(trans); 818 } 819 }; 820 821 /** Mirrors all atoms against a given plane. 820 } 821 }; 822 823 /** Mirrors all atoms against a given plane. 822 824 * \param n[] normal vector of mirror plane. 823 825 */ … … 831 833 Trajectories[ptr].R.at(j).Mirror(n); 832 834 ptr->x.Mirror(n); 833 } 835 } 834 836 }; 835 837 … … 845 847 bool flag; 846 848 Vector Testvector, Translationvector; 847 849 848 850 do { 849 851 Center.Zero(); … … 861 863 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 862 864 for (int j=0;j<NDIM;j++) { 863 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 864 866 if ((fabs(tmp)) > BondDistance) { 865 867 flag = false; … … 877 879 cout << Verbose(1) << "vector is: "; 878 880 Testvector.Output((ofstream *)&cout); 879 cout << endl; 881 cout << endl; 880 882 #ifdef ADDHYDROGEN 881 883 // now also change all hydrogens … … 890 892 cout << Verbose(1) << "Hydrogen vector is: "; 891 893 Testvector.Output((ofstream *)&cout); 892 cout << endl; 894 cout << endl; 893 895 } 894 896 } … … 912 914 913 915 CenterGravity(out, CenterOfGravity); 914 915 // reset inertia tensor 916 917 // reset inertia tensor 916 918 for(int i=0;i<NDIM*NDIM;i++) 917 919 InertiaTensor[i] = 0.; 918 920 919 921 // sum up inertia tensor 920 922 while (ptr->next != end) { … … 941 943 } 942 944 *out << endl; 943 945 944 946 // diagonalize to determine principal axis system 945 947 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM); … … 950 952 gsl_eigen_symmv_free(T); 951 953 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); 952 954 953 955 for(int i=0;i<NDIM;i++) { 954 956 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i); 955 957 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl; 956 958 } 957 959 958 960 // check whether we rotate or not 959 961 if (DoRotate) { 960 *out << Verbose(1) << "Transforming molecule into PAS ... "; 962 *out << Verbose(1) << "Transforming molecule into PAS ... "; 961 963 // the eigenvectors specify the transformation matrix 962 964 ptr = start; … … 970 972 971 973 // summing anew for debugging (resulting matrix has to be diagonal!) 972 // reset inertia tensor 974 // reset inertia tensor 973 975 for(int i=0;i<NDIM*NDIM;i++) 974 976 InertiaTensor[i] = 0.; 975 977 976 978 // sum up inertia tensor 977 979 ptr = start; … … 1000 1002 *out << endl; 1001 1003 } 1002 1004 1003 1005 // free everything 1004 1006 delete(CenterOfGravity); … … 1489 1491 { 1490 1492 atom *walker = NULL; 1491 int AtomNo;1492 1493 ifstream input(file); 1493 1494 string token; 1494 1495 stringstream item; 1495 double a,IonMass, Vector[NDIM], ConstrainedPotentialEnergy, ActualTemp;1496 double IonMass, Vector[NDIM], ConstrainedPotentialEnergy, ActualTemp; 1496 1497 ForceMatrix Force; 1497 1498 1498 1499 CountElements(); // make sure ElementsInMolecule is up to date 1499 1500 1500 1501 // check file 1501 1502 if (input == NULL) { … … 1578 1579 } 1579 1580 } 1581 // correct velocities (rather momenta) so that center of mass remains motionless 1580 1582 for(int d=0;d<NDIM;d++) 1581 1583 Vector[d] /= IonMass; … … 1592 1594 MDSteps++; 1593 1595 1594 1596 1595 1597 // exit 1596 1598 return true; 1597 1599 }; 1598 1599 1600 1600 1601 /** Implementation of various thermostats. … … 1785 1786 ptr = ptr->next; 1786 1787 tmp = ptr->x.x[0]; 1787 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1788 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1788 1789 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1789 1790 for (int j=0;j<MDSteps;j++) { 1790 1791 tmp = Trajectories[ptr].R.at(j).x[0]; 1791 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1792 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1792 1793 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1793 1794 } 1794 } 1795 } 1795 1796 // rotate n vector 1796 1797 tmp = n->x[0]; … … 1800 1801 n->Output((ofstream *)&cout); 1801 1802 cout << endl; 1802 1803 1803 1804 // rotate on z-y plane 1804 1805 ptr = start; … … 1808 1809 ptr = ptr->next; 1809 1810 tmp = ptr->x.x[1]; 1810 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1811 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1811 1812 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1812 1813 for (int j=0;j<MDSteps;j++) { 1813 1814 tmp = Trajectories[ptr].R.at(j).x[1]; 1814 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1815 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1815 1816 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1816 1817 } 1817 } 1818 } 1818 1819 // rotate n vector (for consistency check) 1819 1820 tmp = n->x[1]; 1820 1821 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1821 1822 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1822 1823 1823 1824 cout << Verbose(1) << "alignment vector after second rotation: "; 1824 1825 n->Output((ofstream *)&cout); … … 1831 1832 * \return true - succeeded, false - atom not found in list 1832 1833 */ 1833 bool molecule::RemoveAtom(atom *pointer) 1834 { 1834 bool molecule::RemoveAtom(atom *pointer) 1835 { 1835 1836 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1836 1837 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1837 1838 else 1838 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1839 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1839 1840 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1840 1841 ElementCount--; … … 1846 1847 * \return true - succeeded, false - atom not found in list 1847 1848 */ 1848 bool molecule::CleanupMolecule() 1849 { 1850 return (cleanup(start,end) && cleanup(first,last)); 1849 bool molecule::CleanupMolecule() 1850 { 1851 return (cleanup(start,end) && cleanup(first,last)); 1851 1852 }; 1852 1853 … … 1862 1863 } else { 1863 1864 cout << Verbose(0) << "Atom not found in list." << endl; 1864 return NULL; 1865 return NULL; 1865 1866 } 1866 1867 }; … … 1911 1912 struct lsq_params *par = (struct lsq_params *)params; 1912 1913 atom *ptr = par->mol->start; 1913 1914 1914 1915 // initialize vectors 1915 1916 a.x[0] = gsl_vector_get(x,0); … … 1941 1942 { 1942 1943 int np = 6; 1943 1944 1944 1945 const gsl_multimin_fminimizer_type *T = 1945 1946 gsl_multimin_fminimizer_nmsimplex; … … 1947 1948 gsl_vector *ss; 1948 1949 gsl_multimin_function minex_func; 1949 1950 1950 1951 size_t iter = 0, i; 1951 1952 int status; 1952 1953 double size; 1953 1954 1954 1955 /* Initial vertex size vector */ 1955 1956 ss = gsl_vector_alloc (np); 1956 1957 1957 1958 /* Set all step sizes to 1 */ 1958 1959 gsl_vector_set_all (ss, 1.0); 1959 1960 1960 1961 /* Starting point */ 1961 1962 par->x = gsl_vector_alloc (np); 1962 1963 par->mol = this; 1963 1964 1964 1965 gsl_vector_set (par->x, 0, 0.0); // offset 1965 1966 gsl_vector_set (par->x, 1, 0.0); … … 1968 1969 gsl_vector_set (par->x, 4, 0.0); 1969 1970 gsl_vector_set (par->x, 5, 1.0); 1970 1971 1971 1972 /* Initialize method and iterate */ 1972 1973 minex_func.f = &LeastSquareDistance; 1973 1974 minex_func.n = np; 1974 1975 minex_func.params = (void *)par; 1975 1976 1976 1977 s = gsl_multimin_fminimizer_alloc (T, np); 1977 1978 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1978 1979 1979 1980 do 1980 1981 { 1981 1982 iter++; 1982 1983 status = gsl_multimin_fminimizer_iterate(s); 1983 1984 1984 1985 if (status) 1985 1986 break; 1986 1987 1987 1988 size = gsl_multimin_fminimizer_size (s); 1988 1989 status = gsl_multimin_test_size (size, 1e-2); 1989 1990 1990 1991 if (status == GSL_SUCCESS) 1991 1992 { 1992 1993 printf ("converged to minimum at\n"); 1993 1994 } 1994 1995 1995 1996 printf ("%5d ", (int)iter); 1996 1997 for (i = 0; i < (size_t)np; i++) … … 2001 2002 } 2002 2003 while (status == GSL_CONTINUE && iter < 100); 2003 2004 2004 2005 for (i=0;i<(size_t)np;i++) 2005 2006 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); … … 2018 2019 int ElementNo, AtomNo; 2019 2020 CountElements(); 2020 2021 2021 2022 if (out == NULL) { 2022 2023 return false; … … 2053 2054 int ElementNo, AtomNo; 2054 2055 CountElements(); 2055 2056 2056 2057 if (out == NULL) { 2057 2058 return false; … … 2100 2101 atom *Walker = start; 2101 2102 while (Walker->next != end) { 2102 Walker = Walker->next; 2103 Walker = Walker->next; 2103 2104 #ifdef ADDHYDROGEN 2104 2105 if (Walker->type->Z != 1) { // regard only non-hydrogen … … 2131 2132 int No = 0; 2132 2133 time_t now; 2133 2134 2134 2135 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 2135 2136 walker = start; … … 2158 2159 { 2159 2160 atom *walker = NULL; 2160 int No = 0;2161 int AtomNo = 0, ElementNo; 2161 2162 time_t now; 2162 2163 element *runner = NULL; 2164 2163 2165 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 2164 2166 walker = start; 2165 2167 while (walker->next != end) { // go through every atom and count 2166 2168 walker = walker->next; 2167 No++;2169 AtomNo++; 2168 2170 } 2169 2171 if (out != NULL) { 2170 *out << No << "\n\tCreated by molecuilder on " << ctime(&now); 2171 walker = start; 2172 while (walker->next != end) { // go through every atom of this element 2173 walker = walker->next; 2174 walker->OutputXYZLine(out); 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 } 2175 2187 } 2176 2188 return true; … … 2203 2215 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 2204 2216 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 2205 NoNonHydrogen++; 2217 NoNonHydrogen++; 2206 2218 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 2207 2219 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); … … 2211 2223 } 2212 2224 } else 2213 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 2225 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 2214 2226 } 2215 2227 }; … … 2223 2235 ElementsInMolecule[i] = 0; 2224 2236 ElementCount = 0; 2225 2237 2226 2238 atom *walker = start; 2227 2239 while (walker->next != end) { … … 2259 2271 Binder = Binder->next; 2260 2272 if (Binder->Cyclic) 2261 No++; 2273 No++; 2262 2274 } 2263 2275 delete(BackEdgeStack); … … 2317 2329 2318 2330 /** 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 already 2349 { 2350 *input >> ws >> atom1; 2351 *input >> ws >> atom2; 2352 if(atom2<atom1) //Sort indices of atoms in order 2353 { 2354 temp=atom1; 2355 atom1=atom2; 2356 atom2=temp; 2357 }; 2358 2359 Walker=start; 2360 while(Walker-> nr != atom1) // Find atom corresponding to first index 2361 { 2362 Walker = Walker->next; 2363 }; 2364 OtherWalker = Walker->next; 2365 while(OtherWalker->nr != atom2) // Find atom corresponding to second index 2366 { 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. 2319 2379 * Generally, we use the CSD approach to bond recognition, that is the the distance 2320 2380 * between two atoms A and B must be within [Rcov(A)+Rcov(B)-t,Rcov(A)+Rcov(B)+t] with 2321 * a threshold t = 0.4 Angstroem. 2381 * a threshold t = 0.4 Angstroem. 2322 2382 * To make it O(N log N) the function uses the linked-cell technique as follows: 2323 2383 * The procedure is step-wise: … … 2336 2396 void molecule::CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem) 2337 2397 { 2398 2338 2399 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 2339 2400 int No, NoBonds, CandidateBondNo; … … 2344 2405 Vector x; 2345 2406 int FalseBondDegree = 0; 2346 2407 2347 2408 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 2348 2409 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; … … 2351 2412 cleanup(first,last); 2352 2413 } 2353 2414 2354 2415 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 2355 2416 CountAtoms(out); … … 2370 2431 for (int i=NumberCells;i--;) 2371 2432 CellList[i] = NULL; 2372 2433 2373 2434 // 2b. put all atoms into its corresponding list 2374 2435 Walker = start; … … 2391 2452 if (CellList[index] == NULL) // allocate molecule if not done 2392 2453 CellList[index] = new molecule(elemente); 2393 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 2394 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 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; 2395 2456 } 2396 2457 //for (int i=0;i<NumberCells;i++) 2397 2458 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 2398 2459 2460 2399 2461 // 3a. go through every cell 2400 2462 for (N[0]=divisor[0];N[0]--;) … … 2409 2471 Walker = Walker->next; 2410 2472 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 2411 // 3c. check for possible bond between each atom in this and every one in the 27 cells 2473 // 3c. check for possible bond between each atom in this and every one in the 27 cells 2412 2474 for (n[0]=-1;n[0]<=1;n[0]++) 2413 2475 for (n[1]=-1;n[1]<=1;n[1]++) … … 2441 2503 } 2442 2504 } 2505 2506 2507 2443 2508 // 4. free the cell again 2444 2509 for (int i=NumberCells;i--;) … … 2447 2512 } 2448 2513 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 2449 2514 2450 2515 // create the adjacency list per atom 2451 2516 CreateListOfBondsPerAtom(out); 2452 2517 2453 2518 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 2454 2519 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene … … 2509 2574 *out << endl; 2510 2575 } else 2511 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 2576 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 2512 2577 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 2513 2578 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 2514 }; 2579 2580 }; 2581 2582 2515 2583 2516 2584 /** Performs a Depth-First search on this molecule. … … 2533 2601 bond *Binder = NULL; 2534 2602 bool BackStepping = false; 2535 2603 2536 2604 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 2537 2605 2538 2606 ResetAllBondsToUnused(); 2539 2607 ResetAllAtomNumbers(); … … 2548 2616 LeafWalker->Leaf = new molecule(elemente); 2549 2617 LeafWalker->Leaf->AddCopyAtom(Root); 2550 2618 2551 2619 OldGraphNr = CurrentGraphNr; 2552 2620 Walker = Root; … … 2559 2627 AtomStack->Push(Walker); 2560 2628 CurrentGraphNr++; 2561 } 2629 } 2562 2630 do { // (3) if Walker has no unused egdes, go to (5) 2563 2631 BackStepping = false; // reset backstepping flag for (8) … … 2593 2661 Binder = NULL; 2594 2662 } while (1); // (2) 2595 2663 2596 2664 // 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! 2597 2665 if ((Walker == Root) && (Binder == NULL)) 2598 2666 break; 2599 2600 // (5) if Ancestor of Walker is ... 2667 2668 // (5) if Ancestor of Walker is ... 2601 2669 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 2602 2670 if (Walker->Ancestor->GraphNr != Root->GraphNr) { … … 2641 2709 } while (OtherAtom != Walker); 2642 2710 ComponentNumber++; 2643 2711 2644 2712 // (11) Root is separation vertex, set Walker to Root and go to (4) 2645 2713 Walker = Root; … … 2654 2722 2655 2723 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2656 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2724 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2657 2725 LeafWalker->Leaf->Output(out); 2658 2726 *out << endl; … … 2662 2730 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2663 2731 if (Root->GraphNr != -1) // if already discovered, step on 2664 Root = Root->next; 2732 Root = Root->next; 2665 2733 } 2666 2734 } … … 2684 2752 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2685 2753 } 2686 2754 2687 2755 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2688 2756 Binder = first; … … 2695 2763 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2696 2764 OutputComponentNumber(out, Binder->rightatom); 2697 *out << ">." << endl; 2765 *out << ">." << endl; 2698 2766 if (Binder->Cyclic) // cyclic ?? 2699 2767 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; … … 2710 2778 * the other our initial Walker - and do a Breadth First Search for the Root. We mark down each Predecessor and as soon as 2711 2779 * we have found the Root via BFS, we may climb back the closed cycle via the Predecessors. Thereby we mark atoms and bonds 2712 * as cyclic and print out the cycles. 2780 * as cyclic and print out the cycles. 2713 2781 * \param *out output stream for debugging 2714 2782 * \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! … … 2721 2789 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2722 2790 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2723 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2791 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2724 2792 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2725 2793 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; … … 2733 2801 ColorList[i] = white; 2734 2802 } 2735 2803 2736 2804 *out << Verbose(1) << "Back edge list - "; 2737 2805 BackEdgeStack->Output(out); 2738 2806 2739 2807 *out << Verbose(1) << "Analysing cycles ... " << endl; 2740 2808 NumCycles = 0; … … 2742 2810 BackEdge = BackEdgeStack->PopFirst(); 2743 2811 // this is the target 2744 Root = BackEdge->leftatom; 2812 Root = BackEdge->leftatom; 2745 2813 // this is the source point 2746 Walker = BackEdge->rightatom; 2814 Walker = BackEdge->rightatom; 2747 2815 ShortestPathList[Walker->nr] = 0; 2748 2816 BFSStack->ClearStack(); // start with empty BFS stack … … 2758 2826 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2759 2827 OtherAtom = Binder->GetOtherAtom(Walker); 2760 #ifdef ADDHYDROGEN 2828 #ifdef ADDHYDROGEN 2761 2829 if (OtherAtom->type->Z != 1) { 2762 2830 #endif … … 2767 2835 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2768 2836 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2769 *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; 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; 2770 2838 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2771 2839 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; … … 2777 2845 if (OtherAtom == Root) 2778 2846 break; 2779 #ifdef ADDHYDROGEN 2847 #ifdef ADDHYDROGEN 2780 2848 } else { 2781 2849 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; … … 2815 2883 } 2816 2884 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2817 2885 2818 2886 if (OtherAtom == Root) { 2819 2887 // now climb back the predecessor list and thus find the cycle members … … 2843 2911 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2844 2912 } 2845 2913 2846 2914 // now clean the lists 2847 2915 while (!TouchedStack->IsEmpty()){ … … 2853 2921 } 2854 2922 if (MinRingSize != -1) { 2855 // go over all atoms 2923 // go over all atoms 2856 2924 Root = start; 2857 2925 while(Root->next != end) { 2858 2926 Root = Root->next; 2859 2927 2860 2928 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2861 2929 Walker = Root; … … 2894 2962 } 2895 2963 ColorList[Walker->nr] = black; 2896 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2964 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2897 2965 } 2898 2966 2899 2967 // now clean the lists 2900 2968 while (!TouchedStack->IsEmpty()){ … … 2945 3013 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2946 3014 { 2947 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 3015 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2948 3016 *out << vertex->ComponentNr[i] << " "; 2949 3017 }; … … 3023 3091 { 3024 3092 int c = 0; 3025 int FragmentCount; 3093 int FragmentCount; 3026 3094 // get maximum bond degree 3027 3095 atom *Walker = start; … … 3033 3101 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 3034 3102 return FragmentCount; 3035 }; 3103 }; 3036 3104 3037 3105 /** Scans a single line for number and puts them into \a KeySet. 3038 3106 * \param *out output stream for debugging 3039 3107 * \param *buffer buffer to scan 3040 * \param &CurrentSet filled KeySet on return 3108 * \param &CurrentSet filled KeySet on return 3041 3109 * \return true - at least one valid atom id parsed, false - CurrentSet is empty 3042 3110 */ … … 3046 3114 int AtomNr; 3047 3115 int status = 0; 3048 3116 3049 3117 line.str(buffer); 3050 3118 while (!line.eof()) { … … 3082 3150 double TEFactor; 3083 3151 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 3084 3152 3085 3153 if (FragmentList == NULL) { // check list pointer 3086 3154 FragmentList = new Graph; 3087 3155 } 3088 3156 3089 3157 // 1st pass: open file and read 3090 3158 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; … … 3115 3183 status = false; 3116 3184 } 3117 3185 3118 3186 // 2nd pass: open TEFactors file and read 3119 3187 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; … … 3127 3195 InputFile >> TEFactor; 3128 3196 (*runner).second.second = TEFactor; 3129 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 3197 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 3130 3198 } else { 3131 3199 status = false; … … 3168 3236 if(output != NULL) { 3169 3237 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 3170 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 3238 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 3171 3239 if (sprinter != (*runner).first.begin()) 3172 3240 output << "\t"; … … 3234 3302 status = false; 3235 3303 } 3236 3304 3237 3305 return status; 3238 3306 }; … … 3243 3311 * \param **ListOfAtoms allocated (molecule::AtomCount) and filled lookup table for ids (Atom::nr) to *Atom 3244 3312 * \return true - structure is equal, false - not equivalence 3245 */ 3313 */ 3246 3314 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 3247 3315 { … … 3250 3318 bool status = true; 3251 3319 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 3252 3320 3253 3321 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 3254 3322 File.open(filename.str().c_str(), ios::out); … … 3309 3377 *out << endl; 3310 3378 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 3311 3379 3312 3380 return status; 3313 3381 }; … … 3331 3399 for(int i=AtomCount;i--;) 3332 3400 AtomMask[i] = false; 3333 3401 3334 3402 if (Order < 0) { // adaptive increase of BondOrder per site 3335 3403 if (AtomMask[AtomCount] == true) // break after one step … … 3371 3439 line >> ws >> Value; // skip time entry 3372 3440 line >> ws >> Value; 3373 No -= 1; // indices start at 1 in file, not 0 3441 No -= 1; // indices start at 1 in file, not 0 3374 3442 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 3375 3443 … … 3380 3448 // 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 3381 3449 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 3382 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 3450 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 3383 3451 if (!InsertedElement.second) { // this root is already present 3384 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 3385 //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) 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) 3386 3454 { // if value is smaller, update value and order 3387 3455 (*PresentItem).second.first = fabs(Value); … … 3421 3489 Walker = FindAtom(No); 3422 3490 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 3423 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 3491 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 3424 3492 AtomMask[No] = true; 3425 3493 status = true; 3426 3494 //} else 3427 //*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; 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; 3428 3496 } 3429 3497 // close and done … … 3459 3527 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 3460 3528 status = true; 3461 3529 3462 3530 if (!status) { 3463 3531 if (Order == 0) … … 3467 3535 } 3468 3536 } 3469 3537 3470 3538 // print atom mask for debugging 3471 3539 *out << " "; … … 3476 3544 *out << (AtomMask[i] ? "t" : "f"); 3477 3545 *out << endl; 3478 3546 3479 3547 return status; 3480 3548 }; … … 3490 3558 int AtomNo = 0; 3491 3559 atom *Walker = NULL; 3492 3560 3493 3561 if (SortIndex != NULL) { 3494 3562 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; … … 3548 3616 atom **ListOfAtoms = NULL; 3549 3617 atom ***ListOfLocalAtoms = NULL; 3550 bool *AtomMask = NULL; 3551 3618 bool *AtomMask = NULL; 3619 3552 3620 *out << endl; 3553 3621 #ifdef ADDHYDROGEN … … 3558 3626 3559 3627 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 3560 3628 3561 3629 // ===== 1. Check whether bond structure is same as stored in files ==== 3562 3630 3563 3631 // fill the adjacency list 3564 3632 CreateListOfBondsPerAtom(out); … … 3566 3634 // create lookup table for Atom::nr 3567 3635 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 3568 3636 3569 3637 // === compare it with adjacency file === 3570 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 3638 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 3571 3639 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 3572 3640 … … 3591 3659 // else 3592 3660 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name; 3661 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3593 3662 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 3663 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3594 3664 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize); 3665 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3595 3666 delete(LocalBackEdgeStack); 3596 3667 } … … 3614 3685 FragmentationToDo = FragmentationToDo || CheckOrder; 3615 3686 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 3616 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3687 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3617 3688 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 3618 3689 … … 3623 3694 MolecularWalker = MolecularWalker->next; 3624 3695 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl; 3625 // output ListOfBondsPerAtom for debugging 3626 MolecularWalker->Leaf->OutputListOfBonds(out); 3696 //MolecularWalker->Leaf->OutputListOfBonds(out); // output ListOfBondsPerAtom for debugging 3627 3697 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) { 3628 3629 3698 // call BOSSANOVA method 3630 3699 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl; … … 3646 3715 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3647 3716 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3648 3717 3649 3718 // free subgraph memory again 3650 3719 FragmentCounter = 0; … … 3671 3740 } 3672 3741 *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl; 3673 3742 3674 3743 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3675 3744 if (BondFragments->NumberOfMolecules != 0) { 3676 3745 // create the SortIndex from BFS labels to order in the config file 3677 3746 CreateMappingLabelsToConfigSequence(out, SortIndex); 3678 3747 3679 3748 *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl; 3680 3749 if (BondFragments->OutputConfigForListOfFragments(out, FRAGMENTPREFIX, configuration, SortIndex, true, true)) … … 3682 3751 else 3683 3752 *out << Verbose(1) << "Some config writing failed." << endl; 3684 3753 3685 3754 // store force index reference file 3686 3755 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3687 3688 // store keysets file 3756 3757 // store keysets file 3689 3758 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3690 3691 // store Adjacency file 3759 3760 // store Adjacency file 3692 3761 StoreAdjacencyToFile(out, configuration->configpath); 3693 3762 3694 3763 // store Hydrogen saturation correction file 3695 3764 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3696 3765 3697 3766 // store adaptive orders into file 3698 3767 StoreOrderAtSiteFile(out, configuration->configpath); 3699 3768 3700 3769 // restore orbital and Stop values 3701 3770 CalculateOrbitals(*configuration); 3702 3771 3703 3772 // free memory for bond part 3704 3773 *out << Verbose(1) << "Freeing bond memory" << endl; 3705 3774 delete(FragmentList); // remove bond molecule from memory 3706 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3775 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3707 3776 } else 3708 3777 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3709 //} else 3778 //} else 3710 3779 // *out << Verbose(1) << "No fragments to store." << endl; 3711 3780 *out << Verbose(0) << "End of bond fragmentation." << endl; … … 3736 3805 do { // go through all bonds and push local ones 3737 3806 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3738 if (Walker == NULL) // if this Walker exists in the subgraph ...3739 continue;3740 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds3741 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3742 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond3743 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);3744 break;3745 }3746 }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 bonds 3809 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 break; 3814 } 3815 } 3747 3816 Binder = ReferenceStack->PopFirst(); // loop the stack for next item 3817 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl; 3748 3818 ReferenceStack->Push(Binder); 3749 3819 } while (FirstBond != Binder); … … 3824 3894 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3825 3895 Walker->MaxOrder = MaxArray[Walker->nr]; 3826 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3896 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3827 3897 } 3828 3898 file.close(); … … 3835 3905 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3836 3906 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3837 3907 3838 3908 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3839 3909 return status; … … 3901 3971 } 3902 3972 *out << " -- TotalDegree: " << TotalDegree << endl; 3903 } 3973 } 3904 3974 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3905 3975 }; … … 3907 3977 /** Adds atoms up to \a BondCount distance from \a *Root and notes them down in \a **AddedAtomList. 3908 3978 * Gray vertices are always enqueued in an StackClass<atom *> FIFO queue, the rest is usual BFS with adding vertices found was 3909 * white and putting into queue. 3979 * white and putting into queue. 3910 3980 * \param *out output stream for debugging 3911 3981 * \param *Mol Molecule class to add atoms to … … 3916 3986 * \param BondOrder maximum distance for vertices to add 3917 3987 * \param IsAngstroem lengths are in angstroem or bohrradii 3918 */ 3988 */ 3919 3989 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3920 3990 { … … 3942 4012 } 3943 4013 ShortestPathList[Root->nr] = 0; 3944 4014 3945 4015 // and go on ... Queue always contains all lightgray vertices 3946 4016 while (!AtomStack->IsEmpty()) { … … 3950 4020 // followed by n+1 till top of stack. 3951 4021 Walker = AtomStack->PopFirst(); // pop oldest added 3952 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 4022 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3953 4023 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3954 4024 Binder = ListOfBondsPerAtom[Walker->nr][i]; … … 3957 4027 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3958 4028 if (ColorList[OtherAtom->nr] == white) { 3959 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) 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) 3960 4030 ColorList[OtherAtom->nr] = lightgray; 3961 4031 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3962 4032 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3963 *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; 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; 3964 4034 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3965 4035 *out << Verbose(3); … … 3999 4069 } else { 4000 4070 #ifdef ADDHYDROGEN 4001 Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem); 4071 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 4072 exit(1); 4002 4073 #endif 4003 4074 } … … 4008 4079 // This has to be a cyclic bond, check whether it's present ... 4009 4080 if (AddedBondList[Binder->nr] == NULL) { 4010 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 4081 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 4011 4082 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 4012 4083 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; … … 4014 4085 } else { // if it's root bond it has to broken (otherwise we would not create the fragments) 4015 4086 #ifdef ADDHYDROGEN 4016 Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem); 4087 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 4088 exit(1); 4017 4089 #endif 4018 4090 } … … 4022 4094 } 4023 4095 ColorList[Walker->nr] = black; 4024 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 4096 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 4025 4097 } 4026 4098 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); … … 4046 4118 4047 4119 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 4048 4120 4049 4121 // reset parent list 4050 4122 *out << Verbose(3) << "Resetting ParentList." << endl; 4051 4123 for (int i=Father->AtomCount;i--;) 4052 4124 ParentList[i] = NULL; 4053 4125 4054 4126 // fill parent list with sons 4055 4127 *out << Verbose(3) << "Filling Parent List." << endl; … … 4092 4164 * \param *&Leaf KeySet to look through 4093 4165 * \param *&ShortestPathList list of the shortest path to decide which atom to suggest as removal candidate in the end 4094 * \param index of the atom suggested for removal 4166 * \param index of the atom suggested for removal 4095 4167 */ 4096 4168 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) … … 4098 4170 atom *Runner = NULL; 4099 4171 int SP, Removal; 4100 4172 4101 4173 *out << Verbose(2) << "Looking for removal candidate." << endl; 4102 4174 SP = -1; //0; // not -1, so that Root is never removed … … 4116 4188 /** Stores a fragment from \a KeySet into \a molecule. 4117 4189 * First creates the minimal set of atoms from the KeySet, then creates the bond structure from the complete 4118 * molecule and adds missing hydrogen where bonds were cut. 4190 * molecule and adds missing hydrogen where bonds were cut. 4119 4191 * \param *out output stream for debugging messages 4120 * \param &Leaflet pointer to KeySet structure 4192 * \param &Leaflet pointer to KeySet structure 4121 4193 * \param IsAngstroem whether we have Ansgtroem or bohrradius 4122 4194 * \return pointer to constructed molecule … … 4129 4201 bool LonelyFlag = false; 4130 4202 int size; 4131 4203 4132 4204 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 4133 4205 4134 4206 Leaf->BondDistance = BondDistance; 4135 4207 for(int i=NDIM*2;i--;) 4136 Leaf->cell_size[i] = cell_size[i]; 4208 Leaf->cell_size[i] = cell_size[i]; 4137 4209 4138 4210 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) … … 4147 4219 size++; 4148 4220 } 4149 4221 4150 4222 // create the bonds between all: Make it an induced subgraph and add hydrogen 4151 4223 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; … … 4157 4229 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 4158 4230 // create all bonds 4159 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 4231 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 4160 4232 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 4161 4233 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 4162 4234 if (SonList[OtherFather->nr] != NULL) { 4163 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 4235 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 4164 4236 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 4165 4237 // *out << Verbose(3) << "Adding Bond: "; 4166 // *out << 4238 // *out << 4167 4239 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 4168 4240 // *out << "." << endl; 4169 4241 //NumBonds[Runner->nr]++; 4170 } else { 4242 } else { 4171 4243 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 4172 4244 } 4173 4245 LonelyFlag = false; 4174 4246 } else { 4175 // *out << ", who has no son in this fragment molecule." << endl; 4247 // *out << ", who has no son in this fragment molecule." << endl; 4176 4248 #ifdef ADDHYDROGEN 4177 4249 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; 4178 Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem); 4250 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem)) 4251 exit(1); 4179 4252 #endif 4180 4253 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree; … … 4190 4263 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 4191 4264 Runner = Runner->next; 4192 #endif 4265 #endif 4193 4266 } 4194 4267 Leaf->CreateListOfBondsPerAtom(out); … … 4223 4296 StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself 4224 4297 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! 4225 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 4298 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 4226 4299 MoleculeListClass *FragmentList = NULL; 4227 4300 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL; … … 4273 4346 // clear snake stack 4274 4347 SnakeStack->ClearStack(); 4275 //SnakeStack->TestImplementation(out, start->next); 4348 //SnakeStack->TestImplementation(out, start->next); 4276 4349 4277 4350 ///// INNER LOOP //////////// … … 4294 4367 } 4295 4368 if (ShortestPathList[Walker->nr] == -1) { 4296 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 4369 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 4297 4370 TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed 4298 4371 } … … 4332 4405 OtherAtom = Binder->GetOtherAtom(Walker); 4333 4406 if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us 4334 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 4407 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 4335 4408 //ColorVertexList[OtherAtom->nr] = lightgray; // mark as explored 4336 4409 } else { // otherwise check its colour and element 4337 4410 if ( 4338 4411 #ifdef ADDHYDROGEN 4339 (OtherAtom->type->Z != 1) && 4412 (OtherAtom->type->Z != 1) && 4340 4413 #endif 4341 4414 (ColorEdgeList[Binder->nr] == white)) { // skip hydrogen, look for unexplored vertices … … 4347 4420 //} else { 4348 4421 // *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl; 4349 //} 4422 //} 4350 4423 Walker = OtherAtom; 4351 4424 break; 4352 4425 } else { 4353 if (OtherAtom->type->Z == 1) 4426 if (OtherAtom->type->Z == 1) 4354 4427 *out << "Links to a hydrogen atom." << endl; 4355 else 4428 else 4356 4429 *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl; 4357 4430 } … … 4363 4436 *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl; 4364 4437 } 4365 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 4438 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 4366 4439 *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl; 4367 4440 ColorVertexList[Walker->nr] = black; … … 4370 4443 } 4371 4444 } while ((Walker != Root) || (ColorVertexList[Root->nr] != black)); 4372 *out << Verbose(2) << "Inner Looping is finished." << endl; 4445 *out << Verbose(2) << "Inner Looping is finished." << endl; 4373 4446 4374 4447 // if we reset all AtomCount atoms, we have again technically O(N^2) ... … … 4386 4459 } 4387 4460 } 4388 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 4461 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 4389 4462 4390 4463 // copy together 4391 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 4464 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 4392 4465 FragmentList = new MoleculeListClass(FragmentCounter, AtomCount); 4393 4466 RunningIndex = 0; … … 4460 4533 4461 4534 NumCombinations = 1 << SetDimension; 4462 4535 4463 4536 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 4464 4537 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 4465 4538 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 4466 4539 4467 4540 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 4468 4541 *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; 4469 4542 4470 // initialised touched list (stores added atoms on this level) 4543 // initialised touched list (stores added atoms on this level) 4471 4544 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 4472 4545 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 4473 4546 TouchedList[TouchedIndex] = -1; 4474 4547 TouchedIndex = 0; 4475 4548 4476 4549 // create every possible combination of the endpieces 4477 4550 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; … … 4481 4554 for (int j=SetDimension;j--;) 4482 4555 bits += (i & (1 << j)) >> j; 4483 4556 4484 4557 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 4485 4558 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue … … 4489 4562 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 4490 4563 if (bit) { // if bit is set, we add this bond partner 4491 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 4564 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 4492 4565 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 4493 4566 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 4494 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 4567 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 4495 4568 if (TestKeySetInsert.second) { 4496 4569 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added … … 4505 4578 } 4506 4579 } 4507 4508 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 4580 4581 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 4509 4582 if (SpaceLeft > 0) { 4510 4583 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; … … 4534 4607 } 4535 4608 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 4536 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 4609 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 4537 4610 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 4538 4611 } … … 4543 4616 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 4544 4617 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 4545 *out << (*runner) << " "; 4618 *out << (*runner) << " "; 4546 4619 *out << endl; 4547 4620 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) … … 4551 4624 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 4552 4625 } 4553 4626 4554 4627 // --3-- remove all added items in this level from snake stack 4555 4628 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; … … 4562 4635 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 4563 4636 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 4564 *out << (*runner) << " "; 4637 *out << (*runner) << " "; 4565 4638 *out << endl; 4566 4639 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level … … 4569 4642 } 4570 4643 } 4571 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 4644 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 4572 4645 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 4573 4646 }; … … 4578 4651 * \return true - connected, false - disconnected 4579 4652 * \note this is O(n^2) for it's just a bug checker not meant for permanent use! 4580 */ 4653 */ 4581 4654 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 4582 4655 { … … 4584 4657 bool BondStatus = false; 4585 4658 int size; 4586 4659 4587 4660 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 4588 4661 *out << Verbose(2) << "Disconnected atom: "; 4589 4662 4590 4663 // count number of atoms in graph 4591 4664 size = 0; … … 4633 4706 * \param *out output stream for debugging 4634 4707 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation 4635 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4708 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4636 4709 * \param RestrictedKeySet Restricted vertex set to use in context of molecule 4637 4710 * \return number of inserted fragments 4638 4711 * \note ShortestPathList in FragmentSearch structure is probably due to NumberOfAtomsSPLevel and SP not needed anymore 4639 4712 */ 4640 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4713 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4641 4714 { 4642 4715 int SP, AtomKeyNr; … … 4659 4732 FragmentSearch.BondsPerSPCount[i] = 0; 4660 4733 FragmentSearch.BondsPerSPCount[0] = 1; 4661 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4734 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4662 4735 add(Binder, FragmentSearch.BondsPerSPList[1]); 4663 4736 4664 4737 // do a BFS search to fill the SP lists and label the found vertices 4665 4738 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 4666 4739 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 4667 4740 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 4668 // (EdgeinSPLevel) of this tree ... 4741 // (EdgeinSPLevel) of this tree ... 4669 4742 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 4670 4743 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. … … 4719 4792 } 4720 4793 } 4721 4794 4722 4795 // outputting all list for debugging 4723 4796 *out << Verbose(0) << "Printing all found lists." << endl; … … 4728 4801 Binder = Binder->next; 4729 4802 *out << Verbose(2) << *Binder << endl; 4730 } 4731 } 4732 4803 } 4804 } 4805 4733 4806 // creating fragments with the found edge sets (may be done in reverse order, faster) 4734 4807 SP = -1; // the Root <-> Root edge must be subtracted! … … 4737 4810 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4738 4811 Binder = Binder->next; 4739 SP ++; 4812 SP ++; 4740 4813 } 4741 4814 } … … 4744 4817 // start with root (push on fragment stack) 4745 4818 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4746 FragmentSearch.FragmentSet->clear(); 4819 FragmentSearch.FragmentSet->clear(); 4747 4820 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4748 4821 // prepare the subset and call the generator 4749 4822 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4750 4823 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4751 4824 4752 4825 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4753 4826 4754 4827 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4755 4828 } else { … … 4760 4833 // remove root from stack 4761 4834 *out << Verbose(0) << "Removing root again from stack." << endl; 4762 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4835 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4763 4836 4764 4837 // free'ing the bonds lists … … 4779 4852 } 4780 4853 4781 // return list 4854 // return list 4782 4855 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4783 4856 return (FragmentSearch.FragmentCounter - Counter); … … 4810 4883 // remove bonds that are beyond bonddistance 4811 4884 for(int i=NDIM;i--;) 4812 Translationvector.x[i] = 0.; 4885 Translationvector.x[i] = 0.; 4813 4886 // scan all bonds 4814 4887 Binder = first; … … 4857 4930 } 4858 4931 } 4859 // re-add bond 4932 // re-add bond 4860 4933 link(Binder, OtherBinder); 4861 4934 } else { … … 4911 4984 IteratorB++; 4912 4985 } // end of while loop 4913 }// end of check in case of equal sizes 4986 }// end of check in case of equal sizes 4914 4987 } 4915 4988 return false; // if we reach this point, they are equal … … 4955 5028 * \param graph1 first (dest) graph 4956 5029 * \param graph2 second (source) graph 4957 * \param *counter keyset counter that gets increased 5030 * \param *counter keyset counter that gets increased 4958 5031 */ 4959 5032 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) … … 5000 5073 int RootKeyNr, RootNr; 5001 5074 struct UniqueFragments FragmentSearch; 5002 5075 5003 5076 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 5004 5077 … … 5023 5096 Walker = Walker->next; 5024 5097 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 5025 } 5098 } 5026 5099 5027 5100 // 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 … … 5037 5110 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 5038 5111 // *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; 5039 //} else 5112 //} else 5040 5113 { 5041 5114 // increase adaptive order by one 5042 5115 Walker->GetTrueFather()->AdaptiveOrder++; 5043 5116 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 5044 5117 5045 5118 // initialise Order-dependent entries of UniqueFragments structure 5046 5119 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); … … 5049 5122 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 5050 5123 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 5051 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 5124 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 5052 5125 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 5053 5126 FragmentSearch.BondsPerSPCount[i] = 0; 5054 } 5055 5127 } 5128 5056 5129 // allocate memory for all lower level orders in this 1D-array of ptrs 5057 5130 NumLevels = 1 << (Order-1); // (int)pow(2,Order); … … 5059 5132 for (int i=0;i<NumLevels;i++) 5060 5133 FragmentLowerOrdersList[RootNr][i] = NULL; 5061 5134 5062 5135 // create top order where nothing is reduced 5063 5136 *out << Verbose(0) << "==============================================================================================================" << endl; 5064 5137 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 5065 5138 5066 5139 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 5067 5140 FragmentLowerOrdersList[RootNr][0] = new Graph; … … 5076 5149 // we don't have to dive into suborders! These keysets are all already created on lower orders! 5077 5150 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 5078 5151 5079 5152 // if ((NumLevels >> 1) > 0) { 5080 5153 // // create lower order fragments … … 5083 5156 // 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) 5084 5157 // // step down to next order at (virtual) boundary of powers of 2 in array 5085 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 5158 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 5086 5159 // Order--; 5087 5160 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; … … 5090 5163 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 5091 5164 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 5092 // 5165 // 5093 5166 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 5094 5167 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; … … 5121 5194 RootStack.push_back(RootKeyNr); // put back on stack 5122 5195 RootNr++; 5123 5196 5124 5197 // free Order-dependent entries of UniqueFragments structure for next loop cycle 5125 5198 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); … … 5127 5200 delete(FragmentSearch.BondsPerSPList[2*i]); 5128 5201 delete(FragmentSearch.BondsPerSPList[2*i+1]); 5129 } 5202 } 5130 5203 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 5131 5204 } … … 5138 5211 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 5139 5212 delete(FragmentSearch.FragmentSet); 5140 5141 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 5213 5214 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 5142 5215 // 5433222211111111 5143 5216 // 43221111 … … 5159 5232 RootKeyNr = RootStack.front(); 5160 5233 RootStack.pop_front(); 5161 Walker = FindAtom(RootKeyNr); 5234 Walker = FindAtom(RootKeyNr); 5162 5235 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 5163 5236 for(int i=0;i<NumLevels;i++) { … … 5172 5245 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 5173 5246 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 5174 5247 5175 5248 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 5176 5249 }; … … 5206 5279 atom *Walker = NULL; 5207 5280 bool result = true; // status of comparison 5208 5209 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 5281 5282 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 5210 5283 /// first count both their atoms and elements and update lists thereby ... 5211 5284 //*out << Verbose(0) << "Counting atoms, updating list" << endl; … … 5254 5327 if (CenterOfGravity.Distance(&OtherCenterOfGravity) > threshold) { 5255 5328 *out << Verbose(4) << "Centers of gravity don't match." << endl; 5256 result = false; 5257 } 5258 } 5259 5329 result = false; 5330 } 5331 } 5332 5260 5333 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 5261 5334 if (result) { … … 5273 5346 OtherDistances[Walker->nr] = OtherCenterOfGravity.Distance(&Walker->x); 5274 5347 } 5275 5348 5276 5349 /// ... sort each list (using heapsort (o(N log N)) from GSL) 5277 5350 *out << Verbose(5) << "Sorting distances" << endl; … … 5284 5357 for(int i=AtomCount;i--;) 5285 5358 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 5286 5359 5287 5360 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 5288 5361 *out << Verbose(4) << "Comparing distances" << endl; … … 5295 5368 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 5296 5369 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 5297 5370 5298 5371 /// free memory 5299 5372 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); … … 5303 5376 result = false; 5304 5377 } 5305 } 5378 } 5306 5379 /// return pointer to map if all distances were below \a threshold 5307 5380 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; … … 5312 5385 *out << Verbose(3) << "Result: Not equal." << endl; 5313 5386 return NULL; 5314 } 5387 } 5315 5388 }; 5316 5389 … … 5367 5440 * \param *output output stream of temperature file 5368 5441 * \return file written (true), failure on writing file (false) 5369 */ 5442 */ 5370 5443 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 5371 5444 { … … 5375 5448 if (output == NULL) 5376 5449 return false; 5377 else 5450 else 5378 5451 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 5379 5452 for (int step=startstep;step < endstep; step++) { // loop over all time steps -
Property mode
changed from
-
src/molecules.hpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 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 … … 56 56 #define BoundariesTestPair pair< Boundaries::iterator, bool> 57 57 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 Pair::iterator, bool >65 66 #define TriangleMap map < int, class BoundaryTriangleSet * > 67 #define TrianglePair pair < int, class BoundaryTriangleSet * > 68 #define TriangleTestPair pair < TrianglePair::iterator, bool > 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 < LineMap::iterator, bool > 65 66 #define TriangleMap map < int, class BoundaryTriangleSet * > 67 #define TrianglePair pair < int, class BoundaryTriangleSet * > 68 #define TriangleTestPair pair < TrianglePair::iterator, bool > 69 69 70 70 #define DistanceMultiMap multimap <double, pair < PointMap::iterator, PointMap::iterator> > … … 88 88 //bool operator < (KeySet SubgraphA, KeySet SubgraphB); //note: this declaration is important, otherwise normal < is used (producing wrong order) 89 89 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 90 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter); // Insert all KeySet's in a Graph into another Graph 91 91 int CompareDoubles (const void * a, const void * b); 92 92 … … 142 142 unsigned char AdaptiveOrder; //!< current present bond order at site (0 means "not set") 143 143 bool MaxOrder; //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not 144 144 145 145 atom(); 146 146 ~atom(); 147 147 148 148 bool Output(int ElementNo, int AtomNo, ofstream *out) const; 149 149 bool OutputXYZLine(ofstream *out) const; 150 150 atom *GetTrueFather(); 151 151 bool Compare(atom &ptr); 152 152 153 153 private: 154 154 }; … … 171 171 int nr; //!< unique number in a molecule, updated by molecule::CreateAdjacencyList() 172 172 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 173 enum EdgeType Type;//!< whether this is a tree or back edge 174 175 175 atom * GetOtherAtom(atom *Atom) const; 176 176 bond * GetFirstBond(); 177 177 bond * GetLastBond(); 178 178 179 179 bool MarkUsed(enum Shading color); 180 180 enum Shading IsUsed(); … … 182 182 bool Contains(const atom *ptr); 183 183 bool Contains(const int nr); 184 184 185 185 bond(); 186 186 bond(atom *left, atom *right); … … 188 188 bond(atom *left, atom *right, int degree, int number); 189 189 ~bond(); 190 191 private: 190 191 private: 192 192 enum Shading Used; //!< marker in depth-first search, DepthFirstSearchAnalysis() 193 193 }; … … 226 226 int NoCyclicBonds; //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis() 227 227 double BondDistance; //!< typical bond distance used in CreateAdjacencyList() and furtheron 228 228 229 229 molecule(periodentafel *teil); 230 230 ~molecule(); 231 231 232 232 /// remove atoms from molecule. 233 233 bool AddAtom(atom *pointer); … … 238 238 atom * AddCopyAtom(atom *pointer); 239 239 bool AddXYZFile(string filename); 240 bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem); 240 bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem); 241 241 bond * AddBond(atom *first, atom *second, int degree); 242 242 bool RemoveBond(bond *pointer); 243 243 bool RemoveBonds(atom *BondPartner); 244 244 245 245 /// Find atoms. 246 atom * FindAtom(int Nr) const; 246 atom * FindAtom(int Nr) const; 247 247 atom * AskAtom(string text); 248 248 … … 252 252 void CalculateOrbitals(class config &configuration); 253 253 bool CenterInBox(ofstream *out, Vector *BoxLengths); 254 void CenterEdge(ofstream *out, Vector *max); 255 void CenterOrigin(ofstream *out, Vector *max); 254 void CenterEdge(ofstream *out, Vector *max); 255 void CenterOrigin(ofstream *out, Vector *max); 256 256 void CenterGravity(ofstream *out, Vector *max); 257 257 void Translate(const Vector *x); … … 268 268 double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem); 269 269 270 270 bool VerletForceIntegration(ofstream *out, char *file, config &configuration); 271 271 void Thermostats(config &configuration, double ActualTemp, int Thermostat); 272 272 273 273 double ConstrainedPotential(ofstream *out, atom **permutation, int start, int end, double *constants, bool IsAngstroem); 274 275 276 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); 277 277 278 278 bool CheckBounds(const Vector *x) const; 279 279 void GetAlignvector(struct lsq_params * par) const; 280 280 281 /// Initialising routines in fragmentation 281 /// Initialising routines in fragmentation 282 void CreateAdjacencyList2(ofstream *out, ifstream *output); 282 283 void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem); 283 284 void CreateListOfBondsPerAtom(ofstream *out); 284 285 285 286 // Graph analysis 286 287 MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack); … … 298 299 299 300 molecule *CopyMolecule(); 300 301 301 302 /// Fragment molecule by two different approaches: 302 303 int FragmentMolecule(ofstream *out, int Order, config *configuration); … … 320 321 int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList); 321 322 int GuesstimateFragmentCount(ofstream *out, int order); 322 323 // Recognize doubly appearing molecules in a list of them 323 324 // Recognize doubly appearing molecules in a list of them 324 325 int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold); 325 326 int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule); 326 327 327 328 // Output routines. 328 329 bool Output(ofstream *out); … … 345 346 int NumberOfMolecules; //!< Number of entries in \a **FragmentList and of to be returned one. 346 347 int NumberOfTopAtoms; //!< Number of atoms in the molecule from which all fragments originate 347 348 348 349 MoleculeListClass(); 349 350 MoleculeListClass(int Num, int NumAtoms); … … 355 356 bool OutputConfigForListOfFragments(ofstream *out, const char *fragmentprefix, config *configuration, int *SortIndex, bool DoPeriodic, bool DoCentering); 356 357 void Output(ofstream *out); 357 358 358 359 private: 359 360 }; … … 365 366 class MoleculeLeafClass { 366 367 public: 367 molecule *Leaf; //!< molecule of this leaf 368 molecule *Leaf; //!< molecule of this leaf 368 369 //MoleculeLeafClass *UpLeaf; //!< Leaf one level up 369 370 //MoleculeLeafClass *DownLeaf; //!< First leaf one level down … … 401 402 bool FastParsing; 402 403 double Deltat; 404 string basis; 405 403 406 int DoConstrainedMD; 404 407 int MaxOuterStep; … … 416 419 char *defaultpath; 417 420 char *pseudopotpath; 418 421 419 422 int DoOutVis; 420 423 int DoOutMes; … … 431 434 int UseAddGramSch; 432 435 int Seed; 433 436 434 437 int OutVisStep; 435 438 int OutSrcStep; 436 439 int MaxPsiStep; 437 440 double EpsWannier; 438 441 439 442 int MaxMinStep; 440 443 double RelEpsTotalEnergy; … … 445 448 double InitRelEpsKineticEnergy; 446 449 int InitMaxMinGapStopStep; 447 450 448 451 //double BoxLength[NDIM*NDIM]; 449 452 450 453 double ECut; 451 454 int MaxLevel; … … 456 459 int RTActualUse; 457 460 int AddPsis; 458 461 459 462 double RCut; 460 463 int StructOpt; … … 463 466 int MaxTypes; 464 467 465 468 466 469 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); 467 470 468 471 public: 469 472 config(); … … 474 477 void LoadOld(char *filename, periodentafel *periode, molecule *mol); 475 478 void RetrieveConfigPathAndName(string filename); 476 bool Save( ofstream *file, periodentafel *periode, molecule *mol) const;477 bool SaveMPQC( ofstream *file, molecule *mol) const;479 bool Save(const char *filename, periodentafel *periode, molecule *mol) const; 480 bool SaveMPQC(const char *filename, molecule *mol) const; 478 481 void Edit(molecule *mol); 479 482 bool GetIsAngstroem() const; -
Property mode
changed from
-
src/orbitals.db
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 18 18 18 0 19 19 19 1 20 20 220 20 4 21 21 21 3 22 22 22 4 -
Property mode
changed from
-
src/parser.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 56 56 MatrixContainer::MatrixContainer() { 57 57 Indices = NULL; 58 Header = (char * ) Malloc(sizeof(char)*1023, "MatrixContainer::MatrixContainer:*Header");58 Header = (char **) Malloc(sizeof(char)*1, "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; 61 63 Matrix[0] = NULL; 62 64 RowCounter[0] = -1; 63 65 MatrixCounter = 0; 64 ColumnCounter = 0;66 ColumnCounter[0] = -1; 65 67 }; 66 68 … … 70 72 if (Matrix != NULL) { 71 73 for(int i=MatrixCounter;i--;) { 72 if ( RowCounter != NULL) {74 if ((ColumnCounter != NULL) && (RowCounter != NULL)) { 73 75 for(int j=RowCounter[i]+1;j--;) 74 76 Free((void **)&Matrix[i][j], "MatrixContainer::~MatrixContainer: *Matrix[][]"); … … 76 78 } 77 79 } 78 if (( RowCounter != NULL) && (Matrix[MatrixCounter] != NULL))80 if ((ColumnCounter != NULL) && (RowCounter != NULL) && (Matrix[MatrixCounter] != NULL)) 79 81 for(int j=RowCounter[MatrixCounter]+1;j--;) 80 82 Free((void **)&Matrix[MatrixCounter][j], "MatrixContainer::~MatrixContainer: *Matrix[MatrixCounter][]"); … … 89 91 Free((void **)&Indices, "MatrixContainer::~MatrixContainer: **Indices"); 90 92 91 Free((void **)&Header, "MatrixContainer::~MatrixContainer: *Header"); 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"); 92 97 Free((void **)&RowCounter, "MatrixContainer::~MatrixContainer: *RowCounter"); 93 }; 94 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 }; 95 135 96 136 /** Parsing a number of matrices. … … 120 160 return false; 121 161 } 122 123 // skip some initial lines 162 163 // parse header 164 Header[MatrixNr] = (char *) Malloc(sizeof(char)*1024, "MatrixContainer::ParseMatrix: *Header[]"); 124 165 for (int m=skiplines+1;m--;) 125 input.getline(Header , 1023);166 input.getline(Header[MatrixNr], 1023); 126 167 127 168 // scan header for number of columns 128 line.str(Header );169 line.str(Header[MatrixNr]); 129 170 for(int k=skipcolumns;k--;) 130 line >> Header ;171 line >> Header[MatrixNr]; 131 172 //cout << line.str() << endl; 132 ColumnCounter =0;173 ColumnCounter[MatrixNr]=0; 133 174 while ( getline(line,token, '\t') ) { 134 175 if (token.length() > 0) 135 ColumnCounter ++;176 ColumnCounter[MatrixNr]++; 136 177 } 137 178 //cout << line.str() << endl; 138 //cout << "ColumnCounter : " << ColumnCounter<< "." << endl;139 if (ColumnCounter == 0)140 cerr << "ColumnCounter : " << ColumnCounter<< " from file " << name << ", this is probably an error!" << 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; 141 182 142 183 // scan rest for number of rows/lines … … 155 196 156 197 // allocate matrix if it's not zero dimension in one direction 157 if ((ColumnCounter > 0) && (RowCounter[MatrixNr] > -1)) {158 Matrix[MatrixNr] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixNr]+1), "MatrixContainer::Parse FragmentMatrix: **Matrix[]");198 if ((ColumnCounter[MatrixNr] > 0) && (RowCounter[MatrixNr] > -1)) { 199 Matrix[MatrixNr] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixNr]+1), "MatrixContainer::ParseMatrix: **Matrix[]"); 159 200 160 201 // parse in each entry for this matrix … … 162 203 input.seekg(ios::beg); 163 204 for (int m=skiplines+1;m--;) 164 input.getline(Header , 1023); // skip header165 line.str(Header );205 input.getline(Header[MatrixNr], 1023); // skip header 206 line.str(Header[MatrixNr]); 166 207 for(int k=skipcolumns;k--;) // skip columns in header too 167 208 line >> filename; 168 strncpy(Header , line.str().c_str(), 1023);209 strncpy(Header[MatrixNr], line.str().c_str(), 1023); 169 210 for(int j=0;j<RowCounter[MatrixNr];j++) { 170 Matrix[MatrixNr][j] = (double *) Malloc(sizeof(double)*ColumnCounter , "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");211 Matrix[MatrixNr][j] = (double *) Malloc(sizeof(double)*ColumnCounter[MatrixNr], "MatrixContainer::ParseMatrix: *Matrix[][]"); 171 212 input.getline(filename, 1023); 172 213 stringstream lines(filename); … … 174 215 for(int k=skipcolumns;k--;) 175 216 lines >> filename; 176 for(int k=0;(k<ColumnCounter ) && (!lines.eof());k++) {217 for(int k=0;(k<ColumnCounter[MatrixNr]) && (!lines.eof());k++) { 177 218 lines >> Matrix[MatrixNr][j][k]; 178 219 //cout << " " << setprecision(2) << Matrix[MatrixNr][j][k];; 179 220 } 180 221 //cout << endl; 181 Matrix[MatrixNr][ RowCounter[MatrixNr] ] = (double *) Malloc(sizeof(double)*ColumnCounter , "MatrixContainer::ParseFragmentMatrix: *Matrix[RowCounter[MatrixNr]][]");182 for(int j=ColumnCounter ;j--;)222 Matrix[MatrixNr][ RowCounter[MatrixNr] ] = (double *) Malloc(sizeof(double)*ColumnCounter[MatrixNr], "MatrixContainer::ParseMatrix: *Matrix[RowCounter[MatrixNr]][]"); 223 for(int j=ColumnCounter[MatrixNr];j--;) 183 224 Matrix[MatrixNr][ RowCounter[MatrixNr] ][j] = 0.; 184 225 } 185 226 } else { 186 cerr << "ERROR: Matrix nr. " << MatrixNr << " has column and row count of (" << ColumnCounter << "," << RowCounter[MatrixNr] << "), could not allocate nor parse!" << endl;227 cerr << "ERROR: Matrix nr. " << MatrixNr << " has column and row count of (" << ColumnCounter[MatrixNr] << "," << RowCounter[MatrixNr] << "), could not allocate nor parse!" << endl; 187 228 } 188 229 input.close(); … … 233 274 234 275 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 molecule 235 277 Matrix = (double ***) ReAlloc(Matrix, sizeof(double **)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: ***Matrix"); // one more each for the total molecule 236 278 RowCounter = (int *) ReAlloc(RowCounter, sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *RowCounter"); 279 ColumnCounter = (int *) ReAlloc(ColumnCounter, sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *ColumnCounter"); 237 280 for(int i=MatrixCounter+1;i--;) { 238 281 Matrix[i] = NULL; 282 Header[i] = NULL; 239 283 RowCounter[i] = -1; 284 ColumnCounter[i] = -1; 240 285 } 241 286 for(int i=0; i < MatrixCounter;i++) { … … 252 297 253 298 /** Allocates and resets the memory for a number \a MCounter of matrices. 254 * \param * GivenHeader Header line299 * \param **GivenHeader Header line for each matrix 255 300 * \param MCounter number of matrices 256 301 * \param *RCounter number of rows for each matrix 257 * \param CCounter number of columns for all matrices302 * \param *CCounter number of columns for each matrix 258 303 * \return Allocation successful 259 304 */ 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 305 bool MatrixContainer::AllocateMatrix(char **GivenHeader, int MCounter, int *RCounter, int *CCounter) 306 { 265 307 MatrixCounter = MCounter; 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"); 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"); 269 312 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); 270 315 RowCounter[i] = RCounter[i]; 271 Matrix[i] = (double **) Malloc(sizeof(double *)*(RowCounter[i]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 316 ColumnCounter[i] = CCounter[i]; 317 Matrix[i] = (double **) Malloc(sizeof(double *)*(RowCounter[i]+1), "MatrixContainer::AllocateMatrix: **Matrix[]"); 272 318 for(int j=RowCounter[i]+1;j--;) { 273 Matrix[i][j] = (double *) Malloc(sizeof(double)*ColumnCounter , "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");274 for(int k=ColumnCounter ;k--;)319 Matrix[i][j] = (double *) Malloc(sizeof(double)*ColumnCounter[i], "MatrixContainer::AllocateMatrix: *Matrix[][]"); 320 for(int k=ColumnCounter[i];k--;) 275 321 Matrix[i][j][k] = 0.; 276 322 } … … 286 332 for(int i=MatrixCounter+1;i--;) 287 333 for(int j=RowCounter[i]+1;j--;) 288 for(int k=ColumnCounter ;k--;)334 for(int k=ColumnCounter[i];k--;) 289 335 Matrix[i][j][k] = 0.; 290 336 return true; … … 299 345 for(int i=MatrixCounter+1;i--;) 300 346 for(int j=RowCounter[i]+1;j--;) 301 for(int k=ColumnCounter ;k--;)347 for(int k=ColumnCounter[i];k--;) 302 348 if (fabs(Matrix[i][j][k]) > max) 303 349 max = fabs(Matrix[i][j][k]); … … 315 361 for(int i=MatrixCounter+1;i--;) 316 362 for(int j=RowCounter[i]+1;j--;) 317 for(int k=ColumnCounter ;k--;)363 for(int k=ColumnCounter[i];k--;) 318 364 if (fabs(Matrix[i][j][k]) < min) 319 365 min = fabs(Matrix[i][j][k]); … … 331 377 { 332 378 for(int j=RowCounter[MatrixCounter]+1;j--;) 333 for(int k=skipcolumns;k<ColumnCounter ;k++)379 for(int k=skipcolumns;k<ColumnCounter[MatrixCounter];k++) 334 380 Matrix[MatrixCounter][j][k] = value; 335 381 return true; … … 344 390 { 345 391 for(int j=RowCounter[MatrixCounter]+1;j--;) 346 for(int k=skipcolumns;k<ColumnCounter ;k++)392 for(int k=skipcolumns;k<ColumnCounter[MatrixCounter];k++) 347 393 Matrix[MatrixCounter][j][k] = values[j][k]; 348 394 return true; 349 395 }; 350 396 351 /** Sums the en ergy with each factor and put into last element of \a ***Energies.397 /** Sums the entries with each factor and put into last element of \a ***Matrix. 352 398 * Sums over "E"-terms to create the "F"-terms 353 * \param Matrix MatrixContainer with matrices (LevelCounter by ColumnCounter) with all the energies.399 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies. 354 400 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order 355 401 * \param Order bond order … … 384 430 } 385 431 if (Order == SubOrder) { // equal order is always copy from Energies 386 for(int l=ColumnCounter ;l--;) // then adds/subtract each column432 for(int l=ColumnCounter[ KeySet.OrderSet[SubOrder][j] ];l--;) // then adds/subtract each column 387 433 Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] += MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l]; 388 434 } else { 389 for(int l=ColumnCounter ;l--;)435 for(int l=ColumnCounter[ KeySet.OrderSet[SubOrder][j] ];l--;) 390 436 Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] -= Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l]; 391 437 } 392 438 } 393 //if ((ColumnCounter >1) && (RowCounter[0]-1 >= 1))439 //if ((ColumnCounter[ KeySet.OrderSet[SubOrder][j] ]>1) && (RowCounter[0]-1 >= 1)) 394 440 //cout << "Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " << Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl; 395 441 } … … 426 472 return false; 427 473 } 428 output << Header << endl;474 output << Header[i] << endl; 429 475 for(int j=0;j<RowCounter[i];j++) { 430 for(int k=0;k<ColumnCounter ;k++)476 for(int k=0;k<ColumnCounter[i];k++) 431 477 output << scientific << Matrix[i][j][k] << "\t"; 432 478 output << endl; … … 455 501 return false; 456 502 } 457 output << Header << endl;503 output << Header[MatrixCounter] << endl; 458 504 for(int j=0;j<RowCounter[MatrixCounter];j++) { 459 for(int k=0;k<ColumnCounter ;k++)505 for(int k=0;k<ColumnCounter[MatrixCounter];k++) 460 506 output << scientific << Matrix[MatrixCounter][j][k] << "\t"; 461 507 output << endl; … … 467 513 // ======================================= CLASS EnergyMatrix ============================= 468 514 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 sucessful472 */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 485 515 /** Sums the energy with each factor and put into last element of \a EnergyMatrix::Matrix. 486 516 * Sums over the "F"-terms in ANOVA decomposition. 487 * \param Matrix MatrixContainer with matrices (LevelCounter by ColumnCounter) with all the energies.517 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies. 488 518 * \param CorrectionFragments MatrixContainer with hydrogen saturation correction per fragments 489 519 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order … … 498 528 for(int i=KeySet.FragmentsPerOrder[Order];i--;) 499 529 for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;) 500 for(int k=ColumnCounter ;k--;)530 for(int k=ColumnCounter[ KeySet.OrderSet[Order][i] ];k--;) 501 531 Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k]; 502 532 else 503 533 for(int i=KeySet.FragmentsPerOrder[Order];i--;) 504 534 for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;) 505 for(int k=ColumnCounter ;k--;)535 for(int k=ColumnCounter[ KeySet.OrderSet[Order][i] ];k--;) 506 536 Matrix[MatrixCounter][j][k] += sign*(Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k] + CorrectionFragments->Matrix[ KeySet.OrderSet[Order][i] ][j][k]); 507 537 return true; … … 524 554 // count maximum of columns 525 555 RowCounter[MatrixCounter] = 0; 526 for(int j=0; j < MatrixCounter;j++) // (energy matrix might be bigger than number of atoms in terms of rows) 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) 527 558 if (RowCounter[j] > RowCounter[MatrixCounter]) 528 559 RowCounter[MatrixCounter] = RowCounter[j]; 560 if (ColumnCounter[j] > ColumnCounter[MatrixCounter]) // take maximum of all for last matrix 561 ColumnCounter[MatrixCounter] = ColumnCounter[j]; 562 } 529 563 // allocate last plus one matrix 530 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter << " columns." << endl;564 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter[MatrixCounter] << " columns." << endl; 531 565 Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 532 566 for(int j=0;j<=RowCounter[MatrixCounter];j++) 533 Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter , "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");567 Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter[MatrixCounter], "MatrixContainer::ParseFragmentMatrix: *Matrix[][]"); 534 568 535 569 // try independently to parse global energysuffix file if present … … 589 623 590 624 /** Sums the forces and puts into last element of \a ForceMatrix::Matrix. 591 * \param Matrix MatrixContainer with matrices (LevelCounter by ColumnCounter) with all the energies.625 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies. 592 626 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order 593 627 * \param Order bond order … … 609 643 if (j != -1) { 610 644 //if (j == 0) cout << "Summing onto ion 0, type 0 from fragment " << FragmentNr << ", ion " << l << "." << endl; 611 for(int k=2;k<ColumnCounter ;k++)645 for(int k=2;k<ColumnCounter[MatrixCounter];k++) 612 646 Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ FragmentNr ][l][k]; 613 647 } … … 655 689 RowCounter[MatrixCounter]++; // nr start at 0, count starts at 1 656 690 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 matrix 695 ColumnCounter[MatrixCounter] = ColumnCounter[j]; 696 } 657 697 658 698 // allocate last plus one matrix 659 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter << " columns." << endl;699 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter[MatrixCounter] << " columns." << endl; 660 700 Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 661 701 for(int j=0;j<=RowCounter[MatrixCounter];j++) 662 Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]"); 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[][]"); 663 927 664 928 // try independently to parse global forcesuffix file if present -
Property mode
changed from
-
src/parser.hpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 19 19 20 20 #define EnergySuffix ".energy.all" 21 #define EnergyFragmentSuffix ".energyfragment.all" 22 #define ForcesSuffix ".forces.all" 23 #define ForceFragmentSuffix ".forcefragment.all" 21 24 #define HcorrectionSuffix ".Hcorrection.all" 22 #define ForcesSuffix ".forces.all" 25 #define HcorrectionFragmentSuffix ".Hcorrectionfragment.all" 26 #define HessianSuffix ".hessian_xx.all" 27 #define HessianFragmentSuffix ".hessianfragment_xx.all" 28 #define OrderSuffix ".Order" 23 29 #define ShieldingSuffix ".sigma_all.csv" 24 30 #define ShieldingPASSuffix ".sigma_all_PAS.csv" 25 31 #define ShieldingFragmentSuffix ".sigma_all_fragment.all" 26 32 #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" 27 37 #define TimeSuffix ".speed" 28 #define EnergyFragmentSuffix ".energyfragment.all"29 #define HcorrectionFragmentSuffix ".Hcorrectionfragment.all"30 #define ForceFragmentSuffix ".forcefragment.all"31 #define OrderSuffix ".Order"32 38 33 39 // ======================================= FUNCTIONS ========================================== … … 43 49 double ***Matrix; 44 50 int **Indices; 45 char * Header;51 char **Header; 46 52 int MatrixCounter; 47 53 int *RowCounter; 48 int ColumnCounter;54 int *ColumnCounter; 49 55 50 56 MatrixContainer(); 51 57 ~MatrixContainer(); 52 58 59 bool InitialiseIndices(class MatrixContainer *Matrix = NULL); 53 60 bool ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr); 54 61 virtual bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns); 55 bool AllocateMatrix(char * GivenHeader, int MCounter, int *RCounter, intCCounter);62 bool AllocateMatrix(char **GivenHeader, int MCounter, int *RCounter, int *CCounter); 56 63 bool ResetMatrix(); 57 64 double FindMinValue(); … … 70 77 class EnergyMatrix : public MatrixContainer { 71 78 public: 72 bool ParseIndices();73 79 bool SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign); 74 80 bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns); … … 82 88 bool SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign); 83 89 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; 84 104 }; 85 105 -
Property mode
changed from
-
src/periodentafel.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 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 120 119 /** Prints period table to given stream. 121 120 * \param output stream 122 */ 121 */ 123 122 bool periodentafel::Output(ofstream *output) const 124 123 { … … 131 130 } 132 131 return result; 133 } else 132 } else 134 133 return false; 135 134 }; … … 138 137 * \param *output output stream 139 138 * \param *checkliste elements table for this molecule 140 */ 139 */ 141 140 bool periodentafel::Checkout(ofstream *output, const int *checkliste) const 142 141 { … … 152 151 if ((walker != NULL) && (walker->Z > 0) && (walker->Z < MAX_ELEMENTS) && (checkliste[walker->Z])) { 153 152 walker->No = No; 154 result = result && walker->Checkout(output, No++, checkliste[walker->Z]); 153 result = result && walker->Checkout(output, No++, checkliste[walker->Z]); 155 154 } 156 155 } 157 156 return result; 158 } else 157 } else 159 158 return false; 160 159 }; 161 162 160 163 161 /** Loads element list from file. … … 171 169 bool status = true; 172 170 bool otherstatus = true; 173 char *filename = new char[MAXSTRINGSIZE];174 171 char filename[255]; 172 175 173 // fill elements DB 176 174 strncpy(filename, path, MAXSTRINGSIZE); … … 225 223 if (infile != NULL) { 226 224 while (!infile.eof()) { 227 228 229 230 231 225 infile >> tmp; 226 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; 232 230 } 233 231 infile.close(); … … 253 251 } else 254 252 otherstatus = false; 255 253 256 254 // fill H-BondDistance DB per element 257 255 strncpy(filename, path, MAXSTRINGSIZE); … … 261 259 if (infile != NULL) { 262 260 while (!infile.eof()) { 263 261 infile >> tmp; 264 262 ptr = FindElement((int)tmp); 265 263 infile >> ws; 266 264 infile >> ptr->HBondDistance[0]; 267 265 infile >> ptr->HBondDistance[1]; 268 266 infile >> ptr->HBondDistance[2]; 269 267 infile >> ws; 270 268 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->HBondDistance[0] << " Angstrom typical distance to hydrogen." << endl; 271 269 } … … 274 272 } else 275 273 otherstatus = false; 276 274 277 275 // fill H-BondAngle DB per element 278 276 strncpy(filename, path, MAXSTRINGSIZE); … … 294 292 } else 295 293 otherstatus = false; 296 294 297 295 if (!otherstatus) 298 cerr << " ERROR: Something went wrong while parsing thedatabases!" << endl;299 296 cerr << "WARNING: Something went wrong while parsing the other databases!" << endl; 297 300 298 return status; 301 299 }; … … 308 306 ofstream f; 309 307 char filename[MAXSTRINGSIZE]; 310 308 311 309 strncpy(filename, path, MAXSTRINGSIZE); 312 310 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename)); -
Property mode
changed from
-
src/periodentafel.hpp
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/stackclass.hpp
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/valence.db
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 18 18 18 0.80000000000000E+01 19 19 19 0.30000000000000E+01 20 20 0. 20000000000000E+0120 20 0.40000000000000E+01 21 21 21 0.30000000000000E+01 22 22 22 0.40000000000000E+01 -
Property mode
changed from
-
src/vector.cpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 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 ************************************/ … … 21 21 */ 22 22 Vector::~Vector() {}; 23 24 /** Calculates square of distance between this and another vector. 25 * \param *y array to second vector 26 * \return \f$| x - y |^2\f$ 27 */ 28 double Vector::DistanceSquared(const Vector *y) const 29 { 30 double res = 0.; 31 for (int i=NDIM;i--;) 32 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 33 return (res); 34 }; 23 35 24 36 /** Calculates distance between this and another vector. 25 37 * \param *y array to second vector 26 * \return \f$| x - y | ^2\f$38 * \return \f$| x - y |\f$ 27 39 */ 28 40 double Vector::Distance(const Vector *y) const … … 31 43 for (int i=NDIM;i--;) 32 44 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 33 return ( res);45 return (sqrt(res)); 34 46 }; 35 47 … … 69 81 if (tmp < res) res = tmp; 70 82 } 71 return (res); 83 return (res); 72 84 }; 73 85 … … 112 124 for (int i=NDIM;i--;) 113 125 res += x[i]*y->x[i]; 114 return (res); 115 }; 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 116 146 117 147 /** projects this vector onto plane defined by \a *y. 118 * \param *y array tonormal vector of plane148 * \param *y normal vector of plane 119 149 * \return \f$\langle x, y \rangle\f$ 120 150 */ … … 123 153 Vector tmp; 124 154 tmp.CopyVector(y); 125 tmp.Scale(Projection(y)); 155 tmp.Normalize(); 156 tmp.Scale(ScalarProduct(&tmp)); 126 157 this->SubtractVector(&tmp); 127 158 }; … … 144 175 for (int i=NDIM;i--;) 145 176 res += this->x[i]*this->x[i]; 146 return (sqrt(res)); 177 return (sqrt(res)); 147 178 }; 148 179 … … 178 209 */ 179 210 void Vector::Init(double x1, double x2, double x3) 180 { 211 { 181 212 x[0] = x1; 182 213 x[1] = x2; … … 188 219 * \return \f$\acos\bigl(frac{\langle x, y \rangle}{|x||y|}\bigr)\f$ 189 220 */ 190 double Vector::Angle( Vector *y) const191 { 192 return acos(this->ScalarProduct(y)/Norm()/y->Norm()); 221 double Vector::Angle(const Vector *y) const 222 { 223 return acos(this->ScalarProduct(y)/Norm()/y->Norm()); 193 224 }; 194 225 … … 238 269 239 270 /** Sums two vectors \a and \b component-wise. 240 * \param a first vector 271 * \param a first vector 241 272 * \param b second vector 242 273 * \return a + b … … 251 282 252 283 /** Factors given vector \a a times \a m. 253 * \param a vector 284 * \param a vector 254 285 * \param m factor 255 286 * \return a + b … … 282 313 }; 283 314 284 ofstream& operator<<(ofstream& ost,Vector& m) 285 { 286 m.Output(&ost); 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 << ")"; 287 329 return ost; 288 330 }; … … 309 351 }; 310 352 311 /** Translate atom by given vector. 353 /** Translate atom by given vector. 312 354 * \param trans[] translation vector. 313 355 */ … … 316 358 for (int i=NDIM;i--;) 317 359 x[i] += trans->x[i]; 318 }; 360 }; 319 361 320 362 /** Do a matrix multiplication. … … 355 397 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]); // A_32 356 398 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]); // A_33 357 399 358 400 // do the matrix multiplication 359 401 C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2]; … … 379 421 { 380 422 for(int i=NDIM;i--;) 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. 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. 385 427 * \param n[] normal vector of mirror plane. 386 428 */ … … 398 440 Output((ofstream *)&cout); 399 441 cout << endl; 400 }; 442 }; 401 443 402 444 /** Calculates normal vector for three given vectors (being three points in space). … … 430 472 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]); 431 473 Normalize(); 432 474 433 475 return true; 434 476 }; … … 488 530 /** Creates this vector as one of the possible orthonormal ones to the given one. 489 531 * Just scan how many components of given *vector are unequal to zero and 490 * try to get the skp of both to be zero accordingly. 532 * try to get the skp of both to be zero accordingly. 491 533 * \param *vector given vector 492 534 * \return true - success, false - failure (null vector given) … … 509 551 Components[Last++] = j; 510 552 cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl; 511 553 512 554 switch(Last) { 513 555 case 3: // threecomponent system … … 522 564 case 1: // one component system 523 565 // set sole non-zero component to 0, and one of the other zero component pendants to 1 524 x[(Components[0]+2)%NDIM] = 0.; 525 x[(Components[0]+1)%NDIM] = 1.; 526 x[Components[0]] = 0.; 566 x[(Components[0]+2)%NDIM] = 0.; 567 x[(Components[0]+1)%NDIM] = 1.; 568 x[Components[0]] = 0.; 527 569 return true; 528 570 break; … … 541 583 { 542 584 // cout << Verbose(3) << "For comparison: "; 543 // cout << "A " << A->Projection(this) << "\t"; 544 // cout << "B " << B->Projection(this) << "\t"; 545 // cout << "C " << C->Projection(this) << "\t"; 585 // cout << "A " << A->Projection(this) << "\t"; 586 // cout << "B " << B->Projection(this) << "\t"; 587 // cout << "C " << C->Projection(this) << "\t"; 546 588 // cout << endl; 547 589 return A->Projection(this); … … 553 595 * \return true if success, false if failed due to linear dependency 554 596 */ 555 bool Vector::LSQdistance(Vector **vectors, int num) 597 bool Vector::LSQdistance(Vector **vectors, int num) 556 598 { 557 599 int j; 558 600 559 601 for (j=0;j<num;j++) { 560 602 cout << Verbose(1) << j << "th atom's vector: "; … … 565 607 int np = 3; 566 608 struct LSQ_params par; 567 609 568 610 const gsl_multimin_fminimizer_type *T = 569 611 gsl_multimin_fminimizer_nmsimplex; … … 571 613 gsl_vector *ss, *y; 572 614 gsl_multimin_function minex_func; 573 615 574 616 size_t iter = 0, i; 575 617 int status; 576 618 double size; 577 619 578 620 /* Initial vertex size vector */ 579 621 ss = gsl_vector_alloc (np); 580 622 y = gsl_vector_alloc (np); 581 623 582 624 /* Set all step sizes to 1 */ 583 625 gsl_vector_set_all (ss, 1.0); 584 626 585 627 /* Starting point */ 586 628 par.vectors = vectors; 587 629 par.num = num; 588 630 589 631 for (i=NDIM;i--;) 590 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.); 591 632 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.); 633 592 634 /* Initialize method and iterate */ 593 635 minex_func.f = &LSQ; 594 636 minex_func.n = np; 595 637 minex_func.params = (void *)∥ 596 638 597 639 s = gsl_multimin_fminimizer_alloc (T, np); 598 640 gsl_multimin_fminimizer_set (s, &minex_func, y, ss); 599 641 600 642 do 601 643 { 602 644 iter++; 603 645 status = gsl_multimin_fminimizer_iterate(s); 604 646 605 647 if (status) 606 648 break; 607 649 608 650 size = gsl_multimin_fminimizer_size (s); 609 651 status = gsl_multimin_test_size (size, 1e-2); 610 652 611 653 if (status == GSL_SUCCESS) 612 654 { 613 655 printf ("converged to minimum at\n"); 614 656 } 615 657 616 658 printf ("%5d ", (int)iter); 617 659 for (i = 0; i < (size_t)np; i++) … … 622 664 } 623 665 while (status == GSL_CONTINUE && iter < 100); 624 666 625 667 for (i=(size_t)np;i--;) 626 668 this->x[i] = gsl_vector_get(s->x, i); … … 688 730 * \param alpha first angle 689 731 * \param beta second angle 690 * \param c norm of final vector 732 * \param c norm of final vector 691 733 * \return a vector with \f$\langle x1,x2 \rangle=A\f$, \f$\langle x1,y \rangle = B\f$ and with norm \a c. 692 * \bug this is not yet working properly 734 * \bug this is not yet working properly 693 735 */ 694 736 bool Vector::SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c) … … 706 748 if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping 707 749 if (fabs(x1->x[1]) > MYEPSILON) { 708 flag = 1; 750 flag = 1; 709 751 } else if (fabs(x1->x[2]) > MYEPSILON) { 710 752 flag = 2; … … 739 781 // now comes the case system 740 782 D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1]; 741 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2]; 783 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2]; 742 784 D3 = y->x[0]/x1->x[0]*A-B1; 743 785 cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n"; 744 786 if (fabs(D1) < MYEPSILON) { 745 cout << Verbose(2) << "D1 == 0!\n"; 787 cout << Verbose(2) << "D1 == 0!\n"; 746 788 if (fabs(D2) > MYEPSILON) { 747 cout << Verbose(3) << "D2 != 0!\n"; 789 cout << Verbose(3) << "D2 != 0!\n"; 748 790 x[2] = -D3/D2; 749 791 E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2; … … 755 797 cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 756 798 if (fabs(F1) < MYEPSILON) { 757 cout << Verbose(4) << "F1 == 0!\n"; 799 cout << Verbose(4) << "F1 == 0!\n"; 758 800 cout << Verbose(4) << "Gleichungssystem linear\n"; 759 x[1] = F3/(2.*F2); 801 x[1] = F3/(2.*F2); 760 802 } else { 761 803 p = F2/F1; 762 804 q = p*p - F3/F1; 763 cout << Verbose(4) << "p " << p << "\tq " << q << endl; 805 cout << Verbose(4) << "p " << p << "\tq " << q << endl; 764 806 if (q < 0) { 765 807 cout << Verbose(4) << "q < 0" << endl; … … 782 824 cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 783 825 if (fabs(F1) < MYEPSILON) { 784 cout << Verbose(3) << "F1 == 0!\n"; 826 cout << Verbose(3) << "F1 == 0!\n"; 785 827 cout << Verbose(3) << "Gleichungssystem linear\n"; 786 x[2] = F3/(2.*F2); 828 x[2] = F3/(2.*F2); 787 829 } else { 788 830 p = F2/F1; 789 831 q = p*p - F3/F1; 790 cout << Verbose(3) << "p " << p << "\tq " << q << endl; 832 cout << Verbose(3) << "p " << p << "\tq " << q << endl; 791 833 if (q < 0) { 792 834 cout << Verbose(3) << "q < 0" << endl; … … 832 874 } 833 875 cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n"; 834 // apply sign matrix 876 // apply sign matrix 835 877 for (j=NDIM;j--;) 836 878 x[j] *= sign[j]; … … 838 880 ang = x2->Angle (this); 839 881 cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t"; 840 if (fabs(ang - cos(beta)) < MYEPSILON) { 882 if (fabs(ang - cos(beta)) < MYEPSILON) { 841 883 break; 842 884 } -
Property mode
changed from
-
src/vector.hpp
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 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; 18 19 double PeriodicDistance(const Vector *y, const double *cell_size) const; 19 20 double ScalarProduct(const Vector *y) const; 20 21 double Projection(const Vector *y) const; 21 22 double Norm() const ; 22 double Angle( Vector *y) const;23 double Angle(const Vector *y) const; 23 24 24 25 void AddVector(const Vector *y); … … 26 27 void CopyVector(const Vector *y); 27 28 void RotateVector(const Vector *y, const double alpha); 29 void VectorProduct(const Vector *y); 28 30 void ProjectOntoPlane(const Vector *y); 29 void Zero(); 31 void Zero(); 30 32 void One(double one); 31 33 void Init(double x1, double x2, double x3); … … 40 42 void KeepPeriodic(ofstream *out, double *matrix); 41 43 void LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors); 42 44 43 45 double CutsPlaneAt(Vector *A, Vector *B, Vector *C); 44 46 bool GetOneNormalVector(const Vector *x1); … … 53 55 }; 54 56 55 o fstream& 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);57 ostream & 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); 60 62 61 63 #endif /*VECTOR_HPP_*/ -
Property mode
changed from
-
src/verbose.cpp
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
tests/Makefile.am
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
tests/atlocal.in
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
tests/molecuilder.in
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
tests/testsuite.at
-
Property mode
changed from
100644
to100755
rfcbfc8 r631dcb 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]) 14 18 AT_CLEANUP 15 19 … … 38 42 AT_CHECK([../../molecuilder -e ./ <input], 0, [ignore], [ignore]) 39 43 AT_CHECK([diff main_pcp_linux test.conf], 0, [ignore], [ignore]) 44 # 4. test some more configuration 45 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, [10 47 ], [ignore]) 40 48 AT_CLEANUP 41 49 -
Property mode
changed from
Note:
See TracChangeset
for help on using the changeset viewer.