int tclcommand_inter_coulomb_parse_ewald(Tcl_Interp * interp, int argc, char ** argv) { double r_cut, alpha; int i, kmax; coulomb.method = COULOMB_EWALD; #ifdef PARTIAL_PERIODIC if(PERIODIC(0) == 0 || PERIODIC(1) == 0 || PERIODIC(2) == 0) { Tcl_AppendResult(interp, "Need periodicity (1,1,1) with Coulomb EWALD", (char *) NULL); return TCL_ERROR; } #endif if (argc < 2) { Tcl_AppendResult(interp, "expected: inter coulomb <bjerrum> ewald <r_cut> <alpha> <kmax>", (char *) NULL); return TCL_ERROR; } if(! ARG0_IS_D(r_cut)) return TCL_ERROR; if(argc != 3) { Tcl_AppendResult(interp, "wrong # arguments: inter coulomb <bjerrum> ewald <r_cut> <alpha> <kmax>", (char *) NULL); return TCL_ERROR; } if(! ARG_IS_D(1, alpha)) return TCL_ERROR; if(! ARG_IS_I(2, kmax)) return TCL_ERROR; if ((i = ewald_set_params(r_cut, alpha, kmax)) < 0) { switch (i) { case -1: Tcl_AppendResult(interp, "r_cut must be positive", (char *) NULL); break; case -4: Tcl_AppendResult(interp, "alpha must be positive", (char *) NULL); break; case -5: Tcl_AppendResult(interp, "kmax must be greater than zero", (char *) NULL); default:; Tcl_AppendResult(interp, "unspecified error", (char *) NULL); } return TCL_ERROR; } return TCL_OK; }
void Mmm1dgpuForce::check_periodicity() { if (PERIODIC(0) || PERIODIC(1) || !PERIODIC(2)) { std::cerr << "MMM1D requires periodicity (0,0,1)" << std::endl; exit(EXIT_FAILURE); } }
int mdlc_sanity_checks() { #ifdef PARTIAL_PERIODIC char *errtxt; if (!PERIODIC(0) || !PERIODIC(1) || !PERIODIC(2)) { errtxt = runtime_error(128); ERROR_SPRINTF(errtxt, "{006 mdlc requires periodicity 1 1 1} "); return 1; } #endif return 0; }
int mdlc_sanity_checks() { if (!PERIODIC(0) || !PERIODIC(1) || !PERIODIC(2)) { ostringstream msg; msg <<"mdlc requires periodicity 1 1 1"; runtimeError(msg); return 1; } // It will be desirable to have a checking function that check that the slab geometry is such that // the short direction is along the z component. return 0; }
int MMM1D_sanity_checks() { char *errtxt; if (PERIODIC(0) || PERIODIC(1) || !PERIODIC(2)) { errtxt = runtime_error(128); ERROR_SPRINTF(errtxt, "{022 MMM1D requires periodicity 0 0 1} "); return 1; } if (cell_structure.type != CELL_STRUCTURE_NSQUARE) { errtxt = runtime_error(128); ERROR_SPRINTF(errtxt, "{023 MMM1D requires n-square cellsystem} "); return 1; } return 0; }
// Update the pos of the given virtual particle as defined by the real // particles in the same molecule void update_mol_pos_particle(Particle *p) { // First obtain the real particle responsible for this virtual particle: // Find the 1st real particle in the topology for the virtual particle's mol_id Particle *p_real = vs_relative_get_real_particle(p); // Check, if a real particle was found if (!p_real) { char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"virtual_sites_relative.cpp - update_mol_pos_particle(): No real particle associated with virtual site.\n"); return; } // Calculate the quaternion defining the orientation of the vecotr connectinhg // the virtual site and the real particle // This is obtained, by multiplying the quaternion representing the director // of the real particle with the quaternion of the virtual particle, which // specifies the relative orientation. double q[4]; multiply_quaternions(p_real->r.quat,p->r.quat,q); // Calculate the director resulting from the quaternions double director[3]; convert_quat_to_quatu(q,director); // normalize double l =sqrt(sqrlen(director)); // Division comes in the loop below // Calculate the new position of the virtual sites from // position of real particle + director int i; double new_pos[3]; double tmp; for (i=0;i<3;i++) { new_pos[i] =p_real->r.p[i] +director[i]/l*p->p.vs_relative_distance; // Handle the case that one of the particles had gone over the periodic // boundary and its coordinate has been folded #ifdef PARTIAL_PERIODIC if (PERIODIC(i)) #endif { tmp =p->r.p[i] -new_pos[i]; //printf("%f\n",tmp); if (tmp > box_l[i]/2.) { //printf("greater than box_l/2 %f\n",tmp); p->r.p[i] =new_pos[i] + box_l[i]; } else if (tmp < -box_l[i]/2.) { //printf("smaller than box_l/2 %f\n",tmp); p->r.p[i] =new_pos[i] - box_l[i]; } else p->r.p[i] =new_pos[i]; } #ifdef PARTIAL_PERIODIC else p->r.p[i] =new_pos[i]; #endif // fold_coordinate(p->r.p,p->l.i,i); } }
int mdlc_sanity_checks() { #ifdef PARTIAL_PERIODIC char *errtxt; if (!PERIODIC(0) || !PERIODIC(1) || !PERIODIC(2)) { errtxt = runtime_error(128); ERROR_SPRINTF(errtxt, "{006 mdlc requires periodicity 1 1 1} "); return 1; } #endif // It will be desirable to have a checking function that check that the slab geometry is such that // the short direction is along the z component. return 0; }
static void putInteractingInPrevList(int atom,struct parameters *par,struct systemPos *pos,struct bondList *blist, int *posInPrevList){ int j,bondListPosj,ngbrListPosj; double drx_ij,dry_ij,drz_ij; double rij2; double r02; /* r02 is the distance at which ngbr atoms are included, shoud this include skin ? probably not! */ /* r02=POW2(sqrt(wwwPar.repR02)+par->skin); */ r02=wwwPar.repR02; /* then the atoms it is bonded to */ bondListPosj=blist->head[atom]; /*where the bonds start*/ while(blist->list[bondListPosj]!=-1) /*get bonds of i, stops when the bonds od atom i+1 comes*/ prevInteractionList[(*posInPrevList)++]=blist->list[bondListPosj++]; /* and last the atoms it is ngbr with */ if(wwwPar.includeRepPot){ ngbrListPosj=nd.head[atom]; /*where the ngbrs start*/ while(nd.list[ngbrListPosj]!=-1){ /*get ngbrs of i, stops when the ngbrs of atom i+1 comes*/ j=nd.list[ngbrListPosj++]; /*j is the ngbr*/ drx_ij=pos->x[j]-pos->x[atom]; dry_ij=pos->y[j]-pos->y[atom]; drz_ij=pos->z[j]-pos->z[atom]; PERIODIC(drx_ij,dry_ij,drz_ij); rij2=LENGTH2(drx_ij,dry_ij,drz_ij); if( rij2 <r02 ) prevInteractionList[(*posInPrevList)++]=j; } } prevInteractionList[(*posInPrevList)++]=-1; }
/** update the 'shift' member of those GhostCommunicators, which use that value to speed up the folding process of its ghost members (see \ref dd_prepare_comm for the original), i.e. all which have GHOSTTRANS_POSSHFTD or'd into 'data_parts' upon execution of \ref dd_prepare_comm. */ void dd_update_communicators_w_boxl() { int cnt=0; /* direction loop: x, y, z */ for(int dir=0; dir<3; dir++) { /* lr loop: left right */ for(int lr=0; lr<2; lr++) { if(node_grid[dir] == 1) { #ifdef PARTIAL_PERIODIC if( PERIODIC(dir ) || (boundary[2*dir+lr] == 0) ) #endif { /* prepare folding of ghost positions */ if(boundary[2*dir+lr] != 0) { cell_structure.exchange_ghosts_comm.comm[cnt].shift[dir] = boundary[2*dir+lr]*box_l[dir]; cell_structure.update_ghost_pos_comm.comm[cnt].shift[dir] = boundary[2*dir+lr]*box_l[dir]; } cnt++; } } else { /* i: send/recv loop */ for(int i=0; i<2; i++) { #ifdef PARTIAL_PERIODIC if( PERIODIC(dir) || (boundary[2*dir+lr] == 0) ) #endif if((node_pos[dir]+i)%2==0) { /* prepare folding of ghost positions */ if(boundary[2*dir+lr] != 0) { cell_structure.exchange_ghosts_comm.comm[cnt].shift[dir] = boundary[2*dir+lr]*box_l[dir]; cell_structure.update_ghost_pos_comm.comm[cnt].shift[dir] = boundary[2*dir+lr]*box_l[dir]; } cnt++; } #ifdef PARTIAL_PERIODIC if( PERIODIC(dir) || (boundary[2*dir+(1-lr)] == 0) ) #endif if((node_pos[dir]+(1-i))%2==0) { cnt++; } } } } } }
static void set_params_safe(const std::string &method, const std::string ¶ms, bool dipolar_ia) { if(scafacos && (scafacos->method != method)) { delete scafacos; scafacos = 0; } scafacos = new Scafacos(method, comm_cart, params); scafacos->parse_parameters(params); int per[3] = { PERIODIC(0) != 0, PERIODIC(1) != 0, PERIODIC(2) != 0 }; scafacos->set_dipolar(dipolar_ia); scafacos->set_common_parameters(box_l, per, n_part); on_coulomb_change(); tune(); on_coulomb_change(); }
void computeEnergy(SystemInterface &s) { dds_float box[3]; int per[3]; for (int i=0;i<3;i++) { box[i]=s.box()[i]; per[i] = (PERIODIC(i)); } DipolarDirectSum_kernel_wrapper_energy(k,s.npart_gpu(), s.rGpuBegin(), s.dipGpuBegin(), box,per,(&(((CUDA_energy*)s.eGpu())->dipolar))); };
void computeForces(SystemInterface &s) { dds_float box[3]; int per[3]; for (int i=0;i<3;i++) { box[i]=s.box()[i]; per[i] = (PERIODIC(i)); } DipolarDirectSum_kernel_wrapper_force(k,s.npart_gpu(), s.rGpuBegin(), s.dipGpuBegin(), s.fGpuBegin(),s.torqueGpuBegin(),box,per); };
int EWALD_sanity_checks() { char *errtxt; int ret = 0; if (!PERIODIC(0) || !PERIODIC(1) || !PERIODIC(2)) { errtxt = runtime_error(128); sprintf(errtxt, "{EWALD requires periodicity 1 1 1} "); ret = 1; } if( (box_l[0] != box_l[1]) || (box_l[1] != box_l[2]) ) { errtxt = runtime_error(128); sprintf(errtxt,"{EWALD at present requires a cubic box} "); ret = 1; } if (EWALD_sanity_checks_boxl()) ret = 1; return ret; }
/* new version for new topology structure */ int analyze_fold_molecules(float *coord, double shift[3]) { int m,p,i, tmp; int mol_size, ind; double cm_tmp, com[3]; #ifdef LEES_EDWARDS if(lees_edwards_offset != 0.0 ){ fprintf(stderr, "Error: Folding molecules not supported under Lees-Edwards.\n"); exit(8); } #endif /* check molecule information */ if ( n_molecules < 0 ) return ES_ERROR; if (!sortPartCfg()) { ostringstream msg; msg <<"analyze_fold_molecules: could not sort particle config, particle ids not consecutive?"; runtimeError(msg); return ES_ERROR; } /* loop molecules */ for(m=0; m<n_molecules; m++) { mol_size = topology[m].part.n; if(mol_size > 0) { /* calc center of mass */ calc_mol_center_of_mass(topology[m],com); /* fold coordinates */ for(i=0; i<3; i++) { if ( PERIODIC(i) ) { tmp = (int)floor((com[i]+shift[i])*box_l_i[i]); cm_tmp =0.0; for(p=0; p<mol_size; p++) { ind = 3*topology[m].part.e[p] + i; coord[ind] -= tmp*box_l[i]; coord[ind] += shift[i]; cm_tmp += coord[ind]; } cm_tmp /= (double)mol_size; if(cm_tmp < -10e-6 || cm_tmp > box_l[i]+10e-6) { ostringstream msg; msg <<"analyze_fold_molecules: chain center of mass is out of range (coord " << i << ": " << cm_tmp << " not in box_l " << box_l[i] << ")"; runtimeError(msg); return ES_ERROR; } } } } } return ES_OK; }
int comfixed_set_params(int part_type_a, int part_type_b, int flag) { Particle *p; int i, j, np, c; Cell *cell; IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b); if (!data) return 1; if (n_nodes > 1) return 2; if (PERIODIC(0) || PERIODIC(1) || PERIODIC(2)) { return 3; } data->COMFIXED_flag = flag; /* broadcast interaction parameters */ mpi_bcast_ia_params(part_type_a, part_type_b); for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { if(p[i].p.type==part_type_a) { for(j = 0; j < 3; j++) { p[i].m.v[j] = 0.; p[i].f.f[j] = 0.; } } } } return ES_OK; }
/* new version for new topology structure */ int analyze_fold_molecules(float *coord, double shift[3]) { int m,p,i, tmp; int mol_size, ind; double cm_tmp, com[3]; /* check molecule information */ if ( n_molecules < 0 ) return (TCL_ERROR); if (!sortPartCfg()) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt, "{059 analyze_fold_molecules: could not sort particle config, particle ids not consecutive?} "); return TCL_ERROR; } /* loop molecules */ for(m=0; m<n_molecules; m++) { mol_size = topology[m].part.n; if(mol_size > 0) { /* calc center of mass */ calc_mol_center_of_mass(topology[m],com); /* fold coordinates */ for(i=0; i<3; i++) { if ( PERIODIC(i) ) { tmp = (int)floor((com[i]+shift[i])*box_l_i[i]); cm_tmp =0.0; for(p=0; p<mol_size; p++) { ind = 3*topology[m].part.e[p] + i; coord[ind] -= tmp*box_l[i]; coord[ind] += shift[i]; cm_tmp += coord[ind]; } cm_tmp /= (double)mol_size; if(cm_tmp < -10e-6 || cm_tmp > box_l[i]+10e-6) { char *errtxt = runtime_error(128 + TCL_INTEGER_SPACE + 2*TCL_DOUBLE_SPACE); ERROR_SPRINTF(errtxt,"{060 analyze_fold_molecules: chain center of mass is out of range (coord %d: %.14f not in box_l %.14f)} ", i,cm_tmp,box_l[i]); return (TCL_ERROR); } } } } } return (TCL_OK); }
void check_particles() { Particle *part; int *is_here; Cell *cell; int n, np, dir, c, p; int cell_part_cnt=0, local_part_cnt=0; int cell_err_cnt=0; double skin2 = (skin != -1) ? skin/2 : 0; CELL_TRACE(fprintf(stderr, "%d: entering check_particles\n", this_node)); /* check the consistency of particle_nodes */ /* to this aim the array is broadcasted temporarily */ if (this_node != 0) particle_node = malloc((max_seen_particle + 1)*sizeof(int)); is_here = malloc((max_seen_particle + 1)*sizeof(int)); memset(is_here, 0, (max_seen_particle + 1)*sizeof(int)); MPI_Bcast(particle_node, max_seen_particle + 1, MPI_INT, 0, MPI_COMM_WORLD); /* checks: part_id, part_pos, local_particles id */ for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; cell_part_cnt += cell->n; part = cell->part; np = cell->n; for(n=0; n<cell->n ; n++) { if(part[n].p.identity < 0 || part[n].p.identity > max_seen_particle) { fprintf(stderr,"%d: check_particles: ERROR: Cell %d Part %d has corrupted id=%d\n", this_node,c,n,cell->part[n].p.identity); errexit(); } is_here[part[n].p.identity] = 1; for(dir=0;dir<3;dir++) { if(PERIODIC(dir) && (part[n].r.p[dir] < -skin2 || part[n].r.p[dir] > box_l[dir] + skin2)) { fprintf(stderr,"%d: check_particles: ERROR: illegal pos[%d]=%f of part %d id=%d in cell %d\n", this_node,dir,part[n].r.p[dir],n,part[n].p.identity,c); errexit(); } } if(local_particles[part[n].p.identity] != &part[n]) { fprintf(stderr,"%d: check_particles: ERROR: address mismatch for part id %d: local: %p cell: %p in cell %d\n", this_node,part[n].p.identity,local_particles[part[n].p.identity], &part[n],c); errexit(); } if (particle_node[part[n].p.identity] != this_node) { fprintf(stderr,"%d: check_particles: ERROR: node for particle %d wrong\n", this_node,part[n].p.identity); errexit(); } } } CELL_TRACE(fprintf(stderr,"%d: check_particles: %d particles in local cells.\n", this_node,cell_part_cnt)); /* checks: local particle id */ for(n = 0; n <= max_seen_particle; n++) { if(local_particles[n] != NULL) { local_part_cnt ++; if(local_particles[n]->p.identity != n) { fprintf(stderr,"%d: check_particles: ERROR: local_particles part %d has corrupted id %d\n", this_node,n,local_particles[n]->p.identity); errexit(); } } } CELL_TRACE(fprintf(stderr,"%d: check_particles: %d particles in local_particles.\n", this_node,local_part_cnt)); /* EXIT on severe errors */ if(cell_err_cnt>0) { fprintf(stderr,"%d: check_particles: %d ERRORS detected in cell structure!\n",this_node,cell_err_cnt); errexit(); } /* check whether the particles on my node are actually here */ for (p = 0; p <= max_seen_particle; p++) { if (particle_node[p] == this_node) { if (!is_here[p]) { fprintf(stderr,"%d: check_particles: ERROR: particle %d on this node, but not in local cell\n", this_node, p); } } } free(is_here); if (this_node != 0) { free(particle_node); particle_node = NULL; } else { /* check whether the total count of particles is ok */ c = 0; for (p = 0; p <= max_seen_particle; p++) if (particle_node[p] != -1) c++; if (c != n_total_particles) { fprintf(stderr,"%d: check_particles: #particles in particle_node inconsistent\n", this_node); errexit(); } CELL_TRACE(fprintf(stderr,"%d: check_particles: %d particles in particle_node.\n", this_node,c)); } CELL_TRACE(fprintf(stderr, "%d: leaving check_particles\n", this_node)); }
void check_particle_consistency() { Particle *part; Cell *cell; int n, np, dir, c, p; int cell_part_cnt=0, ghost_part_cnt=0, local_part_cnt=0; int cell_err_cnt=0; /* checks: part_id, part_pos, local_particles id */ for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; cell_part_cnt += cell->n; part = cell->part; np = cell->n; for(n=0; n<cell->n ; n++) { if(part[n].p.identity < 0 || part[n].p.identity > max_seen_particle) { fprintf(stderr,"%d: check_particle_consistency: ERROR: Cell %d Part %d has corrupted id=%d\n", this_node,c,n,cell->part[n].p.identity); errexit(); } for(dir=0;dir<3;dir++) { if(PERIODIC(dir) && (part[n].r.p[dir] < -ROUND_ERROR_PREC || part[n].r.p[dir] - box_l[dir] > ROUND_ERROR_PREC)) { fprintf(stderr,"%d: check_particle_consistency: ERROR: illegal pos[%d]=%f of part %d id=%d in cell %d\n", this_node,dir,part[n].r.p[dir],n,part[n].p.identity,c); errexit(); } } if(local_particles[part[n].p.identity] != &part[n]) { fprintf(stderr,"%d: check_particle_consistency: ERROR: address mismatch for part id %d: local: %p cell: %p in cell %d\n", this_node,part[n].p.identity,local_particles[part[n].p.identity], &part[n],c); errexit(); } } } for (c = 0; c < ghost_cells.n; c++) { cell = ghost_cells.cell[c]; if(cell->n>0) { ghost_part_cnt += cell->n; fprintf(stderr,"%d: check_particle_consistency: WARNING: ghost_cell %d contains %d particles!\n", this_node,c,cell->n); } } CELL_TRACE(fprintf(stderr,"%d: check_particle_consistency: %d particles in cells, %d particles in ghost_cells.\n", this_node,cell_part_cnt, ghost_part_cnt)); /* checks: local particle id */ for(n=0; n< max_seen_particle+1; n++) { if(local_particles[n] != NULL) { local_part_cnt ++; if(local_particles[n]->p.identity != n) { fprintf(stderr,"%d: check_particle_consistency: ERROR: local_particles part %d has corrupted id %d\n", this_node,n,local_particles[n]->p.identity); errexit(); } } } CELL_TRACE(fprintf(stderr,"%d: check_particle_consistency: %d particles in local_particles.\n", this_node,local_part_cnt)); /* EXIT on severe errors */ if(cell_err_cnt>0) { fprintf(stderr,"%d: check_particle_consistency: %d ERRORS detected in cell structure!\n",this_node,cell_err_cnt); errexit(); } if(local_part_cnt != cell_part_cnt) { fprintf(stderr,"%d: check_particle_consistency: ERROR: %d parts in cells but %d parts in local_particles\n", this_node,cell_part_cnt,local_part_cnt); for (c = 0; c < local_cells.n; c++) { for(p = 0; p < local_cells.cell[c]->n; p++) fprintf(stderr, "%d: got particle %d in cell %d\n", this_node, local_cells.cell[c]->part[p].p.identity, c); } for(p = 0; p < n_total_particles; p++) if (local_particles[p]) fprintf(stderr, "%d: got particle %d in local_particles\n", this_node, p); if(ghost_part_cnt==0) errexit(); } if(ghost_part_cnt>0) { fprintf(stderr,"%d: check_particle_consistency: ERROR: Found %d illegal ghost particles!\n", this_node,ghost_part_cnt); errexit(); } }
/** Calculate lj-angle force between particle p1 and p2 Involves 6 particles total */ inline void add_ljangle_force(Particle *p1, Particle *p2, IA_parameters *ia_params, double d[3], double dist) { if(!CUTOFF_CHECK(dist < ia_params->LJANGLE_cut)) return; int j; double frac2=0.0, frac10=0.0, rad=0.0, radprime=0.0; double r31[3], r41[3], r52[3], r62[3], rij[3], rik[3], rkn[3]; double l_rij, l_rik, l_rkn, l_rij2, l_rik2, l_rkn2; double cos_jik, cos_ikn; double angular_jik, angular_ikn, angular_jik_prime, angular_ikn_prime; /* Recreate angular dependence of potential by including 6 particles instead of 2. */ Particle *p3=NULL, *p4=NULL, *p5=NULL, *p6=NULL; int part1p, part1n, part2p, part2n; /* Optional 2nd environment */ double effective_eps=ia_params->LJANGLE_eps, z1, z2, z_middle, z_ref, z_ref5, localz0=ia_params->LJANGLE_z0, localdz2=ia_params->LJANGLE_dz/2., localkappa6=pow(1/ia_params->LJANGLE_kappa,6); /* Retrieve the bonded partners from parsing */ if (ia_params->LJANGLE_bonded1type == p1->p.type) { part1p = p1->p.identity + ia_params->LJANGLE_bonded1pos; part1n = p1->p.identity + ia_params->LJANGLE_bonded1neg; part2p = p2->p.identity + ia_params->LJANGLE_bonded2pos; part2n = p2->p.identity + ia_params->LJANGLE_bonded2neg; } else { part1p = p1->p.identity + ia_params->LJANGLE_bonded2pos; part1n = p1->p.identity + ia_params->LJANGLE_bonded2neg; part2p = p2->p.identity + ia_params->LJANGLE_bonded1pos; part2n = p2->p.identity + ia_params->LJANGLE_bonded1neg; } if (part1p >= 0 && part1p < n_part && part1n >= 0 && part1n < n_part && part2p >= 0 && part2p < n_part && part2n >= 0 && part2n < n_part ) { p3 = local_particles[part1p]; p4 = local_particles[part1n]; p5 = local_particles[part2p]; p6 = local_particles[part2n]; /* Check whether pointers have been allocated. * Otherwise, there's a communication error (verlet skin too small). */ if (p3==NULL ||p4==NULL ||p5==NULL ||p6==NULL) fprintf(stderr, "LJANGLE - Communication error, all particles cannot be reached locally.\n"); get_mi_vector(r31, p1->r.p, p3->r.p); get_mi_vector(r41, p1->r.p, p4->r.p); get_mi_vector(r52, p2->r.p, p5->r.p); get_mi_vector(r62, p2->r.p, p6->r.p); /* Bead i represents the central particle of monomer 1. * Bead j is the virtual particle that gives the orientation of monomer 1. * Bead k represents the central particle of monomer 2. * Bead n is the virtual particle that gives the orientation of monomer 2. */ for(j=0; j<3; ++j) { rij[j] = r31[j] + r41[j]; rik[j] = -d[j]; /* At this point, rik[3] has length dist */ rkn[j] = r52[j] + r62[j]; } l_rij2 = sqrlen(rij); l_rik2 = dist*dist; l_rkn2 = sqrlen(rkn); l_rij = sqrt(l_rij2); l_rik = dist; l_rkn = sqrt(l_rkn2); cos_jik = scalar(rij,rik)/(l_rij*l_rik); cos_ikn = -scalar(rik,rkn)/(l_rik*l_rkn); if(cos_jik>0. && cos_ikn>0.) { angular_jik = pow(cos_jik,2); angular_ikn = pow(cos_ikn,2); angular_jik_prime = -2*cos_jik; angular_ikn_prime = -2*cos_ikn; /* Optional 2nd environment */ if (localdz2 > 0.) { /* calculate center position of the interaction (calculate minimal distance) */ z1 = p1->r.p[2]; z2 = p2->r.p[2]; z_middle = z1 + z2; z_middle /= 2.; if (PERIODIC(2)) if (z_middle > box_l[2] || z_middle < 0.) z_middle -= dround(z_middle *box_l_i[2])*box_l[2]; /* If we're in the environment #2 region, calculate the new interaction strength */ if (z_middle > localz0 - localdz2 && z_middle <= localz0) { z_ref = z_middle - localz0 + localdz2; z_ref5 = pow(z_ref,5); effective_eps += (ia_params->LJANGLE_epsprime - ia_params->LJANGLE_eps) * localkappa6*z_ref5*fabs(z_ref) / (1 + localkappa6*z_ref5*z_ref); } else if (z_middle > localz0 && z_middle < localz0 + localdz2) { z_ref = z_middle - localz0 - localdz2; z_ref5 = pow(z_ref,5); effective_eps -= (ia_params->LJANGLE_epsprime - ia_params->LJANGLE_eps) * localkappa6*z_ref5*fabs(z_ref) / (1 + localkappa6*z_ref5*z_ref); } } /* normal case: resulting force/energy smaller than capping. */ if(dist > ia_params->LJANGLE_capradius) { frac2 = SQR(ia_params->LJANGLE_sig/dist); frac10 = frac2*frac2*frac2*frac2*frac2; rad = effective_eps * frac10*(5.0 * frac2 - 6.0); radprime = 60.0 * effective_eps * frac10*(1.0 - frac2) / dist; #ifdef LJ_WARN_WHEN_CLOSE if(radprime > 1000) fprintf(stderr,"%d: LJANGLE-Warning: Pair (%d-%d) force=%f dist=%f\n", this_node,p1->p.identity,p2->p.identity,radprime,dist); #endif } /* capped part of lj-angle potential. */ else if(dist > 0.0) { /* set the length of rik to capradius */ for (j=0; j<3; ++j) rik[j] *= ia_params->LJANGLE_capradius/dist; l_rik = ia_params->LJANGLE_capradius; frac2 = SQR(ia_params->LJANGLE_sig/ia_params->LJANGLE_capradius); frac10 = frac2*frac2*frac2*frac2*frac2; rad = effective_eps * frac10*(5.0 * frac2 - 6.0); radprime = 60.0 * effective_eps * frac10*(1.0 - frac2) / (ia_params->LJANGLE_capradius); } /* Regroup the last two cases in one */ /* Propagate all forces in this function rather than in the forces.hpp file */ if (dist > 0.0) { for(j=0; j<3; ++j) { p1->f.f[j] += angular_jik * angular_ikn * rik[j]/l_rik *radprime + angular_ikn * rad * angular_jik_prime * ( ( 2*rik[j]-rij[j] )/( l_rij*l_rik ) - cos_jik*( 2*rij[j]/l_rij2 - rik[j]/l_rik2 ) ) + angular_jik * rad * angular_ikn_prime * ( rkn[j]/( l_rik*l_rkn ) + cos_ikn*rik[j]/l_rik2 ); p2->f.f[j] += -angular_jik * angular_ikn * rik[j]/l_rik *radprime + angular_ikn * rad * angular_jik_prime * ( rij[j]/( l_rij*l_rik ) - cos_jik*rik[j]/l_rik2 ) + angular_jik * rad * angular_ikn_prime * ( -(2*rik[j]+rkn[j])/(l_rik*l_rkn) - cos_ikn*( 2*rkn[j]/l_rkn2 + rik[j]/l_rik2 ) ); p3->f.f[j] += angular_ikn * rad * angular_jik_prime * ( -rik[j]/(l_rij*l_rik) + cos_jik*rij[j]/l_rij2 ); p4->f.f[j] += angular_ikn * rad * angular_jik_prime * ( -rik[j]/(l_rij*l_rik) + cos_jik*rij[j]/l_rij2 ); p5->f.f[j] += angular_jik * rad * angular_ikn_prime * ( rik[j]/(l_rik*l_rkn) + cos_ikn*rkn[j]/l_rkn2 ); p6->f.f[j] += angular_jik * rad * angular_ikn_prime * ( rik[j]/(l_rik*l_rkn) + cos_ikn*rkn[j]/l_rkn2 ); } } /* this should not happen! In this case consider only radial potential*/ else { LJ_TRACE(fprintf(stderr, "%d: LJ-angle warning: Particles id1=%d id2=%d exactly on top of each other\n",this_node,p1->p.identity,p2->p.identity)); frac2 = SQR(ia_params->LJANGLE_sig/ia_params->LJANGLE_capradius); frac10 = frac2*frac2*frac2*frac2*frac2; rad = effective_eps * frac10*(5.0 * frac2 - 6.0) / ia_params->LJANGLE_capradius; p1->f.f[0] += rad * ia_params->LJANGLE_capradius; } ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: LJANGLE f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p1->f.f[0],p1->f.f[1],p1->f.f[2],p2->p.identity,dist,radprime)); ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: LJANGLE f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p2->f.f[0],p2->f.f[1],p2->f.f[2],p1->p.identity,dist,radprime)); LJ_TRACE(fprintf(stderr,"%d: LJANGLE: Pair (%d-%d) dist=%.3f: force+-: (%.3e,%.3e,%.3e)\n", this_node,p1->p.identity,p2->p.identity,dist,rad*d[0],rad*d[1],rad*d[2])); }
/** Preparation of the halo parallelization scheme. Sets up the * necessary datastructures for \ref halo_communication * @param hc halo communicator beeing created (Input/Output) * @param lattice lattice the communcation is created for (Input) * @param fieldtype field layout of the lattice data (Input) * @param datatype MPI datatype for the lattice data (Input) */ void prepare_halo_communication(HaloCommunicator *hc, Lattice *lattice, Fieldtype fieldtype, MPI_Datatype datatype) { int k, n, dir, lr, cnt, num = 0 ; int *grid = lattice->grid ; int *period = lattice->halo_grid ; for (n=0; n<hc->num; n++) { MPI_Type_free(&(hc->halo_info[n].datatype)); } num = 2*3; /* two communications in each space direction */ hc->num = num ; hc->halo_info = realloc(hc->halo_info,num*sizeof(HaloInfo)) ; int extent = fieldtype->extent; cnt = 0 ; for (dir=0; dir<3; dir++) { for (lr=0; lr<2; lr++) { HaloInfo *hinfo = &(hc->halo_info[cnt]) ; int nblocks = 1 ; for (k=dir+1;k<3;k++) { nblocks *= period[k] ; } int stride = 1 ; for (k=0;k<dir;k++) { stride *= period[k] ; } int skip = 1 ; for (k=0;k<dir+1 && k<2;k++) { skip *= period[k] ; } if (lr==0) { /* send to left, recv from right */ hinfo->s_offset = extent * stride * 1; hinfo->r_offset = extent * stride * (grid[dir]+1); } else { /* send to right, recv from left */ hinfo->s_offset = extent * stride * grid[dir]; hinfo->r_offset = extent * stride * 0; } hinfo->source_node = node_neighbors[2*dir+1-lr]; hinfo->dest_node = node_neighbors[2*dir+lr]; halo_create_field_vector(nblocks, stride, skip, fieldtype, &hinfo->fieldtype); MPI_Type_vector(nblocks, stride, skip, datatype, &hinfo->datatype); MPI_Type_commit(&hinfo->datatype); #ifdef PARTIAL_PERIODIC if ( !PERIODIC(dir) && (boundary[2*dir+lr] != 0 || boundary[2*dir+1-lr] != 0) ) { if (node_grid[dir] == 1) { hinfo->type = HALO_OPEN; } else if (lr == 0) { if (boundary[2*dir+lr] == 1) { hinfo->type = HALO_RECV; } else { hinfo->type = HALO_SEND; } } else { if (boundary[2*dir+lr] == -1) { hinfo->type = HALO_RECV; } else { hinfo->type = HALO_SEND; } } } else #endif { if (node_grid[dir] == 1) { hc->halo_info[cnt].type = HALO_LOCL; } else { hc->halo_info[cnt].type = HALO_SENDRECV; } } HALO_TRACE(fprintf(stderr,"%d: prepare_halo_communication dir=%d lr=%d s_offset=%ld r_offset=%ld s_node=%d d_node=%d type=%d\n",this_node,dir,lr,hinfo->s_offset,hinfo->r_offset,hinfo->source_node,hinfo->dest_node,hinfo->type)) ; cnt++; } } }
/** Create communicators for cell structure domain decomposition. (see \ref GhostCommunicator) */ void dd_prepare_comm(GhostCommunicator *comm, int data_parts) { int dir,lr,i,cnt, num, n_comm_cells[3]; int lc[3],hc[3],done[3]={0,0,0}; /* calculate number of communications */ num = 0; for(dir=0; dir<3; dir++) { for(lr=0; lr<2; lr++) { #ifdef PARTIAL_PERIODIC /* No communication for border of non periodic direction */ if( PERIODIC(dir) || (boundary[2*dir+lr] == 0) ) #endif { if(node_grid[dir] == 1 ) num++; else num += 2; } } } /* prepare communicator */ CELL_TRACE(fprintf(stderr,"%d Create Communicator: prep_comm data_parts %d num %d\n",this_node,data_parts,num)); prepare_comm(comm, data_parts, num); /* number of cells to communicate in a direction */ n_comm_cells[0] = dd.cell_grid[1] * dd.cell_grid[2]; n_comm_cells[1] = dd.cell_grid[2] * dd.ghost_cell_grid[0]; n_comm_cells[2] = dd.ghost_cell_grid[0] * dd.ghost_cell_grid[1]; cnt=0; /* direction loop: x, y, z */ for(dir=0; dir<3; dir++) { lc[(dir+1)%3] = 1-done[(dir+1)%3]; lc[(dir+2)%3] = 1-done[(dir+2)%3]; hc[(dir+1)%3] = dd.cell_grid[(dir+1)%3]+done[(dir+1)%3]; hc[(dir+2)%3] = dd.cell_grid[(dir+2)%3]+done[(dir+2)%3]; /* lr loop: left right */ /* here we could in principle build in a one sided ghost communication, simply by taking the lr loop only over one value */ for(lr=0; lr<2; lr++) { if(node_grid[dir] == 1) { /* just copy cells on a single node */ #ifdef PARTIAL_PERIODIC if( PERIODIC(dir ) || (boundary[2*dir+lr] == 0) ) #endif { comm->comm[cnt].type = GHOST_LOCL; comm->comm[cnt].node = this_node; /* Buffer has to contain Send and Recv cells -> factor 2 */ comm->comm[cnt].part_lists = malloc(2*n_comm_cells[dir]*sizeof(ParticleList *)); comm->comm[cnt].n_part_lists = 2*n_comm_cells[dir]; /* prepare folding of ghost positions */ if((data_parts & GHOSTTRANS_POSSHFTD) && boundary[2*dir+lr] != 0) comm->comm[cnt].shift[dir] = boundary[2*dir+lr]*box_l[dir]; /* fill send comm cells */ lc[(dir+0)%3] = hc[(dir+0)%3] = 1+lr*(dd.cell_grid[(dir+0)%3]-1); dd_fill_comm_cell_lists(comm->comm[cnt].part_lists,lc,hc); CELL_TRACE(fprintf(stderr,"%d: prep_comm %d copy to grid (%d,%d,%d)-(%d,%d,%d)\n",this_node,cnt, lc[0],lc[1],lc[2],hc[0],hc[1],hc[2])); /* fill recv comm cells */ lc[(dir+0)%3] = hc[(dir+0)%3] = 0+(1-lr)*(dd.cell_grid[(dir+0)%3]+1); /* place recieve cells after send cells */ dd_fill_comm_cell_lists(&comm->comm[cnt].part_lists[n_comm_cells[dir]],lc,hc); CELL_TRACE(fprintf(stderr,"%d: prep_comm %d copy from grid (%d,%d,%d)-(%d,%d,%d)\n",this_node,cnt,lc[0],lc[1],lc[2],hc[0],hc[1],hc[2])); cnt++; } } else { /* i: send/recv loop */ for(i=0; i<2; i++) { #ifdef PARTIAL_PERIODIC if( PERIODIC(dir) || (boundary[2*dir+lr] == 0) ) #endif if((node_pos[dir]+i)%2==0) { comm->comm[cnt].type = GHOST_SEND; comm->comm[cnt].node = node_neighbors[2*dir+lr]; comm->comm[cnt].part_lists = malloc(n_comm_cells[dir]*sizeof(ParticleList *)); comm->comm[cnt].n_part_lists = n_comm_cells[dir]; /* prepare folding of ghost positions */ if((data_parts & GHOSTTRANS_POSSHFTD) && boundary[2*dir+lr] != 0) comm->comm[cnt].shift[dir] = boundary[2*dir+lr]*box_l[dir]; lc[(dir+0)%3] = hc[(dir+0)%3] = 1+lr*(dd.cell_grid[(dir+0)%3]-1); dd_fill_comm_cell_lists(comm->comm[cnt].part_lists,lc,hc); CELL_TRACE(fprintf(stderr,"%d: prep_comm %d send to node %d grid (%d,%d,%d)-(%d,%d,%d)\n",this_node,cnt, comm->comm[cnt].node,lc[0],lc[1],lc[2],hc[0],hc[1],hc[2])); cnt++; } #ifdef PARTIAL_PERIODIC if( PERIODIC(dir) || (boundary[2*dir+(1-lr)] == 0) ) #endif if((node_pos[dir]+(1-i))%2==0) { comm->comm[cnt].type = GHOST_RECV; comm->comm[cnt].node = node_neighbors[2*dir+(1-lr)]; comm->comm[cnt].part_lists = malloc(n_comm_cells[dir]*sizeof(ParticleList *)); comm->comm[cnt].n_part_lists = n_comm_cells[dir]; lc[(dir+0)%3] = hc[(dir+0)%3] = 0+(1-lr)*(dd.cell_grid[(dir+0)%3]+1); dd_fill_comm_cell_lists(comm->comm[cnt].part_lists,lc,hc); CELL_TRACE(fprintf(stderr,"%d: prep_comm %d recv from node %d grid (%d,%d,%d)-(%d,%d,%d)\n",this_node,cnt, comm->comm[cnt].node,lc[0],lc[1],lc[2],hc[0],hc[1],hc[2])); cnt++; } } } done[dir]=1; } } }
double magnetic_dipolar_direct_sum_calculations(int force_flag, int energy_flag) { Cell *cell; Particle *part; int i,c,np; double *x=NULL, *y=NULL, *z=NULL; double *mx=NULL, *my=NULL, *mz=NULL; double *fx=NULL, *fy=NULL, *fz=NULL; #ifdef ROTATION double *tx=NULL, *ty=NULL, *tz=NULL; #endif int dip_particles,dip_particles2; double ppos[3]; int img[3]; double u; if(n_nodes!=1) {fprintf(stderr,"error: magnetic Direct Sum is just for one cpu .... \n"); errexit();} if(!(force_flag) && !(energy_flag) ) {fprintf(stderr," I don't know why you call dawaanr_caclulations with all flags zero \n"); return 0;} x = (double *) malloc(sizeof(double)*n_part); y = (double *) malloc(sizeof(double)*n_part); z = (double *) malloc(sizeof(double)*n_part); mx = (double *) malloc(sizeof(double)*n_part); my = (double *) malloc(sizeof(double)*n_part); mz = (double *) malloc(sizeof(double)*n_part); if(force_flag) { fx = (double *) malloc(sizeof(double)*n_part); fy = (double *) malloc(sizeof(double)*n_part); fz = (double *) malloc(sizeof(double)*n_part); #ifdef ROTATION tx = (double *) malloc(sizeof(double)*n_part); ty = (double *) malloc(sizeof(double)*n_part); tz = (double *) malloc(sizeof(double)*n_part); #endif } dip_particles=0; for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; part = cell->part; np = cell->n; for(i=0;i<np;i++) { if( part[i].p.dipm > 1.e-11 ) { mx[dip_particles]=part[i].r.dip[0]; my[dip_particles]=part[i].r.dip[1]; mz[dip_particles]=part[i].r.dip[2]; /* here we wish the coordinates to be folded into the primary box */ ppos[0]=part[i].r.p[0]; ppos[1]=part[i].r.p[1]; ppos[2]=part[i].r.p[2]; img[0]=part[i].l.i[0]; img[1]=part[i].l.i[1]; img[2]=part[i].l.i[2]; fold_position(ppos, img); x[dip_particles]=ppos[0]; y[dip_particles]=ppos[1]; z[dip_particles]=ppos[2]; if(force_flag) { fx[dip_particles]=0; fy[dip_particles]=0; fz[dip_particles]=0; #ifdef ROTATION tx[dip_particles]=0; ty[dip_particles]=0; tz[dip_particles]=0; #endif } dip_particles++; } } } /*now we do the calculations */ { /* beginning of the area of calculation */ int nx,ny,nz,i,j; double r,rnx,rny,rnz,pe1,pe2,pe3,r3,r5,r2,r7; double a,b,c,d; #ifdef ROTATION double ax,ay,az,bx,by,bz; #endif double rx,ry,rz; double rnx2,rny2; int NCUT[3],NCUT2; for(i=0;i<3;i++){ NCUT[i]=Ncut_off_magnetic_dipolar_direct_sum; if(PERIODIC(i) == 0) {NCUT[i]=0;} } NCUT2=Ncut_off_magnetic_dipolar_direct_sum*Ncut_off_magnetic_dipolar_direct_sum; u=0; fprintf(stderr,"Magnetic Direct sum takes long time. Done of %d: \n",dip_particles); for(i=0;i<dip_particles;i++){ fprintf(stderr,"%d\r",i); for(j=0;j<dip_particles;j++){ pe1=mx[i]*mx[j]+my[i]*my[j]+mz[i]*mz[j]; rx=x[i]-x[j]; ry=y[i]-y[j]; rz=z[i]-z[j]; for(nx=-NCUT[0];nx<=NCUT[0];nx++){ rnx=rx+nx*box_l[0]; rnx2=rnx*rnx; for(ny=-NCUT[1];ny<=NCUT[1];ny++){ rny=ry+ny*box_l[1]; rny2=rny*rny; for(nz=-NCUT[2];nz<=NCUT[2];nz++){ if( !(i==j && nx==0 && ny==0 && nz==0) ) { if(nx*nx+ny*ny +nz*nz<= NCUT2){ rnz=rz+nz*box_l[2]; r2=rnx2+rny2+rnz*rnz; r=sqrt(r2); r3=r2*r; r5=r3*r2; r7=r5*r2; pe2=mx[i]*rnx+my[i]*rny+mz[i]*rnz; pe3=mx[j]*rnx+my[j]*rny+mz[j]*rnz; /*fprintf(stderr,"--------------------------------\n"); fprintf(stderr,"ij: %d %d\n",i,j); fprintf(stderr,"xyz[i]: %lf %lf %lf\n",x[i],y[i],z[i]); fprintf(stderr,"xyz[j]: %lf %lf %lf\n",x[j],y[j],z[j]); fprintf(stderr,"mu xyz[i]: %lf %lf %lf\n",mx[i],my[i],mz[i]); fprintf(stderr,"mu xyz[j]: %lf %lf %lf\n",mx[j],my[j],mz[j]); fprintf(stderr,"rnxyz: %lf %lf %lf\n",rnx,rny,rnz); fprintf(stderr,"--------------------------------\n");*/ //Energy ............................ u+= pe1/r3 - 3.0*pe2*pe3/r5; if(force_flag) { //force ............................ a=mx[i]*mx[j]+my[i]*my[j]+mz[i]*mz[j]; a=3.0*a/r5; b=-15.0*pe2*pe3/r7; c=3.0*pe3/r5; d=3.0*pe2/r5; fx[i]+=(a+b)*rnx+c*mx[i]+d*mx[j]; fy[i]+=(a+b)*rny+c*my[i]+d*my[j]; fz[i]+=(a+b)*rnz+c*mz[i]+d*mz[j]; #ifdef ROTATION //torque ............................ c=3.0/r5*pe3; ax=my[i]*mz[j]-my[j]*mz[i]; ay=mx[j]*mz[i]-mx[i]*mz[j]; az=mx[i]*my[j]-mx[j]*my[i]; bx=my[i]*rnz-rny*mz[i]; by=rnx*mz[i]-mx[i]*rnz; bz=mx[i]*rny-rnx*my[i]; tx[i]+=-ax/r3+bx*c; ty[i]+=-ay/r3+by*c; tz[i]+=-az/r3+bz*c; #endif } /* of force_flag */ } }/* of nx*nx+ny*ny +nz*nz< NCUT*NCUT and !(i==j && nx==0 && ny==0 && nz==0) */ }/* of for nz */ }/* of for ny */ }/* of for nx */ }} /* of j and i */ fprintf(stderr,"done \n"); }/* end of the area of calculation */ /* set the forces, and torques of the particles within Espresso */ if(force_flag) { dip_particles2=0; for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; part = cell->part; np = cell->n; for(i=0;i<np;i++) { if( part[i].p.dipm > 1.e-11 ) { part[i].f.f[0]+=coulomb.Dprefactor*fx[dip_particles2]; part[i].f.f[1]+=coulomb.Dprefactor*fy[dip_particles2]; part[i].f.f[2]+=coulomb.Dprefactor*fz[dip_particles2]; #ifdef ROTATION part[i].f.torque[0]+=coulomb.Dprefactor*tx[dip_particles2]; part[i].f.torque[1]+=coulomb.Dprefactor*ty[dip_particles2]; part[i].f.torque[2]+=coulomb.Dprefactor*tz[dip_particles2]; #endif dip_particles2++; } } } /* small checking */ if(dip_particles != dip_particles2) { fprintf(stderr,"magnetic direct sum calculations: error mismatch of particles \n"); errexit();} } /*of if force_flag */ /* free memory used */ free(x); free(y); free(z); free(mx); free(my); free(mz); if(force_flag) { free(fx); free(fy); free(fz); #ifdef ROTATION free(tx); free(ty); free(tz); #endif } return 0.5*u; }