source: src/Formula.cpp@ d03bb1

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

Added methods to produce formulas from strings

  • Property mode set to 100644
File size: 9.9 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
17using namespace std;
18
19Formula::Formula() :
20 numElements(0)
21{}
22
23Formula::Formula(const Formula &src) :
24 elementCounts(src.elementCounts),
25 numElements(src.numElements)
26{}
27
28Formula::Formula(const string &formula) :
29 numElements(0)
30{
31 fromString(formula);
32}
33
34Formula::~Formula()
35{}
36
37Formula &Formula::operator=(const Formula &rhs){
38 // No self-assignment check needed
39 elementCounts=rhs.elementCounts;
40 numElements=rhs.numElements;
41 return *this;
42}
43
44std::string Formula::toString() const{
45 stringstream sstr;
46 for(const_reverse_iterator iter=rbegin();iter!=rend();++iter){
47 sstr << (*iter).first->symbol << (*iter).second;
48 }
49 return sstr.str();
50}
51
52// quick function used for parsing
53bool isInRange(pair<char,char> range,char character){
54 return range.first<=character && character<=range.second;
55}
56
57void Formula::fromString(const std::string &formula) throw(ParseError){
58 // some constants needed for parsing... Assumes ASCII, change if other encodings are used
59 static const pair<char,char> CapitalLetters = make_pair('A','Z');
60 static const pair<char,char> SmallLetters = make_pair('a','z');
61 static const pair<char,char> Numbers = make_pair('0','9');
62 // clean the formula
63 clear();
64 string::const_iterator end = formula.end(); // will be used frequently
65 for(string::const_iterator it=formula.begin();it!=end;){
66 string shorthand;
67 // Atom names start with a capital letter
68 if(!isInRange(CapitalLetters,(*it)))
69 throw(ParseError(__FILE__,__LINE__));
70 shorthand+=(*it++);
71 // the rest of the name follows
72 while(it!=end && isInRange(SmallLetters,(*it)))
73 shorthand+=(*it++);
74 // now we can count the occurences
75 int count = 0;
76 while(it!=end && isInRange(Numbers,(*it)))
77 count = (count*10) + ((*it++)-Numbers.first);
78 // one is implicit
79 count = (count!=0)?count:1;
80 // done, we can get the next one
81 addElements(shorthand,count);
82 }
83}
84
85bool Formula::checkOut(ostream *output) const{
86 bool result = true;
87 int No = 1;
88
89 if (output != NULL) {
90 *output << "# Ion type data (PP = PseudoPotential, Z = atomic number)" << endl;
91 *output << "#Ion_TypeNr.\tAmount\tZ\tRGauss\tL_Max(PP)L_Loc(PP)IonMass\t# chemical name, symbol" << endl;
92 for(const_iterator iter=begin(); iter!=end();++iter){
93 (*iter).first->No = No;
94 result = result && (*iter).first->Checkout(output, No++, (*iter).second);
95 }
96 return result;
97 } else
98 return false;
99}
100
101unsigned int Formula::getElementCount(){
102 return numElements;
103}
104
105bool Formula::hasElement(const element *element) const{
106 ASSERT(element,"Invalid pointer in Formula::hasElement(element*)");
107 return hasElement(element->getNumber());
108}
109
110bool Formula::hasElement(atomicNumber_t Z) const{
111 ASSERT(Z>0,"Invalid atomic Number");
112 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
113 return elementCounts.size()>=Z && elementCounts[Z-1];
114}
115
116bool Formula::hasElement(const string &shorthand) const{
117 element * element = World::getInstance().getPeriode()->FindElement(shorthand);
118 return hasElement(element);
119}
120
121void Formula::operator+=(const element *element){
122 ASSERT(element,"Invalid pointer in increment of Formula");
123 operator+=(element->getNumber());
124}
125
126void Formula::operator+=(atomicNumber_t Z){
127 ASSERT(Z>0,"Invalid atomic Number");
128 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
129 elementCounts.resize(Z); // No-op when we already have the right size
130 // might need to update number of elements
131 if(!elementCounts[Z-1]){
132 numElements++;
133 }
134 elementCounts[Z-1]++; // atomic numbers start at 1
135}
136
137void Formula::operator+=(const string &shorthand){
138 element * element = World::getInstance().getPeriode()->FindElement(shorthand);
139 operator+=(element);
140}
141
142void Formula::operator-=(const element *element){
143 ASSERT(element,"Invalid pointer in decrement of Formula");
144 operator-=(element->getNumber());
145}
146
147void Formula::operator-=(atomicNumber_t Z){
148 ASSERT(Z>0,"Invalid atomic Number");
149 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
150 ASSERT(elementCounts.size()>=Z && elementCounts[Z-1], "Element not in Formula upon decrement");
151 elementCounts[Z-1]--; // atomic numbers start at 1
152 // might need to update number of elements
153 if(!elementCounts[Z-1]){
154 numElements--;
155 }
156}
157
158void Formula::operator-=(const string &shorthand){
159 element * element = World::getInstance().getPeriode()->FindElement(shorthand);
160 operator-=(element);
161}
162
163void Formula::addElements(const element *element,unsigned int count){
164 ASSERT(element,"Invalid pointer in Formula::addElements(element*)");
165 addElements(element->getNumber(),count);
166}
167
168void Formula::addElements(atomicNumber_t Z,unsigned int count){
169 if(count==0) return;
170 ASSERT(Z>0,"Invalid atomic Number");
171 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
172 elementCounts.resize(Z); // No-op when we already have the right size
173 // might need to update number of elements
174 if(!elementCounts[Z-1]){
175 numElements++;
176 }
177 elementCounts[Z-1]+=count;
178}
179
180void Formula::addElements(const string &shorthand,unsigned int count){
181 element * element = World::getInstance().getPeriode()->FindElement(shorthand);
182 addElements(element,count);
183}
184
185const unsigned int &Formula::operator[](const element *element) const{
186 ASSERT(element,"Invalid pointer in access of Formula");
187 return operator[](element->getNumber());
188}
189
190const unsigned int &Formula::operator[](atomicNumber_t Z) const{
191 ASSERT(Z>0,"Invalid atomic Number");
192 ASSERT(World::getInstance().getPeriode()->FindElement(Z),"No Element with this number in Periodentafel");
193 elementCounts.resize(Z); // No-op when we already have the right size
194 return elementCounts[Z-1]; // atomic numbers start at 1
195}
196
197const unsigned int &Formula::operator[](string shorthand) const{
198 element * element = World::getInstance().getPeriode()->FindElement(shorthand);
199 return operator[](element);
200}
201
202bool Formula::operator==(const Formula &rhs) const{
203 // quick check... number of elements used
204 if(numElements != rhs.numElements){
205 return false;
206 }
207 // slow check: all elements
208 // direct access to internal structure means all element-counts have to be compared
209 // this avoids access to periodentafel to find elements though and is probably faster
210 // in total
211 return equal(elementCounts.begin(),
212 elementCounts.end(),
213 rhs.elementCounts.begin());
214}
215
216bool Formula::operator!=(const Formula &rhs) const{
217 return !operator==(rhs);
218}
219
220Formula::iterator Formula::begin(){
221 return iterator(elementCounts,0);
222}
223Formula::const_iterator Formula::begin() const{
224 return const_iterator(elementCounts,0);
225}
226Formula::iterator Formula::end(){
227 return iterator(elementCounts);
228}
229Formula::const_iterator Formula::end() const{
230 return const_iterator(elementCounts);
231}
232
233Formula::reverse_iterator Formula::rbegin(){
234 return reverse_iterator(end());
235}
236Formula::const_reverse_iterator Formula::rbegin() const{
237 return const_reverse_iterator(end());
238}
239Formula::reverse_iterator Formula::rend(){
240 return reverse_iterator(begin());
241}
242Formula::const_reverse_iterator Formula::rend() const{
243 return const_reverse_iterator(begin());
244}
245
246void Formula::clear(){
247 elementCounts.clear();
248 numElements = 0;
249}
250
251/**************** Iterator structure ********************/
252
253template <class result_type>
254Formula::_iterator<result_type>::_iterator(set_t &_set) :
255 set(&_set)
256{
257 pos=set->size();
258}
259
260template <class result_type>
261Formula::_iterator<result_type>::_iterator(set_t &_set,size_t _pos) :
262 set(&_set),pos(_pos)
263{
264 ASSERT(pos<=set->size(),"invalid position in iterator construction");
265 while(pos<set->size() && (*set)[pos]!=0) ++pos;
266}
267
268template <class result_type>
269Formula::_iterator<result_type>::~_iterator(){}
270
271template <class result_type>
272Formula::_iterator<result_type>&
273Formula::_iterator<result_type>::operator=(const _iterator<result_type> &rhs){
274 set=rhs.set;
275 pos=rhs.pos;
276 return *this;
277}
278
279template <class result_type>
280bool
281Formula::_iterator<result_type>::operator==(const _iterator<result_type> &rhs){
282 return set==rhs.set && pos==rhs.pos;
283}
284
285template <class result_type>
286bool
287Formula::_iterator<result_type>::operator!=(const _iterator<result_type> &rhs){
288 return !operator==(rhs);
289}
290
291template <class result_type>
292Formula::_iterator<result_type>
293Formula::_iterator<result_type>::operator++(){
294 ASSERT(pos!=set->size(),"Incrementing Formula::iterator beyond end");
295 while(pos<set->size() && (*set)[pos]!=0) ++pos;
296 return *this;
297}
298
299template <class result_type>
300Formula::_iterator<result_type>
301Formula::_iterator<result_type>::operator--(){
302 ASSERT(pos!=0,"Decrementing Formula::iterator beyobd begin");
303 while(pos>0 && (*set)[pos]!=0) ++pos;
304 return *this;
305}
306
307template <class result_type>
308result_type
309Formula::_iterator<result_type>::operator*(){
310 element *element = World::getInstance().getPeriode()->FindElement(pos+1);
311 ASSERT(element,"Element with position of iterator not found");
312 return make_pair(element,(*set)[pos]);
313}
314
315template <class result_type>
316result_type*
317Formula::_iterator<result_type>::operator->(){
318 // no one can keep this value around, so a static is ok to avoid temporaries
319 static value_type value=make_pair(reinterpret_cast<element*>(0),0); // no default constructor for std::pair
320 element *element = World::getInstance().getPeriode()->FindElement(pos+1);
321 ASSERT(element,"Element with position of iterator not found");
322 value = make_pair(element,(*set)[pos]);
323 return &value;
324}
325
326/********************** I/O of Formulas ************************************************/
327
328std::ostream &operator<<(std::ostream &ost,const Formula &formula){
329 ost << formula.toString();
330 return ost;
331}
Note: See TracBrowser for help on using the repository browser.