JDFTx  1.2.0
Operators_internal.h
1 /*-------------------------------------------------------------------
2 Copyright 2011 Ravishankar Sundararaman
3 
4 This file is part of JDFTx.
5 
6 JDFTx is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 JDFTx is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with JDFTx. If not, see <http://www.gnu.org/licenses/>.
18 -------------------------------------------------------------------*/
19 
20 #ifndef JDFTX_CORE_OPERATORS_INTERNAL_H
21 #define JDFTX_CORE_OPERATORS_INTERNAL_H
22 
23 #include <core/matrix3.h>
24 #include <core/vector3.h>
25 #include <core/tensor3.h>
26 #include <core/LoopMacros.h>
27 
29 #define COMPUTE_fullRefIndices \
30  vector3<int> iv(iG), ivRef; \
31  for(int k=0; k<3; k++) \
32  { if(iv[k]<0) iv[k] += S[k]; \
33  ivRef[k] = iv[k] ? S[k] - iv[k] : 0; \
34  } \
35  int iFull = iv[2] + S[2]*(iv[1] + S[1]*iv[0]); \
36  int iFullRef = ivRef[2] + S[2]*(ivRef[1] + S[1]*ivRef[0]);
37 
38 
39 __hostanddev__
40 void RealG_calc(int iHalf, const vector3<int> iG, const vector3<int> S,
41  const complex* vFull, complex* vHalf, double scaleFac)
42 {
43  COMPUTE_fullRefIndices
44  vHalf[iHalf] = scaleFac*0.5*(vFull[iFull] + vFull[iFullRef].conj());
45 }
46 
47 __hostanddev__
48 void ImagG_calc(int iHalf, const vector3<int> iG, const vector3<int> S,
49  const complex* vFull, complex* vHalf, double scaleFac)
50 {
51  COMPUTE_fullRefIndices
52  vHalf[iHalf] = complex(0,-scaleFac*0.5)*(vFull[iFull] - vFull[iFullRef].conj());
53 }
54 
55 __hostanddev__
56 void ComplexG_calc(int iHalf, const vector3<int> iG, const vector3<int> S,
57  const complex* vHalf, complex *vFull, double scaleFac)
58 {
59  COMPUTE_fullRefIndices
60  complex temp = scaleFac*vHalf[iHalf];
61  vFull[iFull] = temp; //Copy value into corresponding location in full-space
62  vFull[iFullRef] = temp.conj(); //Also set complex conjugate into the mirror location
63 }
64 
65 __hostanddev__
66 void changeGrid_calc(const vector3<int>& iG, const vector3<int>& Sin, const vector3<int>& Sout, const complex* in, complex* out)
67 { //Compute index:
68  #define COMPUTE_index(suffix) \
69  int i##suffix = 0; \
70  for(int k=0; k<2; k++) \
71  { if(2*iG[k]<1-S##suffix[k] || 2*iG[k]>S##suffix[k]) return; \
72  i##suffix = i##suffix * S##suffix[k] + (iG[k]<0 ? (iG[k]+S##suffix[k]) : iG[k]); \
73  } \
74  if(2*iG[2]>S##suffix[2]) return; \
75  else i##suffix = i##suffix*(1+S##suffix[2]/2) + iG[2];
76  COMPUTE_index(in)
77  COMPUTE_index(out)
78  #undef COMPUTE_index
79  out[iout] = in[iin];
80 }
81 __hostanddev__
82 void changeGridFull_calc(const vector3<int>& iG, const vector3<int>& Sin, const vector3<int>& Sout, const complex* in, complex* out)
83 { //Compute index:
84  #define COMPUTE_index(suffix) \
85  int i##suffix = 0; \
86  for(int k=0; k<3; k++) \
87  { if(2*iG[k]<1-S##suffix[k] || 2*iG[k]>S##suffix[k]) return; \
88  i##suffix = i##suffix * S##suffix[k] + (iG[k]<0 ? (iG[k]+S##suffix[k]) : iG[k]); \
89  }
90  COMPUTE_index(in)
91  COMPUTE_index(out)
92  #undef COMPUTE_index
93  out[iout] = in[iin];
94 }
95 
96 __hostanddev__ void gradient_calc(int i, const vector3<int> iG, bool nyq, const matrix3<> G,
97  const complex* Xtilde, vector3<complex*>& gradTilde)
98 { complex iota(0.0, nyq ? 0.0 : 1.0); //zero nyquist frequencies
99  storeVector((iG*G) * (iota*Xtilde[i]), gradTilde, i);
100 }
101 
102 __hostanddev__ void divergence_calc(int i, const vector3<int> iG, bool nyq, const matrix3<> G,
103  vector3<const complex*>& Vtilde, complex* divTilde)
104 { complex iota(0.0, nyq ? 0.0 : 1.0); //zero nyquist frequencies
105  divTilde[i] = iota * dot(iG*G, loadVector(Vtilde,i));
106 }
107 
108 
109 __hostanddev__ void tensorGradient_calc(int i, const vector3<int> iG, bool nyq, const matrix3<> G,
110  const complex* Xtilde, tensor3<complex*>& gradTilde)
111 {
112  complex minus_Xtilde = nyq ? complex(0,0) : -Xtilde[i]; //zero nyquist frequencies
113  vector3<> Gvec = iG*G;
114  double Gsq = Gvec.length_squared();
115  gradTilde.xy()[i] = minus_Xtilde*Gvec.x()*Gvec.y();
116  gradTilde.yz()[i] = minus_Xtilde*Gvec.y()*Gvec.z();
117  gradTilde.zx()[i] = minus_Xtilde*Gvec.z()*Gvec.x();
118  gradTilde.xxr()[i] = minus_Xtilde*(Gvec.x()*Gvec.x() - (1.0/3)*Gsq);
119  gradTilde.yyr()[i] = minus_Xtilde*(Gvec.y()*Gvec.y() - (1.0/3)*Gsq);
120 }
121 
122 __hostanddev__ void tensorDivergence_calc(int i, const vector3<int> iG, bool nyq, const matrix3<> G,
123  tensor3<const complex*>& Vtilde, complex* divTilde)
124 {
125  complex temp = complex(0,0);
126  if(!nyq)
127  { vector3<> Gvec = iG*G;
128  temp += Vtilde.xy()[i]*( 2*Gvec.x()*Gvec.y() );
129  temp += Vtilde.yz()[i]*( 2*Gvec.y()*Gvec.z() );
130  temp += Vtilde.zx()[i]*( 2*Gvec.z()*Gvec.x() );
131  temp += Vtilde.xxr()[i]*( Gvec.x()*Gvec.x() - Gvec.z()*Gvec.z() );
132  temp += Vtilde.yyr()[i]*( Gvec.y()*Gvec.y() - Gvec.z()*Gvec.z() );
133  }
134  divTilde[i] = -temp;
135 }
136 
137 
138 #endif //JDFTX_CORE_OPERATORS_INTERNAL_H
complex dot(const Tptr &X, const Tptr &Y)
Definition: Operators.h:196
__hostanddev__ scalar & xxr()
xxr = x^2 - r^2/3
Definition: tensor3.h:42
__hostanddev__ void storeVector(const vector3< scalar > &v, vector3< scalar * > &vArr, int i)
Store vector to a vector field.
Definition: vector3.h:171
__hostanddev__ scalar & yyr()
yyr = y^2-r^2/3
Definition: tensor3.h:43
Symmetric traceless rank-2 tensor in 3D.
Definition: tensor3.h:32
__hostanddev__ vector3< scalar > loadVector(const vector3< const scalar * > &vArr, int i)
Load vector from a constant vector field.
Definition: vector3.h:163
Complex number (need to define our own because we need operators for gpu code as well) ...
Definition: scalar.h:49