Example #1
0
inline void calc_bonded_force(Particle *p1, Particle *p2, Bonded_ia_parameters *iaparams, int *i, double dx[3], double force[3]) {
#ifdef TABULATED
    //char* errtxt;
#endif

    /* Calculates the bonded force between two particles */
    switch(iaparams->type) {
    case BONDED_IA_FENE:
        calc_fene_pair_force(p1,p2,iaparams,dx,force);
        break;
#ifdef ROTATION
    case BONDED_IA_HARMONIC_DUMBBELL:
        calc_harmonic_dumbbell_pair_force(p1,p2,iaparams,dx,force);
        break;
#endif
    case BONDED_IA_HARMONIC:
        calc_harmonic_pair_force(p1,p2,iaparams,dx,force);
        break;
#ifdef LENNARD_JONES
    case BONDED_IA_SUBT_LJ:
        calc_subt_lj_pair_force(p1,p2,iaparams,dx,force);
        break;
#endif
    /* since it is not clear at the moment how to handle a many body interaction here, I skip it */
    case BONDED_IA_ANGLE_HARMONIC:
        (*i)++;
        force[0] = force[1] = force[2] = 0;
        break;
    case BONDED_IA_ANGLE_COSINE:
        (*i)++;
        force[0] = force[1] = force[2] = 0;
        break;
    case BONDED_IA_ANGLE_COSSQUARE:
        (*i)++;
        force[0] = force[1] = force[2] = 0;
        break;
    case BONDED_IA_ANGLEDIST:
        (*i)++;
        force[0] = force[1] = force[2] = 0;
        break;
    case BONDED_IA_DIHEDRAL:
        (*i)+=2;
        force[0] = force[1] = force[2] = 0;
        break;

#ifdef TABULATED
    case BONDED_IA_TABULATED:
        // printf("BONDED TAB, Particle: %d, P2: %d TYPE_TAB: %d\n",p1->p.identity,p2->p.identity,iparams->p.tab.type);
        switch(iaparams->p.tab.type) {
        case TAB_BOND_LENGTH:
            calc_tab_bond_force(p1, p2, iaparams, dx, force);
            break;
        case TAB_BOND_ANGLE:
            (*i)++;
            force[0] = force[1] = force[2] = 0;
            break;
        case TAB_BOND_DIHEDRAL:
            (*i)+=2;
            force[0] = force[1] = force[2] = 0;
            break;
        default:
            runtimeErrorMsg() <<"calc_bonded_force: tabulated bond type of atom " << p1->p.identity << " unknown\n";
            return;
        }
        break;
#endif
#ifdef OVERLAPPED
    case BONDED_IA_OVERLAPPED:
        // printf("BONDED OVERLAP, Particle: %d, P2: %d TYPE_OVERLAP: %d\n",p1->p.identity,p2->p.identity,iparams->p.tab.type);
        //char *errtxt;
        switch(iaparams->p.overlap.type) {
        case OVERLAP_BOND_LENGTH:
            calc_overlap_bond_force(p1, p2, iaparams, dx, force);
            break;
        case OVERLAP_BOND_ANGLE:
            (*i)++;
            force[0] = force[1] = force[2] = 0;
            break;
        case OVERLAP_BOND_DIHEDRAL:
            (*i)+=2;
            force[0] = force[1] = force[2] = 0;
            break;
        default:
            runtimeErrorMsg() <<"calc_bonded_force: overlapped bond type of atom " << p1->p.identity << " unknown\n";
            return;
        }
        break;
#endif
#ifdef BOND_CONSTRAINT
    case BONDED_IA_RIGID_BOND:
        force[0] = force[1] = force[2] = 0;
        break;
#endif
#ifdef BOND_VIRTUAL
    case BONDED_IA_VIRTUAL_BOND:
        force[0] = force[1] = force[2] = 0;
        break;
#endif
    default :
        //      fprintf(stderr,"add_bonded_virials: WARNING: Bond type %d of atom %d unhandled\n",bonded_ia_params[type_num].type,p1->p.identity);
        fprintf(stderr,"add_bonded_virials: WARNING: Bond type %d , atom %d unhandled, Atom 2: %d\n",iaparams->type,p1->p.identity,p2->p.identity);
        force[0] = force[1] = force[2] = 0;
        break;
    }
}
Example #2
0
inline void add_bonded_force(Particle *p1)
{
  double dx[3]     = { 0., 0., 0. };
  double force[3]  = { 0., 0., 0. };
  double force2[3] = { 0., 0., 0. };
  double force3[3] = { 0., 0., 0. };
#if defined(HYDROGEN_BOND) || defined(TWIST_STACK) || defined(OIF_LOCAL_FORCES)
  double force4[3] = { 0., 0., 0. };
#endif 
#ifdef TWIST_STACK
  double force5[3] = { 0., 0., 0. };
  double force6[3] = { 0., 0., 0. };
  double force7[3] = { 0., 0., 0. };
  double force8[3] = { 0., 0., 0. };

  Particle *p5 = NULL,*p6 = NULL,*p7 = NULL,*p8 = NULL;
#endif
#ifdef ROTATION
  double torque1[3] = { 0., 0., 0. };
  double torque2[3] = { 0., 0., 0. };
#endif
  Particle *p2 = NULL, *p3 = NULL, *p4 = NULL;
  Bonded_ia_parameters *iaparams;
  int i, j, type_num, type, n_partners, bond_broken;

  i = 0;
  while (i<p1->bl.n) {
    type_num = p1->bl.e[i++];
    iaparams = &bonded_ia_params[type_num];
    type = iaparams->type;
    n_partners = iaparams->num;

    /* fetch particle 2, which is always needed */
    p2 = local_particles[p1->bl.e[i++]];
    if (!p2) {
      ostringstream msg;
      msg << "bond broken between particles " << p1->p.identity << " and " 
          << p1->bl.e[i-1] << " (particles are not stored on the same node)";
      runtimeError(msg);
      return;
    }

    /* fetch particle 3 eventually */
    if (n_partners >= 2) {
      p3 = local_particles[p1->bl.e[i++]];
      if (!p3) {
        ostringstream msg;
        msg << "bond broken between particles " 
            << p1->p.identity << ", " 
            << p1->bl.e[i-2] << " and "
            << p1->bl.e[i-1] << " (particles are not stored on the same node)";
        runtimeError(msg);
	return;
      }
    }

    /* fetch particle 4 eventually */
    if (n_partners >= 3) {
      p4 = local_particles[p1->bl.e[i++]];
      if (!p4) {
      ostringstream msg;
      msg <<"bond broken between particles "<< p1->p.identity << ", " << p1->bl.e[i-3] << ", " << p1->bl.e[i-2]
            << " and " << p1->bl.e[i-1] << " (particles not stored on the same node)";
      runtimeError(msg);
	return;
      }
    }    
#ifdef TWIST_STACK
      if(n_partners >= 7) {
	p5 = local_particles[p1->bl.e[i++]];
	p6 = local_particles[p1->bl.e[i++]];
	p7 = local_particles[p1->bl.e[i++]];
	p8 = local_particles[p1->bl.e[i++]];

	if(!p4 || !p5 || !p6 || !p7 || !p8) {
	  ostringstream msg;
	  msg << "bond broken between particles" <<
	    p1->p.identity << ", " << p1->bl.e[i-7] << ", " << p1->bl.e[i-6] << ", " << p1->bl.e[i-5] << ", " << p1->bl.e[i-4] << ", " << p1->bl.e[i-3] << ", " << p1->bl.e[i-2] << ", " << p1->bl.e[i-1] << " (particles not stored on the same node)";
	  return;
	}
      }
#endif

    if (n_partners == 1) {
      /* because of the NPT pressure calculation for pair forces, we need the
	 1->2 distance vector here. For many body interactions this vector is not needed,
	 and the pressure calculation not yet clear. */
      get_mi_vector(dx, p1->r.p, p2->r.p);
    }

    switch (type) {
    case BONDED_IA_FENE:
      bond_broken = calc_fene_pair_force(p1, p2, iaparams, dx, force);
      break;
#ifdef ROTATION
    case BONDED_IA_HARMONIC_DUMBBELL:
      bond_broken = calc_harmonic_dumbbell_pair_force(p1, p2, iaparams, dx, force);
      break;
#endif
    case BONDED_IA_HARMONIC:
      bond_broken = calc_harmonic_pair_force(p1, p2, iaparams, dx, force);
      break;
    case BONDED_IA_QUARTIC:
      bond_broken = calc_quartic_pair_force(p1, p2,  iaparams, dx, force);
      break;
#ifdef ELECTROSTATICS
    case BONDED_IA_BONDED_COULOMB:
      bond_broken = calc_bonded_coulomb_pair_force(p1, p2, iaparams, dx, force);
      break;
#endif
#ifdef HYDROGEN_BOND
    case BONDED_IA_CG_DNA_BASEPAIR:
      bond_broken = calc_hydrogen_bond_force(p1, p2, p3, p4, iaparams, force, force2, force3, force4);
      break;
#endif
#ifdef TWIST_STACK
    case BONDED_IA_CG_DNA_STACKING:
      bond_broken = calc_twist_stack_force(p1, p2, p3, p4, p5, p6, p7, p8, iaparams,
                                           force, force2, force3, force4, force5, force6, force7, force8);
      break;
#endif
#ifdef MEMBRANE_COLLISION
    case BONDED_IA_OIF_OUT_DIRECTION:
      bond_broken = calc_out_direction(p1, p2, p3, p4, iaparams);
      break;
#endif
#ifdef OIF_GLOBAL_FORCES
    case BONDED_IA_OIF_GLOBAL_FORCES:
      bond_broken = 0;
      break;
#endif
#ifdef OIF_LOCAL_FORCES
    case BONDED_IA_OIF_LOCAL_FORCES:
      bond_broken = calc_oif_local(p1, p2, p3, p4, iaparams, force, force2, force3, force4);
      break;
#endif  
      // IMMERSED_BOUNDARY
#ifdef IMMERSED_BOUNDARY
      /*      case BONDED_IA_IBM_WALL_REPULSION:
              IBM_WallRepulsion_CalcForce(p1, iaparams);
              bond_broken = 0;
              // These may be added later on, but we set them to zero because the force has already been added in IBM_WallRepulsion_CalcForce
              force[0] = force2[0] = force3[0] = 0;
              force[1] = force2[1] = force3[1] = 0;
              force[2] = force2[2] = force3[2] = 0;
              break;*/
    case BONDED_IA_IBM_TRIEL:
      bond_broken = IBM_Triel_CalcForce(p1, p2, p3, iaparams);
      // These may be added later on, but we set them to zero because the force has already been added in IBM_Triel_CalcForce
      force[0] = force2[0] = force3[0] = 0;
      force[1] = force2[1] = force3[1] = 0;
      force[2] = force2[2] = force3[2] = 0;
      break;
    case BONDED_IA_IBM_VOLUME_CONSERVATION:
      bond_broken = 0;
      // Don't do anything here. We calculate and add the global volume forces in IBM_VolumeConservation. They cannot be calculated on a per-bond basis
      force[0] = force2[0] = force3[0] = 0;
      force[1] = force2[1] = force3[1] = 0;
      force[2] = force2[2] = force3[2] = 0;
      break;
    case BONDED_IA_IBM_TRIBEND:
      {
        // First build neighbor list. This includes all nodes around the central node.
        const int numNeighbors = iaparams->num;
        Particle **neighbors = new Particle *[numNeighbors];
        // Three are already there
        neighbors[0] = p2;
        neighbors[1] = p3;
        neighbors[2] = p4;
        // Get rest
        for (int j=3; j < numNeighbors; j++)
          neighbors[j] = local_particles[p1->bl.e[i++]];
        
        IBM_Tribend_CalcForce(p1, numNeighbors, neighbors, *iaparams);
        bond_broken = 0;
        
        // Clean up
        delete []neighbors;
        
        // These may be added later on, but we set them to zero because the force has
        force[0] = force2[0] = force3[0] = 0;
        force[1] = force2[1] = force3[1] = 0;
        force[2] = force2[2] = force3[2] = 0;
        break;
      }
#endif
        
#ifdef LENNARD_JONES
    case BONDED_IA_SUBT_LJ:
      bond_broken = calc_subt_lj_pair_force(p1, p2, iaparams, dx, force);
      break;
#endif
#ifdef BOND_ANGLE_OLD
      /* the first case is not needed and should not be called */ 
    case BONDED_IA_ANGLE_OLD:
      bond_broken = calc_angle_force(p1, p2, p3, iaparams, force, force2);
      break;
#endif
#ifdef BOND_ANGLE
    case BONDED_IA_ANGLE_HARMONIC:
      bond_broken = calc_angle_harmonic_force(p1, p2, p3, iaparams, force, force2);
      break;
    case BONDED_IA_ANGLE_COSINE:
      bond_broken = calc_angle_cosine_force(p1, p2, p3, iaparams, force, force2);
      break;
    case BONDED_IA_ANGLE_COSSQUARE:
      bond_broken = calc_angle_cossquare_force(p1, p2, p3, iaparams, force, force2);
      break;
#endif
#ifdef BOND_ANGLEDIST
    case BONDED_IA_ANGLEDIST:
      bond_broken = calc_angledist_force(p1, p2, p3, iaparams, force, force2);
      break;
#endif
#ifdef BOND_ENDANGLEDIST
    case BONDED_IA_ENDANGLEDIST:
      bond_broken = calc_endangledist_pair_force(p1, p2, iaparams, dx, force, force2);
      break;
#endif
    case BONDED_IA_DIHEDRAL:
      bond_broken = calc_dihedral_force(p1, p2, p3, p4, iaparams, force, force2, force3);
      break;
#ifdef BOND_CONSTRAINT
    case BONDED_IA_RIGID_BOND:
      //add_rigid_bond_pair_force(p1,p2, iaparams, force, force2);
      bond_broken = 0; 
      force[0]=force[1]=force[2]=0.0;
      break;
#endif
#ifdef TABULATED
    case BONDED_IA_TABULATED:
      switch(iaparams->p.tab.type) {
      case TAB_BOND_LENGTH:
	bond_broken = calc_tab_bond_force(p1, p2, iaparams, dx, force);
	break;
      case TAB_BOND_ANGLE:
	bond_broken = calc_tab_angle_force(p1, p2, p3, iaparams, force, force2);
	break;
      case TAB_BOND_DIHEDRAL:
	bond_broken = calc_tab_dihedral_force(p1, p2, p3, p4, iaparams, force, force2, force3);
	break;
      default:
        ostringstream msg;
        msg << "add_bonded_force: tabulated bond type of atom "<< p1->p.identity << " unknown\n";
        runtimeError(msg);
	return;
      }
      break;
#endif
#ifdef OVERLAPPED
    case BONDED_IA_OVERLAPPED:
      switch(iaparams->p.overlap.type) {
      case OVERLAP_BOND_LENGTH:
        bond_broken = calc_overlap_bond_force(p1, p2, iaparams, dx, force);
        break;
      case OVERLAP_BOND_ANGLE:
        bond_broken = calc_overlap_angle_force(p1, p2, p3, iaparams, force, force2);
        break;
      case OVERLAP_BOND_DIHEDRAL:
        bond_broken = calc_overlap_dihedral_force(p1, p2, p3, p4, iaparams, force, force2, force3);
        break;
      default:
        ostringstream msg;
        msg <<"add_bonded_force: overlapped bond type of atom "<< p1->p.identity << " unknown\n";
        runtimeError(msg);
        return;
      }
      break;
#endif
#ifdef BOND_VIRTUAL
    case BONDED_IA_VIRTUAL_BOND:
      bond_broken = 0;
      force[0]=force[1]=force[2]=0.0;
      break;
#endif
    default :
      ostringstream msg;
      msg <<"add_bonded_force: bond type of atom "<< p1->p.identity << " unknown\n";
      runtimeError(msg);
      return;
    }

    switch (n_partners) {
    case 1:
      if (bond_broken) {
        ostringstream msg;
        msg <<"bond broken between particles " << p1->p.identity << " and " << p2->p.identity<<". Distance vector: "<<dx[0]<<" "<<dx[1]<<" "<<dx[2];
        runtimeError(msg);
        continue;
      }
      
      for (j = 0; j < 3; j++) {
	switch (type) {
#ifdef BOND_ENDANGLEDIST
	case BONDED_IA_ENDANGLEDIST:
          p1->f.f[j] += force[j];
          p2->f.f[j] += force2[j];
	  break;
#endif // BOND_ENDANGLEDIST
	default:
	  p1->f.f[j] += force[j];
	  p2->f.f[j] -= force[j];
#ifdef ROTATION
	  p1->f.torque[j] += torque1[j];
	  p2->f.torque[j] += torque2[j];
#endif
	}

#ifdef NPT
	if(integ_switch == INTEG_METHOD_NPT_ISO)
	  nptiso.p_vir[j] += force[j] * dx[j];
#endif
      }
      break;
    case 2:
      if (bond_broken) {
        ostringstream msg;
        msg << "bond broken between particles "<< p1->p.identity << ", " << p2->p.identity << " and "
            << p3->p.identity;
        runtimeError(msg);
	continue;
      }

      for (j = 0; j < 3; j++) {
	switch (type) {
#ifdef OIF_GLOBAL_FORCES
	case BONDED_IA_OIF_GLOBAL_FORCES:
	  break;
#endif
	default:
	  p1->f.f[j] += force[j];
	  p2->f.f[j] += force2[j];
	  p3->f.f[j] -= (force[j] + force2[j]);
	}
      }
      break;
    case 3:
      if (bond_broken) {
	ostringstream msg;
	msg << "bond broken between particles "<< p1->p.identity << ", " << p2->p.identity
	    << ", " << p3->p.identity << " and " << p4->p.identity;
	runtimeError(msg);
	continue;
      }

      switch (type) {
      case BONDED_IA_DIHEDRAL:
        for (j = 0; j < 3; j++) {
          p1->f.f[j] += force[j];
          p2->f.f[j] += force2[j];
          p3->f.f[j] += force3[j];
          p4->f.f[j] -= force[j] + force2[j] + force3[j];
        }
        break;

#ifdef OIF_LOCAL_FORCES
      case BONDED_IA_OIF_LOCAL_FORCES:
        for (j = 0; j < 3; j++) {
          p1->f.f[j] += force2[j];
          p2->f.f[j] += force[j];
          p3->f.f[j] += force3[j];
          p4->f.f[j] += force4[j];
        }
        break;
#endif
#ifdef CG_DNA
      default:
        for (j = 0; j < 3; j++) {
          p1->f.f[j] += force[j];
          p2->f.f[j] += force2[j];
          p3->f.f[j] += force3[j];
          p4->f.f[j] += force4[j];
        }
        break;
#endif	
      }
      break;
    case 7:
      if (bond_broken) {
	ostringstream msg;
	msg << "bond broken between particles "<< p1->p.identity << ", " << p2->p.identity
	    << ", " << p3->p.identity << " and " << p4->p.identity;
	runtimeError(msg);	
	continue;
      }
      switch(type) {
      case BONDED_IA_CG_DNA_STACKING:      
#ifdef CG_DNA
	for (j = 0; j < 3; j++) {
	  p1->f.f[j] += force[j];
	  p2->f.f[j] += force2[j];
	  p3->f.f[j] += force3[j];
	  p4->f.f[j] += force4[j];
	  p5->f.f[j] += force5[j];
	  p6->f.f[j] += force6[j];
	  p7->f.f[j] += force7[j];
	  p8->f.f[j] += force8[j];
	}
#endif
	break;
      }
    }
  }
}