// FIND CELL //------------------------------------------------------------------------- Index RectilinearGrid::findCell(const Vector &point, int flags) const { const bool acceptGhost = flags&AcceptGhost; for (int c=0; c<3; ++c) { if (point[c] < m_coords[c][0]) return InvalidIndex; if (point[c] > m_coords[c][m_numDivisions[c]-1]) return InvalidIndex; } Index n[3] = {0, 0, 0}; for (int c=0; c<3; ++c) { for (Index i=0; i<m_numDivisions[c]; ++i) { if (m_coords[c][i] >= point[c]) break; n[c] = i; } } Index el = cellIndex(n, m_numDivisions); if (acceptGhost || !isGhostCell(el)) return el; return InvalidIndex; }
// FIND CELL //------------------------------------------------------------------------- Index UniformGrid::findCell(const Vector &point, int flags) const { const bool acceptGhost = flags&AcceptGhost; for (int c=0; c<3; ++c) { if (point[c] < m_min[c]) return InvalidIndex; if (point[c] > m_max[c]) return InvalidIndex; } Index n[3]; for (int c=0; c<3; ++c) { n[c] = (point[c]-m_min[c])/m_dist[c]; if (n[c] >= m_numDivisions[c]-1) n[c] = m_numDivisions[c]-2; } Index el = cellIndex(n, m_numDivisions); assert(inside(el, point)); if (acceptGhost || !isGhostCell(el)) return el; return InvalidIndex; }
void ExporterVTK<MeshType,N>::saveNodeData( typename timeset_type::step_ptrtype step, Iterator __var, Iterator en, vtkSmartPointer<vtkout_type> out ) const { while ( __var != en ) { if ( !__var->second.worldComm().isActive() ) return; /* handle faces data */ #if 0 if ( boption( _name="exporter.ensightgold.save-face" ) ) { BOOST_FOREACH( auto m, __mesh->markerNames() ) { if ( m.second[1] != __mesh->nDim-1 ) continue; VLOG(1) << "writing face with marker " << m.first << " with id " << m.second[0]; auto pairit = __mesh->facesWithMarker( m.second[0], this->worldComm().localRank() ); auto fit = pairit.first; auto fen = pairit.second; Feel::detail::MeshPoints<float> mp( __mesh.get(), this->worldComm(), fit, fen, true, true, true ); int __ne = std::distance( fit, fen ); int nverts = fit->numLocalVertices; DVLOG(2) << "Faces : " << __ne << "\n"; if( this->worldComm().isMasterRank() ) { size = sizeof(buffer); } else { size = 0; } memset(buffer, '\0', sizeof(buffer)); strcpy( buffer, "part" ); MPI_File_write_ordered(fh, buffer, size, MPI_CHAR, &status); int32_t partid = m.second[0]; if( this->worldComm().isMasterRank() ) { size = 1; } else { size = 0; } MPI_File_write_ordered(fh, &partid, size, MPI_INT32_T, &status); if( this->worldComm().isMasterRank() ) { size = sizeof(buffer); } else { size = 0; } memset(buffer, '\0', sizeof(buffer)); strcpy( buffer, "coordinates" ); MPI_File_write_ordered(fh, buffer, size, MPI_CHAR, &status); // write values fit = pairit.first; fen = pairit.second; uint16_type nComponents = __var->second.nComponents; if ( __var->second.is_vectorial ) nComponents = 3; int nfaces = mp.ids.size(); std::vector<float> field( nComponents*nfaces, 0.0 ); for( ; fit != fen; ++fit ) { for ( uint16_type c = 0; c < nComponents; ++c ) { for ( size_type j = 0; j < nverts; j++ ) { size_type pid = mp.old2new[fit->point( j ).id()]-1; size_type global_node_id = nfaces*c + pid ; if ( c < __var->second.nComponents ) { size_type thedof = __var->second.start() + boost::get<0>(__var->second.functionSpace()->dof()->faceLocalToGlobal( fit->id(), j, c )); field[global_node_id] = __var->second.globalValue( thedof ); } else { field[global_node_id] = 0; } } } } /* Write each component separately */ for ( uint16_type c = 0; c < __var->second.nComponents; ++c ) { MPI_File_write_ordered(fh, field.data() + nfaces * c, nfaces, MPI_FLOAT, &status); } } // boundaries loop } #endif /* handle elements */ uint16_type nComponents = __var->second.nComponents; VLOG(1) << "nComponents field: " << nComponents; if ( __var->second.is_vectorial ) { nComponents = 3; VLOG(1) << "nComponents field(is_vectorial): " << nComponents; } /* we get that from the local processor */ /* We do not need the renumbered global index */ //auto r = markedelements(__mesh, M_markersToWrite[i], EntityProcessType::ALL); auto r = elements( step->mesh() ); auto elt_it = r.template get<1>(); auto elt_en = r.template get<2>(); Feel::detail::MeshPoints<float> mp( step->mesh().get(), this->worldComm(), elt_it, elt_en, false, true, true, 0 ); // previous implementation //size_type __field_size = mp.ids.size(); //int nelts = std::distance(elt_it, elt_en); int npts = mp.ids.size(); size_type __field_size = npts; if ( __var->second.is_vectorial ) __field_size *= 3; std::vector<float> __field( __field_size, 0.0 ); size_type e = 0; VLOG(1) << "field size=" << __field_size; if ( !__var->second.areGlobalValuesUpdated() ) __var->second.updateGlobalValues(); vtkSmartPointer<vtkFloatArray> da = vtkSmartPointer<vtkFloatArray>::New(); da->SetName(__var->first.c_str()); /* set array parameters */ /* no need for preallocation if we are using Insert* methods */ da->SetNumberOfComponents(nComponents); da->SetNumberOfTuples(npts); /* std::cout << this->worldComm().rank() << " nbPts:" << npts << " nComp:" << nComponents << " __var->second.nComponents:" << __var->second.nComponents << std::endl; */ /* std::cout << this->worldComm().rank() << " marker=" << *mit << " nbPts:" << npts << " nComp:" << nComponents << " __evar->second.nComponents:" << __var->second.nComponents << std::endl; */ /* loop on the elements */ int index = 0; for ( ; elt_it != elt_en; ++elt_it ) { VLOG(3) << "is ghost cell " << elt_it->isGhostCell(); /* looop on the ccomponents is outside of the loop on the vertices */ for ( uint16_type c = 0; c < nComponents; ++c ) { for ( uint16_type p = 0; p < step->mesh()->numLocalVertices(); ++p, ++e ) { size_type ptid = mp.old2new[elt_it->point( p ).id()]; size_type global_node_id = ptid * nComponents + c; //size_type global_node_id = mp.ids.size()*c + ptid ; //LOG(INFO) << elt_it->get().point( p ).id() << " " << ptid << " " << global_node_id << std::endl; DCHECK( ptid < step->mesh()->numPoints() ) << "Invalid point id " << ptid << " element: " << elt_it->id() << " local pt:" << p << " mesh numPoints: " << step->mesh()->numPoints(); DCHECK( global_node_id < __field_size ) << "Invalid dof id : " << global_node_id << " max size : " << __field_size; if ( c < __var->second.nComponents ) { size_type dof_id = boost::get<0>( __var->second.functionSpace()->dof()->localToGlobal( elt_it->id(), p, c ) ); __field[global_node_id] = __var->second.globalValue( dof_id ); //__field[npts*c + index] = __var->second.globalValue( dof_id ); //DVLOG(3) << "v[" << global_node_id << "]=" << __var->second.globalValue( dof_id ) << " dof_id:" << dof_id; DVLOG(3) << "v[" << (npts*c + index) << "]=" << __var->second.globalValue( dof_id ) << " dof_id:" << dof_id; } else { __field[global_node_id] = 0.0; //__field[npts*c + index] = 0.0; } } } /* increment index of vertex */ index++; } /* insert data into array */ for(int i = 0; i < npts; i++) { da->SetTuple(mp.ids[i], __field.data() + i * nComponents); } /* add data array into the vtk object */ out->GetPointData()->AddArray(da); /* Set the first scalar/vector/tensor data, we process as active */ if( __var->second.is_scalar && !(out->GetPointData()->GetScalars())) { out->GetPointData()->SetActiveScalars(da->GetName()); } if( __var->second.is_vectorial && !(out->GetPointData()->GetVectors())) { out->GetPointData()->SetActiveVectors(da->GetName()); } if( __var->second.is_tensor2 && !(out->GetPointData()->GetTensors())) { out->GetPointData()->SetActiveTensors(da->GetName()); } DVLOG(2) << "[ExporterVTK::saveNodal] saving " << __var->first << "done\n"; ++__var; } }
/****************************************************************************** * Generates the tessellation. ******************************************************************************/ bool DelaunayTessellation::generateTessellation(const SimulationCell& simCell, const Point3* positions, size_t numPoints, FloatType ghostLayerSize, FutureInterfaceBase* progress) { if(progress) progress->setProgressRange(0); std::vector<DT::Point> cgalPoints; // Set up random number generator to generate random perturbations. std::mt19937 rng; rng.seed(1); std::uniform_real_distribution<double> displacement(-1e-8, +1e-8); // Insert the original points first. cgalPoints.reserve(numPoints); for(size_t i = 0; i < numPoints; i++, ++positions) { // Add a small random perturbation to the particle positions to make the Delaunay triangulation more robust // against singular input data, e.g. particles forming an ideal crystal lattice. Point3 wp = simCell.wrapPoint(*positions); double coords[3]; coords[0] = (double)wp.x() + displacement(rng); coords[1] = (double)wp.y() + displacement(rng); coords[2] = (double)wp.z() + displacement(rng); cgalPoints.push_back(Point3WithIndex(coords[0], coords[1], coords[2], i, false)); } int vertexCount = numPoints; Vector3I stencilCount; FloatType cuts[3][2]; Vector3 cellNormals[3]; for(size_t dim = 0; dim < 3; dim++) { cellNormals[dim] = simCell.cellNormalVector(dim); cuts[dim][0] = cellNormals[dim].dot(simCell.reducedToAbsolute(Point3(0,0,0)) - Point3::Origin()); cuts[dim][1] = cellNormals[dim].dot(simCell.reducedToAbsolute(Point3(1,1,1)) - Point3::Origin()); if(simCell.pbcFlags()[dim]) { stencilCount[dim] = (int)ceil(ghostLayerSize / simCell.matrix().column(dim).dot(cellNormals[dim])); cuts[dim][0] -= ghostLayerSize; cuts[dim][1] += ghostLayerSize; } else { stencilCount[dim] = 0; cuts[dim][0] -= ghostLayerSize; cuts[dim][1] += ghostLayerSize; } } // Create ghost images of input vertices. for(int ix = -stencilCount[0]; ix <= +stencilCount[0]; ix++) { for(int iy = -stencilCount[1]; iy <= +stencilCount[1]; iy++) { for(int iz = -stencilCount[2]; iz <= +stencilCount[2]; iz++) { if(ix == 0 && iy == 0 && iz == 0) continue; if(progress && progress->isCanceled()) return false; Vector3 shift = simCell.reducedToAbsolute(Vector3(ix,iy,iz)); Vector_3<double> shiftd = (Vector_3<double>)shift; for(int vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) { Point3 pimage = (Point3)cgalPoints[vertexIndex] + shift; bool isClipped = false; for(size_t dim = 0; dim < 3; dim++) { FloatType d = cellNormals[dim].dot(pimage - Point3::Origin()); if(d < cuts[dim][0] || d > cuts[dim][1]) { isClipped = true; break; } } if(!isClipped) { cgalPoints.push_back(Point3WithIndex(cgalPoints[vertexIndex].x() + shift.x(), cgalPoints[vertexIndex].y() + shift.y(), cgalPoints[vertexIndex].z() + shift.z(), vertexIndex, true)); } } } } } if(progress && progress->isCanceled()) return false; CGAL::spatial_sort(cgalPoints.begin(), cgalPoints.end(), _dt.geom_traits()); if(progress) { if(progress->isCanceled()) return false; progress->setProgressRange(cgalPoints.size()); progress->setProgressValue(0); } DT::Vertex_handle hint; for(auto p = cgalPoints.begin(); p != cgalPoints.end(); ++p) { hint = _dt.insert(*p, hint); if(progress && ((p - cgalPoints.begin()) % 4096) == 0) { if(progress->isCanceled()) return false; progress->incrementProgressValue(4096); } } progress->setProgressValue(cgalPoints.size()); // Classify tessellation cells as ghost or local cells. for(CellIterator cell = begin_cells(); cell != end_cells(); ++cell) { cell->info().isGhost = isGhostCell(cell); } return true; }