Commit cf335495 authored by Mark Friedrichs's avatar Mark Friedrichs
Browse files

PME real space and self terms for fixed E-field

parent acb46362
...@@ -1420,6 +1420,18 @@ void gpuKirkwoodAllocate( amoebaGpuContext amoebaGpu ) ...@@ -1420,6 +1420,18 @@ void gpuKirkwoodAllocate( amoebaGpuContext amoebaGpu )
} }
static void tabulateErfc(gpuContext gpu)
{
int tableSize = 2048;
gpu->sim.tabulatedErfcSize = tableSize;
gpu->sim.tabulatedErfcScale = tableSize/(gpu->sim.alphaEwald*gpu->sim.nonbondedCutoff);
gpu->psTabulatedErfc = new CUDAStream<float>(tableSize, 1, "TabulatedErfc");
gpu->sim.pTabulatedErfc = gpu->psTabulatedErfc->_pDevData;
for (int i = 0; i < tableSize; ++i)
(*gpu->psTabulatedErfc)[i] = (float) erfc(i*(gpu->sim.alphaEwald*gpu->sim.nonbondedCutoff)/tableSize);
gpu->psTabulatedErfc->Upload();
}
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
Create/initialize data structs associated w/ molecular -> lab frame calculation Create/initialize data structs associated w/ molecular -> lab frame calculation
...@@ -1525,14 +1537,26 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect ...@@ -1525,14 +1537,26 @@ void gpuSetAmoebaMultipoleParameters(amoebaGpuContext amoebaGpu, const std::vect
} else if( nonbondedMethod == 1 ){ } else if( nonbondedMethod == 1 ){
amoebaGpu->multipoleNonbondedMethod = AMOEBA_PARTICLE_MESH_EWALD; amoebaGpu->multipoleNonbondedMethod = AMOEBA_PARTICLE_MESH_EWALD;
} else { } else {
throw OpenMM::OpenMMException("multipoleNonbondedMethod not recognzied.\n" ); throw OpenMM::OpenMMException("multipoleNonbondedMethod not recognized.\n" );
} }
amoebaGpu->amoebaSim.cutoffDistance2 = cutoffDistance*cutoffDistance;
amoebaGpu->amoebaSim.sqrtPi = sqrt( 3.1415926535897932384626433832795 ); if( amoebaGpu->log ){
amoebaGpu->amoebaSim.aewald = aewald; (void) fprintf( amoebaGpu->log,"%s Nonbonded method=%d %d [NoCutoff=%d PME=%d]\n",
amoebaGpu->amoebaSim.electric = electricConstant; methodName.c_str(), nonbondedMethod, amoebaGpu->multipoleNonbondedMethod,
AMOEBA_NO_CUTOFF, AMOEBA_PARTICLE_MESH_EWALD );
(void) fflush( amoebaGpu->log );
}
amoebaGpu->amoebaSim.cutoffDistance2 = cutoffDistance*cutoffDistance;
amoebaGpu->amoebaSim.sqrtPi = sqrt( 3.1415926535897932384626433832795 );
amoebaGpu->amoebaSim.aewald = aewald;
amoebaGpu->amoebaSim.electric = electricConstant;
amoebaGpu->gpuContext->sim.alphaEwald = aewald;
amoebaGpu->gpuContext->sim.nonbondedCutoff = cutoffDistance;
tabulateErfc(amoebaGpu->gpuContext);
if( amoebaGpu->amoebaSim.dielec < 1.0e-05 ){ if( amoebaGpu->amoebaSim.dielec < 1.0e-05 ){
amoebaGpu->amoebaSim.dielec = 1.0f; amoebaGpu->amoebaSim.dielec = 1.0f;
} }
for( int ii = 0; ii < static_cast<int>(charges.size()); ii++ ){ for( int ii = 0; ii < static_cast<int>(charges.size()); ii++ ){
...@@ -2593,6 +2617,7 @@ void amoebaGpuSetConstants(amoebaGpuContext amoebaGpu) ...@@ -2593,6 +2617,7 @@ void amoebaGpuSetConstants(amoebaGpuContext amoebaGpu)
SetCalculateAmoebaCudaVdw14_7Sim( amoebaGpu ); SetCalculateAmoebaCudaVdw14_7Sim( amoebaGpu );
SetCalculateAmoebaCudaWcaDispersionSim( amoebaGpu ); SetCalculateAmoebaCudaWcaDispersionSim( amoebaGpu );
SetCalculateAmoebaCudaMutualInducedFieldSim( amoebaGpu ); SetCalculateAmoebaCudaMutualInducedFieldSim( amoebaGpu );
SetCalculateAmoebaCudaPmeFixedEFieldSim( amoebaGpu );
SetCalculateAmoebaElectrostaticSim( amoebaGpu ); SetCalculateAmoebaElectrostaticSim( amoebaGpu );
SetCalculateAmoebaRealSpaceEwaldSim( amoebaGpu ); SetCalculateAmoebaRealSpaceEwaldSim( amoebaGpu );
SetCalculateAmoebaCudaMapTorquesSim( amoebaGpu ); SetCalculateAmoebaCudaMapTorquesSim( amoebaGpu );
......
...@@ -65,12 +65,17 @@ extern void SetCalculateAmoebaCudaWcaDispersionSim(amoebaGpuContext gpu); ...@@ -65,12 +65,17 @@ extern void SetCalculateAmoebaCudaWcaDispersionSim(amoebaGpuContext gpu);
extern void GetCalculateAmoebaCudaWcaDispersionSim(amoebaGpuContext gpu); extern void GetCalculateAmoebaCudaWcaDispersionSim(amoebaGpuContext gpu);
extern void kCalculateAmoebaWcaDispersionForces(amoebaGpuContext amoebaGpu ); extern void kCalculateAmoebaWcaDispersionForces(amoebaGpuContext amoebaGpu );
// fixed electric field // fixed electric field -- no cutoff
extern void SetCalculateAmoebaCudaFixedEFieldSim(amoebaGpuContext gpu); extern void SetCalculateAmoebaCudaFixedEFieldSim(amoebaGpuContext gpu);
extern void GetCalculateAmoebaCudaFixedEFieldSim(amoebaGpuContext gpu); extern void GetCalculateAmoebaCudaFixedEFieldSim(amoebaGpuContext gpu);
extern void cudaComputeAmoebaFixedEField( amoebaGpuContext gpu); extern void cudaComputeAmoebaFixedEField( amoebaGpuContext gpu);
// fixed electric field -- PME
extern void SetCalculateAmoebaCudaPmeFixedEFieldSim(amoebaGpuContext gpu);
extern void GetCalculateAmoebaCudaPmeFixedEFieldSim(amoebaGpuContext gpu);
extern void cudaComputeAmoebaPmeFixedEField( amoebaGpuContext gpu);
// fixed electric field and Gk // fixed electric field and Gk
extern void SetCalculateAmoebaCudaFixedEAndGKFieldsSim(amoebaGpuContext gpu); extern void SetCalculateAmoebaCudaFixedEAndGKFieldsSim(amoebaGpuContext gpu);
......
...@@ -83,6 +83,9 @@ void METHOD_NAME(kCalculateAmoebaFixedEAndGkField, _kernel)( ...@@ -83,6 +83,9 @@ void METHOD_NAME(kCalculateAmoebaFixedEAndGkField, _kernel)(
FixedFieldParticle* psA = &sA[tbx]; FixedFieldParticle* psA = &sA[tbx];
unsigned int atomI = x + tgx; unsigned int atomI = x + tgx;
FixedFieldParticle localParticle;
loadFixedFieldShared( &localParticle, atomI, bornRadii );
float4 iCoord = atomCoord[atomI]; float4 iCoord = atomCoord[atomI];
float eFieldSum[3]; float eFieldSum[3];
...@@ -106,9 +109,7 @@ void METHOD_NAME(kCalculateAmoebaFixedEAndGkField, _kernel)( ...@@ -106,9 +109,7 @@ void METHOD_NAME(kCalculateAmoebaFixedEAndGkField, _kernel)(
// load coordinates, charge, ... // load coordinates, charge, ...
loadFixedFieldShared( &(sA[threadIdx.x]), atomI, loadFixedFieldShared( &(sA[threadIdx.x]), atomI, bornRadii );
atomCoord, labFrameDipole, labFrameQuadrupole,
cAmoebaSim.pDampingFactorAndThole, bornRadii );
if (!bExclusionFlag) if (!bExclusionFlag)
{ {
...@@ -125,12 +126,7 @@ void METHOD_NAME(kCalculateAmoebaFixedEAndGkField, _kernel)( ...@@ -125,12 +126,7 @@ void METHOD_NAME(kCalculateAmoebaFixedEAndGkField, _kernel)(
loadFixedFieldParticleData( &(psA[j]), &jCoord, jDipole, jQuadrupole, &jBornRadius ); loadFixedFieldParticleData( &(psA[j]), &jCoord, jDipole, jQuadrupole, &jBornRadius );
calculateFixedEFieldPairIxn_kernel( iCoord, jCoord, calculateFixedEFieldPairIxn_kernel( localParticle, psA[j], ijField
cAmoebaSim.pDampingFactorAndThole[atomI].x, psA[j].damp,
cAmoebaSim.pDampingFactorAndThole[atomI].y, psA[j].thole,
&(labFrameDipole[atomI*3]), jDipole,
&(labFrameQuadrupole[atomI*9]), jQuadrupole,
cAmoebaSim.scalingDistanceCutoff, ijField
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
, pullBack , pullBack
#endif #endif
...@@ -182,12 +178,7 @@ void METHOD_NAME(kCalculateAmoebaFixedEAndGkField, _kernel)( ...@@ -182,12 +178,7 @@ void METHOD_NAME(kCalculateAmoebaFixedEAndGkField, _kernel)(
loadFixedFieldParticleData( &(psA[j]), &jCoord, jDipole, jQuadrupole, &jBornRadius ); loadFixedFieldParticleData( &(psA[j]), &jCoord, jDipole, jQuadrupole, &jBornRadius );
calculateFixedEFieldPairIxn_kernel( iCoord, jCoord, calculateFixedEFieldPairIxn_kernel( localParticle, psA[j], ijField
cAmoebaSim.pDampingFactorAndThole[atomI].x, psA[j].damp,
cAmoebaSim.pDampingFactorAndThole[atomI].y, psA[j].thole,
&(labFrameDipole[atomI*3]), jDipole,
&(labFrameQuadrupole[atomI*9]), jQuadrupole,
cAmoebaSim.scalingDistanceCutoff, ijField
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
, pullBack , pullBack
#endif #endif
...@@ -366,9 +357,7 @@ if( atomI == targetAtom ){ ...@@ -366,9 +357,7 @@ if( atomI == targetAtom ){
{ {
// load coordinates, charge, ... // load coordinates, charge, ...
loadFixedFieldShared( &(sA[threadIdx.x]), (y+tgx), loadFixedFieldShared( &(sA[threadIdx.x]), (y+tgx), bornRadii );
atomCoord, labFrameDipole, labFrameQuadrupole,
cAmoebaSim.pDampingFactorAndThole, bornRadii );
} }
...@@ -387,12 +376,7 @@ if( atomI == targetAtom ){ ...@@ -387,12 +376,7 @@ if( atomI == targetAtom ){
loadFixedFieldParticleData( &(psA[tj]), &jCoord, jDipole, jQuadrupole, &jBornRadius ); loadFixedFieldParticleData( &(psA[tj]), &jCoord, jDipole, jQuadrupole, &jBornRadius );
calculateFixedEFieldPairIxn_kernel( iCoord, jCoord, calculateFixedEFieldPairIxn_kernel( localParticle, psA[tj], ijField
cAmoebaSim.pDampingFactorAndThole[atomI].x, psA[tj].damp,
cAmoebaSim.pDampingFactorAndThole[atomI].y, psA[tj].thole,
&(labFrameDipole[atomI*3]), jDipole,
&(labFrameQuadrupole[atomI*9]), jQuadrupole,
cAmoebaSim.scalingDistanceCutoff, ijField
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
, pullBack , pullBack
#endif #endif
...@@ -563,12 +547,7 @@ if( (atomI == targetAtom || (y + tj) == targetAtom) ){ ...@@ -563,12 +547,7 @@ if( (atomI == targetAtom || (y + tj) == targetAtom) ){
loadFixedFieldParticleData( &(psA[tj]), &jCoord, jDipole, jQuadrupole, &jBornRadius ); loadFixedFieldParticleData( &(psA[tj]), &jCoord, jDipole, jQuadrupole, &jBornRadius );
calculateFixedEFieldPairIxn_kernel( iCoord, jCoord, calculateFixedEFieldPairIxn_kernel( localParticle, psA[tj], ijField
cAmoebaSim.pDampingFactorAndThole[atomI].x, psA[tj].damp,
cAmoebaSim.pDampingFactorAndThole[atomI].y, psA[tj].thole,
&(labFrameDipole[atomI*3]), jDipole,
&(labFrameQuadrupole[atomI*9]), jQuadrupole,
cAmoebaSim.scalingDistanceCutoff, ijField
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
, pullBack , pullBack
#endif #endif
......
...@@ -61,46 +61,6 @@ static void kReduceE_Fields_kernel(amoebaGpuContext amoebaGpu ) ...@@ -61,46 +61,6 @@ static void kReduceE_Fields_kernel(amoebaGpuContext amoebaGpu )
#define METHOD_NAME(a, b) a##N2ByWarp##b #define METHOD_NAME(a, b) a##N2ByWarp##b
#include "kCalculateAmoebaCudaFixedEField.h" #include "kCalculateAmoebaCudaFixedEField.h"
#ifdef AMOEBA_DEBUG
#if 0
static void printEFieldBuffer( amoebaGpuContext amoebaGpu, unsigned int bufferIndex )
{
(void) fprintf( amoebaGpu->log, "EField Buffer %u\n", bufferIndex );
unsigned int start = bufferIndex*3*amoebaGpu->paddedNumberOfAtoms;
unsigned int stop = (bufferIndex+1)*3*amoebaGpu->paddedNumberOfAtoms;
for( unsigned int ii = start; ii < stop; ii += 3 ){
unsigned int ii3Index = ii/3;
unsigned int bufferIndex = ii3Index/(amoebaGpu->paddedNumberOfAtoms);
unsigned int particleIndex = ii3Index - bufferIndex*(amoebaGpu->paddedNumberOfAtoms);
(void) fprintf( amoebaGpu->log, " %6u %3u %6u [%14.6e %14.6e %14.6e] [%14.6e %14.6e %14.6e]\n",
ii/3, bufferIndex, particleIndex,
amoebaGpu->psWorkArray_3_1->_pSysStream[0][ii],
amoebaGpu->psWorkArray_3_1->_pSysStream[0][ii+1],
amoebaGpu->psWorkArray_3_1->_pSysStream[0][ii+2],
amoebaGpu->psWorkArray_3_2->_pSysStream[0][ii],
amoebaGpu->psWorkArray_3_2->_pSysStream[0][ii+1],
amoebaGpu->psWorkArray_3_2->_pSysStream[0][ii+2] );
}
}
static void printEFieldAtomBuffers( amoebaGpuContext amoebaGpu, unsigned int targetAtom )
{
(void) fprintf( amoebaGpu->log, "EField atom %u\n", targetAtom );
for( unsigned int ii = 0; ii < amoebaGpu->outputBuffers; ii++ ){
unsigned int particleIndex = targetAtom + ii*3*amoebaGpu->paddedNumberOfAtoms;
(void) fprintf( amoebaGpu->log, " %2u %6u [%14.6e %14.6e %14.6e] [%14.6e %14.6e %14.6e]\n",
ii, particleIndex,
amoebaGpu->psWorkArray_3_1->_pSysStream[0][particleIndex],
amoebaGpu->psWorkArray_3_1->_pSysStream[0][particleIndex+1],
amoebaGpu->psWorkArray_3_1->_pSysStream[0][particleIndex+2],
amoebaGpu->psWorkArray_3_2->_pSysStream[0][particleIndex],
amoebaGpu->psWorkArray_3_2->_pSysStream[0][particleIndex+1],
amoebaGpu->psWorkArray_3_2->_pSysStream[0][particleIndex+2] );
}
}
#endif
#endif
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
Compute fixed electric field Compute fixed electric field
...@@ -145,9 +105,6 @@ void cudaComputeAmoebaFixedEField( amoebaGpuContext amoebaGpu ) ...@@ -145,9 +105,6 @@ void cudaComputeAmoebaFixedEField( amoebaGpuContext amoebaGpu )
(void) fprintf( amoebaGpu->log, "N2 warp\n" ); (void) fprintf( amoebaGpu->log, "N2 warp\n" );
kCalculateAmoebaFixedE_FieldN2ByWarpForces_kernel<<<amoebaGpu->nonbondBlocks, amoebaGpu->nonbondThreadsPerBlock, sizeof(FixedFieldParticle)*amoebaGpu->nonbondThreadsPerBlock>>>( kCalculateAmoebaFixedE_FieldN2ByWarpForces_kernel<<<amoebaGpu->nonbondBlocks, amoebaGpu->nonbondThreadsPerBlock, sizeof(FixedFieldParticle)*amoebaGpu->nonbondThreadsPerBlock>>>(
amoebaGpu->psWorkUnit->_pDevStream[0], amoebaGpu->psWorkUnit->_pDevStream[0],
gpu->psPosq4->_pDevStream[0],
amoebaGpu->psLabFrameDipole->_pDevStream[0],
amoebaGpu->psLabFrameQuadrupole->_pDevStream[0],
amoebaGpu->psWorkArray_3_1->_pDevStream[0], amoebaGpu->psWorkArray_3_1->_pDevStream[0],
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
amoebaGpu->psWorkArray_3_2->_pDevStream[0], amoebaGpu->psWorkArray_3_2->_pDevStream[0],
...@@ -167,9 +124,6 @@ void cudaComputeAmoebaFixedEField( amoebaGpuContext amoebaGpu ) ...@@ -167,9 +124,6 @@ void cudaComputeAmoebaFixedEField( amoebaGpuContext amoebaGpu )
kCalculateAmoebaFixedE_FieldN2Forces_kernel<<<amoebaGpu->nonbondBlocks, amoebaGpu->nonbondThreadsPerBlock, sizeof(FixedFieldParticle)*amoebaGpu->nonbondThreadsPerBlock>>>( kCalculateAmoebaFixedE_FieldN2Forces_kernel<<<amoebaGpu->nonbondBlocks, amoebaGpu->nonbondThreadsPerBlock, sizeof(FixedFieldParticle)*amoebaGpu->nonbondThreadsPerBlock>>>(
amoebaGpu->psWorkUnit->_pDevStream[0], amoebaGpu->psWorkUnit->_pDevStream[0],
gpu->psPosq4->_pDevStream[0],
amoebaGpu->psLabFrameDipole->_pDevStream[0],
amoebaGpu->psLabFrameQuadrupole->_pDevStream[0],
amoebaGpu->psWorkArray_3_1->_pDevStream[0], amoebaGpu->psWorkArray_3_1->_pDevStream[0],
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
amoebaGpu->psWorkArray_3_2->_pDevStream[0], amoebaGpu->psWorkArray_3_2->_pDevStream[0],
......
...@@ -36,9 +36,6 @@ __launch_bounds__(G8X_NONBOND_THREADS_PER_BLOCK, 1) ...@@ -36,9 +36,6 @@ __launch_bounds__(G8X_NONBOND_THREADS_PER_BLOCK, 1)
#endif #endif
void METHOD_NAME(kCalculateAmoebaFixedE_Field, Forces_kernel)( void METHOD_NAME(kCalculateAmoebaFixedE_Field, Forces_kernel)(
unsigned int* workUnit, unsigned int* workUnit,
float4* atomCoord,
float* labFrameDipole,
float* labFrameQuadrupole,
float* outputEField, float* outputEField,
float* outputEFieldPolar float* outputEFieldPolar
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
...@@ -59,10 +56,6 @@ void METHOD_NAME(kCalculateAmoebaFixedE_Field, Forces_kernel)( ...@@ -59,10 +56,6 @@ void METHOD_NAME(kCalculateAmoebaFixedE_Field, Forces_kernel)(
unsigned int end = (warp+1)*numWorkUnits/totalWarps; unsigned int end = (warp+1)*numWorkUnits/totalWarps;
unsigned int lasty = 0xFFFFFFFF; unsigned int lasty = 0xFFFFFFFF;
float4 jCoord;
float jDipole[3];
float jQuadrupole[9];
while (pos < end) while (pos < end)
{ {
...@@ -80,7 +73,9 @@ void METHOD_NAME(kCalculateAmoebaFixedE_Field, Forces_kernel)( ...@@ -80,7 +73,9 @@ void METHOD_NAME(kCalculateAmoebaFixedE_Field, Forces_kernel)(
FixedFieldParticle* psA = &sA[tbx]; FixedFieldParticle* psA = &sA[tbx];
unsigned int atomI = x + tgx; unsigned int atomI = x + tgx;
float4 iCoord = atomCoord[atomI];
FixedFieldParticle localParticle;
loadFixedFieldShared( &localParticle, atomI );
float fieldSum[3]; float fieldSum[3];
float fieldPolarSum[3]; float fieldPolarSum[3];
...@@ -98,9 +93,7 @@ void METHOD_NAME(kCalculateAmoebaFixedE_Field, Forces_kernel)( ...@@ -98,9 +93,7 @@ void METHOD_NAME(kCalculateAmoebaFixedE_Field, Forces_kernel)(
// load coordinates, charge, ... // load coordinates, charge, ...
loadFixedFieldShared( &(sA[threadIdx.x]), atomI, loadFixedFieldShared( &(sA[threadIdx.x]), atomI );
atomCoord, labFrameDipole, labFrameQuadrupole,
cAmoebaSim.pDampingFactorAndThole );
if (!bExclusionFlag) if (!bExclusionFlag)
{ {
...@@ -113,16 +106,7 @@ void METHOD_NAME(kCalculateAmoebaFixedE_Field, Forces_kernel)( ...@@ -113,16 +106,7 @@ void METHOD_NAME(kCalculateAmoebaFixedE_Field, Forces_kernel)(
float ijField[2][3]; float ijField[2][3];
// load coords, charge, ... calculateFixedEFieldPairIxn_kernel( localParticle, psA[j], ijField
loadFixedFieldParticleData( &(psA[j]), &jCoord, jDipole, jQuadrupole );
calculateFixedEFieldPairIxn_kernel( iCoord, jCoord,
cAmoebaSim.pDampingFactorAndThole[atomI].x, psA[j].damp,
cAmoebaSim.pDampingFactorAndThole[atomI].y, psA[j].thole,
&(labFrameDipole[atomI*3]), jDipole,
&(labFrameQuadrupole[atomI*9]), jQuadrupole,
cAmoebaSim.scalingDistanceCutoff, ijField
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
, pullBack , pullBack
#endif #endif
...@@ -156,14 +140,9 @@ void METHOD_NAME(kCalculateAmoebaFixedE_Field, Forces_kernel)( ...@@ -156,14 +140,9 @@ void METHOD_NAME(kCalculateAmoebaFixedE_Field, Forces_kernel)(
float ijField[2][3]; float ijField[2][3];
loadFixedFieldParticleData( &(psA[j]), &jCoord, jDipole, jQuadrupole ); //loadFixedFieldParticleData( &(psA[j]), &jCoord, jDipole, jQuadrupole );
calculateFixedEFieldPairIxn_kernel( iCoord, jCoord, calculateFixedEFieldPairIxn_kernel( localParticle, psA[j], ijField
cAmoebaSim.pDampingFactorAndThole[atomI].x, psA[j].damp,
cAmoebaSim.pDampingFactorAndThole[atomI].y, psA[j].thole,
&(labFrameDipole[atomI*3]), jDipole,
&(labFrameQuadrupole[atomI*9]), jQuadrupole,
cAmoebaSim.scalingDistanceCutoff, ijField
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
, pullBack , pullBack
#endif #endif
...@@ -280,9 +259,7 @@ if( 0 && atomI == targetAtom ){ ...@@ -280,9 +259,7 @@ if( 0 && atomI == targetAtom ){
// load coordinates, charge, ... // load coordinates, charge, ...
loadFixedFieldShared( &(sA[threadIdx.x]), (y+tgx), loadFixedFieldShared( &(sA[threadIdx.x]), (y+tgx) );
atomCoord, labFrameDipole, labFrameQuadrupole,
cAmoebaSim.pDampingFactorAndThole );
} }
...@@ -297,16 +274,7 @@ if( 0 && atomI == targetAtom ){ ...@@ -297,16 +274,7 @@ if( 0 && atomI == targetAtom ){
float ijField[2][3]; float ijField[2][3];
// load coords, charge, ... calculateFixedEFieldPairIxn_kernel( localParticle, psA[tj], ijField
loadFixedFieldParticleData( &(psA[tj]), &jCoord, jDipole, jQuadrupole );
calculateFixedEFieldPairIxn_kernel( iCoord, jCoord,
cAmoebaSim.pDampingFactorAndThole[atomI].x, psA[tj].damp,
cAmoebaSim.pDampingFactorAndThole[atomI].y, psA[tj].thole,
&(labFrameDipole[atomI*3]), jDipole,
&(labFrameQuadrupole[atomI*9]), jQuadrupole,
cAmoebaSim.scalingDistanceCutoff, ijField
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
, pullBack , pullBack
#endif #endif
...@@ -420,14 +388,7 @@ if( 0 && (atomI == targetAtom || (y + tj) == targetAtom) ){ ...@@ -420,14 +388,7 @@ if( 0 && (atomI == targetAtom || (y + tj) == targetAtom) ){
float ijField[2][3]; float ijField[2][3];
loadFixedFieldParticleData( &(psA[tj]), &jCoord, jDipole, jQuadrupole ); calculateFixedEFieldPairIxn_kernel( localParticle, psA[tj], ijField
calculateFixedEFieldPairIxn_kernel( iCoord, jCoord,
cAmoebaSim.pDampingFactorAndThole[atomI].x, psA[tj].damp,
cAmoebaSim.pDampingFactorAndThole[atomI].y, psA[tj].thole,
&(labFrameDipole[atomI*3]), jDipole,
&(labFrameQuadrupole[atomI*9]), jQuadrupole,
cAmoebaSim.scalingDistanceCutoff, ijField
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
, pullBack , pullBack
#endif #endif
......
...@@ -46,9 +46,7 @@ struct FixedFieldParticle { ...@@ -46,9 +46,7 @@ struct FixedFieldParticle {
#endif #endif
}; };
__device__ void loadFixedFieldShared( struct FixedFieldParticle* sA, unsigned int atomI, __device__ static void loadFixedFieldShared( struct FixedFieldParticle* sA, unsigned int atomI
float4* atomCoord, float* labDipole, float* labQuadrupole,
float2* dampingFactorAndThole
#ifdef GK #ifdef GK
, float* bornR , float* bornR
#endif #endif
...@@ -56,28 +54,28 @@ __device__ void loadFixedFieldShared( struct FixedFieldParticle* sA, unsigned in ...@@ -56,28 +54,28 @@ __device__ void loadFixedFieldShared( struct FixedFieldParticle* sA, unsigned in
{ {
// coordinates & charge // coordinates & charge
sA->x = atomCoord[atomI].x; sA->x = cSim.pPosq[atomI].x;
sA->y = atomCoord[atomI].y; sA->y = cSim.pPosq[atomI].y;
sA->z = atomCoord[atomI].z; sA->z = cSim.pPosq[atomI].z;
sA->q = atomCoord[atomI].w; sA->q = cSim.pPosq[atomI].w;
// lab dipole // lab dipole
sA->labFrameDipole_X = labDipole[atomI*3]; sA->labFrameDipole_X = cAmoebaSim.pLabFrameDipole[atomI*3];
sA->labFrameDipole_Y = labDipole[atomI*3+1]; sA->labFrameDipole_Y = cAmoebaSim.pLabFrameDipole[atomI*3+1];
sA->labFrameDipole_Z = labDipole[atomI*3+2]; sA->labFrameDipole_Z = cAmoebaSim.pLabFrameDipole[atomI*3+2];
// lab quadrupole // lab quadrupole
sA->labFrameQuadrupole_XX = labQuadrupole[atomI*9]; sA->labFrameQuadrupole_XX = cAmoebaSim.pLabFrameQuadrupole[atomI*9];
sA->labFrameQuadrupole_XY = labQuadrupole[atomI*9+1]; sA->labFrameQuadrupole_XY = cAmoebaSim.pLabFrameQuadrupole[atomI*9+1];
sA->labFrameQuadrupole_XZ = labQuadrupole[atomI*9+2]; sA->labFrameQuadrupole_XZ = cAmoebaSim.pLabFrameQuadrupole[atomI*9+2];
sA->labFrameQuadrupole_YY = labQuadrupole[atomI*9+4]; sA->labFrameQuadrupole_YY = cAmoebaSim.pLabFrameQuadrupole[atomI*9+4];
sA->labFrameQuadrupole_YZ = labQuadrupole[atomI*9+5]; sA->labFrameQuadrupole_YZ = cAmoebaSim.pLabFrameQuadrupole[atomI*9+5];
sA->labFrameQuadrupole_ZZ = labQuadrupole[atomI*9+8]; sA->labFrameQuadrupole_ZZ = cAmoebaSim.pLabFrameQuadrupole[atomI*9+8];
sA->damp = dampingFactorAndThole[atomI].x; sA->damp = cAmoebaSim.pDampingFactorAndThole[atomI].x;
sA->thole = dampingFactorAndThole[atomI].y; sA->thole = cAmoebaSim.pDampingFactorAndThole[atomI].y;
#ifdef GK #ifdef GK
sA->bornR = bornR[atomI]; sA->bornR = bornR[atomI];
#endif #endif
...@@ -86,8 +84,8 @@ __device__ void loadFixedFieldShared( struct FixedFieldParticle* sA, unsigned in ...@@ -86,8 +84,8 @@ __device__ void loadFixedFieldShared( struct FixedFieldParticle* sA, unsigned in
// load struct and arrays w/ shared data in sA // load struct and arrays w/ shared data in sA
__device__ void loadFixedFieldParticleData( struct FixedFieldParticle* sA, __device__ static void loadFixedFieldParticleData( struct FixedFieldParticle* sA,
float4* jCoord, float* jDipole, float* jQuadrupole float4* jCoord, float* jDipole, float* jQuadrupole
#ifdef GK #ifdef GK
, float* bornR , float* bornR
#endif #endif
...@@ -142,15 +140,11 @@ __device__ static void zeroFixedFieldParticleSharedField( struct FixedFieldParti ...@@ -142,15 +140,11 @@ __device__ static void zeroFixedFieldParticleSharedField( struct FixedFieldParti
#endif #endif
} }
// body of fixed E-field calculation // body of fixed E-field calculation
__device__ static void calculateFixedEFieldPairIxn_kernel( float4 atomCoordinatesI, float4 atomCoordinatesJ, __device__ static void calculateFixedEFieldPairIxn_kernel( FixedFieldParticle& atomI, FixedFieldParticle& atomJ,
float dampingFactorI, float dampingFactorJ, float field[2][3]
float tholeI, float tholeJ,
float* labDipoleI, float* labDipoleJ,
float* labQuadrupoleI, float* labQuadrupoleJ,
float scalingDistanceCutoff,
float field[2][3]
#ifdef AMOEBA_DEBUG #ifdef AMOEBA_DEBUG
, float4 debugArray[12] , float4 debugArray[12]
#endif #endif
...@@ -163,9 +157,9 @@ __device__ static void calculateFixedEFieldPairIxn_kernel( float4 atomCoordinate ...@@ -163,9 +157,9 @@ __device__ static void calculateFixedEFieldPairIxn_kernel( float4 atomCoordinate
// get deltaR and r between 2 atoms // get deltaR and r between 2 atoms
float deltaR[3]; float deltaR[3];
deltaR[0] = atomCoordinatesJ.x - atomCoordinatesI.x; deltaR[0] = atomJ.x - atomI.x;
deltaR[1] = atomCoordinatesJ.y - atomCoordinatesI.y; deltaR[1] = atomJ.y - atomI.y;
deltaR[2] = atomCoordinatesJ.z - atomCoordinatesI.z; deltaR[2] = atomJ.z - atomI.z;
float r = SQRT( deltaR[0]*deltaR[0] + deltaR[1]*deltaR[1] + deltaR[2]*deltaR[2] ); float r = SQRT( deltaR[0]*deltaR[0] + deltaR[1]*deltaR[1] + deltaR[2]*deltaR[2] );
float rI = 1.0f/r; float rI = 1.0f/r;
...@@ -177,14 +171,14 @@ __device__ static void calculateFixedEFieldPairIxn_kernel( float4 atomCoordinate ...@@ -177,14 +171,14 @@ __device__ static void calculateFixedEFieldPairIxn_kernel( float4 atomCoordinate
// get scaling factors, if needed // get scaling factors, if needed
float damp = dampingFactorI*dampingFactorJ; float damp = atomI.damp*atomJ.damp;
float dampExp; float dampExp;
if( damp != 0.0f && r < scalingDistanceCutoff ){ if( damp != 0.0f && r < cAmoebaSim.scalingDistanceCutoff ){
// get scaling factors // get scaling factors
float ratio = r/damp; float ratio = r/damp;
float pGamma = tholeJ > tholeI ? tholeI : tholeJ; float pGamma = atomJ.thole > atomI.thole ? atomI.thole : atomJ.thole;
damp = ratio*ratio*ratio*pGamma; damp = ratio*ratio*ratio*pGamma;
dampExp = EXP( -damp ); dampExp = EXP( -damp );
} else { } else {
...@@ -197,69 +191,30 @@ __device__ static void calculateFixedEFieldPairIxn_kernel( float4 atomCoordinate ...@@ -197,69 +191,30 @@ __device__ static void calculateFixedEFieldPairIxn_kernel( float4 atomCoordinate
float rr5_2 = rr5*2.0f; float rr5_2 = rr5*2.0f;
#ifdef AMOEBA_DEBUG
int index = 0;
// 0-2
debugArray[index].x = r;
debugArray[index].y = rr3;
debugArray[index].z = rr5;
index++;
#endif
float* dipole = labDipoleJ;
float* quadrupole = labQuadrupoleJ;
float qDotDelta[3]; float qDotDelta[3];
qDotDelta[0] = deltaR[0]*quadrupole[0] + deltaR[1]*quadrupole[1] + deltaR[2]*quadrupole[2]; qDotDelta[0] = deltaR[0]*atomJ.labFrameQuadrupole_XX + deltaR[1]*atomJ.labFrameQuadrupole_XY + deltaR[2]*atomJ.labFrameQuadrupole_XZ;
qDotDelta[1] = deltaR[0]*quadrupole[3] + deltaR[1]*quadrupole[4] + deltaR[2]*quadrupole[5]; qDotDelta[1] = deltaR[0]*atomJ.labFrameQuadrupole_XY + deltaR[1]*atomJ.labFrameQuadrupole_YY + deltaR[2]*atomJ.labFrameQuadrupole_YZ;
qDotDelta[2] = deltaR[0]*quadrupole[6] + deltaR[1]*quadrupole[7] + deltaR[2]*quadrupole[8]; qDotDelta[2] = deltaR[0]*atomJ.labFrameQuadrupole_XZ + deltaR[1]*atomJ.labFrameQuadrupole_YZ + deltaR[2]*atomJ.labFrameQuadrupole_ZZ;
float dotdd = deltaR[0]*dipole[0] + deltaR[1]*dipole[1] + deltaR[2]*dipole[2];
float dotqd = deltaR[0]*qDotDelta[0] + deltaR[1]*qDotDelta[1] + deltaR[2]*qDotDelta[2];
float factor = -rr3*atomCoordinatesJ.w + rr5*dotdd - rr7*dotqd;
#ifdef AMOEBA_DEBUG float dotdd = deltaR[0]*atomJ.labFrameDipole_X + deltaR[1]*atomJ.labFrameDipole_Y + deltaR[2]*atomJ.labFrameDipole_Z;
// 3-5 float dotqd = deltaR[0]*qDotDelta[0] + deltaR[1]*qDotDelta[1] + deltaR[2]*qDotDelta[2];
debugArray[index].x = dotdd;
debugArray[index].y = dotqd;
debugArray[index].z = factor;
index++;
#endif
field[0][0] = deltaR[0]*factor - rr3*dipole[0] + rr5_2*qDotDelta[0]; float factor = -rr3*atomJ.q + rr5*dotdd - rr7*dotqd;
field[0][1] = deltaR[1]*factor - rr3*dipole[1] + rr5_2*qDotDelta[1];
field[0][2] = deltaR[2]*factor - rr3*dipole[2] + rr5_2*qDotDelta[2]; field[0][0] = deltaR[0]*factor - rr3*atomJ.labFrameDipole_X + rr5_2*qDotDelta[0];
field[0][1] = deltaR[1]*factor - rr3*atomJ.labFrameDipole_Y + rr5_2*qDotDelta[1];
field[0][2] = deltaR[2]*factor - rr3*atomJ.labFrameDipole_Z + rr5_2*qDotDelta[2];
dipole = labDipoleI; qDotDelta[0] = deltaR[0]*atomI.labFrameQuadrupole_XX + deltaR[1]*atomI.labFrameQuadrupole_XY + deltaR[2]*atomI.labFrameQuadrupole_XZ;
quadrupole = labQuadrupoleI; qDotDelta[1] = deltaR[0]*atomI.labFrameQuadrupole_XY + deltaR[1]*atomI.labFrameQuadrupole_YY + deltaR[2]*atomI.labFrameQuadrupole_YZ;
qDotDelta[0] = deltaR[0]*quadrupole[0] + deltaR[1]*quadrupole[1] + deltaR[2]*quadrupole[2]; qDotDelta[2] = deltaR[0]*atomI.labFrameQuadrupole_XZ + deltaR[1]*atomI.labFrameQuadrupole_YZ + deltaR[2]*atomI.labFrameQuadrupole_ZZ;
qDotDelta[1] = deltaR[0]*quadrupole[3] + deltaR[1]*quadrupole[4] + deltaR[2]*quadrupole[5];
qDotDelta[2] = deltaR[0]*quadrupole[6] + deltaR[1]*quadrupole[7] + deltaR[2]*quadrupole[8];
dotdd = deltaR[0]*dipole[0] + deltaR[1]*dipole[1] + deltaR[2]*dipole[2]; dotdd = deltaR[0]*atomI.labFrameDipole_X + deltaR[1]*atomI.labFrameDipole_Y + deltaR[2]*atomI.labFrameDipole_Z;
dotqd = deltaR[0]*qDotDelta[0] + deltaR[1]*qDotDelta[1] + deltaR[2]*qDotDelta[2]; dotqd = deltaR[0]*qDotDelta[0] + deltaR[1]*qDotDelta[1] + deltaR[2]*qDotDelta[2];
factor = rr3*atomCoordinatesI.w + rr5*dotdd + rr7*dotqd; factor = rr3*atomI.q + rr5*dotdd + rr7*dotqd;
#ifdef AMOEBA_DEBUG field[1][0] = deltaR[0]*factor - rr3*atomI.labFrameDipole_X - rr5_2*qDotDelta[0];
// 6-8 field[1][1] = deltaR[1]*factor - rr3*atomI.labFrameDipole_Y - rr5_2*qDotDelta[1];
debugArray[index].x = dotdd; field[1][2] = deltaR[2]*factor - rr3*atomI.labFrameDipole_Z - rr5_2*qDotDelta[2];
debugArray[index].y = dotqd;
debugArray[index].z = factor;
index++;
#endif
field[1][0] = deltaR[0]*factor - rr3*dipole[0] - rr5_2*qDotDelta[0];
field[1][1] = deltaR[1]*factor - rr3*dipole[1] - rr5_2*qDotDelta[1];
field[1][2] = deltaR[2]*factor - rr3*dipole[2] - rr5_2*qDotDelta[2];
#if 0
float testValue = 1.0f;
field[0][0] = testValue;
field[0][1] = testValue;
field[0][2] = testValue;
field[1][0] = testValue;
field[1][1] = testValue;
field[1][2] = testValue;
#endif
} }
...@@ -1027,6 +1027,9 @@ void cudaComputeAmoebaRealSpaceEwald( amoebaGpuContext amoebaGpu ) ...@@ -1027,6 +1027,9 @@ void cudaComputeAmoebaRealSpaceEwald( amoebaGpuContext amoebaGpu )
(void) fflush( amoebaGpu->log ); (void) fflush( amoebaGpu->log );
#endif #endif
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
cudaBindTexture(NULL, &tabulatedErfcRef, gpu->psTabulatedErfc->_pDevData, &channelDesc, gpu->psTabulatedErfc->_length*sizeof(float));
kCalculateAmoebaCudaRealSpaceEwaldN2Forces_kernel<<<amoebaGpu->nonbondBlocks, threadsPerBlock, sizeof(RealSpaceEwaldParticle)*threadsPerBlock>>>( kCalculateAmoebaCudaRealSpaceEwaldN2Forces_kernel<<<amoebaGpu->nonbondBlocks, threadsPerBlock, sizeof(RealSpaceEwaldParticle)*threadsPerBlock>>>(
amoebaGpu->psWorkUnit->_pDevStream[0], amoebaGpu->psWorkUnit->_pDevStream[0],
gpu->psPosq4->_pDevStream[0], gpu->psPosq4->_pDevStream[0],
......
...@@ -368,8 +368,12 @@ void kCalculateAmoebaMultipoleForces(amoebaGpuContext amoebaGpu, bool hasAmoebaG ...@@ -368,8 +368,12 @@ void kCalculateAmoebaMultipoleForces(amoebaGpuContext amoebaGpu, bool hasAmoebaG
cudaComputeAmoebaFixedEAndGkFields( amoebaGpu ); cudaComputeAmoebaFixedEAndGkFields( amoebaGpu );
cudaComputeAmoebaMutualInducedAndGkField( amoebaGpu ); cudaComputeAmoebaMutualInducedAndGkField( amoebaGpu );
} else { } else {
cudaComputeAmoebaFixedEField( amoebaGpu ); if( amoebaGpu->multipoleNonbondedMethod == AMOEBA_NO_CUTOFF ){
cudaComputeAmoebaMutualInducedField( amoebaGpu ); cudaComputeAmoebaFixedEField( amoebaGpu );
cudaComputeAmoebaMutualInducedField( amoebaGpu );
} else {
cudaComputeAmoebaPmeFixedEField( amoebaGpu );
}
} }
// check if induce dipole calculation converged -- abort if it did not // check if induce dipole calculation converged -- abort if it did not
......
...@@ -1989,6 +1989,7 @@ static int readAmoebaMultipoleParameters( FILE* filePtr, int version, MapStringI ...@@ -1989,6 +1989,7 @@ static int readAmoebaMultipoleParameters( FILE* filePtr, int version, MapStringI
int usePme = 0; int usePme = 0;
double aewald = 0.0; double aewald = 0.0;
double cutoffDistance = 0.0; double cutoffDistance = 0.0;
double box[3] = { 10.0, 10.0, 10.0 };
// usePme, aewald, cutoffDistance added w/ Version 1 // usePme, aewald, cutoffDistance added w/ Version 1
...@@ -1996,7 +1997,11 @@ static int readAmoebaMultipoleParameters( FILE* filePtr, int version, MapStringI ...@@ -1996,7 +1997,11 @@ static int readAmoebaMultipoleParameters( FILE* filePtr, int version, MapStringI
usePme = atoi( tokens[2].c_str() ); usePme = atoi( tokens[2].c_str() );
aewald = atof( tokens[3].c_str() ); aewald = atof( tokens[3].c_str() );
cutoffDistance = atof( tokens[4].c_str() ); cutoffDistance = atof( tokens[4].c_str() );
box[0] = atof( tokens[5].c_str() );
box[1] = atof( tokens[6].c_str() );
box[2] = atof( tokens[7].c_str() );
} }
if( usePme ){ if( usePme ){
multipoleForce->setNonbondedMethod( AmoebaMultipoleForce::PME ); multipoleForce->setNonbondedMethod( AmoebaMultipoleForce::PME );
} else { } else {
...@@ -2004,6 +2009,7 @@ static int readAmoebaMultipoleParameters( FILE* filePtr, int version, MapStringI ...@@ -2004,6 +2009,7 @@ static int readAmoebaMultipoleParameters( FILE* filePtr, int version, MapStringI
} }
multipoleForce->setAEwald( aewald ); multipoleForce->setAEwald( aewald );
multipoleForce->setCutoffDistance( cutoffDistance ); multipoleForce->setCutoffDistance( cutoffDistance );
system.setDefaultPeriodicBoxVectors( Vec3(box[0], 0.0, 0.0), Vec3(0.0, box[1], 0.0), Vec3(0.0, 0.0, box[2]) );
if( log ){ if( log ){
(void) fprintf( log, "%s number of MultipoleParameter terms=%d usePme=%d aewald=%15.7e cutoffDistance=%12.4f\n", (void) fprintf( log, "%s number of MultipoleParameter terms=%d usePme=%d aewald=%15.7e cutoffDistance=%12.4f\n",
methodName.c_str(), numberOfMultipoles, usePme, aewald, cutoffDistance ); methodName.c_str(), numberOfMultipoles, usePme, aewald, cutoffDistance );
...@@ -2106,10 +2112,26 @@ static int readAmoebaMultipoleParameters( FILE* filePtr, int version, MapStringI ...@@ -2106,10 +2112,26 @@ static int readAmoebaMultipoleParameters( FILE* filePtr, int version, MapStringI
double polarityConversion = AngstromToNm*AngstromToNm*AngstromToNm; double polarityConversion = AngstromToNm*AngstromToNm*AngstromToNm;
double dampingFactorConversion = sqrt( AngstromToNm ); double dampingFactorConversion = sqrt( AngstromToNm );
float scalingDistanceCutoff = static_cast<float>(multipoleForce->getScalingDistanceCutoff()); multipoleForce->setAEwald( multipoleForce->getAEwald()/AngstromToNm);
scalingDistanceCutoff *= static_cast<float>(AngstromToNm); multipoleForce->setCutoffDistance( multipoleForce->getCutoffDistance()*AngstromToNm );
multipoleForce->setScalingDistanceCutoff( scalingDistanceCutoff ); multipoleForce->setScalingDistanceCutoff( multipoleForce->getScalingDistanceCutoff()*AngstromToNm );
Vec3 a,b,c;
system.getDefaultPeriodicBoxVectors( a, b, c);
a[0] *= AngstromToNm;
a[1] *= AngstromToNm;
a[2] *= AngstromToNm;
b[0] *= AngstromToNm;
b[1] *= AngstromToNm;
b[2] *= AngstromToNm;
c[0] *= AngstromToNm;
c[1] *= AngstromToNm;
c[2] *= AngstromToNm;
system.setDefaultPeriodicBoxVectors( a, b, c);
for( int ii = 0; ii < multipoleForce->getNumMultipoles(); ii++ ){ for( int ii = 0; ii < multipoleForce->getNumMultipoles(); ii++ ){
...@@ -2144,6 +2166,15 @@ static int readAmoebaMultipoleParameters( FILE* filePtr, int version, MapStringI ...@@ -2144,6 +2166,15 @@ static int readAmoebaMultipoleParameters( FILE* filePtr, int version, MapStringI
(void) fprintf( log, "%s Sample of parameters using %s units.\n", methodName.c_str(), (void) fprintf( log, "%s Sample of parameters using %s units.\n", methodName.c_str(),
(useOpenMMUnits ? "OpenMM" : "Amoeba") ); (useOpenMMUnits ? "OpenMM" : "Amoeba") );
std::string nonbondedMethod = multipoleForce->getNonbondedMethod( ) == AmoebaMultipoleForce::PME ? "PME" : "NoCutoff";
(void) fprintf( log, "NonbondedMethod=%s aEwald=%15.7e cutoff=%15.7e.\n", nonbondedMethod.c_str(),
multipoleForce->getAEwald(), multipoleForce->getCutoffDistance() );
Vec3 a,b,c;
system.getDefaultPeriodicBoxVectors( a, b, c );
(void) fprintf( log, "Box=[%12.3f %12.3f %12.3f] [%12.3f %12.3f %12.3f] [%12.3f %12.3f %12.3f]\n",
a[0], a[1], a[2], b[0], b[1], b[2], c[0], c[1], c[2] );
(void) fprintf( log, "Supplementary fields %u: ", static_cast<unsigned int>(supplementary.size()) ); (void) fprintf( log, "Supplementary fields %u: ", static_cast<unsigned int>(supplementary.size()) );
for( MapStringVectorOfVectorsCI ii = supplementary.begin(); ii != supplementary.end(); ii++ ){ for( MapStringVectorOfVectorsCI ii = supplementary.begin(); ii != supplementary.end(); ii++ ){
(void) fprintf( log, "%s ", (*ii).first.c_str() ); (void) fprintf( log, "%s ", (*ii).first.c_str() );
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment