Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • molecuilder/src/molecules.cpp

    r1f6efb r560995  
    6262  cell_size[0] = cell_size[2] = cell_size[5]= 20.;
    6363  cell_size[1] = cell_size[3] = cell_size[4]= 0.;
    64   strcpy(name,"none");
    6564};
    6665
     
    597596  cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;
    598597  return false;
    599 };
    600 
    601 /** Set molecule::name from the basename without suffix in the given \a *filename.
    602  * \param *filename filename
    603  */
    604 void molecule::SetNameFromFilename(char *filename)
    605 {
    606   int length = 0;
    607   char *molname = strrchr(filename, '/')+sizeof(char);  // search for filename without dirs
    608   char *endname = strrchr(filename, '.');
    609   if ((endname == NULL) || (endname < molname))
    610     length = strlen(molname);
    611   else
    612     length = strlen(molname) - strlen(endname);
    613   strncpy(name, molname, length);
    614598};
    615599
     
    10251009};
    10261010
     1011/** Evaluates the potential energy used for constrained molecular dynamics.
     1012 * \f$V_i^{con} = c^{bond} \cdot | r_{P(i)} - R_i | + sum_{i \neq j} C^{min} \cdot \frac{1}{C_{ij}} + C^{inj} \Bigl (1 - \theta \bigl (\prod_{i \neq j} (P(i) - P(j)) \bigr ) \Bigr )\f$
     1013 *     where the first term points to the target in minimum distance, the second is a penalty for trajectories lying too close to each other (\f$C_{ij}$ is minimum distance between
     1014 *     trajectories i and j) and the third term is a penalty for two atoms trying to each the same target point.
     1015 * Note that for the second term we have to solve the following linear system:
     1016 * \f$-c_1 \cdot n_1 + c_2 \cdot n_2 + C \cdot n_3 = - p_2 + p_1\f$, where \f$c_1\f$, \f$c_2\f$ and \f$C\f$ are constants,
     1017 * offset vector \f$p_1\f$ in direction \f$n_1\f$, offset vector \f$p_2\f$ in direction \f$n_2\f$,
     1018 * \f$n_3\f$ is the normal vector to both directions. \f$C\f$ would be the minimum distance between the two lines.
     1019 * \sa molecule::MinimiseConstrainedPotential(), molecule::VerletForceIntegration()
     1020 * \param *out output stream for debugging
     1021 * \param *PermutationMap gives target ptr for each atom, array of size molecule::AtomCount (this is "x" in \f$ V^{con}(x) \f$ )
     1022 * \param startstep start configuration (MDStep in molecule::trajectories)
     1023 * \param endstep end configuration (MDStep in molecule::trajectories)
     1024 * \param *constants constant in front of each term
     1025 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)
     1026 * \return potential energy
     1027 * \note This routine is scaling quadratically which is not optimal.
     1028 * \todo There's a bit double counting going on for the first time, bu nothing to worry really about.
     1029 */
     1030double molecule::ConstrainedPotential(ofstream *out, atom **PermutationMap, int startstep, int endstep, double *constants, bool IsAngstroem)
     1031{
     1032  double result = 0., tmp, Norm1, Norm2;
     1033  atom *Walker = NULL, *Runner = NULL, *Sprinter = NULL;
     1034  Vector trajectory1, trajectory2, normal, TestVector;
     1035  gsl_matrix *A = gsl_matrix_alloc(NDIM,NDIM);
     1036  gsl_vector *x = gsl_vector_alloc(NDIM);
     1037
     1038  // go through every atom
     1039  Walker = start;
     1040  while (Walker->next != end) {
     1041    Walker = Walker->next;
     1042    // first term: distance to target
     1043    Runner = PermutationMap[Walker->nr];   // find target point
     1044    tmp = (Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(endstep)));
     1045    tmp *= IsAngstroem ? 1. : 1./AtomicLengthToAngstroem;
     1046    result += constants[0] * tmp;
     1047    //*out << Verbose(4) << "Adding " << tmp*constants[0] << "." << endl;
     1048   
     1049    // second term: sum of distances to other trajectories
     1050    Runner = start;
     1051    while (Runner->next != end) {
     1052      Runner = Runner->next;
     1053      if (Runner == Walker) // hence, we only go up to the Walker, not beyond (similar to i=0; i<j; i++)
     1054        break;
     1055      // determine normalized trajectories direction vector (n1, n2)
     1056      Sprinter = PermutationMap[Walker->nr];   // find first target point
     1057      trajectory1.CopyVector(&Trajectories[Sprinter].R.at(endstep));
     1058      trajectory1.SubtractVector(&Trajectories[Walker].R.at(startstep));
     1059      trajectory1.Normalize();
     1060      Norm1 = trajectory1.Norm();
     1061      Sprinter = PermutationMap[Runner->nr];   // find second target point
     1062      trajectory2.CopyVector(&Trajectories[Sprinter].R.at(endstep));
     1063      trajectory2.SubtractVector(&Trajectories[Runner].R.at(startstep));
     1064      trajectory2.Normalize();
     1065      Norm2 = trajectory1.Norm();
     1066      // check whether either is zero()
     1067      if ((Norm1 < MYEPSILON) && (Norm2 < MYEPSILON)) {
     1068        tmp = Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(startstep));
     1069      } else if (Norm1 < MYEPSILON) {
     1070        Sprinter = PermutationMap[Walker->nr];   // find first target point
     1071        trajectory1.CopyVector(&Trajectories[Sprinter].R.at(endstep));  // copy first offset
     1072        trajectory1.SubtractVector(&Trajectories[Runner].R.at(startstep));  // subtract second offset
     1073        trajectory2.Scale( trajectory1.ScalarProduct(&trajectory2) ); // trajectory2 is scaled to unity, hence we don't need to divide by anything
     1074        trajectory1.SubtractVector(&trajectory2);   // project the part in norm direction away
     1075        tmp = trajectory1.Norm();  // remaining norm is distance
     1076      } else if (Norm2 < MYEPSILON) {
     1077        Sprinter = PermutationMap[Runner->nr];   // find second target point
     1078        trajectory2.CopyVector(&Trajectories[Sprinter].R.at(endstep));  // copy second offset
     1079        trajectory2.SubtractVector(&Trajectories[Walker].R.at(startstep));  // subtract first offset
     1080        trajectory1.Scale( trajectory2.ScalarProduct(&trajectory1) ); // trajectory1 is scaled to unity, hence we don't need to divide by anything
     1081        trajectory2.SubtractVector(&trajectory1);   // project the part in norm direction away
     1082        tmp = trajectory2.Norm();  // remaining norm is distance
     1083      } else if ((fabs(trajectory1.ScalarProduct(&trajectory2)/Norm1/Norm2) - 1.) < MYEPSILON) { // check whether they're linear dependent
     1084//        *out << Verbose(3) << "Both trajectories of " << *Walker << " and " << *Runner << " are linear dependent: ";
     1085//        *out << trajectory1;
     1086//        *out << " and ";
     1087//        *out << trajectory2;
     1088        tmp = Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(startstep));
     1089//        *out << " with distance " << tmp << "." << endl;
     1090      } else { // determine distance by finding minimum distance
     1091//        *out << Verbose(3) << "Both trajectories of " << *Walker << " and " << *Runner << " are linear independent ";
     1092//        *out << endl;
     1093//        *out << "First Trajectory: ";
     1094//        *out << trajectory1 << endl;
     1095//        *out << "Second Trajectory: ";
     1096//        *out << trajectory2 << endl;
     1097        // determine normal vector for both
     1098        normal.MakeNormalVector(&trajectory1, &trajectory2);
     1099        // print all vectors for debugging
     1100//        *out << "Normal vector in between: ";
     1101//        *out << normal << endl;
     1102        // setup matrix
     1103        for (int i=NDIM;i--;) {
     1104          gsl_matrix_set(A, 0, i, trajectory1.x[i]);
     1105          gsl_matrix_set(A, 1, i, trajectory2.x[i]);
     1106          gsl_matrix_set(A, 2, i, normal.x[i]);
     1107          gsl_vector_set(x,i, (Trajectories[Walker].R.at(startstep).x[i] - Trajectories[Runner].R.at(startstep).x[i]));
     1108        }
     1109        // solve the linear system by Householder transformations
     1110        gsl_linalg_HH_svx(A, x);
     1111        // distance from last component
     1112        tmp = gsl_vector_get(x,2);
     1113//        *out << " with distance " << tmp << "." << endl;
     1114        // test whether we really have the intersection (by checking on c_1 and c_2)
     1115        TestVector.CopyVector(&Trajectories[Runner].R.at(startstep));
     1116        trajectory2.Scale(gsl_vector_get(x,1));
     1117        TestVector.AddVector(&trajectory2);
     1118        normal.Scale(gsl_vector_get(x,2));
     1119        TestVector.AddVector(&normal);
     1120        TestVector.SubtractVector(&Trajectories[Walker].R.at(startstep));
     1121        trajectory1.Scale(gsl_vector_get(x,0));
     1122        TestVector.SubtractVector(&trajectory1);
     1123        if (TestVector.Norm() < MYEPSILON) {
     1124//          *out << Verbose(2) << "Test: ok.\tDistance of " << tmp << " is correct." << endl; 
     1125        } else {
     1126//          *out << Verbose(2) << "Test: failed.\tIntersection is off by ";
     1127//          *out << TestVector;
     1128//          *out << "." << endl; 
     1129        }
     1130      }
     1131      // add up
     1132      tmp *= IsAngstroem ? 1. : 1./AtomicLengthToAngstroem;
     1133      if (fabs(tmp) > MYEPSILON) {
     1134        result += constants[1] * 1./tmp;
     1135        //*out << Verbose(4) << "Adding " << 1./tmp*constants[1] << "." << endl;
     1136      }
     1137    }
     1138     
     1139    // third term: penalty for equal targets
     1140    Runner = start;
     1141    while (Runner->next != end) {
     1142      Runner = Runner->next;
     1143      if ((PermutationMap[Walker->nr] == PermutationMap[Runner->nr]) && (Walker->nr < Runner->nr)) {
     1144        Sprinter = PermutationMap[Walker->nr];
     1145//        *out << *Walker << " and " << *Runner << " are heading to the same target at ";
     1146//        *out << Trajectories[Sprinter].R.at(endstep);
     1147//        *out << ", penalting." << endl;
     1148        result += constants[2];
     1149        //*out << Verbose(4) << "Adding " << constants[2] << "." << endl;
     1150      }
     1151    }
     1152  }
     1153 
     1154  return result;
     1155};
     1156
     1157void PrintPermutationMap(ofstream *out, atom **PermutationMap, int Nr)
     1158{
     1159  stringstream zeile1, zeile2;
     1160  int *DoubleList = (int *) Malloc(Nr*sizeof(int), "PrintPermutationMap: *DoubleList");
     1161  int doubles = 0;
     1162  for (int i=0;i<Nr;i++)
     1163    DoubleList[i] = 0;
     1164  zeile1 << "PermutationMap: ";
     1165  zeile2 << "                ";
     1166  for (int i=0;i<Nr;i++) {
     1167    DoubleList[PermutationMap[i]->nr]++;
     1168    zeile1 << i << " ";
     1169    zeile2 << PermutationMap[i]->nr << " ";
     1170  }
     1171  for (int i=0;i<Nr;i++)
     1172    if (DoubleList[i] > 1)
     1173    doubles++;
     1174 // *out << "Found " << doubles << " Doubles." << endl;
     1175  Free((void **)&DoubleList, "PrintPermutationMap: *DoubleList");
     1176//  *out << zeile1.str() << endl << zeile2.str() << endl;
     1177};
     1178
     1179/** Minimises the extra potential for constrained molecular dynamics and gives forces and the constrained potential energy.
     1180 * We do the following:
     1181 *  -# Generate a distance list from all source to all target points
     1182 *  -# Sort this per source point
     1183 *  -# Take for each source point the target point with minimum distance, use this as initial permutation
     1184 *  -# check whether molecule::ConstrainedPotential() is greater than injective penalty
     1185 *     -# If so, we go through each source point, stepping down in the sorted target point distance list and re-checking potential.
     1186 *  -# Next, we only apply transformations that keep the injectivity of the permutations list.
     1187 *  -# Hence, for one source point we step down the ladder and seek the corresponding owner of this new target
     1188 *     point and try to change it for one with lesser distance, or for the next one with greater distance, but only
     1189 *     if this decreases the conditional potential.
     1190 *  -# finished.
     1191 *  -# Then, we calculate the forces by taking the spatial derivative, where we scale the potential to such a degree,
     1192 *     that the total force is always pointing in direction of the constraint force (ensuring that we move in the
     1193 *     right direction).
     1194 *  -# Finally, we calculate the potential energy and return.
     1195 * \param *out output stream for debugging
     1196 * \param **PermutationMap on return: mapping between the atom label of the initial and the final configuration
     1197 * \param startstep current MD step giving initial position between which and \a endstep we perform the constrained MD (as further steps are always concatenated)
     1198 * \param endstep step giving final position in constrained MD
     1199 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)
     1200 * \sa molecule::VerletForceIntegration()
     1201 * \return potential energy (and allocated **PermutationMap (array of molecule::AtomCount ^2)
     1202 * \todo The constrained potential's constants are set to fixed values right now, but they should scale based on checks of the system in order
     1203 *       to ensure they're properties (e.g. constants[2] always greater than the energy of the system).
     1204 * \bug this all is not O(N log N) but O(N^2)
     1205 */
     1206double molecule::MinimiseConstrainedPotential(ofstream *out, atom **&PermutationMap, int startstep, int endstep, bool IsAngstroem)
     1207{
     1208  double Potential, OldPotential, OlderPotential;
     1209  PermutationMap = (atom **) Malloc(AtomCount*sizeof(atom *), "molecule::MinimiseConstrainedPotential: **PermutationMap");
     1210  DistanceMap **DistanceList = (DistanceMap **) Malloc(AtomCount*sizeof(DistanceMap *), "molecule::MinimiseConstrainedPotential: **DistanceList");
     1211  DistanceMap::iterator *DistanceIterators = (DistanceMap::iterator *) Malloc(AtomCount*sizeof(DistanceMap::iterator), "molecule::MinimiseConstrainedPotential: *DistanceIterators");
     1212  int *DoubleList = (int *) Malloc(AtomCount*sizeof(int), "molecule::MinimiseConstrainedPotential: *DoubleList");
     1213  DistanceMap::iterator *StepList = (DistanceMap::iterator *) Malloc(AtomCount*sizeof(DistanceMap::iterator), "molecule::MinimiseConstrainedPotential: *StepList");
     1214  double constants[3];
     1215  int round;
     1216  atom *Walker = NULL, *Runner = NULL, *Sprinter = NULL;
     1217  DistanceMap::iterator Rider, Strider;
     1218 
     1219  /// Minimise the potential
     1220  // set Lagrange multiplier constants
     1221  constants[0] = 10.;
     1222  constants[1] = 1.;
     1223  constants[2] = 1e+7;    // just a huge penalty
     1224  // generate the distance list
     1225  *out << Verbose(1) << "Creating the distance list ... " << endl;
     1226  for (int i=AtomCount; i--;) {
     1227    DoubleList[i] = 0;  // stores for how many atoms in startstep this atom is a target in endstep
     1228    DistanceList[i] = new DistanceMap;    // is the distance sorted target list per atom
     1229    DistanceList[i]->clear();
     1230  }
     1231  *out << Verbose(1) << "Filling the distance list ... " << endl;
     1232  Walker = start;
     1233  while (Walker->next != end) {
     1234    Walker = Walker->next;
     1235    Runner = start;
     1236    while(Runner->next != end) {
     1237      Runner = Runner->next;
     1238      DistanceList[Walker->nr]->insert( DistancePair(Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(endstep)), Runner) );
     1239    }
     1240  }
     1241  // create the initial PermutationMap (source -> target)
     1242  Walker = start;
     1243  while (Walker->next != end) {
     1244    Walker = Walker->next;
     1245    StepList[Walker->nr] = DistanceList[Walker->nr]->begin();    // stores the step to the next iterator that could be a possible next target
     1246    PermutationMap[Walker->nr] = DistanceList[Walker->nr]->begin()->second;   // always pick target with the smallest distance
     1247    DoubleList[DistanceList[Walker->nr]->begin()->second->nr]++;            // increase this target's source count (>1? not injective)
     1248    DistanceIterators[Walker->nr] = DistanceList[Walker->nr]->begin();    // and remember which one we picked
     1249    *out << *Walker << " starts with distance " << DistanceList[Walker->nr]->begin()->first << "." << endl;
     1250  }
     1251  *out << Verbose(1) << "done." << endl;
     1252  // make the PermutationMap injective by checking whether we have a non-zero constants[2] term in it
     1253  *out << Verbose(1) << "Making the PermutationMap injective ... " << endl;
     1254  Walker = start;
     1255  DistanceMap::iterator NewBase;
     1256  OldPotential = fabs(ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem));
     1257  while ((OldPotential) > constants[2]) {
     1258    PrintPermutationMap(out, PermutationMap, AtomCount);
     1259    Walker = Walker->next;
     1260    if (Walker == end) // round-robin at the end
     1261      Walker = start->next;
     1262    if (DoubleList[DistanceIterators[Walker->nr]->second->nr] <= 1)  // no need to make those injective that aren't
     1263      continue;
     1264    // now, try finding a new one
     1265    NewBase = DistanceIterators[Walker->nr];  // store old base
     1266    do {
     1267      NewBase++;  // take next further distance in distance to targets list that's a target of no one
     1268    } while ((DoubleList[NewBase->second->nr] != 0) && (NewBase != DistanceList[Walker->nr]->end()));
     1269    if (NewBase != DistanceList[Walker->nr]->end()) {
     1270      PermutationMap[Walker->nr] = NewBase->second;
     1271      Potential = fabs(ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem));
     1272      if (Potential > OldPotential) { // undo
     1273        PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second;
     1274      } else {  // do
     1275        DoubleList[DistanceIterators[Walker->nr]->second->nr]--;  // decrease the old entry in the doubles list
     1276        DoubleList[NewBase->second->nr]++;    // increase the old entry in the doubles list
     1277        DistanceIterators[Walker->nr] = NewBase;
     1278        OldPotential = Potential;
     1279        *out << Verbose(3) << "Found a new permutation, new potential is " << OldPotential << "." << endl;
     1280      }
     1281    }
     1282  }
     1283  for (int i=AtomCount; i--;) // now each single entry in the DoubleList should be <=1
     1284    if (DoubleList[i] > 1) {
     1285      cerr << "Failed to create an injective PermutationMap!" << endl;
     1286      exit(1);
     1287    }
     1288  *out << Verbose(1) << "done." << endl;
     1289  Free((void **)&DoubleList, "molecule::MinimiseConstrainedPotential: *DoubleList");
     1290  // argument minimise the constrained potential in this injective PermutationMap
     1291  *out << Verbose(1) << "Argument minimising the PermutationMap, at current potential " << OldPotential << " ... " << endl;
     1292  OldPotential = 1e+10;
     1293  round = 0;
     1294  do {
     1295    *out << "Starting round " << ++round << " ... " << endl;
     1296    OlderPotential = OldPotential;
     1297    do {
     1298      Walker = start;
     1299      while (Walker->next != end) { // pick one
     1300        Walker = Walker->next;
     1301        PrintPermutationMap(out, PermutationMap, AtomCount);
     1302        Sprinter = DistanceIterators[Walker->nr]->second;   // store initial partner
     1303        Strider = DistanceIterators[Walker->nr];  //remember old iterator
     1304        DistanceIterators[Walker->nr] = StepList[Walker->nr]; 
     1305        if (DistanceIterators[Walker->nr] == DistanceList[Walker->nr]->end()) {// stop, before we run through the list and still on
     1306          DistanceIterators[Walker->nr] == DistanceList[Walker->nr]->begin();
     1307          break;
     1308        }
     1309        //*out << Verbose(2) << "Current Walker: " << *Walker << " with old/next candidate " << *Sprinter << "/" << *DistanceIterators[Walker->nr]->second << "." << endl;
     1310        // find source of the new target
     1311        Runner = start->next;
     1312        while(Runner != end) { // find the source whose toes we might be stepping on (Walker's new target should be in use by another already)
     1313          if (PermutationMap[Runner->nr] == DistanceIterators[Walker->nr]->second) {
     1314            //*out << Verbose(2) << "Found the corresponding owner " << *Runner << " to " << *PermutationMap[Runner->nr] << "." << endl;
     1315            break;
     1316          }
     1317          Runner = Runner->next;
     1318        }
     1319        if (Runner != end) { // we found the other source
     1320          // then look in its distance list for Sprinter
     1321          Rider = DistanceList[Runner->nr]->begin();
     1322          for (; Rider != DistanceList[Runner->nr]->end(); Rider++)
     1323            if (Rider->second == Sprinter)
     1324              break;
     1325          if (Rider != DistanceList[Runner->nr]->end()) { // if we have found one
     1326            //*out << Verbose(2) << "Current Other: " << *Runner << " with old/next candidate " << *PermutationMap[Runner->nr] << "/" << *Rider->second << "." << endl;
     1327            // exchange both
     1328            PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second; // put next farther distance into PermutationMap
     1329            PermutationMap[Runner->nr] = Sprinter;  // and hand the old target to its respective owner
     1330            PrintPermutationMap(out, PermutationMap, AtomCount);
     1331            // calculate the new potential
     1332            //*out << Verbose(2) << "Checking new potential ..." << endl;
     1333            Potential = ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem);
     1334            if (Potential > OldPotential) { // we made everything worse! Undo ...
     1335              //*out << Verbose(3) << "Nay, made the potential worse: " << Potential << " vs. " << OldPotential << "!" << endl;
     1336              //*out << Verbose(3) << "Setting " << *Runner << "'s source to " << *DistanceIterators[Runner->nr]->second << "." << endl;
     1337              // Undo for Runner (note, we haven't moved the iteration yet, we may use this)
     1338              PermutationMap[Runner->nr] = DistanceIterators[Runner->nr]->second;
     1339              // Undo for Walker
     1340              DistanceIterators[Walker->nr] = Strider;  // take next farther distance target
     1341              //*out << Verbose(3) << "Setting " << *Walker << "'s source to " << *DistanceIterators[Walker->nr]->second << "." << endl;
     1342              PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second;
     1343            } else {
     1344              DistanceIterators[Runner->nr] = Rider;  // if successful also move the pointer in the iterator list
     1345              *out << Verbose(3) << "Found a better permutation, new potential is " << Potential << " vs." << OldPotential << "." << endl;
     1346              OldPotential = Potential;
     1347            }
     1348            if (Potential > constants[2]) {
     1349              cerr << "ERROR: The two-step permutation procedure did not maintain injectivity!" << endl;
     1350              exit(255);
     1351            }
     1352            //*out << endl;
     1353          } else {
     1354            cerr << "ERROR: " << *Runner << " was not the owner of " << *Sprinter << "!" << endl;
     1355            exit(255);
     1356          }
     1357        } else {
     1358          PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second; // new target has no source!
     1359        }
     1360        StepList[Walker->nr]++; // take next farther distance target
     1361      }
     1362    } while (Walker->next != end);
     1363  } while ((OlderPotential - OldPotential) > 1e-3);
     1364  *out << Verbose(1) << "done." << endl;
     1365
     1366 
     1367  /// free memory and return with evaluated potential
     1368  for (int i=AtomCount; i--;)
     1369    DistanceList[i]->clear();
     1370  Free((void **)&DistanceList, "molecule::MinimiseConstrainedPotential: **DistanceList");
     1371  Free((void **)&DistanceIterators, "molecule::MinimiseConstrainedPotential: *DistanceIterators");
     1372  return ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem);
     1373};
     1374
     1375/** Evaluates the (distance-related part) of the constrained potential for the constrained forces.
     1376 * \param *out output stream for debugging
     1377 * \param startstep current MD step giving initial position between which and \a endstep we perform the constrained MD (as further steps are always concatenated)
     1378 * \param endstep step giving final position in constrained MD
     1379 * \param **PermutationMap mapping between the atom label of the initial and the final configuration
     1380 * \param *Force ForceMatrix containing force vectors from the external energy functional minimisation.
     1381 * \todo the constant for the constrained potential distance part is hard-coded independently of the hard-coded value in MinimiseConstrainedPotential()
     1382 */
     1383void molecule::EvaluateConstrainedForces(ofstream *out, int startstep, int endstep, atom **PermutationMap, ForceMatrix *Force)
     1384{
     1385  double constant = 10.;
     1386  atom *Walker = NULL, *Sprinter = NULL;
     1387 
     1388  /// evaluate forces (only the distance to target dependent part) with the final PermutationMap
     1389  *out << Verbose(1) << "Calculating forces and adding onto ForceMatrix ... " << endl;
     1390  Walker = start;
     1391  while (Walker->next != NULL) {
     1392    Walker = Walker->next;
     1393    Sprinter = PermutationMap[Walker->nr];
     1394    // set forces
     1395    for (int i=NDIM;i++;)
     1396      Force->Matrix[0][Walker->nr][5+i] += 2.*constant*sqrt(Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Sprinter].R.at(endstep)));
     1397  } 
     1398  *out << Verbose(1) << "done." << endl;
     1399};
     1400
     1401/** Performs a linear interpolation between two desired atomic configurations with a given number of steps.
     1402 * Note, step number is config::MaxOuterStep
     1403 * \param *out output stream for debugging
     1404 * \param startstep stating initial configuration in molecule::Trajectories
     1405 * \param endstep stating final configuration in molecule::Trajectories
     1406 * \param &config configuration structure
     1407 * \return true - success in writing step files, false - error writing files or only one step in molecule::Trajectories
     1408 */
     1409bool molecule::LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration)
     1410{
     1411  bool status = true;
     1412  int MaxSteps = configuration.MaxOuterStep;
     1413  MoleculeListClass *MoleculePerStep = new MoleculeListClass(MaxSteps+1, AtomCount);
     1414  // Get the Permutation Map by MinimiseConstrainedPotential
     1415  atom **PermutationMap = NULL;
     1416  atom *Walker = NULL, *Sprinter = NULL;
     1417  MinimiseConstrainedPotential(out, PermutationMap, startstep, endstep, configuration.GetIsAngstroem());
     1418
     1419  // check whether we have sufficient space in Trajectories for each atom
     1420  Walker = start;
     1421  while (Walker->next != end) {
     1422    Walker = Walker->next;
     1423    if (Trajectories[Walker].R.size() <= (unsigned int)(MaxSteps)) {
     1424      //cout << "Increasing size for trajectory array of " << keyword << " to " << (MaxSteps+1) << "." << endl;
     1425      Trajectories[Walker].R.resize(MaxSteps+1);
     1426      Trajectories[Walker].U.resize(MaxSteps+1);
     1427      Trajectories[Walker].F.resize(MaxSteps+1);
     1428    }
     1429  }
     1430  // push endstep to last one
     1431  Walker = start;
     1432  while (Walker->next != end) { // remove the endstep (is now the very last one)
     1433    Walker = Walker->next;
     1434    for (int n=NDIM;n--;) {
     1435      Trajectories[Walker].R.at(MaxSteps).x[n] = Trajectories[Walker].R.at(endstep).x[n];
     1436      Trajectories[Walker].U.at(MaxSteps).x[n] = Trajectories[Walker].U.at(endstep).x[n];
     1437      Trajectories[Walker].F.at(MaxSteps).x[n] = Trajectories[Walker].F.at(endstep).x[n];
     1438    }
     1439  }
     1440  endstep = MaxSteps;
     1441 
     1442  // go through all steps and add the molecular configuration to the list and to the Trajectories of \a this molecule
     1443  *out << Verbose(1) << "Filling intermediate " << MaxSteps << " steps with MDSteps of " << MDSteps << "." << endl;
     1444  for (int step = 0; step <= MaxSteps; step++) {
     1445    MoleculePerStep->ListOfMolecules[step] = new molecule(elemente);
     1446    Walker = start;
     1447    while (Walker->next != end) {
     1448      Walker = Walker->next;
     1449      // add to molecule list
     1450      Sprinter = MoleculePerStep->ListOfMolecules[step]->AddCopyAtom(Walker);
     1451      for (int n=NDIM;n--;) {
     1452        Sprinter->x.x[n] = Trajectories[Walker].R.at(startstep).x[n] + (Trajectories[PermutationMap[Walker->nr]].R.at(endstep).x[n] - Trajectories[Walker].R.at(startstep).x[n])*((double)step/(double)MaxSteps);
     1453        // add to Trajectories
     1454        //*out << Verbose(3) << step << ">=" << MDSteps-1 << endl;
     1455        if (step < MaxSteps) {
     1456          Trajectories[Walker].R.at(step).x[n] = Trajectories[Walker].R.at(startstep).x[n] + (Trajectories[PermutationMap[Walker->nr]].R.at(endstep).x[n] - Trajectories[Walker].R.at(startstep).x[n])*((double)step/(double)MaxSteps);
     1457          Trajectories[Walker].U.at(step).x[n] = 0.;
     1458          Trajectories[Walker].F.at(step).x[n] = 0.;
     1459        }
     1460      }
     1461    }
     1462  }
     1463  MDSteps = MaxSteps+1;   // otherwise new Trajectories' points aren't stored on save&exit
     1464 
     1465  // store the list to single step files
     1466  int *SortIndex = (int *) Malloc(AtomCount*sizeof(int), "molecule::LinearInterpolationBetweenConfiguration: *SortIndex");
     1467  for (int i=AtomCount; i--; )
     1468    SortIndex[i] = i;
     1469  status = MoleculePerStep->OutputConfigForListOfFragments(out, "ConstrainedStep", &configuration, SortIndex, false, false);
     1470 
     1471  // free and return
     1472  Free((void **)&PermutationMap, "molecule::MinimiseConstrainedPotential: *PermutationMap");
     1473  delete(MoleculePerStep);
     1474  return status;
     1475};
     1476
    10271477/** Parses nuclear forces from file and performs Verlet integration.
    10281478 * Note that we assume the parsed forces to be in atomic units (hence, if coordinates are in angstroem, we
    10291479 * have to transform them).
    10301480 * This adds a new MD step to the config file.
     1481 * \param *out output stream for debugging
    10311482 * \param *file filename
     1483 * \param config structure with config::Deltat, config::IsAngstroem, config::DoConstrained
    10321484 * \param delta_t time step width in atomic units
    10331485 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)
     1486 * \param DoConstrained whether we perform a constrained (>0, target step in molecule::trajectories) or unconstrained (0) molecular dynamics, \sa molecule::MinimiseConstrainedPotential()
    10341487 * \return true - file found and parsed, false - file not found or imparsable
    1035  */
    1036 bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem)
    1037 {
    1038   element *runner = elemente->start;
     1488 * \todo This is not yet checked if it is correctly working with DoConstrained set to true.
     1489 */
     1490bool molecule::VerletForceIntegration(ofstream *out, char *file, config &configuration)
     1491{
    10391492  atom *walker = NULL;
    1040   int AtomNo;
    10411493  ifstream input(file);
    10421494  string token;
    10431495  stringstream item;
    1044   double a, IonMass;
     1496  double IonMass, Vector[NDIM], ConstrainedPotentialEnergy, ActualTemp;
    10451497  ForceMatrix Force;
    1046   Vector tmpvector;
    10471498
    10481499  CountElements();  // make sure ElementsInMolecule is up to date
     
    10621513    }
    10631514    // correct Forces
    1064 //    for(int d=0;d<NDIM;d++)
    1065 //      tmpvector.x[d] = 0.;
    1066 //    for(int i=0;i<AtomCount;i++)
    1067 //      for(int d=0;d<NDIM;d++) {
    1068 //        tmpvector.x[d] += Force.Matrix[0][i][d+5];
    1069 //      }
    1070 //    for(int i=0;i<AtomCount;i++)
    1071 //      for(int d=0;d<NDIM;d++) {
    1072 //        Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount;
    1073 //      }
     1515    for(int d=0;d<NDIM;d++)
     1516      Vector[d] = 0.;
     1517    for(int i=0;i<AtomCount;i++)
     1518      for(int d=0;d<NDIM;d++) {
     1519        Vector[d] += Force.Matrix[0][i][d+5];
     1520      }
     1521    for(int i=0;i<AtomCount;i++)
     1522      for(int d=0;d<NDIM;d++) {
     1523        Force.Matrix[0][i][d+5] -= Vector[d]/(double)AtomCount;
     1524      }
     1525    // solve a constrained potential if we are meant to
     1526    if (configuration.DoConstrainedMD) {
     1527      // calculate forces and potential
     1528      atom **PermutationMap = NULL;
     1529      ConstrainedPotentialEnergy = MinimiseConstrainedPotential(out, PermutationMap,configuration.DoConstrainedMD, 0, configuration.GetIsAngstroem());
     1530      EvaluateConstrainedForces(out, configuration.DoConstrainedMD, 0, PermutationMap, &Force);
     1531      Free((void **)&PermutationMap, "molecule::MinimiseConstrainedPotential: *PermutationMap");
     1532    }
     1533   
    10741534    // and perform Verlet integration for each atom with position, velocity and force vector
    1075     runner = elemente->start;
    1076     while (runner->next != elemente->end) { // go through every element
    1077       runner = runner->next;
    1078       IonMass = runner->mass;
    1079       a = delta_t*0.5/IonMass;        // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a
    1080       if (ElementsInMolecule[runner->Z]) { // if this element got atoms
    1081         AtomNo = 0;
     1535    walker = start;
     1536    while (walker->next != end) { // go through every atom of this element
     1537      walker = walker->next;
     1538      //a = configuration.Deltat*0.5/walker->type->mass;        // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a
     1539      // check size of vectors
     1540      if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {
     1541        //out << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;
     1542        Trajectories[walker].R.resize(MDSteps+10);
     1543        Trajectories[walker].U.resize(MDSteps+10);
     1544        Trajectories[walker].F.resize(MDSteps+10);
     1545      }
     1546     
     1547      // Update R (and F)
     1548      for (int d=0; d<NDIM; d++) {
     1549        Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][walker->nr][d+5]*(configuration.GetIsAngstroem() ? AtomicLengthToAngstroem : 1.);
     1550        Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];
     1551        Trajectories[walker].R.at(MDSteps).x[d] += configuration.Deltat*(Trajectories[walker].U.at(MDSteps-1).x[d]);     // s(t) = s(0) + v * deltat + 1/2 a * deltat^2
     1552        Trajectories[walker].R.at(MDSteps).x[d] += 0.5*configuration.Deltat*configuration.Deltat*(Trajectories[walker].F.at(MDSteps).x[d]/walker->type->mass);     // F = m * a and s = 0.5 * F/m * t^2 = F * a * t
     1553      }
     1554      // Update U
     1555      for (int d=0; d<NDIM; d++) {
     1556        Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];
     1557        Trajectories[walker].U.at(MDSteps).x[d] += configuration.Deltat * (Trajectories[walker].F.at(MDSteps).x[d]+Trajectories[walker].F.at(MDSteps-1).x[d]/walker->type->mass); // v = F/m * t
     1558      }
     1559//      out << "Integrated position&velocity of step " << (MDSteps) << ": (";
     1560//      for (int d=0;d<NDIM;d++)
     1561//        out << Trajectories[walker].R.at(MDSteps).x[d] << " ";          // next step
     1562//      out << ")\t(";
     1563//      for (int d=0;d<NDIM;d++)
     1564//        cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";          // next step
     1565//      out << ")" << endl;
     1566            // next atom
     1567    }
     1568  }
     1569  // correct velocities (rather momenta) so that center of mass remains motionless
     1570  for(int d=0;d<NDIM;d++)
     1571    Vector[d] = 0.;
     1572  IonMass = 0.;
     1573  walker = start;
     1574  while (walker->next != end) { // go through every atom
     1575    walker = walker->next;
     1576    IonMass += walker->type->mass;  // sum up total mass
     1577    for(int d=0;d<NDIM;d++) {
     1578      Vector[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;
     1579    }
     1580  }
     1581  // correct velocities (rather momenta) so that center of mass remains motionless
     1582  for(int d=0;d<NDIM;d++)
     1583    Vector[d] /= IonMass;
     1584  ActualTemp = 0.;
     1585  walker = start;
     1586  while (walker->next != end) { // go through every atom of this element
     1587    walker = walker->next;
     1588    for(int d=0;d<NDIM;d++) {
     1589      Trajectories[walker].U.at(MDSteps).x[d] -= Vector[d];
     1590      ActualTemp += 0.5 * walker->type->mass * Trajectories[walker].U.at(MDSteps).x[d] * Trajectories[walker].U.at(MDSteps).x[d];
     1591    }
     1592  }
     1593  Thermostats(configuration, ActualTemp, Berendsen);
     1594  MDSteps++;
     1595
     1596
     1597  // exit
     1598  return true;
     1599};
     1600
     1601/** Implementation of various thermostats.
     1602 * All these thermostats apply an additional force which has the following forms:
     1603 * -# Woodcock
     1604 *  \f$p_i \rightarrow \sqrt{\frac{T_0}{T}} \cdot p_i\f$
     1605 * -# Gaussian
     1606 *  \f$ \frac{ \sum_i \frac{p_i}{m_i} \frac{\partial V}{\partial q_i}} {\sum_i \frac{p^2_i}{m_i}} \cdot p_i\f$
     1607 * -# Langevin
     1608 *  \f$p_{i,n} \rightarrow \sqrt{1-\alpha^2} p_{i,0} + \alpha p_r\f$ 
     1609 * -# Berendsen
     1610 *  \f$p_i \rightarrow \left [ 1+ \frac{\delta t}{\tau_T} \left ( \frac{T_0}{T} \right ) \right ]^{\frac{1}{2}} \cdot p_i\f$
     1611 * -# Nose-Hoover
     1612 *  \f$\zeta p_i \f$ with \f$\frac{\partial \zeta}{\partial t} = \frac{1}{M_s} \left ( \sum^N_{i=1} \frac{p_i^2}{m_i} - g k_B T \right )\f$
     1613 * These Thermostats either simply rescale the velocities, thus this function should be called after ion velocities have been updated, and/or
     1614 * have a constraint force acting additionally on the ions. In the latter case, the ion speeds have to be modified
     1615 * belatedly and the constraint force set.
     1616 * \param *P Problem at hand
     1617 * \param i which of the thermostats to take: 0 - none, 1 - Woodcock, 2 - Gaussian, 3 - Langevin, 4 - Berendsen, 5 - Nose-Hoover
     1618 * \sa InitThermostat()
     1619 */
     1620void molecule::Thermostats(config &configuration, double ActualTemp, int Thermostat)
     1621{
     1622  double ekin = 0.;
     1623  double E = 0., G = 0.;
     1624  double delta_alpha = 0.;
     1625  double ScaleTempFactor;
     1626  double sigma;
     1627  double IonMass;
     1628  int d;
     1629  gsl_rng * r;
     1630  const gsl_rng_type * T;
     1631  double *U = NULL, *F = NULL, FConstraint[NDIM];
     1632  atom *walker = NULL;
     1633 
     1634  // calculate scale configuration
     1635  ScaleTempFactor = configuration.TargetTemp/ActualTemp;
     1636   
     1637  // differentating between the various thermostats
     1638  switch(Thermostat) {
     1639     case None:
     1640      cout << Verbose(2) <<  "Applying no thermostat..." << endl;
     1641      break;
     1642     case Woodcock:
     1643      if ((configuration.ScaleTempStep > 0) && ((MDSteps-1) % configuration.ScaleTempStep == 0)) {
     1644        cout << Verbose(2) <<  "Applying Woodcock thermostat..." << endl;
    10821645        walker = start;
    10831646        while (walker->next != end) { // go through every atom of this element
    10841647          walker = walker->next;
    1085           if (walker->type == runner) { // if this atom fits to element
    1086             // check size of vectors
    1087             if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {
    1088               //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;
    1089               Trajectories[walker].R.resize(MDSteps+10);
    1090               Trajectories[walker].U.resize(MDSteps+10);
    1091               Trajectories[walker].F.resize(MDSteps+10);
     1648          IonMass = walker->type->mass;
     1649          U = Trajectories[walker].U.at(MDSteps).x;
     1650          if (walker->FixedIon == 0) // even FixedIon moves, only not by other's forces
     1651            for (d=0; d<NDIM; d++) {
     1652              U[d] *= sqrt(ScaleTempFactor);
     1653              ekin += 0.5*IonMass * U[d]*U[d];
    10921654            }
    1093             // 1. calculate x(t+\delta t)
    1094             for (int d=0; d<NDIM; d++) {
    1095               Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5];
    1096               Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];
    1097               Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]);
    1098               Trajectories[walker].R.at(MDSteps).x[d] += 0.5*delta_t*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d])/IonMass;    // F = m * a and s = 0.5 * F/m * t^2 = F * a * t
     1655        }
     1656      }
     1657      break;
     1658     case Gaussian:
     1659      cout << Verbose(2) <<  "Applying Gaussian thermostat..." << endl;
     1660      walker = start;
     1661      while (walker->next != end) { // go through every atom of this element
     1662        walker = walker->next;
     1663        IonMass = walker->type->mass;
     1664        U = Trajectories[walker].U.at(MDSteps).x;
     1665        F = Trajectories[walker].F.at(MDSteps).x;
     1666        if (walker->FixedIon == 0) // even FixedIon moves, only not by other's forces
     1667          for (d=0; d<NDIM; d++) {
     1668            G += U[d] * F[d];
     1669            E += U[d]*U[d]*IonMass;
     1670          }
     1671      }
     1672      cout << Verbose(1) << "Gaussian Least Constraint constant is " << G/E << "." << endl;
     1673      walker = start;
     1674      while (walker->next != end) { // go through every atom of this element
     1675        walker = walker->next;
     1676        IonMass = walker->type->mass;
     1677        U = Trajectories[walker].U.at(MDSteps).x;
     1678        F = Trajectories[walker].F.at(MDSteps).x;
     1679        if (walker->FixedIon == 0) // even FixedIon moves, only not by other's forces
     1680          for (d=0; d<NDIM; d++) {
     1681            FConstraint[d] = (G/E) * (U[d]*IonMass);
     1682            U[d] += configuration.Deltat/IonMass * (FConstraint[d]);
     1683            ekin += IonMass * U[d]*U[d];
     1684          }
     1685      }
     1686      break;
     1687     case Langevin:
     1688      cout << Verbose(2) <<  "Applying Langevin thermostat..." << endl;
     1689      // init random number generator
     1690      gsl_rng_env_setup();
     1691      T = gsl_rng_default;
     1692      r = gsl_rng_alloc (T);
     1693      // Go through each ion
     1694      walker = start;
     1695      while (walker->next != end) { // go through every atom of this element
     1696        walker = walker->next;
     1697        IonMass = walker->type->mass;
     1698        sigma  = sqrt(configuration.TargetTemp/IonMass); // sigma = (k_b T)/m (Hartree/atomicmass = atomiclength/atomictime)
     1699        U = Trajectories[walker].U.at(MDSteps).x;
     1700        F = Trajectories[walker].F.at(MDSteps).x;
     1701        if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces
     1702          // throw a dice to determine whether it gets hit by a heat bath particle
     1703          if (((((rand()/(double)RAND_MAX))*configuration.TempFrequency) < 1.)) { 
     1704            cout << Verbose(3) << "Particle " << *walker << " was hit (sigma " << sigma << "): " << sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]) << " -> ";
     1705            // pick three random numbers from a Boltzmann distribution around the desired temperature T for each momenta axis
     1706            for (d=0; d<NDIM; d++) {
     1707              U[d] = gsl_ran_gaussian (r, sigma);
    10991708            }
    1100             // 2. Calculate v(t+\delta t)
    1101             for (int d=0; d<NDIM; d++) {
    1102               Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];
    1103               Trajectories[walker].U.at(MDSteps).x[d] += 0.5*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d]+Trajectories[walker].F.at(MDSteps).x[d])/IonMass;
    1104             }
    1105 //            cout << "Integrated position&velocity of step " << (MDSteps) << ": (";
    1106 //            for (int d=0;d<NDIM;d++)
    1107 //              cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";          // next step
    1108 //            cout << ")\t(";
    1109 //            for (int d=0;d<NDIM;d++)
    1110 //              cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";          // next step
    1111 //            cout << ")" << endl;
    1112             // next atom
    1113             AtomNo++;
     1709            cout << sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]) << endl;
     1710          }
     1711          for (d=0; d<NDIM; d++)
     1712            ekin += 0.5*IonMass * U[d]*U[d];
     1713        }
     1714      }
     1715      break;
     1716     case Berendsen:
     1717      cout << Verbose(2) <<  "Applying Berendsen-VanGunsteren thermostat..." << endl;
     1718      walker = start;
     1719      while (walker->next != end) { // go through every atom of this element
     1720        walker = walker->next;
     1721        IonMass = walker->type->mass;
     1722        U = Trajectories[walker].U.at(MDSteps).x;
     1723        F = Trajectories[walker].F.at(MDSteps).x;
     1724        if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces
     1725          for (d=0; d<NDIM; d++) {
     1726            U[d] *= sqrt(1+(configuration.Deltat/configuration.TempFrequency)*(ScaleTempFactor-1));
     1727            ekin += 0.5*IonMass * U[d]*U[d];
    11141728          }
    11151729        }
    11161730      }
    1117     }
    1118   }
    1119 //  // correct velocities (rather momenta) so that center of mass remains motionless
    1120 //  tmpvector.zero()
    1121 //  IonMass = 0.;
    1122 //  walker = start;
    1123 //  while (walker->next != end) { // go through every atom
    1124 //    walker = walker->next;
    1125 //    IonMass += walker->type->mass;  // sum up total mass
    1126 //    for(int d=0;d<NDIM;d++) {
    1127 //      tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;
    1128 //    }
    1129 //  }
    1130 //  walker = start;
    1131 //  while (walker->next != end) { // go through every atom of this element
    1132 //    walker = walker->next;
    1133 //    for(int d=0;d<NDIM;d++) {
    1134 //      Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass;
    1135 //    }
    1136 //  }
    1137   MDSteps++;
    1138 
    1139 
    1140   // exit
    1141   return true;
    1142 };
    1143 
    1144 /** Align all atoms in such a manner that given vector \a *n is along z axis.
     1731      break;
     1732     case NoseHoover:
     1733      cout << Verbose(2) <<  "Applying Nose-Hoover thermostat..." << endl;
     1734      // dynamically evolve alpha (the additional degree of freedom)
     1735      delta_alpha = 0.;
     1736      walker = start;
     1737      while (walker->next != end) { // go through every atom of this element
     1738        walker = walker->next;
     1739        IonMass = walker->type->mass;
     1740        U = Trajectories[walker].U.at(MDSteps).x;
     1741        if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces
     1742          for (d=0; d<NDIM; d++) {
     1743            delta_alpha += U[d]*U[d]*IonMass;
     1744          }
     1745        }
     1746      }
     1747      delta_alpha = (delta_alpha - (3.*AtomCount+1.) * configuration.TargetTemp)/(configuration.HooverMass*Units2Electronmass);
     1748      configuration.alpha += delta_alpha*configuration.Deltat;
     1749      cout << Verbose(3) << "alpha = " << delta_alpha << " * " << configuration.Deltat << " = " << configuration.alpha << "." << endl;
     1750      // apply updated alpha as additional force
     1751      walker = start;
     1752      while (walker->next != end) { // go through every atom of this element
     1753        walker = walker->next;
     1754        IonMass = walker->type->mass;
     1755        U = Trajectories[walker].U.at(MDSteps).x;
     1756        if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces
     1757          for (d=0; d<NDIM; d++) {
     1758              FConstraint[d] = - configuration.alpha * (U[d] * IonMass);
     1759              U[d] += configuration.Deltat/IonMass * (FConstraint[d]);
     1760              ekin += (0.5*IonMass) * U[d]*U[d];
     1761            }
     1762        }
     1763      }
     1764      break;
     1765  }   
     1766  cout << Verbose(1) << "Kinetic energy is " << ekin << "." << endl;
     1767};
     1768
     1769/** Align all atoms in such a manner that given vector \a *n is along z axis.
    11451770 * \param n[] alignment vector.
    11461771 */
     
    12031828};
    12041829
    1205 /** Removes atom from molecule list and deletes it.
     1830/** Removes atom from molecule list.
    12061831 * \param *pointer atom to be removed
    12071832 * \return true - succeeded, false - atom not found in list
     
    12091834bool molecule::RemoveAtom(atom *pointer)
    12101835{
    1211   if (ElementsInMolecule[pointer->type->Z] != 0)  { // this would indicate an error
     1836  if (ElementsInMolecule[pointer->type->Z] != 0)  // this would indicate an error
    12121837    ElementsInMolecule[pointer->type->Z]--;  // decrease number of atom of this element
    1213     AtomCount--;
    1214   } else
     1838  else
    12151839    cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl;
    12161840  if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
     
    12181842  Trajectories.erase(pointer);
    12191843  return remove(pointer, start, end);
    1220 };
    1221 
    1222 /** Removes atom from molecule list, but does not delete it.
    1223  * \param *pointer atom to be removed
    1224  * \return true - succeeded, false - atom not found in list
    1225  */
    1226 bool molecule::UnlinkAtom(atom *pointer)
    1227 {
    1228   if (pointer == NULL)
    1229     return false;
    1230   if (ElementsInMolecule[pointer->type->Z] != 0)  // this would indicate an error
    1231     ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element
    1232   else
    1233     cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl;
    1234   if (ElementsInMolecule[pointer->type->Z] == 0)  // was last atom of this element?
    1235     ElementCount--;
    1236   Trajectories.erase(pointer);
    1237   unlink(pointer);
    1238   return true;
    12391844};
    12401845
     
    17632368            };
    17642369            AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.
    1765 
     2370           
    17662371          }
    17672372
     
    18002405  Vector x;
    18012406  int FalseBondDegree = 0;
    1802 
     2407 
    18032408  BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem);
    18042409  *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl;
     
    18792484                        //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl;
    18802485                        /// \todo periodic check is missing here!
    1881                         //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;
     2486                        //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistance(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;
    18822487                        MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius;
    18832488                        MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem;
    18842489                        MaxDistance = MinDistance + BONDTHRESHOLD;
    18852490                        MinDistance -= BONDTHRESHOLD;
    1886                         distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size);
     2491                        distance =   OtherWalker->x.PeriodicDistance(&(Walker->x), cell_size);
    18872492                        if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller
    1888                           //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl;
     2493                          //*out << Verbose(0) << "Adding Bond between " << *Walker << " and " << *OtherWalker << "." << endl;
    18892494                          AddBond(Walker->father, OtherWalker->father, 1);  // also increases molecule::BondCount
     2495                          BondCount++;
    18902496                        } else {
    18912497                          //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl;
     
    19582564      *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl;
    19592565    *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl;
    1960 
     2566   
    19612567    // output bonds for debugging (if bond chain list was correctly installed)
    19622568    *out << Verbose(1) << endl << "From contents of bond chain list:";
     
    21952801    ColorList[i] = white;
    21962802  }
    2197 
     2803 
    21982804  *out << Verbose(1) << "Back edge list - ";
    21992805  BackEdgeStack->Output(out);
     
    25653171          cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl;
    25663172        }
     3173        //FragmentList->ListOfMolecules[NumberOfFragments++] = StoreFragmentFromKeySet(out, CurrentSet, IsAngstroem);
    25673174      }
    25683175    }
     
    30433650  while (MolecularWalker->next != NULL) {
    30443651    MolecularWalker = MolecularWalker->next;
     3652    *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;
    30453653    LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount);
    30463654//    // check the list of local atoms for debugging
     
    30583666    delete(LocalBackEdgeStack);
    30593667  }
    3060 
     3668 
    30613669  // ===== 3. if structure still valid, parse key set file and others =====
    30623670  FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);
     
    30643672  // ===== 4. check globally whether there's something to do actually (first adaptivity check)
    30653673  FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath);
    3066 
    3067   // =================================== Begin of FRAGMENTATION ===============================
    3068   // ===== 6a. assign each keyset to its respective subgraph =====
     3674 
     3675  // =================================== Begin of FRAGMENTATION =============================== 
     3676  // ===== 6a. assign each keyset to its respective subgraph ===== 
    30693677  Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true);
    30703678
     
    31013709  delete(ParsedFragmentList);
    31023710  delete[](MinimumRingSize);
    3103 
     3711 
    31043712
    31053713  // ==================================== End of FRAGMENTATION ============================================
     
    31233731  //if (FragmentationToDo) {    // we should always store the fragments again as coordination might have changed slightly without changing bond structure
    31243732    // allocate memory for the pointer array and transmorph graphs into full molecular fragments
    3125     BondFragments = new MoleculeListClass();
     3733    BondFragments = new MoleculeListClass(TotalGraph.size(), AtomCount);
    31263734    int k=0;
    31273735    for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) {
    31283736      KeySet test = (*runner).first;
    31293737      *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl;
    3130       BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration));
     3738      BondFragments->ListOfMolecules[k] = StoreFragmentFromKeySet(out, test, configuration);
    31313739      k++;
    31323740    }
    3133     *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl;
     3741    *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl;
    31343742
    31353743    // ===== 9. Save fragments' configuration and keyset files et al to disk ===
    3136     if (BondFragments->ListOfMolecules.size() != 0) {
     3744    if (BondFragments->NumberOfMolecules != 0) {
    31373745      // create the SortIndex from BFS labels to order in the config file
    31383746      CreateMappingLabelsToConfigSequence(out, SortIndex);
    31393747
    3140       *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl;
    3141       if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex))
     3748      *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl;
     3749      if (BondFragments->OutputConfigForListOfFragments(out, FRAGMENTPREFIX, configuration, SortIndex, true, true))
    31423750        *out << Verbose(1) << "All configs written." << endl;
    31433751      else
     
    31943802  atom *Walker = NULL, *OtherAtom = NULL;
    31953803  ReferenceStack->Push(Binder);
    3196 
     3804 
    31973805  do {  // go through all bonds and push local ones
    31983806    Walker = ListOfLocalAtoms[Binder->leftatom->nr];  // get one atom in the reference molecule
     
    32013809        OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    32023810        if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond
    3203           LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);
    3204           *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl;
     3811            LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);
     3812                *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl;
    32053813          break;
    32063814        }
     
    32103818    ReferenceStack->Push(Binder);
    32113819  } while (FirstBond != Binder);
    3212 
     3820 
    32133821  return status;
    32143822};
     
    33553963  Walker = start;
    33563964  while (Walker->next != end) {
    3357     Walker = Walker->next;
     3965    Walker = Walker->next; 
    33583966    *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: ";
    33593967    TotalDegree = 0;
     
    36644272};
    36654273
     4274/** Creates \a MoleculeListClass of all unique fragments of the \a molecule containing \a Order atoms or vertices.
     4275 * The picture to have in mind is that of a DFS "snake" of a certain length \a Order, i.e. as in the infamous
     4276 * computer game, that winds through the connected graph representing the molecule. Color (white,
     4277 * lightgray, darkgray, black) indicates whether a vertex has been discovered so far or not. Labels will help in
     4278 * creating only unique fragments and not additional ones with vertices simply in different sequence.
     4279 * The Predecessor is always the one that came before in discovering, needed on backstepping. And
     4280 * finally, the ShortestPath is needed for removing vertices from the snake stack during the back-
     4281 * stepping.
     4282 * \param *out output stream for debugging
     4283 * \param Order number of atoms in each fragment
     4284 * \param *configuration configuration for writing config files for each fragment
     4285 * \return List of all unique fragments with \a Order atoms
     4286 */
     4287/*
     4288MoleculeListClass * molecule::CreateListOfUniqueFragmentsOfOrder(ofstream *out, int Order, config *configuration)
     4289{
     4290  atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList");
     4291  int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");
     4292  int *Labels = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels");
     4293  enum Shading *ColorVertexList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList");
     4294  enum Shading *ColorEdgeList = (enum Shading *) Malloc(sizeof(enum Shading)*BondCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorBondList");
     4295  StackClass<atom *> *RootStack = new StackClass<atom *>(AtomCount);
     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
     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!
     4298  MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL;
     4299  MoleculeListClass *FragmentList = NULL;
     4300  atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL;
     4301  bond *Binder = NULL;
     4302  int RunningIndex = 0, FragmentCounter = 0;
     4303
     4304  *out << Verbose(1) << "Begin of CreateListOfUniqueFragmentsOfOrder." << endl;
     4305
     4306  // reset parent list
     4307  *out << Verbose(3) << "Resetting labels, parent, predecessor, color and shortest path lists." << endl;
     4308  for (int i=0;i<AtomCount;i++) { // reset all atom labels
     4309    // initialise each vertex as white with no predecessor, empty queue, color lightgray, not labelled, no sons
     4310    Labels[i] = -1;
     4311    SonList[i] = NULL;
     4312    PredecessorList[i] = NULL;
     4313    ColorVertexList[i] = white;
     4314    ShortestPathList[i] = -1;
     4315  }
     4316  for (int i=0;i<BondCount;i++)
     4317    ColorEdgeList[i] = white;
     4318  RootStack->ClearStack();  // clearstack and push first atom if exists
     4319  TouchedStack->ClearStack();
     4320  Walker = start->next;
     4321  while ((Walker != end)
     4322#ifdef ADDHYDROGEN
     4323   && (Walker->type->Z == 1)
     4324#endif
     4325                        ) { // search for first non-hydrogen atom
     4326    *out << Verbose(4) << "Current Root candidate is " << Walker->Name << "." << endl;
     4327    Walker = Walker->next;
     4328  }
     4329  if (Walker != end)
     4330    RootStack->Push(Walker);
     4331  else
     4332    *out << Verbose(0) << "ERROR: Could not find an appropriate Root atom!" << endl;
     4333  *out << Verbose(3) << "Root " << Walker->Name << " is on AtomStack, beginning loop through all vertices ..." << endl;
     4334
     4335  ///// OUTER LOOP ////////////
     4336  while (!RootStack->IsEmpty()) {
     4337    // get new root vertex from atom stack
     4338    Root = RootStack->PopFirst();
     4339    ShortestPathList[Root->nr] = 0;
     4340    if (Labels[Root->nr] == -1)
     4341      Labels[Root->nr] = RunningIndex++; // prevent it from getting again on AtomStack
     4342    PredecessorList[Root->nr] = Root;
     4343    TouchedStack->Push(Root);
     4344    *out << Verbose(0) << "Root for this loop is: " << Root->Name << ".\n";
     4345
     4346    // clear snake stack
     4347    SnakeStack->ClearStack();
     4348    //SnakeStack->TestImplementation(out, start->next);
     4349
     4350    ///// INNER LOOP ////////////
     4351    // Problems:
     4352    // - what about cyclic bonds?
     4353    Walker = Root;
     4354    do {
     4355      *out << Verbose(1) << "Current Walker is: " << Walker->Name;
     4356      // initial setting of the new Walker: label, color, shortest path and put on stacks
     4357      if (Labels[Walker->nr] == -1)  {  // give atom a unique, monotonely increasing number
     4358        Labels[Walker->nr] = RunningIndex++;
     4359        RootStack->Push(Walker);
     4360      }
     4361      *out << ", has label " << Labels[Walker->nr];
     4362      if ((ColorVertexList[Walker->nr] == white) || ((Binder != NULL) && (ColorEdgeList[Binder->nr] == white))) {  // color it if newly discovered and push on stacks (and if within reach!)
     4363        if ((Binder != NULL) && (ColorEdgeList[Binder->nr] == white)) {
     4364          // Binder ought to be set still from last neighbour search
     4365          *out << ", coloring bond " << *Binder << " black";
     4366          ColorEdgeList[Binder->nr] = black; // mark this bond as used
     4367        }
     4368        if (ShortestPathList[Walker->nr] == -1) {
     4369          ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1;
     4370          TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed
     4371        }
     4372        if ((ShortestPathList[Walker->nr] < Order) && (ColorVertexList[Walker->nr] != darkgray)) {  // if not already on snake stack
     4373          SnakeStack->Push(Walker);
     4374          ColorVertexList[Walker->nr] = darkgray; // mark as dark gray of on snake stack
     4375        }
     4376      }
     4377      *out << ", SP of " << ShortestPathList[Walker->nr]  << " and its color is " << GetColor(ColorVertexList[Walker->nr]) << "." << endl;
     4378
     4379      // then check the stack for a newly stumbled upon fragment
     4380      if (SnakeStack->ItemCount() == Order) { // is stack full?
     4381        // store the fragment if it is one and get a removal candidate
     4382        Removal = StoreFragmentFromStack(out, Root, Walker, Leaflet, SnakeStack, ShortestPathList, SonList, Labels, &FragmentCounter, configuration);
     4383        // remove the candidate if one was found
     4384        if (Removal != NULL) {
     4385          *out << Verbose(2) << "Removing item " << Removal->Name << " with SP of " << ShortestPathList[Removal->nr] << " from snake stack." << endl;
     4386          SnakeStack->RemoveItem(Removal);
     4387          ColorVertexList[Removal->nr] = lightgray; // return back to not on snake stack but explored marking
     4388          if (Walker == Removal) { // if the current atom is to be removed, we also have to take a step back
     4389            Walker = PredecessorList[Removal->nr];
     4390            *out << Verbose(2) << "Stepping back to " << Walker->Name << "." << endl;
     4391          }
     4392        }
     4393      } else
     4394        Removal = NULL;
     4395
     4396      // finally, look for a white neighbour as the next Walker
     4397      Binder = NULL;
     4398      if ((Removal == NULL) || (Walker != PredecessorList[Removal->nr])) {  // don't look, if a new walker has been set above
     4399        *out << Verbose(2) << "Snake has currently " << SnakeStack->ItemCount() << " item(s)." << endl;
     4400        OtherAtom = NULL; // this is actually not needed, every atom has at least one neighbour
     4401        if (ShortestPathList[Walker->nr] < Order) {
     4402          for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
     4403            Binder = ListOfBondsPerAtom[Walker->nr][i];
     4404            *out << Verbose(2) << "Current bond is " << *Binder << ": ";
     4405            OtherAtom = Binder->GetOtherAtom(Walker);
     4406            if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us
     4407              *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl;
     4408              //ColorVertexList[OtherAtom->nr] = lightgray;    // mark as explored
     4409            } else { // otherwise check its colour and element
     4410              if (
     4411#ifdef ADDHYDROGEN
     4412              (OtherAtom->type->Z != 1) &&
     4413#endif
     4414                    (ColorEdgeList[Binder->nr] == white)) {  // skip hydrogen, look for unexplored vertices
     4415                *out << "Moving along " << GetColor(ColorEdgeList[Binder->nr]) << " bond " << Binder << " to " << ((ColorVertexList[OtherAtom->nr] == white) ? "unexplored" : "explored") << " item: " << OtherAtom->Name << "." << endl;
     4416                // i find it currently rather sensible to always set the predecessor in order to find one's way back
     4417                //if (PredecessorList[OtherAtom->nr] == NULL) {
     4418                PredecessorList[OtherAtom->nr] = Walker;
     4419                *out << Verbose(3) << "Setting Predecessor of " << OtherAtom->Name << " to " << PredecessorList[OtherAtom->nr]->Name << "." << endl;
     4420                //} else {
     4421                //  *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl;
     4422                //}
     4423                Walker = OtherAtom;
     4424                break;
     4425              } else {
     4426                if (OtherAtom->type->Z == 1)
     4427                  *out << "Links to a hydrogen atom." << endl;
     4428                else
     4429                  *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl;
     4430              }
     4431            }
     4432          }
     4433        } else {  // means we have stepped beyond the horizon: Return!
     4434          Walker = PredecessorList[Walker->nr];
     4435          OtherAtom = Walker;
     4436          *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl;
     4437        }
     4438        if (Walker != OtherAtom) {  // if no white neighbours anymore, color it black
     4439          *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl;
     4440          ColorVertexList[Walker->nr] = black;
     4441          Walker = PredecessorList[Walker->nr];
     4442        }
     4443      }
     4444    } while ((Walker != Root) || (ColorVertexList[Root->nr] != black));
     4445    *out << Verbose(2) << "Inner Looping is finished." << endl;
     4446
     4447    // if we reset all AtomCount atoms, we have again technically O(N^2) ...
     4448    *out << Verbose(2) << "Resetting lists." << endl;
     4449    Walker = NULL;
     4450    Binder = NULL;
     4451    while (!TouchedStack->IsEmpty()) {
     4452      Walker = TouchedStack->PopLast();
     4453      *out << Verbose(3) << "Re-initialising entries of " << *Walker << "." << endl;
     4454      for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)
     4455        ColorEdgeList[ListOfBondsPerAtom[Walker->nr][i]->nr] = white;
     4456      PredecessorList[Walker->nr] = NULL;
     4457      ColorVertexList[Walker->nr] = white;
     4458      ShortestPathList[Walker->nr] = -1;
     4459    }
     4460  }
     4461  *out << Verbose(1) << "Outer Looping over all vertices is done." << endl;
     4462
     4463  // copy together
     4464  *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl;
     4465  FragmentList = new MoleculeListClass(FragmentCounter, AtomCount);
     4466  RunningIndex = 0;
     4467  while ((Leaflet != NULL) && (RunningIndex < FragmentCounter))  {
     4468    FragmentList->ListOfMolecules[RunningIndex++] = Leaflet->Leaf;
     4469    Leaflet->Leaf = NULL; // prevent molecule from being removed
     4470    TempLeaf = Leaflet;
     4471    Leaflet = Leaflet->previous;
     4472    delete(TempLeaf);
     4473  };
     4474
     4475  // free memory and exit
     4476  Free((void **)&PredecessorList, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList");
     4477  Free((void **)&ShortestPathList, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");
     4478  Free((void **)&Labels, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels");
     4479  Free((void **)&ColorVertexList, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList");
     4480  delete(RootStack);
     4481  delete(TouchedStack);
     4482  delete(SnakeStack);
     4483
     4484  *out << Verbose(1) << "End of CreateListOfUniqueFragmentsOfOrder." << endl;
     4485  return FragmentList;
     4486};
     4487*/
     4488
    36664489/** Structure containing all values in power set combination generation.
    36674490 */
     
    45025325    OtherCenterOfGravity.Output(out);
    45035326    *out << endl;
    4504     if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) {
     5327    if (CenterOfGravity.Distance(&OtherCenterOfGravity) > threshold) {
    45055328      *out << Verbose(4) << "Centers of gravity don't match." << endl;
    45065329      result = false;
     
    45165339    while (Walker->next != end) {
    45175340      Walker = Walker->next;
    4518       Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x);
     5341      Distances[Walker->nr] = CenterOfGravity.Distance(&Walker->x);
    45195342    }
    45205343    Walker = OtherMolecule->start;
    45215344    while (Walker->next != OtherMolecule->end) {
    45225345      Walker = Walker->next;
    4523       OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x);
     5346      OtherDistances[Walker->nr] = OtherCenterOfGravity.Distance(&Walker->x);
    45245347    }
    45255348
     
    45395362    flag = 0;
    45405363    for (int i=0;i<AtomCount;i++) {
    4541       *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<  threshold << endl;
    4542       if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold)
     5364      *out << Verbose(5) << "Distances: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<  threshold << endl;
     5365      if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold)
    45435366        flag = 1;
    45445367    }
Note: See TracChangeset for help on using the changeset viewer.