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; }
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; }
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); }
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; }
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; }
// 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; }