Commit 1a6ed291 authored by incardon's avatar incardon
Browse files

Adding missing files

parent 1646fa57
/*
* Derivative.hpp
*
* Created on: Oct 5, 2015
* Author: i-bird
*/
#ifndef OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_DERIVATIVE_HPP_
#define OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_DERIVATIVE_HPP_
#define CENTRAL 0
#define CENTRAL_B_ONE_SIDE 1
#include "util/mathutil.hpp"
#include "Vector/map_vector.hpp"
#include "Grid/comb.hpp"
#include "FiniteDifference/util/common.hpp"
/*! \brief Derivative second order on h (spacing)
*
* \tparam d on which dimension derive
* \tparam Field which field derive
* \tparam impl which implementation
*
*/
template<unsigned int d, typename Field, typename Sys_eqs, unsigned int impl=CENTRAL>
class D
{
/*! \brief Create the row of the Matrix
*
* \tparam ord
*
*/
inline static std::unordered_map<long int,typename Sys_eqs::stype> value(grid_key_dx<Sys_eqs::dims> & pos, const grid_sm<Sys_eqs::dims,void> & gs)
{
std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " only CENTRAL, FORWARD, BACKWARD derivative are defined";
}
/*! \brief Calculate the position where the derivative is calculated
*
* In case on non staggered case this function just return pos, in case of staggered,
* it calculate where the operator is calculated on a staggered grid
*
*/
inline static grid_key_dx<Sys_eqs::dims> position(grid_key_dx<Sys_eqs::dims> & pos, const grid_sm<Sys_eqs::dims,void> & gs)
{
std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " only CENTRAL, FORWARD, BACKWARD derivative are defined";
}
};
/*! \brief Derivative on direction i
*
*
*/
template<unsigned int d, typename arg, typename Sys_eqs>
class D<d,arg,Sys_eqs,CENTRAL>
{
public:
/*! \brief fill the row
*
*
*/
inline static void value(grid_key_dx<Sys_eqs::dims> & pos, const grid_sm<Sys_eqs::dims,void> & gs, std::unordered_map<long int,typename Sys_eqs::stype > & cols, typename Sys_eqs::stype coeff)
{
// forward
if (Sys_eqs::boundary[d] == PERIODIC )
{
long int old_val = pos.get(d);
pos.set_d(d, openfpm::math::positive_modulo(pos.get(d) + 1, gs.size(d)));
arg::value(pos,gs,cols,coeff);
pos.set_d(d,old_val);
}
else
{
long int old_val = pos.get(d);
pos.set_d(d, pos.get(d) + 1);
arg::value(pos,gs,cols,coeff);
pos.set_d(d,old_val);
}
// backward
if (Sys_eqs::boundary[d] == PERIODIC )
{
long int old_val = pos.get(d);
pos.set_d(d, openfpm::math::positive_modulo(pos.get(d) - 1, gs.size(d)));
arg::value(pos,gs,cols,-coeff);
pos.set_d(d,old_val);
}
else
{
long int old_val = pos.get(d);
pos.set_d(d, pos.get(d) - 1);
arg::value(pos,gs,cols,-coeff);
pos.set_d(d,old_val);
}
}
/*! \brief Calculate the position where the derivative is calculated
*
* In case on non staggered case this function just return pos, in case of staggered,
* it calculate where the operator is calculated on a staggered grid
*
* \param pos from the position
* \param fld Field we are deriving, if not provided the function just return pos
* \param s_pos position of the properties in the staggered grid
*
*/
inline static grid_key_dx<Sys_eqs::dims> position(grid_key_dx<Sys_eqs::dims> & pos, long int fld = -1, const openfpm::vector<comb<Sys_eqs::dims>> & s_pos = openfpm::vector<comb<Sys_eqs::dims>>())
{
if (is_grid_staggered<Sys_eqs>::value())
{
if (fld == -1)
return pos;
if (s_pos[fld][d] == 1)
{
grid_key_dx<Sys_eqs::dims> ret = pos;
ret.set_d(d,0);
return pos;
}
else
{
grid_key_dx<Sys_eqs::dims> ret = pos;
ret.set_d(d,1);
return pos;
}
}
return pos;
}
};
/*! \brief Derivative on direction i
*
*
*/
template<unsigned int d, typename arg, typename Sys_eqs>
class D<d,arg,Sys_eqs,CENTRAL_B_ONE_SIDE>
{
public:
/*! \brief fill the row
*
*
*/
static void value(grid_key_dx<Sys_eqs::dims> & pos, const grid_sm<Sys_eqs::dims,void> & gs, std::unordered_map<long int,typename Sys_eqs::stype> & cols, typename Sys_eqs::stype coeff)
{
#ifdef SE_CLASS1
if (Sys_eqs::boundary[d] == PERIODIC)
std::cerr << __FILE__ << ":" << __LINE__ << " error, it make no sense use one sided derivation with periodic boundary\n";
#endif
if (pos.get(d) == (long int)gs.size(d)-1 )
{
arg::value(pos,gs,cols,1.5*coeff);
long int old_val = pos.get(d);
pos.set_d(d, pos.get(d) - 1);
arg::value(pos,gs,cols,-2.0*coeff);
pos.set_d(d,old_val);
old_val = pos.get(d);
pos.set_d(d, pos.get(d) - 2);
arg::value(pos,gs,cols,0.5*coeff);
pos.set_d(d,old_val);
}
else if (pos.get(d) == 0)
{
arg::value(pos,gs,cols,-1.5*coeff);
long int old_val = pos.get(d);
pos.set_d(d, pos.get(d) + 1);
arg::value(pos,gs,cols,2.0*coeff);
pos.set_d(d,old_val);
old_val = pos.get(d);
pos.set_d(d, pos.get(d) + 2);
arg::value(pos,gs,cols,-0.5*coeff);
pos.set_d(d,old_val);
}
else
{
long int old_val = pos.get(d);
pos.set_d(d, pos.get(d) + 1);
arg::value(pos,gs,cols,coeff);
pos.set_d(d,old_val);
old_val = pos.get(d);
pos.set_d(d, pos.get(d) - 1);
arg::value(pos,gs,cols,-coeff);
pos.set_d(d,old_val);
}
}
/*! \brief Calculate the position where the derivative is calculated
*
* In case on non staggered case this function just return pos, in case of staggered,
* it calculate where the operator is calculated on a staggered grid
*
*/
inline static grid_key_dx<Sys_eqs::dims> position(grid_key_dx<Sys_eqs::dims> & pos, long int fld = 0, const openfpm::vector<comb<Sys_eqs::dims>> & s_pos = openfpm::vector<comb<Sys_eqs::dims>>())
{
if (is_grid_staggered<Sys_eqs>::type::value)
{
if (fld == -1)
return pos;
if (s_pos[fld][d] == 1)
{
grid_key_dx<Sys_eqs::dims> ret = pos;
ret.set_d(d,0);
return pos;
}
else
{
grid_key_dx<Sys_eqs::dims> ret = pos;
ret.set_d(d,1);
return pos;
}
}
return pos;
}
};
#endif /* OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_DERIVATIVE_HPP_ */
/*
* FiniteDifferences.hpp
*
* Created on: Sep 17, 2015
* Author: i-bird
*/
#ifndef OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_FDSCHEME_HPP_
#define OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_FDSCHEME_HPP_
#include "Grid/grid_dist_id.hpp"
#include "Matrix/Matrix.hpp"
#include "eq.hpp"
/*! \brief Finite Differences
*
* \tparam dim Dimensionality of the finite differences scheme
*
*/
template<typename Sys_eqs>
class FDScheme
{
openfpm::vector<triplet<typename Sys_eqs::stype>> trpl;
/*! \brief Impose an operator
*
*
*
*/
/* template<typename T> void impose(T & op, grid_key_dx_dist_iterator_sub & it)
{
size_t lin = 0;
std::unordered_map<long int,float> cols;
// iterate all the grid points
while (it.isNext())
{
// get the position
auto key = it.get();
// convert into global coordinate the position
auto keyg = g.getGKey(key);
// Convert local key into global key
T::value(op,cols);
// create the triplet
for ( auto it = cols.begin(); it != cols.end(); ++it )
{
trpl.add();
trpl.last().i = lin;
trpl.last().j = it->first;
trpl.last().value = it->second;
}
std::cout << " " << it->first << ":" << it->second;
cols.clear();
++loc_cnt;
++it;
}
}*/
/*! \brief produce the Matrix
*
* \tparam Syst_eq System of equations, or a single equation
*
*/
template<typename Grid> SparseMatrix<typename Sys_eqs::stype> getMatrix(const Grid & g, const ConstField(& fld)[Sys_eqs::num_cfields::value] )
{
// iterate across the full domain
auto it = g.getDomainIterator();
auto g_sm = g.getGrid();
Sys_eqs eqs();
// iterate all the grid points
while (it.isNext())
{
// get the position
auto key = it.get();
// convert into global coordinate the position
auto keyg = g.getGKey(key);
// Convert local key into global key
size_t row = g_sm.LidId(keyg);
eqs.value(keyg,trpl);
++it;
}
}
};
#define EQS_FIELDS 0
#define EQS_SPACE 1
#endif /* OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_FDSCHEME_HPP_ */
/*
* FDScheme_unit_tests.hpp
*
* Created on: Oct 5, 2015
* Author: i-bird
*/
#ifndef OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_FDSCHEME_UNIT_TESTS_HPP_
#define OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_FDSCHEME_UNIT_TESTS_HPP_
#include "FiniteDifference/Derivative.hpp"
#include "FiniteDifference/Laplacian.hpp"
constexpr unsigned int x = 0;
constexpr unsigned int y = 1;
constexpr unsigned int V = 0;
struct sys_nn
{
// dimensionaly of the equation (2D problem 3D problem ...)
static const unsigned int dims = 2;
// number of fields in the system
static const unsigned int nvar = 1;
static const unsigned int ord = EQS_FIELD;
// boundary at X and Y
static const bool boundary[];
// type of space float, double, ...
typedef float stype;
};
const bool sys_nn::boundary[] = {NON_PERIODIC,NON_PERIODIC};
struct sys_pp
{
// dimensionaly of the equation (2D problem 3D problem ...)
static const unsigned int dims = 2;
// number of fields in the system
static const unsigned int nvar = 1;
static const unsigned int ord = EQS_FIELD;
// boundary at X and Y
static const bool boundary[];
// type of space float, double, ...
typedef float stype;
};
const bool sys_pp::boundary[] = {PERIODIC,PERIODIC};
//////////////////////// STAGGERED CASE //////////////////////////////////
struct syss_nn
{
// dimensionaly of the equation (2D problem 3D problem ...)
static const unsigned int dims = 2;
// number of fields in the system
static const unsigned int nvar = 1;
static const unsigned int ord = EQS_FIELD;
static const unsigned int grid = STAGGERED_GRID;
// boundary at X and Y
static const bool boundary[];
// type of space float, double, ...
typedef float stype;
};
const bool syss_nn::boundary[] = {NON_PERIODIC,NON_PERIODIC};
struct syss_pp
{
// dimensionaly of the equation (2D problem 3D problem ...)
static const unsigned int dims = 2;
// number of fields in the system
static const unsigned int nvar = 1;
static const unsigned int ord = EQS_FIELD;
static const unsigned int grid = STAGGERED_GRID;
// boundary at X and Y
static const bool boundary[];
// type of space float, double, ...
typedef float stype;
};
const bool syss_pp::boundary[] = {PERIODIC,PERIODIC};
BOOST_AUTO_TEST_SUITE( fd_test )
BOOST_AUTO_TEST_CASE( fd_test_use_non_periodic)
{
// grid size
size_t sz[2]={16,16};
// grid_sm
grid_sm<2,void> ginfo(sz);
// Create a derivative row Matrix
grid_key_dx<2> key11(1,1);
grid_key_dx<2> key00(0,0);
grid_key_dx<2> key22(2,2);
grid_key_dx<2> key1515(15,15);
// filled colums
std::unordered_map<long int,float> cols_x;
std::unordered_map<long int,float> cols_y;
D<x,Field<V,sys_nn>,sys_nn>::value(key11,ginfo,cols_x,1);
D<y,Field<V,sys_nn>,sys_nn>::value(key11,ginfo,cols_y,1);
BOOST_REQUIRE_EQUAL(cols_x.size(),2);
BOOST_REQUIRE_EQUAL(cols_y.size(),2);
BOOST_REQUIRE_EQUAL(cols_x[17+1],1);
BOOST_REQUIRE_EQUAL(cols_x[17-1],-1);
BOOST_REQUIRE_EQUAL(cols_y[17+16],1);
BOOST_REQUIRE_EQUAL(cols_y[17-16],-1);
// filled colums
std::unordered_map<long int,float> cols_xx;
std::unordered_map<long int,float> cols_xy;
std::unordered_map<long int,float> cols_yx;
std::unordered_map<long int,float> cols_yy;
// Composed derivative
D<x,D<x,Field<V,sys_nn>,sys_nn>,sys_nn>::value(key22,ginfo,cols_xx,1);
D<x,D<y,Field<V,sys_nn>,sys_nn>,sys_nn>::value(key22,ginfo,cols_xy,1);
D<y,D<x,Field<V,sys_nn>,sys_nn>,sys_nn>::value(key22,ginfo,cols_yx,1);
D<y,D<y,Field<V,sys_nn>,sys_nn>,sys_nn>::value(key22,ginfo,cols_yy,1);
BOOST_REQUIRE_EQUAL(cols_xx.size(),3);
BOOST_REQUIRE_EQUAL(cols_xy.size(),4);
BOOST_REQUIRE_EQUAL(cols_yx.size(),4);
BOOST_REQUIRE_EQUAL(cols_yy.size(),3);
BOOST_REQUIRE_EQUAL(cols_xx[32],1);
BOOST_REQUIRE_EQUAL(cols_xx[34],-2);
BOOST_REQUIRE_EQUAL(cols_xx[36],1);
BOOST_REQUIRE_EQUAL(cols_xy[17],1);
BOOST_REQUIRE_EQUAL(cols_xy[19],-1);
BOOST_REQUIRE_EQUAL(cols_xy[49],-1);
BOOST_REQUIRE_EQUAL(cols_xy[51],1);
BOOST_REQUIRE_EQUAL(cols_yx[17],1);
BOOST_REQUIRE_EQUAL(cols_yx[19],-1);
BOOST_REQUIRE_EQUAL(cols_yx[49],-1);
BOOST_REQUIRE_EQUAL(cols_xy[51],1);
BOOST_REQUIRE_EQUAL(cols_yy[2],1);
BOOST_REQUIRE_EQUAL(cols_yy[34],-2);
BOOST_REQUIRE_EQUAL(cols_yy[66],1);
// Non periodic with one sided
cols_x.clear();
cols_y.clear();
D<x,Field<V,sys_nn>,sys_nn,CENTRAL_B_ONE_SIDE>::value(key11,ginfo,cols_x,1);
D<y,Field<V,sys_nn>,sys_nn,CENTRAL_B_ONE_SIDE>::value(key11,ginfo,cols_y,1);
BOOST_REQUIRE_EQUAL(cols_x.size(),2);
BOOST_REQUIRE_EQUAL(cols_y.size(),2);
BOOST_REQUIRE_EQUAL(cols_x[17+1],1);
BOOST_REQUIRE_EQUAL(cols_x[17-1],-1);
BOOST_REQUIRE_EQUAL(cols_y[17+16],1);
BOOST_REQUIRE_EQUAL(cols_y[17-16],-1);
// Border left
cols_x.clear();
cols_y.clear();
D<x,Field<V,sys_nn>,sys_nn,CENTRAL_B_ONE_SIDE>::value(key00,ginfo,cols_x,1);
D<y,Field<V,sys_nn>,sys_nn,CENTRAL_B_ONE_SIDE>::value(key00,ginfo,cols_y,1);
BOOST_REQUIRE_EQUAL(cols_x.size(),3);
BOOST_REQUIRE_EQUAL(cols_y.size(),3);
BOOST_REQUIRE_EQUAL(cols_x[0],-1.5);
BOOST_REQUIRE_EQUAL(cols_x[1],2);
BOOST_REQUIRE_EQUAL(cols_x[2],-0.5);
BOOST_REQUIRE_EQUAL(cols_y[0],-1.5);
BOOST_REQUIRE_EQUAL(cols_y[16],2);
BOOST_REQUIRE_EQUAL(cols_y[32],-0.5);
// Border Top right
cols_x.clear();
cols_y.clear();
D<x,Field<V,sys_nn>,sys_nn,CENTRAL_B_ONE_SIDE>::value(key1515,ginfo,cols_x,1);
D<y,Field<V,sys_nn>,sys_nn,CENTRAL_B_ONE_SIDE>::value(key1515,ginfo,cols_y,1);
BOOST_REQUIRE_EQUAL(cols_x.size(),3);
BOOST_REQUIRE_EQUAL(cols_y.size(),3);
BOOST_REQUIRE_EQUAL(cols_x[15*16+15],1.5);
BOOST_REQUIRE_EQUAL(cols_x[15*16+14],-2);
BOOST_REQUIRE_EQUAL(cols_x[15*16+13],0.5);
BOOST_REQUIRE_EQUAL(cols_y[15*16+15],1.5);
BOOST_REQUIRE_EQUAL(cols_y[14*16+15],-2);
BOOST_REQUIRE_EQUAL(cols_y[13*16+15],0.5);
}
BOOST_AUTO_TEST_CASE( fd_test_use_periodic)
{
// grid size
size_t sz[2]={16,16};
// grid_sm
grid_sm<2,void> ginfo(sz);
// Create a derivative row Matrix
grid_key_dx<2> key11(1,1);
grid_key_dx<2> key00(0,0);
grid_key_dx<2> key22(2,2);
grid_key_dx<2> key1515(15,15);
// filled colums
std::unordered_map<long int,float> cols_x;
std::unordered_map<long int,float> cols_y;
D<x,Field<V,sys_pp>,sys_pp>::value(key11,ginfo,cols_x,1);
D<y,Field<V,sys_pp>,sys_pp>::value(key11,ginfo,cols_y,1);
BOOST_REQUIRE_EQUAL(cols_x.size(),2);
BOOST_REQUIRE_EQUAL(cols_y.size(),2);
BOOST_REQUIRE_EQUAL(cols_x[17+1],1);
BOOST_REQUIRE_EQUAL(cols_x[17-1],-1);
BOOST_REQUIRE_EQUAL(cols_y[17+16],1);
BOOST_REQUIRE_EQUAL(cols_y[17-16],-1);
cols_x.clear();
cols_y.clear();
D<x,Field<V,sys_pp>,sys_pp>::value(key00,ginfo,cols_x,1);
D<y,Field<V,sys_pp>,sys_pp>::value(key00,ginfo,cols_y,1);
BOOST_REQUIRE_EQUAL(cols_x.size(),2);
BOOST_REQUIRE_EQUAL(cols_y.size(),2);
BOOST_REQUIRE_EQUAL(cols_x[1],1);
BOOST_REQUIRE_EQUAL(cols_x[15],-1);
BOOST_REQUIRE_EQUAL(cols_y[16],1);
BOOST_REQUIRE_EQUAL(cols_y[16*15],-1);