// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void AbaqusSurfaceMeshWriter::execute() { int err = 0; std::stringstream ss; SurfaceMeshDataContainer* sm = getSurfaceMeshDataContainer(); dataCheck(false, 1, 1, 1); if(getErrorCondition() < 0) { return; } // Make sure any directory path is also available as the user may have just typed // in a path without actually creating the full path std::string parentPath = MXAFileInfo::parentPath(getOutputFile()); if(!MXADir::mkdir(parentPath, true)) { std::stringstream ss; ss << "Error creating parent path '" << parentPath << "'"; notifyErrorMessage(ss.str(), -1); setErrorCondition(-1); return; } DREAM3D::SurfaceMesh::VertListPointer_t nodesPtr = sm->getVertices(); DREAM3D::SurfaceMesh::FaceListPointer_t trianglePtr = sm->getFaces(); // Get the Labels(GrainIds or Region Ids) for the triangles Int32ArrayType::Pointer faceLabelsPtr = boost::dynamic_pointer_cast<Int32ArrayType>(sm->getFaceData(DREAM3D::FaceData::SurfaceMeshFaceLabels)); int32_t* faceLabels = faceLabelsPtr->GetPointer(0); // Store all the unique Spins std::set<int> uniqueSpins; for (int i = 0; i < trianglePtr->GetNumberOfTuples(); i++) { uniqueSpins.insert(faceLabels[i*2]); uniqueSpins.insert(faceLabels[i*2+1]); } FILE* f = fopen(m_OutputFile.c_str(), "wb"); ScopedFileMonitor fileMonitor(f); err = writeHeader(f, nodesPtr->GetNumberOfTuples(), trianglePtr->GetNumberOfTuples(), uniqueSpins.size()-1); err = writeNodes(f); err = writeTriangles(f); err = writeGrains(f); setErrorCondition(0); notifyStatusMessage("Complete"); return; }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void TriangleNormalFilter::execute() { int err = 0; std::stringstream ss; setErrorCondition(err); SurfaceMeshDataContainer* m = getSurfaceMeshDataContainer(); if(NULL == m) { setErrorCondition(-999); notifyErrorMessage("The SurfaceMesh DataContainer Object was NULL", -999); return; } setErrorCondition(0); notifyStatusMessage("Starting"); #ifdef DREAM3D_USE_PARALLEL_ALGORITHMS bool doParallel = true; #endif DREAM3D::SurfaceMesh::VertListPointer_t nodesPtr = getSurfaceMeshDataContainer()->getVertices(); DREAM3D::SurfaceMesh::FaceListPointer_t trianglesPtr = getSurfaceMeshDataContainer()->getFaces(); size_t totalPoints = trianglesPtr->GetNumberOfTuples(); // Run the data check to allocate the memory for the centroid array dataCheck(false, trianglesPtr->GetNumberOfTuples(), 0, 0); #ifdef DREAM3D_USE_PARALLEL_ALGORITHMS if (doParallel == true) { tbb::parallel_for(tbb::blocked_range<size_t>(0, totalPoints), CalculateNormalsImpl(nodesPtr, trianglesPtr, m_SurfaceMeshTriangleNormals), tbb::auto_partitioner()); } else #endif { CalculateNormalsImpl serial(nodesPtr, trianglesPtr, m_SurfaceMeshTriangleNormals); serial.generate(0, totalPoints); } /* Let the GUI know we are done with this filter */ notifyStatusMessage("Complete"); }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void SurfaceMeshDataContainerWriter::writeXdmfGridHeader() { if (m_WriteXdmfFile == false || m_XdmfPtr == NULL) { return; } DREAM3D::SurfaceMesh::FaceListPointer_t faces = getSurfaceMeshDataContainer()->getFaces(); if (NULL == faces.get()) { return; } DREAM3D::SurfaceMesh::VertListPointer_t verts = getSurfaceMeshDataContainer()->getVertices(); if(NULL == verts.get()) { return; } std::ostream& out = *m_XdmfPtr; out << " <Grid Name=\"SurfaceMesh DataContainer\">" << std::endl; out << " <Topology TopologyType=\"Triangle\" NumberOfElements=\"" << faces->GetNumberOfTuples() << "\">" << std::endl; out << " <DataItem Format=\"HDF\" NumberType=\"Int\" Dimensions=\"" << faces->GetNumberOfTuples() << " 3\">" << std::endl; ssize_t nameSize = H5Fget_name(m_HdfFileId, NULL, 0) + 1; std::vector<char> nameBuffer(nameSize, 0); nameSize = H5Fget_name(m_HdfFileId, &(nameBuffer.front()), nameSize); std::string hdfFileName(&(nameBuffer.front()), nameSize); hdfFileName = MXAFileInfo::filename(hdfFileName); out << " " << hdfFileName << ":/SurfaceMeshDataContainer/Faces" << std::endl; out << " </DataItem>" << std::endl; out << " </Topology>" << std::endl; out << " <Geometry Type=\"XYZ\">" << std::endl; out << " <DataItem Format=\"HDF\" Dimensions=\"" << verts->GetNumberOfTuples() << " 3\" NumberType=\"Float\" Precision=\"4\">" << std::endl; out << " " << hdfFileName << ":/SurfaceMeshDataContainer/Vertices" << std::endl; out << " </DataItem>" << std::endl; out << " </Geometry>" << std::endl; out << "" << std::endl; }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- int AbaqusSurfaceMeshWriter::writeTriangles(FILE* f) { int err = 0; DREAM3D::SurfaceMesh::FaceListPointer_t trianglePtr = getSurfaceMeshDataContainer()->getFaces(); DREAM3D::SurfaceMesh::Face_t* triangles = trianglePtr->GetPointer(0); size_t numTri = trianglePtr->GetNumberOfTuples(); fprintf(f, "*ELEMENT, TYPE=%s\n", TRI_ELEMENT_TYPE); for(size_t i = 1; i <= numTri; ++i) { // When we get the node index, add 1 to it because Abaqus number is 1 based. int nId0 = triangles[i-1].verts[0] + 1; int nId1 = triangles[i-1].verts[1] + 1; int nId2 = triangles[i-1].verts[2] + 1; fprintf(f, "%lu, %d, %d, %d\n", i, nId0, nId1, nId2); } return err; }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void generateNeighborLists(DREAM3D::SurfaceMesh::VertListPointer_t nodes, DREAM3D::SurfaceMesh::FaceListPointer_t faces, MeshVertLinks::Pointer cellLinks) { size_t nFaces = faces->GetNumberOfTuples(); allocate(faces->GetNumberOfTuples()); // Allocate an array of bools that we use each iteration of triangle so that we don't put duplicates into the array boost::shared_array<bool> visitedPtr(new bool[nFaces]); bool* visited = visitedPtr.get(); ::memset(visitedPtr.get(), 0, nFaces); // Reuse this vector for each loop. Avoids re-allocating the memory each time through the loop std::vector<int> loop_neighbors(32, 0); // Build up the Face Adjacency list now that we have the cell links for(size_t t = 0; t < nFaces; ++t) { // std::cout << "Analyzing Face " << t << std::endl; DREAM3D::SurfaceMesh::Face_t& seedFace = *(faces->GetPointer(t)); for(size_t v = 0; v < 3; ++v) { // std::cout << " vert " << v << std::endl; int nTris = cellLinks->getNumberOfFaces(seedFace.verts[v]); int* vertIdxs = cellLinks->getFaceListPointer(seedFace.verts[v]); for(int vt = 0; vt < nTris; ++vt) { if (vertIdxs[vt] == static_cast<int>(t) ) { continue; } // This is the same triangle as our "source" triangle if (visited[vertIdxs[vt]] == true) { continue; } // We already added this triangle so loop again // std::cout << " Comparing Face " << vertIdxs[vt] << std::endl; DREAM3D::SurfaceMesh::Face_t& vertTri = *(faces->GetPointer(vertIdxs[vt])); int vCount = 0; // Loop over all the vertex indices of this triangle and try to match 2 of them to the current loop triangle // If there are 2 matches then that triangle is a neighbor of this triangle. if there are more than 2 matches // then there is a real problem with the mesh and the program is going to assert. // Unrolled the loop to shave about 25% of time off the outer loop. int seedTriVert0 = seedFace.verts[0]; int seedTriVert1 = seedFace.verts[1]; int seedTriVert2 = seedFace.verts[2]; int trgtTriVert0 = vertTri.verts[0]; int trgtTriVert1 = vertTri.verts[1]; int trgtTriVert2 = vertTri.verts[2]; if (seedTriVert0 == trgtTriVert0 || seedTriVert0 == trgtTriVert1 || seedTriVert0 == trgtTriVert2 ) { vCount++; } if (seedTriVert1 == trgtTriVert0 || seedTriVert1 == trgtTriVert1 || seedTriVert1 == trgtTriVert2 ) { vCount++; } if (seedTriVert2 == trgtTriVert0 || seedTriVert2 == trgtTriVert1 || seedTriVert2 == trgtTriVert2 ) { vCount++; } BOOST_ASSERT(vCount < 3); // No way 2 faces can share all 3 vertices. Something is VERY wrong at this point // So if our vertex match count is 2 and we have not visited the triangle in question then add this triangle index // into the list of Face Indices as neighbors for the source triangle. if (vCount == 2) { //std::cout << " Neighbor: " << vertIdxs[vt] << std::endl; // Use the current count of neighbors as the index // into the loop_neighbors vector and place the value of the vertex triangle at that index loop_neighbors[this->Array[t].ncells] = vertIdxs[vt]; this->Array[t].ncells++;// Increment the count for the next time through if (this->Array[t].ncells >= loop_neighbors.size()) { loop_neighbors.resize(loop_neighbors.size() + 10); } visited[vertIdxs[vt]] = true; // Set this triangle as visited so we do NOT add it again } } } BOOST_ASSERT(this->Array[t].ncells > 2); // Reset all the visited triangle indexs back to false (zero) for(size_t k = 0;k < this->Array[t].ncells; ++k) { visited[loop_neighbors[k]] = false; } // Allocate the array storage for the current triangle to hold its Face list this->Array[t].cells = new int[this->Array[t].ncells]; // Only copy the first "N" values from the loop_neighbors vector into the storage array ::memcpy(this->Array[t].cells, &(loop_neighbors[0]), sizeof(int) * this->Array[t].ncells); } }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- int AbaqusSurfaceMeshWriter::writeGrains(FILE* f) { //*Elset, elset=Grain1 //1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 int err = 0; std::stringstream ss; SurfaceMeshDataContainer* sm = getSurfaceMeshDataContainer(); DREAM3D::SurfaceMesh::VertListPointer_t nodesPtr = sm->getVertices(); DREAM3D::SurfaceMesh::FaceListPointer_t trianglePtr = sm->getFaces(); // Get the Labels(GrainIds or Region Ids) for the triangles Int32ArrayType::Pointer faceLabelsPtr = boost::dynamic_pointer_cast<Int32ArrayType>(sm->getFaceData(DREAM3D::FaceData::SurfaceMeshFaceLabels)); int32_t* faceLabels = faceLabelsPtr->GetPointer(0); int nTriangles = trianglePtr->GetNumberOfTuples(); // Store all the unique Spins std::set<int> uniqueSpins; for (int i = 0; i < nTriangles; i++) { uniqueSpins.insert(faceLabels[i*2]); uniqueSpins.insert(faceLabels[i*2+1]); } int spin = 0; //Loop over the unique Spins for (std::set<int>::iterator spinIter = uniqueSpins.begin(); spinIter != uniqueSpins.end(); ++spinIter ) { spin = *spinIter; if(spin < 0) { continue; } fprintf(f, "*ELSET, ELSET=Grain%d\n", spin); ss.str(""); ss << "Writing ELSET for Grain Id " << spin; notifyStatusMessage(ss.str()); // Loop over all the triangles for this spin int lineCount = 0; for(int t = 0; t < nTriangles; ++t) { if (faceLabels[t*2] != spin && faceLabels[t*2+1] != spin) { continue; // We do not match either spin so move to the next triangle } // Only print 15 Triangles per line if (lineCount == 15) { fprintf(f, ", %d\n", t); lineCount = 0; } else if(lineCount == 0) // First value on the line { fprintf(f,"%d", t); lineCount++; } else { fprintf(f,", %d", t); lineCount++; } } // Make sure we have a new line at the end of the section if (lineCount != 0) { fprintf(f, "\n"); } } return err; }