Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
8db70d34
Commit
8db70d34
authored
Jul 21, 2014
by
peastman
Browse files
Merge pull request #547 from peastman/diis
Implemented DIIS for converging AMOEBA induced dipoles
parents
61595804
bbbc3160
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
1460 additions
and
1132 deletions
+1460
-1132
plugins/amoeba/platforms/cuda/src/AmoebaCudaKernels.cpp
plugins/amoeba/platforms/cuda/src/AmoebaCudaKernels.cpp
+115
-31
plugins/amoeba/platforms/cuda/src/AmoebaCudaKernels.h
plugins/amoeba/platforms/cuda/src/AmoebaCudaKernels.h
+10
-0
plugins/amoeba/platforms/cuda/src/kernels/multipoleInducedField.cu
...moeba/platforms/cuda/src/kernels/multipoleInducedField.cu
+113
-2
plugins/amoeba/platforms/reference/src/SimTKReference/AmoebaReferenceMultipoleForce.cpp
...ence/src/SimTKReference/AmoebaReferenceMultipoleForce.cpp
+962
-855
plugins/amoeba/platforms/reference/src/SimTKReference/AmoebaReferenceMultipoleForce.h
...erence/src/SimTKReference/AmoebaReferenceMultipoleForce.h
+260
-244
No files found.
plugins/amoeba/platforms/cuda/src/AmoebaCudaKernels.cpp
View file @
8db70d34
...
...
@@ -40,6 +40,7 @@
#include "CudaForceInfo.h"
#include "CudaKernelSources.h"
#include "CudaNonbondedUtilities.h"
#include "jama_svd.h"
#include <algorithm>
#include <cmath>
...
...
@@ -796,8 +797,9 @@ private:
CudaCalcAmoebaMultipoleForceKernel
::
CudaCalcAmoebaMultipoleForceKernel
(
std
::
string
name
,
const
Platform
&
platform
,
CudaContext
&
cu
,
const
System
&
system
)
:
CalcAmoebaMultipoleForceKernel
(
name
,
platform
),
cu
(
cu
),
system
(
system
),
hasInitializedScaleFactors
(
false
),
hasInitializedFFT
(
false
),
multipolesAreValid
(
false
),
multipoleParticles
(
NULL
),
molecularDipoles
(
NULL
),
molecularQuadrupoles
(
NULL
),
labFrameDipoles
(
NULL
),
labFrameQuadrupoles
(
NULL
),
field
(
NULL
),
fieldPolar
(
NULL
),
inducedField
(
NULL
),
inducedFieldPolar
(
NULL
),
torque
(
NULL
),
dampingAndThole
(
NULL
),
inducedDipole
(
NULL
),
inducedDipolePolar
(
NULL
),
inducedDipoleErrors
(
NULL
),
polarizability
(
NULL
),
covalentFlags
(
NULL
),
polarizationGroupFlags
(
NULL
),
field
(
NULL
),
fieldPolar
(
NULL
),
inducedField
(
NULL
),
inducedFieldPolar
(
NULL
),
torque
(
NULL
),
dampingAndThole
(
NULL
),
inducedDipole
(
NULL
),
diisCoefficients
(
NULL
),
inducedDipolePolar
(
NULL
),
inducedDipoleErrors
(
NULL
),
prevDipoles
(
NULL
),
prevDipolesPolar
(
NULL
),
prevDipolesGk
(
NULL
),
prevDipolesGkPolar
(
NULL
),
prevErrors
(
NULL
),
diisMatrix
(
NULL
),
polarizability
(
NULL
),
covalentFlags
(
NULL
),
polarizationGroupFlags
(
NULL
),
pmeGrid
(
NULL
),
pmeBsplineModuliX
(
NULL
),
pmeBsplineModuliY
(
NULL
),
pmeBsplineModuliZ
(
NULL
),
pmeIgrid
(
NULL
),
pmePhi
(
NULL
),
pmePhid
(
NULL
),
pmePhip
(
NULL
),
pmePhidp
(
NULL
),
pmeAtomGridIndex
(
NULL
),
lastPositions
(
NULL
),
sort
(
NULL
),
gkKernel
(
NULL
)
{
}
...
...
@@ -832,6 +834,20 @@ CudaCalcAmoebaMultipoleForceKernel::~CudaCalcAmoebaMultipoleForceKernel() {
delete
inducedDipolePolar
;
if
(
inducedDipoleErrors
!=
NULL
)
delete
inducedDipoleErrors
;
if
(
prevDipoles
!=
NULL
)
delete
prevDipoles
;
if
(
prevDipolesPolar
!=
NULL
)
delete
prevDipolesPolar
;
if
(
prevDipolesGk
!=
NULL
)
delete
prevDipolesGk
;
if
(
prevDipolesGkPolar
!=
NULL
)
delete
prevDipolesGkPolar
;
if
(
prevErrors
!=
NULL
)
delete
prevErrors
;
if
(
diisMatrix
!=
NULL
)
delete
diisMatrix
;
if
(
diisCoefficients
!=
NULL
)
delete
diisCoefficients
;
if
(
polarizability
!=
NULL
)
delete
polarizability
;
if
(
covalentFlags
!=
NULL
)
...
...
@@ -959,6 +975,11 @@ void CudaCalcAmoebaMultipoleForceKernel::initialize(const System& system, const
inducedDipole
=
new
CudaArray
(
cu
,
3
*
paddedNumAtoms
,
elementSize
,
"inducedDipole"
);
inducedDipolePolar
=
new
CudaArray
(
cu
,
3
*
paddedNumAtoms
,
elementSize
,
"inducedDipolePolar"
);
inducedDipoleErrors
=
new
CudaArray
(
cu
,
cu
.
getNumThreadBlocks
(),
sizeof
(
float2
),
"inducedDipoleErrors"
);
prevDipoles
=
new
CudaArray
(
cu
,
3
*
numMultipoles
*
MaxPrevDIISDipoles
,
elementSize
,
"prevDipoles"
);
prevDipolesPolar
=
new
CudaArray
(
cu
,
3
*
numMultipoles
*
MaxPrevDIISDipoles
,
elementSize
,
"prevDipolesPolar"
);
prevErrors
=
new
CudaArray
(
cu
,
3
*
numMultipoles
*
MaxPrevDIISDipoles
,
elementSize
,
"prevErrors"
);
diisMatrix
=
new
CudaArray
(
cu
,
MaxPrevDIISDipoles
*
MaxPrevDIISDipoles
,
elementSize
,
"diisMatrix"
);
diisCoefficients
=
new
CudaArray
(
cu
,
MaxPrevDIISDipoles
+
1
,
sizeof
(
float
),
"diisMatrix"
);
cu
.
addAutoclearBuffer
(
*
field
);
cu
.
addAutoclearBuffer
(
*
fieldPolar
);
cu
.
addAutoclearBuffer
(
*
torque
);
...
...
@@ -1088,6 +1109,8 @@ void CudaCalcAmoebaMultipoleForceKernel::initialize(const System& system, const
defines
[
"GK_FQ"
]
=
cu
.
doubleToString
(
3
*
(
1
-
solventDielectric
)
/
(
2
+
3
*
solventDielectric
));
fixedThreadMemory
+=
4
*
elementSize
;
inducedThreadMemory
+=
13
*
elementSize
;
prevDipolesGk
=
new
CudaArray
(
cu
,
3
*
numMultipoles
*
MaxPrevDIISDipoles
,
elementSize
,
"prevDipolesGk"
);
prevDipolesGkPolar
=
new
CudaArray
(
cu
,
3
*
numMultipoles
*
MaxPrevDIISDipoles
,
elementSize
,
"prevDipolesGkPolar"
);
}
int
maxThreads
=
cu
.
getNonbondedUtilities
().
getForceThreadBlockSize
();
fixedFieldThreads
=
min
(
maxThreads
,
cu
.
computeThreadBlockSize
(
fixedThreadMemory
));
...
...
@@ -1102,9 +1125,12 @@ void CudaCalcAmoebaMultipoleForceKernel::initialize(const System& system, const
computeFixedFieldKernel
=
cu
.
getKernel
(
module
,
"computeFixedField"
);
if
(
maxInducedIterations
>
0
)
{
defines
[
"THREAD_BLOCK_SIZE"
]
=
cu
.
intToString
(
inducedFieldThreads
);
defines
[
"MAX_PREV_DIIS_DIPOLES"
]
=
cu
.
intToString
(
MaxPrevDIISDipoles
);
module
=
cu
.
createModule
(
CudaKernelSources
::
vectorOps
+
CudaAmoebaKernelSources
::
multipoleInducedField
,
defines
);
computeInducedFieldKernel
=
cu
.
getKernel
(
module
,
"computeInducedField"
);
updateInducedFieldKernel
=
cu
.
getKernel
(
module
,
"updateInducedFieldBySOR"
);
updateInducedFieldKernel
=
cu
.
getKernel
(
module
,
"updateInducedFieldByDIIS"
);
recordDIISDipolesKernel
=
cu
.
getKernel
(
module
,
"recordInducedDipolesForDIIS"
);
buildMatrixKernel
=
cu
.
getKernel
(
module
,
"computeDIISMatrix"
);
}
stringstream
electrostaticsSource
;
if
(
usePME
)
{
...
...
@@ -1421,7 +1447,6 @@ double CudaCalcAmoebaMultipoleForceKernel::execute(ContextImpl& context, bool in
// Iterate until the dipoles converge.
vector
<
float2
>
errors
;
for
(
int
i
=
0
;
i
<
maxInducedIterations
;
i
++
)
{
cu
.
clearBuffer
(
*
inducedField
);
cu
.
clearBuffer
(
*
inducedFieldPolar
);
...
...
@@ -1440,23 +1465,9 @@ double CudaCalcAmoebaMultipoleForceKernel::execute(ContextImpl& context, bool in
&
gkKernel
->
getInducedDipoles
()
->
getDevicePointer
(),
&
gkKernel
->
getInducedDipolesPolar
()
->
getDevicePointer
(),
&
gkKernel
->
getBornRadii
()
->
getDevicePointer
(),
&
dampingAndThole
->
getDevicePointer
()};
cu
.
executeKernel
(
computeInducedFieldKernel
,
computeInducedFieldArgs
,
numForceThreadBlocks
*
inducedFieldThreads
,
inducedFieldThreads
);
void
*
updateInducedGkFieldArgs
[]
=
{
&
field
->
getDevicePointer
(),
&
fieldPolar
->
getDevicePointer
(),
&
gkKernel
->
getField
()
->
getDevicePointer
(),
&
gkKernel
->
getInducedField
()
->
getDevicePointer
(),
&
gkKernel
->
getInducedFieldPolar
()
->
getDevicePointer
(),
&
gkKernel
->
getInducedDipoles
()
->
getDevicePointer
(),
&
gkKernel
->
getInducedDipolesPolar
()
->
getDevicePointer
(),
&
polarizability
->
getDevicePointer
(),
&
inducedDipoleErrors
->
getDevicePointer
()};
cu
.
executeKernel
(
updateInducedFieldKernel
,
updateInducedGkFieldArgs
,
cu
.
getNumThreadBlocks
()
*
cu
.
ThreadBlockSize
,
cu
.
ThreadBlockSize
,
cu
.
ThreadBlockSize
*
elementSize
*
2
);
}
void
*
updateInducedFieldArgs
[]
=
{
&
field
->
getDevicePointer
(),
&
fieldPolar
->
getDevicePointer
(),
&
npt
,
&
inducedField
->
getDevicePointer
(),
&
inducedFieldPolar
->
getDevicePointer
(),
&
inducedDipole
->
getDevicePointer
(),
&
inducedDipolePolar
->
getDevicePointer
(),
&
polarizability
->
getDevicePointer
(),
&
inducedDipoleErrors
->
getDevicePointer
()};
cu
.
executeKernel
(
updateInducedFieldKernel
,
updateInducedFieldArgs
,
cu
.
getNumThreadBlocks
()
*
cu
.
ThreadBlockSize
,
cu
.
ThreadBlockSize
,
cu
.
ThreadBlockSize
*
elementSize
*
2
);
inducedDipoleErrors
->
download
(
errors
);
double
total1
=
0.0
,
total2
=
0.0
;
for
(
int
j
=
0
;
j
<
(
int
)
errors
.
size
();
j
++
)
{
total1
+=
errors
[
j
].
x
;
total2
+=
errors
[
j
].
y
;
}
if
(
48.033324
*
sqrt
(
max
(
total1
,
total2
)
/
cu
.
getNumAtoms
())
<
inducedEpsilon
)
double
maxEpsilon
=
iterateDipolesByDIIS
(
i
);
if
(
maxEpsilon
<
inducedEpsilon
)
break
;
}
...
...
@@ -1568,17 +1579,8 @@ double CudaCalcAmoebaMultipoleForceKernel::execute(ContextImpl& context, bool in
void
*
pmeRecordInducedFieldDipolesArgs
[]
=
{
&
pmePhid
->
getDevicePointer
(),
&
pmePhip
->
getDevicePointer
(),
&
inducedField
->
getDevicePointer
(),
&
inducedFieldPolar
->
getDevicePointer
(),
cu
.
getInvPeriodicBoxSizePointer
()};
cu
.
executeKernel
(
pmeRecordInducedFieldDipolesKernel
,
pmeRecordInducedFieldDipolesArgs
,
cu
.
getNumAtoms
());
void
*
updateInducedFieldArgs
[]
=
{
&
field
->
getDevicePointer
(),
&
fieldPolar
->
getDevicePointer
(),
&
npt
,
&
inducedField
->
getDevicePointer
(),
&
inducedFieldPolar
->
getDevicePointer
(),
&
inducedDipole
->
getDevicePointer
(),
&
inducedDipolePolar
->
getDevicePointer
(),
&
polarizability
->
getDevicePointer
(),
&
inducedDipoleErrors
->
getDevicePointer
()};
cu
.
executeKernel
(
updateInducedFieldKernel
,
updateInducedFieldArgs
,
cu
.
getNumThreadBlocks
()
*
cu
.
ThreadBlockSize
,
cu
.
ThreadBlockSize
,
cu
.
ThreadBlockSize
*
elementSize
*
2
);
inducedDipoleErrors
->
download
(
errors
);
double
total1
=
0.0
,
total2
=
0.0
;
for
(
int
j
=
0
;
j
<
(
int
)
errors
.
size
();
j
++
)
{
total1
+=
errors
[
j
].
x
;
total2
+=
errors
[
j
].
y
;
}
if
(
48.033324
*
sqrt
(
max
(
total1
,
total2
)
/
cu
.
getNumAtoms
())
<
inducedEpsilon
)
double
maxEpsilon
=
iterateDipolesByDIIS
(
i
);
if
(
maxEpsilon
<
inducedEpsilon
)
break
;
}
...
...
@@ -1612,6 +1614,88 @@ double CudaCalcAmoebaMultipoleForceKernel::execute(ContextImpl& context, bool in
return
0.0
;
}
double
CudaCalcAmoebaMultipoleForceKernel
::
iterateDipolesByDIIS
(
int
iteration
)
{
void
*
npt
=
NULL
;
bool
trueValue
=
true
,
falseValue
=
false
;
int
elementSize
=
(
cu
.
getUseDoublePrecision
()
?
sizeof
(
double
)
:
sizeof
(
float
));
// Record the dipole and errors into the lists of previous dipoles.
if
(
gkKernel
!=
NULL
)
{
void
*
recordDIISDipolesGkArgs
[]
=
{
&
field
->
getDevicePointer
(),
&
fieldPolar
->
getDevicePointer
(),
&
gkKernel
->
getField
()
->
getDevicePointer
(),
&
gkKernel
->
getInducedField
()
->
getDevicePointer
(),
&
gkKernel
->
getInducedFieldPolar
()
->
getDevicePointer
(),
&
gkKernel
->
getInducedDipoles
()
->
getDevicePointer
(),
&
gkKernel
->
getInducedDipolesPolar
()
->
getDevicePointer
(),
&
polarizability
->
getDevicePointer
(),
&
inducedDipoleErrors
->
getDevicePointer
(),
&
prevDipolesGk
->
getDevicePointer
(),
&
prevDipolesGkPolar
->
getDevicePointer
(),
&
prevErrors
->
getDevicePointer
(),
&
iteration
,
&
falseValue
,
&
diisMatrix
->
getDevicePointer
()};
cu
.
executeKernel
(
recordDIISDipolesKernel
,
recordDIISDipolesGkArgs
,
cu
.
getNumThreadBlocks
()
*
cu
.
ThreadBlockSize
,
cu
.
ThreadBlockSize
,
cu
.
ThreadBlockSize
*
elementSize
*
2
);
}
void
*
recordDIISDipolesArgs
[]
=
{
&
field
->
getDevicePointer
(),
&
fieldPolar
->
getDevicePointer
(),
&
npt
,
&
inducedField
->
getDevicePointer
(),
&
inducedFieldPolar
->
getDevicePointer
(),
&
inducedDipole
->
getDevicePointer
(),
&
inducedDipolePolar
->
getDevicePointer
(),
&
polarizability
->
getDevicePointer
(),
&
inducedDipoleErrors
->
getDevicePointer
(),
&
prevDipoles
->
getDevicePointer
(),
&
prevDipolesPolar
->
getDevicePointer
(),
&
prevErrors
->
getDevicePointer
(),
&
iteration
,
&
trueValue
,
&
diisMatrix
->
getDevicePointer
()};
cu
.
executeKernel
(
recordDIISDipolesKernel
,
recordDIISDipolesArgs
,
cu
.
getNumThreadBlocks
()
*
cu
.
ThreadBlockSize
,
cu
.
ThreadBlockSize
,
cu
.
ThreadBlockSize
*
elementSize
*
2
);
float2
*
errors
=
(
float2
*
)
cu
.
getPinnedBuffer
();
inducedDipoleErrors
->
download
(
errors
,
false
);
// Determine the coefficients for selecting the new dipoles.
int
numPrev
=
(
iteration
+
1
<
MaxPrevDIISDipoles
?
iteration
+
1
:
MaxPrevDIISDipoles
);
void
*
buildMatrixArgs
[]
=
{
&
prevErrors
->
getDevicePointer
(),
&
iteration
,
&
diisMatrix
->
getDevicePointer
()};
int
threadBlocks
=
min
(
numPrev
,
cu
.
getNumThreadBlocks
());
cu
.
executeKernel
(
buildMatrixKernel
,
buildMatrixArgs
,
threadBlocks
*
128
,
128
,
128
*
elementSize
);
vector
<
float
>
coefficients
(
MaxPrevDIISDipoles
);
if
(
iteration
==
0
)
coefficients
[
0
]
=
1
;
else
{
vector
<
float
>
matrix
;
diisMatrix
->
download
(
matrix
);
int
rank
=
numPrev
+
1
;
Array2D
<
double
>
b
(
rank
,
rank
);
b
[
0
][
0
]
=
0
;
for
(
int
i
=
1
;
i
<
rank
;
i
++
)
b
[
i
][
0
]
=
b
[
0
][
i
]
=
-
1
;
for
(
int
i
=
0
;
i
<
numPrev
;
i
++
)
for
(
int
j
=
0
;
j
<
numPrev
;
j
++
)
b
[
i
+
1
][
j
+
1
]
=
matrix
[
i
*
MaxPrevDIISDipoles
+
j
];
// Solve using SVD. Since the right hand side is (-1, 0, 0, 0, ...), this is simpler than the general case.
JAMA
::
SVD
<
double
>
svd
(
b
);
Array2D
<
double
>
u
,
v
;
svd
.
getU
(
u
);
svd
.
getV
(
v
);
Array1D
<
double
>
s
;
svd
.
getSingularValues
(
s
);
int
effectiveRank
=
svd
.
rank
();
for
(
int
i
=
1
;
i
<
rank
;
i
++
)
{
double
d
=
0
;
for
(
int
j
=
0
;
j
<
effectiveRank
;
j
++
)
d
-=
u
[
0
][
j
]
*
v
[
i
][
j
]
/
s
[
j
];
coefficients
[
i
-
1
]
=
d
;
}
}
diisCoefficients
->
upload
(
&
coefficients
[
0
]);
// Compute the dipoles.
void
*
updateInducedFieldArgs
[]
=
{
&
inducedDipole
->
getDevicePointer
(),
&
inducedDipolePolar
->
getDevicePointer
(),
&
prevDipoles
->
getDevicePointer
(),
&
prevDipolesPolar
->
getDevicePointer
(),
&
diisCoefficients
->
getDevicePointer
(),
&
numPrev
};
cu
.
executeKernel
(
updateInducedFieldKernel
,
updateInducedFieldArgs
,
cu
.
getNumThreadBlocks
()
*
cu
.
ThreadBlockSize
);
if
(
gkKernel
!=
NULL
)
{
void
*
updateInducedFieldGkArgs
[]
=
{
&
gkKernel
->
getInducedDipoles
()
->
getDevicePointer
(),
&
gkKernel
->
getInducedDipolesPolar
()
->
getDevicePointer
(),
&
prevDipolesGk
->
getDevicePointer
(),
&
prevDipolesGkPolar
->
getDevicePointer
(),
&
diisCoefficients
->
getDevicePointer
(),
&
numPrev
};
cu
.
executeKernel
(
updateInducedFieldKernel
,
updateInducedFieldGkArgs
,
cu
.
getNumThreadBlocks
()
*
cu
.
ThreadBlockSize
);
}
// Compute the overall error for monitoring convergence.
double
total1
=
0.0
,
total2
=
0.0
;
for
(
int
j
=
0
;
j
<
inducedDipoleErrors
->
getSize
();
j
++
)
{
total1
+=
errors
[
j
].
x
;
total2
+=
errors
[
j
].
y
;
}
return
48.033324
*
sqrt
(
max
(
total1
,
total2
)
/
cu
.
getNumAtoms
());
}
void
CudaCalcAmoebaMultipoleForceKernel
::
ensureMultipolesValid
(
ContextImpl
&
context
)
{
if
(
multipolesAreValid
)
{
int
numParticles
=
cu
.
getNumAtoms
();
...
...
plugins/amoeba/platforms/cuda/src/AmoebaCudaKernels.h
View file @
8db70d34
...
...
@@ -375,6 +375,7 @@ private:
const
char
*
getSortKey
()
const
{
return
"value.y"
;}
};
void
initializeScaleFactors
();
double
iterateDipolesByDIIS
(
int
iteration
);
void
ensureMultipolesValid
(
ContextImpl
&
context
);
template
<
class
T
,
class
T4
,
class
M4
>
void
computeSystemMultipoleMoments
(
ContextImpl
&
context
,
std
::
vector
<
double
>&
outputMultipoleMoments
);
int
numMultipoles
,
maxInducedIterations
;
...
...
@@ -399,6 +400,13 @@ private:
CudaArray
*
inducedDipole
;
CudaArray
*
inducedDipolePolar
;
CudaArray
*
inducedDipoleErrors
;
CudaArray
*
prevDipoles
;
CudaArray
*
prevDipolesPolar
;
CudaArray
*
prevDipolesGk
;
CudaArray
*
prevDipolesGkPolar
;
CudaArray
*
prevErrors
;
CudaArray
*
diisMatrix
;
CudaArray
*
diisCoefficients
;
CudaArray
*
polarizability
;
CudaArray
*
covalentFlags
;
CudaArray
*
polarizationGroupFlags
;
...
...
@@ -419,8 +427,10 @@ private:
CUfunction
computeMomentsKernel
,
recordInducedDipolesKernel
,
computeFixedFieldKernel
,
computeInducedFieldKernel
,
updateInducedFieldKernel
,
electrostaticsKernel
,
mapTorqueKernel
;
CUfunction
pmeGridIndexKernel
,
pmeSpreadFixedMultipolesKernel
,
pmeSpreadInducedDipolesKernel
,
pmeFinishSpreadChargeKernel
,
pmeConvolutionKernel
;
CUfunction
pmeFixedPotentialKernel
,
pmeInducedPotentialKernel
,
pmeFixedForceKernel
,
pmeInducedForceKernel
,
pmeRecordInducedFieldDipolesKernel
,
computePotentialKernel
;
CUfunction
recordDIISDipolesKernel
,
buildMatrixKernel
;
CudaCalcAmoebaGeneralizedKirkwoodForceKernel
*
gkKernel
;
static
const
int
PmeOrder
=
5
;
static
const
int
MaxPrevDIISDipoles
=
20
;
};
/**
...
...
plugins/amoeba/platforms/cuda/src/kernels/multipoleInducedField.cu
View file @
8db70d34
...
...
@@ -485,7 +485,7 @@ extern "C" __global__ void updateInducedFieldBySOR(const long long* __restrict__
buffer
[
threadIdx
.
x
]
=
make_real2
(
sumErrors
,
sumPolarErrors
);
__syncthreads
();
for
(
int
offset
=
1
;
offset
<
blockDim
.
x
;
offset
*=
2
)
{
for
(
int
offset
=
1
;
offset
<
blockDim
.
x
;
offset
*=
2
)
{
if
(
threadIdx
.
x
+
offset
<
blockDim
.
x
&&
(
threadIdx
.
x
&
(
2
*
offset
-
1
))
==
0
)
{
buffer
[
threadIdx
.
x
].
x
+=
buffer
[
threadIdx
.
x
+
offset
].
x
;
buffer
[
threadIdx
.
x
].
y
+=
buffer
[
threadIdx
.
x
+
offset
].
y
;
...
...
@@ -494,4 +494,115 @@ extern "C" __global__ void updateInducedFieldBySOR(const long long* __restrict__
}
if
(
threadIdx
.
x
==
0
)
errors
[
blockIdx
.
x
]
=
make_float2
((
float
)
buffer
[
0
].
x
,
(
float
)
buffer
[
0
].
y
);
}
\ No newline at end of file
}
extern
"C"
__global__
void
recordInducedDipolesForDIIS
(
const
long
long
*
__restrict__
fixedField
,
const
long
long
*
__restrict__
fixedFieldPolar
,
const
long
long
*
__restrict__
fixedFieldS
,
const
long
long
*
__restrict__
inducedField
,
const
long
long
*
__restrict__
inducedFieldPolar
,
const
real
*
__restrict__
inducedDipole
,
const
real
*
__restrict__
inducedDipolePolar
,
const
float
*
__restrict__
polarizability
,
float2
*
__restrict__
errors
,
real
*
__restrict__
prevDipoles
,
real
*
__restrict__
prevDipolesPolar
,
real
*
__restrict__
prevErrors
,
int
iteration
,
bool
recordPrevErrors
,
real
*
__restrict__
matrix
)
{
extern
__shared__
real2
buffer
[];
#ifdef USE_EWALD
const
real
ewaldScale
=
(
4
/
(
real
)
3
)
*
(
EWALD_ALPHA
*
EWALD_ALPHA
*
EWALD_ALPHA
)
/
SQRT_PI
;
#else
const
real
ewaldScale
=
0
;
#endif
const
real
fieldScale
=
1
/
(
real
)
0x100000000
;
real
sumErrors
=
0
;
real
sumPolarErrors
=
0
;
for
(
int
atom
=
blockIdx
.
x
*
blockDim
.
x
+
threadIdx
.
x
;
atom
<
NUM_ATOMS
;
atom
+=
blockDim
.
x
*
gridDim
.
x
)
{
real
scale
=
polarizability
[
atom
];
for
(
int
component
=
0
;
component
<
3
;
component
++
)
{
int
dipoleIndex
=
3
*
atom
+
component
;
int
fieldIndex
=
atom
+
component
*
PADDED_NUM_ATOMS
;
if
(
iteration
>=
MAX_PREV_DIIS_DIPOLES
)
{
// We have filled up the buffer for previous dipoles, so shift them all over by one.
for
(
int
i
=
1
;
i
<
MAX_PREV_DIIS_DIPOLES
;
i
++
)
{
int
index1
=
dipoleIndex
+
(
i
-
1
)
*
NUM_ATOMS
*
3
;
int
index2
=
dipoleIndex
+
i
*
NUM_ATOMS
*
3
;
prevDipoles
[
index1
]
=
prevDipoles
[
index2
];
prevDipolesPolar
[
index1
]
=
prevDipolesPolar
[
index2
];
if
(
recordPrevErrors
)
prevErrors
[
index1
]
=
prevErrors
[
index2
];
}
}
// Compute the new dipole, and record it along with the error.
real
oldDipole
=
inducedDipole
[
dipoleIndex
];
real
oldDipolePolar
=
inducedDipolePolar
[
dipoleIndex
];
long
long
fixedS
=
(
fixedFieldS
==
NULL
?
(
long
long
)
0
:
fixedFieldS
[
fieldIndex
]);
real
newDipole
=
scale
*
((
fixedField
[
fieldIndex
]
+
fixedS
+
inducedField
[
fieldIndex
])
*
fieldScale
+
ewaldScale
*
oldDipole
);
real
newDipolePolar
=
scale
*
((
fixedFieldPolar
[
fieldIndex
]
+
fixedS
+
inducedFieldPolar
[
fieldIndex
])
*
fieldScale
+
ewaldScale
*
oldDipolePolar
);
int
storePrevIndex
=
dipoleIndex
+
min
(
iteration
,
MAX_PREV_DIIS_DIPOLES
-
1
)
*
NUM_ATOMS
*
3
;
prevDipoles
[
storePrevIndex
]
=
newDipole
;
prevDipolesPolar
[
storePrevIndex
]
=
newDipolePolar
;
if
(
recordPrevErrors
)
prevErrors
[
storePrevIndex
]
=
newDipole
-
oldDipole
;
sumErrors
+=
(
newDipole
-
oldDipole
)
*
(
newDipole
-
oldDipole
);
sumPolarErrors
+=
(
newDipolePolar
-
oldDipolePolar
)
*
(
newDipolePolar
-
oldDipolePolar
);
}
}
// Sum the errors over threads and store the total for this block.
buffer
[
threadIdx
.
x
]
=
make_real2
(
sumErrors
,
sumPolarErrors
);
__syncthreads
();
for
(
int
offset
=
1
;
offset
<
blockDim
.
x
;
offset
*=
2
)
{
if
(
threadIdx
.
x
+
offset
<
blockDim
.
x
&&
(
threadIdx
.
x
&
(
2
*
offset
-
1
))
==
0
)
{
buffer
[
threadIdx
.
x
].
x
+=
buffer
[
threadIdx
.
x
+
offset
].
x
;
buffer
[
threadIdx
.
x
].
y
+=
buffer
[
threadIdx
.
x
+
offset
].
y
;
}
__syncthreads
();
}
if
(
threadIdx
.
x
==
0
)
errors
[
blockIdx
.
x
]
=
make_float2
((
float
)
buffer
[
0
].
x
,
(
float
)
buffer
[
0
].
y
);
if
(
iteration
>=
MAX_PREV_DIIS_DIPOLES
&&
recordPrevErrors
&&
blockIdx
.
x
==
0
)
{
// Shift over the existing matrix elements.
for
(
int
i
=
0
;
i
<
MAX_PREV_DIIS_DIPOLES
-
1
;
i
++
)
{
if
(
threadIdx
.
x
<
MAX_PREV_DIIS_DIPOLES
-
1
)
matrix
[
threadIdx
.
x
+
i
*
MAX_PREV_DIIS_DIPOLES
]
=
matrix
[(
threadIdx
.
x
+
1
)
+
(
i
+
1
)
*
MAX_PREV_DIIS_DIPOLES
];
__syncthreads
();
}
}
}
extern
"C"
__global__
void
computeDIISMatrix
(
real
*
__restrict__
prevErrors
,
int
iteration
,
real
*
__restrict__
matrix
)
{
extern
__shared__
real
sumBuffer
[];
int
j
=
min
(
iteration
,
MAX_PREV_DIIS_DIPOLES
-
1
);
for
(
int
i
=
blockIdx
.
x
;
i
<=
j
;
i
+=
gridDim
.
x
)
{
// All the threads in this thread block work together to compute a single matrix element.
real
sum
=
0
;
for
(
int
index
=
threadIdx
.
x
;
index
<
NUM_ATOMS
*
3
;
index
+=
blockDim
.
x
)
sum
+=
prevErrors
[
index
+
i
*
NUM_ATOMS
*
3
]
*
prevErrors
[
index
+
j
*
NUM_ATOMS
*
3
];
sumBuffer
[
threadIdx
.
x
]
=
sum
;
__syncthreads
();
for
(
int
offset
=
1
;
offset
<
blockDim
.
x
;
offset
*=
2
)
{
if
(
threadIdx
.
x
+
offset
<
blockDim
.
x
&&
(
threadIdx
.
x
&
(
2
*
offset
-
1
))
==
0
)
sumBuffer
[
threadIdx
.
x
]
+=
sumBuffer
[
threadIdx
.
x
+
offset
];
__syncthreads
();
}
if
(
threadIdx
.
x
==
0
)
{
matrix
[
i
+
MAX_PREV_DIIS_DIPOLES
*
j
]
=
sumBuffer
[
0
];
if
(
i
!=
j
)
matrix
[
j
+
MAX_PREV_DIIS_DIPOLES
*
i
]
=
sumBuffer
[
0
];
}
}
}
extern
"C"
__global__
void
updateInducedFieldByDIIS
(
real
*
__restrict__
inducedDipole
,
real
*
__restrict__
inducedDipolePolar
,
const
real
*
__restrict__
prevDipoles
,
const
real
*
__restrict__
prevDipolesPolar
,
const
float
*
__restrict__
coefficients
,
int
numPrev
)
{
for
(
int
index
=
blockIdx
.
x
*
blockDim
.
x
+
threadIdx
.
x
;
index
<
3
*
NUM_ATOMS
;
index
+=
blockDim
.
x
*
gridDim
.
x
)
{
real
sum
=
0
;
real
sumPolar
=
0
;
for
(
int
i
=
0
;
i
<
numPrev
;
i
++
)
{
sum
+=
coefficients
[
i
]
*
prevDipoles
[
i
*
3
*
NUM_ATOMS
+
index
];
sumPolar
+=
coefficients
[
i
]
*
prevDipolesPolar
[
i
*
3
*
NUM_ATOMS
+
index
];
}
inducedDipole
[
index
]
=
sum
;
inducedDipolePolar
[
index
]
=
sumPolar
;
}
}
plugins/amoeba/platforms/reference/src/SimTKReference/AmoebaReferenceMultipoleForce.cpp
View file @
8db70d34
/* Portions copyright (c) 2006 Stanford University and Simbios.
/* Portions copyright (c) 2006
-2014
Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
...
...
@@ -23,6 +23,7 @@
*/
#include "AmoebaReferenceMultipoleForce.h"
#include "jama_svd.h"
#include <algorithm>
// In case we're using some primitive version of Visual Studio this will
...
...
@@ -34,7 +35,7 @@ using OpenMM::RealVec;
#undef AMOEBA_DEBUG
AmoebaReferenceMultipoleForce
::
AmoebaReferenceMultipoleForce
(
)
:
AmoebaReferenceMultipoleForce
::
AmoebaReferenceMultipoleForce
()
:
_nonbondedMethod
(
NoCutoff
),
_numParticles
(
0
),
_electric
(
138.9354558456
),
...
...
@@ -50,8 +51,8 @@ AmoebaReferenceMultipoleForce::AmoebaReferenceMultipoleForce( ) :
initialize
();
}
AmoebaReferenceMultipoleForce
::
AmoebaReferenceMultipoleForce
(
NonbondedMethod
nonbondedMethod
)
:
_nonbondedMethod
(
NoCutoff
),
AmoebaReferenceMultipoleForce
::
AmoebaReferenceMultipoleForce
(
NonbondedMethod
nonbondedMethod
)
:
_nonbondedMethod
(
nonbondedMethod
),
_numParticles
(
0
),
_electric
(
138.9354558456
),
_dielectric
(
1.0
),
...
...
@@ -66,7 +67,7 @@ AmoebaReferenceMultipoleForce::AmoebaReferenceMultipoleForce( NonbondedMethod no
initialize
();
}
void
AmoebaReferenceMultipoleForce
::
initialize
(
void
)
void
AmoebaReferenceMultipoleForce
::
initialize
()
{
unsigned
int
index
=
0
;
...
...
@@ -100,77 +101,77 @@ void AmoebaReferenceMultipoleForce::initialize( void )
return
;
}
AmoebaReferenceMultipoleForce
::
NonbondedMethod
AmoebaReferenceMultipoleForce
::
getNonbondedMethod
(
void
)
const
AmoebaReferenceMultipoleForce
::
NonbondedMethod
AmoebaReferenceMultipoleForce
::
getNonbondedMethod
()
const
{
return
_nonbondedMethod
;
}
void
AmoebaReferenceMultipoleForce
::
setNonbondedMethod
(
AmoebaReferenceMultipoleForce
::
NonbondedMethod
nonbondedMethod
)
void
AmoebaReferenceMultipoleForce
::
setNonbondedMethod
(
AmoebaReferenceMultipoleForce
::
NonbondedMethod
nonbondedMethod
)
{
_nonbondedMethod
=
nonbondedMethod
;
}
AmoebaReferenceMultipoleForce
::
PolarizationType
AmoebaReferenceMultipoleForce
::
getPolarizationType
(
void
)
const
AmoebaReferenceMultipoleForce
::
PolarizationType
AmoebaReferenceMultipoleForce
::
getPolarizationType
()
const
{
return
_polarizationType
;
}
void
AmoebaReferenceMultipoleForce
::
setPolarizationType
(
AmoebaReferenceMultipoleForce
::
PolarizationType
polarizationType
)
void
AmoebaReferenceMultipoleForce
::
setPolarizationType
(
AmoebaReferenceMultipoleForce
::
PolarizationType
polarizationType
)
{
_polarizationType
=
polarizationType
;
}
int
AmoebaReferenceMultipoleForce
::
getMutualInducedDipoleConverged
(
void
)
const
int
AmoebaReferenceMultipoleForce
::
getMutualInducedDipoleConverged
()
const
{
return
_mutualInducedDipoleConverged
;
}
void
AmoebaReferenceMultipoleForce
::
setMutualInducedDipoleConverged
(
int
mutualInducedDipoleConverged
)
void
AmoebaReferenceMultipoleForce
::
setMutualInducedDipoleConverged
(
int
mutualInducedDipoleConverged
)
{
_mutualInducedDipoleConverged
=
mutualInducedDipoleConverged
;
}
int
AmoebaReferenceMultipoleForce
::
getMutualInducedDipoleIterations
(
void
)
const
int
AmoebaReferenceMultipoleForce
::
getMutualInducedDipoleIterations
()
const
{
return
_mutualInducedDipoleIterations
;
}
void
AmoebaReferenceMultipoleForce
::
setMutualInducedDipoleIterations
(
int
mutualInducedDipoleIterations
)
void
AmoebaReferenceMultipoleForce
::
setMutualInducedDipoleIterations
(
int
mutualInducedDipoleIterations
)
{
_mutualInducedDipoleIterations
=
mutualInducedDipoleIterations
;
}
RealOpenMM
AmoebaReferenceMultipoleForce
::
getMutualInducedDipoleEpsilon
(
void
)
const
RealOpenMM
AmoebaReferenceMultipoleForce
::
getMutualInducedDipoleEpsilon
()
const
{
return
_mutualInducedDipoleEpsilon
;
}
void
AmoebaReferenceMultipoleForce
::
setMutualInducedDipoleEpsilon
(
RealOpenMM
mutualInducedDipoleEpsilon
)
void
AmoebaReferenceMultipoleForce
::
setMutualInducedDipoleEpsilon
(
RealOpenMM
mutualInducedDipoleEpsilon
)
{
_mutualInducedDipoleEpsilon
=
mutualInducedDipoleEpsilon
;
}
int
AmoebaReferenceMultipoleForce
::
getMaximumMutualInducedDipoleIterations
(
void
)
const
int
AmoebaReferenceMultipoleForce
::
getMaximumMutualInducedDipoleIterations
()
const
{
return
_maximumMutualInducedDipoleIterations
;
}
void
AmoebaReferenceMultipoleForce
::
setMaximumMutualInducedDipoleIterations
(
int
maximumMutualInducedDipoleIterations
)
void
AmoebaReferenceMultipoleForce
::
setMaximumMutualInducedDipoleIterations
(
int
maximumMutualInducedDipoleIterations
)
{
_maximumMutualInducedDipoleIterations
=
maximumMutualInducedDipoleIterations
;
}
RealOpenMM
AmoebaReferenceMultipoleForce
::
getMutualInducedDipoleTargetEpsilon
(
void
)
const
RealOpenMM
AmoebaReferenceMultipoleForce
::
getMutualInducedDipoleTargetEpsilon
()
const
{
return
_mutualInducedDipoleTargetEpsilon
;
}
void
AmoebaReferenceMultipoleForce
::
setMutualInducedDipoleTargetEpsilon
(
RealOpenMM
mutualInducedDipoleTargetEpsilon
)
void
AmoebaReferenceMultipoleForce
::
setMutualInducedDipoleTargetEpsilon
(
RealOpenMM
mutualInducedDipoleTargetEpsilon
)
{
_mutualInducedDipoleTargetEpsilon
=
mutualInducedDipoleTargetEpsilon
;
}
void
AmoebaReferenceMultipoleForce
::
setupScaleMaps
(
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleParticleCovalentInfo
)
void
AmoebaReferenceMultipoleForce
::
setupScaleMaps
(
const
vector
<
vector
<
vector
<
int
>
>
>&
multipoleParticleCovalentInfo
)
{
/* Setup for scaling maps:
...
...
@@ -184,30 +185,30 @@ void AmoebaReferenceMultipoleForce::setupScaleMaps( const std::vector< std::vect
* only including covalent particles w/ index >= ii
*/
_scaleMaps
.
resize
(
multipoleParticleCovalentInfo
.
size
()
);
_maxScaleIndex
.
resize
(
multipoleParticleCovalentInfo
.
size
()
);
_scaleMaps
.
resize
(
multipoleParticleCovalentInfo
.
size
());
_maxScaleIndex
.
resize
(
multipoleParticleCovalentInfo
.
size
());
for
(
unsigned
int
ii
=
0
;
ii
<
multipoleParticleCovalentInfo
.
size
();
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
multipoleParticleCovalentInfo
.
size
();
ii
++
)
{
_scaleMaps
[
ii
].
resize
(
LAST_SCALE_TYPE_INDEX
);
_maxScaleIndex
[
ii
]
=
0
;
const
std
::
vector
<
std
::
vector
<
int
>
>&
covalentInfo
=
multipoleParticleCovalentInfo
[
ii
];
const
std
::
vector
<
int
>
covalentListP11
=
covalentInfo
[
AmoebaMultipoleForce
::
PolarizationCovalent11
];
const
vector
<
vector
<
int
>
>&
covalentInfo
=
multipoleParticleCovalentInfo
[
ii
];
const
vector
<
int
>
covalentListP11
=
covalentInfo
[
AmoebaMultipoleForce
::
PolarizationCovalent11
];
// pScale & mScale
for
(
unsigned
jj
=
0
;
jj
<
AmoebaMultipoleForce
::
PolarizationCovalent11
;
jj
++
){
const
std
::
vector
<
int
>
covalentList
=
covalentInfo
[
jj
];
for
(
unsigned
int
kk
=
0
;
kk
<
covalentList
.
size
();
kk
++
){
for
(
unsigned
jj
=
0
;
jj
<
AmoebaMultipoleForce
::
PolarizationCovalent11
;
jj
++
)
{
const
vector
<
int
>
covalentList
=
covalentInfo
[
jj
];
for
(
unsigned
int
kk
=
0
;
kk
<
covalentList
.
size
();
kk
++
)
{
unsigned
int
covalentIndex
=
static_cast
<
unsigned
int
>
(
covalentList
[
kk
]);
if
(
covalentIndex
<
ii
)
continue
;
if
(
covalentIndex
<
ii
)
continue
;
// handle 0.5 factor for p14
int
hit
=
0
;
if
(
jj
==
AmoebaMultipoleForce
::
Covalent14
){
for
(
unsigned
int
mm
=
0
;
mm
<
covalentListP11
.
size
()
&&
hit
==
0
;
mm
++
){
if
(
covalentListP11
[
mm
]
==
covalentIndex
){
if
(
jj
==
AmoebaMultipoleForce
::
Covalent14
)
{
for
(
unsigned
int
mm
=
0
;
mm
<
covalentListP11
.
size
()
&&
hit
==
0
;
mm
++
)
{
if
(
covalentListP11
[
mm
]
==
covalentIndex
)
{
hit
=
1
;
}
}
...
...
@@ -221,11 +222,11 @@ void AmoebaReferenceMultipoleForce::setupScaleMaps( const std::vector< std::vect
// dScale & uScale
for
(
unsigned
jj
=
AmoebaMultipoleForce
::
PolarizationCovalent11
;
jj
<
covalentInfo
.
size
();
jj
++
){
const
std
::
vector
<
int
>
covalentList
=
covalentInfo
[
jj
];
for
(
unsigned
int
kk
=
0
;
kk
<
covalentList
.
size
();
kk
++
){
for
(
unsigned
jj
=
AmoebaMultipoleForce
::
PolarizationCovalent11
;
jj
<
covalentInfo
.
size
();
jj
++
)
{
const
vector
<
int
>
covalentList
=
covalentInfo
[
jj
];
for
(
unsigned
int
kk
=
0
;
kk
<
covalentList
.
size
();
kk
++
)
{
unsigned
int
covalentIndex
=
static_cast
<
unsigned
int
>
(
covalentList
[
kk
]);
if
(
covalentIndex
<
ii
)
continue
;
if
(
covalentIndex
<
ii
)
continue
;
_scaleMaps
[
ii
][
D_SCALE
][
covalentIndex
]
=
_dScale
[
jj
-
4
];
_scaleMaps
[
ii
][
U_SCALE
][
covalentIndex
]
=
_uScale
[
jj
-
4
];
_maxScaleIndex
[
ii
]
=
_maxScaleIndex
[
ii
]
<
covalentIndex
?
covalentIndex
:
_maxScaleIndex
[
ii
];
...
...
@@ -233,104 +234,104 @@ void AmoebaReferenceMultipoleForce::setupScaleMaps( const std::vector< std::vect
}
}
//showScaleMapForParticle(
2, stderr
);
//showScaleMapForParticle(
10, stderr
);
//showScaleMapForParticle(2, stderr);
//showScaleMapForParticle(10, stderr);
return
;
}
void
AmoebaReferenceMultipoleForce
::
showScaleMapForParticle
(
unsigned
int
particleI
,
FILE
*
log
)
const
void
AmoebaReferenceMultipoleForce
::
showScaleMapForParticle
(
unsigned
int
particleI
,
FILE
*
log
)
const
{
#ifdef AMOEBA_DEBUG
(
void
)
fprintf
(
log
,
"Scale map particle %5u maxIndex=%u
\n
"
,
particleI
,
_maxScaleIndex
[
particleI
]
);
(
void
)
fprintf
(
log
,
"Scale map particle %5u maxIndex=%u
\n
"
,
particleI
,
_maxScaleIndex
[
particleI
]);
std
::
string
scaleNames
[
LAST_SCALE_TYPE_INDEX
]
=
{
"D"
,
"P"
,
"M"
};
for
(
unsigned
int
ii
=
0
;
ii
<
_scaleMaps
[
particleI
].
size
();
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_scaleMaps
[
particleI
].
size
();
ii
++
)
{
MapIntRealOpenMM
scaleMap
=
_scaleMaps
[
particleI
][
ii
];
(
void
)
fprintf
(
log
,
" %s scale "
,
scaleNames
[
ii
].
c_str
()
);
for
(
MapIntRealOpenMMCI
jj
=
scaleMap
.
begin
();
jj
!=
scaleMap
.
end
();
jj
++
){
//if
(
jj->first > particleI && jj->second < 1.0
)
if
(
jj
->
second
<
1.0
)
(
void
)
fprintf
(
log
,
"%4d=%5.2f "
,
jj
->
first
,
jj
->
second
);
(
void
)
fprintf
(
log
,
" %s scale "
,
scaleNames
[
ii
].
c_str
());
for
(
MapIntRealOpenMMCI
jj
=
scaleMap
.
begin
();
jj
!=
scaleMap
.
end
();
jj
++
)
{
//if
(
jj->first > particleI && jj->second < 1.0)
if
(
jj
->
second
<
1.0
)
(
void
)
fprintf
(
log
,
"%4d=%5.2f "
,
jj
->
first
,
jj
->
second
);
}
(
void
)
fprintf
(
log
,
"
\n
"
);
(
void
)
fprintf
(
log
,
"
\n
"
);
}
(
void
)
fprintf
(
log
,
"
\n
"
);
(
void
)
fflush
(
log
);
(
void
)
fprintf
(
log
,
"
\n
"
);
(
void
)
fflush
(
log
);
#endif
}
RealOpenMM
AmoebaReferenceMultipoleForce
::
getMultipoleScaleFactor
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
ScaleType
scaleType
)
const
RealOpenMM
AmoebaReferenceMultipoleForce
::
getMultipoleScaleFactor
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
ScaleType
scaleType
)
const
{
MapIntRealOpenMM
scaleMap
=
_scaleMaps
[
particleI
][
scaleType
];
MapIntRealOpenMMCI
isPresent
=
scaleMap
.
find
(
particleJ
);
if
(
isPresent
!=
scaleMap
.
end
()
){
MapIntRealOpenMMCI
isPresent
=
scaleMap
.
find
(
particleJ
);
if
(
isPresent
!=
scaleMap
.
end
())
{
return
isPresent
->
second
;
}
else
{
return
1.0
;
}
}
void
AmoebaReferenceMultipoleForce
::
getDScaleAndPScale
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
RealOpenMM
&
dScale
,
RealOpenMM
&
pScale
)
const
void
AmoebaReferenceMultipoleForce
::
getDScaleAndPScale
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
RealOpenMM
&
dScale
,
RealOpenMM
&
pScale
)
const
{
dScale
=
getMultipoleScaleFactor
(
particleI
,
particleJ
,
D_SCALE
);
pScale
=
getMultipoleScaleFactor
(
particleI
,
particleJ
,
P_SCALE
);
dScale
=
getMultipoleScaleFactor
(
particleI
,
particleJ
,
D_SCALE
);
pScale
=
getMultipoleScaleFactor
(
particleI
,
particleJ
,
P_SCALE
);
}
void
AmoebaReferenceMultipoleForce
::
getMultipoleScaleFactors
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
std
::
vector
<
RealOpenMM
>&
scaleFactors
)
const
void
AmoebaReferenceMultipoleForce
::
getMultipoleScaleFactors
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
vector
<
RealOpenMM
>&
scaleFactors
)
const
{
scaleFactors
[
D_SCALE
]
=
getMultipoleScaleFactor
(
particleI
,
particleJ
,
D_SCALE
);
scaleFactors
[
P_SCALE
]
=
getMultipoleScaleFactor
(
particleI
,
particleJ
,
P_SCALE
);
scaleFactors
[
M_SCALE
]
=
getMultipoleScaleFactor
(
particleI
,
particleJ
,
M_SCALE
);
scaleFactors
[
U_SCALE
]
=
getMultipoleScaleFactor
(
particleI
,
particleJ
,
U_SCALE
);
scaleFactors
[
D_SCALE
]
=
getMultipoleScaleFactor
(
particleI
,
particleJ
,
D_SCALE
);
scaleFactors
[
P_SCALE
]
=
getMultipoleScaleFactor
(
particleI
,
particleJ
,
P_SCALE
);
scaleFactors
[
M_SCALE
]
=
getMultipoleScaleFactor
(
particleI
,
particleJ
,
M_SCALE
);
scaleFactors
[
U_SCALE
]
=
getMultipoleScaleFactor
(
particleI
,
particleJ
,
U_SCALE
);
}
RealOpenMM
AmoebaReferenceMultipoleForce
::
normalizeRealVec
(
RealVec
&
vectorToNormalize
)
const
RealOpenMM
AmoebaReferenceMultipoleForce
::
normalizeRealVec
(
RealVec
&
vectorToNormalize
)
const
{
RealOpenMM
norm
=
SQRT
(
vectorToNormalize
.
dot
(
vectorToNormalize
)
);
if
(
norm
>
0.0
){
RealOpenMM
norm
=
SQRT
(
vectorToNormalize
.
dot
(
vectorToNormalize
)
);
if
(
norm
>
0.0
)
{
vectorToNormalize
*=
(
1.0
/
norm
);
}
return
norm
;
}
void
AmoebaReferenceMultipoleForce
::
initializeRealOpenMMVector
(
vector
<
RealOpenMM
>&
vectorToInitialize
)
const
void
AmoebaReferenceMultipoleForce
::
initializeRealOpenMMVector
(
vector
<
RealOpenMM
>&
vectorToInitialize
)
const
{
RealOpenMM
zero
=
0.0
;
vectorToInitialize
.
resize
(
_numParticles
);
std
::
fill
(
vectorToInitialize
.
begin
(),
vectorToInitialize
.
end
(),
zero
);
vectorToInitialize
.
resize
(
_numParticles
);
std
::
fill
(
vectorToInitialize
.
begin
(),
vectorToInitialize
.
end
(),
zero
);
}
void
AmoebaReferenceMultipoleForce
::
initializeRealVecVector
(
vector
<
RealVec
>&
vectorToInitialize
)
const
void
AmoebaReferenceMultipoleForce
::
initializeRealVecVector
(
vector
<
RealVec
>&
vectorToInitialize
)
const
{
vectorToInitialize
.
resize
(
_numParticles
);
RealVec
zeroVec
(
0.0
,
0.0
,
0.0
);
std
::
fill
(
vectorToInitialize
.
begin
(),
vectorToInitialize
.
end
(),
zeroVec
);
vectorToInitialize
.
resize
(
_numParticles
);
RealVec
zeroVec
(
0.0
,
0.0
,
0.0
);
std
::
fill
(
vectorToInitialize
.
begin
(),
vectorToInitialize
.
end
(),
zeroVec
);
}
void
AmoebaReferenceMultipoleForce
::
copyRealVecVector
(
const
std
::
vector
<
OpenMM
::
RealVec
>&
inputVector
,
std
::
vector
<
OpenMM
::
RealVec
>&
outputVector
)
const
void
AmoebaReferenceMultipoleForce
::
copyRealVecVector
(
const
vector
<
OpenMM
::
RealVec
>&
inputVector
,
vector
<
OpenMM
::
RealVec
>&
outputVector
)
const
{
outputVector
.
resize
(
inputVector
.
size
()
);
for
(
unsigned
int
ii
=
0
;
ii
<
inputVector
.
size
();
ii
++
){
outputVector
.
resize
(
inputVector
.
size
());
for
(
unsigned
int
ii
=
0
;
ii
<
inputVector
.
size
();
ii
++
)
{
outputVector
[
ii
]
=
inputVector
[
ii
];
}
return
;
}
void
AmoebaReferenceMultipoleForce
::
loadParticleData
(
const
std
::
vector
<
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
std
::
vector
<
MultipoleParticleData
>&
particleData
)
const
void
AmoebaReferenceMultipoleForce
::
loadParticleData
(
const
vector
<
RealVec
>&
particlePositions
,
const
vector
<
RealOpenMM
>&
charges
,
const
vector
<
RealOpenMM
>&
dipoles
,
const
vector
<
RealOpenMM
>&
quadrupoles
,
const
vector
<
RealOpenMM
>&
tholes
,
const
vector
<
RealOpenMM
>&
dampingFactors
,
const
vector
<
RealOpenMM
>&
polarity
,
vector
<
MultipoleParticleData
>&
particleData
)
const
{
particleData
.
resize
(
_numParticles
);
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
particleData
.
resize
(
_numParticles
);
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
particleData
[
ii
].
particleIndex
=
ii
;
...
...
@@ -355,18 +356,18 @@ void AmoebaReferenceMultipoleForce::loadParticleData( const std::vector<RealVec>
}
}
void
AmoebaReferenceMultipoleForce
::
zeroFixedMultipoleFields
(
void
)
void
AmoebaReferenceMultipoleForce
::
zeroFixedMultipoleFields
()
{
initializeRealVecVector
(
_fixedMultipoleField
);
initializeRealVecVector
(
_fixedMultipoleFieldPolar
);
initializeRealVecVector
(
_fixedMultipoleField
);
initializeRealVecVector
(
_fixedMultipoleFieldPolar
);
}
void
AmoebaReferenceMultipoleForce
::
checkChiralCenterAtParticle
(
MultipoleParticleData
&
particleI
,
int
axisType
,
MultipoleParticleData
&
particleZ
,
MultipoleParticleData
&
particleX
,
MultipoleParticleData
&
particleY
)
const
void
AmoebaReferenceMultipoleForce
::
checkChiralCenterAtParticle
(
MultipoleParticleData
&
particleI
,
int
axisType
,
MultipoleParticleData
&
particleZ
,
MultipoleParticleData
&
particleX
,
MultipoleParticleData
&
particleY
)
const
{
if
(
axisType
==
AmoebaMultipoleForce
::
ZThenX
){
if
(
axisType
==
AmoebaMultipoleForce
::
ZThenX
)
{
return
;
}
...
...
@@ -374,10 +375,10 @@ void AmoebaReferenceMultipoleForce::checkChiralCenterAtParticle( MultipolePartic
RealVec
deltaBD
=
particleZ
.
position
-
particleY
.
position
;
RealVec
deltaCD
=
particleX
.
position
-
particleY
.
position
;
RealVec
deltaC
=
deltaBD
.
cross
(
deltaCD
);
RealOpenMM
volume
=
deltaC
.
dot
(
deltaAD
);
RealVec
deltaC
=
deltaBD
.
cross
(
deltaCD
);
RealOpenMM
volume
=
deltaC
.
dot
(
deltaAD
);
if
(
volume
<
0.0
){
if
(
volume
<
0.0
)
{
particleI
.
dipole
[
1
]
*=
-
1.0
;
// pole(3,i)
particleI
.
quadrupole
[
QXY
]
*=
-
1.0
;
// pole(6,i) && pole(8,i)
particleI
.
quadrupole
[
QYZ
]
*=
-
1.0
;
// pole(10,i) && pole(12,i)
...
...
@@ -386,29 +387,29 @@ void AmoebaReferenceMultipoleForce::checkChiralCenterAtParticle( MultipolePartic
}
void
AmoebaReferenceMultipoleForce
::
checkChiral
(
std
::
vector
<
MultipoleParticleData
>&
particleData
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
axisTypes
)
const
void
AmoebaReferenceMultipoleForce
::
checkChiral
(
vector
<
MultipoleParticleData
>&
particleData
,
const
vector
<
int
>&
multipoleAtomXs
,
const
vector
<
int
>&
multipoleAtomYs
,
const
vector
<
int
>&
multipoleAtomZs
,
const
vector
<
int
>&
axisTypes
)
const
{
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
if
(
multipoleAtomYs
[
ii
]
>
-
1
){
checkChiralCenterAtParticle
(
particleData
[
ii
],
axisTypes
[
ii
],
particleData
[
multipoleAtomZs
[
ii
]],
particleData
[
multipoleAtomXs
[
ii
]],
particleData
[
multipoleAtomYs
[
ii
]]
);
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
if
(
multipoleAtomYs
[
ii
]
>
-
1
)
{
checkChiralCenterAtParticle
(
particleData
[
ii
],
axisTypes
[
ii
],
particleData
[
multipoleAtomZs
[
ii
]],
particleData
[
multipoleAtomXs
[
ii
]],
particleData
[
multipoleAtomYs
[
ii
]]);
}
}
return
;
}
void
AmoebaReferenceMultipoleForce
::
applyRotationMatrixToParticle
(
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleZ
,
const
MultipoleParticleData
&
particleX
,
MultipoleParticleData
*
particleY
,
int
axisType
)
const
void
AmoebaReferenceMultipoleForce
::
applyRotationMatrixToParticle
(
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleZ
,
const
MultipoleParticleData
&
particleX
,
MultipoleParticleData
*
particleY
,
int
axisType
)
const
{
// handle case where rotation matrix is identity (e.g. single ion)
...
...
@@ -421,61 +422,61 @@ void AmoebaReferenceMultipoleForce::applyRotationMatrixToParticle( Multipo
RealVec
vectorZ
=
particleZ
.
position
-
particleI
.
position
;
RealVec
vectorX
=
particleX
.
position
-
particleI
.
position
;
normalizeRealVec
(
vectorZ
);
normalizeRealVec
(
vectorZ
);
// branch based on axis type
if
(
axisType
==
AmoebaMultipoleForce
::
Bisector
){
if
(
axisType
==
AmoebaMultipoleForce
::
Bisector
)
{
// bisector
// dx = dx1 + dx2 (in TINKER code)
normalizeRealVec
(
vectorX
);
normalizeRealVec
(
vectorX
);
vectorZ
+=
vectorX
;
normalizeRealVec
(
vectorZ
);
normalizeRealVec
(
vectorZ
);
}
else
if
(
axisType
==
AmoebaMultipoleForce
::
ZBisect
){
}
else
if
(
axisType
==
AmoebaMultipoleForce
::
ZBisect
)
{
// z-bisect
// dx = dx1 + dx2 (in TINKER code)
normalizeRealVec
(
vectorX
);
normalizeRealVec
(
vectorX
);
vectorY
=
particleY
->
position
-
particleI
.
position
;
normalizeRealVec
(
vectorY
);
normalizeRealVec
(
vectorY
);
vectorX
+=
vectorY
;
normalizeRealVec
(
vectorX
);
normalizeRealVec
(
vectorX
);
}
else
if
(
axisType
==
AmoebaMultipoleForce
::
ThreeFold
){
}
else
if
(
axisType
==
AmoebaMultipoleForce
::
ThreeFold
)
{
// 3-fold
// dx = dx1 + dx2 + dx3 (in TINKER code)
normalizeRealVec
(
vectorX
);
normalizeRealVec
(
vectorX
);
vectorY
=
particleY
->
position
-
particleI
.
position
;
normalizeRealVec
(
vectorY
);
normalizeRealVec
(
vectorY
);
vectorZ
+=
vectorX
+
vectorY
;
normalizeRealVec
(
vectorZ
);
normalizeRealVec
(
vectorZ
);
}
else
if
(
axisType
==
AmoebaMultipoleForce
::
ZOnly
){
}
else
if
(
axisType
==
AmoebaMultipoleForce
::
ZOnly
)
{
// z-only
vectorX
=
RealVec
(
0.1
,
0.1
,
0.1
);
vectorX
=
RealVec
(
0.1
,
0.1
,
0.1
);
}
RealOpenMM
dot
=
vectorZ
.
dot
(
vectorX
);
RealOpenMM
dot
=
vectorZ
.
dot
(
vectorX
);
vectorX
-=
vectorZ
*
dot
;
normalizeRealVec
(
vectorX
);
vectorY
=
vectorZ
.
cross
(
vectorX
);
normalizeRealVec
(
vectorX
);
vectorY
=
vectorZ
.
cross
(
vectorX
);
RealVec
rotationMatrix
[
3
];
rotationMatrix
[
0
]
=
vectorX
;
...
...
@@ -483,9 +484,9 @@ void AmoebaReferenceMultipoleForce::applyRotationMatrixToParticle( Multipo
rotationMatrix
[
2
]
=
vectorZ
;
RealVec
labDipole
;
for
(
int
ii
=
0
;
ii
<
3
;
ii
++
){
for
(
int
ii
=
0
;
ii
<
3
;
ii
++
)
{
labDipole
[
ii
]
=
particleI
.
dipole
[
0
]
*
rotationMatrix
[
0
][
ii
];
for
(
int
jj
=
1
;
jj
<
3
;
jj
++
){
for
(
int
jj
=
1
;
jj
<
3
;
jj
++
)
{
labDipole
[
ii
]
+=
particleI
.
dipole
[
jj
]
*
rotationMatrix
[
jj
][
ii
];
}
}
...
...
@@ -508,10 +509,10 @@ void AmoebaReferenceMultipoleForce::applyRotationMatrixToParticle( Multipo
mPole
[
2
][
1
]
=
particleI
.
quadrupole
[
QYZ
];
mPole
[
2
][
2
]
=
particleI
.
quadrupole
[
QZZ
];
for
(
int
ii
=
0
;
ii
<
3
;
ii
++
){
for
(
int
jj
=
ii
;
jj
<
3
;
jj
++
){
for
(
int
kk
=
0
;
kk
<
3
;
kk
++
){
for
(
int
mm
=
0
;
mm
<
3
;
mm
++
){
for
(
int
ii
=
0
;
ii
<
3
;
ii
++
)
{
for
(
int
jj
=
ii
;
jj
<
3
;
jj
++
)
{
for
(
int
kk
=
0
;
kk
<
3
;
kk
++
)
{
for
(
int
mm
=
0
;
mm
<
3
;
mm
++
)
{
rPole
[
ii
][
jj
]
+=
rotationMatrix
[
kk
][
ii
]
*
rotationMatrix
[
mm
][
jj
]
*
mPole
[
kk
][
mm
];
}
}
...
...
@@ -530,26 +531,26 @@ void AmoebaReferenceMultipoleForce::applyRotationMatrixToParticle( Multipo
}
void
AmoebaReferenceMultipoleForce
::
applyRotationMatrix
(
std
::
vector
<
MultipoleParticleData
>&
particleData
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
axisTypes
)
const
void
AmoebaReferenceMultipoleForce
::
applyRotationMatrix
(
vector
<
MultipoleParticleData
>&
particleData
,
const
vector
<
int
>&
multipoleAtomXs
,
const
vector
<
int
>&
multipoleAtomYs
,
const
vector
<
int
>&
multipoleAtomZs
,
const
vector
<
int
>&
axisTypes
)
const
{
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
if
(
multipoleAtomZs
[
ii
]
>=
0
&&
multipoleAtomXs
[
ii
]
>=
0
){
applyRotationMatrixToParticle
(
particleData
[
ii
],
particleData
[
multipoleAtomZs
[
ii
]],
particleData
[
multipoleAtomXs
[
ii
]],
multipoleAtomYs
[
ii
]
>
-
1
?
&
particleData
[
multipoleAtomYs
[
ii
]]
:
NULL
,
axisTypes
[
ii
]
);
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
if
(
multipoleAtomZs
[
ii
]
>=
0
&&
multipoleAtomXs
[
ii
]
>=
0
)
{
applyRotationMatrixToParticle
(
particleData
[
ii
],
particleData
[
multipoleAtomZs
[
ii
]],
particleData
[
multipoleAtomXs
[
ii
]],
multipoleAtomYs
[
ii
]
>
-
1
?
&
particleData
[
multipoleAtomYs
[
ii
]]
:
NULL
,
axisTypes
[
ii
]);
}
}
return
;
}
void
AmoebaReferenceMultipoleForce
::
getAndScaleInverseRs
(
RealOpenMM
dampI
,
RealOpenMM
dampJ
,
RealOpenMM
tholeI
,
RealOpenMM
tholeJ
,
RealOpenMM
r
,
std
::
vector
<
RealOpenMM
>&
rrI
)
const
void
AmoebaReferenceMultipoleForce
::
getAndScaleInverseRs
(
RealOpenMM
dampI
,
RealOpenMM
dampJ
,
RealOpenMM
tholeI
,
RealOpenMM
tholeJ
,
RealOpenMM
r
,
vector
<
RealOpenMM
>&
rrI
)
const
{
RealOpenMM
rI
=
1.0
/
r
;
...
...
@@ -557,45 +558,45 @@ void AmoebaReferenceMultipoleForce::getAndScaleInverseRs( RealOpenMM dampI, Real
rrI
[
0
]
=
rI
*
r2I
;
RealOpenMM
constantFactor
=
3.0
;
for
(
unsigned
int
ii
=
1
;
ii
<
rrI
.
size
();
ii
++
){
for
(
unsigned
int
ii
=
1
;
ii
<
rrI
.
size
();
ii
++
)
{
rrI
[
ii
]
=
constantFactor
*
rrI
[
ii
-
1
]
*
r2I
;
constantFactor
+=
2.0
;
}
RealOpenMM
damp
=
dampI
*
dampJ
;
if
(
damp
!=
0.0
){
if
(
damp
!=
0.0
)
{
RealOpenMM
pgamma
=
tholeI
<
tholeJ
?
tholeI
:
tholeJ
;
RealOpenMM
ratio
=
(
r
/
damp
);
ratio
=
ratio
*
ratio
*
ratio
;
damp
=
-
pgamma
*
ratio
;
if
(
damp
>
-
50.0
){
RealOpenMM
dampExp
=
EXP
(
damp
);
if
(
damp
>
-
50.0
)
{
RealOpenMM
dampExp
=
EXP
(
damp
);
rrI
[
0
]
*=
1.0
-
dampExp
;
rrI
[
1
]
*=
1.0
-
(
1.0
-
damp
)
*
dampExp
;
if
(
rrI
.
size
()
>
2
){
rrI
[
2
]
*=
1.0
-
(
1.0
-
damp
+
(
0.6
*
damp
*
damp
))
*
dampExp
;
rrI
[
1
]
*=
1.0
-
(
1.0
-
damp
)
*
dampExp
;
if
(
rrI
.
size
()
>
2
)
{
rrI
[
2
]
*=
1.0
-
(
1.0
-
damp
+
(
0.6
*
damp
*
damp
))
*
dampExp
;
}
}
}
return
;
}
void
AmoebaReferenceMultipoleForce
::
calculateFixedMultipoleFieldPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dScale
,
RealOpenMM
pScale
)
void
AmoebaReferenceMultipoleForce
::
calculateFixedMultipoleFieldPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dScale
,
RealOpenMM
pScale
)
{
if
(
particleI
.
particleIndex
==
particleJ
.
particleIndex
)
return
;
if
(
particleI
.
particleIndex
==
particleJ
.
particleIndex
)
return
;
RealVec
deltaR
=
particleJ
.
position
-
particleI
.
position
;
RealOpenMM
r
=
SQRT
(
deltaR
.
dot
(
deltaR
)
);
std
::
vector
<
RealOpenMM
>
rrI
(
3
);
RealOpenMM
r
=
SQRT
(
deltaR
.
dot
(
deltaR
)
);
vector
<
RealOpenMM
>
rrI
(
3
);
// get scaling factors, if needed
getAndScaleInverseRs
(
particleI
.
dampingFactor
,
particleJ
.
dampingFactor
,
particleI
.
thole
,
particleJ
.
thole
,
r
,
rrI
);
getAndScaleInverseRs
(
particleI
.
dampingFactor
,
particleJ
.
dampingFactor
,
particleI
.
thole
,
particleJ
.
thole
,
r
,
rrI
);
RealOpenMM
rr3
=
rrI
[
0
];
RealOpenMM
rr5
=
rrI
[
1
];
...
...
@@ -609,8 +610,8 @@ void AmoebaReferenceMultipoleForce::calculateFixedMultipoleFieldPairIxn( const M
qDotDelta
[
1
]
=
deltaR
[
0
]
*
particleJ
.
quadrupole
[
QXY
]
+
deltaR
[
1
]
*
particleJ
.
quadrupole
[
QYY
]
+
deltaR
[
2
]
*
particleJ
.
quadrupole
[
QYZ
];
qDotDelta
[
2
]
=
deltaR
[
0
]
*
particleJ
.
quadrupole
[
QXZ
]
+
deltaR
[
1
]
*
particleJ
.
quadrupole
[
QYZ
]
+
deltaR
[
2
]
*
particleJ
.
quadrupole
[
QZZ
];
RealOpenMM
dipoleDelta
=
particleJ
.
dipole
.
dot
(
deltaR
);
RealOpenMM
qdpoleDelta
=
qDotDelta
.
dot
(
deltaR
);
RealOpenMM
dipoleDelta
=
particleJ
.
dipole
.
dot
(
deltaR
);
RealOpenMM
qdpoleDelta
=
qDotDelta
.
dot
(
deltaR
);
RealOpenMM
factor
=
rr3
*
particleJ
.
charge
-
rr5
*
dipoleDelta
+
rr7
*
qdpoleDelta
;
RealVec
field
=
deltaR
*
factor
+
particleJ
.
dipole
*
rr3
-
qDotDelta
*
rr5_2
;
...
...
@@ -625,8 +626,8 @@ void AmoebaReferenceMultipoleForce::calculateFixedMultipoleFieldPairIxn( const M
qDotDelta
[
1
]
=
deltaR
[
0
]
*
particleI
.
quadrupole
[
QXY
]
+
deltaR
[
1
]
*
particleI
.
quadrupole
[
QYY
]
+
deltaR
[
2
]
*
particleI
.
quadrupole
[
QYZ
];
qDotDelta
[
2
]
=
deltaR
[
0
]
*
particleI
.
quadrupole
[
QXZ
]
+
deltaR
[
1
]
*
particleI
.
quadrupole
[
QYZ
]
+
deltaR
[
2
]
*
particleI
.
quadrupole
[
QZZ
];
dipoleDelta
=
particleI
.
dipole
.
dot
(
deltaR
);
qdpoleDelta
=
qDotDelta
.
dot
(
deltaR
);
dipoleDelta
=
particleI
.
dipole
.
dot
(
deltaR
);
qdpoleDelta
=
qDotDelta
.
dot
(
deltaR
);
factor
=
rr3
*
particleI
.
charge
+
rr5
*
dipoleDelta
+
rr7
*
qdpoleDelta
;
field
=
deltaR
*
factor
-
particleI
.
dipole
*
rr3
-
qDotDelta
*
rr5_2
;
...
...
@@ -637,7 +638,7 @@ void AmoebaReferenceMultipoleForce::calculateFixedMultipoleFieldPairIxn( const M
return
;
}
void
AmoebaReferenceMultipoleForce
::
calculateFixedMultipoleField
(
const
vector
<
MultipoleParticleData
>&
particleData
)
void
AmoebaReferenceMultipoleForce
::
calculateFixedMultipoleField
(
const
vector
<
MultipoleParticleData
>&
particleData
)
{
// calculate fixed multipole fields
...
...
@@ -645,33 +646,33 @@ void AmoebaReferenceMultipoleForce::calculateFixedMultipoleField( const vector<M
// loop includes diagonal term ii == jj for GK ixn; other calculateFixedMultipoleFieldPairIxn() methods
// skip calculations for this case
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
for
(
unsigned
int
jj
=
ii
;
jj
<
_numParticles
;
jj
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
for
(
unsigned
int
jj
=
ii
;
jj
<
_numParticles
;
jj
++
)
{
// if site jj is less than max covalent scaling index then get/apply scaling constants
// otherwise add unmodified field and fieldPolar to particle fields
RealOpenMM
dScale
,
pScale
;
if
(
jj
<=
_maxScaleIndex
[
ii
]
){
getDScaleAndPScale
(
ii
,
jj
,
dScale
,
pScale
);
if
(
jj
<=
_maxScaleIndex
[
ii
])
{
getDScaleAndPScale
(
ii
,
jj
,
dScale
,
pScale
);
}
else
{
dScale
=
pScale
=
1.0
;
}
calculateFixedMultipoleFieldPairIxn
(
particleData
[
ii
],
particleData
[
jj
],
dScale
,
pScale
);
calculateFixedMultipoleFieldPairIxn
(
particleData
[
ii
],
particleData
[
jj
],
dScale
,
pScale
);
}
}
return
;
}
void
AmoebaReferenceMultipoleForce
::
initializeInducedDipoles
(
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
void
AmoebaReferenceMultipoleForce
::
initializeInducedDipoles
(
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
{
// initialize inducedDipoles
_inducedDipole
.
resize
(
_numParticles
);
_inducedDipolePolar
.
resize
(
_numParticles
);
_inducedDipole
.
resize
(
_numParticles
);
_inducedDipolePolar
.
resize
(
_numParticles
);
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
_inducedDipole
[
ii
]
=
_fixedMultipoleField
[
ii
];
_inducedDipolePolar
[
ii
]
=
_fixedMultipoleFieldPolar
[
ii
];
}
...
...
@@ -679,81 +680,78 @@ void AmoebaReferenceMultipoleForce::initializeInducedDipoles( std::vector<Update
return
;
}
void
AmoebaReferenceMultipoleForce
::
calculateInducedDipolePairIxn
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
RealOpenMM
rr3
,
RealOpenMM
rr5
,
const
RealVec
&
deltaR
,
const
std
::
vector
<
RealVec
>&
inducedDipole
,
std
::
vector
<
RealVec
>&
field
)
const
void
AmoebaReferenceMultipoleForce
::
calculateInducedDipolePairIxn
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
RealOpenMM
rr3
,
RealOpenMM
rr5
,
const
RealVec
&
deltaR
,
const
vector
<
RealVec
>&
inducedDipole
,
vector
<
RealVec
>&
field
)
const
{
RealOpenMM
dDotDelta
=
rr5
*
(
inducedDipole
[
particleJ
].
dot
(
deltaR
)
);
RealOpenMM
dDotDelta
=
rr5
*
(
inducedDipole
[
particleJ
].
dot
(
deltaR
)
);
field
[
particleI
]
+=
inducedDipole
[
particleJ
]
*
rr3
+
deltaR
*
dDotDelta
;
dDotDelta
=
rr5
*
(
inducedDipole
[
particleI
].
dot
(
deltaR
)
);
dDotDelta
=
rr5
*
(
inducedDipole
[
particleI
].
dot
(
deltaR
)
);
field
[
particleJ
]
+=
inducedDipole
[
particleI
]
*
rr3
+
deltaR
*
dDotDelta
;
return
;
}
void
AmoebaReferenceMultipoleForce
::
calculateInducedDipolePairIxns
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
void
AmoebaReferenceMultipoleForce
::
calculateInducedDipolePairIxns
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
{
if
(
particleI
.
particleIndex
==
particleJ
.
particleIndex
)
return
;
if
(
particleI
.
particleIndex
==
particleJ
.
particleIndex
)
return
;
RealVec
deltaR
=
particleJ
.
position
-
particleI
.
position
;
RealOpenMM
r
=
SQRT
(
deltaR
.
dot
(
deltaR
)
);
std
::
vector
<
RealOpenMM
>
rrI
(
2
);
RealOpenMM
r
=
SQRT
(
deltaR
.
dot
(
deltaR
)
);
vector
<
RealOpenMM
>
rrI
(
2
);
getAndScaleInverseRs
(
particleI
.
dampingFactor
,
particleJ
.
dampingFactor
,
particleI
.
thole
,
particleJ
.
thole
,
r
,
rrI
);
getAndScaleInverseRs
(
particleI
.
dampingFactor
,
particleJ
.
dampingFactor
,
particleI
.
thole
,
particleJ
.
thole
,
r
,
rrI
);
RealOpenMM
rr3
=
-
rrI
[
0
];
RealOpenMM
rr5
=
rrI
[
1
];
for
(
unsigned
int
ii
=
0
;
ii
<
updateInducedDipoleFields
.
size
();
ii
++
){
calculateInducedDipolePairIxn
(
particleI
.
particleIndex
,
particleJ
.
particleIndex
,
rr3
,
rr5
,
deltaR
,
*
(
updateInducedDipoleFields
[
ii
].
inducedDipoles
)
,
updateInducedDipoleFields
[
ii
].
inducedDipoleField
);
for
(
unsigned
int
ii
=
0
;
ii
<
updateInducedDipoleFields
.
size
();
ii
++
)
{
calculateInducedDipolePairIxn
(
particleI
.
particleIndex
,
particleJ
.
particleIndex
,
rr3
,
rr5
,
deltaR
,
*
updateInducedDipoleFields
[
ii
].
inducedDipoles
,
updateInducedDipoleFields
[
ii
].
inducedDipoleField
);
}
return
;
}
void
AmoebaReferenceMultipoleForce
::
calculateInducedDipoleFields
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
{
void
AmoebaReferenceMultipoleForce
::
calculateInducedDipoleFields
(
const
vector
<
MultipoleParticleData
>&
particleData
,
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
{
// Initialize the fields to zero.
RealVec
zeroVec
(
0.0
,
0.0
,
0.0
);
for
(
unsigned
int
ii
=
0
;
ii
<
updateInducedDipoleFields
.
size
();
ii
++
)
std
::
fill
(
updateInducedDipoleFields
[
ii
].
inducedDipoleField
.
begin
(),
updateInducedDipoleFields
[
ii
].
inducedDipoleField
.
end
(),
zeroVec
);
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
){
for
(
unsigned
int
jj
=
ii
;
jj
<
particleData
.
size
();
jj
++
){
calculateInducedDipolePairIxns
(
particleData
[
ii
],
particleData
[
jj
],
updateInducedDipoleFields
);
}
}
// Add fields from all induced dipoles.
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
)
for
(
unsigned
int
jj
=
ii
;
jj
<
particleData
.
size
();
jj
++
)
calculateInducedDipolePairIxns
(
particleData
[
ii
],
particleData
[
jj
],
updateInducedDipoleFields
);
return
;
}
RealOpenMM
AmoebaReferenceMultipoleForce
::
updateInducedDipoleFields
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
RealOpenMM
AmoebaReferenceMultipoleForce
::
updateInducedDipoleFields
(
const
vector
<
MultipoleParticleData
>&
particleData
,
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
{
// Calculate the fields coming from induced dipoles.
calculateInducedDipoleFields
(
particleData
,
updateInducedDipoleFields
);
// (1) zero fields
// (2) calculate induced dipole pair ixns
// (3) update induced dipoles based on pair ixns and calculate/return convergence factor, maxEpsilon
RealVec
zeroVec
(
0.0
,
0.0
,
0.0
);
for
(
unsigned
int
ii
=
0
;
ii
<
updateInducedDipoleFields
.
size
();
ii
++
){
std
::
fill
(
updateInducedDipoleFields
[
ii
].
inducedDipoleField
.
begin
(),
updateInducedDipoleFields
[
ii
].
inducedDipoleField
.
end
(),
zeroVec
);
}
calculateInducedDipoleFields
(
particleData
,
updateInducedDipoleFields
);
// Update the induced dipoles and calculate the convergence factor, maxEpsilon
RealOpenMM
maxEpsilon
=
0.0
;
for
(
unsigned
int
kk
=
0
;
kk
<
updateInducedDipoleFields
.
size
();
kk
++
){
RealOpenMM
epsilon
=
updateInducedDipole
(
particleData
,
*
(
updateInducedDipoleFields
[
kk
].
fixedMultipoleField
)
,
updateInducedDipoleFields
[
kk
].
inducedDipoleField
,
*
(
updateInducedDipoleFields
[
kk
].
inducedDipoles
)
)
;
for
(
unsigned
int
kk
=
0
;
kk
<
updateInducedDipoleFields
.
size
();
kk
++
)
{
RealOpenMM
epsilon
=
updateInducedDipole
(
particleData
,
*
updateInducedDipoleFields
[
kk
].
fixedMultipoleField
,
updateInducedDipoleFields
[
kk
].
inducedDipoleField
,
*
updateInducedDipoleFields
[
kk
].
inducedDipoles
);
maxEpsilon
=
epsilon
>
maxEpsilon
?
epsilon
:
maxEpsilon
;
}
...
...
@@ -761,29 +759,29 @@ RealOpenMM AmoebaReferenceMultipoleForce::updateInducedDipoleFields( const std::
return
maxEpsilon
;
}
RealOpenMM
AmoebaReferenceMultipoleForce
::
updateInducedDipole
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
const
std
::
vector
<
RealVec
>&
fixedMultipoleField
,
const
std
::
vector
<
RealVec
>&
inducedDipoleField
,
std
::
vector
<
RealVec
>&
inducedDipole
)
RealOpenMM
AmoebaReferenceMultipoleForce
::
updateInducedDipole
(
const
vector
<
MultipoleParticleData
>&
particleData
,
const
vector
<
RealVec
>&
fixedMultipoleField
,
const
vector
<
RealVec
>&
inducedDipoleField
,
vector
<
RealVec
>&
inducedDipole
)
{
RealOpenMM
epsilon
=
0.0
;
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
)
{
RealVec
oldValue
=
inducedDipole
[
ii
];
RealVec
newValue
=
fixedMultipoleField
[
ii
]
+
inducedDipoleField
[
ii
]
*
particleData
[
ii
].
polarity
;
RealVec
delta
=
newValue
-
oldValue
;
inducedDipole
[
ii
]
=
oldValue
+
delta
*
_polarSOR
;
epsilon
+=
delta
.
dot
(
delta
);
epsilon
+=
delta
.
dot
(
delta
);
}
return
epsilon
;
}
void
AmoebaReferenceMultipoleForce
::
convergeInduceDipoles
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleField
)
void
AmoebaReferenceMultipoleForce
::
convergeInduceDipoles
BySOR
(
const
vector
<
MultipoleParticleData
>&
particleData
,
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleField
)
{
bool
done
=
false
;
setMutualInducedDipoleConverged
(
false
);
setMutualInducedDipoleConverged
(
false
);
int
iteration
=
0
;
RealOpenMM
currentEpsilon
=
1.0e+50
;
...
...
@@ -791,70 +789,176 @@ void AmoebaReferenceMultipoleForce::convergeInduceDipoles( const std::vector<Mul
// (2) iterations == max iterations or
// (3) convergence factor (spsilon) increases
while
(
!
done
){
while
(
!
done
)
{
RealOpenMM
epsilon
=
updateInducedDipoleFields
(
particleData
,
updateInducedDipoleField
);
epsilon
=
_polarSOR
*
_debye
*
SQRT
(
epsilon
/
(
static_cast
<
RealOpenMM
>
(
_numParticles
)
)
);
RealOpenMM
epsilon
=
updateInducedDipoleFields
(
particleData
,
updateInducedDipoleField
);
epsilon
=
_polarSOR
*
_debye
*
SQRT
(
epsilon
/
(
static_cast
<
RealOpenMM
>
(
_numParticles
)
)
);
if
(
epsilon
<
getMutualInducedDipoleTargetEpsilon
()
){
setMutualInducedDipoleConverged
(
true
);
if
(
epsilon
<
getMutualInducedDipoleTargetEpsilon
())
{
setMutualInducedDipoleConverged
(
true
);
done
=
true
;
}
else
if
(
currentEpsilon
<
epsilon
||
iteration
>=
getMaximumMutualInducedDipoleIterations
()
){
}
else
if
(
currentEpsilon
<
epsilon
||
iteration
>=
getMaximumMutualInducedDipoleIterations
())
{
done
=
true
;
}
currentEpsilon
=
epsilon
;
iteration
++
;
}
setMutualInducedDipoleEpsilon
(
currentEpsilon
);
setMutualInducedDipoleIterations
(
iteration
);
setMutualInducedDipoleEpsilon
(
currentEpsilon
);
setMutualInducedDipoleIterations
(
iteration
);
return
;
}
void
AmoebaReferenceMultipoleForce
::
calculateInducedDipoles
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
)
void
AmoebaReferenceMultipoleForce
::
convergeInduceDipolesByDIIS
(
const
vector
<
MultipoleParticleData
>&
particleData
,
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleField
)
{
int
numFields
=
updateInducedDipoleField
.
size
();
vector
<
vector
<
vector
<
RealVec
>
>
>
prevDipoles
(
numFields
);
vector
<
vector
<
RealVec
>
>
prevErrors
;
setMutualInducedDipoleConverged
(
false
);
int
maxPrevious
=
20
;
for
(
int
iteration
=
0
;
;
iteration
++
)
{
// Compute the field from the induced dipoles.
calculateInducedDipoleFields
(
particleData
,
updateInducedDipoleField
);
// Record the current dipoles and the errors in them.
RealOpenMM
maxEpsilon
=
0
;
prevErrors
.
push_back
(
vector
<
RealVec
>
());
prevErrors
.
back
().
resize
(
_numParticles
);
for
(
int
k
=
0
;
k
<
numFields
;
k
++
)
{
UpdateInducedDipoleFieldStruct
&
field
=
updateInducedDipoleField
[
k
];
prevDipoles
[
k
].
push_back
(
vector
<
RealVec
>
());
prevDipoles
[
k
].
back
().
resize
(
_numParticles
);
RealOpenMM
epsilon
=
0
;
for
(
int
i
=
0
;
i
<
_numParticles
;
i
++
)
{
prevDipoles
[
k
].
back
()[
i
]
=
(
*
field
.
inducedDipoles
)[
i
];
RealVec
newDipole
=
(
*
field
.
fixedMultipoleField
)[
i
]
+
field
.
inducedDipoleField
[
i
]
*
particleData
[
i
].
polarity
;
RealVec
error
=
newDipole
-
(
*
field
.
inducedDipoles
)[
i
];
prevDipoles
[
k
].
back
()[
i
]
=
newDipole
;
if
(
k
==
0
)
prevErrors
.
back
()[
i
]
=
error
;
epsilon
+=
error
.
dot
(
error
);
}
if
(
epsilon
>
maxEpsilon
)
maxEpsilon
=
epsilon
;
}
maxEpsilon
=
_debye
*
SQRT
(
maxEpsilon
/
_numParticles
);
// Decide whether to stop or continue iterating.
if
(
maxEpsilon
<
getMutualInducedDipoleTargetEpsilon
())
setMutualInducedDipoleConverged
(
true
);
if
(
maxEpsilon
<
getMutualInducedDipoleTargetEpsilon
()
||
iteration
==
getMaximumMutualInducedDipoleIterations
())
{
setMutualInducedDipoleEpsilon
(
maxEpsilon
);
setMutualInducedDipoleIterations
(
iteration
);
return
;
}
// Select the new dipoles.
if
(
prevErrors
.
size
()
>
maxPrevious
)
{
prevErrors
.
erase
(
prevErrors
.
begin
());
for
(
int
k
=
0
;
k
<
numFields
;
k
++
)
prevDipoles
[
k
].
erase
(
prevDipoles
[
k
].
begin
());
}
int
numPrevious
=
prevErrors
.
size
();
vector
<
RealOpenMM
>
coefficients
(
numPrevious
);
computeDIISCoefficients
(
prevErrors
,
coefficients
);
for
(
int
k
=
0
;
k
<
numFields
;
k
++
)
{
UpdateInducedDipoleFieldStruct
&
field
=
updateInducedDipoleField
[
k
];
for
(
int
i
=
0
;
i
<
_numParticles
;
i
++
)
{
RealVec
dipole
(
0.0
,
0.0
,
0.0
);
for
(
int
j
=
0
;
j
<
numPrevious
;
j
++
)
dipole
+=
prevDipoles
[
k
][
j
][
i
]
*
coefficients
[
j
];
(
*
field
.
inducedDipoles
)[
i
]
=
dipole
;
}
}
}
}
void
AmoebaReferenceMultipoleForce
::
computeDIISCoefficients
(
const
vector
<
vector
<
RealVec
>
>&
prevErrors
,
vector
<
RealOpenMM
>&
coefficients
)
const
{
int
steps
=
coefficients
.
size
();
if
(
steps
==
1
)
{
coefficients
[
0
]
=
1
;
return
;
}
// Create the DIIS matrix.
int
rank
=
steps
+
1
;
Array2D
<
double
>
b
(
rank
,
rank
);
b
[
0
][
0
]
=
0
;
for
(
int
i
=
0
;
i
<
steps
;
i
++
)
b
[
i
+
1
][
0
]
=
b
[
0
][
i
+
1
]
=
-
1
;
for
(
int
i
=
0
;
i
<
steps
;
i
++
)
for
(
int
j
=
i
;
j
<
steps
;
j
++
)
{
double
sum
=
0
;
for
(
int
k
=
0
;
k
<
_numParticles
;
k
++
)
sum
+=
prevErrors
[
i
][
k
].
dot
(
prevErrors
[
j
][
k
]);
b
[
i
+
1
][
j
+
1
]
=
b
[
j
+
1
][
i
+
1
]
=
sum
;
}
// Solve using SVD. Since the right hand side is (-1, 0, 0, 0, ...), this is simpler than the general case.
JAMA
::
SVD
<
double
>
svd
(
b
);
Array2D
<
double
>
u
,
v
;
svd
.
getU
(
u
);
svd
.
getV
(
v
);
Array1D
<
double
>
s
;
svd
.
getSingularValues
(
s
);
int
effectiveRank
=
svd
.
rank
();
for
(
int
i
=
1
;
i
<
rank
;
i
++
)
{
double
d
=
0
;
for
(
int
j
=
0
;
j
<
effectiveRank
;
j
++
)
d
-=
u
[
0
][
j
]
*
v
[
i
][
j
]
/
s
[
j
];
coefficients
[
i
-
1
]
=
d
;
}
}
void
AmoebaReferenceMultipoleForce
::
calculateInducedDipoles
(
const
vector
<
MultipoleParticleData
>&
particleData
)
{
// calculate fixed electric fields
zeroFixedMultipoleFields
();
calculateFixedMultipoleField
(
particleData
);
calculateFixedMultipoleField
(
particleData
);
// initialize inducedDipoles
// if polarization type is 'Direct', then return after initializing; otherwise
// converge induced dipoles.
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
_fixedMultipoleField
[
ii
]
*=
particleData
[
ii
].
polarity
;
_fixedMultipoleFieldPolar
[
ii
]
*=
particleData
[
ii
].
polarity
;
}
_inducedDipole
.
resize
(
_numParticles
);
_inducedDipolePolar
.
resize
(
_numParticles
);
std
::
vector
<
UpdateInducedDipoleFieldStruct
>
updateInducedDipoleField
;
updateInducedDipoleField
.
push_back
(
UpdateInducedDipoleFieldStruct
(
&
_fixedMultipoleField
,
&
_inducedDipole
)
);
updateInducedDipoleField
.
push_back
(
UpdateInducedDipoleFieldStruct
(
&
_fixedMultipoleFieldPolar
,
&
_inducedDipolePolar
)
);
_inducedDipole
.
resize
(
_numParticles
);
_inducedDipolePolar
.
resize
(
_numParticles
);
vector
<
UpdateInducedDipoleFieldStruct
>
updateInducedDipoleField
;
updateInducedDipoleField
.
push_back
(
UpdateInducedDipoleFieldStruct
(
_fixedMultipoleField
,
_inducedDipole
)
);
updateInducedDipoleField
.
push_back
(
UpdateInducedDipoleFieldStruct
(
_fixedMultipoleFieldPolar
,
_inducedDipolePolar
)
);
initializeInducedDipoles
(
updateInducedDipoleField
);
initializeInducedDipoles
(
updateInducedDipoleField
);
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Direct
){
setMutualInducedDipoleConverged
(
true
);
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Direct
)
{
setMutualInducedDipoleConverged
(
true
);
return
;
}
// UpdateInducedDipoleFieldStruct contains induced dipole, fixed multipole fields and fields
// due to other induced dipoles at each site
convergeInduceDipoles
(
particleData
,
updateInducedDipoleField
);
convergeInduceDipoles
ByDIIS
(
particleData
,
updateInducedDipoleField
);
return
;
}
RealOpenMM
AmoebaReferenceMultipoleForce
::
calculateElectrostaticPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleK
,
const
std
::
vector
<
RealOpenMM
>&
scalingFactors
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torque
)
const
RealOpenMM
AmoebaReferenceMultipoleForce
::
calculateElectrostaticPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleK
,
const
vector
<
RealOpenMM
>&
scalingFactors
,
vector
<
RealVec
>&
forces
,
vector
<
RealVec
>&
torque
)
const
{
RealOpenMM
temp3
,
temp5
,
temp7
;
RealOpenMM
gl
[
9
],
gli
[
7
],
glip
[
7
];
...
...
@@ -865,7 +969,7 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateElectrostaticPairIxn( const M
unsigned
int
kIndex
=
particleK
.
particleIndex
;
RealVec
delta
=
particleK
.
position
-
particleI
.
position
;
RealOpenMM
r2
=
delta
.
dot
(
delta
);
RealOpenMM
r2
=
delta
.
dot
(
delta
);
// set conversion factor, cutoff and switching coefficients
...
...
@@ -890,16 +994,16 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateElectrostaticPairIxn( const M
RealOpenMM
scale5
=
1.0
;
RealOpenMM
scale7
=
1.0
;
RealVec
ddsc3
(
0.0
,
0.0
,
0.0
);
RealVec
ddsc5
(
0.0
,
0.0
,
0.0
);
RealVec
ddsc7
(
0.0
,
0.0
,
0.0
);
RealVec
ddsc3
(
0.0
,
0.0
,
0.0
);
RealVec
ddsc5
(
0.0
,
0.0
,
0.0
);
RealVec
ddsc7
(
0.0
,
0.0
,
0.0
);
RealOpenMM
damp
=
particleI
.
dampingFactor
*
particleK
.
dampingFactor
;
if
(
damp
!=
0.0
){
if
(
damp
!=
0.0
)
{
RealOpenMM
pgamma
=
particleI
.
thole
<
particleK
.
thole
?
particleI
.
thole
:
particleK
.
thole
;
RealOpenMM
ratio
=
(
r
/
damp
);
damp
=
-
pgamma
*
ratio
*
ratio
*
ratio
;
if
(
damp
>
-
50.0
){
if
(
damp
>
-
50.0
)
{
RealOpenMM
expdamp
=
EXP
(
damp
);
scale3
=
1.0
-
expdamp
;
scale5
=
1.0
-
(
1.0
-
damp
)
*
expdamp
;
...
...
@@ -928,13 +1032,13 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateElectrostaticPairIxn( const M
// construct necessary auxiliary vectors
RealVec
dixdk
=
particleI
.
dipole
.
cross
(
particleK
.
dipole
);
RealVec
dixuk
=
particleI
.
dipole
.
cross
(
_inducedDipole
[
kIndex
]
);
RealVec
dkxui
=
particleK
.
dipole
.
cross
(
_inducedDipole
[
iIndex
]
);
RealVec
dixukp
=
particleI
.
dipole
.
cross
(
_inducedDipolePolar
[
kIndex
]
);
RealVec
dkxuip
=
particleK
.
dipole
.
cross
(
_inducedDipolePolar
[
iIndex
]
);
RealVec
dixr
=
particleI
.
dipole
.
cross
(
delta
);
RealVec
dkxr
=
particleK
.
dipole
.
cross
(
delta
);
RealVec
dixdk
=
particleI
.
dipole
.
cross
(
particleK
.
dipole
);
RealVec
dixuk
=
particleI
.
dipole
.
cross
(
_inducedDipole
[
kIndex
]);
RealVec
dkxui
=
particleK
.
dipole
.
cross
(
_inducedDipole
[
iIndex
]);
RealVec
dixukp
=
particleI
.
dipole
.
cross
(
_inducedDipolePolar
[
kIndex
]);
RealVec
dkxuip
=
particleK
.
dipole
.
cross
(
_inducedDipolePolar
[
iIndex
]);
RealVec
dixr
=
particleI
.
dipole
.
cross
(
delta
);
RealVec
dkxr
=
particleK
.
dipole
.
cross
(
delta
);
RealVec
qir
;
qir
[
0
]
=
particleI
.
quadrupole
[
QXX
]
*
delta
[
0
]
+
particleI
.
quadrupole
[
QXY
]
*
delta
[
1
]
+
particleI
.
quadrupole
[
QXZ
]
*
delta
[
2
];
...
...
@@ -978,11 +1082,11 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateElectrostaticPairIxn( const M
particleI
.
quadrupole
[
QYY
]
*
particleK
.
quadrupole
[
QXY
]
-
particleI
.
quadrupole
[
QYZ
]
*
particleK
.
quadrupole
[
QXZ
];
RealVec
rxqir
=
delta
.
cross
(
qir
);
RealVec
rxqkr
=
delta
.
cross
(
qkr
);
RealVec
rxqikr
=
delta
.
cross
(
qiqkr
);
RealVec
rxqkir
=
delta
.
cross
(
qkqir
);
RealVec
qkrxqir
=
qkr
.
cross
(
qir
);
RealVec
rxqir
=
delta
.
cross
(
qir
);
RealVec
rxqkr
=
delta
.
cross
(
qkr
);
RealVec
rxqikr
=
delta
.
cross
(
qiqkr
);
RealVec
rxqkir
=
delta
.
cross
(
qkqir
);
RealVec
qkrxqir
=
qkr
.
cross
(
qir
);
RealVec
qidk
,
qkdi
;
qidk
[
0
]
=
particleI
.
quadrupole
[
QXX
]
*
particleK
.
dipole
[
0
]
+
particleI
.
quadrupole
[
QXY
]
*
particleK
.
dipole
[
1
]
+
particleI
.
quadrupole
[
QXZ
]
*
particleK
.
dipole
[
2
];
...
...
@@ -1011,29 +1115,29 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateElectrostaticPairIxn( const M
qkuip
[
1
]
=
particleK
.
quadrupole
[
QXY
]
*
_inducedDipolePolar
[
iIndex
][
0
]
+
particleK
.
quadrupole
[
QYY
]
*
_inducedDipolePolar
[
iIndex
][
1
]
+
particleK
.
quadrupole
[
QYZ
]
*
_inducedDipolePolar
[
iIndex
][
2
];
qkuip
[
2
]
=
particleK
.
quadrupole
[
QXZ
]
*
_inducedDipolePolar
[
iIndex
][
0
]
+
particleK
.
quadrupole
[
QYZ
]
*
_inducedDipolePolar
[
iIndex
][
1
]
+
particleK
.
quadrupole
[
QZZ
]
*
_inducedDipolePolar
[
iIndex
][
2
];
RealVec
dixqkr
=
particleI
.
dipole
.
cross
(
qkr
);
RealVec
dkxqir
=
particleK
.
dipole
.
cross
(
qir
);
RealVec
uixqkr
=
_inducedDipole
[
iIndex
].
cross
(
qkr
);
RealVec
ukxqir
=
_inducedDipole
[
kIndex
].
cross
(
qir
);
RealVec
uixqkrp
=
_inducedDipolePolar
[
iIndex
].
cross
(
qkr
);
RealVec
ukxqirp
=
_inducedDipolePolar
[
kIndex
].
cross
(
qir
);
RealVec
rxqidk
=
delta
.
cross
(
qidk
);
RealVec
rxqkdi
=
delta
.
cross
(
qkdi
);
RealVec
rxqiuk
=
delta
.
cross
(
qiuk
);
RealVec
rxqkui
=
delta
.
cross
(
qkui
);
RealVec
rxqiukp
=
delta
.
cross
(
qiukp
);
RealVec
rxqkuip
=
delta
.
cross
(
qkuip
);
RealVec
dixqkr
=
particleI
.
dipole
.
cross
(
qkr
);
RealVec
dkxqir
=
particleK
.
dipole
.
cross
(
qir
);
RealVec
uixqkr
=
_inducedDipole
[
iIndex
].
cross
(
qkr
);
RealVec
ukxqir
=
_inducedDipole
[
kIndex
].
cross
(
qir
);
RealVec
uixqkrp
=
_inducedDipolePolar
[
iIndex
].
cross
(
qkr
);
RealVec
ukxqirp
=
_inducedDipolePolar
[
kIndex
].
cross
(
qir
);
RealVec
rxqidk
=
delta
.
cross
(
qidk
);
RealVec
rxqkdi
=
delta
.
cross
(
qkdi
);
RealVec
rxqiuk
=
delta
.
cross
(
qiuk
);
RealVec
rxqkui
=
delta
.
cross
(
qkui
);
RealVec
rxqiukp
=
delta
.
cross
(
qiukp
);
RealVec
rxqkuip
=
delta
.
cross
(
qkuip
);
// calculate scalar products for permanent components
sc
[
1
]
=
particleI
.
dipole
.
dot
(
particleK
.
dipole
);
sc
[
2
]
=
particleI
.
dipole
.
dot
(
delta
);
sc
[
3
]
=
particleK
.
dipole
.
dot
(
delta
);
sc
[
4
]
=
qir
.
dot
(
delta
);
sc
[
5
]
=
qkr
.
dot
(
delta
);
sc
[
6
]
=
qir
.
dot
(
particleK
.
dipole
);
sc
[
7
]
=
qkr
.
dot
(
particleI
.
dipole
);
sc
[
8
]
=
qir
.
dot
(
qkr
);
sc
[
1
]
=
particleI
.
dipole
.
dot
(
particleK
.
dipole
);
sc
[
2
]
=
particleI
.
dipole
.
dot
(
delta
);
sc
[
3
]
=
particleK
.
dipole
.
dot
(
delta
);
sc
[
4
]
=
qir
.
dot
(
delta
);
sc
[
5
]
=
qkr
.
dot
(
delta
);
sc
[
6
]
=
qir
.
dot
(
particleK
.
dipole
);
sc
[
7
]
=
qkr
.
dot
(
particleI
.
dipole
);
sc
[
8
]
=
qir
.
dot
(
qkr
);
sc
[
9
]
=
particleI
.
quadrupole
[
QXX
]
*
particleK
.
quadrupole
[
QXX
]
+
particleI
.
quadrupole
[
QXY
]
*
particleK
.
quadrupole
[
QXY
]
+
particleI
.
quadrupole
[
QXZ
]
*
particleK
.
quadrupole
[
QXZ
]
+
particleI
.
quadrupole
[
QXY
]
*
particleK
.
quadrupole
[
QXY
]
+
particleI
.
quadrupole
[
QYY
]
*
particleK
.
quadrupole
[
QYY
]
+
particleI
.
quadrupole
[
QYZ
]
*
particleK
.
quadrupole
[
QYZ
]
+
particleI
.
quadrupole
[
QXZ
]
*
particleK
.
quadrupole
[
QXZ
]
+
particleI
.
quadrupole
[
QYZ
]
*
particleK
.
quadrupole
[
QYZ
]
+
particleI
.
quadrupole
[
QZZ
]
*
particleK
.
quadrupole
[
QZZ
];
...
...
@@ -1115,10 +1219,10 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateElectrostaticPairIxn( const M
// get the induced force components
RealVec
ftm2i
=
delta
*
gfi
[
0
]
+
qir
*
gfi
[
4
]
+
qkr
*
gfi
[
5
];
ftm2i
+=
(
ftm2i
+=
(
(
_inducedDipole
[
iIndex
]
*
psc3
+
_inducedDipolePolar
[
iIndex
]
*
dsc3
)
*
(
-
rr3
*
particleK
.
charge
)
+
(
_inducedDipole
[
iIndex
]
*
psc5
+
_inducedDipolePolar
[
iIndex
]
*
dsc5
)
*
(
rr5
*
sc
[
3
])
+
(
_inducedDipole
[
iIndex
]
*
psc5
+
_inducedDipolePolar
[
iIndex
]
*
dsc5
)
*
(
rr5
*
sc
[
3
])
+
(
_inducedDipole
[
iIndex
]
*
psc7
+
_inducedDipolePolar
[
iIndex
]
*
dsc7
)
*
(
-
rr7
*
sc
[
5
])
+
(
_inducedDipole
[
kIndex
]
*
psc3
+
_inducedDipolePolar
[
kIndex
]
*
dsc3
)
*
(
rr3
*
particleI
.
charge
)
+
(
_inducedDipole
[
kIndex
]
*
psc5
+
_inducedDipolePolar
[
kIndex
]
*
dsc5
)
*
(
rr5
*
sc
[
2
])
+
...
...
@@ -1147,11 +1251,11 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateElectrostaticPairIxn( const M
// modify induced force for partially excluded interactions
ftm2i
-=
(
fridmp
+
findmp
)
*
0.5
;
ftm2i
-=
(
fridmp
+
findmp
)
*
0.5
;
// correction to convert mutual to direct polarization force
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Direct
){
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Direct
)
{
RealOpenMM
gfd
=
(
rr5
*
scip
[
1
]
*
scale3i
-
rr7
*
(
scip
[
2
]
*
sci
[
3
]
+
sci
[
2
]
*
scip
[
3
])
*
scale5i
);
temp5
=
rr5
*
scale5i
;
...
...
@@ -1161,7 +1265,7 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateElectrostaticPairIxn( const M
_inducedDipolePolar
[
kIndex
]
*
sci
[
2
]
+
_inducedDipole
[
kIndex
]
*
scip
[
2
])
*
temp5
;
ftm2i
+=
(
findmp
-
fdir
)
*
0.5
;
ftm2i
+=
(
findmp
-
fdir
)
*
0.5
;
}
// intermediate terms for induced torque on multipoles
...
...
@@ -1203,18 +1307,18 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateElectrostaticPairIxn( const M
forces
[
iIndex
]
-=
force
;
forces
[
kIndex
]
+=
force
;
torque
[
iIndex
]
+=
(
ttm2
*
scalingFactors
[
M_SCALE
]
+
ttm2i
)
*
f
;
torque
[
kIndex
]
+=
(
ttm3
*
scalingFactors
[
M_SCALE
]
+
ttm3i
)
*
f
;
torque
[
iIndex
]
+=
(
ttm2
*
scalingFactors
[
M_SCALE
]
+
ttm2i
)
*
f
;
torque
[
kIndex
]
+=
(
ttm3
*
scalingFactors
[
M_SCALE
]
+
ttm3i
)
*
f
;
return
energy
;
}
void
AmoebaReferenceMultipoleForce
::
mapTorqueToForceForParticle
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleU
,
const
MultipoleParticleData
&
particleV
,
MultipoleParticleData
*
particleW
,
int
axisType
,
const
Vec3
&
torque
,
std
::
vector
<
RealVec
>&
forces
)
const
void
AmoebaReferenceMultipoleForce
::
mapTorqueToForceForParticle
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleU
,
const
MultipoleParticleData
&
particleV
,
MultipoleParticleData
*
particleW
,
int
axisType
,
const
Vec3
&
torque
,
vector
<
RealVec
>&
forces
)
const
{
static
const
int
U
=
0
;
...
...
@@ -1245,54 +1349,54 @@ void AmoebaReferenceMultipoleForce::mapTorqueToForceForParticle( const Multipole
// compute the vector between the atoms and 1/sqrt(d2), d2 is distance between
// this atom and the axis atom
if
(
axisType
==
AmoebaMultipoleForce
::
NoAxisType
){
if
(
axisType
==
AmoebaMultipoleForce
::
NoAxisType
)
{
return
;
}
RealVec
vectorU
=
particleU
.
position
-
particleI
.
position
;
norms
[
U
]
=
normalizeRealVec
(
vectorU
);
norms
[
U
]
=
normalizeRealVec
(
vectorU
);
RealVec
vectorV
=
particleV
.
position
-
particleI
.
position
;
norms
[
V
]
=
normalizeRealVec
(
vectorV
);
norms
[
V
]
=
normalizeRealVec
(
vectorV
);
RealVec
vectorW
;
if
(
particleW
&&
(
axisType
==
AmoebaMultipoleForce
::
ZBisect
||
axisType
==
AmoebaMultipoleForce
::
ThreeFold
)
){
if
(
particleW
&&
(
axisType
==
AmoebaMultipoleForce
::
ZBisect
||
axisType
==
AmoebaMultipoleForce
::
ThreeFold
))
{
vectorW
=
particleW
->
position
-
particleI
.
position
;
}
else
{
vectorW
=
vectorU
.
cross
(
vectorV
);
vectorW
=
vectorU
.
cross
(
vectorV
);
}
norms
[
W
]
=
normalizeRealVec
(
vectorW
);
norms
[
W
]
=
normalizeRealVec
(
vectorW
);
RealVec
vectorUV
,
vectorUW
,
vectorVW
;
vectorUV
=
vectorV
.
cross
(
vectorU
);
vectorUW
=
vectorW
.
cross
(
vectorU
);
vectorVW
=
vectorW
.
cross
(
vectorV
);
vectorUV
=
vectorV
.
cross
(
vectorU
);
vectorUW
=
vectorW
.
cross
(
vectorU
);
vectorVW
=
vectorW
.
cross
(
vectorV
);
norms
[
UV
]
=
normalizeRealVec
(
vectorUV
);
norms
[
UW
]
=
normalizeRealVec
(
vectorUW
);
norms
[
VW
]
=
normalizeRealVec
(
vectorVW
);
norms
[
UV
]
=
normalizeRealVec
(
vectorUV
);
norms
[
UW
]
=
normalizeRealVec
(
vectorUW
);
norms
[
VW
]
=
normalizeRealVec
(
vectorVW
);
// angles[][0] is cosine of angle
// angles[][1] is sine of angle
angles
[
UV
][
0
]
=
vectorU
.
dot
(
vectorV
);
angles
[
UV
][
1
]
=
SQRT
(
1.0
-
angles
[
UV
][
0
]
*
angles
[
UV
][
0
]);
angles
[
UV
][
0
]
=
vectorU
.
dot
(
vectorV
);
angles
[
UV
][
1
]
=
SQRT
(
1.0
-
angles
[
UV
][
0
]
*
angles
[
UV
][
0
]);
angles
[
UW
][
0
]
=
vectorU
.
dot
(
vectorW
);
angles
[
UW
][
1
]
=
SQRT
(
1.0
-
angles
[
UW
][
0
]
*
angles
[
UW
][
0
]);
angles
[
UW
][
0
]
=
vectorU
.
dot
(
vectorW
);
angles
[
UW
][
1
]
=
SQRT
(
1.0
-
angles
[
UW
][
0
]
*
angles
[
UW
][
0
]);
angles
[
VW
][
0
]
=
vectorV
.
dot
(
vectorW
);
angles
[
VW
][
1
]
=
SQRT
(
1.0
-
angles
[
VW
][
0
]
*
angles
[
VW
][
0
]);
angles
[
VW
][
0
]
=
vectorV
.
dot
(
vectorW
);
angles
[
VW
][
1
]
=
SQRT
(
1.0
-
angles
[
VW
][
0
]
*
angles
[
VW
][
0
]);
RealVec
dphi
;
dphi
[
U
]
=
vectorU
.
dot
(
torque
);
dphi
[
V
]
=
vectorV
.
dot
(
torque
);
dphi
[
W
]
=
vectorW
.
dot
(
torque
);
dphi
[
U
]
=
vectorU
.
dot
(
torque
);
dphi
[
V
]
=
vectorV
.
dot
(
torque
);
dphi
[
W
]
=
vectorW
.
dot
(
torque
);
dphi
*=
-
1.0
;
// branch based on axis type
if
(
axisType
==
AmoebaMultipoleForce
::
ZThenX
||
axisType
==
AmoebaMultipoleForce
::
Bisector
){
if
(
axisType
==
AmoebaMultipoleForce
::
ZThenX
||
axisType
==
AmoebaMultipoleForce
::
Bisector
)
{
RealOpenMM
factor1
;
RealOpenMM
factor2
;
...
...
@@ -1304,14 +1408,14 @@ void AmoebaReferenceMultipoleForce::mapTorqueToForceForParticle( const Multipole
factor2
=
dphi
[
W
]
/
(
norms
[
U
]);
factor3
=
-
dphi
[
U
]
/
(
norms
[
V
]
*
angles
[
UV
][
1
]);
if
(
axisType
==
AmoebaMultipoleForce
::
Bisector
){
if
(
axisType
==
AmoebaMultipoleForce
::
Bisector
)
{
factor2
*=
half
;
factor4
=
half
*
dphi
[
W
]
/
(
norms
[
V
]);
}
else
{
factor4
=
0.0
;
}
for
(
int
ii
=
0
;
ii
<
3
;
ii
++
){
for
(
int
ii
=
0
;
ii
<
3
;
ii
++
)
{
double
forceU
=
vectorUV
[
ii
]
*
factor1
+
factor2
*
vectorUW
[
ii
];
forces
[
particleU
.
particleIndex
][
ii
]
-=
forceU
;
...
...
@@ -1321,50 +1425,50 @@ void AmoebaReferenceMultipoleForce::mapTorqueToForceForParticle( const Multipole
forces
[
particleI
.
particleIndex
][
ii
]
+=
(
forceU
+
forceV
);
}
}
else
if
(
axisType
==
AmoebaMultipoleForce
::
ZBisect
){
}
else
if
(
axisType
==
AmoebaMultipoleForce
::
ZBisect
)
{
RealVec
vectorR
=
vectorV
+
vectorW
;
RealVec
vectorS
=
vectorU
.
cross
(
vectorR
);
RealVec
vectorS
=
vectorU
.
cross
(
vectorR
);
norms
[
R
]
=
normalizeRealVec
(
vectorR
);
norms
[
S
]
=
normalizeRealVec
(
vectorS
);
norms
[
R
]
=
normalizeRealVec
(
vectorR
);
norms
[
S
]
=
normalizeRealVec
(
vectorS
);
RealVec
vectorUR
=
vectorR
.
cross
(
vectorU
);
RealVec
vectorUS
=
vectorS
.
cross
(
vectorU
);
RealVec
vectorVS
=
vectorS
.
cross
(
vectorV
);
RealVec
vectorWS
=
vectorS
.
cross
(
vectorW
);
RealVec
vectorUR
=
vectorR
.
cross
(
vectorU
);
RealVec
vectorUS
=
vectorS
.
cross
(
vectorU
);
RealVec
vectorVS
=
vectorS
.
cross
(
vectorV
);
RealVec
vectorWS
=
vectorS
.
cross
(
vectorW
);
norms
[
UR
]
=
normalizeRealVec
(
vectorUR
);
norms
[
US
]
=
normalizeRealVec
(
vectorUS
);
norms
[
VS
]
=
normalizeRealVec
(
vectorVS
);
norms
[
WS
]
=
normalizeRealVec
(
vectorWS
);
norms
[
UR
]
=
normalizeRealVec
(
vectorUR
);
norms
[
US
]
=
normalizeRealVec
(
vectorUS
);
norms
[
VS
]
=
normalizeRealVec
(
vectorVS
);
norms
[
WS
]
=
normalizeRealVec
(
vectorWS
);
angles
[
UR
][
0
]
=
vectorU
.
dot
(
vectorR
);
angles
[
UR
][
1
]
=
SQRT
(
1.0
-
angles
[
UR
][
0
]
*
angles
[
UR
][
0
]);
angles
[
UR
][
0
]
=
vectorU
.
dot
(
vectorR
);
angles
[
UR
][
1
]
=
SQRT
(
1.0
-
angles
[
UR
][
0
]
*
angles
[
UR
][
0
]);
angles
[
US
][
0
]
=
vectorU
.
dot
(
vectorS
);
angles
[
US
][
1
]
=
SQRT
(
1.0
-
angles
[
US
][
0
]
*
angles
[
US
][
0
]);
angles
[
US
][
0
]
=
vectorU
.
dot
(
vectorS
);
angles
[
US
][
1
]
=
SQRT
(
1.0
-
angles
[
US
][
0
]
*
angles
[
US
][
0
]);
angles
[
VS
][
0
]
=
vectorV
.
dot
(
vectorS
);
angles
[
VS
][
1
]
=
SQRT
(
1.0
-
angles
[
VS
][
0
]
*
angles
[
VS
][
0
]);
angles
[
VS
][
0
]
=
vectorV
.
dot
(
vectorS
);
angles
[
VS
][
1
]
=
SQRT
(
1.0
-
angles
[
VS
][
0
]
*
angles
[
VS
][
0
]);
angles
[
WS
][
0
]
=
vectorW
.
dot
(
vectorS
);
angles
[
WS
][
1
]
=
SQRT
(
1.0
-
angles
[
WS
][
0
]
*
angles
[
WS
][
0
]);
angles
[
WS
][
0
]
=
vectorW
.
dot
(
vectorS
);
angles
[
WS
][
1
]
=
SQRT
(
1.0
-
angles
[
WS
][
0
]
*
angles
[
WS
][
0
]);
RealVec
t1
=
vectorV
-
vectorS
*
angles
[
VS
][
0
];
RealVec
t2
=
vectorW
-
vectorS
*
angles
[
WS
][
0
];
RealOpenMM
notUsed
=
normalizeRealVec
(
t1
);
notUsed
=
normalizeRealVec
(
t2
);
RealOpenMM
notUsed
=
normalizeRealVec
(
t1
);
notUsed
=
normalizeRealVec
(
t2
);
RealOpenMM
ut1cos
=
vectorU
.
dot
(
t1
);
RealOpenMM
ut1sin
=
SQRT
(
1.0
-
ut1cos
*
ut1cos
);
RealOpenMM
ut1cos
=
vectorU
.
dot
(
t1
);
RealOpenMM
ut1sin
=
SQRT
(
1.0
-
ut1cos
*
ut1cos
);
RealOpenMM
ut2cos
=
vectorU
.
dot
(
t2
);
RealOpenMM
ut2sin
=
SQRT
(
1.0
-
ut2cos
*
ut2cos
);
RealOpenMM
ut2cos
=
vectorU
.
dot
(
t2
);
RealOpenMM
ut2sin
=
SQRT
(
1.0
-
ut2cos
*
ut2cos
);
RealOpenMM
dphiR
=
vectorR
.
dot
(
torque
)
*
(
-
1.0
);
RealOpenMM
dphiS
=
vectorS
.
dot
(
torque
)
*
(
-
1.0
);
RealOpenMM
dphiR
=
vectorR
.
dot
(
torque
)
*
(
-
1.0
);
RealOpenMM
dphiS
=
vectorS
.
dot
(
torque
)
*
(
-
1.0
);
RealOpenMM
factor1
=
dphiR
/
(
norms
[
U
]
*
angles
[
UR
][
1
]);
RealOpenMM
factor2
=
dphiS
/
(
norms
[
U
]);
...
...
@@ -1382,11 +1486,11 @@ void AmoebaReferenceMultipoleForce::mapTorqueToForceForParticle( const Multipole
forces
[
particleI
.
particleIndex
]
+=
(
forceU
+
forceV
+
forceW
);
}
else
if
(
axisType
==
AmoebaMultipoleForce
::
ThreeFold
){
}
else
if
(
axisType
==
AmoebaMultipoleForce
::
ThreeFold
)
{
// 3-fold
for
(
int
ii
=
0
;
ii
<
3
;
ii
++
){
for
(
int
ii
=
0
;
ii
<
3
;
ii
++
)
{
RealOpenMM
du
=
vectorUW
[
ii
]
*
dphi
[
W
]
/
(
norms
[
U
]
*
angles
[
UW
][
1
])
+
vectorUV
[
ii
]
*
dphi
[
V
]
/
(
norms
[
U
]
*
angles
[
UV
][
1
])
-
...
...
@@ -1409,16 +1513,16 @@ void AmoebaReferenceMultipoleForce::mapTorqueToForceForParticle( const Multipole
forces
[
particleU
.
particleIndex
][
ii
]
-=
du
;
forces
[
particleV
.
particleIndex
][
ii
]
-=
dv
;
if
(
particleW
)
if
(
particleW
)
forces
[
particleW
->
particleIndex
][
ii
]
-=
dw
;
forces
[
particleI
.
particleIndex
][
ii
]
+=
(
du
+
dv
+
dw
);
}
}
else
if
(
axisType
==
AmoebaMultipoleForce
::
ZOnly
){
}
else
if
(
axisType
==
AmoebaMultipoleForce
::
ZOnly
)
{
// z-only
for
(
int
ii
=
0
;
ii
<
3
;
ii
++
){
for
(
int
ii
=
0
;
ii
<
3
;
ii
++
)
{
RealOpenMM
du
=
vectorUV
[
ii
]
*
dphi
[
V
]
/
(
norms
[
U
]
*
angles
[
UV
][
1
]);
forces
[
particleU
.
particleIndex
][
ii
]
-=
du
;
forces
[
particleI
.
particleIndex
][
ii
]
+=
du
;
...
...
@@ -1429,52 +1533,52 @@ void AmoebaReferenceMultipoleForce::mapTorqueToForceForParticle( const Multipole
}
void
AmoebaReferenceMultipoleForce
::
mapTorqueToForce
(
std
::
vector
<
MultipoleParticleData
>&
particleData
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
axisTypes
,
std
::
vector
<
RealVec
>&
torques
,
std
::
vector
<
RealVec
>&
forces
)
const
void
AmoebaReferenceMultipoleForce
::
mapTorqueToForce
(
vector
<
MultipoleParticleData
>&
particleData
,
const
vector
<
int
>&
multipoleAtomXs
,
const
vector
<
int
>&
multipoleAtomYs
,
const
vector
<
int
>&
multipoleAtomZs
,
const
vector
<
int
>&
axisTypes
,
vector
<
RealVec
>&
torques
,
vector
<
RealVec
>&
forces
)
const
{
// map torques to forces
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
){
if
(
axisTypes
[
ii
]
!=
AmoebaMultipoleForce
::
NoAxisType
){
mapTorqueToForceForParticle
(
particleData
[
ii
],
particleData
[
multipoleAtomZs
[
ii
]],
particleData
[
multipoleAtomXs
[
ii
]],
multipoleAtomYs
[
ii
]
>
-
1
?
&
particleData
[
multipoleAtomYs
[
ii
]]
:
NULL
,
axisTypes
[
ii
],
torques
[
ii
],
forces
);
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
)
{
if
(
axisTypes
[
ii
]
!=
AmoebaMultipoleForce
::
NoAxisType
)
{
mapTorqueToForceForParticle
(
particleData
[
ii
],
particleData
[
multipoleAtomZs
[
ii
]],
particleData
[
multipoleAtomXs
[
ii
]],
multipoleAtomYs
[
ii
]
>
-
1
?
&
particleData
[
multipoleAtomYs
[
ii
]]
:
NULL
,
axisTypes
[
ii
],
torques
[
ii
],
forces
);
}
}
return
;
}
RealOpenMM
AmoebaReferenceMultipoleForce
::
calculateElectrostatic
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
RealVec
>&
torques
,
std
::
vector
<
RealVec
>&
forces
)
RealOpenMM
AmoebaReferenceMultipoleForce
::
calculateElectrostatic
(
const
vector
<
MultipoleParticleData
>&
particleData
,
vector
<
RealVec
>&
torques
,
vector
<
RealVec
>&
forces
)
{
RealOpenMM
energy
=
0.0
;
std
::
vector
<
RealOpenMM
>
scaleFactors
(
LAST_SCALE_TYPE_INDEX
);
for
(
unsigned
int
kk
=
0
;
kk
<
scaleFactors
.
size
();
kk
++
){
vector
<
RealOpenMM
>
scaleFactors
(
LAST_SCALE_TYPE_INDEX
);
for
(
unsigned
int
kk
=
0
;
kk
<
scaleFactors
.
size
();
kk
++
)
{
scaleFactors
[
kk
]
=
1.0
;
}
// main loop over particle pairs
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
){
for
(
unsigned
int
jj
=
ii
+
1
;
jj
<
particleData
.
size
();
jj
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
)
{
for
(
unsigned
int
jj
=
ii
+
1
;
jj
<
particleData
.
size
();
jj
++
)
{
if
(
jj
<=
_maxScaleIndex
[
ii
]
){
getMultipoleScaleFactors
(
ii
,
jj
,
scaleFactors
);
if
(
jj
<=
_maxScaleIndex
[
ii
])
{
getMultipoleScaleFactors
(
ii
,
jj
,
scaleFactors
);
}
energy
+=
calculateElectrostaticPairIxn
(
particleData
[
ii
],
particleData
[
jj
],
scaleFactors
,
forces
,
torques
);
energy
+=
calculateElectrostaticPairIxn
(
particleData
[
ii
],
particleData
[
jj
],
scaleFactors
,
forces
,
torques
);
if
(
jj
<=
_maxScaleIndex
[
ii
]
){
for
(
unsigned
int
kk
=
0
;
kk
<
LAST_SCALE_TYPE_INDEX
;
kk
++
){
if
(
jj
<=
_maxScaleIndex
[
ii
])
{
for
(
unsigned
int
kk
=
0
;
kk
<
LAST_SCALE_TYPE_INDEX
;
kk
++
)
{
scaleFactors
[
kk
]
=
1.0
;
}
}
...
...
@@ -1484,19 +1588,19 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateElectrostatic( const std::vec
return
energy
;
}
void
AmoebaReferenceMultipoleForce
::
setup
(
const
std
::
vector
<
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
std
::
vector
<
MultipoleParticleData
>&
particleData
)
void
AmoebaReferenceMultipoleForce
::
setup
(
const
vector
<
RealVec
>&
particlePositions
,
const
vector
<
RealOpenMM
>&
charges
,
const
vector
<
RealOpenMM
>&
dipoles
,
const
vector
<
RealOpenMM
>&
quadrupoles
,
const
vector
<
RealOpenMM
>&
tholes
,
const
vector
<
RealOpenMM
>&
dampingFactors
,
const
vector
<
RealOpenMM
>&
polarity
,
const
vector
<
int
>&
axisTypes
,
const
vector
<
int
>&
multipoleAtomZs
,
const
vector
<
int
>&
multipoleAtomXs
,
const
vector
<
int
>&
multipoleAtomYs
,
const
vector
<
vector
<
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
vector
<
MultipoleParticleData
>&
particleData
)
{
...
...
@@ -1508,18 +1612,18 @@ void AmoebaReferenceMultipoleForce::setup( const std::vector<RealVec>& particleP
// check if induced dipoles converged
_numParticles
=
particlePositions
.
size
();
loadParticleData
(
particlePositions
,
charges
,
dipoles
,
quadrupoles
,
tholes
,
dampingFactors
,
polarity
,
particleData
);
loadParticleData
(
particlePositions
,
charges
,
dipoles
,
quadrupoles
,
tholes
,
dampingFactors
,
polarity
,
particleData
);
checkChiral
(
particleData
,
multipoleAtomXs
,
multipoleAtomYs
,
multipoleAtomZs
,
axisTypes
);
checkChiral
(
particleData
,
multipoleAtomXs
,
multipoleAtomYs
,
multipoleAtomZs
,
axisTypes
);
applyRotationMatrix
(
particleData
,
multipoleAtomXs
,
multipoleAtomYs
,
multipoleAtomZs
,
axisTypes
);
applyRotationMatrix
(
particleData
,
multipoleAtomXs
,
multipoleAtomYs
,
multipoleAtomZs
,
axisTypes
);
setupScaleMaps
(
multipoleAtomCovalentInfo
);
setupScaleMaps
(
multipoleAtomCovalentInfo
);
calculateInducedDipoles
(
particleData
);
calculateInducedDipoles
(
particleData
);
if
(
!
getMutualInducedDipoleConverged
()
){
if
(
!
getMutualInducedDipoleConverged
())
{
std
::
stringstream
message
;
message
<<
"Induced dipoles did not converge: "
;
message
<<
" iterations="
<<
getMutualInducedDipoleIterations
();
...
...
@@ -1530,104 +1634,104 @@ void AmoebaReferenceMultipoleForce::setup( const std::vector<RealVec>& particleP
return
;
}
RealOpenMM
AmoebaReferenceMultipoleForce
::
calculateForceAndEnergy
(
const
std
::
vector
<
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
std
::
vector
<
RealVec
>&
forces
)
RealOpenMM
AmoebaReferenceMultipoleForce
::
calculateForceAndEnergy
(
const
vector
<
RealVec
>&
particlePositions
,
const
vector
<
RealOpenMM
>&
charges
,
const
vector
<
RealOpenMM
>&
dipoles
,
const
vector
<
RealOpenMM
>&
quadrupoles
,
const
vector
<
RealOpenMM
>&
tholes
,
const
vector
<
RealOpenMM
>&
dampingFactors
,
const
vector
<
RealOpenMM
>&
polarity
,
const
vector
<
int
>&
axisTypes
,
const
vector
<
int
>&
multipoleAtomZs
,
const
vector
<
int
>&
multipoleAtomXs
,
const
vector
<
int
>&
multipoleAtomYs
,
const
vector
<
vector
<
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
vector
<
RealVec
>&
forces
)
{
// setup, including calculating induced dipoles
// calculate electrostatic ixns including torques
// map torques to forces
std
::
vector
<
MultipoleParticleData
>
particleData
;
setup
(
particlePositions
,
charges
,
dipoles
,
quadrupoles
,
tholes
,
vector
<
MultipoleParticleData
>
particleData
;
setup
(
particlePositions
,
charges
,
dipoles
,
quadrupoles
,
tholes
,
dampingFactors
,
polarity
,
axisTypes
,
multipoleAtomZs
,
multipoleAtomXs
,
multipoleAtomYs
,
multipoleAtomCovalentInfo
,
particleData
);
multipoleAtomCovalentInfo
,
particleData
);
std
::
vector
<
RealVec
>
torques
;
initializeRealVecVector
(
torques
);
RealOpenMM
energy
=
calculateElectrostatic
(
particleData
,
torques
,
forces
);
vector
<
RealVec
>
torques
;
initializeRealVecVector
(
torques
);
RealOpenMM
energy
=
calculateElectrostatic
(
particleData
,
torques
,
forces
);
mapTorqueToForce
(
particleData
,
multipoleAtomXs
,
multipoleAtomYs
,
multipoleAtomZs
,
axisTypes
,
torques
,
forces
);
mapTorqueToForce
(
particleData
,
multipoleAtomXs
,
multipoleAtomYs
,
multipoleAtomZs
,
axisTypes
,
torques
,
forces
);
return
energy
;
}
void
AmoebaReferenceMultipoleForce
::
calculateInducedDipoles
(
const
std
::
vector
<
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
std
::
vector
<
RealVec
>&
outputInducedDipoles
)
{
void
AmoebaReferenceMultipoleForce
::
calculateInducedDipoles
(
const
vector
<
RealVec
>&
particlePositions
,
const
vector
<
RealOpenMM
>&
charges
,
const
vector
<
RealOpenMM
>&
dipoles
,
const
vector
<
RealOpenMM
>&
quadrupoles
,
const
vector
<
RealOpenMM
>&
tholes
,
const
vector
<
RealOpenMM
>&
dampingFactors
,
const
vector
<
RealOpenMM
>&
polarity
,
const
vector
<
int
>&
axisTypes
,
const
vector
<
int
>&
multipoleAtomZs
,
const
vector
<
int
>&
multipoleAtomXs
,
const
vector
<
int
>&
multipoleAtomYs
,
const
vector
<
vector
<
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
vector
<
RealVec
>&
outputInducedDipoles
)
{
// setup, including calculating induced dipoles
std
::
vector
<
MultipoleParticleData
>
particleData
;
setup
(
particlePositions
,
charges
,
dipoles
,
quadrupoles
,
tholes
,
vector
<
MultipoleParticleData
>
particleData
;
setup
(
particlePositions
,
charges
,
dipoles
,
quadrupoles
,
tholes
,
dampingFactors
,
polarity
,
axisTypes
,
multipoleAtomZs
,
multipoleAtomXs
,
multipoleAtomYs
,
multipoleAtomCovalentInfo
,
particleData
);
multipoleAtomCovalentInfo
,
particleData
);
outputInducedDipoles
=
_inducedDipole
;
}
void
AmoebaReferenceMultipoleForce
::
calculateAmoebaSystemMultipoleMoments
(
const
std
::
vector
<
RealOpenMM
>&
masses
,
const
std
::
vector
<
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
std
::
vector
<
RealOpenMM
>&
outputMultipoleMoments
)
void
AmoebaReferenceMultipoleForce
::
calculateAmoebaSystemMultipoleMoments
(
const
vector
<
RealOpenMM
>&
masses
,
const
vector
<
RealVec
>&
particlePositions
,
const
vector
<
RealOpenMM
>&
charges
,
const
vector
<
RealOpenMM
>&
dipoles
,
const
vector
<
RealOpenMM
>&
quadrupoles
,
const
vector
<
RealOpenMM
>&
tholes
,
const
vector
<
RealOpenMM
>&
dampingFactors
,
const
vector
<
RealOpenMM
>&
polarity
,
const
vector
<
int
>&
axisTypes
,
const
vector
<
int
>&
multipoleAtomZs
,
const
vector
<
int
>&
multipoleAtomXs
,
const
vector
<
int
>&
multipoleAtomYs
,
const
vector
<
vector
<
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
vector
<
RealOpenMM
>&
outputMultipoleMoments
)
{
// setup, including calculating induced dipoles
// remove center of mass
// calculate system moments
std
::
vector
<
MultipoleParticleData
>
particleData
;
setup
(
particlePositions
,
charges
,
dipoles
,
quadrupoles
,
tholes
,
vector
<
MultipoleParticleData
>
particleData
;
setup
(
particlePositions
,
charges
,
dipoles
,
quadrupoles
,
tholes
,
dampingFactors
,
polarity
,
axisTypes
,
multipoleAtomZs
,
multipoleAtomXs
,
multipoleAtomYs
,
multipoleAtomCovalentInfo
,
particleData
);
multipoleAtomCovalentInfo
,
particleData
);
RealOpenMM
totalMass
=
0.0
;
RealVec
centerOfMass
=
RealVec
(
0.0
,
0.0
,
0.0
);
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
RealVec
centerOfMass
=
RealVec
(
0.0
,
0.0
,
0.0
);
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
RealOpenMM
mass
=
masses
[
ii
];
totalMass
+=
mass
;
centerOfMass
+=
particleData
[
ii
].
position
*
mass
;
}
vector
<
RealVec
>
localPositions
(
_numParticles
);
if
(
totalMass
>
0.0
){
vector
<
RealVec
>
localPositions
(
_numParticles
);
if
(
totalMass
>
0.0
)
{
centerOfMass
*=
1.0
/
totalMass
;
}
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
localPositions
[
ii
]
=
particleData
[
ii
].
position
-
centerOfMass
;
}
RealOpenMM
netchg
=
0.0
;
RealVec
dpl
=
RealVec
(
0.0
,
0.0
,
0.0
);
RealVec
dpl
=
RealVec
(
0.0
,
0.0
,
0.0
);
RealOpenMM
xxqdp
=
0.0
;
RealOpenMM
xyqdp
=
0.0
;
...
...
@@ -1638,7 +1742,7 @@ void AmoebaReferenceMultipoleForce::calculateAmoebaSystemMultipoleMoments( const
RealOpenMM
zzqdp
=
0.0
;
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
RealOpenMM
charge
=
particleData
[
ii
].
charge
;
RealVec
position
=
localPositions
[
ii
];
...
...
@@ -1661,7 +1765,7 @@ void AmoebaReferenceMultipoleForce::calculateAmoebaSystemMultipoleMoments( const
// convert the quadrupole from traced to traceless form
outputMultipoleMoments
.
resize
(
13
);
outputMultipoleMoments
.
resize
(
13
);
RealOpenMM
qave
=
(
xxqdp
+
yyqdp
+
zzqdp
)
/
3.0
;
outputMultipoleMoments
[
4
]
=
0.5
*
(
xxqdp
-
qave
);
outputMultipoleMoments
[
5
]
=
0.5
*
xyqdp
;
...
...
@@ -1672,7 +1776,7 @@ void AmoebaReferenceMultipoleForce::calculateAmoebaSystemMultipoleMoments( const
// add the traceless atomic quadrupoles to total quadrupole
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
outputMultipoleMoments
[
4
]
+=
particleData
[
ii
].
quadrupole
[
QXX
];
outputMultipoleMoments
[
5
]
+=
particleData
[
ii
].
quadrupole
[
QXY
];
outputMultipoleMoments
[
6
]
+=
particleData
[
ii
].
quadrupole
[
QXZ
];
...
...
@@ -1694,22 +1798,22 @@ void AmoebaReferenceMultipoleForce::calculateAmoebaSystemMultipoleMoments( const
outputMultipoleMoments
[
3
]
=
dpl
[
2
];
debye
*=
3.0
;
for
(
unsigned
int
ii
=
4
;
ii
<
13
;
ii
++
){
for
(
unsigned
int
ii
=
4
;
ii
<
13
;
ii
++
)
{
outputMultipoleMoments
[
ii
]
*=
100.0
*
debye
;
}
return
;
}
RealOpenMM
AmoebaReferenceMultipoleForce
::
calculateElectrostaticPotentialForParticleGridPoint
(
const
MultipoleParticleData
&
particleI
,
const
RealVec
&
gridPoint
)
const
RealOpenMM
AmoebaReferenceMultipoleForce
::
calculateElectrostaticPotentialForParticleGridPoint
(
const
MultipoleParticleData
&
particleI
,
const
RealVec
&
gridPoint
)
const
{
RealVec
deltaR
=
particleI
.
position
-
gridPoint
;
getPeriodicDelta
(
deltaR
);
getPeriodicDelta
(
deltaR
);
RealOpenMM
r2
=
deltaR
.
dot
(
deltaR
);
RealOpenMM
r
=
SQRT
(
r2
);
RealOpenMM
r2
=
deltaR
.
dot
(
deltaR
);
RealOpenMM
r
=
SQRT
(
r2
);
RealOpenMM
rr1
=
1.0
/
r
;
RealOpenMM
potential
=
particleI
.
charge
*
rr1
;
...
...
@@ -1717,8 +1821,8 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateElectrostaticPotentialForPart
RealOpenMM
rr2
=
rr1
*
rr1
;
RealOpenMM
rr3
=
rr1
*
rr2
;
RealOpenMM
scd
=
particleI
.
dipole
.
dot
(
deltaR
);
RealOpenMM
scu
=
_inducedDipole
[
particleI
.
particleIndex
].
dot
(
deltaR
);
RealOpenMM
scd
=
particleI
.
dipole
.
dot
(
deltaR
);
RealOpenMM
scu
=
_inducedDipole
[
particleI
.
particleIndex
].
dot
(
deltaR
);
potential
-=
(
scd
+
scu
)
*
rr3
;
RealOpenMM
rr5
=
3.0
*
rr3
*
rr2
;
...
...
@@ -1731,20 +1835,20 @@ RealOpenMM AmoebaReferenceMultipoleForce::calculateElectrostaticPotentialForPart
}
void
AmoebaReferenceMultipoleForce
::
calculateElectrostaticPotential
(
const
std
::
vector
<
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
const
std
::
vector
<
RealVec
>&
grid
,
std
::
vector
<
RealOpenMM
>&
potential
)
void
AmoebaReferenceMultipoleForce
::
calculateElectrostaticPotential
(
const
vector
<
RealVec
>&
particlePositions
,
const
vector
<
RealOpenMM
>&
charges
,
const
vector
<
RealOpenMM
>&
dipoles
,
const
vector
<
RealOpenMM
>&
quadrupoles
,
const
vector
<
RealOpenMM
>&
tholes
,
const
vector
<
RealOpenMM
>&
dampingFactors
,
const
vector
<
RealOpenMM
>&
polarity
,
const
vector
<
int
>&
axisTypes
,
const
vector
<
int
>&
multipoleAtomZs
,
const
vector
<
int
>&
multipoleAtomXs
,
const
vector
<
int
>&
multipoleAtomYs
,
const
vector
<
vector
<
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
const
vector
<
RealVec
>&
grid
,
vector
<
RealOpenMM
>&
potential
)
{
// setup, including calculating induced dipoles
...
...
@@ -1752,38 +1856,36 @@ void AmoebaReferenceMultipoleForce::calculateElectrostaticPotential( const std::
// calculate contribution of each particle to potential at grid point
// apply prefactor
std
::
vector
<
MultipoleParticleData
>
particleData
;
setup
(
particlePositions
,
charges
,
dipoles
,
quadrupoles
,
tholes
,
vector
<
MultipoleParticleData
>
particleData
;
setup
(
particlePositions
,
charges
,
dipoles
,
quadrupoles
,
tholes
,
dampingFactors
,
polarity
,
axisTypes
,
multipoleAtomZs
,
multipoleAtomXs
,
multipoleAtomYs
,
multipoleAtomCovalentInfo
,
particleData
);
multipoleAtomCovalentInfo
,
particleData
);
potential
.
resize
(
grid
.
size
()
);
for
(
unsigned
int
ii
=
0
;
ii
<
grid
.
size
();
ii
++
){
potential
.
resize
(
grid
.
size
());
for
(
unsigned
int
ii
=
0
;
ii
<
grid
.
size
();
ii
++
)
{
potential
[
ii
]
=
0.0
;
}
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
for
(
unsigned
int
jj
=
0
;
jj
<
grid
.
size
();
jj
++
){
potential
[
jj
]
+=
calculateElectrostaticPotentialForParticleGridPoint
(
particleData
[
ii
],
grid
[
jj
]
);
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
for
(
unsigned
int
jj
=
0
;
jj
<
grid
.
size
();
jj
++
)
{
potential
[
jj
]
+=
calculateElectrostaticPotentialForParticleGridPoint
(
particleData
[
ii
],
grid
[
jj
]
);
}
}
RealOpenMM
term
=
_electric
/
_dielectric
;
for
(
unsigned
int
ii
=
0
;
ii
<
grid
.
size
();
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
grid
.
size
();
ii
++
)
{
potential
[
ii
]
*=
term
;
}
return
;
}
AmoebaReferenceMultipoleForce
::
UpdateInducedDipoleFieldStruct
::
UpdateInducedDipoleFieldStruct
(
std
::
vector
<
OpenMM
::
RealVec
>*
inputFixed_E_Field
,
std
::
vector
<
OpenMM
::
RealVec
>*
inputInducedDipoles
)
{
fixedMultipoleField
=
inputFixed_E_Field
;
inducedDipoles
=
inputInducedDipoles
;
inducedDipoleField
.
resize
(
fixedMultipoleField
->
size
()
);
AmoebaReferenceMultipoleForce
::
UpdateInducedDipoleFieldStruct
::
UpdateInducedDipoleFieldStruct
(
vector
<
OpenMM
::
RealVec
>&
inputFixed_E_Field
,
vector
<
OpenMM
::
RealVec
>&
inputInducedDipoles
)
:
fixedMultipoleField
(
&
inputFixed_E_Field
),
inducedDipoles
(
&
inputInducedDipoles
)
{
inducedDipoleField
.
resize
(
fixedMultipoleField
->
size
());
}
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
(
AmoebaReferenceGeneralizedKirkwoodForce
*
amoebaReferenceGeneralizedKirkwoodForce
)
:
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
(
AmoebaReferenceGeneralizedKirkwoodForce
*
amoebaReferenceGeneralizedKirkwoodForce
)
:
AmoebaReferenceMultipoleForce
(
NoCutoff
),
_amoebaReferenceGeneralizedKirkwoodForce
(
amoebaReferenceGeneralizedKirkwoodForce
),
_gkc
(
2.455
)
...
...
@@ -1795,62 +1897,62 @@ AmoebaReferenceGeneralizedKirkwoodMultipoleForce::AmoebaReferenceGeneralizedKirk
_fd
=
2.0
*
(
1.0
-
solventDielectric
)
/
(
1.0
+
2.0
*
solventDielectric
);
_fq
=
3.0
*
(
1.0
-
solventDielectric
)
/
(
2.0
+
3.0
*
solventDielectric
);
_amoebaReferenceGeneralizedKirkwoodForce
->
getGrycukBornRadii
(
_bornRadii
);
_amoebaReferenceGeneralizedKirkwoodForce
->
getAtomicRadii
(
_atomicRadii
);
_amoebaReferenceGeneralizedKirkwoodForce
->
getScaleFactors
(
_scaledRadii
);
_amoebaReferenceGeneralizedKirkwoodForce
->
getGrycukBornRadii
(
_bornRadii
);
_amoebaReferenceGeneralizedKirkwoodForce
->
getAtomicRadii
(
_atomicRadii
);
_amoebaReferenceGeneralizedKirkwoodForce
->
getScaleFactors
(
_scaledRadii
);
_includeCavityTerm
=
_amoebaReferenceGeneralizedKirkwoodForce
->
getIncludeCavityTerm
();
_probeRadius
=
_amoebaReferenceGeneralizedKirkwoodForce
->
getProbeRadius
();
_surfaceAreaFactor
=
_amoebaReferenceGeneralizedKirkwoodForce
->
getSurfaceAreaFactor
();
_dielectricOffset
=
_amoebaReferenceGeneralizedKirkwoodForce
->
getDielectricOffset
();
for
(
unsigned
int
ii
=
0
;
ii
<
_scaledRadii
.
size
();
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_scaledRadii
.
size
();
ii
++
)
{
_scaledRadii
[
ii
]
*=
_atomicRadii
[
ii
];
}
}
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::~
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
(
)
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::~
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
()
{
delete
_amoebaReferenceGeneralizedKirkwoodForce
;
};
int
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
getIncludeCavityTerm
(
void
)
const
int
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
getIncludeCavityTerm
()
const
{
return
_includeCavityTerm
;
};
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
getProbeRadius
(
void
)
const
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
getProbeRadius
()
const
{
return
_probeRadius
;
};
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
getSurfaceAreaFactor
(
void
)
const
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
getSurfaceAreaFactor
()
const
{
return
_surfaceAreaFactor
;
};
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
getDielectricOffset
(
void
)
const
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
getDielectricOffset
()
const
{
return
_dielectricOffset
;
};
void
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
zeroFixedMultipoleFields
(
void
)
void
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
zeroFixedMultipoleFields
()
{
this
->
AmoebaReferenceMultipoleForce
::
zeroFixedMultipoleFields
(
);
initializeRealVecVector
(
_gkField
);
this
->
AmoebaReferenceMultipoleForce
::
zeroFixedMultipoleFields
();
initializeRealVecVector
(
_gkField
);
}
void
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateFixedMultipoleFieldPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dScale
,
RealOpenMM
pScale
)
void
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateFixedMultipoleFieldPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dScale
,
RealOpenMM
pScale
)
{
this
->
AmoebaReferenceMultipoleForce
::
calculateFixedMultipoleFieldPairIxn
(
particleI
,
particleJ
,
dScale
,
pScale
);
this
->
AmoebaReferenceMultipoleForce
::
calculateFixedMultipoleFieldPairIxn
(
particleI
,
particleJ
,
dScale
,
pScale
);
// get deltaR, R2, and R between 2 atoms
RealVec
deltaR
=
particleJ
.
position
-
particleI
.
position
;
RealOpenMM
r
=
SQRT
(
deltaR
.
dot
(
deltaR
)
);
RealOpenMM
r
=
SQRT
(
deltaR
.
dot
(
deltaR
)
);
RealOpenMM
rb2
=
_bornRadii
[
particleI
.
particleIndex
]
*
_bornRadii
[
particleJ
.
particleIndex
];
RealOpenMM
ci
=
particleI
.
charge
;
...
...
@@ -2067,23 +2169,23 @@ void AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateFixedMultipoleFi
+
qyzi
*
gqyz
[
4
]));
_gkField
[
particleI
.
particleIndex
]
+=
fid
;
if
(
particleI
.
particleIndex
!=
particleJ
.
particleIndex
){
if
(
particleI
.
particleIndex
!=
particleJ
.
particleIndex
)
{
_gkField
[
particleJ
.
particleIndex
]
+=
fjd
;
}
return
;
}
void
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateInducedDipolePairGkIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
const
std
::
vector
<
OpenMM
::
RealVec
>&
inputFields
,
std
::
vector
<
OpenMM
::
RealVec
>&
outputFields
)
const
void
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateInducedDipolePairGkIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
const
vector
<
OpenMM
::
RealVec
>&
inputFields
,
vector
<
OpenMM
::
RealVec
>&
outputFields
)
const
{
RealOpenMM
a
[
3
][
3
];
RealVec
deltaR
=
particleJ
.
position
-
particleI
.
position
;
RealOpenMM
r
=
SQRT
(
deltaR
.
dot
(
deltaR
)
);
RealOpenMM
r
=
SQRT
(
deltaR
.
dot
(
deltaR
)
);
RealOpenMM
xr
=
deltaR
[
0
];
RealOpenMM
yr
=
deltaR
[
1
];
...
...
@@ -2134,54 +2236,54 @@ void AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateInducedDipolePai
guz
[
1
]
=
guy
[
2
];
guz
[
2
]
=
(
a
[
1
][
0
]
+
zr2
*
a
[
1
][
1
]);
outputFields
[
iIndex
][
0
]
+=
_fd
*
duks
.
dot
(
gux
);
outputFields
[
iIndex
][
1
]
+=
_fd
*
duks
.
dot
(
guy
);
outputFields
[
iIndex
][
2
]
+=
_fd
*
duks
.
dot
(
guz
);
outputFields
[
iIndex
][
0
]
+=
_fd
*
duks
.
dot
(
gux
);
outputFields
[
iIndex
][
1
]
+=
_fd
*
duks
.
dot
(
guy
);
outputFields
[
iIndex
][
2
]
+=
_fd
*
duks
.
dot
(
guz
);
// skip i == j, i.e., do not include contribution twice
if
(
iIndex
!=
jIndex
){
outputFields
[
jIndex
][
0
]
+=
_fd
*
duis
.
dot
(
gux
);
outputFields
[
jIndex
][
1
]
+=
_fd
*
duis
.
dot
(
guy
);
outputFields
[
jIndex
][
2
]
+=
_fd
*
duis
.
dot
(
guz
);
if
(
iIndex
!=
jIndex
)
{
outputFields
[
jIndex
][
0
]
+=
_fd
*
duis
.
dot
(
gux
);
outputFields
[
jIndex
][
1
]
+=
_fd
*
duis
.
dot
(
guy
);
outputFields
[
jIndex
][
2
]
+=
_fd
*
duis
.
dot
(
guz
);
}
return
;
}
void
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateInducedDipolePairIxns
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
void
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateInducedDipolePairIxns
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
{
AmoebaReferenceMultipoleForce
::
calculateInducedDipolePairIxns
(
particleI
,
particleJ
,
updateInducedDipoleFields
);
AmoebaReferenceMultipoleForce
::
calculateInducedDipolePairIxns
(
particleI
,
particleJ
,
updateInducedDipoleFields
);
// include GK contribution
for
(
unsigned
int
ii
=
2
;
ii
<
updateInducedDipoleFields
.
size
();
ii
++
){
calculateInducedDipolePairGkIxn
(
particleI
,
particleJ
,
*
(
updateInducedDipoleFields
[
ii
].
inducedDipoles
)
,
updateInducedDipoleFields
[
ii
].
inducedDipoleField
);
for
(
unsigned
int
ii
=
2
;
ii
<
updateInducedDipoleFields
.
size
();
ii
++
)
{
calculateInducedDipolePairGkIxn
(
particleI
,
particleJ
,
*
updateInducedDipoleFields
[
ii
].
inducedDipoles
,
updateInducedDipoleFields
[
ii
].
inducedDipoleField
);
}
return
;
}
void
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateInducedDipoles
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
)
void
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateInducedDipoles
(
const
vector
<
MultipoleParticleData
>&
particleData
)
{
// calculate fixed electric fields
zeroFixedMultipoleFields
();
calculateFixedMultipoleField
(
particleData
);
calculateFixedMultipoleField
(
particleData
);
// initialize inducedDipoles
_inducedDipole
.
resize
(
_numParticles
);
_inducedDipolePolar
.
resize
(
_numParticles
);
_inducedDipoleS
.
resize
(
_numParticles
);
_inducedDipolePolarS
.
resize
(
_numParticles
);
vector
<
RealVec
>
gkFieldPolar
(
_numParticles
);
_inducedDipole
.
resize
(
_numParticles
);
_inducedDipolePolar
.
resize
(
_numParticles
);
_inducedDipoleS
.
resize
(
_numParticles
);
_inducedDipolePolarS
.
resize
(
_numParticles
);
vector
<
RealVec
>
gkFieldPolar
(
_numParticles
);
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
_fixedMultipoleField
[
ii
]
*=
particleData
[
ii
].
polarity
;
_fixedMultipoleFieldPolar
[
ii
]
*=
particleData
[
ii
].
polarity
;
...
...
@@ -2197,27 +2299,27 @@ void AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateInducedDipoles(
gkFieldPolar
[
ii
]
=
_inducedDipolePolarS
[
ii
];
}
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Direct
){
setMutualInducedDipoleConverged
(
true
);
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Direct
)
{
setMutualInducedDipoleConverged
(
true
);
return
;
}
std
::
vector
<
UpdateInducedDipoleFieldStruct
>
updateInducedDipoleField
;
updateInducedDipoleField
.
push_back
(
UpdateInducedDipoleFieldStruct
(
&
_fixedMultipoleField
,
&
_inducedDipole
)
);
updateInducedDipoleField
.
push_back
(
UpdateInducedDipoleFieldStruct
(
&
_fixedMultipoleFieldPolar
,
&
_inducedDipolePolar
)
);
updateInducedDipoleField
.
push_back
(
UpdateInducedDipoleFieldStruct
(
&
_gkField
,
&
_inducedDipoleS
)
);
updateInducedDipoleField
.
push_back
(
UpdateInducedDipoleFieldStruct
(
&
gkFieldPolar
,
&
_inducedDipolePolarS
)
);
vector
<
UpdateInducedDipoleFieldStruct
>
updateInducedDipoleField
;
updateInducedDipoleField
.
push_back
(
UpdateInducedDipoleFieldStruct
(
_fixedMultipoleField
,
_inducedDipole
)
);
updateInducedDipoleField
.
push_back
(
UpdateInducedDipoleFieldStruct
(
_fixedMultipoleFieldPolar
,
_inducedDipolePolar
)
);
updateInducedDipoleField
.
push_back
(
UpdateInducedDipoleFieldStruct
(
_gkField
,
_inducedDipoleS
)
);
updateInducedDipoleField
.
push_back
(
UpdateInducedDipoleFieldStruct
(
gkFieldPolar
,
_inducedDipolePolarS
)
);
convergeInduceDipoles
(
particleData
,
updateInducedDipoleField
);
convergeInduceDipoles
ByDIIS
(
particleData
,
updateInducedDipoleField
);
return
;
}
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateKirkwoodPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
,
std
::
vector
<
RealOpenMM
>&
dBorn
)
const
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateKirkwoodPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
vector
<
RealVec
>&
forces
,
vector
<
RealVec
>&
torques
,
vector
<
RealOpenMM
>&
dBorn
)
const
{
RealOpenMM
e
,
ei
;
...
...
@@ -2270,7 +2372,7 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateKirkwoodPa
// decide whether to compute the current interaction
RealVec
deltaR
=
particleJ
.
position
-
particleI
.
position
;
RealOpenMM
r
=
SQRT
(
deltaR
.
dot
(
deltaR
)
);
RealOpenMM
r
=
SQRT
(
deltaR
.
dot
(
deltaR
)
);
xr
=
deltaR
[
0
];
yr
=
deltaR
[
1
];
...
...
@@ -3083,7 +3185,7 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateKirkwoodPa
RealOpenMM
trq_k2
=
0.0
;
RealOpenMM
trq_k3
=
0.0
;
if
(
xr
!=
0.0
||
yr
!=
0.0
||
zr
!=
0.0
)
if
(
xr
!=
0.0
||
yr
!=
0.0
||
zr
!=
0.0
)
{
RealOpenMM
fid1
=
particleJ
.
dipole
[
0
]
*
gux2
+
particleJ
.
dipole
[
1
]
*
gux3
+
particleJ
.
dipole
[
2
]
*
gux4
...
...
@@ -3465,7 +3567,7 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateKirkwoodPa
// mutual polarization electrostatic solvation free energy gradient
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Mutual
){
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Mutual
)
{
dpdx
=
dpdx
-
0.5
*
(
_inducedDipoleS
[
iIndex
][
0
]
*
(
_inducedDipolePolarS
[
jIndex
][
0
]
*
gux5
+
_inducedDipolePolarS
[
jIndex
][
1
]
*
gux6
+
_inducedDipolePolarS
[
jIndex
][
2
]
*
gux7
)
...
...
@@ -3522,27 +3624,27 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateKirkwoodPa
// torque due to induced reaction field gradient on quadrupoles;
RealOpenMM
fidg11
=
-
0.25
*
(
(
sxk
*
gqxx2
+
syk
*
gqxx3
+
szk
*
gqxx4
)
((
sxk
*
gqxx2
+
syk
*
gqxx3
+
szk
*
gqxx4
)
+
(
sxk
*
gux5
+
syk
*
guy5
+
szk
*
guz5
));
RealOpenMM
fidg12
=
-
0.25
*
(
(
sxk
*
gqxy2
+
syk
*
gqxy3
+
szk
*
gqxy4
)
((
sxk
*
gqxy2
+
syk
*
gqxy3
+
szk
*
gqxy4
)
+
(
sxk
*
gux6
+
syk
*
guy6
+
szk
*
guz6
));
RealOpenMM
fidg13
=
-
0.25
*
(
(
sxk
*
gqxz2
+
syk
*
gqxz3
+
szk
*
gqxz4
)
((
sxk
*
gqxz2
+
syk
*
gqxz3
+
szk
*
gqxz4
)
+
(
sxk
*
gux7
+
syk
*
guy7
+
szk
*
guz7
));
RealOpenMM
fidg22
=
-
0.25
*
(
(
sxk
*
gqyy2
+
syk
*
gqyy3
+
szk
*
gqyy4
)
((
sxk
*
gqyy2
+
syk
*
gqyy3
+
szk
*
gqyy4
)
+
(
sxk
*
gux8
+
syk
*
guy8
+
szk
*
guz8
));
RealOpenMM
fidg23
=
-
0.25
*
(
(
sxk
*
gqyz2
+
syk
*
gqyz3
+
szk
*
gqyz4
)
((
sxk
*
gqyz2
+
syk
*
gqyz3
+
szk
*
gqyz4
)
+
(
sxk
*
gux9
+
syk
*
guy9
+
szk
*
guz9
));
RealOpenMM
fidg33
=
-
0.25
*
(
(
sxk
*
gqzz2
+
syk
*
gqzz3
+
szk
*
gqzz4
)
((
sxk
*
gqzz2
+
syk
*
gqzz3
+
szk
*
gqzz4
)
+
(
sxk
*
gux10
+
syk
*
guy10
+
szk
*
guz10
));
RealOpenMM
fidg21
=
fidg12
;
...
...
@@ -3550,23 +3652,23 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateKirkwoodPa
RealOpenMM
fidg32
=
fidg23
;
RealOpenMM
fkdg11
=
0.25
*
(
(
sxi
*
gqxx2
+
syi
*
gqxx3
+
szi
*
gqxx4
)
((
sxi
*
gqxx2
+
syi
*
gqxx3
+
szi
*
gqxx4
)
+
(
sxi
*
gux5
+
syi
*
guy5
+
szi
*
guz5
));
RealOpenMM
fkdg12
=
0.25
*
(
(
sxi
*
gqxy2
+
syi
*
gqxy3
+
szi
*
gqxy4
)
((
sxi
*
gqxy2
+
syi
*
gqxy3
+
szi
*
gqxy4
)
+
(
sxi
*
gux6
+
syi
*
guy6
+
szi
*
guz6
));
RealOpenMM
fkdg13
=
0.25
*
(
(
sxi
*
gqxz2
+
syi
*
gqxz3
+
szi
*
gqxz4
)
((
sxi
*
gqxz2
+
syi
*
gqxz3
+
szi
*
gqxz4
)
+
(
sxi
*
gux7
+
syi
*
guy7
+
szi
*
guz7
));
RealOpenMM
fkdg22
=
0.25
*
(
(
sxi
*
gqyy2
+
syi
*
gqyy3
+
szi
*
gqyy4
)
((
sxi
*
gqyy2
+
syi
*
gqyy3
+
szi
*
gqyy4
)
+
(
sxi
*
gux8
+
syi
*
guy8
+
szi
*
guz8
));
RealOpenMM
fkdg23
=
0.25
*
(
(
sxi
*
gqyz2
+
syi
*
gqyz3
+
szi
*
gqyz4
)
((
sxi
*
gqyz2
+
syi
*
gqyz3
+
szi
*
gqyz4
)
+
(
sxi
*
gux9
+
syi
*
guy9
+
szi
*
guz9
));
RealOpenMM
fkdg33
=
0.25
*
(
(
sxi
*
gqzz2
+
syi
*
gqzz3
+
szi
*
gqzz4
)
((
sxi
*
gqzz2
+
syi
*
gqzz3
+
szi
*
gqzz4
)
+
(
sxi
*
gux10
+
syi
*
guy10
+
szi
*
guz10
));
RealOpenMM
fkdg21
=
fkdg12
;
RealOpenMM
fkdg31
=
fkdg13
;
...
...
@@ -3612,7 +3714,7 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateKirkwoodPa
torques
[
iIndex
][
2
]
+=
(
trq3
+
trqi3
);
dBorn
[
iIndex
]
+=
drbi
+
dpbi
;
if
(
iIndex
!=
jIndex
){
if
(
iIndex
!=
jIndex
)
{
torques
[
jIndex
][
0
]
+=
(
trq_k1
+
trqi_k1
);
torques
[
jIndex
][
1
]
+=
(
trq_k2
+
trqi_k2
);
...
...
@@ -3624,59 +3726,59 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateKirkwoodPa
return
(
energy
);
}
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateElectrostatic
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
RealVec
>&
torques
,
std
::
vector
<
RealVec
>&
forces
)
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateElectrostatic
(
const
vector
<
MultipoleParticleData
>&
particleData
,
vector
<
RealVec
>&
torques
,
vector
<
RealVec
>&
forces
)
{
RealOpenMM
energy
=
AmoebaReferenceMultipoleForce
::
calculateElectrostatic
(
particleData
,
torques
,
forces
);
RealOpenMM
energy
=
AmoebaReferenceMultipoleForce
::
calculateElectrostatic
(
particleData
,
torques
,
forces
);
vector
<
RealOpenMM
>
dBorn
;
initializeRealOpenMMVector
(
dBorn
);
initializeRealOpenMMVector
(
dBorn
);
// Kirkwood loop over particle pairs
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
){
for
(
unsigned
int
jj
=
ii
;
jj
<
particleData
.
size
();
jj
++
){
energy
+=
calculateKirkwoodPairIxn
(
particleData
[
ii
],
particleData
[
jj
],
forces
,
torques
,
dBorn
);
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
)
{
for
(
unsigned
int
jj
=
ii
;
jj
<
particleData
.
size
();
jj
++
)
{
energy
+=
calculateKirkwoodPairIxn
(
particleData
[
ii
],
particleData
[
jj
],
forces
,
torques
,
dBorn
);
}
}
// cavity term
if
(
getIncludeCavityTerm
()
){
energy
+=
calculateCavityTermEnergyAndForces
(
dBorn
);
if
(
getIncludeCavityTerm
())
{
energy
+=
calculateCavityTermEnergyAndForces
(
dBorn
);
}
// apply Born chain rule; skip diagonal terms since these make no contribution to forces
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
){
for
(
unsigned
int
jj
=
ii
+
1
;
jj
<
particleData
.
size
();
jj
++
){
calculateGrycukChainRulePairIxn
(
particleData
[
ii
],
particleData
[
jj
],
dBorn
,
forces
);
calculateGrycukChainRulePairIxn
(
particleData
[
jj
],
particleData
[
ii
],
dBorn
,
forces
);
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
)
{
for
(
unsigned
int
jj
=
ii
+
1
;
jj
<
particleData
.
size
();
jj
++
)
{
calculateGrycukChainRulePairIxn
(
particleData
[
ii
],
particleData
[
jj
],
dBorn
,
forces
);
calculateGrycukChainRulePairIxn
(
particleData
[
jj
],
particleData
[
ii
],
dBorn
,
forces
);
}
}
// correct vacuum to SCRF derivatives (ediff1 in TINKER)
vector
<
RealOpenMM
>
scaleFactors
(
LAST_SCALE_TYPE_INDEX
);
for
(
unsigned
int
kk
=
0
;
kk
<
scaleFactors
.
size
();
kk
++
){
for
(
unsigned
int
kk
=
0
;
kk
<
scaleFactors
.
size
();
kk
++
)
{
scaleFactors
[
kk
]
=
1.0
;
}
RealOpenMM
eDiffEnergy
=
0.0
;
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
){
for
(
unsigned
int
jj
=
ii
+
1
;
jj
<
particleData
.
size
();
jj
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
)
{
for
(
unsigned
int
jj
=
ii
+
1
;
jj
<
particleData
.
size
();
jj
++
)
{
if
(
jj
<=
_maxScaleIndex
[
ii
]
){
getMultipoleScaleFactors
(
ii
,
jj
,
scaleFactors
);
if
(
jj
<=
_maxScaleIndex
[
ii
])
{
getMultipoleScaleFactors
(
ii
,
jj
,
scaleFactors
);
}
eDiffEnergy
+=
calculateKirkwoodEDiffPairIxn
(
particleData
[
ii
],
particleData
[
jj
],
scaleFactors
[
P_SCALE
],
scaleFactors
[
D_SCALE
],
forces
,
torques
);
eDiffEnergy
+=
calculateKirkwoodEDiffPairIxn
(
particleData
[
ii
],
particleData
[
jj
],
scaleFactors
[
P_SCALE
],
scaleFactors
[
D_SCALE
],
forces
,
torques
);
if
(
jj
<=
_maxScaleIndex
[
ii
]
){
for
(
unsigned
int
kk
=
0
;
kk
<
LAST_SCALE_TYPE_INDEX
;
kk
++
){
if
(
jj
<=
_maxScaleIndex
[
ii
])
{
for
(
unsigned
int
kk
=
0
;
kk
<
LAST_SCALE_TYPE_INDEX
;
kk
++
)
{
scaleFactors
[
kk
]
=
1.0
;
}
}
...
...
@@ -3687,8 +3789,8 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateElectrosta
return
energy
;
}
void
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateGrycukChainRulePairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
const
std
::
vector
<
RealOpenMM
>&
dBorn
,
std
::
vector
<
RealVec
>&
forces
)
const
void
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateGrycukChainRulePairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
const
vector
<
RealOpenMM
>&
dBorn
,
vector
<
RealVec
>&
forces
)
const
{
unsigned
int
iIndex
=
particleI
.
particleIndex
;
unsigned
int
jIndex
=
particleJ
.
particleIndex
;
...
...
@@ -3697,19 +3799,19 @@ void AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateGrycukChainRuleP
RealOpenMM
lik
,
uik
;
RealOpenMM
lik4
,
uik4
;
RealOpenMM
factor
=
-
POW
(
M_PI
,
(
1.0
/
3.0
)
)
*
POW
(
6.0
,(
2.0
/
3.0
))
/
9.0
;
RealOpenMM
factor
=
-
POW
(
M_PI
,
(
1.0
/
3.0
))
*
POW
(
6.0
,(
2.0
/
3.0
))
/
9.0
;
RealOpenMM
term
=
pi43
/
(
_bornRadii
[
iIndex
]
*
_bornRadii
[
iIndex
]
*
_bornRadii
[
iIndex
]);
term
=
factor
/
POW
(
term
,
(
4.0
/
3.0
)
);
term
=
factor
/
POW
(
term
,
(
4.0
/
3.0
));
RealVec
deltaR
=
particleJ
.
position
-
particleI
.
position
;
RealOpenMM
sk
=
_scaledRadii
[
jIndex
];
RealOpenMM
sk2
=
sk
*
sk
;
RealOpenMM
r2
=
deltaR
.
dot
(
deltaR
);
RealOpenMM
r2
=
deltaR
.
dot
(
deltaR
);
RealOpenMM
r
=
SQRT
(
r2
);
RealOpenMM
de
=
0.0
;
if
(
(
_atomicRadii
[
iIndex
]
+
r
)
<
sk
){
if
(
(
_atomicRadii
[
iIndex
]
+
r
)
<
sk
)
{
RealOpenMM
uik4
;
uik
=
sk
-
r
;
uik4
=
uik
*
uik
;
...
...
@@ -3717,12 +3819,12 @@ void AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateGrycukChainRuleP
de
=
-
4.0
*
M_PI
/
uik4
;
}
if
(
(
_atomicRadii
[
iIndex
]
+
r
)
<
sk
){
if
(
(
_atomicRadii
[
iIndex
]
+
r
)
<
sk
)
{
lik
=
sk
-
r
;
lik4
=
lik
*
lik
;
lik4
=
lik4
*
lik4
;
de
+=
0.25
*
M_PI
*
(
sk2
-
4.0
*
sk
*
r
+
17.0
*
r2
)
/
(
r2
*
lik4
);
}
else
if
(
r
<
(
_atomicRadii
[
iIndex
]
+
sk
)
){
}
else
if
(
r
<
(
_atomicRadii
[
iIndex
]
+
sk
))
{
lik
=
_atomicRadii
[
iIndex
];
lik4
=
lik
*
lik
;
lik4
=
lik4
*
lik4
;
...
...
@@ -3747,14 +3849,14 @@ void AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateGrycukChainRuleP
return
;
}
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateCavityTermEnergyAndForces
(
std
::
vector
<
RealOpenMM
>&
dBorn
)
const
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateCavityTermEnergyAndForces
(
vector
<
RealOpenMM
>&
dBorn
)
const
{
RealOpenMM
energy
=
0.0
;
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
RealOpenMM
r
=
_atomicRadii
[
ii
]
+
_dielectricOffset
+
_probeRadius
;
RealOpenMM
ratio
=
(
(
_atomicRadii
[
ii
]
+
_dielectricOffset
)
/
_bornRadii
[
ii
]);
RealOpenMM
saTerm
=
_surfaceAreaFactor
*
r
*
r
*
POW
(
ratio
,
6.0
);
RealOpenMM
ratio
=
((
_atomicRadii
[
ii
]
+
_dielectricOffset
)
/
_bornRadii
[
ii
]);
RealOpenMM
saTerm
=
_surfaceAreaFactor
*
r
*
r
*
POW
(
ratio
,
6.0
);
dBorn
[
ii
]
+=
saTerm
/
_bornRadii
[
ii
];
energy
+=
saTerm
;
}
...
...
@@ -3770,11 +3872,11 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateCavityTerm
******************************************************************************/
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateKirkwoodEDiffPairIxn
(
const
MultipoleParticleData
&
particleI
,
RealOpenMM
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
::
calculateKirkwoodEDiffPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
pscale
,
RealOpenMM
dscale
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
)
const
vector
<
RealVec
>&
forces
,
vector
<
RealVec
>&
torques
)
const
{
static
const
RealOpenMM
uscale
=
1.0
;
...
...
@@ -3793,7 +3895,7 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateKirkwoodED
// deltaR
RealVec
deltaR
=
particleJ
.
position
-
particleI
.
position
;
RealOpenMM
r2
=
deltaR
.
dot
(
deltaR
);
RealOpenMM
r2
=
deltaR
.
dot
(
deltaR
);
RealOpenMM
xr
=
deltaR
[
0
];
RealOpenMM
yr
=
deltaR
[
1
];
...
...
@@ -3825,12 +3927,12 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateKirkwoodED
// apply Thole polarization damping to scale factors
RealOpenMM
damp
=
particleI
.
dampingFactor
*
particleJ
.
dampingFactor
;
if
(
damp
!=
0.0
){
if
(
damp
!=
0.0
)
{
pgamma
=
particleJ
.
thole
>
particleI
.
thole
?
particleI
.
thole
:
particleJ
.
thole
;
RealOpenMM
ratio
=
(
r
/
damp
);
damp
=
-
pgamma
*
ratio
*
ratio
*
ratio
;
if
(
damp
>
-
50.0
){
RealOpenMM
dampE
=
EXP
(
damp
);
if
(
damp
>
-
50.0
)
{
RealOpenMM
dampE
=
EXP
(
damp
);
RealOpenMM
damp2
=
damp
*
damp
;
scale3
=
1.0
-
dampE
;
scale5
=
1.0
-
(
1.0
-
damp
)
*
dampE
;
...
...
@@ -4102,7 +4204,7 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateKirkwoodED
// correction to convert mutual to direct polarization force
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Direct
){
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Direct
)
{
RealOpenMM
gfd
=
0.5
*
(
rr5
*
scip2
*
scale3i
-
rr7
*
(
scip3
*
sci4
+
sci3
*
scip4
)
*
scale5i
);
RealOpenMM
fdir1
=
gfd
*
xr
+
0.5
*
rr5
*
scale5i
*
(
sci4
*
_inducedDipolePolarS
[
iIndex
][
0
]
+
scip4
*
_inducedDipoleS
[
iIndex
][
0
]
+
sci3
*
_inducedDipolePolarS
[
jIndex
][
0
]
+
scip3
*
_inducedDipoleS
[
jIndex
][
0
]);
RealOpenMM
fdir2
=
gfd
*
yr
+
0.5
*
rr5
*
scale5i
*
(
sci4
*
_inducedDipolePolarS
[
iIndex
][
1
]
+
scip4
*
_inducedDipoleS
[
iIndex
][
1
]
+
sci3
*
_inducedDipolePolarS
[
jIndex
][
1
]
+
scip3
*
_inducedDipoleS
[
jIndex
][
1
]);
...
...
@@ -4365,7 +4467,7 @@ RealOpenMM AmoebaReferenceGeneralizedKirkwoodMultipoleForce::calculateKirkwoodED
// correction to convert mutual to direct polarization force
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Direct
){
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Direct
)
{
RealOpenMM
gfd
=
0.5
*
(
rr5
*
scip2
*
scale3i
-
rr7
*
(
scip3
*
sci4
+
sci3
*
scip4
)
*
scale5i
);
RealOpenMM
fdir1
=
gfd
*
xr
+
0.5
*
rr5
*
scale5i
*
(
sci4
*
_inducedDipolePolar
[
iIndex
][
0
]
+
scip4
*
_inducedDipole
[
iIndex
][
0
]
+
sci3
*
_inducedDipolePolar
[
jIndex
][
0
]
+
scip3
*
_inducedDipole
[
jIndex
][
0
]);
...
...
@@ -4433,7 +4535,7 @@ const int AmoebaReferencePmeMultipoleForce::AMOEBA_PME_ORDER = 5;
const
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
SQRT_PI
=
1.77245385091
;
AmoebaReferencePmeMultipoleForce
::
AmoebaReferencePmeMultipoleForce
(
void
)
:
AmoebaReferencePmeMultipoleForce
::
AmoebaReferencePmeMultipoleForce
()
:
AmoebaReferenceMultipoleForce
(
PME
),
_cutoffDistance
(
1.0
),
_cutoffDistanceSquared
(
1.0
),
_pmeGridSize
(
0
),
_totalGridSize
(
0
),
_alphaEwald
(
0.0
)
...
...
@@ -4441,44 +4543,44 @@ AmoebaReferencePmeMultipoleForce::AmoebaReferencePmeMultipoleForce( void ) :
_fftplan
=
NULL
;
_pmeGrid
=
NULL
;
_pmeGridDimensions
=
IntVec
(
-
1
,
-
1
,
-
1
);
_pmeGridDimensions
=
IntVec
(
-
1
,
-
1
,
-
1
);
}
AmoebaReferencePmeMultipoleForce
::~
AmoebaReferencePmeMultipoleForce
(
)
AmoebaReferencePmeMultipoleForce
::~
AmoebaReferencePmeMultipoleForce
()
{
if
(
_fftplan
){
fftpack_destroy
(
_fftplan
);
if
(
_fftplan
)
{
fftpack_destroy
(
_fftplan
);
}
if
(
_pmeGrid
){
if
(
_pmeGrid
)
{
delete
_pmeGrid
;
}
};
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
getCutoffDistance
(
void
)
const
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
getCutoffDistance
()
const
{
return
_cutoffDistance
;
};
void
AmoebaReferencePmeMultipoleForce
::
setCutoffDistance
(
RealOpenMM
cutoffDistance
)
void
AmoebaReferencePmeMultipoleForce
::
setCutoffDistance
(
RealOpenMM
cutoffDistance
)
{
_cutoffDistance
=
cutoffDistance
;
_cutoffDistanceSquared
=
cutoffDistance
*
cutoffDistance
;
};
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
getAlphaEwald
(
void
)
const
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
getAlphaEwald
()
const
{
return
_alphaEwald
;
};
void
AmoebaReferencePmeMultipoleForce
::
setAlphaEwald
(
RealOpenMM
alphaEwald
)
void
AmoebaReferencePmeMultipoleForce
::
setAlphaEwald
(
RealOpenMM
alphaEwald
)
{
_alphaEwald
=
alphaEwald
;
};
void
AmoebaReferencePmeMultipoleForce
::
getPmeGridDimensions
(
std
::
vector
<
int
>&
pmeGridDimensions
)
const
void
AmoebaReferencePmeMultipoleForce
::
getPmeGridDimensions
(
vector
<
int
>&
pmeGridDimensions
)
const
{
pmeGridDimensions
.
resize
(
3
);
pmeGridDimensions
.
resize
(
3
);
pmeGridDimensions
[
0
]
=
_pmeGridDimensions
[
0
];
pmeGridDimensions
[
1
]
=
_pmeGridDimensions
[
1
];
...
...
@@ -4487,14 +4589,14 @@ void AmoebaReferencePmeMultipoleForce::getPmeGridDimensions( std::vector<int>& p
return
;
};
void
AmoebaReferencePmeMultipoleForce
::
setPmeGridDimensions
(
std
::
vector
<
int
>&
pmeGridDimensions
)
void
AmoebaReferencePmeMultipoleForce
::
setPmeGridDimensions
(
vector
<
int
>&
pmeGridDimensions
)
{
if
(
(
pmeGridDimensions
[
0
]
==
_pmeGridDimensions
[
0
])
&&
if
(
(
pmeGridDimensions
[
0
]
==
_pmeGridDimensions
[
0
])
&&
(
pmeGridDimensions
[
1
]
==
_pmeGridDimensions
[
1
])
&&
(
pmeGridDimensions
[
2
]
==
_pmeGridDimensions
[
2
])
)
return
;
(
pmeGridDimensions
[
2
]
==
_pmeGridDimensions
[
2
]))
return
;
if
(
_fftplan
){
if
(
_fftplan
)
{
fftpack_destroy
(
_fftplan
);
}
fftpack_init_3d
(
&
_fftplan
,
pmeGridDimensions
[
0
],
pmeGridDimensions
[
1
],
pmeGridDimensions
[
2
]);
...
...
@@ -4503,13 +4605,13 @@ void AmoebaReferencePmeMultipoleForce::setPmeGridDimensions( std::vector<int>& p
_pmeGridDimensions
[
1
]
=
pmeGridDimensions
[
1
];
_pmeGridDimensions
[
2
]
=
pmeGridDimensions
[
2
];
initializeBSplineModuli
(
);
initializeBSplineModuli
();
};
void
AmoebaReferencePmeMultipoleForce
::
setPeriodicBoxSize
(
RealVec
&
boxSize
)
void
AmoebaReferencePmeMultipoleForce
::
setPeriodicBoxSize
(
RealVec
&
boxSize
)
{
if
(
boxSize
[
0
]
==
0.0
||
boxSize
[
1
]
==
0.0
||
boxSize
[
2
]
==
0.0
){
if
(
boxSize
[
0
]
==
0.0
||
boxSize
[
1
]
==
0.0
||
boxSize
[
2
]
==
0.0
)
{
std
::
stringstream
message
;
message
<<
"Box size of zero is invalid."
;
throw
OpenMMException
(
message
.
str
());
...
...
@@ -4524,74 +4626,74 @@ void AmoebaReferencePmeMultipoleForce::setPeriodicBoxSize( RealVec& boxSize )
return
;
};
int
compareInt2
(
const
int2
&
v1
,
const
int2
&
v2
)
int
compareInt2
(
const
int2
&
v1
,
const
int2
&
v2
)
{
return
v1
[
1
]
<
v2
[
1
];
}
void
AmoebaReferencePmeMultipoleForce
::
resizePmeArrays
(
void
)
void
AmoebaReferencePmeMultipoleForce
::
resizePmeArrays
()
{
_totalGridSize
=
_pmeGridDimensions
[
0
]
*
_pmeGridDimensions
[
1
]
*
_pmeGridDimensions
[
2
];
if
(
_pmeGridSize
<
_totalGridSize
){
if
(
_pmeGrid
){
if
(
_pmeGridSize
<
_totalGridSize
)
{
if
(
_pmeGrid
)
{
delete
_pmeGrid
;
}
_pmeGrid
=
new
t_complex
[
_totalGridSize
];
_pmeGridSize
=
_totalGridSize
;
}
for
(
unsigned
int
ii
=
0
;
ii
<
3
;
ii
++
){
_pmeBsplineModuli
[
ii
].
resize
(
_pmeGridDimensions
[
ii
]
);
_thetai
[
ii
].
resize
(
AMOEBA_PME_ORDER
*
_numParticles
);
for
(
unsigned
int
ii
=
0
;
ii
<
3
;
ii
++
)
{
_pmeBsplineModuli
[
ii
].
resize
(
_pmeGridDimensions
[
ii
]);
_thetai
[
ii
].
resize
(
AMOEBA_PME_ORDER
*
_numParticles
);
}
_iGrid
.
resize
(
_numParticles
);
_phi
.
resize
(
20
*
_numParticles
);
_phid
.
resize
(
10
*
_numParticles
);
_phip
.
resize
(
10
*
_numParticles
);
_phidp
.
resize
(
20
*
_numParticles
);
_pmeAtomRange
.
resize
(
_totalGridSize
+
1
);
_pmeAtomGridIndex
.
resize
(
_numParticles
);
_iGrid
.
resize
(
_numParticles
);
_phi
.
resize
(
20
*
_numParticles
);
_phid
.
resize
(
10
*
_numParticles
);
_phip
.
resize
(
10
*
_numParticles
);
_phidp
.
resize
(
20
*
_numParticles
);
_pmeAtomRange
.
resize
(
_totalGridSize
+
1
);
_pmeAtomGridIndex
.
resize
(
_numParticles
);
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
initializePmeGrid
(
void
)
void
AmoebaReferencePmeMultipoleForce
::
initializePmeGrid
()
{
if
(
_pmeGrid
==
NULL
)
return
;
//memset(
_pmeGrid, 0, sizeof(
t_complex
)*_totalGridSize
);
if
(
_pmeGrid
==
NULL
)
return
;
//memset(_pmeGrid, 0, sizeof(t_complex)*_totalGridSize);
for
(
int
jj
=
0
;
jj
<
_totalGridSize
;
jj
++
){
for
(
int
jj
=
0
;
jj
<
_totalGridSize
;
jj
++
)
{
_pmeGrid
[
jj
].
re
=
_pmeGrid
[
jj
].
im
=
0.0
;
}
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
getPeriodicDelta
(
RealVec
&
deltaR
)
const
void
AmoebaReferencePmeMultipoleForce
::
getPeriodicDelta
(
RealVec
&
deltaR
)
const
{
deltaR
[
0
]
-=
FLOOR
(
deltaR
[
0
]
*
_invPeriodicBoxSize
[
0
]
+
0.5
)
*
_periodicBoxSize
[
0
];
deltaR
[
1
]
-=
FLOOR
(
deltaR
[
1
]
*
_invPeriodicBoxSize
[
1
]
+
0.5
)
*
_periodicBoxSize
[
1
];
deltaR
[
2
]
-=
FLOOR
(
deltaR
[
2
]
*
_invPeriodicBoxSize
[
2
]
+
0.5
)
*
_periodicBoxSize
[
2
];
}
void
AmoebaReferencePmeMultipoleForce
::
getPmeScale
(
RealVec
&
scale
)
const
void
AmoebaReferencePmeMultipoleForce
::
getPmeScale
(
RealVec
&
scale
)
const
{
scale
[
0
]
=
static_cast
<
RealOpenMM
>
(
_pmeGridDimensions
[
0
])
*
_invPeriodicBoxSize
[
0
];
scale
[
1
]
=
static_cast
<
RealOpenMM
>
(
_pmeGridDimensions
[
1
])
*
_invPeriodicBoxSize
[
1
];
scale
[
2
]
=
static_cast
<
RealOpenMM
>
(
_pmeGridDimensions
[
2
])
*
_invPeriodicBoxSize
[
2
];
}
void
AmoebaReferencePmeMultipoleForce
::
getDampedInverseDistances
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dscale
,
RealOpenMM
pscale
,
RealOpenMM
r
,
RealVec
&
dampedDInverseDistances
,
RealVec
&
dampedPInverseDistances
)
const
void
AmoebaReferencePmeMultipoleForce
::
getDampedInverseDistances
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dscale
,
RealOpenMM
pscale
,
RealOpenMM
r
,
RealVec
&
dampedDInverseDistances
,
RealVec
&
dampedPInverseDistances
)
const
{
RealVec
scaleFactor
=
RealVec
(
1.0
,
1.0
,
1.0
);
RealVec
scaleFactor
=
RealVec
(
1.0
,
1.0
,
1.0
);
RealOpenMM
damp
=
particleI
.
dampingFactor
*
particleJ
.
dampingFactor
;
if
(
damp
!=
0.0
){
if
(
damp
!=
0.0
)
{
RealOpenMM
ratio
=
(
r
/
damp
);
ratio
=
ratio
*
ratio
*
ratio
;
...
...
@@ -4599,7 +4701,7 @@ void AmoebaReferencePmeMultipoleForce::getDampedInverseDistances( const Multipol
RealOpenMM
pgamma
=
particleI
.
thole
<
particleJ
.
thole
?
particleI
.
thole
:
particleJ
.
thole
;
damp
=
-
pgamma
*
ratio
;
if
(
damp
>
-
50.0
)
{
if
(
damp
>
-
50.0
)
{
RealOpenMM
expdamp
=
EXP
(
damp
);
scaleFactor
[
0
]
=
1.0
-
expdamp
;
scaleFactor
[
1
]
=
1.0
-
expdamp
*
(
1.0
-
damp
);
...
...
@@ -4616,7 +4718,7 @@ void AmoebaReferencePmeMultipoleForce::getDampedInverseDistances( const Multipol
dampedDInverseDistances
[
0
]
=
(
1.0
-
dampedDScale
[
0
])
/
r3
;
dampedDInverseDistances
[
1
]
=
3.0
*
(
1.0
-
dampedDScale
[
1
])
/
r5
;
dampedDInverseDistances
[
2
]
=
15.0
*
(
1.0
-
dampedDScale
[
2
])
/
r7
;
if
(
pscale
==
dscale
){
if
(
pscale
==
dscale
)
{
dampedPInverseDistances
=
dampedDInverseDistances
;
}
else
{
RealVec
dampedPScale
=
scaleFactor
*
pscale
;
...
...
@@ -4628,14 +4730,14 @@ void AmoebaReferencePmeMultipoleForce::getDampedInverseDistances( const Multipol
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
initializeBSplineModuli
(
void
)
void
AmoebaReferencePmeMultipoleForce
::
initializeBSplineModuli
()
{
// Initialize the b-spline moduli.
int
maxSize
=
-
1
;
for
(
unsigned
int
ii
=
0
;
ii
<
3
;
ii
++
){
_pmeBsplineModuli
[
ii
].
resize
(
_pmeGridDimensions
[
ii
]
);
for
(
unsigned
int
ii
=
0
;
ii
<
3
;
ii
++
)
{
_pmeBsplineModuli
[
ii
].
resize
(
_pmeGridDimensions
[
ii
]);
maxSize
=
maxSize
>
_pmeGridDimensions
[
ii
]
?
maxSize
:
_pmeGridDimensions
[
ii
];
}
...
...
@@ -4643,20 +4745,20 @@ void AmoebaReferencePmeMultipoleForce::initializeBSplineModuli( void )
RealOpenMM
x
=
0.0
;
array
[
0
]
=
1.0
-
x
;
array
[
1
]
=
x
;
for
(
int
k
=
2
;
k
<
AMOEBA_PME_ORDER
;
k
++
)
{
for
(
int
k
=
2
;
k
<
AMOEBA_PME_ORDER
;
k
++
)
{
RealOpenMM
denom
=
1.0
/
k
;
array
[
k
]
=
x
*
array
[
k
-
1
]
*
denom
;
for
(
int
i
=
1
;
i
<
k
;
i
++
){
for
(
int
i
=
1
;
i
<
k
;
i
++
)
{
array
[
k
-
i
]
=
((
x
+
i
)
*
array
[
k
-
i
-
1
]
+
((
k
-
i
+
1
)
-
x
)
*
array
[
k
-
i
])
*
denom
;
}
array
[
0
]
=
(
1.0
-
x
)
*
array
[
0
]
*
denom
;
}
vector
<
RealOpenMM
>
bsarray
(
maxSize
+
1
,
0.0
);
for
(
int
i
=
2
;
i
<=
AMOEBA_PME_ORDER
+
1
;
i
++
){
for
(
int
i
=
2
;
i
<=
AMOEBA_PME_ORDER
+
1
;
i
++
)
{
bsarray
[
i
]
=
array
[
i
-
2
];
}
for
(
int
dim
=
0
;
dim
<
3
;
dim
++
)
{
for
(
int
dim
=
0
;
dim
<
3
;
dim
++
)
{
int
size
=
_pmeGridDimensions
[
dim
];
...
...
@@ -4677,15 +4779,15 @@ void AmoebaReferencePmeMultipoleForce::initializeBSplineModuli( void )
// fix for exponential Euler spline interpolation failure
RealOpenMM
eps
=
1.0e-7
;
if
(
_pmeBsplineModuli
[
dim
][
0
]
<
eps
){
if
(
_pmeBsplineModuli
[
dim
][
0
]
<
eps
)
{
_pmeBsplineModuli
[
dim
][
0
]
=
0.5
*
_pmeBsplineModuli
[
dim
][
1
];
}
for
(
int
i
=
1
;
i
<
size
-
1
;
i
++
){
if
(
_pmeBsplineModuli
[
dim
][
i
]
<
eps
){
for
(
int
i
=
1
;
i
<
size
-
1
;
i
++
)
{
if
(
_pmeBsplineModuli
[
dim
][
i
]
<
eps
)
{
_pmeBsplineModuli
[
dim
][
i
]
=
0.5
*
(
_pmeBsplineModuli
[
dim
][
i
-
1
]
+
_pmeBsplineModuli
[
dim
][
i
+
1
]);
}
}
if
(
_pmeBsplineModuli
[
dim
][
size
-
1
]
<
eps
){
if
(
_pmeBsplineModuli
[
dim
][
size
-
1
]
<
eps
)
{
_pmeBsplineModuli
[
dim
][
size
-
1
]
=
0.5
*
_pmeBsplineModuli
[
dim
][
size
-
2
];
}
...
...
@@ -4697,7 +4799,7 @@ void AmoebaReferencePmeMultipoleForce::initializeBSplineModuli( void )
if
(
i
>
size
/
2
)
k
=
k
-
size
;
RealOpenMM
zeta
;
if
(
k
==
0
){
if
(
k
==
0
)
{
zeta
=
1.0
;
}
else
{
RealOpenMM
sum1
=
1.0
;
...
...
@@ -4722,20 +4824,20 @@ void AmoebaReferencePmeMultipoleForce::initializeBSplineModuli( void )
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
calculateFixedMultipoleFieldPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dscale
,
RealOpenMM
pscale
)
void
AmoebaReferencePmeMultipoleForce
::
calculateFixedMultipoleFieldPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dscale
,
RealOpenMM
pscale
)
{
// compute the real space portion of the Ewald summation
if
(
particleI
.
particleIndex
==
particleJ
.
particleIndex
)
return
;
if
(
particleI
.
particleIndex
==
particleJ
.
particleIndex
)
return
;
RealVec
deltaR
=
particleJ
.
position
-
particleI
.
position
;
getPeriodicDelta
(
deltaR
);
RealOpenMM
r2
=
deltaR
.
dot
(
deltaR
);
getPeriodicDelta
(
deltaR
);
RealOpenMM
r2
=
deltaR
.
dot
(
deltaR
);
if
(
r2
>
_cutoffDistanceSquared
)
return
;
if
(
r2
>
_cutoffDistanceSquared
)
return
;
RealOpenMM
r
=
SQRT
(
r2
);
...
...
@@ -4760,7 +4862,7 @@ void AmoebaReferencePmeMultipoleForce::calculateFixedMultipoleFieldPairIxn( cons
RealVec
dampedDInverseDistances
;
RealVec
dampedPInverseDistances
;
getDampedInverseDistances
(
particleI
,
particleJ
,
dscale
,
pscale
,
r
,
dampedDInverseDistances
,
dampedPInverseDistances
);
getDampedInverseDistances
(
particleI
,
particleJ
,
dscale
,
pscale
,
r
,
dampedDInverseDistances
,
dampedPInverseDistances
);
RealOpenMM
drr3
=
dampedDInverseDistances
[
0
];
RealOpenMM
drr5
=
dampedDInverseDistances
[
1
];
...
...
@@ -4770,31 +4872,31 @@ void AmoebaReferencePmeMultipoleForce::calculateFixedMultipoleFieldPairIxn( cons
RealOpenMM
prr5
=
dampedPInverseDistances
[
1
];
RealOpenMM
prr7
=
dampedPInverseDistances
[
2
];
RealOpenMM
dir
=
particleI
.
dipole
.
dot
(
deltaR
);
RealOpenMM
dir
=
particleI
.
dipole
.
dot
(
deltaR
);
RealVec
qxI
=
RealVec
(
particleI
.
quadrupole
[
QXX
],
particleI
.
quadrupole
[
QXY
],
particleI
.
quadrupole
[
QXZ
]
);
RealVec
qyI
=
RealVec
(
particleI
.
quadrupole
[
QXY
],
particleI
.
quadrupole
[
QYY
],
particleI
.
quadrupole
[
QYZ
]
);
RealVec
qzI
=
RealVec
(
particleI
.
quadrupole
[
QXZ
],
particleI
.
quadrupole
[
QYZ
],
particleI
.
quadrupole
[
QZZ
]
);
RealVec
qxI
=
RealVec
(
particleI
.
quadrupole
[
QXX
],
particleI
.
quadrupole
[
QXY
],
particleI
.
quadrupole
[
QXZ
]);
RealVec
qyI
=
RealVec
(
particleI
.
quadrupole
[
QXY
],
particleI
.
quadrupole
[
QYY
],
particleI
.
quadrupole
[
QYZ
]);
RealVec
qzI
=
RealVec
(
particleI
.
quadrupole
[
QXZ
],
particleI
.
quadrupole
[
QYZ
],
particleI
.
quadrupole
[
QZZ
]);
RealVec
qi
=
RealVec
(
qxI
.
dot
(
deltaR
),
qyI
.
dot
(
deltaR
),
qzI
.
dot
(
deltaR
)
);
RealOpenMM
qir
=
qi
.
dot
(
deltaR
);
RealVec
qi
=
RealVec
(
qxI
.
dot
(
deltaR
),
qyI
.
dot
(
deltaR
),
qzI
.
dot
(
deltaR
)
);
RealOpenMM
qir
=
qi
.
dot
(
deltaR
);
RealOpenMM
djr
=
particleJ
.
dipole
.
dot
(
deltaR
);
RealOpenMM
djr
=
particleJ
.
dipole
.
dot
(
deltaR
);
RealVec
qxJ
=
RealVec
(
particleJ
.
quadrupole
[
QXX
],
particleJ
.
quadrupole
[
QXY
],
particleJ
.
quadrupole
[
QXZ
]
);
RealVec
qyJ
=
RealVec
(
particleJ
.
quadrupole
[
QXY
],
particleJ
.
quadrupole
[
QYY
],
particleJ
.
quadrupole
[
QYZ
]
);
RealVec
qzJ
=
RealVec
(
particleJ
.
quadrupole
[
QXZ
],
particleJ
.
quadrupole
[
QYZ
],
particleJ
.
quadrupole
[
QZZ
]
);
RealVec
qxJ
=
RealVec
(
particleJ
.
quadrupole
[
QXX
],
particleJ
.
quadrupole
[
QXY
],
particleJ
.
quadrupole
[
QXZ
]);
RealVec
qyJ
=
RealVec
(
particleJ
.
quadrupole
[
QXY
],
particleJ
.
quadrupole
[
QYY
],
particleJ
.
quadrupole
[
QYZ
]);
RealVec
qzJ
=
RealVec
(
particleJ
.
quadrupole
[
QXZ
],
particleJ
.
quadrupole
[
QYZ
],
particleJ
.
quadrupole
[
QZZ
]);
RealVec
qj
=
RealVec
(
qxJ
.
dot
(
deltaR
),
qyJ
.
dot
(
deltaR
),
qzJ
.
dot
(
deltaR
)
);
RealOpenMM
qjr
=
qj
.
dot
(
deltaR
);
RealVec
qj
=
RealVec
(
qxJ
.
dot
(
deltaR
),
qyJ
.
dot
(
deltaR
),
qzJ
.
dot
(
deltaR
)
);
RealOpenMM
qjr
=
qj
.
dot
(
deltaR
);
RealVec
fim
=
qj
*
(
2.0
*
bn2
)
-
particleJ
.
dipole
*
bn1
-
deltaR
*
(
bn1
*
particleJ
.
charge
-
bn2
*
djr
+
bn3
*
qjr
);
RealVec
fjm
=
qi
*
(
-
2.0
*
bn2
)
-
particleI
.
dipole
*
bn1
+
deltaR
*
(
bn1
*
particleI
.
charge
+
bn2
*
dir
+
bn3
*
qir
);
RealVec
fim
=
qj
*
(
2.0
*
bn2
)
-
particleJ
.
dipole
*
bn1
-
deltaR
*
(
bn1
*
particleJ
.
charge
-
bn2
*
djr
+
bn3
*
qjr
);
RealVec
fjm
=
qi
*
(
-
2.0
*
bn2
)
-
particleI
.
dipole
*
bn1
+
deltaR
*
(
bn1
*
particleI
.
charge
+
bn2
*
dir
+
bn3
*
qir
);
RealVec
fid
=
qj
*
(
2.0
*
drr5
)
-
particleJ
.
dipole
*
drr3
-
deltaR
*
(
drr3
*
particleJ
.
charge
-
drr5
*
djr
+
drr7
*
qjr
);
RealVec
fid
=
qj
*
(
2.0
*
drr5
)
-
particleJ
.
dipole
*
drr3
-
deltaR
*
(
drr3
*
particleJ
.
charge
-
drr5
*
djr
+
drr7
*
qjr
);
RealVec
fjd
=
qi
*
(
-
2.0
*
drr5
)
-
particleI
.
dipole
*
drr3
+
deltaR
*
(
drr3
*
particleI
.
charge
+
drr5
*
dir
+
drr7
*
qir
);
RealVec
fip
=
qj
*
(
2.0
*
prr5
)
-
particleJ
.
dipole
*
prr3
-
deltaR
*
(
prr3
*
particleJ
.
charge
-
prr5
*
djr
+
prr7
*
qjr
);
RealVec
fip
=
qj
*
(
2.0
*
prr5
)
-
particleJ
.
dipole
*
prr3
-
deltaR
*
(
prr3
*
particleJ
.
charge
-
prr5
*
djr
+
prr7
*
qjr
);
RealVec
fjp
=
qi
*
(
-
2.0
*
prr5
)
-
particleI
.
dipole
*
prr3
+
deltaR
*
(
prr3
*
particleI
.
charge
+
prr5
*
dir
+
prr7
*
qir
);
// increment the field at each site due to this interaction
...
...
@@ -4811,20 +4913,20 @@ void AmoebaReferencePmeMultipoleForce::calculateFixedMultipoleFieldPairIxn( cons
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
calculateFixedMultipoleField
(
const
vector
<
MultipoleParticleData
>&
particleData
)
void
AmoebaReferencePmeMultipoleForce
::
calculateFixedMultipoleField
(
const
vector
<
MultipoleParticleData
>&
particleData
)
{
// first calculate reciprocal space fixed multipole fields
resizePmeArrays
();
computeAmoebaBsplines
(
particleData
);
sort
(
_pmeAtomGridIndex
.
begin
(),
_pmeAtomGridIndex
.
end
(),
compareInt2
);
findAmoebaAtomRangeForGrid
(
particleData
);
computeAmoebaBsplines
(
particleData
);
sort
(
_pmeAtomGridIndex
.
begin
(),
_pmeAtomGridIndex
.
end
(),
compareInt2
);
findAmoebaAtomRangeForGrid
(
particleData
);
initializePmeGrid
();
spreadFixedMultipolesOntoGrid
(
particleData
);
fftpack_exec_3d
(
_fftplan
,
FFTPACK_FORWARD
,
_pmeGrid
,
_pmeGrid
);
spreadFixedMultipolesOntoGrid
(
particleData
);
fftpack_exec_3d
(
_fftplan
,
FFTPACK_FORWARD
,
_pmeGrid
,
_pmeGrid
);
performAmoebaReciprocalConvolution
();
fftpack_exec_3d
(
_fftplan
,
FFTPACK_BACKWARD
,
_pmeGrid
,
_pmeGrid
);
fftpack_exec_3d
(
_fftplan
,
FFTPACK_BACKWARD
,
_pmeGrid
,
_pmeGrid
);
computeFixedPotentialFromGrid
();
recordFixedMultipoleField
();
...
...
@@ -4832,7 +4934,7 @@ void AmoebaReferencePmeMultipoleForce::calculateFixedMultipoleField( const vecto
// and initialize _fixedMultipoleFieldPolar to _fixedMultipoleField
RealOpenMM
term
=
(
4.0
/
3.0
)
*
(
_alphaEwald
*
_alphaEwald
*
_alphaEwald
)
/
SQRT_PI
;
for
(
unsigned
int
jj
=
0
;
jj
<
_numParticles
;
jj
++
){
for
(
unsigned
int
jj
=
0
;
jj
<
_numParticles
;
jj
++
)
{
RealVec
selfEnergy
=
particleData
[
jj
].
dipole
*
term
;
_fixedMultipoleField
[
jj
]
+=
selfEnergy
;
_fixedMultipoleFieldPolar
[
jj
]
=
_fixedMultipoleField
[
jj
];
...
...
@@ -4840,7 +4942,7 @@ void AmoebaReferencePmeMultipoleForce::calculateFixedMultipoleField( const vecto
// include direct space fixed multipole fields
this
->
AmoebaReferenceMultipoleForce
::
calculateFixedMultipoleField
(
particleData
);
this
->
AmoebaReferenceMultipoleForce
::
calculateFixedMultipoleField
(
particleData
);
return
;
}
...
...
@@ -4850,7 +4952,7 @@ void AmoebaReferencePmeMultipoleForce::calculateFixedMultipoleField( const vecto
/**
* This is called from computeBsplines(). It calculates the spline coefficients for a single atom along a single axis.
*/
void
AmoebaReferencePmeMultipoleForce
::
computeBSplinePoint
(
std
::
vector
<
RealOpenMM4
>&
thetai
,
RealOpenMM
w
)
void
AmoebaReferencePmeMultipoleForce
::
computeBSplinePoint
(
vector
<
RealOpenMM4
>&
thetai
,
RealOpenMM
w
)
{
RealOpenMM
array
[
AMOEBA_PME_ORDER
*
AMOEBA_PME_ORDER
];
...
...
@@ -4868,11 +4970,11 @@ void AmoebaReferencePmeMultipoleForce::computeBSplinePoint( std::vector<RealOpen
// compute standard B-spline recursion to desired order
for
(
int
i
=
4
;
i
<=
AMOEBA_PME_ORDER
;
i
++
){
for
(
int
i
=
4
;
i
<=
AMOEBA_PME_ORDER
;
i
++
)
{
int
k
=
i
-
1
;
RealOpenMM
denom
=
1.0
/
k
;
ARRAY
(
i
,
i
)
=
denom
*
w
*
ARRAY
(
k
,
k
);
for
(
int
j
=
1
;
j
<=
i
-
2
;
j
++
){
for
(
int
j
=
1
;
j
<=
i
-
2
;
j
++
)
{
ARRAY
(
i
,
i
-
j
)
=
denom
*
((
w
+
j
)
*
ARRAY
(
k
,
i
-
j
-
1
)
+
(
i
-
j
-
w
)
*
ARRAY
(
k
,
i
-
j
));
}
ARRAY
(
i
,
1
)
=
denom
*
(
1.0
-
w
)
*
ARRAY
(
k
,
1
);
...
...
@@ -4916,7 +5018,7 @@ void AmoebaReferencePmeMultipoleForce::computeBSplinePoint( std::vector<RealOpen
// copy coefficients from temporary to permanent storage
for
(
int
i
=
1
;
i
<=
AMOEBA_PME_ORDER
;
i
++
){
for
(
int
i
=
1
;
i
<=
AMOEBA_PME_ORDER
;
i
++
)
{
thetai
[
i
-
1
]
=
RealOpenMM4
(
ARRAY
(
AMOEBA_PME_ORDER
,
i
),
ARRAY
(
AMOEBA_PME_ORDER
-
1
,
i
),
ARRAY
(
AMOEBA_PME_ORDER
-
2
,
i
),
ARRAY
(
AMOEBA_PME_ORDER
-
3
,
i
));
}
...
...
@@ -4926,16 +5028,16 @@ void AmoebaReferencePmeMultipoleForce::computeBSplinePoint( std::vector<RealOpen
/**
* Compute b-spline coefficients.
*/
void
AmoebaReferencePmeMultipoleForce
::
computeAmoebaBsplines
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
)
void
AmoebaReferencePmeMultipoleForce
::
computeAmoebaBsplines
(
const
vector
<
MultipoleParticleData
>&
particleData
)
{
// get the B-spline coefficients for each multipole site
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
RealVec
position
=
particleData
[
ii
].
position
;
getPeriodicDelta
(
position
);
getPeriodicDelta
(
position
);
IntVec
igrid
;
for
(
unsigned
int
jj
=
0
;
jj
<
3
;
jj
++
){
for
(
unsigned
int
jj
=
0
;
jj
<
3
;
jj
++
)
{
RealOpenMM
w
=
position
[
jj
]
*
_invPeriodicBoxSize
[
jj
];
RealOpenMM
fr
=
_pmeGridDimensions
[
jj
]
*
(
w
-
(
int
)(
w
+
0.5
)
+
0.5
);
...
...
@@ -4943,9 +5045,9 @@ void AmoebaReferencePmeMultipoleForce::computeAmoebaBsplines( const std::vector<
w
=
fr
-
ifr
;
igrid
[
jj
]
=
ifr
-
AMOEBA_PME_ORDER
+
1
;
igrid
[
jj
]
+=
igrid
[
jj
]
<
0
?
_pmeGridDimensions
[
jj
]
:
0
;
std
::
vector
<
RealOpenMM4
>
thetaiTemp
(
AMOEBA_PME_ORDER
);
computeBSplinePoint
(
thetaiTemp
,
w
);
for
(
unsigned
int
kk
=
0
;
kk
<
AMOEBA_PME_ORDER
;
kk
++
){
vector
<
RealOpenMM4
>
thetaiTemp
(
AMOEBA_PME_ORDER
);
computeBSplinePoint
(
thetaiTemp
,
w
);
for
(
unsigned
int
kk
=
0
;
kk
<
AMOEBA_PME_ORDER
;
kk
++
)
{
_thetai
[
jj
][
ii
*
AMOEBA_PME_ORDER
+
kk
]
=
thetaiTemp
[
kk
];
}
}
...
...
@@ -4953,7 +5055,7 @@ void AmoebaReferencePmeMultipoleForce::computeAmoebaBsplines( const std::vector<
// Record the grid point.
_iGrid
[
ii
]
=
igrid
;
_pmeAtomGridIndex
[
ii
]
=
int2
(
ii
,
igrid
[
0
]
*
_pmeGridDimensions
[
1
]
*
_pmeGridDimensions
[
2
]
+
igrid
[
1
]
*
_pmeGridDimensions
[
2
]
+
igrid
[
2
]
);
_pmeAtomGridIndex
[
ii
]
=
int2
(
ii
,
igrid
[
0
]
*
_pmeGridDimensions
[
1
]
*
_pmeGridDimensions
[
2
]
+
igrid
[
1
]
*
_pmeGridDimensions
[
2
]
+
igrid
[
2
]);
}
...
...
@@ -4963,18 +5065,18 @@ void AmoebaReferencePmeMultipoleForce::computeAmoebaBsplines( const std::vector<
/**
* For each grid point, find the range of sorted atoms associated with that point.
*/
void
AmoebaReferencePmeMultipoleForce
::
findAmoebaAtomRangeForGrid
(
const
vector
<
MultipoleParticleData
>&
particleData
)
void
AmoebaReferencePmeMultipoleForce
::
findAmoebaAtomRangeForGrid
(
const
vector
<
MultipoleParticleData
>&
particleData
)
{
int
last
;
int
start
=
0
;
last
=
(
start
==
0
?
-
1
:
_pmeAtomGridIndex
[
start
-
1
][
1
]);
for
(
unsigned
int
ii
=
start
;
ii
<
_numParticles
;
++
ii
)
{
for
(
unsigned
int
ii
=
start
;
ii
<
_numParticles
;
++
ii
)
{
int2
atomData
=
_pmeAtomGridIndex
[
ii
];
int
gridIndex
=
atomData
[
1
];
if
(
gridIndex
!=
last
)
{
for
(
int
jj
=
last
+
1
;
jj
<=
gridIndex
;
++
jj
){
for
(
int
jj
=
last
+
1
;
jj
<=
gridIndex
;
++
jj
)
{
_pmeAtomRange
[
jj
]
=
ii
;
}
last
=
gridIndex
;
...
...
@@ -4983,14 +5085,14 @@ void AmoebaReferencePmeMultipoleForce::findAmoebaAtomRangeForGrid( const vector<
// Fill in values beyond the last atom.
for
(
int
j
=
last
+
1
;
j
<=
_totalGridSize
;
++
j
){
for
(
int
j
=
last
+
1
;
j
<=
_totalGridSize
;
++
j
)
{
_pmeAtomRange
[
j
]
=
_numParticles
;
}
// The grid index won't be needed again. Reuse that component to hold the z index, thus saving
// some work in the multipole spreading.
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
RealOpenMM
posz
=
particleData
[
_pmeAtomGridIndex
[
ii
][
0
]].
position
[
2
];
posz
-=
FLOOR
(
posz
*
_invPeriodicBoxSize
[
2
])
*
_periodicBoxSize
[
2
];
...
...
@@ -5003,7 +5105,7 @@ void AmoebaReferencePmeMultipoleForce::findAmoebaAtomRangeForGrid( const vector<
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
getGridPointGivenGridIndex
(
int
gridIndex
,
IntVec
&
gridPoint
)
const
void
AmoebaReferencePmeMultipoleForce
::
getGridPointGivenGridIndex
(
int
gridIndex
,
IntVec
&
gridPoint
)
const
{
gridPoint
[
0
]
=
gridIndex
/
(
_pmeGridDimensions
[
1
]
*
_pmeGridDimensions
[
2
]);
...
...
@@ -5014,9 +5116,9 @@ void AmoebaReferencePmeMultipoleForce::getGridPointGivenGridIndex( int gridIndex
return
;
}
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
computeFixedMultipolesGridValue
(
const
vector
<
MultipoleParticleData
>&
particleData
,
const
int2
&
particleGridIndices
,
const
RealVec
&
scale
,
int
ix
,
int
iy
,
const
IntVec
&
gridPoint
)
const
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
computeFixedMultipolesGridValue
(
const
vector
<
MultipoleParticleData
>&
particleData
,
const
int2
&
particleGridIndices
,
const
RealVec
&
scale
,
int
ix
,
int
iy
,
const
IntVec
&
gridPoint
)
const
{
RealOpenMM
gridValue
=
0.0
;
...
...
@@ -5025,14 +5127,14 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeFixedMultipolesGridValue( co
int
atomIndex
=
atomData
[
0
];
int
z
=
atomData
[
1
];
int
iz
=
gridPoint
[
2
]
-
z
+
(
gridPoint
[
2
]
>=
z
?
0
:
_pmeGridDimensions
[
2
]);
if
(
iz
>=
_pmeGridDimensions
[
2
]
){
if
(
iz
>=
_pmeGridDimensions
[
2
])
{
iz
-=
_pmeGridDimensions
[
2
];
}
RealOpenMM
atomCharge
=
particleData
[
atomIndex
].
charge
;
RealVec
atomDipole
=
RealVec
(
scale
[
0
]
*
particleData
[
atomIndex
].
dipole
[
0
],
scale
[
1
]
*
particleData
[
atomIndex
].
dipole
[
1
],
scale
[
2
]
*
particleData
[
atomIndex
].
dipole
[
2
]
);
RealVec
atomDipole
=
RealVec
(
scale
[
0
]
*
particleData
[
atomIndex
].
dipole
[
0
],
scale
[
1
]
*
particleData
[
atomIndex
].
dipole
[
1
],
scale
[
2
]
*
particleData
[
atomIndex
].
dipole
[
2
]);
RealOpenMM
atomQuadrupoleXX
=
scale
[
0
]
*
scale
[
0
]
*
particleData
[
atomIndex
].
quadrupole
[
QXX
];
RealOpenMM
atomQuadrupoleXY
=
2.0
*
scale
[
0
]
*
scale
[
1
]
*
particleData
[
atomIndex
].
quadrupole
[
QXY
];
...
...
@@ -5052,16 +5154,16 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeFixedMultipolesGridValue( co
return
gridValue
;
}
void
AmoebaReferencePmeMultipoleForce
::
spreadFixedMultipolesOntoGrid
(
const
vector
<
MultipoleParticleData
>&
particleData
)
void
AmoebaReferencePmeMultipoleForce
::
spreadFixedMultipolesOntoGrid
(
const
vector
<
MultipoleParticleData
>&
particleData
)
{
RealVec
scale
;
getPmeScale
(
scale
);
getPmeScale
(
scale
);
for
(
int
gridIndex
=
0
;
gridIndex
<
_totalGridSize
;
gridIndex
++
){
for
(
int
gridIndex
=
0
;
gridIndex
<
_totalGridSize
;
gridIndex
++
)
{
IntVec
gridPoint
;
getGridPointGivenGridIndex
(
gridIndex
,
gridPoint
);
getGridPointGivenGridIndex
(
gridIndex
,
gridPoint
);
RealOpenMM
result
=
0.0
;
for
(
int
ix
=
0
;
ix
<
AMOEBA_PME_ORDER
;
++
ix
)
...
...
@@ -5077,13 +5179,13 @@ void AmoebaReferencePmeMultipoleForce::spreadFixedMultipolesOntoGrid( const vect
int2
particleGridIndices
;
particleGridIndices
[
0
]
=
x
*
_pmeGridDimensions
[
1
]
*
_pmeGridDimensions
[
2
]
+
y
*
_pmeGridDimensions
[
2
]
+
z1
;
particleGridIndices
[
1
]
=
x
*
_pmeGridDimensions
[
1
]
*
_pmeGridDimensions
[
2
]
+
y
*
_pmeGridDimensions
[
2
]
+
z2
;
result
+=
computeFixedMultipolesGridValue
(
particleData
,
particleGridIndices
,
scale
,
ix
,
iy
,
gridPoint
);
result
+=
computeFixedMultipolesGridValue
(
particleData
,
particleGridIndices
,
scale
,
ix
,
iy
,
gridPoint
);
if
(
z1
>
gridPoint
[
2
]){
if
(
z1
>
gridPoint
[
2
])
{
particleGridIndices
[
0
]
=
x
*
_pmeGridDimensions
[
1
]
*
_pmeGridDimensions
[
2
]
+
y
*
_pmeGridDimensions
[
2
];
particleGridIndices
[
1
]
=
x
*
_pmeGridDimensions
[
1
]
*
_pmeGridDimensions
[
2
]
+
y
*
_pmeGridDimensions
[
2
]
+
gridPoint
[
2
];
result
+=
computeFixedMultipolesGridValue
(
particleData
,
particleGridIndices
,
scale
,
ix
,
iy
,
gridPoint
);
result
+=
computeFixedMultipolesGridValue
(
particleData
,
particleGridIndices
,
scale
,
ix
,
iy
,
gridPoint
);
}
}
}
...
...
@@ -5092,7 +5194,7 @@ void AmoebaReferencePmeMultipoleForce::spreadFixedMultipolesOntoGrid( const vect
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
performAmoebaReciprocalConvolution
(
void
)
void
AmoebaReferencePmeMultipoleForce
::
performAmoebaReciprocalConvolution
()
{
RealOpenMM
expFactor
=
(
M_PI
*
M_PI
)
/
(
_alphaEwald
*
_alphaEwald
);
...
...
@@ -5105,7 +5207,7 @@ void AmoebaReferencePmeMultipoleForce::performAmoebaReciprocalConvolution( void
int
ky
=
remainder
/
_pmeGridDimensions
[
2
];
int
kz
=
remainder
-
ky
*
_pmeGridDimensions
[
2
];
if
(
kx
==
0
&&
ky
==
0
&&
kz
==
0
){
if
(
kx
==
0
&&
ky
==
0
&&
kz
==
0
)
{
_pmeGrid
[
index
].
re
=
_pmeGrid
[
index
].
im
=
0.0
;
continue
;
}
...
...
@@ -5131,7 +5233,7 @@ void AmoebaReferencePmeMultipoleForce::performAmoebaReciprocalConvolution( void
}
}
void
AmoebaReferencePmeMultipoleForce
::
computeFixedPotentialFromGrid
(
void
)
void
AmoebaReferencePmeMultipoleForce
::
computeFixedPotentialFromGrid
()
{
// extract the permanent multipole field at each site
...
...
@@ -5239,10 +5341,10 @@ void AmoebaReferencePmeMultipoleForce::computeFixedPotentialFromGrid( void )
}
}
t_complex
AmoebaReferencePmeMultipoleForce
::
computeInducedDipoleGridValue
(
const
int2
&
particleGridIndices
,
const
RealVec
&
scale
,
int
ix
,
int
iy
,
const
IntVec
&
gridPoint
,
const
std
::
vector
<
RealVec
>&
inputInducedDipole
,
const
std
::
vector
<
RealVec
>&
inputInducedDipolePolar
)
const
t_complex
AmoebaReferencePmeMultipoleForce
::
computeInducedDipoleGridValue
(
const
int2
&
particleGridIndices
,
const
RealVec
&
scale
,
int
ix
,
int
iy
,
const
IntVec
&
gridPoint
,
const
vector
<
RealVec
>&
inputInducedDipole
,
const
vector
<
RealVec
>&
inputInducedDipolePolar
)
const
{
...
...
@@ -5251,21 +5353,21 @@ t_complex AmoebaReferencePmeMultipoleForce::computeInducedDipoleGridValue( const
t_complex
gridValue
;
gridValue
.
re
=
gridValue
.
im
=
0.0
;
for
(
int
i
=
_pmeAtomRange
[
particleGridIndices
[
0
]];
i
<
_pmeAtomRange
[
particleGridIndices
[
1
]
+
1
];
++
i
){
for
(
int
i
=
_pmeAtomRange
[
particleGridIndices
[
0
]];
i
<
_pmeAtomRange
[
particleGridIndices
[
1
]
+
1
];
++
i
)
{
int2
atomData
=
_pmeAtomGridIndex
[
i
];
int
atomIndex
=
atomData
[
0
];
int
z
=
atomData
[
1
];
int
iz
=
gridPoint
[
2
]
-
z
+
(
gridPoint
[
2
]
>=
z
?
0
:
_pmeGridDimensions
[
2
]);
if
(
iz
>=
_pmeGridDimensions
[
2
]
){
if
(
iz
>=
_pmeGridDimensions
[
2
])
{
iz
-=
_pmeGridDimensions
[
2
];
}
RealVec
inducedDipole
=
RealVec
(
scale
[
0
]
*
inputInducedDipole
[
atomIndex
][
0
],
RealVec
inducedDipole
=
RealVec
(
scale
[
0
]
*
inputInducedDipole
[
atomIndex
][
0
],
scale
[
1
]
*
inputInducedDipole
[
atomIndex
][
1
],
scale
[
2
]
*
inputInducedDipole
[
atomIndex
][
2
]
);
scale
[
2
]
*
inputInducedDipole
[
atomIndex
][
2
]);
RealVec
inducedDipolePolar
=
RealVec
(
scale
[
0
]
*
inputInducedDipolePolar
[
atomIndex
][
0
],
RealVec
inducedDipolePolar
=
RealVec
(
scale
[
0
]
*
inputInducedDipolePolar
[
atomIndex
][
0
],
scale
[
1
]
*
inputInducedDipolePolar
[
atomIndex
][
1
],
scale
[
2
]
*
inputInducedDipolePolar
[
atomIndex
][
2
]
);
scale
[
2
]
*
inputInducedDipolePolar
[
atomIndex
][
2
]);
RealOpenMM4
t
=
_thetai
[
0
][
atomIndex
*
AMOEBA_PME_ORDER
+
ix
];
RealOpenMM4
u
=
_thetai
[
1
][
atomIndex
*
AMOEBA_PME_ORDER
+
iy
];
...
...
@@ -5283,16 +5385,16 @@ t_complex AmoebaReferencePmeMultipoleForce::computeInducedDipoleGridValue( const
return
gridValue
;
}
void
AmoebaReferencePmeMultipoleForce
::
spreadInducedDipolesOnGrid
(
const
std
::
vector
<
RealVec
>&
inputInducedDipole
,
const
std
::
vector
<
RealVec
>&
inputInducedDipolePolar
)
void
AmoebaReferencePmeMultipoleForce
::
spreadInducedDipolesOnGrid
(
const
vector
<
RealVec
>&
inputInducedDipole
,
const
vector
<
RealVec
>&
inputInducedDipolePolar
)
{
RealVec
scale
;
getPmeScale
(
scale
);
getPmeScale
(
scale
);
for
(
int
gridIndex
=
0
;
gridIndex
<
_totalGridSize
;
gridIndex
++
)
for
(
int
gridIndex
=
0
;
gridIndex
<
_totalGridSize
;
gridIndex
++
)
{
IntVec
gridPoint
;
getGridPointGivenGridIndex
(
gridIndex
,
gridPoint
);
getGridPointGivenGridIndex
(
gridIndex
,
gridPoint
);
t_complex
gridValue
;
gridValue
.
re
=
gridValue
.
im
=
0.0
;
...
...
@@ -5310,13 +5412,13 @@ void AmoebaReferencePmeMultipoleForce::spreadInducedDipolesOnGrid( const std::ve
int2
particleGridIndices
;
particleGridIndices
[
0
]
=
x
*
_pmeGridDimensions
[
1
]
*
_pmeGridDimensions
[
2
]
+
y
*
_pmeGridDimensions
[
2
]
+
z1
;
particleGridIndices
[
1
]
=
x
*
_pmeGridDimensions
[
1
]
*
_pmeGridDimensions
[
2
]
+
y
*
_pmeGridDimensions
[
2
]
+
z2
;
gridValue
+=
computeInducedDipoleGridValue
(
particleGridIndices
,
scale
,
ix
,
iy
,
gridPoint
,
inputInducedDipole
,
inputInducedDipolePolar
);
gridValue
+=
computeInducedDipoleGridValue
(
particleGridIndices
,
scale
,
ix
,
iy
,
gridPoint
,
inputInducedDipole
,
inputInducedDipolePolar
);
if
(
z1
>
gridPoint
[
2
])
{
particleGridIndices
[
0
]
=
x
*
_pmeGridDimensions
[
1
]
*
_pmeGridDimensions
[
2
]
+
y
*
_pmeGridDimensions
[
2
];
particleGridIndices
[
1
]
=
x
*
_pmeGridDimensions
[
1
]
*
_pmeGridDimensions
[
2
]
+
y
*
_pmeGridDimensions
[
2
]
+
gridPoint
[
2
];
gridValue
+=
computeInducedDipoleGridValue
(
particleGridIndices
,
scale
,
ix
,
iy
,
gridPoint
,
inputInducedDipole
,
inputInducedDipolePolar
);
gridValue
+=
computeInducedDipoleGridValue
(
particleGridIndices
,
scale
,
ix
,
iy
,
gridPoint
,
inputInducedDipole
,
inputInducedDipolePolar
);
}
}
}
...
...
@@ -5326,7 +5428,7 @@ void AmoebaReferencePmeMultipoleForce::spreadInducedDipolesOnGrid( const std::ve
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
computeInducedPotentialFromGrid
(
void
)
void
AmoebaReferencePmeMultipoleForce
::
computeInducedPotentialFromGrid
()
{
// extract the induced dipole field at each site
...
...
@@ -5529,17 +5631,17 @@ void AmoebaReferencePmeMultipoleForce::computeInducedPotentialFromGrid( void )
return
;
}
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
computeReciprocalSpaceFixedMultipoleForceAndEnergy
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
)
const
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
computeReciprocalSpaceFixedMultipoleForceAndEnergy
(
const
vector
<
MultipoleParticleData
>&
particleData
,
vector
<
RealVec
>&
forces
,
vector
<
RealVec
>&
torques
)
const
{
RealOpenMM
multipole
[
10
];
const
int
deriv1
[]
=
{
1
,
4
,
7
,
8
,
10
,
15
,
17
,
13
,
14
,
19
};
const
int
deriv2
[]
=
{
2
,
7
,
5
,
9
,
13
,
11
,
18
,
15
,
19
,
16
};
const
int
deriv3
[]
=
{
3
,
8
,
9
,
6
,
14
,
16
,
12
,
19
,
17
,
18
};
RealVec
scale
;
getPmeScale
(
scale
);
getPmeScale
(
scale
);
RealOpenMM
energy
=
0.0
;
for
(
int
i
=
0
;
i
<
_numParticles
;
i
++
)
{
for
(
int
i
=
0
;
i
<
_numParticles
;
i
++
)
{
// Compute the torque.
...
...
@@ -5585,7 +5687,7 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceFixedMultipol
multipole
[
8
]
*=
scale
[
0
]
*
scale
[
2
];
multipole
[
9
]
*=
scale
[
1
]
*
scale
[
2
];
RealVec
f
=
RealVec
(
0.0
,
0.0
,
0.0
);
RealVec
f
=
RealVec
(
0.0
,
0.0
,
0.0
);
for
(
int
k
=
0
;
k
<
10
;
k
++
)
{
energy
+=
multipole
[
k
]
*
phi
[
k
];
f
[
0
]
+=
multipole
[
k
]
*
phi
[
deriv1
[
k
]];
...
...
@@ -5605,9 +5707,9 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceFixedMultipol
/**
* Compute the forces due to the reciprocal space PME calculation for induced dipoles.
*/
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
computeReciprocalSpaceInducedDipoleForceAndEnergy
(
AmoebaReferenceMultipoleForce
::
PolarizationType
polarizationType
,
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
)
const
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
computeReciprocalSpaceInducedDipoleForceAndEnergy
(
AmoebaReferenceMultipoleForce
::
PolarizationType
polarizationType
,
const
vector
<
MultipoleParticleData
>&
particleData
,
vector
<
RealVec
>&
forces
,
vector
<
RealVec
>&
torques
)
const
{
RealOpenMM
multipole
[
10
];
...
...
@@ -5618,9 +5720,9 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceInducedDipole
const
int
deriv2
[]
=
{
2
,
7
,
5
,
9
,
13
,
11
,
18
,
15
,
19
,
16
};
const
int
deriv3
[]
=
{
3
,
8
,
9
,
6
,
14
,
16
,
12
,
19
,
17
,
18
};
RealVec
scale
;
getPmeScale
(
scale
);
getPmeScale
(
scale
);
RealOpenMM
energy
=
0.0
;
for
(
int
i
=
0
;
i
<
_numParticles
;
i
++
)
{
for
(
int
i
=
0
;
i
<
_numParticles
;
i
++
)
{
// Compute the torque.
...
...
@@ -5679,7 +5781,7 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceInducedDipole
energy
+=
scale
[
1
]
*
inducedDipole
[
1
]
*
_phi
[
20
*
i
+
2
];
energy
+=
scale
[
2
]
*
inducedDipole
[
2
]
*
_phi
[
20
*
i
+
3
];
RealVec
f
=
RealVec
(
0.0
,
0.0
,
0.0
);
RealVec
f
=
RealVec
(
0.0
,
0.0
,
0.0
);
for
(
int
k
=
0
;
k
<
3
;
k
++
)
{
...
...
@@ -5691,7 +5793,7 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceInducedDipole
f
[
1
]
+=
(
inducedDipole
[
k
]
+
inducedDipolePolar
[
k
])
*
_phi
[
20
*
i
+
j2
]
*
(
scale
[
k
]
/
scale
[
1
]);
f
[
2
]
+=
(
inducedDipole
[
k
]
+
inducedDipolePolar
[
k
])
*
_phi
[
20
*
i
+
j3
]
*
(
scale
[
k
]
/
scale
[
2
]);
if
(
polarizationType
==
AmoebaReferenceMultipoleForce
::
Mutual
)
if
(
polarizationType
==
AmoebaReferenceMultipoleForce
::
Mutual
)
{
f
[
0
]
+=
(
inducedDipole
[
k
]
*
_phip
[
10
*
i
+
j1
]
+
inducedDipolePolar
[
k
]
*
_phid
[
10
*
i
+
j1
])
*
(
scale
[
k
]
/
scale
[
0
]);
f
[
1
]
+=
(
inducedDipole
[
k
]
*
_phip
[
10
*
i
+
j2
]
+
inducedDipolePolar
[
k
]
*
_phid
[
10
*
i
+
j2
])
*
(
scale
[
k
]
/
scale
[
1
]);
...
...
@@ -5719,12 +5821,12 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::computeReciprocalSpaceInducedDipole
return
(
0.5
*
_electric
*
energy
);
}
void
AmoebaReferencePmeMultipoleForce
::
recordFixedMultipoleField
(
void
)
void
AmoebaReferencePmeMultipoleForce
::
recordFixedMultipoleField
()
{
RealVec
scale
;
getPmeScale
(
scale
);
getPmeScale
(
scale
);
scale
*=
-
1.0
;
for
(
int
i
=
0
;
i
<
_numParticles
;
i
++
){
for
(
int
i
=
0
;
i
<
_numParticles
;
i
++
)
{
_fixedMultipoleField
[
i
][
0
]
=
scale
[
0
]
*
_phi
[
20
*
i
+
1
];
_fixedMultipoleField
[
i
][
1
]
=
scale
[
1
]
*
_phi
[
20
*
i
+
2
];
_fixedMultipoleField
[
i
][
2
]
=
scale
[
2
]
*
_phi
[
20
*
i
+
3
];
...
...
@@ -5732,20 +5834,20 @@ void AmoebaReferencePmeMultipoleForce::recordFixedMultipoleField( void )
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
initializeInducedDipoles
(
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
void
AmoebaReferencePmeMultipoleForce
::
initializeInducedDipoles
(
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
{
this
->
AmoebaReferenceMultipoleForce
::
initializeInducedDipoles
(
updateInducedDipoleFields
);
calculateReciprocalSpaceInducedDipoleField
(
updateInducedDipoleFields
);
this
->
AmoebaReferenceMultipoleForce
::
initializeInducedDipoles
(
updateInducedDipoleFields
);
calculateReciprocalSpaceInducedDipoleField
(
updateInducedDipoleFields
);
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
recordInducedDipoleField
(
vector
<
RealVec
>&
field
,
vector
<
RealVec
>&
fieldPolar
)
void
AmoebaReferencePmeMultipoleForce
::
recordInducedDipoleField
(
vector
<
RealVec
>&
field
,
vector
<
RealVec
>&
fieldPolar
)
{
RealVec
scale
;
getPmeScale
(
scale
);
getPmeScale
(
scale
);
scale
*=
-
1.0
;
for
(
int
i
=
0
;
i
<
_numParticles
;
i
++
)
{
for
(
int
i
=
0
;
i
<
_numParticles
;
i
++
)
{
field
[
i
][
0
]
+=
scale
[
0
]
*
_phid
[
10
*
i
+
1
];
field
[
i
][
1
]
+=
scale
[
1
]
*
_phid
[
10
*
i
+
2
];
...
...
@@ -5758,42 +5860,47 @@ void AmoebaReferencePmeMultipoleForce::recordInducedDipoleField( vector<RealVec>
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
calculateReciprocalSpaceInducedDipoleField
(
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
void
AmoebaReferencePmeMultipoleForce
::
calculateReciprocalSpaceInducedDipoleField
(
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
{
// Perform PME for the induced dipoles.
initializePmeGrid
();
spreadInducedDipolesOnGrid
(
*
(
updateInducedDipoleFields
[
0
].
inducedDipoles
)
,
*
(
updateInducedDipoleFields
[
1
].
inducedDipoles
)
)
;
fftpack_exec_3d
(
_fftplan
,
FFTPACK_FORWARD
,
_pmeGrid
,
_pmeGrid
);
spreadInducedDipolesOnGrid
(
*
updateInducedDipoleFields
[
0
].
inducedDipoles
,
*
updateInducedDipoleFields
[
1
].
inducedDipoles
);
fftpack_exec_3d
(
_fftplan
,
FFTPACK_FORWARD
,
_pmeGrid
,
_pmeGrid
);
performAmoebaReciprocalConvolution
();
fftpack_exec_3d
(
_fftplan
,
FFTPACK_BACKWARD
,
_pmeGrid
,
_pmeGrid
);
fftpack_exec_3d
(
_fftplan
,
FFTPACK_BACKWARD
,
_pmeGrid
,
_pmeGrid
);
computeInducedPotentialFromGrid
();
recordInducedDipoleField
(
updateInducedDipoleFields
[
0
].
inducedDipoleField
,
updateInducedDipoleFields
[
1
].
inducedDipoleField
);
recordInducedDipoleField
(
updateInducedDipoleFields
[
0
].
inducedDipoleField
,
updateInducedDipoleFields
[
1
].
inducedDipoleField
);
}
void
AmoebaReferencePmeMultipoleForce
::
calculateInducedDipoleFields
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
void
AmoebaReferencePmeMultipoleForce
::
calculateInducedDipoleFields
(
const
vector
<
MultipoleParticleData
>&
particleData
,
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
{
// Initialize the fields to zero.
RealVec
zeroVec
(
0.0
,
0.0
,
0.0
);
for
(
unsigned
int
ii
=
0
;
ii
<
updateInducedDipoleFields
.
size
();
ii
++
)
std
::
fill
(
updateInducedDipoleFields
[
ii
].
inducedDipoleField
.
begin
(),
updateInducedDipoleFields
[
ii
].
inducedDipoleField
.
end
(),
zeroVec
);
// direct space i
x
ns
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
){
for
(
unsigned
int
jj
=
ii
+
1
;
jj
<
particleData
.
size
();
jj
++
){
calculateDirectInducedDipolePairIxns
(
particleData
[
ii
],
particleData
[
jj
],
updateInducedDipoleFields
);
//
Add fields from
direct space i
nteractio
ns
.
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
)
{
for
(
unsigned
int
jj
=
ii
+
1
;
jj
<
particleData
.
size
();
jj
++
)
{
calculateDirectInducedDipolePairIxns
(
particleData
[
ii
],
particleData
[
jj
],
updateInducedDipoleFields
);
}
}
// reciprocal space ixns
calculateReciprocalSpaceInducedDipoleField
(
updateInducedDipoleFields
);
calculateReciprocalSpaceInducedDipoleField
(
updateInducedDipoleFields
);
// self ixn
RealOpenMM
term
=
(
4.0
/
3.0
)
*
(
_alphaEwald
*
_alphaEwald
*
_alphaEwald
)
/
SQRT_PI
;
for
(
unsigned
int
ii
=
0
;
ii
<
updateInducedDipoleFields
.
size
();
ii
++
){
vector
<
RealVec
>&
inducedDipoles
=
*
(
updateInducedDipoleFields
[
ii
].
inducedDipoles
)
;
for
(
unsigned
int
ii
=
0
;
ii
<
updateInducedDipoleFields
.
size
();
ii
++
)
{
vector
<
RealVec
>&
inducedDipoles
=
*
updateInducedDipoleFields
[
ii
].
inducedDipoles
;
vector
<
RealVec
>&
field
=
updateInducedDipoleFields
[
ii
].
inducedDipoleField
;
for
(
unsigned
int
jj
=
0
;
jj
<
particleData
.
size
();
jj
++
){
for
(
unsigned
int
jj
=
0
;
jj
<
particleData
.
size
();
jj
++
)
{
field
[
jj
]
+=
inducedDipoles
[
jj
]
*
term
;
}
}
...
...
@@ -5801,29 +5908,29 @@ void AmoebaReferencePmeMultipoleForce::calculateInducedDipoleFields( const std::
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
calculateDirectInducedDipolePairIxn
(
unsigned
int
iIndex
,
unsigned
int
jIndex
,
RealOpenMM
preFactor1
,
RealOpenMM
preFactor2
,
const
RealVec
&
delta
,
const
std
::
vector
<
RealVec
>&
inducedDipole
,
std
::
vector
<
RealVec
>&
field
)
const
void
AmoebaReferencePmeMultipoleForce
::
calculateDirectInducedDipolePairIxn
(
unsigned
int
iIndex
,
unsigned
int
jIndex
,
RealOpenMM
preFactor1
,
RealOpenMM
preFactor2
,
const
RealVec
&
delta
,
const
vector
<
RealVec
>&
inducedDipole
,
vector
<
RealVec
>&
field
)
const
{
// field at i due induced dipole at j
RealOpenMM
dur
=
inducedDipole
[
jIndex
].
dot
(
delta
);
RealOpenMM
dur
=
inducedDipole
[
jIndex
].
dot
(
delta
);
field
[
iIndex
]
+=
delta
*
(
dur
*
preFactor2
)
+
inducedDipole
[
jIndex
]
*
preFactor1
;
// field at j due induced dipole at i
dur
=
inducedDipole
[
iIndex
].
dot
(
delta
);
dur
=
inducedDipole
[
iIndex
].
dot
(
delta
);
field
[
jIndex
]
+=
delta
*
(
dur
*
preFactor2
)
+
inducedDipole
[
iIndex
]
*
preFactor1
;
return
;
}
void
AmoebaReferencePmeMultipoleForce
::
calculateDirectInducedDipolePairIxns
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
void
AmoebaReferencePmeMultipoleForce
::
calculateDirectInducedDipolePairIxns
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
)
{
// compute the real space portion of the Ewald summation
...
...
@@ -5833,10 +5940,10 @@ void AmoebaReferencePmeMultipoleForce::calculateDirectInducedDipolePairIxns( con
// periodic boundary conditions
getPeriodicDelta
(
deltaR
);
RealOpenMM
r2
=
deltaR
.
dot
(
deltaR
);
getPeriodicDelta
(
deltaR
);
RealOpenMM
r2
=
deltaR
.
dot
(
deltaR
);
if
(
r2
>
_cutoffDistanceSquared
)
return
;
if
(
r2
>
_cutoffDistanceSquared
)
return
;
RealOpenMM
r
=
SQRT
(
r2
);
...
...
@@ -5859,14 +5966,14 @@ void AmoebaReferencePmeMultipoleForce::calculateDirectInducedDipolePairIxns( con
RealOpenMM
scale3
=
1.0
;
RealOpenMM
scale5
=
1.0
;
RealOpenMM
damp
=
particleI
.
dampingFactor
*
particleJ
.
dampingFactor
;
if
(
damp
!=
0.0
){
if
(
damp
!=
0.0
)
{
RealOpenMM
ratio
=
(
r
/
damp
);
ratio
=
ratio
*
ratio
*
ratio
;
RealOpenMM
pgamma
=
particleI
.
thole
<
particleJ
.
thole
?
particleI
.
thole
:
particleJ
.
thole
;
damp
=
-
pgamma
*
ratio
;
if
(
damp
>
-
50.0
)
{
if
(
damp
>
-
50.0
)
{
RealOpenMM
expdamp
=
expf
(
damp
);
scale3
=
1.0
-
expdamp
;
scale5
=
1.0
-
expdamp
*
(
1.0
-
damp
);
...
...
@@ -5883,27 +5990,27 @@ void AmoebaReferencePmeMultipoleForce::calculateDirectInducedDipolePairIxns( con
RealOpenMM
preFactor1
=
rr3
-
bn1
;
RealOpenMM
preFactor2
=
bn2
-
rr5
;
for
(
unsigned
int
ii
=
0
;
ii
<
updateInducedDipoleFields
.
size
();
ii
++
){
calculateDirectInducedDipolePairIxn
(
particleI
.
particleIndex
,
particleJ
.
particleIndex
,
preFactor1
,
preFactor2
,
deltaR
,
*
(
updateInducedDipoleFields
[
ii
].
inducedDipoles
)
,
updateInducedDipoleFields
[
ii
].
inducedDipoleField
);
for
(
unsigned
int
ii
=
0
;
ii
<
updateInducedDipoleFields
.
size
();
ii
++
)
{
calculateDirectInducedDipolePairIxn
(
particleI
.
particleIndex
,
particleJ
.
particleIndex
,
preFactor1
,
preFactor2
,
deltaR
,
*
updateInducedDipoleFields
[
ii
].
inducedDipoles
,
updateInducedDipoleFields
[
ii
].
inducedDipoleField
);
}
return
;
}
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
calculatePmeSelfEnergy
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
)
const
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
calculatePmeSelfEnergy
(
const
vector
<
MultipoleParticleData
>&
particleData
)
const
{
RealOpenMM
cii
=
0.0
;
RealOpenMM
dii
=
0.0
;
RealOpenMM
qii
=
0.0
;
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
const
MultipoleParticleData
&
particleI
=
particleData
[
ii
];
cii
+=
particleI
.
charge
*
particleI
.
charge
;
dii
+=
particleI
.
dipole
.
dot
(
particleI
.
dipole
+
_inducedDipole
[
ii
]
)
;
dii
+=
particleI
.
dipole
.
dot
(
particleI
.
dipole
+
_inducedDipole
[
ii
])
;
qii
+=
particleI
.
quadrupole
[
QXX
]
*
particleI
.
quadrupole
[
QXX
]
+
particleI
.
quadrupole
[
QYY
]
*
particleI
.
quadrupole
[
QYY
]
+
...
...
@@ -5921,28 +6028,28 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::calculatePmeSelfEnergy( const std::
return
energy
;
}
void
AmoebaReferencePmeMultipoleForce
::
calculatePmeSelfTorque
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
RealVec
>&
torques
)
const
void
AmoebaReferencePmeMultipoleForce
::
calculatePmeSelfTorque
(
const
vector
<
MultipoleParticleData
>&
particleData
,
vector
<
RealVec
>&
torques
)
const
{
RealOpenMM
term
=
(
2.0
/
3.0
)
*
(
_electric
/
_dielectric
)
*
(
_alphaEwald
*
_alphaEwald
*
_alphaEwald
)
/
SQRT_PI
;
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
_numParticles
;
ii
++
)
{
const
MultipoleParticleData
&
particleI
=
particleData
[
ii
];
RealVec
ui
=
(
_inducedDipole
[
ii
]
+
_inducedDipolePolar
[
ii
]);
RealVec
torque
=
particleI
.
dipole
.
cross
(
ui
);
RealVec
torque
=
particleI
.
dipole
.
cross
(
ui
);
torque
*=
term
;
torques
[
ii
]
+=
torque
;
}
return
;
}
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
calculatePmeDirectElectrostaticPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
const
std
::
vector
<
RealOpenMM
>&
scalingFactors
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
)
const
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
calculatePmeDirectElectrostaticPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
const
vector
<
RealOpenMM
>&
scalingFactors
,
vector
<
RealVec
>&
forces
,
vector
<
RealVec
>&
torques
)
const
{
unsigned
int
iIndex
=
particleI
.
particleIndex
;
...
...
@@ -5950,10 +6057,10 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::calculatePmeDirectElectrostaticPair
RealOpenMM
energy
;
RealVec
deltaR
=
particleJ
.
position
-
particleI
.
position
;
getPeriodicDelta
(
deltaR
);
RealOpenMM
r2
=
deltaR
.
dot
(
deltaR
);
getPeriodicDelta
(
deltaR
);
RealOpenMM
r2
=
deltaR
.
dot
(
deltaR
);
if
(
r2
>
_cutoffDistanceSquared
)
return
0.0
;
if
(
r2
>
_cutoffDistanceSquared
)
return
0.0
;
RealOpenMM
xr
=
deltaR
[
0
];
RealOpenMM
yr
=
deltaR
[
1
];
...
...
@@ -5995,7 +6102,7 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::calculatePmeDirectElectrostaticPair
RealOpenMM
alsq2
=
2.0
*
_alphaEwald
*
_alphaEwald
;
RealOpenMM
alsq2n
=
0.0
;
if
(
_alphaEwald
>
0.0
){
if
(
_alphaEwald
>
0.0
)
{
alsq2n
=
1.0
/
(
SQRT_PI
*
_alphaEwald
);
}
RealOpenMM
exp2a
=
EXP
(
-
(
ralpha
*
ralpha
));
...
...
@@ -6041,11 +6148,11 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::calculatePmeDirectElectrostaticPair
RealOpenMM
ddsc73
=
0.0
;
RealOpenMM
damp
=
particleI
.
dampingFactor
*
particleJ
.
dampingFactor
;
if
(
damp
!=
0.0
){
if
(
damp
!=
0.0
)
{
RealOpenMM
pgamma
=
particleI
.
thole
<
particleJ
.
thole
?
particleI
.
thole
:
particleJ
.
thole
;
RealOpenMM
ratio
=
r
/
damp
;
damp
=
-
pgamma
*
ratio
*
ratio
*
ratio
;
if
(
damp
>
-
50.0
){
if
(
damp
>
-
50.0
)
{
RealOpenMM
expdamp
=
EXP
(
damp
);
scale3
=
1.0
-
expdamp
;
scale5
=
1.0
-
(
1.0
-
damp
)
*
expdamp
;
...
...
@@ -6471,7 +6578,7 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::calculatePmeDirectElectrostaticPair
// correction to convert mutual to direct polarization force
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Direct
){
if
(
getPolarizationType
()
==
AmoebaReferenceMultipoleForce
::
Direct
)
{
RealOpenMM
gfd
=
0.5
*
(
bn2
*
scip2
-
bn3
*
(
scip3
*
sci4
+
sci3
*
scip4
));
ftm2i1
-=
gfd
*
xr
+
0.5
*
bn2
*
(
sci4
*
_inducedDipolePolar
[
iIndex
][
0
]
+
scip4
*
_inducedDipole
[
iIndex
][
0
]
+
sci3
*
_inducedDipolePolar
[
jIndex
][
0
]
+
scip3
*
_inducedDipole
[
jIndex
][
0
]);
...
...
@@ -6634,39 +6741,39 @@ RealOpenMM AmoebaReferencePmeMultipoleForce::calculatePmeDirectElectrostaticPair
}
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
calculateElectrostatic
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
RealVec
>&
torques
,
std
::
vector
<
RealVec
>&
forces
)
RealOpenMM
AmoebaReferencePmeMultipoleForce
::
calculateElectrostatic
(
const
vector
<
MultipoleParticleData
>&
particleData
,
vector
<
RealVec
>&
torques
,
vector
<
RealVec
>&
forces
)
{
RealOpenMM
energy
=
0.0
;
std
::
vector
<
RealOpenMM
>
scaleFactors
(
LAST_SCALE_TYPE_INDEX
);
for
(
unsigned
int
kk
=
0
;
kk
<
scaleFactors
.
size
();
kk
++
){
vector
<
RealOpenMM
>
scaleFactors
(
LAST_SCALE_TYPE_INDEX
);
for
(
unsigned
int
kk
=
0
;
kk
<
scaleFactors
.
size
();
kk
++
)
{
scaleFactors
[
kk
]
=
1.0
;
}
// loop over particle pairs for direct space interactions
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
){
for
(
unsigned
int
jj
=
ii
+
1
;
jj
<
particleData
.
size
();
jj
++
){
for
(
unsigned
int
ii
=
0
;
ii
<
particleData
.
size
();
ii
++
)
{
for
(
unsigned
int
jj
=
ii
+
1
;
jj
<
particleData
.
size
();
jj
++
)
{
if
(
jj
<=
_maxScaleIndex
[
ii
]
){
getMultipoleScaleFactors
(
ii
,
jj
,
scaleFactors
);
if
(
jj
<=
_maxScaleIndex
[
ii
])
{
getMultipoleScaleFactors
(
ii
,
jj
,
scaleFactors
);
}
energy
+=
calculatePmeDirectElectrostaticPairIxn
(
particleData
[
ii
],
particleData
[
jj
],
scaleFactors
,
forces
,
torques
);
energy
+=
calculatePmeDirectElectrostaticPairIxn
(
particleData
[
ii
],
particleData
[
jj
],
scaleFactors
,
forces
,
torques
);
if
(
jj
<=
_maxScaleIndex
[
ii
]
){
for
(
unsigned
int
kk
=
0
;
kk
<
LAST_SCALE_TYPE_INDEX
;
kk
++
){
if
(
jj
<=
_maxScaleIndex
[
ii
])
{
for
(
unsigned
int
kk
=
0
;
kk
<
LAST_SCALE_TYPE_INDEX
;
kk
++
)
{
scaleFactors
[
kk
]
=
1.0
;
}
}
}
}
calculatePmeSelfTorque
(
particleData
,
torques
);
energy
+=
computeReciprocalSpaceInducedDipoleForceAndEnergy
(
getPolarizationType
(),
particleData
,
forces
,
torques
);
energy
+=
computeReciprocalSpaceFixedMultipoleForceAndEnergy
(
particleData
,
forces
,
torques
);
energy
+=
calculatePmeSelfEnergy
(
particleData
);
calculatePmeSelfTorque
(
particleData
,
torques
);
energy
+=
computeReciprocalSpaceInducedDipoleForceAndEnergy
(
getPolarizationType
(),
particleData
,
forces
,
torques
);
energy
+=
computeReciprocalSpaceFixedMultipoleForceAndEnergy
(
particleData
,
forces
,
torques
);
energy
+=
calculatePmeSelfEnergy
(
particleData
);
return
energy
;
}
plugins/amoeba/platforms/reference/src/SimTKReference/AmoebaReferenceMultipoleForce.h
View file @
8db70d34
/* Portions copyright (c) 2006 Stanford University and Simbios.
/* Portions copyright (c) 2006
-2014
Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
...
...
@@ -129,7 +129,7 @@ public:
// plus
IntVec
operator
+
(
const
IntVec
&
rhs
)
const
{
const
IntVec
&
lhs
=
*
this
;
return
IntVec
(
lhs
[
0
]
+
rhs
[
0
],
lhs
[
1
]
+
rhs
[
1
],
lhs
[
2
]
+
rhs
[
2
]
);
return
IntVec
(
lhs
[
0
]
+
rhs
[
0
],
lhs
[
1
]
+
rhs
[
1
],
lhs
[
2
]
+
rhs
[
2
]);
}
IntVec
&
operator
+=
(
const
IntVec
&
rhs
)
{
...
...
@@ -339,48 +339,48 @@ public:
* Constructor
*
*/
AmoebaReferenceMultipoleForce
(
);
AmoebaReferenceMultipoleForce
();
/**
* Constructor
*
* @param nonbondedMethod nonbonded method
*/
AmoebaReferenceMultipoleForce
(
NonbondedMethod
nonbondedMethod
);
AmoebaReferenceMultipoleForce
(
NonbondedMethod
nonbondedMethod
);
/**
* Destructor
*
*/
virtual
~
AmoebaReferenceMultipoleForce
(
){};
virtual
~
AmoebaReferenceMultipoleForce
(){};
/**
* Get nonbonded method.
*
* @return nonbonded method
*/
NonbondedMethod
getNonbondedMethod
(
void
)
const
;
NonbondedMethod
getNonbondedMethod
()
const
;
/**
* Set nonbonded method.
*
* @param nonbondedMethod nonbonded method
*/
void
setNonbondedMethod
(
NonbondedMethod
nonbondedMethod
);
void
setNonbondedMethod
(
NonbondedMethod
nonbondedMethod
);
/**
* Get polarization type.
*
* @return polarization type
*/
PolarizationType
getPolarizationType
(
void
)
const
;
PolarizationType
getPolarizationType
()
const
;
/**
* Set polarization type.
*
* @param polarizationType polarization type
*/
void
setPolarizationType
(
PolarizationType
polarizationType
);
void
setPolarizationType
(
PolarizationType
polarizationType
);
/**
* Get flag indicating if mutual induced dipoles are converged.
...
...
@@ -388,7 +388,7 @@ public:
* @return nonzero if converged
*
*/
int
getMutualInducedDipoleConverged
(
void
)
const
;
int
getMutualInducedDipoleConverged
()
const
;
/**
* Get the number of iterations used in computing mutual induced dipoles.
...
...
@@ -396,7 +396,7 @@ public:
* @return number of iterations
*
*/
int
getMutualInducedDipoleIterations
(
void
)
const
;
int
getMutualInducedDipoleIterations
()
const
;
/**
* Get the final epsilon for mutual induced dipoles.
...
...
@@ -404,7 +404,7 @@ public:
* @return epsilon
*
*/
RealOpenMM
getMutualInducedDipoleEpsilon
(
void
)
const
;
RealOpenMM
getMutualInducedDipoleEpsilon
()
const
;
/**
* Set the target epsilon for converging mutual induced dipoles.
...
...
@@ -412,7 +412,7 @@ public:
* @param targetEpsilon target epsilon for converging mutual induced dipoles
*
*/
void
setMutualInducedDipoleTargetEpsilon
(
RealOpenMM
targetEpsilon
);
void
setMutualInducedDipoleTargetEpsilon
(
RealOpenMM
targetEpsilon
);
/**
* Get the target epsilon for converging mutual induced dipoles.
...
...
@@ -420,7 +420,7 @@ public:
* @return target epsilon for converging mutual induced dipoles
*
*/
RealOpenMM
getMutualInducedDipoleTargetEpsilon
(
void
)
const
;
RealOpenMM
getMutualInducedDipoleTargetEpsilon
()
const
;
/**
* Set the maximum number of iterations to be executed in converging mutual induced dipoles.
...
...
@@ -428,7 +428,7 @@ public:
* @param maximumMutualInducedDipoleIterations maximum number of iterations to be executed in converging mutual induced dipoles
*
*/
void
setMaximumMutualInducedDipoleIterations
(
int
maximumMutualInducedDipoleIterations
);
void
setMaximumMutualInducedDipoleIterations
(
int
maximumMutualInducedDipoleIterations
);
/**
* Get the maximum number of iterations to be executed in converging mutual induced dipoles.
...
...
@@ -436,7 +436,7 @@ public:
* @return maximum number of iterations to be executed in converging mutual induced dipoles
*
*/
int
getMaximumMutualInducedDipoleIterations
(
void
)
const
;
int
getMaximumMutualInducedDipoleIterations
()
const
;
/**
* Calculate force and energy.
...
...
@@ -448,7 +448,7 @@ public:
* @param tholes Thole factors for each particle
* @param dampingFactors damping factors for each particle
* @param polarity polarity for each particle
* @param axisTypes axis type (Z-then-X, ...
) for each particle
* @param axisTypes axis type (Z-then-X, ...) for each particle
* @param multipoleAtomZs indicies of particle specifying the molecular frame z-axis for each particle
* @param multipoleAtomXs indicies of particle specifying the molecular frame x-axis for each particle
* @param multipoleAtomYs indicies of particle specifying the molecular frame y-axis for each particle
...
...
@@ -457,19 +457,19 @@ public:
*
* @return energy
*/
RealOpenMM
calculateForceAndEnergy
(
const
std
::
vector
<
OpenMM
::
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
);
RealOpenMM
calculateForceAndEnergy
(
const
std
::
vector
<
OpenMM
::
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
);
/**
* Calculate particle induced dipoles.
...
...
@@ -482,7 +482,7 @@ public:
* @param tholes Thole factors for each particle
* @param dampingFactors dampling factors for each particle
* @param polarity polarity for each particle
* @param axisTypes axis type (Z-then-X, ...
) for each particle
* @param axisTypes axis type (Z-then-X, ...) for each particle
* @param multipoleAtomZs indicies of particle specifying the molecular frame z-axis for each particle
* @param multipoleAtomXs indicies of particle specifying the molecular frame x-axis for each particle
* @param multipoleAtomYs indicies of particle specifying the molecular frame y-axis for each particle
...
...
@@ -514,27 +514,27 @@ public:
* @param tholes Thole factors for each particle
* @param dampingFactors dampling factors for each particle
* @param polarity polarity for each particle
* @param axisTypes axis type (Z-then-X, ...
) for each particle
* @param axisTypes axis type (Z-then-X, ...) for each particle
* @param multipoleAtomZs indicies of particle specifying the molecular frame z-axis for each particle
* @param multipoleAtomXs indicies of particle specifying the molecular frame x-axis for each particle
* @param multipoleAtomYs indicies of particle specifying the molecular frame y-axis for each particle
* @param multipoleAtomCovalentInfo covalent info needed to set scaling factors
* @param outputMultipoleMoments output multipole moments
*/
void
calculateAmoebaSystemMultipoleMoments
(
const
std
::
vector
<
RealOpenMM
>&
masses
,
const
std
::
vector
<
OpenMM
::
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
std
::
vector
<
RealOpenMM
>&
outputMultipoleMoments
);
void
calculateAmoebaSystemMultipoleMoments
(
const
std
::
vector
<
RealOpenMM
>&
masses
,
const
std
::
vector
<
OpenMM
::
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
std
::
vector
<
RealOpenMM
>&
outputMultipoleMoments
);
/**
* Calculate electrostatic potential at a set of grid points.
...
...
@@ -546,7 +546,7 @@ public:
* @param tholes Thole factors for each particle
* @param dampingFactors dampling factors for each particle
* @param polarity polarity for each particle
* @param axisTypes axis type (Z-then-X, ...
) for each particle
* @param axisTypes axis type (Z-then-X, ...) for each particle
* @param multipoleAtomZs indicies of particle specifying the molecular frame z-axis for each particle
* @param multipoleAtomXs indicies of particle specifying the molecular frame x-axis for each particle
* @param multipoleAtomYs indicies of particle specifying the molecular frame y-axis for each particle
...
...
@@ -554,20 +554,20 @@ public:
* @param input grid input grid points to compute potential
* @param outputPotential output electrostatic potential
*/
void
calculateElectrostaticPotential
(
const
std
::
vector
<
OpenMM
::
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
const
std
::
vector
<
RealVec
>&
inputGrid
,
std
::
vector
<
RealOpenMM
>&
outputPotential
);
void
calculateElectrostaticPotential
(
const
std
::
vector
<
OpenMM
::
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
const
std
::
vector
<
RealVec
>&
inputGrid
,
std
::
vector
<
RealOpenMM
>&
outputPotential
);
protected:
...
...
@@ -596,7 +596,7 @@ protected:
* Helper class used in calculating induced dipoles
*/
struct
UpdateInducedDipoleFieldStruct
{
UpdateInducedDipoleFieldStruct
(
std
::
vector
<
OpenMM
::
RealVec
>
*
inputFixed_E_Field
,
std
::
vector
<
OpenMM
::
RealVec
>
*
inputInducedDipoles
);
UpdateInducedDipoleFieldStruct
(
std
::
vector
<
OpenMM
::
RealVec
>
&
inputFixed_E_Field
,
std
::
vector
<
OpenMM
::
RealVec
>
&
inputInducedDipoles
);
std
::
vector
<
OpenMM
::
RealVec
>*
fixedMultipoleField
;
std
::
vector
<
OpenMM
::
RealVec
>*
inducedDipoles
;
std
::
vector
<
OpenMM
::
RealVec
>
inducedDipoleField
;
...
...
@@ -635,7 +635,7 @@ protected:
* Helper constructor method to centralize initialization of objects.
*
*/
void
initialize
(
void
);
void
initialize
();
/**
* Load particle data.
...
...
@@ -650,14 +650,14 @@ protected:
* @param particleData output data struct
*
*/
void
loadParticleData
(
const
std
::
vector
<
OpenMM
::
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
std
::
vector
<
MultipoleParticleData
>&
particleData
)
const
;
void
loadParticleData
(
const
std
::
vector
<
OpenMM
::
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
std
::
vector
<
MultipoleParticleData
>&
particleData
)
const
;
/**
* Calculate fixed multipole fields.
...
...
@@ -665,7 +665,7 @@ protected:
* @param particleData vector of particle data
*
*/
virtual
void
calculateFixedMultipoleField
(
const
vector
<
MultipoleParticleData
>&
particleData
);
virtual
void
calculateFixedMultipoleField
(
const
vector
<
MultipoleParticleData
>&
particleData
);
/**
* Set flag indicating if mutual induced dipoles are converged.
...
...
@@ -673,7 +673,7 @@ protected:
* @param converged nonzero if converged
*
*/
void
setMutualInducedDipoleConverged
(
int
converged
);
void
setMutualInducedDipoleConverged
(
int
converged
);
/**
* Set number of iterations used in computing mutual induced dipoles.
...
...
@@ -681,7 +681,7 @@ protected:
* @param number of iterations
*
*/
void
setMutualInducedDipoleIterations
(
int
iterations
);
void
setMutualInducedDipoleIterations
(
int
iterations
);
/**
* Set the final epsilon for mutual induced dipoles.
...
...
@@ -689,7 +689,7 @@ protected:
* @param epsilon
*
*/
void
setMutualInducedDipoleEpsilon
(
RealOpenMM
epsilon
);
void
setMutualInducedDipoleEpsilon
(
RealOpenMM
epsilon
);
/**
* Setup scale factors given covalent info.
...
...
@@ -697,7 +697,7 @@ protected:
* @param multipoleAtomCovalentInfo vector of vectors containing the covalent info
*
*/
void
setupScaleMaps
(
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
);
void
setupScaleMaps
(
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
);
/**
* Show scaling factor map
...
...
@@ -706,7 +706,7 @@ protected:
* @param log output destination
*
*/
void
showScaleMapForParticle
(
unsigned
int
particleI
,
FILE
*
log
)
const
;
void
showScaleMapForParticle
(
unsigned
int
particleI
,
FILE
*
log
)
const
;
/**
* Get multipole scale factor for particleI & particleJ
...
...
@@ -717,7 +717,7 @@ protected:
*
* @return scaleFactor
*/
RealOpenMM
getMultipoleScaleFactor
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
ScaleType
scaleType
)
const
;
RealOpenMM
getMultipoleScaleFactor
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
ScaleType
scaleType
)
const
;
/**
* Get scale factor for particleI & particleJ
...
...
@@ -728,7 +728,7 @@ protected:
*
* @return array of scaleFactors
*/
void
getMultipoleScaleFactors
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
std
::
vector
<
RealOpenMM
>&
scaleFactors
)
const
;
void
getMultipoleScaleFactors
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
std
::
vector
<
RealOpenMM
>&
scaleFactors
)
const
;
/**
* Get p- and d-scale factors for particleI & particleJ ixn
...
...
@@ -738,7 +738,7 @@ protected:
* @param dScale output d-scale factor
* @param pScale output p-scale factor
*/
void
getDScaleAndPScale
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
RealOpenMM
&
dScale
,
RealOpenMM
&
pScale
)
const
;
void
getDScaleAndPScale
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
RealOpenMM
&
dScale
,
RealOpenMM
&
pScale
)
const
;
/**
* Calculate damped powers of 1/r.
...
...
@@ -748,8 +748,8 @@ protected:
* @param dScale output d-scale factor
* @param pScale output p-scale factor
*/
void
getAndScaleInverseRs
(
RealOpenMM
dampI
,
RealOpenMM
dampJ
,
RealOpenMM
tholeI
,
RealOpenMM
tholeJ
,
RealOpenMM
r
,
std
::
vector
<
RealOpenMM
>&
rrI
)
const
;
void
getAndScaleInverseRs
(
RealOpenMM
dampI
,
RealOpenMM
dampJ
,
RealOpenMM
tholeI
,
RealOpenMM
tholeJ
,
RealOpenMM
r
,
std
::
vector
<
RealOpenMM
>&
rrI
)
const
;
/**
* Check if multipoles at chiral site should be inverted.
...
...
@@ -761,8 +761,8 @@ protected:
* @param particleY y-axis particle to particleI
*
*/
void
checkChiralCenterAtParticle
(
MultipoleParticleData
&
particleI
,
int
axisType
,
MultipoleParticleData
&
particleZ
,
MultipoleParticleData
&
particleX
,
MultipoleParticleData
&
particleY
)
const
;
void
checkChiralCenterAtParticle
(
MultipoleParticleData
&
particleI
,
int
axisType
,
MultipoleParticleData
&
particleZ
,
MultipoleParticleData
&
particleX
,
MultipoleParticleData
&
particleY
)
const
;
/**
* Invert multipole moments (dipole[Y], quadrupole[XY] and quadrupole[YZ]) if chiral center inverted.
...
...
@@ -773,11 +773,11 @@ protected:
* @param multipoleAtomZs vector of y-particle indices used to map molecular frame to lab frame
* @param axisType axis type
*/
void
checkChiral
(
std
::
vector
<
MultipoleParticleData
>&
particleData
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
axisTypes
)
const
;
void
checkChiral
(
std
::
vector
<
MultipoleParticleData
>&
particleData
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
axisTypes
)
const
;
/**
* Apply rotation matrix to molecular dipole/quadrupoles to get corresponding lab frame values
* for particle I.
...
...
@@ -786,10 +786,10 @@ protected:
* @param particleJ particleI data
* @param axisType axis type
*/
void
applyRotationMatrixToParticle
(
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleZ
,
const
MultipoleParticleData
&
particleX
,
MultipoleParticleData
*
particleY
,
int
axisType
)
const
;
void
applyRotationMatrixToParticle
(
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleZ
,
const
MultipoleParticleData
&
particleX
,
MultipoleParticleData
*
particleY
,
int
axisType
)
const
;
/**
* Apply rotation matrix to molecular dipole/quadrupoles to get corresponding lab frame values.
...
...
@@ -801,15 +801,15 @@ protected:
* @param multipoleAtomZs vector of y-particle indices used to map molecular frame to lab frame
* @param axisType axis type
*/
void
applyRotationMatrix
(
std
::
vector
<
MultipoleParticleData
>&
particleData
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
axisTypes
)
const
;
void
applyRotationMatrix
(
std
::
vector
<
MultipoleParticleData
>&
particleData
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
axisTypes
)
const
;
/**
* Zero fixed multipole fields.
*/
virtual
void
zeroFixedMultipoleFields
(
void
);
virtual
void
zeroFixedMultipoleFields
();
/**
* Calculate electric field at particle I due fixed multipoles at particle J and vice versa
...
...
@@ -820,15 +820,15 @@ protected:
* @param dScale d-scale value for i-j interaction
* @param pScale p-scale value for i-j interaction
*/
virtual
void
calculateFixedMultipoleFieldPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dScale
,
RealOpenMM
pScale
);
virtual
void
calculateFixedMultipoleFieldPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dScale
,
RealOpenMM
pScale
);
/**
* Initialize induced dipoles
*
* @param updateInducedDipoleFields vector of UpdateInducedDipoleFieldStruct containing input induced dipoles and output fields
*/
virtual
void
initializeInducedDipoles
(
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
virtual
void
initializeInducedDipoles
(
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
/**
* Calculate field at particle I due induced dipole at particle J and vice versa
...
...
@@ -842,10 +842,10 @@ protected:
* @param inducedDipole vector of induced dipoles
* @param field vector of induced dipole fields
*/
void
calculateInducedDipolePairIxn
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
RealOpenMM
rr3
,
RealOpenMM
rr5
,
const
RealVec
&
delta
,
const
std
::
vector
<
RealVec
>&
inducedDipole
,
std
::
vector
<
RealVec
>&
field
)
const
;
void
calculateInducedDipolePairIxn
(
unsigned
int
particleI
,
unsigned
int
particleJ
,
RealOpenMM
rr3
,
RealOpenMM
rr5
,
const
RealVec
&
delta
,
const
std
::
vector
<
RealVec
>&
inducedDipole
,
std
::
vector
<
RealVec
>&
field
)
const
;
/**
* Calculate fields due induced dipoles at each site.
...
...
@@ -854,8 +854,8 @@ protected:
* @param particleJ positions and parameters (charge, labFrame dipoles, quadrupoles, ...) for particle J
* @param updateInducedDipoleFields vector of UpdateInducedDipoleFieldStruct containing input induced dipoles and output fields
*/
virtual
void
calculateInducedDipolePairIxns
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
virtual
void
calculateInducedDipolePairIxns
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
/**
* Calculate induced dipole fields.
...
...
@@ -863,16 +863,32 @@ protected:
* @param particleData vector of particle positions and parameters (charge, labFrame dipoles, quadrupoles, ...)
* @param updateInducedDipoleFields vector of UpdateInducedDipoleFieldStruct containing input induced dipoles and output fields
*/
virtual
void
calculateInducedDipoleFields
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
virtual
void
calculateInducedDipoleFields
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
/**
* Converge induced dipoles.
*
* @param particleData vector of particle positions and parameters (charge, labFrame dipoles, quadrupoles, ...)
* @param updateInducedDipoleFields vector of UpdateInducedDipoleFieldStruct containing input induced dipoles and output fields
*/
void
convergeInduceDipoles
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
calculateInducedDipoleField
);
void
convergeInduceDipolesBySOR
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
calculateInducedDipoleField
);
/**
* Converge induced dipoles.
*
* @param particleData vector of particle positions and parameters (charge, labFrame dipoles, quadrupoles, ...)
* @param updateInducedDipoleFields vector of UpdateInducedDipoleFieldStruct containing input induced dipoles and output fields
*/
void
convergeInduceDipolesByDIIS
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
calculateInducedDipoleField
);
/**
* Use DIIS to compute the weighting coefficients for the new induced dipoles.
*
* @param prevErrors the vector of errors from previous iterations
* @param coefficients the coefficients will be stored into this
*/
void
computeDIISCoefficients
(
const
std
::
vector
<
std
::
vector
<
RealVec
>
>&
prevErrors
,
std
::
vector
<
RealOpenMM
>&
coefficients
)
const
;
/**
* Update fields due to induced dipoles for each particle.
...
...
@@ -880,8 +896,8 @@ protected:
* @param particleData vector of particle positions and parameters (charge, labFrame dipoles, quadrupoles, ...)
* @param updateInducedDipoleFields vector of UpdateInducedDipoleFieldStruct containing input induced dipoles and output fields
*/
RealOpenMM
updateInducedDipoleFields
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
calculateInducedDipoleField
);
RealOpenMM
updateInducedDipoleFields
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
calculateInducedDipoleField
);
/**
* Update induced dipole for a particle given updated induced dipole field at the site.
...
...
@@ -891,17 +907,17 @@ protected:
* @param inducedDipoleField fields due induced dipoles at each site
* @param inducedDipoles output vector of updated induced dipoles
*/
RealOpenMM
updateInducedDipole
(
const
std
::
vector
<
MultipoleParticleData
>&
particleI
,
const
std
::
vector
<
RealVec
>&
fixedMultipoleField
,
const
std
::
vector
<
RealVec
>&
inducedDipoleField
,
std
::
vector
<
RealVec
>&
inducedDipoles
);
RealOpenMM
updateInducedDipole
(
const
std
::
vector
<
MultipoleParticleData
>&
particleI
,
const
std
::
vector
<
RealVec
>&
fixedMultipoleField
,
const
std
::
vector
<
RealVec
>&
inducedDipoleField
,
std
::
vector
<
RealVec
>&
inducedDipoles
);
/**
* Calculate induced dipoles.
*
* @param particleData vector of particle positions and parameters (charge, labFrame dipoles, quadrupoles, ...)
*/
virtual
void
calculateInducedDipoles
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
);
virtual
void
calculateInducedDipoles
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
);
/**
* Setup:
...
...
@@ -917,7 +933,7 @@ protected:
* @param tholes Thole factors for each particle
* @param dampingFactors dampling factors for each particle
* @param polarity polarity for each particle
* @param axisTypes axis type (Z-then-X, ...
) for each particle
* @param axisTypes axis type (Z-then-X, ...) for each particle
* @param multipoleAtomZs indicies of particle specifying the molecular frame z-axis for each particle
* @param multipoleAtomXs indicies of particle specifying the molecular frame x-axis for each particle
* @param multipoleAtomYs indicies of particle specifying the molecular frame y-axis for each particle
...
...
@@ -925,19 +941,19 @@ protected:
* @param particleData output vector of parameters (charge, labFrame dipoles, quadrupoles, ...) for particles
*
*/
void
setup
(
const
std
::
vector
<
OpenMM
::
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
std
::
vector
<
MultipoleParticleData
>&
particleData
);
void
setup
(
const
std
::
vector
<
OpenMM
::
RealVec
>&
particlePositions
,
const
std
::
vector
<
RealOpenMM
>&
charges
,
const
std
::
vector
<
RealOpenMM
>&
dipoles
,
const
std
::
vector
<
RealOpenMM
>&
quadrupoles
,
const
std
::
vector
<
RealOpenMM
>&
tholes
,
const
std
::
vector
<
RealOpenMM
>&
dampingFactors
,
const
std
::
vector
<
RealOpenMM
>&
polarity
,
const
std
::
vector
<
int
>&
axisTypes
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>
>
>&
multipoleAtomCovalentInfo
,
std
::
vector
<
MultipoleParticleData
>&
particleData
);
/**
* Calculate electrostatic interaction between particles I and K.
...
...
@@ -948,8 +964,8 @@ protected:
* @param forces vector of particle forces to be updated
* @param torques vector of particle torques to be updated
*/
RealOpenMM
calculateElectrostaticPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleK
,
const
std
::
vector
<
RealOpenMM
>&
scalingFactors
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torque
)
const
;
RealOpenMM
calculateElectrostaticPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleK
,
const
std
::
vector
<
RealOpenMM
>&
scalingFactors
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torque
)
const
;
/**
* Map particle torque to force.
...
...
@@ -961,11 +977,11 @@ protected:
* @param axisType axis type (Bisector/Z-then-X, ...)
* @param torque torque on particle I
*/
void
mapTorqueToForceForParticle
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleU
,
const
MultipoleParticleData
&
particleV
,
MultipoleParticleData
*
particleW
,
int
axisType
,
const
Vec3
&
torque
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
)
const
;
void
mapTorqueToForceForParticle
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleU
,
const
MultipoleParticleData
&
particleV
,
MultipoleParticleData
*
particleW
,
int
axisType
,
const
Vec3
&
torque
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
)
const
;
/**
* Map torques to forces.
...
...
@@ -980,13 +996,13 @@ protected:
*
* @return energy
*/
void
mapTorqueToForce
(
std
::
vector
<
MultipoleParticleData
>&
particleData
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
axisTypes
,
std
::
vector
<
OpenMM
::
RealVec
>&
torques
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
)
const
;
void
mapTorqueToForce
(
std
::
vector
<
MultipoleParticleData
>&
particleData
,
const
std
::
vector
<
int
>&
multipoleAtomXs
,
const
std
::
vector
<
int
>&
multipoleAtomYs
,
const
std
::
vector
<
int
>&
multipoleAtomZs
,
const
std
::
vector
<
int
>&
axisTypes
,
std
::
vector
<
OpenMM
::
RealVec
>&
torques
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
)
const
;
/**
* Calculate electrostatic forces
...
...
@@ -997,9 +1013,9 @@ protected:
*
* @return energy
*/
virtual
RealOpenMM
calculateElectrostatic
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
OpenMM
::
RealVec
>&
torques
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
);
virtual
RealOpenMM
calculateElectrostatic
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
OpenMM
::
RealVec
>&
torques
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
);
/**
* Normalize a RealVec
...
...
@@ -1009,7 +1025,7 @@ protected:
* @return norm of vector on input
*
*/
RealOpenMM
normalizeRealVec
(
RealVec
&
vectorToNormalize
)
const
;
RealOpenMM
normalizeRealVec
(
RealVec
&
vectorToNormalize
)
const
;
/**
* Initialize vector of RealOpenMM (size=numParticles)
...
...
@@ -1017,7 +1033,7 @@ protected:
* @param vectorToInitialize vector to initialize
*
*/
void
initializeRealOpenMMVector
(
vector
<
RealOpenMM
>&
vectorToInitialize
)
const
;
void
initializeRealOpenMMVector
(
vector
<
RealOpenMM
>&
vectorToInitialize
)
const
;
/**
* Initialize vector of RealVec (size=numParticles)
...
...
@@ -1025,7 +1041,7 @@ protected:
* @param vectorToInitialize vector to initialize
*
*/
void
initializeRealVecVector
(
vector
<
RealVec
>&
vectorToInitialize
)
const
;
void
initializeRealVecVector
(
vector
<
RealVec
>&
vectorToInitialize
)
const
;
/**
* Copy vector of RealVec
...
...
@@ -1034,7 +1050,7 @@ protected:
* @param outputVector output vector
*
*/
void
copyRealVecVector
(
const
std
::
vector
<
OpenMM
::
RealVec
>&
inputVector
,
std
::
vector
<
OpenMM
::
RealVec
>&
outputVector
)
const
;
void
copyRealVecVector
(
const
std
::
vector
<
OpenMM
::
RealVec
>&
inputVector
,
std
::
vector
<
OpenMM
::
RealVec
>&
outputVector
)
const
;
/**
* Calculate potential at grid point due to a particle
...
...
@@ -1045,7 +1061,7 @@ protected:
* @return potential at grid point
*
*/
RealOpenMM
calculateElectrostaticPotentialForParticleGridPoint
(
const
MultipoleParticleData
&
particleI
,
const
RealVec
&
gridPoint
)
const
;
RealOpenMM
calculateElectrostaticPotentialForParticleGridPoint
(
const
MultipoleParticleData
&
particleI
,
const
RealVec
&
gridPoint
)
const
;
/**
* Apply periodic boundary conditions to difference in positions
...
...
@@ -1053,7 +1069,7 @@ protected:
* @param deltaR difference in particle positions; modified on output after applying PBC
*
*/
virtual
void
getPeriodicDelta
(
RealVec
&
deltaR
)
const
{};
virtual
void
getPeriodicDelta
(
RealVec
&
deltaR
)
const
{};
};
class
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
:
public
AmoebaReferenceMultipoleForce
{
...
...
@@ -1064,13 +1080,13 @@ public:
* Constructor
*
*/
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
(
AmoebaReferenceGeneralizedKirkwoodForce
*
amoebaReferenceGeneralizedKirkwoodForce
);
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
(
AmoebaReferenceGeneralizedKirkwoodForce
*
amoebaReferenceGeneralizedKirkwoodForce
);
/**
* Destructor
*
*/
~
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
(
);
~
AmoebaReferenceGeneralizedKirkwoodMultipoleForce
();
/**
* Get flag signalling whether cavity term is to be included.
...
...
@@ -1078,7 +1094,7 @@ public:
* @return flag
*
*/
int
getIncludeCavityTerm
(
void
)
const
;
int
getIncludeCavityTerm
()
const
;
/**
* Get probe radius.
...
...
@@ -1086,7 +1102,7 @@ public:
* @return probe radius
*
*/
RealOpenMM
getProbeRadius
(
void
)
const
;
RealOpenMM
getProbeRadius
()
const
;
/**
* Get surface area factor.
...
...
@@ -1094,7 +1110,7 @@ public:
* @return surface area factor
*
*/
RealOpenMM
getSurfaceAreaFactor
(
void
)
const
;
RealOpenMM
getSurfaceAreaFactor
()
const
;
/**
* Get dielectric offset.
...
...
@@ -1102,7 +1118,7 @@ public:
* @return dielectric offset
*
*/
RealOpenMM
getDielectricOffset
(
void
)
const
;
RealOpenMM
getDielectricOffset
()
const
;
private:
...
...
@@ -1131,7 +1147,7 @@ private:
* Zero fixed multipole fields.
*
*/
void
zeroFixedMultipoleFields
(
void
);
void
zeroFixedMultipoleFields
();
/**
* Calculate electric field at particle I due fixed multipoles at particle J and vice versa
...
...
@@ -1142,15 +1158,15 @@ private:
* @param dScale d-scale value for i-j interaction
* @param pScale p-scale value for i-j interaction
*/
void
calculateFixedMultipoleFieldPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dScale
,
RealOpenMM
pScale
);
void
calculateFixedMultipoleFieldPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dScale
,
RealOpenMM
pScale
);
/**
* Calculate induced dipoles.
*
* @param particleData vector of particle positions and parameters (charge, labFrame dipoles, quadrupoles, ...)
*/
void
calculateInducedDipoles
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
);
void
calculateInducedDipoles
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
);
/**
* Calculate fields due induced dipoles at each site.
...
...
@@ -1159,8 +1175,8 @@ private:
* @param particleJ positions and parameters (charge, labFrame dipoles, quadrupoles, ...) for particle J
* @param updateInducedDipoleFields vector of UpdateInducedDipoleFieldStruct containing input induced dipoles and output fields
*/
void
calculateInducedDipolePairIxns
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
void
calculateInducedDipolePairIxns
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
/**
* Calculate electrostatic forces and torques.
...
...
@@ -1171,9 +1187,9 @@ private:
*
* @return energy
*/
RealOpenMM
calculateElectrostatic
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
OpenMM
::
RealVec
>&
torques
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
);
RealOpenMM
calculateElectrostatic
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
OpenMM
::
RealVec
>&
torques
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
);
/**
* Calculate GK field at particle I due induced dipole at particle J and vice versa
...
...
@@ -1184,8 +1200,8 @@ private:
* @param field vector of induced dipole fields
* @param fieldPolar vector of induced dipole polar fields
*/
void
calculateInducedDipolePairGkIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
const
std
::
vector
<
RealVec
>&
field
,
std
::
vector
<
RealVec
>&
fieldPolar
)
const
;
void
calculateInducedDipolePairGkIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
const
std
::
vector
<
RealVec
>&
field
,
std
::
vector
<
RealVec
>&
fieldPolar
)
const
;
/**
* Calculate Kirkwood interaction.
...
...
@@ -1198,10 +1214,10 @@ private:
*
* @return energy
*/
RealOpenMM
calculateKirkwoodPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
,
std
::
vector
<
RealOpenMM
>&
dBorn
)
const
;
RealOpenMM
calculateKirkwoodPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
,
std
::
vector
<
RealOpenMM
>&
dBorn
)
const
;
/**
* Calculate Grycuk 'chain-rule' force.
...
...
@@ -1212,8 +1228,8 @@ private:
* @param forces add Kirkwood force to forces
*
*/
void
calculateGrycukChainRulePairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
const
std
::
vector
<
RealOpenMM
>&
dBorn
,
std
::
vector
<
RealVec
>&
forces
)
const
;
void
calculateGrycukChainRulePairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
const
std
::
vector
<
RealOpenMM
>&
dBorn
,
std
::
vector
<
RealVec
>&
forces
)
const
;
/**
* Calculate TINKER's ACE approximation to non-polar cavity term.
...
...
@@ -1223,7 +1239,7 @@ private:
* @return ACE energy
*
*/
RealOpenMM
calculateCavityTermEnergyAndForces
(
std
::
vector
<
RealOpenMM
>&
dBorn
)
const
;
RealOpenMM
calculateCavityTermEnergyAndForces
(
std
::
vector
<
RealOpenMM
>&
dBorn
)
const
;
/**
* Correct vacuum to SCRF derivatives (TINKER's ediff1()).
...
...
@@ -1237,9 +1253,9 @@ private:
*
* @return energy
*/
RealOpenMM
calculateKirkwoodEDiffPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
pscale
,
RealOpenMM
dscale
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
)
const
;
RealOpenMM
calculateKirkwoodEDiffPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
pscale
,
RealOpenMM
dscale
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
)
const
;
};
...
...
@@ -1251,13 +1267,13 @@ public:
* Constructor
*
*/
AmoebaReferencePmeMultipoleForce
(
void
);
AmoebaReferencePmeMultipoleForce
();
/**
* Destructor
*
*/
~
AmoebaReferencePmeMultipoleForce
(
);
~
AmoebaReferencePmeMultipoleForce
();
/**
* Get cutoff distance.
...
...
@@ -1265,7 +1281,7 @@ public:
* @return cutoff distance
*
*/
RealOpenMM
getCutoffDistance
(
void
)
const
;
RealOpenMM
getCutoffDistance
()
const
;
/**
* Set cutoff distance.
...
...
@@ -1273,7 +1289,7 @@ public:
* @return cutoff distance
*
*/
void
setCutoffDistance
(
RealOpenMM
cutoffDistance
);
void
setCutoffDistance
(
RealOpenMM
cutoffDistance
);
/**
* Get alpha used in Ewald summation.
...
...
@@ -1281,7 +1297,7 @@ public:
* @return alpha
*
*/
RealOpenMM
getAlphaEwald
(
void
)
const
;
RealOpenMM
getAlphaEwald
()
const
;
/**
* Set alpha used in Ewald summation.
...
...
@@ -1289,7 +1305,7 @@ public:
* @return alpha
*
*/
void
setAlphaEwald
(
RealOpenMM
alphaEwald
);
void
setAlphaEwald
(
RealOpenMM
alphaEwald
);
/**
* Get PME grid dimensions.
...
...
@@ -1298,7 +1314,7 @@ public:
*
*/
void
getPmeGridDimensions
(
std
::
vector
<
int
>&
pmeGridDimensions
)
const
;
void
getPmeGridDimensions
(
std
::
vector
<
int
>&
pmeGridDimensions
)
const
;
/**
* Set PME grid dimensions.
...
...
@@ -1306,14 +1322,14 @@ public:
* @param pmeGridDimensions input PME grid dimensions
*
*/
void
setPmeGridDimensions
(
std
::
vector
<
int
>&
pmeGridDimensions
);
void
setPmeGridDimensions
(
std
::
vector
<
int
>&
pmeGridDimensions
);
/**
* Set periodic box size.
*
* @param boxSize box dimensions
*/
void
setPeriodicBoxSize
(
RealVec
&
boxSize
);
void
setPeriodicBoxSize
(
RealVec
&
boxSize
);
private:
...
...
@@ -1351,12 +1367,12 @@ private:
* Resize PME arrays.
*
*/
void
resizePmeArrays
(
void
);
void
resizePmeArrays
();
/**
* Zero Pme grid.
*/
void
initializePmeGrid
(
void
);
void
initializePmeGrid
();
/**
* Modify input vector of differences in particle positions for periodic boundary conditions.
...
...
@@ -1364,13 +1380,13 @@ private:
* @param delta input vector of difference in particle positios; on output adjusted for
* periodic boundary conditions
*/
void
getPeriodicDelta
(
RealVec
&
deltaR
)
const
;
void
getPeriodicDelta
(
RealVec
&
deltaR
)
const
;
/**
* Get PME scale.
*
*/
void
getPmeScale
(
RealVec
&
scale
)
const
;
void
getPmeScale
(
RealVec
&
scale
)
const
;
/**
* Calculate damped inverse distances.
...
...
@@ -1382,15 +1398,15 @@ private:
* @param dampedDInverseDistances damped inverse distances (drr3,drr5,drr7 in udirect2a() in TINKER)
* @param dampedPInverseDistances damped inverse distances (prr3,prr5,prr7 in udirect2a() in TINKER)
*/
void
getDampedInverseDistances
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dscale
,
RealOpenMM
pscale
,
RealOpenMM
r
,
RealVec
&
dampedDInverseDistances
,
RealVec
&
dampedPInverseDistances
)
const
;
void
getDampedInverseDistances
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dscale
,
RealOpenMM
pscale
,
RealOpenMM
r
,
RealVec
&
dampedDInverseDistances
,
RealVec
&
dampedPInverseDistances
)
const
;
/**
* Initialize B-spline moduli.
*
*/
void
initializeBSplineModuli
(
void
);
void
initializeBSplineModuli
();
/**
* Calculate direct-space field at site I due fixed multipoles at site J and vice versa.
...
...
@@ -1400,8 +1416,8 @@ private:
* @param dScale d-scale value for i-j interaction
* @param pScale p-scale value for i-j interaction
*/
void
calculateFixedMultipoleFieldPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dscale
,
RealOpenMM
pscale
);
void
calculateFixedMultipoleFieldPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
RealOpenMM
dscale
,
RealOpenMM
pscale
);
/**
* Calculate fixed multipole fields.
...
...
@@ -1409,7 +1425,7 @@ private:
* @param particleData vector particle data
*
*/
void
calculateFixedMultipoleField
(
const
vector
<
MultipoleParticleData
>&
particleData
);
void
calculateFixedMultipoleField
(
const
vector
<
MultipoleParticleData
>&
particleData
);
/**
* This is called from computeAmoebaBsplines(). It calculates the spline coefficients for a single atom along a single axis.
...
...
@@ -1417,21 +1433,21 @@ private:
* @param thetai output spline coefficients
* @param w offset from grid point
*/
void
computeBSplinePoint
(
std
::
vector
<
RealOpenMM4
>&
thetai
,
RealOpenMM
w
);
void
computeBSplinePoint
(
std
::
vector
<
RealOpenMM4
>&
thetai
,
RealOpenMM
w
);
/**
* Compute bspline coefficients.
*
* @param particleData vector of particle positions and parameters (charge, labFrame dipoles, quadrupoles, ...)
*/
void
computeAmoebaBsplines
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
);
void
computeAmoebaBsplines
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
);
/**
* For each grid point, find the range of sorted atoms associated with that point.
*
* @param particleData vector of particle positions and parameters (charge, labFrame dipoles, quadrupoles, ...)
*/
void
findAmoebaAtomRangeForGrid
(
const
vector
<
MultipoleParticleData
>&
particleData
);
void
findAmoebaAtomRangeForGrid
(
const
vector
<
MultipoleParticleData
>&
particleData
);
/**
* Get grid point given grid index.
...
...
@@ -1439,7 +1455,7 @@ private:
* @param gridIndex input grid index
* @param gridPoint output grid point
*/
void
getGridPointGivenGridIndex
(
int
gridIndex
,
IntVec
&
gridPoint
)
const
;
void
getGridPointGivenGridIndex
(
int
gridIndex
,
IntVec
&
gridPoint
)
const
;
/**
* Compute induced dipole grid value.
...
...
@@ -1453,33 +1469,33 @@ private:
* @param inputInducedDipole induced dipole value
* @param inputInducedDipolePolar induced dipole value
*/
RealOpenMM
computeFixedMultipolesGridValue
(
const
vector
<
MultipoleParticleData
>&
particleData
,
const
int2
&
particleGridIndices
,
const
RealVec
&
scale
,
int
ix
,
int
iy
,
const
IntVec
&
gridPoint
)
const
;
RealOpenMM
computeFixedMultipolesGridValue
(
const
vector
<
MultipoleParticleData
>&
particleData
,
const
int2
&
particleGridIndices
,
const
RealVec
&
scale
,
int
ix
,
int
iy
,
const
IntVec
&
gridPoint
)
const
;
/**
* Spread fixed multipoles onto PME grid.
*
* @param particleData vector of particle positions and parameters (charge, labFrame dipoles, quadrupoles, ...)
*/
void
spreadFixedMultipolesOntoGrid
(
const
vector
<
MultipoleParticleData
>&
particleData
);
void
spreadFixedMultipolesOntoGrid
(
const
vector
<
MultipoleParticleData
>&
particleData
);
/**
* Perform reciprocal convolution.
*
*/
void
performAmoebaReciprocalConvolution
(
void
);
void
performAmoebaReciprocalConvolution
();
/**
* Compute reciprocal potential due fixed multipoles at each particle site.
*
*/
void
computeFixedPotentialFromGrid
(
void
);
void
computeFixedPotentialFromGrid
(
void
);
/**
* Compute reciprocal potential due fixed multipoles at each particle site.
*
*/
void
computeInducedPotentialFromGrid
(
void
);
void
computeInducedPotentialFromGrid
();
/**
* Calculate reciprocal space energy and force due to fixed multipoles.
...
...
@@ -1490,21 +1506,21 @@ private:
*
* @return energy
*/
RealOpenMM
computeReciprocalSpaceFixedMultipoleForceAndEnergy
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
)
const
;
RealOpenMM
computeReciprocalSpaceFixedMultipoleForceAndEnergy
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
)
const
;
/**
* Set reciprocal space fixed multipole fields.
*
*/
void
recordFixedMultipoleField
(
void
);
void
recordFixedMultipoleField
();
/**
* Compute the potential due to the reciprocal space PME calculation for induced dipoles.
*
* @param updateInducedDipoleFields vector of UpdateInducedDipoleFieldStruct containing input induced dipoles and output fields
*/
void
calculateReciprocalSpaceInducedDipoleField
(
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
void
calculateReciprocalSpaceInducedDipoleField
(
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
/**
* Calculate field at particleI due to induced dipole at particle J and vice versa.
...
...
@@ -1517,10 +1533,10 @@ private:
* @param inducedDipole vector of induced dipoles
* @param field vector of field at each particle due induced dipole of other particles
*/
void
calculateDirectInducedDipolePairIxn
(
unsigned
int
iIndex
,
unsigned
int
jIndex
,
RealOpenMM
preFactor1
,
RealOpenMM
preFactor2
,
const
RealVec
&
delta
,
const
std
::
vector
<
RealVec
>&
inducedDipole
,
std
::
vector
<
RealVec
>&
field
)
const
;
void
calculateDirectInducedDipolePairIxn
(
unsigned
int
iIndex
,
unsigned
int
jIndex
,
RealOpenMM
preFactor1
,
RealOpenMM
preFactor2
,
const
RealVec
&
delta
,
const
std
::
vector
<
RealVec
>&
inducedDipole
,
std
::
vector
<
RealVec
>&
field
)
const
;
/**
* Calculate direct space field at particleI due to induced dipole at particle J and vice versa for
...
...
@@ -1530,16 +1546,16 @@ private:
* @param particleJ positions and parameters (charge, labFrame dipoles, quadrupoles, ...) for particle J
* @param updateInducedDipoleFields vector of UpdateInducedDipoleFieldStruct containing input induced dipoles and output fields
*/
void
calculateDirectInducedDipolePairIxns
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
void
calculateDirectInducedDipolePairIxns
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
/**
* Initialize induced dipoles
*
* @param updateInducedDipoleFields vector of UpdateInducedDipoleFieldStruct containing input induced dipoles and output fields
*/
void
initializeInducedDipoles
(
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
void
initializeInducedDipoles
(
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
/**
* Compute induced dipole grid value.
...
...
@@ -1552,9 +1568,9 @@ private:
* @param inputInducedDipole induced dipole value
* @param inputInducedDipolePolar induced dipole polar value
*/
t_complex
computeInducedDipoleGridValue
(
const
int2
&
atomIndices
,
const
RealVec
&
scale
,
int
ix
,
int
iy
,
const
IntVec
&
gridPoint
,
const
std
::
vector
<
RealVec
>&
inputInducedDipole
,
const
std
::
vector
<
RealVec
>&
inputInducedDipolePolar
)
const
;
t_complex
computeInducedDipoleGridValue
(
const
int2
&
atomIndices
,
const
RealVec
&
scale
,
int
ix
,
int
iy
,
const
IntVec
&
gridPoint
,
const
std
::
vector
<
RealVec
>&
inputInducedDipole
,
const
std
::
vector
<
RealVec
>&
inputInducedDipolePolar
)
const
;
/**
* Spread induced dipoles onto grid.
...
...
@@ -1562,8 +1578,8 @@ private:
* @param inputInducedDipole induced dipole value
* @param inputInducedDipolePolar induced dipole polar value
*/
void
spreadInducedDipolesOnGrid
(
const
std
::
vector
<
RealVec
>&
inputInducedDipole
,
const
std
::
vector
<
RealVec
>&
inputInducedDipolePolar
);
void
spreadInducedDipolesOnGrid
(
const
std
::
vector
<
RealVec
>&
inputInducedDipole
,
const
std
::
vector
<
RealVec
>&
inputInducedDipolePolar
);
/**
* Calculate induced dipole fields.
...
...
@@ -1571,8 +1587,8 @@ private:
* @param particleData vector of particle positions and parameters (charge, labFrame dipoles, quadrupoles, ...)
* @param updateInducedDipoleFields vector of UpdateInducedDipoleFieldStruct containing input induced dipoles and output fields
*/
void
calculateInducedDipoleFields
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
void
calculateInducedDipoleFields
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
UpdateInducedDipoleFieldStruct
>&
updateInducedDipoleFields
);
/**
* Set reciprocal space induced dipole fields.
...
...
@@ -1581,14 +1597,14 @@ private:
* @param fieldPolar reciprocal space output induced dipole polar field value at each site
*
*/
void
recordInducedDipoleField
(
vector
<
RealVec
>&
field
,
vector
<
RealVec
>&
fieldPolar
);
void
recordInducedDipoleField
(
vector
<
RealVec
>&
field
,
vector
<
RealVec
>&
fieldPolar
);
/**
* Compute Pme self energy.
*
* @param particleData vector of parameters (charge, labFrame dipoles, quadrupoles, ...) for particles
*/
RealOpenMM
calculatePmeSelfEnergy
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
)
const
;
RealOpenMM
calculatePmeSelfEnergy
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
)
const
;
/**
* Compute the self torques.
...
...
@@ -1596,7 +1612,7 @@ private:
* @param particleData vector of parameters (charge, labFrame dipoles, quadrupoles, ...) for particles
* @param torques vector of torques
*/
void
calculatePmeSelfTorque
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
RealVec
>&
torques
)
const
;
void
calculatePmeSelfTorque
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
RealVec
>&
torques
)
const
;
/**
* Calculate direct space electrostatic interaction between particles I and J.
...
...
@@ -1607,9 +1623,9 @@ private:
* @param forces vector of particle forces to be updated
* @param torques vector of particle torques to be updated
*/
RealOpenMM
calculatePmeDirectElectrostaticPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
const
std
::
vector
<
RealOpenMM
>&
scalingFactors
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
)
const
;
RealOpenMM
calculatePmeDirectElectrostaticPairIxn
(
const
MultipoleParticleData
&
particleI
,
const
MultipoleParticleData
&
particleJ
,
const
std
::
vector
<
RealOpenMM
>&
scalingFactors
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
)
const
;
/**
* Calculate reciprocal space energy/force/torque for dipole interaction.
...
...
@@ -1620,9 +1636,9 @@ private:
* @param forces vector of particle forces to be updated
* @param torques vector of particle torques to be updated
*/
RealOpenMM
computeReciprocalSpaceInducedDipoleForceAndEnergy
(
AmoebaReferenceMultipoleForce
::
PolarizationType
polarizationType
,
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
)
const
;
RealOpenMM
computeReciprocalSpaceInducedDipoleForceAndEnergy
(
AmoebaReferenceMultipoleForce
::
PolarizationType
polarizationType
,
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
RealVec
>&
forces
,
std
::
vector
<
RealVec
>&
torques
)
const
;
/**
* Calculate electrostatic forces.
...
...
@@ -1633,9 +1649,9 @@ private:
*
* @return energy
*/
RealOpenMM
calculateElectrostatic
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
OpenMM
::
RealVec
>&
torques
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
);
RealOpenMM
calculateElectrostatic
(
const
std
::
vector
<
MultipoleParticleData
>&
particleData
,
std
::
vector
<
OpenMM
::
RealVec
>&
torques
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
);
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment