Tinker9 70bd052 (Thu Nov 9 12:11:35 2023 -0800)
Loading...
Searching...
No Matches
rotpole.h
1#pragma once
2#include "ff/amoeba/mpole.h"
3#include "ff/hippo/erepel.h"
4#include "math/libfunc.h"
5#include "seq/seq.h"
6
7namespace tinker {
9inline void chkpoleAtomI(int i, real (*restrict pole)[MPL_TOTAL],
10 LocalFrame* zaxis, const real* restrict x, const real* restrict y,
11 const real* restrict z)
12{
13 int polaxe = zaxis[i].polaxe;
14 bool check = ((polaxe != LFRM_Z_THEN_X) or (zaxis[i].yaxis) == 0) ? false
15 : true;
16 if (check) {
17 int k = zaxis[i].yaxis;
18 int ia = i;
19 int ib = zaxis[i].zaxis;
20 int ic = zaxis[i].xaxis;
21 int id = INT_ABS(k) - 1;
22
23 // compute the signed parallelpiped volume at chiral site
24
25 real xad = x[ia] - x[id];
26 real yad = y[ia] - y[id];
27 real zad = z[ia] - z[id];
28 real xbd = x[ib] - x[id];
29 real ybd = y[ib] - y[id];
30 real zbd = z[ib] - z[id];
31 real xcd = x[ic] - x[id];
32 real ycd = y[ic] - y[id];
33 real zcd = z[ic] - z[id];
34 real c1 = ybd * zcd - zbd * ycd;
35 real c2 = ycd * zad - zcd * yad;
36 real c3 = yad * zbd - zad * ybd;
37 real vol = xad * c1 + xbd * c2 + xcd * c3;
38
39 // invert atomic multipole components involving the y-axis
40
41 if ((k < 0 && vol > 0) or (k > 0 && vol < 0)) {
42 zaxis[i].yaxis = -k;
43 // y -> -y
44 pole[i][MPL_PME_Y] = -pole[i][MPL_PME_Y];
45 // xy -> -xy
46 // yz -> -yz
47 pole[i][MPL_PME_XY] = -pole[i][MPL_PME_XY];
48 pole[i][MPL_PME_YZ] = -pole[i][MPL_PME_YZ];
49 }
50 }
51}
52}
53
54namespace tinker {
56inline void rotpoleNorm(real* a)
57{
58 real a1 = REAL_RSQRT(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
59 a[0] *= a1;
60 a[1] *= a1;
61 a[2] *= a1;
62}
63
65inline void rotpoleAddBy(real* restrict a, const real* restrict b)
66{
67 a[0] += b[0];
68 a[1] += b[1];
69 a[2] += b[2];
70}
71
73inline void rotpoleAddBy2(real* restrict a, const real* restrict b,
74 const real* restrict c)
75{
76 a[0] += (b[0] + c[0]);
77 a[1] += (b[1] + c[1]);
78 a[2] += (b[2] + c[2]);
79}
80
82inline void rotsite(int isite, const real (*restrict a)[3],
83 real (*restrict rpole)[10], const real (*restrict pole)[10])
84{
85 static_assert(MPL_TOTAL == 10, "");
86
87 // charge
88 rpole[isite][0] = pole[isite][0];
89 // dipole
90 rpole[isite][1] = 0;
91 rpole[isite][2] = 0;
92 rpole[isite][3] = 0;
93#if _OPENACC
94#pragma acc loop seq collapse(2)
95#endif
96 for (int i = 1; i < 4; ++i)
97 for (int j = 1; j < 4; ++j)
98 rpole[isite][i] += pole[isite][j] * a[j - 1][i - 1];
99
100 // quadrupole
101 real rp[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
102 real mp[3][3];
103 mp[0][0] = pole[isite][MPL_PME_XX];
104 mp[0][1] = pole[isite][MPL_PME_XY];
105 mp[0][2] = pole[isite][MPL_PME_XZ];
106 mp[1][0] = pole[isite][MPL_PME_YX];
107 mp[1][1] = pole[isite][MPL_PME_YY];
108 mp[1][2] = pole[isite][MPL_PME_YZ];
109 mp[2][0] = pole[isite][MPL_PME_ZX];
110 mp[2][1] = pole[isite][MPL_PME_ZY];
111 mp[2][2] = pole[isite][MPL_PME_ZZ];
112#if _OPENACC
113 #pragma acc loop seq
114#endif
115 for (int i = 0; i < 3; ++i) {
116#if _OPENACC
117#pragma acc loop seq
118#endif
119 for (int j = 0; j <= i; ++j) {
120 // if (j < i) {
121 // rp[j][i] = rp[i][j];
122 // } else {
123#if _OPENACC
124#pragma acc loop seq collapse(2)
125#endif
126 for (int k = 0; k < 3; ++k)
127 for (int m = 0; m < 3; ++m)
128 rp[j][i] += a[k][i] * a[m][j] * mp[m][k];
129 // }
130 }
131 }
132 rpole[isite][MPL_PME_XX] = rp[0][0];
133 rpole[isite][MPL_PME_XY] = rp[0][1];
134 rpole[isite][MPL_PME_XZ] = rp[0][2];
135 rpole[isite][MPL_PME_YY] = rp[1][1];
136 rpole[isite][MPL_PME_YZ] = rp[1][2];
137 rpole[isite][MPL_PME_ZZ] = rp[2][2];
138}
139}
140
141namespace tinker {
143inline void rotpoleAtomI(int i, real (*restrict rpole)[MPL_TOTAL],
145 const real* restrict x, const real* restrict y, const real* restrict z)
146{
147 // rotmat routine
148 real xi = x[i];
149 real yi = y[i];
150 real zi = z[i];
151 int iz = zaxis[i].zaxis;
152 int ix = zaxis[i].xaxis;
153 int iy = INT_ABS(zaxis[i].yaxis) - 1;
154 int polaxe = zaxis[i].polaxe;
155 // the default identity matrix
156 real a[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
157
158 if (polaxe != LFRM_NONE) {
159 real* restrict xx = &a[0][0];
160 real* restrict yy = &a[1][0];
161 real* restrict zz = &a[2][0];
162
163 // STEP 1: PICK Z AND NORM Z
164 // pick z
165 zz[0] = x[iz] - xi;
166 zz[1] = y[iz] - yi;
167 zz[2] = z[iz] - zi;
168 // norm z
169 rotpoleNorm(zz);
170
171 // STEP 2: PICK X AND NORM X
172 // even if it is not needef for z then x)
173 if (polaxe == LFRM_Z_ONLY) {
174 // pick x
175 int okay = !(REAL_ABS(zz[0]) > 0.866f);
176 xx[0] = (okay ? 1 : 0);
177 xx[1] = (okay ? 0 : 1);
178 xx[2] = 0;
179 } else {
180 // pick x
181 xx[0] = x[ix] - xi;
182 xx[1] = y[ix] - yi;
183 xx[2] = z[ix] - zi;
184 rotpoleNorm(xx);
185 }
186
187 // STEP 3: PICK Y AND NORM Y
188 // only for z biscector and 3 fold
189 if (polaxe == LFRM_Z_BISECT || polaxe == LFRM_3_FOLD) {
190 yy[0] = x[iy] - xi;
191 yy[1] = y[iy] - yi;
192 yy[2] = z[iy] - zi;
193 rotpoleNorm(yy);
194 }
195
196 // STEP 4
197 if (polaxe == LFRM_BISECTOR) {
198 rotpoleAddBy(zz, xx);
199 rotpoleNorm(zz);
200 } else if (polaxe == LFRM_Z_BISECT) {
201 rotpoleAddBy(xx, yy);
202 rotpoleNorm(xx);
203 } else if (polaxe == LFRM_3_FOLD) {
204 rotpoleAddBy2(zz, xx, yy);
205 rotpoleNorm(zz);
206 }
207
208 // STEP 5
209 // x -= (x.z) z
210 real dotxz = xx[0] * zz[0] + xx[1] * zz[1] + xx[2] * zz[2];
211 xx[0] -= dotxz * zz[0];
212 xx[1] -= dotxz * zz[1];
213 xx[2] -= dotxz * zz[2];
214 // norm x
215 rotpoleNorm(xx);
216 // y = z cross x
217 a[1][0] = a[0][2] * a[2][1] - a[0][1] * a[2][2];
218 a[1][1] = a[0][0] * a[2][2] - a[0][2] * a[2][0];
219 a[1][2] = a[0][1] * a[2][0] - a[0][0] * a[2][1];
220 } // end if (.not. LFRM_NONE)
221
222 // rotsite routine
223 rotsite(i, a, rpole, pole);
224}
225}
#define SEQ_ROUTINE
Definition: acc/seqdef.h:7
#define restrict
Definition: macro.h:51
real * z
Current coordinates used in energy evaluation and neighbor lists.
real * x
Number of the trajectory frames.
real * y
Current coordinates used in energy evaluation and neighbor lists.
float real
Definition: precision.h:80
Definition: testrt.h:9
@ MPL_PME_ZX
Definition: mpole.h:18
@ MPL_PME_XY
Definition: mpole.h:13
@ MPL_PME_Y
Definition: mpole.h:8
@ LFRM_NONE
Definition: mpole.h:21
@ MPL_PME_ZZ
Definition: mpole.h:12
@ LFRM_3_FOLD
Definition: mpole.h:26
@ LFRM_BISECTOR
Definition: mpole.h:24
@ MPL_PME_YX
Definition: mpole.h:17
@ MPL_PME_ZY
Definition: mpole.h:19
@ MPL_PME_YZ
Definition: mpole.h:15
@ LFRM_Z_THEN_X
Definition: mpole.h:23
@ LFRM_Z_BISECT
Definition: mpole.h:25
@ MPL_PME_XX
Definition: mpole.h:10
@ MPL_PME_XZ
Definition: mpole.h:14
@ MPL_PME_YY
Definition: mpole.h:11
@ LFRM_Z_ONLY
Definition: mpole.h:22
@ MPL_TOTAL
Definition: mpole.h:16
__device__ void rotpoleNorm(real *a)
Definition: rotpole.h:56
__device__ void rotsite(int isite, const real(*__restrict__ a)[3], real(*__restrict__ rpole)[10], const real(*__restrict__ pole)[10])
Definition: rotpole.h:82
__device__ void rotpoleAtomI(int i, real(*__restrict__ rpole)[MPL_TOTAL], const real(*__restrict__ pole)[MPL_TOTAL], const LocalFrame *__restrict__ zaxis, const real *__restrict__ x, const real *__restrict__ y, const real *__restrict__ z)
Definition: rotpole.h:143
__device__ void chkpoleAtomI(int i, real(*__restrict__ pole)[MPL_TOTAL], LocalFrame *zaxis, const real *__restrict__ x, const real *__restrict__ y, const real *__restrict__ z)
Definition: rotpole.h:9
real(* rpole)[MPL_TOTAL]
__device__ void rotpoleAddBy2(real *__restrict__ a, const real *__restrict__ b, const real *__restrict__ c)
Definition: rotpole.h:73
__device__ void rotpoleAddBy(real *__restrict__ a, const real *__restrict__ b)
Definition: rotpole.h:65
real(* pole)[MPL_TOTAL]
LocalFrame * zaxis
Local axis type and x,y,z-axis defining atoms for each multipole site.
Definition: mpole.h:31
int xaxis
X-axis defining atom, starting from 0.
Definition: mpole.h:33
int zaxis
Z-axis defining atom, starting from 0.
Definition: mpole.h:32
int yaxis
Y-axis defining atom, starting from ONE.
Definition: mpole.h:34
int polaxe
Local frame definition.
Definition: mpole.h:35