Allink  v0.1
ForcesForceField.cpp
00001 #include "Forces.h"
00002 //-------------------------SPLINES--------------------------------
00004 int Forces::ForceFieldLine(){
00005   double Sign=1.;
00006   SPLINE Sp1;
00007   SPLINE Sp2;
00008   SPLINE Cub1;
00009   SPLINE Cub2;
00010   SPLINE Par1;
00011   SPLINE Par2;
00012   double fSLap=0.;
00013   double fLap=0.;
00014   //Fm[Part2Move].fExt[2] = -Fm[Part2Move].fHel[2];
00015   //Fm[Part2Move].fExt[2] = 0.;
00016   for(int p=0;p<pNPart();p++){
00017     Fm[p].Ext[2] = -Fm[p].Dir[2]/1.1;
00018     if(IfInterp==FIT_SPLINE3){
00019       if( p == 0)
00020    Sp2 = Mat->Spline3Beg(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,2);
00021       else if( p < pNPart() - 2 )
00022    Sp2 = Mat->Spline3(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,2);
00023       else if( p == pNPart() - 2 )
00024    Sp2 = Mat->Spline3End(Pm[p].Pos,Pm[p+1].Pos,0,2);
00025       fSLap = 0.;//atan(Sp2.a1);
00026       fLap = 2.*Sp2.a2; 
00027     }
00028     else if(IfInterp==FIT_SPLINE4){
00029       if( p == 0){
00030    Sp2 = Mat->Spline4Beg(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,Pm[p+3].Pos,0,2);
00031    //Pm[p].Typ = 2;
00032       }
00033       else if( p < pNPart() - 3 )
00034    Sp2 = Mat->Spline4(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,Pm[p+3].Pos,0,2);
00035       else if( p == pNPart() - 3 ){
00036    Sp2 = Mat->Spline3(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,2);
00037       //Sp2 = Mate->Spline4PreEnd(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,1);
00038    //Pm[p].Typ = 2;
00039       }
00040       else if( p == pNPart() - 2 ){
00041    Sp2 = Mat->Spline3End(Pm[p].Pos,Pm[p+1].Pos,0,2);
00042       //Sp2 = Mate->Spline4End(Pm[p].Pos,Pm[p+1].Pos,0,1);
00043    //Pm[p].Typ = 2;
00044       }
00045       fSLap = (24.*Sp2.a4);
00046       fLap = (2.*Sp2.a2);
00047     }
00048 //     else if(IfInterp==FIT_PARAB){
00049 //       if(p < Gen->NPart - 2){
00050 //    Par1 = Mate->Parab(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,2);
00051 //       }
00052 //       fSLap  = 0.;//(2.*Par2.A*Pm[p].Pos[0]+Par2.B);
00053 //       fLap  = 2.*Par1.A/100.; 
00054 //     }
00055     else if(IfInterp==FIT_PARAB2){
00056       if(p == 0){
00057    Sp2 = Mat->Parab(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,2);
00058       }
00059       if(p < pNPart() - 1){
00060    Sp2 = Mat->Parab2(Pm[p-1].Pos,Pm[p].Pos,Pm[p+1].Pos,0,2);
00061       }
00062       fSLap = 0.;//(Par2.B);
00063       fLap = 2.*Sp2.a2;
00064     }
00065     else if(IfInterp==FIT_CUBIC){
00066       if(p == 0){
00067    Cub2 = Mat->Parab(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,2);
00068       }
00069       if(p < pNPart() - 2){
00070    Cub2 = Mat->Cubica(Pm[p-1].Pos,Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,2);
00071       }
00072       if(p == pNPart() - 2){
00073    Cub2 = Mat->Parab2(Pm[p-1].Pos,Pm[p].Pos,Pm[p+1].Pos,0,2);
00074       }
00075       fSLap = 0.;
00076       fLap = 2.*Cub2.a2;
00077     }
00078     else if(IfInterp==FIT_FORTH){
00079       double Ref=0.;
00080     if(p < 1){
00081       //Sp1 = Mat->Forth(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,Pm[p+3].Pos,Pm[p+4].Pos,0,1);
00082       Sp2 = Mat->Forth(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,Pm[p+3].Pos,Pm[p+4].Pos,0,2);
00083       Ref = Pm[p].Pos[0] - Pm[p+2].Pos[0]; 
00084     }
00085     else if(p < 2){
00086       //Sp1 = Mat->Forth(Pm[p-1].Pos,Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,Pm[p+3].Pos,0,1);
00087       Sp2 = Mat->Forth(Pm[p-1].Pos,Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,Pm[p+3].Pos,0,2);
00088       Ref = Pm[p].Pos[0] - Pm[p+1].Pos[0]; 
00089     }
00090     else if(p < pNPart()-2){
00091       //Sp1 = Mat->Forth(Pm[p-2].Pos,Pm[p-1].Pos,Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,1);
00092       Sp2 = Mat->Forth(Pm[p-2].Pos,Pm[p-1].Pos,Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,2);
00093       Ref = 0.; 
00094     }
00095     else if(p == pNPart()-2){
00096       //Sp1 = Mat->Forth(Pm[p-3].Pos,Pm[p-2].Pos,Pm[p-1].Pos,Pm[p].Pos,Pm[p+1].Pos,0,1);
00097       Sp2 = Mat->Forth(Pm[p-3].Pos,Pm[p-2].Pos,Pm[p-1].Pos,Pm[p].Pos,Pm[p+1].Pos,0,2);
00098       Ref = Pm[p].Pos[0] - Pm[p-1].Pos[0]; 
00099     }
00100     else if(p <= pNPart()-1){
00101       //Sp1 = Mat->Forth(Pm[p-4].Pos,Pm[p-3].Pos,Pm[p-2].Pos,Pm[p-1].Pos,Pm[p].Pos,0,1);
00102       Sp2 = Mat->Forth(Pm[p-4].Pos,Pm[p-3].Pos,Pm[p-2].Pos,Pm[p-1].Pos,Pm[p].Pos,0,2);
00103       Ref = Pm[p].Pos[0] - Pm[p-2].Pos[0]; 
00104     }
00105     fSLap = -(24.*Sp2.a4)*QUAD(QUAD(Dx));
00106     fLap = (2.*Sp2.a2)*QUAD(Dx);
00107     //printf("%d) %lf %lf\n",p,Kf.kLap*fLap,Kf.kSLap*fSLap);
00108     }
00109     if(fLap > 100.)
00110       fLap = 100.;
00111     if(fSLap < -100.)
00112       fSLap = -100.;
00113     if(fSLap > 100.)
00114       fSLap = 100.;
00115     if(fSLap < -100.)
00116       fSLap = -100.;
00117     Fm[p].Dir[2] = Kf.SLap*fSLap + Kf.Lap*fLap;
00118     //if(Pm[p].Pos[2] <0) Sign = -1.;
00119     //else Sign = 1;
00120     //Fm[p].fHel[2] *= Sign;
00121     //if(p == Part2Move)
00122     //if(p > Part2Move -4 && p < Part2Move +4)
00123     {
00124       //printf("%d in (%lf,%lf) ha %lf|%lf Sp %lf %lf\n",p,Pm[p].Pos[2],Pm[p].Vel[2],Fm[p].fHel[2],Fm[p].fExt[2],fSLap,fLap);
00125     }
00126   }
00127   return 0;
00128 }
00130 int Forces::ForceFieldLeaves(){
00131   double Sign=1.;
00132   SPLINE Sp1;
00133   SPLINE Sp2;
00134   PARABOLA Par1;
00135   PARABOLA Par2;
00136   double fSLap=0.;
00137   double fLap=0.;
00138   for(int c=0;c<pNChain();c++){
00139     for(int p=c*NEdge;p<NEdge*(c+1);p++){
00140       Fm[p].Ext[2] = -(Fm[p].Dir[2])/1.1;
00141       //      Fm[p].El[2] = - Kf.El[2]*( c*Kf.Elong[2] + .5 - Pm[p].Pos[2]);
00142       if( p == c*NEdge){
00143    Sp2 = Mat->Spline4Beg(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,Pm[p+3].Pos,0,2);
00144    //Pm[p].Typ = 2;
00145       }
00146       else if( p < NEdge*(c+1) - 3 )
00147    Sp2 = Mat->Forth(Pm[p-2].Pos,Pm[p-1].Pos,Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,2);
00148       //Sp2 = Mat->Spline4(Pm[p].Pos,Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,2);
00149       //      else Pm[p].Typ = 2;
00150       else if( p == NEdge*(c+1) - 3 ){
00151    Sp2 = Mat->Spline3(Pm[p].Pos,Pm[p+1].Pos,Pm[p+2].Pos,0,2);
00152    //Pm[p].Typ = 2;
00153       }
00154       else if( p == pNPart() - 2 ){
00155    Sp2 = Mat->Spline3End(Pm[p].Pos,Pm[p+1].Pos,0,2);
00156    //Pm[p].Typ = 2;
00157       }
00158       fSLap = -(24.*Sp2.a4)*QUAD(QUAD(Dx));
00159       fLap = (2.*Sp2.a2)*QUAD(Dx);
00160       if(fLap > 100.)fLap = 100.;
00161       if(fLap < -100.)fLap = -100.;
00162       if(fSLap > 100.)fSLap = 100.;
00163       if(fSLap < -100.)fSLap = -100.;
00164       Fm[p].Dir[2] = +Kf.SLap*fSLap + Kf.Lap*fLap;
00165       continue;
00166       {
00167    double Rad2=0.;
00168    for(int d=0;d<3;d++){
00169      Rad2 += QUAD((Pm[p].Pos[d] - Nano->Pos[d]));
00170    }
00171    if( Rad2 > QUAD((3.*Nano->Rad))) continue;
00172    double CosTh = (Nano->Pos[0] - Pm[p].Pos[0])/Nano->Rad;
00173    double SenTh = sqrt(1 - QUAD(CosTh));
00174    double Sign = 1.;
00175    double Rad = sqrt(Rad2);
00176    double Strength = 12.*pow( (Nano->Rad/Rad) , 13) + 6.*pow( (Nano->Rad/Rad) , 7);
00177    if(p <= NEdge)
00178      Sign *= -1.;
00179    Fm[p].Dir[0] = Kf.LJ * Strength * CosTh;
00180    Fm[p].Dir[2] = Kf.LJ * Strength * SenTh * Sign;
00181       }
00182     }
00183   }
00184 }
00185 //----------------------HARMONIC-POTENTIAL-------------------
00187 int Forces::ForceFieldBulk(){
00188   for(int p=0;p<pNPart();p++){
00189     for(int d=0;d<3;d++){
00190       Fm[p].Ext[d] = -(Fm[p].Dir[d])/2.;
00191     }
00192     for(int l=0;l<Ln[p].NLink;l++){
00193       int link = Ln[p].Link[l];
00194       for(int d=0;d<3;d++){
00195    double Delta = ASS((Pm[link].Pos[d] - Pm[p].Pos[d]));
00196    if(Delta < 0.001) continue;
00197    // printf("%d-%d (%d) %lf ",p,link,d,Delta);
00198    double Sign = 1.;
00199    if(Pm[p].Pos[d] < Pm[link].Pos[d] )
00200      Sign = -1.;
00201    Fm[p].Dir[d] +=  - Sign*Kf.El[d]*(Delta - Kf.Elong[d])/1.1;
00202       }
00203       //      printf("\n");
00204     }
00205     //if(p > Part2Move -4 && p < Part2Move +4)
00206       //printf("%d) in (%lf,%lf) ha %lf|%lf|%lf Sp %lf %lf\n",p,Pm[p].Pos[2],Pm[p].Vel[2],Fm[p].fHel[2],Fm[p].fExt[2],Fm[p].fEl[2]);
00207   }
00208 }
00210 void Forces::ForceFieldRod(){
00211   double DistRelBA[4];
00212   double DistRelBC[4];
00213   double Pre[12];
00214   for(int b=0;b<pNBlock();b++){
00215     for(int c=0;c<pNChain(b);c++){
00216       for(int p=c*pNPCh(b);p<(c+1)*pNPCh(b)-1;p++){
00217    TwoPartDist(p+1,p,DistRelBA);
00218    double ForceSp = pkSpr()*(1. - pSprRest()/DistRelBA[3]);
00219    for(int d=0;d<3;d++){
00220      Fm[p].Dir[d] += ForceSp*DistRelBA[d];
00221      Fm[p+1].Dir[d] -= ForceSp*DistRelBA[d];
00222    }
00223    if(p < (c+1)*pNPCh(b)-2){
00224      TwoPartDist(p+2,p+1,DistRelBC);
00225      double CosAngle = 0.;
00226      for(int d=0;d<3;d++){
00227        DistRelBA[d] /= DistRelBA[3];
00228        DistRelBC[d] /= DistRelBC[3];
00229        CosAngle += DistRelBA[d]*DistRelBC[d];
00230      }
00231      double PreFactBA = pkBen()/DistRelBA[3];
00232      double PreFactBC = pkBen()/DistRelBC[3];
00233      for(int d=0;d<3;d++){
00234        Fm[p+0].Dir[d] += PreFactBA*(DistRelBC[d]-DistRelBA[d]*CosAngle);
00235        Fm[p+1].Dir[d] -= PreFactBA*(DistRelBC[d]-DistRelBA[d]*CosAngle);
00236        Fm[p+1].Dir[d] += PreFactBC*(DistRelBA[d]-DistRelBC[d]*CosAngle);
00237        Fm[p+2].Dir[d] -= PreFactBC*(DistRelBA[d]-DistRelBC[d]*CosAngle);
00238      }
00239    }    
00240       }
00241     }
00242   }
00243 }
00244 /* obsolete? */
00245 int Forces::SumSomeForces(int HowMany){
00246   double Sign=1.;
00247   SPLINE Par1;
00248   SPLINE Par2;
00249   double Slope1;
00250   double Slope2;
00251   if(Bead2Move - HowMany < 1 || Bead2Move + HowMany > pNPart() - 2)
00252     return 1;
00253   //Fm[Part2Move].fExt[2] = -Fm[Part2Move].fHel[2];
00254   //Fm[Part2Move].fExt[2] = 0.;
00255   int pp = Bead2Move;
00256   for(int h = 0;h<HowMany;h++){
00257     int link1 = Ln[pp].Link[0];
00258     int link2 = Ln[pp].Link[1];
00259 //     printf("(%lf %lf %lf), (%lf %lf %lf), (%lf %lf %lf)\n",
00260 //       Pm[link1].Pos[0],Pm[link1].Pos[1],Pm[link1].Pos[2],
00261 //       Pm[pp].Pos[0],Pm[pp].Pos[1],Pm[pp].Pos[2],
00262 //       Pm[link2].Pos[0],Pm[link2].Pos[1],Pm[link2].Pos[2]);
00263 //    Par1 = Mat->Parab2(Pm[link1].Pos,Pm[pp].Pos,Pm[link2].Pos,0,2);
00264     Par2 = Mat->Parab2(Pm[link1].Pos,Pm[pp].Pos,Pm[link2].Pos,1,2);
00265     Fm[pp].Dir[2] = - Kf.Lap*QUAD(2.*Par1.a2);
00266     Fm[pp].Dir[2] += - Kf.Lap*QUAD(2.*Par2.a2);
00267     //printf("%d-%d|%d) %lf %lf %lf %lf  ",pp,link1,link2,Slope1,Par1.A,Slope2,Par2.A);
00268     link1 = Ln[pp].Link[2];
00269     link2 = Ln[pp].Link[3];
00270     Par1 = Mat->Parab2(Pm[link1].Pos,Pm[pp].Pos,Pm[link2].Pos,0,2);
00271     //Par2 = Mat->Parab2(Pm[link1].Pos,Pm[pp].Pos,Pm[link2].Pos,1,2);
00272     Fm[pp].Dir[2] += - Kf.Lap*QUAD(2.*Par1.a2);
00273     Fm[pp].Dir[2] += - Kf.Lap*QUAD(2.*Par2.a2);
00274     //printf("%d-%d|%d) %lf %lf %lf %lf\n",pp,link1,link2,Slope1,Par1.A,Slope2,Par2.A);
00275     if(Pm[pp].Pos[2] <0) Sign = -1.;
00276     else Sign = 1;
00277     Fm[pp].Dir[2] *= Sign;
00278     //printf("%d) Pos %lf Force %lf %lf\n",pp,Pm[pp].Pos[2],Fm[pp].fHel[2],Fm[pp].fExt[2]);
00279   }
00280   return 0;
00281 }
00282 //-----------------------------RIGID-------------------------
00283 void Forces::ForceFieldRigid(){
00284   double Pot[2];
00285   for(int n=0;n<pNNano();n++){
00286     for(int d=0;d<3;d++){
00287       Nano[n].Force[d] = 0.;
00288       Nano[n].AMom[d] = 0.;
00289     }
00290   }
00291   for(int n=0;n<pNNano();n++){
00292     for(int nn=n+1;nn<pNNano();nn++){
00293       double dr[3] = {0.,0.,0.};
00294       double Dist = RigidDistanceAxis(n,nn,dr);
00295       //if( Dist > CutOff ) continue;
00296       double Cons = RigidLJ(n,Dist,Pot,0);
00297       for(int d=0;d<3;d++){
00298    Nano[n].Force[d] -= Cons*dr[d];
00299    Nano[nn].Force[d] += Cons*dr[d];
00300    Nano[n].AMom[d] -= Nano[n].AMomTemp[d]*Cons;
00301    Nano[nn].AMom[d] += Nano[n].AMomTemp[d]*Cons;
00302    //printf("%d %lf %lf\n",d,Cons*dr[d],Nano[nn].AMom[d]);
00303       }
00304     }
00305     for(int d=0;d<3;d++){
00306       double Ran = Nano[n].Zeta * (2.*Mat->Casuale() - 1.);
00307       double Dis = - Nano[n].Gamma*Nano[n].Vel[d];
00308       //Nano->Force[d] += Ran + Dis;
00309     }
00310     //printf("%d %lf %lf %lf\n",n,Nano[n].AMom[0],Nano[n].AMom[1],Nano[n].AMom[2]);
00311   }
00312 }
00313 double Forces::RigidDistanceAxis(int n,int nn,double *dr){
00314   Vettore Pos1(Nano[n].Pos,3);
00315   Vettore Pos2(Nano[nn].Pos,3);
00316   Vettore PosRel(Pos2[0]-Pos1[0],Pos2[1]-Pos1[1],Pos2[2]-Pos1[2]);
00317   Vettore Axis(Nano[n].Axis,3);
00318   Vettore Perp(3);
00319   Vettore AMomTemp(3);
00320   double Dist = Perp.PerpTo(&PosRel,&Axis);
00321   Perp.Export(dr);
00322   AMomTemp.VetV(&Perp,&PosRel);
00323   AMomTemp.Export(Nano[n].AMomTemp);
00324   //AMomTemp.Export(Nano[nn].AMomTemp);
00325   double HeiOnAxis = Perp.ProjOnAxis(&PosRel,&Axis);
00326    if( fabs(HeiOnAxis) > Nano[n].Height*.5){
00327     double Sign = HeiOnAxis > 0 ? 1. : -1.;
00328     Dist = 0.;
00329     for(int d=0;d<3;d++){
00330       dr[d] = Pos2[d] - Pos1[d];
00331       Dist = SQR(dr[d]);
00332     }
00333     Dist = sqrt(Dist);
00334   }
00335   return Dist;
00336 }
00337 void Forces::NanoInteraction(){
00338   double Pot[2];
00339   for(int n=0;n<pNNano();n++){
00340     for(int d=0;d<3;d++){
00341       Nano[n].Force[d] = 0.;
00342       Nano[n].AMom[d] = 0.;
00343     }
00344   }
00345   for(int n=0;n<pNNano();n++){
00346     Point2Shape(Nano[n].Shape);
00347     for(int p=0;p<pNPart();p++){
00348       double dr[3] = {0.,0.,0.};
00349       double Dist2 = NanoDist2(Pm[p].Pos,n);
00350       if( Dist2 > Kf.CutOff2 ) continue;
00351       double Cons = RigidLJ(n,Dist2,Pot,0);
00352       for(int d=0;d<3;d++){
00353    Nano[n].Force[d] -= Cons*dr[d];
00354    Fm[p].Dir[d] += Cons*dr[d];
00355    Nano[n].AMom[d] -= Nano[n].AMomTemp[d]*Cons;
00356       }
00357     }
00358     for(int d=0;d<3;d++){
00359       double Ran = Nano[n].Zeta * (2.*Mat->Casuale() - 1.);
00360       double Dis = - Nano[n].Gamma*Nano[n].Vel[d];
00361       //Nano->Force[d] += Ran + Dis;
00362     }
00363     //printf("%d %lf %lf %lf\n",n,Nano[n].AMom[0],Nano[n].AMom[1],Nano[n].AMom[2]);
00364   }
00365 }
00366 double Forces::NanoNrg(int p){
00367   double Nrg = NanoNrg(pPos(p),pType(p));
00368   return Nrg;
00369 }
00370 double Forces::NanoNrg(double *Pos,int t){
00371   double Pot[2];
00372   double Cons = 0.;
00373   double Nrg = 0.;
00374   for(int n=0;n<pNNano();n++){
00375     Point2Shape(Nano[n].Shape);
00376     double Dist2 = NanoDist2(Pos,n);
00377     if( Dist2 > SQR(Nano[n].CutOff) ) continue;
00378     double Dist = sqrt(Dist2);
00379     double Sign = -1.;
00380     if(t == 1) Sign = 1.;
00381     Cons += RigidHamaker(n,Dist,Pot,Sign);
00382     //Cons += RigidLJ(n,Dist2,Pot,0);
00383     Nrg += Pot[0];
00384   }
00385   Nrg *= Nano->Coating;
00386   return Nrg;
00387 }
00388 void Forces::DefForceParam(){
00389   double Pot[2];
00390   Kf.ForThr = 50.;
00391   Kf.DistThr = 0.;
00392   Potential(Kf.CutOff2,0,0,Pot);
00393   Kf.BaseLine = -Pot[0];
00394   double CutOff = sqrt(Kf.CutOff2);
00395   for(int i=10000;i>0;i--){
00396     double x = CutOff/10000.*i;
00397     double For = Potential(SQR(x),0,0,Pot)/x;
00398     if(For >= Kf.ForThr){
00399       Kf.DistThr = x;
00400       Kf.PotThr = Pot[0];
00401       break;
00402     }
00403   }
00404 }
00405 void Forces::DefNanoForceParam(){
00406   double Pot[2];
00407   for(int n=0;n<pNNano();n++){
00408     Nano[n].ForThr = 50.;
00409     Point2Shape(Nano[n].Shape);
00410     Nano[n].CutOff = Nano[n].Rad*3.;
00411     Nano[n].BaseLine = 0.;
00412     double For =  RigidLJ(n,Nano[n].CutOff,Pot,0);
00413     Nano[n].BaseLine = -Pot[0];
00414     Nano[n].DistThr = 0.;
00415     for(int i=10000;i>0;i--){
00416       double x = (Nano[n].CutOff)/10000.*i;
00417       For = RigidHamaker(n,x,Pot,0);
00418       //For = RigidLJ(n,x,Pot,0);
00419       if(For >= Nano[n].ForThr){
00420    Nano[n].DistThr = x;
00421    Nano[n].PotThr = Pot[0];
00422    break;
00423       }
00424     }
00425     //printf("DefForce %lf %lf %lf\n",Nano[n].DistThr,Nano[n].PotThr,Nano[n].BaseLine);
00426   }
00427 }
00428 double Forces::RigidDistanceRad(int n,int nn,double *dr){
00429   Vettore Pos1(Nano[n].Pos,3);
00430   Vettore Pos2(Nano[nn].Pos,3);
00431   double Dist = 0.;
00432   for(int d=0;d<3;d++){
00433     dr[d] = Pos2[d] - Pos1[d];
00434     Dist += SQR(dr[d]);
00435   }
00436   return sqrt(Dist);
00437 }
00438 double Forces::RigidLJ(int n,double Dist,double *Pot,double Sign){
00439   double Cons = 0.;
00440   double Strength = pow(Nano[n].Coating,9.)*Nano[n].Hamaker;
00441   double Hamaker  = pow(Nano[n].Coating,3.)*Nano[n].Hamaker;
00442   if( Dist <  Nano[n].DistThr){
00443     Pot[0] = Nano[n].PotThr - Nano[n].ForThr*(Dist - Nano[n].DistThr);
00444     Pot[1] = Nano[n].ForThr;
00445     Cons = Nano[n].ForThr;
00446     return Cons;
00447   }
00448   double idr = 1./(Dist-Nano[n].Rad+Nano[n].Coating);
00449   double idr2 = idr*idr;
00450   double idr4 = idr2*idr2;
00451   double idr6 = idr2*idr4;
00452   Pot[0] = idr*idr2*(Strength*idr6   +Sign*Hamaker)+Nano[n].BaseLine;
00453   Cons   = idr4    *(Strength*9.*idr6+Sign*3.*Hamaker);
00454   Pot[1] = idr4    *(Strength*9.*idr6+Sign*3.*Hamaker);
00455   return Cons;
00456 }
00458 double Forces::RigidHamaker(int n,double Dr,double *Pot,double Sign){
00459   double SurfTens = 3.*Nano[n].Hamaker;
00460   double Cons = 0.;
00461   double Sigma  = 1.0;//0.04;
00462   double Slope = 1.00203;
00463   double Intercept = 0.31739;
00464   double Rnp = Nano[n].Rad/Slope-Intercept;
00465   if( Dr <  Nano[n].DistThr){
00466     Pot[0] = Nano[n].PotThr - Nano[n].ForThr*(Dr - Nano[n].DistThr);
00467     Pot[1] = Nano[n].PotThr;
00468     return Nano[n].ForThr;
00469   }
00470   double DrInv  = 1./Dr;
00471   double DrP1 = 1./(Dr+Rnp);
00472   double DrP3 = CUBE(DrP1);
00473   double DrP6 = SQR(DrP3);
00474   double DrP9 = DrP6*DrP3;
00475   double DrM1 = 1./(-Dr+Rnp);
00476   double DrM3 = CUBE(DrM1);
00477   double DrM6 = SQR(DrM3);
00478   double DrM9 = DrM6*DrM3;
00479   double PreRep = Sigma*1./360.*DrInv*SurfTens;
00480   double PreAttr = 1./12.*DrInv*SurfTens;
00481   double Rep = (9.0*Rnp+Dr)*DrP9 - (9.0*Rnp-Dr)*DrM9;
00482   double Attr= (3.0*Rnp+Dr)*DrP3 - (3.0*Rnp-Dr)*DrM3;
00483   double RepP  = -DrP9+9.*(9.*Rnp+Dr)*DrP9*DrP1
00484     -(9.*Rnp+Dr)*DrP9*DrInv;
00485   double RepM  = -DrM9+9.*(9.*Rnp-Dr)*DrM9*DrM1
00486     -(9.*Rnp-Dr)*DrM9*DrInv;
00487   double AttrP = -DrP3+3.*(3.*Rnp+Dr)*DrP3*DrP1
00488     -(3.*Rnp+Dr)*DrP3*DrInv;
00489   double AttrM = -DrM3+3.*(3.*Rnp-Dr)*DrM3*DrM1
00490     -(3.*Rnp-Dr)*DrM3*DrInv;
00491   double RepChem = 9.*DrP9 - (9.*Rnp+Dr)*9.*DrP9*DrP1 
00492     - 9.*DrM9 + 9.*(9.*Rnp-Dr)*DrM9*DrM1;
00493   double AttrChem = 3.*DrP3 - (3.*Rnp+Dr)*3.*DrP3*DrP1 
00494     - 3.*DrM9 + 3.*(3.*Rnp-Dr)*DrM3*DrM1;
00495   Pot[0] = PreRep*Rep + Sign*PreAttr*Attr + Nano[n].BaseLine;
00496   Pot[1] = PreRep*RepChem + Sign*PreAttr*AttrChem;
00497   Cons = PreRep*(RepP+RepM) + Sign*PreAttr*(AttrP+AttrM);
00498   return Cons;
00499 }
00500 double Forces::RigidCoulomb(int n,double Dist,double *Pot,double Sign){
00501   if(Dist < 2.*Nano[n].Rad)
00502     return 300.;
00503   Pot[0] = Sign*Nano[n].Hamaker/(Dist);
00504   return -Sign*Nano[n].Hamaker/SQR(Dist);
00505 }
00506 //----------------------------DEF-FORCES-POTENTIAL-------------
00507 void Forces::PointShape(int iShape){
00508   Point2Shape(iShape);
00509   if(VAR_IF_TYPE(iShape,SHAPE_SPH))
00510     CalcPot = &Forces::LJ39;
00511   if(VAR_IF_TYPE(iShape,SHAPE_CYL))
00512     CalcPot = &Forces::LJ39;
00513   if(VAR_IF_TYPE(iShape,SHAPE_PILL))
00514     CalcPot = &Forces::LJ39;
00515   if(VAR_IF_TYPE(iShape,SHAPE_TILT))
00516     CalcPot = &Forces::LJ39;
00517   if(VAR_IF_TYPE(iShape,SHAPE_WALL))
00518     CalcPot = &Forces::LJ39;
00519   if(VAR_IF_TYPE(iShape,SHAPE_PORE))
00520     CalcPot = &Forces::LJ39;
00521   if(VAR_IF_TYPE(iShape,SHAPE_EXT)) 
00522     CalcPot = &Forces::LJ39;
00523   if(VAR_IF_TYPE(iShape,SHAPE_JANUS))
00524     CalcPot = &Forces::LJ39;
00525   if(VAR_IF_TYPE(iShape,SHAPE_STALK))
00526     CalcPot = &Forces::LJ39;
00527   if(VAR_IF_TYPE(iShape,SHAPE_TIP))
00528     CalcPot = &Forces::LJ39;
00529   if(VAR_IF_TYPE(iShape,SHAPE_TORUS))
00530     CalcPot = &Forces::LJ39;
00531   if(VAR_IF_TYPE(iShape,SHAPE_HARM))
00532     CalcPot = &Forces::LJ39;
00533   if(VAR_IF_TYPE(iShape,SHAPE_UMBR))
00534     CalcPot = &Forces::LJ39;
00535   DefNanoForceParam();
00536 }
00537 double Forces::Harmonic(double Dist2,int t1,int t2,double *Pot){
00538   double Dist = sqrt(Dist2);
00539   double a = Kf.LJ;
00540   double b = -2.*a*Kf.LJMin;
00541   double c = -a*SQR(Kf.LJMin) - b*Kf.LJMin;
00542   Pot[2] = a*Dist2 + b*Dist + c;
00543   double For =  - 2.*a*Dist2 - b*Dist;
00544   if(t1 != t2){
00545     Pot[2] *= -1.;
00546     return -For;
00547   }
00548   //Pot[2] = 0.;
00549   return For;
00550 }
00551 double Forces::LJ39(double Dist2,int t1,int t2,double *Pot){
00552   double idr6 = CUBE(SQR(Kf.LJMin)/Dist2);
00553   double idr3 = CUBE(Kf.LJMin)/(Dist2*sqrt(Dist2));
00554   // if( Dist2 <  Kf.DistThr){
00555   //   Pot[0] = Kf.PotThr - Kf.ForThr*(Dist2 - Kf.DistThr);
00556   //   return Cons = Kf.ForThr;
00557   // }
00558   if(t1 == t2){
00559     Pot[2] = Kf.LJ*idr3*(idr6-1.)+Kf.BaseLine;
00560     return Kf.LJ*idr3*(9.*idr6-3.);
00561   }
00562   else{
00563     Pot[2] = Kf.LJ*idr3*(idr6+1.)+Kf.BaseLine;
00564     return Kf.LJ*idr3*(9.*idr6+3.);
00565   }
00566 }
00567 double Forces::LJPot(double Dist2,int t1,int t2,double *Pot){
00568   double idr6 = CUBE(SQR(Kf.LJMin)/Dist2);
00569   // if( Dist2 <  Kf.DistThr){
00570   //   Pot[0] = Kf.PotThr - Kf.ForThr*(Dist2 - Kf.DistThr);
00571   //   return Kf.ForThr;
00572   // }
00573   if(t1 == t2){
00574     Pot[2] = Kf.LJ*4.*(idr6*idr6-idr6) + Kf.BaseLine;
00575     return Kf.LJ*48.*(idr6*idr6-.5*idr6);
00576   }
00577   else{
00578     Pot[2] = Kf.LJ*4.*(idr6*idr6+idr6) + Kf.BaseLine;
00579     return Kf.LJ*48.*(idr6*idr6+.5*idr6);
00580   }
00581 }
00582 double Forces::StepPot(double Dist2,int t1,int t2,double *Pot){
00583   if(t1 != t2){
00584     Pot[2] = -Kf.LJ;
00585     return -Kf.LJ*sqrt(Dist2/Kf.CutOff2);
00586   }
00587   Pot[2] = Kf.LJ;
00588   return Kf.LJ*sqrt(Dist2/Kf.CutOff2);
00589 }
00590 double Forces::ElectroPot(double Dist2,int t1,int t2,double *Pot){
00591   if(t1 == t2)
00592     Pot[2] =  Kf.Ext/Dist2;
00593   else 
00594     Pot[2] =  -Kf.LJ/Dist2;
00595   return Pot[2];
00596 }
00597 void Forces::CalcForcesDensFunc(){
00598   if(!VAR_IF_TYPE(SysAlloc,ALL_FORCES)){
00599     printf("Forces not allocated\n");
00600     return;
00601   }
00602   int NTabF = 300;
00603   TabForceAlloc(NTabF);
00604   double *Count = (double *)calloc(NTab*pNType()*pNType(),sizeof(double));
00605   ClearDens();
00606   AddDens(0,pNPart());
00607   SumDens(0,pNPart());
00608   double Dist = 0.;
00609   double DistRelBA[4];
00610   double InvCutOff = 1./sqrt(Kf.CutOff2);
00611   for(int p=0;p<pNPart();p++){
00612     for(int d=0;d<3;d++){
00613       Fm[p].Dir[d] = 0.;
00614     }
00615   }
00616   // non bonded
00617   for(int p1=0;p1<pNPart();p1++){
00618     for(Pc->SetCurr(p1);Pc->IfCurr();Pc->NextCurr()){
00619       int p2 = Pc->p2Curr;
00620       if(p2 <= p1) continue;
00621       Pc->Dist2Curr(DistRelBA);
00622       if(DistRelBA[3] > Kf.CutOff2) continue;
00623       double Force = 0.;
00624       double Dist = sqrt(DistRelBA[3]);
00625       for(int t=0;t<pNType();t++){
00626    Force += MInt->Coeff(Pm[p1].Typ,Pm[p2].Typ,t)*(Dens3[p1*pNType()+t]+Dens3[p2*pNType()+t]);
00627       }
00628       Force *= DerWei3(Dist,pWei3Par())*2./3.;
00629       Force += DerWei2(Dist,pWei2Par())*MInt->Coeff(Pm[p1].Typ,Pm[p2].Typ);
00630       Force /= -Dist;
00631       int x = (int)(Dist*InvCutOff*NTab);
00632       if( x < 0 || x >= NTab) continue;
00633       int t = MIN(Pm[p1].Typ,Pm[p2].Typ)*pNType()+MAX(Pm[p1].Typ,Pm[p2].Typ);
00634       FTab[x*pNType()*pNType()+t] += Force;
00635       Count[x*pNType()*pNType()+t] += 1.;
00636       for(int d=0;d<3;d++){
00637    Fm[p1].Dir[d] += Force*DistRelBA[d];
00638    Fm[p2].Dir[d] -= Force*DistRelBA[d];
00639       }
00640     }
00641   }
00642   for(int t=0;t<NTab;t++){
00643     for(int t1=0;t1<pNType();t1++){
00644       for(int t2=0;t2<pNType();t2++){
00645    int tType = MIN(t1,t2)*pNType()+MAX(t1,t2);
00646    double Norm = Count[t*pNType()*pNType()+tType] > 0. ? 1./Count[t*pNType()*pNType()+tType] : 1.;
00647    FTab[t*pNType()*pNType()+tType] *= Norm;
00648       }
00649     }
00650   }
00651   // bonded
00652   double DistRelBC[4];
00653   double Pre[12];
00654   for(int b=0;b<pNBlock();b++){
00655     for(int c=0;c<pNChain(b);c++){
00656       for(int p=c*pNPCh(b);p<(c+1)*pNPCh(b)-1;p++){
00657    TwoPartDist(p+1,p,DistRelBA);
00658    double ForceSp = pkSpr()*(1. - pSprRest()/DistRelBA[3]);
00659    for(int d=0;d<3;d++){
00660      Fm[p].Dir[d] += ForceSp*DistRelBA[d];
00661      Fm[p+1].Dir[d] -= ForceSp*DistRelBA[d];
00662    }
00663    if(p < (c+1)*pNPCh(b)-2){
00664      TwoPartDist(p+2,p+1,DistRelBC);
00665      double CosAngle = 0.;
00666      for(int d=0;d<3;d++){
00667        DistRelBA[d] /= DistRelBA[3];
00668        DistRelBC[d] /= DistRelBC[3];
00669        CosAngle += DistRelBA[d]*DistRelBC[d];
00670      }
00671      double PreFactBA = pkBen()/DistRelBA[3];
00672      double PreFactBC = pkBen()/DistRelBC[3];
00673      for(int d=0;d<3;d++){
00674        Fm[p+0].Dir[d] -= PreFactBA*(DistRelBC[d]-DistRelBA[d]*CosAngle);
00675        Fm[p+1].Dir[d] += PreFactBA*(DistRelBC[d]-DistRelBA[d]*CosAngle);
00676        Fm[p+1].Dir[d] -= PreFactBC*(DistRelBA[d]-DistRelBC[d]*CosAngle);
00677        Fm[p+2].Dir[d] += PreFactBC*(DistRelBA[d]-DistRelBC[d]*CosAngle);
00678      }
00679    }    
00680       }
00681     }
00682   }
00683 }
00684 void Forces::PrintForce(){
00685   double NPoint = 1000.;
00686   FILE *FWrite = fopen("Force.dat","w");
00687   double Pot[2];
00688   double Delta = sqrt(Kf.CutOff2)/NPoint;
00689   double CutOff = sqrt(Kf.CutOff2);
00690   for(double x=Delta;x<CutOff;x+=Delta){
00691     double Cons = LJPot(x,0,0,Pot);
00692     fprintf(FWrite,"%lf %lf %lf\n",x,Cons,*Pot);
00693   }
00694   fclose(FWrite);
00695 }
00696 void Forces::TabForceAlloc(int NTabExt){
00697   NTab = NTabExt;
00698   double Pot[2];
00699   double Delta = sqrt(Kf.CutOff2)/(double)NTab;
00700   double NrgLim = 20.;
00701   FTab = (double *)calloc(NTab*pNType()*pNType(),sizeof(double));
00702   MTab = (double *)calloc(NTab,sizeof(double));
00703   PTab = (double *)calloc(NTab*pNType()*pNType(),sizeof(double));
00704   VAR_ADD_TYPE(DynFlag,ALL_FORCES);
00705 }
00706 void Forces::TabPot(){
00707   NTab = 10000;
00708   double NrgLim = 10.;
00709   double Delta = 2.*NrgLim/(double)NTab;
00710   int i = 0;
00711   for(double Nrg=-NrgLim;Nrg<NrgLim;Nrg+=Delta,i++){
00712     PTab[i] = Nrg;
00713     MTab[i] = exp(-pTemp()*Nrg);
00714   }
00715   VAR_ADD_TYPE(DynFlag,ALL_METR);
00716   VAR_ADD_TYPE(DynFlag,ALL_POT);
00717 }
00718 double Forces::Wei3(const double r, const double b){
00719   if(r < 0.0001) return 0.;
00720   return (r < b) ? 15. / (2. * M_PI * CUBE(b)) * SQR(1. - r / b) : 0.;
00721 }
00722 double Forces::DerWei3(const double r, const double b){
00723   if(r < 0.0001) return 0.;
00724   return (r < b) ? 15. / (M_PI * SQR(SQR(b))) * (r / b - 1.) : 0.;
00725 }
00726 double Forces::Wei2(const double r, const double a){
00727   if(r < 0.0001) return 0.;
00728   const double b = 1.;
00729   double Ai = .5 * 15. / M_PI / (CUBE(a) + CUBE(a + b) + CUBE(b));
00730   return (r < a) ? Ai : (Ai / CUBE(a - b)) *
00731     ((((-2. * r) + 3. * (a + b)) * r - 6. * a * b) * r +
00732      3. * a * b * b - b * b * b);
00733 }
00734 double Forces::DerWei2(const double r, const double a){
00735   if(r < 0.0001) return 0.;
00736  const double b = 1.;
00737   double Ai = 15. / (M_PI * (((((4. * a) + 6.) * a) + 6.) * a + 4.));
00738   return (r > a && r < b) ? (6. * Ai / CUBE(a - b) * (-r * r + (a + b) *
00739                         r - a * b)) : 0.; 
00740 }