source: src/Formula.cpp@ 9d5803

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 9d5803 was 9d5803, checked in by Tillmann Crueger <crueger@…>, 15 years ago

Added a method that allows adding complete formulas to one another

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