My Project
Loading...
Searching...
No Matches
ewald_preparation.h
1#include <complex>
2#include <vector>
3#define M_PI 3.14159265358979323846
4
5void Ewald_Total(Boxsize& Box, Atoms*& Host_System, ForceField& FF, Components& SystemComponents, MoveEnergy& E)
6{
7 printf("****** Calculating Ewald Energy (CPU) ******\n");
8 int kx_max = Box.kmax.x;
9 int ky_max = Box.kmax.y;
10 int kz_max = Box.kmax.z;
11 if(FF.noCharges) return;
12 double alpha = Box.Alpha; double alpha_squared = alpha * alpha;
13 double prefactor = Box.Prefactor * (2.0 * M_PI / Box.Volume);
14
15
16 double3 ax = {Box.InverseCell[0], Box.InverseCell[3], Box.InverseCell[6]}; //printf("ax: %.10f, %.10f, %.10f\n", Box.InverseCell[0], Box.InverseCell[3], Box.InverseCell[6]);
17 double3 ay = {Box.InverseCell[1], Box.InverseCell[4], Box.InverseCell[7]}; //printf("ay: %.10f, %.10f, %.10f\n", Box.InverseCell[1], Box.InverseCell[4], Box.InverseCell[7]);
18 double3 az = {Box.InverseCell[2], Box.InverseCell[5], Box.InverseCell[8]}; //printf("az: %.10f, %.10f, %.10f\n", Box.InverseCell[2], Box.InverseCell[5], Box.InverseCell[8]);
19
20 size_t numberOfAtoms = 0;
21 for(size_t i=0; i < SystemComponents.Total_Components; i++) //Skip the first one(framework)
22 {
23 numberOfAtoms += SystemComponents.Moleculesize[i] * SystemComponents.NumberOfMolecule_for_Component[i];
24 }
25 //size_t numberOfWaveVectors = (kx_max + 1) * (2 * ky_max + 1) * (2 * kz_max + 1);
26 //Zhao's note: if starting with an empty box, numberOfAtoms = 0, but to allocate space on the GPU, you cannot do zero space for an array//
27 //Here, we use 2 * adsorbate_size, since this is the max size gonna be used in the Monte Carlo steps//
28 size_t eik_atomsize = 0;
29 for(size_t i = 0; i < SystemComponents.Moleculesize.size(); i++)
30 if(eik_atomsize < SystemComponents.Moleculesize[i]) eik_atomsize = SystemComponents.Moleculesize[i];
31 eik_atomsize *= 2;
32 if(eik_atomsize < numberOfAtoms) eik_atomsize = numberOfAtoms;
33 std::vector<std::complex<double>>eik_x(eik_atomsize * (kx_max + 1));
34 std::vector<std::complex<double>>eik_y(eik_atomsize * (ky_max + 1));
35 std::vector<std::complex<double>>eik_z(eik_atomsize * (kz_max + 1));
36 std::vector<std::complex<double>>eik_xy(eik_atomsize);
37 size_t numberOfWaveVectors = (Box.kmax.x + 1) * (2 * Box.kmax.y + 1) * (2 * Box.kmax.z + 1);
38 std::vector<std::complex<double>>AdsorbateEik(numberOfWaveVectors);
39 std::vector<std::complex<double>>FrameworkEik(numberOfWaveVectors);
40 // Construct exp(ik.r) for atoms and k-vectors kx, ky, kz = 0, 1 explicitly
41 size_t count=0;
42 for(size_t comp=0; comp < SystemComponents.Total_Components; comp++)
43 {
44 for(size_t posi=0; posi < SystemComponents.NumberOfMolecule_for_Component[comp] * SystemComponents.Moleculesize[comp]; posi++)
45 {
46 //determine the component for i
47 double3 pos = Host_System[comp].pos[posi];
48 eik_x[count + 0 * numberOfAtoms] = std::complex<double>(1.0, 0.0);
49 eik_y[count + 0 * numberOfAtoms] = std::complex<double>(1.0, 0.0);
50 eik_z[count + 0 * numberOfAtoms] = std::complex<double>(1.0, 0.0);
51 double3 s; matrix_multiply_by_vector(Box.InverseCell, pos, s); s*=2*M_PI;
52 eik_x[count + 1 * numberOfAtoms] = std::complex<double>(std::cos(s.x), std::sin(s.x));
53 eik_y[count + 1 * numberOfAtoms] = std::complex<double>(std::cos(s.y), std::sin(s.y));
54 eik_z[count + 1 * numberOfAtoms] = std::complex<double>(std::cos(s.z), std::sin(s.z));
55 count++;
56 }
57 }
58 // Calculate remaining positive kx, ky and kz by recurrence
59 for(size_t kx = 2; kx <= kx_max; ++kx)
60 {
61 for(size_t i = 0; i != numberOfAtoms; ++i)
62 {
63 eik_x[i + kx * numberOfAtoms] = eik_x[i + (kx - 1) * numberOfAtoms] * eik_x[i + 1 * numberOfAtoms];
64 }
65 }
66 for(size_t ky = 2; ky <= ky_max; ++ky)
67 {
68 for(size_t i = 0; i != numberOfAtoms; ++i)
69 {
70 eik_y[i + ky * numberOfAtoms] = eik_y[i + (ky - 1) * numberOfAtoms] * eik_y[i + 1 * numberOfAtoms];
71 }
72 }
73 for(size_t kz = 2; kz <= kz_max; ++kz)
74 {
75 for(size_t i = 0; i != numberOfAtoms; ++i)
76 {
77 eik_z[i + kz * numberOfAtoms] = eik_z[i + (kz - 1) * numberOfAtoms] * eik_z[i + 1 * numberOfAtoms];
78 }
79 }
80 size_t nvec = 0;
81 //for debugging
82 size_t kxcount = 0; size_t kycount = 0; size_t kzcount = 0; size_t kzinactive = 0;
83 for(std::make_signed_t<std::size_t> kx = 0; kx <= kx_max; ++kx)
84 {
85 double3 kvec_x = ax * 2.0 * M_PI * static_cast<double>(kx);
86 // Only positive kx are used, the negative kx are taken into account by the factor of two
87 double factor = (kx == 0) ? (1.0 * prefactor) : (2.0 * prefactor);
88
89 for(std::make_signed_t<std::size_t> ky = -ky_max; ky <= ky_max; ++ky)
90 {
91 double3 kvec_y = ay * 2.0 * M_PI * static_cast<double>(ky);
92 // Precompute and store eik_x * eik_y outside the kz-loop
93 for(size_t i = 0; i != numberOfAtoms; ++i)
94 {
95 std::complex<double> eiky_temp = eik_y[i + numberOfAtoms * static_cast<size_t>(std::abs(ky))];
96 eiky_temp.imag(ky>=0 ? eiky_temp.imag() : -eiky_temp.imag());
97 eik_xy[i] = eik_x[i + numberOfAtoms * static_cast<size_t>(kx)] * eiky_temp;
98 }
99
100 for(std::make_signed_t<std::size_t> kz = -kz_max; kz <= kz_max; ++kz)
101 {
102 // Ommit kvec==0
103 double ksqr = static_cast<double>(kx * kx + ky * ky + kz * kz);
104 std::complex<double> Adsorbateck(0.0, 0.0);
105 std::complex<double> Frameworkck(0.0, 0.0);
106
107 if(Box.UseLAMMPSEwald) //Overwrite ksqr if we use the LAMMPS Setup for Ewald//
108 {
109 const double lx = Box.Cell[0];
110 const double ly = Box.Cell[4];
111 const double lz = Box.Cell[8];
112 const double xy = Box.Cell[3];
113 const double xz = Box.Cell[6];
114 const double yz = Box.Cell[7];
115 const double ux = 2*M_PI/lx;
116 const double uy = 2*M_PI*(-xy)/lx/ly;
117 const double uz = 2*M_PI*(xy*yz - ly*xz)/lx/ly/lz;
118 const double vy = 2*M_PI/ly;
119 const double vz = 2*M_PI*(-yz)/ly/lz;
120 const double wz = 2*M_PI/lz;
121 const double kvecx = kx*ux;
122 const double kvecy = kx*uy + ky*vy;
123 const double kvecz = kx*uz + ky*vz + kz*wz;
124 ksqr = kvecx*kvecx + kvecy*kvecy + kvecz*kvecz;
125 }
126 //if((ksqr != 0) && (ksqr < Box.ReciprocalCutOff))
127 if((ksqr > 1e-10) && (ksqr < Box.ReciprocalCutOff))
128 {
129 double3 kvec_z = az * 2.0 * M_PI * static_cast<double>(kz);
130 //std::complex<double> Adsorbateck(0.0, 0.0);
131 count=0;
132 for(size_t comp=0; comp<SystemComponents.Total_Components; comp++)
133 {
134 for(size_t posi=0; posi<SystemComponents.NumberOfMolecule_for_Component[comp]*SystemComponents.Moleculesize[comp]; posi++)
135 {
136 std::complex<double> eikz_temp = eik_z[count + numberOfAtoms * static_cast<size_t>(std::abs(kz))];
137 eikz_temp.imag(kz>=0 ? eikz_temp.imag() : -eikz_temp.imag());
138 double charge = Host_System[comp].charge[posi];
139 double scaling = Host_System[comp].scaleCoul[posi];
140 Adsorbateck += scaling * charge * (eik_xy[count] * eikz_temp);
141 if(comp < SystemComponents.NComponents.y && SystemComponents.NumberOfFrameworks > 0) Frameworkck += scaling * charge * (eik_xy[count] * eikz_temp);
142 count++;
143 }
144 }
145 double3 tempkvec = kvec_x + kvec_y + kvec_z;
146 double rksq = dot(tempkvec, tempkvec);
147 double temp = factor * std::exp((-0.25 / alpha_squared) * rksq) / rksq;
148 if(SystemComponents.NumberOfFrameworks > 0 && Box.ExcludeHostGuestEwald)
149 Adsorbateck -= Frameworkck;
150 double tempsum = temp * (Adsorbateck.real() * Adsorbateck.real() + Adsorbateck.imag() * Adsorbateck.imag());
151 double tempFramework = 0.0; double tempFrameworkGuest = 0.0;
152
153 tempFramework = temp * (Frameworkck.real() * Frameworkck.real() + Frameworkck.imag() * Frameworkck.imag());
154 tempFrameworkGuest = temp * (Frameworkck.real() * Adsorbateck.real() + Frameworkck.imag() * Adsorbateck.imag()) * 2.0;
155 E.GGEwaldE += tempsum;
156 E.HHEwaldE += tempFramework;
157 E.HGEwaldE += tempFrameworkGuest;
158 //AdsorbateEik[nvec] = Adsorbateck;
159 //++nvec;
160 kzcount++;
161 }
162 FrameworkEik[nvec] = Frameworkck;
163 AdsorbateEik[nvec] = Adsorbateck;
164 /*
165 if(Box.ExcludeHostGuestEwald)
166 {
167 AdsorbateEik[nvec] -= FrameworkEik[nvec]; //exclude Framework contribution in Eik, this will also exclude it on the GPU and kernel functions
168 }
169 */
170 ++nvec;
171 kzinactive++;
172 }
173 kycount++;
174 }
175 kxcount++;
176 }
177
178 printf("Guest-Guest Fourier: %.5f, Host-Host Fourier: %.5f, Framework-Guest Fourier: %.5f\n", E.GGEwaldE, E.HHEwaldE, E.HGEwaldE);
179 if(Box.ExcludeHostGuestEwald) E.GGEwaldE += E.HHEwaldE;
180
181 // Subtract self-energy
182 double prefactor_self = Box.Prefactor * alpha / std::sqrt(M_PI);
183 count=0;
184 for(size_t comp=0; comp<SystemComponents.Total_Components; comp++)
185 {
186 double SelfE = 0.0;
187 for(size_t posi=0; posi<SystemComponents.NumberOfMolecule_for_Component[comp]*SystemComponents.Moleculesize[comp]; posi++)
188 {
189 double charge = Host_System[comp].charge[posi];
190 double scaling = Host_System[comp].scaleCoul[posi];
191 E.GGEwaldE -= prefactor_self * scaling * charge * scaling * charge;
192 SelfE += prefactor_self * scaling * charge * scaling * charge;
193 if(comp < SystemComponents.NComponents.y && SystemComponents.NumberOfFrameworks > 0) E.HHEwaldE -= prefactor_self * scaling * charge * scaling * charge;
194 }
195 printf("Component: %zu, SelfAtomE: %.5f\n", comp, SelfE);
196 }
197
198 // Subtract exclusion-energy, Zhao's note: taking out the pairs of energies that belong to the same molecule
199 size_t j_count = 0;
200 for(size_t l = 0; l != SystemComponents.Total_Components; ++l)
201 {
202 double exclusionE = 0.0;
203 //printf("Exclusion on component %zu, size: %zu\n", l, Host_System[l].size);
204 if(Host_System[l].size != 0)
205 {
206 for(size_t mol = 0; mol != SystemComponents.NumberOfMolecule_for_Component[l]; mol++)
207 {
208 size_t AtomID = mol * SystemComponents.Moleculesize[l];
209 for(size_t i = AtomID; i != AtomID + SystemComponents.Moleculesize[l] - 1; i++)
210 {
211 double factorA = Host_System[l].scaleCoul[i] * Host_System[l].charge[i];
212 double3 posA = Host_System[l].pos[i];
213 for(size_t j = i + 1; j != AtomID + SystemComponents.Moleculesize[l]; j++)
214 {
215 double factorB = Host_System[l].scaleCoul[j] * Host_System[l].charge[j];
216 double3 posB = Host_System[l].pos[j];
217
218 double3 posvec = posA - posB;
219 PBC(posvec, Box.Cell, Box.InverseCell, Box.Cubic);
220 double rr_dot = dot(posvec, posvec);
221 double r = std::sqrt(rr_dot);
222
223 E.GGEwaldE -= Box.Prefactor * factorA * factorB * std::erf(alpha * r) / r;
224 exclusionE -= Box.Prefactor * factorA * factorB * std::erf(alpha * r) / r;
225 if(l < SystemComponents.NComponents.y && SystemComponents.NumberOfFrameworks > 0) E.HHEwaldE -= Box.Prefactor * factorA * factorB * std::erf(alpha * r) / r;
226 j_count++;
227 }
228 }
229 }
230 }
231 printf("Component: %zu, Intra-Molecular ExclusionE: %.5f\n", l, exclusionE);
232 }
233 SystemComponents.FrameworkEwald = E.HHEwaldE;
234
235 /*
236 if(Box.ExcludeHostGuestEwald)
237 E -= E.HHEwaldE;
238 */
239 //Record the values for the Ewald Vectors//
240// for(size_t i = 0; i < eik_xy.size(); i++)
241 SystemComponents.eik_xy = eik_xy;
242// for(size_t i = 0; i < eik_x.size(); i++)
243 SystemComponents.eik_x = eik_x;
244// for(size_t i = 0; i < eik_y.size(); i++)
245 SystemComponents.eik_y = eik_y;
246// for(size_t i = 0; i < eik_z.size(); i++)
247 SystemComponents.eik_z = eik_z;
248// for(size_t i = 0; i < AdsorbateEik.size(); i++)
249 SystemComponents.AdsorbateEik = AdsorbateEik;
250
251 SystemComponents.FrameworkEik = FrameworkEik;
252 //IF RUN ON CPU, check tempEik vs. AdsorbateEik//
253 /*
254 if(SystemComponents.tempEik.size() > 0)
255 {
256 for(size_t i = 0; i < AdsorbateEik.size(); i++)
257 {
258 if((SystemComponents.AdsorbateEik[i].real() != SystemComponents.tempEik[i].real()) || (SystemComponents.AdsorbateEik[i].imag() != SystemComponents.tempEik[i].imag()))
259 {
260 printf("element %zu: stored: %.15f %.15f, updated: %.15f %.15f\n", i, AdsorbateEik[i].real(), AdsorbateEik[i].imag(), SystemComponents.tempEik[i].real(), SystemComponents.tempEik[i].imag());
261 }
262 }
263 }
264 */
265}
266
267double Calculate_Intra_Molecule_Exclusion(Boxsize& Box, Atoms* System, double alpha, double Prefactor, Components& SystemComponents, size_t SelectedComponent)
268{
269 double E = 0.0;
270 if(SystemComponents.Moleculesize[SelectedComponent] == 0) return 0.0;
271 for(size_t i = 0; i != SystemComponents.Moleculesize[SelectedComponent] - 1; i++)
272 {
273 double factorA = System[SelectedComponent].scaleCoul[i] * System[SelectedComponent].charge[i];
274 double3 posA = System[SelectedComponent].pos[i];
275 for(size_t j = i + 1; j != SystemComponents.Moleculesize[SelectedComponent]; j++)
276 {
277 double factorB = System[SelectedComponent].scaleCoul[j] * System[SelectedComponent].charge[j];
278 double3 posB = System[SelectedComponent].pos[j];
279
280 double3 posvec = posA - posB;
281 PBC(posvec, Box.Cell, Box.InverseCell, Box.Cubic);
282 double rr_dot = dot(posvec, posvec);
283 double r = std::sqrt(rr_dot);
284
285 E += Prefactor * factorA * factorB * std::erf(alpha * r) / r;
286 }
287 }
288 printf("Component %zu, Intra Exclusion Energy: %.5f\n", SelectedComponent, E);
289 return E;
290}
291
292double Calculate_Self_Exclusion(Boxsize& Box, Atoms* System, double alpha, double Prefactor, Components& SystemComponents, size_t SelectedComponent)
293{
294 double E = 0.0; double prefactor_self = Prefactor * alpha / std::sqrt(M_PI);
295 if(SystemComponents.Moleculesize[SelectedComponent] == 0) return 0.0;
296 for(size_t i=0; i<SystemComponents.Moleculesize[SelectedComponent]; i++)
297 {
298 double charge = System[SelectedComponent].charge[i];
299 double scaling = System[SelectedComponent].scaleCoul[i];
300 E += prefactor_self * scaling * charge * scaling * charge;
301 }
302 printf("Component %zu, Atom Self Exclusion Energy: %.5f\n", SelectedComponent, E);
303 return E;
304}
305
306void Check_WaveVector_CPUGPU(Boxsize& Box, Components& SystemComponents)
307{
308 printf(" ****** CHECKING WaveVectors Stored on CPU vs. GPU ****** \n");
309 size_t numberOfWaveVectors = (Box.kmax.x + 1) * (2 * Box.kmax.y + 1) * (2 * Box.kmax.z + 1);
310 Complex GPUWV[numberOfWaveVectors];
311 cudaMemcpy(GPUWV, Box.AdsorbateEik, numberOfWaveVectors * sizeof(Complex), cudaMemcpyDeviceToHost);
312 size_t numWVCPU = SystemComponents.AdsorbateEik.size();
313 if(numberOfWaveVectors != numWVCPU) printf("ERROR: Number of CPU WaveVectors does NOT EQUAL to the GPU one!!!");
314 size_t counter = 0;
315 for(size_t i = 0; i < numberOfWaveVectors; i++)
316 {
317 double diff_real = abs(SystemComponents.AdsorbateEik[i].real() - GPUWV[i].real);
318 double diff_imag = abs(SystemComponents.AdsorbateEik[i].imag() - GPUWV[i].imag);
319 if(i < 10)
320 printf("Wave Vector %zu, CPU: %.5f %.5f, GPU: %.5f %.5f\n", i, SystemComponents.AdsorbateEik[i].real(), SystemComponents.AdsorbateEik[i].imag(), GPUWV[i].real, GPUWV[i].imag);
321 if(diff_real > 1e-10 || diff_imag > 1e-10)
322 {
323 counter++;
324 if(counter < 10) printf("There is a difference in GPU/CPU WaveVector at position %zu: CPU: %.5f %.5f, GPU: %.5f %.5f\n", i, SystemComponents.AdsorbateEik[i].real(), SystemComponents.AdsorbateEik[i].imag(), GPUWV[i].real, GPUWV[i].imag);
325 }
326 }
327 if(counter >= 10) printf("More than 10 WaveVectors mismatch.\n");
328 //Also check Framework Eik vectors//
329 printf(" ****** CHECKING Framework WaveVectors Stored on CPU ****** \n");
330 for(size_t i = 0; i < numberOfWaveVectors; i++)
331 {
332 if(i < 10) printf("Framework Wave Vector %zu, real: %.5f imag: %.5f\n", i, SystemComponents.FrameworkEik[i].real(), SystemComponents.FrameworkEik[i].imag());
333 }
334}
335
336void CPU_GPU_EwaldTotalEnergy(Boxsize& Box, Boxsize& device_Box, Atoms* System, Atoms* d_a, ForceField FF, ForceField device_FF, Components& SystemComponents, MoveEnergy& E)
337{
339 // Run CPU Ewald //
341 double start = omp_get_wtime();
342 Ewald_Total(Box, System, FF, SystemComponents, E);
343 double end = omp_get_wtime(); double CPU_ewald_time = end-start;
344 printf("HostEwald took %.5f sec\n", CPU_ewald_time);
345}
346
347void Calculate_Exclusion_Energy_Rigid(Boxsize& Box, Atoms* System, ForceField FF, Components& SystemComponents)
348{
349 for(size_t i = 0; i < SystemComponents.Total_Components; i++)
350 {
351 double IntraE = 0.0; double SelfE = 0.0;
352 if(SystemComponents.rigid[i]) //Only Calculate this when the component is rigid//
353 {
354 IntraE = Calculate_Intra_Molecule_Exclusion(Box, System, Box.Alpha, Box.Prefactor, SystemComponents, i);
355 SelfE = Calculate_Self_Exclusion(Box, System, Box.Alpha, Box.Prefactor, SystemComponents, i);
356 }
357 SystemComponents.ExclusionIntra.push_back(IntraE);
358 SystemComponents.ExclusionAtom.push_back(SelfE);
359 printf("DEBUG: comp: %zu, IntraE: %.5f, SelfE: %.5f\n", i, SystemComponents.ExclusionIntra[i], SystemComponents.ExclusionAtom[i]);
360 }
361
362}
Definition data_struct.h:746
Definition data_struct.h:819
Definition data_struct.h:46
Definition data_struct.h:843
Definition data_struct.h:794
Definition data_struct.h:615