int XC::ParallelNumberer::numberDOF(int lastDOF) { int result = 0; // get a pointer to the model & check its not null AnalysisModel *theModel = this->getAnalysisModelPtr(); Domain *theDomain = 0; if(theModel) theDomain = theModel->getDomainPtr(); if(theModel == 0 || theDomain == 0) { std::cerr << "WARNING XC::ParallelNumberer::numberDOF(int) -"; std::cerr << " - no AnalysisModel.\n"; return -1; } if(lastDOF != -1) { std::cerr << "WARNING XC::ParallelNumberer::numberDOF(int lastDOF):"; std::cerr << " does not use the lastDOF as requested\n"; } Graph &theGraph= theModel->getDOFGroupGraph(); // if subdomain, collect graph, send it off, get // ID back containing dof tags & start id numbers. if(processID != 0) { CommParameters cp(0,*theChannels[0]); const int numVertex = theGraph.getNumVertex(); /* static XC::ID test(2); test(0) = processID; test(1) = 25; theChannel->recvID(0, 0, test); */ cp.sendMovable(theGraph,DistributedObj::getDbTagData(),CommMetaData(1)); // recv iD ID theID(2*numVertex); cp.receiveID(theID,DistributedObj::getDbTagData(),CommMetaData(2)); // set vertex numbering based on ID received for(int i=0; i<numVertex; i ++) { const int vertexTag= theID(i); int startID= theID(i+numVertex); //Vertex *vertexPtr = theGraph.getVertexPtr(vertexTag); const int dofTag= vertexTag; DOF_Group *dofPtr= theModel->getDOF_GroupPtr(dofTag); if(!dofPtr) { std::cerr << "WARNING ParallelNumberer::numberDOF - "; std::cerr << "DOF_Group " << dofTag << "not in XC::AnalysisModel!\n"; result= -4; } else { const ID &theDOFID= dofPtr->getID(); //std::cerr << "P: " << processID << " dofTag: " << dofTag << " " << "start: " << startID << " " << theDOFID; const int idSize= theDOFID.Size(); for(int j=0; j<idSize; j++) if(theDOFID(j) == -2 || theDOFID(j) == -3) dofPtr->setID(j, startID++); } //const ID &theDOFID= dofPtr->getID(); } cp.sendID(theID,DistributedObj::getDbTagData(),CommMetaData(2)); } else { // if XC::main domain, collect graphs from all subdomains, // merge into 1, number this one, send to subdomains the // id containing dof tags & start id's. // for P0 domain determine original vertex and ref tags const int numVertex= theGraph.getNumVertex(); const int numVertexP0= numVertex; ID vertexTags(numVertex); ID vertexRefs(numVertex); Vertex *vertexPtr; int loc= 0; VertexIter &theVertices= theGraph.getVertices(); while((vertexPtr= theVertices()) != 0) { vertexTags[loc]= vertexPtr->getTag(); vertexRefs[loc]= vertexPtr->getRef(); loc++; } const int numChannels= theChannels.size(); std::vector<ID> theSubdomainIDs(numChannels); FEM_ObjectBroker theBroker; // for each subdomain we receive graph, create an XC::ID (to store // subdomain graph to merged graph vertex mapping and the final // subdoain graph vertex to startDOF mapping) and finally merge the // subdomain graph for(int j=0; j<numChannels; j++) { CommParameters cp(0,*theChannels[j]); Graph theSubGraph; /* static XC::ID test(2); test(0)= processID; test(1)= 25; theChannel->sendID(0, 0, test); */ cp.receiveMovable(theSubGraph,DistributedObj::getDbTagData(),CommMetaData(3)); theSubdomainIDs[j]= ID(theSubGraph.getNumVertex()*2); this->mergeSubGraph(theGraph, theSubGraph, vertexTags, vertexRefs, theSubdomainIDs[j]); } // we use graph numberer if one was provided in constructor, // otherwise we number based on subdomains (all in subdomain 1 numbered first, // then those in 2 not in 1 and so on till done. // GraphNumberer *theNumberer= this->getGraphNumbererPtr(); ID theOrderedRefs(theGraph.getNumVertex()); if(theNumberer) { // use the supplied graph numberer to number the merged graph theOrderedRefs= theNumberer->number(theGraph, lastDOF); } else { // assign numbers based on the subdomains int loc= 0; for(int l=0; l<numChannels; l++) { const ID &theSubdomain= theSubdomainIDs[l]; int numVertexSubdomain= theSubdomain.Size()/2; for(int i=0; i<numVertexSubdomain; i++) { const int vertexTagMerged= theSubdomain(i+numVertexSubdomain); // int refTag= vertexRefs[vertexTags.getLocation(vertexTagMerged)]; if(theOrderedRefs.getLocation(vertexTagMerged) == -1) theOrderedRefs[loc++]= vertexTagMerged; } } // now order those not yet ordered in p0 for(int j=0; j<numVertexP0; j++) { int refTagP0= vertexTags[j]; if(theOrderedRefs.getLocation(refTagP0) == -1) theOrderedRefs[loc++]= refTagP0; } } int count= 0; for(int i=0; i<theOrderedRefs.Size(); i++) { int vertexTag= theOrderedRefs(i); // int vertexTag= vertexTags[vertexRefs.getLocation(tag)]; Vertex *vertexPtr= theGraph.getVertexPtr(vertexTag); int numDOF= vertexPtr->getColor(); vertexPtr->setTmp(count); count += numDOF; } // number own dof's for(int i=0; i<numVertexP0; i++ ) { int vertexTag= vertexTags(i); Vertex *vertexPtr= theGraph.getVertexPtr(vertexTag); int startID= vertexPtr->getTmp(); int dofTag= vertexTag; DOF_Group *dofPtr; dofPtr= theModel->getDOF_GroupPtr(dofTag); if(dofPtr == 0) { std::cerr << "WARNING XC::ParallelNumberer::numberDOF - "; std::cerr << "DOF_Group (P0) " << dofTag << "not in XC::AnalysisModel!\n"; result= -4; } else { const ID &theDOFID= dofPtr->getID(); int idSize= theDOFID.Size(); for(int j=0; j<idSize; j++) if(theDOFID(j) == -2 || theDOFID(j) == -3) dofPtr->setID(j, startID++); } } // now given the ordered refs we determine the mapping for each subdomain // and send the id with the information back to the subdomain, which it uses to order // it's own graph for(int k=0; k<numChannels; k++) { CommParameters cp(0,*theChannels[k]); ID &theSubdomain= theSubdomainIDs[k]; int numVertexSubdomain= theSubdomain.Size()/2; for(int i=0; i<numVertexSubdomain; i++) { int vertexTagMerged= theSubdomain[numVertexSubdomain+i]; Vertex *vertexPtr= theGraph.getVertexPtr(vertexTagMerged); int startDOF= vertexPtr->getTmp(); theSubdomain[i+numVertexSubdomain]= startDOF; } cp.sendID(theSubdomain,DistributedObj::getDbTagData(),CommMetaData(4)); cp.receiveID(theSubdomain,DistributedObj::getDbTagData(),CommMetaData(4)); } } // iterate through the XC::FE_Element getting them to set their IDs FE_EleIter &theEle= theModel->getFEs(); FE_Element *elePtr; while ((elePtr= theEle()) != 0) elePtr->setID(); return result; }
int GModel::writeDIFF(const std::string &name, bool binary, bool saveAll, double scalingFactor) { if(binary){ Msg::Error("Binary DIFF output is not implemented"); return 0; } FILE *fp = Fopen(name.c_str(), binary ? "wb" : "w"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } if(noPhysicalGroups()) saveAll = true; // get the number of vertices and index the vertices in a continuous // sequence int numVertices = indexMeshVertices(saveAll); // tag the vertices according to which surface they belong to (Note // that we use a brute force approach here, so that we can deal with // models with incomplete topology. For example, when we merge 2 STL // triangulations we don't have the boundary information between the // faces, and the vertices would end up categorized on either one.) std::vector<std::list<int> > vertexTags(numVertices); std::list<int> boundaryIndicators; for(riter it = firstRegion(); it != lastRegion(); it++){ std::list<GFace*> faces = (*it)->faces(); for(std::list<GFace*>::iterator itf = faces.begin(); itf != faces.end(); itf++){ GFace *gf = *itf; boundaryIndicators.push_back(gf->tag()); for(unsigned int i = 0; i < gf->getNumMeshElements(); i++){ MElement *e = gf->getMeshElement(i); for(int j = 0; j < e->getNumVertices(); j++){ MVertex *v = e->getVertex(j); if(v->getIndex() > 0) vertexTags[v->getIndex() - 1].push_back(gf->tag()); } } } } boundaryIndicators.sort(); boundaryIndicators.unique(); for(int i = 0; i < numVertices; i++){ vertexTags[i].sort(); vertexTags[i].unique(); } // get all the entities in the model std::vector<GEntity*> entities; getEntities(entities); // find max dimension of mesh elements we need to save int dim = 0; for(unsigned int i = 0; i < entities.size(); i++) if(entities[i]->physicals.size() || saveAll) for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++) dim = std::max(dim, entities[i]->getMeshElement(j)->getDim()); // loop over all elements we need to save int numElements = 0, maxNumNodesPerElement = 0; for(unsigned int i = 0; i < entities.size(); i++){ if(entities[i]->physicals.size() || saveAll){ for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){ MElement *e = entities[i]->getMeshElement(j); if(e->getStringForDIFF() && e->getDim() == dim){ numElements++; maxNumNodesPerElement = std::max(maxNumNodesPerElement, e->getNumVertices()); } } } } fprintf(fp, "\n\n"); fprintf(fp, " Finite element mesh (GridFE):\n\n"); fprintf(fp, " Number of space dim. = 3\n"); fprintf(fp, " Number of elements = %d\n", numElements); fprintf(fp, " Number of nodes = %d\n\n", numVertices); fprintf(fp, " All elements are of the same type : dpTRUE\n"); fprintf(fp, " Max number of nodes in an element: %d \n", maxNumNodesPerElement); fprintf(fp, " Only one subdomain : dpFALSE\n"); fprintf(fp, " Lattice data ? 0\n\n\n\n"); fprintf(fp, " %d Boundary indicators: ", (int)boundaryIndicators.size()); for(std::list<int>::iterator it = boundaryIndicators.begin(); it != boundaryIndicators.end(); it++) fprintf(fp, " %d", *it); fprintf(fp, "\n\n\n"); fprintf(fp," Nodal coordinates and nodal boundary indicators,\n"); fprintf(fp," the columns contain:\n"); fprintf(fp," - node number\n"); fprintf(fp," - coordinates\n"); fprintf(fp," - no of boundary indicators that are set (ON)\n"); fprintf(fp," - the boundary indicators that are set (ON) if any.\n"); fprintf(fp,"#\n"); // write mesh vertices for(unsigned int i = 0; i < entities.size(); i++){ for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++){ MVertex *v = entities[i]->mesh_vertices[j]; if(v->getIndex() > 0){ v->writeDIFF(fp, binary, scalingFactor); fprintf(fp, " [%d] ", (int)vertexTags[v->getIndex() - 1].size()); for(std::list<int>::iterator it = vertexTags[v->getIndex() - 1].begin(); it != vertexTags[v->getIndex() - 1].end(); it++) fprintf(fp," %d ", *it); fprintf(fp,"\n"); } } } fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, " Element types and connectivity\n"); fprintf(fp, " the columns contain:\n"); fprintf(fp, " - element number\n"); fprintf(fp, " - element type\n"); fprintf(fp, " - subdomain number \n"); fprintf(fp, " - the global node numbers of the nodes in the element.\n"); fprintf(fp, "#\n"); // write mesh elements int num = 0; for(unsigned int i = 0; i < entities.size(); i++){ if(entities[i]->physicals.size() || saveAll){ for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){ MElement *e = entities[i]->getMeshElement(j); if(e->getStringForDIFF() && e->getDim() == dim) e->writeDIFF(fp, ++num, binary, entities[i]->tag()); } } } fprintf(fp, "\n"); fclose(fp); return 1; }
int XC::ParallelNumberer::numberDOF(ID &lastDOFs) { int result= 0; // get a pointer to the model & check its not null AnalysisModel *theModel= this->getAnalysisModelPtr(); Domain *theDomain= 0; if(theModel != 0) theDomain= theModel->getDomainPtr(); if(theModel == 0 || theDomain == 0) { std::cerr << "WARNING ParallelNumberer::numberDOF(int) -"; std::cerr << " - no AnalysisModel.\n"; return -1; } Graph &theGraph= theModel->getDOFGroupGraph(); // if subdomain, collect graph, send it off, get // ID back containing dof tags & start id numbers. if(processID != 0) { CommParameters cp(0,*theChannels[0]); int numVertex= theGraph.getNumVertex(); cp.sendMovable(theGraph,DistributedObj::getDbTagData(),CommMetaData(5)); ID theID(2*numVertex); cp.receiveID(theID,DistributedObj::getDbTagData(),CommMetaData(6)); for(int i=0; i<numVertex; i += 2) { int dofTag= theID(i); int startID= theID(i+1); DOF_Group *dofPtr; dofPtr= theModel->getDOF_GroupPtr(dofTag); if(dofPtr == 0) { std::cerr << "WARNING XC::ParallelNumberer::numberDOF - "; std::cerr << "DOF_Group " << dofTag << "not in XC::AnalysisModel!\n"; result= -4; } else { const ID &theID= dofPtr->getID(); int idSize= theID.Size(); for(int j=0; j<idSize; j++) if(theID(j) == -2) dofPtr->setID(j, startID++); } } } // if XC::main domain, collect graphs from all subdomains, // merge into 1, number this one, send to subdomains the // id containing dof tags & start id's. else { // determine original vertex and ref tags int numVertex= theGraph.getNumVertex(); ID vertexTags(numVertex); ID vertexRefs(numVertex); Vertex *vertexPtr; int loc= 0; VertexIter &theVertices= theGraph.getVertices(); while ((vertexPtr= theVertices()) != 0) { vertexTags[loc]= vertexPtr->getTag(); vertexRefs[loc]= vertexPtr->getRef(); loc++; } const int numChannels= theChannels.size(); std::vector<ID> theSubdomainIDs(numChannels); FEM_ObjectBroker theBroker; // merge all subdomain graphs for(int j=0; j<numChannels; j++) { CommParameters cp(0,*theChannels[j]); Graph theSubGraph; cp. receiveMovable(theSubGraph,DistributedObj::getDbTagData(),CommMetaData(6)); theSubdomainIDs[j]= ID(theSubGraph.getNumVertex()*2); this->mergeSubGraph(theGraph, theSubGraph, vertexTags, vertexRefs, theSubdomainIDs[j]); } // number the merged graph // result= this->XC::DOF_Numberer::number(theGraph); // send results of numbered back to subdomains for(int k=0; k<numChannels; k++) { Channel *theChannel= theChannels[k]; // this->determineSubIDs theChannel->sendID(0, 0, theSubdomainIDs[k]); } } return result; }