diff --git a/.gitignore b/.gitignore index d55e76cb535b79f68639000251f8833a9a291a26..234c9dd01b7bddde1ab85d0085fd6c2edb152e51 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +*.o +*.a *~ build/ CMakeFiles/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 054669b0cb75609caa7bf5ec7685670b6f6f4e49..ed5d6751e582a55ffa238c030118b074c2122a91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,13 +20,16 @@ set(PASTIS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") # Kokkos set(KOKKOS_ENABLE_OPENMP ON CACHE BOOL "") -add_subdirectory(${CMAKE_SOURCE_DIR}/packages/kokkos) +add_subdirectory(${PASTIS_SOURCE_DIR}/packages/kokkos) include_directories(${Kokkos_INCLUDE_DIRS_RET}) # Compiler flags include(GetKokkosCompilerFlags) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +# Add debug mode for Standard C++ library +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG -D_LIBCPP_DEBUG=1") + #------------------------------------------------------ # Rang (colors? Useless thus necessary!) @@ -39,6 +42,10 @@ include_directories(${PASTIS_SOURCE_DIR}/packages/CLI11/include) add_subdirectory(utils) include_directories(utils) +# Pastis algebra +#add_subdirectory(algebra) +include_directories(algebra) + # Pastis experimental add_subdirectory(experimental) include_directories(experimental) @@ -54,6 +61,8 @@ configure_file("${PASTIS_SOURCE_DIR}/pastis_config.hpp.in" "${CMAKE_CURRENT_BINARY_DIR}/pastis_config.hpp" @ONLY) +link_libraries("-rdynamic") + # ------------------- Source files -------------------- # Pastis binary add_executable( diff --git a/algebra/TinyVector.hpp b/algebra/TinyVector.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4dec9f1a80c2e0d3bfb81158352eab80e60005d4 --- /dev/null +++ b/algebra/TinyVector.hpp @@ -0,0 +1,151 @@ +#ifndef TINY_VECTOR_HPP +#define TINY_VECTOR_HPP + +#include <cassert> +#include <iostream> + +template <size_t N, typename T=double> +class TinyVector +{ +private: + T m_values[N]; + static_assert((N>0),"TinyVector size must be strictly positive"); + +public: + KOKKOS_INLINE_FUNCTION + T operator,(const TinyVector& v) + { + T t = m_values[0]*v.m_values[0]; + for (size_t i=1; i<N; ++i) { + t += m_values[i]*v.m_values[i]; + } + return std::move(t); + } + + KOKKOS_INLINE_FUNCTION + friend TinyVector operator*(const T& t, const TinyVector& v) + { + TinyVector tv; + for (size_t i=0; i<N; ++i) { + tv.m_values[i] = t * v.m_values[i]; + } + return std::move(tv); + } + + KOKKOS_INLINE_FUNCTION + friend std::ostream& operator<<(std::ostream& os, const TinyVector& v) + { + os << '(' << v.m_values[0]; + for (size_t i=1; i<N; ++i) { + os << ',' << v.m_values[i]; + } + os << ')'; + return os; + } + + KOKKOS_INLINE_FUNCTION + TinyVector operator+(const TinyVector& v) const + { + TinyVector sum; + for (size_t i=0; i<N; ++i) { + sum[i] = m_values[i]+v.m_values[i]; + } + return std::move(sum); + } + + KOKKOS_INLINE_FUNCTION + TinyVector operator-(const TinyVector& v) const + { + TinyVector difference; + for (size_t i=0; i<N; ++i) { + difference[i] = m_values[i]-v.m_values[i]; + } + return std::move(difference); + } + + KOKKOS_INLINE_FUNCTION + TinyVector& operator+=(const TinyVector& v) + { + for (size_t i=0; i<N; ++i) { + m_values[i] += v.m_values[i]; + } + return *this; + } + + KOKKOS_INLINE_FUNCTION + TinyVector& operator-=(const TinyVector& v) + { + for (size_t i=0; i<N; ++i) { + m_values[i] -= v.m_values[i]; + } + return *this; + } + + KOKKOS_INLINE_FUNCTION + TinyVector& operator=(const T& t) + { + for (size_t i=0; i<N; ++i) { + m_values[i] = t; + } + return *this; + } + + KOKKOS_INLINE_FUNCTION + T& operator[](const size_t& i) + { + assert(i<N); + return m_values[i]; + } + + KOKKOS_INLINE_FUNCTION + const T& operator[](const size_t& i) const + { + assert(i<N); + return m_values[i]; + } + + KOKKOS_INLINE_FUNCTION + const TinyVector& operator=(const TinyVector& v) + { + for (size_t i=0; i<N; ++i) { + m_values[i] = v.m_values[i]; + } + return *this; + } + + KOKKOS_INLINE_FUNCTION + TinyVector& operator=(TinyVector&& v) = default; + + KOKKOS_INLINE_FUNCTION + TinyVector() + { + ; + } + + KOKKOS_INLINE_FUNCTION + TinyVector(const T& t) + { + for (size_t i=0; i<N; ++i) { + m_values[i] = t; + } + } + + KOKKOS_INLINE_FUNCTION + TinyVector(const TinyVector& v) + { + for (size_t i=0; i<N; ++i) { + m_values[i] = v.m_values[i]; + } + } + + KOKKOS_INLINE_FUNCTION + TinyVector(TinyVector&& v) = default; + + KOKKOS_INLINE_FUNCTION + ~TinyVector() + { + ; + } +}; + +#endif // TINYVECTOR_HPP diff --git a/experimental/AcousticSolver.cpp b/experimental/AcousticSolver.cpp index fc875ffadb5a48fc9150c28150e7eeb723d2d00e..3088ff7176c03d46e6e429cb0b503123d0ecd66f 100644 --- a/experimental/AcousticSolver.cpp +++ b/experimental/AcousticSolver.cpp @@ -42,62 +42,43 @@ public: dst= Kokkos::reduction_identity<value_type>::min(); } }; - KOKKOS_INLINE_FUNCTION -double AcousticSolver:: -acoustic_dt(const Kokkos::View<const double*>& Vj, - const Kokkos::View<const double*>& cj) const +const Kokkos::View<const double*> +AcousticSolver::computeRhoCj(const Kokkos::View<const double*>& rhoj, + const Kokkos::View<const double*>& cj) { - const size_t nj = Vj.size(); - double dt = std::numeric_limits<double>::max(); - - Kokkos::View<double*> Vj_cj("Vj_cj", nj); - - Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ - Vj_cj[j] = Vj[j]/cj[j]; + Kokkos::View<double*> rhocj("rho_c", m_nj); + Kokkos::parallel_for(m_nj, KOKKOS_LAMBDA(const int& j) { + rhocj[j] = rhoj[j]*cj[j]; }); - - Kokkos::parallel_reduce(nj, ReduceMin(Vj_cj), dt); - - return dt; + return rhocj; } - KOKKOS_INLINE_FUNCTION -void AcousticSolver::computeExplicitFluxes(const Kokkos::View<const double*>& xr, - const Kokkos::View<const double*>& xj, - const Kokkos::View<const double*>& rhoj, - const Kokkos::View<const double*>& uj, - const Kokkos::View<const double*>& pj, - const Kokkos::View<const double*>& cj, - const Kokkos::View<const double*>& Vj, - const Kokkos::View<const double*[2]>& Cjr, - const Kokkos::View<const int*[2]>& cell_nodes, - const Kokkos::View<const int*[2]>& node_cells, - const Kokkos::View<const int*>& node_nb_cells, - const Kokkos::View<const int*[2]>& node_cell_local_node, - Kokkos::View<double*>& ur, - Kokkos::View<double*[2]>& Fjr) const +const Kokkos::View<const double*[2]> +AcousticSolver::computeAjr(const Kokkos::View<const double*>& rhocj, + const Kokkos::View<const double*[2]>& Cjr) { - // calcul de ur - const size_t nr = ur.size(); - const size_t nj = uj.size(); - - Kokkos::View<double*> rhocj("rho_c", nj); - Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j) { - rhocj[j] = rhoj[j]*cj[j]; - }); - - Kokkos::View<double*[2]> Ajr("Ajr", nj); - Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j) { + Kokkos::View<double*[2]> Ajr("Ajr", m_nj); + Kokkos::parallel_for(m_nj, KOKKOS_LAMBDA(const int& j) { for (int r=0; r<2; ++r) { Ajr(j,r) = rhocj(j)*Cjr(j,r)*Cjr(j,r); } }); - Kokkos::View<double*> Ar("Ar", nr); - Kokkos::parallel_for(nr, KOKKOS_LAMBDA(const int& r) { + return Ajr; +} + +KOKKOS_INLINE_FUNCTION +const Kokkos::View<const double*> +AcousticSolver::computeAr(const Kokkos::View<const double*[2]>& Ajr, + const Kokkos::View<const int*[2]>& node_cells, + const Kokkos::View<const int*[2]>& node_cell_local_node, + const Kokkos::View<const int*>& node_nb_cells) +{ + Kokkos::View<double*> Ar("Ar", m_nr); + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r) { double sum = 0; for (int j=0; j<node_nb_cells(r); ++j) { const int J = node_cells(r,j); @@ -107,14 +88,21 @@ void AcousticSolver::computeExplicitFluxes(const Kokkos::View<const double*>& xr Ar(r) = sum; }); - Kokkos::View<double*> invAr("invAr", nr); - Kokkos::parallel_for(nr, KOKKOS_LAMBDA(const int& r) { - invAr(r) = 1./Ar(r); - }); - + return Ar; +} - Kokkos::View<double*> br("br", nr); - Kokkos::parallel_for(nr, KOKKOS_LAMBDA(const int& r) { +KOKKOS_INLINE_FUNCTION +const Kokkos::View<const double*> +AcousticSolver::computeBr(const Kokkos::View<const double*[2]>& Ajr, + const Kokkos::View<const double*[2]>& Cjr, + const Kokkos::View<const double*>& uj, + const Kokkos::View<const double*>& pj, + const Kokkos::View<const int*[2]>& node_cells, + const Kokkos::View<const int*[2]>& node_cell_local_node, + const Kokkos::View<const int*>& node_nb_cells) +{ + Kokkos::View<double*> br("br", m_nr); + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r) { double sum = 0; for (int j=0; j<node_nb_cells(r); ++j) { const int J = node_cells(r,j); @@ -124,69 +112,151 @@ void AcousticSolver::computeExplicitFluxes(const Kokkos::View<const double*>& xr br(r) = sum; }); - Kokkos::parallel_for(nr, KOKKOS_LAMBDA(const int& r) { + return br; +} + +KOKKOS_INLINE_FUNCTION +Kokkos::View<double*> +AcousticSolver::computeUr(const Kokkos::View<const double*>& Ar, + const Kokkos::View<const double*>& br) +{ + const Kokkos::View<const double*> invAr = inverse(Ar); + Kokkos::View<double*> ur("ur", m_nr); + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r) { ur[r]=br(r)*invAr(r); }); ur[0]=0; - ur[nr-1]=0; + ur[m_nr-1]=0; - Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j) { + return ur; +} + +KOKKOS_INLINE_FUNCTION +Kokkos::View<double*[2]> +AcousticSolver::computeFjr(const Kokkos::View<const double*[2]>& Ajr, + const Kokkos::View<const double*>& ur, + const Kokkos::View<const double*[2]>& Cjr, + const Kokkos::View<const double*>& uj, + const Kokkos::View<const double*>& pj, + const Kokkos::View<const int*[2]>& cell_nodes) +{ + Kokkos::View<double*[2]> Fjr("Fjr", m_nj); + + Kokkos::parallel_for(m_nj, KOKKOS_LAMBDA(const int& j) { for (int r=0; r<2; ++r) { Fjr(j,r) = Ajr(j,r)*(uj(j)-ur(cell_nodes(j,r)))+Cjr(j,r)*pj(j); } }); + + return Fjr; } -AcousticSolver::AcousticSolver(const long int& nj) +KOKKOS_INLINE_FUNCTION +double AcousticSolver:: +acoustic_dt(const Kokkos::View<const double*>& Vj, + const Kokkos::View<const double*>& cj) const +{ + double dt = std::numeric_limits<double>::max(); + + Kokkos::View<double*> Vj_cj("Vj_cj", m_nj); + + Kokkos::parallel_for(m_nj, KOKKOS_LAMBDA(const int& j){ + Vj_cj[j] = Vj[j]/cj[j]; + }); + + Kokkos::parallel_reduce(m_nj, ReduceMin(Vj_cj), dt); + + return dt; +} + +KOKKOS_INLINE_FUNCTION +const Kokkos::View<const double*> +AcousticSolver::inverse(const Kokkos::View<const double*>& x) const +{ + Kokkos::View<double*> inv_x("inv_x", x.size()); + Kokkos::parallel_for(x.size(), KOKKOS_LAMBDA(const int& r) { + inv_x(r) = 1./x(r); + }); + + return inv_x; +} + +KOKKOS_INLINE_FUNCTION +void AcousticSolver::computeExplicitFluxes(const Kokkos::View<const double*>& xr, + const Kokkos::View<const double*>& xj, + const Kokkos::View<const double*>& rhoj, + const Kokkos::View<const double*>& uj, + const Kokkos::View<const double*>& pj, + const Kokkos::View<const double*>& cj, + const Kokkos::View<const double*>& Vj, + const Kokkos::View<const double*[2]>& Cjr, + const Kokkos::View<const int*[2]>& cell_nodes, + const Kokkos::View<const int*[2]>& node_cells, + const Kokkos::View<const int*>& node_nb_cells, + const Kokkos::View<const int*[2]>& node_cell_local_node, + Kokkos::View<double*>& ur, + Kokkos::View<double*[2]>& Fjr) { - Kokkos::View<double*> xj("xj", nj); - Kokkos::View<double*> rhoj("rhoj", nj); + const Kokkos::View<const double*> rhocj = computeRhoCj(rhoj, cj); + const Kokkos::View<const double*[2]> Ajr = computeAjr(rhocj, Cjr); - Kokkos::View<double*> uj("uj", nj); + const Kokkos::View<const double*> Ar = computeAr(Ajr, node_cells, node_cell_local_node, node_nb_cells); + const Kokkos::View<const double*> br = computeBr(Ajr, Cjr, uj, pj, + node_cells, node_cell_local_node, node_nb_cells); - Kokkos::View<double*> Ej("Ej", nj); - Kokkos::View<double*> ej("ej", nj); - Kokkos::View<double*> pj("pj", nj); - Kokkos::View<double*> Vj("Vj", nj); - Kokkos::View<double*> gammaj("gammaj", nj); - Kokkos::View<double*> cj("cj", nj); - Kokkos::View<double*> mj("mj", nj); - Kokkos::View<double*> inv_mj("inv_mj", nj); + ur = computeUr(Ar, br); + Fjr = computeFjr(Ajr, ur, Cjr, uj, pj, cell_nodes); +} + +AcousticSolver::AcousticSolver(const long int& nj) + : m_nj(nj), + m_nr(nj+1) +{ + Kokkos::View<double*> xj("xj",m_nj); + Kokkos::View<double*> rhoj("rhoj",m_nj); + + Kokkos::View<double*> uj("uj",m_nj); - const int nr=nj+1; + Kokkos::View<double*> Ej("Ej",m_nj); + Kokkos::View<double*> ej("ej",m_nj); + Kokkos::View<double*> pj("pj",m_nj); + Kokkos::View<double*> Vj("Vj",m_nj); + Kokkos::View<double*> gammaj("gammaj",m_nj); + Kokkos::View<double*> cj("cj",m_nj); + Kokkos::View<double*> mj("mj",m_nj); - Kokkos::View<double*> xr("xr", nr); + Kokkos::View<double*> xr("xr", m_nr); - const double delta_x = 1./nj; + const double delta_x = 1./m_nj; - Kokkos::parallel_for(nr, KOKKOS_LAMBDA(const int& r){ + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r){ xr[r] = r*delta_x; }); - Kokkos::View<int*[2]> cell_nodes("cell_nodes",nj,2); - Kokkos::View<int*[2]> node_cells("node_cells",nr,2); - Kokkos::View<int*[2]> node_cell_local_node("node_cells",nr,2); - Kokkos::View<int*> node_nb_cells("node_cells",nr); + Kokkos::View<int*[2]> cell_nodes("cell_nodes",m_nj,2); + Kokkos::View<int*[2]> node_cells("node_cells",m_nr,2); + Kokkos::View<int*[2]> node_cell_local_node("node_cells",m_nr,2); + Kokkos::View<int*> node_nb_cells("node_cells",m_nr); - Kokkos::parallel_for(nr, KOKKOS_LAMBDA(const int& r){ + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r){ node_nb_cells(r) = 2; }); node_nb_cells(0) = 1; - node_nb_cells(nr-1) = 1; + node_nb_cells(m_nr-1) = 1; node_cells(0,0) = 0; - Kokkos::parallel_for(nr-2, KOKKOS_LAMBDA(const int& r){ + Kokkos::parallel_for(m_nr-2, KOKKOS_LAMBDA(const int& r){ node_cells(r+1,0) = r; node_cells(r+1,1) = r+1; }); - node_cells(nr-1,0) = nj-1; + node_cells(m_nr-1,0) =m_nj-1; Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ cell_nodes(j,0) = j; cell_nodes(j,1) = j+1; }); - Kokkos::parallel_for(nr, KOKKOS_LAMBDA(const int& r){ + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r){ for (int J=0; J<node_nb_cells(r); ++J) { int j = node_cells(r,J); for (int R=0; R<2; ++R) { @@ -237,13 +307,15 @@ AcousticSolver::AcousticSolver(const long int& nj) mj[j] = rhoj[j] * Vj[j]; }); + const Kokkos::View<const double*> inv_mj=inverse(mj); + const double tmax=0.2; double t=0; int itermax=std::numeric_limits<int>::max(); int iteration=0; - Kokkos::View<double*[2]> Cjr("Cjr", nj); + Kokkos::View<double*[2]> Cjr("Cjr",m_nj); Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j) { Cjr(j,0)=-1; Cjr(j,1)= 1; @@ -258,17 +330,14 @@ AcousticSolver::AcousticSolver(const long int& nj) t=tmax; } - Kokkos::View<double*> ur("ur", nr); - Kokkos::View<double*[2]> Fjr("Fjr", nr); - + Kokkos::View<double*> ur; + Kokkos::View<double*[2]> Fjr; + computeExplicitFluxes(xr, xj, rhoj, uj, pj, cj, Vj, Cjr, cell_nodes, node_cells, node_nb_cells, node_cell_local_node, ur, Fjr); - Kokkos::View<double*> new_uj("new_uj", nj); - Kokkos::View<double*> new_Ej("new_Ej", nj); - Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ double momentum_fluxes = 0; double energy_fluxes = 0; @@ -277,25 +346,18 @@ AcousticSolver::AcousticSolver(const long int& nj) momentum_fluxes += Fjr(j,R); energy_fluxes += Fjr(j,R)*ur[r]; } - new_uj[j] = uj[j] - dt/mj[j]*(momentum_fluxes); - new_Ej[j] = Ej[j] - dt/mj[j]*(energy_fluxes); + uj[j] -= dt*inv_mj[j]*(momentum_fluxes); + Ej[j] -= dt*inv_mj[j]*(energy_fluxes); }); - uj=new_uj; - Ej=new_Ej; - Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j) { ej[j] = Ej[j] - 0.5 * uj[j]*uj[j]; }); - Kokkos::View<double*> xr_new("new_xr", nr); - - Kokkos::parallel_for(nr, KOKKOS_LAMBDA(const int& r){ - xr_new[r] = xr[r] + dt*ur[r]; + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r){ + xr[r] += dt*ur[r]; }); - xr = xr_new; - Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ xj[j] = 0.5*(xr[j]+xr[j+1]); Vj[j] = xr[j+1]-xr[j]; @@ -310,6 +372,13 @@ AcousticSolver::AcousticSolver(const long int& nj) ++iteration; } + // { + // std::ofstream fout("rho"); + // for (int j=0; j<nj; ++j) { + // fout << xj[j] << ' ' << rhoj[j] << '\n'; + // } + // } + std::cout << "* " << rang::style::underline << "Final time" << rang::style::reset << ": " << rang::fgB::green << t << rang::fg::reset << " (" << iteration << " iterations)\n"; diff --git a/experimental/AcousticSolver.hpp b/experimental/AcousticSolver.hpp index ba1462770b4bb1018f0f4945cfe0892bce2a09ab..d8429d5acc023acea9ef6930c8de1306f0bc1370 100644 --- a/experimental/AcousticSolver.hpp +++ b/experimental/AcousticSolver.hpp @@ -7,8 +7,43 @@ class AcousticSolver { private: - inline double e(double rho, double p, double gamma) const; - inline double p(double rho, double e, double gamma) const; + inline const Kokkos::View<const double*> + computeRhoCj(const Kokkos::View<const double*>& rhoj, + const Kokkos::View<const double*>& cj); + + inline const Kokkos::View<const double*[2]> + computeAjr(const Kokkos::View<const double*>& rhocj, + const Kokkos::View<const double*[2]>& Cjr); + + inline const Kokkos::View<const double*> + computeAr(const Kokkos::View<const double*[2]>& Ajr, + const Kokkos::View<const int*[2]>& node_cells, + const Kokkos::View<const int*[2]>& node_cell_local_node, + const Kokkos::View<const int*>& node_nb_cells); + + inline const Kokkos::View<const double*> + computeBr(const Kokkos::View<const double*[2]>& Ajr, + const Kokkos::View<const double*[2]>& Cjr, + const Kokkos::View<const double*>& uj, + const Kokkos::View<const double*>& pj, + const Kokkos::View<const int*[2]>& node_cells, + const Kokkos::View<const int*[2]>& node_cell_local_node, + const Kokkos::View<const int*>& node_nb_cells); + + Kokkos::View<double*> + computeUr(const Kokkos::View<const double*>& Ar, + const Kokkos::View<const double*>& br); + + Kokkos::View<double*[2]> + computeFjr(const Kokkos::View<const double*[2]>& Ajr, + const Kokkos::View<const double*>& ur, + const Kokkos::View<const double*[2]>& Cjr, + const Kokkos::View<const double*>& uj, + const Kokkos::View<const double*>& pj, + const Kokkos::View<const int*[2]>& cell_nodes); + + const Kokkos::View<const double*> + inverse(const Kokkos::View<const double*>& x) const; inline double acoustic_dt(const Kokkos::View<const double*>& Vj, const Kokkos::View<const double*>& cj) const; @@ -26,9 +61,13 @@ private: const Kokkos::View<const int*>& node_nb_cells, const Kokkos::View<const int*[2]>& node_cell_local_node, Kokkos::View<double*>& ur, - Kokkos::View<double*[2]>& Fjr) const; + Kokkos::View<double*[2]>& Fjr); struct ReduceMin; + + const long int m_nj; + const long int m_nr; + public: AcousticSolver(const long int& nj); }; diff --git a/experimental/AcousticSolverTest.cpp b/experimental/AcousticSolverTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c1e190b8f06163cb952db133523067d9b142bca --- /dev/null +++ b/experimental/AcousticSolverTest.cpp @@ -0,0 +1,383 @@ +#include <AcousticSolverTest.hpp> +#include <rang.hpp> + +#include <memory> + +#include <BlockPerfectGas.hpp> + +typedef const double my_double; + +struct AcousticSolverTest::ReduceMin +{ +private: + const Kokkos::View<my_double*> x_; + +public: + typedef Kokkos::View<my_double*>::non_const_value_type value_type; + + ReduceMin(const Kokkos::View<my_double*>& x) : x_ (x) {} + + typedef Kokkos::View<my_double*>::size_type size_type; + + KOKKOS_INLINE_FUNCTION void + operator() (const size_type i, value_type& update) const + { + if (x_(i) < update) { + update = x_(i); + } + } + + KOKKOS_INLINE_FUNCTION void + join (volatile value_type& dst, + const volatile value_type& src) const + { + if (src < dst) { + dst = src; + } + } + + KOKKOS_INLINE_FUNCTION void + init (value_type& dst) const + { // The identity under max is -Inf. + dst= Kokkos::reduction_identity<value_type>::min(); + } +}; + +KOKKOS_INLINE_FUNCTION +const Kokkos::View<const double*> +AcousticSolverTest::computeRhoCj(const Kokkos::View<const double*>& rhoj, + const Kokkos::View<const double*>& cj) +{ + Kokkos::parallel_for(m_nj, KOKKOS_LAMBDA(const int& j) { + m_rhocj[j] = rhoj[j]*cj[j]; + }); + return m_rhocj; +} + +KOKKOS_INLINE_FUNCTION +const Kokkos::View<const double*[2]> +AcousticSolverTest::computeAjr(const Kokkos::View<const double*>& rhocj, + const Kokkos::View<const double*[2]>& Cjr) +{ + Kokkos::parallel_for(m_nj, KOKKOS_LAMBDA(const int& j) { + for (int r=0; r<2; ++r) { + m_Ajr(j,r) = rhocj(j)*Cjr(j,r)*Cjr(j,r); + } + }); + + return m_Ajr; +} + +KOKKOS_INLINE_FUNCTION +const Kokkos::View<const double*> +AcousticSolverTest::computeAr(const Kokkos::View<const double*[2]>& Ajr, + const Kokkos::View<const int*[2]>& node_cells, + const Kokkos::View<const int*[2]>& node_cell_local_node, + const Kokkos::View<const int*>& node_nb_cells) +{ + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r) { + double sum = 0; + for (int j=0; j<node_nb_cells(r); ++j) { + const int J = node_cells(r,j); + const int R = node_cell_local_node(r,j); + sum += Ajr(J,R); + } + m_Ar(r) = sum; + }); + + return m_Ar; +} + +KOKKOS_INLINE_FUNCTION +const Kokkos::View<const double*> +AcousticSolverTest::computeBr(const Kokkos::View<const double*[2]>& Ajr, + const Kokkos::View<const double*[2]>& Cjr, + const Kokkos::View<const double*>& uj, + const Kokkos::View<const double*>& pj, + const Kokkos::View<const int*[2]>& node_cells, + const Kokkos::View<const int*[2]>& node_cell_local_node, + const Kokkos::View<const int*>& node_nb_cells) +{ + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r) { + double sum = 0; + for (int j=0; j<node_nb_cells(r); ++j) { + const int J = node_cells(r,j); + const int R = node_cell_local_node(r,j); + sum += Ajr(J,R)*uj(J) + Cjr(J,R)*pj(J); + } + m_br(r) = sum; + }); + + return m_br; +} + +KOKKOS_INLINE_FUNCTION +Kokkos::View<double*> +AcousticSolverTest::computeUr(const Kokkos::View<const double*>& Ar, + const Kokkos::View<const double*>& br) +{ + inverse(Ar, m_inv_Ar); + const Kokkos::View<const double*> invAr = m_inv_Ar; + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r) { + m_ur[r]=br(r)*invAr(r); + }); + m_ur[0]=0; + m_ur[m_nr-1]=0; + + return m_ur; +} + +KOKKOS_INLINE_FUNCTION +Kokkos::View<double*[2]> +AcousticSolverTest::computeFjr(const Kokkos::View<const double*[2]>& Ajr, + const Kokkos::View<const double*>& ur, + const Kokkos::View<const double*[2]>& Cjr, + const Kokkos::View<const double*>& uj, + const Kokkos::View<const double*>& pj, + const Kokkos::View<const int*[2]>& cell_nodes) +{ + Kokkos::parallel_for(m_nj, KOKKOS_LAMBDA(const int& j) { + for (int r=0; r<2; ++r) { + m_Fjr(j,r) = Ajr(j,r)*(uj(j)-ur(cell_nodes(j,r)))+Cjr(j,r)*pj(j); + } + }); + + return m_Fjr; +} + +KOKKOS_INLINE_FUNCTION +double AcousticSolverTest:: +acoustic_dt(const Kokkos::View<const double*>& Vj, + const Kokkos::View<const double*>& cj) const +{ + Kokkos::parallel_for(m_nj, KOKKOS_LAMBDA(const int& j){ + m_Vj_over_cj[j] = Vj[j]/cj[j]; + }); + + double dt = std::numeric_limits<double>::max(); + Kokkos::parallel_reduce(m_nj, ReduceMin(m_Vj_over_cj), dt); + + return dt; +} + +KOKKOS_INLINE_FUNCTION +void +AcousticSolverTest::inverse(const Kokkos::View<const double*>& x, + Kokkos::View<double*>& inv_x) const +{ + Kokkos::parallel_for(x.size(), KOKKOS_LAMBDA(const int& r) { + inv_x(r) = 1./x(r); + }); +} + +KOKKOS_INLINE_FUNCTION +void AcousticSolverTest::computeExplicitFluxes(const Kokkos::View<const double*>& xr, + const Kokkos::View<const double*>& xj, + const Kokkos::View<const double*>& rhoj, + const Kokkos::View<const double*>& uj, + const Kokkos::View<const double*>& pj, + const Kokkos::View<const double*>& cj, + const Kokkos::View<const double*>& Vj, + const Kokkos::View<const double*[2]>& Cjr, + const Kokkos::View<const int*[2]>& cell_nodes, + const Kokkos::View<const int*[2]>& node_cells, + const Kokkos::View<const int*>& node_nb_cells, + const Kokkos::View<const int*[2]>& node_cell_local_node, + Kokkos::View<double*>& ur, + Kokkos::View<double*[2]>& Fjr) +{ + const Kokkos::View<const double*> rhocj = computeRhoCj(rhoj, cj); + const Kokkos::View<const double*[2]> Ajr = computeAjr(rhocj, Cjr); + + const Kokkos::View<const double*> Ar = computeAr(Ajr, node_cells, node_cell_local_node, node_nb_cells); + const Kokkos::View<const double*> br = computeBr(Ajr, Cjr, uj, pj, + node_cells, node_cell_local_node, node_nb_cells); + + ur = computeUr(Ar, br); + Fjr = computeFjr(Ajr, ur, Cjr, uj, pj, cell_nodes); +} + +AcousticSolverTest::AcousticSolverTest(const long int& nj) + : m_nj(nj), + m_nr(nj+1), + m_br("br", m_nr), + m_Ajr("Ajr", m_nj), + m_Ar("Ar", m_nr), + m_inv_Ar("inv_Ar", m_nr), + m_Fjr("Fjr", m_nj), + m_ur("ur", m_nr), + m_rhocj("rho_c", m_nj), + m_Vj_over_cj("Vj_over_cj", m_nj) +{ + Kokkos::View<double*> xj("xj",m_nj); + Kokkos::View<double*> rhoj("rhoj",m_nj); + + Kokkos::View<double*> uj("uj",m_nj); + + Kokkos::View<double*> Ej("Ej",m_nj); + Kokkos::View<double*> ej("ej",m_nj); + Kokkos::View<double*> pj("pj",m_nj); + Kokkos::View<double*> Vj("Vj",m_nj); + Kokkos::View<double*> gammaj("gammaj",m_nj); + Kokkos::View<double*> cj("cj",m_nj); + Kokkos::View<double*> mj("mj",m_nj); + + Kokkos::View<double*> xr("xr", m_nr); + + const double delta_x = 1./m_nj; + + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r){ + xr[r] = r*delta_x; + }); + + Kokkos::View<int*[2]> cell_nodes("cell_nodes",m_nj,2); + Kokkos::View<int*[2]> node_cells("node_cells",m_nr,2); + Kokkos::View<int*[2]> node_cell_local_node("node_cells",m_nr,2); + Kokkos::View<int*> node_nb_cells("node_cells",m_nr); + + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r){ + node_nb_cells(r) = 2; + }); + node_nb_cells(0) = 1; + node_nb_cells(m_nr-1) = 1; + + node_cells(0,0) = 0; + Kokkos::parallel_for(m_nr-2, KOKKOS_LAMBDA(const int& r){ + node_cells(r+1,0) = r; + node_cells(r+1,1) = r+1; + }); + node_cells(m_nr-1,0) =m_nj-1; + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + cell_nodes(j,0) = j; + cell_nodes(j,1) = j+1; + }); + + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r){ + for (int J=0; J<node_nb_cells(r); ++J) { + int j = node_cells(r,J); + for (int R=0; R<2; ++R) { + if (cell_nodes(j,R) == r) { + node_cell_local_node(r,J) = R; + } + } + } + }); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + xj[j] = 0.5*(xr[cell_nodes(j,0)]+xr[cell_nodes(j,1)]); + }); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + Vj[j] = xr[cell_nodes(j,1)]-xr[cell_nodes(j,0)]; + }); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + if (xj[j]<0.5) { + rhoj[j]=1; + } else { + rhoj[j]=0.125; + } + }); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + if (xj[j]<0.5) { + pj[j]=1; + } else { + pj[j]=0.1; + } + }); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + gammaj[j] = 1.4; + }); + + BlockPerfectGas block_eos(rhoj, ej, pj, gammaj, cj); + + block_eos.updateEandCFromRhoP(); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + Ej[j] = ej[j]+0.5*uj[j]*uj[j]; + }); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + mj[j] = rhoj[j] * Vj[j]; + }); + + Kokkos::View<double*> inv_mj("inv_mj",m_nj); + inverse(mj, inv_mj); + + const double tmax=0.2; + double t=0; + + int itermax=std::numeric_limits<int>::max(); + int iteration=0; + + Kokkos::View<double*[2]> Cjr("Cjr",m_nj); + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j) { + Cjr(j,0)=-1; + Cjr(j,1)= 1; + }); + + while((t<tmax) and (iteration<itermax)) { + double dt = 0.4*acoustic_dt(Vj, cj); + if (t+dt<tmax) { + t+=dt; + } else { + dt=tmax-t; + t=tmax; + } + + computeExplicitFluxes(xr, xj, + rhoj, uj, pj, cj, Vj, Cjr, + cell_nodes, node_cells, node_nb_cells, node_cell_local_node, + m_ur, m_Fjr); + + const Kokkos::View<const double*[2]> Fjr = m_Fjr; + const Kokkos::View<const double*> ur = m_ur; + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + double momentum_fluxes = 0; + double energy_fluxes = 0; + for (int R=0; R<2; ++R) { + const int r=cell_nodes(j,R); + momentum_fluxes += Fjr(j,R); + energy_fluxes += Fjr(j,R)*ur[r]; + } + uj[j] -= dt*inv_mj[j]*(momentum_fluxes); + Ej[j] -= dt*inv_mj[j]*(energy_fluxes); + }); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j) { + ej[j] = Ej[j] - 0.5 * uj[j]*uj[j]; + }); + + Kokkos::parallel_for(m_nr, KOKKOS_LAMBDA(const int& r){ + xr[r] += dt*ur[r]; + }); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + xj[j] = 0.5*(xr[j]+xr[j+1]); + Vj[j] = xr[j+1]-xr[j]; + }); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + rhoj[j] = mj[j]/Vj[j]; + }); + + block_eos.updatePandCFromRhoE(); + + ++iteration; + } + + // { + // std::ofstream fout("rho"); + // for (int j=0; j<nj; ++j) { + // fout << xj[j] << ' ' << rhoj[j] << '\n'; + // } + // } + + std::cout << "* " << rang::style::underline << "Final time" << rang::style::reset + << ": " << rang::fgB::green << t << rang::fg::reset << " (" << iteration << " iterations)\n"; + +} diff --git a/experimental/AcousticSolverTest.hpp b/experimental/AcousticSolverTest.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f1281635550cb9323452c5d4cb85e688b6216704 --- /dev/null +++ b/experimental/AcousticSolverTest.hpp @@ -0,0 +1,84 @@ +#ifndef ACOUSTIC_SOLVER_TEST_HPP +#define ACOUSTIC_SOLVER_TEST_HPP + +#include <Kokkos_Core.hpp> + +class AcousticSolverTest +{ +private: + inline const Kokkos::View<const double*> + computeRhoCj(const Kokkos::View<const double*>& rhoj, + const Kokkos::View<const double*>& cj); + + inline const Kokkos::View<const double*[2]> + computeAjr(const Kokkos::View<const double*>& rhocj, + const Kokkos::View<const double*[2]>& Cjr); + + inline const Kokkos::View<const double*> + computeAr(const Kokkos::View<const double*[2]>& Ajr, + const Kokkos::View<const int*[2]>& node_cells, + const Kokkos::View<const int*[2]>& node_cell_local_node, + const Kokkos::View<const int*>& node_nb_cells); + + inline const Kokkos::View<const double*> + computeBr(const Kokkos::View<const double*[2]>& Ajr, + const Kokkos::View<const double*[2]>& Cjr, + const Kokkos::View<const double*>& uj, + const Kokkos::View<const double*>& pj, + const Kokkos::View<const int*[2]>& node_cells, + const Kokkos::View<const int*[2]>& node_cell_local_node, + const Kokkos::View<const int*>& node_nb_cells); + + Kokkos::View<double*> + computeUr(const Kokkos::View<const double*>& Ar, + const Kokkos::View<const double*>& br); + + Kokkos::View<double*[2]> + computeFjr(const Kokkos::View<const double*[2]>& Ajr, + const Kokkos::View<const double*>& ur, + const Kokkos::View<const double*[2]>& Cjr, + const Kokkos::View<const double*>& uj, + const Kokkos::View<const double*>& pj, + const Kokkos::View<const int*[2]>& cell_nodes); + + void inverse(const Kokkos::View<const double*>& x, + Kokkos::View<double*>& inv_x) const; + + inline double acoustic_dt(const Kokkos::View<const double*>& Vj, + const Kokkos::View<const double*>& cj) const; + + inline void computeExplicitFluxes(const Kokkos::View<const double*>& xr, + const Kokkos::View<const double*>& xj, + const Kokkos::View<const double*>& rhoj, + const Kokkos::View<const double*>& uj, + const Kokkos::View<const double*>& pj, + const Kokkos::View<const double*>& cj, + const Kokkos::View<const double*>& Vj, + const Kokkos::View<const double*[2]>& Cjr, + const Kokkos::View<const int*[2]>& cell_nodes, + const Kokkos::View<const int*[2]>& node_cells, + const Kokkos::View<const int*>& node_nb_cells, + const Kokkos::View<const int*[2]>& node_cell_local_node, + Kokkos::View<double*>& ur, + Kokkos::View<double*[2]>& Fjr); + + struct ReduceMin; + + const long int m_nj; + const long int m_nr; + + Kokkos::View<double*> m_br; + Kokkos::View<double*[2]> m_Ajr; + Kokkos::View<double*> m_Ar; + Kokkos::View<double*> m_inv_Ar; + Kokkos::View<double*[2]> m_Fjr; + Kokkos::View<double*> m_ur; + Kokkos::View<double*> m_rhocj; + Kokkos::View<double*> m_Vj_over_cj; + + +public: + AcousticSolverTest(const long int& nj); +}; + +#endif // ACOUSTIC_SOLVER_TEST_HPP diff --git a/experimental/CMakeLists.txt b/experimental/CMakeLists.txt index bd8990bd83911408a40c53a874945e753d732b33..35eeea33d4e73abd2217fa5f8e57f754ec52d3be 100644 --- a/experimental/CMakeLists.txt +++ b/experimental/CMakeLists.txt @@ -9,6 +9,7 @@ include_directories(${PASTIS_SOURCE_DIR}/packages/rang/include) add_library( PastisExperimental AcousticSolver.cpp + AcousticSolverTest.cpp RawKokkosAcousticSolver.cpp MeshLessAcousticSolver.cpp ) diff --git a/experimental/MeshLessAcousticSolver.cpp b/experimental/MeshLessAcousticSolver.cpp index edf67693c9ab3b23d5f9d9a50ab9fea8efdb830e..bf501448130f9e2291a2692d956f2757f5ccfc05 100644 --- a/experimental/MeshLessAcousticSolver.cpp +++ b/experimental/MeshLessAcousticSolver.cpp @@ -172,6 +172,10 @@ MeshLessAcousticSolver::MeshLessAcousticSolver(const long int& nj) mj[j] = rhoj[j] * Vj[j]; }); + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + inv_mj[j] = 1./mj[j]; + }); + const double tmax=0.2; double t=0; @@ -201,8 +205,8 @@ MeshLessAcousticSolver::MeshLessAcousticSolver(const long int& nj) int rm=j; int rp=j+1; - new_uj[j] = uj[j] + dt/mj[j]*(pr[rm]-pr[rp]); - new_Ej[j] = Ej[j] + dt/mj[j]*(pr[rm]*ur[rm]-pr[rp]*ur[rp]); + new_uj[j] = uj[j] + dt*inv_mj[j]*(pr[rm]-pr[rp]); + new_Ej[j] = Ej[j] + dt*inv_mj[j]*(pr[rm]*ur[rm]-pr[rp]*ur[rp]); }); uj=new_uj; diff --git a/experimental/RawKokkosAcousticSolver.cpp b/experimental/RawKokkosAcousticSolver.cpp index b7369fde473d8d18286182edb7269fe26166dd19..d27549d349183d6eb714be477750ca4fee6381b5 100644 --- a/experimental/RawKokkosAcousticSolver.cpp +++ b/experimental/RawKokkosAcousticSolver.cpp @@ -185,6 +185,10 @@ void AcousticSolver(const long int& nj) mj[j] = rhoj[j] * Vj[j]; }); + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + inv_mj[j] = 1./mj[j]; + }); + const double tmax=0.2; double t=0; @@ -211,8 +215,8 @@ void AcousticSolver(const long int& nj) int rm=j; int rp=j+1; - uj[j] += dt/mj[j]*(pr[rm]-pr[rp]); - Ej[j] += dt/mj[j]*(pr[rm]*ur[rm]-pr[rp]*ur[rp]); + uj[j] += dt*inv_mj[j]*(pr[rm]-pr[rp]); + Ej[j] += dt*inv_mj[j]*(pr[rm]*ur[rm]-pr[rp]*ur[rp]); }); Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ diff --git a/main.cpp b/main.cpp index 981358f6c9309d58ccba0fa49e4519e212af16a4..f2a8f173cdc0bb527e731c54cd5072a4abac99bb 100644 --- a/main.cpp +++ b/main.cpp @@ -9,6 +9,9 @@ #include <RawKokkosAcousticSolver.hpp> #include <MeshLessAcousticSolver.hpp> #include <AcousticSolver.hpp> +#include <AcousticSolverTest.hpp> + +#include <TinyVector.hpp> #include <CLI/CLI.hpp> #include <cassert> @@ -92,6 +95,13 @@ int main(int argc, char *argv[]) method_cost_map["MeshLessAcousticSolver"] = timer.seconds(); } + { // class for acoustic solver test + Kokkos::Timer timer; + timer.reset(); + AcousticSolverTest acoustic_solver(number); + method_cost_map["AcousticSolverTest"] = timer.seconds(); + } + { // class for acoustic solver Kokkos::Timer timer; timer.reset(); @@ -99,6 +109,12 @@ int main(int argc, char *argv[]) method_cost_map["AcousticSolver"] = timer.seconds(); } + Kokkos::View<TinyVector<2,double>*[2]> test("test", 10); + constexpr size_t N = 3; + std::cout << "sizeof(TinyVector<" << N << ",double>)=" << sizeof(TinyVector<N,double>) << std::endl; + std::cout << "sizeof(double)=" << sizeof(double) << std::endl; + + Kokkos::finalize(); std::cout << "----------------------\n"; @@ -117,5 +133,13 @@ int main(int argc, char *argv[]) << rang::style::reset << '\n'; } + TinyVector<2> x=1; + TinyVector<2> y=2; + + std::cout << x << "-" << y << "=" << x-y << std::endl; + std::cout << x << "+" << y << "=" << x+y << std::endl; + std::cout << "3*" << x << '=' << 3*x << std::endl; + x[1]=3; y[1]=0.1; + std::cout << "< " << x << " | " << y << " > = " << (x,y) << std::endl; return 0; } diff --git a/utils/BacktraceManager.cpp b/utils/BacktraceManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8df01921e1f477ef071a68993e07b15e4548cdad --- /dev/null +++ b/utils/BacktraceManager.cpp @@ -0,0 +1,62 @@ +#include <BacktraceManager.hpp> + +#include <iomanip> +#include <rang.hpp> + +#include <execinfo.h> +#include <cxxabi.h> +#include <regex> +#include <cmath> + +BacktraceManager:: +BacktraceManager() +{ + const int size = 100; + void *buffer[size]; + + int ret = ::backtrace(buffer, size); + char **ptr = backtrace_symbols(buffer, ret); + + for (int i=2; i<ret; ++i) { + m_lines.push_back(ptr[i]); + } + + free(ptr); +} + +std::ostream& operator<<(std::ostream& os, + const BacktraceManager& btm) +{ + const std::vector<std::string>& lines = btm.m_lines; + + const std::regex mangled_function(R"%(\(.*\+)%"); + const int width=std::log10(lines.size())+1; + + for (size_t i_line=0; i_line<lines.size(); ++i_line) { + const auto& line = lines[i_line]; + os << rang::fg::green << "[" << std::setw(width) << i_line+1 << '/' << lines.size() << "] " << rang::fg::reset; + std::smatch matchex; + int status = -1; + if (std::regex_search(line, matchex, mangled_function)) { + std::string prefix = matchex.prefix().str(); + std::string function = line.substr(matchex.position()+1,matchex.length()-2); + std::string suffix = matchex.suffix().str(); + + os << prefix << '('; + if (function.size() > 0) { + char* demangled = abi::__cxa_demangle(function.c_str(), NULL, NULL, &status); + if (status==0) { + os << rang::fgB::yellow << demangled << rang::fg::reset; + free(demangled); + } else { + os << rang::fgB::yellow << function << rang::fg::reset; + } + } + os<< '+' << suffix << '\n'; + } else { + os << line << '\n'; + } + } + + return os; +} diff --git a/utils/BacktraceManager.hpp b/utils/BacktraceManager.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cb2fdc9f9d93e360fd13e8fa886019a7f327ed89 --- /dev/null +++ b/utils/BacktraceManager.hpp @@ -0,0 +1,21 @@ +#ifndef BACKTRACE_MANAGER_HPP +#define BACKTRACE_MANAGER_HPP + +#include <vector> +#include <string> + +class BacktraceManager +{ +private: + std::vector<std::string> m_lines; + +public: + BacktraceManager(); + + friend std::ostream& operator<<(std::ostream& os, const BacktraceManager& btm); + + BacktraceManager(const BacktraceManager&) = default; + ~BacktraceManager() = default; +}; + +#endif // BACKTRACE_MANAGER_HPP diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index b1a57d9cfbf6446db736f950d4ce158057f59b4d..e8877d862b05e786c0e3d3b65cad217c89b03296 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_library( PastisUtils + BacktraceManager.cpp ConsoleManager.cpp FPEManager.cpp RevisionInfo.cpp diff --git a/utils/SignalManager.cpp b/utils/SignalManager.cpp index f82d0f4e6336fa3b09211cae5be691f2eb79f0cc..271720d0df0d3c60738dc8300ca3675100c6b943 100644 --- a/utils/SignalManager.cpp +++ b/utils/SignalManager.cpp @@ -1,85 +1,98 @@ #include <SignalManager.hpp> + +#include <BacktraceManager.hpp> #include <ConsoleManager.hpp> + #include <csignal> #include <rang.hpp> -#include <iomanip> -#warning must create a specific class for pausing and use enum class -#include <string> std::string SignalManager::s_pause_on_error = "auto"; void SignalManager::setPauseForDebug(const std::string& pause_on_error) { s_pause_on_error = pause_on_error; } -std::string SignalManager::signalName(int s) +std::string SignalManager::signalName(const int& signal) { - switch (s) { - case SIGTERM: return "SIGTERM"; - case SIGSEGV: return "SIGSEGV"; - case SIGINT: return "SIGINT"; + switch (signal) { case SIGILL: return "SIGILL"; - case SIGABRT: return "SIGABRT"; case SIGFPE: return "SIGFPE"; + case SIGABRT: return "SIGABRT"; + case SIGINT: return "SIGINT"; + case SIGSEGV: return "SIGSEGV"; + case SIGTERM: return "SIGTERM"; } return "SIGNAL undefined!"; } -void SignalManager::pauseForDebug() +void SignalManager::pauseForDebug(const int& signal) { - std::cerr << "\n======================================\n"; - std::cerr << rang::style::reset + + std::cout << "\n======================================\n"; + std::cout << rang::style::reset << rang::fg::reset << rang::style::bold; - std::cerr << "to attach gdb to this process run\n"; - std::cerr << "\tgdb -pid " + std::cout << "to attach gdb to this process run\n"; + std::cout << "\tgdb -pid " << rang::fg::red << getpid() << rang::fg::reset << '\n'; - std::cerr << "else press Control-C to exit\n"; - std::cerr << rang::style::reset; - std::cerr << "======================================\n"; + std::cout << "else press Control-C to exit\n"; + std::cout << rang::style::reset; + std::cout << "======================================\n"; + std::cout << std::flush; ::sigset_t sig; ::sigaddset(&sig,SIGSTOP); ::sigsuspend(&sig); -} -//#include <libunwind.h> + std::exit(signal); +} -void SignalManager::handler(int s) +void SignalManager::handler(int signal) { + std::signal(SIGFPE, SIG_DFL); + std::signal(SIGSEGV, SIG_IGN); + std::signal(SIGTERM, SIG_DFL); + std::signal(SIGINT, SIG_DFL); + std::signal(SIGABRT, SIG_DFL); + std::cerr << "\n *** " << rang::style::reset << rang::fg::reset << rang::style::bold; std::cerr << "Signal " << rang::fgB::yellow - << signalName(s) + << signalName(signal) << rang::fg::reset << " caught" << rang::style::reset << " ***\n"; + BacktraceManager bm; + std::cerr << bm << '\n'; + if ((ConsoleManager::isTerminal(std::cout) and (s_pause_on_error == "auto")) or (s_pause_on_error == "yes")) { - std::signal(SIGINT, SIG_DFL); - SignalManager::pauseForDebug(); + SignalManager::pauseForDebug(signal); } else { - std::exit(0); + std::exit(signal); } } void SignalManager::init(const bool& enable) { + if (enable) { std::signal(SIGFPE, SignalManager::handler); std::signal(SIGSEGV, SignalManager::handler); std::signal(SIGTERM, SignalManager::handler); std::signal(SIGINT, SignalManager::handler); std::signal(SIGABRT, SignalManager::handler); + std::signal(SIGPIPE, SignalManager::handler); + std::cout << "Signal management: " << rang::style::bold << rang::fgB::green diff --git a/utils/SignalManager.hpp b/utils/SignalManager.hpp index d4ff3239dfaa7b7dde7315eedc55d73e43c0545e..6232fdee2b941868352d4c555cb05ca8491ccc34 100644 --- a/utils/SignalManager.hpp +++ b/utils/SignalManager.hpp @@ -7,8 +7,8 @@ struct SignalManager { private: static std::string s_pause_on_error; - static std::string signalName(int signal); - static void pauseForDebug(); + static std::string signalName(const int& signal); + static void pauseForDebug(const int& signal); static void handler(int signal); public: static void setPauseForDebug(const std::string& pause_on_error);