| [14de469] | 1 | /** \file MoleculeListClass.cpp
 | 
|---|
 | 2 |  * 
 | 
|---|
 | 3 |  * Function implementations for the class MoleculeListClass.
 | 
|---|
 | 4 |  * 
 | 
|---|
 | 5 |  */
 | 
|---|
 | 6 | 
 | 
|---|
 | 7 | #include "molecules.hpp"
 | 
|---|
 | 8 | 
 | 
|---|
 | 9 | /*********************************** Functions for class MoleculeListClass *************************/
 | 
|---|
 | 10 | 
 | 
|---|
 | 11 | /** Constructor for MoleculeListClass.
 | 
|---|
 | 12 |  */
 | 
|---|
 | 13 | MoleculeListClass::MoleculeListClass()
 | 
|---|
 | 14 | {
 | 
|---|
 | 15 | };
 | 
|---|
 | 16 | 
 | 
|---|
 | 17 | /** constructor for MoleculeListClass.
 | 
|---|
 | 18 |  * \param NumMolecules number of molecules to allocate for
 | 
|---|
 | 19 |  * \param NumAtoms number of atoms to allocate for
 | 
|---|
 | 20 |  */
 | 
|---|
 | 21 | MoleculeListClass::MoleculeListClass(int NumMolecules, int NumAtoms)
 | 
|---|
 | 22 | {
 | 
|---|
 | 23 |   TEList = (double*) Malloc(sizeof(double)*NumMolecules, "MoleculeListClass:MoleculeListClass: *TEList");
 | 
|---|
 | 24 |   ListOfMolecules = (molecule **) Malloc(sizeof(molecule *)*NumMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");
 | 
|---|
 | 25 |   for (int i=0;i<NumMolecules;i++) {
 | 
|---|
 | 26 |     TEList[i] = 0.;
 | 
|---|
 | 27 |     ListOfMolecules[i] = NULL;
 | 
|---|
 | 28 |   }
 | 
|---|
 | 29 |   NumberOfMolecules = NumMolecules;
 | 
|---|
 | 30 |   NumberOfTopAtoms = NumAtoms;
 | 
|---|
 | 31 | };
 | 
|---|
 | 32 | 
 | 
|---|
 | 33 | 
 | 
|---|
 | 34 | /** Destructor for MoleculeListClass.
 | 
|---|
 | 35 |  */
 | 
|---|
 | 36 | MoleculeListClass::~MoleculeListClass()
 | 
|---|
 | 37 | {
 | 
|---|
 | 38 |   cout << Verbose(3) << this << ": Freeing ListOfMolcules and TEList." << endl;
 | 
|---|
 | 39 |   for (int i=0;i<NumberOfMolecules;i++) {
 | 
|---|
 | 40 |     if (ListOfMolecules[i] != NULL) { // if NULL don't free
 | 
|---|
 | 41 |       cout << Verbose(4) << "ListOfMolecules: Freeing " << ListOfMolecules[i] << "." << endl;
 | 
|---|
 | 42 |       delete(ListOfMolecules[i]);
 | 
|---|
 | 43 |       ListOfMolecules[i] = NULL;
 | 
|---|
 | 44 |     }
 | 
|---|
 | 45 |   }
 | 
|---|
 | 46 |   cout << Verbose(4) << "Freeing ListOfMolecules." << endl;
 | 
|---|
 | 47 |   Free((void **)&ListOfMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");
 | 
|---|
 | 48 |   cout << Verbose(4) << "Freeing TEList." << endl;
 | 
|---|
 | 49 |   Free((void **)&TEList, "MoleculeListClass:MoleculeListClass: *TEList");
 | 
|---|
 | 50 | };
 | 
|---|
 | 51 | 
 | 
|---|
 | 52 | int MolCompare(const void *a, const void *b)
 | 
|---|
 | 53 | {
 | 
|---|
 | 54 |   int *aList = NULL, *bList = NULL;
 | 
|---|
 | 55 |   int Count, Counter, aCounter, bCounter;
 | 
|---|
 | 56 |   int flag;
 | 
|---|
 | 57 |   atom *aWalker = NULL;
 | 
|---|
 | 58 |   atom *bWalker = NULL;
 | 
|---|
 | 59 |   
 | 
|---|
 | 60 |   // sort each atom list and put the numbers into a list, then go through
 | 
|---|
 | 61 |   //cout << "Comparing fragment no. " << *(molecule **)a << " to " << *(molecule **)b << "." << endl;
 | 
|---|
 | 62 |   if ( (**(molecule **)a).AtomCount < (**(molecule **)b).AtomCount ) {
 | 
|---|
 | 63 |     return -1;
 | 
|---|
 | 64 |   } else { if ((**(molecule **)a).AtomCount > (**(molecule **)b).AtomCount)
 | 
|---|
 | 65 |     return +1;
 | 
|---|
 | 66 |     else {
 | 
|---|
 | 67 |       Count = (**(molecule **)a).AtomCount;
 | 
|---|
 | 68 |       aList = (int *) Malloc(sizeof(int)*Count, "MolCompare: *aList");
 | 
|---|
 | 69 |       bList = (int *) Malloc(sizeof(int)*Count, "MolCompare: *bList");
 | 
|---|
 | 70 |   
 | 
|---|
 | 71 |       // fill the lists
 | 
|---|
 | 72 |       aWalker = (**(molecule **)a).start;
 | 
|---|
 | 73 |       bWalker = (**(molecule **)b).start;
 | 
|---|
 | 74 |       Counter = 0;
 | 
|---|
 | 75 |       aCounter = 0;
 | 
|---|
 | 76 |       bCounter = 0;
 | 
|---|
 | 77 |       while ((aWalker->next != (**(molecule **)a).end) && (bWalker->next != (**(molecule **)b).end)) {
 | 
|---|
 | 78 |         aWalker = aWalker->next;
 | 
|---|
 | 79 |         bWalker = bWalker->next;
 | 
|---|
 | 80 |         if (aWalker->GetTrueFather() == NULL)
 | 
|---|
 | 81 |           aList[Counter] = Count + (aCounter++);
 | 
|---|
 | 82 |         else
 | 
|---|
 | 83 |           aList[Counter] = aWalker->GetTrueFather()->nr;
 | 
|---|
 | 84 |         if (bWalker->GetTrueFather() == NULL)
 | 
|---|
 | 85 |           bList[Counter] = Count + (bCounter++);
 | 
|---|
 | 86 |         else
 | 
|---|
 | 87 |           bList[Counter] = bWalker->GetTrueFather()->nr;
 | 
|---|
 | 88 |         Counter++;
 | 
|---|
 | 89 |       }
 | 
|---|
 | 90 |       // check if AtomCount was for real
 | 
|---|
 | 91 |       flag = 0;
 | 
|---|
 | 92 |       if ((aWalker->next == (**(molecule **)a).end) && (bWalker->next != (**(molecule **)b).end)) {
 | 
|---|
 | 93 |         flag = -1;
 | 
|---|
 | 94 |       } else {
 | 
|---|
 | 95 |         if ((aWalker->next != (**(molecule **)a).end) && (bWalker->next == (**(molecule **)b).end))
 | 
|---|
 | 96 |           flag = 1;
 | 
|---|
 | 97 |       }
 | 
|---|
 | 98 |       if (flag == 0) {
 | 
|---|
 | 99 |         // sort the lists
 | 
|---|
 | 100 |         gsl_heapsort(aList,Count, sizeof(int), CompareDoubles); 
 | 
|---|
 | 101 |         gsl_heapsort(bList,Count, sizeof(int), CompareDoubles);
 | 
|---|
 | 102 |         // compare the lists 
 | 
|---|
 | 103 |         
 | 
|---|
 | 104 |         flag = 0;
 | 
|---|
 | 105 |         for(int i=0;i<Count;i++) {
 | 
|---|
 | 106 |           if (aList[i] < bList[i]) {
 | 
|---|
 | 107 |             flag = -1;
 | 
|---|
 | 108 |           } else {
 | 
|---|
 | 109 |             if (aList[i] > bList[i])
 | 
|---|
 | 110 |               flag = 1;
 | 
|---|
 | 111 |           }
 | 
|---|
 | 112 |           if (flag != 0)
 | 
|---|
 | 113 |             break;
 | 
|---|
 | 114 |         }
 | 
|---|
 | 115 |       }
 | 
|---|
 | 116 |       Free((void **)&aList, "MolCompare: *aList");
 | 
|---|
 | 117 |       Free((void **)&bList, "MolCompare: *bList");
 | 
|---|
 | 118 |       return flag;
 | 
|---|
 | 119 |     }
 | 
|---|
 | 120 |   }
 | 
|---|
 | 121 |   return  -1;
 | 
|---|
 | 122 | };
 | 
|---|
 | 123 | 
 | 
|---|
 | 124 | /** Returns an allocated index list which fragment should remain and which are doubly appearing.
 | 
|---|
 | 125 |  * Again, we use linked cell however not with \a threshold which in most cases is too small and would
 | 
|---|
 | 126 |  * generate too many cells, but a too be specified \a celldistance which should e.g. be chosen in
 | 
|---|
 | 127 |  * the magnitude of the typical bond distance. In order to avoid so far the need of a vector list,
 | 
|---|
 | 128 |  * we simply use the molecule structure and the vector sitting in the atom structure.
 | 
|---|
 | 129 |  * \param *out output stream for debugging
 | 
|---|
 | 130 |  * \param **MapList empty but allocated(MoleculeListClass::NumberOfMolecules), containing on return mapping of for which equal molecule which atoms corresponds to which one (needed for ForceFactors)
 | 
|---|
 | 131 |  * \param threshold threshold value for molecule::IsEqualToWithinThreshold()
 | 
|---|
 | 132 |  * \param cell_size 6 entries specifying the unit cell vectors (matrix is symmetric)
 | 
|---|
 | 133 |  * \param celldistance needed for linked-cell technique to find possible equals
 | 
|---|
 | 134 |  * \return allocated index list with \a Num entries.
 | 
|---|
 | 135 |  */
 | 
|---|
 | 136 | int * MoleculeListClass::GetMappingToUniqueFragments(ofstream *out, double threshold, double *cell_size, double celldistance)
 | 
|---|
 | 137 | {
 | 
|---|
 | 138 |   int j, UniqueIndex, HighestNumber;
 | 
|---|
 | 139 |   //int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index;
 | 
|---|
 | 140 |   int Counter;
 | 
|---|
 | 141 |   //molecule **CellList;
 | 
|---|
 | 142 |   int *MapList = NULL;
 | 
|---|
 | 143 |   size_t *SortMap = NULL;
 | 
|---|
 | 144 |   //atom *Walker = NULL, *OtherWalker = NULL;
 | 
|---|
 | 145 |   //molecule *LinkedCellContainer = new molecule(NULL);  // container for all the center of gravities stored as atoms
 | 
|---|
 | 146 |   
 | 
|---|
 | 147 |   /// Allocated MapList with range NumberOfMolecules. 
 | 
|---|
 | 148 |   MapList = (int *) Malloc(sizeof(int)*NumberOfMolecules, "MoleculeListClass::GetMappingToUniqueFragments: *MapList");
 | 
|---|
 | 149 |   SortMap = (size_t *) Malloc(sizeof(size_t)*NumberOfMolecules, "MoleculeListClass::GetMappingToUniqueFragments: *MapList");
 | 
|---|
 | 150 |   for (j=0;j<NumberOfMolecules;j++) {
 | 
|---|
 | 151 |     if (ListOfMolecules[j] ==  NULL)
 | 
|---|
 | 152 |       cerr << "ERROR: Molecule " << j << " is NULL!" << endl;
 | 
|---|
 | 153 |     //else 
 | 
|---|
 | 154 |       //cerr << "ERROR: Molecule " << j << " is " << ListOfMolecules[j] << " with count " << ListOfMolecules[j]->AtomCount << "." << endl;
 | 
|---|
 | 155 |     MapList[j] = -1;
 | 
|---|
 | 156 |     SortMap[j] = 0;
 | 
|---|
 | 157 |   }
 | 
|---|
 | 158 |   *out << Verbose(1) << "Get mapping to unique fragments with " << NumberOfMolecules << " fragments total." << endl;
 | 
|---|
 | 159 |   
 | 
|---|
 | 160 |   // sort the list with heapsort according to sort function
 | 
|---|
 | 161 |   gsl_heapsort_index(SortMap, ListOfMolecules, NumberOfMolecules, sizeof(molecule *), MolCompare);
 | 
|---|
 | 162 |   // check next neighbours and remap
 | 
|---|
 | 163 |   Counter = 0;
 | 
|---|
 | 164 |   MapList[SortMap[0]] = Counter++;
 | 
|---|
 | 165 |   for(int i=1;i<NumberOfMolecules;i++) {
 | 
|---|
 | 166 |     if (MolCompare(&ListOfMolecules[SortMap[i]], &ListOfMolecules[SortMap[i-1]]) == 0)
 | 
|---|
 | 167 |       MapList[SortMap[i]] = MapList[SortMap[i-1]];
 | 
|---|
 | 168 |     else
 | 
|---|
 | 169 |       MapList[SortMap[i]] = Counter++; 
 | 
|---|
 | 170 |   } 
 | 
|---|
 | 171 |   Free((void **)&SortMap, "MoleculeListClass::GetMappingToUniqueFragments: *SortMap");
 | 
|---|
 | 172 | 
 | 
|---|
 | 173 |   *out << Verbose(2) << "Map: ";
 | 
|---|
 | 174 |   for(int i=0;i<NumberOfMolecules;i++)
 | 
|---|
 | 175 |     *out << MapList[i] << " ";
 | 
|---|
 | 176 |   *out << endl;
 | 
|---|
 | 177 | 
 | 
|---|
 | 178 |   // bring MapList indices into an ascending order
 | 
|---|
 | 179 |   HighestNumber = Counter;
 | 
|---|
 | 180 |   *out << Verbose(3) << "HighestNumber: " << HighestNumber << "." << endl;
 | 
|---|
 | 181 |   SortMap = (size_t *) Malloc(sizeof(size_t)*NumberOfMolecules, "MoleculeListClass::GetMappingToUniqueFragments: *SortMap");
 | 
|---|
 | 182 |   for(int i=0;i<NumberOfMolecules;i++)
 | 
|---|
 | 183 |     SortMap[i] = HighestNumber;   // is the first number that will not appear anymore in list   
 | 
|---|
 | 184 |   UniqueIndex = 0;
 | 
|---|
 | 185 |   for(int i=0;i<NumberOfMolecules;i++)
 | 
|---|
 | 186 |     if (MapList[i] != -1) {
 | 
|---|
 | 187 |       if ((unsigned int)SortMap[MapList[i]] == (unsigned int)HighestNumber)
 | 
|---|
 | 188 |         SortMap[MapList[i]] = UniqueIndex++;
 | 
|---|
 | 189 |       MapList[i] = SortMap[MapList[i]];
 | 
|---|
 | 190 |     } else {
 | 
|---|
 | 191 |       MapList[i] = -1;
 | 
|---|
 | 192 |     }
 | 
|---|
 | 193 |   *out << Verbose(2) << "Ascending Map: ";
 | 
|---|
 | 194 |   for(int i=0;i<NumberOfMolecules;i++)
 | 
|---|
 | 195 |     *out << MapList[i] << " ";
 | 
|---|
 | 196 |   *out << endl;
 | 
|---|
 | 197 |   Free((void **)&SortMap, "MoleculeListClass::GetMappingToUniqueFragments: *SortMap");
 | 
|---|
 | 198 | 
 | 
|---|
 | 199 |   /// Return the constructed list.
 | 
|---|
 | 200 |   return MapList;
 | 
|---|
 | 201 | };
 | 
|---|
 | 202 | 
 | 
|---|
 | 203 | 
 | 
|---|
 | 204 | /** Takes a list of molecules and returns the list with doubles removed.
 | 
|---|
 | 205 |  * Checks by using molecule::IsEqualToWithinThreshold() whether fragments within the list
 | 
|---|
 | 206 |  * are actually doubles. If not, the pointer are copied to a new list, if so,
 | 
|---|
 | 207 |  * they are dropped. The new list is then copied back to the reallocated \a **FragmentList
 | 
|---|
 | 208 |  * and the new number of elements therein returned.
 | 
|---|
 | 209 |  * \param *out output stream for debugging
 | 
|---|
 | 210 |  * \param *Map mapping of which index goes on which (from molecule::GetMappingToUniqueFragments())
 | 
|---|
 | 211 |  * \return number of molecules in the new realloacted **FragmentList
 | 
|---|
 | 212 |  */
 | 
|---|
 | 213 | int MoleculeListClass::ReduceFragmentToUniqueOnes(ofstream *out, int *Map)
 | 
|---|
 | 214 | {
 | 
|---|
 | 215 |   *out << Verbose(2) << "Begin of ReduceFragmentToUniqueOnes" << endl;
 | 
|---|
 | 216 |   /// Allocate temporary lists of size \a Num.
 | 
|---|
 | 217 |   molecule **NewMolList = (molecule **) Malloc(sizeof(molecule *)*NumberOfMolecules, "MoleculeListClass::ReduceFragmentToUniqueOnes: NewList");
 | 
|---|
 | 218 |   double *NewTEList = (double *) Malloc(sizeof(double)*NumberOfMolecules, "MoleculeListClass::ReduceFragmentToUniqueOnes: *NewTEList");
 | 
|---|
 | 219 |   for(int i=0;i<NumberOfMolecules;i++) {
 | 
|---|
 | 220 |     NewTEList[i] = 0;
 | 
|---|
 | 221 |     NewMolList[i] = NULL;
 | 
|---|
 | 222 |   }
 | 
|---|
 | 223 |   int ReducedNum = 0, j;
 | 
|---|
 | 224 |   *out << Verbose(3) << "Reducing TE and Forces lists." << endl;
 | 
|---|
 | 225 |   for(int i=0;i<NumberOfMolecules;i++) {                       /// Count new reduced number of molecules ...
 | 
|---|
 | 226 |     //*out << Verbose(4) << i << "th TE Value " << " goes to " << Map[i] << ": " << TEList[i] << "." << endl;
 | 
|---|
 | 227 |     NewTEList[Map[i]] += TEList[i];
 | 
|---|
 | 228 |     if (Map[i] == i) {                           /// ... by checking if Map[i] != i, then Fragment[i] is double of Fragment[Map[i]].
 | 
|---|
 | 229 |       *out << Verbose(4) << "Copying molecule " << i << " as it is unique so far ... " << ListOfMolecules[i]<< endl;
 | 
|---|
 | 230 |       NewMolList[ReducedNum++] = ListOfMolecules[i];   /// ..., whilst copying each value to temporary list, ...
 | 
|---|
 | 231 |     } else {  // else free molecule cause it appears doubly
 | 
|---|
 | 232 |       *out << Verbose(4) << "Removing molecule " << i << "." << endl;
 | 
|---|
 | 233 |       delete(ListOfMolecules[i]);
 | 
|---|
 | 234 |       ListOfMolecules[i] = NULL;
 | 
|---|
 | 235 |     }
 | 
|---|
 | 236 |   }
 | 
|---|
 | 237 |   /// Reallocate \a **FragmentList ...
 | 
|---|
 | 238 |   *out << Verbose(3) << "Reallocating to Unique Fragments:" << endl;
 | 
|---|
 | 239 |   if ((ReducedNum != 0) && (TEList != 0)) {
 | 
|---|
 | 240 |     // factor list
 | 
|---|
 | 241 |     *out << Verbose(4) << "Reallocating TEList [" << TEList << "] to " << ReducedNum << endl;
 | 
|---|
 | 242 |     TEList = (double *) ReAlloc(TEList, sizeof(double)*ReducedNum, "MoleculeListClass::ReduceFragmentToUniqueOnes: *TEList");
 | 
|---|
 | 243 | 
 | 
|---|
 | 244 |     *out << Verbose(4) << "Copying values to new list: " << endl;
 | 
|---|
 | 245 |     j = 0;  // is ReducedNum index
 | 
|---|
 | 246 |     for(int i=0;i<NumberOfMolecules;i++) {/// copy value from temporary to return list
 | 
|---|
 | 247 |       if (Map[i] == i) {
 | 
|---|
 | 248 |       //if (fabs(NewTEList[i]) > MYEPSILON) { // this is a good check also, if TEList[i] = 0 then fragment cancels and may be dropped!
 | 
|---|
 | 249 |         TEList[j] = NewTEList[i];
 | 
|---|
 | 250 |         *out << Verbose(5) << "TE [i" << i << "<->j" << j << "]:" << NewTEList[i] << "->" << TEList[j];
 | 
|---|
 | 251 |         j++;
 | 
|---|
 | 252 |       }
 | 
|---|
 | 253 |       *out << endl;
 | 
|---|
 | 254 |     }
 | 
|---|
 | 255 |     if (j != ReducedNum)
 | 
|---|
 | 256 |       *out << "Panic:  j " << j << " != ReducedNum " << ReducedNum << "." << endl;
 | 
|---|
 | 257 |       
 | 
|---|
 | 258 | 
 | 
|---|
 | 259 |     // molecule list
 | 
|---|
 | 260 |     *out << Verbose(4) << "Reallocating ListOfMolecules ... " << endl;
 | 
|---|
 | 261 |     ListOfMolecules = (molecule **) ReAlloc(ListOfMolecules, sizeof(molecule *)*ReducedNum, "MoleculeListClass::ReduceFragmentToUniqueOnes: ListOfMolecules");
 | 
|---|
 | 262 |     NumberOfMolecules = ReducedNum;
 | 
|---|
 | 263 |     /// ... and copy the reduced number back
 | 
|---|
 | 264 |     *out << Verbose(5) << "Transfering to ListOfMolecules ... ";
 | 
|---|
 | 265 |     for(int i=0;i<ReducedNum;i++) {
 | 
|---|
 | 266 |       ListOfMolecules[i] = NewMolList[i];
 | 
|---|
 | 267 |       *out << NewMolList[i] << " -> " << ListOfMolecules[i] << "\t";
 | 
|---|
 | 268 |     }
 | 
|---|
 | 269 |     *out << endl;
 | 
|---|
 | 270 | 
 | 
|---|
 | 271 | 
 | 
|---|
 | 272 |   } else {
 | 
|---|
 | 273 |     Free((void **)&ListOfMolecules, "MoleculeListClass::ReduceFragmentToUniqueOnes: ListOfMolecules");
 | 
|---|
 | 274 |     NumberOfMolecules = ReducedNum;
 | 
|---|
 | 275 |     *out << Verbose(3) << "ReducedNum is " << ReducedNum << ", Number of Molecules is " << NumberOfMolecules << "." << endl;
 | 
|---|
 | 276 |   }
 | 
|---|
 | 277 |   // free all the lists again
 | 
|---|
 | 278 |   *out << Verbose(3) << "Freeing temporary lists." << endl;
 | 
|---|
 | 279 |   Free((void **)&NewTEList, "MoleculeListClass::ReduceFragmentToUniqueOnes: *NewTEList");      /// free temporary list again
 | 
|---|
 | 280 |   Free((void **)&NewMolList, "MoleculeListClass::ReduceFragmentToUniqueOnes: *NewMolList");
 | 
|---|
 | 281 |   *out << Verbose(2) << "End of ReduceFragmentToUniqueOnes" << endl;
 | 
|---|
 | 282 |   return(ReducedNum);
 | 
|---|
 | 283 | };
 | 
|---|
 | 284 | 
 | 
|---|
 | 285 | /** Simple output of the pointers in ListOfMolecules.
 | 
|---|
 | 286 |  * \param *out output stream
 | 
|---|
 | 287 |  */
 | 
|---|
 | 288 | void MoleculeListClass::Output(ofstream *out)
 | 
|---|
 | 289 | {
 | 
|---|
 | 290 |   *out<< Verbose(1) << "MoleculeList: ";
 | 
|---|
 | 291 |   for (int i=0;i<NumberOfMolecules;i++)
 | 
|---|
 | 292 |     *out << ListOfMolecules[i] << "\t";
 | 
|---|
 | 293 |   *out << endl;
 | 
|---|
 | 294 | };
 | 
|---|
 | 295 | 
 | 
|---|
 | 296 | /** Writes a config file for each molecule in the given \a **FragmentList.
 | 
|---|
 | 297 |  * Note that molecules with a TEList factor of 0 are not stored!
 | 
|---|
 | 298 |  * \param *prefix prefix for the file name
 | 
|---|
 | 299 |  * \param *configuration standard configuration to attach atoms in fragment molecule to.
 | 
|---|
 | 300 |  * \param *SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config
 | 
|---|
 | 301 |  * \return true - success (each file was written), false - something went wrong.
 | 
|---|
 | 302 |  */
 | 
|---|
 | 303 | bool MoleculeListClass::OutputConfigForListOfFragments(char *prefix, config *configuration, int *SortIndex)
 | 
|---|
 | 304 | {
 | 
|---|
 | 305 |   ofstream outputFragment;
 | 
|---|
 | 306 |   char FragmentName[255];
 | 
|---|
 | 307 |   char PathBackup[255];
 | 
|---|
 | 308 |   bool result = true;
 | 
|---|
 | 309 |   bool intermediateResult = true;
 | 
|---|
 | 310 |   atom *Walker = NULL;
 | 
|---|
 | 311 |   vector BoxDimension;
 | 
|---|
 | 312 |   char TEFilename[255];
 | 
|---|
 | 313 |   char *FragmentNumber;
 | 
|---|
 | 314 |   int FragmentCounter = 0;
 | 
|---|
| [a8aac8d] | 315 |   ofstream output;
 | 
|---|
| [14de469] | 316 |   element *runner = NULL;
 | 
|---|
 | 317 |   
 | 
|---|
 | 318 |   // store the fragments as config and as xyz
 | 
|---|
 | 319 |   for(int i=0;i<NumberOfMolecules;i++) {
 | 
|---|
 | 320 |     //if (TEList[i] != 0) {
 | 
|---|
| [b5ecd9] | 321 |       strcpy(PathBackup, configuration->configpath);
 | 
|---|
| [14de469] | 322 | 
 | 
|---|
 | 323 |       // scan all atoms in the current molecule for their fathers and write each vertex index to forces file
 | 
|---|
 | 324 | 
 | 
|---|
 | 325 |       // correct periodic
 | 
|---|
 | 326 |       ListOfMolecules[i]->ScanForPeriodicCorrection((ofstream *)&cout);
 | 
|---|
 | 327 | 
 | 
|---|
 | 328 |       // output xyz file
 | 
|---|
 | 329 |       FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++);
 | 
|---|
 | 330 |       sprintf(FragmentName, "%s/%s%s.conf.xyz", PathBackup, prefix, FragmentNumber);
 | 
|---|
 | 331 |       outputFragment.open(FragmentName, ios::out);
 | 
|---|
 | 332 |       cout << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as XYZ ...";
 | 
|---|
 | 333 |       if (intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment))
 | 
|---|
 | 334 |         cout << " done." << endl;
 | 
|---|
 | 335 |       else
 | 
|---|
 | 336 |         cout << " failed." << endl;
 | 
|---|
 | 337 |       result = result && intermediateResult;
 | 
|---|
 | 338 |       outputFragment.close();
 | 
|---|
 | 339 |       outputFragment.clear();
 | 
|---|
 | 340 |   
 | 
|---|
 | 341 |       cout << Verbose(2) << "Contained atoms: ";
 | 
|---|
 | 342 |       Walker = ListOfMolecules[i]->start;
 | 
|---|
 | 343 |       while (Walker->next != ListOfMolecules[i]->end) {
 | 
|---|
 | 344 |         Walker = Walker->next;
 | 
|---|
 | 345 |         cout << Walker->Name << " ";
 | 
|---|
 | 346 |       }
 | 
|---|
 | 347 |       cout << endl;
 | 
|---|
 | 348 |       // prepare output of config file
 | 
|---|
 | 349 |       sprintf(FragmentName, "%s/%s%s.conf", PathBackup, prefix, FragmentNumber);
 | 
|---|
 | 350 |       outputFragment.open(FragmentName, ios::out);
 | 
|---|
| [b5ecd9] | 351 |       strcpy(PathBackup, configuration->configpath);
 | 
|---|
| [14de469] | 352 |       sprintf(FragmentName, "%s/%s%s/", PathBackup, prefix, FragmentNumber);
 | 
|---|
 | 353 |       
 | 
|---|
 | 354 |       // center on edge
 | 
|---|
 | 355 |       ListOfMolecules[i]->CenterEdge((ofstream *)&cout, &BoxDimension);
 | 
|---|
 | 356 |       ListOfMolecules[i]->SetBoxDimension(&BoxDimension);  // update Box of atoms by boundary
 | 
|---|
 | 357 |       int j = -1;
 | 
|---|
 | 358 |       for (int k=0;k<3;k++) {
 | 
|---|
 | 359 |         j += k+1;
 | 
|---|
 | 360 |         BoxDimension.x[k] = 5.;
 | 
|---|
 | 361 |         ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.;
 | 
|---|
 | 362 |       }
 | 
|---|
 | 363 |       ListOfMolecules[i]->Translate(&BoxDimension);
 | 
|---|
 | 364 | 
 | 
|---|
 | 365 |       // also calculate necessary orbitals
 | 
|---|
 | 366 |       ListOfMolecules[i]->CountElements();  // this is a bugfix, atoms should should actually be added correctly to this fragment 
 | 
|---|
 | 367 |       ListOfMolecules[i]->CalculateOrbitals(*configuration);
 | 
|---|
 | 368 |       
 | 
|---|
 | 369 |       // change path in config
 | 
|---|
 | 370 |       configuration->SetDefaultPath(FragmentName);
 | 
|---|
 | 371 |       cout << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as config ...";
 | 
|---|
 | 372 |       if (intermediateResult = configuration->Save(&outputFragment, ListOfMolecules[i]->elemente, ListOfMolecules[i]))
 | 
|---|
 | 373 |         cout << " done." << endl;
 | 
|---|
 | 374 |       else
 | 
|---|
 | 375 |         cout << " failed." << endl;
 | 
|---|
 | 376 |       // restore old config
 | 
|---|
 | 377 |       configuration->SetDefaultPath(PathBackup);
 | 
|---|
 | 378 |       
 | 
|---|
 | 379 |       result = result && intermediateResult;
 | 
|---|
 | 380 |       outputFragment.close();
 | 
|---|
 | 381 |       outputFragment.clear();
 | 
|---|
 | 382 |       Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber");
 | 
|---|
 | 383 |     }
 | 
|---|
 | 384 | 
 | 
|---|
| [b5ecd9] | 385 |   strcpy(PathBackup, configuration->configpath);
 | 
|---|
| [14de469] | 386 |   // open file for the total energy factor
 | 
|---|
| [10f641] | 387 |   sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, TEFACTORSFILE);
 | 
|---|
| [a8aac8d] | 388 |   output.open(TEFilename, ios::out);
 | 
|---|
| [14de469] | 389 |   // output TEList (later to file AtomicTEList.dat)
 | 
|---|
 | 390 |   cout << Verbose(2) << "Saving " << prefix << " energy factors ...";
 | 
|---|
 | 391 |   //cout << Verbose(1) << "Final ATEList: ";
 | 
|---|
| [a8aac8d] | 392 |   //less output << prefix << "TE\t";
 | 
|---|
| [14de469] | 393 |   for(int i=0;i<NumberOfMolecules;i++) {
 | 
|---|
 | 394 |     //cout << TEList[i] << "\t";
 | 
|---|
 | 395 |     //if (TEList[i] != 0)
 | 
|---|
| [a8aac8d] | 396 |       output << TEList[i] << "\t";
 | 
|---|
| [14de469] | 397 |   }
 | 
|---|
 | 398 |   //cout << endl;
 | 
|---|
| [a8aac8d] | 399 |   output << endl;
 | 
|---|
 | 400 |   output.close();
 | 
|---|
| [14de469] | 401 |   cout << " done." << endl;
 | 
|---|
 | 402 |   
 | 
|---|
 | 403 |   // open file for the force factors
 | 
|---|
| [10f641] | 404 |   sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, FORCESFILE);
 | 
|---|
| [a8aac8d] | 405 |   output.open(TEFilename, ios::out);
 | 
|---|
| [14de469] | 406 |   //cout << Verbose(1) << "Final AtomicForcesList: ";
 | 
|---|
 | 407 |   cout << Verbose(2) << "Saving " << prefix << " force factors ...";
 | 
|---|
| [a8aac8d] | 408 |   //output << prefix << "Forces" << endl;
 | 
|---|
| [14de469] | 409 |   for(int j=0;j<NumberOfMolecules;j++) {
 | 
|---|
 | 410 |     //if (TEList[j] != 0) {
 | 
|---|
 | 411 |     runner = ListOfMolecules[j]->elemente->start;
 | 
|---|
 | 412 |     while (runner->next != ListOfMolecules[j]->elemente->end) { // go through every element
 | 
|---|
 | 413 |       runner = runner->next;
 | 
|---|
 | 414 |       if (ListOfMolecules[j]->ElementsInMolecule[runner->Z]) { // if this element got atoms
 | 
|---|
 | 415 |         Walker = ListOfMolecules[j]->start;
 | 
|---|
 | 416 |         while (Walker->next != ListOfMolecules[j]->end) { // go through every atom of this element
 | 
|---|
 | 417 |           Walker = Walker->next;
 | 
|---|
 | 418 |           if (Walker->type->Z == runner->Z) {
 | 
|---|
 | 419 |             if ((Walker->GetTrueFather() != NULL) && (Walker->GetTrueFather() != Walker)) {// if there is a real father, prints its index
 | 
|---|
| [c67e16] | 420 |               //cout << "Walker is " << *Walker << " with true father " << *( Walker->GetTrueFather()) << ", its number " << Walker->GetTrueFather()->nr << " and index " << SortIndex[Walker->GetTrueFather()->nr] << "." << endl;  
 | 
|---|
| [a8aac8d] | 421 |               output <<  SortIndex[Walker->GetTrueFather()->nr] << "\t";
 | 
|---|
| [14de469] | 422 |             } else  // otherwise a -1 to indicate an added saturation hydrogen
 | 
|---|
| [a8aac8d] | 423 |               output << "-1\t";
 | 
|---|
| [14de469] | 424 |           }
 | 
|---|
 | 425 |         }
 | 
|---|
 | 426 |       }
 | 
|---|
 | 427 |     }
 | 
|---|
 | 428 |     //cout << endl << endl;
 | 
|---|
| [a8aac8d] | 429 |     output << endl;
 | 
|---|
| [14de469] | 430 |   }
 | 
|---|
| [a8aac8d] | 431 |   output.close();
 | 
|---|
| [14de469] | 432 |   cout << " done." << endl;
 | 
|---|
 | 433 | 
 | 
|---|
 | 434 |   // open KeySet file
 | 
|---|
 | 435 |   sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, "KeySets.dat");
 | 
|---|
| [a8aac8d] | 436 |   output.open(TEFilename, ios::out);
 | 
|---|
| [14de469] | 437 |   cout << Verbose(2) << "Saving " << prefix << " key sets of each subgraph ...";
 | 
|---|
 | 438 |   for(int j=0;j<NumberOfMolecules;j++) {
 | 
|---|
 | 439 |     //if (TEList[j] != 0) {
 | 
|---|
 | 440 |       Walker = ListOfMolecules[j]->start;
 | 
|---|
 | 441 |       while(Walker->next != ListOfMolecules[j]->end) {
 | 
|---|
 | 442 |         Walker = Walker->next;        
 | 
|---|
 | 443 | #ifdef ADDHYDROGEN
 | 
|---|
 | 444 |         if ((Walker->GetTrueFather() != NULL) && (Walker->type->Z != 1)) // if there is a real father, prints its index
 | 
|---|
 | 445 | #else
 | 
|---|
 | 446 |         if ((Walker->GetTrueFather() != NULL)) // if there is a real father, prints its index
 | 
|---|
 | 447 | #endif 
 | 
|---|
| [a8aac8d] | 448 |           output <<  Walker->GetTrueFather()->nr << "\t";
 | 
|---|
| [14de469] | 449 | #ifdef ADDHYDROGEN
 | 
|---|
 | 450 |         else  // otherwise a -1 to indicate an added saturation hydrogen
 | 
|---|
| [a8aac8d] | 451 |           output << "-1\t";
 | 
|---|
| [14de469] | 452 | #endif 
 | 
|---|
 | 453 |       }
 | 
|---|
 | 454 |       //cout << endl << endl;
 | 
|---|
| [a8aac8d] | 455 |       output << endl;
 | 
|---|
| [14de469] | 456 |     }
 | 
|---|
| [a8aac8d] | 457 |   output.close();
 | 
|---|
| [14de469] | 458 |   cout << " done." << endl;
 | 
|---|
 | 459 |   
 | 
|---|
 | 460 |   // printing final number
 | 
|---|
 | 461 |   cout << "Final number of fragments: " << FragmentCounter << "." << endl;
 | 
|---|
 | 462 |       
 | 
|---|
 | 463 |   return result;
 | 
|---|
 | 464 | };
 | 
|---|
 | 465 | 
 | 
|---|
 | 466 | /** Reduce the list of molecules to unique pieces.
 | 
|---|
 | 467 |  * molecule::IsEqualToWithinThreshold() is used by GetMappingToUniqueFragments() to provide a mapping for
 | 
|---|
 | 468 |  * ReduceFragmentToUniqueOnes(). 
 | 
|---|
 | 469 |  * \param *out output stream for debugging
 | 
|---|
 | 470 |  * \param cell_size 6 entries specifying the unit cell vectors (matrix is symmetric) for getting the map
 | 
|---|
 | 471 |  * \param celldistance needed for linked-cell technique when getting the map
 | 
|---|
 | 472 |  */
 | 
|---|
 | 473 | void MoleculeListClass::ReduceToUniqueList(ofstream *out, double *cell_size, double celldistance)
 | 
|---|
 | 474 | {
 | 
|---|
 | 475 |   int *ReduceMapping = NULL;
 | 
|---|
 | 476 |   
 | 
|---|
 | 477 |   *out << Verbose(0) << "Begin of ReduceToUniqueList." << endl; 
 | 
|---|
 | 478 |   // again, check whether there are equal fragments by ReduceToUniqueOnes
 | 
|---|
 | 479 |   *out << Verbose(1) << "Get reduce mapping." << endl;
 | 
|---|
 | 480 |   ReduceMapping = GetMappingToUniqueFragments(out, 0.05, cell_size, celldistance);
 | 
|---|
 | 481 |   *out << Verbose(1) << "MapList: ";
 | 
|---|
 | 482 |   for(int i=0;i<NumberOfMolecules;i++)
 | 
|---|
 | 483 |     *out << ReduceMapping[i] << " ";
 | 
|---|
 | 484 |   *out << endl << endl;
 | 
|---|
 | 485 |   *out << Verbose(1) << "Apply reduce mapping." << endl;
 | 
|---|
 | 486 |   ReduceFragmentToUniqueOnes(out, ReduceMapping);
 | 
|---|
 | 487 |   Free((void **)&ReduceMapping, "MoleculeListClass::FragmentTopDown: *ReduceMapping");  // free map after reduce
 | 
|---|
 | 488 |   *out << Verbose(1) << "Number of Fragments after Reducing is " << NumberOfMolecules << "." << endl;
 | 
|---|
 | 489 |   *out << Verbose(0) << "End of ReduceToUniqueList." << endl; 
 | 
|---|
 | 490 | };
 | 
|---|
 | 491 | 
 | 
|---|
 | 492 | /** Fragments a molecule and resulting pieces recursively until the number of bonds
 | 
|---|
 | 493 |  * Here the idea is similar to the FragmentBottomUp() approach, only that we split up the molecule
 | 
|---|
 | 494 |  * bond per bond into left and right fragments and this recursively also with each yielded
 | 
|---|
 | 495 |  * fragment until there is no fragment with continuous number of bonds greater than \a BondDegree.
 | 
|---|
 | 496 |  * are below the given \a BondDegree.
 | 
|---|
 | 497 |  * \param *out output stream for debugging
 | 
|---|
 | 498 |  * \param BondDegree maximum number of continuous bonds in a fragment
 | 
|---|
 | 499 |  * \param bonddistance typical bond distance
 | 
|---|
 | 500 |  * \param *configuration configuration for writing config files for each fragment
 | 
|---|
 | 501 |  * \param CutCyclic cut cyclic bonds (saturate with hydrogen) or add 
 | 
|---|
 | 502 |  * \return pointer to MoleculeListClass with all the fragments or NULL if something went wrong.
 | 
|---|
 | 503 |  * \todo so far we volontarily mix up the above BondDegree definition and molecule::NoNonBonds
 | 
|---|
 | 504 |  * 
 | 
|---|
 | 505 |  * \bug  FragmentTopDown does not work right now due to NULL being given as cell_size to ReduceToUniqueOnes()
 | 
|---|
 | 506 |  */
 | 
|---|
 | 507 | MoleculeListClass * MoleculeListClass::FragmentTopDown(ofstream *out, int BondDegree, double bonddistance, config *configuration, enum CutCyclicBond CutCyclic)
 | 
|---|
 | 508 | {
 | 
|---|
 | 509 |   int Num, No, Cyclic, NoBonds;
 | 
|---|
 | 510 |   MoleculeListClass *ReturnList = NULL;
 | 
|---|
 | 511 |   MoleculeListClass **FragmentsList = NULL;
 | 
|---|
 | 512 |   molecule *CurrentMolecule = NULL;
 | 
|---|
 | 513 |   bond *Binder = NULL;
 | 
|---|
 | 514 |  
 | 
|---|
 | 515 |   *out << Verbose(0) << "Begin of FragmentTopDown:" << this << "." << endl; 
 | 
|---|
 | 516 |   Num = 0;
 | 
|---|
 | 517 |   FragmentsList = (MoleculeListClass **) Malloc(sizeof(MoleculeListClass *)*NumberOfMolecules, "MoleculeListClass::FragmentTopDown: **FragmentsList");
 | 
|---|
 | 518 |   // fragment each molecule into its own MoleculeListClass
 | 
|---|
 | 519 |   for(int i=0;i<NumberOfMolecules;i++) {
 | 
|---|
 | 520 |     CurrentMolecule = ListOfMolecules[i];
 | 
|---|
 | 521 |     CurrentMolecule->CountAtoms(out);
 | 
|---|
 | 522 |     Cyclic = CurrentMolecule->CountCyclicBonds(out);
 | 
|---|
 | 523 |     NoBonds = 
 | 
|---|
 | 524 | #ifdef ADDHYDROGEN
 | 
|---|
 | 525 | CurrentMolecule->NoNonBonds
 | 
|---|
 | 526 | #else 
 | 
|---|
 | 527 | CurrentMolecule->BondCount
 | 
|---|
 | 528 | #endif 
 | 
|---|
 | 529 |                 - ((CutCyclic == KeepBond) ? Cyclic : 0);
 | 
|---|
 | 530 |     // check if NoNonBonds < BondDegree, then don't split any further: Here, correct for greatest continuous bond length!
 | 
|---|
 | 531 |     *out << Verbose(0) << "Checking on Number of true Bonds " << NoBonds << " (i.e. no -H, if chosen no cyclic) greater than " << BondDegree << "." << endl;
 | 
|---|
 | 532 |     if (NoBonds > BondDegree) {
 | 
|---|
 | 533 |       //cerr << Verbose(1) << "TopDown Level of Molecule " << CurrentMolecule << ": " << (CurrentMolecule->NoNonBonds - BondDegree) << "." << endl; 
 | 
|---|
 | 534 |       *out << Verbose(1) << "Breaking up molecule " << i << " in fragment list." << endl;
 | 
|---|
 | 535 |       CurrentMolecule->CreateListOfBondsPerAtom(out);
 | 
|---|
 | 536 |       // Get atomic fragments for the list
 | 
|---|
 | 537 |       *out << Verbose(1) << "Getting Atomic fragments for molecule " << i << "." << endl;
 | 
|---|
 | 538 |       MoleculeListClass *AtomicFragments = CurrentMolecule->GetAtomicFragments(out, NumberOfTopAtoms, configuration->GetIsAngstroem(), TEList[i]/(1. - NoBonds), CutCyclic);
 | 
|---|
 | 539 |       
 | 
|---|
 | 540 |       // build the atomic part of the list of molecules
 | 
|---|
 | 541 |       *out << Verbose(1) << "Putting atomic fragment into list of molecules." << endl;
 | 
|---|
 | 542 |       
 | 
|---|
 | 543 |       // cutting cyclic bonds yields only a single fragment, not two as non-cyclic!
 | 
|---|
 | 544 |       No = (CutCyclic == KeepBond) ? ((
 | 
|---|
 | 545 | #ifdef ADDHYDROGEN
 | 
|---|
 | 546 | CurrentMolecule->NoNonBonds - Cyclic)*2) : CurrentMolecule->NoNonBonds*2 - Cyclic; 
 | 
|---|
 | 547 | #else 
 | 
|---|
 | 548 | CurrentMolecule->BondCount - Cyclic)*2) : CurrentMolecule->BondCount*2 - Cyclic; 
 | 
|---|
 | 549 | #endif 
 | 
|---|
 | 550 |       
 | 
|---|
 | 551 |       if (AtomicFragments != NULL) {
 | 
|---|
 | 552 |         ReturnList = new MoleculeListClass(No+AtomicFragments->NumberOfMolecules, NumberOfTopAtoms);
 | 
|---|
 | 553 |         for (int j=0;j<AtomicFragments->NumberOfMolecules;j++) { // shift all Atomic Fragments into this one here
 | 
|---|
 | 554 |           ReturnList->ListOfMolecules[j+No] = AtomicFragments->ListOfMolecules[j];
 | 
|---|
 | 555 |           AtomicFragments->ListOfMolecules[j] = NULL;
 | 
|---|
 | 556 |           ReturnList->ListOfMolecules[j+No]->NoNonBonds = 0;
 | 
|---|
 | 557 |           ReturnList->ListOfMolecules[j+No]->NoNonHydrogen = 1;
 | 
|---|
 | 558 |           ReturnList->TEList[j+No] = AtomicFragments->TEList[j];
 | 
|---|
 | 559 |         }
 | 
|---|
 | 560 |         *out << Verbose(3) << "Freeing Atomic memory" << endl;
 | 
|---|
 | 561 |         delete(AtomicFragments);
 | 
|---|
 | 562 |         AtomicFragments = NULL;
 | 
|---|
 | 563 |       } else {
 | 
|---|
 | 564 |         *out << Verbose(2) << "AtomicFragments is NULL, filling list with whole molecule only." << endl; 
 | 
|---|
 | 565 |         ReturnList = new MoleculeListClass(No, NumberOfTopAtoms);
 | 
|---|
 | 566 |       }
 | 
|---|
 | 567 | 
 | 
|---|
 | 568 |       // build the side pieces part of the list of molecules
 | 
|---|
 | 569 |       *out << Verbose(1) << "Building side piece fragments and putting into list of molecules." << endl;
 | 
|---|
 | 570 |       No = 0;
 | 
|---|
 | 571 |       Binder = CurrentMolecule->first;
 | 
|---|
 | 572 |       while(Binder->next != CurrentMolecule->last) {
 | 
|---|
 | 573 |         Binder = Binder->next;
 | 
|---|
 | 574 | #ifdef ADDHYDROGEN
 | 
|---|
 | 575 |         if (Binder->HydrogenBond == 0)
 | 
|---|
 | 576 | #endif        
 | 
|---|
 | 577 |           if ((CutCyclic == SaturateBond) || (!Binder->Cyclic)) {
 | 
|---|
 | 578 |             // split each bond into left and right side piece
 | 
|---|
 | 579 |             if (Binder->Cyclic) {
 | 
|---|
 | 580 |               molecule *dummy = NULL; // we lazily hand FragmentMoleculeByBond() a dummy as second fragment and ... 
 | 
|---|
 | 581 |               *out << Verbose(1) << "Breaking up " << Binder->nr << "th and " << No << "th non-hydrogen, CYCLIC bond " << *Binder << " of molecule " << i << " [" << CurrentMolecule << "] into a single pieces." << endl; 
 | 
|---|
 | 582 |               CurrentMolecule->FragmentMoleculeByBond(out, Binder, &(ReturnList->ListOfMolecules[No]), &(dummy), configuration->GetIsAngstroem(), CutCyclic);
 | 
|---|
 | 583 |               delete(dummy);  // ... free the dummy which is due to the cyclic bond the exacy same fragment
 | 
|---|
 | 584 |               *out << Verbose(1) << "Single fragment is " << ReturnList->ListOfMolecules[No] << "." << endl;
 | 
|---|
 | 585 |       
 | 
|---|
 | 586 |               // write down the necessary TE-summation in order to regain TE of whole molecule
 | 
|---|
 | 587 |               *out << Verbose(2) << "Creating TEList for Fragment " << i << " of Bond " << No << "." << endl;
 | 
|---|
 | 588 | #ifdef ADDHYDROGEN
 | 
|---|
 | 589 |               ReturnList->TEList[No] = -TEList[i]/(1. -CurrentMolecule->NoNonBonds);
 | 
|---|
 | 590 | #else              
 | 
|---|
 | 591 |               ReturnList->TEList[No] = -TEList[i]/(1. -CurrentMolecule->BondCount);
 | 
|---|
 | 592 | #endif
 | 
|---|
 | 593 |             } else {
 | 
|---|
 | 594 |               *out << Verbose(1) << "Breaking up " << Binder->nr << "th and " << No << "th non-hydrogen, non-cyclic bond " << *Binder << " of molecule " << i << " [" << CurrentMolecule << "] into left and right side pieces." << endl; 
 | 
|---|
 | 595 |               CurrentMolecule->FragmentMoleculeByBond(out, Binder, &(ReturnList->ListOfMolecules[No]), &(ReturnList->ListOfMolecules[No+1]), configuration->GetIsAngstroem(), CutCyclic);
 | 
|---|
 | 596 |               *out << Verbose(1) << "Left Fragment is " << ReturnList->ListOfMolecules[No] << ", right Fragment is " << ReturnList->ListOfMolecules[No+1] << "." << endl;
 | 
|---|
 | 597 |       
 | 
|---|
 | 598 |               // write down the necessary TE-summation in order to regain TE of whole molecule
 | 
|---|
 | 599 |               *out << Verbose(2) << "Creating TEList for Fragment " << i << " of Bond " << No << "." << endl;
 | 
|---|
 | 600 |               ReturnList->TEList[No] = -TEList[i]/(1. - NoBonds);
 | 
|---|
 | 601 |               ReturnList->TEList[No+1] = -TEList[i]/(1. - NoBonds);
 | 
|---|
 | 602 |             }
 | 
|---|
 | 603 |             No += ((Binder->Cyclic) ? 1 : 2);
 | 
|---|
 | 604 |           }
 | 
|---|
 | 605 |       }
 | 
|---|
 | 606 | 
 | 
|---|
 | 607 |       // Reduce this list
 | 
|---|
 | 608 |       ReturnList->ReduceToUniqueList(out, NULL, bonddistance);
 | 
|---|
 | 609 | 
 | 
|---|
 | 610 |       // recurse and receive List
 | 
|---|
 | 611 |       *out << Verbose(1) << "Calling TopDown " << ReturnList<< " with filled list: ";
 | 
|---|
 | 612 |       ReturnList->Output(out);
 | 
|---|
 | 613 |       FragmentsList[i] = ReturnList->FragmentTopDown(out, BondDegree, bonddistance, configuration, CutCyclic);
 | 
|---|
 | 614 |       *out << Verbose(1) << "Returning from TopDown " << ReturnList<< " with filled list: ";
 | 
|---|
 | 615 |       ReturnList->Output(out);
 | 
|---|
 | 616 |       
 | 
|---|
 | 617 |       // remove list after we're done
 | 
|---|
 | 618 |       *out << Verbose(2) << "Removing caller list." << endl;
 | 
|---|
 | 619 |       delete(ReturnList);
 | 
|---|
 | 620 |       ReturnList = NULL;
 | 
|---|
 | 621 |       
 | 
|---|
 | 622 |     } else {  // create a list with only a single molecule inside, transfer everything from "this" list to return list
 | 
|---|
 | 623 |       *out << Verbose(1) << "Not breaking up molecule " << i << " in fragment list." << endl;
 | 
|---|
 | 624 |       FragmentsList[i] = new MoleculeListClass(1, NumberOfTopAtoms);
 | 
|---|
 | 625 |       FragmentsList[i]->ListOfMolecules[0] = ListOfMolecules[i];
 | 
|---|
 | 626 |       ListOfMolecules[i] = NULL;
 | 
|---|
 | 627 |       FragmentsList[i]->TEList[0] = TEList[i]; 
 | 
|---|
 | 628 |     }
 | 
|---|
 | 629 |     Num += FragmentsList[i]->NumberOfMolecules;
 | 
|---|
 | 630 |   }
 | 
|---|
 | 631 |   
 | 
|---|
 | 632 |   // now, we have a list of MoleculeListClasses: combine all fragments list into one single list
 | 
|---|
 | 633 |   *out << Verbose(2) << "Combining to a list of " << Num << " molecules and Memory cleanup of old list of lists." << endl; 
 | 
|---|
 | 634 |   ReturnList = new MoleculeListClass(Num, NumberOfTopAtoms);
 | 
|---|
 | 635 |   No = 0;
 | 
|---|
 | 636 |   for(int i=0;i<NumberOfMolecules;i++) {
 | 
|---|
 | 637 |     for(int j=0;j<FragmentsList[i]->NumberOfMolecules;j++) {
 | 
|---|
 | 638 |       // transfer molecule
 | 
|---|
 | 639 |       ReturnList->ListOfMolecules[No] = FragmentsList[i]->ListOfMolecules[j];
 | 
|---|
 | 640 |       FragmentsList[i]->ListOfMolecules[j] = NULL;
 | 
|---|
 | 641 |       // transfer TE factor
 | 
|---|
 | 642 |       ReturnList->TEList[No] = FragmentsList[i]->TEList[j];
 | 
|---|
 | 643 |       No++;
 | 
|---|
 | 644 |     }
 | 
|---|
 | 645 |     delete(FragmentsList[i]);
 | 
|---|
 | 646 |     FragmentsList[i] = NULL;
 | 
|---|
 | 647 |   }
 | 
|---|
 | 648 |   Free((void **)&FragmentsList, "MoleculeListClass::FragmentTopDown: **FragmentsList");
 | 
|---|
 | 649 |   
 | 
|---|
 | 650 |   // Reduce the list to unique fragments
 | 
|---|
 | 651 |   ReturnList->ReduceToUniqueList(out, NULL, bonddistance);
 | 
|---|
 | 652 |   
 | 
|---|
 | 653 |   // return pointer to list
 | 
|---|
 | 654 |   *out << Verbose(0) << "Return with filled list: ";
 | 
|---|
 | 655 |   ReturnList->Output(out);
 | 
|---|
 | 656 |   
 | 
|---|
 | 657 |   *out << Verbose(0) << "End of FragmentTopDown:" << this << "." << endl; 
 | 
|---|
 | 658 |   return (ReturnList);
 | 
|---|
 | 659 | }; 
 | 
|---|
 | 660 | 
 | 
|---|
 | 661 | /******************************************* Class MoleculeLeafClass ************************************************/
 | 
|---|
 | 662 | 
 | 
|---|
 | 663 | /** Constructor for MoleculeLeafClass root leaf.
 | 
|---|
 | 664 |  * \param *Up Leaf on upper level
 | 
|---|
 | 665 |  * \param *PreviousLeaf NULL - We are the first leaf on this level, otherwise points to previous in list
 | 
|---|
 | 666 |  */
 | 
|---|
 | 667 | //MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *Up = NULL, MoleculeLeafClass *Previous = NULL)
 | 
|---|
 | 668 | MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL)
 | 
|---|
 | 669 | {
 | 
|---|
 | 670 | //  if (Up != NULL)
 | 
|---|
 | 671 | //    if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?
 | 
|---|
 | 672 | //      Up->DownLeaf = this;
 | 
|---|
 | 673 | //  UpLeaf = Up;
 | 
|---|
 | 674 | //  DownLeaf = NULL;
 | 
|---|
 | 675 |   Leaf = NULL;
 | 
|---|
 | 676 |   previous = PreviousLeaf;
 | 
|---|
 | 677 |   if (previous != NULL) {
 | 
|---|
 | 678 |     MoleculeLeafClass *Walker = previous->next;
 | 
|---|
 | 679 |     previous->next = this;
 | 
|---|
 | 680 |     next = Walker;
 | 
|---|
 | 681 |   } else {
 | 
|---|
 | 682 |     next = NULL;
 | 
|---|
 | 683 |   }
 | 
|---|
 | 684 | };
 | 
|---|
 | 685 | 
 | 
|---|
 | 686 | /** Destructor for MoleculeLeafClass.
 | 
|---|
 | 687 |  */
 | 
|---|
 | 688 | MoleculeLeafClass::~MoleculeLeafClass()
 | 
|---|
 | 689 | {
 | 
|---|
 | 690 | //  if (DownLeaf != NULL) {// drop leaves further down
 | 
|---|
 | 691 | //    MoleculeLeafClass *Walker = DownLeaf;
 | 
|---|
 | 692 | //    MoleculeLeafClass *Next;
 | 
|---|
 | 693 | //    do {
 | 
|---|
 | 694 | //      Next = Walker->NextLeaf;
 | 
|---|
 | 695 | //      delete(Walker);
 | 
|---|
 | 696 | //      Walker = Next;
 | 
|---|
 | 697 | //    } while (Walker != NULL);
 | 
|---|
 | 698 | //    // Last Walker sets DownLeaf automatically to NULL
 | 
|---|
 | 699 | //  }
 | 
|---|
 | 700 |   // remove the leaf itself
 | 
|---|
 | 701 |   if (Leaf != NULL) {
 | 
|---|
 | 702 |     delete(Leaf);
 | 
|---|
 | 703 |     Leaf = NULL;
 | 
|---|
 | 704 |   }
 | 
|---|
 | 705 |   // remove this Leaf from level list
 | 
|---|
 | 706 |   if (previous != NULL)   
 | 
|---|
 | 707 |     previous->next = next;
 | 
|---|
 | 708 | //  } else { // we are first in list (connects to UpLeaf->DownLeaf)
 | 
|---|
 | 709 | //    if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))
 | 
|---|
 | 710 | //      NextLeaf->UpLeaf = UpLeaf;  // either null as we are top level or the upleaf of the first node
 | 
|---|
 | 711 | //    if (UpLeaf != NULL)
 | 
|---|
 | 712 | //      UpLeaf->DownLeaf = NextLeaf;  // either null as we are only leaf or NextLeaf if we are just the first
 | 
|---|
 | 713 | //  }
 | 
|---|
 | 714 | //  UpLeaf = NULL;
 | 
|---|
 | 715 |   if (next != NULL) // are we last in list
 | 
|---|
 | 716 |     next->previous = previous;
 | 
|---|
 | 717 |   next = NULL;
 | 
|---|
 | 718 |   previous = NULL;
 | 
|---|
 | 719 | };
 | 
|---|
 | 720 | 
 | 
|---|
 | 721 | /** Adds \a molecule leaf to the tree.
 | 
|---|
 | 722 |  * \param *ptr ptr to molecule to be added
 | 
|---|
 | 723 |  * \param *Previous previous MoleculeLeafClass referencing level and which on the level
 | 
|---|
 | 724 |  * \return true - success, false - something went wrong
 | 
|---|
 | 725 |  */
 | 
|---|
 | 726 | bool MoleculeLeafClass::AddLeaf(molecule *ptr, MoleculeLeafClass *Previous)
 | 
|---|
 | 727 | {
 | 
|---|
 | 728 |   return false;
 | 
|---|
 | 729 | };
 | 
|---|