source: src/Formula.cpp@ 38032a

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 38032a was ed26ae, checked in by Frederik Heber <heber@…>, 13 years ago

Renamed calls to element::getNumber() -> ::getAtomicNumber().

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