QMCPACK
LatticeIO.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) 2016 Jeongnim Kim and 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 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
11 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
12 //
13 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
14 //////////////////////////////////////////////////////////////////////////////////////
15 
16 
17 #include <string>
18 #include <vector>
19 #include <utility>
20 #include <iostream>
21 #include <fstream>
22 #include "OhmmsData/FileUtility.h"
23 #include "LatticeIO.h"
24 #include "OhmmsData/AttributeSet.h"
27 #include "ModernStringUtils.hpp"
29 
30 namespace qmcplusplus
31 {
32 bool LatticeParser::put(xmlNodePtr cur)
33 {
35  double a0 = 1.0;
36  double rs = -1.0;
37  int nptcl = 0;
38  int nsh = 0; //for backwards compatibility w/ odd heg initialization style
39  int pol = 0;
40  using SingleParticleIndex = ParticleLayout::SingleParticleIndex;
41  TinyVector<std::string, DIM> bconds("p");
42 
44  bool lattice_defined = false;
45  bool bconds_defined = false;
46  int boxsum = 0;
47 
48  app_summary() << std::endl;
49  app_summary() << " Lattice" << std::endl;
50  app_summary() << " -------" << std::endl;
51  cur = cur->xmlChildrenNode;
52  while (cur != NULL)
53  {
54  std::string cname((const char*)cur->name);
55  if (cname == "parameter")
56  {
57  const std::string aname(getXMLAttributeValue(cur, "name"));
58  if (aname == "scale")
59  {
60  putContent(a0, cur);
61  }
62  else if (aname == "lattice")
63  {
64  const std::string units_prop(getXMLAttributeValue(cur, "units"));
65  if (!units_prop.empty() && units_prop != "bohr")
66  {
67  std::ostringstream err_msg;
68  err_msg << "LatticeParser::put. Only atomic units (bohr) supported for lattice units. Input file uses: "
69  << units_prop;
70  throw UniformCommunicateError(err_msg.str());
71  }
72 
73  putContent(lattice_in, cur);
74  lattice_defined = true;
75  //putContent(ref_.R,cur);
76  }
77  else if (aname == "bconds")
78  {
79  putContent(bconds, cur);
80  bconds_defined = true;
81  for (int idir = 0; idir < DIM; idir++)
82  {
83  char b = bconds[idir][0];
84  if (b == 'n' || b == 'N')
85  {
86  ref_.BoxBConds[idir] = false;
87  }
88  else if (b == 'p' || b == 'P')
89  {
90  ref_.BoxBConds[idir] = true;
91  boxsum++;
92  }
93  else
94  {
95  std::ostringstream err_msg;
96  err_msg << "LatticeParser::put. Unknown label '" + bconds[idir] +
97  "' used for periodicity. Only 'p', 'P', 'n' and 'N' are valid!";
98  throw UniformCommunicateError(err_msg.str());
99  }
100 
101  // Protect BCs which are not implemented.
102  if (idir > 0 && !ref_.BoxBConds[idir - 1] && ref_.BoxBConds[idir])
103  {
104  std::ostringstream err_msg;
105  err_msg
106  << "LatticeParser::put. In \"bconds\", non periodic directions must be placed after the periodic ones.";
107  throw UniformCommunicateError(err_msg.str());
108  }
109  }
110  }
111  else if (aname == "vacuum")
112  {
114  }
115  else if (aname == "LR_dim_cutoff")
116  {
117  putContent(ref_.LR_dim_cutoff, cur);
118  }
119  else if (aname == "ewald_grid")
120  {
121  putContent(ref_.num_ewald_grid_points, cur);
122  }
123  else if (aname == "LR_handler")
124  {
125  std::string handler_type("opt_breakup");
126  //This chops whitespace so the simple str == comparisons work
127  putContent(handler_type, cur);
128  handler_type = lowerCase(handler_type);
129  if (handler_type == "ewald")
131  else if (handler_type == "opt_breakup")
133  else if (handler_type == "opt_breakup_original")
135  else if (handler_type == "ewald_strict2d")
136  {
138  ref_.ndim = 2;
139  }
140  else if (handler_type == "ewald_quasi2d")
142  else
143  throw UniformCommunicateError("LatticeParser::put. Long range breakup handler not recognized.");
144  }
145  else if (aname == "LR_tol")
146  {
147  putContent(ref_.LR_tol, cur);
148  }
149  else if (aname == "rs")
150  {
151  lattice_defined = true;
152  OhmmsAttributeSet rAttrib;
153  rAttrib.add(nptcl, "condition");
154  rAttrib.add(pol, "polarized");
155  rAttrib.add(nsh, "shell");
156  rAttrib.put(cur);
157  putContent(rs, cur);
158  }
159  else if (aname == "nparticles")
160  {
161  putContent(nptcl, cur);
162  }
163  }
164  cur = cur->next;
165  }
166 
167  // checking boundary conditions
168  if (lattice_defined)
169  {
170  if (!bconds_defined)
171  {
172  app_log() << " Lattice is specified but boundary conditions are not. Assuming PBC." << std::endl;
173  ref_.BoxBConds = true;
174  }
175  }
176  else if (boxsum == 0)
177  app_log() << " Lattice is not specified for the Open BC. Add a huge box." << std::endl;
178  else
179  throw UniformCommunicateError("LatticeParser::put. Mixed boundary is supported only when a lattice is specified!");
180 
181  //special heg processing
182  if (rs > 0.0)
183  {
185  if (pol == 0)
186  {
187  if (nsh > 0)
188  nptcl = 2 * heg.getNumberOfKpoints(nsh);
189  else
190  nsh = heg.getShellIndex(nptcl / 2);
191  }
192  else
193  { // spin polarized
194  if (nsh > 0)
195  nptcl = heg.getNumberOfKpoints(nsh);
196  else
197  nsh = heg.getShellIndex(nptcl);
198  }
199  ParticleLayout::Scalar_t acubic = heg.getCellLength(nptcl, rs);
200  app_log() << " " << OHMMS_DIM << "D HEG system"
201  << "\n rs = " << rs;
202  if (pol == 0)
203  {
204  app_log() << "\n number of up particles = " << nptcl / 2 << "\n number of dn particles = " << nptcl / 2;
205  }
206  else
207  {
208  app_log() << "\n number of up particles = " << nptcl;
209  }
210  app_log() << "\n filled kshells = " << nsh << "\n lattice constant = " << acubic << " bohr"
211  << std::endl;
212  lattice_in = 0.0;
213  for (int idim = 0; idim < DIM; idim++)
214  lattice_in(idim, idim) = acubic;
215  a0 = 1.0;
216  }
217 
218  if (lattice_defined)
219  {
220  lattice_in *= a0;
221  ref_.set(lattice_in);
222  }
223 
225  throw UniformCommunicateError("LatticeParser::put. Quasi 2D Ewald only works with boundary condition 'p p n'!");
226 
229 
230  std::string unit_name = "bohr";
231  app_log() << std::fixed;
232  app_log() << " Simulation cell radius = " << ref_.SimulationCellRadius << " " << unit_name << std::endl;
233  app_log() << " Wigner-Seitz cell radius = " << ref_.WignerSeitzRadius << " " << unit_name << std::endl;
234  app_log() << std::endl;
235 
236  return lattice_defined;
237 }
238 
239 
240 bool LatticeXMLWriter::get(std::ostream& os) const
241 {
242  os << "<unitcell>" << std::endl;
243  os << R"(<parameter name="lattice" datatype="tensor">)" << std::endl;
244  os << ref_.R << "</parameter>" << std::endl;
245  os << "<parameter name=\"bconds\">";
247  for (int idir = 0; idir < DIM; idir++)
248  {
249  if (ref_.BoxBConds[idir])
250  os << "p ";
251  else
252  os << "n ";
253  }
254  os << "</parameter>" << std::endl;
255  os << "</unitcell>" << std::endl;
256  return true;
257 }
258 
260 {
261  xmlNodePtr cur = xmlNewNode(NULL, (const xmlChar*)"unitcell");
262  std::ostringstream l;
263  l.setf(std::ios_base::scientific);
264  l.precision(12);
265  l << ref_.R;
266  xmlNodePtr p = xmlNewTextChild(cur, NULL, (const xmlChar*)"parameter", (const xmlChar*)l.str().c_str());
267  xmlNewProp(p, (const xmlChar*)"name", (const xmlChar*)"lattice");
268  return cur;
269 }
270 } // namespace qmcplusplus
void set(const Tensor< TT, D > &lat)
set the lattice vector from the command-line options
int SuperCellEnum
supercell enumeration
Fixed-size array.
Definition: OhmmsTinyMeta.h:30
const ParticleLayout & ref_
Definition: LatticeIO.h:37
ParticleLayout & ref_
Definition: LatticeIO.h:26
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
std::ostream & app_log()
Definition: OutputManager.h:65
bool put(xmlNodePtr cur)
Definition: LatticeIO.cpp:32
std::ostream & app_summary()
Definition: OutputManager.h:63
bool put(xmlNodePtr cur)
assign attributes to the set
Definition: AttributeSet.h:55
int getShellIndex(int nkpt) const
Definition: HEGGrid.h:53
T VacuumScale
The scale factor for adding vacuum.
bool get(std::ostream &) const
Definition: LatticeIO.cpp:240
#define OHMMS_DIM
Definition: config.h:64
TinyVector< int, D > BoxBConds
The boundary condition in each direction.
Tensor<T,D> class for D by D tensor.
Definition: OhmmsTinyMeta.h:32
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.
std::string lowerCase(const std::string_view s)
++17
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...
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
Define a LRHandler with two template parameters.
Scalar_t SimulationCellRadius
simulation cell radii
int getNumberOfKpoints(int nsh) const
Definition: HEGGrid.h:44
Scalar_t WignerSeitzRadius
Wigner-Seitz cell radius.
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
Tensor_t R
Real-space unit vectors. R(i,j) i=vector and j=x,y,z.
static bool isQuasi2D()
return true if quasi 2D is selected
T getCellLength(int nptcl, T rs_in) const
return the cell size for the number of particles and rs
Definition: HEGGrid.h:66
TinyVector< int, D > SingleParticleIndex
the type of a D-dimensional index vector
T Scalar_t
the type of scalar