#ifndef CELLS_H #define CELLS_H #include #include #include #include #include using namespace dealii; template struct CellLocation { typename DoFHandler::active_cell_iterator cell; Point reference_point; }; template class CellLocator { public: void rebuild(const DoFHandler &dof_handler, const Triangulation &triangulation); CellLocation locate(const Point &p) const; private: const DoFHandler *dof_handler_ptr = nullptr; typename Triangulation::cell_iterator root; Point lower; Point upper; }; template void CellLocator::rebuild(const DoFHandler &dof_handler, const Triangulation &triangulation) { dof_handler_ptr = &dof_handler; // Everything below assumes the mesh is a single hyper_cube coarse cell // (true for your create_mesh(): GridGenerator::hyper_cube + refine_global). AssertThrow(triangulation.n_cells(0) == 1, ExcMessage("CellLocator assumes exactly one coarse/root cell.")); root = triangulation.begin(0); lower = root->vertex(0); upper = root->vertex(GeometryInfo::vertices_per_cell - 1); } template CellLocation CellLocator::locate(const Point &p) const { AssertThrow(dof_handler_ptr != nullptr, ExcMessage("CellLocator::rebuild() has not been called.")); // Step 1: periodic wrap into [lower, upper) per axis. Point p_wrapped; for (unsigned int d = 0; d < dim; ++d) { const double L = upper[d] - lower[d]; double x = p[d] - lower[d]; x = x - L * std::floor(x / L); p_wrapped[d] = lower[d] + x; } // Step 2: reference coordinates in the root cell, clamped against // floating-point drift at the domain boundary. Point xi; for (unsigned int d = 0; d < dim; ++d) { xi[d] = (p_wrapped[d] - lower[d]) / (upper[d] - lower[d]); xi[d] = std::min(std::max(xi[d], 0.0), 1.0); } // Steps 3-5: descend the refinement tree using deal.II's own // reference-cell child logic (branch-free, handles dim=1,2,3 uniformly). typename Triangulation::cell_iterator cell = root; while (cell->has_children()) { const unsigned int child_index = GeometryInfo::child_cell_from_point(xi); xi = GeometryInfo::cell_to_child_coordinates(xi, child_index); cell = cell->child(child_index); } // cell is now active (leaf) -> bind it to the DoFHandler. typename DoFHandler::active_cell_iterator dof_cell( &cell->get_triangulation(), cell->level(), cell->index(), dof_handler_ptr); CellLocation location; location.cell = dof_cell; location.reference_point = xi; return location; } #endif // !CELLS_H