source: src/Formula.cpp@ bf3817

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 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 bf3817 was bf3817, checked in by Frederik Heber <heber@…>, 15 years ago

Added ifdef HAVE_CONFIG and config.h include to each and every cpp file.

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