| 1 | /*
 | 
|---|
| 2 |  * Project: MoleCuilder
 | 
|---|
| 3 |  * Description: creates and alters molecular systems
 | 
|---|
| 4 |  * Copyright (C)  2010-2012 University of Bonn. All rights reserved.
 | 
|---|
| 5 |  * Copyright (C)  2013 Frederik Heber. All rights reserved.
 | 
|---|
| 6 |  * 
 | 
|---|
| 7 |  *
 | 
|---|
| 8 |  *   This file is part of MoleCuilder.
 | 
|---|
| 9 |  *
 | 
|---|
| 10 |  *    MoleCuilder is free software: you can redistribute it and/or modify
 | 
|---|
| 11 |  *    it under the terms of the GNU General Public License as published by
 | 
|---|
| 12 |  *    the Free Software Foundation, either version 2 of the License, or
 | 
|---|
| 13 |  *    (at your option) any later version.
 | 
|---|
| 14 |  *
 | 
|---|
| 15 |  *    MoleCuilder is distributed in the hope that it will be useful,
 | 
|---|
| 16 |  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 17 |  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 18 |  *    GNU General Public License for more details.
 | 
|---|
| 19 |  *
 | 
|---|
| 20 |  *    You should have received a copy of the GNU General Public License
 | 
|---|
| 21 |  *    along with MoleCuilder.  If not, see <http://www.gnu.org/licenses/>.
 | 
|---|
| 22 |  */
 | 
|---|
| 23 | 
 | 
|---|
| 24 | /*
 | 
|---|
| 25 |  * PcpParser_helper.cpp
 | 
|---|
| 26 |  *
 | 
|---|
| 27 |  *  Created on: Oct 27, 2011
 | 
|---|
| 28 |  *      Author: heber
 | 
|---|
| 29 |  */
 | 
|---|
| 30 | 
 | 
|---|
| 31 | // include config.h
 | 
|---|
| 32 | #ifdef HAVE_CONFIG_H
 | 
|---|
| 33 | #include <config.h>
 | 
|---|
| 34 | #endif
 | 
|---|
| 35 | 
 | 
|---|
| 36 | //#include "CodePatterns/MemDebug.hpp"
 | 
|---|
| 37 | 
 | 
|---|
| 38 | #include <boost/tokenizer.hpp>
 | 
|---|
| 39 | #include <map>
 | 
|---|
| 40 | #include <sstream>
 | 
|---|
| 41 | #include <string>
 | 
|---|
| 42 | #include <vector>
 | 
|---|
| 43 | 
 | 
|---|
| 44 | #include "CodePatterns/Log.hpp"
 | 
|---|
| 45 | #include "Element/element.hpp"
 | 
|---|
| 46 | #include "Element/periodentafel.hpp"
 | 
|---|
| 47 | #include "Helpers/helpers.hpp"
 | 
|---|
| 48 | #include "molecule.hpp"
 | 
|---|
| 49 | #include "Parser/ConfigFileBuffer.hpp"
 | 
|---|
| 50 | 
 | 
|---|
| 51 | /** Reads parameter from a parsed file.
 | 
|---|
| 52 |  * The file is either parsed for a certain keyword or if null is given for
 | 
|---|
| 53 |  * the value in row yth and column xth. If the keyword was necessity#critical,
 | 
|---|
| 54 |  * then an error is thrown and the programme aborted.
 | 
|---|
| 55 |  * \warning value is modified (both in contents and position)!
 | 
|---|
| 56 |  * \param verbose 1 - print found value to stderr, 0 - don't
 | 
|---|
| 57 |  * \param *file file to be parsed
 | 
|---|
| 58 |  * \param name Name of value in file (at least 3 chars!)
 | 
|---|
| 59 |  * \param sequential 1 - do not reset file pointer to begin of file, 0 - set to beginning
 | 
|---|
| 60 |  *        (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read -
 | 
|---|
| 61 |  *         best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now
 | 
|---|
| 62 |  *         counted from this unresetted position!)
 | 
|---|
| 63 |  * \param xth Which among a number of parameters it is (in grid case it's row number as grid is read as a whole!)
 | 
|---|
| 64 |  * \param yth In grid case specifying column number, otherwise the yth \a name matching line
 | 
|---|
| 65 |  * \param type Type of the Parameter to be read
 | 
|---|
| 66 |  * \param value address of the value to be read (must have been allocated)
 | 
|---|
| 67 |  * \param repetition determines, if the keyword appears multiply in the config file, which repetition shall be parsed, i.e. 1 if not multiply
 | 
|---|
| 68 |  * \param critical necessity of this keyword being specified (optional, critical)
 | 
|---|
| 69 |  * \return 1 - found, 0 - not found
 | 
|---|
| 70 |  * \note Routine is taken from the pcp project and hack-a-slack adapted to C++
 | 
|---|
| 71 |  */
 | 
|---|
| 72 | int ParseForParameter(const int verbose, ifstream * const file, const char * const name, const int sequential, const int xth, const int yth, const int type, void * value, const int repetition, const int critical) {
 | 
|---|
| 73 |   int i = 0;
 | 
|---|
| 74 |   int j = 0;  // loop variables
 | 
|---|
| 75 |   int length = 0;
 | 
|---|
| 76 |   int maxlength = -1;
 | 
|---|
| 77 |   long file_position = file->tellg(); // mark current position
 | 
|---|
| 78 |   char *dummy1 = NULL;
 | 
|---|
| 79 |   char *dummy = NULL;
 | 
|---|
| 80 |   char free_dummy[MAXSTRINGSIZE];    // pointers in the line that is read in per step
 | 
|---|
| 81 |   dummy1 = free_dummy;
 | 
|---|
| 82 | 
 | 
|---|
| 83 |   //fprintf(stderr,"Parsing for %s\n",name);
 | 
|---|
| 84 |   if (repetition == 0)
 | 
|---|
| 85 |     //Error(SomeError, "ParseForParameter(): argument repetition must not be 0!");
 | 
|---|
| 86 |     return 0;
 | 
|---|
| 87 | 
 | 
|---|
| 88 |   int line = 0; // marks line where parameter was found
 | 
|---|
| 89 |   int found = (type >= grid) ? 0 : (-yth + 1);  // marks if yth parameter name was found
 | 
|---|
| 90 |   while((found != repetition)) {
 | 
|---|
| 91 |     dummy1 = dummy = free_dummy;
 | 
|---|
| 92 |     do {
 | 
|---|
| 93 |       file->getline(dummy1, 256); // Read the whole line
 | 
|---|
| 94 |       if (file->eof()) {
 | 
|---|
| 95 |         if ((critical) && (found == 0)) {
 | 
|---|
| 96 |           //Error(InitReading, name);
 | 
|---|
| 97 |           fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
 | 
|---|
| 98 |           exit(255);
 | 
|---|
| 99 |         } else {
 | 
|---|
| 100 |           //if (!sequential)
 | 
|---|
| 101 |           file->clear();
 | 
|---|
| 102 |           file->seekg(file_position, ios::beg);  // rewind to start position
 | 
|---|
| 103 |           return 0;
 | 
|---|
| 104 |         }
 | 
|---|
| 105 |       }
 | 
|---|
| 106 |       line++;
 | 
|---|
| 107 |     } while (dummy != NULL && dummy1 != NULL && ((dummy1[0] == '#') || (dummy1[0] == '\0'))); // skip commentary and empty lines
 | 
|---|
| 108 | 
 | 
|---|
| 109 |     // C++ getline removes newline at end, thus re-add
 | 
|---|
| 110 |     if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {
 | 
|---|
| 111 |       i = strlen(dummy1);
 | 
|---|
| 112 |       dummy1[i] = '\n';
 | 
|---|
| 113 |       dummy1[i+1] = '\0';
 | 
|---|
| 114 |     }
 | 
|---|
| 115 |     //fprintf(stderr,"line %i ends at %i, newline at %i\n", line, strlen(dummy1), strchr(dummy1,'\n')-free_dummy);
 | 
|---|
| 116 | 
 | 
|---|
| 117 |     if (dummy1 == NULL) {
 | 
|---|
| 118 |       if (verbose) fprintf(stderr,"Error reading line %i\n",line);
 | 
|---|
| 119 |     } else {
 | 
|---|
| 120 |       //fprintf(stderr,"Now parsing the line %i: %s\n", line, dummy1);
 | 
|---|
| 121 |     }
 | 
|---|
| 122 |     // Seek for possible end of keyword on line if given ...
 | 
|---|
| 123 |     if (name != NULL) {
 | 
|---|
| 124 |       dummy = strchr(dummy1,'\t');  // set dummy on first tab or space which ever's nearer
 | 
|---|
| 125 |       if (dummy == NULL) {
 | 
|---|
| 126 |         dummy = strchr(dummy1, ' ');  // if not found seek for space
 | 
|---|
| 127 |         while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' ')))    // skip some more tabs and spaces if necessary
 | 
|---|
| 128 |           dummy++;
 | 
|---|
| 129 |       }
 | 
|---|
| 130 |       if (dummy == NULL) {
 | 
|---|
| 131 |         dummy = strchr(dummy1, '\n'); // set on line end then (whole line = keyword)
 | 
|---|
| 132 |         //fprintf(stderr,"Error: Cannot find tabs or spaces on line %i in search for %s\n", line, name);
 | 
|---|
| 133 |         //Error(FileOpenParams, NULL);
 | 
|---|
| 134 |       } else {
 | 
|---|
| 135 |         //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)dummy1);
 | 
|---|
| 136 |       }
 | 
|---|
| 137 |     } else dummy = dummy1;
 | 
|---|
| 138 |     // ... and check if it is the keyword!
 | 
|---|
| 139 |     //fprintf(stderr,"name %p, dummy %i/%c, dummy1 %i/%c, strlen(name) %i\n", &name, dummy, *dummy, dummy1, *dummy1, strlen(name));
 | 
|---|
| 140 |     if ((name == NULL) || (((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0)) && ((unsigned int)(dummy-dummy1) == strlen(name)))) {
 | 
|---|
| 141 |       found++; // found the parameter!
 | 
|---|
| 142 |       //fprintf(stderr,"found %s at line %i between %i and %i\n", name, line, dummy1, dummy);
 | 
|---|
| 143 | 
 | 
|---|
| 144 |       if (found == repetition) {
 | 
|---|
| 145 |         for (i=0;i<xth;i++) { // i = rows
 | 
|---|
| 146 |           if (type >= grid) {
 | 
|---|
| 147 |             // grid structure means that grid starts on the next line, not right after keyword
 | 
|---|
| 148 |             dummy1 = dummy = free_dummy;
 | 
|---|
| 149 |             do {
 | 
|---|
| 150 |               file->getline(dummy1, 256); // Read the whole line, skip commentary and empty ones
 | 
|---|
| 151 |               if (file->eof()) {
 | 
|---|
| 152 |                 if ((critical) && (found == 0)) {
 | 
|---|
| 153 |                   //Error(InitReading, name);
 | 
|---|
| 154 |                   fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
 | 
|---|
| 155 |                   exit(255);
 | 
|---|
| 156 |                 } else {
 | 
|---|
| 157 |                   //if (!sequential)
 | 
|---|
| 158 |                   file->clear();
 | 
|---|
| 159 |                   file->seekg(file_position, ios::beg);  // rewind to start position
 | 
|---|
| 160 |                   return 0;
 | 
|---|
| 161 |                 }
 | 
|---|
| 162 |               }
 | 
|---|
| 163 |               line++;
 | 
|---|
| 164 |             } while ((dummy1[0] == '#') || (dummy1[0] == '\n'));
 | 
|---|
| 165 | //            if (dummy1 == NULL){
 | 
|---|
| 166 | //              if (verbose) fprintf(stderr,"Error reading line %i\n", line);
 | 
|---|
| 167 | //            } else {
 | 
|---|
| 168 | //              //fprintf(stderr,"Reading next line %i: %s\n", line, dummy1);
 | 
|---|
| 169 | //            }
 | 
|---|
| 170 |           } else { // simple int, strings or doubles start in the same line
 | 
|---|
| 171 |             while ((*dummy == '\t') || (*dummy == ' '))   // skip interjacent tabs and spaces
 | 
|---|
| 172 |               dummy++;
 | 
|---|
| 173 |           }
 | 
|---|
| 174 |           // C++ getline removes newline at end, thus re-add
 | 
|---|
| 175 |           if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {
 | 
|---|
| 176 |             j = strlen(dummy1);
 | 
|---|
| 177 |             dummy1[j] = '\n';
 | 
|---|
| 178 |             dummy1[j+1] = '\0';
 | 
|---|
| 179 |           }
 | 
|---|
| 180 | 
 | 
|---|
| 181 |           int start = (type >= grid) ? 0 : yth-1 ;
 | 
|---|
| 182 |           for (j=start;j<yth;j++) { // j = columns
 | 
|---|
| 183 |             // check for lower triangular area and upper triangular area
 | 
|---|
| 184 |             if ( ((i > j) && (type == upper_trigrid)) || ((j > i) && (type == lower_trigrid))) {
 | 
|---|
| 185 |               *((double *)value) = 0.0;
 | 
|---|
| 186 |               fprintf(stderr,"%f\t",*((double *)value));
 | 
|---|
| 187 |               value = (void *)((long)value + sizeof(double));
 | 
|---|
| 188 |               //value += sizeof(double);
 | 
|---|
| 189 |             } else {
 | 
|---|
| 190 |               // otherwise we must skip all interjacent tabs and spaces and find next value
 | 
|---|
| 191 |               dummy1 = dummy;
 | 
|---|
| 192 |               dummy = strchr(dummy1, '\t'); // seek for tab or space
 | 
|---|
| 193 |               if (dummy == NULL)
 | 
|---|
| 194 |                 dummy = strchr(dummy1, ' ');  // if not found seek for space
 | 
|---|
| 195 |               if (dummy == NULL) { // if still zero returned ...
 | 
|---|
| 196 |                 dummy = strchr(dummy1, '\n');  // ... at line end then
 | 
|---|
| 197 |                 if ((j < yth-1) && (type < 4)) {  // check if xth value or not yet
 | 
|---|
| 198 |                   if (critical) {
 | 
|---|
| 199 |                     if (verbose) fprintf(stderr,"Error: EoL at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);
 | 
|---|
| 200 |                     //return 0;
 | 
|---|
| 201 |                     exit(255);
 | 
|---|
| 202 |                     //Error(FileOpenParams, NULL);
 | 
|---|
| 203 |                   } else {
 | 
|---|
| 204 |                     //if (!sequential)
 | 
|---|
| 205 |                     file->clear();
 | 
|---|
| 206 |                     file->seekg(file_position, ios::beg);  // rewind to start position
 | 
|---|
| 207 |                     return 0;
 | 
|---|
| 208 |                   }
 | 
|---|
| 209 |                 }
 | 
|---|
| 210 |               } else {
 | 
|---|
| 211 |                 //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)free_dummy);
 | 
|---|
| 212 |               }
 | 
|---|
| 213 |               if (*dummy1 == '#') {
 | 
|---|
| 214 |                 // found comment, skipping rest of line
 | 
|---|
| 215 |                 //if (verbose) fprintf(stderr,"Error: '#' at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);
 | 
|---|
| 216 |                 if (!sequential) { // here we need it!
 | 
|---|
| 217 |                   file->seekg(file_position, ios::beg);  // rewind to start position
 | 
|---|
| 218 |                 }
 | 
|---|
| 219 |                 return 0;
 | 
|---|
| 220 |               }
 | 
|---|
| 221 |               //fprintf(stderr,"value from %i to %i\n",(char *)dummy1-(char *)free_dummy,(char *)dummy-(char *)free_dummy);
 | 
|---|
| 222 |               switch(type) {
 | 
|---|
| 223 |                 case (row_int):
 | 
|---|
| 224 |                   *((int *)value) = atoi(dummy1);
 | 
|---|
| 225 |                   if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
 | 
|---|
| 226 |                   if (verbose) fprintf(stderr,"%i\t",*((int *)value));
 | 
|---|
| 227 |                     value = (void *)((long)value + sizeof(int));
 | 
|---|
| 228 |                     //value += sizeof(int);
 | 
|---|
| 229 |                   break;
 | 
|---|
| 230 |                 case(row_double):
 | 
|---|
| 231 |                 case(grid):
 | 
|---|
| 232 |                 case(lower_trigrid):
 | 
|---|
| 233 |                 case(upper_trigrid):
 | 
|---|
| 234 |                   *((double *)value) = atof(dummy1);
 | 
|---|
| 235 |                   if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
 | 
|---|
| 236 |                   if (verbose) fprintf(stderr,"%lg\t",*((double *)value));
 | 
|---|
| 237 |                   value = (void *)((long)value + sizeof(double));
 | 
|---|
| 238 |                   //value += sizeof(double);
 | 
|---|
| 239 |                   break;
 | 
|---|
| 240 |                 case(double_type):
 | 
|---|
| 241 |                   *((double *)value) = atof(dummy1);
 | 
|---|
| 242 |                   if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %lg\n", name, *((double *) value));
 | 
|---|
| 243 |                   //value += sizeof(double);
 | 
|---|
| 244 |                   break;
 | 
|---|
| 245 |                 case(int_type):
 | 
|---|
| 246 |                   *((int *)value) = atoi(dummy1);
 | 
|---|
| 247 |                   if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %i\n", name, *((int *) value));
 | 
|---|
| 248 |                   //value += sizeof(int);
 | 
|---|
| 249 |                   break;
 | 
|---|
| 250 |                 default:
 | 
|---|
| 251 |                 case(string_type):
 | 
|---|
| 252 |                   if (value != NULL) {
 | 
|---|
| 253 |                     //if (maxlength == -1) maxlength = strlen((char *)value); // get maximum size of string array
 | 
|---|
| 254 |                     maxlength = MAXSTRINGSIZE;
 | 
|---|
| 255 |                     length = maxlength > (dummy-dummy1) ? (dummy-dummy1) : maxlength; // cap at maximum
 | 
|---|
| 256 |                     strncpy((char *)value, dummy1, length);  // copy as much
 | 
|---|
| 257 |                     ((char *)value)[length] = '\0';  // and set end marker
 | 
|---|
| 258 |                     if ((verbose) && (i == xth-1)) fprintf(stderr,"%s is '%s' (%i chars)\n",name,((char *) value), length);
 | 
|---|
| 259 |                     //value += sizeof(char);
 | 
|---|
| 260 |                   } else {
 | 
|---|
| 261 |                   }
 | 
|---|
| 262 |                 break;
 | 
|---|
| 263 |               }
 | 
|---|
| 264 |             }
 | 
|---|
| 265 |             while (*dummy == '\t')
 | 
|---|
| 266 |               dummy++;
 | 
|---|
| 267 |           }
 | 
|---|
| 268 |         }
 | 
|---|
| 269 |       }
 | 
|---|
| 270 |     }
 | 
|---|
| 271 |   }
 | 
|---|
| 272 |   if ((type >= row_int) && (verbose))
 | 
|---|
| 273 |     fprintf(stderr,"\n");
 | 
|---|
| 274 |   if (!sequential) {
 | 
|---|
| 275 |     file->clear();
 | 
|---|
| 276 |     file->seekg(file_position, ios::beg);  // rewind to start position
 | 
|---|
| 277 |   }
 | 
|---|
| 278 |   //fprintf(stderr, "End of Parsing\n\n");
 | 
|---|
| 279 | 
 | 
|---|
| 280 |   return (found); // true if found, false if not
 | 
|---|
| 281 | }
 | 
|---|
| 282 | 
 | 
|---|
| 283 | 
 | 
|---|
| 284 | /** Reads parameter from a parsed file.
 | 
|---|
| 285 |  * The file is either parsed for a certain keyword or if null is given for
 | 
|---|
| 286 |  * the value in row yth and column xth. If the keyword was necessity#critical,
 | 
|---|
| 287 |  * then an error is thrown and the programme aborted.
 | 
|---|
| 288 |  * \warning value is modified (both in contents and position)!
 | 
|---|
| 289 |  * \param verbose 1 - print found value to stderr, 0 - don't
 | 
|---|
| 290 |  * \param *FileBuffer pointer to buffer structure
 | 
|---|
| 291 |  * \param name Name of value in file (at least 3 chars!)
 | 
|---|
| 292 |  * \param sequential 1 - do not reset file pointer to begin of file, 0 - set to beginning
 | 
|---|
| 293 |  *        (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read -
 | 
|---|
| 294 |  *         best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now
 | 
|---|
| 295 |  *         counted from this unresetted position!)
 | 
|---|
| 296 |  * \param xth Which among a number of parameters it is (in grid case it's row number as grid is read as a whole!)
 | 
|---|
| 297 |  * \param yth In grid case specifying column number, otherwise the yth \a name matching line
 | 
|---|
| 298 |  * \param type Type of the Parameter to be read
 | 
|---|
| 299 |  * \param value address of the value to be read (must have been allocated)
 | 
|---|
| 300 |  * \param repetition determines, if the keyword appears multiply in the config file, which repetition shall be parsed, i.e. 1 if not multiply
 | 
|---|
| 301 |  * \param critical necessity of this keyword being specified (optional, critical)
 | 
|---|
| 302 |  * \return 1 - found, 0 - not found
 | 
|---|
| 303 |  * \note Routine is taken from the pcp project and hack-a-slack adapted to C++
 | 
|---|
| 304 |  */
 | 
|---|
| 305 | int ParseForParameter(const int verbose, struct ConfigFileBuffer * const FileBuffer, const char * const name, const int sequential, const int xth, const int yth, const int type, void * value, const int repetition, const int critical) {
 | 
|---|
| 306 |   int i = 0;
 | 
|---|
| 307 |   int j = 0;  // loop variables
 | 
|---|
| 308 |   int length = 0;
 | 
|---|
| 309 |   int maxlength = -1;
 | 
|---|
| 310 |   int OldCurrentLine = FileBuffer->CurrentLine;
 | 
|---|
| 311 |   char *dummy1 = NULL;
 | 
|---|
| 312 |   char *dummy = NULL;    // pointers in the line that is read in per step
 | 
|---|
| 313 |   char *free_dummy = NULL;
 | 
|---|
| 314 | 
 | 
|---|
| 315 |   if (verbose) fprintf(stderr,"Begin of Parsing for %s\n",name);
 | 
|---|
| 316 |   if (repetition == 0)
 | 
|---|
| 317 |     //Error(SomeError, "ParseForParameter(): argument repetition must not be 0!");
 | 
|---|
| 318 |     return 0;
 | 
|---|
| 319 | 
 | 
|---|
| 320 |   int found = (type >= grid) ? 0 : (-yth + 1);  // marks if yth parameter name was found
 | 
|---|
| 321 |   while((found != repetition)) {
 | 
|---|
| 322 |     dummy1 = dummy = NULL;
 | 
|---|
| 323 |     do {
 | 
|---|
| 324 |       if (FileBuffer->CurrentLine < FileBuffer->NoLines)
 | 
|---|
| 325 |         free_dummy = dummy1 = FileBuffer->buffer[ FileBuffer->LineMapping[FileBuffer->CurrentLine++] ];
 | 
|---|
| 326 |       if (FileBuffer->CurrentLine >= FileBuffer->NoLines) {
 | 
|---|
| 327 |         if ((critical) && (found == 0)) {
 | 
|---|
| 328 |           //Error(InitReading, name);
 | 
|---|
| 329 |           fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
 | 
|---|
| 330 |           return 0;
 | 
|---|
| 331 |         } else {
 | 
|---|
| 332 |           //fprintf(stdout,"Rewinding to OldCurrentLine due to search till end of file.\n");
 | 
|---|
| 333 |           FileBuffer->CurrentLine = OldCurrentLine; // rewind to start position
 | 
|---|
| 334 |           return 0;
 | 
|---|
| 335 |         }
 | 
|---|
| 336 |       }
 | 
|---|
| 337 |       if (dummy1 == NULL) {
 | 
|---|
| 338 |         if (verbose) fprintf(stderr,"Error reading line %i\n",FileBuffer->CurrentLine);
 | 
|---|
| 339 |       } else {
 | 
|---|
| 340 |         if (verbose) fprintf(stderr,"Now parsing the line %i: %s\n", FileBuffer->CurrentLine, dummy1);
 | 
|---|
| 341 |       }
 | 
|---|
| 342 |       //FileBuffer->CurrentLine++;
 | 
|---|
| 343 |     } while (dummy1 != NULL && ((dummy1[0] == '#') || (dummy1[0] == '\0'))); // skip commentary and empty lines
 | 
|---|
| 344 | 
 | 
|---|
| 345 |     // Seek for possible end of keyword on line if given ...
 | 
|---|
| 346 |     if (name != NULL) {
 | 
|---|
| 347 |       dummy = strchr(dummy1,'\t');  // set dummy on first tab or space which ever's nearer
 | 
|---|
| 348 |       if (dummy == NULL) {
 | 
|---|
| 349 |         dummy = strchr(dummy1, ' ');  // if not found seek for space
 | 
|---|
| 350 |         while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' ')))    // skip some more tabs and spaces if necessary
 | 
|---|
| 351 |           dummy++;
 | 
|---|
| 352 |       }
 | 
|---|
| 353 |       if (dummy == NULL) {
 | 
|---|
| 354 |         dummy = strchr(dummy1, '\n'); // set on line end then (whole line = keyword)
 | 
|---|
| 355 |         //fprintf(stderr,"Error: Cannot find tabs or spaces on line %i in search for %s\n", line, name);
 | 
|---|
| 356 |         //Error(FileOpenParams, NULL);
 | 
|---|
| 357 |       } else {
 | 
|---|
| 358 |         if (verbose) fprintf(stderr,"found tab at line %i at position %li\n",FileBuffer->CurrentLine, (char *)dummy-(char *)dummy1);
 | 
|---|
| 359 |       }
 | 
|---|
| 360 |     } else dummy = dummy1;
 | 
|---|
| 361 |     // ... and check if it is the keyword!
 | 
|---|
| 362 |     //fprintf(stderr,"name %p, dummy %i/%c, dummy1 %i/%c, strlen(name) %i\n", &name, dummy, *dummy, dummy1, *dummy1, strlen(name));
 | 
|---|
| 363 |     if ((name == NULL) || (((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0)) && ((unsigned int)(dummy-dummy1) == strlen(name)))) {
 | 
|---|
| 364 |       found++; // found the parameter!
 | 
|---|
| 365 |       if (verbose) fprintf(stderr,"found %s at line %i between %li and %li\n", name, FileBuffer->CurrentLine, (unsigned long)dummy1, (unsigned long)dummy);
 | 
|---|
| 366 | 
 | 
|---|
| 367 |       if (found == repetition) {
 | 
|---|
| 368 |         for (i=0;i<xth;i++) { // i = rows
 | 
|---|
| 369 |           if (type >= grid) {
 | 
|---|
| 370 |             // grid structure means that grid starts on the next line, not right after keyword
 | 
|---|
| 371 |             dummy1 = dummy = NULL;
 | 
|---|
| 372 |             do {
 | 
|---|
| 373 |               dummy1 = FileBuffer->buffer[ FileBuffer->LineMapping[ FileBuffer->CurrentLine++] ];
 | 
|---|
| 374 |               if (FileBuffer->CurrentLine >= FileBuffer->NoLines) {
 | 
|---|
| 375 |                 if ((critical) && (found == 0)) {
 | 
|---|
| 376 |                   //Error(InitReading, name);
 | 
|---|
| 377 |                   fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
 | 
|---|
| 378 |                   exit(255);
 | 
|---|
| 379 |                 } else {
 | 
|---|
| 380 |                   //fprintf(stdout,"Rewinding to OldCurrentLine due to search till end of line.\n");
 | 
|---|
| 381 |                   FileBuffer->CurrentLine = OldCurrentLine; // rewind to start position
 | 
|---|
| 382 |                   return 0;
 | 
|---|
| 383 |                 }
 | 
|---|
| 384 |               }
 | 
|---|
| 385 |               if (dummy1 == NULL) {
 | 
|---|
| 386 |                 if (verbose) fprintf(stderr,"Error reading line %i\n", FileBuffer->CurrentLine);
 | 
|---|
| 387 |               } else {
 | 
|---|
| 388 |                 if (verbose) fprintf(stderr,"Reading next line %i: %s\n", FileBuffer->CurrentLine, dummy1);
 | 
|---|
| 389 |               }
 | 
|---|
| 390 |               //FileBuffer->CurrentLine++;
 | 
|---|
| 391 |             } while ((dummy1 != NULL) && ((dummy1[0] == '#') || (dummy1[0] == '\n')));
 | 
|---|
| 392 |             dummy = dummy1;
 | 
|---|
| 393 |           } else { // simple int, strings or doubles start in the same line
 | 
|---|
| 394 |             while ((*dummy == '\t') || (*dummy == ' '))  // skip interjacent tabs and spaces
 | 
|---|
| 395 |               dummy++;
 | 
|---|
| 396 |           }
 | 
|---|
| 397 | 
 | 
|---|
| 398 |           for (j=((type >= grid) ? 0 : yth-1);j<yth;j++) { // j = columns
 | 
|---|
| 399 |             // check for lower triangular area and upper triangular area
 | 
|---|
| 400 |             if ( ((i > j) && (type == upper_trigrid)) || ((j > i) && (type == lower_trigrid))) {
 | 
|---|
| 401 |               *((double *)value) = 0.0;
 | 
|---|
| 402 |               fprintf(stderr,"%f\t",*((double *)value));
 | 
|---|
| 403 |               value = (void *)((long)value + sizeof(double));
 | 
|---|
| 404 |               //value += sizeof(double);
 | 
|---|
| 405 |             } else {
 | 
|---|
| 406 |               // otherwise we must skip all interjacent tabs and spaces and find next value
 | 
|---|
| 407 |               dummy1 = dummy;
 | 
|---|
| 408 |               dummy = strchr(dummy1, '\t'); // seek for tab or space
 | 
|---|
| 409 |               if (dummy == NULL)
 | 
|---|
| 410 |                 dummy = strchr(dummy1, ' ');  // if not found seek for space
 | 
|---|
| 411 |               if (dummy == NULL) { // if still zero returned ...
 | 
|---|
| 412 |                 dummy = strchr(dummy1, '\n'); // ... at line end then
 | 
|---|
| 413 |                 if ((j < yth-1) && (type < 4)) {  // check if xth value or not yet
 | 
|---|
| 414 |                   if (critical) {
 | 
|---|
| 415 |                     if (verbose) fprintf(stderr,"Error: EoL at %i and still missing %i value(s) for parameter %s\n", FileBuffer->CurrentLine, yth-j, name);
 | 
|---|
| 416 |                     //return 0;
 | 
|---|
| 417 |                     exit(255);
 | 
|---|
| 418 |                     //Error(FileOpenParams, NULL);
 | 
|---|
| 419 |                   } else {
 | 
|---|
| 420 |                     if (!sequential) { // here we need it!
 | 
|---|
| 421 |                       //fprintf(stdout,"Rewinding to OldCurrentLine due to end of line and sequential %d.\n", sequential);
 | 
|---|
| 422 |                       FileBuffer->CurrentLine = OldCurrentLine; // rewind to start position
 | 
|---|
| 423 |                     }
 | 
|---|
| 424 |                     return 0;
 | 
|---|
| 425 |                   }
 | 
|---|
| 426 |                 }
 | 
|---|
| 427 |               } else {
 | 
|---|
| 428 |                 if (verbose) fprintf(stderr,"found tab at line %i at position %li\n",FileBuffer->CurrentLine, (char *)dummy-(char *)free_dummy);
 | 
|---|
| 429 |               }
 | 
|---|
| 430 |               if (*dummy1 == '#') {
 | 
|---|
| 431 |                 // found comment, skipping rest of line
 | 
|---|
| 432 |                 //if (verbose) fprintf(stderr,"Error: '#' at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);
 | 
|---|
| 433 |                 if (!sequential) { // here we need it!
 | 
|---|
| 434 |                   //fprintf(stdout,"Rewinding to OldCurrentLine due to comment and sequential %d.\n", sequential);
 | 
|---|
| 435 |                   FileBuffer->CurrentLine = OldCurrentLine; // rewind to start position
 | 
|---|
| 436 |                 }
 | 
|---|
| 437 |                 return 0;
 | 
|---|
| 438 |               }
 | 
|---|
| 439 |               if (verbose) fprintf(stderr,"value from %li to %li\n",(char *)dummy1-(char *)free_dummy,(char *)dummy-(char *)free_dummy);
 | 
|---|
| 440 |               switch(type) {
 | 
|---|
| 441 |                 case (row_int):
 | 
|---|
| 442 |                   *((int *)value) = atoi(dummy1);
 | 
|---|
| 443 |                   if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
 | 
|---|
| 444 |                   if (verbose) fprintf(stderr,"%i\t",*((int *)value));
 | 
|---|
| 445 |                     value = (void *)((long)value + sizeof(int));
 | 
|---|
| 446 |                     //value += sizeof(int);
 | 
|---|
| 447 |                   break;
 | 
|---|
| 448 |                 case(row_double):
 | 
|---|
| 449 |                 case(grid):
 | 
|---|
| 450 |                 case(lower_trigrid):
 | 
|---|
| 451 |                 case(upper_trigrid):
 | 
|---|
| 452 |                   *((double *)value) = atof(dummy1);
 | 
|---|
| 453 |                   if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
 | 
|---|
| 454 |                   if (verbose) fprintf(stderr,"%lg\t",*((double *)value));
 | 
|---|
| 455 |                   value = (void *)((long)value + sizeof(double));
 | 
|---|
| 456 |                   //value += sizeof(double);
 | 
|---|
| 457 |                   break;
 | 
|---|
| 458 |                 case(double_type):
 | 
|---|
| 459 |                   *((double *)value) = atof(dummy1);
 | 
|---|
| 460 |                   if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %lg\n", name, *((double *) value));
 | 
|---|
| 461 |                   //value += sizeof(double);
 | 
|---|
| 462 |                   break;
 | 
|---|
| 463 |                 case(int_type):
 | 
|---|
| 464 |                   *((int *)value) = atoi(dummy1);
 | 
|---|
| 465 |                   if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %i\n", name, *((int *) value));
 | 
|---|
| 466 |                   //value += sizeof(int);
 | 
|---|
| 467 |                   break;
 | 
|---|
| 468 |                 default:
 | 
|---|
| 469 |                 case(string_type):
 | 
|---|
| 470 |                   if (value != NULL) {
 | 
|---|
| 471 |                     //if (maxlength == -1) maxlength = strlen((char *)value); // get maximum size of string array
 | 
|---|
| 472 |                     maxlength = MAXSTRINGSIZE;
 | 
|---|
| 473 |                     length = maxlength > (dummy-dummy1) ? (dummy-dummy1) : maxlength; // cap at maximum
 | 
|---|
| 474 |                     strncpy((char *)value, dummy1, length); // copy as much
 | 
|---|
| 475 |                     ((char *)value)[length] = '\0'; // and set end marker
 | 
|---|
| 476 |                     if ((verbose) && (i == xth-1)) fprintf(stderr,"%s is '%s' (%i chars)\n",name,((char *) value), length);
 | 
|---|
| 477 |                     //value += sizeof(char);
 | 
|---|
| 478 |                   } else {
 | 
|---|
| 479 |                   }
 | 
|---|
| 480 |                 break;
 | 
|---|
| 481 |               }
 | 
|---|
| 482 |             }
 | 
|---|
| 483 |             while (*dummy == '\t')
 | 
|---|
| 484 |               dummy++;
 | 
|---|
| 485 |           }
 | 
|---|
| 486 |         }
 | 
|---|
| 487 |       }
 | 
|---|
| 488 |     }
 | 
|---|
| 489 |   }
 | 
|---|
| 490 |   if ((type >= row_int) && (verbose)) fprintf(stderr,"\n");
 | 
|---|
| 491 |   if (!sequential) {
 | 
|---|
| 492 |     //fprintf(stdout,"Rewinding to OldCurrentLine due to sequential %d.\n", sequential);
 | 
|---|
| 493 |     FileBuffer->CurrentLine = OldCurrentLine; // rewind to start position
 | 
|---|
| 494 |   }
 | 
|---|
| 495 |   if (verbose) fprintf(stderr, "End of Parsing for %s\n\n",name);
 | 
|---|
| 496 | 
 | 
|---|
| 497 |   return (found); // true if found, false if not
 | 
|---|
| 498 | }
 | 
|---|
| 499 | 
 | 
|---|
| 500 | /** Loads a molecule from a ConfigFileBuffer.
 | 
|---|
| 501 |  * \param *mol molecule to load
 | 
|---|
| 502 |  * \param *FileBuffer ConfigFileBuffer to use
 | 
|---|
| 503 |  * \param *periode periodentafel for finding elements
 | 
|---|
| 504 |  * \param FastParsing whether to parse trajectories or not
 | 
|---|
| 505 |  */
 | 
|---|
| 506 | void LoadMolecule(molecule * const &mol, struct ConfigFileBuffer * const &FileBuffer, const periodentafel * const periode, const bool FastParsing)
 | 
|---|
| 507 | {
 | 
|---|
| 508 |   int MaxTypes = 0;
 | 
|---|
| 509 |   const element *elementhash[MAX_ELEMENTS];
 | 
|---|
| 510 |   char name[MAXSTRINGSIZE];
 | 
|---|
| 511 |   int Z = -1;
 | 
|---|
| 512 |   int No[MAX_ELEMENTS];
 | 
|---|
| 513 |   int verbose = DoLog(4);
 | 
|---|
| 514 |   double value[3];
 | 
|---|
| 515 | 
 | 
|---|
| 516 |   if (mol == NULL) {
 | 
|---|
| 517 |     ELOG(0, "Molecule is not allocated in LoadMolecule(), exit.");
 | 
|---|
| 518 |     performCriticalExit();
 | 
|---|
| 519 |   }
 | 
|---|
| 520 | 
 | 
|---|
| 521 |   ParseForParameter(verbose,FileBuffer,"MaxTypes", 0, 1, 1, int_type, &(MaxTypes), 1, critical);
 | 
|---|
| 522 |   if (MaxTypes == 0) {
 | 
|---|
| 523 |     ELOG(1, "There are no atoms according to MaxTypes in this config file." << endl);
 | 
|---|
| 524 |     //performCriticalExit();
 | 
|---|
| 525 |   } else {
 | 
|---|
| 526 |     // prescan number of ions per type
 | 
|---|
| 527 |     LOG(0, "STATUS: Prescanning ions per type: " << endl);
 | 
|---|
| 528 |     int NoAtoms = 0;
 | 
|---|
| 529 |     for (int i=0; i < MaxTypes; i++) {
 | 
|---|
| 530 |       sprintf(name,"Ion_Type%i",i+1);
 | 
|---|
| 531 |       ParseForParameter(verbose,FileBuffer, (const char*)name, 0, 1, 1, int_type, &No[i], 1, critical);
 | 
|---|
| 532 |       ParseForParameter(verbose,FileBuffer, name, 0, 2, 1, int_type, &Z, 1, critical);
 | 
|---|
| 533 |       elementhash[i] = periode->FindElement(Z);
 | 
|---|
| 534 |       LOG(1, i << ". Z = " << elementhash[i]->getAtomicNumber() << " with " << No[i] << " ions.");
 | 
|---|
| 535 |       NoAtoms += No[i];
 | 
|---|
| 536 |     }
 | 
|---|
| 537 |     int repetition = -1; // which repeated keyword shall be read
 | 
|---|
| 538 | 
 | 
|---|
| 539 |     // sort the lines via the LineMapping
 | 
|---|
| 540 |     sprintf(name,"Ion_Type%i",MaxTypes);
 | 
|---|
| 541 |     if (!ParseForParameter(verbose,FileBuffer, (const char*)name, 1, 1, 1, int_type, &value[0], 1, critical)) {
 | 
|---|
| 542 |       ELOG(0, "There are no atoms in the config file!" << endl);
 | 
|---|
| 543 |       performCriticalExit();
 | 
|---|
| 544 |       return;
 | 
|---|
| 545 |     }
 | 
|---|
| 546 | 
 | 
|---|
| 547 |     FileBuffer->CurrentLine++;  // skip to next line
 | 
|---|
| 548 |     FileBuffer->MapIonTypesInBuffer(NoAtoms);
 | 
|---|
| 549 |     for (int i=FileBuffer->CurrentLine; i<FileBuffer->NoLines;++i) {
 | 
|---|
| 550 |       LOG(4, FileBuffer->buffer[ FileBuffer->LineMapping[i] ]);
 | 
|---|
| 551 |     }
 | 
|---|
| 552 | 
 | 
|---|
| 553 |     std::vector<map<int, atom *> > AtomList(MaxTypes);
 | 
|---|
| 554 |     map<int, atom *> LinearList;
 | 
|---|
| 555 |     atom *neues = NULL;
 | 
|---|
| 556 |     Vector tempVector;
 | 
|---|
| 557 |     int _fixedion;
 | 
|---|
| 558 | 
 | 
|---|
| 559 |     typedef boost::tokenizer<boost::char_separator<char> >
 | 
|---|
| 560 |         tokenizer;
 | 
|---|
| 561 |     boost::char_separator<char> sep("\t ");
 | 
|---|
| 562 |     ConvertTo<double> toDouble;
 | 
|---|
| 563 |     ConvertTo<int> toInt;
 | 
|---|
| 564 | 
 | 
|---|
| 565 |     for (int i=0; i < MaxTypes; i++) {
 | 
|---|
| 566 |       for(int j=0;j<No[i];j++) {
 | 
|---|
| 567 |         int step = 0;
 | 
|---|
| 568 |         std::stringstream keyword_stream;
 | 
|---|
| 569 |         keyword_stream << "Ion_Type" << i+1 << "_" << j+1;
 | 
|---|
| 570 |         const std::string keyword = keyword_stream.str();
 | 
|---|
| 571 |         LOG(3, "INFO: Parsing for " << keyword << "." << std::endl);
 | 
|---|
| 572 |         while (true) {
 | 
|---|
| 573 |           const std::string line(FileBuffer->buffer[ FileBuffer->LineMapping[FileBuffer->CurrentLine] ]);
 | 
|---|
| 574 |           const std::string line_without_comment = line.substr(0,line.find("#"));
 | 
|---|
| 575 |           tokenizer tokens(line_without_comment, sep);
 | 
|---|
| 576 |           if (tokens.begin() != tokens.end()) {
 | 
|---|
| 577 |             tokenizer::iterator tok_iter = tokens.begin();
 | 
|---|
| 578 |             const std::string token = *tok_iter++;
 | 
|---|
| 579 |             if (token == keyword) {
 | 
|---|
| 580 |               LOG(3, "INFO: Found keyword " << keyword << " in line " << FileBuffer->CurrentLine << std::endl);
 | 
|---|
| 581 |               if (step == 0) {
 | 
|---|
| 582 |                 neues = World::getInstance().createAtom();
 | 
|---|
| 583 |                 AtomList[i][j] = neues;
 | 
|---|
| 584 |                 LOG(4, "Filling LinearList [ (FileBuffer->LineMapping[" << FileBuffer->CurrentLine << "]) = " << FileBuffer->LineMapping[FileBuffer->CurrentLine] << " with " << neues << endl);
 | 
|---|
| 585 |                 LinearList[ FileBuffer->LineMapping[FileBuffer->CurrentLine] ] = neues;
 | 
|---|
| 586 |                 neues->setType(elementhash[i]); // find element type
 | 
|---|
| 587 |               } else
 | 
|---|
| 588 |                 neues = AtomList[i][j];
 | 
|---|
| 589 | 
 | 
|---|
| 590 |               // count tokens
 | 
|---|
| 591 |               size_t tokens_size = 0;
 | 
|---|
| 592 |               for (tokenizer::iterator tokiter = tokens.begin(); tokiter != tokens.end(); ++tokiter)
 | 
|---|
| 593 |                 ++tokens_size;
 | 
|---|
| 594 |               LOG(3, "INFO: Line contains " << tokens_size << " tokens." << std::endl);
 | 
|---|
| 595 |               // and parse
 | 
|---|
| 596 |               tempVector.Zero();
 | 
|---|
| 597 |               if (tokens_size >= 5) { // only AtomicPosition and FixedIon
 | 
|---|
| 598 |                 for (int i=0;i<NDIM;++i)
 | 
|---|
| 599 |                   tempVector[i] = toDouble(*tok_iter++);
 | 
|---|
| 600 |                 neues->setPositionAtStep(step, tempVector);
 | 
|---|
| 601 |                 _fixedion = toInt(*tok_iter++);
 | 
|---|
| 602 |                 neues->setFixedIon(_fixedion == 1);
 | 
|---|
| 603 |                 LOG(3, "INFO: Parsing AtomicPosition " << tempVector << " and FixedIon " << _fixedion << "." << std::endl);
 | 
|---|
| 604 |               }
 | 
|---|
| 605 |               tempVector.Zero();
 | 
|---|
| 606 |               if (tokens_size >= 8) { // AtomicVelocity
 | 
|---|
| 607 |                 for (int i=0;i<NDIM;++i)
 | 
|---|
| 608 |                   tempVector[i] = toDouble(*tok_iter++);
 | 
|---|
| 609 |                 LOG(3, "INFO: Parsing AtomicVelocity " << tempVector << "." << std::endl);
 | 
|---|
| 610 |               }
 | 
|---|
| 611 |               neues->setAtomicVelocityAtStep(step, tempVector);
 | 
|---|
| 612 |               tempVector.Zero();
 | 
|---|
| 613 |               if (tokens_size >= 11) {  // AtomicForce
 | 
|---|
| 614 |                 LOG(3, "INFO: Parsing AtomicForce" << std::endl);
 | 
|---|
| 615 |                 for (int i=0;i<NDIM;++i)
 | 
|---|
| 616 |                   tempVector[i] = toDouble(*tok_iter++);
 | 
|---|
| 617 |               }
 | 
|---|
| 618 |               neues->setAtomicForceAtStep(step, tempVector);
 | 
|---|
| 619 |               std::stringstream output;
 | 
|---|
| 620 |               output << "Parsed position of step " << (step+1) << ": ";
 | 
|---|
| 621 |               output << neues->getPositionAtStep(step);          // next step
 | 
|---|
| 622 |               output << "\t";
 | 
|---|
| 623 |               output << (neues->getFixedIon() ? "true" : "false");
 | 
|---|
| 624 |               output << "\t";
 | 
|---|
| 625 |               output << neues->getAtomicVelocityAtStep(step);          // next step
 | 
|---|
| 626 |               output << "\t";
 | 
|---|
| 627 |               output << neues->getAtomicForceAtStep(step);          // next step
 | 
|---|
| 628 |               LOG(2, output.str());
 | 
|---|
| 629 | 
 | 
|---|
| 630 |               step++;
 | 
|---|
| 631 |             } else {
 | 
|---|
| 632 |               if ((repetition > step) || (repetition == -1))
 | 
|---|
| 633 |                 repetition = step;
 | 
|---|
| 634 |               break;
 | 
|---|
| 635 |             }
 | 
|---|
| 636 |           }
 | 
|---|
| 637 |           FileBuffer->CurrentLine++;
 | 
|---|
| 638 |         }
 | 
|---|
| 639 |       }
 | 
|---|
| 640 |     }
 | 
|---|
| 641 | 
 | 
|---|
| 642 |     if (repetition <= 1)  // if onyl one step, desactivate use of trajectories
 | 
|---|
| 643 |       mol->MDSteps = 0;
 | 
|---|
| 644 |     else {
 | 
|---|
| 645 |       LOG(0, "Found " << repetition << " trajectory step(s).");
 | 
|---|
| 646 |       mol->MDSteps = repetition;
 | 
|---|
| 647 |     }
 | 
|---|
| 648 | 
 | 
|---|
| 649 |     // put atoms into the molecule in their original order
 | 
|---|
| 650 |     for(map<int, atom*>::iterator runner = LinearList.begin(); runner != LinearList.end(); ++runner) {
 | 
|---|
| 651 |       mol->AddAtom(runner->second);
 | 
|---|
| 652 |     }
 | 
|---|
| 653 |   }
 | 
|---|
| 654 | }
 | 
|---|