mirror of
https://codeberg.org/vcbferreira/NuFI_deal.ii
synced 2026-08-12 22:43:17 +02:00
locator with refinement tree implemented, to test
This commit is contained in:
+106
-65
@@ -2,116 +2,157 @@
|
|||||||
#define CELLS_H
|
#define CELLS_H
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <boost/geometry/geometries/concepts/point_concept.hpp>
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include <deal.II/base/exceptions.h>
|
||||||
#include <deal.II/base/geometry_info.h>
|
#include <deal.II/base/geometry_info.h>
|
||||||
#include <deal.II/base/point.h>
|
#include <deal.II/base/point.h>
|
||||||
#include <deal.II/dofs/dof_handler.h>
|
#include <deal.II/dofs/dof_handler.h>
|
||||||
#include <deal.II/fe/mapping_q.h>
|
|
||||||
#include <deal.II/grid/tria.h>
|
#include <deal.II/grid/tria.h>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
using namespace dealii;
|
using namespace dealii;
|
||||||
|
|
||||||
template <int dim> struct CellInfo {
|
// Current Locator needs Grid to be a hypercube !!
|
||||||
// what needs to be given to evaluator
|
|
||||||
typename DoFHandler<dim>::active_cell_iterator cell;
|
|
||||||
// for locator
|
|
||||||
Point<dim> lower;
|
|
||||||
Point<dim> upper;
|
|
||||||
double h;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int dim> struct CellLocation {
|
template <int dim> struct CellLocation {
|
||||||
const CellInfo<dim> *info;
|
using CellIterator = typename DoFHandler<dim>::cell_iterator;
|
||||||
|
|
||||||
|
CellIterator cell;
|
||||||
Point<dim> reference_point;
|
Point<dim> reference_point;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int dim> class CellLocator {
|
template <int dim> class CellLocator {
|
||||||
public:
|
public:
|
||||||
using CellIterator = typename DoFHandler<dim>::active_cell_iterator;
|
|
||||||
|
|
||||||
void rebuild(const DoFHandler<dim> &dof_handler,
|
void rebuild(const DoFHandler<dim> &dof_handler,
|
||||||
const Triangulation<dim> &triangulation);
|
const Triangulation<dim> &triangulation);
|
||||||
CellLocation<dim> locate(const Point<dim> &p) const;
|
|
||||||
|
|
||||||
const std::vector<Point<dim>> &get_cell_centers() const;
|
CellLocation<dim> locate(const Point<dim> &point) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<CellInfo<dim>> cells;
|
const DoFHandler<dim> *dof_handler_ = nullptr;
|
||||||
std::vector<Point<dim>> cell_centers;
|
|
||||||
|
Point<dim> domain_lower_;
|
||||||
|
Point<dim> domain_upper_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int dim>
|
template <int dim>
|
||||||
void CellLocator<dim>::rebuild(const DoFHandler<dim> &dof_handler,
|
void CellLocator<dim>::rebuild(const DoFHandler<dim> &dof_handler,
|
||||||
const Triangulation<dim> &triangulation) {
|
const Triangulation<dim> &triangulation) {
|
||||||
|
AssertThrow(&dof_handler.get_triangulation() == &triangulation,
|
||||||
|
ExcMessage("CellLocator::rebuild(): DoFHandler and Triangulation "
|
||||||
|
"do not refer to the same mesh."));
|
||||||
|
|
||||||
cells.clear();
|
auto root = dof_handler.begin(0);
|
||||||
cells.reserve(triangulation.n_active_cells());
|
|
||||||
|
|
||||||
for (const auto &cell : dof_handler.active_cell_iterators()) {
|
AssertThrow(
|
||||||
CellInfo<dim> info;
|
root != dof_handler.end(0),
|
||||||
|
ExcMessage("CellLocator::rebuild(): triangulation has no level-zero "
|
||||||
|
"cell."));
|
||||||
|
|
||||||
info.cell = cell;
|
auto after_root = root;
|
||||||
info.lower = cell->vertex(0);
|
++after_root;
|
||||||
info.upper = cell->vertex(GeometryInfo<dim>::vertices_per_cell - 1);
|
|
||||||
|
|
||||||
info.h = info.upper[0] - info.lower[0];
|
AssertThrow(
|
||||||
|
after_root == dof_handler.end(0),
|
||||||
|
ExcMessage("CellLocator currently requires exactly one coarse cell."));
|
||||||
|
|
||||||
cells.push_back(info);
|
dof_handler_ = &dof_handler;
|
||||||
|
|
||||||
|
for (unsigned int d = 0; d < dim; ++d) {
|
||||||
|
domain_lower_[d] = std::numeric_limits<double>::max();
|
||||||
|
domain_upper_[d] = std::numeric_limits<double>::lowest();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(cells.begin(), cells.end(),
|
for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
|
||||||
[](const CellInfo<dim> &a, const CellInfo<dim> &b) {
|
for (unsigned int d = 0; d < dim; ++d) {
|
||||||
return a.lower[0] < b.lower[0];
|
domain_lower_[d] = std::min(domain_lower_[d], root->vertex(v)[d]);
|
||||||
});
|
|
||||||
|
|
||||||
cell_centers.clear();
|
domain_upper_[d] = std::max(domain_upper_[d], root->vertex(v)[d]);
|
||||||
cell_centers.reserve(cells.size());
|
}
|
||||||
|
|
||||||
for (const auto &cell : cells) {
|
for (unsigned int d = 0; d < dim; ++d) {
|
||||||
Point<dim> center;
|
const double length = domain_upper_[d] - domain_lower_[d];
|
||||||
for (unsigned int d = 0; d < dim; ++d)
|
|
||||||
center[d] = 0.5 * (cell.lower[d] + cell.upper[d]);
|
|
||||||
|
|
||||||
cell_centers.push_back(center);
|
AssertThrow(length > 0.0,
|
||||||
|
ExcMessage("CellLocator::rebuild(): coarse-cell domain has "
|
||||||
|
"non-positive extent."));
|
||||||
|
|
||||||
|
const double scale =
|
||||||
|
std::max({1.0, std::abs(domain_lower_[d]), std::abs(domain_upper_[d])});
|
||||||
|
|
||||||
|
const double tolerance =
|
||||||
|
100.0 * std::numeric_limits<double>::epsilon() * scale;
|
||||||
|
|
||||||
|
for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v) {
|
||||||
|
const double coordinate = root->vertex(v)[d];
|
||||||
|
|
||||||
|
const bool lies_on_lower =
|
||||||
|
std::abs(coordinate - domain_lower_[d]) <= tolerance;
|
||||||
|
|
||||||
|
const bool lies_on_upper =
|
||||||
|
std::abs(coordinate - domain_upper_[d]) <= tolerance;
|
||||||
|
|
||||||
|
AssertThrow(
|
||||||
|
lies_on_lower || lies_on_upper,
|
||||||
|
ExcMessage(
|
||||||
|
"CellLocator requires an axis-aligned hypercube coarse cell."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int dim>
|
template <int dim>
|
||||||
CellLocation<dim> CellLocator<dim>::locate(const Point<dim> &p) const {
|
CellLocation<dim> CellLocator<dim>::locate(const Point<dim> &point) const {
|
||||||
static_assert(dim == 1,
|
AssertThrow(
|
||||||
"Current CellLocator implementation only supports 1D.");
|
dof_handler_ != nullptr,
|
||||||
|
ExcMessage("CellLocator::locate(): rebuild() has not been called."));
|
||||||
|
|
||||||
AssertThrow(!cells.empty(),
|
Point<dim> reference_point;
|
||||||
ExcMessage("CellLocator::rebuild() has not been called."));
|
|
||||||
|
|
||||||
const double x = p[0];
|
for (unsigned int d = 0; d < dim; ++d) {
|
||||||
|
const double length = domain_upper_[d] - domain_lower_[d];
|
||||||
|
|
||||||
auto it = std::upper_bound(cells.begin(), cells.end(), x,
|
const double shifted = point[d] - domain_lower_[d];
|
||||||
[](double value, const CellInfo<dim> &cell) {
|
|
||||||
return value < cell.lower[0];
|
|
||||||
}); // returns cell to the right of cell with x
|
|
||||||
|
|
||||||
if (it == cells.begin())
|
double periodic_offset = shifted - length * std::floor(shifted / length);
|
||||||
it = cells.begin();
|
|
||||||
else
|
|
||||||
--it;
|
|
||||||
|
|
||||||
// Safety check: make sure the point is really inside this cell
|
if (periodic_offset < 0.0)
|
||||||
AssertThrow(x >= it->lower[0] - 1e-12 && x <= it->upper[0] + 1e-12,
|
periodic_offset += length;
|
||||||
ExcMessage("CellLocator failed to find containing cell."));
|
|
||||||
|
|
||||||
CellLocation<dim> location;
|
if (periodic_offset >= length)
|
||||||
|
periodic_offset = 0.0;
|
||||||
|
|
||||||
location.info = &(*it);
|
reference_point[d] = periodic_offset / length;
|
||||||
location.reference_point[0] = (p[0] - it->lower[0]) / it->h;
|
}
|
||||||
|
|
||||||
return location;
|
auto cell = dof_handler_->begin(0);
|
||||||
|
|
||||||
|
while (cell->has_children()) {
|
||||||
|
AssertThrow(
|
||||||
|
cell->n_children() == GeometryInfo<dim>::max_children_per_cell,
|
||||||
|
ExcMessage(
|
||||||
|
"CellLocator currently supports isotropic refinement only."));
|
||||||
|
|
||||||
|
const unsigned int child_index =
|
||||||
|
GeometryInfo<dim>::child_cell_from_point(reference_point);
|
||||||
|
|
||||||
|
reference_point = GeometryInfo<dim>::cell_to_child_coordinates(
|
||||||
|
reference_point, child_index);
|
||||||
|
|
||||||
|
cell = cell->child(child_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertThrow(
|
||||||
|
cell->is_active(),
|
||||||
|
ExcMessage("CellLocator tree traversal did not finish on an active "
|
||||||
|
"cell."));
|
||||||
|
|
||||||
|
AssertThrow(
|
||||||
|
GeometryInfo<dim>::is_inside_unit_cell(reference_point, 1e-12),
|
||||||
|
ExcMessage(
|
||||||
|
"CellLocator produced a reference point outside the unit cell."));
|
||||||
|
|
||||||
|
return CellLocation<dim>{cell, reference_point};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int dim>
|
#endif // CELLS_H
|
||||||
const std::vector<Point<dim>> &CellLocator<dim>::get_cell_centers() const {
|
|
||||||
return cell_centers;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // !CELLS_H
|
|
||||||
|
|||||||
+6
-8
@@ -89,20 +89,18 @@ inline double f0(const double x, const double v,
|
|||||||
inline std::vector<double> eval(std::vector<double> &X,
|
inline std::vector<double> eval(std::vector<double> &X,
|
||||||
const GridStructure<1> &grid,
|
const GridStructure<1> &grid,
|
||||||
const Vector<double> &solution) noexcept {
|
const Vector<double> &solution) noexcept {
|
||||||
|
|
||||||
AssertThrow(grid.dof_handler->n_dofs() == solution.size(),
|
AssertThrow(grid.dof_handler->n_dofs() == solution.size(),
|
||||||
ExcMessage("@ eval(...) grid's number of DoFs doesn't correspond "
|
ExcMessage("@ eval(...) grid's number of DoFs doesn't correspond "
|
||||||
"to solution's size"));
|
"to solution's size"));
|
||||||
size_t x_size = X.size();
|
|
||||||
std::vector<Point<1>> Points(x_size);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < x_size; ++i) {
|
const size_t x_size = X.size();
|
||||||
X[i] = X[i] - Parameters::X_DOMAIN_LEFT;
|
std::vector<Point<1>> points(x_size);
|
||||||
X[i] = X[i] - Parameters::LX * std::floor(X[i] * Parameters::LX_INV);
|
|
||||||
|
|
||||||
Points[i][0] = X[i];
|
for (size_t i = 0; i < x_size; ++i)
|
||||||
}
|
points[i][0] = X[i];
|
||||||
|
|
||||||
return grid.eval_vector_grad(solution, Points);
|
return grid.eval_vector_grad(solution, points);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double integral_space_vector(const GridStructure<1> &grid,
|
inline double integral_space_vector(const GridStructure<1> &grid,
|
||||||
|
|||||||
+2
-2
@@ -72,12 +72,12 @@ template <int dim> struct GridStructure {
|
|||||||
|
|
||||||
const auto cell_location = locator->locate(points[p]);
|
const auto cell_location = locator->locate(points[p]);
|
||||||
|
|
||||||
cell_location.info->cell->get_dof_values(solution,
|
cell_location.cell->get_dof_values(solution,
|
||||||
local_solution_buffer.begin(),
|
local_solution_buffer.begin(),
|
||||||
local_solution_buffer.end());
|
local_solution_buffer.end());
|
||||||
|
|
||||||
evaluator.reinit(
|
evaluator.reinit(
|
||||||
cell_location.info->cell,
|
cell_location.cell,
|
||||||
ArrayView<const Point<dim>>(&cell_location.reference_point, 1));
|
ArrayView<const Point<dim>>(&cell_location.reference_point, 1));
|
||||||
|
|
||||||
evaluator.evaluate(local_solution_buffer, EvaluationFlags::gradients);
|
evaluator.evaluate(local_solution_buffer, EvaluationFlags::gradients);
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ constexpr double DV = std::abs(V_DOMAIN_RIGHT - V_DOMAIN_LEFT) / NV;
|
|||||||
// 1 -> landau-damping
|
// 1 -> landau-damping
|
||||||
// 2 -> maxwellian
|
// 2 -> maxwellian
|
||||||
// 3 -> bump-on-tail
|
// 3 -> bump-on-tail
|
||||||
constexpr size_t f0_TYPE = 3;
|
constexpr size_t f0_TYPE = 0;
|
||||||
|
|
||||||
// deal.ii options
|
// deal.ii options
|
||||||
constexpr unsigned int GLOBAL_REFINEMENT = 7;
|
constexpr unsigned int GLOBAL_REFINEMENT = 7;
|
||||||
|
|||||||
Reference in New Issue
Block a user