inline int calc_area_force_local_complicated(Particle *p1, Particle *p2, Particle *p3,
         Bonded_ia_parameters *iaparams, double force1[3], double force2[3], double force3[3]) // more complicated approach
{
 int k; 
 double A, aa, uh[3], vh[3], rh[3], hn;
 double uu[3],vv[3];

 get_mi_vector(uu, p2->r.p, p1->r.p);
 get_mi_vector(vv, p3->r.p, p1->r.p);

 for(k=0;k<3;k++) rh[k]=1.0/3.0 *(uu[k]+vv[k]);
 for(k=0;k<3;k++) uh[k]=rh[k]-uu[k];
 for(k=0;k<3;k++) vh[k]=rh[k]-vv[k];

 A=area_triangle_new(uu,vv);
 //printf("area %e uu %e %e %e vv %e %e %e\n", A, uu[0], uu[1], uu[2], vv[0], vv[1], vv[2]);
 aa=(A - iaparams->p.area_force_local.A0_l)/iaparams->p.area_force_local.A0_l;

 hn=normr(rh);
 for(k=0;k<3;k++) {
  force1[k] =  iaparams->p.area_force_local.ka_l * aa * rh[k]/hn;
 }
 hn=normr(uh);
 for(k=0;k<3;k++) {
  force2[k] =  iaparams->p.area_force_local.ka_l * aa * uh[k]/hn;
 }
 hn=normr(vh);
 for(k=0;k<3;k++) {
  force3[k] =  iaparams->p.area_force_local.ka_l * aa * vh[k]/hn;
 }
  return 0;
}
示例#2
0
/** 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;
}
/** 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;
}
示例#4
0
/** Computes the area of triangle between vectors P1 and P2, 
 *  by computing the crossproduct P1 x P2 and taking the half of its norm */
inline double area_triangle_new(double *P1, double *P2) {
 double area;
 double normal[3], n; //auxiliary variables
 vector_product(P1,P2,normal); 
 n=normr(normal);
 area = 0.5*n;
 return area;
}
示例#5
0
bool IterativeSolvers::pcg(const IRCMatrix &A,
                           Vector &x,
                           const Vector &b,
                           const Preconditioner &M) {
    /*!
      Solves Ax=b using the preconditioned conjugate gradient method.
      */
    const idx N = x.getLength();
    real resid(100.0);
    Vector p(N), z(N), q(N);
    real alpha;
    real normr(0);
    real normb = norm(b);
    real rho(0), rho_1(0), beta(0);
    Vector r = b - A * x;
    if (normb == 0.0)
        normb = 1;
    resid = norm(r) / normb;
    if (resid <= IterativeSolvers::toler) {
        IterativeSolvers::toler = resid;
        IterativeSolvers::maxIter = 0;
        return true;
    }
    // MAIN LOOP
    idx i = 1;
    for (; i <= IterativeSolvers::maxIter; i++) {
        M.solveMxb(z, r);
        rho = dot(r, z);
        if (i == 1)
            p = z;
        else {
            beta = rho / rho_1;
            aypx(beta, p, z); // p = beta*p + z;
        }
        // CALCULATES q = A*p AND dp = dot(q,p)
        real dp = multiply_dot(A, p, q);
        alpha = rho / dp;
        normr = 0;
#ifdef USES_OPENMP
        #pragma omp parallel for reduction(+:normr)
#endif
        for (idx j = 0 ; j < N ; ++j) {
            x[j] += alpha * p[j]; // x + alpha(0) * p;
            r[j] -= alpha * q[j]; // r - alpha(0) * q;
            normr += r[j] * r[j];
        }
        normr = sqrt(normr);
        resid = normr / normb;
        if (resid <= IterativeSolvers::toler) {
            IterativeSolvers::toler = resid;
            IterativeSolvers::maxIter = i;
            return true;
        }
        rho_1 = rho;
    }
    IterativeSolvers::toler = resid;
    return false;
}
示例#6
0
/** Computes the area of triangle between vectors P1,P2,P3, 
 *  by computing the crossproduct P1P2 x P1P3 and taking the half of its norm */
inline double area_triangle(double *P1, double *P2, double *P3) {
	double area;
	double u[3],v[3],normal[3], n; //auxiliary variables
	u[0] = P2[0] - P1[0]; // u = P1P2
	u[1] = P2[1] - P1[1]; 
	u[2] = P2[2] - P1[2]; 
	v[0] = P3[0] - P1[0]; // v = P1P3
	v[1] = P3[1] - P1[1]; 
	v[2] = P3[2] - P1[2]; 
	vector_product(u,v,normal); 
	n=normr(normal);
	area = 0.5*n;
	return area;
}
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;
				}
			}
		}
    }
	
}
示例#9
0
bool steepest_descent_step(void) {
  Cell *cell;
  Particle *p;
  int c, i, j, np;
  
  // Maximal force encountered on node
  double f_max = -std::numeric_limits<double>::max();
  // and globally
  double f_max_global;
  
  // Square of force,torque on particle
  double f,t;
  
  // Positional increments
  double dp, dp2, dp2_max = -std::numeric_limits<double>::max();
    
  // Iteration over all local particles
  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++) {
      f = 0.0;
      t = 0.0;
      dp2 = 0.0;
#ifdef EXTERNAL_FORCES
        // Skip, if coordinate is fixed
        if (!(p[i].p.ext_flag & COORD_FIXED(j)))
#endif
      // For all Cartesian coordinates
      for(j=0; j < 3; j++){
#ifdef VIRTUAL_SITES
      // Skip positional increments of virtual particles
      if (!ifParticleIsVirtual(&p[i])) 
#endif
        {
            // Square of force on particle
	    f += SQR(p[i].f.f[j]);	    	    
	    
	    // Positional increment
	    dp = params->gamma * p[i].f.f[j];
	    if(fabs(dp) > params->max_displacement)
	      // Crop to maximum allowed by user
	      dp = sgn<double>(dp)*params->max_displacement;
	    dp2 += SQR(dp);
            
	    // Move particle
	    p[i].r.p[j] += dp;
	    MINIMIZE_ENERGY_TRACE(printf("part %d dim %d dp %e gamma*f %e\n", i, j, dp, params->gamma * p[i].f.f[j]));
          }
	}
#ifdef ROTATION
	// Rotational increment
	double dq[3]; // Vector parallel to torque

        for (int j=0;j<3;j++){
          dq[j]=0;
          // Square of torque
	  t += SQR(p[i].f.torque[j]);	    	    
	    
	  // Rotational increment
	  dq[j] = params->gamma * p[i].f.torque[j];
	    
      }
      // Normalize rotation axis and compute amount of rotation
      double l=normr(dq);
      if (l>0.0)
      {
        for (j=0;j<3;j++)
          dq[j]/=l;
  
        if(fabs(l) > params->max_displacement)
          // Crop to maximum allowed by user
  	l=sgn(l)*params->max_displacement;
        
        
//        printf("dq: %g %g %g, l=%g\n",dq[0],dq[1],dq[2],l);
        // Rotate the particle around axis dq by amount l
        rotate_particle(&(p[i]),dq,l);
      }
#endif

      // Note maximum force/torque encountered
      f_max = std::max(f_max, f);
      f_max = std::max(f_max, t);
      dp2_max = std::max(dp2_max, dp2);
      resort_particles = 1;
    }
  }
  MINIMIZE_ENERGY_TRACE(printf("f_max %e resort_particles %d\n", f_max, resort_particles));
  announce_resort_particles();
  
  // Synchronize maximum force/torque encountered
  MPI_Allreduce(&f_max, &f_max_global, 1, MPI_DOUBLE, MPI_MAX, comm_cart);
  
  // Return true, if the maximum force/torque encountered is below the user limit.
  return (sqrt(f_max_global) < params->f_max);
}
示例#10
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];
	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);
}
示例#11
0
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;
				}
			}
		}
    }
	
}