Example #1
0
int ComputeBondLocal::compute_bonds(int flag)
{
  int i,m,n,nb,atom1,atom2,imol,iatom,btype;
  tagint tagprev;
  double dx,dy,dz,rsq;
  double mass1,mass2,masstotal,invmasstotal;
  double xcm[3],vcm[3];
  double delr1[3],delr2[3],delv1[3],delv2[3];
  double r12[3],vpar1,vpar2;
  double vvib,vrotsq;
  double inertia,omegasq;
  double mvv2e;
  double engpot,engtrans,engvib,engrot,fbond;
  double *ptr;

  double **x = atom->x;
  double **v = atom->v;
  int *type = atom->type;
  double *mass = atom->mass;
  double *rmass = atom->rmass;
  tagint *tag = atom->tag;
  int *num_bond = atom->num_bond;
  tagint **bond_atom = atom->bond_atom;
  int **bond_type = atom->bond_type;
  int *mask = atom->mask;

  int *molindex = atom->molindex;
  int *molatom = atom->molatom;
  Molecule **onemols = atom->avec->onemols;

  int nlocal = atom->nlocal;
  int newton_bond = force->newton_bond;
  int molecular = atom->molecular;

  Bond *bond = force->bond;

  // communicate ghost velocities if needed

  if (ghostvelflag && !initflag) comm->forward_comm_compute(this);

  // loop over all atoms and their bonds

  m = n = 0;
  for (atom1 = 0; atom1 < nlocal; atom1++) {
    if (!(mask[atom1] & groupbit)) continue;

    if (molecular == 1) nb = num_bond[atom1];
    else {
      if (molindex[atom1] < 0) continue;
      imol = molindex[atom1];
      iatom = molatom[atom1];
      nb = onemols[imol]->num_bond[iatom];
    }

    for (i = 0; i < nb; i++) {
      if (molecular == 1) {
        btype = bond_type[atom1][i];
        atom2 = atom->map(bond_atom[atom1][i]);
      } else {
        tagprev = tag[atom1] - iatom - 1;
        btype = onemols[imol]->bond_type[iatom][i];
        atom2 = atom->map(onemols[imol]->bond_atom[iatom][i]+tagprev);
      }

      if (atom2 < 0 || !(mask[atom2] & groupbit)) continue;
      if (newton_bond == 0 && tag[atom1] > tag[atom2]) continue;
      if (btype == 0) continue;

      if (!flag) {
        m++;
        continue;
      }

      dx = x[atom1][0] - x[atom2][0];
      dy = x[atom1][1] - x[atom2][1];
      dz = x[atom1][2] - x[atom2][2];
      domain->minimum_image(dx,dy,dz);
      rsq = dx*dx + dy*dy + dz*dz;
      
      if (btype == 0) {
        engpot = fbond = 0.0;
        engvib = engrot = engtrans = omegasq = vvib = 0.0;
      } else {

        if (singleflag) engpot = bond->single(btype,rsq,atom1,atom2,fbond);
        
        if (velflag) {
          if (rmass) {
            mass1 = rmass[atom1];
            mass2 = rmass[atom2];
          }
          else {
            mass1 = mass[type[atom1]];
            mass2 = mass[type[atom2]];
          }
          masstotal = mass1+mass2;
          invmasstotal = 1.0 / (masstotal);
          xcm[0] = (mass1*x[atom1][0] + mass2*x[atom2][0]) * invmasstotal;
          xcm[1] = (mass1*x[atom1][1] + mass2*x[atom2][1]) * invmasstotal;
          xcm[2] = (mass1*x[atom1][2] + mass2*x[atom2][2]) * invmasstotal;
          vcm[0] = (mass1*v[atom1][0] + mass2*v[atom2][0]) * invmasstotal;
          vcm[1] = (mass1*v[atom1][1] + mass2*v[atom2][1]) * invmasstotal;
          vcm[2] = (mass1*v[atom1][2] + mass2*v[atom2][2]) * invmasstotal;
          
          engtrans = 0.5 * masstotal * MathExtra::lensq3(vcm);
          
          // r12 = unit bond vector from atom1 to atom2
          
          MathExtra::sub3(x[atom2],x[atom1],r12);
          MathExtra::norm3(r12);
          
          // delr = vector from COM to each atom
          // delv = velocity of each atom relative to COM
          
          MathExtra::sub3(x[atom1],xcm,delr1);
          MathExtra::sub3(x[atom2],xcm,delr2);
          MathExtra::sub3(v[atom1],vcm,delv1);
          MathExtra::sub3(v[atom2],vcm,delv2);
          
          // vpar = component of delv parallel to bond vector
          
          vpar1 = MathExtra::dot3(delv1,r12);
          vpar2 = MathExtra::dot3(delv2,r12);
          engvib = 0.5 * (mass1*vpar1*vpar1 + mass2*vpar2*vpar2);
          
          // vvib = relative velocity of 2 atoms along bond direction
          // vvib < 0 for 2 atoms moving towards each other
          // vvib > 0 for 2 atoms moving apart
          
          vvib = vpar2 - vpar1;
          
          // vrotsq = tangential speed squared of atom1 only
          // omegasq = omega squared, and is the same for atom1 and atom2
          
          inertia = mass1*MathExtra::lensq3(delr1) + 
            mass2*MathExtra::lensq3(delr2);
          vrotsq = MathExtra::lensq3(delv1) - vpar1*vpar1;
          omegasq = vrotsq / MathExtra::lensq3(delr1);
          
          engrot = 0.5 * inertia * omegasq;
          
          // sanity check: engtotal = engtrans + engvib + engrot
          
          //engtot = 0.5 * (mass1*MathExtra::lensq3(v[atom1]) + 
          //                mass2*MathExtra::lensq3(v[atom2]));
          //if (fabs(engtot-engtrans-engvib-engrot) > EPSILON)
          //  error->one(FLERR,"Sanity check on 3 energy components failed");
          
          // scale energies by units

          mvv2e = force->mvv2e;
          engtrans *= mvv2e;
          engvib *= mvv2e;
          engrot *= mvv2e;
        }

        if (nvalues == 1) ptr = &vector[m];
        else ptr = array[m];

        for (n = 0; n < nvalues; n++) {
          switch (bstyle[n]) {
          case DIST:
            ptr[n] = sqrt(rsq);
            break;
          case ENGPOT:
            ptr[n] = engpot;
            break;
          case FORCE:
            ptr[n] = sqrt(rsq)*fbond;
            break;
          case ENGVIB:
            ptr[n] = engvib;
            break;
          case ENGROT:
            ptr[n] = engrot;
            break;
          case ENGTRANS:
            ptr[n] = engtrans;
            break;
          case OMEGA:
            ptr[n] = sqrt(omegasq);
            break;
          case VELVIB:
            ptr[n] = vvib;
            break;
          }
        }
      }

      m++;
    }
  }

  return m;
}
int ComputeBondLocal::compute_bonds(int flag)
{
  int i,m,n,nb,atom1,atom2,imol,iatom,btype;
  tagint tagprev;
  double delx,dely,delz,rsq;
  double *ptr;

  double **x = atom->x;
  tagint *tag = atom->tag;
  int *num_bond = atom->num_bond;
  tagint **bond_atom = atom->bond_atom;
  int **bond_type = atom->bond_type;
  int *mask = atom->mask;

  int *molindex = atom->molindex;
  int *molatom = atom->molatom;
  Molecule **onemols = atom->avec->onemols;

  int nlocal = atom->nlocal;
  int newton_bond = force->newton_bond;
  int molecular = atom->molecular;

  Bond *bond = force->bond;
  double eng,fbond;

  m = n = 0;
  for (atom1 = 0; atom1 < nlocal; atom1++) {
    if (!(mask[atom1] & groupbit)) continue;

    if (molecular == 1) nb = num_bond[atom1];
    else {
      if (molindex[atom1] < 0) continue;
      imol = molindex[atom1];
      iatom = molatom[atom1];
      nb = onemols[imol]->num_bond[iatom];
    }

    for (i = 0; i < nb; i++) {
      if (molecular == 1) {
        btype = bond_type[atom1][i];
        atom2 = atom->map(bond_atom[atom1][i]);
      } else {
        tagprev = tag[atom1] - iatom - 1;
        btype = atom->map(onemols[imol]->bond_type[iatom][i]);
        atom2 = atom->map(onemols[imol]->bond_atom[iatom][i]+tagprev);
      }

      if (atom2 < 0 || !(mask[atom2] & groupbit)) continue;
      if (newton_bond == 0 && tag[atom1] > tag[atom2]) continue;
      if (btype == 0) continue;

      if (flag) {
        delx = x[atom1][0] - x[atom2][0];
        dely = x[atom1][1] - x[atom2][1];
        delz = x[atom1][2] - x[atom2][2];
        domain->minimum_image(delx,dely,delz);
        rsq = delx*delx + dely*dely + delz*delz;

        if (singleflag && (btype > 0))
          eng = bond->single(btype,rsq,atom1,atom2,fbond);
        else eng = fbond = 0.0;

        if (nvalues == 1) ptr = &vector[m];
        else ptr = array[m];

        for (n = 0; n < nvalues; n++) {
          switch (bstyle[n]) {
          case DIST:
            ptr[n] = sqrt(rsq);
            break;
          case ENG:
            ptr[n] = eng;
            break;
          case FORCE:
            ptr[n] = sqrt(rsq)*fbond;
            break;
          }
        }
      }

      m++;
    }
  }

  return m;
}