int main() { { CD cxy( CD(2) * CD(3) ); check( test() == cxy, __LINE__ ); } _PASS; }
CD test() { CD x(2); CD y(3); CD cxy(2*3); CD xy = x * y; check( xy == cxy, __LINE__ ); xy = x * 3; check( xy == cxy, __LINE__ ); xy = 2 * y; check( xy == cxy, __LINE__ ); xy = x * y; check( xy == cxy, __LINE__ ); return xy; }
void CouplerWakeFieldProcess::CalculateWakeT() { // This routine is rather cpu intensive. // First, calculate the transverse centroid of // each bunch slice by taking the mean of the // particle positions vector<Point2D> xyc; xyc.reserve(nbins+1); size_t i; for(i=0; i<nbins; i++) { xyc.push_back(GetSliceCentroid(bunchSlices[i],bunchSlices[i+1])); } xyc.push_back(xyc.back()); // Now estimate the transverse bunch wake at the slice // boundaries in the same way we did for the longitudinal wake. double a0 = dz*(fabs(currentBunch->GetTotalCharge()))*ElectronCharge*Volt; wake_x = vector<double>(bunchSlices.size(),0.0); wake_y = vector<double>(bunchSlices.size(),0.0); // a0=dz*Qtot*ElectronCharge*Volt // volt=1.0e-9 (std unit is GeV) ElectronCharge=1.60219e-19C // wake field unit V/C // zmin = -nsig*sigz+z0;zmax = nsig*sigz+z0;dz = (zmax-zmin)/nbins; for(i=0; i<bunchSlices.size(); i++) { Vector2D cxy(0,0); if(i<bunchSlices.size()-1) { // coupler wake kick (const, independent of z) at x[m],y[m] // cxy [V/m] cxy = currentWake->Wxy(xyc[i].x,xyc[i].y); // RF kick independent of bunch charge // x[m],y[m],V[m]=Vacc // phase[rad]=phi+k*dz, dz[m] // rfxy [1/cavity], V [GeV] Vector2D rfxy = currentWake->CouplerRFKick(xyc[i].x,xyc[i].y,fabs(phi)+k*(zmin+(i+0.5)*dz)); // = currentWake->CouplerRFKick(xyc[i].x,xyc[i].y,fabs(phi)); wake_x[i] += rfxy.x*V/clen/a0; // V[GeV] -> V[V] wake_y[i] += rfxy.y*V/clen/a0; } for(size_t j=i; j<bunchSlices.size()-1; j++) { // cavity transverse wake // kick goes into the same direction as offset // dx>0 => dx'>0 double wxy = Qd[j]*(currentWake->Wtrans((j-i+0.5)*dz)); wake_x[i] += wxy*xyc[j].x; wake_y[i] += wxy*xyc[j].y; // coupler kick assumed to be constant (short bunch) wake_x[i] += Qd[j]*cxy.x/clen; wake_y[i] += Qd[j]*cxy.y/clen; } wake_x[i]*=a0; wake_y[i]*=a0; } }
void choosePair(double* D,int n,double* R,int* s, int* sw, int* x, int* y, int fS) { int i=0,j=0,k=0; int sww=0; double cFS[fS]; int iFS[fS]; int jFS[fS]; for(k=0;k<fS;k++) {cFS[k]=-1e50; iFS[k]=0; jFS[k]=0; } double max=-1e50; for (i = 1; i < n; i++) { for (j = i + 1; j <= n; j++) {if(D[give_index(i,j,n)]==-1){sww=1;continue;} if(s[give_index(i,j,n)]<=2)continue; //Rprintf("R[%i,%i]=%f\n",i,j,R[give_index(i,j,n)]); //Rprintf("s[%i,%i]=%i\n",i,j,s[give_index(i,j,n)]); //Rprintf("D[%i,%i]=%f\n",i,j,D[give_index(i,j,n)]); int tr=0; double numb=((R[give_index(i,j,n)])/(s[give_index(i,j,n)]-2))-D[give_index(i,j,n)]; //Rprintf("numb(%i,%i)=%f\n",i,j,numb); for(k=0;k<fS && cFS[k]>numb;k++); //Rprintf("k=%i ",k); for(tr=fS-1;tr>k;tr--) {cFS[tr]=cFS[tr-1]; iFS[tr]=iFS[tr-1]; jFS[tr]=jFS[tr-1]; } if(k<fS){cFS[k]=numb; iFS[k]=i; jFS[k]=j; } } } //no missing distances, just return the one with maximal Q-criterion if(sww==0){*x=iFS[0];*y=jFS[0];*sw=0;return; } /*for(k=0;k<fS;k++) {Rprintf("value[%i]=%f ",k,cFS[k]); Rprintf("i=%i ",iFS[k]); Rprintf("j=%i ",jFS[k]); Rprintf("\n"); }*/ //calculate N*(x,y) for(i=0;i<fS;i++) { if(iFS[i]==0 || jFS[i]==0)continue; double nb=nxy(iFS[i],jFS[i],n,D); if(nb>max){max=nb;} cFS[i]=nb; } /*Rprintf("all N*(x,y)\n"); for(k=0;k<fS;k++) {Rprintf("value[%i]=%f ",k,cFS[k]); Rprintf("i=%i ",iFS[k]); Rprintf("j=%i ",jFS[k]); Rprintf("\n"); }*/ int dk=0; //shift the max N*xy to the front of the array for(i=0;i<fS;i++) { if(cFS[i]==max) { cFS[dk]=cFS[i]; iFS[dk]=iFS[i]; jFS[dk]=jFS[i]; dk++; } } //if just one pair realises max N*xy, return it if(dk==1){*x=iFS[0];*y=jFS[0];return;} fS=dk; /*Rprintf("max n*xy values\n"); for(k=0;k<fS;k++) {Rprintf("value[%i]=%f ",k,cFS[k]); Rprintf("i=%i ",iFS[k]); Rprintf("j=%i ",jFS[k]); Rprintf("\n"); }*/ max=-1e50; //on the front of the array containing max N*xy values compute cxy for(i=0;i<fS;i++) { if(iFS[i]==0 || jFS[i]==0)continue; double nb=cxy(iFS[i],jFS[i],n,D); if(nb>max){max=nb;} cFS[i]=nb; } /*Rprintf("all c*xy values\n"); for(k=0;k<fS;k++) {Rprintf("value[%i]=%f ",k,cFS[k]); Rprintf("i=%i ",iFS[k]); Rprintf("j=%i ",jFS[k]); Rprintf("\n"); }*/ //and again shift maximal C*xy values at the fron of the array dk=0; for(i=0;i<fS;i++) { if(cFS[i]==max) { cFS[dk]=cFS[i]; iFS[dk]=iFS[i]; jFS[dk]=jFS[i]; dk++; } } //if just one C*xy with maximal value, return pair realising it if(dk==1){*x=iFS[0];*y=jFS[0];return;} fS=dk; /*Rprintf("max c*xy values\n"); for(k=0;k<fS;k++) {Rprintf("value[%i]=%f ",k,cFS[k]); Rprintf("i=%i ",iFS[k]); Rprintf("j=%i ",jFS[k]); Rprintf("\n"); }*/ max=-1e50; //on the front of the array containing max C*xy compute m*xy for(i=0;i<fS;i++) { if(iFS[i]==0 || jFS[i]==0)continue; double nb=mxy(iFS[i],jFS[i],n,D); if(nb>max){max=nb;} cFS[i]=nb; } /*Rprintf("all m*xy values\n"); for(k=0;k<fS;k++) {Rprintf("value[%i]=%f ",k,cFS[k]); Rprintf("i=%i ",iFS[k]); Rprintf("j=%i ",jFS[k]); Rprintf("\n"); }*/ //again shift maximal m*xy values to the fron of the array dk=0; for(i=0;i<fS;i++) { if(cFS[i]==max) { cFS[dk]=cFS[i]; iFS[dk]=iFS[i]; jFS[dk]=jFS[i]; dk++; } } //if just one maximal value for m*xy return the pair realising it, found at 0 if(dk==1){*x=iFS[0];*y=jFS[0];return;} fS=dk; /*Rprintf("max m*xy values\n"); for(k=0;k<fS;k++) {Rprintf("value[%i]=%f ",k,cFS[k]); Rprintf("i=%i ",iFS[k]); Rprintf("j=%i ",jFS[k]); Rprintf("\n"); }*/ //and calculate cnxy on these values, but this time we do not shift, but simply //return the pair realising the maximum, stored at iPos max=-1e50; int iPos=0; for(i=0;i<fS;i++) { if(iFS[i]==0 || jFS[i]==0)continue; double nb=cnxy(iFS[i],jFS[i],n,D); if(nb>max){max=nb;iPos=i;} cFS[i]=nb; } /*Rprintf("cN*xy\n"); Rprintf("value[%i]=%f ",0,cFS[0]); Rprintf("i=%i ",iFS[0]); Rprintf("j=%i ",jFS[0]); Rprintf("\n");*/ if(iFS[iPos]==0 || jFS[iPos]==0) { error("distance information insufficient to construct a tree, cannot calculate agglomeration criterion"); } *x=iFS[iPos];*y=jFS[iPos]; }