source: src/Parser/XmlParser.cpp@ 47cee7

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 47cee7 was 5aaa43, checked in by Frederik Heber <heber@…>, 12 years ago

FIX: Fixed new copyright line since start of 2013 in CodeChecks test.

  • we must look for either Uni Bonn or myself.
  • added second copyright line since from 1st of Jan 2013 I am not employed by University of Bonn anymore, hence changes to the code are my own copyright.
  • Property mode set to 100644
File size: 12.2 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2012 University of Bonn. All rights reserved.
5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
6 *
7 *
8 * This file is part of MoleCuilder.
9 *
10 * MoleCuilder is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * MoleCuilder is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24/*
25 * XmlParser.cpp
26 *
27 * Created on: Mar 23, 2012
28 * Author: heber
29 */
30
31// include config.h
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36#include "CodePatterns/MemDebug.hpp"
37
38#include <limits>
39#include <vector>
40
41#include "CodePatterns/Log.hpp"
42#include "CodePatterns/Verbose.hpp"
43
44#include "XmlParser.hpp"
45
46#include "Atom/atom.hpp"
47#include "Box.hpp"
48#include "Element/element.hpp"
49#include "Element/periodentafel.hpp"
50#include "molecule.hpp"
51#include "MoleculeListClass.hpp"
52#include "World.hpp"
53
54#include "Parser/pugixml/pugixml.hpp"
55
56// static instances
57FormatParser< xml >::additionalAtomInfo FormatParser< xml >::defaultAtomInfo;
58
59// declare specialized static variables
60const std::string FormatParserTrait<xml>::name = "xml";
61const std::string FormatParserTrait<xml>::suffix = "xml";
62const ParserTypes FormatParserTrait<xml>::type = xml;
63
64const char *box_axis[NDIM] = { "box_a", "box_b", "box_c" };
65
66/**
67 * Constructor.
68 */
69FormatParser< xml >::FormatParser() :
70 FormatParser_common(NULL)
71{}
72
73/**
74 * Destructor.
75 */
76FormatParser< xml >::~FormatParser()
77{}
78
79Vector toVector(const std::string &value)
80{
81 std::stringstream inputstream(value);
82 Vector returnVector;
83 for (size_t i=0;i<NDIM;++i)
84 inputstream >> std::setprecision(16) >> returnVector[i];
85 return returnVector;
86}
87
88double toDouble(const std::string &value)
89{
90 std::stringstream inputstream(value);
91 double returnDouble;
92 inputstream >> std::setprecision(16) >> returnDouble;
93 return returnDouble;
94}
95
96std::string fromVector(const Vector&a)
97{
98 std::stringstream returnstring;
99 for (size_t i=0;i<NDIM;++i) {
100 returnstring << std::setprecision(16) << a[i];
101 if (i != NDIM-1)
102 returnstring << std::string(" ");
103 }
104 return returnstring.str();
105}
106
107std::string fromDouble(const double &a)
108{
109 std::stringstream returnstring;
110 returnstring << std::setprecision(16) << a;
111 return returnstring.str();
112}
113
114std::string fromBoolean(const bool c[])
115{
116 std::stringstream returnstring;
117 for (size_t i=0;i<NDIM;++i) {
118 returnstring << (c[i] ? std::string("1") : std::string("0"));
119 if (i != NDIM-1)
120 returnstring << std::string(" ");
121 }
122 return returnstring.str();
123}
124
125/**
126 * Loads an XYZ file into the World.
127 *
128 * \param XYZ file
129 */
130void FormatParser< xml >::load(std::istream* file)
131{
132 // create the molecule
133 molecule * const newmol = World::getInstance().createMolecule();
134 newmol->ActiveFlag = true;
135 // TODO: Remove the insertion into molecule when saving does not depend on them anymore. Also, remove molecule.hpp include
136 World::getInstance().getMolecules()->insert(newmol);
137
138 // load file into xml tree
139 pugi::xml_document doc;
140 doc.load(*file);
141
142 // header
143 pugi::xml_node scafacos_test = doc.root().child("scafacos_test");
144 data.name = toString(scafacos_test.attribute("name").value());
145 data.description = toString(scafacos_test.attribute("description").value());
146 data.reference_method = toString(scafacos_test.attribute("reference_method").value());
147 data.error_potential = scafacos_test.attribute("error_potential").as_double();
148 data.error_field = scafacos_test.attribute("error_field").as_double();
149 LOG(1, "INFO: scafacos_test.name is '" << data.name << "'.");
150 newmol->setName(data.name);
151
152 // configuration information
153 pugi::xml_node configuration = scafacos_test.child("configuration");
154 data.config.offset = toVector(configuration.attribute("offset").value());
155 for (size_t i=0; i<NDIM; ++i)
156 data.config.box.column(i) = toVector(configuration.attribute(box_axis[i]).value());
157 World::getInstance().getDomain().setM(data.config.box);
158 {
159 std::stringstream inputstream(configuration.attribute("periodicity").value());
160 for (size_t i=0; i<NDIM; ++i) {
161 ASSERT( inputstream.good(),
162 "FormatParser< xml >::load() - periodicity attribute has less than 3 entries.");
163 inputstream >> data.config.periodicity[i];
164 }
165 }
166 data.config.epsilon = toString(configuration.attribute("epsilon").value());
167
168 // particles
169 for(pugi::xml_node::iterator iter = configuration.begin();
170 iter != configuration.end(); ++iter) {
171 struct scafacos::configuration::particle p;
172 p.position = toVector((*iter).attribute("position").value());
173 p.q = toDouble((*iter).attribute("q").value());
174 p.potential = toDouble((*iter).attribute("potential").value());
175 p.field = toVector((*iter).attribute("field").value());
176 data.config.p.push_back(p);
177 LOG(2, "DEBUG: Parsing particle at " << p.position << ".");
178 atom * const newAtom = World::getInstance().createAtom();
179 // for the moment each becomes a hydrogen
180 newAtom->setType(World::getInstance().getPeriode()->FindElement((atomicNumber_t)1));
181 newAtom->setPosition(p.position);
182 newAtom->setCharge(p.q);
183 newmol->AddAtom(newAtom);
184 additionalAtomInfo atomInfo(p.q, p.potential, p.field);
185#ifndef NDEBUG
186 std::pair<AtomInfoMap_t::iterator, bool> inserter =
187#endif
188 additionalAtomData.insert( std::make_pair(newAtom->getId(), atomInfo) );
189 ASSERT( inserter.second,
190 "FormatParser< xml >::load() - atomInfo entry for atom "+toString(newAtom->getId())
191 +" already present.");
192 }
193
194 BOOST_FOREACH(atom *_atom, World::getInstance().getAllAtoms())
195 LOG(3, "INFO: Atom " << _atom->getName() << " " << *dynamic_cast<AtomInfo *>(_atom) << ".");
196
197 // refresh atom::nr and atom::name
198 newmol->getAtomCount();
199}
200
201/**
202 * Saves the \a atoms into as a XYZ file.
203 *
204 * \param file where to save the state
205 * \param atoms atoms to store
206 */
207void FormatParser< xml >::save(std::ostream* file, const std::vector<atom *> &atoms) {
208 LOG(2, "DEBUG: Saving changes to xml.");
209
210 // fill the structure with updated information
211 const Box &domain = World::getInstance().getDomain();
212 data.config.box = domain.getM();
213 for (size_t i=0;i<NDIM;++i)
214 data.config.periodicity[i] = domain.getCondition(i) == BoundaryConditions::Wrap;
215 data.config.p.clear();
216 for(std::vector<atom*>::const_iterator it = atoms.begin(); it != atoms.end(); it++) {
217 struct scafacos::configuration::particle p;
218 const additionalAtomInfo &atomInfo = getAtomData(*(*it));
219 p.position = (*it)->getPosition();
220 p.q = (*it)->getCharge();
221 p.potential = atomInfo.potential;
222 p.field = atomInfo.field;
223 data.config.p.push_back(p);
224 }
225
226 // create the xml tree
227 pugi::xml_document doc;
228 pugi::xml_attribute attr;
229
230 // header
231 pugi::xml_node xml_scafacos_test = doc.root().append_child();
232 xml_scafacos_test.set_name("scafacos_test");
233 xml_scafacos_test.append_attribute("name").set_value(data.name.c_str());
234 xml_scafacos_test.append_attribute("description").set_value(data.description.c_str());
235 xml_scafacos_test.append_attribute("reference_method").set_value(data.reference_method.c_str());
236 xml_scafacos_test.append_attribute("error_potential").set_value(data.error_potential);
237 xml_scafacos_test.append_attribute("error_field").set_value(data.error_field);
238
239 // configuration
240 pugi::xml_node xml_configuration = xml_scafacos_test.append_child();
241 xml_configuration.set_name("configuration");
242 xml_configuration.append_attribute("offset").set_value(fromVector(data.config.offset).c_str());
243 for (size_t i=0; i<NDIM; ++i)
244 xml_configuration.append_attribute(box_axis[i]).set_value(fromVector(data.config.box.column(i)).c_str());
245 xml_configuration.append_attribute("periodicity").set_value(fromBoolean(data.config.periodicity).c_str());
246 xml_configuration.append_attribute("epsilon").set_value(toString(data.config.epsilon).c_str());
247
248 // particles
249 for (std::vector<scafacos::configuration::particle>::const_iterator iter = data.config.p.begin();
250 iter != data.config.p.end();++iter) {
251 pugi::xml_node particle = xml_configuration.append_child();
252 particle.set_name("particle");
253 particle.append_attribute("position").set_value(fromVector((*iter).position).c_str());
254 particle.append_attribute("q").set_value(fromDouble((*iter).q).c_str());
255 particle.append_attribute("potential").set_value(fromDouble((*iter).potential).c_str());
256 particle.append_attribute("field").set_value(fromVector((*iter).field).c_str());
257 }
258
259 // print standard header and save without declaration
260 *file << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
261 *file << "<!DOCTYPE scafacos_test SYSTEM 'scafacos_test.dtd'>\n";
262 doc.save(*file, "\t", pugi::format_no_declaration, pugi::encoding_utf8);
263}
264
265/** Observer callback when new atom is added to World.
266 *
267 * @param id of atom
268 */
269void FormatParser< xml >::AtomInserted(atomId_t id)
270{
271 std::map<const atomId_t, additionalAtomInfo>::iterator iter = additionalAtomData.find(id);
272 ASSERT(iter == additionalAtomData.end(),
273 "FormatParser< xml >::AtomInserted() - additionalAtomData already present for newly added atom "
274 +toString(id)+".");
275 // additionalAtomData.insert( std::make_pair(id, additionalAtomInfo()) );
276}
277
278/** Remove additional AtomData info, when atom has been removed from World.
279 *
280 * @param id of atom
281 */
282void FormatParser< xml >::AtomRemoved(atomId_t id)
283{
284 std::map<const atomId_t, additionalAtomInfo>::iterator iter = additionalAtomData.find(id);
285 // as we do not insert AtomData on AtomInserted, we cannot be assured of its presence
286// ASSERT(iter != additionalAtomData.end(),
287// "FormatParser< tremolo >::AtomRemoved() - additionalAtomData is not present for atom "
288// +toString(id)+" to remove.");
289 if (iter != additionalAtomData.end())
290 additionalAtomData.erase(iter);
291}
292
293const FormatParser< xml >::additionalAtomInfo& FormatParser< xml >::getAtomData(const atom &_atom) const
294{
295 {
296 // has its own entry?
297 AtomInfoMap_t::const_iterator iter = additionalAtomData.find(_atom.getId());
298 if (iter != additionalAtomData.end()) {
299 return iter->second;
300 }
301 }
302 {
303 // father has an entry?
304 AtomInfoMap_t::const_iterator iter = additionalAtomData.find(_atom.GetTrueFather()->getId());
305 if (iter != additionalAtomData.end()) {
306 return iter->second;
307 }
308 }
309 return defaultAtomInfo;
310}
311
312
313#define comparator(x,y) if (x != y) { LOG(2, "DEBUG: Mismatch in " << #x << ": " << x << " != " << y); return false; }
314#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; }
315
316bool FormatParser< xml >::scafacos::configuration::particle::operator==(const particle &p) const {
317 comparator(position, p.position)
318 num_comparator(q, p.q)
319 num_comparator(potential, p.potential)
320 comparator(field, p.field)
321 return true;
322}
323
324bool FormatParser< xml >::scafacos::configuration::operator==(const configuration &c) const {
325 comparator(offset, c.offset)
326 comparator(box, c.box)
327 for (size_t i=0;i<NDIM;++i)
328 comparator(periodicity[i], c.periodicity[i])
329 comparator(epsilon, c.epsilon)
330
331 if (p.size() != c.p.size()) {
332 LOG(2, "DEBUG: Mismatch in p's size: " << p.size() << " != " << c.p.size() << ".");
333 return false;
334 }
335 std::vector<scafacos::configuration::particle>::const_iterator iter = p.begin();
336 std::vector<scafacos::configuration::particle>::const_iterator citer = c.p.begin();
337 for (;iter != p.end(); ++iter, ++citer) {
338 if ((*iter) != (*citer))
339 return false;
340 }
341 return true;
342}
343
344
345bool FormatParser< xml >::scafacos::operator==(const scafacos &s) const {
346 comparator(name, s.name)
347 comparator(description, s.description)
348 comparator(reference_method, s.reference_method)
349 num_comparator(error_potential, s.error_potential)
350 num_comparator(error_field, s.error_field)
351
352 if (config != s.config) {
353 return false;
354 }
355 return true;
356}
Note: See TracBrowser for help on using the repository browser.