/** Computes the bending force (Dupin2007 eqn. 20 and 21) and adds this force to the particle forces (see \ref tclcommand_inter). @param p1,p2,p3 Pointers to particles of triangle 1. @param p2,p3,p4 Pointers to particles of triangle 2. (triangles have particles p2 and p3 in common) @param iaparams bending stiffness kb, initial rest angle phi0 (see \ref tclcommand_inter). @param force1 returns force on particles of triangle 1 @param force2 returns force on particles of triangle 2 (p1 += force1; p2 += 0.5*force1+0.5*force2; p3 += 0.5*force1+0.5*force2; p4 += force2; @return 0 */ inline int calc_bending_force(Particle *p2, Particle *p1, Particle *p3, Particle *p4, Bonded_ia_parameters *iaparams, double force1[3], double force2[2])// first-fold-then-the-same approach { double n1[3],n2[3],dn1,dn2,phi,aa,fac,penal; int k; double fp1[3],fp2[3],fp3[3],fp4[3]; #ifdef LEES_EDWARDS double vv[3]; #endif int img[3]; memcpy(fp1, p1->r.p, 3*sizeof(double)); memcpy(img, p1->l.i, 3*sizeof(int)); fold_position(fp1, img); memcpy(fp2, p2->r.p, 3*sizeof(double)); memcpy(img, p2->l.i, 3*sizeof(int)); fold_position(fp2, img); memcpy(fp3, p3->r.p, 3*sizeof(double)); memcpy(img, p3->l.i, 3*sizeof(int)); fold_position(fp3, img); memcpy(fp4, p4->r.p, 3*sizeof(double)); memcpy(img, p4->l.i, 3*sizeof(int)); fold_position(fp4, img); get_n_triangle(fp2,fp1,fp3,n1); dn1=normr(n1); get_n_triangle(fp2,fp3,fp4,n2); dn2=normr(n2); phi = angle_btw_triangles(fp1,fp2,fp3,fp4); if (iaparams->p.bending_force.phi0 < 0.001 || iaparams->p.bending_force.phi0 > 2*M_PI - 0.001) printf("bending_force.h, calc_bending_force: Resting angle is close to zero!!!\n"); aa = (phi-iaparams->p.bending_force.phi0)/iaparams->p.bending_force.phi0; fac = iaparams->p.bending_force.kb * aa; penal = (1+1/pow(10*(2*M_PI-phi),2) + 1/pow(10*(phi),2)); if (penal > 5.) penal = 5.; // fac = fac*penal; // This is to penalize the angles smaller than some threshold tr and also it penalizes angles greater than 2*Pi - tr. It prevents the objects to have negative angles. if (phi < 0.001 || phi > 2*M_PI - 0.001) printf("bending_force.h, calc_bending_force: Angle approaches 0 or 2*Pi\n"); for(k=0;k<3;k++) { force1[k]=fac * n1[k]/dn1; force2[k]=fac * n2[k]/dn2; } return 0; }
inline void calc_volume(double *volume, int molType){ //first-fold-then-the-same approach double partVol=0.,A,norm[3],dn,hz; /** loop over particles */ int c, np, i ,j; Cell *cell; Particle *p, *p1, *p2, *p3; double p11[3],p22[3],p33[3]; int img[3]; Bonded_ia_parameters *iaparams; int type_num, n_partners, id; BondedInteraction type; char *errtxt; //int test=0; //printf("rank%d, molType2: %d\n", rank,molType); /* Loop local cells */ for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; /* Loop cell particles */ for(i=0; i < np; i++) { j = 0; p1 = &p[i]; //printf("rank%d, i=%d neigh=%d\n", rank, i, p1->bl.n); while(j<p1->bl.n){ /* bond type */ type_num = p1->bl.e[j++]; //bond_number iaparams = &bonded_ia_params[type_num]; type = iaparams->type; //type of interaction 14...volume_force n_partners = iaparams->num; //bonded_neigbours id=p1->p.mol_id; //mol_id of blood cell if(type == BONDED_IA_VOLUME_FORCE && id == molType){ // BONDED_IA_VOLUME_FORCE with correct molType !!!!!!!!!!!!! needs area force local !!!!!!!!!!!!!!!!!! p2 = local_particles[p1->bl.e[j++]]; if (!p2) { printf("broken: particles sum %d, id %d, partn %d, bond %d\n", np,id,n_partners,type_num); errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"{volume calc 078 bond broken between particles %d and %d (particles not stored on the same node - volume_force1)} ", p1->p.identity, p1->bl.e[j-1]); return; } /* fetch particle 3 */ p3 = local_particles[p1->bl.e[j++]]; if (!p3) { errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"{volume calc 079 bond broken between particles %d, %d and %d (particles not stored on the same node); n %d max %d} ", p1->p.identity, p1->bl.e[j-2], p1->bl.e[j-1],p1->bl.n,p1->bl.max); return; } memcpy(p11, p1->r.p, 3*sizeof(double)); memcpy(img, p1->l.i, 3*sizeof(int)); fold_position(p11, img); memcpy(p22, p2->r.p, 3*sizeof(double)); memcpy(img, p2->l.i, 3*sizeof(int)); fold_position(p22, img); memcpy(p33, p3->r.p, 3*sizeof(double)); memcpy(img, p3->l.i, 3*sizeof(int)); fold_position(p33, img); get_n_triangle(p11,p22,p33,norm); dn=normr(norm); A=area_triangle(p11,p22,p33); hz=1.0/3.0 *(p11[2]+p22[2]+p33[2]); partVol += A * -1*norm[2]/dn * hz; } else{ j+=n_partners; } } } } MPI_Allreduce(&partVol, volume, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); }
inline void add_volume_force(double volume, int molType){ //first-fold-then-the-same approach double A,norm[3],dn; //partVol=0. double vv, force[3]; int k; int img[3]; /** loop over particles */ int c, np, i ,j; Cell *cell; Particle *p, *p1, *p2, *p3; double p11[3],p22[3],p33[3]; Bonded_ia_parameters *iaparams; int type_num, n_partners, id; BondedInteraction type; char *errtxt; int test=0; /* Loop local cells */ for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; /* Loop cell particles */ for(i=0; i < np; i++) { j = 0; p1=&p[i]; //printf("i=%d neigh=%d\n", i, p1->bl.n); while(j<p1->bl.n){ /* bond type */ type_num = p1->bl.e[j++]; iaparams = &bonded_ia_params[type_num]; type = iaparams->type; n_partners = iaparams->num; id=p1->p.mol_id; if(type == BONDED_IA_VOLUME_FORCE && id == molType){ // BONDED_IA_VOLUME_FORCE with correct molType test++; /* fetch particle 2 */ p2 = local_particles[p1->bl.e[j++]]; if (!p2) { errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"{volume add 078 bond broken between particles %d and %d (particles not stored on the same node - volume_force2)} ", p1->p.identity, p1->bl.e[j-1]); return; } /* fetch particle 3 */ p3 = local_particles[p1->bl.e[j++]]; if (!p3) { errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"{volume add 079 bond broken between particles %d, %d and %d (particles not stored on the same node); n %d max %d} ", p1->p.identity, p1->bl.e[j-2], p1->bl.e[j-1],p1->bl.n,p1->bl.max); return; } memcpy(p11, p1->r.p, 3*sizeof(double)); memcpy(img, p1->l.i, 3*sizeof(int)); fold_position(p11, img); memcpy(p22, p2->r.p, 3*sizeof(double)); memcpy(img, p2->l.i, 3*sizeof(int)); fold_position(p22, img); memcpy(p33, p3->r.p, 3*sizeof(double)); memcpy(img, p3->l.i, 3*sizeof(int)); fold_position(p33, img); get_n_triangle(p11,p22,p33,norm); dn=normr(norm); A=area_triangle(p11,p22,p33); { } vv=(volume - iaparams->p.volume_force.V0)/iaparams->p.volume_force.V0; for(k=0;k<3;k++) { force[k]=iaparams->p.volume_force.kv * vv * A * norm[k]/dn * 1.0 / 3.0; //printf("%e ",force[k]); p1->f.f[k] += force[k]; p2->f.f[k] += force[k]; p3->f.f[k] += force[k]; } } else{ j+=n_partners; } } } } }
inline void calc_volume(double *volume, int molType){ //first-fold-then-the-same approach double partVol=0.,A,norm[3],dn,hz; /** loop over particles */ int c, np, i ,j; Cell *cell; Particle *p, *p1, *p2, *p3; double p11[3],p22[3],p33[3]; int img[3]; double AA[3],BB[3]; Bonded_ia_parameters *iaparams; int type_num, n_partners, id; BondedInteraction type; //int test=0; //printf("rank%d, molType2: %d\n", rank,molType); /* Loop local cells */ for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; /* Loop cell particles */ for(i=0; i < np; i++) { j = 0; p1 = &p[i]; //printf("rank%d, i=%d neigh=%d\n", rank, i, p1->bl.n); while(j<p1->bl.n){ /* bond type */ type_num = p1->bl.e[j++]; //bond_number iaparams = &bonded_ia_params[type_num]; type = iaparams->type; //type of interaction 14...volume_force n_partners = iaparams->num; //bonded_neigbours id=p1->p.mol_id; //mol_id of blood cell if(type == BONDED_IA_VOLUME_FORCE && id == molType){ // BONDED_IA_VOLUME_FORCE with correct molType !!!!!!!!!!!!! needs area force local !!!!!!!!!!!!!!!!!! p2 = local_particles[p1->bl.e[j++]]; if (!p2) { printf("broken: particles sum %d, id %d, partn %d, bond %d\n", np,id,n_partners,type_num); ostringstream msg; msg <<"volume calc: bond broken between particles " << p1->p.identity << " and " << p1->bl.e[j-1] << " (particles not stored on the same node - volume_force1)"; runtimeError(msg); return; } /* fetch particle 3 */ p3 = local_particles[p1->bl.e[j++]]; if (!p3) { ostringstream msg; msg <<"volume calc: bond broken between particles " << p1->p.identity << ", " << p1->bl.e[j-2] << " and " << p1->bl.e[j-1] << " (particles not stored on the same node); n " << p1->bl.n << " max " << p1->bl.max; runtimeError(msg); return; } // particles fetched #ifdef GHOST_FLAG // first find out which particle out of p1, p2 (possibly p3, p4) is not a ghost particle. In almost all cases it is p1, however, it might be other one. we call this particle reference particle. if (p1->l.ghost != 1) { //unfold non-ghost particle using image, because for physical particles, the structure p->l.i is correctly set memmove(p11, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(p11,img); // other coordinates are obtained from its relative positions to the reference particle get_mi_vector(AA, p2->r.p, p11); get_mi_vector(BB, p3->r.p, p11); for (int i=0; i < 3; i++) { p22[i] = p11[i] + AA[i]; p33[i] = p11[i] + BB[i]; } } else { // in case the first particle is a ghost particle if (p2->l.ghost != 1) { memmove(p22, p2->r.p, 3*sizeof(double)); memmove(img, p2->l.i, 3*sizeof(int)); unfold_position(p22,img); get_mi_vector(AA, p1->r.p, p22); get_mi_vector(BB, p3->r.p, p22); for (int i=0; i < 3; i++) { p11[i] = p22[i] + AA[i]; p33[i] = p22[i] + BB[i]; } } else { // in case the first and the second particle are ghost particles if (p3->l.ghost != 1) { memmove(p33, p3->r.p, 3*sizeof(double)); memmove(img, p3->l.i, 3*sizeof(int)); unfold_position(p33,img); get_mi_vector(AA, p1->r.p, p33); get_mi_vector(BB, p2->r.p, p33); for (int i=0; i < 3; i++) { p11[i] = p33[i] + AA[i]; p22[i] = p33[i] + BB[i]; } } else { printf("Something wrong in area_force_local.hpp: All particles in a bond are ghost particles, impossible to unfold the positions..."); return; } } } #endif #ifndef GHOST_FLAG // if ghost flag was not defined we have no other option than to assume the first particle is a physical one. memmove(p11, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(p11,img); // other coordinates are obtained from its relative positions to the reference particle get_mi_vector(AA, p2->r.p, p11); get_mi_vector(BB, p3->r.p, p11); for (int i=0; i < 3; i++) { p22[i] = p11[i] + AA[i]; p33[i] = p11[i] + BB[i]; } #endif get_n_triangle(p11,p22,p33,norm); dn=normr(norm); A=area_triangle(p11,p22,p33); hz=1.0/3.0 *(p11[2]+p22[2]+p33[2]); partVol += A * -1*norm[2]/dn * hz; } else{ j+=n_partners; } } } } MPI_Allreduce(&partVol, volume, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); }
inline void add_volume_force(double volume, int molType){ //first-fold-then-the-same approach double A,norm[3],dn; //partVol=0. double vv, force[3]; int k; int img[3]; /** loop over particles */ int c, np, i ,j; Cell *cell; Particle *p, *p1, *p2, *p3; double p11[3],p22[3],p33[3]; Bonded_ia_parameters *iaparams; int type_num, n_partners, id; BondedInteraction type; double AA[3],BB[3]; int test=0; /* Loop local cells */ for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; /* Loop cell particles */ for(i=0; i < np; i++) { j = 0; p1=&p[i]; //printf("i=%d neigh=%d\n", i, p1->bl.n); while(j<p1->bl.n){ /* bond type */ type_num = p1->bl.e[j++]; iaparams = &bonded_ia_params[type_num]; type = iaparams->type; n_partners = iaparams->num; id=p1->p.mol_id; if(type == BONDED_IA_VOLUME_FORCE && id == molType){ // BONDED_IA_VOLUME_FORCE with correct molType test++; /* fetch particle 2 */ p2 = local_particles[p1->bl.e[j++]]; if (!p2) { ostringstream msg; msg <<"volume add: bond broken between particles " << p1->p.identity << " and " << p1->bl.e[j-1] << " (particles not stored on the same node - volume_force2)"; runtimeError(msg); return; } /* fetch particle 3 */ p3 = local_particles[p1->bl.e[j++]]; if (!p3) { ostringstream msg; msg <<"volume calc: bond broken between particles " << p1->p.identity << ", " << p1->bl.e[j-2] << " and " << p1->bl.e[j-1] << " (particles not stored on the same node); n " << p1->bl.n << " max " << p1->bl.max; runtimeError(msg); return; } // particles fetched #ifdef GHOST_FLAG // first find out which particle out of p1, p2 (possibly p3, p4) is not a ghost particle. In almost all cases it is p1, however, it might be other one. we call this particle reference particle. if (p1->l.ghost != 1) { //unfold non-ghost particle using image, because for physical particles, the structure p->l.i is correctly set memmove(p11, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(p11,img); // other coordinates are obtained from its relative positions to the reference particle get_mi_vector(AA, p2->r.p, p11); get_mi_vector(BB, p3->r.p, p11); for (int i=0; i < 3; i++) { p22[i] = p11[i] + AA[i]; p33[i] = p11[i] + BB[i]; } } else { // in case the first particle is a ghost particle if (p2->l.ghost != 1) { memmove(p22, p2->r.p, 3*sizeof(double)); memmove(img, p2->l.i, 3*sizeof(int)); unfold_position(p22,img); get_mi_vector(AA, p1->r.p, p22); get_mi_vector(BB, p3->r.p, p22); for (int i=0; i < 3; i++) { p11[i] = p22[i] + AA[i]; p33[i] = p22[i] + BB[i]; } } else { // in case the first and the second particle are ghost particles if (p3->l.ghost != 1) { memmove(p33, p3->r.p, 3*sizeof(double)); memmove(img, p3->l.i, 3*sizeof(int)); unfold_position(p33,img); get_mi_vector(AA, p1->r.p, p33); get_mi_vector(BB, p2->r.p, p33); for (int i=0; i < 3; i++) { p11[i] = p33[i] + AA[i]; p22[i] = p33[i] + BB[i]; } } else { printf("Something wrong in area_force_local.hpp: All particles in a bond are ghost particles, impossible to unfold the positions..."); return; } } } #endif #ifndef GHOST_FLAG // if ghost flag was not defined we have no other option than to assume the first particle is a physical one. memmove(p11, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(p11,img); // other coordinates are obtained from its relative positions to the reference particle get_mi_vector(AA, p2->r.p, p11); get_mi_vector(BB, p3->r.p, p11); for (int i=0; i < 3; i++) { p22[i] = p11[i] + AA[i]; p33[i] = p11[i] + BB[i]; } #endif get_n_triangle(p11,p22,p33,norm); dn=normr(norm); A=area_triangle(p11,p22,p33); { } vv=(volume - iaparams->p.volume_force.V0)/iaparams->p.volume_force.V0; for(k=0;k<3;k++) { force[k]=iaparams->p.volume_force.kv * vv * A * norm[k]/dn * 1.0 / 3.0; //printf("%e ",force[k]); p1->f.f[k] += force[k]; p2->f.f[k] += force[k]; p3->f.f[k] += force[k]; } } else{ j+=n_partners; } } } } }