Esempio n. 1
0
/** \param a1 First set of XYZ coordinates.
  * \param a2 Second set of XYZ coordinates.
  * \param ucell Unit cell vectors.
  * \param recip Fractional cell vectors.
  * \return the shortest vector from a1 to a2. 
  */
Vec3 MinImagedVec(Vec3 const& a1, Vec3 const& a2,
                  Matrix_3x3 const& ucell, Matrix_3x3 const& recip)
{
  Vec3 f1 = recip * a1;
  Vec3 f2 = recip * a2;
//  mprintf("DEBUG: a1= %g %g %g, f1= %g %g %g\n", a1[0], a1[1], a1[2], f1[0], f1[1], f1[2]);
//  mprintf("DEBUG: a2= %g %g %g, f2= %g %g %g\n", a2[0], a2[1], a2[2], f2[0], f2[1], f2[2]);
  for (unsigned int i = 0; i < 3; i++) {
    f1[i] = f1[i] - floor(f1[i]);
    f2[i] = f2[i] - floor(f2[i]);
  }
  // Self
  Vec3 c1 = ucell.TransposeMult( f1 );
  Vec3 c2 = ucell.TransposeMult( f2 );
  Vec3 minVec = c2 - c1;
  double minDist2 = minVec.Magnitude2();
  // Images
  for (int ix = -1; ix < 2; ix++) {
    for (int iy = -1; iy < 2; iy++) {
      for (int iz = -1; iz < 2; iz++) {
        if (ix != 0 || iy != 0 || iz != 0) { // Ignore a2 self
          Vec3 ixyz(ix, iy, iz);
          c2 = ucell.TransposeMult(f2 + ixyz); // a2 image back in Cartesian space
          Vec3 dxyz = c2 - c1;
          double dist2 = dxyz.Magnitude2();
          if (dist2 < minDist2) {
            minDist2 = dist2;
            minVec = dxyz;
          }
        }
      }
    }
  }
  return minVec;
}
Esempio n. 2
0
// Action_ReplicateCell::Init()
Action::RetType Action_ReplicateCell::Init(ArgList& actionArgs, ActionInit& init, int debugIn)
{
  // Require imaging.
  image_.InitImaging( true );
  // Set up output traj
  std::string trajfilename = actionArgs.GetStringKey("out");
  parmfilename_ = actionArgs.GetStringKey("parmout");
  bool setAll = actionArgs.hasKey("all");
  std::string dsname = actionArgs.GetStringKey("name");
  if (!dsname.empty()) {
    coords_ = (DataSet_Coords*)init.DSL().AddSet(DataSet::COORDS, dsname, "RCELL");
    if (coords_ == 0) return Action::ERR;
  }
  if (trajfilename.empty() && coords_ == 0) {
    mprinterr("Error: Either 'out <traj filename> or 'name <dsname>' must be specified.\n");
    return Action::ERR;
  }
  // Get Mask
  Mask1_.SetMaskString( actionArgs.GetMaskNext() );

  // Determine which directions to set
  if (setAll) {
    for (int ix = -1; ix < 2; ix++)
      for (int iy = -1; iy < 2; iy++)
        for (int iz = -1; iz < 2; iz++) {
          directionArray_.push_back( ix );
          directionArray_.push_back( iy );
          directionArray_.push_back( iz );
        }
  } else {
    std::string dirstring = actionArgs.GetStringKey("dir");
    while (!dirstring.empty()) {
      std::vector<int> ixyz(3, -2);
      std::vector<int>::iterator iptr = ixyz.begin();
      for (std::string::const_iterator c = dirstring.begin();
                                       c != dirstring.end(); ++c)
      {
        if (iptr == ixyz.end()) {
          mprinterr("Error: 'dir' string has too many characters.\n");
          return Action::ERR;
        }
        int sign = 1;
        if      (*c == '+') ++c;
        else if (*c == '-') { sign = -1; ++c; }
        
        if (isdigit( *c ))
          *iptr = toDigit( *c ) * sign;
        else {
          mprinterr("Error: illegal character '%c' in 'dir' string '%s'; only numbers allowed.\n",
                    *c, dirstring.c_str());
          return Action::ERR;
        }
        ++iptr;
      }
      //mprintf("DEBUG: %s = %i %i %i\n", dirstring.c_str(), ixyz[0], ixyz[1], ixyz[2]);
      directionArray_.push_back( ixyz[0] );
      directionArray_.push_back( ixyz[1] );
      directionArray_.push_back( ixyz[2] );
      dirstring = actionArgs.GetStringKey("dir");
    }
  }
  ncopies_ = (int)(directionArray_.size() / 3);
  if (ncopies_ < 1) {
    mprinterr("Error: No directions (or 'all') specified.\n");
    return Action::ERR;
  }
  // Initialize output trajectory with remaining arguments
  if (!trajfilename.empty()) {
    outtraj_.SetDebug( debugIn );
    if ( outtraj_.InitEnsembleTrajWrite(trajfilename, actionArgs.RemainingArgs(),
                                        TrajectoryFile::UNKNOWN_TRAJ, init.DSL().EnsembleNum()) )
      return Action::ERR;
    writeTraj_ = true;
#   ifdef MPI
    outtraj_.SetTrajComm( init.TrajComm() );
#   endif
  } else
    writeTraj_ = false;

  mprintf("    REPLICATE CELL: Replicating cell in %i directions:\n", ncopies_);
  mprintf("\t\t X  Y  Z\n");
  for (unsigned int i = 0; i != directionArray_.size(); i += 3)
    mprintf("\t\t%2i %2i %2i\n", directionArray_[i], 
            directionArray_[i+1], directionArray_[i+2]);
  mprintf("\tUsing atoms in mask '%s'\n", Mask1_.MaskString());
  if (writeTraj_)
    mprintf("\tWriting to trajectory %s\n", outtraj_.Traj().Filename().full());
  if (!parmfilename_.empty())
    mprintf("\tWriting topology %s\n", parmfilename_.c_str());
  if (coords_ != 0)
    mprintf("\tSaving coords to data set %s\n", coords_->legend());

  return Action::OK;
}
Esempio n. 3
0
// Action_Diffusion::DoAction()
Action::RetType Action_Diffusion::DoAction(int frameNum, ActionFrame& frm) {
  Matrix_3x3 ucell, recip;
  // Load initial frame if necessary
  if (initial_.empty()) {
    initial_ = frm.Frm();
#   ifdef MPI
    if (trajComm_.Size() > 1) {
      if (trajComm_.Master())
        for (int rank = 1; rank < trajComm_.Size(); ++rank)
          initial_.SendFrame( rank, trajComm_ );
      else
        initial_.RecvFrame( 0, trajComm_ );
    }
#   endif
    for (AtomMask::const_iterator atom = mask_.begin(); atom != mask_.end(); ++atom)
    {
      const double* XYZ = initial_.XYZ(*atom);
      previous_.push_back( XYZ[0] );
      previous_.push_back( XYZ[1] );
      previous_.push_back( XYZ[2] );
    }
  }
  // Diffusion calculation
  if (image_.ImageType() != NOIMAGE) {
    boxcenter_ = frm.Frm().BoxCrd().Center();
    if (image_.ImageType() == NONORTHO)
      frm.Frm().BoxCrd().ToRecip(ucell, recip);
  }
  // For averaging over selected atoms
  double average2 = 0.0;
  double avgx = 0.0;
  double avgy = 0.0;
  double avgz = 0.0;
  unsigned int idx = 0; // Index into previous_ and delta_
  for (AtomMask::const_iterator at = mask_.begin(); at != mask_.end(); ++at, idx += 3)
  { // Get current and initial coords for this atom.
    const double* XYZ = frm.Frm().XYZ(*at);
    const double* iXYZ = initial_.XYZ(*at);
    // Calculate distance from initial position. 
    double delx, dely, delz;
    if ( image_.ImageType() == ORTHO ) {
      // Orthorhombic imaging
      // Calculate distance to previous frames coordinates.
      delx = XYZ[0] - previous_[idx  ];
      dely = XYZ[1] - previous_[idx+1];
      delz = XYZ[2] - previous_[idx+2];
      // If the particle moved more than half the box, assume it was imaged
      // and adjust the distance of the total movement with respect to the
      // original frame.
      if      (delx >  boxcenter_[0]) delta_[idx  ] -= frm.Frm().BoxCrd().BoxX();
      else if (delx < -boxcenter_[0]) delta_[idx  ] += frm.Frm().BoxCrd().BoxX();
      if      (dely >  boxcenter_[1]) delta_[idx+1] -= frm.Frm().BoxCrd().BoxY();
      else if (dely < -boxcenter_[1]) delta_[idx+1] += frm.Frm().BoxCrd().BoxY();
      if      (delz >  boxcenter_[2]) delta_[idx+2] -= frm.Frm().BoxCrd().BoxZ();
      else if (delz < -boxcenter_[2]) delta_[idx+2] += frm.Frm().BoxCrd().BoxZ();
      // Calculate the distance between this "fixed" coordinate
      // and the reference (initial) frame.
      delx = XYZ[0] + delta_[idx  ] - iXYZ[0];
      dely = XYZ[1] + delta_[idx+1] - iXYZ[1];
      delz = XYZ[2] + delta_[idx+2] - iXYZ[2];
    } else if ( image_.ImageType() == NONORTHO ) {
      // Non-orthorhombic imaging
      // Calculate distance to previous frames coordinates.
      delx = XYZ[0] - previous_[idx  ];
      dely = XYZ[1] - previous_[idx+1];
      delz = XYZ[2] - previous_[idx+2];
      // If the particle moved more than half the box, assume it was imaged
      // and adjust the distance of the total movement with respect to the
      // original frame.
      if (fabs(delx) > boxcenter_[0] ||
          fabs(dely) > boxcenter_[1] ||
          fabs(delz) > boxcenter_[2])
      {
        // Previous position in Cartesian space
        Vec3 pCart( previous_[idx], previous_[idx+1], previous_[idx+2] );
        // Current position in fractional coords
        Vec3 cFrac = recip * Vec3( XYZ[0], XYZ[1], XYZ[2] );
        // Look for imaged distance closer to previous than current position
        double minDist2 = frm.Frm().BoxCrd().BoxX() *
                          frm.Frm().BoxCrd().BoxY() *
                          frm.Frm().BoxCrd().BoxZ();
        Vec3 minCurr(0.0);
        for (int ix = -1; ix < 2; ix++) {
          for (int iy = -1; iy < 2; iy++) {
            for (int iz = -1; iz < 2; iz++) {
              if (ix != 0 || iy != 0 || iz != 0) { // Ignore current position
                Vec3 ixyz(ix, iy, iz);
                // Current position shifted and back in Cartesian space
                Vec3 IMG = ucell.TransposeMult(cFrac + ixyz);
                // Distance from previous position to imaged current position
                Vec3 dxyz = IMG - pCart;
                double dist2 = dxyz.Magnitude2();
                if (dist2 < minDist2) {
                  minDist2 = dist2;
                  minCurr = IMG;
                }
              }
            }
          }
        }
        // Update the delta for this atom
        delta_[idx  ] += minCurr[0] - XYZ[0]; // cCart
        delta_[idx+1] += minCurr[1] - XYZ[1];
        delta_[idx+2] += minCurr[2] - XYZ[2];
      }
      // Calculate the distance between this "fixed" coordinate
      // and the reference (initial) frame.
      delx = XYZ[0] + delta_[idx  ] - iXYZ[0];
      dely = XYZ[1] + delta_[idx+1] - iXYZ[1];
      delz = XYZ[2] + delta_[idx+2] - iXYZ[2];
    } else {
      // No imaging. Calculate distance from current position to initial position.
      delx = XYZ[0] - iXYZ[0];
      dely = XYZ[1] - iXYZ[1];
      delz = XYZ[2] - iXYZ[2];
    }
    // Calc distances for this atom
    double distx = delx * delx;
    double disty = dely * dely;
    double distz = delz * delz;
    double dist2 = distx + disty + distz;
    // Accumulate averages
    avgx += distx;
    avgy += disty;
    avgz += distz;
    average2 += dist2;
    // Store distances for this atom
    if (printIndividual_) {
      float fval = (float)distx;
      atom_x_[*at]->Add(frameNum, &fval);
      fval = (float)disty;
      atom_y_[*at]->Add(frameNum, &fval);
      fval = (float)distz;
      atom_z_[*at]->Add(frameNum, &fval);
      fval = (float)dist2;
      atom_r_[*at]->Add(frameNum, &fval);
      dist2 = sqrt(dist2);
      fval = (float)dist2;
      atom_a_[*at]->Add(frameNum, &fval);
    }
    // Update the previous coordinate set to match the current coordinates
    previous_[idx  ] = XYZ[0];
    previous_[idx+1] = XYZ[1];
    previous_[idx+2] = XYZ[2];
  } // END loop over selected atoms
  // Calc averages
  double dNselected = 1.0 / (double)mask_.Nselected();
  avgx *= dNselected;
  avgy *= dNselected;
  avgz *= dNselected;
  average2 *= dNselected;
  // Save averages
  avg_x_->Add(frameNum, &avgx);
  avg_y_->Add(frameNum, &avgy);
  avg_z_->Add(frameNum, &avgz);
  avg_r_->Add(frameNum, &average2);
  average2 = sqrt(average2);
  avg_a_->Add(frameNum, &average2);
  return Action::OK;
}
// Action_ReplicateCell::Init()
Action::RetType Action_ReplicateCell::Init(ArgList& actionArgs, TopologyList* PFL, DataSetList* DSL, DataFileList* DFL, int debugIn)
{
  // Require imaging.
  image_.InitImaging( true );
  // Set up output traj
  trajfilename_ = actionArgs.GetStringKey("out");
  parmfilename_ = actionArgs.GetStringKey("parmout");
  Topology* tempParm = PFL->GetParm( actionArgs );
  bool setAll = actionArgs.hasKey("all");
  std::string dsname = actionArgs.GetStringKey("name");
  if (!dsname.empty()) {
    coords_ = (DataSet_Coords*)DSL->AddSet(DataSet::COORDS, dsname, "RCELL");
    if (coords_ == 0) return Action::ERR;
  }
  if (trajfilename_.empty() && coords_ == 0) {
    mprinterr("Error: Either 'out <traj filename> or 'name <dsname>' must be specified.\n");
    return Action::ERR;
  }
  // Get Mask
  Mask1_.SetMaskString( actionArgs.GetMaskNext() );

  // Determine which directions to set
  if (setAll) {
    for (int ix = -1; ix < 2; ix++)
      for (int iy = -1; iy < 2; iy++)
        for (int iz = -1; iz < 2; iz++) {
          directionArray_.push_back( ix );
          directionArray_.push_back( iy );
          directionArray_.push_back( iz );
        }
  } else {
    std::string dirstring = actionArgs.GetStringKey("dir");
    while (!dirstring.empty()) {
      std::vector<int> ixyz(3, -2);
      std::vector<int>::iterator iptr = ixyz.begin();
      for (std::string::const_iterator c = dirstring.begin();
                                       c != dirstring.end(); ++c)
      {
        if (iptr == ixyz.end()) {
          mprinterr("Error: 'dir' string has too many characters.\n");
          return Action::ERR;
        }
        int sign = 1;
        if      (*c == '+') ++c;
        else if (*c == '-') { sign = -1; ++c; }
        
        if      (*c == '1') *iptr = 1 * sign;
        else if (*c == '0') *iptr = 0;
        ++iptr;
      }
      mprintf("DEBUG: %s = %i %i %i\n", dirstring.c_str(), ixyz[0], ixyz[1], ixyz[2]);
      directionArray_.push_back( ixyz[0] );
      directionArray_.push_back( ixyz[1] );
      directionArray_.push_back( ixyz[2] );
      dirstring = actionArgs.GetStringKey("dir");
    }
  }
  ncopies_ = (int)(directionArray_.size() / 3);
  if (ncopies_ < 1) {
    mprinterr("Error: No directions (or 'all') specified.\n");
    return Action::ERR;
  }
  // Set up output trajectory
  if (!trajfilename_.empty()) {
    if (tempParm == 0) {
      mprinterr("Error: Could not get topology for %s\n", trajfilename_.c_str());
      return Action::ERR;
    }
    outtraj_.SetDebug( debugIn );
    // Initialize output trajectory with remaining arguments
    trajArgs_ = actionArgs.RemainingArgs();
    ensembleNum_ = DSL->EnsembleNum();
  }

  mprintf("    REPLICATE CELL: Replicating cell in %i directions:\n", ncopies_);
  mprintf("\t\t X  Y  Z\n");
  for (unsigned int i = 0; i != directionArray_.size(); i += 3)
    mprintf("\t\t%2i %2i %2i\n", directionArray_[i], 
            directionArray_[i+1], directionArray_[i+2]);
  mprintf("\tUsing atoms in mask '%s'\n", Mask1_.MaskString());
  if (!trajfilename_.empty())
    mprintf("\tWriting to trajectory %s\n", trajfilename_.c_str());
  if (!parmfilename_.empty())
    mprintf("\tWriting topology %s\n", parmfilename_.c_str());
  if (coords_ != 0)
    mprintf("\tSaving coords to data set %s\n", coords_->legend());

  return Action::OK;
}