Allink  v0.1
ForcesTens.cpp
00001 #include "Forces.h"
00002 void Forces::AllocTens(){
00003   if(VAR_IF_TYPE(SysAlloc,ALL_TENS)) return;
00004   for(int d=0;d<3;d++){
00005     Tens.RefPos[d] = pNanoPos(0,d);//.5*pEdge(d);
00006   }
00007   Tens.Pre = (double **)calloc(Tens.NComp,sizeof(double));
00008   Tens.Dens = (double **)calloc(2,sizeof(double));
00009   //   2d
00010   if(VAR_IF_TYPE(Tens.CalcMode,CALC_2d)){
00011     Tens_Ref = &Forces::TensRefPol;
00012     SetEdge(.5*MIN(pEdge(CLat1),pEdge(CLat2)),3);
00013     Tens.Edge[0] = pEdge(3);
00014     Tens.Edge[1] = pEdge(CNorm);
00015     Tens.Edge[2] = 1.;
00016     Tens.Wrap[0] = 0;
00017     Tens.Wrap[1] = 1;
00018     for(int d=0;d<3;d++){
00019       Tens.EdgeInv[d] = 1./Tens.Edge[d];
00020     }
00021     for(int c=0;c<Tens.NComp;c++){
00022       Tens.Pre[c] = (double *)calloc(SQR(Tens.NSlab),sizeof(double));
00023     }
00024     for(int c=0;c<2;c++){
00025       Tens.Dens[c] = (double *)calloc(SQR(Tens.NSlab),sizeof(double));
00026     }
00027   }
00028   //  3d
00029   if(VAR_IF_TYPE(Tens.CalcMode,CALC_3d)){
00030     Tens_Ref = &Forces::TensRefCart;
00031     for(int d=0;d<3;d++){
00032       Tens.Edge[d] = pEdge(d);
00033       Tens.Wrap[d] = 1;
00034       Tens.EdgeInv[d] = pInvEdge(d);
00035     }
00036     for(int c=0;c<Tens.NComp;c++){
00037       Tens.Pre[c] = (double *)calloc(CUBE(Tens.NSlab),sizeof(double));
00038     }
00039     for(int c=0;c<2;c++){
00040       Tens.Dens[c] = (double *)calloc(CUBE(Tens.NSlab),sizeof(double));
00041     }
00042   }
00043   VAR_ADD_TYPE(SysAlloc,ALL_TENS);
00044 }
00045 void Forces::CalcDens(){
00046   // 3d
00047   if(VAR_IF_TYPE(Tens.CalcMode,CALC_3d)){
00048     double PosRel[3];
00049     for(int p=0;p<pNPart();p++){
00050       for(int d=0;d<3;d++){
00051    PosRel[d] = pPos(p,d) - (pEdge(d)*.5 - Tens.RefPos[d]);
00052    PosRel[d] -= floor(PosRel[d]*pInvEdge(d))*pEdge(d);
00053       }
00054       int sx = (int)(PosRel[0]*pInvEdge(0)*Tens.NSlab);
00055       int sy = (int)(PosRel[1]*pInvEdge(1)*Tens.NSlab);
00056       int sz = (int)(PosRel[2]*pInvEdge(2)*Tens.NSlab);
00057       int v = (sx*Tens.NSlab+sy)*Tens.NSlab+sz;
00058       int t = pType(p);
00059       if(t > 1) continue;
00060       Tens.Dens[t][v] += 1.;
00061     }
00062   }
00063   // 2d
00064   else if(VAR_IF_TYPE(Tens.CalcMode,CALC_2d)){
00065     double PosRel[3];
00066     for(int p=0;p<pNPart();p++){
00067       PosRel[CLat1] = pPos(p,CLat1) - Tens.RefPos[CLat1];
00068       PosRel[CLat2] = pPos(p,CLat2) - Tens.RefPos[CLat2];
00069       PosRel[CNorm] = pPos(p,CNorm) + (pEdge(CNorm)*.5 - Tens.RefPos[CNorm]);
00070       for(int d=0;d<3;d++){
00071    PosRel[d] -= floor(PosRel[d]*pInvEdge(d))*pEdge(d);
00072       }
00073       int sr = (int)(hypot(PosRel[CLat1],PosRel[CLat2])*Tens.EdgeInv[0]*Tens.NSlab);
00074       int sz = (int)(PosRel[CNorm]*pInvEdge(CNorm)*Tens.NSlab);
00075       if(sr < 0 || sr >= Tens.NSlab) continue;
00076       if(sz < 0 || sz >= Tens.NSlab) continue;
00077       int v = (sr*Tens.NSlab+sz);
00078       int t = pType(p);
00079       if(t > 1) continue;
00080       Tens.Dens[t][v] += 1.;
00081       //printf("%d %d %d %lf\n",sr,sz,v,Tens.Dens[t][v]);
00082     }
00083   }
00084 }
00085 void Forces::CalcTens(){
00086   if(!VAR_IF_TYPE(SysAlloc,ALL_FORCES)){
00087     printf("Forces not allocated\n");
00088     return;
00089   }
00090   ClearDens();
00091   AddDens(0,pNPart());
00092   SumDens(0,pNPart());
00093   double Dist = 0.;
00094   double DistRelBA[4];
00095   for(int p=0;p<pNPart();p++){
00096     for(int d=0;d<3;d++){
00097       Fm[p].Dir[d] = 0.;
00098     }
00099   }
00100   // non bonded
00101   double Pos[3];
00102   for(int p1=0;p1<pNPart();p1++){
00103     for(Pc->SetCurr(p1);Pc->IfCurr();Pc->NextCurr()){
00104       int p2 = Pc->p2Curr;
00105       if(p2 <= p1) continue;
00106       Pc->Dist2Curr(DistRelBA);
00107       if(DistRelBA[3] > Kf.CutOff2) continue;
00108       double Dist = sqrt(DistRelBA[3]);
00109       double Force = 0.;
00110       for(int t=0;t<pNType();t++){
00111    Force += MInt->Coeff(pType(p1),pType(p2),t)*(Dens3[p1*pNType()+t]+Dens3[p2*pNType()+t]);
00112       }
00113       Force *= DerWei3(Dist,pWei3Par())*2./3.;
00114       Force += DerWei2(Dist,pWei2Par())*MInt->Coeff(pType(p1),pType(p2));
00115       SumTens(p1,p2,Force,DistRelBA);
00116       Force /= -Dist;
00117       SigErr(Force > 5000.,"Forces over the limit %lf\n",Force);
00118       for(int d=0;d<3;d++){
00119    Fm[p1].Dir[d] += Force*DistRelBA[d];
00120    Fm[p2].Dir[d] -= Force*DistRelBA[d];
00121       }
00122     }
00123   }
00124   // bonded
00125   double DistRelBC[4];
00126   double Pre[12];
00127   for(int b=0;b<pNBlock();b++){
00128     for(int c=0;c<pNChain(b);c++){
00129       for(int p=c*pNPCh(b);p<(c+1)*pNPCh(b)-1;p++){
00130    TwoPartDist(p+1,p,DistRelBA);
00131    double ForceSp = pkSpr()*(1. - pSprRest()/DistRelBA[3]);
00132    SumTens(p,p+1,ForceSp,DistRelBA);
00133    for(int d=0;d<3;d++){
00134      Fm[p].Dir[d] += ForceSp*DistRelBA[d];
00135      Fm[p+1].Dir[d] -= ForceSp*DistRelBA[d];
00136    }
00137    if(p < (c+1)*pNPCh(b)-2){
00138      TwoPartDist(p+2,p+1,DistRelBC);
00139      double CosAngle = 0.;
00140      for(int d=0;d<3;d++){
00141        DistRelBA[d] /= DistRelBA[3];
00142        DistRelBC[d] /= DistRelBC[3];
00143        CosAngle += DistRelBA[d]*DistRelBC[d];
00144      }
00145      double PreFactBA = pkBen()/DistRelBA[3];
00146      double PreFactBC = pkBen()/DistRelBC[3];
00147      for(int d=0;d<3;d++){
00148        Fm[p+0].Dir[d] += PreFactBA*(DistRelBC[d]-DistRelBA[d]*CosAngle);
00149        Fm[p+1].Dir[d] -= PreFactBA*(DistRelBC[d]-DistRelBA[d]*CosAngle);
00150        Fm[p+1].Dir[d] += PreFactBC*(DistRelBA[d]-DistRelBC[d]*CosAngle);
00151        Fm[p+2].Dir[d] -= PreFactBC*(DistRelBA[d]-DistRelBC[d]*CosAngle);
00152        Pre[d  ] = DistRelBA[d]*pkBen()*(DistRelBC[d]-DistRelBA[d]*CosAngle);
00153        Pre[d+6] = DistRelBC[d]*pkBen()*(DistRelBA[d]-DistRelBC[d]*CosAngle);
00154      }
00155      Pre[ 3] = DistRelBA[0]*pkBen()*(DistRelBC[1]-DistRelBA[1]*CosAngle);
00156      Pre[ 4] = DistRelBA[0]*pkBen()*(DistRelBC[2]-DistRelBA[2]*CosAngle);
00157      Pre[ 5] = DistRelBA[1]*pkBen()*(DistRelBC[2]-DistRelBA[2]*CosAngle);
00158      Pre[ 9] = DistRelBC[0]*pkBen()*(DistRelBA[1]-DistRelBC[1]*CosAngle);
00159      Pre[10] = DistRelBC[0]*pkBen()*(DistRelBA[2]-DistRelBC[2]*CosAngle);
00160      Pre[11] = DistRelBC[1]*pkBen()*(DistRelBA[2]-DistRelBC[2]*CosAngle);
00161      SumTens(p,p+1,Pre);
00162      SumTens(p+1,p+2,Pre+6);
00163    }
00164       }
00165     }
00166   }
00167   return;
00168   //external
00169   double Pot[3];
00170   double PosBf[3];
00171   double dr[4];
00172   double NPos[3];
00173   for(int n=0;n<pNNano();n++){
00174     Point2Shape(Nano[n].Shape);
00175     for(int p=0;p<pNPart();p++){
00176       pPos(p,Pos);
00177       double Dr2 = NanoDist2(Pos,n);
00178       double InvDist = 1./Dr2;
00179       double Cons = Potential(Dr2,0,pType(p),Pot);
00180       for(int d=0;d<3;d++){
00181    dr[d] = Nano[n].Pos[d] - pPos(p,d);
00182    if(dr[d] >  .5*pInvEdge(d)) dr[d] -= pEdge(d);
00183    if(dr[d] < -.5*pInvEdge(d)) dr[d] += pEdge(d);
00184       }
00185       double Norm = SQR(Nano[n].Rad)/(SQR(dr[0]) + SQR(dr[1]) + SQR(dr[2]));
00186       Norm = sqrt(Norm);
00187       for(int d=0;d<3;d++){
00188    NPos[d] = NPos[d] + dr[d]*Norm;
00189    Fm[p].Dir[d] += Cons*dr[d]*InvDist;
00190    Pre[d  ] = Cons*dr[d]*dr[d]*InvDist;
00191       }
00192       Pre[3] = Cons*dr[0]*dr[1]*InvDist;
00193       Pre[4] = Cons*dr[0]*dr[2]*InvDist;
00194       Pre[5] = Cons*dr[1]*dr[2]*InvDist;
00195       SumTens(NPos,Pos,Pre);
00196     }
00197   }
00198 }
00199 double Forces::TensRefCart(double *Pos1,double *Pos2,double *PosP1,double *PosP2){
00200   for(int d=0;d<3;d++){
00201     PosP1[d] = Pos1[d] - (pEdge(d)*.5 - Tens.RefPos[d]);
00202     PosP2[d] = Pos2[d] - (pEdge(d)*.5 - Tens.RefPos[d]);
00203     PosP1[d] -= floor(PosP1[d]*pInvEdge(d))*pEdge(d);
00204     PosP2[d] -= floor(PosP2[d]*pInvEdge(d))*pEdge(d);
00205   }
00206 }
00207 double Forces::TensRefPol(double *PosO1,double *PosO2,double *PosP1,double *PosP2){
00208   double Pos1[2] = {PosO1[CLat1]-Tens.RefPos[CLat1],PosO1[CLat2]-Tens.RefPos[CLat2]};
00209   double Pos2[2] = {PosO2[CLat1]-Tens.RefPos[CLat1],PosO2[CLat2]-Tens.RefPos[CLat2]};
00210   for(int d=0;d<2;d++){
00211     Pos1[d] -= floor(Pos1[d]*pInvEdge(d) + .5)*pEdge(d);
00212     Pos2[d] -= floor(Pos2[d]*pInvEdge(d) + .5)*pEdge(d);
00213   }
00214   PosP1[0] = hypot(Pos1[0],Pos1[1]);
00215   PosP2[0] = hypot(Pos2[0],Pos2[1]);
00216   PosP1[1] = PosO1[CNorm] + (pEdge(CNorm)*.5 - Tens.RefPos[CNorm]);
00217   PosP2[1] = PosO2[CNorm] + (pEdge(CNorm)*.5 - Tens.RefPos[CNorm]);
00218   for(int d=1;d<2;d++){
00219     PosP1[d] -= floor(PosP1[d]*Tens.EdgeInv[d])*Tens.Edge[d];
00220     PosP2[d] -= floor(PosP2[d]*Tens.EdgeInv[d])*Tens.Edge[d];
00221   }
00222   //printf("%d %d %lf %lf %lf %lf \n",p1,p2,PosP1[0],PosP1[1],PosP2[0],PosP2[0]);
00223 }
00224 void Forces::SumTens(int p1,int p2,double *Pre){
00225   SumTens(Pm[p1].Pos,Pm[p2].Pos,Pre);
00226 }
00227 void Forces::SumTens(double *Pos1,double *Pos2,double *Pre){
00228   double PosP1[3];
00229   double PosP2[3];
00230   TensRef(Pos1,Pos2,PosP1,PosP2);
00231   int NPoint = 100;
00232   double PointInv = 1./(double)NPoint;
00233   double Deltav[3];
00234   double Pos[3];
00235   int vCurr[3];
00236   for(int d=0;d<Tens.NDim;d++){
00237     // starts from the smallest position
00238     Pos[d] = PosP1[d] < PosP2[d] ? PosP1[d] : PosP2[d];
00239     Deltav[d] = fabs((PosP2[d]-PosP1[d])*PointInv);
00240     // forward/backward?
00241     if( fabs(PosP2[d] - PosP1[d]) > Tens.Edge[d]*.5){
00242       Deltav[d] = -fabs((MAX(PosP1[d],PosP2[d])-Tens.Edge[d]-Pos[d])*PointInv);
00243     }
00244   }
00245   //printf("%d %d) [%lf %lf] [%lf %lf] (%lf %lf) (%lf %lf)\n",p1,p2,PosP1[0],PosP1[1],PosP2[0],PosP2[1],Deltav[0],Deltav[1],Tens.Edge[0],Tens.Edge[1]);
00246   for(int p=0;p<NPoint;p++){
00247     for(int d=0;d<Tens.NDim;d++){
00248       vCurr[d] = (int)(Pos[d]*Tens.NSlab*Tens.EdgeInv[d]);
00249       //assert(vCurr[d] >= 0 && vCurr[d] < Tens.NSlab);
00250       if(vCurr[d] < 0 || vCurr[d] >= Tens.NSlab) return;
00251       // update the current position forward/backward
00252       Pos[d] += Deltav[d];
00253       // wrap the position to the other end
00254       if(Pos[d] > Tens.Edge[d]){
00255    if(!Tens.Wrap[d]) return;
00256    Pos[d] -= floor(Pos[d]*Tens.EdgeInv[d])*Tens.Edge[d];
00257       }
00258     }
00259     int vTot = 0;
00260     for(int d=0;d<Tens.NDim;d++){
00261       vTot += vCurr[d];
00262       if(d < Tens.NDim-1)
00263    vTot *= Tens.NSlab;
00264     }
00265     //printf("%d %d %d (%lf %lf) %lf\n",vCurr[0],vCurr[1],vTot,Pos[0],Pos[1],Pre[0]);
00266     for(int c=0;c<Tens.NComp;c++){
00267       Tens.Pre[c][vTot] += Pre[c]*PointInv;
00268     }
00269   }
00270 }
00271 void Forces::SumTens(int p1,int p2,double Force,double *DistRel){
00272   if(fabs(Force) < 0.) return;
00273   if(fabs(Force) > 5000.) return;
00274   double Pre[6];
00275   double InvDist = Force/DistRel[3];
00276   Pre[0] = DistRel[0]*DistRel[0]*InvDist;
00277   Pre[1] = DistRel[1]*DistRel[1]*InvDist;
00278   Pre[2] = DistRel[2]*DistRel[2]*InvDist;
00279   Pre[3] = DistRel[0]*DistRel[1]*InvDist;
00280   Pre[4] = DistRel[0]*DistRel[2]*InvDist;
00281   Pre[5] = DistRel[1]*DistRel[2]*InvDist;
00282   SumTens(p1,p2,Pre);
00283 }
00284 void Forces::WriteTens2d(FILE *FWrite,int Comp,double InvNFile){
00285   int link[4] = {0,0,0,0};
00286   fprintf(FWrite,"# l(%.1f %.1f %.1f) r(%.2f %.2f %.2f) v[%d] d[color]\n",Tens.Edge[0],Tens.Edge[1],1.,Tens.RefPos[0],Tens.RefPos[1],Tens.RefPos[2],Tens.NSlab);
00287   double *VolContr = (double *)calloc(Tens.NSlab,sizeof(double));
00288   VolumeCircSlab(VolContr,Tens.NSlab);
00289   for(int sr=1,p=0,c=0;sr<Tens.NSlab;sr++){
00290     double r = sr*Tens.Edge[0]/(double)Tens.NSlab;
00291     for(int sz=0;sz<Tens.NSlab;sz++){
00292       double z = sz*Tens.Edge[1]/(double)Tens.NSlab;
00293       int v = sr*Tens.NSlab+sz;
00294       if(Tens.Dens[0][v] <= 0. && Tens.Dens[1][v] <= 0. && fabs(Tens.Pre[Comp][v]) <= 0.) continue;
00295       double Press = -Tens.Pre[Comp][v]*InvNFile/VolContr[sr];
00296       double Dens1 = Tens.Dens[0][v]*InvNFile/VolContr[sr];
00297       double Dens2 = Tens.Dens[1][v]*InvNFile/VolContr[sr];
00298       fprintf(FWrite,"{x(%.3f %.3f %.3f) v( %lf %.2f %.2f)}\n",r,z,0.,Press,Dens1,Dens2);continue;
00299       link[0] = (sr+0)*Tens.NSlab+(sz+0);
00300       link[1] = (sr+0)*Tens.NSlab+(sz+1);
00301       link[2] = (sr+1)*Tens.NSlab+(sz+0);
00302       link[3] = (sr+1)*Tens.NSlab+(sz+1);
00303       for(int lx=0;lx<2;lx++){
00304          for(int ly=0;ly<2;ly++){
00305            int l = 2*lx+ly;
00306            int l1 = p + (p+1)%4;
00307            int l2 = p + (p+2)%4;
00308            int l3 = p + (p+3)%4;
00309            fprintf(FWrite,"{t[%d %d %d]",p,c,0);
00310            fprintf(FWrite," x(%.3f %.3f %.3f)",r,z,Press);
00311            fprintf(FWrite," v( %lf %.2f %.2f)",Press,Dens1,Dens2);
00312               // -Tens.Pre[Comp][v]*InvNFile,
00313               // Tens.Dens[0][v]*InvNFile,
00314               // Tens.Dens[1][v]*InvNFile);  
00315            fprintf(FWrite," l[%d] l[%d] l[%d]}\n",l1,l2,l3);
00316            p++;
00317          }
00318       }
00319       c++;
00320     }
00321   }
00322   //free(VolContr);
00323 }
00324 void Forces::WriteTens(char *FTens,int Comp,double InvNFile){
00325   double InvValues = 1. / Tens.NSlab;
00326   double InvVolume = prho()*CUBE(Tens.NSlab)/pVol();
00327   if(VAR_IF_TYPE(Tens.CalcMode,CALC_2d)){
00328 #ifdef OMPI_MPI_H
00329   MPI_Allreduce(MPI_IN_PLACE,Tens.Pre[Comp],SQR(Tens.NSlab),MPI_DOUBLE,MPI_SUM,Proc->CommGrid);  
00330   for(int t=0;t<2;t++){
00331     MPI_Allreduce(MPI_IN_PLACE,Tens.Dens[t],SQR(Tens.NSlab),MPI_DOUBLE,MPI_SUM,Proc->CommGrid);
00332   }
00333  int Rank=0;
00334   MPI_Comm_rank(Proc->CommGrid, &Rank);
00335   if(Rank==0){
00336 #endif
00337     FILE *FWrite = fopen(FTens,"w");
00338     WriteTens2d(FWrite,Comp,InvNFile);
00339     fclose(FWrite);
00340     for(int s=0;s<SQR(Tens.NSlab);s++){
00341       Tens.Pre[Comp][s] = 0.;
00342       Tens.Dens[0][s] = 0.;
00343       Tens.Dens[1][s] = 0.;      
00344     }
00345     #ifdef OMPI_MPI_H
00346         }
00347     #endif
00348   }
00349   if(VAR_IF_TYPE(Tens.CalcMode,CALC_3d)){
00350 #ifdef OMPI_MPI_H
00351     MPI_Allreduce(MPI_IN_PLACE,Tens.Pre[Comp],CUB(Tens.NSlab),MPI_DOUBLE,MPI_SUM,Proc->CommGrid);  
00352     for(int t=0;t<2;t++){
00353       MPI_Allreduce(MPI_IN_PLACE,Tens.Dens[t],CUB(Tens.NSlab),MPI_DOUBLE,MPI_SUM,Proc->CommGrid);
00354     }
00355     int Rank=0;
00356     MPI_Comm_rank(Proc->CommGrid, &Rank);
00357     if(Rank==0){
00358 #endif
00359     FILE *FWrite = fopen(FTens,"w");
00360     fprintf(FWrite,"# l(%.1f %.1f %.1f) r(%.2f %.2f %.2f) v[%d] d[color]\n",pEdge(0),pEdge(1),pEdge(2),Tens.RefPos[0],Tens.RefPos[1],Tens.RefPos[2],Tens.NSlab);
00361     for(int sx=0;sx<Tens.NSlab;sx++){
00362       double x = sx*InvValues*pEdge(CLat1);
00363       for(int sy=0;sy<Tens.NSlab;sy++){
00364    double y = sy*InvValues*pEdge(CLat2);
00365    for(int sz=0;sz<Tens.NSlab;sz++){
00366      double z = sz*InvValues*pEdge(CNorm);
00367      int v = (sx*Tens.NSlab+sy)*Tens.NSlab+sz;
00368      if(Tens.Dens[0][v] <= 0 && Tens.Dens[1][v] <= 0 && ABS(Tens.Pre[Comp][v]) <= 0) continue;
00369      fprintf(FWrite,"{x(%.3f %.3f %.3f)",x,y,z);
00370      fprintf(FWrite," v( %lf %.2f %.2f)}\n",
00371         -Tens.Pre[Comp][v]*InvNFile*InvVolume,
00372           Tens.Dens[0][v]*InvNFile*InvVolume,
00373         Tens.Dens[1][v]*InvNFile*InvVolume);
00374    }
00375       }
00376     }
00377     fclose(FWrite);
00378     for(int s=0;s<CUB(Tens.NSlab);s++){
00379       Tens.Pre[Comp][s] = 0.;
00380       Tens.Dens[0][s] = 0.;
00381       Tens.Dens[1][s] = 0.;      
00382     }
00383   }
00384 #ifdef OMPI_MPI_H
00385   }
00386 #endif
00387 }
00388