source: molecuilder/src/atom.cpp@ c75363

Last change on this file since c75363 was c75363, checked in by Frederik Heber <heber@…>, 17 years ago

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

  • Property mode set to 100644
File size: 10.8 KB
Line 
1/** \file atom.cpp
2 *
3 * Function implementations for the class atom.
4 *
5 */
6
7#include "molecules.hpp"
8
9/************************************* Functions for class atom *************************************/
10
11/** Constructor of class atom.
12 */
13atom::atom()
14{
15 Name = NULL;
16 previous = NULL;
17 next = NULL;
18 father = this; // generally, father is itself
19 Ancestor = NULL;
20 type = NULL;
21 sort = NULL;
22 FixedIon = 0;
23 nr = -1;
24 GraphNr = -1;
25 ComponentNr = NULL;
26 SeparationVertex = false;
27 LowpointNr = -1;
28 AdaptiveOrder = 0;
29};
30
31/** Destructor of class atom.
32 */
33atom::~atom()
34{
35 Free((void **)&Name, "atom::~atom: *Name");
36 Free((void **)&ComponentNr, "atom::~atom: *ComponentNr");
37};
38
39
40/** Climbs up the father list until NULL, last is returned.
41 * \return true father, i.e. whose father points to itself, NULL if it could not be found or has none (added hydrogen)
42 */
43atom *atom::GetTrueFather()
44{
45 atom *walker = this;
46 do {
47 if (walker == walker->father) // top most father is the one that points on itself
48 break;
49 walker = walker->father;
50 } while (walker != NULL);
51 return walker;
52};
53
54/** Output of a single atom.
55 * \param ElementNo cardinal number of the element
56 * \param AtomNo cardinal number among these atoms of the same element
57 * \param *out stream to output to
58 */
59bool atom::Output(int ElementNo, int AtomNo, ofstream *out) const
60{
61 if (out != NULL) {
62 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t" << fixed << setprecision(9) << showpoint;
63 *out << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2];
64 *out << "\t" << FixedIon;
65 if (v.Norm() > MYEPSILON)
66 *out << "\t" << scientific << setprecision(6) << v.x[0] << "\t" << v.x[1] << "\t" << v.x[2] << "\t";
67 *out << " # Number in molecule " << nr << endl;
68 return true;
69 } else
70 return false;
71};
72
73/** Output of a single atom as one lin in xyz file.
74 * \param *out stream to output to
75 */
76bool atom::OutputXYZLine(ofstream *out) const
77{
78 if (out != NULL) {
79 *out << type->symbol << "\t" << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2] << "\t" << endl;
80 return true;
81 } else
82 return false;
83};
84
85ostream & operator << (ostream &ost, atom &a)
86{
87 ost << "[" << a.Name << "|" << &a << "]";
88 return ost;
89};
90
91/** Compares the indices of \a this atom with a given \a ptr.
92 * \param ptr atom to compare index against
93 * \return true - this one's is smaller, false - not
94 */
95bool atom::Compare(atom &ptr)
96{
97 if (nr < ptr.nr)
98 return true;
99 else
100 return false;
101};
102
103bool operator < (atom &a, atom &b)
104{
105 return a.Compare(b);
106};
107
108/******************************** Functions for class AtomStackClass ********************************/
109
110/** Constructor of class AtomStackClass.
111 */
112AtomStackClass::AtomStackClass(int dimension)
113{
114 CurrentLastEntry = 0;
115 CurrentFirstEntry = 0;
116 NextFreeField = 0;
117 EntryCount = dimension;
118 StackList = (atom **) Malloc(sizeof(atom *)*EntryCount, "AtomStackClass::AtomStackClass: **StackList");
119};
120
121/** Destructor of class AtomStackClass.
122 */
123AtomStackClass::~AtomStackClass()
124{
125 Free((void **)&StackList, "AtomStackClass::AtomStackClass: **StackList");
126};
127
128/** Pushes an object onto the stack.
129 * \param *object atom to be pushed on stack
130 * \return true - sucess, false - failure, meaning stack field was occupied
131 */
132bool AtomStackClass::Push(atom *object)
133{
134 if (!IsFull()) { // check whether free field is really not occupied
135 StackList[NextFreeField] = object;
136 CurrentLastEntry = NextFreeField;
137 NextFreeField = (NextFreeField + 1) % EntryCount; // step on to next free field
138 return true;
139 } else {
140 cerr << "ERROR: Stack is full, " << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tNextFreeField " << NextFreeField << "\tEntryCount " << EntryCount << "!" << endl;
141 return false;
142 }
143};
144
145/** Pops first/oldest atom from stack.
146 * First in, last out.
147 * \return atom pointer from stack, NULL - if failure (no atom pointer in field)
148 */
149atom *AtomStackClass::PopFirst()
150{
151 atom *Walker = NULL;
152 if (!IsEmpty()) {
153 Walker = StackList[CurrentFirstEntry];
154 if (Walker == NULL)
155 cerr << "ERROR: Stack's field is empty!" << endl;
156 StackList[CurrentFirstEntry] = NULL;
157 if (CurrentFirstEntry != CurrentLastEntry) { // hasn't last item been popped as well?
158 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)
159 } else {
160 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)
161 CurrentLastEntry = CurrentFirstEntry;
162 }
163 } else
164 cerr << "ERROR: Stack is empty!" << endl;
165 return Walker;
166};
167
168/** Pops last atom from stack.
169 * First in, first out.
170 * \return atom pointer from stack, NULL - if failure (no atom pointer in field)
171 */
172atom *AtomStackClass::PopLast()
173{
174 atom *Walker = NULL;
175 if (!IsEmpty()) {
176 Walker = StackList[CurrentLastEntry];
177 StackList[CurrentLastEntry] = NULL;
178 if (Walker == NULL)
179 cerr << "ERROR: Stack's field is empty!" << endl;
180 NextFreeField = CurrentLastEntry;
181 if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack
182 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; // step back from current free field to last (modulo does not work in -1, thus go EntryCount-1 instead)
183 } else {
184 cerr << "ERROR: Stack is empty!" << endl;
185 }
186 return Walker;
187};
188
189/** Removes a certain item from the stack.
190 * Item is seeked between \a CurrentFirstEntry and \a CurrentLastEntry, if found, place in stack is NULL'd and
191 * all subsequent items shifted by one position downward (with wrapping taken into account).
192 * \param *ptr adress of item
193 * \return true - item was removed, false - item was not found
194 */
195bool AtomStackClass::RemoveItem(atom *ptr)
196{
197 bool found = false;
198 cout << Verbose(5) << "First " << CurrentFirstEntry<< "\tLast " << CurrentLastEntry<< "\tNext " << NextFreeField<< "\tCount " << EntryCount<< "." << endl;
199 int i=CurrentFirstEntry;
200 if (!IsEmpty())
201 do {
202 if (StackList[i] == ptr) { // if item found, remove
203 cout << Verbose(5) << "Item " << *ptr << " was number " << i << " on stack, removing it." << endl;
204 found = true;
205 StackList[i] = NULL;
206 }
207 if ((found) && (StackList[i] != NULL)) { // means we have to shift (and not the removed item)
208 if (i == 0) { // we are down to first item in stack, have to put onto last item
209 cout << Verbose(5) << "Shifting item 0 to place " << EntryCount-1 << "." << endl;
210 StackList[EntryCount-1] = StackList[0];
211 } else {
212 cout << Verbose(5) << "Shifting item " << i << " to place " << i-1 << "." << endl;
213 StackList[i-1] = StackList[i];
214 }
215 }
216 i=((i + 1) % EntryCount); // step on
217 } while (i!=NextFreeField);
218 else
219 cerr << "ERROR: Stack is already empty!" << endl;
220 if (found) {
221 NextFreeField = CurrentLastEntry;
222 if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack
223 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount;
224 }
225 return found;
226};
227
228/** Test the functionality of the stack.
229 * \param *out ofstream for debugging
230 * \param *test one item to put on stack
231 * \return true - all tests worked correctly
232 */
233void AtomStackClass::TestImplementation(ofstream *out, atom *test)
234{
235 atom *Walker = test;
236 *out << Verbose(1) << "Testing the snake stack..." << endl;
237 for (int i=0;i<EntryCount;i++) {
238 *out << Verbose(2) << "Filling " << i << "th element of stack." << endl;
239 Push(Walker);
240 Walker=Walker->next;
241 }
242 *out << endl;
243 Output(out);
244 if (IsFull())
245 *out << "Stack is full as supposed to be!" << endl;
246 else
247 *out << "ERROR: Stack is not as full as supposed to be!" << endl;
248 //if (StackList[(EntryCount+1)/2] != NULL) {
249 *out << "Removing element in the middle ..." << endl;
250 RemoveItem(StackList[(EntryCount+1)/2]);
251 Output(out);
252 //}
253 //if (StackList[CurrentFirstEntry] != NULL) {
254 *out << "Removing first element ..." << endl;
255 RemoveItem(StackList[CurrentFirstEntry]);
256 Output(out);
257 //}
258 //if (StackList[CurrentLastEntry] != NULL) {
259 *out << "Removing last element ..." << endl;
260 RemoveItem(StackList[CurrentLastEntry]);
261 Output(out);
262 //}
263 *out << "Clearing stack ... " << endl;
264 ClearStack();
265 Output(out);
266 if (IsEmpty())
267 *out << "Stack is empty as supposed to be!" << endl;
268 else
269 *out << "ERROR: Stack is not as empty as supposed to be!" << endl;
270 *out << "done." << endl;
271};
272
273/** Puts contents of stack into ofstream \a *out.
274 * \param *out ofstream for output
275 */
276void AtomStackClass::Output(ofstream *out) const
277{
278 *out << "Contents of Stack: ";
279 for(int i=0;i<EntryCount;i++) {
280 *out << "\t";
281 if (i == CurrentFirstEntry)
282 *out << " 1";
283 if (i == CurrentLastEntry)
284 *out << " "<< EntryCount;
285 if (i == NextFreeField)
286 *out << " F";
287 *out << ": " << StackList[i];
288 }
289 *out << endl;
290};
291
292/** Checks whether stack is empty.
293 * Simply checks whether AtomStackClass::NextFreeField is equal to AtomStackClass::CurrentFirstEntry and
294 * AtomStackClass::CurrentFirstEntry is equal to AtomStackClass::CurrentLastEntry.
295 * \return true - empty, false - not
296 */
297bool AtomStackClass::IsEmpty()
298{
299 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry == CurrentFirstEntry));
300};
301
302/** Checks whether stack is full.
303 * Simply checks whether AtomStackClass::NextFreeField is equal to AtomStackClass::CurrentFirstEntry and
304 * AtomStackClass::CurrentFirstEntry is _not_ equal to AtomStackClass::CurrentLastEntry.
305 * \return true - full, false - not
306 */
307bool AtomStackClass::IsFull()
308{
309 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry != CurrentFirstEntry));
310};
311
312/** Returns number of items on stack.
313 * Simply returns difference between AtomStackClass::Stacklist entry AtomStackClass::CurrentEntry-1.
314 * \return number of items on stack
315 * \warning will never return correct item count if stack is full, i.e. count would be AtomStackClass::EntryCount.
316 */
317int AtomStackClass::ItemCount()
318{
319 //cout << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tEntryCount " << EntryCount << "." << endl;
320 return((NextFreeField + (EntryCount - CurrentFirstEntry)) % EntryCount);
321};
322
323/** Clears the stack from all atoms.
324 * \return true - sucess, false - failure
325 */
326void AtomStackClass::ClearStack()
327{
328 for(int i=0;i<EntryCount; i++)
329 StackList[i] = NULL;
330 CurrentFirstEntry = 0;
331 CurrentLastEntry = 0;
332 NextFreeField = 0;
333};
334
Note: See TracBrowser for help on using the repository browser.