mirror of
https://codeberg.org/vcbferreira/NuFI_deal.ii
synced 2026-08-12 14:33:18 +02:00
advanced with new splines, updated readme todo
This commit is contained in:
@@ -7,4 +7,6 @@ This simulation of the Vlasov-Poisson system in 1x1v dimensions uses
|
|||||||
---
|
---
|
||||||
Todo:
|
Todo:
|
||||||
- Correct dealii solver, check ftilda results to see whats happening
|
- Correct dealii solver, check ftilda results to see whats happening
|
||||||
- ...
|
- implement least squares thingy
|
||||||
|
- marry it to fields interpolation
|
||||||
|
- make nufi solver use new spline interpolation and evaluation
|
||||||
|
|||||||
+109
@@ -35,6 +35,115 @@ inline double compute_rho(const double x,
|
|||||||
return 1.0 - integral;
|
return 1.0 - integral;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename real, size_t order, size_t dx = 0>
|
||||||
|
real eval( real x, const real *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 );
|
||||||
|
|
||||||
|
// Knot number
|
||||||
|
real x_knot = floor( x/Parameters::SPLINE_DX);
|
||||||
|
|
||||||
|
size_t ii = static_cast<size_t>(x_knot);
|
||||||
|
|
||||||
|
// Convert x to reference coordinates.
|
||||||
|
x = x/Parameters::SPLINE_DX - x_knot;
|
||||||
|
|
||||||
|
// Scale according to derivative.
|
||||||
|
real factor = 1;
|
||||||
|
for ( size_t i = 0; i < dx; ++i ) factor *= 1/Parameters::SPLINE_DX;
|
||||||
|
|
||||||
|
return factor*splines1d::eval<real,order,dx>( x, coeffs + ii );
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename real, size_t order>
|
||||||
|
void interpolate( real *coeffs, const real *values) // Least Squares needs to be made
|
||||||
|
{
|
||||||
|
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 // STRUCT AND CONFIG NEEDS TO BE REVIEWED
|
||||||
|
{
|
||||||
|
const config_t<real> &config;
|
||||||
|
real N[ order ];
|
||||||
|
|
||||||
|
mat_t( const config_t<real> &conf ): config { conf }
|
||||||
|
{
|
||||||
|
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 // STRUCT AND CONFIG NEEDS TO BE REVIEWED
|
||||||
|
{
|
||||||
|
const config_t<real> &config;
|
||||||
|
real N[ order ];
|
||||||
|
|
||||||
|
transposed_mat_t( const config_t<real> &conf ): config { conf }
|
||||||
|
{
|
||||||
|
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 { config }; transposed_mat_t Mt { config };
|
||||||
|
lsmr_options<real> opt; opt.silent = true;
|
||||||
|
lsmr( config.Nx, config.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 ];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <int dim>
|
template <int dim>
|
||||||
class ChargeDensity : public Function<dim> // only uses f0
|
class ChargeDensity : public Function<dim> // only uses f0
|
||||||
{
|
{
|
||||||
|
|||||||
+14
-13
@@ -15,7 +15,8 @@
|
|||||||
#include "parameters.hpp"
|
#include "parameters.hpp"
|
||||||
#include "poisson_problem.hpp"
|
#include "poisson_problem.hpp"
|
||||||
#include "fields.hpp" // holds f0(x,v), and compute_rho(x)
|
#include "fields.hpp" // holds f0(x,v), and compute_rho(x)
|
||||||
#include "spline_field.hpp"
|
#include "spline_field.hpp" // old GPT splines
|
||||||
|
#include "splines.hpp" //new splines
|
||||||
|
|
||||||
using namespace dealii;
|
using namespace dealii;
|
||||||
|
|
||||||
@@ -25,9 +26,9 @@ public:
|
|||||||
NuFISolver();
|
NuFISolver();
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
double eval_rho(unsigned int n, double x, const UniformSpline1D<double,4>& E_spline, unsigned int Nv = Parameters::NV);
|
double eval_rho(unsigned int n, double x, const std::vector<double> E_coeffs, unsigned int Nv = Parameters::NV);
|
||||||
double eval_ftilda(unsigned int n, double x, double u, const UniformSpline1D<double, 4>& E_spline);
|
double eval_ftilda(unsigned int n, double x, double u, const std::vector<double> E_coeffs);
|
||||||
void save_ftilda(unsigned int n, const UniformSpline1D<double,4>& E_spline, unsigned int Nx_out, unsigned int Nv_out, const std::string &filename);
|
void save_ftilda(unsigned int n, const std::vector<double> E_coeffs, unsigned int Nx_out, unsigned int Nv_out, const std::string &filename);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ private:
|
|||||||
inline double NuFISolver::eval_ftilda(unsigned int n,
|
inline double NuFISolver::eval_ftilda(unsigned int n,
|
||||||
double x,
|
double x,
|
||||||
double u,
|
double u,
|
||||||
const UniformSpline1D<double, 4>& E_spline)
|
const std::vector<double> E_coeffs)
|
||||||
{
|
{
|
||||||
double Lu = std::abs(Parameters::V_DOMAIN_LEFT - Parameters::V_DOMAIN_RIGHT);
|
double Lu = std::abs(Parameters::V_DOMAIN_LEFT - Parameters::V_DOMAIN_RIGHT);
|
||||||
|
|
||||||
@@ -78,7 +79,7 @@ inline double NuFISolver::eval_ftilda(unsigned int n,
|
|||||||
|
|
||||||
inline double NuFISolver::eval_rho(const unsigned int n,
|
inline double NuFISolver::eval_rho(const unsigned int n,
|
||||||
const double x,
|
const double x,
|
||||||
const UniformSpline1D<double, 4>& E_spline,
|
const std::vector<double> E_coeffs,
|
||||||
const unsigned int Nv)
|
const unsigned int Nv)
|
||||||
{
|
{
|
||||||
const double dv = (Parameters::V_DOMAIN_RIGHT - Parameters::V_DOMAIN_LEFT) / Nv;
|
const double dv = (Parameters::V_DOMAIN_RIGHT - Parameters::V_DOMAIN_LEFT) / Nv;
|
||||||
@@ -97,25 +98,25 @@ inline double NuFISolver::eval_rho(const unsigned int n,
|
|||||||
class ChargeDensity_NuFI : public Function<1>
|
class ChargeDensity_NuFI : public Function<1>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ChargeDensity_NuFI(NuFISolver &solver, size_t n, const UniformSpline1D<double,4> &E_spline)
|
ChargeDensity_NuFI(NuFISolver &solver, size_t n, const std::vector<double> E_coeffs)
|
||||||
: solver(solver), n(n), E_spline(E_spline) {}
|
: solver(solver), n(n), E_coeffs(E_coeffs) {}
|
||||||
|
|
||||||
virtual double value(const Point<1> &p,
|
virtual double value(const Point<1> &p,
|
||||||
[[maybe_unused]] const unsigned int component = 0) const override
|
[[maybe_unused]] const unsigned int component = 0) const override
|
||||||
{
|
{
|
||||||
double x = p[0];
|
double x = p[0];
|
||||||
|
|
||||||
return solver.eval_rho(n, x, E_spline);
|
return solver.eval_rho(n, x, E_coeffs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NuFISolver &solver;
|
NuFISolver &solver;
|
||||||
size_t n;
|
size_t n;
|
||||||
const UniformSpline1D<double, 4> &E_spline;
|
const std::vector<double> E_coeffs;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void NuFISolver::save_ftilda(unsigned int n,
|
inline void NuFISolver::save_ftilda(unsigned int n,
|
||||||
const UniformSpline1D<double,4>& E_spline,
|
const std::vector<double> E_coeffs,
|
||||||
unsigned int Nx_out,
|
unsigned int Nx_out,
|
||||||
unsigned int Nv_out,
|
unsigned int Nv_out,
|
||||||
const std::string &filename)
|
const std::string &filename)
|
||||||
@@ -176,7 +177,7 @@ inline void NuFISolver::run()
|
|||||||
E_grid[i] = 0;
|
E_grid[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UniformSpline1D<double,4> E_spline(E_grid, Parameters::X_DOMAIN_LEFT, Parameters::X_DOMAIN_RIGHT);
|
std::vector<double> E_coeffs(E_grid, Parameters::X_DOMAIN_LEFT, Parameters::X_DOMAIN_RIGHT); // Needs correction
|
||||||
|
|
||||||
for (unsigned int it = 0; it < Nt; ++it)
|
for (unsigned int it = 0; it < Nt; ++it)
|
||||||
{
|
{
|
||||||
@@ -212,7 +213,7 @@ inline void NuFISolver::run()
|
|||||||
|
|
||||||
E_grid = poisson.sample_electric_field(poisson, Nx, 0.0, Lx);
|
E_grid = poisson.sample_electric_field(poisson, Nx, 0.0, Lx);
|
||||||
|
|
||||||
E_spline = UniformSpline1D<double, 4>(E_grid, 0.0, Lx);
|
E_spline = std::vector<double> E_coeffs; // needs correction
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "NuFI simulation finished.\n";
|
std::cout << "NuFI simulation finished.\n";
|
||||||
|
|||||||
+3
-2
@@ -28,10 +28,11 @@ namespace Parameters
|
|||||||
constexpr unsigned int TMAX = 10;
|
constexpr unsigned int TMAX = 10;
|
||||||
|
|
||||||
//spline options
|
//spline options
|
||||||
constexpr int SPLINE_NX = 256;
|
constexpr int SPLINE_NX = 512;
|
||||||
|
constexpr double SPLINE_DX = LX/SPLINE_NX;
|
||||||
|
|
||||||
//Plotting options
|
//Plotting options
|
||||||
constexpr int PLOT_FREQUENCY = 3;
|
constexpr int PLOT_FREQUENCY = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
#ifndef SPLINES_HPP
|
||||||
|
#define SPLINES_HPP
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace splines1d
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename real>
|
||||||
|
constexpr real faculty( size_t n ) noexcept
|
||||||
|
{
|
||||||
|
return (n > 1) ? real(n)*faculty<real>(n-1) : real(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename real, size_t order, size_t derivative = 0>
|
||||||
|
void N( real x, real *result, size_t stride = 1 ) noexcept
|
||||||
|
{
|
||||||
|
static_assert( order > 0, "Splines must have order greater than zero." );
|
||||||
|
constexpr int n { order };
|
||||||
|
constexpr int d { derivative };
|
||||||
|
|
||||||
|
if ( derivative >= order )
|
||||||
|
for ( size_t i = 0; i < order; ++i )
|
||||||
|
result[ i*stride ] = 0;
|
||||||
|
|
||||||
|
if ( n == 1 )
|
||||||
|
{
|
||||||
|
*result = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
real v[n]; v[n-1] = 1;
|
||||||
|
for ( int k = 1; k < n - d; ++k )
|
||||||
|
{
|
||||||
|
v[n-k-1] = (1-x)*v[n-k];
|
||||||
|
|
||||||
|
for ( int i = 1-k; i < 0; ++i )
|
||||||
|
v[n-1+i] = (x-i)*v[n-1+i] + (k+1+i-x)*v[n+i];
|
||||||
|
|
||||||
|
v[n-1] *= x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Differentiate if necessary.
|
||||||
|
for ( size_t j = derivative; j-- > 0; )
|
||||||
|
{
|
||||||
|
v[j] = -v[j+1];
|
||||||
|
for ( size_t i = j + 1; i < order - 1; ++i )
|
||||||
|
v[i] = v[i] - v[i+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr real factor = real(1) / faculty<real>(order-derivative-1);
|
||||||
|
for ( size_t i = 0; i < order; ++i )
|
||||||
|
result[i*stride] = v[i]*factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename real, size_t order, size_t derivative = 0>
|
||||||
|
real eval( real x, const real *coefficients, size_t stride = 1 ) noexcept
|
||||||
|
{
|
||||||
|
static_assert( order > 0, "Splines must have order greater than zero." );
|
||||||
|
static_assert( order > derivative, "Too high derivative requested." );
|
||||||
|
constexpr size_t n { order };
|
||||||
|
constexpr size_t d { derivative };
|
||||||
|
|
||||||
|
if ( d >= n ) return 0;
|
||||||
|
if ( n == 1 ) return *coefficients;
|
||||||
|
|
||||||
|
// Gather coefficients.
|
||||||
|
real c[ order ];
|
||||||
|
for ( size_t j = 0; j < order; ++j )
|
||||||
|
c[j] = coefficients[ stride * j ];
|
||||||
|
|
||||||
|
// Differentiate if necessary.
|
||||||
|
for ( size_t j = 1; j <= d; ++j )
|
||||||
|
for ( size_t i = n; i-- > j; )
|
||||||
|
c[i] = c[i] - c[i-1];
|
||||||
|
|
||||||
|
// Evaluate using de Boor’s algorithm.
|
||||||
|
for ( size_t j = 1; j < n-d; ++j )
|
||||||
|
for ( size_t i = n-d; i-- > j; )
|
||||||
|
c[d+i] = (x+n-d-1-i)*c[d+i] + (i-j+1-x)*c[d+i-1];
|
||||||
|
|
||||||
|
constexpr real factor = real(1) / faculty<real>(order-derivative-1);
|
||||||
|
return factor*c[n-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user