mirror of
https://codeberg.org/vcbferreira/NuFI_deal.ii
synced 2026-08-12 14:33:18 +02:00
eval with point_value() working
This commit is contained in:
+107
-167
@@ -1,35 +1,79 @@
|
||||
#ifndef FIELDS_H
|
||||
#define FIELDS_H
|
||||
|
||||
#include "nufi/parameters.h"
|
||||
#include "poisson_problem.h"
|
||||
#include <cmath>
|
||||
#include <deal.II/base/function.h>
|
||||
#include "nufi/parameters.h"
|
||||
#include "nufi/splines.h"
|
||||
#include "nufi/lsmr.h"
|
||||
#include <deal.II/base/point.h>
|
||||
|
||||
using namespace dealii;
|
||||
|
||||
inline double f0(const double x,
|
||||
const double v,
|
||||
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 double f0(const double x, const double v,
|
||||
const double eps = Parameters::EPS,
|
||||
const double k = Parameters::WAVE_NR)
|
||||
{
|
||||
const double prefactor = Parameters::F0_FACTOR * (1.0 + eps * std::cos(k*x));
|
||||
const double gaussian = v*v * std::exp(-0.5 * v*v);
|
||||
const double k = Parameters::WAVE_NR) {
|
||||
const double prefactor =
|
||||
Parameters::F0_FACTOR * (1.0 + eps * std::cos(k * x));
|
||||
const double gaussian = v * v * std::exp(-0.5 * v * v);
|
||||
|
||||
return prefactor * gaussian;
|
||||
}
|
||||
|
||||
|
||||
inline double compute_rho(const double x,
|
||||
const unsigned int Nv = Parameters::NV)
|
||||
{
|
||||
const double dv = (Parameters::V_DOMAIN_RIGHT - Parameters::V_DOMAIN_LEFT) / Nv;
|
||||
const unsigned int Nv = Parameters::NV) {
|
||||
const double dv =
|
||||
(Parameters::V_DOMAIN_RIGHT - Parameters::V_DOMAIN_LEFT) / Nv;
|
||||
|
||||
double integral = 0.0;
|
||||
|
||||
for (unsigned int i = 0; i < Nv; ++i)
|
||||
{
|
||||
for (unsigned int i = 0; i < Nv; ++i) {
|
||||
const double v = Parameters::V_DOMAIN_LEFT + (i + 0.5) * dv;
|
||||
integral += f0(x, v) * dv;
|
||||
}
|
||||
@@ -37,185 +81,82 @@ inline double compute_rho(const double x,
|
||||
return 1.0 - integral;
|
||||
}
|
||||
|
||||
|
||||
template <size_t dx = 0>
|
||||
double eval(double x, const double *coeffs) noexcept
|
||||
{
|
||||
using std::floor;
|
||||
|
||||
// Shift to a box that starts at 0.
|
||||
x -= Parameters::X_DOMAIN_LEFT;
|
||||
|
||||
// Get "periodic position" in box at origin.
|
||||
x = x - Parameters::LX * floor( x*Parameters::LX_INV );
|
||||
|
||||
// Knot number
|
||||
double x_knot = floor( x*Parameters::SPLINE_DX_INV);
|
||||
|
||||
size_t ii = static_cast<size_t>(x_knot);
|
||||
|
||||
// Convert x to reference coordinates.
|
||||
x = x*Parameters::SPLINE_DX_INV - x_knot;
|
||||
|
||||
// Scale according to derivative.
|
||||
double factor = 1;
|
||||
for ( size_t i = 0; i < dx; ++i ) factor *= 1*Parameters::SPLINE_DX_INV;
|
||||
|
||||
return factor*splines1d::eval<double,Parameters::SPLINE_ORDER,dx>(x, coeffs + ii);
|
||||
double eval(double x, const PoissonProblem<1> &poisson) noexcept {
|
||||
return poisson.evaluate_potential(Point<1>(x));
|
||||
}
|
||||
|
||||
template <typename real, size_t order>
|
||||
void interpolate( real *coeffs, const real *values)
|
||||
{
|
||||
std::unique_ptr<real[]> tmp { new real[ Parameters::SPLINE_NX ] };
|
||||
|
||||
for ( size_t i = 0; i < Parameters::SPLINE_NX; ++i )
|
||||
tmp[ i ] = coeffs[ i ];
|
||||
|
||||
struct mat_t
|
||||
{
|
||||
real N[ order ];
|
||||
|
||||
mat_t()
|
||||
{
|
||||
splines1d::N<real,order>(0,N);
|
||||
}
|
||||
|
||||
void operator()( const real *in, real *out ) const
|
||||
{
|
||||
#pragma omp parallel for
|
||||
for ( size_t i = 0; i < Parameters::SPLINE_NX; ++i )
|
||||
{
|
||||
real result = 0;
|
||||
if ( i + order <= Parameters::SPLINE_NX )
|
||||
{
|
||||
for ( size_t ii = 0; ii < order; ++ii )
|
||||
result += N[ii] * in[ i + ii ];
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( size_t ii = 0; ii < order; ++ii )
|
||||
result += N[ii]*in[ (i+ii) % Parameters::SPLINE_NX];
|
||||
}
|
||||
out[ i ] = result;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct transposed_mat_t
|
||||
{
|
||||
real N[ order ];
|
||||
|
||||
transposed_mat_t()
|
||||
{
|
||||
splines1d::N<real,order>(0,N);
|
||||
}
|
||||
|
||||
void operator()( const real *in, real *out ) const
|
||||
{
|
||||
for ( size_t i = 0; i < Parameters::SPLINE_NX; ++i )
|
||||
out[ i ] = 0;
|
||||
|
||||
for ( size_t i = 0; i < Parameters::SPLINE_NX; ++i )
|
||||
{
|
||||
if ( i + order <= Parameters::SPLINE_NX )
|
||||
{
|
||||
for ( size_t ii = 0; ii < order; ++ii )
|
||||
out[ i + ii ] += N[ii] * in[ i ];
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( size_t ii = 0; ii < order; ++ii )
|
||||
out[ (i+ii) % Parameters::SPLINE_NX ] += N[ii]*in[ i ];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mat_t M; transposed_mat_t Mt;
|
||||
lsmr_options<real> opt; opt.silent = true;
|
||||
lsmr( Parameters::SPLINE_NX, Parameters::SPLINE_NX , M, Mt, values, tmp.get(), opt );
|
||||
|
||||
if ( opt.iter == opt.max_iter )
|
||||
std::cerr << "Warning. LSMR did not converge.\n";
|
||||
|
||||
for ( size_t i = 0; i < Parameters::SPLINE_NX + order - 1; ++i )
|
||||
coeffs[ i ] = tmp[ i % Parameters::SPLINE_NX ];
|
||||
}
|
||||
|
||||
inline double integral_space_vector(const double *current_coeffs, double dx = Parameters::SPLINE_DX, size_t Nx = Parameters::SPLINE_NX)
|
||||
{
|
||||
inline double integral_space_vector(const PoissonProblem<1> &poisson,
|
||||
double dx = Parameters::PLOT_DX,
|
||||
size_t Nx = Parameters::PLOT_NX) {
|
||||
double integral = 0.0;
|
||||
double xmin = Parameters::X_DOMAIN_LEFT;
|
||||
#pragma omp parallel for reduction (+:integral)
|
||||
for (size_t i=0; i<Nx ; ++i) {
|
||||
#pragma omp parallel for reduction(+ : integral)
|
||||
for (size_t i = 0; i < Nx; ++i) {
|
||||
double x = xmin + i * dx;
|
||||
integral += eval<1>(x, current_coeffs);
|
||||
integral += eval(x, poisson);
|
||||
}
|
||||
return integral*dx;
|
||||
return integral * dx;
|
||||
};
|
||||
|
||||
inline double integral_space_vector_squared(const double *current_coeffs, double dx = Parameters::SPLINE_DX, size_t Nx = Parameters::SPLINE_NX)
|
||||
{
|
||||
inline double integral_space_vector_squared(const PoissonProblem<1> &poisson,
|
||||
double dx = Parameters::PLOT_DX,
|
||||
size_t Nx = Parameters::PLOT_NX) {
|
||||
double integral = 0.0;
|
||||
double xmin = Parameters::X_DOMAIN_LEFT;
|
||||
#pragma omp parallel for reduction (+:integral)
|
||||
for (size_t i=0; i<Nx ; ++i) {
|
||||
double x = xmin + i*dx;
|
||||
double val = eval<1>(x, current_coeffs);
|
||||
integral += val*val;
|
||||
#pragma omp parallel for reduction(+ : integral)
|
||||
for (size_t i = 0; i < Nx; ++i) {
|
||||
double x = xmin + i * dx;
|
||||
double val = eval(x, poisson);
|
||||
integral += val * val;
|
||||
}
|
||||
return integral*dx;
|
||||
return integral * dx;
|
||||
};
|
||||
|
||||
class Gradient {
|
||||
public:
|
||||
Gradient(double xmin, double xmax, unsigned int Nx)
|
||||
: xmin_(xmin), xmax_(xmax), Nx_(Nx)
|
||||
{
|
||||
if (xmax_ <= xmin_) {
|
||||
throw std::invalid_argument("xmax must be greater than xmin");
|
||||
}
|
||||
Gradient(double xmin, double xmax, unsigned int Nx)
|
||||
: xmin_(xmin), xmax_(xmax), Nx_(Nx) {
|
||||
if (xmax_ <= xmin_) {
|
||||
throw std::invalid_argument("xmax must be greater than xmin");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<double> compute(const std::vector<double> &values) const {
|
||||
size_t n = values.size();
|
||||
if (n < 2) {
|
||||
throw std::invalid_argument("Need at least 2 points");
|
||||
}
|
||||
|
||||
std::vector<double> compute(const std::vector<double>& values) const {
|
||||
size_t n = values.size();
|
||||
if (n < 2) {
|
||||
throw std::invalid_argument("Need at least 2 points");
|
||||
}
|
||||
std::vector<double> grad(n);
|
||||
|
||||
std::vector<double> grad(n);
|
||||
double dx = (xmax_ - xmin_) / (n - 1);
|
||||
// periodic boundaries
|
||||
grad[0] = -(values[1] - values[n - 1]) / (2.0 * dx);
|
||||
grad[n - 1] = -(values[0] - values[n - 2]) / (2.0 * dx);
|
||||
|
||||
double dx = (xmax_ - xmin_) / (n-1);
|
||||
// periodic boundaries
|
||||
grad[0] = -(values[1] - values[n-1]) / (2.0 * dx);
|
||||
grad[n-1] = -(values[0] - values[n-2]) / (2.0 * dx);
|
||||
|
||||
for (size_t i = 1; i < n-1; ++i) {
|
||||
grad[i] = -(values[i+1] - values[i-1]) / (2.0 * dx);
|
||||
}
|
||||
|
||||
|
||||
return grad;
|
||||
for (size_t i = 1; i < n - 1; ++i) {
|
||||
grad[i] = -(values[i + 1] - values[i - 1]) / (2.0 * dx);
|
||||
}
|
||||
|
||||
return grad;
|
||||
}
|
||||
|
||||
private:
|
||||
double xmin_;
|
||||
double xmax_;
|
||||
[[maybe_unused]] unsigned int Nx_;
|
||||
double xmin_;
|
||||
double xmax_;
|
||||
[[maybe_unused]] unsigned int Nx_;
|
||||
};
|
||||
|
||||
template <int dim>
|
||||
class ChargeDensity : public Function<dim> // only uses f0
|
||||
{
|
||||
public:
|
||||
ChargeDensity(double eps,
|
||||
double k,
|
||||
unsigned int Nv)
|
||||
: Function<dim>(1), eps(eps), k(k), Nv(Nv) {}
|
||||
ChargeDensity(double eps, double k, unsigned int Nv)
|
||||
: Function<dim>(1), eps(eps), k(k), Nv(Nv) {}
|
||||
|
||||
virtual double value(const Point<dim> &p,
|
||||
[[maybe_unused]] const unsigned int component = 0) const override
|
||||
{
|
||||
virtual double
|
||||
value(const Point<dim> &p,
|
||||
[[maybe_unused]] const unsigned int component = 0) const override {
|
||||
return compute_rho(p[0], Nv);
|
||||
}
|
||||
|
||||
@@ -225,5 +166,4 @@ private:
|
||||
const unsigned int Nv;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user