int MakeBoxDomains(const Box &box,int nproc, int nx, int ny, int nz, inp_it result){ int ndir[3]={nx,ny,nz}, nspl[3]={nx,ny,nz}; int np=(nproc>0 ? nproc : -nproc); int startdir=2; int dd, curdir=-1; // getting minimal splits int nauto=0, autod[3]={-1, -1, -1}, ndef=0; for(dd=0;dd<3;dd++){ int dir=(dd+startdir)%3; if(ndir[dir]>0 && ndir[dir]>curdir)curdir=dir; else if(ndir[dir]<0){ autod[nauto++]=dir; } if(ndir[dir]==0)ndef++; } if(curdir<0 && nauto>0){ if(nauto==1){ ndir[autod[0]]=np; curdir=autod[0]; } else{ // auto-finding direction and number of slices to split int i; vec_type lprod=1.; for(i=0;i<nauto;i++){ lprod*=box.GetSize()[autod[i]]; } vec_type k=pow((vec_type)np/lprod,vec_type(1)/vec_type(nauto)); int mnp=0, mdir=0; for(i=0;i<nauto;i++){ int tnp=(int)(box.GetSize()[autod[i]]*k); if(mnp<tnp){ mnp=tnp; mdir=i; } } if(mnp>0){ ndir[autod[mdir]]=mnp; curdir=autod[mdir]; } } } if(curdir>=0){ // splitting by minimal dir, auto split is ignored // number of domains int ndom=0; // determining sub-nps // THIS IS NP SWITCH : !!! if(np<ndir[curdir])ndir[curdir]=np; if(np>ndir[curdir] && ndef==2){ // the last axis ndir[curdir]=np; } int snp=(np>ndir[curdir] ? np : ndir[curdir]); int mnp=snp/ndir[curdir]; // minimal np int dntot=snp%ndir[curdir]; // difference vec_type c0=(vec_type)mnp/snp, c1=(vec_type)(mnp+1)/snp; Vector_3 p1=box.get_p1(); Vector_3 p2=box.get_p2(); vec_type l=box.GetSize()[curdir]; int i; for(i=0;i<ndir[curdir];i++){ vec_type dl=(dntot>0 ? l*c1 : l*c0); int cnp=(dntot>0 ? mnp+1 : mnp); if(cnp<=0)break; dntot--; p2[curdir]=p1[curdir]+dl; Box subdiv(p1,p2); nspl[curdir]=0; // this direction is processed int ddom=MakeBoxDomains(subdiv,(nproc>0 ? cnp: -cnp),nspl[0],nspl[1],nspl[2],result); if(nproc>0)result+=ddom; ndom+=ddom; p1[curdir]=p2[curdir]; } return ndom; } /// called with (0,0,0) split: put this box into the set if(nproc>0) *result=box; return 1; }
vec_type normal() const { vec_type _d = p_[1] - p_[0]; return vec_type(-_d.y(),_d.x()); }