Allink
v0.1
|
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