source: src/Formula.cpp@ bbbad5

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 Candidate_v1.7.0 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since bbbad5 was bbbad5, checked in by Frederik Heber <heber@…>, 15 years ago

Added MemDebug.hpp to each and every .cpp file (were it was still missing).

  • is topmost include and separated by a newline from rest.
  • NOTE: QT includes have to appear before MemDebug.hpp due to strange magic happening therein.
  • Property mode set to 100644
File size: 14.4 KB
Line 
1/*
2 * Formula.cpp
3 *
4 * Created on: Jul 21, 2010
5 * Author: crueger
6 */
7
8#include "Helpers/MemDebug.hpp"
9
10#include "Formula.hpp"
11
12#include <sstream>
13
14#include "World.hpp"
15#include "periodentafel.hpp"
16#include "element.hpp"
17#include "Helpers/Assert.hpp"
18#include "Helpers/Range.hpp"
19
20using namespace std;
21
22Formula::Formula() :
23 numElements(0)
24{}
25
26Formula::Formula(const Formula &src) :
27 elementCounts(src.elementCounts),
28 numElements(src.numElements)
29{}
30
31Formula::Formula(const string &formula) :
32 numElements(0)
33{
34 fromString(formula);
35}
36
37Formula::~Formula()
38{}
39
40Formula &Formula::operator=(const Formula &rhs){
41 // No self-assignment check needed
42 elementCounts=rhs.elementCounts;
43 numElements=rhs.numElements;
44 return *this;
45}
46
47std::string Formula::toString() const{
48 stringstream sstr;
49 for(const_iterator iter=end();iter!=begin();){
50 --iter;
51 sstr << (*iter).first->getSymbol();
52 if((*iter).second>1)
53 sstr << (*iter).second;
54 }
55 return sstr.str();
56}
57
58void Formula::fromString(const std::string &formula) throw(ParseError){
59 // make this transactional, in case an error is thrown
60 Formula res;
61 string::const_iterator begin = formula.begin();
62 string::const_iterator end = formula.end();
63 res.parseFromString(begin,end,static_cast<char>(0));
64 (*this)=res;
65}
66
67int Formula::parseMaybeNumber(string::const_iterator &it,string::const_iterator &end) throw(ParseError){
68 static const range<char> Numbers = makeRange('0',static_cast<char>('9'+1));
69 int count = 0;
70 while(it!=end && Numbers.isInRange(*it))
71 count = (count*10) + ((*it++)-Numbers.first);
72 // one is implicit
73 count = (count!=0)?count:1;
74 return count;
75}
76
77void Formula::parseFromString(string::const_iterator &it,string::const_iterator &end,char delimiter) throw(ParseError){
78 // some constants needed for parsing... Assumes ASCII, change if other encodings are used
79 static const range<char> CapitalLetters = makeRange('A',static_cast<char>('Z'+1));
80 static const range<char> SmallLetters = makeRange('a',static_cast<char>('z'+1));
81 map<char,char> delimiters;
82 delimiters['('] = ')';
83 delimiters['['] = ']';
84 // clean the formula
85 clear();
86 for(/*send from above*/;it!=end && *it!=delimiter;/*updated in loop*/){
87 // we might have a sub formula
88 if(delimiters.count(*it)){
89 Formula sub;
90 char nextdelim=delimiters[*it];
91 sub.parseFromString(++it,end,nextdelim);
92 if(!sub.getElementCount()){
93 throw(ParseError(__FILE__,__LINE__));
94 }
95 int count = parseMaybeNumber(++it,end);
96 addFormula(sub,count);
97 continue;
98 }
99 string shorthand;
100 // Atom names start with a capital letter
101 if(!CapitalLetters.isInRange(*it))
102 throw(ParseError(__FILE__,__LINE__));
103 shorthand+=(*it++);
104 // the rest of the name follows
105 while(it!=end && SmallLetters.isInRange(*it))
106 shorthand+=(*it++);
107 int count = parseMaybeNumber(it,end);
108 // test if the shorthand exists
109 if(!World::getInstance().getPeriode()->FindElement(shorthand))
110 throw(ParseError(__FILE__,__LINE__));
111 // done, we can get the next one
112 addElements(shorthand,count);
113 }
114 if(it==end && delimiter!=0){
115 throw(ParseError(__FILE__,__LINE__));
116 }
117}
118
119bool Formula::checkOut(ostream *output) const{
120 bool result = true;
121 int No = 1;
122
123 if (output != NULL) {
124 *output << "# Ion type data (PP = PseudoPotential, Z = atomic number)" << endl;
125 *output << "#Ion_TypeNr.\tAmount\tZ\tRGauss\tL_Max(PP)L_Loc(PP)IonMass\t# chemical name, symbol" << endl;
126 for(const_iterator iter=begin(); iter!=end();++iter){
127 result = result && (*iter).first->Checkout(output, No++, (*iter).second);
128 }
129 return result;
130 } else
131 return false;
132}
133
134unsigned int Formula::getElementCount() const{
135 return numElements;
136}
137
138bool Formula::hasElement(const element *element) const{
139 ASSERT(element,"Invalid pointer in Formula::hasElement(element*)");
140 return hasElement(element->getNumber());
141}
142
143bool Formula::hasElement(atomicNumber_t Z) const{
144 ASSERT(Z>0,"Invalid atomic Number");
145 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
146 return elementCounts.size()>=Z && elementCounts[Z-1];
147}
148
149bool Formula::hasElement(const string &shorthand) const{
150 const element * element = World::getInstance().getPeriode()->FindElement(shorthand);
151 return hasElement(element);
152}
153
154void Formula::operator+=(const element *element){
155 ASSERT(element,"Invalid pointer in increment of Formula");
156 operator+=(element->getNumber());
157}
158
159void Formula::operator+=(atomicNumber_t Z){
160 ASSERT(Z>0,"Invalid atomic Number");
161 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
162 elementCounts.resize(max<atomicNumber_t>(Z,elementCounts.size()),0); // No-op when we already have the right size
163 // might need to update number of elements
164 if(!elementCounts[Z-1]){
165 numElements++;
166 }
167 elementCounts[Z-1]++; // atomic numbers start at 1
168}
169
170void Formula::operator+=(const string &shorthand){
171 const element * element = World::getInstance().getPeriode()->FindElement(shorthand);
172 operator+=(element);
173}
174
175void Formula::operator-=(const element *element){
176 ASSERT(element,"Invalid pointer in decrement of Formula");
177 operator-=(element->getNumber());
178}
179
180void Formula::operator-=(atomicNumber_t Z){
181 ASSERT(Z>0,"Invalid atomic Number");
182 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
183 ASSERT(elementCounts.size()>=Z && elementCounts[Z-1], "Element not in Formula upon decrement");
184 elementCounts[Z-1]--; // atomic numbers start at 1
185 // might need to update number of elements
186 if(!elementCounts[Z-1]){
187 numElements--;
188 // resize the Array if this was at the last position
189 if(Z==elementCounts.size()){
190 // find the first element from the back that is not equal to zero
191 set_t::reverse_iterator riter = find_if(elementCounts.rbegin(),
192 elementCounts.rend(),
193 bind1st(not_equal_to<mapped_type>(),0));
194 // see how many elements are in this range
195 set_t::reverse_iterator::difference_type diff = riter - elementCounts.rbegin();
196 elementCounts.resize(elementCounts.size()-diff);
197 }
198 }
199}
200
201void Formula::operator-=(const string &shorthand){
202 const element * element = World::getInstance().getPeriode()->FindElement(shorthand);
203 operator-=(element);
204}
205
206void Formula::addElements(const element *element,unsigned int count){
207 ASSERT(element,"Invalid pointer in Formula::addElements(element*)");
208 addElements(element->getNumber(),count);
209}
210
211void Formula::addElements(atomicNumber_t Z,unsigned int count){
212 if(count==0) return;
213 ASSERT(Z>0,"Invalid atomic Number");
214 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
215 elementCounts.resize(max<atomicNumber_t>(Z,elementCounts.size()),0); // No-op when we already have the right size
216 // might need to update number of elements
217 if(!elementCounts[Z-1]){
218 numElements++;
219 }
220 elementCounts[Z-1]+=count;
221}
222
223void Formula::addElements(const string &shorthand,unsigned int count){
224 const element * element = World::getInstance().getPeriode()->FindElement(shorthand);
225 addElements(element,count);
226}
227
228void Formula::addFormula(const Formula &formula,unsigned int n){
229 for(Formula::const_iterator iter=formula.begin();iter!=formula.end();++iter){
230 this->addElements(iter->first,iter->second*n);
231 }
232}
233
234enumeration<Formula::key_type> Formula::enumerateElements() const{
235 enumeration<key_type> res(1);
236 for(Formula::const_iterator iter=begin();iter!=end();++iter){
237 res.add(iter->first);
238 }
239 return res;
240}
241
242const unsigned int Formula::operator[](const element *element) const{
243 ASSERT(element,"Invalid pointer in access of Formula");
244 return operator[](element->getNumber());
245}
246
247const unsigned int Formula::operator[](atomicNumber_t Z) const{
248 ASSERT(Z>0,"Invalid atomic Number");
249 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
250 if(elementCounts.size()<Z)
251 return 0;
252 return elementCounts[Z-1]; // atomic numbers start at 1
253}
254
255const unsigned int Formula::operator[](string shorthand) const{
256 const element * element = World::getInstance().getPeriode()->FindElement(shorthand);
257 return operator[](element);
258}
259
260bool Formula::operator==(const Formula &rhs) const{
261 // quick check... number of elements used
262 if(numElements != rhs.numElements){
263 return false;
264 }
265 // second quick check, size of vectors (== last element in formula)
266 if(elementCounts.size()!=rhs.elementCounts.size()){
267 return false;
268 }
269 // slow check: all elements
270 // direct access to internal structure means all element-counts have to be compared
271 // this avoids access to periodentafel to find elements though and is probably faster
272 // in total
273 return equal(elementCounts.begin(),
274 elementCounts.end(),
275 rhs.elementCounts.begin());
276}
277
278bool Formula::operator!=(const Formula &rhs) const{
279 return !operator==(rhs);
280}
281
282Formula::iterator Formula::begin(){
283 return iterator(elementCounts,0);
284}
285Formula::const_iterator Formula::begin() const{
286 // this is the only place where this is needed, so this is better than making it mutable
287 return const_iterator(const_cast<set_t&>(elementCounts),0);
288}
289Formula::iterator Formula::end(){
290 return iterator(elementCounts);
291}
292Formula::const_iterator Formula::end() const{
293 // this is the only place where this is needed, so this is better than making it mutable
294 return const_iterator(const_cast<set_t&>(elementCounts));
295}
296
297void Formula::clear(){
298 elementCounts.clear();
299 numElements = 0;
300}
301
302/**************** Iterator structure ********************/
303
304template <class result_type>
305Formula::_iterator<result_type>::_iterator(set_t &_set) :
306 set(&_set)
307{
308 pos=set->size();
309}
310
311template <class result_type>
312Formula::_iterator<result_type>::_iterator(set_t &_set,size_t _pos) :
313 set(&_set),pos(_pos)
314{
315 ASSERT(pos<=set->size(),"invalid position in iterator construction");
316 while(pos<set->size() && (*set)[pos]==0) ++pos;
317}
318
319template <class result_type>
320Formula::_iterator<result_type>::_iterator(const _iterator &rhs) :
321 set(rhs.set),pos(rhs.pos)
322{}
323
324template <class result_type>
325Formula::_iterator<result_type>::~_iterator(){}
326
327template <class result_type>
328Formula::_iterator<result_type>&
329Formula::_iterator<result_type>::operator=(const _iterator<result_type> &rhs){
330 set=rhs.set;
331 pos=rhs.pos;
332 return *this;
333}
334
335template <class result_type>
336bool
337Formula::_iterator<result_type>::operator==(const _iterator<result_type> &rhs){
338 return set==rhs.set && pos==rhs.pos;
339}
340
341template <class result_type>
342bool
343Formula::_iterator<result_type>::operator!=(const _iterator<result_type> &rhs){
344 return !operator==(rhs);
345}
346
347template <class result_type>
348Formula::_iterator<result_type>
349Formula::_iterator<result_type>::operator++(){
350 ASSERT(pos!=set->size(),"Incrementing Formula::iterator beyond end");
351 pos++;
352 while(pos<set->size() && (*set)[pos]==0) ++pos;
353 return *this;
354}
355
356template <class result_type>
357Formula::_iterator<result_type>
358Formula::_iterator<result_type>::operator++(int){
359 Formula::_iterator<result_type> retval = *this;
360 ++(*this);
361 return retval;
362}
363
364template <class result_type>
365Formula::_iterator<result_type>
366Formula::_iterator<result_type>::operator--(){
367 ASSERT(pos!=0,"Decrementing Formula::iterator beyond begin");
368 pos--;
369 while(pos>0 && (*set)[pos]==0) --pos;
370 return *this;
371}
372
373template <class result_type>
374Formula::_iterator<result_type>
375Formula::_iterator<result_type>::operator--(int){
376 Formula::_iterator<result_type> retval = *this;
377 --(*this);
378 return retval;
379}
380
381template <class result_type>
382result_type
383Formula::_iterator<result_type>::operator*(){
384 const element *element = World::getInstance().getPeriode()->FindElement(pos+1);
385 ASSERT(element,"Element with position of iterator not found");
386 return make_pair(element,(*set)[pos]);
387}
388
389template <class result_type>
390result_type*
391Formula::_iterator<result_type>::operator->(){
392 // no one can keep this value around, so a static is ok to avoid temporaries
393 static value_type value=make_pair(reinterpret_cast<element*>(0),0); // no default constructor for std::pair
394 const element *element = World::getInstance().getPeriode()->FindElement(pos+1);
395 ASSERT(element,"Element with position of iterator not found");
396 value = make_pair(element,(*set)[pos]);
397 return &value;
398}
399
400// explicit instantiation of all iterator template methods
401// this is quite ugly, but there is no better way unless we expose iterator implementation
402
403// instantiate Formula::iterator
404template Formula::iterator::_iterator(set_t&);
405template Formula::iterator::_iterator(set_t&,size_t);
406template Formula::iterator::_iterator(const Formula::iterator&);
407template Formula::iterator::~_iterator();
408template Formula::iterator &Formula::iterator::operator=(const Formula::iterator&);
409template bool Formula::iterator::operator==(const Formula::iterator&);
410template bool Formula::iterator::operator!=(const Formula::iterator&);
411template Formula::iterator Formula::iterator::operator++();
412template Formula::iterator Formula::iterator::operator++(int);
413template Formula::iterator Formula::iterator::operator--();
414template Formula::iterator Formula::iterator::operator--(int);
415template Formula::value_type Formula::iterator::operator*();
416template Formula::value_type *Formula::iterator::operator->();
417
418// instantiate Formula::const_iterator
419template Formula::const_iterator::_iterator(set_t&);
420template Formula::const_iterator::_iterator(set_t&,size_t);
421template Formula::const_iterator::_iterator(const Formula::const_iterator&);
422template Formula::const_iterator::~_iterator();
423template Formula::const_iterator &Formula::const_iterator::operator=(const Formula::const_iterator&);
424template bool Formula::const_iterator::operator==(const Formula::const_iterator&);
425template bool Formula::const_iterator::operator!=(const Formula::const_iterator&);
426template Formula::const_iterator Formula::const_iterator::operator++();
427template Formula::Formula::const_iterator Formula::const_iterator::operator++(int);
428template Formula::Formula::const_iterator Formula::const_iterator::operator--();
429template Formula::Formula::const_iterator Formula::const_iterator::operator--(int);
430template const Formula::value_type Formula::const_iterator::operator*();
431template const Formula::value_type *Formula::const_iterator::operator->();
432
433/********************** I/O of Formulas ************************************************/
434
435std::ostream &operator<<(std::ostream &ost,const Formula &formula){
436 ost << formula.toString();
437 return ost;
438}
Note: See TracBrowser for help on using the repository browser.