Exemple #1
0
/** This function returns the angle btw the triangle p1,p2,p3 and p2,p3,p4. 
 *  Be careful, the angle depends on the orientation of the trianlges! 
 *  You need to be sure that the orientation (direction of normal vector) 
 *  of p1p2p3 is given by the cross product p2p1 x p2p3. 
 *  The orientation of p2p3p4 must be given by p2p3 x p2p4. 
 * 
 *  Example: p1 = (0,0,1), p2 = (0,0,0), p3=(1,0,0), p4=(0,1,0). 
 *  The orientation of p1p2p3 should be in the direction (0,1,0) 
 *  and indeed: p2p1 x p2p3 = (0,0,1)x(1,0,0) = (0,1,0)
 *  This function is called in the beginning of the simulation when creating 
 *  bonds depending on the angle btw the triangles, the bending_force.
 *  Here, we determine the orientations by looping over the triangles 
 *  and checking the correct orientation. So when defining the bonds by tcl command
 *  "part p2 bond xxxx p1 p3 p4", we correctly input the particle id's.
 *  So if you have the access to the order of particles, you are safe to call this
 *  function with exactly this order. Otherwise you need to check the orientations. */
inline double angle_btw_triangles(double *P1, double *P2, double *P3, double *P4) {
	double phi;
	double u[3],v[3],normal1[3],normal2[3]; //auxiliary variables
	u[0] = P1[0] - P2[0]; // u = P2P1
	u[1] = P1[1] - P2[1]; 
	u[2] = P1[2] - P2[2]; 
	v[0] = P3[0] - P2[0]; // v = P2P3
	v[1] = P3[1] - P2[1]; 
	v[2] = P3[2] - P2[2]; 
	vector_product(u,v,normal1); 
	u[0] = P3[0] - P2[0]; // u = P2P3
	u[1] = P3[1] - P2[1]; 
	u[2] = P3[2] - P2[2]; 
	v[0] = P4[0] - P2[0]; // v = P2P4
	v[1] = P4[1] - P2[1]; 
	v[2] = P4[2] - P2[2]; 
	vector_product(u,v,normal2); 

	double tmp11,tmp22,tmp33;
	// Now we compute the scalar product of n1 and n2 divided by the norms of n1 and n2
	//tmp11 = dot(3,normal1,normal2);         // tmp11 = n1.n2
	tmp11 = scalar(normal1,normal2);         // tmp11 = n1.n2
	
	/*	
	tmp22 = normr(normal1);
	tmp33 = normr(normal2);
	tmp11 /= (tmp22*tmp33);  // tmp11 = n1.n2/(|n1||n2|)
*/
	tmp11 *= fabs(tmp11); // tmp11 = (n1.n2)^2
	tmp22 = sqrlen(normal1);  //tmp22 = |n1|^2
	tmp33 = sqrlen(normal2);  //tmp33 = |n1|^2
	tmp11 /= (tmp22*tmp33);  // tmp11 = (n1.n2/(|n1||n2|))^2
	if (tmp11 > 0 ) {
		tmp11 = sqrt(tmp11);
	} else {
		tmp11 = - sqrt(- tmp11);
	}		

	if(tmp11>=1.) { tmp11=0.0;}
	else if(tmp11<=-1.) { tmp11=M_PI;}
	phi = M_PI - acos(tmp11); 	// The angle between the faces (not considering the orientation, always less or equal to Pi) is
								// equal to Pi minus angle between the normals
	
	// Now we need to determine, if the angle btw two triangles is less than Pi or more than Pi. To do this we check, 
	// if the point P4 lies in the halfspace given by trianlge P1P2P3 and the normal to this triangle. If yes, we have 
	// angle less than Pi, if not, we have angle more than Pi.
	// General equation of the plane is n_x*x + n_y*y + n_z*z + d = 0 where (n_x,n_y,n_z) is the normal to the plane.
	// Point P1 lies in the plane, therefore d = -(n_x*P1_x + n_y*P1_y + n_z*P1_z)
	// Point P4 lies in the halfspace given by normal iff n_x*P4_x + n_y*P4_y + n_z*P4_z + d >= 0
	tmp11 = - (normal1[0]*P1[0] + normal1[1]*P1[1] + normal1[2]*P1[2]);
	if (normal1[0]*P4[0] + normal1[1]*P4[1] + normal1[2]*P4[2] + tmp11 < 0) phi = 2*M_PI - phi;
	return phi;
}
Bool find_three_point_transform(float P1[3], float P2[3], float P3[3], 
		     float Q1[3], float Q2[3], float Q3[3],
		     float mv[3], float R[3][3])
      /*  assumption: for each Pi!=Pj and Qi!=Qj */
{
  float u[3][3], w[3][3];
  int i,j,k;

  vector_sub(P2,P1, u[0]);
  vector_sub(P3,P1, u[1]);
  vector_product(u[0], u[1], u[1]);  /*  u[1] = (P2-P1)x(P3-P1) */
  vector_normalize(u[0]);
  vector_normalize(u[1]);
  vector_product(u[0], u[1], u[2]);  /*  u[2] |_ u[1] |_ u[2] */

  if(vector_length(u[2])==0) 
    {
      printf("three points transformation: the first three points are colinear !!!\n");
      return False;
    }

  vector_sub(Q2,Q1, w[0]);
  vector_sub(Q3,Q1, w[1]);
  vector_product(w[0], w[1], w[1]);  /*  w[1] = (Q2-Q1)x(Q3-Q1) */
  vector_normalize(w[0]);
  vector_normalize(w[1]);
  vector_product(w[0], w[1], w[2]);  /*  w[2] |_ w[1] |_ w[2] */
  if(vector_length(w[2])==0) 
    {
      printf("three points transformation: the last three points are colinear !!!\n");
      return False;
    }


  for(i=0; i<3; i++)
    for(j=0; j<3; j++)
      {
	R[i][j]=0;
	for(k=0; k<3; k++)
	  R[i][j]+=u[k][j]*w[k][i];
      }

  matrix3_vector_mult(R, P1, mv);
  vector_sub(Q1, mv, mv);  /*  mv = Q1 - R*P1 */
  return True;

}
Exemple #3
0
/* Hypothesis:

  - either nmat is a matrix allocated with _matrix_alloc_int,
    and his coefficients are not initialized,

  - or nmat==mat
*/
static
matrix_t* matrix_assign_variable(pk_internal_t* pk,
				 bool destructive,
				 matrix_t* mat,
				 ap_dim_t dim, numint_t* tab)
{
  size_t i,j,var;
  bool den;
  matrix_t* nmat;

  var = pk->dec + dim;
  den = numint_cmp_int(tab[0],1)>0;

  nmat =
    destructive ?
    mat :
    _matrix_alloc_int(mat->nbrows,mat->nbcolumns,false);

  nmat->_sorted = false;

  for (i=0; i<mat->nbrows; i++){
    /* product for var column */
    vector_product(pk,pk->matrix_prod,
		   mat->p[i],
		   tab,mat->nbcolumns);
    /* columns != var */
    if (!destructive){
      /* Functional */
      numint_init_set(nmat->p[i][0],mat->p[i][0]);
      for (j=1; j<mat->nbcolumns; j++){
	if (j!=var){
	  numint_init_set(nmat->p[i][j],mat->p[i][j]);
	  if (den){
	    numint_mul(nmat->p[i][j],mat->p[i][j],tab[0]);
	  }
	}
      }
    }
    else {
      /* Side-effect */
      for (j=0; j<mat->nbcolumns; j++){
	if (j!=var){
	  if (den)
	    numint_mul(nmat->p[i][j],mat->p[i][j],tab[0]);
	  else
	    numint_set(nmat->p[i][j],mat->p[i][j]);
	}
      }
    }
    /* var column */
    if (!destructive)
      numint_init_set(nmat->p[i][var],pk->matrix_prod);
    else
      numint_set(nmat->p[i][var],pk->matrix_prod);

    matrix_normalize_row(pk,nmat,i);
  }
  return nmat;
}
Exemple #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;
}
Exemple #5
0
int main() {
	vector v1 = { 2, 4, 6 };
	vector v2 = { 3, 5, 9 };
	vector v;
	v = vector_product(v1, v2);
	printf("v1 * v2 = %.2f\n", scalar_product(v1, v2));
	printf("v1 x v2 = [%.2f, %.2f, %.2f]\n", v.x, v.y, v.z);
	return 0;
}
Exemple #6
0
bool do_segments_intersect(const point *A1, const point *A2,
                           const point *B1, const point *B2){
    long double v_x = A2->x - A1->x,
           v_y = A2->y - A1->y,
           b_x = B1->x - A1->x,
           b_y = B1->y - A1->y;

    if(vectors_on_two_sides(vector_product(v_x, v_y, B2->x - A1->x, B2->y - A1->y), vector_product(v_x, v_y, b_x, b_y))){
        b_x = -b_x;
        b_y = -b_y;
        v_x = B2->x - B1->x;
        v_y = B2->y - B1->y;
        if(vectors_on_two_sides(vector_product(v_x, v_y, b_x, b_y), vector_product(v_x, v_y, A2->x - B1->x, A2->y - B1->y))){
            return true;
        }else{
            return false;
        }
    }else{
        return false;
    }
}
Exemple #7
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;
}
t_bool			intersect_triangle(t_ray ray, t_triangle *obj, float *out)
{
	t_tri	tri;

	tri.e1 = vector_substract(obj->pos2, obj->pos);
	tri.e2 = vector_substract(obj->pos3, obj->pos);
	tri.p = vector_product(ray.dir, tri.e2);
	tri.det = vector_dotproduct(tri.e1, tri.p);
	if (tri.det > -1e-4f && tri.det < 1e-4f)
		return (FALSE);
	tri.det = 1.f / tri.det;
	tri.t = vector_substract(ray.pos, obj->pos);
	tri.u = vector_dotproduct(tri.t, tri.p) * tri.det;
	if (tri.u < 0. || tri.u > 1.)
		return (FALSE);
	tri.q = vector_product(tri.t, tri.e1);
	tri.v = vector_dotproduct(ray.dir, tri.q) * tri.det;
	if (tri.v < 0. || (tri.u + tri.v) > 1.)
		return (FALSE);
	*out = vector_dotproduct(tri.e2, tri.q) * tri.det;
	if (*out > 1e-4f)
		return (TRUE);
	return (FALSE);
}
Exemple #9
0
/** Calculates the dihedral angle between particle quadruple p1, p2,
p3 and p4. The dihedral angle is the angle between the planes
specified by the particle triples (p1,p2,p3) and (p2,p3,p4). 
Vectors a, b and c are the bond vectors between consequtive particles.
If the a,b or b,c are parallel the dihedral angle is not defined in which
case the routine returns phi=-1. Calling functions should check for that
(Written by: Arijit Maitra) */
inline void calc_dihedral_angle(Particle *p1, Particle *p2, Particle *p3, Particle *p4, 
				  double a[3], double b[3], double c[3], 
				  double aXb[3], double *l_aXb, double bXc[3], double *l_bXc, 
				  double *cosphi, double *phi)
{
  int i;

  get_mi_vector(a, p2->r.p, p1->r.p);
  get_mi_vector(b, p3->r.p, p2->r.p);
  get_mi_vector(c, p4->r.p, p3->r.p);

  /* calculate vector product a X b and b X c */
  vector_product(a, b, aXb);
  vector_product(b, c, bXc);

  /* calculate the unit vectors */
  *l_aXb = sqrt(sqrlen(aXb));
  *l_bXc = sqrt(sqrlen(bXc));

  /* catch case of undefined dihedral angle */
   if ( *l_aXb <= TINY_LENGTH_VALUE || *l_bXc <= TINY_LENGTH_VALUE ) { *phi = -1.0; *cosphi = 0; return;}

  for (i=0;i<3;i++) {
    aXb[i] /= *l_aXb;
    bXc[i] /= *l_bXc;
  }

  *cosphi = scalar(aXb, bXc);

  if ( fabs(fabs(*cosphi)-1)  < TINY_SIN_VALUE  ) *cosphi = dround(*cosphi);

  /* Calculate dihedral angle */
  *phi = acos(*cosphi);
  if( scalar(aXb, c) < 0.0 ) *phi = (2.0*PI) - *phi;

}
// Distribute forces that have accumulated on virtual particles to the 
// associated real particles
void distribute_mol_force()
{
  // Iterate over all the particles in the local cells
  Particle *p;
  int i, np, c;
  Cell *cell;
  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++) {
      // We only care about virtual particles
      if (ifParticleIsVirtual(&p[i])) {
       update_mol_pos_particle(&p[i]);

       // First obtain the real particle responsible for this virtual particle:
       Particle *p_real = vs_relative_get_real_particle(&p[i]);

       // Get distance vector pointing from real to virtual particle, respecting periodic boundary i
       // conditions
       double d[3];
       get_mi_vector(d,p[i].r.p,p_real->r.p);

       // The rules for transfering forces are:
       // F_realParticle +=F_virtualParticle
       // T_realParticle +=f_realParticle \times (r_virtualParticle-r_realParticle)
       
       // Calculate torque to be added on real particle
       double tmp[3];
       vector_product(d,p[i].f.f,tmp);

       // Add forces and torques
       int j;
//       printf("Particle %d gets torque from %f %f %f of particle %d\n",p_real->p.identity, p[i].f.f[0], p[i].f.f[1],p[i].f.f[2], p[i].p.identity);
       for (j=0;j<3;j++) {
         p_real->f.torque[j]+=tmp[j];
//	 printf("%f ",tmp[j]);
	 p_real->f.f[j]+=p[i].f.f[j];
	 // Clear forces on virtual particle
	 p[i].f.f[j]=0;

       }
      }
    }
  }
}
// Update the vel of the given virtual particle as defined by the real 
// particles in the same molecule
void update_mol_vel_particle(Particle *p)
{
 // NOT TESTED!
 
 // First obtain the real particle responsible for this virtual particle:
 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

 // Get omega of real particle in space-fixed frame
 double omega_space_frame[3];
 convert_omega_body_to_space(p_real,omega_space_frame);
 // Obtain velocity from v=v_real particle + omega_real_particle \times director
 vector_product(omega_space_frame,director,p->m.v);

 int i;
 // Add prefactors and add velocity of real particle
 for (i=0;i<3;i++)
 {
  // Scale the velocity by the distance of virtual particle from the real particle
  // Also, espresso stores not velocity but velocity * time_step
  p->m.v[i] *= time_step * p->p.vs_relative_distance/l;
  // Add velocity of real particle
  p->m.v[i] += p_real->m.v[i];
 }
}
Exemple #12
0
void
set_rotate_axis(double *axis)
{

  void normalize_vec(double *);
  void vector_product(double *, double *, double *);

  int i;

  /* Set up local axis frame */

  /* rotate_axis_n is parallel to rotate_axis */

  for(i = 0; i < 3; i++)
    {
      rotate_axis_n[i] = axis[i];
    }

  normalize_vec(rotate_axis_n);

  /* rotate_axis_l is perpendicular to rotate_axis_n and lies in the
     001 plane */

  if(fabs(rotate_axis_n[2]) == 1.0)
    {
      rotate_axis_l[0] = 1.0;               /* Arbitrary */
      rotate_axis_l[1] = 0.0;
      rotate_axis_l[2] = 0.0;
    }
  else
    {
      rotate_axis_l[0] =  rotate_axis_n[1];
      rotate_axis_l[1] = -rotate_axis_n[0];
      rotate_axis_l[2] =  0.0;
    }

  normalize_vec(rotate_axis_l);

  /* m is perpendicular to l and n */

  vector_product(rotate_axis_m, rotate_axis_n, rotate_axis_l);


}
void angularmomentum(int type, double *com)
{
  int i, j;
  double tmp[3];
  double pre_factor;
  com[0]=com[1]=com[2]=0.;

  updatePartCfg(WITHOUT_BONDS);
  for (j=0; j<n_part; j++) 
  {
    if (type == partCfg[j].p.type) 
    {
      vector_product(partCfg[j].r.p,partCfg[j].m.v,tmp);
      pre_factor=PMASS(partCfg[j]);
      for (i=0; i<3; i++) {
        com[i] += tmp[i]*pre_factor;
      }
    }
  }
  return;
}
Exemple #14
0
// plot the horizon in green
static void draw_horizon(struct FTR *f)
{
	struct viewer_state *e = f->userdata;

	// four control points in projective coordinates
	double a[3] = {e->c[0][0], e->c[0][1], 1};
	double b[3] = {e->c[1][0], e->c[1][1], 1};
	double c[3] = {e->c[2][0], e->c[2][1], 1};
	double d[3] = {e->c[3][0], e->c[3][1], 1};

	// lines though the control points
	double lab[3]; vector_product(lab, a, b);
	double lcd[3]; vector_product(lcd, c, d);
	double lad[3]; vector_product(lad, a, d);
	double lbc[3]; vector_product(lbc, b, c);

	// intersections of opposite sides (vanishing points)
	double p[3]; vector_product(p, lab, lcd);
	double q[3]; vector_product(q, lad, lbc);

	// horizon := line through two vanishing points
	double horizon[3]; vector_product(horizon, p, q);

	// affine coordinates of points
	for (int k = 0; k < 2; k++) {
		p[k] /= p[2];
		q[k] /= q[2];
	}
	p[2] = q[2] = 1;

	// plot the horizon
	double v[2][2];
	map_view_to_window(e, v[0], p);
	map_view_to_window(e, v[1], q);
	if (hypot(hypot(v[0][0], v[0][1]), hypot(v[1][0], v[1][1])) < 1e5)
		plot_segment_green(f, v[0][0], v[0][1], v[1][0], v[1][1]);

}
Exemple #15
0
real StressMajorizationSmoother_smooth(StressMajorizationSmoother sm, int dim, real *x, int maxit_sm, real tol) {
  SparseMatrix Lw = sm->Lw, Lwd = sm->Lwd, Lwdd = NULL;
  int i, j, m, *id, *jd, *iw, *jw, idiag, flag = 0, iter = 0;
  real *w, *dd, *d, *y = NULL, *x0 = NULL, *x00 = NULL, diag, diff = 1, *lambda = sm->lambda, maxit, res, alpha = 0., M = 0.;
  SparseMatrix Lc = NULL;

  Lwdd = SparseMatrix_copy(Lwd);
  m = Lw->m;
  x0 = N_GNEW(dim*m,real);
  if (!x0) goto RETURN;

  x0 = MEMCPY(x0, x, sizeof(real)*dim*m);
  y = N_GNEW(dim*m,real);
  if (!y) goto RETURN;

  id = Lwd->ia; jd = Lwd->ja;
  d = (real*) Lwd->a;
  dd = (real*) Lwdd->a;
  w = (real*) Lw->a;
  iw = Lw->ia; jw = Lw->ja;

  /* for the additional matrix L due to the position constraints */
  if (sm->scheme == SM_SCHEME_NORMAL_ELABEL){
    get_edge_label_matrix(sm->data, m, dim, x, &Lc, &x00);
    if (Lc) Lw = SparseMatrix_add(Lw, Lc);
  } else if (sm->scheme == SM_SCHEME_UNIFORM_STRESS){
    alpha = ((real*) (sm->data))[0];
    M = ((real*) (sm->data))[1];
  }

  while (iter++ < maxit_sm && diff > tol){

    for (i = 0; i < m; i++){
      idiag = -1;
      diag = 0.;
      for (j = id[i]; j < id[i+1]; j++){
	if (i == jd[j]) {
	  idiag = j;
	  continue;
	}
	dd[j] = d[j]/distance_cropped(x, dim, i, jd[j]);
	diag += dd[j];
      }
      assert(idiag >= 0);
      dd[idiag] = -diag;
    }

    /* solve (Lw+lambda*I) x = Lwdd y + lambda x0 */

    SparseMatrix_multiply_dense(Lwdd, FALSE, x, FALSE, &y, FALSE, dim);
 
    if (lambda){/* is there a penalty term? */
      for (i = 0; i < m; i++){
	for (j = 0; j < dim; j++){
	  y[i*dim+j] += lambda[i]*x0[i*dim+j];
	}
      }
    }

    if (sm->scheme == SM_SCHEME_NORMAL_ELABEL){
      for (i = 0; i < m; i++){
	for (j = 0; j < dim; j++){
	  y[i*dim+j] += x00[i*dim+j];
	}
      }
    } else if (sm->scheme == SM_SCHEME_UNIFORM_STRESS){/* this part can be done more efficiently using octree approximation */
      uniform_stress_augment_rhs(m, dim, x, y, alpha, M);
    }

#ifdef DEBUG_PRINT
    if (Verbose) fprintf(stderr, "stress1 = %f\n",get_stress(m, dim, iw, jw, w, d, x, sm->scaling, sm->data, 0));
#endif

    maxit = sqrt((double) m);
    if (sm->scheme == SM_SCHEME_UNIFORM_STRESS){
      res = uniform_stress_solve(Lw, alpha, dim, x, y, 0.01, maxit, &flag);
    } else {
      res = SparseMatrix_solve(Lw, dim, x, y, 0.01, maxit, SOLVE_METHOD_CG, &flag);
    }
    if (flag) goto RETURN;
#ifdef DEBUG_PRINT
    if (Verbose) fprintf(stderr, "stress2 = %f\n",get_stress(m, dim, iw, jw, w, d, y, sm->scaling, sm->data, 0));
#endif

    diff = total_distance(m, dim, x, y)/sqrt(vector_product(m*dim, x, x));
#ifdef DEBUG_PRINT
    if (Verbose){
      fprintf(stderr, "Outer iter = %d, res = %g Stress Majorization diff = %g\n",iter, res, diff);
    }
#endif
    MEMCPY(x, y, sizeof(real)*m*dim);
  }

#ifdef DEBUG
  _statistics[1] += iter-1;
#endif

 RETURN:
  SparseMatrix_delete(Lwdd);
  if (Lc) {
    SparseMatrix_delete(Lc);
    SparseMatrix_delete(Lw);
  }

  if (x0) FREE(x0);
  if (y) FREE(y);
  if (x00) FREE(x00);
  return diff;
  
}
void CalcVolumeForce()
{
  // Loop over all particles on local node
  for (int c = 0; c < local_cells.n; c++)
  {
    const Cell *const cell = local_cells.cell[c];
    
    for (int i = 0; i < cell->n; i++)
    {
      Particle &p1 = cell->part[i];
      
      // Check if particle has a BONDED_IA_IBM_TRIEL and a BONDED_IA_IBM_VOLUME_CONSERVATION
      // Basically this loops over all triangles, not all particles
      // First round to check for volume conservation and virtual
      // Loop over all bonds of this particle
      // Actually j loops over the bond-list, i.e. the bond partners (see particle_data.hpp)
      int softID = -1;
      double volRef, kappaV;
      int j = 0;
      while ( j < p1.bl.n )
      {
        const int type_num = p1.bl.e[j];
        const Bonded_ia_parameters &iaparams = bonded_ia_params[type_num];
        const int type = iaparams.type;
        if ( type == BONDED_IA_IBM_VOLUME_CONSERVATION )
        {
          if ( !p1.p.isVirtual) { printf("Error. Encountered non-virtual particle with VOLUME_CONSERVATION_IBM\n"); exit(1); }
          softID = iaparams.p.ibmVolConsParameters.softID;
          volRef = iaparams.p.ibmVolConsParameters.volRef;
          kappaV = iaparams.p.ibmVolConsParameters.kappaV;
        }
        // Iterate, increase by the number of partners of this bond + 1 for bond type
        j += iaparams.num+1;
      }
      
      
      // Second round for triel
      if ( softID > -1 )
      {
        j = 0;
        while ( j < p1.bl.n)
        {
          const int type_num = p1.bl.e[j];
          const Bonded_ia_parameters &iaparams = bonded_ia_params[type_num];
          const int type = iaparams.type;
          
          if ( type == BONDED_IA_IBM_TRIEL )
          {
            // Our particle is the leading particle of a triel
            // Get second and third particle of the triangle
            Particle *p2 = local_particles[p1.bl.e[j+1]];
            Particle *p3 = local_particles[p1.bl.e[j+2]];
            
            // Unfold position of first node
            // this is to get a continuous trajectory with no jumps when box boundaries are crossed
            double x1[3] = { p1.r.p[0], p1.r.p[1], p1.r.p[2] };
            int img[3] = { p1.l.i[0], p1.l.i[1], p1.l.i[2] };
            unfold_position(x1,img);
            
            // Unfolding seems to work only for the first particle of a triel
            // so get the others from relative vectors considering PBC
            double a12[3];
            get_mi_vector(a12, p2->r.p, x1);
            double a13[3];
            get_mi_vector(a13, p3->r.p, x1);
            

            
            // Now we have the true and good coordinates
            // Compute force according to eq. C.46 Krüger thesis
            // It is the same as deriving Achim's equation w.r.t x
            /*                        const double fact = kappaV * 1/6. * (IBMVolumesCurrent[softID] - volRef) / IBMVolumesCurrent[softID];
             
             double x2[3];
            double x3[3];
            
            for (int i=0; i < 3; i++)
            {
              x2[i] = x1[i] + a12[i];
              x3[i] = x1[i] + a13[i];
            }
             
             double n[3];
             vector_product(x3, x2, n);
             for (int k=0; k < 3; k++) p1.f.f[k] += fact*n[k];
             vector_product(x1, x3, n);
             for (int k=0; k < 3; k++) p2->f.f[k] += fact*n[k];
             vector_product(x2, x1, n);
             for (int k=0; k < 3; k++) p3->f.f[k] += fact*n[k];*/
            
            
            // This is Dupin 2008. I guess the result will be very similar as the code above
            double n[3];
            vector_product(a12, a13, n);
            const double ln = sqrt( n[0]*n[0] + n[1]*n[1] + n[2]*n[2] );
            const double A = 0.5 * ln;
            const double fact = kappaV * (VolumesCurrent[softID] - volRef) / VolumesCurrent[softID];
            double nHat[3];
            nHat[0] = n[0] / ln;
            nHat[1] = n[1] / ln;
            nHat[2] = n[2] / ln;
            
            double force[3];
            force[0] = -fact * A * nHat[0];
            force[1] = -fact * A * nHat[1];
            force[2] = -fact * A * nHat[2];
            
            // Add forces
            for (int k=0; k < 3; k++)
            {
              p1.f.f[k] += force[k];
              p2->f.f[k] += force[k];
              p3->f.f[k] += force[k];
            }
            
          }
          // Iterate, increase by the number of partners of this bond + 1 for bond type
          j += iaparams.num+1;
        }
      }
    }
  }
}
Exemple #17
0
static real conjugate_gradient(Operator A, Operator precon, int n, real *x, real *rhs, real tol, int maxit, int *flag){
  real *z, *r, *p, *q, res = 10*tol, alpha;
  real rho = 1.0e20, rho_old = 1, res0, beta;
  real* (*Ax)(Operator o, real *in, real *out) = A->Operator_apply;
  real* (*Minvx)(Operator o, real *in, real *out) = precon->Operator_apply;
  int iter = 0;

  z = N_GNEW(n,real);
  r = N_GNEW(n,real);
  p = N_GNEW(n,real);
  q = N_GNEW(n,real);

  r = Ax(A, x, r);
  r = vector_subtract_to(n, rhs, r);

  res0 = res = sqrt(vector_product(n, r, r))/n;
#ifdef DEBUG_PRINT
    if (Verbose && 0){
      fprintf(stderr, "   cg iter = %d, residual = %g\n", iter, res);
    }
#endif

  while ((iter++) < maxit && res > tol*res0){
    z = Minvx(precon, r, z);
    rho = vector_product(n, r, z);

    if (iter > 1){
      beta = rho/rho_old;
      p = vector_saxpy(n, z, p, beta);
    } else {
      MEMCPY(p, z, sizeof(real)*n);
    }

    q = Ax(A, p, q);

    alpha = rho/vector_product(n, p, q);

    x = vector_saxpy2(n, x, p, alpha);
    r = vector_saxpy2(n, r, q, -alpha);
    
    res = sqrt(vector_product(n, r, r))/n;

#ifdef DEBUG_PRINT
    if (Verbose && 0){
      fprintf(stderr, "   cg iter = %d, residual = %g\n", iter, res);
    }
#endif



    rho_old = rho;
  }
  FREE(z); FREE(r); FREE(p); FREE(q);
#ifdef DEBUG
    _statistics[0] += iter - 1;
#endif

#ifdef DEBUG_PRINT
  if (Verbose && 0){
    fprintf(stderr, "   cg iter = %d, residual = %g\n", iter, res);
  }
#endif
  return res;
}
Exemple #18
0
/* #include "matrix_market.h" */
void power_method(SparseMatrix A, int random_seed, int maxit, real tol, real **eigv){
  /* find the largest eigenvector of a matrix A. Result in eigv. if eigv == NULL; memory will be allocated.
     maxium of maxit iterations will be done, and tol is the convergence criterion

     This converges only if the largest eigenvector/value is real and the next largest eigenvalue separate from teh largest one

   */
  int n;
  real *v, *u;
  int iter = 0;
  real res, unorm;
  int i;
  assert(A->m == A->n);
  assert(A->type = MATRIX_TYPE_REAL || A->type == MATRIX_TYPE_INTEGER);

  n = A->m;
  if (!(*eigv)) *eigv = MALLOC(sizeof(real)*n);
  u = MALLOC(sizeof(real)*n);

  srand(random_seed);

  for (i = 0; i < n; i++) (*eigv)[i] = drand();

  res = vector_product(n, *eigv, *eigv);
  if (res > 0) res =  1/res;
  for (i = 0; i < n; i++) (*eigv)[i] = (*eigv)[i]*res;
  
  v = *eigv;
  
  do {
    SparseMatrix_multiply_vector(A, v, &u, FALSE);

    unorm = vector_product(n, u, u);/* ||u||^2 */
    unorm = sqrt(unorm);
    if (unorm > 0) unorm = 1/unorm;
    res = 0.;
    for (i = 0; i < n; i++) {
      u[i] = u[i]*unorm;
      res = res + (u[i] - v[i])*(u[i] - v[i]);
      v[i] = u[i];
    }
   
    /* 
    printf("=== %d === %f\n",iter,res);
    printf("{");
    {int j;
      for (j = 0; j < MIN(10,n); j++){
      if (j == n-1){
	printf("%f",v[j]);
      } else {
	printf("%f,",v[j]);
      }
    }
    printf("\n");
    }
    */

  } while (res/n > tol*tol && iter++ < maxit);
  
  
}
Exemple #19
0
EXPORT int intersection_of_two_shock_polars(
	Locstate	         st0,
	Locstate	         st1,
	float		         *abs_v,
	float		         *p,
	float		         *pmin,
	float		         *pmax,
	bool		         Cplus_w0,
	bool		         Cplus_w1,
	RIEMANN_SOLVER_WAVE_TYPE *wtype0,
	RIEMANN_SOLVER_WAVE_TYPE *wtype1)
{
	float		v0[MAXD];	/* Velocities in the steady frame */
	float		v1[MAXD];
	float		M0sq, M1sq;	/* Mach #'s squared in steady frame */
	float		theta01;	/* turn angle vector v0 to v1 */
	float		v0_x_v1;
	float		v0_d_v1;
	float		p0, p1;
	float		p_upper, p_lower;
	const float     meps = 10.0*MACH_EPS;/*TOLERANCE*/
	float		eps_theta;
	float		eps_pressure;
#if !defined(UNRESTRICTED_THERMODYNAMICS)
	float		min_pressure;
#endif /* !defined(UNRESTRICTED_THERMODYNAMICS) */
	int		dim;
	DT_ANG_PARAMS	parameters;
	static char	yesstatus[] =
		"Left intersection_of_two_shock_polars() status = YES\n";
	static	char	nostatus[]  =
		"Left intersection_of_two_shock_polars() status = NO\n";
	
	debug_print("shock_polar","Entered intersection_of_two_shock_polars()\n");

	dim = Params(st0)->dim;
	p0 = pressure(st0);
	p1 = pressure(st1);
	M0sq = mach_number_squared(st0,abs_v,v0);
	M1sq = mach_number_squared(st1,abs_v,v1);

	(void) vector_product(v0,v1,&v0_x_v1,dim);
	v0_d_v1 = scalar_product(v0,v1,dim);
	theta01 = atan2(v0_x_v1,v0_d_v1);
#if defined(DEBUG_GIPOLAR)
	if (debugging("shock_polar")) 
	{
		(void) printf("abs_v = (%g, %g)\n",abs_v[0],abs_v[1]);
		(void) printf("Cplus_w0 = %s, Cplus_w1 = %s\n",
			      (Cplus_w0) ? "YES" : "NO",
			      (Cplus_w1) ? "YES" : "NO");
		verbose_print_state("st0",st0);
		(void) printf("v0 = (%g, %g), q0 = %g, M0 = %g\n",v0[0],v0[1],
			      mag_vector(v0,dim),sqrt(M0sq));
		verbose_print_state("st1",st1);
		(void) printf("v1 = (%g, %g), q1 = %g, M1 = %g\n\n",v1[0],v1[1],
			      mag_vector(v1,dim),sqrt(M1sq));
		print_angle("theta01 =",theta01,"\n");
	}
#endif /* defined(DEBUG_GIPOLAR) */

	*wtype0 = *wtype1 = UNSET_RIEMANN_SOLVER_WAVE_TYPE;
	if (!spolar_intersect_bounds(theta01,M0sq,M1sq,st0,
					st1,pmin,pmax,&p_upper,&p_lower,
					Cplus_w0,Cplus_w1,wtype0,wtype1))
	{
	    if (debugging("shock_polar"))
	    {
		(void) printf("WARNING in intersection_of_two_shock_polars(), "
		              "spolar_intersect_bounds() failed.\n");
		debug_print("shock_polar",nostatus);
	    }
	    return NO;
	}
#if !defined(UNRESTRICTED_THERMODYNAMICS)
	min_pressure = max(Min_pressure(st0),Min_pressure(st1));
	if (p_upper < min_pressure)
	{
	    *p = min_pressure;
	    *wtype0 = *wtype1 = RAREFACTION;
	    debug_print("shock_polar",yesstatus);
	    return YES;
	}
#endif /* !defined(UNRESTRICTED_THERMODYNAMICS) */
	if (p_upper <= p0)	*wtype0 = RAREFACTION;
	if (p_lower >= p0)	*wtype0 = SHOCK;
	if (p_upper <= p1)	*wtype1 = RAREFACTION;
	if (p_lower >= p1)	*wtype1 = SHOCK;
	eps_theta = fabs(theta01)*EPS;
	eps_theta = max(meps,eps_theta);
	eps_pressure = max(p0,p1)*EPS;
	eps_pressure = max(meps,eps_pressure);
	set_parameters(parameters,Cplus_w0,Cplus_w1,st0,st1,M0sq,M1sq);
	if (find_root(diff_turn_ang,(POINTER)&parameters,theta01,p,p_lower,
		      p_upper,eps_theta,eps_pressure) == FUNCTION_FAILED)
	{
	    if (debugging("shock_polar"))
	    {
		(void) printf("WARNING in intersection_of_two_shock_polars()");
		(void) printf(", No intersection of shock polars.\n");
	    }
	    debug_print("shock_polar",nostatus);
	    return NO;
	}
	*wtype0 = (*p >= p0) ? SHOCK : RAREFACTION;
	*wtype1 = (*p >= p1) ? SHOCK : RAREFACTION;
	debug_print("shock_polar",yesstatus);
	return YES;
}		/*end intersection_of_two_shock_polars*/
Exemple #20
0
/* ---------------------------------------------------------------------- */
static
matrix_t* matrix_assign_variables(pk_internal_t* pk,
				  matrix_t* mat,
				  ap_dim_t* tdim,
				  numint_t** tvec,
				  size_t size)
{
  size_t i,j,eindex;
  matrix_t* nmat = _matrix_alloc_int(mat->nbrows, mat->nbcolumns,false);
  numint_t den;

  /* Computing common denominator */
  numint_init_set(den,tvec[0][0]);
  for (i=1; i<size; i++){
    numint_mul(den,den,tvec[i][0]);
  }

  if (numint_cmp_int(den,1)!=0){
    /* General case */
    numint_t* vden = vector_alloc(size);
    for (i=0; i<size; i++){
      numint_divexact(vden[i],den,tvec[i][0]);
    }
    /* Column 0: copy */
    for (i=0; i<mat->nbrows; i++){
      numint_init_set(nmat->p[i][0],mat->p[i][0]);
    }
    /* Other columns */
    eindex = 0;
    for (j=1; j<mat->nbcolumns; j++){
      if (eindex < size && pk->dec + tdim[eindex] == j){
	/* We are on an assigned column */
	for (i=0; i<mat->nbrows; i++){ /* For each row */
	  vector_product(pk,pk->matrix_prod,
			 mat->p[i],
			 tvec[eindex],mat->nbcolumns);
	  numint_mul(pk->matrix_prod,pk->matrix_prod,vden[eindex]);
	  /* Put the result */
	  numint_init_set(nmat->p[i][j],pk->matrix_prod);
	}
	eindex++;
      }
      else {
	/* We are on a normal column */
	for (i=0; i<mat->nbrows; i++){ /* For each row */
	  numint_init(nmat->p[i][j]);
	  numint_mul(nmat->p[i][j],mat->p[i][j],den);
	}
      }
    }
    vector_free(vden,size);
  }
  else {
    /* Special case: all denominators are 1 */
    /* Column 0: copy */
    for (i=0; i<mat->nbrows; i++){
      numint_init_set(nmat->p[i][0],mat->p[i][0]);
    }
    /* Other columns */
    eindex = 0;
    for (j=1; j<mat->nbcolumns; j++){
      if (eindex < size && pk->dec + tdim[eindex] == j){
	/* We are on a assigned column */
	for (i=0; i<mat->nbrows; i++){ /* For each row */
	  vector_product(pk,pk->matrix_prod,
			 mat->p[i],
			 tvec[eindex],mat->nbcolumns);
	  numint_init_set(nmat->p[i][j],pk->matrix_prod);
	}
	eindex++;
      }
      else {
	/* We are on a normal column */
	for (i=0; i<mat->nbrows; i++){ /* For each row */
	  numint_init_set(nmat->p[i][j],mat->p[i][j]);
	}
      }
    }
  }
  numint_clear(den);
  for (i=0; i<mat->nbrows; i++){
    matrix_normalize_row(pk,nmat,i);
  }

  return nmat;
}
Exemple #21
0
int main(void)
{
	//	Engine initialization
	TinyRender::EngineManager engine;
	engine.set_viewport(0, 0, width, height);
	engine.set_depth(width);
	//	TODO: (alxe) simplify api!!
	TinyRender::Vec3f light_vec;
	light_vec[0] = 0.0; light_vec[1] = 0.0; light_vec[2] = -1.0;
	engine.set_light_direction(light_vec);
	//	Shader creation
	std::unique_ptr<TinyRender::Shader> shader = std::make_unique<TinyRender::DummyShader>(engine);

	std::vector<std::vector<int>> z_buffer(height, std::vector<int>(width, std::numeric_limits<int>::min()));
	TinyRender::TGAImage tga_image(width, height, TinyRender::TGAImage::ImageFormat_RGB);
	TinyRender::Model model("../../Models/AfricanHead.obj");
	TinyRender::TGAImage text_map("../../Models/AfricanHeadDiffuse.tga");
	std::ofstream out_tga_file("../../Temp/TGATEST.tga", std::ios::binary);
	
	//	Buffer of screen points
	std::array<TinyRender::Vec3i, 3> screen_points;

	for (size_t tr_id = 0; tr_id < model.triangles().size(); ++tr_id)
	{

		const TinyRender::Vec3f& p1 = model.vertices()[model.triangles()[tr_id].vertices[0]];
		const TinyRender::Vec3f& uv1 = model.uv_vertices()[model.triangles()[tr_id].uv_vertices[0]];
		const TinyRender::Vec3f& p2 = model.vertices()[model.triangles()[tr_id].vertices[1]];
		const TinyRender::Vec3f& uv2 = model.uv_vertices()[model.triangles()[tr_id].uv_vertices[1]];
		const TinyRender::Vec3f& p3 = model.vertices()[model.triangles()[tr_id].vertices[2]];
		const TinyRender::Vec3f& uv3 = model.uv_vertices()[model.triangles()[tr_id].uv_vertices[2]];

		const TinyRender::Vec3i& p1i = engine.transform(p1);
		const TinyRender::Vec3i& p2i = engine.transform(p2);
		const TinyRender::Vec3i& p3i = engine.transform(p3);

		const float u1x  = uv1[0] * text_map.width();
		const float u1y =  uv1[1] * text_map.height();


		const float u2x = uv2[0] * text_map.width();
		const float u2y = uv2[1] * text_map.height();

		const float u3x = uv3[0] * text_map.width();
		const float u3y = uv3[1] * text_map.height();

		TinyRender::Vec3f norm_vec = vector_product((p3 - p1), (p2 - p1));
		norm_vec.normalize();
		const float intense = light_vec * norm_vec;
		if (intense > 0)
		{
			TinyRender::render_triangle(p1i[0], p1i[1], p1i[2], u1x, u1y, 
										p2i[0], p2i[1], p2i[2], u2x, u2y,
										p3i[0], p3i[1], p3i[2], u3x, u3y,
										tga_image, text_map, z_buffer, intense);
		}
	}
	tga_image << out_tga_file;
	out_tga_file.close();
	return 0;
}
void IBM_Tribend_CalcForce(Particle *p1, const int numPartners, Particle **const partners, const Bonded_ia_parameters &iaparams)
{

  const tBendingMethod method = iaparams.p.ibm_tribend.method;
  if ( method == NodeNeighbors ) CalcForceGompper(p1, numPartners, partners, iaparams.p.ibm_tribend.kb);
  if ( method == TriangleNormals )
  {
    // move to separate function
    if ( numPartners != 3 ) { printf("Error. TriangleNormals bending with != 3 partners!\n"); exit(1); }
    Particle *p2 = partners[0];
    Particle *p3 = partners[1];
    Particle *p4 = partners[2];
    
    // ************* This is Wolfgang's code **************
    // with some corrections by Achim
    
    //Get vectors making up the two 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 n1[3], n2[3];
    vector_product(dx1, dx2, n1);
    vector_product(dx1, dx3, n2);
    
    // Wolfgang here had a minus. It seems to work, so leave it in
    n2[0]=-1*n2[0];
    n2[1]=-1*n2[1];
    n2[2]=-1*n2[2];
    
    
    // Get 2*area of triangles out of the magnitude of the resulting normals and make the latter unity
    const double Ai = sqrt(n1[0]*n1[0] + n1[1]*n1[1] + n1[2]*n1[2]);
    n1[0] = n1[0]/Ai;
    n1[1]=n1[1]/Ai;
    n1[2]=n1[2]/Ai;
    
    const double Aj = sqrt(n2[0]*n2[0] + n2[1]*n2[1] + n2[2]*n2[2]);
    n2[0] = n2[0]/Aj;
    n2[1]=n2[1]/Aj;
    n2[2]=n2[2]/Aj;
    
    
    //Get the prefactor for the force term
    double sc = scalar(n1,n2);
    if ( sc > 1.0) sc = 1.0;
    
    //Get theta as angle between normals
    double theta = acos(sc);
    
    double direc[3];
    vector_product(n1,n2,direc);
    const double desc = scalar(dx1,direc);
    
    if (desc < 0) theta = -1.0*theta;
    const double DTh = theta - iaparams.p.ibm_tribend.theta0;
   
    double Pre;
    // Classical Wolfgang version
/*    if ( theta > 0) Pre = 1.0*iaparams.p.ibm_tribend.kb * sin(DTh);
      else Pre = -1.0*iaparams.p.ibm_tribend.kb * sin(DTh);*/
    // Correct version with linearized sin
    if ( theta > 0) Pre = 1.0*iaparams.p.ibm_tribend.kb * DTh;
    else Pre = -1.0*iaparams.p.ibm_tribend.kb * DTh;
    
    double v1l[3], v2l[3];
    for (int i = 0; i < 3; i++)
    {
      v1l[i] = n2[i]-sc*n1[i];
      v2l[i] = n1[i]-sc*n2[i];
    }
    
    double len = sqrt(sqrlen(v1l));
    double v1[3], v2[3];
    if (len>0) for ( int i = 0;i <3; i++)  v1[i]=v1l[i]/len;
    
    // Achim normalizes both with the length of v1, Wolfgang uses v1 and v2
    // However, the length should be identical, so it does not matter
//    if ( method == Krueger )
//      len = sqrt(sqrlen(v2l));
    
    if ( len > 0) for (int i = 0;i <3; i++)  v2[i]=v2l[i]/len;
    
    
    // Force for particle 1:
    double tmp[3], tmp2[3], term1[3], term2[3];
    get_mi_vector(tmp,p2->r.p,p3->r.p);
    get_mi_vector(tmp2, p3->r.p, p4->r.p);
    vector_product(tmp,v1, term1);
    vector_product(tmp2,v2, term2);
    for (int i = 0; i < 3; i++ )
      p1->f.f[i] += Pre*(term1[i]/Ai + term2[i]/Aj);
    
     // Force for particle 2:
    get_mi_vector(tmp,p3->r.p,p1->r.p);
    vector_product(tmp,v1, term1);
    for (int i = 0; i < 3; i++)
      p2->f.f[i] += Pre*(term1[i]/Ai);
    
    // Force for Particle 3:
    get_mi_vector(tmp,p1->r.p,p2->r.p);
    get_mi_vector(tmp2, p4->r.p, p1->r.p);
    vector_product(tmp,v1, term1);
    vector_product(tmp2,v2, term2);
    for (int i = 0; i < 3; i++)
      p3->f.f[i] += Pre*(term1[i]/Ai + term2[i]/Aj);
    
    // Force for Particle 4:
    get_mi_vector(tmp,p1->r.p,p3->r.p);
    vector_product(tmp,v2, term1);
    for (int i = 0; i < 3; i++) p4->f.f[i] += Pre*(term1[i]/Aj);
  }
}
Exemple #23
0
void power_method(void (*matvec)(void *, int, int, real*, real **, int, int*),
		  void *A, int n, int K, int random_seed, int maxit, real tol, real **eigv, real **eigs){
  /* find k-largest eigenvectors of a matrix A. Result in eigv. if eigv == NULL; memory will be allocated.
     maxium of maxit iterations will be done, and tol is the convergence criterion

     This converges only if the largest eigenvectors/values are real (e.g., if A is symmetric) and the 
     next largest eigenvalues separate from the largest ones

     input:
     matvec: a function point that takes a matrix M and a vector u, produce v = M.u
     A: the matrix
     n: dimension of matrix A
     K: number of eigenes to find
     random_seed: seed for eigenvector initialization
     matrix: max number f iterations
     tol: accuracy control

     output:
     eigv: eigenvectors. The i-th is at eigvs[i*n, i*(n+1) - 1]
     eigs: eigenvalues.  The i-th is at eigs[i]


     Function PowerIteration (A – m × m matrix )
     % This function computes u1, u2, . . . , uk, the first k eigenvectors of S.
     const tol ← 0.001
     for i = 1 to k do
     . ui ← random
     . ui ← ui/||ui||
     . do
     .   vi ← ui
     .   % orthogonalize against previous eigenvectors
     .   for j = 1 to i − 1 do
     .     vi ← vi − (vi^Tvi)vj
     .   end for
     .   ui ← A vi/||A vi||
     . while (ui^T vi < 1-tol) (halt when direction change is small)
     . vi = ui
     end for
     return v1,v2,...
   */
  real **v, *u, *vv;
  int iter = 0;
  real res, unorm;
  int i, j, k;
  real uij;
  int flag;

  K = MAX(0, MIN(n, K));
  assert(K <= n && K > 0);

  if (!(*eigv)) *eigv = MALLOC(sizeof(real)*n*K);
  if (!(*eigs)) *eigs = MALLOC(sizeof(real)*K);
  v = MALLOC(sizeof(real*)*K);

  vv = MALLOC(sizeof(real)*n);
  u = MALLOC(sizeof(real)*n);

  srand(random_seed);

  for (k = 0; k < K; k++){
    //fprintf(stderr,"calculating eig k ==================== %d\n",k);
    v[k] = &((*eigv)[k*n]);
    for (i = 0; i < n; i++) u[i] = drand();
    res = sqrt(vector_product(n, u, u));
    if (res > 0) res =  1/res;
    for (i = 0; i < n; i++) {
      u[i] = u[i]*res;
      v[k][i] = u[i];
    }
    /*
    fprintf(stderr,"inital vec=");
    for (i = 0; i < n; i++) fprintf(stderr,"%f,",u[i]);fprintf(stderr,"\n");
    */
    iter = 0;
    do {


      /* normalize against previous eigens */
      for (j = 0; j < k; j++){
	uij = vector_product(n, u, v[j]);
	for (i = 0; i < n; i++) {
	  u[i] = u[i] - uij *v[j][i];
	}
      }
      matvec(A, n, n, u, &vv, FALSE, &flag);
      assert(!flag);

      /*
      fprintf(stderr,"normalized aginst prev vec=");
      for (i = 0; i < n; i++) fprintf(stderr,"%f,",u[i]);fprintf(stderr,"\n");
      */

      unorm = vector_product(n, vv, vv);/* ||u||^2 */    
      unorm = sqrt(unorm);
      (*eigs)[k] = unorm;
      if (unorm > 0) {
	unorm = 1/unorm;
      } else {
	// ||A.v||=0, so v must be an eigenvec correspond to eigenvalue zero
	for (i = 0; i < n; i++) vv[i] = u[i];
	unorm = sqrt(vector_product(n, vv, vv));
	if (unorm > 0) unorm = 1/unorm;
      }
      res = 0.;

      for (i = 0; i < n; i++) {
	//res = MAX(res, ABS(vv[i]-(*eigs)[k]*u[i]));
	u[i] = vv[i]*unorm;
	res = res + u[i]*v[k][i];
	v[k][i] = u[i];
      }
      //fprintf(stderr,"res=%g, tol = %g, res < 1-tol=%d\n",res, tol,res < 1 - tol);
    } while (res < 1 - tol && iter++ < maxit);
    //} while (iter++ < maxit);
    //fprintf(stderr,"iter= %d, res=%f\n",iter, res);
  }
  FREE(u);
  FREE(vv);  
}
real StressMajorizationSmoother_smooth(StressMajorizationSmoother sm, int dim, real *x, int maxit_sm, real tol) {
  SparseMatrix Lw = sm->Lw, Lwd = sm->Lwd, Lwdd = NULL;
  int i, j, k, m, *id, *jd, *iw, *jw, idiag, flag = 0, iter = 0;
  real *w, *dd, *d, *y = NULL, *x0 = NULL, *x00 = NULL, diag, diff = 1, *lambda = sm->lambda, res, alpha = 0., M = 0.;
  SparseMatrix Lc = NULL;
  real dij, dist;


  Lwdd = SparseMatrix_copy(Lwd);
  m = Lw->m;
  x0 = N_GNEW(dim*m,real);
  if (!x0) goto RETURN;

  x0 = MEMCPY(x0, x, sizeof(real)*dim*m);
  y = N_GNEW(dim*m,real);
  if (!y) goto RETURN;

  id = Lwd->ia; jd = Lwd->ja;
  d = (real*) Lwd->a;
  dd = (real*) Lwdd->a;
  w = (real*) Lw->a;
  iw = Lw->ia; jw = Lw->ja;

#ifdef DEBUG_PRINT
  if (Verbose) fprintf(stderr, "initial stress = %f\n", get_stress(m, dim, iw, jw, w, d, x, sm->scaling, sm->data, 1));
#endif
  /* for the additional matrix L due to the position constraints */
  if (sm->scheme == SM_SCHEME_NORMAL_ELABEL){
    get_edge_label_matrix(sm->data, m, dim, x, &Lc, &x00);
    if (Lc) Lw = SparseMatrix_add(Lw, Lc);
  } else if (sm->scheme == SM_SCHEME_UNIFORM_STRESS){
    alpha = ((real*) (sm->data))[0];
    M = ((real*) (sm->data))[1];
  }

  while (iter++ < maxit_sm && diff > tol){
#ifdef GVIEWER
    if (Gviewer) {
      drawScene();
      if (iter%2 == 0) gviewer_dump_current_frame();
    }
#endif

    if (sm->scheme != SM_SCHEME_STRESS_APPROX){
      for (i = 0; i < m; i++){
	idiag = -1;
	diag = 0.;
	for (j = id[i]; j < id[i+1]; j++){
	  if (i == jd[j]) {
	    idiag = j;
	    continue;
	  }
	  
	  dist = distance(x, dim, i, jd[j]);
	  //if (d[j] >= -0.0001*dist){
	  //   /* sometimes d[j] = 0 and ||x_i-x_j||=0*/
	  //   dd[j] = d[j]/MAX(0.0001, dist);
	  if (d[j] == 0){
	    dd[j] = 0;
	  } else {
	    if (dist == 0){
	      dij = d[j]/w[j];/* the ideal distance */
	      /* perturb so points do not sit at the same place */
	      for (k = 0; k < dim; k++) x[jd[j]*dim+k] += 0.0001*(drand()+.0001)*dij;
	      dist = distance(x, dim, i, jd[j]);	
	    }
	    dd[j] = d[j]/dist;
	    
#if 0	  
	    /* if two points are at the same place, we do not want a huge entry,
	       as this cause problem with CG./ In any case, 
	       at thw limit d[j] == ||x[i] - x[jd[j]]||, 
	       or close. */
	    if (dist < -d[j]*0.0000001){
	      dd[j] = -10000.;
	    } else {
	      dd[j] = d[j]/dist;
	    }
#endif
	    
	  }
	diag += dd[j];
	}
	assert(idiag >= 0);
	dd[idiag] = -diag;
      }
      /* solve (Lw+lambda*I) x = Lwdd y + lambda x0 */

      SparseMatrix_multiply_dense(Lwdd, FALSE, x, FALSE, &y, FALSE, dim);
    } else {
      for (i = 0; i < m; i++){
	for (j = 0; j < dim; j++){
	  y[i*dim+j] = 0;/* for stress_approx scheme, the whole rhs is calculated in stress_maxent_augment_rhs */
	}
      }
    }

    if (lambda){/* is there a penalty term? */
      for (i = 0; i < m; i++){
	for (j = 0; j < dim; j++){
	  y[i*dim+j] += lambda[i]*x0[i*dim+j];
	}
      }
    } 

    /* additional term added to the rhs */
    switch (sm->scheme){
    case SM_SCHEME_NORMAL_ELABEL: {
      for (i = 0; i < m; i++){
	for (j = 0; j < dim; j++){
	  y[i*dim+j] += x00[i*dim+j];
	}
      }
      break;
    }
    case SM_SCHEME_UNIFORM_STRESS:{/* this part can be done more efficiently using octree approximation */
      uniform_stress_augment_rhs(m, dim, x, y, alpha, M);
      break;
    } 
#if UNIMPEMENTED
    case SM_SCHEME_MAXENT:{
#ifdef GVIEWER
      if (Gviewer){
	char *lab;
	lab = MALLOC(sizeof(char)*100);
	sprintf(lab,"maxent. alpha=%10.2g, iter=%d",stress_maxent_data_get_alpha(sm->data), iter);
	gviewer_set_label(lab);
	FREE(lab);
      }
#endif
      stress_maxent_augment_rhs_fast(sm, dim, x, y, &flag);
      if (flag) goto RETURN;
      break;
    }
    case SM_SCHEME_STRESS_APPROX:{
      stress_approx_augment_rhs(sm, dim, x, y, &flag);
      if (flag) goto RETURN;
      break;
    }
    case SM_SCHEME_STRESS:{
#ifdef GVIEWER
      if (Gviewer){
	char *lab;
	lab = MALLOC(sizeof(char)*100);
	sprintf(lab,"pmds(k), iter=%d", iter);
	gviewer_set_label(lab);
	FREE(lab);
      }
#endif
    }
#endif /* UNIMPEMENTED */
    default:
      break;
  }

#ifdef DEBUG_PRINT
    if (Verbose) {
      fprintf(stderr, "stress1 = %g\n",get_stress(m, dim, iw, jw, w, d, x, sm->scaling, sm->data, 1));
    }
#endif

    if (sm->scheme == SM_SCHEME_UNIFORM_STRESS){
      res = uniform_stress_solve(Lw, alpha, dim, x, y, sm->tol_cg, sm->maxit_cg, &flag);
    } else {
      res = SparseMatrix_solve(Lw, dim, x, y,  sm->tol_cg, sm->maxit_cg, SOLVE_METHOD_CG, &flag);
      //res = SparseMatrix_solve(Lw, dim, x, y,  sm->tol_cg, 1, SOLVE_METHOD_JACOBI, &flag);
    }

    if (flag) goto RETURN;
#ifdef DEBUG_PRINT
    if (Verbose) fprintf(stderr, "stress2 = %g\n",get_stress(m, dim, iw, jw, w, d, y, sm->scaling, sm->data, 1));
#endif
    diff = total_distance(m, dim, x, y)/sqrt(vector_product(m*dim, x, x));
#ifdef DEBUG_PRINT
    if (Verbose){
      fprintf(stderr, "Outer iter = %d, cg res = %g, ||x_{k+1}-x_k||/||x_k|| = %g\n",iter, res, diff);
    }
#endif


    MEMCPY(x, y, sizeof(real)*m*dim);
  }

#ifdef DEBUG
  _statistics[1] += iter-1;
#endif

#ifdef DEBUG_PRINT
  if (Verbose) fprintf(stderr, "iter = %d, final stress = %f\n", iter, get_stress(m, dim, iw, jw, w, d, x, sm->scaling, sm->data, 1));
#endif

 RETURN:
  SparseMatrix_delete(Lwdd);
  if (Lc) {
    SparseMatrix_delete(Lc);
    SparseMatrix_delete(Lw);
  }

  if (x0) FREE(x0);
  if (y) FREE(y);
  if (x00) FREE(x00);
  return diff;
  
}
int calc_radial_density_map (int xbins,int ybins,int thetabins,double xrange,double yrange, double axis[3], double center[3], IntList *beadids, DoubleList *density_map, DoubleList *density_profile) {
  int i,j,t;
  int pi,bi;
  int nbeadtypes;
  int beadcount;
  double vectprod[3];
  double pvector[3];
  double xdist,ydist,rdist,xav,yav,theta;
  double xbinwidth,ybinwidth,binvolume;
  double thetabinwidth;
  double *thetaradii;
  int *thetacounts;
  int xindex,yindex,tindex;
  xbinwidth = xrange/(double)(xbins);
  ybinwidth = yrange/(double)(ybins);

  nbeadtypes = beadids->n;
  /* Update particles */
  updatePartCfg(WITHOUT_BONDS);

  /*Make sure particles are folded  */
  for (i = 0 ; i < n_part ; i++) {
    fold_coordinate(partCfg[i].r.p,partCfg[i].l.i,0);
    fold_coordinate(partCfg[i].r.p,partCfg[i].l.i,1);
    fold_coordinate(partCfg[i].r.p,partCfg[i].l.i,2);
  }

  beadcount = 0;
  xav = 0.0;
  yav = 0.0;
  for ( pi = 0 ; pi < n_part ; pi++ ) {
    for ( bi = 0 ; bi < nbeadtypes ; bi++ ) {
      if ( beadids->e[bi] == partCfg[pi].p.type ) {


	/* Find the vector from the point to the center */
	vecsub(center,partCfg[pi].r.p,pvector);

	/* Work out x and y coordinates with respect to rotation axis */
	
	/* Find the minimum distance of the point from the axis */
	vector_product(axis,pvector,vectprod);
	xdist = sqrt(sqrlen(vectprod)/sqrlen(axis));

	/* Find the projection of the vector from the point to the center
	   onto the axis vector */
	ydist = scalar(axis,pvector)/sqrt(sqrlen(axis));
	
    
	/* Work out relevant indices for x and y */
	xindex = (int)(floor(xdist/xbinwidth));
	yindex = (int)(floor((ydist+yrange*0.5)/ybinwidth));
	/*
	printf("x %d y %d \n",xindex,yindex);
	printf("p %f %f %f \n",partCfg[pi].r.p[0],partCfg[pi].r.p[1],partCfg[pi].r.p[2]);
	printf("pvec %f %f %f \n",pvector[0],pvector[1],pvector[2]);
	printf("axis %f %f %f \n",axis[0],axis[1],axis[2]);
	printf("dists %f %f \n",xdist,ydist);
	fflush(stdout);
	*/
	/* Check array bounds */
	if ( (xindex < xbins && xindex > 0) && (yindex < ybins && yindex > 0) ) {
	  density_map[bi].e[ybins*xindex+yindex] += 1;
	  xav += xdist;
	  yav += ydist;
	  beadcount += 1;
	} else {
	  //	    fprintf(stderr,"ERROR: outside array bounds in calc_radial_density_map"); fflush(NULL); errexit(); 
	}
      }

    }
  }


  /* Now turn counts into densities for the density map */
  for ( bi = 0 ; bi < nbeadtypes ; bi++ ) {
    for ( i = 0 ; i < xbins ; i++ ) {
      /* All bins are cylinders and therefore constant in yindex */
      binvolume = PI*(2*i*xbinwidth + xbinwidth*xbinwidth)*yrange;
      for ( j = 0 ; j < ybins ; j++ ) {
	density_map[bi].e[ybins*i+j] /= binvolume;
      }
    }
  }


  /* if required calculate the theta density profile */
  if ( thetabins > 0 ) {
    /* Convert the center to an output of the density center */
    xav = xav/(double)(beadcount);
    yav = yav/(double)(beadcount);
    thetabinwidth = 2*PI/(double)(thetabins);
    thetaradii = (double*)malloc(thetabins*nbeadtypes*sizeof(double));
    thetacounts = (int*)malloc(thetabins*nbeadtypes*sizeof(int));
    for ( bi = 0 ; bi < nbeadtypes ; bi++ ) {
      for ( t = 0 ; t < thetabins ; t++ ) {
	thetaradii[bi*thetabins+t] = 0.0;
	thetacounts[bi*thetabins+t] = 0.0;
      }
    }
    /* Maybe there is a nicer way to do this but now I will just repeat the loop over all particles */
      for ( pi = 0 ; pi < n_part ; pi++ ) {
	for ( bi = 0 ; bi < nbeadtypes ; bi++ ) {
	  if ( beadids->e[bi] == partCfg[pi].p.type ) {
	    vecsub(center,partCfg[pi].r.p,pvector);
	    vector_product(axis,pvector,vectprod);
	    xdist = sqrt(sqrlen(vectprod)/sqrlen(axis));
	    ydist = scalar(axis,pvector)/sqrt(sqrlen(axis));
	    /* Center the coordinates */

	    xdist = xdist - xav;
	    ydist = ydist - yav;
	    rdist = sqrt(xdist*xdist+ydist*ydist);
	    if ( ydist >= 0 ) {
	      theta = acos(xdist/rdist);
	    } else {
	      theta = 2*PI-acos(xdist/rdist);
	    }
	    tindex = (int)(floor(theta/thetabinwidth));
	    thetaradii[bi*thetabins+tindex] += xdist + xav;
	    thetacounts[bi*thetabins+tindex] += 1;
	    if ( tindex >= thetabins ) {
	      fprintf(stderr,"ERROR: outside density_profile array bounds in calc_radial_density_map"); fflush(NULL); errexit(); 
	    } else {
	      density_profile[bi].e[tindex] += 1;
	    }
	  }	  
	}
      }



      /* normalize the theta densities*/
      for ( bi = 0 ; bi < nbeadtypes ; bi++ ) {
	for ( t = 0 ; t < thetabins ; t++ ) {
	  rdist = thetaradii[bi*thetabins+t]/(double)(thetacounts[bi*thetabins+t]);
	  density_profile[bi].e[t] /= rdist*rdist;
	}
      }
       


      free(thetaradii);
      free(thetacounts);

  }
  






  //  printf("done \n");
  return ES_OK;
}
Exemple #26
0
/** calculate dihedral force between particles p1, p2 p3 and p4 
    Written by Arijit Maitra, adapted to new force interface by Hanjo,
    more general new dihedral form by Ana.
*/
inline int calc_dihedral_force(Particle *p2, Particle *p1, Particle *p3, Particle *p4,
				 Bonded_ia_parameters *iaparams, double force2[3],
				 double force1[2], double force3[2])
{
  int i;
  /* vectors for dihedral angle calculation */
  double v12[3], v23[3], v34[3], v12Xv23[3], v23Xv34[3], l_v12Xv23, l_v23Xv34;
  double v23Xf1[3], v23Xf4[3], v34Xf4[3], v12Xf1[3];
  /* dihedral angle, cosine of the dihedral angle */
  double phi, cosphi, sinmphi_sinphi;
  /* force factors */
  double fac, f1[3], f4[3];

  /* dihedral angle */
  calc_dihedral_angle(p1, p2, p3, p4, v12, v23, v34, v12Xv23, &l_v12Xv23, v23Xv34, &l_v23Xv34, &cosphi, &phi);
  /* dihedral angle not defined - force zero */
  if ( phi == -1.0 ) { 
    for(i=0;i<3;i++) { force1[i] = 0.0; force2[i] = 0.0; force3[i] = 0.0; }
    return 0;
  }

  /* calculate force components (directions) */
  for(i=0;i<3;i++)  {
    f1[i] = (v23Xv34[i] - cosphi*v12Xv23[i])/l_v12Xv23;;
    f4[i] = (v12Xv23[i] - cosphi*v23Xv34[i])/l_v23Xv34;
  }
  vector_product(v23, f1, v23Xf1);
  vector_product(v23, f4, v23Xf4);
  vector_product(v34, f4, v34Xf4);
  vector_product(v12, f1, v12Xf1);

  /* calculate force magnitude */
#ifdef OLD_DIHEDRAL
  fac = iaparams->p.dihedral.bend * iaparams->p.dihedral.phase * iaparams->p.dihedral.mult;
#else
  fac = -iaparams->p.dihedral.bend * iaparams->p.dihedral.mult;
#endif

  if(fabs(sin(phi)) < TINY_SIN_VALUE) {
#ifdef OLD_DIHEDRAL
    sinmphi_sinphi = iaparams->p.dihedral.mult * cos(2.0*PI - iaparams->p.dihedral.mult*phi)/cos(phi);
#else
    /*(comes from taking the first term of the MacLaurin expansion of
      sin(n*phi - phi0) and sin(phi) and then making the division).
      The original code had a 2PI term in the cosine (cos(2PI - nPhi))
      but I removed it because it wasn't doing anything. AnaVV*/
    sinmphi_sinphi = iaparams->p.dihedral.mult*
      cos(iaparams->p.dihedral.mult*phi - iaparams->p.dihedral.phase)/cosphi;
#endif
  }
  else {
#ifdef OLD_DIHEDRAL
    sinmphi_sinphi = sin(iaparams->p.dihedral.mult*phi)/sin(phi);
#else
    sinmphi_sinphi = sin(iaparams->p.dihedral.mult*phi - iaparams->p.dihedral.phase)/sin(phi);
#endif
  }

  fac *= sinmphi_sinphi;


  /* store dihedral forces */
  for(i=0;i<3;i++) {
      force1[i] = fac*v23Xf1[i];
      force2[i] = fac*(v34Xf4[i] - v12Xf1[i] - v23Xf1[i]);
      force3[i] = fac*(v12Xf1[i] - v23Xf4[i] - v34Xf4[i]);
  }
  return 0;
}
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;
  
}
/** Main method for calculation of bending forces described in literature
 *  @param p_ind1 particle object for particle 1
 *  @param p_ind2 particle object for particle 2
 *  @param p_ind3 particle object for particle 3
 *  @param p_ind3 particle object for particle 4
 *  @param iaparams parameters of the interaction such as max stretch, kb and theta0
 *  @param force forces in xyz on particle 1
 *  @param force2 forces in xyz on particle 2
 *  @param force3 forces in xyz on particle 3
 *  @param force4 forces in xyz on particle 4
 */
inline int calc_bending_force_ibm(Particle *p1, Particle *p2, Particle *p3, Particle *p4, Bonded_ia_parameters *iaparams, double force[3], double force2[3], double force3[3], double force4[3]) { 
  double theta, Ai, Aj;
  double dx1[3], dx2[3], dx3[3], n1[3], n2[3];
  double Pre, sc, len;
  double v1l[3], v2l[3], v1[3], v2[3], tmp[3], tmp2[3], term1[3], term2[3];
  double direc[3];
  double desc, DTh;
  int i;
  
  
  //Get vectors making up the two triangles
  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);
    
  //printf("dx1: %lf %lf %lf\n", dx1[0], dx1[1], dx1[2]);
  //printf("dx2: %lf %lf %lf\n", dx2[0], dx2[1], dx2[2]);
  //printf("dx3: %lf %lf %lf\n", dx3[0], dx3[1], dx3[2]);
  
  //Get normals on triangle; pointing outwards by definition of indices sequence
  vector_product(dx1, dx2, n1);
  vector_product(dx1, dx3, n2);
    
  if(iaparams->p.bending_force_ibm.boo == 0) {
      n2[0]=-1*n2[0]; n2[1]=-1*n2[1]; n2[2]=-1*n2[2];
  }
   
  //Get 2*area of triangles out of the magnitude of the resulting normals and make the latter unity 
  Ai = sqrt(n1[0]*n1[0] + n1[1]*n1[1] + n1[2]*n1[2]);
  n1[0] = n1[0]/Ai; n1[1]=n1[1]/Ai; n1[2]=n1[2]/Ai; 
  
  Aj = sqrt(n2[0]*n2[0] + n2[1]*n2[1] + n2[2]*n2[2]);
  n2[0] = n2[0]/Aj; n2[1]=n2[1]/Aj; n2[2]=n2[2]/Aj; 
  
  //printf("n1 = %lf %lf %lf\n", n1[0], n1[1], n1[2]);
  //printf("n2 = %lf %lf %lf\n", n2[0], n2[1], n2[2]);
  //printf("Ai = %lf   Aj = %lf\n", Ai, Aj);
  
  //Get the prefactor for the force term
  sc = scalar(n1,n2);
  
  if(sc>1.0) {
      sc = 1.0;
  }
  
  //Get theta as angle between normals
  theta = acos(sc);
  
  //printf("Theta_Pure = %lf\n", theta);
  //printf("n1: %lf %lf %lf\n", n1[0], n1[1], n1[2]);
  //printf("n2: %lf %lf %lf\n", n2[0], n2[1], n2[2]);
  
  vector_product(n1,n2,direc);
  
  //printf("direc = %lf %lf %lf\n", direc[0], direc[1], direc[2]);
  
  desc = scalar(dx1,direc);
  
  //printf("dec = %lf\n", desc);
  
  if(desc<0) {
      theta = -1.0*theta;
  }
  
  //printf("theta = %lf  theta0 = %lf\n", theta, iaparams->p.bending_force_ibm.theta0);
  
  
  DTh = theta-iaparams->p.bending_force_ibm.theta0;  
  
 
  //printf("DTh = %lf\n", DTh);
  
  if(isnan(theta)) {
      printf("Triangle-Pair: %d %d %d %d\n", p1->p.identity, p2->p.identity, p3->p.identity, p4->p.identity);
      printf("n1: %lf %lf %lf\n", n1[0], n1[1], n1[2]);
      printf("n2: %lf %lf %lf\n", n2[0], n2[1], n2[2]);
      printf("scalar: %lf\n", scalar(n1,n2));
      printf("p1: %lf %lf %lf\n", p1->r.p[0], p1->r.p[1], p1->r.p[2]);
      printf("p2: %lf %lf %lf\n", p2->r.p[0], p2->r.p[1], p2->r.p[2]);
      printf("p3: %lf %lf %lf\n", p3->r.p[0], p3->r.p[1], p3->r.p[2]);
      printf("p4: %lf %lf %lf\n", p4->r.p[0], p4->r.p[1], p4->r.p[2]);
  }
  
  
  //printf("%lf %lf\n", theta*TOANGLE, iaparams->p.bending_force_ibm.theta0*TOANGLE);
  
  //printf("sc = %lf\n", sc);
  
  
  if(theta>0) {
    Pre = 1.0*iaparams->p.bending_force_ibm.kb * sin(DTh);  
  } else {
    Pre = -1.0*iaparams->p.bending_force_ibm.kb * sin(DTh); 
  }
  
  //printf("Pre = %lf  kb=%lf\n", Pre, iaparams->p.bending_force_ibm.kb); 
  
  for(i=0; i<3; i++) {
      v1l[i] = n2[i]-sc*n1[i];
      v2l[i] = n1[i]-sc*n2[i];
  }
  
  //printf("v1l: %lf %lf %lf\n", v1l[0], v1l[1], v1l[2]);
  //printf("v2l: %lf %lf %lf\n", v2l[0], v2l[1], v2l[2]);
  
  len = sqrt(sqrlen(v1l));
  
  //printf("len1 = %lf\n", len);
  
  if(len>0) {
      for(i=0;i <3; i++)
	v1[i]=v1l[i]/len;
  }
  
  len = sqrt(sqrlen(v2l));
  
   //printf("len2 = %lf\n", len);
  
  if(len>0) {
      for(i=0;i <3; i++)
	v2[i]=v2l[i]/len;
  }
  
  //printf("v1: %lf %lf %lf\n", v1[0], v1[1], v1[2]);
  //printf("v2: %lf %lf %lf\n", v2[0], v2[1], v2[2]);
  
  //Force for particle 1:
  get_mi_vector(tmp,p2->r.p,p3->r.p); get_mi_vector(tmp2, p3->r.p, p4->r.p);
  vector_product(tmp,v1, term1); vector_product(tmp2,v2, term2);
  
  //printf("tmp: %lf %lf %lf\n", tmp[0], tmp[1], tmp[2]);
  //printf("tmp2: %lf %lf %lf\n", tmp2[0], tmp2[1], tmp2[2]);
  
  //printf("p1f: ");
  
  for(i=0;i<3;i++) {
      force[i] = Pre*(term1[i]/Ai + term2[i]/Aj);
      //printf("%lf ", Pre*(term1[i]/Ai + term2[i]/Aj));
  }
  
  //Force for particle 2:
  get_mi_vector(tmp,p3->r.p,p1->r.p);
  vector_product(tmp,v1, term1);
  
  //printf("\np2f: ");
  
  for(i=0;i<3;i++) {
      force2[i] = Pre*(term1[i]/Ai);
      //printf("%lf ", term1[i]/Ai);
  }
  
  //Force for Particle 3:
  get_mi_vector(tmp,p1->r.p,p2->r.p); get_mi_vector(tmp2, p4->r.p, p1->r.p);
  vector_product(tmp,v1, term1); vector_product(tmp2,v2, term2);
  
  //printf("\np3f: ");
  
  for(i=0;i<3;i++) {
      force3[i] = Pre*(term1[i]/Ai + term2[i]/Aj);
      //printf("%lf ", Pre*(term1[i]/Ai + term2[i]/Aj));
  }
  
  //Force for Particle 4:
  get_mi_vector(tmp,p1->r.p,p3->r.p);
  vector_product(tmp,v2, term1);
  
  //printf("\np4f: ");
  
  for(i=0;i<3;i++) {
      force4[i] = Pre*(term1[i]/Aj);
      //printf("%lf ", Pre*(term1[i]/Aj));
  }
  
  //printf("\n");
  
  return 0;
  
}
Exemple #29
0
void calc_comforce()
{
  IA_parameters *ia_params;
  std::vector<double> com0 (3), com1 (3);
  double  MofImatrix[9], diff[3];
  double vect0[3], vect1[3], eva[3], eve[3], fvect[3];
  Particle *p;
  int np;
  Cell *cell;
  
  for (int t0=0; t0<n_particle_types-1; t0++) {
    for (int t1=t0+1; t1<n_particle_types; t1++) {
      ia_params = get_ia_param(t0,t1);
      if (ia_params->COMFORCE_flag == 1) {
        com0 = centerofmass(t0);
        com1 = centerofmass(t1);
        for (int i = 0; i < 3; i++) {
          diff[i]=com1[i]-com0[i];
        }
        momentofinertiamatrix(t0, MofImatrix);
        calc_eigenvalues_3x3(MofImatrix, eva);
        /* perpendicular force */
        if(ia_params->COMFORCE_dir == 1) {
          calc_eigenvector_3x3(MofImatrix,eva[0],eve);
          /*By doing two vector products find radial axis along the target system */
          vector_product(eve,diff,vect0);
          vector_product(vect0,eve,vect1);
          
          /* normalize vect1, return is fvect */
          unit_vector(vect1,fvect);
        } else {
          /* parallel force */
          calc_eigenvector_3x3(MofImatrix,eva[0],fvect);
        }
        
        /* orient it along the com vector */
        if (scalar(fvect,diff) < 0.) {
          for (int i = 0; i < 3; i++) {
            fvect[i] = -fvect[i];
          }
        }
        
        /* Now apply the force */
        for (int c = 0; c < local_cells.n; c++) {
          cell = local_cells.cell[c];
          p  = cell->part;
          np = cell->n;
          for(int i = 0; i < np; i++) {
            if(p[i].p.type==t0) {
      	      for(int j = 0; j < 3; j++) {
                p[i].f.f[j] -= ia_params->COMFORCE_fratio * ia_params->COMFORCE_force * fvect[j];
              }
            }
            if(p[i].p.type==t1) {
      	      for (int j = 0; j < 3; j++) {
                p[i].f.f[j] +=  ia_params->COMFORCE_force * fvect[j];
              }
            }
          }
        }
        /*end of force application */
      }
    }
  }
  
}
Exemple #30
0
/** Computes the four body overlapped dihedral interaction force.
    Adds this force to the particle forces in forces.hpp (see \ref tclcommand_inter). 
    @param p1, p2, p3, p4 define the angle between the planes p1,p2,p3 and p2,p3,p4
    @param iaparams  bond type number of the angle interaction (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
    Needs feature OVERLAPPED compiled in (see \ref config.hpp). 
*/
inline int calc_overlap_dihedral_force(Particle *p2, Particle *p1,
					 Particle *p3, Particle *p4, Bonded_ia_parameters *iaparams,
					 double force2[3], double force1[3], double force3[3])
{
 int i;
  /* vectors for dihedral angle calculation */
  double v12[3], v23[3], v34[3], v12Xv23[3], v23Xv34[3], l_v12Xv23, l_v23Xv34;
  double v23Xf1[3], v23Xf4[3], v34Xf4[3], v12Xf1[3];
  /* dihedral angle, cosine of the dihedral angle */
  double phi, cosphi, sinmphi_sinphi;
  /* force factors */
  double fac, f1[3], f4[3];
  
  int ig;
  double f_dihe = 0.;

  /* dihedral angle */
  calc_dihedral_angle(p1, p2, p3, p4, v12, v23, v34, v12Xv23, &l_v12Xv23, v23Xv34, &l_v23Xv34, &cosphi, &phi);
  /* dihedral angle not defined - force zero */
  if ( phi == -1.0 ) { 
    for(i=0;i<3;i++) { force1[i] = 0.0; force2[i] = 0.0; force3[i] = 0.0; }
    return 0;
  }

  /* calculate force components (directions) */
  for(i=0;i<3;i++)  {
    f1[i] = (v23Xv34[i] - cosphi*v12Xv23[i])/l_v12Xv23;; 
    f4[i] = (v12Xv23[i] - cosphi*v23Xv34[i])/l_v23Xv34;
  }
  vector_product(v23, f1, v23Xf1);
  vector_product(v23, f4, v23Xf4);
  vector_product(v34, f4, v34Xf4);
  vector_product(v12, f1, v12Xf1);

  /* calculate force magnitude */
                //fac = sum_(i=1,N) { a_i * c_i * c_i * cos(c_i*x + b_i)/cos(phi) }
                //fac = sum_(i=1,N) { a_i * c_i * sin(c_i*phi + b_i) /sin(phi)}
  for(ig=0; ig<iaparams->p.overlap.noverlaps; ig++) {
  	fac = iaparams->p.overlap.para_a[ig] * iaparams->p.overlap.para_c[ig];

  	if(fabs(sin(phi)) < TINY_SIN_VALUE) {
    		/*(comes from taking the first term of the MacLaurin expansion of
      		sin(n*phi - phi0) and sin(phi) and then making the division).
      		The original code had a 2PI term in the cosine (cos(2PI - nPhi))
      		but I removed it because it wasn't doing anything. AnaVV*/
    		sinmphi_sinphi = iaparams->p.overlap.para_c[ig]*
      			cos(iaparams->p.overlap.para_c[ig] * phi + iaparams->p.overlap.para_b[ig])/cosphi;
  	}
  	else {
    		sinmphi_sinphi = sin(iaparams->p.overlap.para_c[ig] * phi - iaparams->p.overlap.para_b[ig])/sin(phi);
 	}
  	fac *= sinmphi_sinphi;
  	f_dihe += fac;
  }

  /* store dihedral forces */
  for(i=0;i<3;i++) {
      force1[i] = f_dihe*v23Xf1[i];
      force2[i] = f_dihe*(v34Xf4[i] - v12Xf1[i] - v23Xf1[i]);
      force3[i] = f_dihe*(v12Xf1[i] - v23Xf4[i] - v34Xf4[i]);
  }
  return 0;
}