Unverified Commit 8e8923a7 authored by Peter Eastman's avatar Peter Eastman Committed by GitHub
Browse files

Converted AMOEBA to common platform (#3120)

* Began converting AMOEBA to common platform

* Beginning of OpenCL platform for AMOEBA

* Converted AmoebaVdwForce to common platform

* Cleaned up reference AMOEBA tests

* Began converting AmoebaMultipoleForce to common platform

* Continue converting AmoebaMultipoleForce to common platform

* Bug fixes

* Bug fix

* Continue converting AmoebaMultipoleForce to common platform

* Converting AmoebaMultipoleForce and AmoebaGeneralizedKirkwoodForce to common platform

* Converting AmoebaMultipoleForce and AmoebaGeneralizedKirkwoodForce to common platform

* Creating OpenCL version of AmoebaMultipoleForce and AmoebaGeneralizedKirkwoodForce

* Creating OpenCL version of AmoebaMultipoleForce and AmoebaGeneralizedKirkwoodForce

* Creating OpenCL version of AmoebaMultipoleForce and AmoebaGeneralizedKirkwoodForce

* Converted arrays from real3 to real

* Bug fix to OpenCL AmoebaGeneralizedKirkwoodForce

* Fixes for AMD GPUs

* Began converting HippoNonbondedForce to common platform

* Continuing to convert HippoNonbondedForce to common platform

* Continuing to convert HippoNonbondedForce to common platform

* Working on unifying PME kernels

* Fixed error on devices without 64 bit atomics

* Unified PME kernels

* Converted HippoNonbondedForce to common platform

* Creating OpenCL implementation of HippoNonbondedForce

* Continuing OpenCL implementation of HippoNonbondedForce

* Mostly finished OpenCL implementation of HippoNonbondedForce

* Eliminated three component vector types in host code

* Fix errors on CPU OpenCL

* Skip double precision tests for AMOEBA on OpenCL

* Bug fixes

* Bug fixes

* Fixed compilation error
parent 393a4dbd
...@@ -351,16 +351,16 @@ __device__ void computeOneInteraction(AtomData& atom1, AtomData& atom2, real3 de ...@@ -351,16 +351,16 @@ __device__ void computeOneInteraction(AtomData& atom1, AtomData& atom2, real3 de
extern "C" __global__ void computeInducedField( extern "C" __global__ void computeInducedField(
unsigned long long* __restrict__ field, unsigned long long* __restrict__ fieldPolar, const real4* __restrict__ posq, const int2* __restrict__ exclusionTiles, unsigned long long* __restrict__ field, unsigned long long* __restrict__ fieldPolar, const real4* __restrict__ posq, const int2* __restrict__ exclusionTiles,
const real3* __restrict__ inducedDipole, const real3* __restrict__ inducedDipolePolar, unsigned int startTileIndex, unsigned int numTileIndices, const real3* __restrict__ inducedDipole, const real3* __restrict__ inducedDipolePolar, unsigned int startTileIndex, unsigned int numTileIndices,
#ifdef EXTRAPOLATED_POLARIZATION
unsigned long long* __restrict__ fieldGradient, unsigned long long* __restrict__ fieldGradientPolar,
#endif
#ifdef USE_CUTOFF #ifdef USE_CUTOFF
const int* __restrict__ tiles, const unsigned int* __restrict__ interactionCount, real4 periodicBoxSize, real4 invPeriodicBoxSize, const int* __restrict__ tiles, const unsigned int* __restrict__ interactionCount, real4 periodicBoxSize, real4 invPeriodicBoxSize,
real4 periodicBoxVecX, real4 periodicBoxVecY, real4 periodicBoxVecZ, unsigned int maxTiles, const real4* __restrict__ blockCenter, const unsigned int* __restrict__ interactingAtoms, real4 periodicBoxVecX, real4 periodicBoxVecY, real4 periodicBoxVecZ, unsigned int maxTiles, const real4* __restrict__ blockCenter, const unsigned int* __restrict__ interactingAtoms,
#elif defined USE_GK #elif defined USE_GK
unsigned long long* __restrict__ fieldS, unsigned long long* __restrict__ fieldPolarS, const real3* __restrict__ inducedDipoleS, unsigned long long* __restrict__ fieldS, unsigned long long* __restrict__ fieldPolarS, const real3* __restrict__ inducedDipoleS,
const real3* __restrict__ inducedDipolePolarS, const real* __restrict__ bornRadii, const real3* __restrict__ inducedDipolePolarS, const real* __restrict__ bornRadii,
#ifdef EXTRAPOLATED_POLARIZATION #endif
#ifdef EXTRAPOLATED_POLARIZATION
unsigned long long* __restrict__ fieldGradient, unsigned long long* __restrict__ fieldGradientPolar,
#ifdef USE_GK
unsigned long long* __restrict__ fieldGradientS, unsigned long long* __restrict__ fieldGradientPolarS, unsigned long long* __restrict__ fieldGradientS, unsigned long long* __restrict__ fieldGradientPolarS,
#endif #endif
#endif #endif
...@@ -549,10 +549,11 @@ extern "C" __global__ void computeInducedField( ...@@ -549,10 +549,11 @@ extern "C" __global__ void computeInducedField(
} }
extern "C" __global__ void recordInducedDipolesForDIIS(const long long* __restrict__ fixedField, const long long* __restrict__ fixedFieldPolar, extern "C" __global__ void recordInducedDipolesForDIIS(const long long* __restrict__ fixedField, const long long* __restrict__ fixedFieldPolar,
const float* __restrict__ polarizability, float2* __restrict__ errors, real* __restrict__ prevErrors, real* __restrict__ matrix,
const long long* __restrict__ fixedFieldS, const long long* __restrict__ inducedField, const long long* __restrict__ inducedFieldPolar, 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, const real* __restrict__ inducedDipole, const real* __restrict__ inducedDipolePolar,
real* __restrict__ prevDipoles, real* __restrict__ prevDipolesPolar, real* __restrict__ prevErrors, int iteration, bool recordPrevErrors, real* __restrict__ matrix) { real* __restrict__ prevDipoles, real* __restrict__ prevDipolesPolar, int iteration, bool recordPrevErrors) {
extern __shared__ real2 buffer[]; __shared__ real2 buffer[64];
const real fieldScale = 1/(real) 0x100000000; const real fieldScale = 1/(real) 0x100000000;
real sumErrors = 0; real sumErrors = 0;
real sumPolarErrors = 0; real sumPolarErrors = 0;
...@@ -617,7 +618,7 @@ extern "C" __global__ void recordInducedDipolesForDIIS(const long long* __restri ...@@ -617,7 +618,7 @@ extern "C" __global__ void recordInducedDipolesForDIIS(const long long* __restri
} }
extern "C" __global__ void computeDIISMatrix(real* __restrict__ prevErrors, int iteration, real* __restrict__ matrix) { extern "C" __global__ void computeDIISMatrix(real* __restrict__ prevErrors, int iteration, real* __restrict__ matrix) {
extern __shared__ real sumBuffer[]; __shared__ real sumBuffer[512];
int j = min(iteration, MAX_PREV_DIIS_DIPOLES-1); int j = min(iteration, MAX_PREV_DIIS_DIPOLES-1);
for (int i = blockIdx.x; i <= j; i += gridDim.x) { 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. // All the threads in this thread block work together to compute a single matrix element.
......
...@@ -1271,10 +1271,11 @@ extern "C" __global__ void calculateSelfEnergyAndTorque(long long* __restrict__ ...@@ -1271,10 +1271,11 @@ extern "C" __global__ void calculateSelfEnergyAndTorque(long long* __restrict__
#else #else
extern "C" __global__ void recordInducedFieldDipoles(const real* __restrict__ phid, real* const __restrict__ phip, long long* __restrict__ inducedField, extern "C" __global__ void recordInducedFieldDipoles(const real* __restrict__ phid, real* const __restrict__ phip, long long* __restrict__ inducedField,
long long* __restrict__ inducedFieldPolar, const real3* __restrict__ inducedDipole, const real3* __restrict__ inducedDipolePolar, long long* __restrict__ inducedFieldPolar, const real3* __restrict__ inducedDipole, const real3* __restrict__ inducedDipolePolar,
real3 recipBoxVecX, real3 recipBoxVecY, real3 recipBoxVecZ
#ifdef EXTRAPOLATED_POLARIZATION #ifdef EXTRAPOLATED_POLARIZATION
unsigned long long* __restrict__ fieldGradient, unsigned long long* __restrict__ fieldGradientPolar, , unsigned long long* __restrict__ fieldGradient, unsigned long long* __restrict__ fieldGradientPolar
#endif #endif
real3 recipBoxVecX, real3 recipBoxVecY, real3 recipBoxVecZ) { ) {
__shared__ real fracToCart[3][3]; __shared__ real fracToCart[3][3];
if (threadIdx.x == 0) { if (threadIdx.x == 0) {
fracToCart[0][0] = GRID_SIZE_X*recipBoxVecX.x; fracToCart[0][0] = GRID_SIZE_X*recipBoxVecX.x;
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
ENABLE_TESTING() ENABLE_TESTING()
INCLUDE_DIRECTORIES(${CUDA_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${CUDA_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${OPENMM_DIR}/plugins/amoeba/tests)
INCLUDE_DIRECTORIES(${OPENMM_DIR}/platforms/cuda/tests)
# Automatically create tests using files named "Test*.cpp" # Automatically create tests using files named "Test*.cpp"
FILE(GLOB TEST_PROGS "*Test*.cpp") FILE(GLOB TEST_PROGS "*Test*.cpp")
......
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2013 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "CudaTests.h"
extern "C" void registerAmoebaCudaKernelFactories();
using namespace OpenMM;
void setupKernels (int argc, char* argv[]) {
registerAmoebaCudaKernelFactories();
platform = dynamic_cast<CudaPlatform&>(Platform::getPlatformByName("CUDA"));
initializeTests(argc, argv);
}
/* -------------------------------------------------------------------------- * /* -------------------------------------------------------------------------- *
* OpenMMAmoeba * * OpenMM *
* -------------------------------------------------------------------------- * * -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from * * This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of * * Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2015 Stanford University and the Authors. * * Portions copyright (c) 2021 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
* Permission is hereby granted, free of charge, to any person obtaining a * * Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), * * copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation * * to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, * * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the * * and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: * * Software is furnished to do so, subject to the following conditions: *
* * * *
...@@ -29,498 +29,7 @@ ...@@ -29,498 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
/** #include "CudaAmoebaTests.h"
* This tests the CUDA implementation of the extrapolated polarization algorithms in AmoebaMultipoleForce. #include "TestAmoebaExtrapolatedPolarization.h"
*/
#include "openmm/internal/AssertionUtilities.h" void runPlatformTests() {}
#include "openmm/Context.h"
#include "OpenMMAmoeba.h"
#include "openmm/System.h"
#include "openmm/AmoebaMultipoleForce.h"
#include "openmm/LangevinIntegrator.h"
#include "openmm/Vec3.h"
#include "openmm/Units.h"
#include <iostream>
#include <iomanip>
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#define ASSERT_EQUAL_TOL_MOD(expected, found, tol, testname) {double _scale_ = std::abs(expected) > 1.0 ? std::abs(expected) : 1.0; if (!(std::abs((expected)-(found))/_scale_ <= (tol))) {std::stringstream details; details << testname << " Expected "<<(expected)<<", found "<<(found); throwException(__FILE__, __LINE__, details.str());}};
#define ASSERT_EQUAL_VEC_MOD(expected, found, tol, testname) {double _norm_ = std::sqrt(expected.dot(expected)); double _scale_ = _norm_ > 1.0 ? _norm_ : 1.0; if ((std::abs((expected[0])-(found[0]))/_scale_ > (tol)) || (std::abs((expected[1])-(found[1]))/_scale_ > (tol)) || (std::abs((expected[2])-(found[2]))/_scale_ > (tol))) {std::stringstream details; details << testname << " Expected "<<(expected)<<", found "<<(found); throwException(__FILE__, __LINE__, details.str());}};
using namespace OpenMM;
using namespace std;
extern "C" void registerAmoebaCudaKernelFactories();
const double TOL = 1e-4;
// print the energy and forces out, in AKMA units, to allow comparison with TINKER
static void printEnergyAndForces(double energy, vector<Vec3> &forces){
size_t natoms = forces.size();
double sf = 1.0;
std::cout << "Energy (SI):" << std::setw(20) << std::setprecision(10) << energy << std::endl;
std::cout << "Forces (SI):" << std::endl;
for(int i = 0; i < natoms; ++i){
std::cout << i+1 << "\t" << std::setw(20) << std::setprecision(10) << forces[i][0]*sf <<
std::setw(20) << std::setprecision(10) << forces[i][1]*sf <<
std::setw(20) << std::setprecision(10) << forces[i][2]*sf << std::endl;
}
sf = -OpenMM::KcalPerKJ/10.0;
std::cout << "Energy (AKMA):" << std::setw(20) << std::setprecision(10) << energy*OpenMM::KcalPerKJ << std::endl;
std::cout << "Forces (AKMA):" << std::endl;
for(int i = 0; i < natoms; ++i){
std::cout << i+1 << "\t" << std::setw(20) << std::setprecision(10) << forces[i][0]*sf <<
std::setw(20) << std::setprecision(10) << forces[i][1]*sf <<
std::setw(20) << std::setprecision(10) << forces[i][2]*sf << std::endl;
}
}
// compare forces and energies
static void compareForcesEnergy(std::string& testName, double expectedEnergy, double energy,
const std::vector<Vec3>& expectedForces,
const std::vector<Vec3>& forces, double tolerance) {
for (unsigned int ii = 0; ii < forces.size(); ii++) {
ASSERT_EQUAL_VEC_MOD(expectedForces[ii], forces[ii], tolerance, testName);
}
ASSERT_EQUAL_TOL_MOD(expectedEnergy, energy, tolerance, testName);
}
// compare relative differences in force norms and energies
static void compareForceNormsEnergy(std::string& testName, double expectedEnergy, double energy,
std::vector<Vec3>& expectedForces,
const std::vector<Vec3>& forces, double tolerance) {
for (unsigned int ii = 0; ii < forces.size(); ii++) {
double expectedNorm = sqrt(expectedForces[ii][0]*expectedForces[ii][0] +
expectedForces[ii][1]*expectedForces[ii][1] +
expectedForces[ii][2]*expectedForces[ii][2]);
double norm = sqrt(forces[ii][0]*forces[ii][0] + forces[ii][1]*forces[ii][1] + forces[ii][2]*forces[ii][2]);
double absDiff = fabs(norm - expectedNorm);
double relDiff = 2.0*absDiff/(fabs(norm) + fabs(expectedNorm) + 1.0e-08);
if (relDiff > tolerance && absDiff > 0.001) {
std::stringstream details;
details << testName << "Relative difference in norms " << relDiff << " larger than allowed tolerance at particle=" << ii;
details << ": norms=" << norm << " expected norm=" << expectedNorm;
throwException(__FILE__, __LINE__, details.str());
}
}
double energyAbsDiff = fabs(expectedEnergy - energy);
double energyRelDiff = 2.0*energyAbsDiff/(fabs(expectedEnergy) + fabs(energy) + 1.0e-08);
if (energyRelDiff > tolerance) {
std::stringstream details;
details << testName << "Relative difference in energies " << energyRelDiff << " larger than allowed tolerance.";
details << "Energies=" << energy << " expected energy=" << expectedEnergy;
throwException(__FILE__, __LINE__, details.str());
}
}
vector<Vec3> setupWaterDimer(System& system, AmoebaMultipoleForce* amoebaMultipoleForce, bool use_pol_groups) {
const int NATOMS = 6;
const char* atom_types[NATOMS] = {"O", "H1", "H2", "O", "H1", "H2"};
const double coords[NATOMS][3] = {
{ 2.000000, 2.000000, 2.000000},
{ 2.500000, 2.000000, 3.000000},
{ 1.500000, 2.000000, 3.000000},
{ 0.000000, 0.000000, 0.000000},
{ 0.500000, 0.000000, 1.000000},
{ -0.500000, 0.000000, 1.000000}
};
std::map < std::string, double > tholemap;
std::map < std::string, double > polarmap;
std::map < std::string, double > chargemap;
std::map < std::string, std::vector<double> > dipolemap;
std::map < std::string, std::vector<double> > quadrupolemap;
std::map < std::string, AmoebaMultipoleForce::MultipoleAxisTypes > axesmap;
std::map < std::string, std::vector<int> > anchormap;
std::map < std::string, double > massmap;
std::map < std::string, std::vector<int> > polgrpmap;
std::map < std::string, std::vector<int> > cov12map;
std::map < std::string, std::vector<int> > cov13map;
axesmap["O"] = AmoebaMultipoleForce::Bisector;
axesmap["H1"] = AmoebaMultipoleForce::ZThenX;
axesmap["H2"] = AmoebaMultipoleForce::ZThenX;
chargemap["O"] = -0.51966;
chargemap["H1"] = 0.25983;
chargemap["H2"] = 0.25983;
int oanc[3] = {1, 2, 0};
int h1anc[3] = {-1, 1, 0};
int h2anc[3] = {-2, -1, 0};
std::vector<int> oancv(&oanc[0], &oanc[3]);
std::vector<int> h1ancv(&h1anc[0], &h1anc[3]);
std::vector<int> h2ancv(&h2anc[0], &h2anc[3]);
anchormap["O"] = oancv;
anchormap["H1"] = h1ancv;
anchormap["H2"] = h2ancv;
double od[3] = {0.0, 0.0, 0.00755612136146};
double hd[3] = {-0.00204209484795, 0.0, -0.00307875299958};
std::vector<double> odv(&od[0], &od[3]);
std::vector<double> hdv(&hd[0], &hd[3]);
dipolemap["O"] = odv;
dipolemap["H1"] = hdv;
dipolemap["H2"] = hdv;
double oq[9] = {0.000354030721139, 0.0, 0.0,
0.0, -0.000390257077096, 0.0,
0.0, 0.0, 3.62263559571e-05};
double hq[9] = {-3.42848248983e-05, 0.0, -1.89485963908e-06,
0.0, -0.000100240875193, 0.0,
-1.89485963908e-06, 0.0, 0.000134525700091};
std::vector<double> oqv(&oq[0], &oq[9]);
std::vector<double> hqv(&hq[0], &hq[9]);
quadrupolemap["O"] = oqv;
quadrupolemap["H1"] = hqv;
quadrupolemap["H2"] = hqv;
polarmap["O"] = 0.3069876538;
polarmap["H1"] = 0.2813500172;
polarmap["H2"] = 0.2813500172;
polarmap["O"] = 0.000837;
polarmap["H1"] = 0.000496;
polarmap["H2"] = 0.000496;
tholemap["O"] = 0.3900;
tholemap["H1"] = 0.3900;
tholemap["H2"] = 0.3900;
massmap["O"] = 15.999;
massmap["H1"] = 1.0080000;
massmap["H2"] = 1.0080000;
int opg[3] = {0,1,2};
int h1pg[3] = {-1,0,1};
int h2pg[3] = {-2,-1,0};
std::vector<int> opgv(&opg[0], &opg[3]);
std::vector<int> h1pgv(&h1pg[0], &h1pg[3]);
std::vector<int> h2pgv(&h2pg[0], &h2pg[3]);
if(!use_pol_groups){
opgv.clear();
h1pgv.clear();
h2pgv.clear();
}
polgrpmap["O"] = opgv;
polgrpmap["H1"] = h1pgv;
polgrpmap["H2"] = h2pgv;
int cov12o[2] = {1,2};
int cov12h1[1] = {-1};
int cov12h2[1] = {-2};
std::vector<int> cov12ov(&cov12o[0], &cov12o[2]);
std::vector<int> cov12h1v(&cov12h1[0], &cov12h1[1]);
std::vector<int> cov12h2v(&cov12h2[0], &cov12h2[1]);
cov12map["O"] = cov12ov;
cov12map["H1"] = cov12h1v;
cov12map["H2"] = cov12h2v;
int cov13h1[1] = {1};
int cov13h2[1] = {-1};
std::vector<int> cov13h1v(&cov13h1[0], &cov13h1[1]);
std::vector<int> cov13h2v(&cov13h2[0], &cov13h2[1]);
cov13map["O"] = std::vector<int>();
cov13map["H1"] = cov13h1v;
cov13map["H2"] = cov13h2v;
std::vector<Vec3> positions(NATOMS);
for(int atom = 0; atom < NATOMS; ++atom){
const char* element = atom_types[atom];
double damp = polarmap[element];
double alpha = pow(damp, 1.0/6.0);
int atomz = atom + anchormap[element][0];
int atomx = atom + anchormap[element][1];
int atomy = anchormap[element][2]==0 ? -1 : atom + anchormap[element][2];
amoebaMultipoleForce->addMultipole(chargemap[element], dipolemap[element], quadrupolemap[element],
axesmap[element], atomz, atomx, atomy, tholemap[element], alpha, damp);
system.addParticle(massmap[element]);
double offset =0.0;
positions[atom] = Vec3(coords[atom][0]+offset, coords[atom][1]+offset, coords[atom][2]+offset)*OpenMM::NmPerAngstrom;
// Polarization groups
std::vector<int> tmppol;
std::vector<int>& polgrps = polgrpmap[element];
for(int i=0; i < polgrps.size(); ++i)
tmppol.push_back(polgrps[i]+atom);
if(!tmppol.empty())
amoebaMultipoleForce->setCovalentMap(atom, AmoebaMultipoleForce::PolarizationCovalent11, tmppol);
// 1-2 covalent groups
std::vector<int> tmp12;
std::vector<int>& cov12s = cov12map[element];
for(int i=0; i < cov12s.size(); ++i)
tmp12.push_back(cov12s[i]+atom);
if(!tmp12.empty())
amoebaMultipoleForce->setCovalentMap(atom, AmoebaMultipoleForce::Covalent12, tmp12);
// 1-3 covalent groups
std::vector<int> tmp13;
std::vector<int>& cov13s = cov13map[element];
for(int i=0; i < cov13s.size(); ++i)
tmp13.push_back(cov13s[i]+atom);
if(!tmp13.empty())
amoebaMultipoleForce->setCovalentMap(atom, AmoebaMultipoleForce::Covalent13, tmp13);
}
system.addForce(amoebaMultipoleForce);
return positions;
}
static void check_finite_differences(vector<Vec3> analytic_forces, Context &context, vector<Vec3> positions)
{
double tol = 1e-5;
// We allow more permissive testing for single precision.
if(Platform::getPlatformByName("CUDA").getPropertyValue(context, "Precision") != "double") tol = 5e-4;
// Take a small step in the direction of the energy gradient and see whether the potential energy changes by the expected amount.
double norm = 0.0;
for (auto& f : analytic_forces)
norm += f.dot(f);
norm = std::sqrt(norm);
const double stepSize = 1e-3;
double step = 0.5*stepSize/norm;
vector<Vec3> positions2(analytic_forces.size()), positions3(analytic_forces.size());
for (int i = 0; i < (int) positions.size(); ++i) {
Vec3 p = positions[i];
Vec3 f = analytic_forces[i];
positions2[i] = Vec3(p[0]-f[0]*step, p[1]-f[1]*step, p[2]-f[2]*step);
positions3[i] = Vec3(p[0]+f[0]*step, p[1]+f[1]*step, p[2]+f[2]*step);
}
context.setPositions(positions2);
State state2 = context.getState(State::Energy);
context.setPositions(positions3);
State state3 = context.getState(State::Energy);
ASSERT_EQUAL_TOL(norm, (state2.getPotentialEnergy()-state3.getPotentialEnergy())/stepSize, tol);
}
static void testWaterDimerTriclinicPME() {
std::string testName = "testWaterDimerTriclinicPME";
System system;
AmoebaMultipoleForce* amoebaMultipoleForce = new AmoebaMultipoleForce();;
vector<Vec3> coords = setupWaterDimer(system, amoebaMultipoleForce, true);
system.setDefaultPeriodicBoxVectors(Vec3(2.0, 0.0, 0.0),
Vec3(0.2, 2.0, 0.0),
Vec3(0.1, 0.5, 2.0));
amoebaMultipoleForce->setNonbondedMethod(AmoebaMultipoleForce::PME);
amoebaMultipoleForce->setPolarizationType(AmoebaMultipoleForce::Extrapolated);
std::vector<double> coefs;
coefs.push_back(0.0); // The mu_0 coefficient
coefs.push_back(-0.3); // The mu_1 coefficient
coefs.push_back(0.0); // The mu_2 coefficient
coefs.push_back(1.3); // The mu_3 coefficient
amoebaMultipoleForce->setExtrapolationCoefficients(coefs);
amoebaMultipoleForce->setCutoffDistance(9.0*OpenMM::NmPerAngstrom);
amoebaMultipoleForce->setAEwald(4);
amoebaMultipoleForce->setEwaldErrorTolerance(1.0e-06);
std::vector<int> pmeGridDimension(3);
pmeGridDimension[0] = pmeGridDimension[1] = pmeGridDimension[2] = 64;
amoebaMultipoleForce->setPmeGridDimensions(pmeGridDimension);
LangevinIntegrator integrator(0.0, 0.1, 0.01);
Context context(system, integrator, Platform::getPlatformByName("CUDA"));
context.setPositions(coords);
OpenMM::State state = context.getState(State::Forces | State::Energy);
std::vector<Vec3> forces = state.getForces();
double energy = state.getPotentialEnergy();
// printEnergyAndForces(energy, forces);
double expectedEnergy = -1.945797427;
std::vector<Vec3> expectedForces(forces.size());
expectedForces[0] = Vec3( -131.1099603, -187.2725558, 36.94657685);
expectedForces[1] = Vec3( 38.6397841, 2.410997985, 8.008437937);
expectedForces[2] = Vec3( 38.69034185, 117.5018257, 32.43097836);
expectedForces[3] = Vec3( -117.3212339, -102.3366145, -30.50621066);
expectedForces[4] = Vec3( 124.8343077, 169.7729804, -24.10742414);
expectedForces[5] = Vec3( 46.26244074, -0.07194110719, -22.77727325);
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
check_finite_differences(forces, context, coords);
}
static void testWaterDimerTriclinicPMENoPolGroups() {
std::string testName = "testWaterDimerTriclinicPMENoPolGroups";
System system;
AmoebaMultipoleForce* amoebaMultipoleForce = new AmoebaMultipoleForce();;
vector<Vec3> coords = setupWaterDimer(system, amoebaMultipoleForce, false);
system.setDefaultPeriodicBoxVectors(Vec3(2.0, 0.0, 0.0),
Vec3(0.2, 2.0, 0.0),
Vec3(0.1, 0.5, 2.0));
amoebaMultipoleForce->setNonbondedMethod(AmoebaMultipoleForce::PME);
amoebaMultipoleForce->setPolarizationType(AmoebaMultipoleForce::Extrapolated);
std::vector<double> coefs;
coefs.push_back(0.0); // The mu_0 coefficient
coefs.push_back(-0.3); // The mu_1 coefficient
coefs.push_back(0.0); // The mu_2 coefficient
coefs.push_back(1.3); // The mu_3 coefficient
amoebaMultipoleForce->setExtrapolationCoefficients(coefs);
amoebaMultipoleForce->setCutoffDistance(9.0*OpenMM::NmPerAngstrom);
amoebaMultipoleForce->setAEwald(4);
amoebaMultipoleForce->setEwaldErrorTolerance(1.0e-06);
std::vector<int> pmeGridDimension(3);
pmeGridDimension[0] = pmeGridDimension[1] = pmeGridDimension[2] = 64;
amoebaMultipoleForce->setPmeGridDimensions(pmeGridDimension);
LangevinIntegrator integrator(0.0, 0.1, 0.01);
Context context(system, integrator, Platform::getPlatformByName("CUDA"));
context.setPositions(coords);
OpenMM::State state = context.getState(State::Forces | State::Energy);
std::vector<Vec3> forces = state.getForces();
double energy = state.getPotentialEnergy();
// printEnergyAndForces(energy, forces);
double expectedEnergy = -1.840068409;
std::vector<Vec3> expectedForces(forces.size());
expectedForces[0] = Vec3( -69.85154559, -104.2092334, 3.586495334);
expectedForces[1] = Vec3( 19.50350452, -14.5844519, 9.400418341);
expectedForces[2] = Vec3( 16.75641493, 75.15006506, 19.14553199);
expectedForces[3] = Vec3( -67.24268213, -47.39994175, -18.81277222);
expectedForces[4] = Vec3( 75.15808251, 110.6109313, 4.355432435);
expectedForces[5] = Vec3( 25.67255306, -19.56378113, -17.68217953);
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
check_finite_differences(forces, context, coords);
}
static void testWaterDimerNoCutoff() {
std::string testName = "testWaterDimerNoCutoff";
System system;
AmoebaMultipoleForce* amoebaMultipoleForce = new AmoebaMultipoleForce();;
vector<Vec3> coords = setupWaterDimer(system, amoebaMultipoleForce, true);
amoebaMultipoleForce->setNonbondedMethod(AmoebaMultipoleForce::NoCutoff);
amoebaMultipoleForce->setPolarizationType(AmoebaMultipoleForce::Extrapolated);
std::vector<double> coefs;
coefs.push_back(0.0); // The mu_0 coefficient
coefs.push_back(-0.3); // The mu_1 coefficient
coefs.push_back(0.0); // The mu_2 coefficient
coefs.push_back(1.3); // The mu_3 coefficient
amoebaMultipoleForce->setExtrapolationCoefficients(coefs);
LangevinIntegrator integrator(0.0, 0.1, 0.01);
Context context(system, integrator, Platform::getPlatformByName("CUDA"));
context.setPositions(coords);
OpenMM::State state = context.getState(State::Forces | State::Energy);
std::vector<Vec3> forces = state.getForces();
double energy = state.getPotentialEnergy();
// printEnergyAndForces(energy, forces);
double expectedEnergy = -1.399194432;
std::vector<Vec3> expectedForces(forces.size());
expectedForces[0] = Vec3( -130.7294487, -186.3287444, 41.40628056);
expectedForces[1] = Vec3( 38.90143386, 2.140957908, 5.564712102);
expectedForces[2] = Vec3( 38.32881448, 117.0462626, 29.90093041);
expectedForces[3] = Vec3( -117.1147396, -101.6981494, -25.55733439);
expectedForces[4] = Vec3( 124.7421318, 169.1571359, -26.38724373);
expectedForces[5] = Vec3( 45.87180816, -0.3174626947, -24.92734495);
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
check_finite_differences(forces, context, coords);
}
static void testWaterDimerNoCutoffNoPolGroups() {
std::string testName = "testWaterDimerNoCutoffNoPolGroups";
System system;
AmoebaMultipoleForce* amoebaMultipoleForce = new AmoebaMultipoleForce();;
vector<Vec3> coords = setupWaterDimer(system, amoebaMultipoleForce, false);
amoebaMultipoleForce->setNonbondedMethod(AmoebaMultipoleForce::NoCutoff);
amoebaMultipoleForce->setPolarizationType(AmoebaMultipoleForce::Extrapolated);
std::vector<double> coefs;
coefs.push_back(0.0); // The mu_0 coefficient
coefs.push_back(-0.3); // The mu_1 coefficient
coefs.push_back(0.0); // The mu_2 coefficient
coefs.push_back(1.3); // The mu_3 coefficient
amoebaMultipoleForce->setExtrapolationCoefficients(coefs);
LangevinIntegrator integrator(0.0, 0.1, 0.01);
Context context(system, integrator, Platform::getPlatformByName("CUDA"));
context.setPositions(coords);
OpenMM::State state = context.getState(State::Forces | State::Energy);
std::vector<Vec3> forces = state.getForces();
double energy = state.getPotentialEnergy();
// printEnergyAndForces(energy, forces);
double expectedEnergy = -1.56926564;
std::vector<Vec3> expectedForces(forces.size());
expectedForces[0] = Vec3( -69.623843, -103.7006124, 6.162774255);
expectedForces[1] = Vec3( 19.54326912, -14.69441322, 8.014369439);
expectedForces[2] = Vec3( 16.65441143, 74.88100242, 17.70364405);
expectedForces[3] = Vec3( -67.10049929, -47.08900953, -16.01092086);
expectedForces[4] = Vec3( 74.98800293, 110.2649458, 3.020145768);
expectedForces[5] = Vec3( 25.53865881, -19.66191302, -18.89001266);
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
check_finite_differences(forces, context, coords);
}
int main(int numberOfArguments, char* argv[]) {
try {
registerAmoebaCudaKernelFactories();
if (numberOfArguments > 1)
Platform::getPlatformByName("CUDA").setPropertyDefaultValue("Precision", std::string(argv[1]));
/*
* Water dimer energy / force tests under various conditions.
*/
// PME, triclinic
testWaterDimerTriclinicPME();
// PME, triclinic, no polarization groups
testWaterDimerTriclinicPMENoPolGroups();
// No cutoff
testWaterDimerNoCutoff();
// No cutoff, no polarization groups
testWaterDimerNoCutoffNoPolGroups();
}
catch(const std::exception& e) {
std::cout << "exception: " << e.what() << std::endl;
std::cout << "FAIL - ERROR. Test failed." << std::endl;
return 1;
}
std::cout << "Done" << std::endl;
return 0;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
/* -------------------------------------------------------------------------- * /* -------------------------------------------------------------------------- *
* OpenMMAmoeba * * OpenMM *
* -------------------------------------------------------------------------- * * -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from * * This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of * * Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2020 Stanford University and the Authors. * * Portions copyright (c) 2021 Stanford University and the Authors. *
* Authors: Mark Friedrichs * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
* Permission is hereby granted, free of charge, to any person obtaining a * * Permission is hereby granted, free of charge, to any person obtaining a *
...@@ -29,2261 +29,7 @@ ...@@ -29,2261 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
/** #include "CudaAmoebaTests.h"
* This tests the CUDA implementation of CudaAmoebaVdwForce. #include "TestAmoebaVdwForce.h"
*/
#include "openmm/internal/AssertionUtilities.h" void runPlatformTests() {}
#include "openmm/Context.h"
#include "openmm/CustomNonbondedForce.h"
#include "OpenMMAmoeba.h"
#include "openmm/System.h"
#include "openmm/AmoebaVdwForce.h"
#include "openmm/LangevinIntegrator.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#define ASSERT_EQUAL_TOL_MOD(expected, found, tol, testname) {double _scale_ = std::abs(expected) > 1.0 ? std::abs(expected) : 1.0; if (!(std::abs((expected)-(found))/_scale_ <= (tol))) {std::stringstream details; details << testname << " Expected "<<(expected)<<", found "<<(found); throwException(__FILE__, __LINE__, details.str());}};
#define ASSERT_EQUAL_VEC_MOD(expected, found, tol,testname) {ASSERT_EQUAL_TOL_MOD((expected)[0], (found)[0], (tol),(testname)); ASSERT_EQUAL_TOL_MOD((expected)[1], (found)[1], (tol),(testname)); ASSERT_EQUAL_TOL_MOD((expected)[2], (found)[2], (tol),(testname));};
using namespace OpenMM;
using namespace std;
extern "C" void registerAmoebaCudaKernelFactories();
const double TOL = 1e-4;
void testVdw() {
System system;
int numberOfParticles = 6;
AmoebaVdwForce* amoebaVdwForce = new AmoebaVdwForce();
std::string sigmaCombiningRule = std::string("CUBIC-MEAN");
amoebaVdwForce->setSigmaCombiningRule(sigmaCombiningRule);
std::string epsilonCombiningRule = std::string("HHG");
amoebaVdwForce->setEpsilonCombiningRule(epsilonCombiningRule);
for (int ii = 0; ii < numberOfParticles; ii++) {
int indexIV;
double mass, sigma, epsilon, reduction;
std::vector< int > exclusions;
if (ii == 0 || ii == 3) {
mass = 16.0;
indexIV = ii;
sigma = 1.70250E+00;
epsilon = 1.10000E-01;
reduction = 0.0;
} else {
mass = 1.0;
indexIV = ii < 3 ? 0 : 3;
sigma = 1.32750E+00;
epsilon = 1.35000E-02;
reduction = 0.91;
}
// exclusions
if (ii < 3) {
exclusions.push_back (0);
exclusions.push_back (1);
exclusions.push_back (2);
} else {
exclusions.push_back (3);
exclusions.push_back (4);
exclusions.push_back (5);
}
system.addParticle(mass);
amoebaVdwForce->addParticle(indexIV, sigma, epsilon, reduction);
amoebaVdwForce->setParticleExclusions(ii, exclusions);
}
LangevinIntegrator integrator(0.0, 0.1, 0.01);
std::vector<Vec3> positions(numberOfParticles);
std::vector<Vec3> expectedForces(numberOfParticles);
double expectedEnergy;
positions[0] = Vec3(-0.254893450E+02, -0.876646600E+01, 0.174761600E+01);
positions[1] = Vec3(-0.263489690E+02, -0.907798000E+01, 0.205385100E+01);
positions[2] = Vec3(-0.252491680E+02, -0.949411200E+01, 0.115017600E+01);
positions[3] = Vec3( 0.172827200E+01, 0.195873090E+02, 0.100059800E+01);
positions[4] = Vec3( 0.129370700E+01, 0.190112810E+02, 0.169576300E+01);
positions[5] = Vec3( 0.256122300E+01, 0.191601930E+02, 0.854382000E+00);
double offset = 27.0;
for (int ii = 0; ii < 3; ii++) {
positions[ii][0] += offset;
positions[ii][1] += offset;
}
expectedForces[0] = Vec3( -0.729561040E+03, 0.425828484E+04, -0.769114213E+03);
expectedForces[1] = Vec3( 0.181000041E+02, 0.328216639E+02, -0.126210511E+02);
expectedForces[2] = Vec3( -0.943743014E+00, 0.199728310E+02, 0.884567842E+00);
expectedForces[3] = Vec3( 0.615734500E+01, -0.747350431E+03, 0.264726489E+03);
expectedForces[4] = Vec3( 0.735772031E+03, -0.353310112E+04, 0.490066356E+03);
expectedForces[5] = Vec3( -0.295245970E+02, -0.306277797E+02, 0.260578506E+02);
expectedEnergy = 0.740688488E+03;
system.addForce(amoebaVdwForce);
std::string platformName;
#define AngstromToNm 0.1
#define CalToJoule 4.184
for (int ii = 0; ii < numberOfParticles; ii++) {
positions[ii][0] *= AngstromToNm;
positions[ii][1] *= AngstromToNm;
positions[ii][2] *= AngstromToNm;
}
for (int ii = 0; ii < amoebaVdwForce->getNumParticles(); ii++) {
int indexIV, type;
double sigma, epsilon, reduction;
bool isAlchemical;
amoebaVdwForce->getParticleParameters(ii, indexIV, sigma, epsilon, reduction, isAlchemical, type);
sigma *= AngstromToNm;
epsilon *= CalToJoule;
amoebaVdwForce->setParticleParameters(ii, indexIV, sigma, epsilon, reduction, isAlchemical, type);
}
platformName = "CUDA";
Context context(system, integrator, Platform::getPlatformByName(platformName));
context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy);
std::vector<Vec3> forces = state.getForces();
const double conversion = -AngstromToNm/CalToJoule;
for (unsigned int ii = 0; ii < forces.size(); ii++) {
forces[ii][0] *= conversion;
forces[ii][1] *= conversion;
forces[ii][2] *= conversion;
}
expectedEnergy *= CalToJoule;
double tolerance = 1.0e-03;
for (unsigned int ii = 0; ii < forces.size(); ii++) {
ASSERT_EQUAL_VEC(expectedForces[ii], forces[ii], tolerance);
}
ASSERT_EQUAL_TOL(expectedEnergy, state.getPotentialEnergy(), tolerance);
// Try changing the particle parameters and make sure it's still correct.
for (int i = 0; i < numberOfParticles; i++) {
int indexIV, type;
double mass, sigma, epsilon, reduction;
bool isAlchemical;
amoebaVdwForce->getParticleParameters(i, indexIV, sigma, epsilon, reduction, isAlchemical, type);
amoebaVdwForce->setParticleParameters(i, indexIV, 0.9*sigma, 2.0*epsilon, 0.95*reduction, isAlchemical, type);
}
LangevinIntegrator integrator2(0.0, 0.1, 0.01);
Context context2(system, integrator2, Platform::getPlatformByName(platformName));
context2.setPositions(positions);
State state1 = context.getState(State::Forces | State::Energy);
State state2 = context2.getState(State::Forces | State::Energy);
bool exceptionThrown = false;
try {
// This should throw an exception.
for (int i = 0; i < numberOfParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], tolerance);
}
catch (std::exception ex) {
exceptionThrown = true;
}
ASSERT(exceptionThrown);
amoebaVdwForce->updateParametersInContext(context);
state1 = context.getState(State::Forces | State::Energy);
for (int i = 0; i < numberOfParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], tolerance);
ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), tolerance);
}
void setupAndGetForcesEnergyVdwAmmonia2(const std::string& sigmaCombiningRule, const std::string& epsilonCombiningRule, double cutoff,
double boxDimension, std::vector<Vec3>& forces, double& energy,
AmoebaVdwForce::AlchemicalMethod alchemicalMethod, int softcorePower, double softcoreAlpha, double vdwLambda){
// beginning of Vdw setup
System system;
AmoebaVdwForce* amoebaVdwForce = new AmoebaVdwForce();
int numberOfParticles = 8;
amoebaVdwForce->setSigmaCombiningRule(sigmaCombiningRule);
amoebaVdwForce->setEpsilonCombiningRule(epsilonCombiningRule);
amoebaVdwForce->setCutoff(cutoff);
bool alchemical = false;
if (alchemicalMethod != AmoebaVdwForce::None) {
amoebaVdwForce->setAlchemicalMethod(alchemicalMethod);
amoebaVdwForce->setSoftcorePower(softcorePower);
amoebaVdwForce->setSoftcoreAlpha(softcoreAlpha);
alchemical = true;
}
if (boxDimension > 0.0) {
Vec3 a(boxDimension, 0.0, 0.0);
Vec3 b(0.0, boxDimension, 0.0);
Vec3 c(0.0, 0.0, boxDimension);
system.setDefaultPeriodicBoxVectors(a, b, c);
amoebaVdwForce->setNonbondedMethod(AmoebaVdwForce::CutoffPeriodic);
amoebaVdwForce->setUseDispersionCorrection(1);
}
else {
amoebaVdwForce->setNonbondedMethod(AmoebaVdwForce::NoCutoff);
amoebaVdwForce->setUseDispersionCorrection(0);
}
// addParticle: ivIndex, radius, epsilon, reductionFactor
system.addParticle( 1.4007000e+01);
amoebaVdwForce->addParticle(0, 1.8550000e-01, 4.3932000e-01, 0.0000000e+00);
system.addParticle( 1.0080000e+00);
amoebaVdwForce->addParticle(0, 1.3500000e-01, 8.3680000e-02, 9.1000000e-01);
system.addParticle( 1.0080000e+00);
amoebaVdwForce->addParticle(0, 1.3500000e-01, 8.3680000e-02, 9.1000000e-01);
system.addParticle( 1.0080000e+00);
amoebaVdwForce->addParticle(0, 1.3500000e-01, 8.3680000e-02, 9.1000000e-01);
system.addParticle( 1.4007000e+01);
amoebaVdwForce->addParticle(4, 1.8550000e-01, 4.3932000e-01, 0.0000000e+00, alchemical);
system.addParticle( 1.0080000e+00);
amoebaVdwForce->addParticle(4, 1.3500000e-01, 8.3680000e-02, 9.1000000e-01, alchemical);
system.addParticle( 1.0080000e+00);
amoebaVdwForce->addParticle(4, 1.3500000e-01, 8.3680000e-02, 9.1000000e-01, alchemical);
system.addParticle( 1.0080000e+00);
amoebaVdwForce->addParticle(4, 1.3500000e-01, 8.3680000e-02, 9.1000000e-01, alchemical);
// ParticleExclusions
std::vector< int > exclusions;
exclusions.resize(0);
exclusions.push_back(0);
exclusions.push_back(1);
exclusions.push_back(2);
exclusions.push_back(3);
amoebaVdwForce->setParticleExclusions(0, exclusions);
exclusions.resize(0);
exclusions.push_back(1);
exclusions.push_back(0);
exclusions.push_back(2);
exclusions.push_back(3);
amoebaVdwForce->setParticleExclusions(1, exclusions);
exclusions.resize(0);
exclusions.push_back(2);
exclusions.push_back(0);
exclusions.push_back(1);
exclusions.push_back(3);
amoebaVdwForce->setParticleExclusions(2, exclusions);
exclusions.resize(0);
exclusions.push_back(3);
exclusions.push_back(0);
exclusions.push_back(1);
exclusions.push_back(2);
amoebaVdwForce->setParticleExclusions(3, exclusions);
exclusions.resize(0);
exclusions.push_back(4);
exclusions.push_back(5);
exclusions.push_back(6);
exclusions.push_back(7);
amoebaVdwForce->setParticleExclusions(4, exclusions);
exclusions.resize(0);
exclusions.push_back(5);
exclusions.push_back(4);
exclusions.push_back(6);
exclusions.push_back(7);
amoebaVdwForce->setParticleExclusions(5, exclusions);
exclusions.resize(0);
exclusions.push_back(6);
exclusions.push_back(4);
exclusions.push_back(5);
exclusions.push_back(7);
amoebaVdwForce->setParticleExclusions(6, exclusions);
exclusions.resize(0);
exclusions.push_back(7);
exclusions.push_back(4);
exclusions.push_back(5);
exclusions.push_back(6);
amoebaVdwForce->setParticleExclusions(7, exclusions);
// end of Vdw setup
std::vector<Vec3> positions(numberOfParticles);
positions[0] = Vec3( 1.5927280e-01, 1.7000000e-06, 1.6491000e-03);
positions[1] = Vec3( 2.0805540e-01, -8.1258800e-02, 3.7282500e-02);
positions[2] = Vec3( 2.0843610e-01, 8.0953200e-02, 3.7462200e-02);
positions[3] = Vec3( 1.7280780e-01, 2.0730000e-04, -9.8741700e-02);
positions[4] = Vec3( -1.6743680e-01, 1.5900000e-05, -6.6149000e-03);
positions[5] = Vec3( -2.0428260e-01, 8.1071500e-02, 4.1343900e-02);
positions[6] = Vec3( -6.7308300e-02, 1.2800000e-05, 1.0623300e-02);
positions[7] = Vec3( -2.0426290e-01, -8.1231400e-02, 4.1033500e-02);
system.addForce(amoebaVdwForce);
std::string platformName;
platformName = "CUDA";
LangevinIntegrator integrator(0.0, 0.1, 0.01);
Context context(system, integrator, Platform::getPlatformByName(platformName));
// Load the vdw lambda value into the context.
if (alchemicalMethod != AmoebaVdwForce::None) {
context.setParameter(AmoebaVdwForce::Lambda(), vdwLambda);
}
context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy);
forces = state.getForces();
energy = state.getPotentialEnergy();
}
void setupAndGetForcesEnergyVdwAmmonia(const std::string& sigmaCombiningRule, const std::string& epsilonCombiningRule, double cutoff,
double boxDimension, std::vector<Vec3>& forces, double& energy) {
AmoebaVdwForce::AlchemicalMethod alchemicalMethod = AmoebaVdwForce::None;
int softcorePower = 5;
double softcoreAlpha = 0.7;
double vdwLambda = 1.0;
setupAndGetForcesEnergyVdwAmmonia2(sigmaCombiningRule, epsilonCombiningRule, cutoff, boxDimension, forces, energy,
alchemicalMethod, softcorePower, softcoreAlpha, vdwLambda);
}
void compareForcesEnergy(std::string& testName, double expectedEnergy, double energy,
std::vector<Vec3>& expectedForces,
std::vector<Vec3>& forces, double tolerance) {
for (unsigned int ii = 0; ii < forces.size(); ii++) {
ASSERT_EQUAL_VEC_MOD(expectedForces[ii], forces[ii], tolerance, testName);
}
ASSERT_EQUAL_TOL_MOD(expectedEnergy, energy, tolerance, testName);
}
// test VDW w/ sigmaRule=CubicMean and epsilonRule=HHG
void testVdwAmmoniaCubicMeanHhg() {
std::string testName = "testVdwAmmoniaCubicMeanHhg";
int numberOfParticles = 8;
double boxDimension = -1.0;
double cutoff = 9000000.0;
std::vector<Vec3> forces;
double energy;
setupAndGetForcesEnergyVdwAmmonia("CUBIC-MEAN", "HHG", cutoff, boxDimension, forces, energy);
std::vector<Vec3> expectedForces(numberOfParticles);
double expectedEnergy = 4.8012258e+00;
expectedForces[0] = Vec3( 2.9265247e+02, -1.4507808e-02, -6.9562123e+00);
expectedForces[1] = Vec3( -2.2451693e+00, 4.8143073e-01, -2.0041494e-01);
expectedForces[2] = Vec3( -2.2440698e+00, -4.7905450e-01, -2.0125284e-01);
expectedForces[3] = Vec3( -1.0840394e+00, -5.8531253e-04, 2.6934135e-01);
expectedForces[4] = Vec3( -5.6305662e+01, 1.4733908e-03, -1.8083306e-01);
expectedForces[5] = Vec3( 1.6750145e+00, -3.2448374e-01, -1.8030914e-01);
expectedForces[6] = Vec3( -2.3412420e+02, 1.0754069e-02, 7.6287492e+00);
expectedForces[7] = Vec3( 1.6756544e+00, 3.2497316e-01, -1.7906832e-01);
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
}
// test VDW w/ sigmaRule=CubicMean and epsilonRule=W-H
void testVdwAmmoniaCubicMeanWH() {
std::string testName = "testVdwAmmoniaCubicMeanWH";
int numberOfParticles = 8;
double boxDimension = -1.0;
double cutoff = 9000000.0;
std::vector<Vec3> forces;
double energy;
setupAndGetForcesEnergyVdwAmmonia("CUBIC-MEAN", "W-H", cutoff, boxDimension, forces, energy);
std::vector<Vec3> expectedForces(numberOfParticles);
double expectedEnergy = 3.771794e+00;
expectedForces[0] = Vec3( 2.3979839e+02, -1.1829842e-02, -5.3258772e+00);
expectedForces[1] = Vec3(-1.9942459e+00, 4.3142144e-01, -1.7290171e-01);
expectedForces[2] = Vec3(-1.9935442e+00, -4.2937965e-01, -1.7369876e-01);
expectedForces[3] = Vec3(-8.9050582e-01, -4.8659920e-04, 2.2190848e-01);
expectedForces[4] = Vec3(-5.2306326e+01, 1.4895040e-03, -3.3588483e-01);
expectedForces[5] = Vec3( 1.4153288e+00, -2.7130186e-01, -1.5480591e-01);
expectedForces[6] = Vec3(-1.8544507e+02, 8.4027272e-03, 6.0950274e+00);
expectedForces[7] = Vec3( 1.4159723e+00, 2.7168386e-01, -1.5376786e-01);
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
}
// test alchemical VDW
void testVdwAlchemical(int power, double alpha, double lambda, AmoebaVdwForce::AlchemicalMethod method) {
std::string testName = "testVdwAlchemical";
int numberOfParticles = 8;
double boxDimension = -1.0;
double cutoff = 9000000.0;
std::vector<Vec3> forces;
double energy;
setupAndGetForcesEnergyVdwAmmonia2("CUBIC-MEAN", "HHG", cutoff, boxDimension, forces, energy,
method, power, alpha, lambda);
std::vector<Vec3> expectedForces(numberOfParticles);
double expectedEnergy = 4.8012258e+00;
expectedForces[0] = Vec3( 2.9265247e+02, -1.4507808e-02, -6.9562123e+00);
expectedForces[1] = Vec3(-2.2451693e+00, 4.8143073e-01, -2.0041494e-01);
expectedForces[2] = Vec3(-2.2440698e+00, -4.7905450e-01, -2.0125284e-01);
expectedForces[3] = Vec3(-1.0840394e+00, -5.8531253e-04, 2.6934135e-01);
expectedForces[4] = Vec3(-5.6305662e+01, 1.4733908e-03, -1.8083306e-01);
expectedForces[5] = Vec3( 1.6750145e+00, -3.2448374e-01, -1.8030914e-01);
expectedForces[6] = Vec3(-2.3412420e+02, 1.0754069e-02, 7.6287492e+00);
expectedForces[7] = Vec3( 1.6756544e+00, 3.2497316e-01, -1.7906832e-01);
double scale = pow(lambda, power);
expectedEnergy *= scale;
for (int i=0; i<8; i++) {
expectedForces[i] *= scale;
}
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
}
// test VDW w/ sigmaRule=Arithmetic and epsilonRule=Arithmetic
void testVdwAmmoniaArithmeticArithmetic() {
std::string testName = "testVdwAmmoniaArithmeticArithmetic";
int numberOfParticles = 8;
double boxDimension = -1.0;
double cutoff = 9000000.0;
std::vector<Vec3> forces;
double energy;
setupAndGetForcesEnergyVdwAmmonia("ARITHMETIC", "ARITHMETIC", cutoff, boxDimension, forces, energy);
std::vector<Vec3> expectedForces(numberOfParticles);
double expectedEnergy = 4.2252403e+00;
expectedForces[0] = Vec3( 3.0603839e+02, -1.5550310e-02, -7.2661707e+00);
expectedForces[1] = Vec3( -2.7801357e+00, 5.8805051e-01, -2.5907269e-01);
expectedForces[2] = Vec3( -2.7753968e+00, -5.8440732e-01, -2.5969111e-01);
expectedForces[3] = Vec3( -2.2496416e+00, -1.1797440e-03, 5.5501757e-01);
expectedForces[4] = Vec3( -5.5077629e+01, 8.3417114e-04, -3.3668921e-01);
expectedForces[5] = Vec3( 2.3752452e+00, -4.6788669e-01, -2.4907764e-01);
expectedForces[6] = Vec3( -2.4790697e+02, 1.1419770e-02, 8.0629999e+00);
expectedForces[7] = Vec3( 2.3761408e+00, 4.6871961e-01, -2.4731607e-01);
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
}
// test VDW w/ sigmaRule=Geometric and epsilonRule=Geometric
void testVdwAmmoniaGeometricGeometric() {
std::string testName = "testVdwAmmoniaGeometricGeometric";
int numberOfParticles = 8;
double boxDimension = -1.0;
double cutoff = 9000000.0;
std::vector<Vec3> forces;
double energy;
setupAndGetForcesEnergyVdwAmmonia("GEOMETRIC", "GEOMETRIC", cutoff, boxDimension, forces, energy);
std::vector<Vec3> expectedForces(numberOfParticles);
double expectedEnergy = 2.5249914e+00;
expectedForces[0] = Vec3( 2.1169631e+02, -1.0710925e-02, -4.3728025e+00);
expectedForces[1] = Vec3( -2.2585621e+00, 4.8409995e-01, -2.0188344e-01);
expectedForces[2] = Vec3( -2.2551351e+00, -4.8124855e-01, -2.0246986e-01);
expectedForces[3] = Vec3( -1.7178028e+00, -9.0851787e-04, 4.2466975e-01);
expectedForces[4] = Vec3( -4.8302147e+01, 9.6603376e-04, -5.7972068e-01);
expectedForces[5] = Vec3( 1.8100634e+00, -3.5214093e-01, -1.9357207e-01);
expectedForces[6] = Vec3( -1.6078365e+02, 7.2117601e-03, 5.3180261e+00);
expectedForces[7] = Vec3( 1.8109211e+00, 3.5273117e-01, -1.9224723e-01);
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
}
void testVdwAmmoniaCubicMeanHarmonic() {
std::string testName = "testVdwAmmoniaCubicMeanHarmonic";
int numberOfParticles = 8;
double boxDimension = -1.0;
double cutoff = 9000000.0;
std::vector<Vec3> forces;
double energy;
setupAndGetForcesEnergyVdwAmmonia("CUBIC-MEAN", "HARMONIC", cutoff, boxDimension, forces, energy);
std::vector<Vec3> expectedForces(numberOfParticles);
double expectedEnergy = 4.1369069e+00;
expectedForces[0] = Vec3( 2.5854436e+02, -1.2779529e-02, -5.9041148e+00);
expectedForces[1] = Vec3( -2.0832419e+00, 4.4915831e-01, -1.8266000e-01);
expectedForces[2] = Vec3( -2.0823991e+00, -4.4699804e-01, -1.8347141e-01);
expectedForces[3] = Vec3( -9.5914714e-01, -5.2162026e-04, 2.3873165e-01);
expectedForces[4] = Vec3( -5.3724787e+01, 1.4838241e-03, -2.8089191e-01);
expectedForces[5] = Vec3( 1.5074325e+00, -2.9016397e-01, -1.6385118e-01);
expectedForces[6] = Vec3( -2.0271029e+02, 9.2367947e-03, 6.6389988e+00);
expectedForces[7] = Vec3( 1.5080748e+00, 2.9058422e-01, -1.6274118e-01);
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
}
// test w/ cutoff=0.25 nm; single ixn between two particles (0 and 6); force nonzero on
// particle 4 due to reduction applied to NH
// the distance between 0 and 6 is ~ 0.235 so the ixn is in the tapered region
void testVdwTaper() {
std::string testName = "testVdwTaper";
int numberOfParticles = 8;
double boxDimension = 50.0;
double cutoff = 0.25;
std::vector<Vec3> forces;
double energy;
setupAndGetForcesEnergyVdwAmmonia("CUBIC-MEAN", "HHG", cutoff, boxDimension, forces, energy);
std::vector<Vec3> expectedForces(numberOfParticles);
double expectedEnergy = 3.5478444e+00;
expectedForces[0] = Vec3( 5.6710779e+02, -2.7391004e-02, -1.7867730e+01);
expectedForces[1] = Vec3( -0.0000000e+00, -0.0000000e+00, -0.0000000e+00);
expectedForces[2] = Vec3( -0.0000000e+00, -0.0000000e+00, -0.0000000e+00);
expectedForces[3] = Vec3( -0.0000000e+00, -0.0000000e+00, -0.0000000e+00);
expectedForces[4] = Vec3( -5.1039701e+01, 2.4651903e-03, 1.6080957e+00);
expectedForces[5] = Vec3( -0.0000000e+00, -0.0000000e+00, -0.0000000e+00);
expectedForces[6] = Vec3( -5.1606809e+02, 2.4925813e-02, 1.6259634e+01);
expectedForces[7] = Vec3( -0.0000000e+00, -0.0000000e+00, -0.0000000e+00);
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
}
// test PBC
void testVdwPBC() {
std::string testName = "testVdwPBC";
int numberOfParticles = 8;
double boxDimension = 0.6;
double cutoff = 0.25;
std::vector<Vec3> forces;
double energy;
setupAndGetForcesEnergyVdwAmmonia("CUBIC-MEAN", "HHG", cutoff, boxDimension, forces, energy);
std::vector<Vec3> expectedForces(numberOfParticles);
double expectedEnergy = 1.4949141e+01;
expectedForces[0] = Vec3( 5.1453069e+02, 4.9751912e-01, -1.2759570e+01);
expectedForces[1] = Vec3( -2.5622586e+02, -4.6524265e+01, 2.4281465e+01);
expectedForces[2] = Vec3( -2.7538705e+02, 5.1831690e+01, 2.7367710e+01);
expectedForces[3] = Vec3( -0.0000000e+00, -0.0000000e+00, -0.0000000e+00);
expectedForces[4] = Vec3( 3.0883034e+02, -5.8876974e+00, -5.8286122e+01);
expectedForces[5] = Vec3( 1.1319359e+02, -3.2047069e-01, 1.6181231e+00);
expectedForces[6] = Vec3( -5.1606809e+02, 2.4925813e-02, 1.6259634e+01);
expectedForces[7] = Vec3( 1.1112638e+02, 3.7829857e-01, 1.5187587e+00);
// tolerance is higher here due to interpolation used in setting tapering coefficients;
// if tapering turned off, then absolute difference < 2.0e-05
double tolerance = 5.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
}
// create box of 216 water molecules
void setupAndGetForcesEnergyVdwWater(const std::string& sigmaCombiningRule, const std::string& epsilonCombiningRule, double cutoff,
double boxDimension, int includeVdwDispersionCorrection,
std::vector<Vec3>& forces, double& energy) {
// beginning of Vdw setup
System system;
AmoebaVdwForce* amoebaVdwForce = new AmoebaVdwForce();;
int numberOfParticles = 648;
amoebaVdwForce->setSigmaCombiningRule(sigmaCombiningRule);
amoebaVdwForce->setEpsilonCombiningRule(epsilonCombiningRule);
amoebaVdwForce->setCutoff(cutoff);
if (boxDimension > 0.0) {
Vec3 a(boxDimension, 0.0, 0.0);
Vec3 b(0.0, boxDimension, 0.0);
Vec3 c(0.0, 0.0, boxDimension);
system.setDefaultPeriodicBoxVectors(a, b, c);
amoebaVdwForce->setNonbondedMethod(AmoebaVdwForce::CutoffPeriodic);
amoebaVdwForce->setUseDispersionCorrection(includeVdwDispersionCorrection);
} else {
amoebaVdwForce->setNonbondedMethod(AmoebaVdwForce::NoCutoff);
amoebaVdwForce->setUseDispersionCorrection(0);
}
// addParticle: ivIndex, radius, epsilon, reductionFactor
int classIndex = 0;
for (unsigned int ii = 0; ii < numberOfParticles; ii += 3) {
system.addParticle( 1.5995000e+01);
amoebaVdwForce->addParticle(ii, 1.7025000e-01, 4.6024000e-01, 0.0000000e+00);
system.addParticle( 1.0080000e+00);
amoebaVdwForce->addParticle(ii, 1.3275000e-01, 5.6484000e-02, 9.1000000e-01);
system.addParticle( 1.0080000e+00);
amoebaVdwForce->addParticle(ii, 1.3275000e-01, 5.6484000e-02, 9.1000000e-01);
}
// exclusions
std::vector< int > exclusions(3);
for (unsigned int ii = 0; ii < numberOfParticles; ii += 3) {
exclusions[0] = ii;
exclusions[1] = ii+1;
exclusions[2] = ii+2;
amoebaVdwForce->setParticleExclusions(ii, exclusions);
amoebaVdwForce->setParticleExclusions(ii+1, exclusions);
amoebaVdwForce->setParticleExclusions(ii+2, exclusions);
}
// end of Vdw setup
// set positions
std::vector<Vec3> positions(numberOfParticles);
positions[0] = Vec3( 8.0394300e-01, 5.8680350e-01, 4.9277700e-02);
positions[1] = Vec3( 7.5814940e-01, 5.0226660e-01, 4.0375900e-02);
positions[2] = Vec3( 8.2870560e-01, 6.0624400e-01, -3.9707400e-02);
positions[3] = Vec3( 1.1484000e-02, -8.8765990e-01, 6.4458520e-01);
positions[4] = Vec3( 9.5892500e-02, -8.4464940e-01, 6.4052470e-01);
positions[5] = Vec3( 2.4723500e-02, -9.7944710e-01, 6.1378930e-01);
positions[6] = Vec3( -6.5763670e-01, -2.5260000e-02, 8.1046320e-01);
positions[7] = Vec3( -6.6454990e-01, 6.8992500e-02, 7.8963560e-01);
positions[8] = Vec3( -6.6845370e-01, -4.0076000e-02, 9.1037470e-01);
positions[9] = Vec3( 6.5831270e-01, 8.5501500e-02, -6.6685290e-01);
positions[10] = Vec3( 6.2600580e-01, 8.8732600e-02, -5.7651320e-01);
positions[11] = Vec3( 6.1694860e-01, 5.3229000e-03, -7.0543230e-01);
positions[12] = Vec3( 5.4954790e-01, 6.4357640e-01, 1.8420070e-01);
positions[13] = Vec3( 4.7740750e-01, 6.5609280e-01, 1.2079650e-01);
positions[14] = Vec3( 6.2544340e-01, 6.3485600e-01, 1.2346110e-01);
positions[15] = Vec3( -4.6646340e-01, -8.5021310e-01, -2.6526210e-01);
positions[16] = Vec3( -4.5053590e-01, -8.3883300e-01, -3.6069710e-01);
positions[17] = Vec3( -5.5653260e-01, -8.7510810e-01, -2.5955820e-01);
positions[18] = Vec3( -7.7550740e-01, -4.6613180e-01, 4.9045930e-01);
positions[19] = Vec3( -7.3577510e-01, -5.4400590e-01, 5.3107060e-01);
positions[20] = Vec3( -7.0755520e-01, -4.1773140e-01, 4.4037930e-01);
positions[21] = Vec3( -2.8190600e-02, 7.4872450e-01, -7.6855300e-01);
positions[22] = Vec3( -7.9443300e-02, 7.4463600e-01, -6.8256160e-01);
positions[23] = Vec3( 1.7033100e-02, 8.3813000e-01, -7.6365310e-01);
positions[24] = Vec3( -3.7112750e-01, -2.2624390e-01, -1.9170030e-01);
positions[25] = Vec3( -4.4236150e-01, -2.4258640e-01, -2.4723220e-01);
positions[26] = Vec3( -4.0233380e-01, -2.2106530e-01, -9.7227800e-02);
positions[27] = Vec3( -5.8120030e-01, -5.6157220e-01, 8.3549400e-02);
positions[28] = Vec3( -6.6764500e-01, -5.7119710e-01, 1.2970660e-01);
positions[29] = Vec3( -5.1434340e-01, -5.5317060e-01, 1.5597670e-01);
positions[30] = Vec3( 8.5281410e-01, 4.9997870e-01, 3.4439320e-01);
positions[31] = Vec3( 8.8661040e-01, 4.7595500e-01, 4.3409810e-01);
positions[32] = Vec3( 7.6829200e-01, 4.5403270e-01, 3.3783460e-01);
positions[33] = Vec3( 6.2913000e-03, 3.9622090e-01, -6.4448110e-01);
positions[34] = Vec3( -6.4546800e-02, 4.4539620e-01, -6.0008300e-01);
positions[35] = Vec3( 7.0262000e-03, 3.1229330e-01, -5.9892730e-01);
positions[36] = Vec3( 1.6883500e-02, 6.5824910e-01, 6.0982750e-01);
positions[37] = Vec3( 2.9114400e-02, 6.3714540e-01, 7.0403040e-01);
positions[38] = Vec3( -3.9569500e-02, 5.9419720e-01, 5.6714930e-01);
positions[39] = Vec3( 3.7393550e-01, 6.2909200e-01, 8.1318410e-01);
positions[40] = Vec3( 4.1500630e-01, 6.1010560e-01, 9.0110400e-01);
positions[41] = Vec3( 4.3953600e-01, 5.9208230e-01, 7.5268270e-01);
positions[42] = Vec3( 3.2500410e-01, 4.5615770e-01, -2.5643980e-01);
positions[43] = Vec3( 3.7432790e-01, 4.5313140e-01, -3.3754880e-01);
positions[44] = Vec3( 2.6987370e-01, 5.3785040e-01, -2.4860760e-01);
positions[45] = Vec3( 5.6184630e-01, 5.2015900e-01, 6.3763990e-01);
positions[46] = Vec3( 5.6189080e-01, 5.6140190e-01, 5.5312940e-01);
positions[47] = Vec3( 5.4901540e-01, 4.2688810e-01, 6.2109450e-01);
positions[48] = Vec3( -8.7750980e-01, 6.9408570e-01, -6.1784650e-01);
positions[49] = Vec3( -8.2179580e-01, 7.3187880e-01, -5.4705510e-01);
positions[50] = Vec3( -9.0362240e-01, 7.7367480e-01, -6.6488210e-01);
positions[51] = Vec3( -6.9406820e-01, 2.2491740e-01, 7.1940890e-01);
positions[52] = Vec3( -7.3674620e-01, 2.2091000e-01, 6.3486690e-01);
positions[53] = Vec3( -7.4149900e-01, 2.8970280e-01, 7.7200060e-01);
positions[54] = Vec3( 4.8285280e-01, -1.8445100e-02, 3.1521130e-01);
positions[55] = Vec3( 5.5574910e-01, 2.4338500e-02, 2.7236750e-01);
positions[56] = Vec3( 4.1347360e-01, 5.0063500e-02, 3.2371450e-01);
positions[57] = Vec3( -2.2024800e-01, -3.1071870e-01, 9.1706370e-01);
positions[58] = Vec3( -2.3195790e-01, -4.0722320e-01, 9.2465160e-01);
positions[59] = Vec3( -2.8015290e-01, -2.9349640e-01, 8.4209880e-01);
positions[60] = Vec3( 1.6893780e-01, 6.6734280e-01, -2.4352040e-01);
positions[61] = Vec3( 1.9716270e-01, 7.5186390e-01, -2.0536790e-01);
positions[62] = Vec3( 8.7430700e-02, 6.4225300e-01, -1.9539020e-01);
positions[63] = Vec3( -9.0804840e-01, -6.2437310e-01, -8.8188300e-02);
positions[64] = Vec3( -8.6732940e-01, -7.0428590e-01, -4.8030200e-02);
positions[65] = Vec3( -8.3644480e-01, -5.8139450e-01, -1.3828190e-01);
positions[66] = Vec3( -8.6567760e-01, -8.6537570e-01, 5.6295900e-02);
positions[67] = Vec3( -8.1778220e-01, -9.4654890e-01, 8.4163600e-02);
positions[68] = Vec3( -9.4534460e-01, -8.6858770e-01, 1.0560810e-01);
positions[69] = Vec3( -5.7716930e-01, -2.6316670e-01, -4.5880740e-01);
positions[70] = Vec3( -5.4569620e-01, -3.1693230e-01, -5.2720970e-01);
positions[71] = Vec3( -5.5496000e-01, -1.7071220e-01, -4.7392400e-01);
positions[72] = Vec3( 7.2367810e-01, -8.4678300e-01, -6.9502250e-01);
positions[73] = Vec3( 7.9899670e-01, -8.9648580e-01, -7.2759260e-01);
positions[74] = Vec3( 7.5075030e-01, -8.1725850e-01, -6.0600380e-01);
positions[75] = Vec3( -2.3769060e-01, -6.2523350e-01, 1.2921080e-01);
positions[76] = Vec3( -1.8309420e-01, -6.2163180e-01, 4.8693900e-02);
positions[77] = Vec3( -2.3929030e-01, -5.3708810e-01, 1.6453540e-01);
positions[78] = Vec3( 8.3347800e-02, -5.0189060e-01, 5.4317800e-01);
positions[79] = Vec3( 1.0917180e-01, -5.7641330e-01, 4.8632230e-01);
positions[80] = Vec3( 1.4837200e-02, -5.5084220e-01, 5.9546910e-01);
positions[81] = Vec3( 7.4250070e-01, -2.7418580e-01, 8.3795900e-02);
positions[82] = Vec3( 6.8666720e-01, -2.4554090e-01, 1.6206940e-01);
positions[83] = Vec3( 7.1516850e-01, -3.6419530e-01, 7.2493400e-02);
positions[84] = Vec3( -2.5059100e-02, 8.6314620e-01, 2.2861410e-01);
positions[85] = Vec3( 9.6445000e-03, 9.0720400e-01, 1.4964290e-01);
positions[86] = Vec3( 4.5097900e-02, 8.7155360e-01, 2.9051950e-01);
positions[87] = Vec3( 4.7779490e-01, 9.0242640e-01, 8.2515620e-01);
positions[88] = Vec3( 4.3957480e-01, 8.0786830e-01, 8.2489220e-01);
positions[89] = Vec3( 4.6833310e-01, 9.2867710e-01, 9.1788160e-01);
positions[90] = Vec3( 8.2204140e-01, 9.0145630e-01, -2.5081510e-01);
positions[91] = Vec3( 8.5191840e-01, 8.1397830e-01, -2.2168590e-01);
positions[92] = Vec3( 7.6397810e-01, 9.2011290e-01, -1.8137750e-01);
positions[93] = Vec3( -7.9443650e-01, 1.7601300e-01, 4.6436790e-01);
positions[94] = Vec3( -7.9212150e-01, 2.3533020e-01, 3.8657500e-01);
positions[95] = Vec3( -8.7057070e-01, 1.1288830e-01, 4.4595260e-01);
positions[96] = Vec3( 3.2425690e-01, 3.8214720e-01, -8.2471120e-01);
positions[97] = Vec3( 2.8321830e-01, 4.2912450e-01, -7.4875880e-01);
positions[98] = Vec3( 2.7681870e-01, 2.9837230e-01, -8.2620080e-01);
positions[99] = Vec3( 7.5575820e-01, -8.9620900e-01, 2.3680670e-01);
positions[100] = Vec3( 6.6600420e-01, -8.7027760e-01, 2.7104280e-01);
positions[101] = Vec3( 8.1544110e-01, -9.1190240e-01, 3.1149610e-01);
positions[102] = Vec3( -8.4248740e-01, 3.5007110e-01, -4.4389740e-01);
positions[103] = Vec3( -7.5693800e-01, 3.9510690e-01, -4.4710480e-01);
positions[104] = Vec3( -8.6984880e-01, 3.5457480e-01, -5.3702920e-01);
positions[105] = Vec3( 3.8837250e-01, -4.8496240e-01, 6.5322550e-01);
positions[106] = Vec3( 4.1237110e-01, -4.0401080e-01, 7.0255980e-01);
positions[107] = Vec3( 3.0065040e-01, -4.6399160e-01, 6.0513040e-01);
positions[108] = Vec3( 6.2063930e-01, -5.0831230e-01, 4.9540430e-01);
positions[109] = Vec3( 6.8959700e-01, -5.3506820e-01, 5.6328860e-01);
positions[110] = Vec3( 5.3663630e-01, -5.1121830e-01, 5.4640900e-01);
positions[111] = Vec3( 7.0354670e-01, -5.1748580e-01, -7.3878700e-02);
positions[112] = Vec3( 7.8529450e-01, -5.6535940e-01, -9.5943500e-02);
positions[113] = Vec3( 6.7807440e-01, -4.7921810e-01, -1.6187590e-01);
positions[114] = Vec3( -4.4116790e-01, -4.7749880e-01, 3.0876830e-01);
positions[115] = Vec3( -5.0645290e-01, -4.1075220e-01, 3.1159470e-01);
positions[116] = Vec3( -4.6594720e-01, -5.2568230e-01, 3.8755370e-01);
positions[117] = Vec3( -9.1937480e-01, -5.8400000e-05, -2.5359570e-01);
positions[118] = Vec3( -8.5894750e-01, -7.0402500e-02, -2.2230370e-01);
positions[119] = Vec3( -8.7441760e-01, 8.3170500e-02, -2.3447490e-01);
positions[120] = Vec3( 5.0867290e-01, 2.3568780e-01, 5.5935510e-01);
positions[121] = Vec3( 4.1446460e-01, 2.6088930e-01, 5.8683440e-01);
positions[122] = Vec3( 5.1853820e-01, 1.4937830e-01, 5.8561390e-01);
positions[123] = Vec3( -4.6831090e-01, -6.1465890e-01, -1.6794620e-01);
positions[124] = Vec3( -4.8688540e-01, -5.9611250e-01, -7.4636500e-02);
positions[125] = Vec3( -4.9162010e-01, -7.0497770e-01, -1.8127910e-01);
positions[126] = Vec3( -3.1791800e-01, -5.4450000e-03, -3.6397680e-01);
positions[127] = Vec3( -2.2253910e-01, -2.4457600e-02, -3.5240990e-01);
positions[128] = Vec3( -3.6044390e-01, -3.5065000e-02, -2.8414310e-01);
positions[129] = Vec3( 1.0461140e-01, 2.6758700e-01, -2.2684050e-01);
positions[130] = Vec3( 1.8426490e-01, 3.2453330e-01, -2.3574350e-01);
positions[131] = Vec3( 1.0569370e-01, 2.3628020e-01, -1.3834830e-01);
positions[132] = Vec3( -1.4119340e-01, 4.1653970e-01, -2.7320250e-01);
positions[133] = Vec3( -5.2065100e-02, 3.6979030e-01, -2.6662970e-01);
positions[134] = Vec3( -1.3834110e-01, 4.7690560e-01, -1.9435870e-01);
positions[135] = Vec3( -7.6602450e-01, -2.1216400e-01, -1.9516640e-01);
positions[136] = Vec3( -8.0191290e-01, -2.8391260e-01, -1.3557910e-01);
positions[137] = Vec3( -7.4415500e-01, -2.6044280e-01, -2.8169590e-01);
positions[138] = Vec3( -1.3600310e-01, 1.9674000e-01, 2.0349610e-01);
positions[139] = Vec3( -1.6201050e-01, 2.8693750e-01, 2.3123820e-01);
positions[140] = Vec3( -2.1785650e-01, 1.4514420e-01, 1.9201990e-01);
positions[141] = Vec3( 6.2897820e-01, -4.2302590e-01, -7.6557210e-01);
positions[142] = Vec3( 6.2334100e-01, -4.4471660e-01, -6.7174140e-01);
positions[143] = Vec3( 6.3346670e-01, -5.0696850e-01, -8.0495300e-01);
positions[144] = Vec3( 9.1588260e-01, -3.9845200e-02, 3.5189180e-01);
positions[145] = Vec3( 9.8891550e-01, -4.4673900e-02, 2.9156120e-01);
positions[146] = Vec3( 8.4126090e-01, -2.2841000e-03, 2.9707980e-01);
positions[147] = Vec3( 4.8470900e-01, -8.2561400e-02, 6.0082980e-01);
positions[148] = Vec3( 3.9021850e-01, -6.2932500e-02, 6.0195610e-01);
positions[149] = Vec3( 5.0563070e-01, -7.9866200e-02, 5.0777230e-01);
positions[150] = Vec3( -7.2845180e-01, -3.4650580e-01, 7.5973620e-01);
positions[151] = Vec3( -7.6073760e-01, -3.6974690e-01, 6.7323450e-01);
positions[152] = Vec3( -7.1326740e-01, -2.4916760e-01, 7.5651020e-01);
positions[153] = Vec3( -3.0896820e-01, -3.8029640e-01, 6.5520670e-01);
positions[154] = Vec3( -3.5019560e-01, -4.5571260e-01, 6.1040330e-01);
positions[155] = Vec3( -2.8479430e-01, -3.2175460e-01, 5.7933340e-01);
positions[156] = Vec3( -6.2826700e-02, -6.4315900e-02, -6.8812300e-02);
positions[157] = Vec3( -7.4971500e-02, 1.9900000e-02, -1.8191100e-02);
positions[158] = Vec3( 3.2478400e-02, -8.8932300e-02, -5.6413600e-02);
positions[159] = Vec3( 1.1667520e-01, -6.6784990e-01, 1.1452860e-01);
positions[160] = Vec3( 6.5194200e-02, -7.3080350e-01, 6.5294000e-02);
positions[161] = Vec3( 1.6133150e-01, -6.1778770e-01, 4.7196600e-02);
positions[162] = Vec3( 8.8627400e-02, -7.1850240e-01, 3.7581390e-01);
positions[163] = Vec3( 1.2356120e-01, -8.0690930e-01, 3.7094210e-01);
positions[164] = Vec3( 9.2028600e-02, -6.8313750e-01, 2.8412340e-01);
positions[165] = Vec3( 2.1347270e-01, 8.4107000e-03, 6.0413030e-01);
positions[166] = Vec3( 1.8845570e-01, 4.3251500e-02, 5.1600410e-01);
positions[167] = Vec3( 1.6789670e-01, -7.6656800e-02, 6.0793520e-01);
positions[168] = Vec3( 1.8425700e-02, 3.0164400e-02, 8.4213210e-01);
positions[169] = Vec3( -7.1641800e-02, 4.1848500e-02, 8.7065260e-01);
positions[170] = Vec3( 4.4510400e-02, -6.2982500e-02, 8.6373290e-01);
positions[171] = Vec3( -3.1486750e-01, -1.9966860e-01, -5.7954700e-01);
positions[172] = Vec3( -3.2321140e-01, -1.4613590e-01, -5.0133480e-01);
positions[173] = Vec3( -3.4769180e-01, -1.4810900e-01, -6.5567720e-01);
positions[174] = Vec3( 2.2013690e-01, -4.8207100e-02, -6.6169910e-01);
positions[175] = Vec3( 1.3676160e-01, -9.4600100e-02, -6.4525960e-01);
positions[176] = Vec3( 2.7051720e-01, -1.2158460e-01, -6.9535940e-01);
positions[177] = Vec3( -1.5721060e-01, -2.0015580e-01, 4.8442010e-01);
positions[178] = Vec3( -7.4675400e-02, -2.0952300e-01, 5.3560160e-01);
positions[179] = Vec3( -1.8522760e-01, -1.0781560e-01, 5.0024110e-01);
positions[180] = Vec3( 5.4002730e-01, 6.3800500e-01, -8.0040500e-01);
positions[181] = Vec3( 5.0366070e-01, 7.1545920e-01, -7.5257350e-01);
positions[182] = Vec3( 5.1480770e-01, 5.5941670e-01, -7.4903220e-01);
positions[183] = Vec3( -6.3383580e-01, 5.7282910e-01, -1.7429980e-01);
positions[184] = Vec3( -6.0668100e-01, 4.7712900e-01, -1.7677570e-01);
positions[185] = Vec3( -5.6638740e-01, 6.1288510e-01, -2.2951390e-01);
positions[186] = Vec3( -2.0998170e-01, -2.7747820e-01, 7.0579400e-02);
positions[187] = Vec3( -1.4055440e-01, -3.0201380e-01, 1.3644740e-01);
positions[188] = Vec3( -1.6881700e-01, -2.1818660e-01, 6.9733000e-03);
positions[189] = Vec3( -7.6400000e-04, 5.6326380e-01, 1.4175360e-01);
positions[190] = Vec3( -7.3688000e-02, 5.0031150e-01, 1.5514670e-01);
positions[191] = Vec3( -2.5553000e-02, 6.4733770e-01, 1.7711800e-01);
positions[192] = Vec3( 3.9595890e-01, -1.9078420e-01, -1.9708050e-01);
positions[193] = Vec3( 4.3887020e-01, -1.5694200e-01, -1.1582060e-01);
positions[194] = Vec3( 3.7635540e-01, -1.1834040e-01, -2.5323660e-01);
positions[195] = Vec3( 3.9638900e-02, -2.4093090e-01, 8.9424300e-01);
positions[196] = Vec3( -4.9643600e-02, -2.7156660e-01, 8.9962920e-01);
positions[197] = Vec3( 8.4318200e-02, -2.7149840e-01, 9.7721820e-01);
positions[198] = Vec3( -5.9039370e-01, -3.5975630e-01, -7.1984370e-01);
positions[199] = Vec3( -5.3914870e-01, -4.0214860e-01, -7.8361060e-01);
positions[200] = Vec3( -6.8562580e-01, -3.9051900e-01, -7.4071320e-01);
positions[201] = Vec3( 4.7759800e-01, 3.2863960e-01, -5.4274200e-02);
positions[202] = Vec3( 4.5034450e-01, 3.6680450e-01, -1.4201230e-01);
positions[203] = Vec3( 4.3083410e-01, 3.8043410e-01, 1.5118500e-02);
positions[204] = Vec3( 1.8100450e-01, 1.6674000e-01, -8.4907090e-01);
positions[205] = Vec3( 1.0479500e-01, 1.5721720e-01, -9.0737790e-01);
positions[206] = Vec3( 1.7365410e-01, 9.7140100e-02, -7.7842430e-01);
positions[207] = Vec3( -6.9841710e-01, 8.5211760e-01, 4.9956020e-01);
positions[208] = Vec3( -6.3194850e-01, 9.0336360e-01, 4.5467020e-01);
positions[209] = Vec3( -6.7863830e-01, 7.5666570e-01, 5.1268950e-01);
positions[210] = Vec3( 8.0356880e-01, -7.6669620e-01, 5.6240980e-01);
positions[211] = Vec3( 8.9444390e-01, -7.9421520e-01, 5.4379860e-01);
positions[212] = Vec3( 8.0061200e-01, -7.1151420e-01, 6.3743510e-01);
positions[213] = Vec3( -2.3686380e-01, 4.4018650e-01, 2.7494630e-01);
positions[214] = Vec3( -2.1006750e-01, 4.1932880e-01, 3.6593160e-01);
positions[215] = Vec3( -3.2910900e-01, 4.6299420e-01, 2.7725190e-01);
positions[216] = Vec3( 7.3324180e-01, 9.1021100e-02, 8.6347740e-01);
positions[217] = Vec3( 6.4934460e-01, 5.3444800e-02, 8.7843600e-01);
positions[218] = Vec3( 7.1407590e-01, 1.8691830e-01, 8.6323690e-01);
positions[219] = Vec3( 3.6906600e-02, 1.4742360e-01, 4.0082880e-01);
positions[220] = Vec3( -1.0515300e-02, 1.4450010e-01, 4.8531790e-01);
positions[221] = Vec3( -3.6861400e-02, 1.5333190e-01, 3.3364650e-01);
positions[222] = Vec3( 5.7666790e-01, -9.2075640e-01, 5.7305300e-01);
positions[223] = Vec3( 5.4452540e-01, -9.3954290e-01, 6.5798160e-01);
positions[224] = Vec3( 6.7020160e-01, -8.8052280e-01, 5.6852240e-01);
positions[225] = Vec3( 4.1616300e-01, -2.3723450e-01, 7.8105700e-02);
positions[226] = Vec3( 4.4947640e-01, -2.2465620e-01, 1.6469280e-01);
positions[227] = Vec3( 3.6093380e-01, -3.1332780e-01, 7.1125100e-02);
positions[228] = Vec3( -1.9830990e-01, -6.8678560e-01, -7.6648560e-01);
positions[229] = Vec3( -1.1489950e-01, -6.8356660e-01, -8.2028210e-01);
positions[230] = Vec3( -2.0935090e-01, -5.9618710e-01, -7.3178710e-01);
positions[231] = Vec3( -4.3741650e-01, -7.8889500e-01, 1.7785560e-01);
positions[232] = Vec3( -3.6424030e-01, -7.2995610e-01, 1.5380490e-01);
positions[233] = Vec3( -5.0710310e-01, -7.4066850e-01, 1.3917790e-01);
positions[234] = Vec3( 5.1605280e-01, 6.8521860e-01, 4.5545030e-01);
positions[235] = Vec3( 5.3920960e-01, 7.6750670e-01, 4.8965960e-01);
positions[236] = Vec3( 5.4441350e-01, 6.8153880e-01, 3.6305340e-01);
positions[237] = Vec3( -9.1377180e-01, 9.0412110e-01, -8.0577110e-01);
positions[238] = Vec3( -8.6299150e-01, 9.8552780e-01, -7.9463610e-01);
positions[239] = Vec3( -9.1270510e-01, 8.7715830e-01, -9.0107170e-01);
positions[240] = Vec3( -5.6874630e-01, -3.9330600e-02, 5.3540210e-01);
positions[241] = Vec3( -6.0667690e-01, 3.6619200e-02, 4.9922460e-01);
positions[242] = Vec3( -5.8307630e-01, -4.4694300e-02, 6.3380260e-01);
positions[243] = Vec3( 1.0312020e-01, 2.2809180e-01, 5.7525600e-02);
positions[244] = Vec3( 1.8161800e-02, 2.2164820e-01, 1.0293620e-01);
positions[245] = Vec3( 1.4691520e-01, 3.0734480e-01, 9.4432600e-02);
positions[246] = Vec3( -5.3437690e-01, -9.0689060e-01, -7.7012560e-01);
positions[247] = Vec3( -6.0761130e-01, -8.5593580e-01, -8.0463440e-01);
positions[248] = Vec3( -5.5313680e-01, -9.9745020e-01, -8.0224750e-01);
positions[249] = Vec3( 1.7436730e-01, -4.6935620e-01, -7.7408150e-01);
positions[250] = Vec3( 1.3315640e-01, -4.6856170e-01, -6.8363440e-01);
positions[251] = Vec3( 2.3486700e-01, -3.9970620e-01, -7.7872930e-01);
positions[252] = Vec3( 5.0382310e-01, 8.6391330e-01, -6.1751380e-01);
positions[253] = Vec3( 5.7851670e-01, 9.1774780e-01, -6.3741940e-01);
positions[254] = Vec3( 5.2100060e-01, 8.2278060e-01, -5.3449130e-01);
positions[255] = Vec3( -2.3461000e-03, 8.8439120e-01, -3.5703750e-01);
positions[256] = Vec3( -4.5869800e-02, 9.2025060e-01, -4.4264850e-01);
positions[257] = Vec3( 7.7568300e-02, 8.3812640e-01, -3.7824790e-01);
positions[258] = Vec3( -1.6677150e-01, -9.0353490e-01, -5.6323410e-01);
positions[259] = Vec3( -1.5077930e-01, -8.7448310e-01, -6.5150250e-01);
positions[260] = Vec3( -2.5054260e-01, -8.5746520e-01, -5.4471400e-01);
positions[261] = Vec3( -1.0245710e-01, -4.1390500e-01, 2.9240710e-01);
positions[262] = Vec3( -1.6375100e-01, -3.5806090e-01, 3.3803800e-01);
positions[263] = Vec3( -3.4371600e-02, -4.4188880e-01, 3.6032470e-01);
positions[264] = Vec3( 6.7721230e-01, -9.2755000e-01, -6.1695000e-03);
positions[265] = Vec3( 6.3209610e-01, -8.4066740e-01, 1.5854000e-03);
positions[266] = Vec3( 7.2195780e-01, -9.3506790e-01, 7.6821700e-02);
positions[267] = Vec3( -5.2597410e-01, 5.0741940e-01, 2.8142130e-01);
positions[268] = Vec3( -5.3172740e-01, 5.6506650e-01, 2.0013640e-01);
positions[269] = Vec3( -5.9533220e-01, 4.4193270e-01, 2.6673520e-01);
positions[270] = Vec3( 4.3852700e-02, -7.1092730e-01, -3.0056810e-01);
positions[271] = Vec3( 1.2232900e-02, -6.7601300e-01, -2.1679320e-01);
positions[272] = Vec3( 3.0039200e-02, -8.0474130e-01, -3.0050550e-01);
positions[273] = Vec3( 4.7537430e-01, 6.7956000e-03, -8.8926760e-01);
positions[274] = Vec3( 4.4972180e-01, -8.1937800e-02, -8.5037740e-01);
positions[275] = Vec3( 3.9238110e-01, 5.4650000e-02, -9.0978500e-01);
positions[276] = Vec3( 8.4526190e-01, -3.2384610e-01, 4.4702430e-01);
positions[277] = Vec3( 8.5335920e-01, -2.3860050e-01, 4.1507690e-01);
positions[278] = Vec3( 9.3799800e-01, -3.6222940e-01, 4.5249690e-01);
positions[279] = Vec3( -8.5624140e-01, -3.3540460e-01, -5.3955060e-01);
positions[280] = Vec3( -8.9833150e-01, -3.2177130e-01, -6.2636700e-01);
positions[281] = Vec3( -7.6568080e-01, -3.0076830e-01, -5.3672910e-01);
positions[282] = Vec3( -4.0866080e-01, -7.0070860e-01, 9.2586930e-01);
positions[283] = Vec3( -4.5043520e-01, -7.7640050e-01, 9.7012510e-01);
positions[284] = Vec3( -3.2086210e-01, -6.9414110e-01, 9.6526100e-01);
positions[285] = Vec3( -2.9612090e-01, 2.9021400e-01, -4.6137730e-01);
positions[286] = Vec3( -3.0085180e-01, 1.9752840e-01, -4.3159520e-01);
positions[287] = Vec3( -2.4502340e-01, 3.3756140e-01, -3.9070450e-01);
positions[288] = Vec3( -8.4956240e-01, -3.3051010e-01, 4.2215900e-02);
positions[289] = Vec3( -8.2077940e-01, -3.9086690e-01, 1.1548590e-01);
positions[290] = Vec3( -9.3822180e-01, -3.1618550e-01, 5.2894000e-02);
positions[291] = Vec3( -8.6464030e-01, 7.5345250e-01, 1.9545370e-01);
positions[292] = Vec3( -9.2073720e-01, 6.7584430e-01, 1.8998460e-01);
positions[293] = Vec3( -8.9310500e-01, 7.8515510e-01, 2.8077440e-01);
positions[294] = Vec3( 5.3248170e-01, 6.8435100e-02, -1.1431070e-01);
positions[295] = Vec3( 6.1630600e-01, 5.7417300e-02, -6.9794300e-02);
positions[296] = Vec3( 4.9275030e-01, 1.5234490e-01, -7.9235100e-02);
positions[297] = Vec3( -3.0166400e-02, 3.6028840e-01, -9.2023940e-01);
positions[298] = Vec3( 2.5390700e-02, 4.3355180e-01, -9.4581010e-01);
positions[299] = Vec3( -1.2837900e-02, 3.5198820e-01, -8.2331230e-01);
positions[300] = Vec3( -7.6094250e-01, -7.4142570e-01, -7.6415170e-01);
positions[301] = Vec3( -7.5826150e-01, -6.8315050e-01, -8.4024930e-01);
positions[302] = Vec3( -7.8169550e-01, -6.8557300e-01, -6.8728990e-01);
positions[303] = Vec3( -7.1618050e-01, -8.6617600e-02, -7.8297100e-01);
positions[304] = Vec3( -6.9164460e-01, -1.6643810e-01, -7.3660090e-01);
positions[305] = Vec3( -8.1169890e-01, -8.6541300e-02, -7.7380060e-01);
positions[306] = Vec3( 8.6280550e-01, -2.8731190e-01, -7.5013210e-01);
positions[307] = Vec3( 8.4297110e-01, -2.0142080e-01, -7.9688520e-01);
positions[308] = Vec3( 7.7553640e-01, -3.3421630e-01, -7.5754400e-01);
positions[309] = Vec3( 2.9607200e-02, -6.7251560e-01, -9.1368960e-01);
positions[310] = Vec3( 1.0909000e-03, -6.2708430e-01, -9.9528360e-01);
positions[311] = Vec3( 8.0161300e-02, -5.9814710e-01, -8.7106130e-01);
positions[312] = Vec3( -2.2829370e-01, 4.6661410e-01, 7.7985190e-01);
positions[313] = Vec3( -2.4730820e-01, 5.6404020e-01, 7.8763210e-01);
positions[314] = Vec3( -1.7899690e-01, 4.3324110e-01, 8.5622400e-01);
positions[315] = Vec3( -5.1323270e-01, -2.6480150e-01, 7.2113100e-02);
positions[316] = Vec3( -4.4180310e-01, -2.8480730e-01, 1.4166490e-01);
positions[317] = Vec3( -5.5826690e-01, -3.4508980e-01, 5.6782300e-02);
positions[318] = Vec3( 3.5970320e-01, -7.1101700e-01, -8.5706800e-01);
positions[319] = Vec3( 3.5573750e-01, -6.6123030e-01, -7.7069560e-01);
positions[320] = Vec3( 2.9308100e-01, -6.7738800e-01, -9.1162920e-01);
positions[321] = Vec3( -8.6077820e-01, -8.3187420e-01, 3.5264550e-01);
positions[322] = Vec3( -7.9919290e-01, -8.9965630e-01, 3.8875110e-01);
positions[323] = Vec3( -8.4377450e-01, -8.2428940e-01, 2.5657630e-01);
positions[324] = Vec3( -6.9407750e-01, 8.5240530e-01, -4.8975260e-01);
positions[325] = Vec3( -6.0369970e-01, 8.2005830e-01, -4.7948010e-01);
positions[326] = Vec3( -6.8257340e-01, 9.0158170e-01, -5.7057020e-01);
positions[327] = Vec3( -8.6181560e-01, 2.1174420e-01, 3.2775000e-02);
positions[328] = Vec3( -9.5070390e-01, 2.5868190e-01, 2.6787700e-02);
positions[329] = Vec3( -8.8015990e-01, 1.3696510e-01, 9.1486900e-02);
positions[330] = Vec3( -6.7034530e-01, -7.0959980e-01, 5.7197940e-01);
positions[331] = Vec3( -6.3447070e-01, -7.7970770e-01, 5.1435410e-01);
positions[332] = Vec3( -7.1147280e-01, -7.6230200e-01, 6.4084900e-01);
positions[333] = Vec3( -4.2433970e-01, 1.6353470e-01, -7.5364040e-01);
positions[334] = Vec3( -3.3715920e-01, 1.3734360e-01, -7.8660110e-01);
positions[335] = Vec3( -4.5203330e-01, 2.3873860e-01, -8.1607320e-01);
positions[336] = Vec3( -4.2091960e-01, -8.1633330e-01, -5.3063920e-01);
positions[337] = Vec3( -4.2728590e-01, -7.1806470e-01, -5.4109270e-01);
positions[338] = Vec3( -4.5013260e-01, -8.3810340e-01, -6.1998700e-01);
positions[339] = Vec3( 6.0367930e-01, 3.3084920e-01, -8.4465460e-01);
positions[340] = Vec3( 5.0455880e-01, 3.3698360e-01, -8.4011240e-01);
positions[341] = Vec3( 6.2487550e-01, 2.4834360e-01, -8.0607210e-01);
positions[342] = Vec3( 1.8546120e-01, -6.3282200e-02, 5.1304500e-02);
positions[343] = Vec3( 2.8101390e-01, -7.7771500e-02, 5.1163200e-02);
positions[344] = Vec3( 1.7127760e-01, 2.0996700e-02, 9.0574100e-02);
positions[345] = Vec3( -3.5029200e-02, -7.9917400e-02, -3.4468400e-01);
positions[346] = Vec3( -6.3903800e-02, -6.0213300e-02, -2.5206780e-01);
positions[347] = Vec3( -4.6785200e-02, -1.7349570e-01, -3.5772680e-01);
positions[348] = Vec3( 2.5567190e-01, 6.2355480e-01, 4.2852620e-01);
positions[349] = Vec3( 1.9093710e-01, 6.4505930e-01, 4.9102940e-01);
positions[350] = Vec3( 3.4540670e-01, 6.4937420e-01, 4.5902510e-01);
positions[351] = Vec3( -7.3742490e-01, -8.7628820e-01, -2.6411710e-01);
positions[352] = Vec3( -7.3220480e-01, -9.1540050e-01, -3.5104230e-01);
positions[353] = Vec3( -7.9968040e-01, -9.2863850e-01, -2.1682500e-01);
positions[354] = Vec3( 5.1017210e-01, -2.7173980e-01, 7.9174500e-01);
positions[355] = Vec3( 5.1045830e-01, -2.0746280e-01, 7.2138780e-01);
positions[356] = Vec3( 5.9967910e-01, -3.0815350e-01, 7.9296320e-01);
positions[357] = Vec3( 6.1703300e-02, -6.0490320e-01, -5.4304490e-01);
positions[358] = Vec3( 6.5202000e-03, -6.6388800e-01, -5.9525970e-01);
positions[359] = Vec3( 6.2525700e-02, -6.3466150e-01, -4.5175130e-01);
positions[360] = Vec3( -5.0181950e-01, 6.8138390e-01, -8.8794760e-01);
positions[361] = Vec3( -4.0469720e-01, 6.5541180e-01, -8.8475300e-01);
positions[362] = Vec3( -5.4953810e-01, 6.3245150e-01, -8.1669610e-01);
positions[363] = Vec3( -3.5708340e-01, 8.1787480e-01, 1.0372050e-01);
positions[364] = Vec3( -4.3575160e-01, 7.6657380e-01, 8.8357500e-02);
positions[365] = Vec3( -3.8126100e-01, 9.1312250e-01, 1.2894930e-01);
positions[366] = Vec3( -1.0889180e-01, 6.4289110e-01, -1.1000150e-01);
positions[367] = Vec3( -9.5792300e-02, 6.5121590e-01, -1.2915400e-02);
positions[368] = Vec3( -1.4253020e-01, 7.3532640e-01, -1.2649680e-01);
positions[369] = Vec3( -8.0675190e-01, 3.8993580e-01, -9.3061890e-01);
positions[370] = Vec3( -8.4285770e-01, 4.7693320e-01, -9.5868770e-01);
positions[371] = Vec3( -7.4065520e-01, 4.1059110e-01, -8.6270860e-01);
positions[372] = Vec3( -7.3221050e-01, -8.3486000e-02, 1.8651540e-01);
positions[373] = Vec3( -6.6332990e-01, -2.5838100e-02, 1.5155080e-01);
positions[374] = Vec3( -7.5939010e-01, -1.4675440e-01, 1.1813700e-01);
positions[375] = Vec3( 6.1370510e-01, -3.7510720e-01, -2.9444790e-01);
positions[376] = Vec3( 5.3141590e-01, -3.1971250e-01, -2.8369080e-01);
positions[377] = Vec3( 6.7472620e-01, -3.0544670e-01, -3.2680390e-01);
positions[378] = Vec3( 2.8333090e-01, 7.0116700e-01, 6.3582400e-02);
positions[379] = Vec3( 2.3304950e-01, 7.8436370e-01, 8.8113000e-02);
positions[380] = Vec3( 2.1603670e-01, 6.3345680e-01, 4.3706900e-02);
positions[381] = Vec3( 3.4046290e-01, -5.8425160e-01, -5.8383960e-01);
positions[382] = Vec3( 4.2396660e-01, -5.6867730e-01, -5.4787780e-01);
positions[383] = Vec3( 2.7987870e-01, -5.6273080e-01, -5.1485370e-01);
positions[384] = Vec3( 4.8651200e-01, 3.9384650e-01, -5.0852640e-01);
positions[385] = Vec3( 4.8954070e-01, 2.9830160e-01, -5.1540010e-01);
positions[386] = Vec3( 5.7513360e-01, 4.2777280e-01, -4.8094980e-01);
positions[387] = Vec3( -4.9931530e-01, -8.6556710e-01, 4.1410020e-01);
positions[388] = Vec3( -4.0971070e-01, -9.0364250e-01, 4.1539320e-01);
positions[389] = Vec3( -5.0187830e-01, -8.1863570e-01, 3.2854240e-01);
positions[390] = Vec3( -9.2923250e-01, -9.5140200e-02, 7.7175180e-01);
positions[391] = Vec3( -1.0068535e+00, -4.9193300e-02, 8.1361050e-01);
positions[392] = Vec3( -8.5382270e-01, -3.5167000e-02, 7.7988780e-01);
positions[393] = Vec3( 5.8200510e-01, -2.7347380e-01, 3.2175080e-01);
positions[394] = Vec3( 5.9114530e-01, -2.1232990e-01, 3.9188270e-01);
positions[395] = Vec3( 6.2697690e-01, -3.5436570e-01, 3.5518080e-01);
positions[396] = Vec3( -4.3869270e-01, 7.1030180e-01, -3.4435510e-01);
positions[397] = Vec3( -3.5798370e-01, 6.6801330e-01, -3.8293170e-01);
positions[398] = Vec3( -3.9584820e-01, 7.8582280e-01, -3.0015890e-01);
positions[399] = Vec3( 3.0315060e-01, 2.0553140e-01, 3.3518590e-01);
positions[400] = Vec3( 2.0466680e-01, 2.0029920e-01, 3.3800050e-01);
positions[401] = Vec3( 3.1784090e-01, 2.6138240e-01, 4.0966770e-01);
positions[402] = Vec3( 7.3144120e-01, 1.1861840e-01, 2.1872590e-01);
positions[403] = Vec3( 6.9245610e-01, 2.0755440e-01, 2.3848660e-01);
positions[404] = Vec3( 7.4250960e-01, 1.1063670e-01, 1.1673060e-01);
positions[405] = Vec3( 3.0774670e-01, -6.7782260e-01, -6.9330000e-02);
positions[406] = Vec3( 3.0161020e-01, -7.5652530e-01, -1.2627210e-01);
positions[407] = Vec3( 3.7612340e-01, -6.9199170e-01, -2.0688000e-03);
positions[408] = Vec3( 4.8241200e-02, 1.4991530e-01, -4.8562930e-01);
positions[409] = Vec3( 7.0825700e-02, 1.7883510e-01, -4.0076820e-01);
positions[410] = Vec3( -1.4581300e-02, 7.7868400e-02, -4.8044320e-01);
positions[411] = Vec3( 2.6566210e-01, -4.7972300e-02, -3.9240060e-01);
positions[412] = Vec3( 2.5708940e-01, -2.6958700e-02, -4.8906580e-01);
positions[413] = Vec3( 1.8079360e-01, -1.7099600e-02, -3.5945650e-01);
positions[414] = Vec3( 7.3593670e-01, 3.2192010e-01, 6.3185000e-03);
positions[415] = Vec3( 7.5313070e-01, 3.1236830e-01, -9.0780600e-02);
positions[416] = Vec3( 6.4125230e-01, 3.3242850e-01, 5.3072000e-03);
positions[417] = Vec3( -7.2074000e-03, -2.1935180e-01, -6.7044710e-01);
positions[418] = Vec3( -7.9916200e-02, -2.2604130e-01, -7.3330810e-01);
positions[419] = Vec3( -3.2871000e-03, -2.9557560e-01, -6.1702790e-01);
positions[420] = Vec3( 8.0182800e-01, 3.3340310e-01, -2.5836160e-01);
positions[421] = Vec3( 8.9266890e-01, 3.1760310e-01, -2.9990300e-01);
positions[422] = Vec3( 7.7135080e-01, 4.0881250e-01, -3.1490320e-01);
positions[423] = Vec3( -3.1753700e-01, 3.7248900e-02, 5.0846140e-01);
positions[424] = Vec3( -3.3276340e-01, 1.2794660e-01, 5.4135580e-01);
positions[425] = Vec3( -4.0442920e-01, -2.1535000e-03, 5.2164500e-01);
positions[426] = Vec3( 7.7089090e-01, -1.7749490e-01, -4.1090550e-01);
positions[427] = Vec3( 8.0919970e-01, -9.9267700e-02, -3.6080690e-01);
positions[428] = Vec3( 8.4794900e-01, -2.2265030e-01, -4.4286640e-01);
positions[429] = Vec3( -5.0985980e-01, 6.5271910e-01, 5.1660950e-01);
positions[430] = Vec3( -4.1891080e-01, 6.9500010e-01, 5.0933000e-01);
positions[431] = Vec3( -5.2072650e-01, 6.0609800e-01, 4.2889530e-01);
positions[432] = Vec3( 8.8931480e-01, -1.5854900e-02, -7.9057690e-01);
positions[433] = Vec3( 8.4049130e-01, 2.2454500e-02, -7.1223150e-01);
positions[434] = Vec3( 8.6392620e-01, 4.6002000e-02, -8.5696830e-01);
positions[435] = Vec3( -4.2632820e-01, -5.4538160e-01, -5.2698140e-01);
positions[436] = Vec3( -3.4047810e-01, -5.2088280e-01, -5.5637760e-01);
positions[437] = Vec3( -4.9107950e-01, -5.2513960e-01, -5.9520410e-01);
positions[438] = Vec3( 8.8830700e-01, 7.8506050e-01, 4.7420010e-01);
positions[439] = Vec3( 9.6737760e-01, 8.0796480e-01, 5.2210120e-01);
positions[440] = Vec3( 8.3449840e-01, 7.2694370e-01, 5.2968560e-01);
positions[441] = Vec3( -3.0889500e-02, -5.4040860e-01, -7.7446500e-02);
positions[442] = Vec3( 2.4910200e-02, -4.7046460e-01, -5.3187100e-02);
positions[443] = Vec3( -1.0937030e-01, -5.1212170e-01, -1.2642620e-01);
positions[444] = Vec3( 5.0722190e-01, -8.0898340e-01, 3.3208510e-01);
positions[445] = Vec3( 5.1254280e-01, -8.4333670e-01, 4.2962250e-01);
positions[446] = Vec3( 4.8459280e-01, -7.1548850e-01, 3.3664280e-01);
positions[447] = Vec3( 7.0974400e-02, -8.6268490e-01, -7.2122900e-01);
positions[448] = Vec3( 8.8211100e-02, -8.1266230e-01, -7.9698760e-01);
positions[449] = Vec3( 1.4856180e-01, -8.7440360e-01, -6.6601020e-01);
positions[450] = Vec3( -2.7264270e-01, 8.2117820e-01, 4.0979220e-01);
positions[451] = Vec3( -1.8893860e-01, 7.8611730e-01, 4.4435560e-01);
positions[452] = Vec3( -2.7256440e-01, 8.1557060e-01, 3.0746650e-01);
positions[453] = Vec3( -2.3667600e-01, 7.0807760e-01, 9.0055470e-01);
positions[454] = Vec3( -1.7087350e-01, 7.0278860e-01, 9.7330650e-01);
positions[455] = Vec3( -2.2325560e-01, 8.0596230e-01, 8.7050690e-01);
positions[456] = Vec3( 6.0904540e-01, -5.3471490e-01, -5.1588800e-01);
positions[457] = Vec3( 6.6627390e-01, -6.1177680e-01, -4.9309950e-01);
positions[458] = Vec3( 6.1303950e-01, -4.7414890e-01, -4.3691960e-01);
positions[459] = Vec3( -6.9432470e-01, 5.5588670e-01, -7.2750070e-01);
positions[460] = Vec3( -6.8524660e-01, 5.1427650e-01, -6.4407660e-01);
positions[461] = Vec3( -7.7219850e-01, 6.0882800e-01, -7.1352640e-01);
positions[462] = Vec3( -6.5544400e-01, 5.6801890e-01, 7.6654940e-01);
positions[463] = Vec3( -5.9853210e-01, 5.8150060e-01, 6.8630620e-01);
positions[464] = Vec3( -6.0728400e-01, 6.2604000e-01, 8.2970960e-01);
positions[465] = Vec3( -1.7725100e-01, -7.5128040e-01, 4.8288320e-01);
positions[466] = Vec3( -1.1106490e-01, -7.1604590e-01, 4.2681180e-01);
positions[467] = Vec3( -1.2808000e-01, -8.2063050e-01, 5.2385060e-01);
positions[468] = Vec3( 5.0880810e-01, -1.7782370e-01, -5.5526690e-01);
positions[469] = Vec3( 4.7579150e-01, -1.6757400e-01, -4.6732050e-01);
positions[470] = Vec3( 6.0010540e-01, -1.6566020e-01, -5.4639700e-01);
positions[471] = Vec3( 7.9737120e-01, -5.3326000e-03, -2.2789800e-02);
positions[472] = Vec3( 7.5436910e-01, -9.2537600e-02, -2.7176000e-03);
positions[473] = Vec3( 8.4035540e-01, -2.5845500e-02, -1.0913300e-01);
positions[474] = Vec3( 2.4805290e-01, -4.5182680e-01, -2.5649240e-01);
positions[475] = Vec3( 2.6536400e-01, -5.1313010e-01, -1.8699050e-01);
positions[476] = Vec3( 2.8661880e-01, -3.6531040e-01, -2.2184290e-01);
positions[477] = Vec3( 8.9407190e-01, 6.4140150e-01, -2.2838520e-01);
positions[478] = Vec3( 8.6394270e-01, 5.7649930e-01, -2.9124340e-01);
positions[479] = Vec3( 9.8698980e-01, 6.3685520e-01, -2.2087390e-01);
positions[480] = Vec3( -5.0297400e-01, 3.8595440e-01, -9.1329410e-01);
positions[481] = Vec3( -4.2761710e-01, 4.4573350e-01, -8.9961960e-01);
positions[482] = Vec3( -5.7109730e-01, 4.3620760e-01, -9.6075240e-01);
positions[483] = Vec3( -5.7912630e-01, 3.1473530e-01, -1.3174480e-01);
positions[484] = Vec3( -6.4359930e-01, 2.3775370e-01, -1.3815260e-01);
positions[485] = Vec3( -5.1910350e-01, 2.9841740e-01, -5.0386200e-02);
positions[486] = Vec3( -2.3287450e-01, -4.5325250e-01, -2.6295780e-01);
positions[487] = Vec3( -3.1705790e-01, -5.0582880e-01, -2.5755610e-01);
positions[488] = Vec3( -2.4988940e-01, -3.6717760e-01, -2.2456790e-01);
positions[489] = Vec3( 7.3902040e-01, 6.0596960e-01, 8.7531410e-01);
positions[490] = Vec3( 6.8510920e-01, 5.6584400e-01, 8.0394270e-01);
positions[491] = Vec3( 6.7885220e-01, 6.2492120e-01, 9.4854880e-01);
positions[492] = Vec3( -1.7342650e-01, -4.4833620e-01, -6.2689720e-01);
positions[493] = Vec3( -1.2120170e-01, -4.7044370e-01, -5.5178260e-01);
positions[494] = Vec3( -2.1756220e-01, -3.7095040e-01, -5.9046920e-01);
positions[495] = Vec3( -9.7909800e-02, 4.1047140e-01, 5.5154950e-01);
positions[496] = Vec3( -1.5085520e-01, 4.3078300e-01, 6.2923170e-01);
positions[497] = Vec3( -2.2121000e-02, 3.5854830e-01, 5.8628920e-01);
positions[498] = Vec3( -2.9249090e-01, 4.2502460e-01, -7.0552100e-01);
positions[499] = Vec3( -2.3858950e-01, 3.8279980e-01, -7.7129020e-01);
positions[500] = Vec3( -2.8537830e-01, 3.6194940e-01, -6.3036240e-01);
positions[501] = Vec3( -4.1927200e-01, -1.0765570e-01, -8.1010100e-01);
positions[502] = Vec3( -4.5513170e-01, -1.8389200e-01, -8.5055730e-01);
positions[503] = Vec3( -4.6978720e-01, -3.2915400e-02, -8.4249770e-01);
positions[504] = Vec3( -8.3022800e-01, -5.9366610e-01, -5.2440890e-01);
positions[505] = Vec3( -8.3569020e-01, -5.0053960e-01, -5.4596070e-01);
positions[506] = Vec3( -7.7653500e-01, -5.9680800e-01, -4.4872510e-01);
positions[507] = Vec3( 4.7451900e-02, 2.4985900e-01, 7.1027380e-01);
positions[508] = Vec3( 5.2750000e-03, 2.6682820e-01, 8.0047760e-01);
positions[509] = Vec3( 9.2790500e-02, 1.6390540e-01, 7.2751450e-01);
positions[510] = Vec3( 9.8318300e-02, -2.4834430e-01, 6.2217110e-01);
positions[511] = Vec3( 7.1376800e-02, -2.3868900e-01, 7.1029050e-01);
positions[512] = Vec3( 1.0725160e-01, -3.3946690e-01, 5.9525570e-01);
positions[513] = Vec3( -1.7389390e-01, 6.3857050e-01, -4.3802350e-01);
positions[514] = Vec3( -1.0857550e-01, 7.0876020e-01, -4.2023360e-01);
positions[515] = Vec3( -1.6180390e-01, 5.6775180e-01, -3.7084920e-01);
positions[516] = Vec3( -8.3384410e-01, -7.8320210e-01, 7.9714340e-01);
positions[517] = Vec3( -8.6597850e-01, -8.7176550e-01, 7.7689410e-01);
positions[518] = Vec3( -9.1332720e-01, -7.1912210e-01, 7.9807020e-01);
positions[519] = Vec3( 3.0122650e-01, 4.4099240e-01, 1.7747380e-01);
positions[520] = Vec3( 3.0879580e-01, 3.5962220e-01, 2.2668340e-01);
positions[521] = Vec3( 2.9198270e-01, 5.0655710e-01, 2.4655760e-01);
positions[522] = Vec3( 3.8346200e-01, -2.8443150e-01, -8.3961770e-01);
positions[523] = Vec3( 4.1227770e-01, -2.9408340e-01, -9.3409110e-01);
positions[524] = Vec3( 4.5498420e-01, -3.3552520e-01, -7.8643110e-01);
positions[525] = Vec3( 5.4535540e-01, 1.2249720e-01, -4.0869350e-01);
positions[526] = Vec3( 6.0755050e-01, 1.6343320e-01, -3.4805580e-01);
positions[527] = Vec3( 4.8362230e-01, 8.8573600e-02, -3.4405000e-01);
positions[528] = Vec3( 1.3637990e-01, -3.3186850e-01, 1.0338270e-01);
positions[529] = Vec3( 1.5761460e-01, -2.5187340e-01, 1.5683210e-01);
positions[530] = Vec3( 7.8556700e-02, -3.8461200e-01, 1.6118390e-01);
positions[531] = Vec3( 8.4245020e-01, 3.8084570e-01, -6.9184990e-01);
positions[532] = Vec3( 9.0750590e-01, 3.9283710e-01, -7.7288830e-01);
positions[533] = Vec3( 7.5053500e-01, 3.8878480e-01, -7.2751780e-01);
positions[534] = Vec3( 2.7768360e-01, -8.5899240e-01, -5.3138620e-01);
positions[535] = Vec3( 2.8386750e-01, -7.7018020e-01, -5.6323660e-01);
positions[536] = Vec3( 3.4891330e-01, -9.1242960e-01, -5.6853820e-01);
positions[537] = Vec3( 2.6823810e-01, -7.8504070e-01, 6.9926380e-01);
positions[538] = Vec3( 3.3824260e-01, -8.3764610e-01, 7.3839250e-01);
positions[539] = Vec3( 3.0089590e-01, -6.9098950e-01, 7.0290360e-01);
positions[540] = Vec3( 9.5946000e-02, 5.9757730e-01, 8.8417370e-01);
positions[541] = Vec3( 1.9084960e-01, 5.8892180e-01, 8.6811780e-01);
positions[542] = Vec3( 7.0090900e-02, 6.3001980e-01, 9.7622150e-01);
positions[543] = Vec3( -3.2687830e-01, -9.5478000e-03, 2.1684540e-01);
positions[544] = Vec3( -3.2605730e-01, -1.4225700e-02, 3.1463820e-01);
positions[545] = Vec3( -2.7582100e-01, -8.4479800e-02, 1.8809180e-01);
positions[546] = Vec3( -8.3433230e-01, -5.5202940e-01, 2.1864880e-01);
positions[547] = Vec3( -8.2396710e-01, -5.4694370e-01, 3.1266070e-01);
positions[548] = Vec3( -9.3264700e-01, -5.5452020e-01, 1.9359510e-01);
positions[549] = Vec3( -3.7479050e-01, 2.2505660e-01, 7.1205330e-01);
positions[550] = Vec3( -4.7509020e-01, 2.3675960e-01, 7.1906840e-01);
positions[551] = Vec3( -3.3344270e-01, 3.0911900e-01, 7.2096390e-01);
positions[552] = Vec3( 5.4909720e-01, -6.8048160e-01, 7.2400200e-02);
positions[553] = Vec3( 6.0527360e-01, -6.6696760e-01, 1.5170900e-01);
positions[554] = Vec3( 5.8614280e-01, -6.1178520e-01, 1.7524700e-02);
positions[555] = Vec3( -2.3127640e-01, 9.0287820e-01, -1.3411380e-01);
positions[556] = Vec3( -2.8615520e-01, 9.5668910e-01, -1.9830460e-01);
positions[557] = Vec3( -2.9306830e-01, 8.7146310e-01, -6.8234400e-02);
positions[558] = Vec3( -5.4794480e-01, 6.9927600e-02, 4.9211700e-02);
positions[559] = Vec3( -4.8467110e-01, 1.3673600e-02, 9.6662900e-02);
positions[560] = Vec3( -5.5944570e-01, 3.5041600e-02, -4.0422400e-02);
positions[561] = Vec3( -4.0842490e-01, -6.1610810e-01, 5.3013490e-01);
positions[562] = Vec3( -3.5055240e-01, -6.7988460e-01, 4.9398580e-01);
positions[563] = Vec3( -4.6296070e-01, -6.7880320e-01, 5.8633470e-01);
positions[564] = Vec3( 4.6585780e-01, 7.8746100e-01, -1.2817710e-01);
positions[565] = Vec3( 5.3858490e-01, 8.3094890e-01, -7.7410200e-02);
positions[566] = Vec3( 4.0552000e-01, 7.4979180e-01, -6.1891900e-02);
positions[567] = Vec3( -1.6560700e-02, -3.7062430e-01, -3.6569060e-01);
positions[568] = Vec3( -9.0792700e-02, -4.1378610e-01, -3.2720710e-01);
positions[569] = Vec3( 5.1374900e-02, -4.3774530e-01, -3.4403280e-01);
positions[570] = Vec3( -5.9512760e-01, 1.7073000e-02, -2.2772060e-01);
positions[571] = Vec3( -5.8225940e-01, 7.1421900e-02, -3.0604790e-01);
positions[572] = Vec3( -6.2819960e-01, -6.3276600e-02, -2.6202260e-01);
positions[573] = Vec3( -4.7641750e-01, -4.2323550e-01, 8.9604240e-01);
positions[574] = Vec3( -5.4796980e-01, -4.1341290e-01, 8.3129580e-01);
positions[575] = Vec3( -4.6422920e-01, -5.2061790e-01, 8.9834640e-01);
positions[576] = Vec3( 1.4489300e-02, -8.9340740e-01, -3.4831200e-02);
positions[577] = Vec3( -6.9252500e-02, -9.1064710e-01, -8.0576000e-02);
positions[578] = Vec3( 8.8146500e-02, -9.1521790e-01, -9.6184600e-02);
positions[579] = Vec3( -6.0237270e-01, 6.8170090e-01, 6.7672100e-02);
positions[580] = Vec3( -6.3353490e-01, 6.5944010e-01, -1.4737000e-02);
positions[581] = Vec3( -6.7945440e-01, 7.0260310e-01, 1.2553510e-01);
positions[582] = Vec3( -7.9759390e-01, -4.8566970e-01, -8.8075620e-01);
positions[583] = Vec3( -7.6587590e-01, -4.4277470e-01, -9.5861500e-01);
positions[584] = Vec3( -8.8262650e-01, -4.4354590e-01, -8.6497650e-01);
positions[585] = Vec3( 6.0913180e-01, 7.5063640e-01, -3.7944500e-01);
positions[586] = Vec3( 6.8958950e-01, 8.0236210e-01, -3.5044320e-01);
positions[587] = Vec3( 5.5351750e-01, 7.5362410e-01, -2.9669720e-01);
positions[588] = Vec3( 7.4485800e-01, 5.3041050e-01, -4.4708420e-01);
positions[589] = Vec3( 7.0182180e-01, 6.1806940e-01, -4.3652910e-01);
positions[590] = Vec3( 8.0156580e-01, 5.2857300e-01, -5.2411300e-01);
positions[591] = Vec3( -6.9004280e-01, -5.9012070e-01, -2.9270410e-01);
positions[592] = Vec3( -7.1539690e-01, -6.8384200e-01, -2.8572180e-01);
positions[593] = Vec3( -5.9319910e-01, -5.8219810e-01, -2.7391860e-01);
positions[594] = Vec3( -2.0769030e-01, -9.0263320e-01, 8.2559380e-01);
positions[595] = Vec3( -1.2326710e-01, -9.0347650e-01, 7.7889800e-01);
positions[596] = Vec3( -2.4674410e-01, -8.1114260e-01, 8.1400270e-01);
positions[597] = Vec3( -5.9770390e-01, -2.5353030e-01, 3.7815410e-01);
positions[598] = Vec3( -5.7799760e-01, -1.8503970e-01, 4.3781640e-01);
positions[599] = Vec3( -6.3056510e-01, -1.9169960e-01, 3.0646360e-01);
positions[600] = Vec3( 2.5756560e-01, -9.0983610e-01, -2.2681580e-01);
positions[601] = Vec3( 3.3909840e-01, -9.6122750e-01, -2.1952540e-01);
positions[602] = Vec3( 2.5286730e-01, -8.8095350e-01, -3.1936560e-01);
positions[603] = Vec3( -5.7980030e-01, 4.5624440e-01, -4.8053250e-01);
positions[604] = Vec3( -5.0283550e-01, 4.0235700e-01, -4.7629430e-01);
positions[605] = Vec3( -5.5234760e-01, 5.5030960e-01, -4.6445780e-01);
positions[606] = Vec3( 2.6417710e-01, 3.6149920e-01, 5.5726940e-01);
positions[607] = Vec3( 1.8510390e-01, 3.4649300e-01, 6.1450570e-01);
positions[608] = Vec3( 2.5328370e-01, 4.4988030e-01, 5.1753010e-01);
positions[609] = Vec3( 8.0108540e-01, -7.3935090e-01, -4.6186460e-01);
positions[610] = Vec3( 8.1693510e-01, -7.9012220e-01, -3.8198140e-01);
positions[611] = Vec3( 8.8304810e-01, -6.9238110e-01, -4.8097940e-01);
positions[612] = Vec3( -5.8628640e-01, 1.5133800e-02, -5.2805090e-01);
positions[613] = Vec3( -5.0874980e-01, 5.8718200e-02, -5.5884230e-01);
positions[614] = Vec3( -6.4503990e-01, 1.9133400e-02, -6.0165090e-01);
positions[615] = Vec3( 7.6453220e-01, -5.9994620e-01, 2.8797170e-01);
positions[616] = Vec3( 7.0859250e-01, -5.4012040e-01, 3.3515640e-01);
positions[617] = Vec3( 7.9449730e-01, -6.7260900e-01, 3.4844210e-01);
positions[618] = Vec3( -4.1271350e-01, 6.8162960e-01, -6.2517570e-01);
positions[619] = Vec3( -3.4841290e-01, 6.1054470e-01, -6.4194430e-01);
positions[620] = Vec3( -3.5808100e-01, 7.5958210e-01, -6.0333290e-01);
positions[621] = Vec3( -2.3867290e-01, 5.9441400e-02, 9.1386800e-01);
positions[622] = Vec3( -2.9103650e-01, -1.4337800e-02, 9.5259360e-01);
positions[623] = Vec3( -2.8602000e-01, 1.0405050e-01, 8.3648420e-01);
positions[624] = Vec3( 6.2908620e-01, -6.6369160e-01, -8.8313160e-01);
positions[625] = Vec3( 5.3309000e-01, -6.6824080e-01, -8.8386380e-01);
positions[626] = Vec3( 6.6687380e-01, -7.2037270e-01, -8.1674370e-01);
positions[627] = Vec3( 2.5101170e-01, -8.8838680e-01, 2.2900940e-01);
positions[628] = Vec3( 2.4302200e-01, -8.1686710e-01, 1.6969450e-01);
positions[629] = Vec3( 3.4457660e-01, -8.9596990e-01, 2.4839760e-01);
positions[630] = Vec3( -9.1418940e-01, 8.0389630e-01, 7.8826000e-01);
positions[631] = Vec3( -8.3833600e-01, 7.4209380e-01, 7.8290720e-01);
positions[632] = Vec3( -9.9161100e-01, 7.5608500e-01, 8.2971860e-01);
positions[633] = Vec3( 7.9708930e-01, -3.2882190e-01, 7.1789600e-01);
positions[634] = Vec3( 8.5609970e-01, -2.5716920e-01, 7.4938090e-01);
positions[635] = Vec3( 7.9853320e-01, -3.2248890e-01, 6.2155040e-01);
positions[636] = Vec3( 7.9743030e-01, -6.0061740e-01, 7.6822330e-01);
positions[637] = Vec3( 8.2105340e-01, -5.0895770e-01, 7.5902860e-01);
positions[638] = Vec3( 7.2970170e-01, -6.0508550e-01, 8.3860140e-01);
positions[639] = Vec3( -1.1738970e-01, -5.9305270e-01, 7.0381050e-01);
positions[640] = Vec3( -1.5290840e-01, -6.5518590e-01, 6.3431800e-01);
positions[641] = Vec3( -1.6038250e-01, -5.0776740e-01, 6.8496070e-01);
positions[642] = Vec3( 5.8567050e-01, 3.6131160e-01, 3.0656670e-01);
positions[643] = Vec3( 5.1450330e-01, 4.2381370e-01, 2.6162660e-01);
positions[644] = Vec3( 5.3597340e-01, 3.2574600e-01, 3.8272470e-01);
positions[645] = Vec3( -7.5114680e-01, 3.5944460e-01, 2.4369600e-01);
positions[646] = Vec3( -8.1938720e-01, 4.1907000e-01, 2.7265900e-01);
positions[647] = Vec3( -7.8315770e-01, 3.2541650e-01, 1.6165560e-01);
system.addForce(amoebaVdwForce);
std::string platformName;
platformName = "CUDA";
LangevinIntegrator integrator(0.0, 0.1, 0.01);
Context context(system, integrator, Platform::getPlatformByName(platformName));
context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy);
forces = state.getForces();
energy = state.getPotentialEnergy();
}
// test employing box of 216 water molecules w/ and w/o dispersion correction
void testVdwWater(int includeVdwDispersionCorrection) {
std::string testName;
if (includeVdwDispersionCorrection) {
testName = "testVdwWaterWithDispersionCorrection";
} else {
testName = "testVdwWater";
}
int numberOfParticles = 648;
double boxDimension = 1.8643;
double cutoff = 0.9;
std::vector<Vec3> forces;
double energy;
setupAndGetForcesEnergyVdwWater("CUBIC-MEAN", "HHG", cutoff, boxDimension, includeVdwDispersionCorrection, forces, energy);
std::vector<Vec3> expectedForces(numberOfParticles);
// initialize expected energy and forces
double expectedEnergy;
if (includeVdwDispersionCorrection) {
expectedEnergy = 4.0108819792e+03;
} else {
expectedEnergy = 4.0349101e+03;
}
expectedForces[0] = Vec3( 2.3025909e+02, -1.0422757e+01, -2.1413965e+02);
expectedForces[1] = Vec3( 1.1261936e+02, 5.5882575e+02, 9.6539143e+01);
expectedForces[2] = Vec3( -8.8436857e+01, -4.4737313e+01, 2.5242022e+02);
expectedForces[3] = Vec3( 6.3548886e+02, -1.9582636e+02, -1.2229882e+02);
expectedForces[4] = Vec3( -3.9513809e+02, -1.3738635e+02, -1.2488717e+02);
expectedForces[5] = Vec3( 6.8771170e+00, 9.1574345e+01, -1.3865672e+00);
expectedForces[6] = Vec3( 3.6928792e+02, -7.1025648e+01, 5.2550320e+02);
expectedForces[7] = Vec3( 1.5531325e+02, -7.9256260e+02, 3.8119809e+02);
expectedForces[8] = Vec3( 1.5408049e+02, 1.4633285e+02, -5.4573735e+02);
expectedForces[9] = Vec3( -3.2549641e+02, 2.8613802e+01, 1.8082150e+02);
expectedForces[10] = Vec3( 1.9968249e+02, -7.7742415e+01, -4.2188467e+02);
expectedForces[11] = Vec3( 4.6645952e+01, 2.1362909e+01, 5.7120135e+01);
expectedForces[12] = Vec3( 4.2971265e+01, -4.2927865e+01, -7.6319121e+02);
expectedForces[13] = Vec3( 2.1889551e+02, -5.1806784e+01, 7.6637073e+01);
expectedForces[14] = Vec3( -3.0028991e+02, 9.0479382e+01, 1.3199449e+02);
expectedForces[15] = Vec3( -1.8041801e+00, -1.2176813e+03, -5.9679371e+02);
expectedForces[16] = Vec3( -1.4773339e+02, -1.2582057e+02, 8.4242040e+02);
expectedForces[17] = Vec3( 6.8633312e+02, -2.4864325e+01, 1.0675519e+01);
expectedForces[18] = Vec3( 4.8211733e+02, -2.2044742e+02, 1.8105309e+02);
expectedForces[19] = Vec3( -2.1956736e+02, 5.4786741e+02, -1.4827263e+02);
expectedForces[20] = Vec3( -1.0476100e+02, -1.6922280e+02, 8.3220473e+01);
expectedForces[21] = Vec3( 5.5455350e+01, 1.7851224e+02, 6.0598643e+02);
expectedForces[22] = Vec3( 7.1915871e+00, -1.6455057e+01, -6.3929797e+00);
expectedForces[23] = Vec3( -2.4371864e+02, -7.0765288e+02, -1.7820148e+02);
expectedForces[24] = Vec3( -4.3715367e+02, 2.8707226e+02, 2.2558361e+02);
expectedForces[25] = Vec3( 2.3735557e+00, -4.2064130e+00, 2.5933632e+01);
expectedForces[26] = Vec3( 1.0192415e+02, 5.3205842e+01, -2.0158900e+02);
expectedForces[27] = Vec3( -5.1276812e+02, 2.4860179e+02, 2.5150125e+02);
expectedForces[28] = Vec3( 3.9608987e+02, -4.0544816e+01, -2.1579831e+02);
expectedForces[29] = Vec3( -2.5926005e+02, -1.1691294e+02, -4.7278417e+02);
expectedForces[30] = Vec3( -1.1036158e+02, 3.3229287e+01, 8.8351491e+01);
expectedForces[31] = Vec3( -4.1178603e+00, 1.2957632e+00, 1.2617868e+00);
expectedForces[32] = Vec3( 1.9401524e+02, 1.0030314e+02, 3.0386141e+01);
expectedForces[33] = Vec3( 1.0870981e+02, 2.1865882e+02, 6.7672725e+02);
expectedForces[34] = Vec3( 3.6812338e+01, -2.9347382e-01, 1.2959790e+01);
expectedForces[35] = Vec3( -5.5738560e+01, 2.2268442e+02, -1.4911862e+02);
expectedForces[36] = Vec3( -1.6659719e+02, 8.1941190e+01, 7.8132996e+01);
expectedForces[37] = Vec3( -1.1985659e+02, 7.1891763e+01, -3.2559738e+02);
expectedForces[38] = Vec3( 1.4441653e+02, 4.1824194e+02, 3.4293255e+01);
expectedForces[39] = Vec3( 1.1307312e+02, -3.4981802e+02, -1.0676819e+02);
expectedForces[40] = Vec3( -1.2857487e+02, -4.0798950e+01, -1.7800009e+02);
expectedForces[41] = Vec3( -4.1244991e+02, 2.3439565e+02, 3.8546709e+02);
expectedForces[42] = Vec3( 2.1799653e+02, 2.9397348e+02, -3.8955146e+02);
expectedForces[43] = Vec3( -9.4254462e+01, 5.0157547e+01, 1.3707146e+02);
expectedForces[44] = Vec3( 8.0520929e+02, -1.0228045e+03, -4.5813594e+01);
expectedForces[45] = Vec3( 5.3451125e+02, -7.0725115e+02, -2.3828883e+02);
expectedForces[46] = Vec3( 3.6991801e+02, -1.0410466e+03, 8.4889413e+02);
expectedForces[47] = Vec3( 5.8096458e+01, 2.3859368e+02, 7.3104979e+01);
expectedForces[48] = Vec3( -1.3230378e+03, 7.1827816e+02, 9.4372946e+02);
expectedForces[49] = Vec3( -4.2398413e+02, -3.6766481e+02, -1.6666711e+02);
expectedForces[50] = Vec3( 8.6374766e+00, -2.7870227e+02, 3.0621233e+02);
expectedForces[51] = Vec3( -2.4404981e+02, 1.0510491e+03, -3.5202340e+02);
expectedForces[52] = Vec3( 1.7461155e+02, 1.3419948e+02, 5.0279733e+02);
expectedForces[53] = Vec3( 9.7089193e+01, -1.4826120e+02, -2.3426711e+02);
expectedForces[54] = Vec3( -1.0647432e+02, 2.3266543e+02, -3.5025025e+02);
expectedForces[55] = Vec3( -1.9951717e+02, -1.0804258e+02, 6.2114265e+01);
expectedForces[56] = Vec3( 2.5354284e+02, -3.5074926e+02, -2.9176946e+01);
expectedForces[57] = Vec3( -8.8328002e+02, -1.8937053e+02, 2.0772189e+02);
expectedForces[58] = Vec3( 4.5809698e+01, -1.8636513e+00, 1.6742910e+01);
expectedForces[59] = Vec3( 8.6670673e+01, 1.2653519e+02, 2.0046372e+02);
expectedForces[60] = Vec3( -9.6142275e+02, 1.1800289e+03, 1.0064471e+02);
expectedForces[61] = Vec3( -6.9751453e+01, -1.9324691e+02, 2.2638891e+01);
expectedForces[62] = Vec3( 1.3671815e+02, 1.0129231e+01, -6.1136892e+01);
expectedForces[63] = Vec3( 7.6032938e+02, -1.9779542e+02, -2.5706161e+01);
expectedForces[64] = Vec3( -9.8966607e+00, 3.6294058e+02, -2.3247376e+02);
expectedForces[65] = Vec3( -1.3142673e+02, 9.9368000e+00, 1.4225069e+02);
expectedForces[66] = Vec3( 5.2691625e+01, -4.0618331e+02, -1.0942115e+02);
expectedForces[67] = Vec3( 5.8137742e+01, 2.1942441e+02, -1.7191686e+02);
expectedForces[68] = Vec3( 1.2480778e+02, 2.4086799e+01, -1.9588545e+02);
expectedForces[69] = Vec3( 2.4577512e+02, -2.3516051e+01, 2.3764379e+02);
expectedForces[70] = Vec3( 4.2298797e+01, 8.6807583e+01, 2.9276129e+02);
expectedForces[71] = Vec3( 3.0309915e+01, -3.4686002e+02, 1.0849989e+02);
expectedForces[72] = Vec3( 5.5170999e+02, -1.5797913e+02, 9.8379834e+01);
expectedForces[73] = Vec3( -5.3706921e+02, 2.2236470e+02, 2.7548665e+02);
expectedForces[74] = Vec3( -2.7734936e+02, -4.2949693e+02, -8.2303469e+02);
expectedForces[75] = Vec3( 1.1749001e+03, 9.2734627e+02, -2.6342291e+02);
expectedForces[76] = Vec3( -1.2345216e+02, -6.6220297e+01, 1.1022778e+02);
expectedForces[77] = Vec3( -4.4861284e+01, -7.4560959e+01, -8.0791275e+01);
expectedForces[78] = Vec3( 1.7692476e+01, -9.9067626e+02, -3.3083363e+02);
expectedForces[79] = Vec3( 6.4276566e+01, 5.1865608e+02, 4.1241764e+02);
expectedForces[80] = Vec3( 6.5867999e+02, 2.0995465e+02, -5.0989840e+02);
expectedForces[81] = Vec3( -5.2826435e+02, -1.3719887e+02, 1.9730314e+02);
expectedForces[82] = Vec3( 2.3329314e+02, 5.1589944e+01, -3.3942818e+02);
expectedForces[83] = Vec3( -2.5756193e+00, 1.3788257e+02, 1.3074778e+02);
expectedForces[84] = Vec3( -2.8925811e+01, 8.8185346e+01, 1.1547804e+02);
expectedForces[85] = Vec3( -3.3582542e+01, -1.3079843e+02, 3.4774799e+02);
expectedForces[86] = Vec3( -5.9585326e+01, -3.7973755e+01, 1.0206767e+01);
expectedForces[87] = Vec3( -7.1691223e+01, -1.9547311e+02, 9.3856472e+02);
expectedForces[88] = Vec3( 1.4832977e+02, 4.2005795e+02, 2.7235044e+01);
expectedForces[89] = Vec3( 8.6221698e+00, -1.3935906e+01, -2.5473157e+00);
expectedForces[90] = Vec3( 3.0044348e+02, 3.4320406e+02, 2.5305998e+02);
expectedForces[91] = Vec3( -1.6694013e+02, 7.4645776e+02, 3.3266168e+01);
expectedForces[92] = Vec3( 1.6931562e+02, -2.3972286e+01, -3.0802865e+02);
expectedForces[93] = Vec3( -2.5931152e+02, -9.7825375e+01, -5.5598386e+02);
expectedForces[94] = Vec3( -7.8473519e+01, -2.6244561e+02, 2.9622027e+02);
expectedForces[95] = Vec3( 1.5788473e+02, 2.9806605e+02, 1.8283700e+02);
expectedForces[96] = Vec3( -4.2033208e+02, 4.8745845e+02, 9.7957219e+01);
expectedForces[97] = Vec3( 1.3261733e+00, 3.7143158e+00, -1.8329960e+00);
expectedForces[98] = Vec3( 7.4741051e+02, 1.0482696e+03, 1.7182445e+02);
expectedForces[99] = Vec3( 2.0366606e+02, 1.1586652e+02, 1.5482927e+03);
expectedForces[100] = Vec3( 5.7569884e+02, -2.2068597e+02, -1.9305186e+02);
expectedForces[101] = Vec3( -2.4259775e+02, -6.1359858e+01, -7.5753918e+01);
expectedForces[102] = Vec3( 2.4382837e+02, 1.3660693e+01, -2.8717824e+02);
expectedForces[103] = Vec3( -4.1914381e+02, -1.4506334e+02, 7.7692658e+01);
expectedForces[104] = Vec3( 9.5422158e+01, -1.4261849e+01, 1.0122453e+02);
expectedForces[105] = Vec3( -6.1222151e+02, 6.1398147e+01, 3.2961693e+02);
expectedForces[106] = Vec3( -2.7982116e+02, -3.7564793e+02, -2.4318658e+02);
expectedForces[107] = Vec3( 8.2892383e+01, 1.1992522e+01, 2.4802899e+01);
expectedForces[108] = Vec3( -3.3626753e+02, -7.8892295e+01, 8.1184535e+02);
expectedForces[109] = Vec3( -4.6396103e+01, 3.1165111e+01, -3.5184949e+01);
expectedForces[110] = Vec3( 4.6295297e+02, -8.0135823e+01, -3.2963637e+02);
expectedForces[111] = Vec3( 5.5325945e+02, 3.8213691e+02, -5.9449911e+02);
expectedForces[112] = Vec3( -6.1770559e+02, 2.2322880e+02, -2.1022934e+01);
expectedForces[113] = Vec3( 2.3716825e+02, -3.8085281e+02, 4.9618193e+02);
expectedForces[114] = Vec3( 2.9972570e+02, 3.3773759e+02, 3.4933501e+02);
expectedForces[115] = Vec3( 1.9913039e+02, -3.2035626e+02, -9.7987777e+01);
expectedForces[116] = Vec3( -2.3506456e+02, 4.0030561e+02, -6.2604809e+02);
expectedForces[117] = Vec3( 6.0408777e+02, 5.6271523e+02, -5.8742635e+02);
expectedForces[118] = Vec3( -5.0707285e+02, 7.8511351e+02, -1.7561830e+02);
expectedForces[119] = Vec3( 5.6759945e+00, 6.9735233e+00, -9.8853787e+00);
expectedForces[120] = Vec3( 1.1918531e+02, -5.6200785e+02, 3.2333502e+02);
expectedForces[121] = Vec3( 5.1801315e+02, -3.4460898e+02, 1.1488242e+02);
expectedForces[122] = Vec3( 7.5859703e+00, 6.9528951e+01, -6.2437444e+00);
expectedForces[123] = Vec3( 1.1990899e+03, -1.2507886e+01, 1.1906562e+03);
expectedForces[124] = Vec3( 2.6001536e+02, -9.5041373e+01, -4.2547252e+02);
expectedForces[125] = Vec3( -3.5601586e+01, 9.1460220e+02, 6.2306102e+02);
expectedForces[126] = Vec3( -3.8254176e+01, 2.4796243e+02, 3.0638741e+02);
expectedForces[127] = Vec3( -3.8798311e+02, 1.2532794e+02, -3.1926601e+01);
expectedForces[128] = Vec3( 5.7672682e+01, 1.7487900e+02, -1.0319581e+02);
expectedForces[129] = Vec3( 4.4276215e+02, -1.5517993e+02, 3.8122873e+02);
expectedForces[130] = Vec3( -2.8119980e+02, -2.6530936e+02, 4.3545814e+01);
expectedForces[131] = Vec3( 5.9375768e+00, 1.6335780e+01, -3.6204644e+02);
expectedForces[132] = Vec3( 5.9733834e+02, -2.9843602e+02, 1.0541092e+03);
expectedForces[133] = Vec3( -3.4568461e+02, 2.2794808e+02, -8.4675886e+01);
expectedForces[134] = Vec3( -6.7882706e+01, -4.5016799e+02, -1.9387646e+02);
expectedForces[135] = Vec3( 5.6125478e+02, -1.1741092e+03, 1.4214256e+02);
expectedForces[136] = Vec3( 1.2766648e+02, 1.2519441e+02, -4.4359129e+02);
expectedForces[137] = Vec3( -2.7235507e+01, -1.0871423e+01, 3.2406976e+01);
expectedForces[138] = Vec3( -1.2110689e+03, 1.3038667e+02, -7.5331947e+02);
expectedForces[139] = Vec3( 3.2504988e+02, -7.1577942e+02, -2.4351454e+02);
expectedForces[140] = Vec3( 2.6466925e+02, 3.6878498e+02, -6.2044711e+01);
expectedForces[141] = Vec3( -6.2647276e+02, -4.7112562e+02, -6.1885184e+01);
expectedForces[142] = Vec3( 3.0996699e+01, 3.1033732e+02, -5.7493337e+02);
expectedForces[143] = Vec3( 2.4664962e+01, 7.8306665e+02, 3.7907751e+02);
expectedForces[144] = Vec3( -1.9847551e+02, -3.0052499e+02, -6.5192951e+01);
expectedForces[145] = Vec3( -5.0686773e+02, 1.1972933e+02, 3.6202910e+02);
expectedForces[146] = Vec3( 4.0004521e+02, -4.3205645e+02, 2.8583074e+02);
expectedForces[147] = Vec3( -2.9447542e+01, 6.3434099e+02, -6.5189179e+02);
expectedForces[148] = Vec3( 4.1588516e+02, -1.5534873e+02, -1.1031323e+01);
expectedForces[149] = Vec3( 1.2761543e+01, -5.6871456e+01, 2.8032565e+02);
expectedForces[150] = Vec3( -4.7527199e+01, 6.2549647e+02, -8.5007589e+02);
expectedForces[151] = Vec3( 1.6598949e+01, 1.1210199e+02, 2.0667266e+02);
expectedForces[152] = Vec3( -2.4012423e+00, -6.1728962e+01, -1.5057977e+01);
expectedForces[153] = Vec3( -3.6934056e+02, 2.3087063e+02, -3.3268511e+02);
expectedForces[154] = Vec3( 1.2658460e+02, 4.1809355e+02, 1.9550635e+02);
expectedForces[155] = Vec3( -1.9528152e+02, -1.9035919e+02, 1.4986704e+02);
expectedForces[156] = Vec3( -5.9608803e+00, 2.7258190e+02, 5.5318395e+02);
expectedForces[157] = Vec3( -1.0545084e+01, -1.8397001e+00, -3.3615498e+00);
expectedForces[158] = Vec3( -4.0827462e+02, -6.4070993e+01, -2.6614992e+02);
expectedForces[159] = Vec3( -1.5773827e+02, 4.7708702e+02, -9.9622711e+02);
expectedForces[160] = Vec3( 8.3896122e+01, 2.5959601e+02, 1.7728081e+02);
expectedForces[161] = Vec3( -2.4859055e+02, 8.1617294e+01, 2.7905586e+02);
expectedForces[162] = Vec3( 1.3694593e+02, -6.2640483e+02, -2.5308878e+02);
expectedForces[163] = Vec3( -1.5156337e+02, 1.1567379e+02, 1.8384602e+02);
expectedForces[164] = Vec3( -1.4794785e+02, -8.0381965e+01, 9.4028021e+02);
expectedForces[165] = Vec3( -3.5851252e+02, 2.6066489e+02, -4.1225343e+01);
expectedForces[166] = Vec3( 1.0820389e+02, -8.3485138e+01, 9.5047812e+01);
expectedForces[167] = Vec3( 2.0019411e+02, 5.0864719e+02, -4.8662239e+01);
expectedForces[168] = Vec3( -3.0716707e+02, -9.8820762e+02, 1.3660536e+01);
expectedForces[169] = Vec3( 8.5788590e+02, -1.0335921e+02, -2.2197815e+02);
expectedForces[170] = Vec3( 9.8072705e+00, 6.6224870e+02, -1.1594055e+02);
expectedForces[171] = Vec3( -3.6572453e+01, 2.4062731e+02, 1.7831682e+02);
expectedForces[172] = Vec3( -2.1274187e+00, -2.5471785e+02, -2.5813525e+02);
expectedForces[173] = Vec3( 3.4763673e+02, -2.0753062e+02, 7.5125390e+02);
expectedForces[174] = Vec3( 2.9010685e+01, -4.1894498e+02, -6.3847846e+02);
expectedForces[175] = Vec3( 3.0255245e+02, 2.5945698e+02, 2.3530662e+01);
expectedForces[176] = Vec3( -2.0827676e+01, 2.2568888e+01, 1.0890440e+01);
expectedForces[177] = Vec3( 2.2415739e+02, 3.5720682e+02, -8.7208211e+01);
expectedForces[178] = Vec3( -2.9808276e+02, 7.0108444e+01, -1.5361211e+02);
expectedForces[179] = Vec3( 2.3882234e+02, -2.6764176e+02, -1.7847229e+01);
expectedForces[180] = Vec3( -4.7380966e+02, 5.2547306e+01, 7.4446526e+02);
expectedForces[181] = Vec3( 4.2804072e+00, -2.2456284e+02, -2.0288206e+02);
expectedForces[182] = Vec3( 2.5474630e+00, 2.5211778e+01, 1.2675317e+01);
expectedForces[183] = Vec3( -1.4519676e+02, -1.7268277e+02, -8.4750014e+02);
expectedForces[184] = Vec3( -1.6850633e+02, 9.5223081e+02, -2.5415253e+02);
expectedForces[185] = Vec3( -2.1600185e+02, -1.6313340e+02, 1.8746411e+02);
expectedForces[186] = Vec3( 4.5719348e+01, -5.8877840e+01, -1.1199622e+02);
expectedForces[187] = Vec3( -9.0377199e+01, 2.2045926e+02, -3.2532356e+02);
expectedForces[188] = Vec3( -1.4523032e+02, -2.2127499e+02, 1.1526636e+02);
expectedForces[189] = Vec3( 1.9857975e+02, -1.8170037e+02, 3.2016150e+02);
expectedForces[190] = Vec3( 1.5659789e+02, 5.2984420e+01, -1.0121553e+02);
expectedForces[191] = Vec3( 1.3925504e+01, -1.1627739e+02, 1.7106106e+00);
expectedForces[192] = Vec3( 1.7560737e+01, 3.1275548e+02, 1.4568181e+02);
expectedForces[193] = Vec3( 8.5129168e-01, 3.2688468e+01, -2.0471785e+02);
expectedForces[194] = Vec3( 2.5640904e+02, -1.8345358e+02, 3.3082812e+02);
expectedForces[195] = Vec3( 1.5159266e+02, -7.9091822e+02, 7.6475475e+02);
expectedForces[196] = Vec3( 7.8546101e+02, 1.7887845e+02, -7.4508377e+01);
expectedForces[197] = Vec3( 6.9010029e+00, 2.1336674e+01, -7.8256484e+01);
expectedForces[198] = Vec3( -3.4033432e+01, -1.6471994e+02, -2.8721884e+02);
expectedForces[199] = Vec3( -1.2248359e+02, 5.3002993e+01, 3.5296174e+02);
expectedForces[200] = Vec3( 1.7497881e+02, 1.1744848e+02, 1.8127502e+02);
expectedForces[201] = Vec3( -1.1710882e+03, 8.7114752e+02, -1.3353036e+02);
expectedForces[202] = Vec3( 2.7510368e+02, -1.9393814e+02, 2.6671453e+02);
expectedForces[203] = Vec3( 7.3421287e+01, -3.8409917e+01, -1.0910368e+02);
expectedForces[204] = Vec3( -8.7394869e+02, -1.2323430e+03, -1.3693068e+02);
expectedForces[205] = Vec3( 2.5439149e+02, 2.4002077e+02, 3.0231859e+02);
expectedForces[206] = Vec3( -9.8167431e+01, 3.1515278e+02, -2.5512038e+02);
expectedForces[207] = Vec3( 2.7501189e+02, -4.9189774e+02, 4.5827877e+02);
expectedForces[208] = Vec3( -8.2333908e+02, -7.0609881e+02, 2.9188070e+02);
expectedForces[209] = Vec3( -2.9200330e+02, 1.9955124e+02, -7.9227826e+00);
expectedForces[210] = Vec3( 8.0151971e+02, 3.8996996e+02, -1.9508756e+02);
expectedForces[211] = Vec3( -6.2168096e+01, 2.4323951e+01, 9.8845638e+01);
expectedForces[212] = Vec3( 2.2980428e+01, -6.2829693e+02, -7.5253154e+02);
expectedForces[213] = Vec3( -5.7502634e+02, 8.2310635e+02, 3.7934867e+02);
expectedForces[214] = Vec3( -8.9168889e+01, 5.0052167e+01, -8.6850564e+01);
expectedForces[215] = Vec3( 2.7414821e+02, -5.9725191e+01, -3.7278778e+00);
expectedForces[216] = Vec3( -5.3230933e+02, 4.7698725e+02, -2.5857751e+02);
expectedForces[217] = Vec3( 2.1615644e+02, 6.0001233e+01, -1.1880182e+02);
expectedForces[218] = Vec3( 2.9837823e+01, -3.9275454e+01, -4.3913571e+01);
expectedForces[219] = Vec3( -5.6516561e+02, -1.6539113e+02, 3.3185872e+02);
expectedForces[220] = Vec3( -1.5484833e+01, -1.0085566e+01, -2.8199778e+01);
expectedForces[221] = Vec3( 6.4295337e+02, -2.7398997e+02, 8.2320867e+02);
expectedForces[222] = Vec3( 3.3816540e+02, -1.8492046e+02, 8.6215770e+02);
expectedForces[223] = Vec3( 2.4367872e+02, 8.9527142e+01, -5.9973680e+02);
expectedForces[224] = Vec3( -6.1601439e+02, -5.3093862e+02, 4.1696221e+01);
expectedForces[225] = Vec3( 2.2521478e+02, -2.9234267e+02, 2.9760244e+02);
expectedForces[226] = Vec3( -1.2672295e+02, 2.5753736e+01, -1.6216252e+02);
expectedForces[227] = Vec3( 1.1136724e+02, 4.3446676e+00, -1.4045447e+01);
expectedForces[228] = Vec3( 3.5554849e+02, 7.7446255e+00, 5.8722356e+02);
expectedForces[229] = Vec3( -7.8313952e+02, -5.9206053e+01, 5.1181391e+02);
expectedForces[230] = Vec3( -9.5647729e+01, -4.6045792e+02, -3.1515210e+02);
expectedForces[231] = Vec3( 8.7273284e+01, 8.0310279e+02, -1.2212040e+03);
expectedForces[232] = Vec3( -9.0853819e+02, -7.6005570e+02, 1.8578569e+02);
expectedForces[233] = Vec3( 1.2061615e+02, -3.2834560e+02, 5.1291192e+01);
expectedForces[234] = Vec3( 6.0149262e+02, 1.6081852e+03, -1.0922015e+03);
expectedForces[235] = Vec3( -5.8087260e+01, -2.6676779e+02, -1.5006920e+02);
expectedForces[236] = Vec3( -1.0997771e+01, 1.3012815e+02, 5.8615633e+02);
expectedForces[237] = Vec3( 4.9821503e+02, -9.5783644e+01, -6.5708073e+02);
expectedForces[238] = Vec3( -4.9394992e+02, -7.0445435e+02, -1.5540228e+02);
expectedForces[239] = Vec3( 1.5710340e+01, 1.9170336e+02, 4.6707393e+02);
expectedForces[240] = Vec3( -1.2599557e+03, 5.6104975e+02, 6.5853210e+02);
expectedForces[241] = Vec3( 1.3032986e+01, -2.7481865e+01, 8.0373029e+00);
expectedForces[242] = Vec3( 1.4371505e+02, -5.2615293e+01, -3.7929456e+02);
expectedForces[243] = Vec3( 6.0025739e+01, 1.4474905e+02, 3.6414330e+02);
expectedForces[244] = Vec3( 4.5364033e+02, 7.0785823e+01, -2.9279112e+02);
expectedForces[245] = Vec3( -9.7012956e+01, -8.2545229e+01, -5.4567106e+01);
expectedForces[246] = Vec3( -3.6449281e+02, -5.6669832e+02, -3.5196038e+02);
expectedForces[247] = Vec3( 2.6571354e+02, -2.5051716e+02, -4.7199161e+01);
expectedForces[248] = Vec3( -4.7285701e+01, 1.7950093e+02, 8.0633971e+01);
expectedForces[249] = Vec3( 1.8035439e+02, 4.6977540e+02, 2.2589769e+02);
expectedForces[250] = Vec3( 5.9853399e+01, 1.5477006e+02, -1.7011806e+02);
expectedForces[251] = Vec3( -2.6084741e+02, -2.0538756e+02, 1.0269002e+02);
expectedForces[252] = Vec3( 4.0221722e+02, -1.0368371e+02, -1.3842460e+01);
expectedForces[253] = Vec3( -4.4264447e+02, -3.0334810e+02, 1.6740779e+02);
expectedForces[254] = Vec3( -1.7373662e+02, 1.5020202e+02, -3.3761418e+02);
expectedForces[255] = Vec3( 4.7508953e+01, -5.4028784e+02, -3.6291329e+01);
expectedForces[256] = Vec3( 5.4807168e+02, -2.0293664e+02, 5.5114363e+02);
expectedForces[257] = Vec3( -4.9787370e+01, 4.5106329e+01, -5.7524550e+01);
expectedForces[258] = Vec3( -5.1584935e+02, 1.5014186e+02, -6.6369834e+02);
expectedForces[259] = Vec3( -6.0140298e+01, -9.4127280e+01, 8.7495796e+01);
expectedForces[260] = Vec3( 8.0619588e+02, -2.1066454e+02, -5.9371508e+01);
expectedForces[261] = Vec3( 1.2817429e+02, -2.7044116e+02, 5.3213275e+02);
expectedForces[262] = Vec3( -4.1467442e-01, -1.3641138e+02, -8.5576287e+01);
expectedForces[263] = Vec3( -5.6508528e+01, 2.4091504e+01, -7.9236147e+01);
expectedForces[264] = Vec3( 1.4123799e+02, 2.1326444e+02, 1.9141445e+02);
expectedForces[265] = Vec3( 1.6579721e+02, -3.2221503e+02, -1.5197776e+02);
expectedForces[266] = Vec3( -2.5871222e+02, -2.6345996e+02, -1.1149413e+03);
expectedForces[267] = Vec3( -1.2859743e+02, -3.9214753e+02, -6.5874862e+02);
expectedForces[268] = Vec3( 1.7237157e+02, -2.8729010e+02, 3.2000889e+02);
expectedForces[269] = Vec3( 6.6312203e+02, 3.5683926e+02, 9.7235616e+01);
expectedForces[270] = Vec3( -1.1860349e+02, -4.3528895e+02, 1.1598672e+03);
expectedForces[271] = Vec3( 7.7135123e+01, -2.1671305e+02, -2.3088548e+02);
expectedForces[272] = Vec3( 7.2863708e+01, 5.2065158e+02, 1.5704752e+02);
expectedForces[273] = Vec3( -3.6727477e+02, -6.0885463e+01, 4.1193960e+01);
expectedForces[274] = Vec3( 5.4858881e+01, 1.6886577e+02, -1.1662392e+01);
expectedForces[275] = Vec3( 3.2070061e+01, -1.6138709e+01, -7.6648912e+00);
expectedForces[276] = Vec3( 2.5695892e+02, 7.7719531e+01, -8.3154765e+02);
expectedForces[277] = Vec3( -3.3460202e+01, -1.3077348e+02, 3.6110539e+01);
expectedForces[278] = Vec3( -4.1360402e+02, 2.7754335e+02, -1.1139467e+02);
expectedForces[279] = Vec3( 1.0012775e+02, 1.4365237e+03, 2.6972544e+02);
expectedForces[280] = Vec3( 7.8750024e+02, -2.3376123e+02, 9.5969232e+02);
expectedForces[281] = Vec3( -2.2493912e+02, -1.1444344e+01, -6.3713547e+01);
expectedForces[282] = Vec3( -9.4211966e+01, -3.9286586e+02, -7.0932607e+01);
expectedForces[283] = Vec3( 1.6192138e+02, 2.3010404e+02, -2.1511498e+02);
expectedForces[284] = Vec3( -4.9644702e+02, -1.1894844e+01, -4.7458477e+02);
expectedForces[285] = Vec3( -1.0151600e+02, -4.2789293e+02, 5.2698223e+02);
expectedForces[286] = Vec3( 1.1350409e+01, 1.5126445e+02, -5.2740587e+01);
expectedForces[287] = Vec3( -4.7715521e+02, -3.6476152e+02, -5.4346958e+02);
expectedForces[288] = Vec3( -9.4019721e+01, -2.4758228e+02, 4.2219712e+02);
expectedForces[289] = Vec3( 3.1525053e+01, 3.7927245e+02, -2.4577041e+02);
expectedForces[290] = Vec3( 4.4004025e+02, -9.4883983e+01, -6.9075632e+01);
expectedForces[291] = Vec3( -2.6553328e+02, -2.7059185e+02, 3.1145935e+02);
expectedForces[292] = Vec3( 1.1199463e+02, 9.0805870e+01, 8.0258804e+01);
expectedForces[293] = Vec3( 7.8056273e+01, -3.5931761e+01, -1.9249727e+02);
expectedForces[294] = Vec3( -1.2443366e+01, -1.4631721e+02, 7.9733561e+01);
expectedForces[295] = Vec3( -3.2866900e+02, 1.1527926e+02, -9.3135590e+01);
expectedForces[296] = Vec3( 7.5078643e+01, -7.2653837e+02, -1.0830908e+02);
expectedForces[297] = Vec3( 1.0361037e+02, 1.5478274e+02, 1.1293089e+03);
expectedForces[298] = Vec3( -2.4014663e+02, -5.6771824e+02, 1.5441974e+02);
expectedForces[299] = Vec3( -6.8441034e+01, -1.1226846e+02, -5.4497343e+02);
expectedForces[300] = Vec3( 2.9803689e+02, 1.0649462e+03, 2.5408768e+02);
expectedForces[301] = Vec3( 5.6356599e+01, -2.3035579e+02, 7.6928758e+01);
expectedForces[302] = Vec3( 1.0229494e+02, -1.9615696e+02, -3.2600199e+02);
expectedForces[303] = Vec3( -7.0312065e+01, -3.1170055e+02, 5.6453888e+02);
expectedForces[304] = Vec3( -7.0752582e+01, 1.2273280e+02, -1.6740503e+01);
expectedForces[305] = Vec3( 6.8972998e+02, -2.8067032e+02, 6.6502848e+01);
expectedForces[306] = Vec3( -8.8407472e+02, 3.7818347e+02, -1.2141945e+03);
expectedForces[307] = Vec3( -1.0445122e+02, -4.4818836e+02, -9.5227168e+00);
expectedForces[308] = Vec3( 8.3015802e+02, 5.0941309e+02, 3.2593793e+01);
expectedForces[309] = Vec3( 7.6887033e+02, 4.3490548e+02, -1.0826101e+03);
expectedForces[310] = Vec3( 1.4352949e+02, -3.9479802e+01, 1.7718790e+02);
expectedForces[311] = Vec3( -2.5204642e+02, -3.3888239e+02, -2.7365802e+02);
expectedForces[312] = Vec3( -4.4783121e+02, 4.4465580e+02, 9.2506336e+02);
expectedForces[313] = Vec3( -3.3390337e+01, -5.0097602e+02, -3.6812516e+02);
expectedForces[314] = Vec3( -4.1862341e+02, 1.9519764e+02, -2.4571211e+02);
expectedForces[315] = Vec3( -1.4176845e+02, -3.3767798e+01, 1.7800248e+02);
expectedForces[316] = Vec3( -4.7411046e+01, 2.3841278e+01, -1.5183689e+01);
expectedForces[317] = Vec3( 1.6723204e+01, 1.4145797e+02, -1.6930384e+01);
expectedForces[318] = Vec3( -8.4841167e+02, -2.1282818e+02, 8.1614626e+01);
expectedForces[319] = Vec3( 6.5941519e+00, -1.1472179e+02, -2.3181002e+02);
expectedForces[320] = Vec3( 2.2464095e+01, -5.7606215e+00, 5.2865780e+00);
expectedForces[321] = Vec3( 3.8063827e+02, 2.4597014e+02, -4.1947008e+01);
expectedForces[322] = Vec3( -3.1531672e+02, 3.5038104e+02, -3.2724191e+02);
expectedForces[323] = Vec3( 7.4741163e+01, 7.2296536e+01, 3.1768919e+02);
expectedForces[324] = Vec3( 7.9578966e+02, -1.5345175e+02, -7.1301288e+02);
expectedForces[325] = Vec3( -3.1387318e+01, 1.7528515e+01, -3.4100670e+01);
expectedForces[326] = Vec3( 9.3853572e-01, 6.8496077e+00, 1.2234894e+01);
expectedForces[327] = Vec3( -1.3099690e+02, -4.0135958e+02, -4.3248135e+02);
expectedForces[328] = Vec3( 4.3988113e+02, -1.5944416e+02, 5.4620163e+01);
expectedForces[329] = Vec3( 1.3509243e+01, 3.6990268e+00, -2.6251838e-01);
expectedForces[330] = Vec3( -8.7459998e+01, -6.4319025e+02, 2.2863360e+02);
expectedForces[331] = Vec3( -3.5181606e+02, 3.1131978e+02, 2.8037788e+02);
expectedForces[332] = Vec3( 1.9545884e+02, 4.3994512e+01, -2.5158598e+02);
expectedForces[333] = Vec3( 1.8100917e+00, 1.9534738e+02, 1.7181161e+02);
expectedForces[334] = Vec3( -1.1846876e+02, 1.5368782e+02, 2.2261016e+02);
expectedForces[335] = Vec3( 1.4866155e+02, -4.7983795e+02, 3.0361323e+02);
expectedForces[336] = Vec3( -7.7242468e+02, 2.0736079e+02, -8.6661236e+02);
expectedForces[337] = Vec3( -7.9875679e+00, -9.0946585e+02, -7.1617627e+01);
expectedForces[338] = Vec3( 2.2543457e+02, 2.0215639e+02, 4.4285374e+02);
expectedForces[339] = Vec3( -2.6252013e+02, -1.0336519e+02, -2.6630451e+02);
expectedForces[340] = Vec3( 5.0907589e+02, -1.2491931e+02, -4.3015857e+01);
expectedForces[341] = Vec3( -6.0362692e+01, 1.0025664e+02, -9.3389235e+01);
expectedForces[342] = Vec3( 5.8779874e+02, 3.7600030e+02, 2.5345454e+02);
expectedForces[343] = Vec3( -1.3661048e+02, 1.6498482e+02, -2.6789925e+01);
expectedForces[344] = Vec3( 4.9840419e+01, -1.2136315e+02, 2.5455320e+01);
expectedForces[345] = Vec3( 2.3324807e+02, -3.6601512e+02, 5.6798114e+01);
expectedForces[346] = Vec3( 5.5853546e+01, -4.9035168e+00, -5.8726331e+02);
expectedForces[347] = Vec3( -3.8918158e+01, 3.0380495e+02, 1.0944883e+01);
expectedForces[348] = Vec3( -2.6092065e+02, 4.3443036e+02, -1.3673862e+02);
expectedForces[349] = Vec3( 1.5195166e+02, 1.1879426e+01, -1.1429493e+02);
expectedForces[350] = Vec3( -8.5687107e+02, -1.7938881e+02, 4.5576455e+00);
expectedForces[351] = Vec3( -1.0117388e+03, -3.2686610e+02, 2.9733049e+02);
expectedForces[352] = Vec3( -2.3946369e+02, 4.9753786e+02, 7.2681440e+02);
expectedForces[353] = Vec3( 3.9085837e+01, 7.4391931e+00, 3.4179196e+00);
expectedForces[354] = Vec3( 1.0462977e+03, 4.3639578e+02, -5.7349371e+02);
expectedForces[355] = Vec3( 1.2715333e+02, -5.7907885e+02, 5.7463165e+02);
expectedForces[356] = Vec3( -1.5968981e+02, 2.2295605e+01, 6.3554487e+01);
expectedForces[357] = Vec3( -1.9666111e+02, -2.0286725e+02, -8.3590992e+01);
expectedForces[358] = Vec3( 5.9985006e+00, 2.9764307e+01, 3.1304672e+01);
expectedForces[359] = Vec3( 1.0409792e+02, 4.3974987e+02, -9.1530162e+02);
expectedForces[360] = Vec3( 2.9538724e+02, 1.4353710e+02, 2.1558768e+02);
expectedForces[361] = Vec3( -3.7974445e+02, -9.0749144e+01, 1.4531502e+02);
expectedForces[362] = Vec3( 3.7089093e+02, 2.2523397e+02, -2.9760698e+02);
expectedForces[363] = Vec3( -7.6884906e+01, -2.7486958e+02, 3.5671043e+02);
expectedForces[364] = Vec3( 4.3400097e+02, 2.2275226e+02, 5.9201087e+01);
expectedForces[365] = Vec3( 2.1177620e+02, -6.4990517e+02, -1.8431623e+02);
expectedForces[366] = Vec3( -8.2234148e+01, 4.9900036e+02, 3.0906858e+02);
expectedForces[367] = Vec3( -1.4784097e+02, 1.3442463e+02, -2.6811487e+02);
expectedForces[368] = Vec3( 2.2289541e+02, -4.1933983e+02, 1.3646246e+01);
expectedForces[369] = Vec3( -2.1199481e+02, 6.2103281e+01, 1.6049768e+02);
expectedForces[370] = Vec3( -2.9429845e+01, -1.3944740e+01, 1.6000003e+01);
expectedForces[371] = Vec3( -1.5093250e+02, -1.9541345e+02, -1.5879844e+02);
expectedForces[372] = Vec3( 2.2218133e+02, 7.5740668e+01, -7.0754853e+02);
expectedForces[373] = Vec3( -4.7529615e+02, -3.5259490e+02, 3.8025744e+02);
expectedForces[374] = Vec3( 4.9308495e+01, 1.2206152e+02, 4.2704595e+01);
expectedForces[375] = Vec3( -3.6408113e+02, 9.5905960e+02, 3.3861668e+02);
expectedForces[376] = Vec3( 1.5324093e+02, -1.4375341e+02, -9.1369900e+01);
expectedForces[377] = Vec3( -3.5343609e+02, -4.4662438e+02, 3.1741831e+02);
expectedForces[378] = Vec3( -8.2721281e+02, -6.4969313e+01, 4.1869320e+02);
expectedForces[379] = Vec3( -8.7419096e+00, -4.6278343e+01, -3.0259942e+01);
expectedForces[380] = Vec3( 1.6814871e+01, 4.5462601e+01, -3.5204538e+01);
expectedForces[381] = Vec3( 1.9043143e+02, 5.1101135e+02, 2.9970918e+02);
expectedForces[382] = Vec3( -4.3547560e+02, -7.7495770e+01, -8.2311440e+01);
expectedForces[383] = Vec3( 1.3206505e+02, 4.0993476e+01, 1.5150623e+01);
expectedForces[384] = Vec3( 4.6163268e+01, -2.7722119e+01, -2.2996255e+02);
expectedForces[385] = Vec3( -4.7033552e+01, 1.5721545e+02, -9.2562636e+01);
expectedForces[386] = Vec3( -2.4164903e+02, -1.4771464e+02, -5.1675638e+01);
expectedForces[387] = Vec3( 1.3445564e+03, 3.5387081e+02, -3.7402713e+02);
expectedForces[388] = Vec3( -2.6290280e+02, 2.5025510e+02, 3.0570707e+01);
expectedForces[389] = Vec3( -4.4624214e+02, -2.4919412e+02, 1.1336564e+03);
expectedForces[390] = Vec3( 3.1188483e+02, 6.4836125e+02, 4.5477683e+01);
expectedForces[391] = Vec3( 2.5570674e+02, -2.7101115e+02, -1.2579817e+02);
expectedForces[392] = Vec3( -3.4941759e+02, -3.2508734e+01, -5.6131515e+01);
expectedForces[393] = Vec3( -1.2734301e+02, -2.0417657e+02, 5.7738004e+02);
expectedForces[394] = Vec3( 5.0435795e+01, -9.5203527e+01, -4.1237509e+00);
expectedForces[395] = Vec3( -6.8258463e+01, 1.7475914e+02, -1.6422294e+02);
expectedForces[396] = Vec3( 2.6455575e+02, 2.6880230e+02, -1.6607620e+01);
expectedForces[397] = Vec3( -3.5968167e+02, 6.6092937e+01, 1.5915445e+02);
expectedForces[398] = Vec3( 8.4092494e-01, -5.9896731e+01, -2.1856007e+01);
expectedForces[399] = Vec3( -1.9237984e+02, -1.6506355e+02, 1.3370845e+02);
expectedForces[400] = Vec3( 4.7023043e+02, 1.2931257e+02, -1.7013618e+02);
expectedForces[401] = Vec3( 9.4928843e+01, -3.1613892e+02, -4.6973091e+02);
expectedForces[402] = Vec3( -2.9180818e+02, 6.5496755e+02, -2.9430870e+02);
expectedForces[403] = Vec3( 1.6670668e+02, -2.4693913e+02, -8.8775735e+01);
expectedForces[404] = Vec3( -1.4218604e+02, 2.3173349e+02, 3.9869740e+02);
expectedForces[405] = Vec3( 4.3469431e+02, -2.4686568e+02, -2.6838523e+02);
expectedForces[406] = Vec3( 1.0671130e+02, 3.9710106e+02, 2.6478100e+02);
expectedForces[407] = Vec3( -4.4281099e+02, -3.2746126e+01, -2.0719929e+02);
expectedForces[408] = Vec3( 1.1864952e+01, -1.5901568e+02, 1.1865945e+01);
expectedForces[409] = Vec3( -6.0546863e+01, -1.3488005e+02, -2.9223986e+02);
expectedForces[410] = Vec3( 2.5845942e+01, 1.7545933e+02, -1.4590654e+02);
expectedForces[411] = Vec3( -3.0776460e+02, 2.7351986e+02, -2.0386483e+02);
expectedForces[412] = Vec3( 1.7301558e+02, 8.3012339e+01, 7.6018513e+02);
expectedForces[413] = Vec3( 1.2893147e+02, -3.9937475e+00, 1.4197628e+01);
expectedForces[414] = Vec3( -3.9803615e+02, -4.4825663e+02, 2.8616211e+01);
expectedForces[415] = Vec3( -2.3586809e+02, -8.9306136e+01, 7.5265669e+02);
expectedForces[416] = Vec3( 8.3814512e+02, -9.5563706e+00, 2.8738759e+02);
expectedForces[417] = Vec3( -3.8269399e+02, -2.3650170e+02, 1.7330415e+01);
expectedForces[418] = Vec3( 7.2310675e+00, 2.4731653e+01, 1.9491126e+01);
expectedForces[419] = Vec3( 8.4485111e+01, 9.0560261e+01, -1.4261777e+01);
expectedForces[420] = Vec3( 2.1829925e+02, -8.3951651e+01, -7.8910117e+02);
expectedForces[421] = Vec3( -2.4228018e+02, -5.7097512e+01, 2.6447829e+02);
expectedForces[422] = Vec3( 6.9666665e+01, -4.7313678e+02, 4.5559673e+02);
expectedForces[423] = Vec3( 1.0108369e+02, 4.6568610e+02, 2.5612541e+02);
expectedForces[424] = Vec3( 7.2334238e+01, -1.5660040e+02, -2.6278686e+02);
expectedForces[425] = Vec3( 1.0749954e+03, 2.4395658e+02, -8.7308262e+01);
expectedForces[426] = Vec3( 5.4983082e+02, 5.6528577e+02, -3.0489991e+02);
expectedForces[427] = Vec3( -2.1210132e+02, -1.5871954e+02, -1.6936452e+02);
expectedForces[428] = Vec3( -9.5473983e+01, 7.4879276e+01, 5.5720204e+01);
expectedForces[429] = Vec3( 5.6417182e+02, -1.3478250e+02, -4.8006673e+01);
expectedForces[430] = Vec3( -1.0055266e+02, -8.3811289e+01, 6.5259748e+01);
expectedForces[431] = Vec3( 3.0553989e+01, 4.0927300e+02, 6.2242246e+02);
expectedForces[432] = Vec3( -6.0956353e+02, 9.0301312e+02, -1.4063582e+01);
expectedForces[433] = Vec3( 3.2774559e+02, -1.0849473e+02, -8.8877712e+01);
expectedForces[434] = Vec3( 2.1371643e+02, -7.2067980e+01, 2.4803863e+02);
expectedForces[435] = Vec3( -9.0636479e+01, 1.0673514e+03, 1.3005625e+02);
expectedForces[436] = Vec3( -3.5058624e+02, -1.4968284e+02, 1.4340635e+02);
expectedForces[437] = Vec3( 3.4640813e+01, -4.8035225e+01, 4.4066226e+01);
expectedForces[438] = Vec3( -2.3414523e+02, -9.1359130e+01, 2.8535427e+02);
expectedForces[439] = Vec3( -2.7156547e+02, -6.3426763e+01, 1.6968017e+01);
expectedForces[440] = Vec3( -2.8751166e+00, 4.3192169e+00, -2.1401359e+00);
expectedForces[441] = Vec3( -2.0241419e+01, 4.2856138e+02, 7.3204868e+01);
expectedForces[442] = Vec3( -4.2166169e+01, -2.2454013e+01, -5.4998450e+01);
expectedForces[443] = Vec3( 2.6442026e+02, -1.1670567e+02, 2.8879291e+02);
expectedForces[444] = Vec3( -4.9762729e+02, 4.7320314e+02, 3.2506251e+02);
expectedForces[445] = Vec3( -3.0994232e+02, 3.6728867e+02, -6.8793662e+02);
expectedForces[446] = Vec3( -5.6328374e+00, -2.3284824e+00, 1.9650486e+01);
expectedForces[447] = Vec3( 4.0145354e+02, 7.0143762e+02, 1.3039041e+02);
expectedForces[448] = Vec3( 1.3270713e+02, -3.3050447e+02, 2.8630784e+02);
expectedForces[449] = Vec3( -3.8904836e+02, -4.6125118e+01, -3.8815388e+02);
expectedForces[450] = Vec3( 4.6293066e+02, -2.4970158e+02, -5.7231818e+01);
expectedForces[451] = Vec3( -4.7707142e+00, 1.7120822e-01, 4.5081299e+00);
expectedForces[452] = Vec3( 3.5968818e+01, -1.1892248e+01, 1.2184792e+02);
expectedForces[453] = Vec3( 4.4939172e+02, 4.8377647e+02, 3.0529778e+02);
expectedForces[454] = Vec3( -2.9071570e+02, -9.0611613e+01, -2.5190431e+02);
expectedForces[455] = Vec3( -1.4344537e+02, -1.3061997e+03, 3.8343947e+02);
expectedForces[456] = Vec3( 4.1580940e+02, -3.6864043e+02, 6.6384066e+02);
expectedForces[457] = Vec3( -3.4869949e+02, 3.3262427e+02, -8.3156358e+01);
expectedForces[458] = Vec3( -5.8565457e+00, -5.1879987e+02, -7.2717213e+02);
expectedForces[459] = Vec3( -1.0514593e+02, -2.6844396e+02, 3.0849659e+02);
expectedForces[460] = Vec3( -1.2562153e+02, 6.5438031e+01, -2.3521687e+02);
expectedForces[461] = Vec3( 8.3330016e+02, -6.7961048e+02, -7.2442064e+02);
expectedForces[462] = Vec3( -1.3328298e+02, 1.6143544e+02, -3.2000493e+02);
expectedForces[463] = Vec3( -1.1035002e+02, -8.6040775e+01, 2.0953986e+02);
expectedForces[464] = Vec3( -2.7702219e+02, -1.2156319e+02, -3.8897654e+02);
expectedForces[465] = Vec3( 3.6277432e+02, -7.0422679e+02, -8.2487472e+02);
expectedForces[466] = Vec3( -2.3947587e+02, -4.3625964e+00, 4.8716989e+01);
expectedForces[467] = Vec3( -2.6210552e+02, 9.9730213e+01, -2.4465307e+02);
expectedForces[468] = Vec3( -4.1344138e+01, -3.8636310e+01, -1.0720610e+01);
expectedForces[469] = Vec3( 2.3928584e+01, -1.3030908e+01, -1.7631168e+01);
expectedForces[470] = Vec3( -1.1873594e+02, -3.3905287e+00, -8.4575994e+01);
expectedForces[471] = Vec3( 4.3384846e+02, -4.8660929e+02, -2.4015737e+02);
expectedForces[472] = Vec3( 3.8974922e+01, 2.4401913e+02, -1.2060132e+02);
expectedForces[473] = Vec3( -4.2239647e+02, -8.6924630e+01, 5.7884013e+02);
expectedForces[474] = Vec3( 1.7222431e+02, -1.9292167e+01, 4.4184770e+01);
expectedForces[475] = Vec3( -4.8871102e+01, 1.8185057e+02, -1.3144294e+02);
expectedForces[476] = Vec3( -1.1467881e+02, -1.8387284e+02, -2.6935761e+01);
expectedForces[477] = Vec3( 4.4415601e+02, -8.6415426e+02, -2.2765803e+02);
expectedForces[478] = Vec3( 2.0893474e+02, 1.3529112e+02, 2.4108004e+02);
expectedForces[479] = Vec3( -1.2802570e+01, -4.7089261e+00, -7.0024810e+00);
expectedForces[480] = Vec3( -1.0878354e+02, 4.5030357e+02, -3.9086153e+02);
expectedForces[481] = Vec3( -3.7659745e+01, -4.9295745e+01, -6.0028516e+01);
expectedForces[482] = Vec3( 1.8851809e+02, -1.6863914e+02, 1.2031505e+02);
expectedForces[483] = Vec3( 2.2040686e+02, -1.1953187e+03, 2.9106238e+02);
expectedForces[484] = Vec3( -1.1642847e+01, 5.6739977e+01, 3.7532413e+00);
expectedForces[485] = Vec3( 3.5013234e+00, 2.8236323e+01, -1.1738866e+01);
expectedForces[486] = Vec3( -2.0051506e+03, -5.3138994e+02, 4.0428126e+02);
expectedForces[487] = Vec3( 1.6887843e+02, 1.1687735e+02, -9.6232177e+01);
expectedForces[488] = Vec3( 2.5030722e+02, -3.6662537e+02, -5.8595505e+01);
expectedForces[489] = Vec3( -1.5924273e+01, -2.1761920e+02, -3.4885425e+01);
expectedForces[490] = Vec3( 1.0423157e+02, 4.0767827e+01, 1.4036192e+02);
expectedForces[491] = Vec3( 5.0090776e+02, -5.0455702e+01, -4.2524815e+02);
expectedForces[492] = Vec3( 3.8037844e+02, 5.7460724e+02, 2.1243310e+02);
expectedForces[493] = Vec3( -1.1487653e+02, 3.3550952e+01, -5.7050397e+01);
expectedForces[494] = Vec3( 1.8425697e+02, -2.7223857e+02, -2.9384020e+01);
expectedForces[495] = Vec3( -1.1115514e+02, -4.4519957e+02, -3.3628896e+02);
expectedForces[496] = Vec3( 3.8865823e+02, -2.1372852e+02, -7.8979988e+02);
expectedForces[497] = Vec3( -3.1740258e+02, 4.4824683e+02, -5.0382680e+02);
expectedForces[498] = Vec3( 1.5521684e+02, -1.5278429e+02, -1.8418006e+02);
expectedForces[499] = Vec3( -2.2213191e+01, 7.1015095e+00, 1.0308820e+01);
expectedForces[500] = Vec3( 3.0011560e+01, 2.4584541e+02, -5.3231694e+02);
expectedForces[501] = Vec3( -8.4865171e+02, -2.0279022e+02, -6.8435095e+02);
expectedForces[502] = Vec3( 7.0477549e+00, 2.7626774e+01, -1.6246047e+01);
expectedForces[503] = Vec3( -7.1309648e+01, -1.6054218e+02, -3.1621746e+01);
expectedForces[504] = Vec3( 3.6317856e+02, 1.9055487e+02, 3.9196046e+01);
expectedForces[505] = Vec3( 1.4643265e+02, -1.2295335e+03, -2.2268806e+01);
expectedForces[506] = Vec3( -3.6638240e+02, -6.5310612e+00, -6.8077013e+02);
expectedForces[507] = Vec3( 1.9107813e+02, -6.2176534e+02, 5.1826941e+02);
expectedForces[508] = Vec3( 1.7226933e+02, -3.8939126e+02, -7.4174355e+02);
expectedForces[509] = Vec3( 1.3541890e+02, 4.1350561e+02, -2.6155396e+02);
expectedForces[510] = Vec3( 1.6452609e+02, -4.1963597e+02, 1.6322800e+02);
expectedForces[511] = Vec3( 9.1248387e+01, -1.3380408e+01, -5.1326806e+02);
expectedForces[512] = Vec3( 1.2420564e+02, 8.9492432e+02, 2.8660661e+02);
expectedForces[513] = Vec3( 4.5609859e+02, 3.4252036e+01, -2.3830457e+02);
expectedForces[514] = Vec3( -8.8282131e+01, -1.4512876e+02, -4.5703642e+01);
expectedForces[515] = Vec3( -6.9194714e+01, 5.5053415e+02, -3.9527911e+02);
expectedForces[516] = Vec3( -1.5570798e+02, 4.1650792e-02, 3.0224667e+02);
expectedForces[517] = Vec3( 9.2007640e+01, 3.6378499e+02, -2.2069415e+01);
expectedForces[518] = Vec3( 2.7996922e+02, -2.0932322e+02, 6.2987796e+01);
expectedForces[519] = Vec3( -7.4985282e+01, 1.3508916e+02, 1.1453750e+02);
expectedForces[520] = Vec3( 1.2149786e+01, 4.2161047e+02, -2.9521571e+02);
expectedForces[521] = Vec3( 1.9419524e+01, -8.6619683e+01, -9.4040609e+01);
expectedForces[522] = Vec3( 3.5495800e+01, 6.4028894e+01, 1.2320699e+02);
expectedForces[523] = Vec3( -5.6501302e+02, -1.2497462e+02, 8.1633096e+02);
expectedForces[524] = Vec3( -3.1775230e+02, 1.6467221e+02, -4.8242287e+01);
expectedForces[525] = Vec3( -1.8325245e+02, -1.0751941e+02, 6.2172117e+02);
expectedForces[526] = Vec3( 1.8164299e+00, 8.0654784e-01, -1.4484741e+01);
expectedForces[527] = Vec3( 2.6686986e+00, 1.5933475e+01, -6.8843007e+01);
expectedForces[528] = Vec3( -1.3208642e+02, -1.2281791e+02, 7.8417959e+01);
expectedForces[529] = Vec3( -4.8078193e+01, -1.5140963e+02, 8.3605002e+01);
expectedForces[530] = Vec3( 8.5925332e+01, 1.9959621e+01, -5.9034655e+01);
expectedForces[531] = Vec3( -3.1311626e+00, -3.4009931e+01, -1.5895685e+02);
expectedForces[532] = Vec3( -9.9694666e+01, 1.0296874e+00, 1.0482739e+02);
expectedForces[533] = Vec3( 2.8954747e+02, 1.2018666e+02, 2.2155006e+02);
expectedForces[534] = Vec3( 3.2588176e+02, 3.6622498e+01, 3.5801460e+02);
expectedForces[535] = Vec3( -6.5985617e+01, -3.5501709e+02, 6.8149810e+01);
expectedForces[536] = Vec3( -4.7632753e+02, 2.7936656e+02, 1.5548558e+02);
expectedForces[537] = Vec3( 4.7724904e+02, 2.1647106e+02, 1.2003317e+02);
expectedForces[538] = Vec3( -1.6225405e+02, 1.4264998e+02, -1.0113321e+02);
expectedForces[539] = Vec3( -3.2540487e+01, -7.5643223e+01, 1.6054148e+01);
expectedForces[540] = Vec3( 4.3311991e+02, 5.8082595e+02, 1.9354276e+02);
expectedForces[541] = Vec3( -3.4924430e+02, -7.0056069e+01, 1.0274560e+02);
expectedForces[542] = Vec3( 1.9441645e+02, -2.0017354e+02, -2.3280717e+02);
expectedForces[543] = Vec3( -4.1530380e+01, -5.6394351e+02, 2.4472509e+02);
expectedForces[544] = Vec3( -1.6193396e+01, -8.0431396e+01, -2.9094018e+02);
expectedForces[545] = Vec3( -1.9414773e+01, 4.6180982e+01, 3.3123072e+01);
expectedForces[546] = Vec3( -3.9314039e+02, -3.9874866e+02, 4.5308571e+02);
expectedForces[547] = Vec3( -7.1897482e+01, -1.1940445e+02, -2.7405931e+02);
expectedForces[548] = Vec3( 3.0646396e+02, 6.1235747e+01, -1.5253270e+02);
expectedForces[549] = Vec3( -3.2480464e+02, 4.3056561e+02, 3.2532485e+01);
expectedForces[550] = Vec3( 1.2818655e+02, 7.4294994e-01, -5.7650521e+00);
expectedForces[551] = Vec3( -1.7481437e+02, -2.6203225e+02, -9.6793481e+01);
expectedForces[552] = Vec3( 1.9259110e+02, 3.0171883e+02, 5.2403235e+02);
expectedForces[553] = Vec3( -7.8132123e+01, -7.6569340e+00, -1.1140240e+02);
expectedForces[554] = Vec3( -5.2504673e+02, -4.3700574e+02, 4.3321261e+02);
expectedForces[555] = Vec3( -9.9785283e+02, 2.7139143e+02, -4.1723547e+02);
expectedForces[556] = Vec3( 2.7115933e+02, -8.7444541e+01, 1.0745103e+02);
expectedForces[557] = Vec3( 1.4348018e+02, 1.4013343e+02, -4.0305733e+02);
expectedForces[558] = Vec3( 4.9491010e+02, 4.3040089e+02, -3.5558583e+02);
expectedForces[559] = Vec3( -1.8510736e+02, 6.7129731e+01, -2.1324364e+02);
expectedForces[560] = Vec3( 8.4478090e+01, 4.0986269e+01, 4.1401094e+02);
expectedForces[561] = Vec3( 4.4188419e+01, -8.6520108e+02, 6.8555821e+02);
expectedForces[562] = Vec3( -4.5036974e+02, 2.2379481e+02, 6.2457971e+01);
expectedForces[563] = Vec3( 2.4325836e+02, 6.9725116e+01, 3.6266296e+01);
expectedForces[564] = Vec3( 1.5611925e+02, -2.4471023e+02, 4.7857332e+02);
expectedForces[565] = Vec3( -3.5692822e+02, -2.7248961e+02, -1.8165146e+02);
expectedForces[566] = Vec3( 4.3093388e+02, 1.6944839e+02, -4.4177741e+02);
expectedForces[567] = Vec3( 5.2118711e+02, -1.5252783e+02, -1.6964047e+02);
expectedForces[568] = Vec3( 1.3899083e+03, 3.8363654e+02, -6.4623177e+02);
expectedForces[569] = Vec3( -1.4984858e+02, 4.5097170e+01, -5.0257768e+01);
expectedForces[570] = Vec3( -8.1979709e+01, -4.1632909e+01, -5.1367825e+02);
expectedForces[571] = Vec3( -7.8645235e+00, 1.8105470e+01, 9.2902759e+01);
expectedForces[572] = Vec3( 1.2725548e+02, 1.3926229e+02, -4.3752260e+01);
expectedForces[573] = Vec3( -2.7817289e+01, -8.0900345e+01, -4.3178498e+02);
expectedForces[574] = Vec3( 2.2115263e+02, -7.8807799e+01, 8.8367391e+01);
expectedForces[575] = Vec3( -1.2756938e+02, 4.2170937e+02, -6.8418245e+01);
expectedForces[576] = Vec3( 8.8370341e+01, -1.4671130e+02, -5.6211071e+02);
expectedForces[577] = Vec3( 6.7701453e+02, 2.1228010e+02, 2.3047236e+02);
expectedForces[578] = Vec3( -1.2694819e+02, -7.2734890e+00, 1.1007893e+02);
expectedForces[579] = Vec3( -6.8945756e+02, 1.7359485e+02, -2.5607776e+02);
expectedForces[580] = Vec3( 6.7323923e+00, 3.1574487e+02, 5.9741152e+02);
expectedForces[581] = Vec3( 2.1214031e+02, -4.7565197e+01, -9.6896159e+01);
expectedForces[582] = Vec3( -3.4876562e+02, 5.8335489e+01, -1.7058451e+02);
expectedForces[583] = Vec3( -1.6516914e+02, -3.8913162e+02, 5.8832025e+02);
expectedForces[584] = Vec3( 4.7753612e+01, -6.6792213e+01, -4.6492749e+01);
expectedForces[585] = Vec3( -4.7166578e+02, 7.1811831e+02, 7.0620222e+02);
expectedForces[586] = Vec3( -3.0570577e+02, -1.7681907e+02, -2.1227370e+02);
expectedForces[587] = Vec3( 1.8122997e+02, -6.8318737e+01, -3.4853368e+02);
expectedForces[588] = Vec3( 7.5752093e+01, 3.9702196e+02, -9.0196404e+02);
expectedForces[589] = Vec3( 5.1185528e+02, -7.7747186e+02, -3.3969581e+02);
expectedForces[590] = Vec3( -3.1187606e+01, 5.9593198e+01, 7.7918649e+01);
expectedForces[591] = Vec3( 2.2741676e+02, 2.1705631e+02, 3.9920149e+02);
expectedForces[592] = Vec3( 7.0516894e+01, 3.3389665e+02, -6.8443760e+00);
expectedForces[593] = Vec3( -9.9645406e+02, 2.8574127e+02, -8.0946834e+02);
expectedForces[594] = Vec3( 1.0930460e+02, 1.5869363e+03, -4.0704089e+02);
expectedForces[595] = Vec3( -3.0341438e+02, -5.7494385e+00, 2.9655509e+02);
expectedForces[596] = Vec3( 8.7955203e+01, -7.6811348e+01, -6.9558652e+01);
expectedForces[597] = Vec3( -9.4378353e+01, 3.6253070e+02, 9.0703343e-01);
expectedForces[598] = Vec3( -4.7595525e+01, -6.9148379e+02, -4.6737971e+02);
expectedForces[599] = Vec3( 2.2339987e+02, -2.5503335e+02, 2.8552040e+02);
expectedForces[600] = Vec3( 1.0309072e+02, -2.1298204e+02, -4.3393283e+02);
expectedForces[601] = Vec3( -2.4581477e+02, 2.5126386e+02, -1.8679710e+02);
expectedForces[602] = Vec3( 7.7926618e+00, -2.4947558e+01, 1.5962011e+02);
expectedForces[603] = Vec3( 7.0099476e+02, 5.9496129e+01, 2.0314640e+02);
expectedForces[604] = Vec3( -5.2583810e+01, 3.1237489e+01, -4.0902937e+00);
expectedForces[605] = Vec3( -5.4435871e+01, -7.7056693e+01, -1.5137215e+01);
expectedForces[606] = Vec3( -7.8684074e+02, 8.1673860e+02, 5.0192222e+02);
expectedForces[607] = Vec3( 2.9859285e+02, 1.9661708e+02, -1.9940993e+02);
expectedForces[608] = Vec3( -9.9358476e-01, -3.4789219e+02, 1.7693106e+02);
expectedForces[609] = Vec3( 6.7880927e+02, 7.2768533e+01, 1.1973248e+03);
expectedForces[610] = Vec3( -1.2072838e+00, 1.1770157e+02, -8.6765918e+01);
expectedForces[611] = Vec3( -4.3236695e+02, -2.8583002e+02, 1.3459508e+02);
expectedForces[612] = Vec3( -6.1894609e+01, 4.4705141e+02, -2.3264215e+02);
expectedForces[613] = Vec3( -2.6948720e+01, -2.7688230e+01, 4.6300601e+01);
expectedForces[614] = Vec3( 4.3954815e+01, 6.1244278e+01, 1.0727211e+02);
expectedForces[615] = Vec3( -2.2049132e+02, -9.7233594e+01, 8.3807949e+01);
expectedForces[616] = Vec3( 2.8631226e+02, -1.3478640e+02, -5.0675977e+02);
expectedForces[617] = Vec3( -1.1458029e+01, 6.3762007e+01, -4.9643140e+01);
expectedForces[618] = Vec3( 7.7363305e+01, 1.1936816e+02, 3.9692323e+01);
expectedForces[619] = Vec3( -8.4199858e+01, 2.3567494e+02, 7.2885200e+01);
expectedForces[620] = Vec3( -7.4500104e+00, 3.5567340e+00, -2.2676267e+01);
expectedForces[621] = Vec3( -7.9200057e+02, 3.2245192e+01, 1.1829644e+01);
expectedForces[622] = Vec3( 3.9959336e+02, 2.2447865e+02, -3.1413233e+02);
expectedForces[623] = Vec3( 1.5810527e+02, -2.2341997e+02, 2.3388212e+02);
expectedForces[624] = Vec3( -2.9248657e+02, -1.0806250e+03, -6.1268035e+01);
expectedForces[625] = Vec3( 6.5061442e+02, 1.2244756e+02, -1.1976147e+02);
expectedForces[626] = Vec3( -1.7787710e+02, 3.7279354e+02, -3.7911745e+02);
expectedForces[627] = Vec3( 3.7145927e+02, -2.5203732e+02, -2.2889342e+02);
expectedForces[628] = Vec3( 1.9440281e+02, -2.3076142e+02, 7.2945279e+01);
expectedForces[629] = Vec3( -2.3603693e+02, -1.1987203e+02, -1.2000208e+02);
expectedForces[630] = Vec3( -8.4811726e+01, -6.4500846e+02, -5.1257210e+02);
expectedForces[631] = Vec3( -1.6183393e+01, 1.3980655e+01, -2.3189702e+00);
expectedForces[632] = Vec3( 1.3526098e+02, 1.3800365e+02, -9.4360476e+01);
expectedForces[633] = Vec3( 2.0983514e+01, 5.1156494e+02, -4.3526557e+01);
expectedForces[634] = Vec3( -2.8666500e+02, -5.8235691e+02, -8.7425194e+01);
expectedForces[635] = Vec3( -1.7183604e+02, 1.0002944e+01, 6.5855812e+02);
expectedForces[636] = Vec3( -2.1735465e+02, 9.4664675e+02, 8.9132890e+02);
expectedForces[637] = Vec3( 6.3759184e+01, -5.2436201e+02, 1.2455578e+02);
expectedForces[638] = Vec3( 3.2176621e+02, 1.8182348e+02, -4.4863340e+02);
expectedForces[639] = Vec3( -8.4308252e+02, -1.6268681e+02, 5.8113352e+02);
expectedForces[640] = Vec3( 6.1223389e+01, 3.6767423e+02, 5.9071999e+02);
expectedForces[641] = Vec3( 2.2546928e+02, -2.2022805e+02, 8.3027103e+01);
expectedForces[642] = Vec3( -4.0385190e+02, 2.0141033e+02, 2.7296512e+01);
expectedForces[643] = Vec3( 8.4204485e+01, -7.1102294e+01, 5.7642677e+01);
expectedForces[644] = Vec3( 6.1859901e+01, 1.4828523e+02, -2.6764016e+02);
expectedForces[645] = Vec3( -6.7249932e+02, -8.4613525e+01, -3.9792609e+02);
expectedForces[646] = Vec3( 9.9116485e+01, -3.7714583e+01, -5.3966332e+01);
expectedForces[647] = Vec3( 2.0868628e+02, 2.9747206e+02, 3.3931416e+02);
// tolerance is higher here due to interpolation used in setting tapering coefficients;
// if tapering turned off, then absolute difference < 2.0e-05
double tolerance = 5.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
// test sigma/epsilon rules for dispersion correction
if (includeVdwDispersionCorrection) {
std::vector<std::string> sigmaRules;
std::vector<std::string> epsilonRules;
std::vector<double> expectedEnergies;
sigmaRules.push_back("ARITHMETIC");
epsilonRules.push_back("ARITHMETIC");
expectedEnergies.push_back(6.2137988e+03);
sigmaRules.push_back("GEOMETRIC");
epsilonRules.push_back("GEOMETRIC");
expectedEnergies.push_back( 3.6358216e+03);
sigmaRules.push_back("CUBIC-MEAN");
epsilonRules.push_back("HARMONIC");
expectedEnergies.push_back(3.2774624e+03);
for (unsigned int ii = 0; ii < sigmaRules.size(); ii++) {
setupAndGetForcesEnergyVdwWater(sigmaRules[ii], epsilonRules[ii], cutoff, boxDimension, includeVdwDispersionCorrection, forces, energy);
testName = "testVdwWaterWithDispersionCorrection_" + sigmaRules[ii] + '_' + epsilonRules[ii];
ASSERT_EQUAL_TOL_MOD(expectedEnergies[ii], energy, tolerance, testName);
}
}
}
void testTriclinic() {
System system;
system.addParticle(1.0);
system.addParticle(1.0);
Vec3 a(3.1, 0, 0);
Vec3 b(0.4, 3.5, 0);
Vec3 c(-0.1, -0.5, 4.0);
system.setDefaultPeriodicBoxVectors(a, b, c);
LangevinIntegrator integrator(0.0, 0.1, 0.01);
AmoebaVdwForce* vdw = new AmoebaVdwForce();
vdw->setUseDispersionCorrection(false);
vdw->addParticle(0, 0.5, 1.0, 0.0);
vdw->addParticle(1, 0.5, 1.0, 0.0);
vdw->setNonbondedMethod(AmoebaVdwForce::CutoffPeriodic);
const double cutoff = 1.5;
vdw->setCutoff(cutoff);
system.addForce(vdw);
Context context(system, integrator, Platform::getPlatformByName("CUDA"));
vector<Vec3> positions(2);
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
for (int iteration = 0; iteration < 50; iteration++) {
// Generate random positions for the two particles.
positions[0] = a*genrand_real2(sfmt) + b*genrand_real2(sfmt) + c*genrand_real2(sfmt);
positions[1] = a*genrand_real2(sfmt) + b*genrand_real2(sfmt) + c*genrand_real2(sfmt);
context.setPositions(positions);
// Loop over all possible periodic copies and find the nearest one.
Vec3 delta;
double distance2 = 100.0;
for (int i = -1; i < 2; i++)
for (int j = -1; j < 2; j++)
for (int k = -1; k < 2; k++) {
Vec3 d = positions[1]-positions[0]+a*i+b*j+c*k;
if (d.dot(d) < distance2) {
delta = d;
distance2 = d.dot(d);
}
}
double distance = sqrt(distance2);
// See if the energy is correct.
State state = context.getState(State::Energy);
if (distance >= cutoff) {
ASSERT_EQUAL(0.0, state.getPotentialEnergy());
}
else if (distance < 0.9*cutoff) {
const double energy = pow(1.07/(distance+0.07), 7.0)*(1.12/(pow(distance, 7.0)+0.12)-2);
ASSERT_EQUAL_TOL(energy, state.getPotentialEnergy(), TOL);
}
}
}
void testCompareToCustom(AmoebaVdwForce::PotentialFunction potential) {
const int numParticles = 10;
const double cutoff = 1.0;
System system;
AmoebaVdwForce* vdw = new AmoebaVdwForce();
vdw->setNonbondedMethod(AmoebaVdwForce::CutoffPeriodic);
vdw->setCutoff(cutoff);
vdw->setPotentialFunction(potential);
vdw->setSigmaCombiningRule("ARITHMETIC");
vdw->setEpsilonCombiningRule("GEOMETRIC");
vdw->setUseDispersionCorrection(true);
system.addForce(vdw);
CustomNonbondedForce* custom;
if (potential == AmoebaVdwForce::LennardJones)
custom = new CustomNonbondedForce("4*eps*((sigma/r)^12-(sigma/r)^6); sigma=sigma1+sigma2; eps=sqrt(eps1*eps2)");
else
custom = new CustomNonbondedForce("eps*((1.07/(p+0.07))^7 * ((1.12/(p^7+0.12))-2)); p=r/sigma; sigma=sigma1+sigma2; eps=sqrt(eps1*eps2)");
custom->addPerParticleParameter("sigma");
custom->addPerParticleParameter("eps");
custom->setNonbondedMethod(CustomNonbondedForce::CutoffPeriodic);
custom->setCutoffDistance(cutoff);
custom->setUseLongRangeCorrection(true);
custom->setUseSwitchingFunction(true);
custom->setSwitchingDistance(0.9*cutoff);
custom->setForceGroup(1);
system.addForce(custom);
vector<Vec3> positions;
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
for (int i = 0; i < numParticles; i++) {
system.addParticle(1.0);
if (i%2 == 0) {
vdw->addParticle(i, 0.2, 1.0, 0.0);
custom->addParticle({0.2, 1.0});
}
else {
vdw->addParticle(i, 0.25, 0.5, 0.0);
custom->addParticle({0.25, 0.5});
}
positions.push_back(2*Vec3(genrand_real2(sfmt), genrand_real2(sfmt), genrand_real2(sfmt)));
}
LangevinIntegrator integrator(0.0, 0.1, 0.01);
Context context(system, integrator, Platform::getPlatformByName("CUDA"));
context.setPositions(positions);
State state1 = context.getState(State::Energy | State::Forces, true, 1);
State state2 = context.getState(State::Energy | State::Forces, true, 2);
ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-3);
for (int i = 0; i < numParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
}
void testParticleTypes() {
System system;
for (int i = 0; i < 4; i++)
system.addParticle(1.0);
AmoebaVdwForce* vdw = new AmoebaVdwForce();
system.addForce(vdw);
vdw->setPotentialFunction(AmoebaVdwForce::LennardJones);
vdw->setSigmaCombiningRule("ARITHMETIC");
vdw->setEpsilonCombiningRule("GEOMETRIC");
vdw->addParticle(0, 0, 1.0);
vdw->addParticle(1, 2, 1.0);
vdw->addParticle(2, 0, 1.0);
vdw->addParticle(3, 1, 1.0);
vdw->addParticleType(0.3, 1.0);
vdw->addParticleType(0.4, 1.1);
vdw->addParticleType(0.5, 1.2);
vdw->addTypePair(2, 0, 0.6, 1.5);
vector<Vec3> positions;
positions.push_back(Vec3(0, 0, 0));
positions.push_back(Vec3(1, 0, 0));
positions.push_back(Vec3(0, 1, 0));
positions.push_back(Vec3(1, 1, 0));
LangevinIntegrator integrator(0.0, 0.1, 0.01);
Context context(system, integrator, Platform::getPlatformByName("CUDA"));
context.setPositions(positions);
State state = context.getState(State::Energy);
vector<double> r = {1.0, 1.0, sqrt(2.0), sqrt(2.0), 1.0, 1.0};
vector<double> sigma = {0.6, 0.3+0.3, 0.3+0.4, 0.6, 0.5+0.4, 0.3+0.4};
vector<double> epsilon = {1.5, sqrt(1.0*1.0), sqrt(1.0*1.1), 1.5, sqrt(1.1*1.2), sqrt(1.0*1.1)};
double expectedEnergy = 0;
for (int i = 0; i < 6; i++) {
double p = sigma[i]/r[i];
expectedEnergy += 4*epsilon[i]*(pow(p, 12) - pow(p, 6));
}
ASSERT_EQUAL_TOL(expectedEnergy, state.getPotentialEnergy(), 1e-5);
}
int main(int argc, char* argv[]) {
try {
std::cout << "TestCudaAmoebaVdwForce running test..." << std::endl;
registerAmoebaCudaKernelFactories();
if (argc > 1)
Platform::getPlatformByName("CUDA").setPropertyDefaultValue("Precision", std::string(argv[1]));
testVdw();
// tests using two ammonia molecules
// test VDW w/ sigmaRule=CubicMean and epsilonRule=HHG
testVdwAmmoniaCubicMeanHhg();
// test VDW w/ sigmaRule=CubicMean and epsilonRule=HHG
testVdwAmmoniaCubicMeanWH();
// test VDW w/ sigmaRule=Arithmetic and epsilonRule=Arithmetic
testVdwAmmoniaArithmeticArithmetic();
// test VDW w/ sigmaRule=Geometric and epsilonRule=Geometric
testVdwAmmoniaGeometricGeometric();
// test VDW w/ sigmaRule=CubicMean and epsilonRule=Harmonic
testVdwAmmoniaCubicMeanHarmonic();
// test w/ cutoff=0.25 nm; single ixn between two particles (0 and 6); force nonzero on
// particle 4 due to reduction applied to NH
// the distance between 0 and 6 is ~ 0.235 so the ixn is in the tapered region
testVdwTaper();
// test PBC
testVdwPBC();
// tests based on box of water
int includeVdwDispersionCorrection = 0;
testVdwWater(includeVdwDispersionCorrection);
// includes tests for various combinations of sigma/epsilon rules
// when computing vdw dispersion correction
includeVdwDispersionCorrection = 1;
testVdwWater(includeVdwDispersionCorrection);
// test triclinic boxes
testTriclinic();
// Compare to an equivalent CustomNonbondedForce.
testCompareToCustom(AmoebaVdwForce::Buffered147);
testCompareToCustom(AmoebaVdwForce::LennardJones);
// Test specifying parameters by particle type.
testParticleTypes();
// Set lambda and the softcore power (n) to any values, while softcore alpha set to 0.
// The energy and forces are equal to scaling those from testVdwAmmoniaCubicMeanHhg by lambda^n;
int n = 5;
double alpha = 0.0;
double lambda = 0.9;
AmoebaVdwForce::AlchemicalMethod method = AmoebaVdwForce::Annihilate;
testVdwAlchemical(n, alpha, lambda, method);
// Test the Decouple alchemical method.
lambda = 0.5;
method = AmoebaVdwForce::Decouple;
testVdwAlchemical(n, alpha, lambda, method);
// Test alpha > 0.
// This requires lambda = 0, since the energy and forces are not simply scaled by lambda^n.
lambda = 0.0;
alpha = 0.7;
testVdwAlchemical(n, alpha, lambda, method);
} catch(const std::exception& e) {
std::cout << "exception: " << e.what() << std::endl;
std::cout << "FAIL - ERROR. Test failed." << std::endl;
return 1;
}
std::cout << "Done" << std::endl;
return 0;
}
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2019 Stanford University and the Authors. * * Portions copyright (c) 2021 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -29,1545 +29,7 @@ ...@@ -29,1545 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
/** #include "CudaAmoebaTests.h"
* This tests the CUDA implementation of HippoNonbondedForce. #include "TestHippoNonbondedForce.h"
*/
#include "openmm/internal/AssertionUtilities.h" void runPlatformTests() {}
#include "openmm/Context.h"
#include "OpenMMAmoeba.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
extern "C" void registerAmoebaCudaKernelFactories();
double forceTol, energyTol, consistencyTol;
void buildWaterSystem(System& system, int numWaters, HippoNonbondedForce* hippo) {
system.addForce(hippo);
hippo->setExtrapolationCoefficients({0.042, 0.635, 0.414});
for (int mol = 0; mol < numWaters; mol++) {
system.addParticle(15.995);
system.addParticle(1.008);
system.addParticle(1.008);
double bohr = 0.52917720859;
double ds = 0.1*bohr;
double qs = 0.01*bohr*bohr/3.0;
double c6s = sqrt(4.184)*0.001;
double ps = sqrt(4.184*0.1);
hippo->addParticle(-0.38280, {0.0, 0.0, ds*0.05477}, {qs*0.69866, 0.0, 0.0, 0.0, qs*-0.60471, 0.0, 0.0, 0.0, qs*-0.09395}, 6.0,
10*4.7075, 4.184*1326.0, 10*40.0, c6s*18.7737, ps*2.7104, -2.4233, 10*4.3097,
0.001*0.795, HippoNonbondedForce::Bisector, 3*mol+1, 3*mol+2, -1);
hippo->addParticle(0.19140, {0.0, 0.0, ds*-0.20097}, {qs*0.03881, 0.0, 0.0, 0.0, qs*0.02214, 0.0, 0.0, 0.0, qs*-0.06095}, 1.0,
10*4.7909, 0.0, 10*3.5582, c6s*4.5670, ps*2.0037, -0.8086, 10*4.6450,
0.001*0.341, HippoNonbondedForce::ZThenX, 3*mol, 3*mol+2, -1);
hippo->addParticle(0.19140, {0.0, 0.0, ds*-0.20097}, {qs*0.03881, 0.0, 0.0, 0.0, qs*0.02214, 0.0, 0.0, 0.0, qs*-0.06095}, 1.0,
10*4.7909, 0.0, 10*3.5582, c6s*4.5670, ps*2.0037, -0.8086, 10*4.6450,
0.001*0.341, HippoNonbondedForce::ZThenX, 3*mol, 3*mol+1, -1);
hippo->addException(3*mol, 3*mol+1, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0);
hippo->addException(3*mol, 3*mol+2, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0);
hippo->addException(3*mol+1, 3*mol+2, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0);
}
}
void checkForceEnergyConsistency(Context& context) {
// Find the direction and magnitude of the force.
State state = context.getState(State::Positions | State::Forces | State::Energy);
int numParticles = context.getSystem().getNumParticles();
double norm = 0.0;
for (int i = 0; i < numParticles; ++i) {
Vec3 f = state.getForces()[i];
norm += f[0]*f[0] + f[1]*f[1] + f[2]*f[2];
}
norm = std::sqrt(norm);
// Take a small step in the direction of the force and see whether the potential energy changes by the expected amount.
const double delta = 1e-3;
double step = 0.5*delta/norm;
vector<Vec3> positions2(numParticles), positions3(numParticles);
for (int i = 0; i < numParticles; ++i) {
Vec3 p = state.getPositions()[i];
Vec3 f = state.getForces()[i];
positions2[i] = p-f*step;
positions3[i] = p+f*step;
}
context.setPositions(positions2);
State state2 = context.getState(State::Energy);
context.setPositions(positions3);
State state3 = context.getState(State::Energy);
ASSERT_EQUAL_TOL(state2.getPotentialEnergy()-state3.getPotentialEnergy(), norm*delta, consistencyTol)
}
void testWaterDimer() {
System system;
HippoNonbondedForce* hippo = new HippoNonbondedForce();
buildWaterSystem(system, 2, hippo);
VerletIntegrator integrator(0.001);
Context context(system, integrator, Platform::getPlatformByName("CUDA"));
vector<Vec3> positions = {
0.1*Vec3(1.505434, 0.0, -0.065656),
0.1*Vec3(0.553912, 0.0, 0.057710),
0.1*Vec3(1.907155, 0.0, 0.801980),
0.1*Vec3(-1.436029, 0.0, 0.060505),
0.1*Vec3(-1.781197, 0.772272, -0.388976),
0.1*Vec3(-1.781197, -0.772272, -0.388976)
};
context.setPositions(positions);
State state = context.getState(State::Energy | State::Forces);
// Compare the forces and energy to reference values computed with Tinker.
ASSERT_EQUAL_TOL(-18.393623712669680, state.getPotentialEnergy(), energyTol);
vector<Vec3> expectedForces = {
Vec3(-162.94090034728887, 0.0, 35.06615691195519),
Vec3(127.50063696213348, 0.0, -46.51857483822334),
Vec3(39.59601328153432, 0.0, 11.805509637931072),
Vec3(-73.52341534248339, 0.0, -92.08855312751808),
Vec3(34.68383272305204, -26.35219958830841, 45.867730707927564),
Vec3(34.68383272305204, 26.35219958830841, 45.867730707927564),
};
for (int i = 0; i < system.getNumParticles(); i++)
ASSERT_EQUAL_VEC(-expectedForces[i], state.getForces()[i], forceTol);
// Compare the permanent dipoles to reference values computed with Tinker.
vector<Vec3> expectedLabDipoles = {
Vec3(-1.3999971343167967e-3, 0.0, 2.5377493339976591e-3),
Vec3(-1.0546602554698980e-2, 0.0, 1.3673800193405874e-3),
Vec3(4.4683063920526751e-3, 0.0, 9.6506368469037353e-3),
Vec3(-1.7652415043849052e-3, 0.0, -2.2987140077655862e-3),
Vec3(-3.8321399176713630e-3, 8.5739534328208283e-3, -4.9902484654859164e-3),
Vec3(-3.8321399176713630e-3, -8.5739534328208283e-3, -4.9902484654859164e-3)
};
vector<Vec3> labDipoles;
hippo->getLabFramePermanentDipoles(context, labDipoles);
for (int i = 0; i < system.getNumParticles(); i++)
ASSERT_EQUAL_VEC(expectedLabDipoles[i], labDipoles[i], 1e-5);
// Compare the induced dipoles to reference values computed with Tinker.
vector<Vec3> expectedInducedDipoles = {
Vec3(-2.6946897397455059e-3, 0.0, 5.7283370317562626e-4),
Vec3(-3.4687164828218306e-3, 0.0, 2.3558084682622801e-4),
Vec3(-8.3759103839743578e-4, 0.0, -4.0453541836814088e-4),
Vec3(-4.7635598636156719e-3, 0.0, -6.2133742026147971e-4),
Vec3(-6.3777660942845697e-4, 5.2439508203868156e-4, -4.3219965383009991e-4),
Vec3(-6.3777660942845697e-4, -5.2439508203868156e-4, -4.3219965383009991e-4)
};
vector<Vec3> inducedDipoles;
hippo->getInducedDipoles(context, inducedDipoles);
for (int i = 0; i < system.getNumParticles(); i++)
ASSERT_EQUAL_VEC(expectedInducedDipoles[i], inducedDipoles[i], 1e-5);
// Check for consistency between forces and energy.
checkForceEnergyConsistency(context);
}
void testWaterBox() {
System system;
HippoNonbondedForce* hippo = new HippoNonbondedForce();
buildWaterSystem(system, 216, hippo);
system.setDefaultPeriodicBoxVectors(Vec3(1.8643, 0, 0), Vec3(0, 1.8643, 0), Vec3(0, 0, 1.8643));
hippo->setNonbondedMethod(HippoNonbondedForce::PME);
hippo->setCutoffDistance(0.7);
hippo->setSwitchingDistance(0.6);
hippo->setPMEParameters(3.85037, 24, 24, 24);
hippo->setDPMEParameters(3.85037, 20, 20, 20);
VerletIntegrator integrator(0.001);
Context context(system, integrator, Platform::getPlatformByName("CUDA"));
double alpha;
int nx, ny, nz;
hippo->getPMEParametersInContext(context, alpha, nx, ny, nz);
ASSERT_EQUAL_TOL(alpha, 3.85037, 1e-5);
ASSERT_EQUAL(24, nx);
ASSERT_EQUAL(24, ny);
ASSERT_EQUAL(24, nz);
hippo->getDPMEParametersInContext(context, alpha, nx, ny, nz);
ASSERT_EQUAL_TOL(alpha, 3.85037, 1e-5);
ASSERT_EQUAL(20, nx);
ASSERT_EQUAL(20, ny);
ASSERT_EQUAL(20, nz);
vector<Vec3> positions = {
Vec3(0.8679662000000001, 0.7087692, -0.0696862),
Vec3(0.7809455000000001, 0.6755792, -0.03822590000000001),
Vec3(0.8722232000000001, 0.6814243000000001, -0.1617561),
Vec3(-0.0117313, 0.8244446999999999, 0.6837616),
Vec3(0.021689200000000002, 0.7895445, 0.6050027),
Vec3(0.0444268, 0.7826013, 0.7530196),
Vec3(0.8379057, -0.0092611, 0.6814631000000001),
Vec3(0.9340423, 0.0098069, 0.6734062000000001),
Vec3(0.7939619000000001, 0.0573676, 0.6269838000000001),
Vec3(0.6589952000000001, 0.1844323, -0.6923167000000001),
Vec3(0.5885429000000001, 0.2402305, -0.6717934),
Vec3(0.6181533, 0.10627470000000001, -0.7273678000000001),
Vec3(0.7146600000000001, 0.5753582, 0.2331517),
Vec3(0.6368123, 0.6126035000000001, 0.2862678),
Vec3(0.7025018000000001, 0.6294645000000001, 0.15181960000000003),
Vec3(-0.24265810000000002, -0.8504195, -0.25048339999999997),
Vec3(-0.16920630000000003, -0.8368252, -0.3058292),
Vec3(-0.27932070000000003, -0.7602469000000001, -0.2403097),
Vec3(-0.8038375000000001, -0.3605589, 0.23036910000000002),
Vec3(-0.8113753000000001, -0.42481270000000004, 0.30184940000000005),
Vec3(-0.7619392, -0.2863004, 0.2709622),
Vec3(-0.1480631, 0.8244085000000001, -0.8272214999999999),
Vec3(-0.2090204, 0.8687978, -0.7676996),
Vec3(-0.0700878, 0.8823325000000001, -0.8322213),
Vec3(-0.37419620000000003, -0.277783, -0.2326319),
Vec3(-0.4620456, -0.2444778, -0.23905189999999998),
Vec3(-0.37289210000000006, -0.3160952, -0.1433101),
Vec3(-0.6467812000000001, -0.5265942, 0.0408263),
Vec3(-0.6585076000000001, -0.4796537, -0.0413008),
Vec3(-0.7021252, -0.4752640000000001, 0.10079579999999999),
Vec3(0.9273577, 0.5342431000000001, 0.405546),
Vec3(0.8645939, 0.54665, 0.4837640000000001),
Vec3(0.8741774, 0.5686149, 0.330282),
Vec3(0.183016, 0.42767310000000003, -0.6993499000000001),
Vec3(0.17032750000000002, 0.5223773, -0.6703852000000001),
Vec3(0.24081130000000003, 0.38534470000000004, -0.6383339000000001),
Vec3(0.1964382, 0.6832988000000001, 0.8373101000000001),
Vec3(0.24961350000000004, 0.7215781, 0.9056298),
Vec3(0.18112830000000002, 0.5905846, 0.8573539000000001),
Vec3(0.5405568, 0.43889940000000005, 0.7932737000000001),
Vec3(0.553738, 0.3438955, 0.7781311),
Vec3(0.47551560000000004, 0.4734908, 0.7290617),
Vec3(0.32299980000000006, 0.29284170000000004, -0.109065),
Vec3(0.39310900000000004, 0.3198265, -0.1702769),
Vec3(0.30044380000000004, 0.37089690000000003, -0.0493266),
Vec3(0.74624, 0.5262829, 0.613117),
Vec3(0.8025650000000001, 0.5588493, 0.688177),
Vec3(0.6935076, 0.4455766, 0.6325405000000001),
Vec3(-0.8864042, 0.7023845, -0.6659632000000001),
Vec3(-0.8370939000000001, 0.6372557, -0.7141895),
Vec3(-0.9489800000000002, 0.7315873, -0.7293125),
Vec3(-0.45262990000000003, 0.3549989, 0.8030031),
Vec3(-0.516977, 0.42241270000000003, 0.7731323),
Vec3(-0.42620959999999997, 0.3801892, 0.8884875),
Vec3(0.48232860000000005, -0.1386218, 0.40384640000000005),
Vec3(0.5493155, -0.0669965, 0.4013081),
Vec3(0.4187463, -0.1101832, 0.33384330000000006),
Vec3(-0.215115, -0.201706, -0.8593685000000001),
Vec3(-0.24757090000000004, -0.2320356, -0.7783564000000001),
Vec3(-0.2650484, -0.2434614, -0.9307384000000001),
Vec3(0.1944893, 0.49332260000000006, 0.049791),
Vec3(0.25532210000000005, 0.5263352, 0.1205303),
Vec3(0.2082534, 0.5590999, -0.020217100000000002),
Vec3(-0.6827006, -0.5285917000000001, -0.2371899),
Vec3(-0.7405873000000001, -0.6022738000000001, -0.2075913),
Vec3(-0.6398443, -0.5453726, -0.3235054),
Vec3(-0.8538047000000001, -0.7577917000000001, -0.1688532),
Vec3(-0.8075591, -0.844826, -0.15134550000000002),
Vec3(-0.9389507, -0.7836271, -0.20518350000000002),
Vec3(-0.6916556, -0.1100882, -0.5168782000000001),
Vec3(-0.6365888000000001, -0.1659366, -0.5746209999999999),
Vec3(-0.6538885, -0.024937400000000002, -0.5325993000000001),
Vec3(0.6330290000000001, -0.9323893000000001, -0.641663),
Vec3(0.7026026000000001, -0.9680578000000001, -0.7007727),
Vec3(0.6812488000000001, -0.8683594, -0.5925798999999999),
Vec3(-0.24243450000000002, -0.5918126, 0.2701855),
Vec3(-0.1613829, -0.5486394, 0.2503024),
Vec3(-0.31447970000000003, -0.5307275, 0.2618121),
Vec3(0.0637202, -0.6080457, 0.5849135000000001),
Vec3(0.08923120000000001, -0.6092342000000001, 0.4907709),
Vec3(-0.0339074, -0.5838972, 0.5853292),
Vec3(0.5199216, -0.22649180000000002, -0.0138343),
Vec3(0.5802838, -0.2788698, -0.06975360000000001),
Vec3(0.567034, -0.1679393, 0.0462296),
Vec3(0.0510145, 0.7629450000000001, 0.40545000000000003),
Vec3(-0.007113500000000001, 0.8146563000000001, 0.3452959),
Vec3(0.14649620000000002, 0.7740819000000001, 0.36691720000000005),
Vec3(0.3146724, 0.8895843, 0.6526257000000001),
Vec3(0.3506091, 0.8599906000000002, 0.7352942),
Vec3(0.21457290000000004, 0.8929622, 0.6682029),
Vec3(0.7308541000000001, -0.8339335000000001, -0.2471342),
Vec3(0.6562127000000001, -0.8180601, -0.30628030000000006),
Vec3(0.6993025, -0.8364954, -0.1531235),
Vec3(-0.7530792000000001, 0.1069683, 0.4989387),
Vec3(-0.7565406000000001, 0.19714220000000002, 0.4648636),
Vec3(-0.793825, 0.0433547, 0.43702660000000004),
Vec3(0.4452035000000001, 0.2700609, -0.5437815),
Vec3(0.46033260000000004, 0.3058652, -0.45515900000000004),
Vec3(0.43864530000000007, 0.1737004, -0.5180418999999999),
Vec3(0.8427922000000001, -0.8619286000000002, 0.17846910000000002),
Vec3(0.8340498000000001, -0.8005342000000001, 0.25362250000000003),
Vec3(0.849672, -0.9530562, 0.2174667),
Vec3(-0.8109456, 0.175383, -0.3096997),
Vec3(-0.7245287, 0.1827177, -0.27214170000000004),
Vec3(-0.8082178000000001, 0.1783171, -0.40593290000000004),
Vec3(0.27769330000000003, -0.5701955, 0.7748213),
Vec3(0.3287974, -0.5069688, 0.7233816000000001),
Vec3(0.19870410000000002, -0.5817355000000001, 0.7200131000000001),
Vec3(0.36351710000000004, -0.6953519, 0.5339628000000001),
Vec3(0.33538510000000005, -0.7592789, 0.6031367000000001),
Vec3(0.2875801, -0.6787975, 0.4740576),
Vec3(0.6888027000000001, -0.41690230000000006, -0.180019),
Vec3(0.7559735000000001, -0.4813701, -0.2004669),
Vec3(0.6603805, -0.3759237, -0.2626496),
Vec3(-0.4470837000000001, -0.41056400000000004, 0.3415362),
Vec3(-0.4991607, -0.3358538, 0.31409560000000003),
Vec3(-0.4791764, -0.43922140000000004, 0.42543870000000006),
Vec3(0.8282263000000001, -0.0462068, -0.2560579),
Vec3(0.8776769, -0.1293641, -0.23359450000000004),
Vec3(0.8760297, 0.038481600000000005, -0.2651128),
Vec3(0.4737236, 0.161643, 0.49011150000000003),
Vec3(0.3969692, 0.21683680000000002, 0.5152631000000001),
Vec3(0.5184651, 0.2148403, 0.4154746),
Vec3(-0.3497332, -0.5781436000000001, -0.22027130000000003),
Vec3(-0.4038857, -0.5773824000000001, -0.138168),
Vec3(-0.415297, -0.6012265000000001, -0.2829379),
Vec3(-0.2863989, -0.025933400000000002, -0.1857006),
Vec3(-0.2132201, -0.0027953, -0.1174211),
Vec3(-0.2873625, -0.12244250000000001, -0.18742530000000002),
Vec3(0.11383000000000001, 0.11331000000000001, -0.2085899),
Vec3(0.19655060000000002, 0.150352, -0.1725316),
Vec3(0.0420521, 0.15344400000000002, -0.1551356),
Vec3(-0.05613280000000001, 0.4590705, -0.2780017),
Vec3(-0.0061173, 0.39193560000000005, -0.32941280000000006),
Vec3(-0.0082763, 0.4733898, -0.19556020000000002),
Vec3(-0.6423002000000001, -0.17052040000000002, -0.2528225),
Vec3(-0.7233989000000001, -0.1949552, -0.1975418),
Vec3(-0.6678416, -0.1321413, -0.33512780000000003),
Vec3(-0.27721, 0.25522100000000003, -0.0672282),
Vec3(-0.29074890000000003, 0.34835520000000003, -0.0385605),
Vec3(-0.2977127, 0.2592348, -0.163582),
Vec3(0.6708678, -0.4852016, -0.837928),
Vec3(0.6593474, -0.5094964000000001, -0.7447187),
Vec3(0.6582524000000001, -0.5591596, -0.8966502000000001),
Vec3(-0.8497001, -0.0440284, 0.2803721),
Vec3(-0.8422350000000001, 0.0331961, 0.2183451),
Vec3(-0.9377295000000001, -0.07561600000000002, 0.2677026),
Vec3(0.2975383, -0.08949700000000001, 0.6060783000000001),
Vec3(0.2093991, -0.09957, 0.5670129),
Vec3(0.34588320000000006, -0.07592480000000001, 0.5263958),
Vec3(-0.6085023, -0.16296200000000002, 0.7970284000000001),
Vec3(-0.6685848000000001, -0.23918300000000003, 0.7820849000000001),
Vec3(-0.6177296000000001, -0.11905840000000001, 0.8835912000000001),
Vec3(-0.37635230000000003, -0.3356777, 0.8285436000000002),
Vec3(-0.46606500000000006, -0.3029414, 0.8406662000000001),
Vec3(-0.3411834, -0.31789470000000003, 0.7431180000000001),
Vec3(-0.110012, -0.0320162, 0.0375372),
Vec3(-0.0527013, -0.10121830000000001, 0.0128652),
Vec3(-0.0673226, 0.028855900000000004, 0.0934677),
Vec3(0.09102090000000002, -0.8271801999999999, 0.14114290000000002),
Vec3(0.0158544, -0.8759532000000001, 0.18708950000000002),
Vec3(0.0565924, -0.7546113000000001, 0.0944383),
Vec3(0.1554065, -0.6468033000000001, 0.3310872),
Vec3(0.1362455, -0.7162802, 0.27223400000000003),
Vec3(0.16162330000000003, -0.5622409, 0.28728539999999997),
Vec3(0.054312700000000005, -0.1388652, 0.4886094),
Vec3(0.011032, -0.0665826, 0.5311239),
Vec3(0.04203660000000001, -0.22163670000000002, 0.5267301),
Vec3(0.1100526, 0.10194900000000001, -0.9255318000000001),
Vec3(0.1460815, 0.0575286, -0.8484128000000001),
Vec3(0.0265613, 0.0594128, -0.9297750000000001),
Vec3(-0.18423480000000003, 0.2327827, -0.5355326),
Vec3(-0.1572941, 0.2573139, -0.6288125),
Vec3(-0.22166790000000003, 0.14399340000000002, -0.5361006),
Vec3(0.2452307, -0.2814686, -0.6448759000000001),
Vec3(0.2862295, -0.3091668, -0.5589336),
Vec3(0.29139200000000004, -0.3262923, -0.7181510000000001),
Vec3(-0.2207998, -0.31120070000000005, 0.5945795),
Vec3(-0.1262203, -0.31253390000000003, 0.6205467),
Vec3(-0.22282690000000002, -0.2421858, 0.5220629),
Vec3(0.5845471, 0.5020556, -0.6836491),
Vec3(0.5557986, 0.5913737, -0.6753889000000001),
Vec3(0.5089998, 0.4459153, -0.6661079000000001),
Vec3(-0.34216430000000003, 0.4865553, 0.0731755),
Vec3(-0.3965419, 0.44584520000000005, 0.1478214),
Vec3(-0.3973445, 0.49583380000000005, -0.004443),
Vec3(-0.23029500000000003, -0.2349717, 0.2112168),
Vec3(-0.25764380000000003, -0.1873492, 0.2873191),
Vec3(-0.1882868, -0.1715106, 0.15037820000000002),
Vec3(0.030588500000000005, 0.4878766, 0.3791182),
Vec3(0.0299338, 0.5855407, 0.40975780000000006),
Vec3(0.1169911, 0.4563497, 0.4030616),
Vec3(0.2925008, -0.36648450000000005, -0.36074500000000004),
Vec3(0.3015896, -0.39166180000000006, -0.2644267),
Vec3(0.2353923, -0.28894590000000003, -0.35182840000000004),
Vec3(0.1111505, -0.40702550000000004, -0.9085692999999999),
Vec3(0.20849050000000002, -0.4227348, -0.9180249),
Vec3(0.0897072, -0.49022180000000004, -0.8740523),
Vec3(-0.49929290000000004, -0.1974219, -0.7099668000000001),
Vec3(-0.5173269, -0.11863090000000001, -0.7673625000000001),
Vec3(-0.5070893, -0.2753273, -0.7658821),
Vec3(0.4730983, 0.147842, 0.0720986),
Vec3(0.4271686, 0.19882650000000002, 0.0034225),
Vec3(0.41174130000000003, 0.0788607, 0.10618179999999999),
Vec3(0.14215830000000002, -0.0176666, -0.6729105),
Vec3(0.121766, 0.0394331, -0.5978213),
Vec3(0.19484440000000003, -0.08779880000000001, -0.6400659000000001),
Vec3(-0.7093223000000001, -0.8541193, 0.4116187),
Vec3(-0.7074252000000001, -0.8047477000000001, 0.3242159),
Vec3(-0.6153142, -0.8537148000000001, 0.445555),
Vec3(0.838254, -0.6460958, 0.3765735),
Vec3(0.9258625, -0.6141972, 0.4060763),
Vec3(0.7637364, -0.621791, 0.44078520000000004),
Vec3(-0.4320241, 0.40371370000000006, 0.32970920000000004),
Vec3(-0.3750151, 0.4141786, 0.41054700000000005),
Vec3(-0.5172925, 0.4455578, 0.34889060000000005),
Vec3(0.5581877000000001, 0.1781994, 0.7505132),
Vec3(0.5017196, 0.1139584, 0.8120950000000001),
Vec3(0.5330781, 0.15912170000000003, 0.6595286),
Vec3(-0.0734443, 0.1125031, 0.48846660000000003),
Vec3(-0.0239224, 0.1540322, 0.41420700000000005),
Vec3(-0.0961628, 0.1783437, 0.5554548),
Vec3(0.6831005000000001, -0.924997, 0.4497165),
Vec3(0.6836746, -0.9068011, 0.5427145999999999),
Vec3(0.7668067000000001, -0.965251, 0.42499570000000003),
Vec3(0.2714055, -0.36775810000000003, 0.1962003),
Vec3(0.33334320000000006, -0.3851775, 0.266354),
Vec3(0.3095021, -0.3978526, 0.1102566),
Vec3(-0.1364034, -0.5762724, -0.5514747),
Vec3(-0.2238584, -0.5409106, -0.5314718),
Vec3(-0.0948185, -0.4908428, -0.5559580000000001),
Vec3(-0.36234350000000004, -0.8061229000000001, 0.1383141),
Vec3(-0.3132847, -0.7446722000000001, 0.18579060000000003),
Vec3(-0.4307943, -0.7546630000000001, 0.0933298),
Vec3(0.5717894, 0.6958376000000001, 0.4528556),
Vec3(0.5852657, 0.7879846, 0.434179),
Vec3(0.6443636, 0.6708413000000001, 0.5135144),
Vec3(0.8121415000000001, 0.8262619000000001, -0.8483986),
Vec3(0.8585190000000001, 0.8939651, -0.8974230000000001),
Vec3(0.7560207000000001, 0.7748539000000001, -0.9044644000000001),
Vec3(-0.5111889, -0.0352865, 0.5807903),
Vec3(-0.5940048, 0.0102298, 0.556963),
Vec3(-0.5349104, -0.101409, 0.6507582000000001),
Vec3(0.0327324, 0.2563438, 0.011325100000000001),
Vec3(-0.0633994, 0.25221360000000004, -0.0069385),
Vec3(0.0724331, 0.3482989, 0.016056400000000002),
Vec3(-0.6003367000000001, -0.7683112000000001, -0.8874252),
Vec3(-0.6987751000000001, -0.7912403000000001, -0.8892689000000001),
Vec3(-0.5699015000000001, -0.8504722, -0.8558813000000001),
Vec3(0.0789377, -0.6357883000000001, -0.7563043),
Vec3(-0.015110100000000001, -0.6341313000000001, -0.7440906),
Vec3(0.10908810000000001, -0.5879281, -0.6770796),
Vec3(0.5045666, 0.7219298000000001, -0.5151826),
Vec3(0.5598994, 0.7846492, -0.5618276),
Vec3(0.5480466, 0.6978976000000001, -0.4337211),
Vec3(0.1286092, 0.6990271, -0.6806004),
Vec3(0.048132900000000006, 0.7140371000000001, -0.7345224),
Vec3(0.1716012, 0.7791024000000001, -0.6762706),
Vec3(-0.31987830000000006, -0.9175883000000001, -0.6334156000000001),
Vec3(-0.30327210000000004, -0.8198157, -0.6198635000000001),
Vec3(-0.3084774, -0.9539992, -0.5434969),
Vec3(-0.2002554, -0.5668583, 0.5440781),
Vec3(-0.23474930000000002, -0.4756386, 0.5542471),
Vec3(-0.21330269999999998, -0.6049986, 0.4540349),
Vec3(0.6174952, -0.8574733000000001, 0.0210584),
Vec3(0.5358389, -0.8191902000000001, 0.0557392),
Vec3(0.6760918, -0.856171, 0.0943985),
Vec3(-0.627861, 0.6057339, 0.40423580000000003),
Vec3(-0.6169211, 0.6708022, 0.3383078),
Vec3(-0.7221766000000001, 0.5771239, 0.40322050000000004),
Vec3(0.0124733, -0.5816398, 0.0203961),
Vec3(0.0029974000000000003, -0.5049468, 0.07868710000000001),
Vec3(-0.0458026, -0.5646677000000001, -0.0555312),
Vec3(0.3839311, -0.0064469, 0.861972),
Vec3(0.35862530000000004, -0.0282978, 0.7705313),
Vec3(0.30799360000000003, 0.0282626, 0.9065559000000001),
Vec3(0.7375986000000001, -0.1368885, 0.4452411),
Vec3(0.8024931000000001, -0.0682735, 0.4768078),
Vec3(0.7477247, -0.1279372, 0.3493009),
Vec3(0.9209092000000001, -0.1611532, -0.6423337),
Vec3(0.9487648000000001, -0.2470973, -0.6800897),
Vec3(0.9998917, -0.1354277, -0.5866779000000001),
Vec3(-0.5314625000000001, -0.5613762000000001, 0.7941745),
Vec3(-0.5589748, -0.6389969, 0.8478078),
Vec3(-0.4444519, -0.5357513, 0.814946),
Vec3(-0.36558840000000004, 0.2941259, -0.3295211),
Vec3(-0.4418712, 0.25281630000000005, -0.3712668),
Vec3(-0.29375680000000004, 0.30250050000000006, -0.3971189),
Vec3(-0.8786626000000001, -0.31490900000000005, -0.16403790000000001),
Vec3(-0.8441651000000001, -0.4011755, -0.1901885),
Vec3(-0.9285717, -0.3276173, -0.08345350000000001),
Vec3(-0.7358188000000001, 0.8239942, -0.2093781),
Vec3(-0.7811518000000001, 0.7751233000000001, -0.2768278),
Vec3(-0.689243, 0.7625331000000001, -0.1541437),
Vec3(0.3770974, -0.0453172, -0.1931225),
Vec3(0.42457570000000006, -0.09662180000000001, -0.12861140000000001),
Vec3(0.3797803, 0.0441972, -0.15421800000000002),
Vec3(0.2205813, 0.40988939999999996, 0.8958738),
Vec3(0.3001973, 0.355544, 0.8746430000000001),
Vec3(0.2103639, 0.42436680000000004, 0.9940011000000001),
Vec3(-0.8723398, -0.8284874000000001, -0.8890692),
Vec3(-0.9298972, -0.7537539, -0.9239127),
Vec3(-0.8772683000000001, -0.8361037, -0.792594),
Vec3(-0.8908952, 0.0807167, -0.7785764000000001),
Vec3(-0.906123, -0.006191200000000001, -0.7422589),
Vec3(-0.9534219, 0.1030144, -0.8475490000000001),
Vec3(0.9182207, -0.3418263, -0.8430667000000001),
Vec3(0.9046738, -0.2558299, -0.8879898000000002),
Vec3(0.8390804, -0.39587340000000004, -0.8701949000000001),
Vec3(0.10031620000000002, 0.9279866999999999, -0.8313986),
Vec3(0.1167271, 1.0190392, -0.8070619000000001),
Vec3(0.18499620000000003, 0.8761188000000001, -0.8493178000000001),
Vec3(-0.1842572, 0.4893383, 0.8198130000000001),
Vec3(-0.246821, 0.5316242, 0.8833179),
Vec3(-0.1155294, 0.438941, 0.8716281000000001),
Vec3(-0.40050549999999996, -0.3953707, 0.040234700000000005),
Vec3(-0.36821480000000006, -0.3305443, 0.10587690000000001),
Vec3(-0.4738199, -0.44524340000000007, 0.0841144),
Vec3(0.35118150000000004, -0.7590537, -0.9004707000000001),
Vec3(0.3415066, -0.7281286, -0.8094635000000001),
Vec3(0.325155, -0.6835442, -0.9579171000000001),
Vec3(-0.7614136, -0.7773463, 0.1262079),
Vec3(-0.7489497, -0.6927033, 0.0753779),
Vec3(-0.8528840000000001, -0.8050689000000001, 0.11647099999999999),
Vec3(-0.5419143000000001, 0.706188, -0.5745275000000001),
Vec3(-0.4504905, 0.6840455000000001, -0.5750772000000001),
Vec3(-0.5895918, 0.6221393000000001, -0.5676189),
Vec3(-0.9017162000000001, 0.18887810000000002, 0.09378130000000001),
Vec3(-0.9868157000000001, 0.21150560000000002, 0.0623903),
Vec3(-0.8466599000000001, 0.1708818, 0.0191067),
Vec3(-0.8037596000000001, -0.5106016000000001, 0.47508020000000006),
Vec3(-0.7322228000000001, -0.5707104000000001, 0.5043673000000001),
Vec3(-0.8230169, -0.44810510000000003, 0.5475067),
Vec3(-0.43905459999999996, 0.16915020000000003, -0.7756245),
Vec3(-0.35588440000000005, 0.12649660000000001, -0.7996466),
Vec3(-0.41361210000000004, 0.2629917, -0.7760619000000001),
Vec3(-0.3975194, -0.6218233, -0.692733),
Vec3(-0.3085645, -0.6066352, -0.7325296),
Vec3(-0.46408150000000004, -0.6676349, -0.7524295000000001),
Vec3(0.8240648, 0.5082183, -0.8857912000000001),
Vec3(0.7453645, 0.5101728, -0.8259448000000001),
Vec3(0.8368223000000001, 0.4228825, -0.9227974),
Vec3(0.1598931, -0.18297960000000002, -0.0316752),
Vec3(0.1992252, -0.1475465, -0.11498150000000001),
Vec3(0.1726926, -0.2749881, -0.0397199),
Vec3(0.1433819, -0.13867020000000002, -0.3304673),
Vec3(0.1323094, -0.0486757, -0.306711),
Vec3(0.0623143, -0.18020160000000002, -0.3264828),
Vec3(0.3735991, 0.5554990000000001, 0.6219603),
Vec3(0.33209160000000004, 0.6265941, 0.6761937),
Vec3(0.4195666, 0.6053207, 0.5526652000000001),
Vec3(-0.6285976, -0.9228132000000001, -0.4460410000000001),
Vec3(-0.5683885000000001, -1.0005163, -0.47408700000000004),
Vec3(-0.6707036000000001, -0.9488426000000001, -0.36084380000000005),
Vec3(0.40362000000000003, -0.3378299, 0.6905724000000001),
Vec3(0.34574410000000005, -0.2618106, 0.6794504),
Vec3(0.4929409, -0.2991177, 0.6666963),
Vec3(0.0606517, 0.8561279000000002, -0.37824060000000004),
Vec3(0.049809900000000004, 0.9526035, -0.36992990000000003),
Vec3(0.1288545, 0.8500162, -0.4475972),
Vec3(-0.5666717, 0.8368298, -0.8299623),
Vec3(-0.49266610000000005, 0.7904359000000001, -0.8744783),
Vec3(-0.5742748, 0.8095703000000001, -0.7389592),
Vec3(-0.3344692, 0.7636718, 0.34758300000000003),
Vec3(-0.4140634000000001, 0.7105012, 0.32964720000000003),
Vec3(-0.33507970000000004, 0.7470949, 0.44333500000000003),
Vec3(-0.13221860000000002, 0.6638182, 0.0028906),
Vec3(-0.18950880000000003, 0.6054034, 0.0554933),
Vec3(-0.1928852, 0.7271511, -0.0442137),
Vec3(0.8793551000000002, 0.692545, 0.7841717),
Vec3(0.9639675000000001, 0.7325848, 0.785068),
Vec3(0.8776882000000001, 0.6398711, 0.8674035999999999),
Vec3(-0.6322101, 0.0607808, 0.11740990000000001),
Vec3(-0.5647986, 0.1150825, 0.15883480000000003),
Vec3(-0.5852992, -0.0060471, 0.066073),
Vec3(0.5685139, -0.35460460000000005, -0.41285489999999997),
Vec3(0.47279660000000007, -0.3473549, -0.4165755),
Vec3(0.6024761000000001, -0.2749532, -0.4610993),
Vec3(0.38219990000000004, 0.6538527000000001, 0.167803),
Vec3(0.3549684, 0.7331168, 0.1175762),
Vec3(0.3816423, 0.6788603000000001, 0.2602522),
Vec3(0.3892622, -0.7034239000000001, -0.6415978),
Vec3(0.4720509, -0.6539827, -0.6295004),
Vec3(0.32628100000000004, -0.6550918000000001, -0.589037),
Vec3(0.5454437000000001, 0.3881722, -0.2767521),
Vec3(0.5906266, 0.32404890000000003, -0.32722500000000004),
Vec3(0.6116652, 0.4657253, -0.2669082),
Vec3(-0.4179373, -0.8326009000000001, 0.43950050000000007),
Vec3(-0.3737878, -0.8754474999999999, 0.5134173),
Vec3(-0.39345840000000004, -0.882532, 0.3534465),
Vec3(0.7949488, -0.13534980000000002, 0.9244688000000001),
Vec3(0.7234465000000001, -0.1100736, 0.9869694000000001),
Vec3(0.8010855, -0.0754076, 0.8476271000000001),
Vec3(0.44986030000000005, -0.42192670000000004, 0.3963173),
Vec3(0.48952260000000003, -0.3311215, 0.4147093),
Vec3(0.48023710000000003, -0.48716980000000004, 0.4671292),
Vec3(-0.430725, 0.7384668, -0.28794620000000004),
Vec3(-0.3402854, 0.7237543, -0.3252031),
Vec3(-0.41432310000000006, 0.7834459, -0.2019767),
Vec3(0.28687520000000005, -0.041838900000000005, 0.19093400000000002),
Vec3(0.2544472, -0.0880398, 0.1179279),
Vec3(0.20828410000000003, -0.0227627, 0.24579640000000003),
Vec3(0.7961389, 0.1611971, 0.4525253),
Vec3(0.7498497000000001, 0.18331740000000002, 0.3728113),
Vec3(0.884188, 0.20509960000000002, 0.4576281),
Vec3(0.2692467, -0.45179460000000005, -0.0884665),
Vec3(0.17894350000000003, -0.48356170000000004, -0.0587396),
Vec3(0.3330887, -0.5126025000000001, -0.04746790000000001),
Vec3(0.0711797, 0.1680547, -0.4780435),
Vec3(0.08545960000000001, 0.15679110000000002, -0.3850059),
Vec3(-0.0187286, 0.1868256, -0.4936632000000001),
Vec3(0.45582000000000006, -0.0044434, -0.4673875),
Vec3(0.5376141, -0.0551202, -0.4913295),
Vec3(0.44096, -0.0197728, -0.37395550000000005),
Vec3(0.7109730000000001, 0.045347500000000006, -0.026884400000000003),
Vec3(0.6996444, 0.009859900000000001, -0.1119484),
Vec3(0.6343115, 0.1050849, -0.0110689),
Vec3(-0.2549577, -0.0200852, -0.4492507),
Vec3(-0.3199039, -0.0856439, -0.48887520000000007),
Vec3(-0.260512, -0.0151501, -0.3534),
Vec3(-0.8527353, 0.4524174000000001, -0.23474080000000003),
Vec3(-0.7662213000000001, 0.43424660000000004, -0.21048520000000004),
Vec3(-0.8794374, 0.36967930000000004, -0.279574),
Vec3(-0.28204310000000005, -0.07004780000000001, 0.4413266),
Vec3(-0.20883430000000003, -0.0069797, 0.45305210000000007),
Vec3(-0.3535913, -0.0413547, 0.5069151),
Vec3(0.6924598, -0.1285634, -0.4901833),
Vec3(0.7496477, -0.083151, -0.4206076000000001),
Vec3(0.7527035, -0.1446676, -0.5677236),
Vec3(-0.5353763, 0.6572088, 0.6734366),
Vec3(-0.4428432, 0.6663173, 0.6834862),
Vec3(-0.5603600000000001, 0.6385787, 0.5822425),
Vec3(0.7661597000000001, 0.2386104, 0.9175259000000001),
Vec3(0.7321694000000001, 0.2395921, 1.0055536),
Vec3(0.6959141, 0.21022, 0.8533079000000001),
Vec3(-0.349659, -0.3765912, -0.4994838),
Vec3(-0.36121810000000004, -0.3620689, -0.4036115),
Vec3(-0.4323649, -0.35278160000000003, -0.5463213),
Vec3(-0.9351953000000001, 0.8343146000000001, 0.3704719),
Vec3(-0.8465363, 0.8758592000000001, 0.3736785),
Vec3(-0.9159223000000001, 0.7399420000000001, 0.3880808),
Vec3(-0.0957571, -0.5174275, -0.21901700000000002),
Vec3(-0.19073450000000003, -0.5209294, -0.23031640000000003),
Vec3(-0.0758582, -0.4314608, -0.2636469),
Vec3(0.5048831, -0.7988284000000001, 0.25875149999999997),
Vec3(0.5870168, -0.8296198000000001, 0.30438160000000003),
Vec3(0.455197, -0.7498875, 0.32292800000000005),
Vec3(0.37056580000000006, 0.8368298, -0.8304931),
Vec3(0.38606070000000003, 0.9297256000000002, -0.8425405),
Vec3(0.3866516, 0.8146007000000002, -0.7371475000000001),
Vec3(-0.25351340000000006, 0.7116414, 0.6338590000000001),
Vec3(-0.19188840000000001, 0.7705593000000001, 0.6804078),
Vec3(-0.19752250000000002, 0.6330832000000001, 0.6121365000000001),
Vec3(-0.3440263, 0.7005018000000001, 0.9111704),
Vec3(-0.2633953, 0.7421761, 0.9465848),
Vec3(-0.3654896, 0.7513753000000001, 0.825647),
Vec3(0.6452501, -0.5478051, -0.5722874),
Vec3(0.7297698, -0.5914122, -0.5586895000000001),
Vec3(0.6253267, -0.4919338, -0.4937095),
Vec3(-0.6528475, 0.4497861000000001, -0.5573636),
Vec3(-0.625784, 0.46840560000000003, -0.4656222),
Vec3(-0.7247764000000001, 0.3931701, -0.5623068),
Vec3(-0.7310706, 0.8183648, 0.7852201000000001),
Vec3(-0.6552879, 0.7735013000000001, 0.7436342),
Vec3(-0.6877865000000001, 0.8451022, 0.8686616000000001),
Vec3(-0.1476441, -0.7867001, 0.7421787000000001),
Vec3(-0.0852398, -0.8570669000000001, 0.7084405),
Vec3(-0.136374, -0.7190554, 0.6737331000000001),
Vec3(0.5228019, -0.049587, -0.7592953),
Vec3(0.4737616, -0.053813900000000005, -0.6742036),
Vec3(0.4625354, -0.09013290000000002, -0.8269022),
Vec3(0.7566531000000001, -0.10067340000000001, 0.18082130000000002),
Vec3(0.7657411000000001, -0.1866188, 0.1428564),
Vec3(0.7358547, -0.0388051, 0.11399429999999999),
Vec3(0.18509240000000002, -0.5717449, -0.5035416),
Vec3(0.172104, -0.6227449, -0.4217213),
Vec3(0.2199319, -0.48563780000000006, -0.46928919999999996),
Vec3(-0.8904325000000001, 0.6791585000000001, -0.38428660000000003),
Vec3(-0.8690637000000001, 0.5952111999999999, -0.3490118),
Vec3(-0.8676001, 0.6844077000000001, -0.4770651),
Vec3(-0.3434304, 0.43971980000000005, -0.7863568000000001),
Vec3(-0.26347770000000004, 0.3892027, -0.7779256000000001),
Vec3(-0.34328470000000005, 0.5161485, -0.7310788),
Vec3(-0.7446738, 0.6124823, 0.0150068),
Vec3(-0.7404893000000001, 0.5207959, 0.0481504),
Vec3(-0.8405563000000001, 0.6215466000000001, -0.0024439),
Vec3(0.019533000000000002, -0.7307128, -0.3501714),
Vec3(-0.0240912, -0.6769004000000001, -0.42436550000000006),
Vec3(-0.019491500000000002, -0.6981989, -0.267986),
Vec3(0.7068819000000001, 0.9130323000000001, 0.7260588000000001),
Vec3(0.6559855, 0.8400987000000001, 0.7699406),
Vec3(0.7972497000000001, 0.8829223000000002, 0.7213747),
Vec3(-0.0185218, -0.319229, -0.6289346),
Vec3(0.0776651, -0.3073203, -0.6391948000000001),
Vec3(-0.0497426, -0.2964088, -0.7170893),
Vec3(-0.20736300000000002, 0.4369672, 0.5251074),
Vec3(-0.18686380000000002, 0.3811508, 0.6060261),
Vec3(-0.1253174, 0.4326708, 0.478168),
Vec3(-0.0855003, 0.30691080000000004, -0.7935226000000001),
Vec3(0.007575800000000001, 0.3132202, -0.7617253),
Vec3(-0.10098450000000002, 0.22074870000000002, -0.8320426),
Vec3(-0.6328833, 0.0064083000000000005, -0.8467228000000001),
Vec3(-0.7268416000000001, 0.0384648, -0.8383978000000001),
Vec3(-0.5825246000000001, 0.09193040000000001, -0.8320175000000001),
Vec3(-0.8276352, -0.8809851000000001, -0.634491),
Vec3(-0.7541457, -0.8792368, -0.5688031),
Vec3(-0.8510208000000001, -0.9731116000000001, -0.6353248),
Vec3(0.0463654, 0.28267760000000003, 0.7018388),
Vec3(0.08753240000000001, 0.3588447, 0.7482107),
Vec3(0.0770257, 0.2126646, 0.758365),
Vec3(0.0478371, -0.3407198, 0.6910039000000001),
Vec3(0.0585298, -0.299675, 0.7756467),
Vec3(0.055653100000000004, -0.4390636, 0.7183527000000001),
Vec3(-0.16895590000000002, 0.7002511, -0.33035610000000004),
Vec3(-0.10091520000000001, 0.7635432, -0.3553133),
Vec3(-0.1333699, 0.6195680000000001, -0.2919485),
Vec3(0.9000097, -0.6227871, 0.8137681000000001),
Vec3(0.9373858, -0.6821152, 0.7497417000000001),
Vec3(0.8024020000000001, -0.6011019000000001, 0.8033727000000002),
Vec3(0.1272378, 0.1954065, 0.3058033),
Vec3(0.1260842, 0.2615112, 0.2341207),
Vec3(0.1890312, 0.2223439, 0.37329340000000005),
Vec3(0.4139066, -0.3527427, -0.9022608999999999),
Vec3(0.4070028, -0.34991170000000005, -0.9985525000000002),
Vec3(0.4960292, -0.39423640000000004, -0.8778433),
Vec3(0.7176276, 0.2178662, -0.407594),
Vec3(0.6995275000000001, 0.1684022, -0.48732230000000004),
Vec3(0.7621313000000001, 0.2984315, -0.43939940000000005),
Vec3(-0.0034836, -0.3929919, 0.21480950000000001),
Vec3(0.08380030000000001, -0.3513346, 0.22596630000000004),
Vec3(-0.0654999, -0.32885810000000004, 0.2426748),
Vec3(-0.8701616, 0.27952370000000004, -0.5700842),
Vec3(-0.8848959000000001, 0.2145603, -0.6420186000000001),
Vec3(-0.9464654, 0.3362988, -0.5610379),
Vec3(0.28044440000000004, 0.8909551000000001, -0.5635389000000001),
Vec3(0.3063615, 0.9805993000000002, -0.5770957),
Vec3(0.3512196, 0.8486179, -0.5165468),
Vec3(0.3236002, 0.8357402, 0.36366390000000004),
Vec3(0.34508540000000004, 0.9071799, 0.3073263),
Vec3(0.3476445, 0.8586691000000001, 0.4607935000000001),
Vec3(0.5628532, 0.7185941, 0.8510937000000001),
Vec3(0.5467837000000001, 0.6318153, 0.8138885),
Vec3(0.4964153, 0.7477925000000001, 0.9150467000000001),
Vec3(-0.3767261, 0.12603899999999998, 0.2017681),
Vec3(-0.37077340000000003, 0.20195200000000002, 0.2565591),
Vec3(-0.33646020000000004, 0.1609935, 0.1212351),
Vec3(0.8228917, -0.34417610000000004, 0.0850139),
Vec3(0.9022130000000002, -0.3709208, 0.1334881),
Vec3(0.7553662000000001, -0.3976731, 0.1276651),
Vec3(-0.3004292, 0.1345869, 0.7236734),
Vec3(-0.3715311, 0.0724731, 0.6912689000000001),
Vec3(-0.3525684, 0.21119010000000002, 0.7538936),
Vec3(0.49014230000000003, -0.5547141, -0.0119795),
Vec3(0.532755, -0.5560969, 0.076977),
Vec3(0.5447642, -0.49307520000000005, -0.0617088),
Vec3(-0.33062100000000005, 0.8469477, -0.04950570000000001),
Vec3(-0.2836855, 0.9122642000000001, -0.1080706),
Vec3(-0.3311215, 0.8916887, 0.0353875),
Vec3(-0.6572180000000001, 0.3018421, -0.026207900000000003),
Vec3(-0.6711444000000001, 0.26599560000000005, 0.060646000000000005),
Vec3(-0.6040782, 0.2473886, -0.0843542),
Vec3(-0.5429147000000001, -0.5967833, 0.5177682),
Vec3(-0.4896648, -0.6608203, 0.46925340000000004),
Vec3(-0.5386594, -0.6130690000000001, 0.6117931),
Vec3(0.6054430000000001, 0.7035601, 0.0031519),
Vec3(0.5939348, 0.7951184, -0.014109400000000001),
Vec3(0.5390949, 0.6866654, 0.0702638),
Vec3(-0.08902290000000002, -0.2615376, -0.3621726),
Vec3(-0.1695442, -0.2097314, -0.35379760000000005),
Vec3(-0.0895128, -0.2637531, -0.4561712),
Vec3(-0.5446979, 0.0994907, -0.21067140000000004),
Vec3(-0.4494883, 0.09979120000000001, -0.1881595),
Vec3(-0.5759736000000001, 0.009419900000000002, -0.1919247),
Vec3(-0.7517688, -0.40783400000000003, 0.7202707),
Vec3(-0.8242348, -0.4324693, 0.7729813000000001),
Vec3(-0.6924399000000001, -0.48174530000000004, 0.726943),
Vec3(-0.1134884, 0.8628488000000001, 0.20810689999999998),
Vec3(-0.1962897, 0.8634713, 0.2554947),
Vec3(-0.1119731, 0.7882422, 0.15160030000000002),
Vec3(-0.6288317000000001, 0.8011683, 0.20221290000000003),
Vec3(-0.6404647, 0.8858198, 0.1546109),
Vec3(-0.6669138000000001, 0.7315199, 0.14826140000000002),
Vec3(-0.6766934, -0.4026505, -0.8306645),
Vec3(-0.6542552, -0.4855702, -0.8828363),
Vec3(-0.7743726, -0.3954163, -0.8170031),
Vec3(0.6895244, 0.7052113000000001, -0.30312890000000003),
Vec3(0.7810039, 0.7265357, -0.3330751),
Vec3(0.6666757, 0.7541675, -0.22021780000000002),
Vec3(0.800326, 0.4735929, -0.5168656),
Vec3(0.7233375, 0.4730204, -0.5685772),
Vec3(0.8406708, 0.562958, -0.5300038),
Vec3(-0.523016, -0.6461196, -0.4390836),
Vec3(-0.5701558999999999, -0.7313756, -0.4377348),
Vec3(-0.48555450000000006, -0.632797, -0.5273443999999999),
Vec3(-0.3803496, -0.9221115, 0.7305476),
Vec3(-0.2934288, -0.8877999000000001, 0.7425047),
Vec3(-0.4416066, -0.8566250000000001, 0.7573191),
Vec3(-0.5990438, -0.1574415, 0.30725210000000003),
Vec3(-0.5805447, -0.11192930000000001, 0.39337310000000003),
Vec3(-0.6651651000000001, -0.0947206, 0.2634773),
Vec3(0.11554510000000001, 0.7138377, -0.11783170000000001),
Vec3(0.0330359, 0.7363227000000001, -0.0724568),
Vec3(0.10551450000000001, 0.7478676000000001, -0.2100793),
Vec3(-0.5886817, 0.5150957, -0.2997276),
Vec3(-0.5191777000000001, 0.4556623, -0.2611465),
Vec3(-0.5401622, 0.6003350000000001, -0.3064194),
Vec3(0.2539927, 0.3387568, 0.49761800000000006),
Vec3(0.1760904, 0.3182324, 0.5589217),
Vec3(0.2841539, 0.4315465, 0.5278853),
Vec3(0.8331859, -0.7344673, -0.5188191),
Vec3(0.8424401, -0.7586778000000001, -0.4198621),
Vec3(0.8911675000000001, -0.7764424000000001, -0.5823267000000001),
Vec3(-0.5774081, 0.1315144, -0.5304553000000001),
Vec3(-0.5222992, 0.1580336, -0.6077077000000001),
Vec3(-0.6219878, 0.21784409999999998, -0.509336),
Vec3(0.6340084, -0.49260640000000006, 0.2149626),
Vec3(0.5639784, -0.4766017, 0.2829591),
Vec3(0.6883511000000001, -0.5598794, 0.256282),
Vec3(-0.2722394, 0.6614441000000001, -0.5843805),
Vec3(-0.23324140000000002, 0.7251953000000001, -0.6403722000000001),
Vec3(-0.2221682, 0.6596615, -0.5034993),
Vec3(-0.1813152, 0.07128240000000001, -0.9048176),
Vec3(-0.17639210000000002, -0.0271744, -0.8916841),
Vec3(-0.20977960000000004, 0.08605000000000002, -0.9970314),
Vec3(0.6146244000000001, -0.6879929, 0.8376712),
Vec3(0.5324465, -0.7183905, 0.8841506000000001),
Vec3(0.6642264, -0.7749945, 0.8201756),
Vec3(0.2887544, 0.8612615, 0.0453821),
Vec3(0.2452117, 0.8047637000000001, -0.0251289),
Vec3(0.2348751, 0.9285636, 0.08956420000000001),
Vec3(-0.8475558, -0.8180718000000001, 0.6501232),
Vec3(-0.803431, -0.8945692, 0.6891221000000001),
Vec3(-0.8173606, -0.8179435, 0.5569319),
Vec3(0.6714205, -0.2947903, 0.6551671),
Vec3(0.7143284000000001, -0.2459194, 0.7270891),
Vec3(0.7212365000000001, -0.2637046, 0.5791018),
Vec3(0.6445003, -0.5462306, 0.5577966),
Vec3(0.6730099, -0.4696457, 0.6073312),
Vec3(0.6099428, -0.6099736, 0.6222859000000001),
Vec3(-0.1818761, -0.6080111, -0.880542),
Vec3(-0.1644534, -0.6777931, -0.9477669000000001),
Vec3(-0.2078582, -0.5258591, -0.9215838000000001),
Vec3(0.6037377, 0.2950576, 0.2863541),
Vec3(0.6409766000000001, 0.3757001, 0.2570754),
Vec3(0.5577033, 0.2617474, 0.20905870000000004),
Vec3(-0.7731645, 0.33376680000000003, 0.3301121),
Vec3(-0.8345957, 0.40272220000000003, 0.3589257),
Vec3(-0.8130328000000001, 0.28452380000000005, 0.2577949)
};
context.setPositions(positions);
State state = context.getState(State::Energy | State::Forces);
// Compare the forces and energy to reference values computed with Tinker.
ASSERT_EQUAL_TOL(-8689.0456938244151, state.getPotentialEnergy(), energyTol);
vector<Vec3> expectedForces = {
Vec3(-335.0172933029931, 22.266752620867532, -311.0298423949193),
Vec3(125.33189469021171, -48.64909489077264, 173.68519722812303),
Vec3(-68.82118100602865, 201.02869856438417, -111.6897919454047),
Vec3(-61.153379096776426, -616.9805120862311, -185.54939132041835),
Vec3(-36.81384802661533, 127.429744136704, 389.96946400173465),
Vec3(-149.5327745486792, 304.0904995695656, -167.18743050384256),
Vec3(-5.774742682153585, 373.60988946029994, -361.47500169984926),
Vec3(-181.40211600742782, -247.91603688859874, 134.01205148261855),
Vec3(21.198833848005762, -339.8691795138551, 45.802133678195986),
Vec3(-572.6283376708045, -212.1053261376012, 252.67837117733575),
Vec3(217.70654441990092, 196.93954185286114, -214.91066333815215),
Vec3(301.133383969155, 213.93807850760453, 28.9133028668968),
Vec3(-299.08443712963157, 434.0122811695415, 0.013121440693021303),
Vec3(59.52664104608579, -247.94912563119672, -230.14506152824993),
Vec3(90.95139727044368, -62.875870942678866, -7.637291617312463),
Vec3(88.67134147030124, 257.7041314274848, -28.532734429050475),
Vec3(-70.26814245017862, -105.14173766805607, -18.25952793194643),
Vec3(-70.28148862947461, -261.8105030692827, 28.87470048624826),
Vec3(209.77702595833722, 416.2567365924144, 632.57753195419),
Vec3(-190.08312952734263, -18.294772882839077, -505.8441797104047),
Vec3(-179.7429255793455, -92.01351813231925, -160.07155590063837),
Vec3(-26.02384439787512, 330.90933534519417, -140.8958215021164),
Vec3(109.63698884057686, -571.6693436875398, -139.96868562036477),
Vec3(-137.30575212422485, -18.590762562776803, 26.55457387413793),
Vec3(-470.7904899631753, -245.44713111184723, 266.2903954223516),
Vec3(472.8083986505288, -89.0282869998406, -203.89855802595156),
Vec3(320.6697244615793, 384.48206499977783, -301.7069190335516),
Vec3(-52.803387093321916, 371.49950630788226, -134.22826294908592),
Vec3(36.99526542998541, -48.845037544586425, 191.51299040052936),
Vec3(128.42355577787023, -408.4164655600154, -173.3124425056217),
Vec3(-878.269059321722, -405.611635336188, 58.17112139996775),
Vec3(311.21777122108915, 348.87955985753723, -41.081660659626756),
Vec3(616.7791174948256, 246.05437434041508, 135.81742400623813),
Vec3(103.45047101349174, 200.32520291949814, 272.8589209780621),
Vec3(-9.490187025589702, -290.6683465976385, -73.40438173785563),
Vec3(-55.4759120118965, 162.87656847420035, -230.05485334711796),
Vec3(109.52717578132189, -336.2359129283262, 497.0416460397142),
Vec3(-75.0006907250051, 202.17953028474363, -292.48773052352334),
Vec3(-262.4420239324133, 234.94106079413922, -125.27331602906199),
Vec3(-14.202580814281575, -262.83218804797286, -229.84220570272163),
Vec3(212.05109735217303, 99.3513392917139, -63.47217888422316),
Vec3(69.01293955243082, 367.7778083972, 163.89342426801701),
Vec3(-147.74894232097182, 622.1821269496787, 90.0489458605032),
Vec3(-296.7521624967717, -446.6548799522563, 184.76666740616145),
Vec3(213.50832760333225, -163.1447531897083, -133.1253079707448),
Vec3(-263.12394827367666, -272.8332624893659, 627.1233508940367),
Vec3(130.22756305721452, -174.11906923075196, -141.92061497589265),
Vec3(29.750796355350722, -46.36135673544522, -249.62285120478313),
Vec3(-9.13445457731486, -104.19390094140452, -664.7908266736111),
Vec3(-6.098628627937129, 75.3690598663586, 214.20148433669854),
Vec3(93.85773518954444, 70.31730678831572, 419.69479715633724),
Vec3(153.08875466165682, 481.7270969394399, 57.00333898487111),
Vec3(-40.77543925453837, -220.28139776477002, -1.1259274322172284),
Vec3(-4.0235594287871335, -383.61042422379546, -71.23508976663497),
Vec3(418.0952203126167, 258.72039518106965, -47.349109649340804),
Vec3(0.04695838952295269, 74.96915961237585, -51.56319329013884),
Vec3(29.043347800433725, -121.56146857432789, 448.008737586852),
Vec3(-635.3406965422951, -130.49158863352883, -16.637291453440223),
Vec3(357.06426206105454, -79.87073091942342, -79.98429428457332),
Vec3(259.79092998995526, 176.66734932402687, -68.32489685158053),
Vec3(41.586627904206296, 911.714192439227, 348.02477261221054),
Vec3(-160.06817726684196, -346.7078180859659, 70.76436888328635),
Vec3(234.35149116384792, -460.58513477969444, -73.426128633765),
Vec3(157.4675603840564, -424.1782014191973, -372.6497703158724),
Vec3(119.26625771982772, 531.6272342992715, 112.81649088166586),
Vec3(-34.07274116756812, 110.6794010683938, 210.08473261060942),
Vec3(-198.40995599088754, -570.8909011764729, 115.21000416227702),
Vec3(51.41637305126889, 346.8967211007784, 46.042161875197216),
Vec3(143.69207010587456, 232.12347501298257, -111.85121609580156),
Vec3(587.8256947940419, 167.03440041641014, -344.5262841142951),
Vec3(-294.0302209549635, -102.8160127286171, 278.0538118178713),
Vec3(-155.3754267902171, -109.36554731955172, 119.48308135091925),
Vec3(334.73319863236054, 377.32048036240354, -77.85868301095428),
Vec3(-227.14891011932315, -91.8088898622582, 287.0865066368314),
Vec3(-203.96567623951984, -185.40142586146987, -38.135012396093074),
Vec3(-20.4293898817084, 592.6694193025131, -22.971076219709346),
Vec3(-115.34910930011313, -232.3372229865608, 196.22480672888415),
Vec3(68.25750021108932, -475.02332746194145, -164.93581903944687),
Vec3(-333.7383046001966, 132.27112439169812, -761.0324474778728),
Vec3(216.86879805383205, 53.879327754001224, 149.678361921911),
Vec3(147.69195577766362, -257.43256468417815, 562.7838289823908),
Vec3(381.03219261827206, -306.7234704626524, 223.53742098150207),
Vec3(-303.05669134128937, 47.5927486894213, -37.253967643358976),
Vec3(-65.56006757720597, 57.30446123065876, -99.92542301755618),
Vec3(16.45016285279712, 176.9512834170706, -749.5247703975105),
Vec3(8.8502897582912, 134.11245318402337, 256.66351522740337),
Vec3(-172.84287762857088, -320.6199115936171, 55.79038894807629),
Vec3(-164.2330289485781, -76.7611788656553, 310.152391940976),
Vec3(-2.2175942260194152, -78.54632557153865, -80.75861093555594),
Vec3(98.54858566877967, -12.069149082363449, -137.1999706358292),
Vec3(-484.3780436682154, -19.13689509690661, 310.75160467834843),
Vec3(171.0767536821465, -34.60959395997303, -115.3288869482195),
Vec3(304.9942121214169, -98.24199876126227, -359.2513692773626),
Vec3(-46.917816002077096, 342.99848016254066, -710.7609279934222),
Vec3(-255.7733125462255, -130.61213124346506, 333.6902423638203),
Vec3(130.3665876050882, 72.45464900777448, 407.67413132012115),
Vec3(362.6959350832374, -625.6289663832105, 534.8145739471075),
Vec3(109.9449670148772, 34.02485255261072, -29.333173337415655),
Vec3(10.609296002267028, 319.0453059680116, -209.23668662392288),
Vec3(489.92703773110577, -90.97242966996552, 470.6492704242861),
Vec3(-148.6591729184633, -262.71858457289375, -401.94526102641487),
Vec3(-282.1158812260683, 19.459896854715428, -211.49662848026315),
Vec3(368.7383546475742, -20.484173872570658, -219.36806133763213),
Vec3(-270.8205798617515, 311.9392165851896, 27.643007573580448),
Vec3(140.56187148787137, -87.90210361076366, 151.4747821114451),
Vec3(-60.16866721698693, 302.97054215665713, -819.4553589015721),
Vec3(35.79598871589246, -122.39126281358682, 210.26426229337034),
Vec3(-66.10611807867937, 157.5398290851135, 448.861116021134),
Vec3(-498.3505587804024, 32.47643839609101, 501.6056415549782),
Vec3(21.42926264054984, 35.45731305548093, -32.13558813571573),
Vec3(176.69598167411476, -8.818539210212053, 82.33055000489443),
Vec3(311.69676437401915, -180.34661299766054, -374.47482858089404),
Vec3(-55.6362284394929, -23.143898952474096, 0.6568904901292746),
Vec3(97.0788452798702, 279.8982155045794, 202.65171870217557),
Vec3(-378.30748347232014, 127.61358171776939, 290.9515219066664),
Vec3(197.2613702769855, -292.04013928277976, -142.4748620807829),
Vec3(282.63019847216043, 122.84174235642894, 20.537956693491076),
Vec3(357.0756608486188, 80.38597643570732, 293.7034380840931),
Vec3(-206.42247820888818, 234.27232340296675, -90.7074846249461),
Vec3(-307.70713998461395, -196.037137219103, 27.15152638460597),
Vec3(-64.97305840292616, 432.6702312462856, -377.1701790062745),
Vec3(192.39934479522014, -209.42186728613302, 321.17117572988707),
Vec3(-34.070401388556284, -242.92310385438617, -161.37927007292356),
Vec3(-210.06535904776248, 475.94338248099257, 39.573057705113),
Vec3(196.6392201325647, -178.23021411913012, -52.06018603864398),
Vec3(366.96563306664547, -75.50449018422802, 234.11118983874277),
Vec3(-87.45285537955262, -292.1388809885602, 125.9245047297564),
Vec3(-2.6097614349141502, 61.38814525645277, -238.2875371484905),
Vec3(224.299624134995, 129.03756654996485, -209.3802240227379),
Vec3(130.06059150251497, 383.3327075111684, 747.1711009467334),
Vec3(175.21625830299126, -416.5788853289343, -243.601499615591),
Vec3(-364.4521367639826, -106.04727942609144, -330.2576636999889),
Vec3(99.5129561601014, -7.0737493392099795, -171.21060084342537),
Vec3(-73.40659512011415, 32.77319925171829, 116.94825700535361),
Vec3(-141.09592782476182, 91.41482357556552, -122.03803728317106),
Vec3(-607.1238052871533, -332.23592016130823, -493.8941057121413),
Vec3(243.01331892218482, 308.991212840969, 92.08162012563092),
Vec3(185.80085793917712, 216.10179468907106, 302.86857771039007),
Vec3(-401.0890281173852, 388.4391946603248, -367.9309797163247),
Vec3(-100.81625054195577, 110.90568711955605, -60.98830214711071),
Vec3(57.5827034562495, -200.39318297705665, 221.16502473467597),
Vec3(15.479198217011403, -294.8476780974793, 313.05202536753137),
Vec3(-22.68966762034828, -16.883065945378583, -222.31114691758262),
Vec3(60.131175414220685, 259.0717252907813, 43.812674683776464),
Vec3(-244.29545015574348, -13.003701760585107, -521.0596730034538),
Vec3(253.30455540194777, -53.74416045641287, 322.4507796394325),
Vec3(59.53271516593827, -172.86192268690564, 428.91232924831996),
Vec3(-94.18810336875917, -213.91761035510586, -774.2959734446436),
Vec3(-42.66916874467921, 67.67886910782568, 261.31730399501794),
Vec3(-135.18139010892307, 182.14511102572936, 39.19620603730564),
Vec3(-267.48903981479583, 323.93677093152576, 155.57926646179976),
Vec3(265.68057580662486, 237.15137320106408, -73.8073231300024),
Vec3(163.6422175243033, -344.1016778626731, -98.9553131951134),
Vec3(-417.57769260569216, 372.9724079786472, -354.9144199200316),
Vec3(174.60383046684865, -295.19215783245784, 245.12914586006102),
Vec3(-89.98904496649995, -87.2775956819704, 353.4653488579693),
Vec3(286.75766928201676, 187.08878816951588, 7.134623737454445),
Vec3(-658.3418339179785, 0.8204879635860092, 161.42627569588382),
Vec3(-179.1795611511418, -123.25665912137428, -27.946948054390216),
Vec3(-503.57735364056236, 43.16812666561538, -255.79483040075291),
Vec3(402.9967717966019, 165.9311189465745, 269.5058302465449),
Vec3(293.37065377232165, -273.6332290743603, 320.63041436390574),
Vec3(-262.10212008659437, -46.7955813969605, -581.4088275555852),
Vec3(-30.2320497047736, -9.079949804681405, 147.56286166198885),
Vec3(-43.93173355284762, -132.38098797288382, 270.16597187974565),
Vec3(-168.36792036071273, -53.98374514539546, 225.78668913751721),
Vec3(334.7967152701796, -263.8406209142154, 166.4503781499664),
Vec3(-186.90785272583642, 182.96718206224855, -256.451054140323),
Vec3(-394.49463290750947, -146.77389944500393, 594.9063097843305),
Vec3(377.0132355528018, 172.2165949478846, -658.2310181509444),
Vec3(87.99398155638868, 95.45955377229726, -224.7212655405849),
Vec3(91.35908549169696, -283.11956651302893, -158.37895642205956),
Vec3(-22.156629024982795, -67.2336785087731, 193.14902926414084),
Vec3(41.72481944476615, 343.97275897996354, -77.0897828280966),
Vec3(-227.92503372467664, -139.8115628103093, -139.55704139377036),
Vec3(-154.60617592523425, 6.595226244996243, -26.050724130230446),
Vec3(-202.81419832720695, 11.338982518476884, 309.4286928931821),
Vec3(435.77631768531353, 20.104427710837115, -230.79703011625188),
Vec3(-280.3722173344336, -5.317699878558584, -173.66993018163438),
Vec3(118.23315941393871, -405.4829647949468, 37.80228471408086),
Vec3(-458.5673721340151, 112.65705030065294, 409.6634223706711),
Vec3(280.331368333651, 22.57328190427317, -384.40378205387753),
Vec3(185.38078021818973, 9.77483717142891, -103.57091253465515),
Vec3(-278.14912325432425, -36.20838885976491, 267.73561222615245),
Vec3(-34.830853667667476, -18.943233607275854, -335.7974137018089),
Vec3(478.4250193364935, -316.0844609317257, -106.9495030481627),
Vec3(-206.10138317271623, 479.25253681999743, 26.423499841774987),
Vec3(237.7517285969004, -408.2186042733612, -104.62920759536269),
Vec3(237.47608164868515, -396.53375556819947, -62.01554416514412),
Vec3(246.13264323273938, 299.2182541382955, -101.60304862993172),
Vec3(-88.3888451297483, -234.54057850287776, 249.45343181489312),
Vec3(74.20321439970564, 32.783072104780274, 27.84285720322591),
Vec3(-227.73218962858508, 25.955765828861534, 768.9909275501468),
Vec3(218.04593781599476, 68.13904535430797, -373.67055762036176),
Vec3(-70.85593969488238, -465.75757735272515, -386.9288173904391),
Vec3(337.4971335703799, -610.401933199198, 41.7376937632877),
Vec3(-128.19389877563995, 225.52623728832899, 120.85438004154167),
Vec3(-197.36890509908193, 149.33425686805785, -73.66235648792265),
Vec3(-529.8844689771222, 136.96655160230569, -520.4899602281171),
Vec3(358.12374781973904, -33.68519613067586, 90.92035558030787),
Vec3(449.57843590236314, 102.2033934671651, 148.3933944651018),
Vec3(-573.5551815876588, -168.7468657009597, 91.64110217984988),
Vec3(438.7190198207128, -172.82187813986562, -87.74461307839385),
Vec3(346.16872244254057, 67.52112917677196, -299.6681425397538),
Vec3(-81.42562048805756, -169.45181146484416, 686.7534291826855),
Vec3(-48.77863644337722, -57.02529540436205, -239.34917988192007),
Vec3(98.97471436009545, 66.29734927568607, -147.2160842675108),
Vec3(571.4868223675801, 109.37640359293688, -241.82852144361874),
Vec3(-27.302491797473444, -112.70580053011595, 310.4651161763384),
Vec3(-296.45138867950146, 16.11991536911067, 190.39253933211316),
Vec3(244.1906180549886, 445.984116282156, 730.4335661266872),
Vec3(-24.92525709360532, -287.34251883027173, -224.27905729827484),
Vec3(-52.28210358734295, -112.55664731155846, -406.45432093102903),
Vec3(-35.93533629631095, 303.0684473948616, 544.1190864213654),
Vec3(-280.26263220953695, -144.32736752996388, -186.22540145446177),
Vec3(139.8295597293426, -77.8076576832115, -270.5449832550807),
Vec3(-355.6661141215022, -154.03179563848596, -206.73818107160739),
Vec3(243.1742601175141, 213.0696851632588, 33.94148512402239),
Vec3(-15.957294605174972, 143.9105658917933, 300.125564885917),
Vec3(177.7591556586813, 492.52778610498217, -74.34220357918292),
Vec3(-226.830631991299, -155.6469051553185, 87.86685132810285),
Vec3(-64.02516018286668, -92.32797627847043, -62.480563960283256),
Vec3(492.8294568021554, -161.5459500935738, 549.2843326732387),
Vec3(-110.76036948748197, 94.9855493501626, -234.97576425629097),
Vec3(-449.1619568111018, -102.48984366369703, -200.96370925656765),
Vec3(570.9163346756443, 82.30432988258791, -186.75547798110142),
Vec3(-167.3224429913125, 124.82326502308682, -16.057485298110592),
Vec3(-223.22476312479617, -204.6397809328862, -53.18667195553344),
Vec3(-271.5556269469767, 683.6702538648904, -102.07762941144526),
Vec3(134.62606565263354, -410.44767192891493, -37.45205679258815),
Vec3(74.3886024417582, -380.2265778392809, 167.12841474834616),
Vec3(51.97506596324779, 526.4093096850187, 29.1896719191959),
Vec3(-120.11128754642573, -355.2133509248956, 32.492509082662444),
Vec3(98.11863631229781, -144.1612884646125, -98.15665591329949),
Vec3(622.8039474941972, 627.8848271429141, 309.5672683525694),
Vec3(-224.65594596550676, -207.01495109188178, -268.61904935094833),
Vec3(-145.45934471329684, 68.77728500682441, -184.11358107811122),
Vec3(305.8113859131425, -40.76685071110852, -999.2423905417055),
Vec3(-200.5858959306156, -3.212783801977652, 104.99355118038582),
Vec3(65.75975451314979, -6.185961208359154, 260.7217381132384),
Vec3(-465.325630006053, 57.243087558111455, 244.48446186690254),
Vec3(284.39071908119865, -403.30368265456985, -227.93324395547202),
Vec3(319.566870539745, -154.25285215328194, -244.75552729911286),
Vec3(113.95989360867209, 210.3673617061578, 24.4869768189808),
Vec3(460.4983861239349, -226.50133066112335, -88.59685197216878),
Vec3(-98.09787243132699, -244.04610698615312, -163.59809551548102),
Vec3(-585.0908382278882, -889.1343804189501, 261.8360010792674),
Vec3(-5.758449030052453, 117.8568682173512, -39.074275143409196),
Vec3(211.12632405257287, 426.9945188148396, 26.337265835984113),
Vec3(-261.1123357379434, 397.37927572746406, 385.80418113770185),
Vec3(193.80057938382404, -156.03070640112747, -164.3047139303805),
Vec3(95.64032398633752, 130.1828205456674, -356.2199481014633),
Vec3(613.4334217010296, 72.2340712870241, 388.29832354067554),
Vec3(-298.17301652117567, -485.9210453626593, -198.3924134013901),
Vec3(-327.28584175027964, -69.94548015665167, -100.92794190916767),
Vec3(-95.35204059147279, 758.8346740109748, -194.78919552260624),
Vec3(100.98823322759415, -213.1945318796383, 64.24599810971583),
Vec3(225.68708404163152, -77.61888875340239, -192.77536729645487),
Vec3(-246.52466151347878, 190.681831372716, 252.93416398953948),
Vec3(129.60771170235893, -186.19056827830264, -68.5035780563697),
Vec3(93.5709211341456, -118.66636057842628, -199.0551553620597),
Vec3(-234.7503041241301, 650.242143690075, -687.8965017480454),
Vec3(-75.97170398650412, -40.86957278265794, 221.02893728463457),
Vec3(224.04760000079307, -161.68890748532917, 235.32139129294472),
Vec3(-74.00277073089084, 549.5541839324454, 907.3249138777222),
Vec3(-41.53734323654314, -87.68222100616845, -283.5794117156566),
Vec3(-163.26973194049333, -119.24675888406907, 58.022839403782754),
Vec3(-361.68978882794306, 203.22693867650017, -228.11712287648672),
Vec3(354.5436461015289, -398.4125169812179, 73.95001180998987),
Vec3(212.09479737847641, -38.76073634658328, 29.716200325408277),
Vec3(-482.44796651544783, 450.52466265861904, -49.53658099063551),
Vec3(264.8763703413555, -176.1523824510752, -179.5364728358089),
Vec3(25.934723044885093, -296.1137082397114, 153.9122506945108),
Vec3(-454.9541821120418, -54.12890962459669, -206.31506876664034),
Vec3(447.0240999051737, 243.6131266820493, 281.33572023230363),
Vec3(278.5724047530407, -82.33441841810905, 288.83145603927267),
Vec3(-205.86073760331593, 252.96028131048593, -327.951075003245),
Vec3(-8.102335280217162, -21.25603560331037, 282.5453411439364),
Vec3(103.04228102611414, -82.98598255630152, 84.99892701613994),
Vec3(277.886957196108, -390.7010994011783, -20.81660705735313),
Vec3(38.85218525806698, 65.47184623788992, 145.50643468675383),
Vec3(-389.44531367623784, 209.15181976831985, -267.86500262317975),
Vec3(341.2590622095847, 355.96996723289317, 297.3182674750273),
Vec3(-143.21413877558632, 435.64524536899194, -402.5198602393208),
Vec3(-9.1574004574585, -214.91977155827013, -89.97013896442718),
Vec3(88.10148161888606, -381.39540185252184, -519.6040717554135),
Vec3(-99.01610917808237, 367.8255314129375, 132.8955373395401),
Vec3(-18.737962788115055, 57.01667717253856, 255.84577394353622),
Vec3(-99.0955840838852, -530.6962970253314, 65.53533222740258),
Vec3(-237.92161335829448, 67.03743308303048, 110.37769253762544),
Vec3(309.8838329638783, 132.35911932869914, -138.5522797283263),
Vec3(-96.6853311031437, -710.2881975293326, 58.34437189638875),
Vec3(213.86805033080176, 288.2392680555765, -105.81975964779848),
Vec3(22.772096275540605, 235.6350351773449, -65.47097586247526),
Vec3(-94.00421852809512, -192.87250405359734, 246.73260365131748),
Vec3(-247.11680926114641, 225.04786856058493, -210.8380653655543),
Vec3(-127.8970001261775, 57.72938451084627, -159.15484814975818),
Vec3(375.5728222836788, -381.28196818590226, 439.7283099955979),
Vec3(-217.16080164887964, -53.01981186700791, -90.89745186747565),
Vec3(-95.68140738731651, 305.01411462510595, -279.0369626510706),
Vec3(371.37239377715747, 317.440137340223, 160.40093833792014),
Vec3(-94.21505282887951, -350.9893416523208, 78.21621943988582),
Vec3(-222.54281618460953, -171.3855599524479, -146.0877533579349),
Vec3(-323.21815571674796, -342.9579687506031, -88.45352114131323),
Vec3(388.04238540141733, 255.65859010927807, 14.001619399996128),
Vec3(213.20205319044996, -32.28586591346377, 162.39314984533453),
Vec3(-805.8058051882732, 372.3107473646138, -203.15301715170082),
Vec3(395.93943462922255, 57.12474515707026, 45.644819760124264),
Vec3(293.94722535676993, -37.328318287498064, -182.27190610751978),
Vec3(532.0401793893479, -77.39412079621457, 52.21771947192521),
Vec3(-161.227850710132, -328.78876308408985, 112.0919283045154),
Vec3(-41.03660306291223, -359.6277647538153, 14.983452501856092),
Vec3(-569.13236331891, 185.63153390797075, 228.2621086521638),
Vec3(22.441031195862237, -60.82374909827159, 100.45918016682288),
Vec3(117.5885525974438, 87.53966101612221, -203.05548955437476),
Vec3(-214.58602140325254, -36.579422801152866, 605.2727706004744),
Vec3(-200.27682635530584, 28.830562583079605, -289.31910886246925),
Vec3(159.49590951095988, -121.40513788929071, -28.819158731892223),
Vec3(-409.8711277579596, 516.8007911315127, 132.53563908239533),
Vec3(-167.0747576875269, -336.21944443805734, -85.74302903364367),
Vec3(324.6782925866288, -227.62736204544572, 239.66332745765882),
Vec3(-522.3235597701688, 283.2165343551196, -406.29658609135186),
Vec3(-47.239971300907676, -17.319738387750075, 117.69492699127983),
Vec3(139.0179249406367, -65.17933149069559, 56.22262714627035),
Vec3(194.92258039190506, -495.6735324881299, 191.00496219578724),
Vec3(-155.58871524729037, 158.85939335788166, -59.76117566037533),
Vec3(-46.97301692216656, 118.25286655504905, 206.041971459776),
Vec3(-162.37161796443198, -113.6059127535774, -604.8797596743224),
Vec3(57.7537729943822, 204.73071565228176, 214.1526142931406),
Vec3(48.971414258803634, -68.10961851908384, 209.61380632419835),
Vec3(592.3172324044921, 161.93944862884157, 731.2515728272998),
Vec3(-373.4260162119567, -153.043454184166, 124.54463246735587),
Vec3(-280.80249648048533, 65.32981422622129, -212.025129334847),
Vec3(186.31448691865677, -78.90028853688928, -384.906890722121),
Vec3(-286.0808210223127, 11.502688246210578, 233.87274807182425),
Vec3(-27.574013807316593, -237.75767920620768, 24.276091840117044),
Vec3(173.97345602308616, 47.625454491439996, -438.22872656915433),
Vec3(-105.84156806925954, 117.86387370805265, 269.1195268405124),
Vec3(151.41030640361936, 82.54193589475396, 299.8083517509004),
Vec3(-584.9051666003791, -540.6482923909504, -96.85519120238199),
Vec3(273.94930496542975, 217.0974436280911, 33.49000156469636),
Vec3(348.7666456141812, 303.4735198887688, 41.90434154552069),
Vec3(452.56750856888493, -375.1900613590575, -509.7678128241393),
Vec3(56.47335585171018, 89.7725082191558, 260.75623048626727),
Vec3(-359.37837810269326, -10.624492892056933, 87.6887444718302),
Vec3(-377.6978561428832, 616.8984655801014, 133.2059803025605),
Vec3(40.134048794209875, -78.89965459234843, -159.62634062699297),
Vec3(360.66030946972086, -288.2118563365973, 108.3758118381954),
Vec3(318.5607438464587, 96.50621836570497, 292.56313106969037),
Vec3(249.26781863372435, -222.2491090376534, 21.576020205573677),
Vec3(-340.5686506786288, -418.5024552015164, 91.60690985250798),
Vec3(277.7794522103271, -892.1351514277258, 372.7040292998588),
Vec3(116.95787510292236, 322.6731113652018, -107.63726638764396),
Vec3(-308.3546601856363, 237.35078259429588, -294.1483889125617),
Vec3(164.1738590858144, 438.0549652370004, -425.9657274016055),
Vec3(-63.05481952284951, -304.942673686842, 398.5654893635808),
Vec3(-69.89996880598419, -90.5574199449692, 71.62949433934261),
Vec3(401.94154181825047, 527.4927748047301, -441.3641269369436),
Vec3(-212.44927885097604, -334.32524893063555, 60.89200958920557),
Vec3(-55.705402265470276, -215.19833979078726, 185.46660493215018),
Vec3(421.74746596498085, -400.5066571353421, 406.065002095627),
Vec3(-312.65620354632034, 273.92078627718433, -173.64786975397487),
Vec3(-185.49903825078508, 278.9923405014473, -205.32705783231194),
Vec3(-194.09762863805068, -341.91084014807365, 241.45607142436228),
Vec3(-46.74969004931445, 6.173596837525256, -16.88792508920924),
Vec3(-109.8945867456066, 203.78117837060773, -271.0692141914807),
Vec3(-688.5161850407885, -192.27352781951956, -40.526530898570634),
Vec3(264.0441921794354, 207.8029017969357, 48.022138260367136),
Vec3(510.5755183071709, 39.212284510797396, -132.72271330720213),
Vec3(58.91843480738649, 48.16337984914947, 428.38999683203394),
Vec3(-488.55847606571126, 41.551085099982664, -50.65864762524458),
Vec3(-70.79796461361309, 184.62653852151868, -173.03256792603696),
Vec3(736.4806590328083, -182.66692835105675, 74.59070581354057),
Vec3(-596.9188933568696, 381.18771263768883, -140.21476278402355),
Vec3(-204.72373982572086, -20.43531170016827, -71.06998781726801),
Vec3(-48.55272200733267, 81.05798542574162, -20.543518122230417),
Vec3(212.30179451958665, -92.24219154270519, -248.2649876337345),
Vec3(-53.92002968681649, -223.7934791614247, -88.83796848312214),
Vec3(-552.4083690241632, 729.0134449872447, 121.0187961635613),
Vec3(388.52435559625064, -300.507650523301, -428.23107647492037),
Vec3(56.60142788506428, -403.9019799029175, -120.16275565049197),
Vec3(308.37156127951414, 393.6081020430882, 14.959894152546308),
Vec3(-290.8469062326849, -126.10075403283811, -202.179648519888),
Vec3(135.281948695074, -349.368436260298, -125.09978807611155),
Vec3(731.1720290468502, 148.9220767745155, -125.78362223638345),
Vec3(-634.5063246495208, 170.0384301552944, -192.212272470312),
Vec3(-140.27435992540563, -168.1995921499923, 79.48356744390934),
Vec3(250.804188818791, -441.1486773375977, -36.70551482612697),
Vec3(25.085877970121736, 207.87404818412796, -163.67099199580164),
Vec3(26.950675730895643, 234.0932818942474, 28.56397358876569),
Vec3(-9.454435747271129, -20.917863986387033, 301.2174328607685),
Vec3(237.82781821871458, -52.948950459254156, -107.70003032789225),
Vec3(61.73475120535793, -296.08429582596233, 143.95438124074064),
Vec3(170.14773327424908, 158.21624761087693, 462.41826264479556),
Vec3(-10.212404180033044, -342.449842395608, -179.30692529008857),
Vec3(-7.9008953016637955, -27.386307692329506, -279.06223556604647),
Vec3(623.8039636448013, 204.85655792186034, 327.2389520583137),
Vec3(-151.40310120225476, -102.53356803519355, -373.67932569927854),
Vec3(-114.60108510899096, 49.56765040252641, -92.43163950075933),
Vec3(-655.4535985329173, -231.14956837314008, 3.116939149128992),
Vec3(296.310271026448, 486.70967996995785, 35.39255793924772),
Vec3(172.08210633165635, -230.4114817253959, 67.2429770869512),
Vec3(-117.51457238759482, 245.89189704794484, -365.4507607803772),
Vec3(137.983421929608, -238.63953239741107, 15.905738135326954),
Vec3(-20.615187840314757, -85.26834402580137, 141.97729391004376),
Vec3(268.74586567330704, -444.5911718723675, 320.8208665983761),
Vec3(186.01833330852335, 581.0752468784148, -18.836715858421186),
Vec3(-186.37150359219203, 105.4510492534819, 102.23449649830738),
Vec3(-378.59501900893537, -212.52931276037933, 213.47242953695846),
Vec3(34.54860314915441, 136.27116508160643, -172.85833667790186),
Vec3(82.46135646309041, 35.78982735165146, -192.3643679675803),
Vec3(362.6764195504091, -310.1156978932209, 464.7454537873777),
Vec3(-390.3172393695492, -77.78660095363016, -339.32454199292266),
Vec3(138.9725052448885, 253.2950341885662, -195.8551343953917),
Vec3(-77.77699415519196, -418.58538413391784, -74.28670560809776),
Vec3(-194.84445301328364, -7.877080531814001, 165.5212090227259),
Vec3(357.5114108099747, 169.62849296589957, -58.7318256241748),
Vec3(-205.0719400595654, 74.5439957691607, 459.81989777117826),
Vec3(225.79111975528735, 26.27998014053224, 38.169840613421854),
Vec3(225.28920964919845, -302.2653713591056, -67.27751628149855),
Vec3(607.5108973708401, -504.1751214140174, 160.94819170794239),
Vec3(-69.93045100299327, -36.799354260333494, 30.49281294423247),
Vec3(-223.07693729429133, 321.7339859642227, -119.94994217496966),
Vec3(-386.152206081632, 783.636531768563, 107.55137251024011),
Vec3(9.610827297518053, -347.14092395716125, -74.09274261126966),
Vec3(158.34185609366665, -11.999361448019783, 222.95633958634434),
Vec3(577.7097100440483, 48.895330528079, 241.95854692308532),
Vec3(-215.62481585775666, 111.85868020159693, -231.96801104109238),
Vec3(-465.5774615091408, -100.35047728153442, -27.60777043752202),
Vec3(349.00841247283637, 135.21443424697273, -361.5545055351252),
Vec3(-240.73972384220488, 65.15458605945898, 418.44623667785595),
Vec3(-7.185843457200288, 9.124662863122898, 252.5855944998341),
Vec3(-670.9137873329693, 15.628041411782526, -69.24683889488085),
Vec3(281.5562132077926, 125.61210072926009, -207.65352575771374),
Vec3(12.288853384156322, 46.72417772340007, 88.99682617128613),
Vec3(-310.16819954567063, 75.12792236473321, 146.45728694979894),
Vec3(74.81025034077423, -67.3523719690747, -192.46124232071003),
Vec3(80.39367736970732, -12.269727817000502, 21.517057746940612),
Vec3(504.6565508295855, 145.38275628042413, 41.84222177852041),
Vec3(-343.5623653676825, -52.04010867142658, -115.60974758310779),
Vec3(-274.03281448918597, -22.6974453925755, -111.28736000953147),
Vec3(-196.35502702123955, 337.8740247082284, -360.83640000130913),
Vec3(39.71851872750599, -176.69454550309882, 53.6900525850605),
Vec3(171.77374557034238, -286.48483828517936, 176.38100740537547),
Vec3(402.9083736209138, -35.23596085508224, 314.0963205000684),
Vec3(6.208976548032057, 121.898605161116, -482.97911323925143),
Vec3(-106.38659258059808, -122.98007642890884, -323.82127140573044),
Vec3(-126.78592336340877, 612.4875853611072, 714.8845442538958),
Vec3(-130.95742751268318, -327.8035588626552, 13.737051202125194),
Vec3(43.71022005636412, -234.93308610993728, -157.91845354232677),
Vec3(764.7690122403798, -156.77912679824576, 607.6853461644266),
Vec3(-279.82785463996305, 211.25912315893075, 124.66847330052909),
Vec3(31.54241986777193, 259.96481449469456, -226.62496190811885),
Vec3(634.6703333518747, 134.76599836974347, -452.5086582950348),
Vec3(-67.58336133802118, -144.24401501768097, 184.37864194783114),
Vec3(-297.7952840660286, -303.8271815484487, 0.30101761797852833),
Vec3(328.4835557514249, 283.13839189958037, 435.2983771026576),
Vec3(-43.43474055359954, 249.38873432379353, -265.557800712022),
Vec3(-83.87619214816716, -170.04197577715345, 151.66596729141796),
Vec3(-258.36384461101056, 23.057091916769785, 238.25614025098204),
Vec3(146.07267917397894, 103.8552762455757, -480.2259138132139),
Vec3(372.1197039472768, -49.14203788650857, 85.21854473285518),
Vec3(621.1763220000987, -250.40437867264362, 309.00536151120116),
Vec3(-275.5795704453378, 231.3583108255857, -88.82107171408583),
Vec3(-189.29412828047478, 151.36733815176305, -221.13733462711662),
Vec3(128.94381918230957, -33.18758467435246, -422.22565139314895),
Vec3(-352.2990515271668, 82.92506167420726, 34.68838626963287),
Vec3(133.53902986709014, 51.727136668888996, 204.40305583162265),
Vec3(-497.37923463749974, -121.76607553558905, -49.41904612249853),
Vec3(305.44954752398826, 112.78595133385349, 4.749053765389011),
Vec3(125.83710649669833, 13.163438021461062, 149.83453651819747),
Vec3(157.06912791278268, -0.5171966142119424, -678.1427777935485),
Vec3(-360.19887193863485, 124.22102885526218, 294.9326731520692),
Vec3(-255.04962761056123, 111.62485842221265, 203.03660695470904),
Vec3(-292.9522603455384, 137.08735478655865, 621.8258240445643),
Vec3(114.45010624125372, -59.64977272268843, -191.2132501685082),
Vec3(-12.411578194131781, 103.20865834708889, -506.930988926099),
Vec3(290.14080300222923, -375.58836058229264, -151.2870847893579),
Vec3(-117.54170340541573, 469.116879143056, -152.40985286627517),
Vec3(-178.55829097854638, -49.900688136833786, 220.5830222523799),
Vec3(391.14454811810003, 531.5288051680091, 249.98791692405663),
Vec3(-583.7409446744587, -341.1384248320302, -18.439901520528462),
Vec3(-82.62162728437389, -35.02370226948587, -200.97065983524251),
Vec3(-404.588325394559, -293.3517374583258, -355.19998309556837),
Vec3(47.3362991211429, 220.2421315309823, 223.6934819900016),
Vec3(191.57160728928307, -69.89142137133237, 85.45212433443848),
Vec3(-307.1788543156219, 898.603579545786, 57.777382167454284),
Vec3(436.0276793597111, -288.27080875909036, 128.92230922633965),
Vec3(-25.696018868319396, -609.6668554680576, 27.354330973549036),
Vec3(134.53485728281302, -863.1490487463003, 7.55358533767775),
Vec3(5.82649846805037, 222.45609829127227, 163.53219858266843),
Vec3(-43.712515913246115, 281.64431832406166, -87.08799262286338),
Vec3(637.7742866308085, 304.6587993385723, -642.0124184924257),
Vec3(126.97153318910993, -85.32640272260798, 246.00996641890754),
Vec3(-300.6884250888344, -91.77690391919501, 246.4295213323357),
Vec3(387.27044011243385, -82.48255245008419, 217.47527107587888),
Vec3(-14.940331308857358, -164.74177925605835, -287.2327509247083),
Vec3(-257.87748881436744, 11.809289741603672, 138.3446665319014),
Vec3(577.2679078626843, -250.21001338910187, -277.3369530946959),
Vec3(-282.0363468890284, -36.17855136726721, 22.048373133570482),
Vec3(-134.7451993216848, 280.74108286050057, 218.47129336793103),
Vec3(-193.8962746036012, 485.2982947874612, 299.4412942973369),
Vec3(17.16241104600595, -210.14712380790678, -189.10103821046442),
Vec3(76.92194834694459, -31.337624771612827, 96.68889655327172),
Vec3(630.0668312787265, -400.23005935079476, 181.36518690260235),
Vec3(-250.09130296853994, 305.6744427499183, -210.93746077607477),
Vec3(-383.2488674743835, 327.6804240583259, -172.94242028992176),
Vec3(73.23368257902733, -131.4472136725954, 752.3484326841066),
Vec3(-57.69978616889563, 96.88548556561102, -553.4908020962104),
Vec3(-166.43100257299437, -11.695430425660156, -351.7235364565684),
Vec3(491.228097123417, -542.4077749028473, 710.1342661566871),
Vec3(-91.2119044228842, 408.3221870989447, -387.0742839973131),
Vec3(-104.23747094053064, -194.80935879057512, -146.52341438529993),
Vec3(313.0040153135171, -135.3888007619903, 220.4997248835101),
Vec3(-487.3267874613191, -43.92592526959597, -25.44129044175576),
Vec3(-154.285006296245, 127.40939857390963, 254.38116439651583),
Vec3(-116.95731351105863, -237.0365834340773, -301.6290164354321),
Vec3(-102.71983863601567, 281.34141019219516, 429.95906087048684),
Vec3(98.60524549006234, 69.34468577352828, 79.48869874911504),
Vec3(279.8574704659307, 547.4574046928512, 7.74649169850069),
Vec3(62.828239428798646, -35.644496681660314, 67.55144834910989),
Vec3(-124.16274013373202, -266.10917000985285, 171.01805953382186),
Vec3(467.07610186013306, -137.81362696517292, -708.9007529966486),
Vec3(-179.17422437424494, 13.025404631925724, 168.11275807641016),
Vec3(-262.2255109426203, 56.42206232341501, 117.09032776785075),
Vec3(58.20833329696738, 48.613368504855416, -572.7032892022513),
Vec3(27.96132210619347, -101.65864258202168, 256.21802343532363),
Vec3(-138.76741655453398, -21.2341274466359, 93.92135436389086),
Vec3(78.99152809446993, 361.12363776076154, 26.62134492435415),
Vec3(-268.0120697505899, -109.08303805052158, 1.3635238691132316),
Vec3(186.37358587599041, -163.87403602761174, 126.94521216192753),
Vec3(-483.20013472222496, 101.44448086225994, -266.99308870651856),
Vec3(81.88348785839946, 112.63875606345701, 279.06738748752235),
Vec3(57.4830077303275, -229.22969619673017, 200.29706555483068),
Vec3(322.24722802404386, 104.24996045823842, -76.70125948877903),
Vec3(-303.3238597300328, -229.16713804079458, 25.0240171259158),
Vec3(-307.45777387177907, 135.19078133981913, -89.10952709869348),
Vec3(285.09317684199146, 395.7647971144089, 88.26577084274554),
Vec3(-290.9840438847235, -226.53830623585532, -16.796689636714003),
Vec3(-23.83913870765369, -220.6526293716373, -187.4772525940614),
Vec3(-87.01301510311579, -374.8631668085156, 54.85654373558141),
Vec3(-250.258540694562, 274.1321785560846, -282.868527504452),
Vec3(156.57046895421834, 30.488710446415638, -203.29654567913954),
Vec3(138.88414554474255, 36.705825153250224, 63.58758294392938),
Vec3(-4.151571944920135, -206.61221790456332, -99.658948111508),
Vec3(-70.19767894734504, -138.86098184015916, 213.00848447002988),
Vec3(-76.39918265300803, -150.6542911790245, 463.5555072133937),
Vec3(-124.82936097661748, -183.16458718145077, -432.2498258464293),
Vec3(107.61052644067013, 196.24722683573492, -80.25788683696474),
Vec3(-639.7206172413605, 159.83837252039942, -96.40857828147178),
Vec3(319.3869620018208, -95.85515371593043, 46.62835038957132),
Vec3(342.52961175614536, -176.3485447649931, 132.1060961515659),
Vec3(520.7563945995084, 432.15659620947457, 111.7784151280868),
Vec3(-300.9403100085422, -238.89318795815262, -37.69035433643073),
Vec3(-347.8083865480956, 67.95605091292002, 13.157759331918607),
Vec3(1.5749012469905102, 430.3719470570706, 197.47929117707534),
Vec3(-78.26989547040932, -340.30657694098545, 43.88020100777593),
Vec3(73.85568916021155, -383.5418100622305, -60.7756672464542),
Vec3(90.01352035714248, -698.8095371136719, 161.2599804433718),
Vec3(-150.47445153358203, 173.9490213227927, 96.11280656668865),
Vec3(-122.86959495054164, 382.11089136243186, -40.81352305302425),
Vec3(314.9315882143728, -258.37212719399747, -42.139726323323345),
Vec3(-148.25848969940404, 289.61038370201067, -70.75381164996946),
Vec3(-308.11282405564015, -52.44439012540086, -144.48587589718113),
Vec3(-374.71942537327294, 343.3335092983839, 164.04489669219944),
Vec3(93.81792620376217, -515.6354264427762, -413.51432518435627),
Vec3(461.9949240574166, -0.09008484391950301, 110.3541715874114),
Vec3(-218.62882048951369, 425.32378382006, -513.5901548412263),
Vec3(10.963230050428185, 31.56447804567961, 294.93650039424455),
Vec3(32.18094429272624, -99.32424744128294, 352.54963154899485),
Vec3(451.407785318005, -769.9530349296572, -185.2498205291093),
Vec3(-157.0319740102172, 391.84102588800323, 55.71567257894609),
Vec3(-99.11311391591164, 294.5711001972031, 187.28407776299665),
Vec3(265.6825036786936, -526.649964721742, 217.34022020671608),
Vec3(87.40422739093127, 258.1004620432469, -273.0363388629197),
Vec3(-201.84490114860725, -49.40784641125451, -300.6952856923296),
Vec3(-521.814880804564, -615.3258874534415, -256.4726239810002),
Vec3(300.0336167913912, 427.5500550949781, 14.325919378935538),
Vec3(140.70851604331958, 225.52329767742208, 171.16777412027113),
Vec3(-236.32025130170496, 439.2270680201855, -390.7403710451149),
Vec3(156.78573037355073, -162.48705980757663, 43.74351661511086),
Vec3(213.72101149918407, -17.284880435513287, 604.9972686468564),
Vec3(-494.73667110153434, -68.89668838318043, -222.68431916369033),
Vec3(78.9821487923666, 9.468356163031238, -25.498020388630966),
Vec3(212.25737233103033, -17.014340050902813, 267.5905554210995),
Vec3(453.8067723566274, 364.4637246448333, 149.99069571746608),
Vec3(-177.47592105862327, -92.47170385751126, 169.70729912876791),
Vec3(-104.09745588910576, -123.90105537632645, 29.522603476622823),
Vec3(-107.90878722010852, 633.7491206220252, -240.4464663940923),
Vec3(159.34660603668124, -288.6290805893232, 229.07768586571527),
Vec3(82.68827196740764, -7.161172237208839, 97.78218824458624),
Vec3(81.29530506356198, -376.6140571239579, -574.5689313963147),
Vec3(-87.68559126725243, 462.3667113764172, 184.41737271069144),
Vec3(-123.19231964696777, -10.559140090610708, 185.36834732329862),
Vec3(243.01796459337638, 282.25591797878195, 181.47417858162524),
Vec3(45.2898345551462, -413.43208301813036, -74.19004547178974),
Vec3(11.348452030736503, -36.93955436131568, -142.26172505197883),
Vec3(-141.46232685056015, 742.5898479355589, 33.381914772132724),
Vec3(-160.53203784824868, -63.65230818640389, 32.061533600221324),
Vec3(-40.00480367990102, -133.40392761241463, -151.80158045713034),
Vec3(-626.2242891551515, 167.54149648585627, -59.1097468593287),
Vec3(254.89919627881363, 268.61581103224705, -24.795078403231052),
Vec3(157.28962521631803, -295.6151357122448, 226.90365007432416),
Vec3(275.5351313879823, 295.9876800692807, 63.89447055579131),
Vec3(-322.70702417452617, -39.0452311440029, 111.25885306794342),
Vec3(-349.06739199083313, -223.66742515428317, -177.45885174916506),
Vec3(-74.92000429420452, 110.12864306681907, 235.00430137274853),
Vec3(254.890722497277, 65.05627636369265, -384.8900072500228),
Vec3(-190.73124035400733, 22.30064920161101, -432.4659619095808),
Vec3(490.14912212769315, -70.1432315160618, 167.97112704968632),
Vec3(-83.0307607982963, 110.28831525177955, -116.1565512974211),
Vec3(-548.089261697656, 126.87402362774641, -211.47775932847372),
Vec3(-107.93505397529555, 17.030788494915257, -283.1388171720635),
Vec3(-3.4809026660346523, -27.953928581550617, 227.67373947798032),
Vec3(-45.50885518571216, -134.74602913718573, 314.7601381833695),
Vec3(-88.62115952094847, 164.37013541780107, 466.10807016366635),
Vec3(-69.60286837324972, -159.56832569587237, -99.77915939835437),
Vec3(-116.51859911169545, 98.82107579980642, -246.1109912835994),
Vec3(330.91464120411547, 253.24094200709567, 278.32557143034154),
Vec3(-230.72408649508694, 75.75839302811679, 5.5286568710674295),
Vec3(-119.75342432690866, -28.727415427120302, -163.8918033736238),
Vec3(-392.13986021968697, -406.41792298821673, -363.12164150302135),
Vec3(265.1049055053364, 309.5074043470523, -64.34976323639101),
Vec3(335.55814506611324, 53.213670844593665, 291.0120981627222),
Vec3(-256.17287309248604, -432.08147957460494, 43.21907098068741),
Vec3(275.356818222935, 224.93852052245637, -30.26875753305559),
Vec3(65.29543353236605, 406.3291811412344, 128.85286503051742),
Vec3(-604.9833265293979, -48.42128327343298, 102.39782144299821),
Vec3(476.45168231702087, -120.11194342860455, 219.4027004166261),
Vec3(333.913117764101, -123.58365613445721, 51.02492093651193),
Vec3(475.3975678272806, -433.5265405655237, -316.3981032215494),
Vec3(-212.10667007171378, 196.09782456397198, -84.82998433177549),
Vec3(-200.20660716300733, 158.67182460151994, 124.8362392636121),
Vec3(-19.303927332973775, 540.3592637874732, -155.01453617600419),
Vec3(-157.5646877458501, -125.41942170628774, -48.404235316186345),
Vec3(95.18633129549345, -584.9352579495654, 187.15265106316366),
Vec3(-128.76536264812614, 370.2794308351056, 288.99352710822967),
Vec3(156.4187369167104, -153.43507609852202, -224.87846656142537),
Vec3(125.18419924488227, 23.91919275428273, -314.1009483097722),
Vec3(131.17329953709526, -36.97312115913363, -306.54336244017543),
Vec3(-21.286261187231993, 156.10334206080432, 306.58378116609765),
Vec3(-98.98290263405354, -141.13219958169117, 191.02386737902773),
Vec3(-156.3949247096025, 244.45355232257597, -63.09411046638876),
Vec3(-35.367487762748, -291.56419465924836, 87.10776038858218),
Vec3(83.68999913747565, 84.08039214623521, 335.84533905135044),
Vec3(-247.3465381366986, 197.8175231855145, -196.2466922112647),
Vec3(240.57262994423147, -12.631455037628108, 55.997914104948784),
Vec3(233.29776444327882, 35.00686695783241, 265.51562401167655)
};
for (int i = 0; i < system.getNumParticles(); i++)
ASSERT_EQUAL_VEC(-expectedForces[i], state.getForces()[i], forceTol);
checkForceEnergyConsistency(context);
}
void testChangingParameters() {
System system;
HippoNonbondedForce* hippo = new HippoNonbondedForce();
buildWaterSystem(system, 2, hippo);
VerletIntegrator integrator(0.001);
Context context(system, integrator, Platform::getPlatformByName("CUDA"));
vector<Vec3> positions = {
0.1*Vec3(1.505434, 0.0, -0.065656),
0.1*Vec3(0.553912, 0.0, 0.057710),
0.1*Vec3(1.907155, 0.0, 0.801980),
0.1*Vec3(-1.436029, 0.0, 0.060505),
0.1*Vec3(-1.781197, 0.772272, -0.388976),
0.1*Vec3(-1.781197, -0.772272, -0.388976)
};
context.setPositions(positions);
State state1 = context.getState(State::Energy | State::Forces);
// Change some of the parameters and make sure the results change.
hippo->setParticleParameters(0, -0.2, {0.0, 0.0, 0.005}, {0.001, 0.0, 0.0, 0.0, -0.001, 0.0, 0.0, 0.0, 0.0}, 6.0,
20, 4.184*1326.0, 10*40.0, 0.03, 2.0, -2.4233, 10*4.3097,
0.001*0.795, HippoNonbondedForce::Bisector, 1, 2, -1);
hippo->setExceptionParameters(3, 3, 4, 0.1, 0.1, 0.3, 0.05, 0.05, 0.15);
hippo->updateParametersInContext(context);
State state2 = context.getState(State::Energy | State::Forces);
ASSERT(fabs(state1.getPotentialEnergy()-state2.getPotentialEnergy()) > 1.0)
// Create a new context with the altered parameters and see if it agrees.
VerletIntegrator integrator2(0.001);
Context context2(system, integrator2, Platform::getPlatformByName("CUDA"));
context.setPositions(positions);
State state3 = context.getState(State::Energy | State::Forces);
ASSERT_EQUAL_TOL(state2.getPotentialEnergy(), state3.getPotentialEnergy(), 1e-5);
for (int i = 0; i < system.getNumParticles(); i++)
ASSERT_EQUAL_VEC(state2.getForces()[i], state3.getForces()[i], 1e-5);
}
int main(int argc, char* argv[]) {
try {
registerAmoebaCudaKernelFactories();
if (argc > 1)
Platform::getPlatformByName("CUDA").setPropertyDefaultValue("Precision", std::string(argv[1]));
string precision = Platform::getPlatformByName("CUDA").getPropertyDefaultValue("Precision");
if (precision == "double") {
forceTol = 1e-5;
energyTol = 1e-5;
consistencyTol = 5e-3;
}
else {
forceTol = 5e-3;
energyTol = 1e-3;
consistencyTol = 5e-2;
}
testWaterDimer();
testWaterBox();
testChangingParameters();
}
catch (const std::exception& e) {
std::cout << "exception: " << e.what() << std::endl;
return 1;
}
std::cout << "Done" << std::endl;
return 0;
}
/* -------------------------------------------------------------------------- * /* -------------------------------------------------------------------------- *
* OpenMMAmoeba * * OpenMM *
* -------------------------------------------------------------------------- * * -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from * * This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of * * Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2012 Stanford University and the Authors. * * Portions copyright (c) 2021 Stanford University and the Authors. *
* Authors: Mark Friedrichs * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
* Permission is hereby granted, free of charge, to any person obtaining a * * Permission is hereby granted, free of charge, to any person obtaining a *
...@@ -29,161 +29,7 @@ ...@@ -29,161 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
/** #include "CudaAmoebaTests.h"
* This tests the CUDA implementation of CudaAmoebaWcaDispersionForce. #include "TestWcaDispersionForce.h"
*/
#include "openmm/internal/AssertionUtilities.h" void runPlatformTests() {}
#include "openmm/Context.h"
#include "OpenMMAmoeba.h"
#include "openmm/System.h"
#include "openmm/AmoebaWcaDispersionForce.h"
#include "openmm/LangevinIntegrator.h"
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#define ASSERT_EQUAL_TOL_MOD(expected, found, tol, testname) {double _scale_ = std::abs(expected) > 1.0 ? std::abs(expected) : 1.0; if (!(std::abs((expected)-(found))/_scale_ <= (tol))) {std::stringstream details; details << testname << " Expected "<<(expected)<<", found "<<(found); throwException(__FILE__, __LINE__, details.str());}};
#define ASSERT_EQUAL_VEC_MOD(expected, found, tol,testname) {ASSERT_EQUAL_TOL_MOD((expected)[0], (found)[0], (tol),(testname)); ASSERT_EQUAL_TOL_MOD((expected)[1], (found)[1], (tol),(testname)); ASSERT_EQUAL_TOL_MOD((expected)[2], (found)[2], (tol),(testname));};
using namespace OpenMM;
const double TOL = 1e-4;
extern "C" void registerAmoebaCudaKernelFactories();
void compareForcesEnergy(std::string& testName, double expectedEnergy, double energy,
const std::vector<Vec3>& expectedForces,
const std::vector<Vec3>& forces, double tolerance) {
for (unsigned int ii = 0; ii < forces.size(); ii++) {
ASSERT_EQUAL_VEC_MOD(expectedForces[ii], forces[ii], tolerance, testName);
}
ASSERT_EQUAL_TOL_MOD(expectedEnergy, energy, tolerance, testName);
}
// test Wca dispersion
void testWcaDispersionAmmonia() {
std::string testName = "testWcaDispersionAmmonia";
int numberOfParticles = 8;
// Create the system.
System system;
AmoebaWcaDispersionForce* amoebaWcaDispersionForce = new AmoebaWcaDispersionForce();;
amoebaWcaDispersionForce->setEpso( 4.6024000e-01);
amoebaWcaDispersionForce->setEpsh( 5.6484000e-02);
amoebaWcaDispersionForce->setRmino( 1.7025000e-01);
amoebaWcaDispersionForce->setRminh( 1.3275000e-01);
amoebaWcaDispersionForce->setDispoff(2.6000000e-02);
amoebaWcaDispersionForce->setAwater( 3.3428000e+01);
amoebaWcaDispersionForce->setSlevy( 1.0000000e+00);
amoebaWcaDispersionForce->setShctd( 8.1000000e-01);
// addParticle: radius, epsilon
for (unsigned int ii = 0; ii < 2; ii++) {
system.addParticle( 1.4007000e+01);
amoebaWcaDispersionForce->addParticle( 1.8550000e-01, 4.3932000e-01);
system.addParticle( 1.0080000e+00);
amoebaWcaDispersionForce->addParticle( 1.3500000e-01, 8.3680000e-02);
system.addParticle( 1.0080000e+00);
amoebaWcaDispersionForce->addParticle( 1.3500000e-01, 8.3680000e-02);
system.addParticle( 1.0080000e+00);
amoebaWcaDispersionForce->addParticle( 1.3500000e-01, 8.3680000e-02);
}
std::vector<Vec3> positions(numberOfParticles);
positions[0] = Vec3( 1.5927280e-01, 1.7000000e-06, 1.6491000e-03);
positions[1] = Vec3( 2.0805540e-01, -8.1258800e-02, 3.7282500e-02);
positions[2] = Vec3( 2.0843610e-01, 8.0953200e-02, 3.7462200e-02);
positions[3] = Vec3( 1.7280780e-01, 2.0730000e-04, -9.8741700e-02);
positions[4] = Vec3( -1.6743680e-01, 1.5900000e-05, -6.6149000e-03);
positions[5] = Vec3( -2.0428260e-01, 8.1071500e-02, 4.1343900e-02);
positions[6] = Vec3( -6.7308300e-02, 1.2800000e-05, 1.0623300e-02);
positions[7] = Vec3( -2.0426290e-01, -8.1231400e-02, 4.1033500e-02);
system.addForce(amoebaWcaDispersionForce);
std::string platformName;
platformName = "CUDA";
LangevinIntegrator integrator(0.0, 0.1, 0.01);
Context context(system, integrator, Platform::getPlatformByName(platformName));
context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy);
std::vector<Vec3> forces = state.getForces();
double energy = state.getPotentialEnergy();
// TINKER-computed values
std::vector<Vec3> expectedForces(numberOfParticles);
double expectedEnergy = -2.6981209e+01;
expectedForces[0] = Vec3( 4.7839388e+00, -7.3510133e-04, -5.0382764e-01);
expectedForces[1] = Vec3( 1.4657758e+00, 1.2431003e+00, -6.7075886e-01);
expectedForces[2] = Vec3( 1.4563936e+00, -1.2399917e+00, -6.7443841e-01);
expectedForces[3] = Vec3( 2.1116744e+00, -2.7407512e-03, 1.3271245e+00);
expectedForces[4] = Vec3( -4.7528440e+00, -1.5148066e-03, 1.2653813e+00);
expectedForces[5] = Vec3( -1.1875619e+00, -1.2866678e+00, -3.9109060e-01);
expectedForces[6] = Vec3( -2.6885679e+00, -4.3038639e-04, 3.3763583e-02);
expectedForces[7] = Vec3( -1.1888087e+00, 1.2889802e+00, -3.8615387e-01);
double tolerance = 1.0e-04;
compareForcesEnergy(testName, expectedEnergy, energy, expectedForces, forces, tolerance);
// Try changing the particle parameters and make sure it's still correct.
for (int i = 0; i < numberOfParticles; i++) {
double radius, epsilon;
amoebaWcaDispersionForce->getParticleParameters(i, radius, epsilon);
amoebaWcaDispersionForce->setParticleParameters(i, 0.9*radius, 2.0*epsilon);
}
LangevinIntegrator integrator2(0.0, 0.1, 0.01);
Context context2(system, integrator2, Platform::getPlatformByName(platformName));
context2.setPositions(positions);
State state1 = context.getState(State::Forces | State::Energy);
State state2 = context2.getState(State::Forces | State::Energy);
bool exceptionThrown = false;
try {
// This should throw an exception.
compareForcesEnergy(testName, state1.getPotentialEnergy(), state2.getPotentialEnergy(), state1.getForces(), state2.getForces(), tolerance);
}
catch (std::exception ex) {
exceptionThrown = true;
}
ASSERT(exceptionThrown);
amoebaWcaDispersionForce->updateParametersInContext(context);
state1 = context.getState(State::Forces | State::Energy);
compareForcesEnergy(testName, state1.getPotentialEnergy(), state2.getPotentialEnergy(), state1.getForces(), state2.getForces(), tolerance);
}
int main(int argc, char* argv[]) {
try {
std::cout << "TestCudaAmoebaWcaDispersionForce running test..." << std::endl;
registerAmoebaCudaKernelFactories();
if (argc > 1)
Platform::getPlatformByName("CUDA").setPropertyDefaultValue("Precision", std::string(argv[1]));
// test Wca dispersion force using two ammonia molecules
testWcaDispersionAmmonia();
} catch(const std::exception& e) {
std::cout << "exception: " << e.what() << std::endl;
std::cout << "FAIL - ERROR. Test failed." << std::endl;
return 1;
}
std::cout << "Done" << std::endl;
return 0;
}
#---------------------------------------------------
# OpenMM OpenCL Amoeba Implementation
#
# Creates OpenMMAmoebaOpenCL library.
#
# Windows:
# OpenMMAmoebaOpenCL.dll
# OpenMMAmoebaOpenCL.lib
# Unix:
# libOpenMMAmoebaOpenCL.so
#----------------------------------------------------
# The source is organized into subdirectories, but we handle them all from
# this CMakeLists file rather than letting CMake visit them as SUBDIRS.
SET(OPENMM_SOURCE_SUBDIRS . ../common)
# Collect up information about the version of the OpenMM library we're building
# and make it available to the code so it can be built into the binaries.
SET(OPENMMAMOEBAOPENCL_LIBRARY_NAME OpenMMAmoebaOpenCL)
SET(SHARED_TARGET ${OPENMMAMOEBAOPENCL_LIBRARY_NAME})
SET(STATIC_TARGET ${OPENMMAMOEBAOPENCL_LIBRARY_NAME}_static)
# These are all the places to search for header files which are
# to be part of the API.
SET(API_INCLUDE_DIRS) # start empty
FOREACH(subdir ${OPENMM_SOURCE_SUBDIRS})
# append
SET(API_INCLUDE_DIRS ${API_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/include
${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/include/internal)
ENDFOREACH(subdir)
# We'll need both *relative* path names, starting with their API_INCLUDE_DIRS,
# and absolute pathnames.
SET(API_REL_INCLUDE_FILES) # start these out empty
SET(API_ABS_INCLUDE_FILES)
FOREACH(dir ${API_INCLUDE_DIRS})
FILE(GLOB fullpaths ${dir}/*.h) # returns full pathnames
SET(API_ABS_INCLUDE_FILES ${API_ABS_INCLUDE_FILES} ${fullpaths})
FOREACH(pathname ${fullpaths})
GET_FILENAME_COMPONENT(filename ${pathname} NAME)
SET(API_REL_INCLUDE_FILES ${API_REL_INCLUDE_FILES} ${dir}/${filename})
ENDFOREACH(pathname)
ENDFOREACH(dir)
# collect up source files
SET(SOURCE_FILES) # empty
SET(SOURCE_INCLUDE_FILES)
FOREACH(subdir ${OPENMM_SOURCE_SUBDIRS})
FILE(GLOB_RECURSE src_files ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/src/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/src/*.c)
FILE(GLOB incl_files ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/src/*.h)
SET(SOURCE_FILES ${SOURCE_FILES} ${src_files}) #append
SET(SOURCE_INCLUDE_FILES ${SOURCE_INCLUDE_FILES} ${incl_files})
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/include)
ENDFOREACH(subdir)
SET(COMMON_KERNELS_CPP ${CMAKE_CURRENT_BINARY_DIR}/../common/src/CommonAmoebaKernelSources.cpp)
SET(SOURCE_FILES ${SOURCE_FILES} ${COMMON_KERNELS_CPP})
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/src)
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/../common/src)
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_SOURCE_DIR}/platforms/opencl/include)
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_SOURCE_DIR}/platforms/opencl/src)
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_BINARY_DIR}/platforms/opencl/src)
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_SOURCE_DIR}/platforms/common/include)
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_BINARY_DIR}/platforms/common/src)
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/../common/src)
# Create the library
INCLUDE_DIRECTORIES(${OPENCL_INCLUDE_DIR})
SET_SOURCE_FILES_PROPERTIES(${COMMON_KERNELS_CPP} PROPERTIES GENERATED TRUE)
# Build the shared plugin library.
IF (OPENMM_BUILD_SHARED_LIB)
ADD_LIBRARY(${SHARED_TARGET} SHARED ${SOURCE_FILES} ${SOURCE_INCLUDE_FILES} ${API_ABS_INCLUDE_FILES})
ADD_DEPENDENCIES(${SHARED_TARGET} AmoebaCommonKernels)
TARGET_LINK_LIBRARIES(${SHARED_TARGET} ${OPENMM_LIBRARY_NAME} ${PTHREADS_LIB})
TARGET_LINK_LIBRARIES(${SHARED_TARGET} ${OPENMM_LIBRARY_NAME}OpenCL)
TARGET_LINK_LIBRARIES(${SHARED_TARGET} ${SHARED_AMOEBA_TARGET})
SET_TARGET_PROPERTIES(${SHARED_TARGET} PROPERTIES COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_BUILDING_SHARED_LIBRARY")
INSTALL_TARGETS(/lib/plugins RUNTIME_DIRECTORY /lib/plugins ${SHARED_TARGET})
ENDIF (OPENMM_BUILD_SHARED_LIB)
# Build the static plugin library.
IF(OPENMM_BUILD_STATIC_LIB)
ADD_LIBRARY(${STATIC_TARGET} STATIC ${SOURCE_FILES} ${SOURCE_INCLUDE_FILES} ${API_ABS_INCLUDE_FILES})
TARGET_LINK_LIBRARIES(${STATIC_TARGET} ${OPENMM_LIBRARY_NAME} ${PTHREADS_LIB})
TARGET_LINK_LIBRARIES(${STATIC_TARGET} ${OPENMM_LIBRARY_NAME}OpenCL)
TARGET_LINK_LIBRARIES(${STATIC_TARGET} ${STATIC_AMOEBA_TARGET})
SET_TARGET_PROPERTIES(${STATIC_TARGET} PROPERTIES COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_BUILDING_STATIC_LIBRARY")
INSTALL_TARGETS(/lib/plugins RUNTIME_DIRECTORY /lib/plugins ${STATIC_TARGET})
ENDIF(OPENMM_BUILD_STATIC_LIB)
INSTALL(TARGETS ${SHARED_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/plugins)
# Ensure that links to the main OpenCL library will be resolved.
IF (APPLE)
SET(OPENCL_LIBRARY libOpenMMOpenCL.dylib)
INSTALL(CODE "EXECUTE_PROCESS(COMMAND install_name_tool -change ${OPENCL_LIBRARY} @loader_path/${OPENCL_LIBRARY} ${CMAKE_INSTALL_PREFIX}/lib/plugins/lib${SHARED_TARGET}.dylib)")
ENDIF (APPLE)
if(OPENMM_BUILD_OPENCL_TESTS)
SUBDIRS (tests)
endif(OPENMM_BUILD_OPENCL_TESTS)
#ifndef AMOEBA_OPENMM_OPENCLKERNELFACTORY_H_
#define AMOEBA_OPENMM_OPENCLKERNELFACTORY_H_
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2021 Stanford University and the Authors. *
* Authors: *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/KernelFactory.h"
namespace OpenMM {
/**
* This KernelFactory creates all kernels for the AMOEBA OpenCL platform.
*/
class AmoebaOpenCLKernelFactory : public KernelFactory {
public:
KernelImpl* createKernelImpl(std::string name, const Platform& platform, ContextImpl& context) const;
};
} // namespace OpenMM
#endif /*AMOEBA_OPENMM_OPENCLKERNELFACTORY_H_*/
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2021 Stanford University and the Authors. *
* Authors: Mark Friedrichs, Peter Eastman *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "AmoebaOpenCLKernelFactory.h"
#include "AmoebaOpenCLKernels.h"
#include "AmoebaCommonKernels.h"
#include "OpenCLContext.h"
#include "OpenCLPlatform.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/OpenMMException.h"
#include "openmm/internal/windowsExport.h"
using namespace OpenMM;
#ifdef OPENMM_BUILDING_STATIC_LIBRARY
static void registerPlatforms() {
#else
extern "C" OPENMM_EXPORT void registerPlatforms() {
#endif
}
#ifdef OPENMM_BUILDING_STATIC_LIBRARY
static void registerKernelFactories() {
#else
extern "C" OPENMM_EXPORT void registerKernelFactories() {
#endif
try {
Platform& platform = Platform::getPlatformByName("OpenCL");
AmoebaOpenCLKernelFactory* factory = new AmoebaOpenCLKernelFactory();
platform.registerKernelFactory(CalcAmoebaTorsionTorsionForceKernel::Name(), factory);
platform.registerKernelFactory(CalcAmoebaMultipoleForceKernel::Name(), factory);
platform.registerKernelFactory(CalcAmoebaGeneralizedKirkwoodForceKernel::Name(), factory);
platform.registerKernelFactory(CalcAmoebaVdwForceKernel::Name(), factory);
platform.registerKernelFactory(CalcAmoebaWcaDispersionForceKernel::Name(), factory);
platform.registerKernelFactory(CalcHippoNonbondedForceKernel::Name(), factory);
}
catch (...) {
// Ignore. The OpenCL platform isn't available.
}
}
extern "C" OPENMM_EXPORT void registerAmoebaOpenCLKernelFactories() {
try {
Platform::getPlatformByName("OpenCL");
}
catch (...) {
Platform::registerPlatform(new OpenCLPlatform());
}
registerKernelFactories();
}
KernelImpl* AmoebaOpenCLKernelFactory::createKernelImpl(std::string name, const Platform& platform, ContextImpl& context) const {
OpenCLPlatform::PlatformData& data = *static_cast<OpenCLPlatform::PlatformData*>(context.getPlatformData());
OpenCLContext& cc = *data.contexts[0];
if (name == CalcAmoebaTorsionTorsionForceKernel::Name())
return new CommonCalcAmoebaTorsionTorsionForceKernel(name, platform, cc, context.getSystem());
if (name == CalcAmoebaMultipoleForceKernel::Name())
return new OpenCLCalcAmoebaMultipoleForceKernel(name, platform, cc, context.getSystem());
if (name == CalcAmoebaGeneralizedKirkwoodForceKernel::Name())
return new CommonCalcAmoebaGeneralizedKirkwoodForceKernel(name, platform, cc, context.getSystem());
if (name == CalcAmoebaVdwForceKernel::Name())
return new CommonCalcAmoebaVdwForceKernel(name, platform, cc, context.getSystem());
if (name == CalcAmoebaWcaDispersionForceKernel::Name())
return new CommonCalcAmoebaWcaDispersionForceKernel(name, platform, cc, context.getSystem());
if (name == CalcHippoNonbondedForceKernel::Name())
return new OpenCLCalcHippoNonbondedForceKernel(name, platform, cc, context.getSystem());
throw OpenMMException((std::string("Tried to create kernel with illegal kernel name '")+name+"'").c_str());
}
\ No newline at end of file
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2021 Stanford University and the Authors. *
* Authors: Peter Eastman, Mark Friedrichs *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "AmoebaOpenCLKernels.h"
using namespace OpenMM;
using namespace std;
/* -------------------------------------------------------------------------- *
* AmoebaMultipole *
* -------------------------------------------------------------------------- */
OpenCLCalcAmoebaMultipoleForceKernel::~OpenCLCalcAmoebaMultipoleForceKernel() {
if (fft != NULL)
delete fft;
}
void OpenCLCalcAmoebaMultipoleForceKernel::initialize(const System& system, const AmoebaMultipoleForce& force) {
CommonCalcAmoebaMultipoleForceKernel::initialize(system, force);
if (usePME)
fft = new OpenCLFFT3D(dynamic_cast<OpenCLContext&>(cc), gridSizeX, gridSizeY, gridSizeZ, false);
}
void OpenCLCalcAmoebaMultipoleForceKernel::computeFFT(bool forward) {
OpenCLArray& grid1 = dynamic_cast<OpenCLContext&>(cc).unwrap(pmeGrid1);
OpenCLArray& grid2 = dynamic_cast<OpenCLContext&>(cc).unwrap(pmeGrid2);
if (forward)
fft->execFFT(grid1, grid2, true);
else
fft->execFFT(grid2, grid1, false);
}
/* -------------------------------------------------------------------------- *
* HippoNonbondedForce *
* -------------------------------------------------------------------------- */
OpenCLCalcHippoNonbondedForceKernel::~OpenCLCalcHippoNonbondedForceKernel() {
if (sort != NULL)
delete sort;
if (hasInitializedFFT) {
delete fftForward;
delete dfftForward;
}
}
void OpenCLCalcHippoNonbondedForceKernel::initialize(const System& system, const HippoNonbondedForce& force) {
CommonCalcHippoNonbondedForceKernel::initialize(system, force);
if (usePME) {
OpenCLContext& cl = dynamic_cast<OpenCLContext&>(cc);
sort = new OpenCLSort(cl, new SortTrait(), cc.getNumAtoms());
fftForward = new OpenCLFFT3D(cl, gridSizeX, gridSizeY, gridSizeZ, true);
dfftForward = new OpenCLFFT3D(cl, dispersionGridSizeX, dispersionGridSizeY, dispersionGridSizeZ, true);
hasInitializedFFT = true;
}
}
void OpenCLCalcHippoNonbondedForceKernel::computeFFT(bool forward, bool dispersion) {
OpenCLArray& grid1 = dynamic_cast<OpenCLContext&>(cc).unwrap(pmeGrid1);
OpenCLArray& grid2 = dynamic_cast<OpenCLContext&>(cc).unwrap(pmeGrid2);
OpenCLFFT3D* fft = (dispersion ? dfftForward : fftForward);
if (forward)
fft->execFFT(grid1, grid2, true);
else
fft->execFFT(grid2, grid1, false);
}
void OpenCLCalcHippoNonbondedForceKernel::sortGridIndex() {
sort->sort(dynamic_cast<OpenCLContext&>(cc).unwrap(pmeAtomGridIndex));
}
#ifndef AMOEBA_OPENMM_OPENCLKERNELS_H
#define AMOEBA_OPENMM_OPENCLKERNELS_H
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2021 Stanford University and the Authors. *
* Authors: Mark Friedrichs, Peter Eastman *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/amoebaKernels.h"
#include "openmm/kernels.h"
#include "openmm/System.h"
#include "AmoebaCommonKernels.h"
#include "OpenCLContext.h"
#include "OpenCLFFT3D.h"
#include "OpenCLSort.h"
namespace OpenMM {
/**
* This kernel is invoked by AmoebaMultipoleForce to calculate the forces acting on the system and the energy of the system.
*/
class OpenCLCalcAmoebaMultipoleForceKernel : public CommonCalcAmoebaMultipoleForceKernel {
public:
OpenCLCalcAmoebaMultipoleForceKernel(const std::string& name, const Platform& platform, OpenCLContext& cl, const System& system) :
CommonCalcAmoebaMultipoleForceKernel(name, platform, cl, system), fft(NULL) {
}
~OpenCLCalcAmoebaMultipoleForceKernel();
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the AmoebaMultipoleForce this kernel will be used for
*/
void initialize(const System& system, const AmoebaMultipoleForce& force);
/**
* Compute the FFT.
*/
void computeFFT(bool forward);
/**
* Get whether charge spreading should be done in fixed point.
*/
bool useFixedPointChargeSpreading() const {
return true;
}
private:
OpenCLFFT3D* fft;
};
/**
* This kernel is invoked by HippoNonbondedForce to calculate the forces acting on the system and the energy of the system.
*/
class OpenCLCalcHippoNonbondedForceKernel : public CommonCalcHippoNonbondedForceKernel {
public:
OpenCLCalcHippoNonbondedForceKernel(const std::string& name, const Platform& platform, OpenCLContext& cl, const System& system) :
CommonCalcHippoNonbondedForceKernel(name, platform, cl, system), sort(NULL), hasInitializedFFT(false) {
}
~OpenCLCalcHippoNonbondedForceKernel();
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the HippoNonbondedForce this kernel will be used for
*/
void initialize(const System& system, const HippoNonbondedForce& force);
/**
* Compute the FFT.
*/
void computeFFT(bool forward, bool dispersion);
/**
* Get whether charge spreading should be done in fixed point.
*/
bool useFixedPointChargeSpreading() const {
return true;
}
/**
* Sort the atom grid indices.
*/
void sortGridIndex();
private:
class SortTrait : public OpenCLSort::SortTrait {
int getDataSize() const {return 8;}
int getKeySize() const {return 4;}
const char* getDataType() const {return "int2";}
const char* getKeyType() const {return "int";}
const char* getMinKey() const {return "(-2147483647-1)";}
const char* getMaxKey() const {return "2147483647";}
const char* getMaxValue() const {return "make_int2(2147483647, 2147483647)";}
const char* getSortKey() const {return "value.y";}
};
bool hasInitializedFFT;
OpenCLSort* sort;
OpenCLFFT3D *fftForward, *fftBackward, *dfftForward, *dfftBackward;
};
} // namespace OpenMM
#endif /*AMOEBA_OPENMM_OPENCLKERNELS_H*/
#
# Testing
#
ENABLE_TESTING()
INCLUDE_DIRECTORIES(${OPENCL_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${OPENMM_DIR}/plugins/amoeba/tests)
INCLUDE_DIRECTORIES(${OPENMM_DIR}/platforms/opencl/tests)
# Automatically create tests using files named "Test*.cpp"
FILE(GLOB TEST_PROGS "*Test*.cpp")
FOREACH(TEST_PROG ${TEST_PROGS})
GET_FILENAME_COMPONENT(TEST_ROOT ${TEST_PROG} NAME_WE)
# Link with shared library
ADD_EXECUTABLE(${TEST_ROOT} ${TEST_PROG})
TARGET_LINK_LIBRARIES(${TEST_ROOT} ${SHARED_AMOEBA_TARGET} ${SHARED_TARGET})
SET_TARGET_PROPERTIES(${TEST_ROOT} PROPERTIES LINK_FLAGS "${EXTRA_LINK_FLAGS}" COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS}")
ADD_TEST(${TEST_ROOT}Single ${EXECUTABLE_OUTPUT_PATH}/${TEST_ROOT} single ${OPENCL_TEST_PLATFORM_INDEX} ${OPENCL_TEST_DEVICE_INDEX})
IF (OPENMM_BUILD_OPENCL_DOUBLE_PRECISION_TESTS)
ADD_TEST(${TEST_ROOT}Mixed ${EXECUTABLE_OUTPUT_PATH}/${TEST_ROOT} mixed ${OPENCL_TEST_PLATFORM_INDEX} ${OPENCL_TEST_DEVICE_INDEX})
# Some AMOEBA classes don't work correctly in double precision on some OpenCL implementations.
# Eventually it would be good to make them work, but for the moment just skip those tests.
#ADD_TEST(${TEST_ROOT}Double ${EXECUTABLE_OUTPUT_PATH}/${TEST_ROOT} double ${OPENCL_TEST_PLATFORM_INDEX} ${OPENCL_TEST_DEVICE_INDEX})
ENDIF(OPENMM_BUILD_OPENCL_DOUBLE_PRECISION_TESTS)
ENDFOREACH(TEST_PROG ${TEST_PROGS})
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2013 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "OpenCLTests.h"
extern "C" void registerAmoebaOpenCLKernelFactories();
using namespace OpenMM;
void setupKernels (int argc, char* argv[]) {
registerAmoebaOpenCLKernelFactories();
platform = dynamic_cast<OpenCLPlatform&>(Platform::getPlatformByName("OpenCL"));
initializeTests(argc, argv);
}
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2021 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "OpenCLAmoebaTests.h"
#include "TestAmoebaExtrapolatedPolarization.h"
void runPlatformTests() {}
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2021 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "OpenCLAmoebaTests.h"
#include "TestAmoebaGeneralizedKirkwoodForce.h"
void runPlatformTests() {}
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