diff --git a/build_pdata.sh b/build_pdata.sh index 0940a20657cfa7529ae836d738aad4d2080de443..9c196a7dcc98dbed001f4de8cdda3d1d7de9aa36 100644 --- a/build_pdata.sh +++ b/build_pdata.sh @@ -230,27 +230,27 @@ then exit 1 ; fi - salloc --nodes=1 --ntasks-per-node=24 --time=00:10:00 --mem-per-cpu=1900 --partition=haswell bash -c "ulimit -s unlimited && mpirun -np 24 src/pdata" + salloc --nodes=1 --ntasks-per-node=24 --time=00:5:00 --mem-per-cpu=1900 --partition=haswell bash -c "ulimit -s unlimited && mpirun -np 24 src/pdata --report_level=no" if [ $? -ne 0 ]; then curl -X POST --data "payload={\"icon_emoji\": \":jenkins:\", \"username\": \"jenkins\" , \"attachments\":[{ \"title\":\"Error:\", \"color\": \"#FF0000\", \"text\":\"$2 failed to complete the openfpm_pdata test \" }] }" https://hooks.slack.com/services/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 exit 1 ; fi - salloc --nodes=2 --ntasks-per-node=24 --time=00:10:00 --mem-per-cpu=1900 --partition=haswell bash -c "ulimit -s unlimited && mpirun -np 48 src/pdata" + salloc --nodes=2 --ntasks-per-node=24 --time=00:5:00 --mem-per-cpu=1900 --partition=haswell bash -c "ulimit -s unlimited && mpirun -np 48 src/pdata --report_level=no" if [ $? -ne 0 ]; then curl -X POST --data "payload={\"icon_emoji\": \":jenkins:\", \"username\": \"jenkins\" , \"attachments\":[{ \"title\":\"Error:\", \"color\": \"#FF0000\", \"text\":\"$2 failed to complete the openfpm_pdata test \" }] }" https://hooks.slack.com/services/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 exit 1 ; fi - salloc --nodes=4 --ntasks-per-node=24 --time=00:10:00 --mem-per-cpu=1900 --partition=haswell bash -c "ulimit -s unlimited && mpirun -np 96 src/pdata" + salloc --nodes=4 --ntasks-per-node=24 --time=00:5:00 --mem-per-cpu=1900 --partition=haswell bash -c "ulimit -s unlimited && mpirun -np 96 src/pdata --report_level=no" if [ $? -ne 0 ]; then curl -X POST --data "payload={\"icon_emoji\": \":jenkins:\", \"username\": \"jenkins\" , \"attachments\":[{ \"title\":\"Error:\", \"color\": \"#FF0000\", \"text\":\"$2 failed to complete the openfpm_pdata test \" }] }" https://hooks.slack.com/services/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 exit 1 ; fi - salloc --nodes=8 --ntasks-per-node=24 --time=00:10:00 --mem-per-cpu=1900 --partition=haswell bash -c "ulimit -s unlimited && mpirun -np 192 src/pdata" + salloc --nodes=8 --ntasks-per-node=24 --time=00:5:00 --mem-per-cpu=1900 --partition=haswell bash -c "ulimit -s unlimited && mpirun -np 192 src/pdata --report_level=no" if [ $? -ne 0 ]; then curl -X POST --data "payload={\"icon_emoji\": \":jenkins:\", \"username\": \"jenkins\" , \"attachments\":[{ \"title\":\"Error:\", \"color\": \"#FF0000\", \"text\":\"$2 failed to complete the openfpm_pdata test \" }] }" https://hooks.slack.com/services/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 exit 1 ; fi - salloc --nodes=10 --ntasks-per-node=24 --time=00:10:00 --mem-per-cpu=1900 --partition=haswell bash -c "ulimit -s unlimited && mpirun -np 240 src/pdata" + salloc --nodes=10 --ntasks-per-node=24 --time=00:5:00 --mem-per-cpu=1900 --partition=haswell bash -c "ulimit -s unlimited && mpirun -np 240 src/pdata --report_level=no" if [ $? -ne 0 ]; then curl -X POST --data "payload={\"icon_emoji\": \":jenkins:\", \"username\": \"jenkins\" , \"attachments\":[{ \"title\":\"Error:\", \"color\": \"#FF0000\", \"text\":\"$2 failed to complete the openfpm_pdata test \" }] }" https://hooks.slack.com/services/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 exit 1 ; diff --git a/example/Grid/0_simple/main.cpp b/example/Grid/0_simple/main.cpp index 0e59f1dbd9ef23dbd059b8e1508640e8b8cd0cbc..deeb3f39667c588834bc3c870d35f503a31a98d0 100644 --- a/example/Grid/0_simple/main.cpp +++ b/example/Grid/0_simple/main.cpp @@ -1,5 +1,5 @@ #include "Grid/grid_dist_id.hpp" -#include "data_type/scalar.hpp" +#include "data_type/aggregate.hpp" #include "Decomposition/CartDecomposition.hpp" /* @@ -26,9 +26,9 @@ int main(int argc, char* argv[]) // // ### WIKI 3 ### // - // Create several object needed later, in particular + // Create // * A 3D box that define the domain - // * an array of 3 unsigned integer that define the size of the grid on each dimension + // * an array of 3 unsigned integer that will define the size of the grid on each dimension // * A Ghost object that will define the extension of the ghost part for each sub-domain in physical units Box<3,float> domain({0.0,0.0,0.0},{1.0,1.0,1.0}); @@ -43,8 +43,9 @@ int main(int argc, char* argv[]) // // ### WIKI 4 ### // - // Create a distributed grid in 3D (1° template parameter) defined in R^3 with float precision (2° template parameter) - // using a CartesianDecomposition strategy (3° parameter) (the parameter 1° and 2° inside CartDecomposition must match 1° and 2° + // Create a distributed grid in 3D (1° template parameter) space in with float precision (2° template parameter) + // each grid point contain a vector of dimension 3 (float[3]), + // using a CartesianDecomposition strategy (4° parameter) (the parameter 1° and 2° inside CartDecomposition must match 1° and 2° // of grid_dist_id) // // Constructor parameters: @@ -53,11 +54,11 @@ int main(int argc, char* argv[]) // * domain: where the grid is defined // * g: ghost extension // - grid_dist_id<3, float, scalar<float[3]>, CartDecomposition<3,float>> g_dist(sz,domain,g); + grid_dist_id<3, float, aggregate<float[3]>, CartDecomposition<3,float>> g_dist(sz,domain,g); // ### WIKI 5 ### // - // Get an iterator that go throught the point of the domain (No ghost) + // Get an iterator that go through the points of the grid (No ghost) // auto dom = g_dist.getDomainIterator(); @@ -71,8 +72,8 @@ int main(int argc, char* argv[]) // // ### WIKI 6 ### // - // Get the local grid key, the local grid key store internaly the sub-domain id (each sub-domain contain a grid) - // and the local grid point id identified by 2 integers in 2D 3 integer in 3D and so on. These two dinstinc element are + // Get the local grid key, the local grid key store internally the sub-domain id (each sub-domain contain a grid) + // and the local grid point id identified by 2 integers in 2D 3 integer in 3D and so on. These two distinct elements are // available with key.getSub() and key.getKey() // auto key = dom.get(); @@ -120,7 +121,7 @@ int main(int argc, char* argv[]) // // count contain the number of points the local processor contain, if we are interested to count the total number across the processor // we can use the function add, to sum across processors. First we have to get an instance of Vcluster, queue an operation of add with - // the variable count and finaly execute. All the operation are asynchronous, execute work like a barrier and ensure that all the + // the variable count and finally execute. All the operation are asynchronous, execute work like a barrier and ensure that all the // queued operations are executed // Vcluster & vcl = g_dist.getVC(); @@ -142,7 +143,7 @@ int main(int argc, char* argv[]) // // ### WIKI 13 ### // - // For debugging porpouse and demostration we output the decomposition + // For debugging purpose and demonstration we output the decomposition // g_dist.getDecomposition().write("out_dec"); diff --git a/example/Grid/1_stencil/main.cpp b/example/Grid/1_stencil/main.cpp index 3d4470c6cbc3606b3448cc56f781ee0477b410c6..f216412945b951a80aef5668567d7ec0ce6ec353 100644 --- a/example/Grid/1_stencil/main.cpp +++ b/example/Grid/1_stencil/main.cpp @@ -1,5 +1,5 @@ #include "Grid/grid_dist_id.hpp" -#include "data_type/scalar.hpp" +#include "data_type/aggregate.hpp" #include "Decomposition/CartDecomposition.hpp" /* @@ -7,9 +7,8 @@ * * ## Simple example * - * This example show how to move grid_key in order to create a laplacian stencil, - * be carefull, the function move are convenient, we suggest to not use in case speed - * of a speed critical part of the code + * This example show how to move grid_key in order to create a Laplacian stencil, + * be careful, the function move are convenient, but not the fastest implementation * * ### WIKI END ### * @@ -19,13 +18,18 @@ * * ### WIKI 2 ### * - * Define some convenient constant + * Define some convenient constants and types * */ constexpr size_t x = 0; constexpr size_t y = 1; constexpr size_t z = 2; +constexpr size_t A = 0; +constexpr size_t B = 0; + +typedef aggregate<float[3],float[3]> grid_point; + int main(int argc, char* argv[]) { // @@ -55,8 +59,9 @@ int main(int argc, char* argv[]) // // ### WIKI 4 ### // - // Create a distributed grid in 3D (1° template parameter) defined in R^3 with float precision (2° template parameter) - // using a CartesianDecomposition strategy (3° parameter) (the parameter 1° and 2° inside CartDecomposition must match 1° and 2° + // Create a distributed grid in 3D (1° template parameter) space in with float precision (2° template parameter) + // each grid point contain a vector of dimension 3 (float[3]), + // using a CartesianDecomposition strategy (4° parameter) (the parameter 1° and 2° inside CartDecomposition must match 1° and 2° // of grid_dist_id) // // Constructor parameters: @@ -65,7 +70,7 @@ int main(int argc, char* argv[]) // * domain: where the grid is defined // * g: ghost extension // - grid_dist_id<3, float, scalar<float[3]>, CartDecomposition<3,float>> g_dist(sz,domain,g); + grid_dist_id<3, float, grid_point, CartDecomposition<3,float>> g_dist(sz,domain,g); // ### WIKI 5 ### // @@ -80,8 +85,8 @@ int main(int argc, char* argv[]) // // ### WIKI 6 ### // - // Get the local grid key, the local grid key store internaly the sub-domain id (each sub-domain contain a grid) - // and the local grid point id identified by 2 integers in 2D 3 integer in 3D and so on. These two dinstinc element are + // Get the local grid key, the local grid key store internally the sub-domain id (each sub-domain contain a grid) + // and the local grid point id identified by 2 integers in 2D 3 integer in 3D and so on. These two distinct elements are // available with key.getSub() and key.getKey() // auto key = dom.get(); @@ -133,10 +138,10 @@ int main(int argc, char* argv[]) auto key = dom.get(); // Laplace stencil - g_dist.template get<0>(key)[1] = g_dist.template get<0>(key.move(x,1))[0] + g_dist.template get<0>(key.move(x,-1))[0] + - g_dist.template get<0>(key.move(y,1))[0] + g_dist.template get<0>(key.move(y,-1))[0] + - g_dist.template get<0>(key.move(z,1))[0] + g_dist.template get<0>(key.move(z,-1))[0] - - 6*g_dist.template get<0>(key)[0]; + g_dist.template get<B>(key)[1] = g_dist.template get<A>(key.move(x,1))[0] + g_dist.template get<A>(key.move(x,-1))[0] + + g_dist.template get<A>(key.move(y,1))[0] + g_dist.template get<A>(key.move(y,-1))[0] + + g_dist.template get<A>(key.move(z,1))[0] + g_dist.template get<A>(key.move(z,-1))[0] - + 6*g_dist.template get<A>(key)[0]; ++dom; diff --git a/example/Vector/0_simple/main.cpp b/example/Vector/0_simple/main.cpp index 8fb81a1c9f96ab275babd98bc622ea227372537a..64074f9f21d411608313db49198752e327c2cb06 100644 --- a/example/Vector/0_simple/main.cpp +++ b/example/Vector/0_simple/main.cpp @@ -1,6 +1,5 @@ #include "Vector/vector_dist.hpp" #include "Decomposition/CartDecomposition.hpp" -#include "Point_test.hpp" /* * ### WIKI 1 ### @@ -13,6 +12,32 @@ * */ +/* + * ### WIKI 2 ### + * + * We define a particle structure it contain 4 scalars one vector with 3 components + * and a tensor of rank 2 3x3 + * + * ### WIKI END ### + * + */ + +template<typename T> class Particle +{ +public: + + typedef boost::fusion::vector<T,T,T,T,T[3],T[3][3]> type; + + type data; + + static const unsigned int x = 0; + static const unsigned int y = 1; + static const unsigned int z = 2; + static const unsigned int s = 3; + static const unsigned int v = 4; + static const unsigned int t = 5; + static const unsigned int max_prop = 6; +}; int main(int argc, char* argv[]) { @@ -55,7 +80,7 @@ int main(int argc, char* argv[]) // objects with an undefined position in space. This non-space decomposition is also called data-driven // decomposition // - vector_dist<2,float, Point_test<float>, CartDecomposition<2,float> > vd(4096,box); + vector_dist<2,float, Particle<float>, CartDecomposition<2,float> > vd(4096,box); // // ### WIKI 5 ### diff --git a/src/Grid/grid_dist_id.hpp b/src/Grid/grid_dist_id.hpp index f7f436fe1c3dc788e40dd89fe042921a5511dac4..1322be66047be34406ce3bb0696405c31cd1f38b 100644 --- a/src/Grid/grid_dist_id.hpp +++ b/src/Grid/grid_dist_id.hpp @@ -415,6 +415,9 @@ class grid_dist_id */ grid_dist_id(const grid_dist_id<dim,St,T,Decomposition,Memory,device_grid> & g) { +#ifdef SE_CLASS2 + check_new(this,8,GRID_DIST_EVENT,4); +#endif } void write_ie_boxes(std::string output) @@ -545,6 +548,18 @@ public: return ginfo_v.size(); } + /*! \brief Return the total number of points in the grid + * + * \param i direction + * + * \return number of points on direction i + * + */ + size_t size(size_t i) const + { + return ginfo_v.size(); + } + static inline Ghost<dim,float> convert_ghost(const Ghost<dim,long int> & gd,const CellDecomposer_sm<dim,St> & cd_sm) { Ghost<dim,float> gc; @@ -581,8 +596,9 @@ public: grid_dist_id(Decomposition && dec, const size_t (& g_sz)[dim], const Box<dim,St> & domain, const Ghost<dim,St> & ghost) :domain(domain),ghost(ghost),dec(dec),v_cl(*global_v_cluster) { - // Increment the reference counter of the decomposition - this->dec.incRef(); +#ifdef SE_CLASS2 + check_new(this,8,GRID_DIST_EVENT,4); +#endif InitializeCellDecomposer(g_sz); InitializeStructures(g_sz); @@ -608,8 +624,9 @@ public: grid_dist_id(const Decomposition & dec, const size_t (& g_sz)[dim],const Box<dim,St> & domain, const Ghost<dim,long int> & g) :domain(domain),dec(dec),v_cl(*global_v_cluster),ginfo(g_sz),ginfo_v(g_sz) { - // Increment the reference counter of the decomposition - this->dec.incRef(); +#ifdef SE_CLASS2 + check_new(this,8,GRID_DIST_EVENT,4); +#endif InitializeCellDecomposer(g_sz); @@ -629,9 +646,9 @@ public: grid_dist_id(Decomposition && dec, const size_t (& g_sz)[dim],const Box<dim,St> & domain, const Ghost<dim,long int> & g) :domain(domain),dec(dec),v_cl(*global_v_cluster),ginfo(g_sz),ginfo_v(g_sz) { - // Increment the reference counter of the decomposition - this->dec.incRef(); - +#ifdef SE_CLASS2 + check_new(this,8,GRID_DIST_EVENT,4); +#endif InitializeCellDecomposer(g_sz); ghost = convert_ghost(g,cd_sm); @@ -668,8 +685,13 @@ public: grid_dist_id(const size_t (& g_sz)[dim],const Box<dim,St> & domain, const Ghost<dim,long int> & g) :domain(domain),dec(*global_v_cluster),v_cl(*global_v_cluster),ginfo(g_sz),ginfo_v(g_sz) { - // Increment the reference counter of the decomposition - this->dec.incRef(); +#ifdef SE_CLASS2 + check_new(this,8,GRID_DIST_EVENT,4); +#endif + InitializeCellDecomposer(g_sz); + + // get the grid spacing + Box<dim,St> sp = cd_sm.getCellBox(); InitializeCellDecomposer(g_sz); @@ -712,6 +734,9 @@ public: */ const grid_sm<dim,T> & getGridInfo() const { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif return ginfo; } @@ -722,6 +747,9 @@ public: */ const grid_sm<dim,void> & getGridInfoVoid() const { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif return ginfo_v; } @@ -732,6 +760,9 @@ public: */ Decomposition & getDecomposition() { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif return dec; } @@ -742,6 +773,9 @@ public: */ const CellDecomposer_sm<dim,St> & getCellDecomposer() { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif return cd_sm; } @@ -752,6 +786,9 @@ public: */ bool isInside(const grid_key_dx<dim> & gk) const { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif for (size_t i = 0 ; i < dim ; i++) { if (gk.get(i) < 0 || gk.get(i) >= (long int)g_sz[i]) @@ -768,6 +805,9 @@ public: */ size_t getLocalDomainSize() { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif size_t total = 0; for (size_t i = 0 ; i < gdb_ext.size() ; i++) @@ -785,6 +825,9 @@ public: */ const openfpm::vector<GBoxes<device_grid::dims>> & getLocalGridsInfo() { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif return gdb_ext; } @@ -795,6 +838,10 @@ public: */ grid_dist_iterator<dim,device_grid,FREE> getDomainIterator() { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif + grid_key_dx<dim> stop(ginfo_v.getSize()); grid_key_dx<dim> one; one.one(); @@ -811,6 +858,9 @@ public: */ grid_dist_iterator<dim,device_grid,FIXED> getDomainGhostIterator() const { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif grid_dist_iterator<dim,device_grid,FIXED> it(loc_grid,gdb_ext); return it; @@ -828,6 +878,9 @@ public: */ grid_dist_iterator_sub<dim,device_grid> getSubDomainIterator(const grid_key_dx<dim> & start, const grid_key_dx<dim> & stop) const { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif grid_dist_iterator_sub<dim,device_grid> it(start,stop,loc_grid,gdb_ext); return it; @@ -853,6 +906,9 @@ public: //! Destructor ~grid_dist_id() { +#ifdef SE_CLASS2 + check_delete(this); +#endif dec.decRef(); } @@ -864,6 +920,9 @@ public: Vcluster & getVC() { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif return v_cl; } @@ -885,6 +944,9 @@ public: */ template <unsigned int p>inline auto get(const grid_dist_key_dx<dim> & v1) const -> typename std::add_lvalue_reference<decltype(loc_grid.get(v1.getSub()).template get<p>(v1.getKey()))>::type { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif return loc_grid.get(v1.getSub()).template get<p>(v1.getKey()); } @@ -896,6 +958,9 @@ public: */ template <unsigned int p>inline auto get(const grid_dist_key_dx<dim> & v1) -> typename std::add_lvalue_reference<decltype(loc_grid.get(v1.getSub()).template get<p>(v1.getKey()))>::type { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif return loc_grid.get(v1.getSub()).template get<p>(v1.getKey()); } @@ -1032,6 +1097,10 @@ public: */ template<int... prp> void ghost_get() { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif + // Sending property object typedef object<typename object_creator<typename T::type,prp...>::type> prp_object; @@ -1211,6 +1280,9 @@ public: */ inline grid_key_dx<dim> getGKey(const grid_dist_key_dx<dim> & k) { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif // Get the sub-domain id size_t sub_id = k.getSub(); @@ -1232,6 +1304,10 @@ public: */ bool write(std::string output) { +#ifdef SE_CLASS2 + check_valid(this,8); +#endif + // Create a writer and write VTKWriter<boost::mpl::pair<device_grid,float>,VECTOR_GRIDS> vtk_g; for (size_t i = 0 ; i < loc_grid.size() ; i++) @@ -1267,6 +1343,19 @@ public: { return loc_grid.size(); } + + + /* \brief It return the id of structure in the allocation list + * + * \see print_alloc and SE_CLASS2 + * + */ + long int who() + { +#ifdef SE_CLASS2 + return check_whoami(this,8); +#endif + } }; diff --git a/src/Grid/grid_dist_id_iterator.hpp b/src/Grid/grid_dist_id_iterator.hpp index e63cb25e77ebe39a0f6263099b743e7a2094a37d..4b0c4acd847a126225500415fcd32986bfd91fc3 100644 --- a/src/Grid/grid_dist_id_iterator.hpp +++ b/src/Grid/grid_dist_id_iterator.hpp @@ -134,7 +134,7 @@ class grid_dist_iterator<dim,device_grid,FREE> * \param gk std::vector of the local grid * */ - grid_dist_iterator(Vcluster_object_array<device_grid> & gk, openfpm::vector<GBoxes<device_grid::dims>> & gdb_ext, grid_key_dx<dim> stop) + grid_dist_iterator(const Vcluster_object_array<device_grid> & gk, openfpm::vector<GBoxes<device_grid::dims>> & gdb_ext, grid_key_dx<dim> stop) :g_c(0),gList(gk),gdb_ext(gdb_ext),stop(stop) { // Initialize the current iterator @@ -288,7 +288,7 @@ class grid_dist_iterator<dim,device_grid,FIXED> * \param gk std::vector of the local grid * */ - grid_dist_iterator(Vcluster_object_array<device_grid> & gk, const openfpm::vector<GBoxes<device_grid::dims>> & gdb_ext) + grid_dist_iterator(const Vcluster_object_array<device_grid> & gk, const openfpm::vector<GBoxes<device_grid::dims>> & gdb_ext) :g_c(0),gList(gk),gdb_ext(gdb_ext) { // Initialize the current iterator diff --git a/src/Vector/vector_dist.hpp b/src/Vector/vector_dist.hpp index 73dc114dce1e74b64e0edfbd72f221df7ff80a77..aedfc2d58f7ac7adf05fedf85251dc47a7c046e4 100644 --- a/src/Vector/vector_dist.hpp +++ b/src/Vector/vector_dist.hpp @@ -99,6 +99,10 @@ public: vector_dist(size_t np, Box<dim,St> box, Ghost<dim,St> g = Ghost<dim,St>()) :dec(*global_v_cluster),v_cl(*global_v_cluster) { +#ifdef SE_CLASS2 + check_new(this,8,VECTOR_DIST_EVENT,4); +#endif + // Allocate unassigned particles vectors v_pos = v_cl.template allocate<openfpm::vector<Point<dim,St>>>(1); v_prp = v_cl.template allocate<openfpm::vector<prop>>(1); @@ -138,6 +142,13 @@ public: p.zero(); } + ~vector_dist() + { +#ifdef SE_CLASS2 + check_delete(this); +#endif + } + /*! \brief Get the number of minimum sub-domain * * \return minimum number @@ -757,6 +768,18 @@ public: // Write the CSV return csv_writer.write(output,v_pos.get(INTERNAL),v_prp.get(INTERNAL)); } + + /* \brief It return the id of structure in the allocation list + * + * \see print_alloc and SE_CLASS2 + * + */ + long int who() + { +#ifdef SE_CLASS2 + return check_whoami(this,8); +#endif + } };