Grid 0.7.0
CovariantLaplacian.h
Go to the documentation of this file.
1/*************************************************************************************
2
3Grid physics library, www.github.com/paboyle/Grid
4
5Source file: ./lib/qcd/action/scalar/CovariantLaplacian.h
6
7Copyright (C) 2016
8
9Author: Guido Cossu <guido.cossu@ed.ac.uk>
10
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2 of the License, or
14(at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License along
22with this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25See the full license in the file "LICENSE" in the top level distribution
26directory
27*************************************************************************************/
28 /* END LEGAL */
29#pragma once
30
32
33struct LaplacianParams : Serializable {
35 RealD, lo,
36 RealD, hi,
37 int, MaxIter,
38 RealD, tolerance,
39 int, degree,
40 int, precision);
41
42 // constructor
44 RealD hi = 1.0,
45 int maxit = 1000,
46 RealD tol = 1.0e-8,
47 int degree = 10,
48 int precision = 64)
49 : lo(lo),
50 hi(hi),
51 MaxIter(maxit),
52 tolerance(tol),
53 degree(degree),
54 precision(precision){};
55};
56
57
58
60// Laplacian operator L on adjoint fields
61//
62// phi: adjoint field
63// L: D_mu^dag D_mu
64//
65// L phi(x) = Sum_mu [ U_mu(x)phi(x+mu)U_mu(x)^dag +
66// U_mu(x-mu)^dag phi(x-mu)U_mu(x-mu)
67// -2phi(x)]
68//
69// Operator designed to be encapsulated by
70// an HermitianLinearOperator<.. , ..>
72
73template <class Impl>
74class LaplacianAdjointField: public Metric<typename Impl::Field> {
79
80public:
82
84 : U(Nd, grid), Solver(S), param(p), kappa(k){
85 AlgRemez remez(param.lo,param.hi,param.precision);
86 std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
87 remez.generateApprox(param.degree,1,2);
88 PowerHalf.Init(remez,param.tolerance,false);
89 PowerInvHalf.Init(remez,param.tolerance,true);
90
91
92 };
93
94 void Mdir(const GaugeField&, GaugeField&, int, int){ assert(0);}
95 void MdirAll(const GaugeField&, std::vector<GaugeField> &){ assert(0);}
96 void Mdiag(const GaugeField&, GaugeField&){ assert(0);}
97
98 void ImportGauge(const GaugeField& _U) {
99 for (int mu = 0; mu < Nd; mu++) {
100 U[mu] = PeekIndex<LorentzIndex>(_U, mu);
101 }
102 }
103
104 void M(const GaugeField& in, GaugeField& out) {
105 // in is an antihermitian matrix
106 // test
107 //GaugeField herm = in + adj(in);
108 //std::cout << "AHermiticity: " << norm2(herm) << std::endl;
109
110 GaugeLinkField tmp(in.Grid());
111 GaugeLinkField tmp2(in.Grid());
112 GaugeLinkField sum(in.Grid());
113
114 for (int nu = 0; nu < Nd; nu++) {
115 sum = Zero();
116 GaugeLinkField in_nu = PeekIndex<LorentzIndex>(in, nu);
117 GaugeLinkField out_nu(out.Grid());
118 for (int mu = 0; mu < Nd; mu++) {
119 tmp = U[mu] * Cshift(in_nu, mu, +1) * adj(U[mu]);
120 tmp2 = adj(U[mu]) * in_nu * U[mu];
121 sum += tmp + Cshift(tmp2, mu, -1) - 2.0 * in_nu;
122 }
123 out_nu = (1.0 - kappa) * in_nu - kappa / (double(4 * Nd)) * sum;
124 PokeIndex<LorentzIndex>(out, out_nu, nu);
125 }
126 }
127
128 void MDeriv(const GaugeField& in, GaugeField& der) {
129 // in is anti-hermitian
130 RealD factor = -kappa / (double(4 * Nd));
131
132 for (int mu = 0; mu < Nd; mu++){
133 GaugeLinkField der_mu(der.Grid());
134 der_mu = Zero();
135 for (int nu = 0; nu < Nd; nu++){
136 GaugeLinkField in_nu = PeekIndex<LorentzIndex>(in, nu);
137 der_mu += U[mu] * Cshift(in_nu, mu, 1) * adj(U[mu]) * in_nu;
138 }
139 // the minus sign comes by using the in_nu instead of the
140 // adjoint in the last multiplication
141 PokeIndex<LorentzIndex>(der, -2.0 * factor * der_mu, mu);
142 }
143 }
144
145 // separating this temporarily
146 void MDeriv(const GaugeField& left, const GaugeField& right,
147 GaugeField& der) {
148 // in is anti-hermitian
149 RealD factor = -kappa / (double(4 * Nd));
150
151 for (int mu = 0; mu < Nd; mu++) {
152 GaugeLinkField der_mu(der.Grid());
153 der_mu = Zero();
154 for (int nu = 0; nu < Nd; nu++) {
155 GaugeLinkField left_nu = PeekIndex<LorentzIndex>(left, nu);
156 GaugeLinkField right_nu = PeekIndex<LorentzIndex>(right, nu);
157 der_mu += U[mu] * Cshift(left_nu, mu, 1) * adj(U[mu]) * right_nu;
158 der_mu += U[mu] * Cshift(right_nu, mu, 1) * adj(U[mu]) * left_nu;
159 }
160 PokeIndex<LorentzIndex>(der, -factor * der_mu, mu);
161 }
162 }
163
164 void Minv(const GaugeField& in, GaugeField& inverted){
166 Solver(HermOp, in, inverted);
167 }
168
169 void MSquareRoot(GaugeField& P){
170 GaugeField Gp(P.Grid());
173 msCG(HermOp,P,Gp);
174 P = Gp;
175 }
176
177 void MInvSquareRoot(GaugeField& P){
178 GaugeField Gp(P.Grid());
181 msCG(HermOp,P,Gp);
182 P = Gp;
183 }
184
185
186
187private:
189 std::vector<GaugeLinkField> U;
190};
191
auto Cshift(const Expression &expr, int dim, int shift) -> decltype(closure(expr))
Definition Cshift.h:55
void PokeIndex(Lattice< vobj > &lhs, const Lattice< decltype(peekIndex< Index >(vobj(), 0))> &rhs, int i)
auto PeekIndex(const Lattice< vobj > &lhs, int i) -> Lattice< decltype(peekIndex< Index >(vobj(), i))>
Lattice< vobj > adj(const Lattice< vobj > &lhs)
vobj::scalar_object sum(const vobj *arg, Integer osites)
GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL")
#define NAMESPACE_BEGIN(A)
Definition Namespace.h:35
#define NAMESPACE_END(A)
Definition Namespace.h:36
static constexpr int Nd
Definition QCD.h:52
double RealD
Definition Simd.h:61
double generateApprox(int num_degree, int den_degree, unsigned long power_num, unsigned long power_den, int a_len, double *a_param, int *a_pow)
Definition Remez.cc:114
OperatorFunction< typename Impl::Field > & Solver
void Mdiag(const GaugeField &, GaugeField &)
MultiShiftFunction PowerHalf
void MDeriv(const GaugeField &in, GaugeField &der)
void Mdir(const GaugeField &, GaugeField &, int, int)
MultiShiftFunction PowerInvHalf
LaplacianAdjointField(GridBase *grid, OperatorFunction< GaugeField > &S, LaplacianParams &p, const RealD k=1.0)
void MInvSquareRoot(GaugeField &P)
void MDeriv(const GaugeField &left, const GaugeField &right, GaugeField &der)
void ImportGauge(const GaugeField &_U)
std::vector< GaugeLinkField > U
void MSquareRoot(GaugeField &P)
void M(const GaugeField &in, GaugeField &out)
void MdirAll(const GaugeField &, std::vector< GaugeField > &)
void Minv(const GaugeField &in, GaugeField &inverted)
Definition Simd.h:194
LaplacianParams(RealD lo=0.0, RealD hi=1.0, int maxit=1000, RealD tol=1.0e-8, int degree=10, int precision=64)
GRID_SERIALIZABLE_CLASS_MEMBERS(LaplacianParams, RealD, lo, RealD, hi, int, MaxIter, RealD, tolerance, int, degree, int, precision)