* their right values
*/
- exchange->beta=&(params->beta[num]);
- exchange->n=&(params->n[num]);
- exchange->c=&(params->c[num]);
- exchange->d=&(params->d[num]);
- exchange->h=&(params->h[num]);
-
- exchange->betan=pow(*(exchange->beta),*(exchange->n));
- exchange->n_betan=*(exchange->n)*exchange->betan;
- exchange->c2=params->c[num]*params->c[num];
- exchange->d2=params->d[num]*params->d[num];
- exchange->c2d2=exchange->c2/exchange->d2;
+ exchange->beta_i=&(params->beta[num]);
+ exchange->n_i=&(params->n[num]);
+ exchange->c_i=&(params->c[num]);
+ exchange->d_i=&(params->d[num]);
+ exchange->h_i=&(params->h[num]);
+
+ exchange->betaini=pow(*(exchange->beta_i),*(exchange->n_i));
+ exchange->ci2=params->c[num]*params->c[num];
+ exchange->di2=params->d[num]*params->d[num];
+ exchange->ci2di2=exchange->ci2/exchange->di2;
return 0;
}
double scale;
params=moldyn->pot2b_params;
- num=ai->bnum;
+ num=aj->bnum;
exchange=&(params->exchange);
- exchange->run3bp=0;
- exchange->run2bp_post=0;
+ /* clear 3bp and 2bp post run */
+ exchange->run3bp_ij=0;
+ exchange->run3bp_ji=0;
+ exchange->run3bp_jk=0;
+ exchange->run2bp_post_ij=0;
+ exchange->run2bp_post_ji=0;
+ exchange->run2bp_post_jk=0;
/*
- * we need: f_c, df_c, f_r, df_r
+ * calc of 2bp contribution of V_ij and dV_ij/ji
+ *
+ * for Vij and dV_ij we need:
+ * - f_c_ij, df_c_ij
+ * - f_r_ij, df_r_ij
+ *
+ * for dV_ji we need:
+ * - f_c_ji = f_c_ij, df_c_ji = df_c_ij
+ * - f_r_ji = f_r_ij; df_r_ji = df_r_ij
*
- * therefore we need: R, S, A, lambda
*/
+ /* dist_ij, d_ij */
v3_sub(&dist_ij,&(aj->r),&(ai->r));
-
if(bc) check_per_bound(moldyn,&dist_ij);
-
d_ij=v3_norm(&dist_ij);
/* save for use in 3bp */
exchange->dist_ij=dist_ij;
/* constants */
- if(num==aj->bnum) {
+ if(num==ai->bnum) {
S=params->S[num];
R=params->R[num];
A=params->A[num];
B=params->B[num];
lambda=params->lambda[num];
mu=params->mu[num];
- params->exchange.chi=1.0;
+ exchange->chi=1.0;
}
else {
S=params->Smixed;
mu=params->mu_m;
params->exchange.chi=params->chi;
}
+
+ /* if d_ij > S => no force & potential energy contribution */
if(d_ij>S)
return 0;
+ /* more constants */
+ exchange->beta_j=&(params->beta[num]);
+ exchange->n_j=&(params->n[num]);
+ exchange->c_j=&(params->c[num]);
+ exchange->d_j=&(params->d[num]);
+ exchange->h_j=&(params->h[num]);
+ if(num==ai->bnum) {
+ exchange->betajnj=exchange->betaini;
+ exchange->cj2=exchange->ci2;
+ exchange->dj2=exchange->di2;
+ exchange->cj2dj2=exchange->ci2di2;
+ }
+ else {
+ exchange->betajnj=pow(*(exchange->beta_j),*(exchange->n_j));
+ exchange->cj2=params->c[num]*params->c[num];
+ exchange->dj2=params->d[num]*params->d[num];
+ exchange->cj2dj2=exchange->cj2/exchange->dj2;
+ }
+
+ /* f_r_ij = f_r_ji, df_r_ij = df_r_ji */
f_r=A*exp(-lambda*d_ij);
df_r=-lambda*f_r/d_ij;
- /* f_a, df_a calc + save for later use */
+ /* f_a, df_a calc (again, same for ij and ji) | save for later use! */
exchange->f_a=-B*exp(-mu*d_ij);
exchange->df_a=-mu*exchange->f_a/d_ij;
+ /* f_c, df_c calc (again, same for ij and ji) */
if(d_ij<R) {
/* f_c = 1, df_c = 0 */
f_c=1.0;
df_c=0.0;
- v3_scale(&force,&dist_ij,df_r);
+ /* two body contribution (ij, ji) */
+ v3_scale(&force,&dist_ij,-df_r);
}
else {
s_r=S-R;
arg=M_PI*(d_ij-R)/s_r;
f_c=0.5+0.5*cos(arg);
df_c=-0.5*sin(arg)*(M_PI/(s_r*d_ij));
- scale=df_c*f_r+df_r*f_c;
- v3_scale(&force,&dist_ij,scale);
+ /* two body contribution (ij, ji) */
+ v3_scale(&force,&dist_ij,-df_c*f_r-df_r*f_c);
}
- /* add forces */
+ /* add forces of 2bp (ij, ji) contribution
+ * dVij = dVji and we sum up both: no 1/2) */
v3_add(&(ai->f),&(ai->f),&force);
- /* energy is 0.5 f_r f_c ... */
+
+ /* energy 2bp contribution (ij, ji) is 0.5 f_r f_c ... */
moldyn->energy+=(0.5*f_r*f_c);
/* save for use in 3bp */
exchange->run2bp_post=1;
/* reset 3bp sums */
- exchange->zeta=0.0;
+ exchange->zeta_ij=0.0;
+ exchange->zeta_ji=0.0;
+ exchange->zeta_kl=0.0;
v3_zero(&(exchange->db_ij));
+ v3_zero(&(exchange->db_ji));
+ v3_zero(&(exchange->db_jk));
return 0;
}
t_tersoff_mult_params *params;
t_tersoff_exchange *exchange;
- t_3dvec dist_ij,dist_ik;
- t_3dvec temp,force;
+ t_3dvec dist_ij,dist_ik,dist_jk;
+ t_3dvec temp1,temp2;
double R,S,s_r;
- double d_ij,d_ik;
- double rijrik,dijdik;
+ double d_ij,d_ik,d_jk;
+ double rxxryy,dxxdyy;
double f_c,df_c,f_a,df_a;
double f_c_ik,df_c_ik,arg;
double n,c,d,h;
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
+ * calc of 3bp contribution of V_ij and dV_ij/ji/jk &
+ * 2bp contribution of dV_jk
+ *
+ * for Vij and dV_ij we still need:
+ * - b_ij, db_ij (zeta_ij)
+ * - f_c_ik, df_c_ik, constants_i, cos_theta_ijk, d_costheta_ijk
+ *
+ * for dV_ji we still need:
+ * - b_ji, db_ji (zeta_ji)
+ * - f_c_jk, d_c_jk, constants_j, cos_theta_jik, d_costheta_jik
+ *
+ * for dV_jk we need:
+ * - f_c_jk
+ * - f_a_jk
+ * - db_jk (zeta_jk)
+ * - f_c_ji, df_c_ji, constants_j, cos_theta_jki, d_costheta_jki
*
- * we got f_c, df_c, f_a, df_a from 2bp calculation
*/
- d_ij=exchange->d_ij;
- dist_ij=exchange->dist_ij;
+ /*
+ * get exchange data
+ */
- f_a=params->exchange.f_a;
- df_a=params->exchange.df_a;
+ /* dist_ij, d_ij - this is < S_ij ! */
+ dist_ij=exchange->dist_ij;
+ d_ij=exchange->d_ij;
+ /* f_c_ij, df_c_ij (same for ji) */
f_c=exchange->f_c;
df_c=exchange->df_c;
-
- /* 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_costheta, cos_theta, f_c_ik, df_c_ik, w_ik
- *
+ * calculate unknown values now ...
*/
+ /* V_ij and dV_ij stuff (in b_ij there is f_c_ik) */
+
+ /* dist_ik, d_ik */
v3_sub(&dist_ik,&(ak->r),&(ai->r));
if(bc) check_per_bound(moldyn,&dist_ik);
d_ik=v3_norm(&dist_ik);
- /* constants */
+ /* ik constants */
+ num=ai->bnum;
if(num==ak->bnum) {
R=params->R[num];
S=params->S[num];
S=params->Smixed;
}
- /* there is no contribution if f_c_ik = 0 */
- if(d_ik>S)
- return 0;
-
- /* get exchange data */
- n=*(exchange->n);
- c=*(exchange->c);
- d=*(exchange->d);
- h=*(exchange->h);
- c2=exchange->c2;
- d2=exchange->d2;
- c2d2=exchange->c2d2;
-
- /* cosine of theta by scalaproduct */
- rijrik=v3_scalar_product(&dist_ij,&dist_ik);
- dijdik=d_ij*d_ik;
- cos_theta=rijrik/dijdik;
-
- /* hack - cos theta machine accuracy problems! */
- if(cos_theta>1.0||cos_theta<-1.0) {
- printf("THETA CORRECTION\n");
- moldyn->debug++;
- if(fabs(cos_theta)>1.0+ACCEPTABLE_ERROR)
- printf("[moldyn] WARNING: cos theta failure!\n");
- if(cos_theta<0) {
- cos_theta=-1.0;
+ /* zeta_ij/dzeta_ij contribution only for d_ik < S */
+ if(d_ik<S) {
+
+ /* get constants_i from exchange data */
+ n=*(exchange->n_i);
+ c=*(exchange->c_i);
+ d=*(exchange->d_i);
+ h=*(exchange->h_i);
+ c2=exchange->ci2;
+ d2=exchange->di2;
+ c2d2=exchange->ci2di2;
+
+ /* cosine of theta_ijk by scalaproduct */
+ rijrik=v3_scalar_product(&dist_ij,&dist_ik);
+ dijdik=d_ij*d_ik;
+ cos_theta=rijrik/dijdik;
+
+ /* d_costheta */
+ tmp=1.0/dijdik;
+ d_costheta1=cos_theta/(d_ij*d_ij)-tmp;
+ d_costheta2=cos_theta/(d_ik*d_ik)-tmp;
+
+ /* some usefull values */
+ h_cos=(h-cos_theta);
+ d2_h_cos2=d2+(h_cos*h_cos);
+ frac=c2/(d2_h_cos2);
+
+ /* g(cos_theta) */
+ g=1.0+c2d2-frac;
+
+ /* d_costheta_ij and dg(cos_theta) - needed in any case! */
+ v3_scale(&temp1,&dist_ij,d_costheta1);
+ v3_scale(&temp2,&dist_ik,d_costheta2);
+ v3_add(&temp1,&temp1,&temp2);
+ v3_scale(&temp1,&temp1,-2.0*frac*h_cos/d2_h_cos2); /* dg */
+
+ /* f_c_ik & df_c_ik + {d,}zeta contribution */
+ if(d_ik<R) {
+ /* {d,}f_c_ik */
+ // => f_c_ik=1.0;
+ // => df_c_ik=0.0; of course we do not set this!
+
+ /* zeta_ij */
+ exchange->zeta_ij+=g;
+
+ /* dzeta_ij */
+ v3_add(dzeta_ij,dzeta_ij,&temp1);
}
else {
- cos_theta=1.0;
+ /* {d,}f_c_ik */
+ 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));
+
+ /* zeta_ij */
+ exchange->zeta_ij+=f_c_ik*g;
+
+ /* dzeta_ij */
+ v3_scale(&temp1,&temp1,f_c_ik);
+ v3_scale(&temp2,&dist_ik,g*df_c_ik);
+ v3_add(dzeta_ij,&temp2,&temp1);
}
}
- d_costheta1=dijdik-rijrik*d_ik/d_ij;
- d_costheta2=dijdik-rijrik*d_ij/d_ik;
+ /* dV_ji stuff (in b_ji there is f_c_jk) + dV_jk stuff! */
+
+ /* dist_jk, d_jk */
+ v3_sub(&dist_jk,&(ak->r),&(aj->r));
+ if(bc) check_per_bound(moldyn,&dist_jk);
+ d_jk=v3_norm(&dist_jk);
- h_cos=(h-cos_theta);
- d2_h_cos2=d2+(h_cos*h_cos);
+ /* jk constants */
+ num=aj->bnum;
+ if(num==ak->bnum) {
+ R=params->R[num];
+ S=params->S[num];
+ }
+ else {
+ R=params->Rmixed;
+ S=params->Smixed;
+ }
- frac=c2/(d2_h_cos2);
- g=1.0+c2d2-frac;
+ /* zeta_ji/dzeta_ji contribution only for d_jk < S_jk */
+ if(d_jk<S) {
+
+ /* constants_j from exchange data */
+ n=*(exchange->n_j);
+ c=*(exchange->c_j);
+ d=*(exchange->d_j);
+ h=*(exchange->h_j);
+ c2=exchange->cj2;
+ d2=exchange->dj2;
+ c2d2=exchange->cj2dj2;
+
+ /* cosine of theta_jik by scalaproduct */
+ rxxryy=v3_scalar_product(&dist_ij,&dist_jk); /* times -1 */
+ dxxdyy=d_ij*d_jk;
+ cos_theta=rxxryy/dxxdyy;
+
+ /* d_costheta */
+ d_costheta1=1.0/(d_jk*d_ij);
+ d_costheta2=cos_theta/(d_ij*d_ij); /* in fact -cos(), but ^ */
+
+ /* some usefull values */
+ h_cos=(h-cos_theta);
+ d2_h_cos2=d2+(h_cos*h_cos);
+ frac=c2/(d2_h_cos2);
+
+ /* g(cos_theta) */
+ g=1.0+c2d2-frac;
+
+ /* d_costheta_ij and dg(cos_theta) - needed in any case! */
+ v3_scale(&temp1,&dist_jk,d_costheta1);
+ v3_scale(&temp2,&dist_ij,-d_costheta2); /* ji -> ij => -1 */
+ v3_add(&temp1,&temp1,&temp2);
+ v3_scale(&temp1,&temp1,-2.0*frac*h_cos/d2_h_cos2); /* dg */
+
+ /* dV_jk stuff | add force contribution on atom i immediately */
+ if(exchange->d_ij_between_rs) {
+ tmp=pow(f_c_ij*g,(n_j-1.0)); /* zeta_jk ^ n_j-1 */
+ v3_scale(&temp2,&temp1,f_c_ij)
+ v3_scale(&temp3,&dist_ij,df_c_ij);
+ v3_add(&temp3,&temp3,&temp2); /* dzeta_jk */
+ }
+ else {
+ /* f_c_ij = 1, df_c_ij = 0 */
+ tmp=pow(g,(n_j-1.0)); /* zeta_jk ^ n_j-1 */
+ tmp
+ /* dzeta_jk in temp1 */
+ /* HIER WEITER !!! */
+ }
- /* d_costheta contrib to db_ij (needed in all remaining cases) */
- v3_scale(&temp,&dist_ij,d_costheta1);
- v3_scale(&force,&dist_ik,d_costheta2);
- v3_add(&force,&force,&temp);
- v3_scale(&force,&force,-2.0*frac*h_cos/d2_h_cos2); /* f_c_ik missing */
+ /* f_c_jk + {d,}zeta contribution (df_c_jk = 0) */
+ if(d_jk<R) {
+ /* f_c_jk */
+ // f_c_jk=1.0; again, we do not set this!
- if(d_ik<R) {
- /* f_c_ik = 1, df_c_ik = 0 */
- /* => only d_costheta contrib to db_ij */
- // => do nothing ...
+ /* zeta_ji */
+ exchange->zeta_ji+=g;
- /* zeta, f_c_ik = 1 */
- exchange->zeta+=g;
- }
- 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));
- /* scale d_costheta contrib with f_c_ik */
- v3_scale(&force,&force,f_c_ik);
+ /* dzeta_ji */
+ v3_add(dzeta_ji,dzeta_ji,&temp1);
+ }
+ else {
+ /* f_c_jk */
+ s_r=S-R;
+ arg=M_PI*(d_jk-R)/s_r;
+ f_c_jk=0.5+0.5*cos(arg);
- /* df_c_ik contrib to db_ij */
- v3_scale(&temp,&dist_ik,df_c_ik*g);
+ /* zeta_ji */
+ exchange->zeta_ji+=f_c_jk*g;
- /* sum up both parts */
- v3_add(&force,&force,&temp);
-
- /* zeta */
- exchange->zeta+=f_c_ik*g;
+ /* dzeta_ij */
+ v3_scale(&temp1,&temp1,f_c_jk);
+ v3_add(dzeta_ji,dzeta_ji,&temp1);
+ }
}
-printf("%.30f\n",exchange->zeta);
-
- /* add to db_ij */
- v3_add(&(exchange->db_ij),&(exchange->db_ij),&force);
-
+
return 0;
}