/** * \file mpi_node.txx * \author Dhairya Malhotra, dhairya.malhotra@gmail.com * \date 12-11-2010 * \brief This file contains the implementation of the class MPI_Node. */ #include #include #include namespace pvfmm{ template MPI_Node::~MPI_Node(){ } template void MPI_Node::Initialize(TreeNode* parent_,int path2node_, TreeNode::NodeData* data_){ TreeNode::Initialize(parent_,path2node_,data_); //Set node coordinates. Real_t coord_offset=((Real_t)1.0)/((Real_t)(((uint64_t)1)<*)parent_)->coord[j]+ ((Path2Node() & flag)?coord_offset:0.0f); flag=flag<<1; } } //Initialize colleagues array. int n=(int)pow(3.0,Dim()); for(int i=0;i::NodeData* mpi_data=dynamic_cast::NodeData*>(data_); if(data_){ max_pts =mpi_data->max_pts; pt_coord=mpi_data->pt_coord; pt_value=mpi_data->pt_value; }else if(parent){ max_pts =((MPI_Node*)parent)->max_pts; SetGhost(((MPI_Node*)parent)->IsGhost()); } } template void MPI_Node::ClearData(){ pt_coord.ReInit(0); pt_value.ReInit(0); } template MortonId MPI_Node::GetMortonId(){ assert(coord); Real_t s=0.25/(1UL< void MPI_Node::SetCoord(MortonId& mid){ assert(coord); mid.GetCoord(coord); depth=mid.GetDepth(); } template TreeNode* MPI_Node::NewNode(TreeNode* n_){ MPI_Node* n=(n_?static_cast*>(n_):new MPI_Node()); n->max_pts=max_pts; return TreeNode::NewNode(n); } template bool MPI_Node::SubdivCond(){ int n=(1UL<Dim()); // Do not subdivide beyond max_depth if(this->Depth()>=this->max_depth-1) return false; if(!this->IsLeaf()){ // If has non-leaf children, then return true. for(int i=0;i* ch=static_cast*>(this->Child(i)); assert(ch); //ch==NULL should never happen if(!ch->IsLeaf() || ch->IsGhost()) return true; } } else{ // Do not refine ghost leaf nodes. if(this->IsGhost()) return false; } if(!this->IsLeaf()){ size_t pt_vec_size=0; for(int i=0;i* ch=static_cast*>(this->Child(i)); pt_vec_size+=ch->pt_coord.Dim(); } return pt_vec_size/Dim()>max_pts; }else{ return pt_coord.Dim()/Dim()>max_pts; } } template void MPI_Node::Subdivide(){ if(!this->IsLeaf()) return; TreeNode::Subdivide(); int nchld=(1UL<Dim()); if(!IsGhost()){ // Partition point coordinates and values. std::vector*> pt_coord; std::vector*> pt_value; std::vector*> pt_scatter; this->NodeDataVec(pt_coord, pt_value, pt_scatter); std::vector*> > chld_pt_coord(nchld); std::vector*> > chld_pt_value(nchld); std::vector*> > chld_pt_scatter(nchld); for(size_t i=0;i*>((MPI_Node*)this->Child(i)) ->NodeDataVec(chld_pt_coord[i], chld_pt_value[i], chld_pt_scatter[i]); } Real_t* c=this->Coord(); Real_t s=pow(0.5,this->Depth()+1); for(size_t j=0;jDim()) continue; Vector& coord=*pt_coord[j]; size_t npts=coord.Dim()/this->dim; Vector cdata(nchld+1); for(size_t i=0;i1){ // binary search long long pt3=(pt1+pt2)/2; assert(pt3=c[0]+s)*1+ (coord[pt3*3+1]>=c[1]+s)*2+ (coord[pt3*3+2]>=c[2]+s)*4; if(ch_id< i) pt1=pt3; if(ch_id>=i) pt2=pt3; } cdata[i]=pt2; } if(pt_coord[j]){ Vector& vec=*pt_coord[j]; size_t dof=vec.Dim()/npts; if(dof>0) for(size_t i=0;i& chld_vec=*chld_pt_coord[i][j]; chld_vec.ReInit((cdata[i+1]-cdata[i])*dof, &vec[0]+cdata[i]*dof); } vec.ReInit(0); } if(pt_value[j]){ Vector& vec=*pt_value[j]; size_t dof=vec.Dim()/npts; if(dof>0) for(size_t i=0;i& chld_vec=*chld_pt_value[i][j]; chld_vec.ReInit((cdata[i+1]-cdata[i])*dof, &vec[0]+cdata[i]*dof); } vec.ReInit(0); } if(pt_scatter[j]){ Vector& vec=*pt_scatter[j]; size_t dof=vec.Dim()/npts; if(dof>0) for(size_t i=0;i& chld_vec=*chld_pt_scatter[i][j]; chld_vec.ReInit((cdata[i+1]-cdata[i])*dof, &vec[0]+cdata[i]*dof); } vec.ReInit(0); } } } }; template void MPI_Node::Truncate(){ if(!this->IsLeaf()){ int nchld=(1UL<Dim()); for(size_t i=0;iChild(i)->IsLeaf()){ this->Child(i)->Truncate(); } } std::vector*> pt_coord; std::vector*> pt_value; std::vector*> pt_scatter; this->NodeDataVec(pt_coord, pt_value, pt_scatter); std::vector*> > chld_pt_coord(nchld); std::vector*> > chld_pt_value(nchld); std::vector*> > chld_pt_scatter(nchld); for(size_t i=0;i*>((MPI_Node*)this->Child(i)) ->NodeDataVec(chld_pt_coord[i], chld_pt_value[i], chld_pt_scatter[i]); } for(size_t j=0;j& chld_vec=*chld_pt_coord[i][j]; vec_size+=chld_vec.Dim(); } Vector vec=*pt_coord[j]; vec.ReInit(vec_size); vec_size=0; for(size_t i=0;i& chld_vec=*chld_pt_coord[i][j]; if(chld_vec.Dim()>0){ mem::memcopy(&vec[vec_size],&chld_vec[0],chld_vec.Dim()*sizeof(Real_t)); vec_size+=chld_vec.Dim(); } } } if(pt_value[j]){ size_t vec_size=0; for(size_t i=0;i& chld_vec=*chld_pt_value[i][j]; vec_size+=chld_vec.Dim(); } Vector vec=*pt_value[j]; vec.ReInit(vec_size); vec_size=0; for(size_t i=0;i& chld_vec=*chld_pt_value[i][j]; if(chld_vec.Dim()>0){ mem::memcopy(&vec[vec_size],&chld_vec[0],chld_vec.Dim()*sizeof(Real_t)); vec_size+=chld_vec.Dim(); } } } if(pt_scatter[j]){ size_t vec_size=0; for(size_t i=0;i& chld_vec=*chld_pt_scatter[i][j]; vec_size+=chld_vec.Dim(); } Vector vec=*pt_scatter[j]; vec.ReInit(vec_size); vec_size=0; for(size_t i=0;i& chld_vec=*chld_pt_scatter[i][j]; if(chld_vec.Dim()>0){ mem::memcopy(&vec[vec_size],&chld_vec[0],chld_vec.Dim()*sizeof(Real_t)); vec_size+=chld_vec.Dim(); } } } } } TreeNode::Truncate(); } template PackedData MPI_Node::Pack(bool ghost, void* buff_ptr, size_t offset){ std::vector*> pt_coord; std::vector*> pt_value; std::vector*> pt_scatter; this->NodeDataVec(pt_coord, pt_value, pt_scatter); PackedData p0; // Determine data length. p0.length =sizeof(size_t)+sizeof(int)+sizeof(long long)+sizeof(MortonId); for(size_t j=0;jDim())*sizeof(Real_t); if(pt_value [j]) p0.length+=(pt_value [j]->Dim())*sizeof(Real_t); if(pt_scatter[j]) p0.length+=(pt_scatter[j]->Dim())*sizeof(size_t); } // Allocate memory. p0.data=(char*)buff_ptr; if(!p0.data){ this->packed_data.Resize(p0.length+offset); p0.data=&this->packed_data[0]; } char* data_ptr=(char*)p0.data; data_ptr+=offset; // Header ((size_t*)data_ptr)[0]=p0.length; data_ptr+=sizeof(size_t); ((int*)data_ptr)[0]=this->Depth(); data_ptr+=sizeof(int); ((long long*)data_ptr)[0]=this->NodeCost(); data_ptr+=sizeof(long long); ((MortonId*)data_ptr)[0]=this->GetMortonId(); data_ptr+=sizeof(MortonId); // Copy Vector data. for(size_t j=0;j& vec=*pt_coord[j]; ((size_t*)data_ptr)[0]=vec.Dim(); data_ptr+=sizeof(size_t); if(vec.Dim()>0 && data_ptr!=(char*)&vec[0]) mem::memcopy(data_ptr, &vec[0], sizeof(Real_t)*vec.Dim()); data_ptr+=vec.Dim()*sizeof(Real_t); }else{ ((size_t*)data_ptr)[0]=0; data_ptr+=sizeof(size_t); } if(pt_value[j]){ Vector& vec=*pt_value[j]; ((size_t*)data_ptr)[0]=vec.Dim(); data_ptr+=sizeof(size_t); if(vec.Dim()>0 && data_ptr!=(char*)&vec[0]) mem::memcopy(data_ptr, &vec[0], sizeof(Real_t)*vec.Dim()); data_ptr+=vec.Dim()*sizeof(Real_t); }else{ ((size_t*)data_ptr)[0]=0; data_ptr+=sizeof(size_t); } if(pt_scatter[j] && !ghost){ Vector& vec=*pt_scatter[j]; ((size_t*)data_ptr)[0]=vec.Dim(); data_ptr+=sizeof(size_t); if(vec.Dim()>0 && data_ptr!=(char*)&vec[0]) mem::memcopy(data_ptr, &vec[0], sizeof(size_t)*vec.Dim()); data_ptr+=vec.Dim()*sizeof(size_t); }else{ ((size_t*)data_ptr)[0]=0; data_ptr+=sizeof(size_t); } } return p0; } template void MPI_Node::Unpack(PackedData p0, bool own_data){ std::vector*> pt_coord; std::vector*> pt_value; std::vector*> pt_scatter; this->NodeDataVec(pt_coord, pt_value, pt_scatter); char* data_ptr=(char*)p0.data; // Check header assert(((size_t*)data_ptr)[0]==p0.length); data_ptr+=sizeof(size_t); this->depth=(((int*)data_ptr)[0]); data_ptr+=sizeof(int); this->NodeCost()=(((long long*)data_ptr)[0]); data_ptr+=sizeof(long long); this->SetCoord(((MortonId*)data_ptr)[0]); data_ptr+=sizeof(MortonId); for(size_t j=0;j& vec=*pt_coord[j]; size_t vec_sz=(((size_t*)data_ptr)[0]); data_ptr+=sizeof(size_t); if(own_data){ vec=Vector(vec_sz,(Real_t*)data_ptr,false); }else{ vec.ReInit(vec_sz,(Real_t*)data_ptr,false); } data_ptr+=vec_sz*sizeof(Real_t); }else{ assert(!((size_t*)data_ptr)[0]); data_ptr+=sizeof(size_t); } if(pt_value[j]){ Vector& vec=*pt_value[j]; size_t vec_sz=(((size_t*)data_ptr)[0]); data_ptr+=sizeof(size_t); if(own_data){ vec=Vector(vec_sz,(Real_t*)data_ptr,false); }else{ vec.ReInit(vec_sz,(Real_t*)data_ptr,false); } data_ptr+=vec_sz*sizeof(Real_t); }else{ assert(!((size_t*)data_ptr)[0]); data_ptr+=sizeof(size_t); } if(pt_scatter[j]){ Vector& vec=*pt_scatter[j]; size_t vec_sz=(((size_t*)data_ptr)[0]); data_ptr+=sizeof(size_t); if(own_data){ vec=Vector(vec_sz,(size_t*)data_ptr,false); }else{ vec.ReInit(vec_sz,(size_t*)data_ptr,false); } data_ptr+=vec_sz*sizeof(size_t); }else{ assert(!((size_t*)data_ptr)[0]); data_ptr+=sizeof(size_t); } } } template void MPI_Node::ReadVal(std::vector x,std::vector y, std::vector z, Real_t* val, bool show_ghost){ if(!pt_coord.Dim()) return; size_t n_pts=pt_coord.Dim()/dim; size_t data_dof=pt_value.Dim()/n_pts; std::vector v(data_dof,0); for(size_t i=0;i void MPI_Node::VTU_Data(std::vector& coord, std::vector& value, std::vector& connect, std::vector& offset, std::vector& types, int lod){ if(!pt_coord.Dim()) return; size_t point_cnt=coord.size()/COORD_DIM; size_t connect_cnt=connect.size(); for(size_t i=0;iCoord(); Real_t s=pow(0.5,this->Depth()); size_t data_dof=pt_value.Dim()/(pt_coord.Dim()/dim); for(int i=0;i<8;i++){ coord.push_back(c[0]+(i&1?1:0)*s); coord.push_back(c[1]+(i&2?1:0)*s); coord.push_back(c[2]+(i&4?1:0)*s); for(int j=0;j x(2); std::vector y(2); std::vector z(2); x[0]=c[0]; x[1]=c[0]+s; y[0]=c[1]; y[1]=c[1]+s; z[0]=c[2]; z[1]=c[2]+s; this->ReadVal(x, y, z, val_ptr); //Rearrrange data //(x1,x2,x3,...,y1,y2,...z1,...) => (x1,y1,z1,x2,y2,z2,...) Matrix M(data_dof,8,val_ptr,false); M=M.Transpose(); } } }//end namespace