Commit b0988af9 by Francois Gygi

merge trunk as of 1709


git-svn-id: http://qboxcode.org/svn/qb/branches/efield@1710 cba15fb0-1239-40c8-b417-11db7ca47a34
parent 0e693aab
......@@ -33,7 +33,6 @@ BasisMapping::BasisMapping (const Basis &basis) : basis_(basis)
np0_ = basis.np(0);
np1_ = basis.np(1);
np2_ = basis.np(2);
np012_ = np0_ * np1_ * np2_;
np2_loc_.resize(nprocs_);
np2_first_.resize(nprocs_);
......
......@@ -31,7 +31,7 @@ class BasisMapping
const Basis& basis_;
int nprocs_, myproc_;
int np0_, np1_, np2_, np012_, np012loc_;
int np0_, np1_, np2_, np012loc_;
int nvec_;
std::vector<int> np2_loc_; // np2_loc_[iproc], iproc=0, nprocs_-1
......@@ -50,7 +50,6 @@ class BasisMapping
int np1(void) const { return np1_; }
int np2(void) const { return np2_; }
int np2loc(void) const { return np2_loc_[myproc_]; }
int np012(void) const { return np012_; }
int np012loc(void) const { return np012loc_; }
int nvec(void) const { return nvec_; }
int zvec_size(void) const { return nvec_ * np2_; }
......
......@@ -156,6 +156,12 @@ void CGOptimizer::compute_xp(const valarray<double>& x, const double f,
fp0_ = fp;
}
// set the starting alpha of the minimizer to be the current alpha_
if ( alpha_ < linmin_.alpha_max() )
linmin_.set_alpha_start(alpha_);
else
linmin_.set_alpha_start(0.5*linmin_.alpha_max());
// reset the line minimizer
linmin_.reset();
alpha_ = linmin_.next_alpha(alpha_,f,fp);
......
......@@ -287,9 +287,12 @@ class D3tensor
os.setf(ios::fixed,ios::floatfield);
os.setf(ios::right,ios::adjustfield);
os.precision(8);
os << setw(12) << v[0] << setw(12) << v[3] << setw(12) << v[6] << "\n"
<< setw(12) << v[1] << setw(12) << v[4] << setw(12) << v[7] << "\n"
<< setw(12) << v[2] << setw(12) << v[5] << setw(12) << v[8] << "\n";
os << setw(14) << v[0] << " " << setw(14) << v[3] << " " << setw(14) << v[6]
<< "\n"
<< setw(14) << v[1] << " " << setw(14) << v[4] << " " << setw(14) << v[7]
<< "\n"
<< setw(14) << v[2] << " " << setw(14) << v[5] << " " << setw(14) << v[8]
<< "\n";
return os;
}
......
......@@ -1273,14 +1273,14 @@ void FourierTransform::fwd(complex<double>* val)
#if USE_ESSL_FFT
int inc1 = 1, inc2 = np2_, ntrans = nvec_, isign = 1, initflag = 0;
double scale = 1.0 / (np0_ * np1_ * np2_);
double scale = 1.0 / np012();
dcft_(&initflag,&zvec_[0],&inc1,&inc2,&zvec_[0],&inc1,&inc2,&np2_,&ntrans,
&isign,&scale,&aux1zf[0],&naux1z,&aux2[0],&naux2);
#elif USE_FFTW2
#if _OPENMP
const double fac = 1.0 / ( np0_ * np1_ * np2_ );
const double fac = 1.0 / np012();
#pragma omp parallel for
for ( int i = 0; i < nvec_; i++ )
{
......@@ -1306,7 +1306,7 @@ void FourierTransform::fwd(complex<double>* val)
fftw(fwplan2,ntrans,(FFTW_COMPLEX*)&zvec_[0],inc1,inc2,
(FFTW_COMPLEX*)0,0,0);
int len = zvec_.size();
double fac = 1.0 / ( np0_ * np1_ * np2_ );
double fac = 1.0 / np012();
zdscal(&len,&fac,&zvec_[0],&inc1);
#endif
#elif USE_FFTW3
......@@ -1324,7 +1324,7 @@ void FourierTransform::fwd(complex<double>* val)
}
#endif
// scale
double fac = 1.0 / ( np0_ * np1_ * np2_ );
double fac = 1.0 / np012();
int len = zvec_.size();
int inc1 = 1;
zdscal(&len,&fac,&zvec_[0],&inc1);
......@@ -1335,7 +1335,7 @@ void FourierTransform::fwd(complex<double>* val)
int length = np2_;
int ainc = 1;
int ajmp = np2_;
double scale = 1.0 / ( np0_ * np1_ * np2_ );
double scale = 1.0 / np012();
int idir = 1;
cfftm ( &zvec_[0], &zvec_[0], scale, ntrans, length, ainc, ajmp, idir );
#else
......@@ -1390,7 +1390,7 @@ void FourierTransform::init_lib(void)
isign = -1;
dcft_(&initflag,p,&inc1,&inc2,p,&inc1,&inc2,&np2_,&ntrans,
&isign,&scale,&aux1zb[0],&naux1z,&aux2[0],&naux2);
isign = 1; scale = 1.0 / ( np0_ * np1_ * np2_ );
isign = 1; scale = 1.0 / np012();
dcft_(&initflag,p,&inc1,&inc2,p,&inc1,&inc2,&np2_,&ntrans,
&isign,&scale,&aux1zf[0],&naux1z,&aux2[0],&naux2);
#else // USE_ESSL_2DFFT
......@@ -1441,7 +1441,7 @@ void FourierTransform::init_lib(void)
isign = -1;
dcft_(&initflag,p,&inc1,&inc2,p,&inc1,&inc2,&np2_,&ntrans,
&isign,&scale,&aux1zb[0],&naux1z,&aux2[0],&naux2);
isign = 1; scale = 1.0 / ( np0_ * np1_ * np2_ );
isign = 1; scale = 1.0 / np012();
dcft_(&initflag,p,&inc1,&inc2,p,&inc1,&inc2,&np2_,&ntrans,
&isign,&scale,&aux1zf[0],&naux1z,&aux2[0],&naux2);
......@@ -1804,7 +1804,7 @@ void cfftm ( complex<double> *ain, complex<double> *aout, double scale,
* Transcription from 'FFT as Nested Multiplication, with a twist'
* C. de Boor, SIAM Sci. Stat. Comput., Vol 1, No 1, March 1980
*
* Adapted to C by F.Gygi, 17 Feb 1993, 9 Dec 1993
* Adapted to C 17 Feb 1993, 9 Dec 1993
*
******************************************************************************/
......
......@@ -142,7 +142,7 @@ class FourierTransform
int np2_loc(int iproc) const { return np2_loc_[iproc]; }
int np2_first() const { return np2_first_[myproc_]; }
int np2_first(int iproc) const { return np2_first_[iproc]; }
int np012() const { return np0_ * np1_ * np2_; }
long int np012() const { return ((long int)np0_) * np1_ * np2_; }
int np012loc(int iproc) const { return np0_ * np1_ * np2_loc_[iproc]; }
int np012loc() const { return np0_ * np1_ * np2_loc_[myproc_]; }
int index(int i, int j, int k) const
......
......@@ -28,7 +28,7 @@ OBJECTS=qb.o AtomSet.o Atom.o Species.o \
LoadCmd.o SaveCmd.o \
SpeciesCmd.o SpeciesReader.o SpeciesHandler.o \
XCOperator.o ExchangeOperator.o Bisection.o KPGridConnectivity.o \
XCPotential.o LDAFunctional.o \
XCPotential.o LDAFunctional.o VWNFunctional.o \
PBEFunctional.o BLYPFunctional.o B3LYPFunctional.o \
NonLocalPotential.o SampleReader.o StructuredDocumentHandler.o \
SampleHandler.o AtomSetHandler.o WavefunctionHandler.o \
......
......@@ -145,7 +145,7 @@ void PBEFunctional::setxc(void)
// excpbe: PBE exchange-correlation
// K.Burke's modification of PW91 codes, May 14, 1996.
// Modified again by K.Burke, June 29, 1996, with simpler Fx(s)
// Translated into C and modified by F.Gygi, Dec 9, 1996.
// Translated into C and modified Dec 9, 1996.
//
// input:
// rho: density
......@@ -480,7 +480,7 @@ void PBEFunctional::excpbe_sp(double rho_up, double rho_dn,
//
// gcor2.c: Interpolate LSD correlation energy
// as given by (10) of Perdew & Wang, Phys Rev B45 13244 (1992)
// Translated into C by F.Gygi, Dec 9, 1996
// Translated into C Dec 9, 1996
//
////////////////////////////////////////////////////////////////////////////////
......
......@@ -112,8 +112,7 @@ bool Species::initialize_ncpp()
// ndft_ is a power of 2 larger than ( rdftmin / deltar_ )
// minimum outer bound in (a.u.)
const double rdftmin = 40.0;
// next line: limit small mesh sizes
assert(deltar_ > 0.0001);
assert(deltar_ > 0.0);
ndft_ = 1;
while ( ndft_ * deltar_ < rdftmin )
ndft_ *= 2;
......@@ -1146,6 +1145,8 @@ void Species::print(ostream &os, bool expanded_form)
}
else
{
os.setf(ios::scientific,ios::floatfield);
os << setprecision(12);
os <<"<species name=\"" << name() << "\">" << endl;
os << "<description>" << description() << "</description>" << endl;
os << "<symbol>" << symbol() << "</symbol>" << endl;
......@@ -1160,8 +1161,6 @@ void Species::print(ostream &os, bool expanded_form)
os << "<nquad>" << nquad() << "</nquad>" << endl;
os << "<rquad>" << rquad() << "</rquad>" << endl;
os << "<mesh_spacing>" << deltar() << "</mesh_spacing>" << endl;
os.setf(ios::fixed,ios::floatfield);
os << setprecision(6);
if ( nlcc_.size() > 0 ) print_nlcc(os);
for ( int l = 0; l <= lmax(); l++ )
{
......@@ -1271,8 +1270,8 @@ void Species::info(ostream &os)
// describe type of potential
if ( type_ == NCPP )
{
os.setf(ios::fixed,ios::floatfield);
os << setprecision(6);
os.setf(ios::scientific,ios::floatfield);
os << setprecision(12);
if ( nquad() == 0 )
{
if ( lmax() == 0 )
......
......@@ -15,7 +15,6 @@
// StrX.h
//
////////////////////////////////////////////////////////////////////////////////
// $Id: StrX.h,v 1.5 2008-09-08 15:56:19 fgygi Exp $
#ifndef STRX_H
#define STRX_H
......@@ -40,7 +39,7 @@ public :
~StrX()
{
delete [] fLocalForm;
XMLString::release(&fLocalForm);
}
// -----------------------------------------------------------------------
......
......@@ -15,7 +15,6 @@
// StructuredDocumentHandler.C
//
////////////////////////////////////////////////////////////////////////////////
// $Id: StructuredDocumentHandler.C,v 1.10 2009-11-30 02:35:35 fgygi Exp $
#if USE_XERCES
......@@ -60,7 +59,10 @@ void StructuredDocumentHandler::startElement(const XMLCh* const uri,
}
////////////////////////////////////////////////////////////////////////////////
#if XERCESC_3
#ifndef XERCES_VERSION_MAJOR
#error "XERCES_VERSION_MAJOR not defined"
#endif
#if XERCES_VERSION_MAJOR > 2
void StructuredDocumentHandler::characters(const XMLCh* const chars,
const XMLSize_t length)
#else
......
......@@ -15,7 +15,6 @@
// StructuredDocumentHandler.h
//
////////////////////////////////////////////////////////////////////////////////
// $Id: StructuredDocumentHandler.h,v 1.5 2008-09-08 15:56:19 fgygi Exp $
#ifndef STRUCTUREDDOCUMENTHANDLER_H
#define STRUCTUREDDOCUMENTHANDLER_H
......@@ -61,7 +60,10 @@ class StructuredDocumentHandler : public DefaultHandler
void startElement(const XMLCh* const uri,const XMLCh* const localname,
const XMLCh* const qname, const Attributes& attributes);
#if XERCESC_3
#ifndef XERCES_VERSION_MAJOR
#error "XERCES_VERSION_MAJOR not defined"
#endif
#if XERCES_VERSION_MAJOR > 2
void characters(const XMLCh* const chars, const XMLSize_t length);
#else
void characters(const XMLCh* const chars, const unsigned int length);
......
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 The Regents of the University of California
//
// This file is part of Qbox
//
// Qbox is distributed under the terms of the GNU General Public License
// as published by the Free Software Foundation, either version 2 of
// the License, or (at your option) any later version.
// See the file COPYING in the root directory of this distribution
// or <http://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////////////
//
// VWNFunctional.C
//
// LDA Exchange-correlation energy and potential
// S.H.Vosko, L.Wilk, M.Nusair, Can. J. Phys. 58, 1200 (1980)
//
////////////////////////////////////////////////////////////////////////////////
#include <cmath>
#include <cassert>
#include <vector>
#include "VWNFunctional.h"
#include<iostream>
using namespace std;
void VWNFunctional::setxc(void)
{
if ( _np == 0 ) return;
if ( _nspin == 1 )
{
// unpolarized
assert(rho != 0);
assert(exc != 0);
assert(vxc1 != 0);
#pragma omp parallel for
for ( int ir = 0; ir < _np; ir++ )
{
double ex,vx,ec,vc;
xc_unpolarized(rho[ir],ex,vx,ec,vc);
exc[ir] = ex + ec;
vxc1[ir] = vx + vc;
}
}
else
{
// polarized
assert(rho_up != 0);
assert(rho_dn != 0);
assert(exc != 0);
assert(vxc1_up != 0);
assert(vxc1_dn != 0);
const double fz_prefac = 1.0 / ( cbrt(2.0)*2.0 - 2.0 );
const double dfz_prefac = (4.0/3.0) * fz_prefac;
#pragma omp parallel for
for ( int ir = 0; ir < _np; ir++ )
{
double ex = 0.0;
double ec = 0.0;
double vx_up = 0.0;
double vx_dn = 0.0;
double vc_up = 0.0;
double vc_dn = 0.0;
double roe_up = rho_up[ir];
double roe_dn = rho_dn[ir];
double roe = roe_up + roe_dn;
if ( roe > 0.0 )
{
const double zeta = ( roe_up - roe_dn ) / roe;
const double zp1 = 1.0 + zeta;
const double zm1 = 1.0 - zeta;
const double zp1_13 = cbrt(zp1);
const double zm1_13 = cbrt(zm1);
const double fz = fz_prefac * ( zp1_13 * zp1 + zm1_13 * zm1 - 2.0 );
const double dfz = dfz_prefac * ( zp1_13 - zm1_13 );
double ex_u,ec_u,vx_u,vc_u;
double ex_p,ec_p,vx_p,vc_p;
double a,da;
xc_unpolarized(roe,ex_u,vx_u,ec_u,vc_u);
xc_polarized(roe,ex_p,vx_p,ec_p,vc_p);
alpha_c(roe,a,da);
const double ex_pu = ex_p - ex_u;
ex = ex_u + fz * ex_pu;
double vx = vx_u + fz * ( vx_p - vx_u );
vx_up = vx + ex_pu * ( 1.0 - zeta ) * dfz;
vx_dn = vx - ex_pu * ( 1.0 + zeta ) * dfz;
const double zeta3 = zeta*zeta*zeta;
const double zeta4 = zeta3*zeta;
a *= (9.0/8.0)*fz_prefac;
da *= (9.0/8.0)*fz_prefac;
double ec_pu = ec_p - ec_u - a;
ec = ec_u + a * fz + ec_pu * fz * zeta4;
const double vc1 = vc_u + da * fz + ( vc_p - vc_u - da ) * fz * zeta4;
const double vc2 = a * dfz + ec_pu * zeta3 * ( 4.0*fz + zeta*dfz );
vc_up = vc1 + ( 1.0 - zeta ) * vc2;
vc_dn = vc1 - ( 1.0 + zeta ) * vc2;
}
vxc1_up[ir] = vx_up + vc_up;
vxc1_dn[ir] = vx_dn + vc_dn;
exc[ir] = ex + ec;
}
}
}
void VWNFunctional::xc_unpolarized(const double rh, double &ex, double &vx,
double &ec, double &vc)
{
// unpolarized xc energy and potential
// const double third=1.0/3.0;
// c1 is (3.D0/(4.D0*pi))**third
const double c1 = 0.6203504908994001;
// alpha = (4/(9*pi))**third = 0.521061761198
// const double alpha = 0.521061761198;
// c2 = -(3/(4*pi)) / alpha = -0.458165293283
// const double c2 = -0.458165293283;
// c3 = (4/3) * c2 = -0.610887057711
const double c3 = -0.610887057711;
ex = 0.0;
vx = 0.0;
ec = 0.0;
vc = 0.0;
if ( rh > 0.0 )
{
const double A = 0.0310907;
const double x0 = -0.10498;
const double b = 3.72744;
const double c = 12.9352;
const double Q = sqrt( 4.0 * c - b * b );
const double fac1 = 2.0 * b / Q;
const double fac2 = b * x0 / ( x0 * x0 + b * x0 + c );
const double fac3 = 2.0 * ( 2.0 * x0 + b ) / Q;
double ro13 = cbrt(rh);
double rs = c1 / ro13;
// Next line : exchange part in Hartree units
vx = c3 / rs;
ex = 0.75 * vx;
double sqrtrs = sqrt(rs);
double X = rs + b * sqrtrs + c;
double fatan = atan( Q / ( 2.0 * sqrtrs + b ) );
ec = A * ( log( rs / X ) + fac1 * fatan -
fac2 * ( log( (sqrtrs-x0)*(sqrtrs-x0) / X ) +
fac3 * fatan ));
double t = sqrtrs - x0;
vc = ec + ( A / 3.0 ) * ( b * sqrtrs * x0 - c * t ) / ( X * t );
}
}
void VWNFunctional::xc_polarized(const double rh, double &ex, double &vx,
double &ec, double &vc)
{
// polarized xc energy and potential
// const double third=1.0/3.0;
// c1 is (3.D0/(4.D0*pi))**third
const double c1 = 0.6203504908994001;
// alpha = (4/(9*pi))**third = 0.521061761198
// const double alpha = 0.521061761198;
// c2 = -(3/(4*pi)) / alpha = -0.458165293283
// const double c2 = -0.458165293283;
// c3 = (4/3) * c2 = -0.610887057711
// c4 = 2**third * c3
const double c4 = -0.769669463118;
ex = 0.0;
vx = 0.0;
ec = 0.0;
vc = 0.0;
if ( rh > 0.0 )
{
const double A = 0.01554535;
const double x0 = -0.32500;
const double b = 7.06042;
const double c = 18.0578;
const double Q = sqrt( 4.0 * c - b * b );
const double fac1 = 2.0 * b / Q;
const double fac2 = b * x0 / ( x0 * x0 + b * x0 + c );
const double fac3 = 2.0 * ( 2.0 * x0 + b ) / Q;
double ro13 = cbrt(rh);
double rs = c1 / ro13;
// Next line : exchange part in Hartree units
vx = c4 / rs;
ex = 0.75 * vx;
double sqrtrs = sqrt(rs);
double X = rs + b * sqrtrs + c;
double fatan = atan( Q / ( 2.0 * sqrtrs + b ) );
ec = A * ( log( rs / X ) + fac1 * fatan -
fac2 * ( log( (sqrtrs-x0)*(sqrtrs-x0) / X ) +
fac3 * fatan ));
double t = sqrtrs - x0;
vc = ec + ( A / 3.0 ) * ( b * sqrtrs * x0 - c * t ) / ( X * t );
}
}
void VWNFunctional::alpha_c(const double rh, double &a, double &da)
{
// VWN spin stiffness alpha_c(rh)
// a = spin stiffness
// da = d(rh * a)/drh
// const double third=1.0/3.0;
// c1 is (3.D0/(4.D0*pi))**third
const double c1 = 0.6203504908994001;
// alpha = (4/(9*pi))**third = 0.521061761198
// const double alpha = 0.521061761198;
// c2 = -(3/(4*pi)) / alpha = -0.458165293283
// const double c2 = -0.458165293283;
// c3 = (4/3) * c2 = -0.610887057711
a = 0.0;
da = 0.0;
if ( rh > 0.0 )
{
const double A = 1.0/(6.0*M_PI*M_PI);
const double x0 = -0.0047584;
const double b = 1.13107;
const double c = 13.0045;
const double Q = sqrt( 4.0 * c - b * b );
const double fac1 = 2.0 * b / Q;
const double fac2 = b * x0 / ( x0 * x0 + b * x0 + c );
const double fac3 = 2.0 * ( 2.0 * x0 + b ) / Q;
double ro13 = cbrt(rh);
double rs = c1 / ro13;
double sqrtrs = sqrt(rs);
double X = rs + b * sqrtrs + c;
double fatan = atan( Q / ( 2.0 * sqrtrs + b ) );
a = A * ( log( rs / X ) + fac1 * fatan -
fac2 * ( log( (sqrtrs-x0)*(sqrtrs-x0) / X ) +
fac3 * fatan ));
double t = sqrtrs - x0;
da = a + ( A / 3.0 ) * ( b * sqrtrs * x0 - c * t ) / ( X * t );
}
}
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 The Regents of the University of California
//
// This file is part of Qbox
//
// Qbox is distributed under the terms of the GNU General Public License
// as published by the Free Software Foundation, either version 2 of
// the License, or (at your option) any later version.
// See the file COPYING in the root directory of this distribution
// or <http://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////////////
//
// VWNFunctional.h
//
////////////////////////////////////////////////////////////////////////////////
#ifndef VWNFUNCTIONAL_H
#define VWNFUNCTIONAL_H
#include <vector>
#include <cassert>
#include "XCFunctional.h"
class VWNFunctional : public XCFunctional
{
void xc_unpolarized(const double rh, double &ex, double &vx,
double &ec, double &vc);
void xc_polarized(const double rh, double &ex, double &vx,
double &ec, double &vc);
void alpha_c(const double rh, double &a, double &da);
std::vector<double> _exc;
std::vector<std::vector<double> > _vxc;
VWNFunctional();
public:
VWNFunctional(const std::vector<std::vector<double> > &rhoe)
{
_nspin = rhoe.size();
if ( _nspin > 1 ) assert(rhoe[0].size() == rhoe[1].size());
_np = rhoe[0].size();
_exc.resize(_np);
_vxc.resize(_nspin);
for ( int i = 0; i < _nspin; i++ )
{
_vxc[i].resize(_np);
}
if ( _nspin == 1 )
{
rho = &rhoe[0][0];
exc = &_exc[0];
vxc1 = &_vxc[0][0];
}
else
{
rho_up = &rhoe[0][0];
rho_dn = &rhoe[1][0];
exc = &_exc[0];
vxc1_up = &_vxc[0][0];
vxc1_dn = &_vxc[1][0];
}
};
bool isGGA() const { return false; };
std::string name() const { return "VWN"; };
void setxc(void);
};
#endif
......@@ -35,6 +35,7 @@ XCOperator::XCOperator(Sample& s, const ChargeDensity& cd) :cd_(cd)
// check the name of the functional
if ( ( functional_name == "LDA" ) ||
( functional_name == "VWN" ) ||
( functional_name == "PBE" ) ||
( functional_name == "BLYP" ) )
{
......
......@@ -18,6 +18,7 @@
#include "XCPotential.h"
#include "LDAFunctional.h"
#include "VWNFunctional.h"
#include "PBEFunctional.h"
#include "BLYPFunctional.h"
#include "B3LYPFunctional.h"
......@@ -35,6 +36,10 @@ XCPotential::XCPotential(const ChargeDensity& cd, const string functional_name,
{
xcf_ = new LDAFunctional(cd_.rhor);
}
else if ( functional_name == "VWN" )
{
xcf_ = new VWNFunctional(cd_.rhor);
}
else if ( functional_name == "PBE" )
{
xcf_ = new PBEFunctional(cd_.rhor);
......
......@@ -45,6 +45,7 @@ class Xc : public Var
string v = argv[1];
if ( !( v == "LDA" ||
v == "VWN" ||
v == "PBE" ||
v == "BLYP" ||
v == "HF" ||
......@@ -52,7 +53,7 @@ class Xc : public Var
v == "B3LYP" ) )
{
if ( ui->onpe0() )
cout << " xc must be LDA, PBE, BLYP, HF, PBE0 or B3LYP" << endl;
cout << " xc must be LDA, VWN, PBE, BLYP, HF, PBE0 or B3LYP" << endl;
return 1;
}
......
......@@ -19,5 +19,5 @@
#include "release.h"
std::string release(void)
{
return std::string("efield1");
return std::string("efield2");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment