Ignore:
Timestamp:
May 2, 2008, 1:25:48 PM (17 years ago)
Author:
Frederik Heber <heber@…>
Children:
30fda2
Parents:
e936b3
Message:

HUGE REWRITE to allow for adaptive increase of the bond order, first working commit

Lots of code was thrown out:
-BottomUp, TopDown and GetAtomicFragments
-TEFactors are now used as "CreationCounters", i.e. the count how often a fragment as been created (ideal would be only once)
-ReduceToUniqueOnes and stuff all thrown out, since they are out-dated since use of hash table
Other changes:
-CreateListofUniqueFragments renamed to PowerSetGenerator
-PowerSetGenerator goes not over all reachable roots, but one given by calling function FragmentBOSSANOVA
-FragmentBOSSANOVA loops over all possible root sites and hands this over to PowerSetGenerator
-by the virtue of the hash table it is not important anymore whether created keysets are unique or not, as this is recognized in log(n). Hence, the label < label is not important anymore (and not applicable in an adaptive scheme with old, parsed keysets and unknown labels) (THIS IS HOWEVER NOT DONE YET!)
The setup is then as follows:

  1. FragmentMolecule
    1. parses adjacency, keysets and orderatsite files
    2. performs DFS to find connected subgraphs (to leave this in was a design decision: might be useful later)
    3. a RootStack is created for every subgraph (here, later we implement the "update 10 sites with highest energy contribution", and that's why this consciously not done in the following loop)
    4. in a loop over all subgraphs

d1. calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure
d2. creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)

  1. combines the generated molecule lists from all subgraphs
  2. saves to disk: fragment configs, adjacency, orderatsite, keyset files
  1. FragmentBOSSANOVA
    1. constructs a complete keyset of the molecule
    2. In a loop over all possible roots from the given rootstack

b1. increases order of root site
b2. calls PowerSetGenerator with this order, the complete keyset and the rootkeynr
b3. for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset as the restricted one and each site in the set as the root)
b4. these are merged into a fragment list of keysets

  1. All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return
  1. PowerSetGenerator
    1. initialises UniqueFragments structure
    2. fills edge list via BFS
    3. creates the fragment by calling recursive function SPFragmentGenerator with UniqueFragments structure, 0 as root distance, the edge set, its dimension and the current suborder
    4. Free'ing structure
  2. SPFragmentGenerator (nothing much has changed here)
    1. loops over every possible combination (2dimension of edge set)

a1. inserts current set, if there's still space left

a11. yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root distance+1
a12. no: stores fragment into keyset list by calling InsertFragmentIntoGraph

a2. removes all items added into the snake stack (in UniqueFragments structure) added during level (root distance) and current set

File:
1 edited

Legend:

Unmodified
Added
Removed
  • molecuilder/src/moleculelist.cpp

    re936b3 rc75363  
    2121MoleculeListClass::MoleculeListClass(int NumMolecules, int NumAtoms)
    2222{
    23   TEList = (double*) Malloc(sizeof(double)*NumMolecules, "MoleculeListClass:MoleculeListClass: *TEList");
    2423  ListOfMolecules = (molecule **) Malloc(sizeof(molecule *)*NumMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");
    25   for (int i=0;i<NumMolecules;i++) {
    26     TEList[i] = 0.;
     24  for (int i=0;i<NumMolecules;i++)
    2725    ListOfMolecules[i] = NULL;
    28   }
    2926  NumberOfMolecules = NumMolecules;
    3027  NumberOfTopAtoms = NumAtoms;
     
    3633MoleculeListClass::~MoleculeListClass()
    3734{
    38   cout << Verbose(3) << this << ": Freeing ListOfMolcules and TEList." << endl;
     35  cout << Verbose(3) << this << ": Freeing ListOfMolcules." << endl;
    3936  for (int i=0;i<NumberOfMolecules;i++) {
    4037    if (ListOfMolecules[i] != NULL) { // if NULL don't free
     
    4643  cout << Verbose(4) << "Freeing ListOfMolecules." << endl;
    4744  Free((void **)&ListOfMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");
    48   cout << Verbose(4) << "Freeing TEList." << endl;
    49   Free((void **)&TEList, "MoleculeListClass:MoleculeListClass: *TEList");
    50 };
    51 
     45};
     46
     47/** Compare whether two molecules are equal.
     48 * \param *a molecule one
     49 * \param *n molecule two
     50 * \return lexical value (-1, 0, +1)
     51 */
    5252int MolCompare(const void *a, const void *b)
    5353{
     
    122122};
    123123
    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 
    285124/** Simple output of the pointers in ListOfMolecules.
    286125 * \param *out output stream
     
    295134
    296135/** 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
     136 * \param *out output stream for debugging
    299137 * \param *configuration standard configuration to attach atoms in fragment molecule to.
    300138 * \param *SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config
    301139 * \return true - success (each file was written), false - something went wrong.
    302140 */
    303 bool MoleculeListClass::OutputConfigForListOfFragments(char *prefix, config *configuration, int *SortIndex)
     141bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex)
    304142{
    305143  ofstream outputFragment;
     
    310148  atom *Walker = NULL;
    311149  vector BoxDimension;
    312   char TEFilename[MAXSTRINGSIZE];
    313150  char *FragmentNumber;
    314151  int FragmentCounter = 0;
    315152  ofstream output;
    316   element *runner = NULL;
    317153 
    318154  // store the fragments as config and as xyz
    319155  for(int i=0;i<NumberOfMolecules;i++) {
    320     //if (TEList[i] != 0) {
    321       strcpy(PathBackup, configuration->configpath);
    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);
    351       strcpy(PathBackup, configuration->configpath);
    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 
    385   strcpy(PathBackup, configuration->configpath);
    386   // open file for the total energy factor
    387   sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, TEFACTORSFILE);
    388   output.open(TEFilename, ios::out);
    389   // output TEList (later to file AtomicTEList.dat)
    390   cout << Verbose(2) << "Saving " << prefix << " energy factors ...";
    391   //cout << Verbose(1) << "Final ATEList: ";
    392   //less output << prefix << "TE\t";
    393   for(int i=0;i<NumberOfMolecules;i++) {
    394     //cout << TEList[i] << "\t";
    395     //if (TEList[i] != 0)
    396       output << TEList[i] << "\t";
    397   }
    398   //cout << endl;
    399   output << endl;
     156    // save default path as it is changed for each fragment
     157    strcpy(PathBackup, configuration->GetDefaultPath());
     158
     159    // correct periodic
     160    ListOfMolecules[i]->ScanForPeriodicCorrection(out);
     161
     162    // output xyz file
     163    FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++);
     164    sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
     165    outputFragment.open(FragmentName, ios::out);
     166    *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as XYZ ...";
     167    if (intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment))
     168      *out << " done." << endl;
     169    else
     170      *out << " failed." << endl;
     171    result = result && intermediateResult;
     172    outputFragment.close();
     173    outputFragment.clear();
     174
     175    *out << Verbose(2) << "Contained atoms: ";
     176    Walker = ListOfMolecules[i]->start;
     177    while (Walker->next != ListOfMolecules[i]->end) {
     178      Walker = Walker->next;
     179      *out << Walker->Name << " ";
     180    }
     181    *out << endl;
     182    // prepare output of config file
     183    sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
     184    outputFragment.open(FragmentName, ios::out);
     185    strcpy(PathBackup, configuration->configpath);
     186    sprintf(FragmentName, "%s/%s%s/", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
     187   
     188    // center on edge
     189    ListOfMolecules[i]->CenterEdge(out, &BoxDimension);
     190    ListOfMolecules[i]->SetBoxDimension(&BoxDimension);  // update Box of atoms by boundary
     191    int j = -1;
     192    for (int k=0;k<3;k++) {
     193      j += k+1;
     194      BoxDimension.x[k] = 5.;
     195      ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.;
     196    }
     197    ListOfMolecules[i]->Translate(&BoxDimension);
     198
     199    // also calculate necessary orbitals
     200    ListOfMolecules[i]->CountElements();  // this is a bugfix, atoms should should actually be added correctly to this fragment
     201    ListOfMolecules[i]->CalculateOrbitals(*configuration);
     202   
     203    // change path in config
     204    configuration->SetDefaultPath(FragmentName);
     205    *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as config ...";
     206    if (intermediateResult = configuration->Save(&outputFragment, ListOfMolecules[i]->elemente, ListOfMolecules[i]))
     207      *out << " done." << endl;
     208    else
     209      *out << " failed." << endl;
     210    // restore old config
     211    configuration->SetDefaultPath(PathBackup);
     212   
     213    result = result && intermediateResult;
     214    outputFragment.close();
     215    outputFragment.clear();
     216    Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber");
     217  }
     218
     219  // open KeySet file
     220  sprintf(FragmentName, "%s/%s%s", configuration->configpath,  FRAGMENTPREFIX , KEYSETFILE);
     221  output.open(FragmentName, ios::out);
     222  *out << Verbose(2) << "Saving " << FRAGMENTPREFIX << " key sets of each subgraph ...";
     223  for(int j=0;j<NumberOfMolecules;j++) {
     224    Walker = ListOfMolecules[j]->start;
     225    while(Walker->next != ListOfMolecules[j]->end) {
     226      Walker = Walker->next;       
     227#ifdef ADDHYDROGEN
     228      if ((Walker->GetTrueFather() != NULL) && (Walker->type->Z != 1)) // if there is a real father, prints its index
     229#else
     230      if ((Walker->GetTrueFather() != NULL)) // if there is a real father, prints its index
     231#endif
     232        output <<  Walker->GetTrueFather()->nr << "\t";
     233#ifdef ADDHYDROGEN
     234      else  // otherwise a -1 to indicate an added saturation hydrogen
     235        output << "-1\t";
     236#endif
     237    }
     238    output << endl;
     239  }
    400240  output.close();
    401   cout << " done." << endl;
    402  
    403   // open file for the force factors
    404   sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, FORCESFILE);
    405   output.open(TEFilename, ios::out);
    406   //cout << Verbose(1) << "Final AtomicForcesList: ";
    407   cout << Verbose(2) << "Saving " << prefix << " force factors ...";
    408   //output << prefix << "Forces" << endl;
    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
    420               //cout << "Walker is " << *Walker << " with true father " << *( Walker->GetTrueFather()) << ", its number " << Walker->GetTrueFather()->nr << " and index " << SortIndex[Walker->GetTrueFather()->nr] << "." << endl; 
    421               output <<  SortIndex[Walker->GetTrueFather()->nr] << "\t";
    422             } else  // otherwise a -1 to indicate an added saturation hydrogen
    423               output << "-1\t";
    424           }
    425         }
    426       }
    427     }
    428     //cout << endl << endl;
    429     output << endl;
    430   }
    431   output.close();
    432   cout << " done." << endl;
    433 
    434   // open KeySet file
    435   sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, "KeySets.dat");
    436   output.open(TEFilename, ios::out);
    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
    448           output <<  Walker->GetTrueFather()->nr << "\t";
    449 #ifdef ADDHYDROGEN
    450         else  // otherwise a -1 to indicate an added saturation hydrogen
    451           output << "-1\t";
    452 #endif
    453       }
    454       //cout << endl << endl;
    455       output << endl;
    456     }
    457   output.close();
    458   cout << " done." << endl;
     241  *out << " done." << endl;
    459242 
    460243  // printing final number
    461   cout << "Final number of fragments: " << FragmentCounter << "." << endl;
     244  *out << "Final number of fragments: " << FragmentCounter << "." << endl;
    462245     
    463246  return result;
    464247};
    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 };
    660248
    661249/******************************************* Class MoleculeLeafClass ************************************************/
Note: See TracChangeset for help on using the changeset viewer.