[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;
|
---|
[c750cc] | 306 | char FragmentName[MAXSTRINGSIZE];
|
---|
| 307 | char PathBackup[MAXSTRINGSIZE];
|
---|
[14de469] | 308 | bool result = true;
|
---|
| 309 | bool intermediateResult = true;
|
---|
| 310 | atom *Walker = NULL;
|
---|
| 311 | vector BoxDimension;
|
---|
[c750cc] | 312 | char TEFilename[MAXSTRINGSIZE];
|
---|
[14de469] | 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 | };
|
---|