-
-/* tersoff 3 body part */
-
-int tersoff_mult_3bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,t_atom *ak,u8 bc) {
-
- t_tersoff_mult_params *params;
- t_tersoff_exchange *exchange;
- t_3dvec dist_ij,dist_ik,dist_jk;
- t_3dvec temp,force;
- double R,S,s_r;
- double d_ij,d_ij2,d_ik,d_jk;
- double f_c,df_c,b_ij,f_a,df_a;
- double f_c_ik,df_c_ik,arg;
- double scale;
- double chi;
- double n,c,d,h,beta,betan;
- double c2,d2,c2d2;
- double numer,denom;
- double theta,cos_theta,sin_theta;
- double d_theta,d_theta1,d_theta2;
- double h_cos,h_cos2,d2_h_cos2;
- double frac1,bracket1,bracket2,bracket2_n_1,bracket2_n;
- double bracket3,bracket3_pow_1,bracket3_pow;
- int num;
-
- params=moldyn->pot3b_params;
- num=ai->bnum;
- exchange=&(params->exchange);
-
- if(!(exchange->run3bp))
- return 0;
-
- /*
- * we need: f_c, d_fc, b_ij, db_ij, f_a, df_a
- *
- * we got f_c, df_c, f_a, df_a from 2bp calculation
- */
-
- d_ij=exchange->d_ij;
- d_ij2=exchange->d_ij2;
-
- f_a=params->exchange.f_a;
- df_a=params->exchange.df_a;
-
- /* d_ij is <= S, as we didn't return so far! */
-
- /*
- * calc of b_ij (scalar) and db_ij (vector)
- *
- * - for b_ij: chi, beta, f_c_ik, w(=1), c, d, h, n, cos_theta
- *
- * - for db_ij: d_theta, sin_theta, cos_theta, f_c_ik, df_c_ik,
- * w_ik,
- *
- */
-
- v3_sub(&dist_ik,&(ai->r),&(ak->r));
- if(bc) check_per_bound(moldyn,&dist_ik);
- d_ik=v3_norm(&dist_ik);
-
- /* constants for f_c_ik calc */
- if(num==ak->bnum) {
- R=params->R[num];
- S=params->S[num];
- }
- else {
- R=params->Rmixed;
- S=params->Smixed;
- }
-
- /* calc of f_c_ik */
- if(d_ik>S) {
- f_c_ik=0.0;
- df_c_ik=0.0;
- }
- else if(d_ik<R) {
- f_c_ik=1.0;
- df_c_ik=0.0;
- }
- else {
- s_r=S-R;
- arg=M_PI*(d_ik-R)/s_r;
- f_c_ik=0.5+0.5*cos(arg);
- df_c_ik=-0.5*sin(arg)*(M_PI/(s_r*d_ik));
- }
-
- v3_sub(&dist_jk,&(aj->r),&(ak->r));
- if(bc) check_per_bound(moldyn,&dist_jk);
- d_jk=v3_norm(&dist_jk);
-
- beta=*(exchange->beta);
- betan=exchange->betan;
- n=*(exchange->n);
- c=*(exchange->c);
- d=*(exchange->d);
- h=*(exchange->h);
- chi=exchange->chi;
- c2=exchange->c2;
- d2=exchange->d2;
- c2d2=exchange->c2d2;
-
- numer=d_ij2+d_ik*d_ik-d_jk*d_jk;
- denom=2*d_ij*d_ik;
- //cos_theta=numer/denom;
- cos_theta=v3_scalar_product(&dist_ij,&dist_ik)/(d_ij*d_ik);
- sin_theta=sqrt(1.0-(cos_theta*cos_theta));
- theta=acos(cos_theta);
- d_theta=(-1.0/sqrt(1.0-cos_theta*cos_theta))/(denom*denom);
- d_theta1=2*denom-numer*2*d_ik/d_ij;
- d_theta2=2*denom-numer*2*d_ij/d_ik;
- d_theta1*=d_theta;
- d_theta2*=d_theta;
-
- h_cos=(h-cos_theta);
- h_cos2=h_cos*h_cos;
- d2_h_cos2=d2-h_cos2;
-
- /* some usefull expressions */
- frac1=c2/(d2-h_cos2);
- bracket1=1+c2d2-frac1;
- if(f_c_ik==0.0) {
- bracket2=0.0;
- bracket2_n_1=0.0;
- bracket2_n=0.0;
- bracket3=1.0;
- printf("Foo -> 0: ");
- }
- else {
- bracket2=f_c_ik*bracket1;
- bracket2_n_1=pow(bracket2,n-1.0);
- bracket2_n=bracket2_n_1*bracket2;
- bracket3=1.0+betan*bracket2_n;
- printf("Foo -> 1: ");
- }
- bracket3_pow_1=pow(bracket3,(-1.0/(2.0*n))-1.0);
-printf("THETA: %.15f %.15f\n",cos_theta,theta*180/(2*M_PI));
- bracket3_pow=bracket3_pow_1*bracket3;
-
- /* now go on with calc of b_ij and derivation of b_ij */
- b_ij=chi*bracket3_pow;
-
- /* derivation of theta */
- v3_scale(&force,&dist_ij,d_theta1);
- v3_scale(&temp,&dist_ik,d_theta2);
- v3_add(&force,&force,&temp);
-
- /* part 1 of derivation of b_ij */
- v3_scale(&force,&force,sin_theta*2*h_cos*f_c_ik*frac1);
-
- /* part 2 of derivation of b_ij */
- v3_scale(&temp,&dist_ik,df_c_ik*bracket1);
-
- /* sum up and scale ... */
- v3_add(&temp,&temp,&force);
- scale=bracket2_n_1*n*betan*(1+betan*bracket3_pow_1)*chi*(1.0/(2.0*n));
- v3_scale(&temp,&temp,scale);
-
- /* now construct an energy and a force out of that */
- v3_scale(&temp,&temp,f_a);
- v3_scale(&force,&dist_ij,df_a*b_ij);
- v3_add(&temp,&temp,&force);
- v3_scale(&temp,&temp,f_c);
- v3_scale(&force,&dist_ij,df_c*b_ij*f_a);
- v3_add(&force,&force,&temp);
-
- /* add forces */
- v3_add(&(ai->f),&(ai->f),&force);
- /* energy is 0.5 f_r f_c */
- moldyn->energy+=(0.5*f_a*b_ij*f_c);
-
- return 0;
-}
-