Skip to content
Snippets Groups Projects
Commit 1a6ed291 authored by Pietro Incardona's avatar Pietro Incardona
Browse files

Adding missing files

parent 1646fa57
No related branches found
No related tags found
No related merge requests found
/*
* 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);
// periodic composed derivative
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;
D<x,D<x,Field<V,sys_pp>,sys_pp>,sys_pp>::value(key00,ginfo,cols_xx,1);
D<x,D<y,Field<V,sys_pp>,sys_pp>,sys_pp>::value(key00,ginfo,cols_xy,1);
D<y,D<x,Field<V,sys_pp>,sys_pp>,sys_pp>::value(key00,ginfo,cols_yx,1);
D<y,D<y,Field<V,sys_pp>,sys_pp>,sys_pp>::value(key00,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[14],1);
BOOST_REQUIRE_EQUAL(cols_xx[0],-2);
BOOST_REQUIRE_EQUAL(cols_xx[2],1);
BOOST_REQUIRE_EQUAL(cols_xy[17],1);
BOOST_REQUIRE_EQUAL(cols_xy[16+15],-1);
BOOST_REQUIRE_EQUAL(cols_xy[15*16+1],-1);
BOOST_REQUIRE_EQUAL(cols_xy[15*16+15],1);
BOOST_REQUIRE_EQUAL(cols_yx[17],1);
BOOST_REQUIRE_EQUAL(cols_yx[16+15],-1);
BOOST_REQUIRE_EQUAL(cols_yx[15*16+1],-1);
BOOST_REQUIRE_EQUAL(cols_xy[15*16+15],1);
BOOST_REQUIRE_EQUAL(cols_yy[32],1);
BOOST_REQUIRE_EQUAL(cols_yy[0],-2);
BOOST_REQUIRE_EQUAL(cols_yy[14*16],1);
// Border Top right
cols_x.clear();
cols_y.clear();
D<x,Field<V,sys_pp>,sys_pp>::value(key1515,ginfo,cols_x,1);
D<y,Field<V,sys_pp>,sys_pp>::value(key1515,ginfo,cols_y,1);
BOOST_REQUIRE_EQUAL(cols_x.size(),2);
BOOST_REQUIRE_EQUAL(cols_y.size(),2);
BOOST_REQUIRE_EQUAL(cols_x[15*16+0],1);
BOOST_REQUIRE_EQUAL(cols_x[15*16+14],-1);
BOOST_REQUIRE_EQUAL(cols_y[0*16+15],1);
BOOST_REQUIRE_EQUAL(cols_y[14*16+15],-1);
}
/////////////// Laplacian test
BOOST_AUTO_TEST_CASE( fd_test_lap_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;
Lap<Field<V,sys_pp>,sys_pp>::value(key11,ginfo,cols,1);
BOOST_REQUIRE_EQUAL(cols.size(),5);
BOOST_REQUIRE_EQUAL(cols[1],1);
BOOST_REQUIRE_EQUAL(cols[17-1],1);
BOOST_REQUIRE_EQUAL(cols[17+1],1);
BOOST_REQUIRE_EQUAL(cols[17+16],1);
BOOST_REQUIRE_EQUAL(cols[17],-4);
cols.clear();
Lap<Field<V,sys_pp>,sys_pp>::value(key00,ginfo,cols,1);
BOOST_REQUIRE_EQUAL(cols.size(),5);
BOOST_REQUIRE_EQUAL(cols[1],1);
BOOST_REQUIRE_EQUAL(cols[15],1);
BOOST_REQUIRE_EQUAL(cols[16],1);
BOOST_REQUIRE_EQUAL(cols[15*16],1);
BOOST_REQUIRE_EQUAL(cols[0],-4);
// Border Top right
cols.clear();
Lap<Field<V,sys_pp>,sys_pp>::value(key1515,ginfo,cols,1);
BOOST_REQUIRE_EQUAL(cols.size(),5);
BOOST_REQUIRE_EQUAL(cols[15*16+14],1);
BOOST_REQUIRE_EQUAL(cols[15*16],1);
BOOST_REQUIRE_EQUAL(cols[14*16+15],1);
BOOST_REQUIRE_EQUAL(cols[15],1);
BOOST_REQUIRE_EQUAL(cols[15*16+15],-4);
}
//////////////// Position ////////////////////
BOOST_AUTO_TEST_CASE( fd_test_use_staggered_position)
{
// grid size
/* size_t sz[2]={16,16};
// 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);
openfpm::vector<comb<2>> vx_c;
comb<2> cx = {{1,0}};
vx_c.add(cx); // like v_x
openfpm::vector<comb<2>> vy_c;
comb<2> cy = {{0,1}};
vy_c.add(cy); // like v_y
grid_key_dx<2> key_ret_x = D<x,Field<V,sys_nn>,sys_nn>::position(key11,0,vx_c);
grid_key_dx<2> key_ret_y = D<y,Field<V,sys_nn>,sys_nn>::position(key11,0,vx_c);
BOOST_REQUIRE_EQUAL(key_ret_x.get(0),1);
BOOST_REQUIRE_EQUAL(key_ret_x.get(1),1);
BOOST_REQUIRE_EQUAL(key_ret_y.get(0),0);
BOOST_REQUIRE_EQUAL(key_ret_y.get(1),0);
key_ret_x = D<x,Field<V,sys_nn>,sys_nn>::position(key11,0,vy_c);
key_ret_y = D<y,Field<V,sys_nn>,sys_nn>::position(key11,0,vy_c);
BOOST_REQUIRE_EQUAL(key_ret_x.get(0),0);
BOOST_REQUIRE_EQUAL(key_ret_x.get(1),0);
BOOST_REQUIRE_EQUAL(key_ret_y.get(0),1);
BOOST_REQUIRE_EQUAL(key_ret_y.get(1),1);
// Composed derivative
grid_key_dx<2> key_ret_xx = D<x,D<x,Field<V,sys_nn>,sys_nn>,sys_nn>::position(key00,0);
grid_key_dx<2> key_ret_xy = D<x,D<y,Field<V,sys_nn>,sys_nn>,sys_nn>::position(key00,0);
grid_key_dx<2> key_ret_yx = D<y,D<x,Field<V,sys_nn>,sys_nn>,sys_nn>::position(key00,0);
grid_key_dx<2> key_ret_yy = D<y,D<y,Field<V,sys_nn>,sys_nn>,sys_nn>::position(key00,0);
BOOST_REQUIRE_EQUAL(key_ret_xx.get(0),1);
BOOST_REQUIRE_EQUAL(key_ret_xx.get(1),0);
BOOST_REQUIRE_EQUAL(key_ret_xy.get(0),1);
BOOST_REQUIRE_EQUAL(key_ret_xy.get(1),0);
BOOST_REQUIRE_EQUAL(key_ret_xy.get(0),0);
BOOST_REQUIRE_EQUAL(key_ret_xy.get(1),1);
BOOST_REQUIRE_EQUAL(key_ret_xy.get(0),0);
BOOST_REQUIRE_EQUAL(key_ret_xy.get(1),1);
////////////////// Non periodic with one sided
key_ret_x = D<x,Field<V,sys_nn>,sys_nn,CENTRAL_B_ONE_SIDE>::position(key00,0,vx_c);
key_ret_y = D<y,Field<V,sys_nn>,sys_nn,CENTRAL_B_ONE_SIDE>::position(key00,0,vx_c);
BOOST_REQUIRE_EQUAL(key_ret_x.get(0),0);
BOOST_REQUIRE_EQUAL(key_ret_x.get(1),1);
BOOST_REQUIRE_EQUAL(key_ret_x,0);
BOOST_REQUIRE_EQUAL(key_ret_y,0);
// Border left*/
}
BOOST_AUTO_TEST_SUITE_END()
#endif /* OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_FDSCHEME_UNIT_TESTS_HPP_ */
/*
* Laplacian.hpp
*
* Created on: Oct 5, 2015
* Author: i-bird
*/
#ifndef OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_LAPLACIAN_HPP_
#define OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_LAPLACIAN_HPP_
/*! \brief Laplacian second order on h (spacing)
*
* \tparam Field which field derive
* \tparam impl which implementation
*
*/
template<typename arg, typename Sys_eqs, unsigned int impl=CENTRAL>
class Lap
{
/*! \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 laplacian 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<typename arg, typename Sys_eqs>
class Lap<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)
{
// for each dimension
for (size_t i = 0 ; i < Sys_eqs::dims ; i++)
{
// forward
if (Sys_eqs::boundary[i] == PERIODIC )
{
long int old_val = pos.get(i);
pos.set_d(i, openfpm::math::positive_modulo(pos.get(i) + 1, gs.size(i)));
arg::value(pos,gs,cols,coeff);
pos.set_d(i,old_val);
}
else
{
long int old_val = pos.get(i);
pos.set_d(i, pos.get(i) + 1);
arg::value(pos,gs,cols,coeff);
pos.set_d(i,old_val);
}
// backward
if (Sys_eqs::boundary[i] == PERIODIC )
{
long int old_val = pos.get(i);
pos.set_d(i, openfpm::math::positive_modulo(pos.get(i) - 1, gs.size(i)));
arg::value(pos,gs,cols,coeff);
pos.set_d(i,old_val);
}
else
{
long int old_val = pos.get(i);
pos.set_d(i, pos.get(i) - 1);
arg::value(pos,gs,cols,coeff);
pos.set_d(i,old_val);
}
}
arg::value(pos,gs,cols, - 2.0 * Sys_eqs::dims * coeff);
}
/*! \brief Calculate the position where the derivative is calculated
*
* In case of 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 openfpm::vector<comb<Sys_eqs::dims>> & s_pos, long int & fld)
{
return pos;
}
};
#endif /* OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_LAPLACIAN_HPP_ */
/*
* System.hpp
*
* Created on: Oct 5, 2015
* Author: i-bird
*/
#ifndef OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_SYSTEM_HPP_
#define OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_SYSTEM_HPP_
/*! \brief System of equations
*
* This class model a system of equations
*
* \tparam dim Dimensionality of the system
* \tparam nvf number of variable fields
* \tparam ncf number of constants fields
* \tparam eqs sets of equations
*
*/
template<unsigned int dim, unsigned int nvf, unsigned int ncf, typename ... eqs>
class System
{
// Define the number of constant fields
typedef num_cfields boost::mpl::int_<nf>;
// Define the number of variable fields
typedef num_vfields boost::mpl::int_<nf>;
// set of equations as boost::mpl::vector
typedef eqs_v make_vactor<eqs>;
/*! \brief Create the row of the Matrix
*
* \tparam ord
*
*/
template<unsigned int ord=EQS_FIELDS> void value(const grid_key_dx_dist<dim> & pos)
{
if (EQS_FIELDS)
value_f(pos);
else
value_s(pos);
}
/*! \brief fill the row
*
*
*/
template<unsigned int eq_id> void value_s(grid_key_dx_dist<dim> & it)
{
boost::mpl::at<eqs_v,boost::mpl::int_<eq_id>>::type eq;
eq.value_s(it);
}
/*! \brief fill the row
*
*
*/
template<unsigned int eq_id> void value_f(grid_key_dx_dist<dim> & it)
{
boost::mpl::at<eqs_v,boost::mpl::int_<eq_id>>::type eq;
eq.value_f(it);
}
};
#endif /* OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_SYSTEM_HPP_ */
/*
* eq.hpp
*
* Created on: Oct 5, 2015
* Author: i-bird
*/
#ifndef OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_EQ_HPP_
#define OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_EQ_HPP_
#define EQS_FIELD 0
#define EQS_POS 1
#define STAGGERED_GRID 1
#define NORMAL_GRID 0
#define PERIODIC true
#define NON_PERIODIC false
/*! \brief Equation
*
* It model an equation like expr1 = expr2
*
* \tparam expr1
* \tparam expr2
*
*/
template<typename expr1,typename expr2,typename Sys_eqs>
class Eq
{
/*! \brief Create the row of the Matrix
*
* \tparam ord
*
*/
template<unsigned int ord=EQS_FIELD> static void value(const grid_key_dx<Sys_eqs::dims> & pos)
{
if (EQS_FIELD)
value_f(pos);
else
value_s(pos);
}
/*! \brief fill the row
*
*
*/
static openfpm::vector<cval<typename Sys_eqs::stype>> value_s(grid_key_dx<Sys_eqs::dims> & it)
{
return expr1::value_s(it) - expr2::value_s(it);
}
/*! \brief fill the row
*
*
*/
static void value_f(grid_key_dx<Sys_eqs::dims> & it)
{
return expr1::value_s(it) - expr2::value_s(it);
}
};
/*! \brief It model an expression expr1 - expr2
*
* \tparam expr1
* \tparam expr2
*
*/
template<typename expr1,typename expr2, typename Sys_eqs>
class minus
{
/*! \brief Create the row of the Matrix
*
* \tparam ord
*
*/
template<unsigned int ord=EQS_FIELD> static void value(const grid_key_dx<Sys_eqs::dims> & pos)
{
if (EQS_FIELD)
value_f(pos);
else
value_s(pos);
}
/*! \brief fill the row
*
*
*/
static openfpm::vector<triplet<typename Sys_eqs::stype>> value_s(grid_key_dx<Sys_eqs::dims> & it)
{
return expr1::value_s(it) - expr2::value_s(it);
}
/*! \brief fill the row
*
*
*/
static void value_f(grid_key_dx<Sys_eqs::dims> & it)
{
return expr1::value_s(it) - expr2::value_s(it);
}
};
/*! \brief It model an expression expr1 * expr2
*
* \warning expr1 MUST be a constant expression
*
* \tparam expr1
* \tparam expr2
*
*/
template<typename expr1,typename expr2, typename Sys_eqs>
class mul
{
/*! \brief Create the row of the Matrix
*
* \tparam ord
*
*/
template<unsigned int ord=EQS_FIELD> static void value(const grid_key_dx<Sys_eqs::dims> & pos)
{
if (EQS_FIELD)
value_f(pos);
else
value_s(pos);
}
/*! \brief fill the row
*
*
*/
static openfpm::vector<triplet<typename Sys_eqs::stype>> value_s(grid_key_dx<Sys_eqs::dims> & it)
{
return expr1::const_value(it) * expr2::value_s(it);
}
/*! \brief fill the row
*
*
*/
static void value_f(grid_key_dx<Sys_eqs::dims> & it)
{
return expr1::const_value(it) * expr2::value_s(it);
}
};
// spatial position + value
template<unsigned int dim,typename T>
struct pos_val
{
/*! \brief Initialize to zero the value
*
*/
pos_val()
{
value = 0.0;
}
grid_key_dx<dim> pos;
T value;
};
template<unsigned int f, typename Sys_eqs>
class Field
{
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)
{
if (Sys_eqs::ord == EQS_FIELD)
cols[gs.LinId(pos) + f] += coeff;
else
cols[gs.LinId(pos) + f * gs.size()] += coeff;
}
};
class ConstField
{
};
inline size_t mat_factor(size_t nvar, size_t sz, const size_t ord)
{
if (ord == EQS_FIELD)
return nvar;
else
return sz;
}
#endif /* OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_EQ_HPP_ */
/*
* eq_unit_test.hpp
*
* Created on: Oct 13, 2015
* Author: i-bird
*/
#ifndef OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_EQ_UNIT_TEST_HPP_
#define OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_EQ_UNIT_TEST_HPP_
#include "Laplacian.hpp"
#include "FiniteDifference/eq.hpp"
#include "FiniteDifference/sum.hpp"
// Stokes flow
struct lid_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 = 3;
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 lid_nn::boundary[] = {NON_PERIODIC,NON_PERIODIC};
// Constant Field
struct eta
{
};
// Model the equation
constexpr unsigned int v[] = {0,1};
constexpr unsigned int P = 2;
typedef Field<v[x],lid_nn> v_x;
typedef Field<v[y],lid_nn> v_y;
typedef Field<P,lid_nn> Prs;
// Eq1 V_x
typedef mul<eta,Lap<v_x,lid_nn>,lid_nn> eta_lap_vx;
typedef D<x,Prs,lid_nn> p_x;
typedef sum<eta_lap_vx,p_x> vx_eq;
// Eq2 V_y
typedef mul<eta,Lap<v_y,lid_nn>,lid_nn> eta_lap_vy;
typedef D<x,Prs,lid_nn> p_x;
typedef sum<eta_lap_vy,p_x,lid_nn> vy_eq;
// Eq3 Incompressibility
typedef D<x,v_x,lid_nn> dx_vx;
typedef D<y,v_y,lid_nn> dy_vy;
typedef sum<dx_vx,dy_vy> incompressibility;
// Lid driven cavity, uncompressible fluid
BOOST_AUTO_TEST_CASE( lid_driven_cavity )
{
}
#endif /* OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_EQ_UNIT_TEST_HPP_ */
/*
* sum.hpp
*
* Created on: Oct 13, 2015
* Author: i-bird
*/
#ifndef OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_SUM_HPP_
#define OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_SUM_HPP_
#include <boost/mpl/vector.hpp>
/*! \brief It model an expression expr1 + ... exprn
*
* \tparam expr.. two or more expression to be summed
* \tparam Sys_eqs stystem specification
*
*/
template<typename ... expr>
class sum
{
// Transform from variadic template to boost mpl vector
typedef boost::mpl::vector<expr... > v_expr;
};
#endif /* OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_SUM_HPP_ */
/*
* common.hpp
*
* Created on: Oct 11, 2015
* Author: i-bird
*/
#ifndef OPENFPM_NUMERICS_SRC_UTIL_COMMON_HPP_
#define OPENFPM_NUMERICS_SRC_UTIL_COMMON_HPP_
template<typename T, typename Sfinae = void>
struct has_grid_type: std::false_type {};
/*! \brief has_noPointers check if a type has defined a
* method called noPointers
*
* ### Example
*
* \snippet util.hpp Check no pointers
*
* return true if T::noPointers() is a valid expression (function pointers)
* and produce a defined type
*
*/
template<typename T>
struct has_grid_type<T, typename Void<decltype( T::grid_type )>::type> : std::true_type
{};
/*! \brief is_grid_staggered analyse T if it has a property that define the type of grid
*
* This struct define a method value that return id T define a staggered or normal grid
*
*/
template<typename T, bool has_gt = has_grid_type<T>::type::value >
struct is_grid_staggered
{
/*! \brief Return true if the grid is staggered
*
* If T define a staggered grid return true, if define a NORMAL grid or does not
* define any grid type return false
*
* \return true in case the grid type is staggered
*
*/
static bool value()
{
return T::grid_type;
};
};
/*! \brief is_grid_staggered analyse T if it has a property that define the type of grid
*
* This struct define a method value that return id T define a staggered or normal grid
*
*/
template<typename T>
struct is_grid_staggered<T,false>
{
/*! \brief Return true if the grid is staggered
*
* If T define a staggered grid return true, if define a NORMAL grid or does not
* define any grid type return false
*
* \return true in case the grid type is staggered
*
*/
static bool value()
{
return false;
};
};
#endif /* OPENFPM_NUMERICS_SRC_UTIL_COMMON_HPP_ */
/*
* common_test.hpp
*
* Created on: Oct 11, 2015
* Author: i-bird
*/
#ifndef OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_UTIL_COMMON_TEST_HPP_
#define OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_UTIL_COMMON_TEST_HPP_
#include "FiniteDifference/util/common.hpp"
struct test_grid_type_staggered
{
static const int grid_type = STAGGERED_GRID;
};
struct test_grid_type_normal
{
static const int grid_type = NORMAL_GRID;
};
struct test_grid_type_no_def
{
};
BOOST_AUTO_TEST_SUITE( util_pdata_test )
BOOST_AUTO_TEST_CASE( check_pdata_templates_util_function )
{
{
//! [Check grid_type]
BOOST_REQUIRE_EQUAL(has_grid_type<test_grid_type_staggered>::type::value,true);
BOOST_REQUIRE_EQUAL(has_grid_type<test_grid_type_normal>::type::value,true);
BOOST_REQUIRE_EQUAL(has_grid_type<test_grid_type_no_def>::type::value,false);
//! [Check grid_type]
}
{
//! [Check grid_type staggered]
BOOST_REQUIRE_EQUAL(is_grid_staggered<test_grid_type_staggered>::value(),true);
BOOST_REQUIRE_EQUAL(is_grid_staggered<test_grid_type_normal>::value(),false);
BOOST_REQUIRE_EQUAL(is_grid_staggered<test_grid_type_no_def>::value(),false);
//! [Check grid_type staggered]
}
}
BOOST_AUTO_TEST_SUITE_END()
#endif /* OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_UTIL_COMMON_TEST_HPP_ */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment