Пример #1
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;
}
Пример #2
0
int place_particle(int part, double p[3])
{
  int i;
  int pnode, retcode = ES_PART_OK;

  if (part < 0)
    return ES_PART_ERROR;

  if (!particle_node)
    build_particle_node();

  pnode = (part <= max_seen_particle) ? particle_node[part] : -1;
  if (pnode == -1) {
    /* new particle, node by spatial position */
    pnode = cell_structure.position_to_node(p);

    /* master node specific stuff */
    realloc_particle_node(part);
    particle_node[part] = pnode;

    /* fill up possible gap */
    for (i = max_seen_particle + 1; i < part; i++)
      particle_node[i] = -1;

    retcode = ES_PART_CREATED;

    mpi_place_new_particle(pnode, part, p);

  } else {
    mpi_place_particle(pnode, part, p);
  }

  return retcode;
}
Пример #3
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;
}
Пример #4
0
int change_particle_bond(int part, int *bond, int _delete)
{
  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;
  if(_delete != 0 || bond == NULL)
    _delete = 1;

  if (bond != NULL) {
    if (bond[0] < 0 || bond[0] >= n_bonded_ia) {
        ostringstream msg;
        msg <<"invalid/unknown bonded interaction type " << bond[0];
        runtimeError(msg);
      return ES_ERROR;
    }
  }
  return mpi_send_bond(pnode, part, bond, _delete);
}
Пример #5
0
int set_particle_fix(int part,  int flag)
{
  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;
  mpi_send_ext_force(pnode, part, flag, COORDS_FIX_MASK, NULL);
  return ES_OK;
}
Пример #6
0
int get_particle_data(int part, Particle *data)
{
  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;
  mpi_recv_part(pnode, part, data);
  return ES_OK;
}
Пример #7
0
int set_particle_rotational_inertia(int part, double rinertia[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;
  mpi_send_rotational_inertia(pnode, part, rinertia);
  return ES_OK;
}
Пример #8
0
int set_particle_dipm(int part, double dipm)
{
  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;
  mpi_send_dipm(pnode, part, dipm);
  return ES_OK;
}
Пример #9
0
int set_particle_mu_E(int part, double mu_E[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;
  mpi_send_mu_E(pnode, part, mu_E);
  return ES_OK;
}
Пример #10
0
int set_particle_virtual(int part, int isVirtual)
{
  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;
  mpi_send_virtual(pnode, part, isVirtual); 
  return ES_OK;
}
Пример #11
0
int set_particle_solvation(int part, double * solvation)
{
  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;
  mpi_send_solvation(pnode, part, solvation);
  return ES_OK;
}
Пример #12
0
int set_particle_rotation(int part, int rot)
{
  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;
  mpi_send_rotation(pnode, part, rot);
  return ES_OK;
}
Пример #13
0
int set_particle_quat(int part, double quat[4])
{
  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;
  mpi_send_quat(pnode, part, quat);
  return ES_OK;
}
Пример #14
0
int change_exclusion(int part1, int part2, int _delete)
{
  if (!particle_node)
    build_particle_node();

  if (part1 < 0 || part1 > max_seen_particle ||
      part2 < 0 || part2 > max_seen_particle ||
      part1 == part2 ||
      particle_node[part1] == -1 ||
      particle_node[part2] == -1)
    return ES_ERROR;

  mpi_send_exclusion(part1, part2, _delete);
  return ES_OK;
}
Пример #15
0
int set_particle_mol_id(int part, int mid)
{
  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;
  mpi_send_mol_id(pnode, part, mid);
  return ES_OK;
}
Пример #16
0
int set_particle_ext_force(int part, int flag, double force[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;

  mpi_send_ext_force(pnode, part, flag, PARTICLE_EXT_FORCE, force);
    return ES_OK;
}
Пример #17
0
int set_particle_temperature(int part, double T)
{
  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;
    
  mpi_set_particle_temperature(pnode, part, T);
  return ES_OK;
}
Пример #18
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;
}
Пример #19
0
int set_particle_vs_relative(int part, int vs_relative_to, double vs_distance)
{
  // Find out, on what node the particle is
  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;
  
  // Send the stuff
  mpi_send_vs_relative(pnode, part, vs_relative_to, vs_distance);
  return ES_OK;
}
Пример #20
0
int set_particle_gamma(int part, double gamma)
{
  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;
    
  mpi_set_particle_gamma(pnode, part, gamma);
  return ES_OK;
}
Пример #21
0
int set_particle_torque_body(int part, double torque[3])
{
  /* Nothing to be done but pass, since the coordinates
     are already in the proper frame */

  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;
  mpi_send_torque(pnode, part, torque);
  return ES_OK;
}
Пример #22
0
int change_particle_bond(int part, int *bond, int _delete)
{
  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;
  if(_delete != 0 || bond == NULL)
    _delete = 1;

  if (bond != NULL) {
    if (bond[0] < 0 || bond[0] >= n_bonded_ia) {
      char *errtxt = runtime_error(128 + ES_INTEGER_SPACE);
      ERROR_SPRINTF(errtxt, "{048 invalid/unknown bonded interaction type %d}", bond[0]);
      return ES_ERROR;
    }
  }
  return mpi_send_bond(pnode, part, bond, _delete);
}
Пример #23
0
int tclcommand_readmd(ClientData dummy, Tcl_Interp *interp,
	   int argc, char **argv)
{
  char *row;
  int pos_row[3] = { -1 }, v_row[3] = { -1 }, 
  #ifdef DIPOLES 
  dip_row[3] = { -1 }, 
  #endif
  f_row[3] = { -1 };
  
  int av_pos = 0, av_v = 0, 
#ifdef DIPOLES 
    av_dip=0, 
#endif
#ifdef MASS
    av_mass=0,
#endif
#ifdef SHANCHEN
    av_solvation=0,
#endif
    av_f = 0,
#ifdef ELECTROSTATICS
    av_q = 0,
#endif
    av_type = 0;
  
  int node, i;
  struct MDHeader header;
  Particle data;
  int tcl_file_mode;
  Tcl_Channel channel;

  if (argc != 2) {
    Tcl_AppendResult(interp, "wrong # args:  should be \"",
		     argv[0], " <file>\"",
		     (char *) NULL);
    return (TCL_ERROR);
  }

  if ((channel = Tcl_GetChannel(interp, argv[1], &tcl_file_mode)) == NULL)
    return (TCL_ERROR);

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

  Tcl_Read(channel, (char *)&header, sizeof(header));
  /* check token */
  if (strncmp(header.magic, MDMAGIC, 4) || header.n_rows < 0) {
    Tcl_AppendResult(interp, "data file \"", argv[1],
		     "\" does not contain tcl MD data",
		     (char *) NULL);
    return (TCL_ERROR);
  }

  if (!particle_node)
    build_particle_node();

  /* parse rows */
  row = (char*)malloc(header.n_rows*sizeof(char));
  for (i = 0; i < header.n_rows; i++) {
    Tcl_Read(channel, (char *)&row[i], sizeof(char));
    switch (row[i]) {
    case POSX: pos_row[0] = i; break;
    case POSY: pos_row[1] = i; break;
    case POSZ: pos_row[2] = i; break;
    case   VX:   v_row[0] = i; break;
    case   VY:   v_row[1] = i; break;
    case   VZ:   v_row[2] = i; break;
#ifdef DIPOLES
    case   MX:   dip_row[0] = i; break;
    case   MY:   dip_row[1] = i; break;
    case   MZ:   dip_row[2] = i; break;
#endif
    case   FX:   f_row[0] = i; break;
    case   FY:   f_row[1] = i; break;
    case   FZ:   f_row[2] = i; break;
#ifdef MASS
    case MASSES: av_mass  = 1; break;
#endif
#ifdef SHANCHEN
    case SOLVATION: av_solvation = 1; break;
#endif
#ifdef ELECTROSTATICS
    case    Q:   av_q     = 1; break;
#endif
    case TYPE:   av_type  = 1; break;
    }
  }

  /* *_row[0] tells if * data is completely available -
   * otherwise we ignore it */
  if (pos_row[0] != -1 && pos_row[1] != -1 && pos_row[2] != -1) {
    av_pos = 1;
  }
  if (v_row[0] != -1 && v_row[1] != -1 && v_row[2] != -1) {
    av_v = 1;
  }
  if (f_row[0] != -1 && f_row[1] != -1 && f_row[2] != -1) {
    av_f = 1;
  }
  
  #ifdef DIPOLES
  if (dip_row[0] != -1 && dip_row[1] != -1 && dip_row[2] != -1) {
    av_dip = 1;
  }
  #endif


  while (!Tcl_Eof(channel)) {
    Tcl_Read(channel, (char *)&data.p.identity, sizeof(int));
    if (data.p.identity == -1)
      break;

    /* printf("id=%d\n", data.identity); */

    if (data.p.identity < 0) {
      Tcl_AppendResult(interp, "illegal data format in data file \"", argv[1],
		       "\", perhaps wrong file?",
		       (char *) NULL);
      free(row);
      return (TCL_ERROR);
    }

    for (i = 0; i < header.n_rows; i++) {
      switch (row[i]) {
      case POSX: Tcl_Read(channel, (char *)&data.r.p[0], sizeof(double)); break;
      case POSY: Tcl_Read(channel, (char *)&data.r.p[1], sizeof(double)); break;
      case POSZ: Tcl_Read(channel, (char *)&data.r.p[2], sizeof(double)); break;
      case   VX: Tcl_Read(channel, (char *)&data.m.v[0], sizeof(double)); break;
      case   VY: Tcl_Read(channel, (char *)&data.m.v[1], sizeof(double)); break;
      case   VZ: Tcl_Read(channel, (char *)&data.m.v[2], sizeof(double)); break;
      case   FX: Tcl_Read(channel, (char *)&data.f.f[0], sizeof(double)); break;
      case   FY: Tcl_Read(channel, (char *)&data.f.f[1], sizeof(double)); break;
      case   FZ: Tcl_Read(channel, (char *)&data.f.f[2], sizeof(double)); break;
      case MASSES:
#ifdef MASS
          Tcl_Read(channel, (char *)&data.p.mass, sizeof(double)); break;
#else
          {
              double dummy_mass;
              Tcl_Read(channel, (char *)&dummy_mass, sizeof(double)); break;
          }
#endif
#ifdef ELECTROSTATICS
      case    Q: Tcl_Read(channel, (char *)&data.p.q, sizeof(double)); break;
#endif
#ifdef DIPOLES
      case   MX: Tcl_Read(channel, (char *)&data.r.dip[0], sizeof(double)); break;
      case   MY: Tcl_Read(channel, (char *)&data.r.dip[1], sizeof(double)); break;
      case   MZ: Tcl_Read(channel, (char *)&data.r.dip[2], sizeof(double)); break;
#endif

      case TYPE: Tcl_Read(channel, (char *)&data.p.type, sizeof(int)); break;
      }
    }

    node = (data.p.identity <= max_seen_particle) ? particle_node[data.p.identity] : -1;
    if (node == -1) {
      if (!av_pos) {
	Tcl_AppendResult(interp, "new particle without position data",
			 (char *) NULL);
	free(row);
	return (TCL_ERROR);
      }
    }

    if (av_pos)
      place_particle(data.p.identity, data.r.p);
#ifdef MASS
    if (av_mass)
      set_particle_mass(data.p.identity, data.p.mass);
#endif
#ifdef SHANCHEN
    if (av_solvation)
      set_particle_solvation(data.p.identity, data.p.solvation);
#endif
#ifdef ELECTROSTATICS
    if (av_q)
      set_particle_q(data.p.identity, data.p.q);
#endif
#ifdef DIPOLES
    if (av_dip)
      set_particle_dip(data.p.identity, data.r.dip);
#endif
    if (av_v)
      set_particle_v(data.p.identity, data.m.v);
    if (av_f)
      set_particle_f(data.p.identity, data.f.f);
    if (av_type)
      set_particle_type(data.p.identity, data.p.type);
  }

  free(row);
  return TCL_OK;
}
Пример #24
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;
}