/** Computes the local area force (Dupin2007 eqn. 15) and adds this force to the particle forces (see \ref tclcommand_inter). @param p1,p2,p3 Pointers to triangle particles. @param iaparams elastic area modulus ka, initial area A0 (see \ref tclcommand_inter). @param force1 returns force of particle 1 @param force2 returns force of particle 2 @param force3 returns force of particle 3 @return 0 */ inline int calc_area_force_local(Particle *p1, Particle *p2, Particle *p3, Bonded_ia_parameters *iaparams, double force1[3], double force2[3], double force3[3]) //first-fold-then-the-same approach { int k; double A, aa, h[3], rh[3], hn; double p11[3],p22[3],p33[3]; int img[3]; 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); for(k=0;k<3;k++) h[k]=1.0/3.0 *(p11[k]+p22[k]+p33[k]); //volume+=A * -n[2]/dn * h[2]; A=area_triangle(p11,p22,p33); aa=(A - iaparams->p.area_force_local.A0_l)/iaparams->p.area_force_local.A0_l; //aminusb(3,h,p11,rh); // area_forces for each triangle node vecsub(h,p11,rh); // area_forces for each triangle node hn=normr(rh); for(k=0;k<3;k++) { force1[k] = iaparams->p.area_force_local.ka_l * aa * rh[k]/hn; //(&part1)->f.f[k]+=force[k]; } //aminusb(3,h,p22,rh); // area_forces for each triangle node vecsub(h,p22,rh); // area_forces for each triangle node hn=normr(rh); for(k=0;k<3;k++) { force2[k] = iaparams->p.area_force_local.ka_l * aa * rh[k]/hn; //(&part2)->f.f[k]+=force[k]; } //aminusb(3,h,p33,rh); // area_forces for each triangle node vecsub(h,p33,rh); // area_forces for each triangle node hn=normr(rh); for(k=0;k<3;k++) { force3[k] = iaparams->p.area_force_local.ka_l * aa * rh[k]/hn; //(&part3)->f.f[k]+=force[k]; } 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; } } } } }