Commit 8c7890b6 authored by Stefan Paquay's avatar Stefan Paquay Committed by Pierre de Buyl
Browse files

Added two modes, one via velocity and one via quaternion.

parent 7076e9fe
Loading
Loading
Loading
Loading
+104 −18
Original line number Diff line number Diff line
@@ -51,24 +51,34 @@ static constexpr const bool debug_out = false;
FixPropelSelf::FixPropelSelf( LAMMPS *lmp, int narg, char **argv )
  : Fix(lmp, narg, argv)
{
  // if( lmp->citeme) lmp->citeme->add(cite_fix_active);
  if( narg < 4 ) error->all(FLERR, "Illegal fix propel/self command");
  if( narg < 5 ) error->all(FLERR, "Illegal fix propel/self command");

  AtomVecEllipsoid *av = static_cast<AtomVecEllipsoid*>(atom->avec);
  if (!av) error->all(FLERR, "FixPropelSelf requires atom_style ellipsoid");
  // The fix is to support the following cases:
  // 1. Simple atoms, in which case the force points along the velocity
  // 2. Cases where the atoms have an internal ellipsoid. Currently those
  //    styles are only body and aspherical particles.
  // The first argument (mode) is used to differentiate between these.

  if( debug_out && comm->me == 0 ){
    fprintf(screen, "This is fix active, narg is %d\n", narg );
    fprintf(screen, "args:");
    for( int i = 0; i < narg; ++i ){
      fprintf(screen, " %s", argv[i]);
  // args: fix ID all propel/self mode magnitude
  // Optional args are
  const char *mode_str = argv[3];
  if (strncmp(mode_str, "velocity", 8) == 0) {
    mode = VELOCITY;
  } else if (strncmp(mode_str, "quaternion", 10) == 0) {
    // This mode should only be supported if the atom style has
    // a quaternion (and if all atoms in the group have it)
    if (verify_atoms_have_quaternion()) {
      error->all(FLERR, "All atoms need a quaternion");
    }
    fprintf(screen, "\n");
    mode = QUATERNION;
  } else {
    char msg[2048];
    sprintf(msg, "Illegal mode \"%s\" for fix propel/self", mode_str);
    error->all(FLERR, msg);
  }

  // args: fix ID all propel/self magnitude prop1 prop2 prop3
  // Optional args are
  magnitude = force->numeric( FLERR, argv[3] );
  
  magnitude = force->numeric( FLERR, argv[4] );
}


@@ -92,17 +102,29 @@ double FixPropelSelf::memory_usage()
}


void FixPropelSelf::post_force(int vflag )
{
	switch(mode) {
	case QUATERNION:
		post_force_quaternion(vflag);
		break;
	case VELOCITY:
		post_force_velocity(vflag);
		break;
	default:
		error->all(FLERR, "reached statement that should be unreachable");
	}
}



void FixPropelSelf::post_force(int /* vflag */ )
void FixPropelSelf::post_force_quaternion(int /* vflag */ )
{
  // Then do the rest:
  double **f = atom->f;

  AtomVecEllipsoid *av = static_cast<AtomVecEllipsoid*>(atom->avec);

  int *mask = atom->mask;
  int nlocal = atom->nlocal;
  if (igroup == atom->firstgroup) nlocal = atom->nfirst;

  AtomVecEllipsoid::Bonus *bonus = av->bonus;
  // Add the active force to the atom force:
@@ -141,7 +163,71 @@ void FixPropelSelf::post_force(int /* vflag */ )
      f[i][0] += magnitude * f_rot[0];
      f[i][1] += magnitude * f_rot[1];
      f[i][2] += magnitude * f_rot[2];
    }
  }
}



void FixPropelSelf::post_force_velocity(int /*vflag*/ )
{
  double **f = atom->f;
  double **v = atom->v;
  int *mask = atom->mask;
  int nlocal = atom->nlocal;
  tagint *tag = atom->tag;

  // Add the active force to the atom force:
  for( int i = 0; i < nlocal; ++i ){
    if( mask[i] & groupbit ){
	    const double *vi = v[i];
	    double f_act[3] = { vi[0], vi[1], vi[2] };
	    double nv2 = vi[0]*vi[0] + vi[1]*vi[1] + vi[2]*vi[2];
	    double fnorm = magnitude / sqrt(nv2);
      
      if (debug_out && comm->me == 0) {
        // Magical reference particle:
        if (tag[i] == 12) {
          fprintf(screen, "Active force on atom %d: (%f %f %f)\n",
                  tag[i], f_act[0], f_act[1], f_act[2]);
          fprintf(screen, "  Total force before: (%f %f %f)\n",
                  f[i][0], f[i][1], f[i][2]);
        }
      }

      f[i][0] += fnorm * f_act[0];
      f[i][1] += fnorm * f_act[1];
      f[i][2] += fnorm * f_act[2];
    }
  }
}


int FixPropelSelf::verify_atoms_have_quaternion()
{
	int ellipsoid_flag = atom->ellipsoid_flag;
	int body_flag = atom->body_flag;
	int *mask = atom->mask;
  if (! (ellipsoid_flag || body_flag) ){
    error->all(FLERR, "mode quaternion requires body or ellipsoid atoms");
  }
  
  // Make sure all atoms have ellipsoid or body set:
  for (int i = 0; i < atom->nlocal; ++i) {
    if (mask[i] & groupbit) {
	    if (ellipsoid_flag && atom->ellipsoid[i] < 0) {
		    error->all(FLERR, "Got atom without ellipsoid set");
		    // Kind-of pointless but silences some compiler warnings:
		    return 1;
	    }
	    if (body_flag && atom->body[i] < 0) {
		    error->all(FLERR, "Got atom without body set");
		    // Kind-of pointless but silences some compiler warnings:
		    return 1;
	    }
    }
  }
  
  return 0;
}
+14 −1
Original line number Diff line number Diff line
@@ -26,6 +26,12 @@ namespace LAMMPS_NS {

class FixPropelSelf : public Fix {
 public:

  enum operation_modes {
    VELOCITY = 0,
    QUATERNION = 1
  };
	
  FixPropelSelf(class LAMMPS *, int, char **);
  virtual ~FixPropelSelf();
  virtual int setmask();
@@ -34,9 +40,16 @@ class FixPropelSelf : public Fix {

  double memory_usage();

protected:
private:
  double magnitude;
  int thermostat_orient;
  int mode;

  int verify_atoms_have_quaternion();
  void post_force_velocity(int);
  void post_force_quaternion(int);
	
	
};

}