Esempio n. 1
0
int set_particle_torque_lab(int part, double torque_lab[3])
{
  int pnode;
  if (!particle_node)
    build_particle_node();

  if (part < 0 || part > max_seen_particle)
    return ES_ERROR;
  pnode = particle_node[part];

  if (pnode == -1)
    return ES_ERROR;

  /* Internal functions require the body coordinates
     so we need to convert to these from the lab frame */

  double A[9];
  double torque[3];
  Particle particle;

  get_particle_data(part, &particle);
  define_rotation_matrix(&particle, A);

  torque[0] = A[0 + 3*0]*torque_lab[0] + A[0 + 3*1]*torque_lab[1] + A[0 + 3*2]*torque_lab[2];
  torque[1] = A[1 + 3*0]*torque_lab[0] + A[1 + 3*1]*torque_lab[1] + A[1 + 3*2]*torque_lab[2];
  torque[2] = A[2 + 3*0]*torque_lab[0] + A[2 + 3*1]*torque_lab[1] + A[2 + 3*2]*torque_lab[2];

  mpi_send_torque(pnode, part, torque);
  return ES_OK;
}
Esempio n. 2
0
int remove_particle(int part)
{
  int pnode;

  Particle *cur_par = (Particle *) malloc (sizeof(Particle));
  if (get_particle_data(part, cur_par) == ES_ERROR )
	  return ES_ERROR;
  int type = cur_par->p.type;
  free(cur_par);
  if (remove_id_type_array(part, type) == ES_ERROR )
	  return ES_ERROR;

  if (!particle_node)
    build_particle_node();

  if (part > max_seen_particle)
    return ES_ERROR;

  pnode = particle_node[part];
  if (pnode == -1)
    return ES_ERROR;

  particle_node[part] = -1;

  mpi_remove_particle(pnode, part);

  if (part == max_seen_particle) {
    while (max_seen_particle >= 0 && particle_node[max_seen_particle] == -1)
      max_seen_particle--;
    mpi_bcast_parameter(FIELD_MAXPART);
  }
  return ES_OK;
}
Esempio n. 3
0
int set_particle_type(int part, int type)
{

  int pnode;
  make_particle_type_exist(type);

  if (!particle_node)
    build_particle_node();

  if (part < 0 || part > max_seen_particle)
    return ES_ERROR;
  pnode = particle_node[part];

  if (pnode == -1)
    return ES_ERROR;

// check if the particle exists already and the type is changed, then remove it from the list which contains it
  Particle *cur_par = (Particle *) malloc( sizeof(Particle) );
  if ( Type_array_init ) {
	  if ( cur_par != (Particle *) 0 ) {
		  if ( get_particle_data(part, cur_par) != ES_ERROR ) {
			  int prev_type = cur_par->p.type;
			  if ( prev_type != type ) {
			  // particle existed before so delete it from the list
			  remove_id_type_array(part, prev_type);
			  }
		  }
	  }
	  free(cur_par);
  }

  mpi_send_type(pnode, part, type);

#ifdef ADDITIONAL_CHECKS
  if ( Type_array_init ) { 
	  if ( add_particle_to_list(part, type) ==  ES_ERROR ){
		  //Tcl_AppendResult(interp, "gc particle add failed", (char *) NULL);
		  return ES_ERROR;
	  }
  }
#endif
  

  return ES_OK;
}
int tclcommand_analyze_parse_and_print_check_mol(Tcl_Interp *interp,int argc, char **argv){
   int j,count=0;
   double dist;
   char buffer[TCL_DOUBLE_SPACE];
   Particle p;
   updatePartCfg(WITHOUT_BONDS);
   for(j=0; j<n_total_particles; j++){
      if (!ifParticleIsVirtual(&partCfg[j])) continue;
      get_particle_data(j,&p);
      //dist=min_distance(partCfg[j].r.p,p.r.p);
      unfold_position(p.r.p,p.l.i);
      dist=distance(partCfg[j].r.p,p.r.p);
      if (dist > 0.01){
         if (count==0) Tcl_AppendResult(interp,"BEGIN Particle Missmatch: \n", (char *)NULL);
         sprintf(buffer,"%i",j);
         Tcl_AppendResult(interp,"Particle ",buffer, (char *)NULL);
         Tcl_PrintDouble(interp,partCfg[j].r.p[0] , buffer);
         Tcl_AppendResult(interp," partCfg x ",buffer, (char *)NULL);
         Tcl_PrintDouble(interp,partCfg[j].r.p[1] , buffer);
         Tcl_AppendResult(interp," y ",buffer, (char *)NULL);
         Tcl_PrintDouble(interp,partCfg[j].r.p[2] , buffer);
         Tcl_AppendResult(interp," z ",buffer, (char *)NULL);
         Tcl_PrintDouble(interp,p.r.p[0] , buffer);
         Tcl_AppendResult(interp," my_partCfg x ",buffer, (char *)NULL);
         Tcl_PrintDouble(interp,p.r.p[1] , buffer);
         Tcl_AppendResult(interp," y ",buffer, (char *)NULL);
         Tcl_PrintDouble(interp,p.r.p[2] , buffer);
         Tcl_AppendResult(interp," z ",buffer, (char *)NULL);
         Tcl_PrintDouble(interp, dist, buffer);
         Tcl_AppendResult(interp," dist ",buffer,"\n", (char *)NULL);
         count++;
      }
   }
   if (count!=0){
      Tcl_AppendResult(interp,"END Particle Missmatch\n", (char *)NULL);
      return(TCL_ERROR);
   }
   return(TCL_OK);
}
Esempio n. 5
0
int IBM_Tribend_SetParams(const int bond_type, const int ind1, const int ind2, const int ind3, const int ind4, const tBendingMethod method, const double kb, const bool flat)
{
  // Create bond
  make_bond_type_exist(bond_type);
  
  // General parameters
  bonded_ia_params[bond_type].type = BONDED_IA_IBM_TRIBEND;
  
  // Specific parameters
  bonded_ia_params[bond_type].p.ibm_tribend.method = method;
  
  // Distinguish bending methods
  if ( method == TriangleNormals )
  {
    double theta0;
  
    if ( !flat )
    {
      // Compute theta0
      Particle p1, p2, p3, p4;
      get_particle_data(ind1, &p1);
      get_particle_data(ind2, &p2);
      get_particle_data(ind3, &p3);
      get_particle_data(ind4, &p4);
      
      //Get vectors of triangles
      double dx1[3], dx2[3], dx3[3];
      get_mi_vector(dx1, p1.r.p, p3.r.p);
      get_mi_vector(dx2, p2.r.p, p3.r.p);
      get_mi_vector(dx3, p4.r.p, p3.r.p);
      
      //Get normals on triangle; pointing outwards by definition of indices sequence
      double n1l[3], n2l[3];
      vector_product(dx1, dx2, n1l);
      vector_product(dx1, dx3, n2l);
      
      // Wolfgang here had a minus. It seems to work, so leave it in
      n2l[0] = -1*n2l[0];
      n2l[1] = -1*n2l[1];
      n2l[2] = -1*n2l[2];
      
      double n1[3], n2[3];
      unit_vector(n1l,n1);
      unit_vector(n2l,n2);
      
      
      //calculate theta by taking the acos of the scalar n1*n2
      double sc = scalar(n1,n2);
      if ( sc > 1.0) sc = 1.0;
      
      theta0 = acos(sc);
      double tmp[3];
      vector_product(n1,n2,tmp);
      
      const double desc = scalar(dx1,tmp);
      if ( desc < 0) theta0 = 2.0*PI-theta0;
      
    }
    else theta0 = 0;        // Flat

    // Krüger always has three partners
    bonded_ia_params[bond_type].num = 3;
    bonded_ia_params[bond_type].p.ibm_tribend.theta0 = theta0;
    // NOTE: This is the bare bending modulus used by the program.
    // If triangle pairs appear only once, the total bending force should get a factor 2
    // For the numerical model, a factor sqrt(3) should be added, see Gompper&Kroll J. Phys. 1996 and Krüger thesis
    // This is an approximation, it holds strictly only for a sphere
    bonded_ia_params[bond_type].p.ibm_tribend.kb = kb;
  }
  
  // Gompper
  if ( method == NodeNeighbors )
  {
    // Interpret ind2 as number of partners
    // Note: the actual partners are not set here, but must be set using the part command on the tcl level
    
    if ( ind1 != 5 && ind1 != 6) { printf("Gompper bending with %d partners seems strange. Are you sure?\n", ind2); return ES_ERROR; }
    
    bonded_ia_params[bond_type].num = ind1;
    
    // Only flat eq possible, but actually this is ignored in the computation anyway
    bonded_ia_params[bond_type].p.ibm_tribend.theta0 = 0;
    bonded_ia_params[bond_type].p.ibm_tribend.kb = kb;
  }
  
  // Broadcast and return
  mpi_bcast_ia_params(bond_type, -1);
  return ES_OK;
  
}
// Setup the virtual_sites_relative properties of a particle so that the given virtaul particle will follow the given real particle
int vs_relate_to(int part_num, int relate_to)
{
    // Get the data for the particle we act on and the one we wnat to relate
    // it to.
    Particle  p_current,p_relate_to;
    if ((get_particle_data(relate_to,&p_relate_to)!=ES_OK) || 
        (get_particle_data(part_num,&p_current)!=ES_OK)) {
      char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE);
      ERROR_SPRINTF(errtxt, "Could not retrieve particle data for the given id");
      return ES_ERROR;
    }
    
    // get teh distance between the particles
    double d[3];
    get_mi_vector(d, p_current.r.p,p_relate_to.r.p);
    
    // Set the particle id of the particle we want to relate to and the distnace
    if (set_particle_vs_relative(part_num, relate_to, sqrt(sqrlen(d))) == ES_ERROR) {
      char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE);
      ERROR_SPRINTF(errtxt, "setting the vs_relative attributes failed");
      return ES_ERROR;
    }
    
    
    // Check, if the distance between virtual and non-virtual particles is larger htan minimum global cutoff
    // If so, warn user
    double l=sqrt(sqrlen(d));
    if (l>min_global_cut) {
      char *errtxt = runtime_error(300 + 3*ES_INTEGER_SPACE);
      ERROR_SPRINTF(errtxt, "Warning: The distance between virtual and non-virtual particle (%f) is\nlarger than the minimum global cutoff (%f). This may lead to incorrect simulations\nunder certain conditions. Use \"setmd min_global_cut\" to increase the minimum cutoff.\n",l,min_global_cut);
      return ES_ERROR;
    }

    // Now, calculate the quaternions which specify the angle between 
    // the director of the particel we relate to and the vector
    // (paritlce_we_relate_to - this_particle)
    double quat[4];
    // The vs_relative implemnation later obtains the direcotr by multiplying
    // the quaternions representing the orientation of the real particle
    // with those in the virtual particle. The re quulting quaternion is then
    // converted to a director.
    // Whe have quat_(real particle) *quat_(virtual particle) 
    // = quat_(obtained from desired director)
    // Resolving this for the quat_(virtaul particle)

    //Normalize desired director
    int i;
    for (i=0;i<3;i++)
     d[i]/=l;

    // Obtain quaternions from desired director
    double quat_director[4];
    convert_quatu_to_quat(d, quat_director);

    // Define quat as described above:
    double x=0;
    for (i=0;i<4;i++)
     x+=p_relate_to.r.quat[i]*p_relate_to.r.quat[i];

    quat[0]=0;
    for (i=0;i<4;i++)
     quat[0] +=p_relate_to.r.quat[i]*quat_director[i];
    
    quat[1] =-quat_director[0] *p_relate_to.r.quat[1] 
       +quat_director[1] *p_relate_to.r.quat[0]
       +quat_director[2] *p_relate_to.r.quat[3]
       -quat_director[3] *p_relate_to.r.quat[2];
    quat[2] =p_relate_to.r.quat[1] *quat_director[3] 
      + p_relate_to.r.quat[0] *quat_director[2] 
      - p_relate_to.r.quat[3] *quat_director[1] 
      - p_relate_to.r.quat[2] * quat_director[0];
    quat[3] =quat_director[3] *p_relate_to.r.quat[0]
      - p_relate_to.r.quat[3] *quat_director[0] 
      + p_relate_to.r.quat[2] * quat_director[1] 
      - p_relate_to.r.quat[1] *quat_director[2];
    for (i=0;i<4;i++)
     quat[i]/=x;
   
   
   // Verify result
   double qtemp[4];
   multiply_quaternions(p_relate_to.r.quat,quat,qtemp);
   for (i=0;i<4;i++)
     if (fabs(qtemp[i]-quat_director[i])>1E-9)
       fprintf(stderr, "vs_relate_to: component %d: %f instead of %f\n",
	       i, qtemp[i], quat_director[i]);


   // Save the quaternions in the particle
   if (set_particle_quat(part_num, quat) == ES_ERROR) {
     char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE);
     ERROR_SPRINTF(errtxt, "set particle position first");

     return ES_ERROR;
   }
   
   return ES_OK;
}
Esempio n. 7
0
int tclcommand_writemd(ClientData data, Tcl_Interp *interp,
	    int argc, char **argv)
{
  static int end_num = -1;
  char *row;
  int p, i;
  struct MDHeader header;
  int tcl_file_mode;
  Tcl_Channel channel;

  if (argc < 3) {
    #if defined(ELECTROSTATICS) && defined(DIPOLES)
      Tcl_AppendResult(interp, "wrong # args:  should be \"",
	  	       argv[0], " <file> ?posx|posy|posz|q|mx|my|mz|vx|vy|vz|fx|fy|fz|type?* ...\"",
		       (char *) NULL);
    #else
      #ifdef ELECTROSTATICS
      Tcl_AppendResult(interp, "wrong # args:  should be \"",
	  	       argv[0], " <file> ?posx|posy|posz|q|vx|vy|vz|fx|fy|fz|type?* ...\"",
		       (char *) NULL);
      #endif
      
      #ifdef DIPOLES
      Tcl_AppendResult(interp, "wrong # args:  should be \"",
	  	       argv[0], " <file> ?posx|posy|posz|mx|my|mz|vx|vy|vz|fx|fy|fz|type?* ...\"",
		       (char *) NULL);
      #endif
    
    #endif		       
   		     
    return (TCL_ERROR);
  }

  if ((channel = Tcl_GetChannel(interp, argv[1], &tcl_file_mode)) == NULL)
    return (TCL_ERROR);
  if (!(tcl_file_mode & TCL_WRITABLE)) {
    Tcl_AppendResult(interp, "\"", argv[1], "\" not writeable", (char *) NULL);
    return (TCL_ERROR);
  }

  /* tune channel to binary translation, e.g. none */
  Tcl_SetChannelOption(interp, channel, "-translation", "binary");

  /* assemble rows */
  argc -= 2;
  argv += 2;
  row = (char*)malloc(sizeof(char)*argc);
  for (i = 0; i < argc; i++) {
    if (!strncmp(*argv, "posx", strlen(*argv))) {
      row[i] = POSX;
    }
    else if (!strncmp(*argv, "posy", strlen(*argv))) {
      row[i] = POSY;
    }
    else if (!strncmp(*argv, "posz", strlen(*argv))) {
      row[i] = POSZ;
    }
#ifdef MASS
    else if (!strncmp(*argv, "mass", strlen(*argv))) {
      row[i] = MASSES;
    }
#endif
    else if (!strncmp(*argv, "q", strlen(*argv))) {
      row[i] = Q;
    }
#ifdef DIPOLES    
    else if (!strncmp(*argv, "mx", strlen(*argv))) {
      row[i] = MX;
    }
    else if (!strncmp(*argv, "my", strlen(*argv))) {
      row[i] = MY;
    }
    else if (!strncmp(*argv, "mz", strlen(*argv))) {
      row[i] = MZ;
    }    
#endif    
    else if (!strncmp(*argv, "vx", strlen(*argv))) {
      row[i] = VX;
    }
    else if (!strncmp(*argv, "vy", strlen(*argv))) {
      row[i] = VY;
    }
    else if (!strncmp(*argv, "vz", strlen(*argv))) {
      row[i] = VZ;
    }
    else if (!strncmp(*argv, "fx", strlen(*argv))) {
      row[i] = FX;
    }
    else if (!strncmp(*argv, "fy", strlen(*argv))) {
      row[i] = FY;
    }
    else if (!strncmp(*argv, "fz", strlen(*argv))) {
      row[i] = FZ;
    }
    else if (!strncmp(*argv, "type", strlen(*argv))) {
      row[i] = TYPE;
    }
    else {
      Tcl_AppendResult(interp, "no particle data field \"", *argv, "\"?",
		       (char *) NULL);
      free(row);
      return (TCL_ERROR);
    }
    argv++;
  }

  if (!particle_node)
    build_particle_node();

  /* write header and row data */
  memmove(header.magic, MDMAGIC, 4*sizeof(char));
  header.n_rows = argc;
  Tcl_Write(channel, (char *)&header, sizeof(header));
  Tcl_Write(channel, row, header.n_rows*sizeof(char));

  for (p = 0; p <= max_seen_particle; p++) {
    Particle data;
    if (get_particle_data(p, &data) == ES_OK) {
      unfold_position(data.r.p, data.m.v, data.l.i);

      /* write particle index */
      Tcl_Write(channel, (char *)&p, sizeof(int));

      for (i = 0; i < header.n_rows; i++) {
	switch (row[i]) {
	case POSX: Tcl_Write(channel, (char *)&data.r.p[0], sizeof(double)); break;
	case POSY: Tcl_Write(channel, (char *)&data.r.p[1], sizeof(double)); break;
	case POSZ: Tcl_Write(channel, (char *)&data.r.p[2], sizeof(double)); break;
	case VX:   Tcl_Write(channel, (char *)&data.m.v[0], sizeof(double)); break;
	case VY:   Tcl_Write(channel, (char *)&data.m.v[1], sizeof(double)); break;
	case VZ:   Tcl_Write(channel, (char *)&data.m.v[2], sizeof(double)); break;
	case FX:   Tcl_Write(channel, (char *)&data.f.f[0], sizeof(double)); break;
	case FY:   Tcl_Write(channel, (char *)&data.f.f[1], sizeof(double)); break;
	case FZ:   Tcl_Write(channel, (char *)&data.f.f[2], sizeof(double)); break;
#ifdef MASS
	case MASSES: Tcl_Write(channel, (char *)&data.p.mass, sizeof(double)); break;
#endif
#ifdef ELECTROSTATICS
	case Q:    Tcl_Write(channel, (char *)&data.p.q, sizeof(double)); break;
#endif
#ifdef DIPOLES
	case MX:   Tcl_Write(channel, (char *)&data.r.dip[0], sizeof(double)); break;
	case MY:   Tcl_Write(channel, (char *)&data.r.dip[1], sizeof(double)); break;
	case MZ:   Tcl_Write(channel, (char *)&data.r.dip[2], sizeof(double)); break;
#endif
	case TYPE: Tcl_Write(channel, (char *)&data.p.type, sizeof(int)); break;
	}
      }
      free_particle(&data);
    }
  }
  /* end marker */
  Tcl_Write(channel, (char *)&end_num, sizeof(int));
  free(row);
  return TCL_OK;
}
Esempio n. 8
0
// Setup the virtual_sites_relative properties of a particle so that the given virtaul particle will follow the given real particle
int vs_relate_to(int part_num, int relate_to)
{
    // Get the data for the particle we act on and the one we wnat to relate
    // it to.
    Particle  p_current,p_relate_to;
    if ((get_particle_data(relate_to,&p_relate_to)!=TCL_OK) || 
        (get_particle_data(part_num,&p_current)!=TCL_OK)) {
         printf("Could not retrieve particle data for the given id.\n");
          return TCL_ERROR;
    }
    
    // get teh distance between the particles
    double d[3];
    get_mi_vector(d, p_current.r.p,p_relate_to.r.p);
    
    // Set the particle id of the particle we want to relate to and the distnace
    if (set_particle_vs_relative(part_num, relate_to, sqrt(sqrlen(d))) == TCL_ERROR) {
      printf("setting the vs_relative attributes failed.\n");
      return TCL_ERROR;
    }

    // Now, calculate the quaternions which specify the angle between 
    // the director of the particel we relate to and the vector
    // (paritlce_we_relate_to - this_particle)
    double quat[4];
    // The vs_relative implemnation later obtains the direcotr by multiplying
    // the quaternions representing the orientation of the real particle
    // with those in the virtual particle. The re quulting quaternion is then
    // converted to a director.
    // Whe have quat_(real particle) *quat_(virtual particle) 
    // = quat_(obtained from desired director)
    // Resolving this for the quat_(virtaul particle)

    //Normalize desired director
    double l=sqrt(sqrlen(d));
    int i;
    for (i=0;i<3;i++)
     d[i]/=l;

    // Obtain quaternions from desired director
    double quat_director[4];
    convert_quatu_to_quat(d, quat_director);

    // Define quat as described above:
    double x=0;
    for (i=0;i<4;i++)
     x+=p_relate_to.r.quat[i]*p_relate_to.r.quat[i];

    quat[0]=0;
    for (i=0;i<4;i++)
     quat[0] +=p_relate_to.r.quat[i]*quat_director[i];
    
    quat[1] =-quat_director[0] *p_relate_to.r.quat[1] 
       +quat_director[1] *p_relate_to.r.quat[0]
       +quat_director[2] *p_relate_to.r.quat[3]
       -quat_director[3] *p_relate_to.r.quat[2];
    quat[2] =p_relate_to.r.quat[1] *quat_director[3] 
      + p_relate_to.r.quat[0] *quat_director[2] 
      - p_relate_to.r.quat[3] *quat_director[1] 
      - p_relate_to.r.quat[2] * quat_director[0];
    quat[3] =quat_director[3] *p_relate_to.r.quat[0]
      - p_relate_to.r.quat[3] *quat_director[0] 
      + p_relate_to.r.quat[2] * quat_director[1] 
      - p_relate_to.r.quat[1] *quat_director[2];
    for (i=0;i<4;i++)
     quat[i]/=x;
   
   
   // Verify result
   double qtemp[4];
   multiply_quaternions(p_relate_to.r.quat,quat,qtemp);
   for (i=0;i<4;i++)
    if (fabs(qtemp[i]-quat_director[i])>1E-9)
     printf("Component %d: %f instead of %f\n",i,qtemp[i],quat_director[i]);


   // Save the quaternions in the particle
   if (set_particle_quat(part_num, quat) == TCL_ERROR) {
     printf("set particle position first\n");

     return TCL_ERROR;
   }
   
   return TCL_OK;
}