new paradigm, grids saved when changed old solutions not interpolated to new grids

This commit is contained in:
Vasco C. B. Ferreira
2026-07-09 19:23:15 +02:00
parent 47d7540961
commit 43eec84c40
9 changed files with 219 additions and 154 deletions
+2
View File
@@ -6,7 +6,9 @@
#include <deal.II/base/geometry_info.h>
#include <deal.II/base/point.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/fe/mapping_q.h>
#include <deal.II/grid/tria.h>
#include <memory>
#include <vector>
using namespace dealii;
+7 -54
View File
@@ -1,6 +1,7 @@
#ifndef FIELDS_H
#define FIELDS_H
#include "grids.h"
#include "nufi/parameters.h"
#include "nufi/poisson_problem.h"
#include <cmath>
@@ -11,54 +12,6 @@
using namespace dealii;
// inline std::vector<int> Indices_of_points(const std::vector<double> &points,
// double x_min, double x_max, double dx, int grid_type=0)
// {
// // grid type:
// // 0 => uniform
// // 1 => non uniform (TODO)
//
// if (dx <= 0.0) {
// throw std::invalid_argument("dx must be positive");
// }
// if (x_max <= x_min) {
// throw std::invalid_argument("x_max must be > x_min");
// }
//
// std::vector<int> indices;
// indices.reserve(points.size());
//
// switch (grid_type) {
// case 0:
// {
// const double L = x_max - x_min;
// const int N = std::floor(L/dx);
//
//
// for (double x : points) //GPT loop, to check
// {
// x-= x_min;
// x = x - L * std::floor(x/L);
//
// int i = static_cast<int>(std::floor(x / dx));
//
// // safety: handle rare edge case due to floating precision
// if (i == N) i = 0;
//
// indices.push_back(i);
// }
// }
// case 1:
// {
// throw std::invalid_argument("Case for non uniform grid is not
// completed");
// }
// default:
// throw std::invalid_argument("Invalid grid_type argument");
//
// }
// return indices;
// }
inline std::vector<double> make_x_eval(size_t Nx) {
std::vector<double> x_eval(Nx);
const double dx = Parameters::LX / Nx;
@@ -86,7 +39,7 @@ inline double f0(const double x, const double v,
// wrapper for eval_point() { VectorTools::point_values() }
inline std::vector<double> eval(std::vector<double> &X,
const PoissonProblem<1> &poisson,
const GridStructure<1> &grid,
const Vector<double> &solution) noexcept {
size_t x_size = X.size();
std::vector<double> evals(x_size);
@@ -99,10 +52,10 @@ inline std::vector<double> eval(std::vector<double> &X,
Points[i][0] = X[i];
}
return poisson.eval_vector_grad(solution, Points);
return grid.eval_vector_grad(solution, Points);
}
inline double integral_space_vector(const PoissonProblem<1> &poisson,
inline double integral_space_vector(const GridStructure<1> &grid,
const Vector<double> &solution,
double dx = Parameters::PLOT_DX,
size_t Nx = Parameters::PLOT_NX) {
@@ -112,13 +65,13 @@ inline double integral_space_vector(const PoissonProblem<1> &poisson,
for (size_t i = 0; i < Nx; ++i)
x_eval[i] = xmin + i * dx;
std::vector<double> tmp = eval(x_eval, poisson, solution);
std::vector<double> tmp = eval(x_eval, grid, solution);
for (size_t i = 0; i < Nx; ++i)
integral += tmp[i];
return integral * dx;
};
inline double integral_space_vector_squared(const PoissonProblem<1> &poisson,
inline double integral_space_vector_squared(const GridStructure<1> &grid,
const Vector<double> &solution,
double dx = Parameters::PLOT_DX,
size_t Nx = Parameters::PLOT_NX) {
@@ -128,7 +81,7 @@ inline double integral_space_vector_squared(const PoissonProblem<1> &poisson,
for (size_t i = 0; i < Nx; ++i)
x_eval[i] = xmin + i * dx;
std::vector<double> tmp = eval(x_eval, poisson, solution);
std::vector<double> tmp = eval(x_eval, grid, solution);
for (size_t i = 0; i < Nx; ++i)
integral += tmp[i] * tmp[i];
return integral * dx;
+116
View File
@@ -0,0 +1,116 @@
#ifndef GRIDS_H
#define GRIDS_H
#include "nufi/cells.h"
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/fe/mapping_q.h>
#include <deal.II/grid/tria.h>
#include <deal.II/matrix_free/fe_point_evaluation.h>
#include <memory>
#include <vector>
using namespace dealii;
template <int dim> class PoissonProblem;
template <int dim> struct GridStructure {
//==//==//
// Vars //
//==//==//
std::unique_ptr<Triangulation<dim>> triangulation;
std::unique_ptr<DoFHandler<dim>> dof_handler;
std::unique_ptr<MappingQ<dim>> mapping;
std::unique_ptr<FE_Q<dim>> fe;
CellLocator<dim> locator;
unsigned int grid_version;
// === // === //
// Evaluator //
// === // === //
std::vector<double>
eval_vector_grad(const Vector<double> &solution,
const std::vector<Point<dim>> &points) const {
std::vector<double> values(points.size());
#pragma omp parallel
{
std::vector<double> local_solution_buffer(fe->n_dofs_per_cell());
FEPointEvaluation<dim, dim> evaluator(*mapping, *fe, update_gradients);
#pragma omp for
for (unsigned int p = 0; p < points.size(); ++p) {
const auto cell_location = locator.locate(points[p]);
cell_location.info->cell->get_dof_values(solution,
local_solution_buffer.begin(),
local_solution_buffer.end());
evaluator.reinit(
cell_location.info->cell,
ArrayView<const Point<dim>>(&cell_location.reference_point, 1));
evaluator.evaluate(local_solution_buffer, EvaluationFlags::gradients);
values[p] = evaluator.get_gradient(0)[0];
}
}
return values;
}
};
template <int dim>
GridStructure<dim> make_grid_snapshot(const PoissonProblem<dim> &poisson) {
GridStructure<dim> grid;
grid.grid_version = 0;
grid.triangulation = std::make_unique<Triangulation<dim>>();
grid.triangulation->copy_triangulation(poisson.get_triangulation());
grid.mapping = std::make_unique<MappingQ<dim>>(poisson.get_mapping());
grid.dof_handler = std::make_unique<DoFHandler<dim>>(*grid.triangulation);
grid.dof_handler->distribute_dofs(poisson.get_dof_handler().get_fe());
grid.locator.rebuild(*grid.dof_handler, *grid.triangulation);
grid.fe = std::make_unique<FE_Q<dim>>(poisson.get_fe());
return grid;
}
template <int dim> struct SolutionSnapshot {
unsigned int grid_version;
Vector<double> solution;
};
template <int dim>
inline void update_grid_versions(std::vector<GridStructure<dim>> &grid_versions,
PoissonProblem<dim> &poisson) {
auto grid = make_grid_snapshot(poisson);
if (!grid_versions.empty())
grid.grid_version = grid_versions.back().grid_version + 1;
grid_versions.push_back(std::move(grid));
}
template <int dim>
inline void
update_solution_history(std::vector<SolutionSnapshot<dim>> &solution_history,
PoissonProblem<dim> &poisson,
unsigned int current_grid_version) {
SolutionSnapshot<dim> snapshot;
snapshot.grid_version = current_grid_version;
Vector<double> solution = poisson.get_solution();
snapshot.solution = solution;
solution_history.push_back(std::move(snapshot));
}
#endif // !GRIDS_H
+10 -8
View File
@@ -9,6 +9,7 @@
#include <vector>
#include "nufi/fields.h" //dont remove
#include "nufi/grids.h"
#include "nufi/parameters.h"
#include "nufi/poisson_problem.h"
@@ -19,18 +20,19 @@ public:
NuFISolver();
void run();
std::vector<double> eval_rho(unsigned int n, std::vector<double> &x,
const PoissonProblem<1> &poisson,
const std::vector<Vector<double>> &phi_history,
const unsigned int Nv = Parameters::NV) const;
std::vector<double>
eval_rho(unsigned int n, std::vector<double> &x,
const std::vector<GridStructure<1>> &grid_struct,
const std::vector<SolutionSnapshot<1>> &phi_history,
const unsigned int Nv = Parameters::NV) const;
std::vector<double>
eval_ftilda(unsigned int, std::vector<double> &x, double u,
const PoissonProblem<1> &poisson,
const std::vector<Vector<double>> &phi_history) const;
const std::vector<GridStructure<1>> &grid_struct,
const std::vector<SolutionSnapshot<1>> &phi_history) const;
std::vector<double>
eval_f(unsigned int n, std::vector<double> &x, double u,
const PoissonProblem<1> &poisson,
const std::vector<Vector<double>> &phi_history) const;
const std::vector<GridStructure<1>> &grid_struct,
const std::vector<SolutionSnapshot<1>> &phi_history) const;
private:
unsigned int Nt = std::floor(Parameters::TMAX / Parameters::DT);
+17 -49
View File
@@ -54,7 +54,9 @@
#include <vector>
#include "nufi/cells.h"
#include "nufi/grids.h"
#include "nufi/parameters.h"
#include "omp.h"
using namespace dealii;
@@ -66,8 +68,7 @@ public:
void initialize();
void solve_step();
void coarse_and_refine_grid(size_t it,
std::vector<Vector<double>> &solution_history);
void coarse_and_refine_grid(size_t it);
void run();
unsigned int get_rhs_size();
@@ -78,6 +79,9 @@ public:
const Vector<double> &get_solution() const { return solution; }
const MappingQ<dim> &get_mapping() const { return mapping; }
const DoFHandler<dim> &get_dof_handler() const { return dof_handler; }
const Triangulation<dim> &get_triangulation() const { return triangulation; }
const FE_Q<dim> &get_fe() const { return fe; }
const CellLocator<dim> &get_locator() const { return cell_locator; }
std::vector<double> sample_electric_field(double x_min, double x_max,
unsigned int Nx);
@@ -117,8 +121,8 @@ private:
MappingQ<dim> mapping;
mutable std::vector<double> local_solution_buffer;
mutable std::unique_ptr<FEPointEvaluation<dim, dim>> evaluator;
// mutable std::vector<double> local_solution_buffer;
// mutable std::unique_ptr<FEPointEvaluation<dim, dim>> evaluator;
};
//====//====//
@@ -211,31 +215,6 @@ PoissonProblem<dim>::sample_electric_potential(double x_min, double x_max,
return values;
}
template <int dim>
std::vector<double> PoissonProblem<dim>::eval_vector_grad(
const Vector<double> &solution,
const std::vector<Point<dim>> &points) const {
std::vector<double> values(points.size());
for (unsigned int p = 0; p < points.size(); ++p) {
const auto cell_location = cell_locator.locate(points[p]);
cell_location.info->cell->get_dof_values(
solution, local_solution_buffer.begin(), local_solution_buffer.end());
evaluator->reinit(
cell_location.info->cell,
ArrayView<const Point<dim>>(&cell_location.reference_point, 1));
evaluator->evaluate(local_solution_buffer, EvaluationFlags::gradients);
values[p] = evaluator->get_gradient(0)[0];
}
return values;
}
template <int dim>
std::vector<double>
eval_point_grad(const Mapping<dim> &mapping, const DoFHandler<dim> &dof_handler,
@@ -347,9 +326,9 @@ template <int dim> void PoissonProblem<dim>::setup_system() {
// used for evaluator to avoid running it anytime there is an eval
cell_locator.rebuild(dof_handler, triangulation);
local_solution_buffer.resize(fe.n_dofs_per_cell());
evaluator = std::make_unique<FEPointEvaluation<dim, dim>>(mapping, fe,
update_gradients);
// local_solution_buffer.resize(fe.n_dofs_per_cell());
// evaluator = std::make_unique<FEPointEvaluation<dim, dim>>(mapping, fe,
// update_gradients);
}
// Paul
@@ -402,9 +381,7 @@ template <int dim> void PoissonProblem<dim>::assemble_system() {
}
}
template <int dim>
void PoissonProblem<dim>::coarse_and_refine_grid(
size_t it, std::vector<Vector<double>> &solution_history) {
template <int dim> void PoissonProblem<dim>::coarse_and_refine_grid(size_t it) {
std::cout << "Refinement Started" << "\n";
Vector<float> error_per_cell(triangulation.n_active_cells());
@@ -417,29 +394,20 @@ void PoissonProblem<dim>::coarse_and_refine_grid(
0.3, 0.03);
triangulation.prepare_coarsening_and_refinement();
SolutionTransfer<dim, Vector<double>> transfer(dof_handler);
transfer.prepare_for_coarsening_and_refinement(solution_history);
const Vector<double> refined_solution = solution;
transfer.prepare_for_coarsening_and_refinement(refined_solution);
triangulation.execute_coarsening_and_refinement();
setup_system();
std::vector<Vector<double>> new_solution_history(solution_history.size());
for (auto &vec : new_solution_history)
vec.reinit(dof_handler.n_dofs());
transfer.interpolate(solution_history, new_solution_history);
solution_history.swap(new_solution_history);
solution = solution_history.back();
transfer.interpolate(refined_solution, solution);
constraints.distribute(solution);
// cell_locator.rebuild(dof_handler, triangulation); // No need to be called
// again because its in setup_system();
std::cout << "Refinement Finished" << "\n";
std::string grid_file_name =
+8 -6
View File
@@ -1,23 +1,25 @@
#ifndef SAVE_RESULTS_H
#define SAVE_RESULTS_H
#include "nufi/grids.h"
#include "nufi/nufi_solver.h"
#include "nufi/poisson_problem.h"
#include <deal.II/lac/vector.h>
#include <string>
#include <vector>
void save_f(const NuFISolver &solver, unsigned int n,
const PoissonProblem<1> &poisson,
const std::vector<Vector<double>> &phi_history, unsigned int Nx_out,
std::vector<GridStructure<1>> &grid_struct,
std::vector<SolutionSnapshot<1>> &phi_history, unsigned int Nx_out,
unsigned int Nv_out, const std::string &filename);
void save_rho(const NuFISolver &solver, unsigned int n,
const PoissonProblem<1> &poisson,
const std::vector<Vector<double>> &phi_history,
std::vector<GridStructure<1>> &grid_struct,
std::vector<SolutionSnapshot<1>> &phi_history,
unsigned int Nx_out, const std::string &filename);
void save_Efield(unsigned int n, const PoissonProblem<1> &poisson,
const std::vector<Vector<double>> &phi_history,
void save_Efield(unsigned int n, GridStructure<1> &grid_struct,
std::vector<SolutionSnapshot<1>> &phi_history,
unsigned int Nx_out, const std::string &filename);
void save_space_vector(const std::vector<double> &vals,