QMCPACK
XMLParticleIO.cpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2020 QMCPACK developers.
6 //
7 // File developed by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
9 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
10 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
11 //
12 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
13 //////////////////////////////////////////////////////////////////////////////////////
14 
15 
16 #include <string>
17 #include <vector>
18 #include <utility>
19 #include <iostream>
20 #include <fstream>
21 #include "OhmmsData/FileUtility.h"
22 #include "OhmmsData/AttributeSet.h"
23 #include "OhmmsData/ParameterSet.h"
24 #include "ParticleIO/LatticeIO.h"
25 #include "XMLParticleIO.h"
29 
30 namespace qmcplusplus
31 {
32 /** set the property of a SpeciesSet
33  * @param tspecies SpeciesSet
34  * @param sid id of the species whose properties to be set
35  *
36  * Need unit handlers but for now, everything is in AU:
37  * m_e=1.0, hartree and bohr and unit="au"
38  * Example to define C(arbon)
39  * <group name="C">
40  * <parameter name="mass" unit="amu">12</parameter>
41  * <parameter name="charge">-6</parameter>
42  * </group>
43  * Note that unit="amu" is given for the mass.
44  * When mass is not given, they are set to the electron mass.
45  */
46 void setSpeciesProperty(SpeciesSet& tspecies, int sid, xmlNodePtr cur)
47 {
48  const double proton_mass = 1822.888530063;
49  cur = cur->xmlChildrenNode;
50  while (cur != NULL)
51  {
52  std::string cname((const char*)cur->name);
53  if (cname == "parameter")
54  {
55  std::string pname;
56  std::string unit_name("au"); //hartree, bohr & me=1
57  OhmmsAttributeSet pAttrib;
58  pAttrib.add(pname, "name");
59  pAttrib.add(unit_name, "unit");
60  pAttrib.put(cur);
61  if (pname.size())
62  {
63  int iproperty = tspecies.addAttribute(pname);
64  double ap = 0.0;
65  double unit_conv = 1.0;
66  putContent(ap, cur);
67  if (pname == "mass")
68  {
69  if (unit_name == "amu")
70  unit_conv = proton_mass;
71  }
72  tspecies(iproperty, sid) = ap * unit_conv;
73  }
74  }
75  cur = cur->next;
76  }
77 }
78 
79 
81 {
82  //add ref particle attributes
84 }
85 
86 /** process xmlnode &lt;particleset/&gt; which contains everything about the particle set to initialize
87  *@param cur the xmlnode to work on
88  *
89  */
90 bool XMLParticleParser::readXML(xmlNodePtr cur)
91 {
92  ReportEngine PRE("XMLParticleParser", "readXML");
93 
94  if (ref_.getTotalNum())
95  throw UniformCommunicateError("The ParticleSet object to load XML input was not empty. Report a bug!");
96 
97  SpeciesSet& tspecies(ref_.getSpeciesSet());
98  if (tspecies.size() != 0)
99  throw UniformCommunicateError("The SpeciesSet object to load XML input was not empty. Report a bug!");
100 
101  // the total number of particles, once it is set non-zero, always check against it.
102  int nat = 0;
103  // the number of particles by group, once it is constructed, always check against it.
104  std::vector<int> nat_group;
105 
106  std::string pname("none");
107  std::string randomizeR("no");
108  OhmmsAttributeSet pAttrib;
109  pAttrib.add(randomizeR, "random");
110  pAttrib.add(nat, "size");
111  pAttrib.add(pname, "name");
112  pAttrib.put(cur);
113 
114  ref_.setName(pname.c_str());
115 
116  if (nat != 0)
117  {
118  app_debug() << "Set the total size " << nat
119  << " by the 'size' attribute found in 'particleset' XML element node named '" << pname << "'."
120  << std::endl;
121  }
122 
123  bool ionid_found = false;
124  { // parse all the 'group's to obtain or verify the total number of particles
125  //total count of the particles to be created
126  int ntot = 0;
127  int num_non_zero_group = 0;
128  bool group_found = false;
129 
130  processChildren(cur, [&](const std::string& cname, const xmlNodePtr element) {
131  if (cname == "atom")
132  throw UniformCommunicateError("XML element node atom is no more supported");
133  else if (cname.find("ell") < cname.size()) //accept UnitCell, unitcell, supercell
134  throw UniformCommunicateError("Constructing cell inside particleset is illegal!");
135  else if (cname == "group")
136  {
137  group_found = true;
138  std::string sname = getXMLAttributeValue(element, "name");
139  if (sname.empty())
140  throw UniformCommunicateError("'group' element node must include a name attribute!");
141  else
142  {
143  const int sid = tspecies.addSpecies(sname);
144  setSpeciesProperty(tspecies, sid, element);
145  }
146 
147  int nat_per_group = 0;
148  OhmmsAttributeSet gAttrib;
149  gAttrib.add(nat_per_group, "size");
150  gAttrib.put(element);
151 
152  nat_group.push_back(nat_per_group);
153  ntot += nat_per_group;
154  if (nat_per_group > 0)
155  num_non_zero_group++;
156  }
157  else if (cname == attrib_tag && getXMLAttributeValue(element, "name") == ionid_tag)
158  ionid_found = true;
159  });
160 
161  if (!group_found)
162  throw UniformCommunicateError("No 'group' XML element node was found. Check XML input!");
163 
164  if (nat != 0 && ntot != 0 && nat != ntot)
165  {
166  std::ostringstream msg;
167  msg << "The total number of particles deterimined previously was " << nat
168  << "but the sum of the sizes from all the 'group' XML element nodes is " << ntot
169  << ". Please check the 'particleset' XML element node!" << std::endl;
170  throw UniformCommunicateError(msg.str());
171  }
172 
173  if (nat == 0 && ntot != 0)
174  {
175  nat = ntot;
176  app_debug() << "Set the total size " << nat << " by the sum of the 'size's on all the 'group' XML element nodes."
177  << std::endl;
178  }
179 
180  if (ntot > 0 && num_non_zero_group != nat_group.size())
181  throw UniformCommunicateError("Some 'group' XML element node doesn't contain a 'size' attribute! 'size = 0' is not allowed in the input. Make appropriate adjustments to the input or converter.");
182  }
183 
184  { // parse all the 'attrib's to obtain or verify the total number of particles
185  processChildren(cur, [&](const std::string& cname, const xmlNodePtr element) {
186  if (cname == attrib_tag)
187  {
188  std::string sname = getXMLAttributeValue(element, "name");
189  if (sname.empty())
191  "' XML element node must include a name attribute!");
192 
193  int size_att = 0;
194  OhmmsAttributeSet aAttrib;
195  aAttrib.add(size_att, "size");
196  aAttrib.put(element);
197 
198  if (nat != 0 && size_att != 0 && nat != size_att)
199  {
200  std::ostringstream msg;
201  msg << "The total number of particles deterimined previously was " << nat
202  << " but the 'size' atttribute found on the '" << ParticleTags::attrib_tag
203  << "' XML element nodes named '" << sname << "' is " << size_att
204  << ". Please check the 'particleset' XML element node!" << std::endl;
205  throw UniformCommunicateError(msg.str());
206  }
207 
208  if (nat == 0 && size_att != 0)
209  {
210  nat = size_att;
211  app_debug() << "Set the total size " << nat << " by the 'size' on the '" << ParticleTags::attrib_tag
212  << "' XML element node named '" << sname << "'." << std::endl;
213  }
214  }
215  });
216  }
217 
218  if (nat == 0)
219  throw UniformCommunicateError("Failed in figuring out the total number of particles. Check XML input!");
220 
221  if (ionid_found)
222  { // parse ionid and construct input order to stored order
223  std::vector<int> map_storage_to_input(nat);
224  processChildren(cur, [&](const std::string& cname, const xmlNodePtr element) {
225  if (cname == attrib_tag && getXMLAttributeValue(element, "name") == ionid_tag)
226  {
227  std::string datatype = getXMLAttributeValue(element, datatype_tag);
228  if (datatype != stringtype_tag)
229  throw UniformCommunicateError("'ionid' only supports datatype=\"" + stringtype_tag + "\"");
230  std::vector<std::string> d_in(nat);
231  putContent(d_in, element);
232  bool input_ungrouped = false;
233  int storage_index = 0;
234  for (int ig = 0; ig < nat_group.size(); ig++)
235  {
236  const auto& group_species_name = tspecies.getSpeciesName(ig);
237  int count_group_size = 0;
238  for (int iat = 0; iat < nat; iat++)
239  {
240  const int element_index = tspecies.findSpecies(d_in[iat]);
241  if (element_index == tspecies.size())
242  throw UniformCommunicateError("Element " + d_in[iat] +
243  " doesn't match any species from 'group' XML element nodes.");
244  if (element_index == ig)
245  {
246  if (iat != storage_index)
247  input_ungrouped = true;
248  count_group_size++;
249  map_storage_to_input[storage_index++] = iat;
250  }
251  }
252 
253  if (count_group_size == 0)
254  throw UniformCommunicateError("Element '" + group_species_name + "' not found in 'ionid'.");
255 
256  if (nat_group[ig] == 0)
257  nat_group[ig] = count_group_size;
258  else if (nat_group[ig] != count_group_size)
259  {
260  std::ostringstream msg;
261  msg << "The number of particles of element '" << group_species_name << "' from 'group' XML elment node was "
262  << nat_group[ig] << " but 'ionid' contains " << count_group_size << " entries." << std::endl;
263  throw UniformCommunicateError(msg.str());
264  }
265  }
266 
267  if (input_ungrouped)
268  {
269  app_log() << " Input particle set is not grouped by species. Remapping particle position indices "
270  "internally."
271  << std::endl;
272  app_debug() << " Species : input particle index -> internal particle index" << std::endl;
273  for (int new_idx = 0; new_idx < map_storage_to_input.size(); new_idx++)
274  {
275  int old_idx = map_storage_to_input[new_idx];
276  if (new_idx != old_idx)
277  {
278  app_debug() << " " << d_in[old_idx] << " : " << old_idx << " -> " << new_idx << std::endl;
279  }
280  }
281  }
282  }
283  });
284 
285  checkGrouping(nat, nat_group);
286  ref_.create(nat_group);
287  // save map_storage_to_input
288  ref_.setMapStorageToInput(map_storage_to_input);
289 
290  for (int iat = 0; iat < nat; iat++)
291  {
292  processChildren(cur, [&](const std::string& cname, const xmlNodePtr element) {
293  if (cname == attrib_tag && getXMLAttributeValue(element, "name") != ionid_tag)
294  getPtclAttrib(element, map_storage_to_input[iat], 1, iat);
295  });
296  }
297  }
298  else
299  {
300  // fix old input with positions outside 'group'
301  if (nat_group.size() == 1 && nat_group[0] == 0)
302  nat_group[0] = nat;
303 
304  checkGrouping(nat, nat_group);
305  ref_.create(nat_group);
306 
307  // obtain 'attrib' inside 'group'
308  size_t start = 0;
309  size_t ig = 0;
310  processChildren(cur, [&](const std::string& cname, const xmlNodePtr child) {
311  if (cname == "group")
312  {
313  processChildren(child, [&](const std::string& cname, const xmlNodePtr element) {
314  if (cname == attrib_tag)
315  getPtclAttrib(element, 0, nat_group[ig], start);
316  });
317  start += nat_group[ig];
318  ig++;
319  }
320  else if (cname == attrib_tag)
321  {
322  if (nat_group.size() > 1)
323  throw UniformCommunicateError("An 'attrib' XML element node was found outside 'group'"
324  " without XML element node named 'ionid'."
325  " Cannot map particles to more than one species. Check XML input!");
326  getPtclAttrib(child, 0, nat, 0);
327  }
328  });
329  }
330 
331  if (ref_.getLattice().SuperCellEnum)
332  {
333  if (randomizeR == "yes")
334  {
339  ref_.spins *= 2 * M_PI;
340  }
341  else // put them [0,1) in the cell
342  ref_.applyBC(ref_.R);
343  }
344 
345  //this sets Mass, Z
346  ref_.resetGroups();
347  ref_.createSK();
348 
349  return true;
350 }
351 
352 void XMLParticleParser::checkGrouping(int nat, const std::vector<int>& nat_group) const
353 {
354  app_debug() << "There are " << nat << " particles in " << nat_group.size() << " species containing:" << std::endl;
355  for (int ig = 0; ig < nat_group.size(); ig++)
356  {
357  const auto& group_species_name = ref_.getSpeciesSet().getSpeciesName(ig);
358  if (nat_group[ig] == 0)
359  throw UniformCommunicateError("Element '" + group_species_name + "' was provided but never referenced.");
360  app_debug() << " " << nat_group[ig] << " '" << group_species_name << "'" << std::endl;
361  }
362 
363  if (std::accumulate(nat_group.begin(), nat_group.end(), 0) != nat)
365  "The total number of particles doesn't match the sum of the particle counts of all the species.");
366 }
367 
368 /** process xmlnode to reset the properties of a particle set
369  * @param cur current node
370  * @return true, if successful
371  *
372  * This resets or adds new attributes to a particle set.
373  * It cannot modify the size of the particle set.
374  */
375 bool XMLParticleParser::reset(xmlNodePtr cur)
376 {
377  ReportEngine PRE("XMLParticleParser", "reset");
378  SpeciesSet& tspecies(ref_.getSpeciesSet());
379  cur = cur->xmlChildrenNode;
380  while (cur != NULL)
381  {
382  std::string cname((const char*)cur->name);
383  if (cname == "group")
384  {
385  std::string sname;
386  OhmmsAttributeSet gAttrib;
387  gAttrib.add(sname, "name");
388  gAttrib.put(cur);
389  if (sname.size())
390  {
391  int sid = tspecies.addSpecies(sname);
392  setSpeciesProperty(tspecies, sid, cur);
393  }
394  }
395  cur = cur->next;
396  }
397  // //@todo Will add a member function to ParticleSet to handle these
398  // int massind=tspecies.addAttribute("mass");
399  // for(int iat=0; iat<ref_.getTotalNum(); iat++)
400  // ref_.Mass[iat]=tspecies(massind,ref_.GroupID[iat]);
401  //
402  // int qind=tspecies.addAttribute("charge");
403  // for(int iat=0; iat<ref_.getTotalNum(); iat++)
404  // ref_.Z[iat]=tspecies(qind,ref_.GroupID[iat]);
405  //
406  return true;
407 }
408 
409 template<typename PAT>
411 {
412  PAT& ref_;
413 
414  inline ParticleAttribXmlNode(PAT& a, PosUnit utype) : ref_(a) { ref_.InUnit = utype; }
415 
416  inline bool put(xmlNodePtr cur, int in_offset, int copy_size, int out_offset)
417  {
418  using data_type = typename PAT::Type_t;
419  std::vector<data_type> data_in;
420  putContent(data_in, cur);
421  if (data_in.size() < in_offset + copy_size)
422  {
423  std::ostringstream msg;
424  msg << "Insufficient data to copy from XML input which holds " << data_in.size() << " entries."
425  << " Need to copy from [" << in_offset << ", " << in_offset + copy_size << ")." << std::endl;
426  throw UniformCommunicateError(msg.str());
427  }
428  std::copy_n(data_in.begin() + in_offset, copy_size, ref_.begin() + out_offset);
429  return true;
430  }
431 };
432 
433 void XMLParticleParser::getPtclAttrib(xmlNodePtr cur, int in_offset, int copy_size, int out_offset)
434 {
435  std::string oname, otype;
436  int utype = 0;
437  int size_in = 0;
438  OhmmsAttributeSet pAttrib;
439  pAttrib.add(otype, datatype_tag); //datatype
440  pAttrib.add(oname, "name"); //name
441  pAttrib.add(utype, condition_tag); //condition
442  pAttrib.add(size_in, "size"); //size
443  pAttrib.put(cur);
444  if (oname.empty() || otype.empty())
445  {
446  app_error() << " Missing attrib/@name or attrib/@datatype " << std::endl;
447  app_error() << R"( <attrib name="aname" datatype="atype"/>)" << std::endl;
448  return;
449  }
450  int t_id = ref_AttribList.getAttribType(otype);
451 
452  if (oname == ionid_tag)
453  throw UniformCommunicateError("'ionid' should not be parsed by getPtclAttrib.");
454  else
455  {
456  //very permissive in that a unregistered attribute will be created and stored by ParticleSet
457  //cloning is not going to work
458  if (t_id == PA_IndexType)
459  {
461  ParticleAttribXmlNode<ParticleIndex> a(*obj, static_cast<PosUnit>(utype));
462  a.put(cur, in_offset, copy_size, out_offset);
463  }
464  else if (t_id == PA_ScalarType)
465  {
467  ParticleAttribXmlNode<ParticleScalar> a(*obj, static_cast<PosUnit>(utype));
468  a.put(cur, in_offset, copy_size, out_offset);
469  }
470  else if (t_id == PA_PositionType)
471  {
473  ParticleAttribXmlNode<ParticlePos> a(*obj, static_cast<PosUnit>(utype));
474  a.put(cur, in_offset, copy_size, out_offset);
475  }
476  else if (t_id == PA_TensorType)
477  {
479  ParticleAttribXmlNode<ParticleTensor> a(*obj, static_cast<PosUnit>(utype));
480  a.put(cur, in_offset, copy_size, out_offset);
481  }
482  }
483 }
484 
485 
487 
489 
490 void XMLSaveParticle::reset(const char* fileroot, bool append)
491 {
492  //append is ignored
493  FileRoot = fileroot;
494  FileName = fileroot;
495  FileName.append(".xml");
497 }
498 
500 {
501  // writing a meta file
502  std::ofstream fxml(FileName.c_str()); // always overwrite
503  fxml << "<?xml version=\"1.0\"?>" << std::endl;
504  get(fxml, 1);
505  fxml.close();
506 }
507 
508 void XMLSaveParticle::get(std::ostream& fxml, int olevel) const
509 {
510  ref_.begin_node(fxml);
511  fxml.setf(std::ios::scientific);
512  fxml.precision(15);
513  LatticeXMLWriter latticeout(ref_.getLattice());
514  latticeout.get(fxml);
515  for (int i = 0; i < SpeciesName.size(); i++)
516  {
517  fxml << "<group name=\"" << SpeciesName[i] << "\"/>" << std::endl;
518  }
519  //only write the local particles
520  int nloc = ref_.getTotalNum();
521  if (olevel)
522  {
523  /*
524  Particle_t::PAListIterator it = ref_.first_attrib();
525  while(it != ref_.last_attrib())
526  {
527  OhmmsObject* ooref= (*it).second;
528 // if(ooref->objName() == ionid_tag) {
529 // IonName.begin_node(fxml);
530 // for(int iat=0; iat<nloc; iat++) {
531 // fxml << IonName[iat] << " ";
532 // if(iat%20 == 19) fxml << std::endl;
533 // }
534 // IonName.end_node(fxml);
535 // } else {
536  int t_id = ref_AttribList.getAttribType(otype);
537  int o_id = ooref->id();
538  ooref->begin_node(fxml);
539  if(t_id == PA_IndexType)
540  {
541  const ParticleIndex* itmp=dynamic_cast<ParticleIndex*>(ooref);
542  for(int iat=0; iat<nloc; iat++)
543  {
544  fxml << (*itmp)[iat] << " ";
545  if(iat%20 == 19)
546  fxml << std::endl;
547  }
548  }
549  else if(t_id == PA_ScalarType)
550  {
551  fxml.precision(6);
552  const ParticleScalar* stmp=dynamic_cast<ParticleScalar*>(ooref);
553  for(int iat=0; iat<nloc; iat++)
554  {
555  fxml << (*stmp)[iat] << " ";
556  if(iat%5 == 4)
557  fxml << std::endl;
558  }
559  if(nloc%5 != 0)
560  fxml<< std::endl;
561  }
562  else if (t_id == PA_PositionType)
563  {
564  fxml.precision(15);
565  const ParticlePos* rtmp=dynamic_cast<ParticlePos*>(ooref);
566  for(int iat=0; iat<nloc; iat++)
567  {
568  fxml << (*rtmp)[iat] << std::endl;
569  }
570  }
571  else if (t_id == PA_TensorType)
572  {
573  fxml.precision(15);
574  const ParticleTensor* ttmp=dynamic_cast<ParticleTensor*>(ooref);
575  for(int iat=0; iat<nloc; iat++)
576  {
577  fxml << (*ttmp)[iat];
578  }
579  }
580  ooref->end_node(fxml);
581  // }
582  it++;
583  }
584  */
585  }
586  else
587  {
588  ref_.R.begin_node(fxml);
589  for (int iat = 0; iat < nloc; iat++)
590  fxml << ref_.R[iat] << std::endl;
591  ref_.R.end_node(fxml);
592  ref_.GroupID.begin_node(fxml);
593  for (int iat = 0; iat < nloc; iat++)
594  {
595  fxml << ref_.GroupID[iat] << " ";
596  if (iat % 20 == 19)
597  fxml << std::endl;
598  }
599  if (nloc % 20 != 19)
600  fxml << std::endl;
601  ref_.GroupID.end_node(fxml);
602  }
603  ref_.end_node(fxml);
604 }
605 
606 bool XMLSaveParticle::put(xmlNodePtr cur) { return true; }
607 
608 /** create particleset node
609  * @param addlattice if true, add unitcell
610  */
611 xmlNodePtr XMLSaveParticle::createNode(bool addlattice)
612 {
613  if (SpeciesName.size() != ref_.getSpeciesSet().getTotalNum())
614  {
616  }
617  //if(addlattice) {
618  // ref_.getLattice().print(std::cout);
619  //}
620  xmlNodePtr cur = xmlNewNode(NULL, (const xmlChar*)"particleset");
621  xmlNewProp(cur, (const xmlChar*)"name", (const xmlChar*)ref_.getName().c_str());
622  if (ref_.groups() > 1)
623  {
624  const SpeciesSet& mySpecies(ref_.getSpeciesSet());
625  int nitem(mySpecies.numAttributes());
626  int nspecies(mySpecies.getTotalNum());
627  for (int is = 0; is < nspecies; is++)
628  {
629  std::ostringstream ng;
630  ng << ref_.last(is) - ref_.first(is);
631  xmlNodePtr g = xmlNewNode(NULL, (const xmlChar*)"group");
632  xmlNewProp(g, (const xmlChar*)"name", (const xmlChar*)SpeciesName[is].c_str());
633  xmlNewProp(g, (const xmlChar*)"size", (const xmlChar*)ng.str().c_str());
634  for (int item = 0; item < nitem; item++)
635  {
636  std::ostringstream prop;
637  prop << mySpecies(item, is);
638  xmlNodePtr p = xmlNewTextChild(g, NULL, (const xmlChar*)"parameter", (const xmlChar*)prop.str().c_str());
639  xmlNewProp(p, (const xmlChar*)"name", (const xmlChar*)mySpecies.attribName[item].c_str());
640  }
641  std::ostringstream pos;
642  pos.setf(std::ios_base::scientific);
643  pos << "\n";
644  for (int iat = ref_.first(is); iat < ref_.last(is); iat++)
645  {
646  pos << ref_.R[iat] << std::endl;
647  }
648  xmlNodePtr posPtr = xmlNewTextChild(g, NULL, (const xmlChar*)"attrib", (const xmlChar*)pos.str().c_str());
649  xmlNewProp(posPtr, (const xmlChar*)"name", (const xmlChar*)"position");
650  xmlNewProp(posPtr, (const xmlChar*)"datatype", (const xmlChar*)"posArray");
651  xmlAddChild(cur, g);
652  }
653  }
654  else
655  {
656  std::ostringstream nat;
657  nat << ref_.getTotalNum();
658  xmlNewProp(cur, (const xmlChar*)"size", (const xmlChar*)nat.str().c_str());
659  const SpeciesSet& mySpecies(ref_.getSpeciesSet());
660  int nitem(mySpecies.numAttributes());
661  int nspecies(mySpecies.getTotalNum());
662  for (int is = 0; is < nspecies; is++)
663  {
664  xmlNodePtr g = xmlNewNode(NULL, (const xmlChar*)"group");
665  xmlNewProp(g, (const xmlChar*)"name", (const xmlChar*)SpeciesName[is].c_str());
666  for (int item = 0; item < nitem; item++)
667  {
668  std::ostringstream prop;
669  prop << mySpecies(item, is);
670  xmlNodePtr p = xmlNewTextChild(g, NULL, (const xmlChar*)"parameter", (const xmlChar*)prop.str().c_str());
671  xmlNewProp(p, (const xmlChar*)"name", (const xmlChar*)mySpecies.attribName[item].c_str());
672  }
673  xmlAddChild(cur, g);
674  }
675  std::ostringstream pos, gid;
676  pos.setf(std::ios_base::scientific);
677  pos << "\n";
678  for (int iat = 0; iat < ref_.getTotalNum(); iat++)
679  {
680  pos << ref_.R[iat] << std::endl;
681  }
682  xmlNodePtr posPtr = xmlNewTextChild(cur, NULL, (const xmlChar*)"attrib", (const xmlChar*)pos.str().c_str());
683  xmlNewProp(posPtr, (const xmlChar*)"name", (const xmlChar*)"position");
684  xmlNewProp(posPtr, (const xmlChar*)"datatype", (const xmlChar*)"posArray");
685  gid << "\n ";
686  for (int iat = 0; iat < ref_.getTotalNum(); iat++)
687  {
688  gid << SpeciesName[ref_.GroupID[iat]] << " ";
689  }
690  gid << std::endl;
691  xmlNodePtr gPtr = xmlNewTextChild(cur, NULL, (const xmlChar*)"attrib", (const xmlChar*)gid.str().c_str());
692  xmlNewProp(gPtr, (const xmlChar*)"name", (const xmlChar*)"ionid");
693  xmlNewProp(gPtr, (const xmlChar*)"datatype", (const xmlChar*)"stringArray");
694  }
695  return cur;
696 }
697 } // namespace qmcplusplus
static std::string attrib_tag
the name of particle attribute node
Definition: ParticleTags.h:118
void makeUniformRandom(ParticleAttrib< TinyVector< T, D >> &a)
void setName(const std::string &aname)
Definition: ParticleSet.h:237
bool reset(xmlNodePtr cur)
reset the properties of a particle set
void checkGrouping(int nat, const std::vector< int > &nat_group) const
Fixed-size array.
Definition: OhmmsTinyMeta.h:30
bool put(xmlNodePtr cur, int in_offset, int copy_size, int out_offset)
xmlNodePtr createNode(bool addlattice)
create particleset node
const std::string & getName() const
return the name
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
ParticleScalar spins
internal spin variables for dynamical spin calculations
Definition: ParticleSet.h:81
void reset(const char *fileroot, bool append=false) override
#define app_debug
Definition: OutputManager.h:75
size_t getTotalNum() const
Definition: ParticleSet.h:493
std::ostream & app_log()
Definition: OutputManager.h:65
bool put(xmlNodePtr cur)
assign attributes to the set
Definition: AttributeSet.h:55
std::ostream & app_error()
Definition: OutputManager.h:67
std::string FileName
static std::string condition_tag
the attribute name of condition
Definition: ParticleTags.h:124
void applyBC(const ParticlePos &pin, ParticlePos &pout)
int first(int igroup) const
return the first index of a group i
Definition: ParticleSet.h:514
bool get(std::ostream &) const
Definition: LatticeIO.cpp:240
Attaches a unit to a Vector for IO.
int addAttribute(const std::string &aname)
for a new attribute, allocate the data, !More often used to get the index of a species ...
Definition: SpeciesSet.cpp:45
ParticleAttribXmlNode(PAT &a, PosUnit utype)
int getAttribType(const std::string &tname)
return a type id: one of the enum values
Definition: XMLParticleIO.h:71
std::vector< std::string > SpeciesName
ParticleIndex GroupID
Species ID.
Definition: ParticleSet.h:77
ParticleAttrib< AT > * getAttribute(const std::string &tname, const std::string &oname)
generic get function attribute function
Definition: XMLParticleIO.h:79
int getTotalNum() const
return the number of species
Definition: SpeciesSet.h:55
int groups() const
return the number of groups
Definition: ParticleSet.h:511
void createAttributeList(ATList &AttribList)
add attributes to list for IO
Definition: ParticleSet.h:531
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
Tensor<T,D> class for D by D tensor.
Definition: OhmmsTinyMeta.h:32
Final class and should not be derived.
const std::string & getSpeciesName(int index) const
Definition: SpeciesSet.h:142
class to handle a set of attributes of an xmlNode
Definition: AttributeSet.h:24
This a subclass for runtime errors that will occur on all ranks.
declaration of ProgressReportEngine
void convert2Cart(const ParticlePos &pin, ParticlePos &pout)
bool put(xmlNodePtr cur) override
virtual void begin_node(std::ostream &os) const
write the start of a node
bool readXML(xmlNodePtr cur)
process xmlnode <particleset/> which contains everything about the particle set to initialize ...
ParticlePos R
Position.
Definition: ParticleSet.h:79
int last(int igroup) const
return the last index of a group i
Definition: ParticleSet.h:517
static std::string ionid_tag
the name for ionid attribute
Definition: ParticleTags.h:93
std::string getXMLAttributeValue(const xmlNodePtr cur, const std::string_view name)
get the value string for attribute name if name is unfound in cur you get an empty string back this i...
void getPtclAttrib(xmlNodePtr cur, int in_offset, int copy_size, int out_offset)
read the data of a particle attribute
static std::string datatype_tag
the attribute name of datatype
Definition: ParticleTags.h:122
SpeciesSet & getSpeciesSet()
retrun the SpeciesSet of this particle set
Definition: ParticleSet.h:231
void create(const std::vector< int > &agroup)
create grouped particles
std::vector< std::string > speciesName
Species name list.
Definition: SpeciesSet.h:44
void setMapStorageToInput(const std::vector< int > &mapping)
Definition: ParticleSet.h:563
bool putContent(T &a, xmlNodePtr cur)
replaces a&#39;s value with the first "element" in the "string" returned by XMLNodeString{cur}.
Definition: libxmldefs.h:88
void report(int iter) override
void processChildren(const xmlNodePtr cur, const F &functor)
process through all the children of an XML element F is a lambda or functor void F/[](const std::stri...
Definition: libxmldefs.h:175
sycl::event copy_n(sycl::queue &aq, const T1 *restrict VA, size_t array_size, T2 *restrict VC, const std::vector< sycl::event > &events)
Definition: syclBLAS.cpp:548
void get(std::ostream &os, int olevel) const
static std::string stringtype_tag
the datatype tag for the string-type attribute
Definition: ParticleTags.h:61
PosUnit
enum class to assist copy and unit conversion operations on position vectors
Definition: PosUnit.h:21
XMLSaveParticle(Particle_t &pin)
const auto & getLattice() const
Definition: ParticleSet.h:251
void createSK()
create Structure Factor with PBCs
XMLParticleParser(Particle_t &aptcl)
constructor
Custom container for set of attributes for a set of species.
Definition: SpeciesSet.h:33
void setSpeciesProperty(SpeciesSet &tspecies, int sid, xmlNodePtr cur)
set the property of a SpeciesSet
void add(PDT &aparam, const std::string &aname, std::vector< PDT > candidate_values={}, TagStatus status=TagStatus::OPTIONAL)
add a new attribute
Definition: AttributeSet.h:42
virtual void end_node(std::ostream &os) const
write the end of a node