45#include "applications/staticProps/GofRAngle.hpp" 
   52#include "types/MultipoleAdapter.hpp" 
   53#include "utils/Revision.hpp" 
   54#include "utils/simError.h" 
   58  GofRAngle::GofRAngle(SimInfo* info, 
const std::string& filename,
 
   59                       const std::string& sele1, 
const std::string& sele2,
 
   60                       RealType len, 
int nrbins, 
int nangleBins) :
 
   61      RadialDistrFunc(info, filename, sele1, sele2, nrbins),
 
   62      nAngleBins_(nangleBins), len_(len), doSele3_(false), seleMan3_(info),
 
   64    deltaR_        = len_ / (double)nBins_;
 
   65    deltaCosAngle_ = 2.0 / (double)nAngleBins_;
 
   66    histogram_.resize(nBins_);
 
   67    avgGofr_.resize(nBins_);
 
   68    for (
unsigned int i = 0; i < nBins_; ++i) {
 
   69      histogram_[i].resize(nAngleBins_);
 
   70      avgGofr_[i].resize(nAngleBins_);
 
   73    setAnalysisType(
"Radial Distribution Function");
 
   75    std::stringstream params;
 
   76    params << 
" nBins = " << nBins_ << 
", maxLen = " << len_
 
   77           << 
", deltaR = " << deltaR_ << 
", nAngleBins = " << nAngleBins_
 
   78           << 
", deltaCosAngle = " << deltaCosAngle_;
 
   79    const std::string paramString = params.str();
 
   80    setParameterString(paramString);
 
   83  GofRAngle::GofRAngle(SimInfo* info, 
const std::string& filename,
 
   84                       const std::string& sele1, 
const std::string& sele2,
 
   85                       const std::string& sele3, RealType len, 
int nrbins,
 
   87      RadialDistrFunc(info, filename, sele1, sele2, nrbins),
 
   88      nAngleBins_(nangleBins), len_(len), doSele3_(true),
 
   89      selectionScript3_(sele3), seleMan3_(info), evaluator3_(info) {
 
   90    deltaR_        = len_ / (double)nBins_;
 
   91    deltaCosAngle_ = 2.0 / (double)nAngleBins_;
 
   92    histogram_.resize(nBins_);
 
   93    avgGofr_.resize(nBins_);
 
   94    for (
unsigned int i = 0; i < nBins_; ++i) {
 
   95      histogram_[i].resize(nAngleBins_);
 
   96      avgGofr_[i].resize(nAngleBins_);
 
   99    evaluator3_.loadScriptString(sele3);
 
  100    if (!evaluator3_.isDynamic()) {
 
  101      seleMan3_.setSelectionSet(evaluator3_.evaluate());
 
  105  void GofRAngle::processNonOverlapping(SelectionManager& sman1,
 
  106                                        SelectionManager& sman2) {
 
  120      if (evaluator3_.isDynamic()) {
 
  121        seleMan3_.setSelectionSet(evaluator3_.evaluate());
 
  123      if (sman1.getSelectionCount() != seleMan3_.getSelectionCount()) {
 
  124        RadialDistrFunc::processNonOverlapping(sman1, sman2);
 
  127      for (sd1 = sman1.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
 
  128           sd1 != NULL && sd3 != NULL;
 
  129           sd1 = sman1.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
 
  130        for (sd2 = sman2.beginSelected(j); sd2 != NULL;
 
  131             sd2 = sman2.nextSelected(j)) {
 
  132          collectHistogram(sd1, sd2, sd3);
 
  136      RadialDistrFunc::processNonOverlapping(sman1, sman2);
 
  140  void GofRAngle::processOverlapping(SelectionManager& sman) {
 
  154      if (evaluator3_.isDynamic()) {
 
  155        seleMan3_.setSelectionSet(evaluator3_.evaluate());
 
  157      if (sman.getSelectionCount() != seleMan3_.getSelectionCount()) {
 
  158        RadialDistrFunc::processOverlapping(sman);
 
  160      for (sd1 = sman.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
 
  161           sd1 != NULL && sd3 != NULL;
 
  162           sd1 = sman.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
 
  163        for (j = i, sd2 = sman.nextSelected(j); sd2 != NULL;
 
  164             sd2 = sman.nextSelected(j)) {
 
  165          collectHistogram(sd1, sd2, sd3);
 
  169      RadialDistrFunc::processOverlapping(sman);
 
  173  void GofRAngle::preProcess() {
 
  174    for (
unsigned int i = 0; i < avgGofr_.size(); ++i) {
 
  175      std::fill(avgGofr_[i].begin(), avgGofr_[i].end(), 0);
 
  179  void GofRAngle::initializeHistogram() {
 
  181    for (
unsigned int i = 0; i < histogram_.size(); ++i) {
 
  182      std::fill(histogram_[i].begin(), histogram_[i].end(), 0);
 
  186  void GofRAngle::processHistogram() {
 
  187    int nPairs = getNPairs();
 
  189        info_->getSnapshotManager()->getCurrentSnapshot()->getVolume();
 
  190    RealType pairDensity  = nPairs / volume;
 
  191    RealType pairConstant = (4.0 * Constants::PI * pairDensity) / 3.0;
 
  193    for (
unsigned int i = 0; i < histogram_.size(); ++i) {
 
  194      RealType rLower = i * deltaR_;
 
  195      RealType rUpper = rLower + deltaR_;
 
  197          (rUpper * rUpper * rUpper) - (rLower * rLower * rLower);
 
  198      RealType nIdeal = volSlice * pairConstant;
 
  200      for (
unsigned int j = 0; j < histogram_[i].size(); ++j) {
 
  201        avgGofr_[i][j] += histogram_[i][j] / nIdeal;
 
  206  void GofRTheta::processHistogram() {
 
  207    int nPairs = getNPairs();
 
  209        info_->getSnapshotManager()->getCurrentSnapshot()->getVolume();
 
  210    RealType pairDensity = nPairs / volume;
 
  211    RealType pairConstant =
 
  212        (4.0 * Constants::PI * pairDensity) / (3.0 * (
double)nAngleBins_);
 
  214    for (
unsigned int i = 0; i < histogram_.size(); ++i) {
 
  215      RealType rLower = i * deltaR_;
 
  216      RealType rUpper = rLower + deltaR_;
 
  218          (rUpper * rUpper * rUpper) - (rLower * rLower * rLower);
 
  219      RealType nIdeal = volSlice * pairConstant;
 
  221      for (
unsigned int j = 0; j < histogram_[i].size(); ++j) {
 
  222        avgGofr_[i][j] += histogram_[i][j] / nIdeal;
 
  227  void GofRAngle::collectHistogram(StuntDouble* sd1, StuntDouble* sd2) {
 
  228    if (sd1 == sd2) { 
return; }
 
  229    bool usePeriodicBoundaryConditions_ =
 
  230        info_->getSimParams()->getUsePeriodicBoundaryConditions();
 
  232    Vector3d pos1 = sd1->getPos();
 
  233    Vector3d pos2 = sd2->getPos();
 
  234    Vector3d r12  = pos2 - pos1;
 
  235    if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
 
  238    int whichRBin     = int(distance / deltaR_);
 
  240    if (distance <= len_) {
 
  241      RealType cosAngle = evaluateAngle(sd1, sd2);
 
  242      RealType halfBin  = (nAngleBins_ - 1) * 0.5;
 
  243      int whichThetaBin = int(halfBin * (cosAngle + 1.0));
 
  244      ++histogram_[whichRBin][whichThetaBin];
 
  250  void GofRAngle::collectHistogram(StuntDouble* sd1, StuntDouble* sd2,
 
  252    if (sd1 == sd2) { 
return; }
 
  253    bool usePeriodicBoundaryConditions_ =
 
  254        info_->getSimParams()->getUsePeriodicBoundaryConditions();
 
  256    Vector3d p1 = sd1->getPos();
 
  257    Vector3d p3 = sd3->getPos();
 
  259    Vector3d c   = 0.5 * (p1 + p3);
 
  260    Vector3d r13 = p3 - p1;
 
  262    Vector3d r12 = sd2->getPos() - c;
 
  264    if (usePeriodicBoundaryConditions_) {
 
  265      currentSnapshot_->wrapVector(r12);
 
  266      currentSnapshot_->wrapVector(r13);
 
  270    int whichRBin     = int(distance / deltaR_);
 
  272    if (distance <= len_) {
 
  273      RealType cosAngle = evaluateAngle(sd1, sd2, sd3);
 
  274      RealType halfBin  = (nAngleBins_ - 1) * 0.5;
 
  275      int whichThetaBin = int(halfBin * (cosAngle + 1.0));
 
  276      ++histogram_[whichRBin][whichThetaBin];
 
  282  void GofRAngle::writeRdf() {
 
  283    std::ofstream ofs(outputFilename_.c_str());
 
  286      ofs << 
"# " << getAnalysisType() << 
"\n";
 
  287      ofs << 
"# OpenMD " << r.getFullRevision() << 
"\n";
 
  288      ofs << 
"# " << r.getBuildDate() << 
"\n";
 
  289      ofs << 
"# selection script1: \"" << selectionScript1_;
 
  290      ofs << 
"\"\tselection script2: \"" << selectionScript2_ << 
"\"";
 
  292        ofs << 
"\tselection script3: \"" << selectionScript3_ << 
"\"\n";
 
  297      if (!paramString_.empty())
 
  298        ofs << 
"# parameters: " << paramString_ << 
"\n";
 
  300      for (
unsigned int i = 0; i < avgGofr_.size(); ++i) {
 
  303        for (
unsigned int j = 0; j < avgGofr_[i].size(); ++j) {
 
  305          ofs << avgGofr_[i][j] / nProcessed_ << 
"\t";
 
  312      snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
 
  313               "GofRAngle: unable to open %s\n", outputFilename_.c_str());
 
  314      painCave.isFatal = 1;
 
  321  RealType GofRTheta::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2) {
 
  322    bool usePeriodicBoundaryConditions_ =
 
  323        info_->getSimParams()->getUsePeriodicBoundaryConditions();
 
  325    Vector3d pos1 = sd1->getPos();
 
  326    Vector3d pos2 = sd2->getPos();
 
  327    Vector3d r12  = pos2 - pos1;
 
  329    if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
 
  335    if (!sd1->isDirectional()) {
 
  336      snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
 
  337               "GofRTheta: attempted to use a non-directional object: %s\n",
 
  338               sd1->getType().c_str());
 
  339      painCave.isFatal = 1;
 
  344      AtomType* atype1     = 
static_cast<Atom*
>(sd1)->getAtomType();
 
  345      MultipoleAdapter ma1 = MultipoleAdapter(atype1);
 
  348        vec = sd1->getDipole();
 
  350        vec = sd1->getA().transpose() * V3Z;
 
  352      vec = sd1->getA().transpose() * V3Z;
 
  357    return dot(r12, vec);
 
  360  RealType GofRTheta::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2,
 
  362    bool usePeriodicBoundaryConditions_ =
 
  363        info_->getSimParams()->getUsePeriodicBoundaryConditions();
 
  365    Vector3d p1 = sd1->getPos();
 
  366    Vector3d p3 = sd3->getPos();
 
  368    Vector3d c   = 0.5 * (p1 + p3);
 
  369    Vector3d r13 = p3 - p1;
 
  371    Vector3d r12 = sd2->getPos() - c;
 
  373    if (usePeriodicBoundaryConditions_) {
 
  374      currentSnapshot_->wrapVector(r12);
 
  375      currentSnapshot_->wrapVector(r13);
 
  381    return dot(r12, r13);
 
  384  RealType GofROmega::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2) {
 
  387    if (!sd1->isDirectional()) {
 
  388      snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
 
  389               "GofROmega: attempted to use a non-directional object: %s\n",
 
  390               sd1->getType().c_str());
 
  391      painCave.isFatal = 1;
 
  396      AtomType* atype1     = 
static_cast<Atom*
>(sd1)->getAtomType();
 
  397      MultipoleAdapter ma1 = MultipoleAdapter(atype1);
 
  399        v1 = sd1->getDipole();
 
  401        v1 = sd1->getA().transpose() * V3Z;
 
  403      v1 = sd1->getA().transpose() * V3Z;
 
  406    if (!sd2->isDirectional()) {
 
  407      snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
 
  408               "GofROmega attempted to use a non-directional object: %s\n",
 
  409               sd2->getType().c_str());
 
  410      painCave.isFatal = 1;
 
  415      AtomType* atype2     = 
static_cast<Atom*
>(sd2)->getAtomType();
 
  416      MultipoleAdapter ma2 = MultipoleAdapter(atype2);
 
  419        v2 = sd2->getDipole();
 
  421        v2 = sd2->getA().transpose() * V3Z;
 
  423      v2 = sd2->getA().transpose() * V3Z;
 
  431  RealType GofROmega::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2,
 
  433    bool usePeriodicBoundaryConditions_ =
 
  434        info_->getSimParams()->getUsePeriodicBoundaryConditions();
 
  439    v1 = sd3->getPos() - sd1->getPos();
 
  440    if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(v1);
 
  442    if (!sd2->isDirectional()) {
 
  443      snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
 
  444               "GofROmega: attempted to use a non-directional object: %s\n",
 
  445               sd2->getType().c_str());
 
  446      painCave.isFatal = 1;
 
  451      AtomType* atype2     = 
static_cast<Atom*
>(sd2)->getAtomType();
 
  452      MultipoleAdapter ma2 = MultipoleAdapter(atype2);
 
  455        v2 = sd2->getDipole();
 
  457        v2 = sd2->getA().transpose() * V3Z;
 
  459      v2 = sd2->getA().transpose() * V3Z;
 
void normalize()
Normalizes this vector in place.
 
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
 
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
 
Real distance(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the distance between two DynamicVectors.