source: src/Parser/XmlParser.cpp@ d2596b

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

Added XmlParser for parsing configurations for ScaFaCoS generic test code.

  • XML is parsed via pugixml which is placed in subfolder pugixml in src/Parser.
  • NOTE: pugixml does not import/export double with high enough precision. Hence, we always obtain strings and convert them ourselves.
  • also added unit test on the new parser.
  • NOTE: Unit test is failing as charges are not yet written correctly, hence marked as XFAIL.
  • Property mode set to 100644
File size: 9.4 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2012 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * XmlParser.cpp
10 *
11 * Created on: Mar 23, 2012
12 * Author: heber
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20#include "CodePatterns/MemDebug.hpp"
21
22#include <limits>
23#include <vector>
24
25#include "CodePatterns/Log.hpp"
26#include "CodePatterns/Verbose.hpp"
27
28#include "XmlParser.hpp"
29
30#include "Atom/atom.hpp"
31#include "Box.hpp"
32#include "Element/element.hpp"
33#include "Element/periodentafel.hpp"
34#include "molecule.hpp"
35#include "MoleculeListClass.hpp"
36#include "World.hpp"
37
38#include "Parser/pugixml/pugixml.hpp"
39
40// declare specialized static variables
41const std::string FormatParserTrait<xml>::name = "xml";
42const std::string FormatParserTrait<xml>::suffix = "xml";
43const ParserTypes FormatParserTrait<xml>::type = xml;
44
45const char *box_axis[NDIM] = { "box_a", "box_b", "box_c" };
46
47/**
48 * Constructor.
49 */
50FormatParser< xml >::FormatParser() :
51 FormatParser_common(NULL)
52{}
53
54/**
55 * Destructor.
56 */
57FormatParser< xml >::~FormatParser()
58{}
59
60Vector toVector(const std::string &value)
61{
62 std::stringstream inputstream(value);
63 Vector returnVector;
64 for (size_t i=0;i<NDIM;++i)
65 inputstream >> std::setprecision(16) >> returnVector[i];
66 return returnVector;
67}
68
69double toDouble(const std::string &value)
70{
71 std::stringstream inputstream(value);
72 double returnDouble;
73 inputstream >> std::setprecision(16) >> returnDouble;
74 return returnDouble;
75}
76
77std::string fromVector(const Vector&a)
78{
79 std::stringstream returnstring;
80 for (size_t i=0;i<NDIM;++i) {
81 returnstring << std::setprecision(16) << a[i];
82 if (i != NDIM-1)
83 returnstring << std::string(" ");
84 }
85 return returnstring.str();
86}
87
88std::string fromDouble(const double &a)
89{
90 std::stringstream returnstring;
91 returnstring << std::setprecision(16) << a;
92 return returnstring.str();
93}
94
95std::string fromBoolean(const bool c[])
96{
97 std::stringstream returnstring;
98 for (size_t i=0;i<NDIM;++i) {
99 returnstring << (c[i] ? std::string("1") : std::string("0"));
100 if (i != NDIM-1)
101 returnstring << std::string(" ");
102 }
103 return returnstring.str();
104}
105
106/**
107 * Loads an XYZ file into the World.
108 *
109 * \param XYZ file
110 */
111void FormatParser< xml >::load(std::istream* file)
112{
113 // create the molecule
114 molecule * const newmol = World::getInstance().createMolecule();
115 newmol->ActiveFlag = true;
116 // TODO: Remove the insertion into molecule when saving does not depend on them anymore. Also, remove molecule.hpp include
117 World::getInstance().getMolecules()->insert(newmol);
118
119 // load file into xml tree
120 pugi::xml_document doc;
121 doc.load(*file);
122
123 // header
124 pugi::xml_node scafacos_test = doc.root().child("scafacos_test");
125 data.name = toString(scafacos_test.attribute("name").value());
126 data.description = toString(scafacos_test.attribute("description").value());
127 data.reference_method = toString(scafacos_test.attribute("reference_method").value());
128 data.error_potential = scafacos_test.attribute("error_potential").as_double();
129 data.error_field = scafacos_test.attribute("error_field").as_double();
130 LOG(1, "INFO: scafacos_test.name is '" << data.name << "'.");
131 newmol->setName(data.name);
132
133 // configuration information
134 pugi::xml_node configuration = scafacos_test.child("configuration");
135 data.config.offset = toVector(configuration.attribute("offset").value());
136 for (size_t i=0; i<NDIM; ++i)
137 data.config.box.column(i) = toVector(configuration.attribute(box_axis[i]).value());
138 World::getInstance().getDomain().setM(data.config.box);
139 {
140 std::stringstream inputstream(configuration.attribute("periodicity").value());
141 for (size_t i=0; i<NDIM; ++i) {
142 ASSERT( inputstream.good(),
143 "FormatParser< xml >::load() - periodicity attribute has less than 3 entries.");
144 inputstream >> data.config.periodicity[i];
145 }
146 }
147 data.config.epsilon = toString(configuration.attribute("epsilon").value());
148
149 // particles
150 for(pugi::xml_node::iterator iter = configuration.begin();
151 iter != configuration.end(); ++iter) {
152 struct scafacos::configuration::particle p;
153 p.position = toVector((*iter).attribute("position").value());
154 p.q = toDouble((*iter).attribute("q").value());
155 p.potential = toDouble((*iter).attribute("potential").value());
156 p.field = toVector((*iter).attribute("field").value());
157 data.config.p.push_back(p);
158 LOG(2, "DEBUG: Parsing particle at " << p.position << ".");
159 atom * const newAtom = World::getInstance().createAtom();
160 // for the moment each becomes a hydrogen
161 newAtom->setType(World::getInstance().getPeriode()->FindElement((atomicNumber_t)1));
162 newAtom->setPosition(p.position);
163 newmol->AddAtom(newAtom);
164 }
165
166 BOOST_FOREACH(atom *_atom, World::getInstance().getAllAtoms())
167 LOG(3, "INFO: Atom " << _atom->getName() << " " << *dynamic_cast<AtomInfo *>(_atom) << ".");
168
169 // refresh atom::nr and atom::name
170 newmol->getAtomCount();
171}
172
173/**
174 * Saves the \a atoms into as a XYZ file.
175 *
176 * \param file where to save the state
177 * \param atoms atoms to store
178 */
179void FormatParser< xml >::save(std::ostream* file, const std::vector<atom *> &atoms) {
180 LOG(0, "Saving changes to xml.");
181
182 // fill the structure with updated information
183 const Box &domain = World::getInstance().getDomain();
184 data.config.box = domain.getM();
185 for (size_t i=0;i<NDIM;++i)
186 data.config.periodicity[i] = domain.getCondition(i) == BoundaryConditions::Wrap;
187 data.config.p.clear();
188 for(std::vector<atom*>::const_iterator it = atoms.begin(); it != atoms.end(); it++) {
189 struct scafacos::configuration::particle p;
190 p.position = (*it)->getPosition();
191 p.q = 0.;
192 p.potential = 0.;
193 p.field = zeroVec;
194 data.config.p.push_back(p);
195 }
196
197 // create the xml tree
198 pugi::xml_document doc;
199 pugi::xml_attribute attr;
200
201 // header
202 pugi::xml_node xml_scafacos_test = doc.root().append_child();
203 xml_scafacos_test.set_name("scafacos_test");
204 xml_scafacos_test.append_attribute("name").set_value(data.name.c_str());
205 xml_scafacos_test.append_attribute("description").set_value(data.description.c_str());
206 xml_scafacos_test.append_attribute("reference_method").set_value(data.reference_method.c_str());
207 xml_scafacos_test.append_attribute("error_potential").set_value(data.error_potential);
208 xml_scafacos_test.append_attribute("error_field").set_value(data.error_field);
209
210 // configuration
211 pugi::xml_node xml_configuration = xml_scafacos_test.append_child();
212 xml_configuration.set_name("configuration");
213 xml_configuration.append_attribute("offset").set_value(fromVector(data.config.offset).c_str());
214 for (size_t i=0; i<NDIM; ++i)
215 xml_configuration.append_attribute(box_axis[i]).set_value(fromVector(data.config.box.column(i)).c_str());
216 xml_configuration.append_attribute("periodicity").set_value(fromBoolean(data.config.periodicity).c_str());
217 xml_configuration.append_attribute("epsilon").set_value(toString(data.config.epsilon).c_str());
218
219 // particles
220 for (std::vector<scafacos::configuration::particle>::const_iterator iter = data.config.p.begin();
221 iter != data.config.p.end();++iter) {
222 pugi::xml_node particle = xml_configuration.append_child();
223 particle.set_name("particle");
224 particle.append_attribute("position").set_value(fromVector((*iter).position).c_str());
225 particle.append_attribute("q").set_value(fromDouble((*iter).q).c_str());
226 particle.append_attribute("potential").set_value(fromDouble((*iter).potential).c_str());
227 particle.append_attribute("field").set_value(fromVector((*iter).field).c_str());
228 }
229
230 // print standard header and save without declaration
231 *file << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
232 *file << "<!DOCTYPE scafacos_test SYSTEM 'scafacos_test.dtd'>\n";
233 doc.save(*file, "\t", pugi::format_no_declaration, pugi::encoding_utf8);
234}
235
236#define comparator(x,y) if (x != y) { LOG(2, "DEBUG: Mismatch in " << #x << ": " << x << " != " << y); return false; }
237#define num_comparator(x,y) if (fabs(x - y) > MYEPSILON) { LOG(2, "DEBUG: Numeric mismatch in " << #x << ": " << x << " != " << y << " by " << fabs(x - y) << "."); return false; }
238
239bool FormatParser< xml >::scafacos::configuration::particle::operator==(const particle &p) const {
240 comparator(position, p.position)
241 num_comparator(q, p.q)
242 num_comparator(potential, p.potential)
243 comparator(field, p.field)
244 return true;
245}
246
247bool FormatParser< xml >::scafacos::configuration::operator==(const configuration &c) const {
248 comparator(offset, c.offset)
249 comparator(box, c.box)
250 for (size_t i=0;i<NDIM;++i)
251 comparator(periodicity[i], c.periodicity[i])
252 comparator(epsilon, c.epsilon)
253
254 if (p.size() != c.p.size()) {
255 LOG(2, "DEBUG: Mismatch in p's size: " << p.size() << " != " << c.p.size() << ".");
256 return false;
257 }
258 std::vector<scafacos::configuration::particle>::const_iterator iter = p.begin();
259 std::vector<scafacos::configuration::particle>::const_iterator citer = c.p.begin();
260 for (;iter != p.end(); ++iter, ++citer) {
261 if ((*iter) != (*citer))
262 return false;
263 }
264 return true;
265}
266
267bool FormatParser< xml >::scafacos::operator==(const scafacos &s) const {
268 comparator(name, s.name)
269 comparator(description, s.description)
270 comparator(reference_method, s.reference_method)
271 num_comparator(error_potential, s.error_potential)
272 num_comparator(error_field, s.error_field)
273
274 if (config != s.config) {
275 return false;
276 }
277 return true;
278}
Note: See TracBrowser for help on using the repository browser.