diff --git a/experimental/AcousticSolver.cpp b/experimental/AcousticSolver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f9984d2bb70e6f88a1d3dae379ed31b5cd60290 --- /dev/null +++ b/experimental/AcousticSolver.cpp @@ -0,0 +1,253 @@ +#include <AcousticSolver.hpp> +#include <rang.hpp> + + +KOKKOS_INLINE_FUNCTION +double AcousticSolver::e(double rho, double p, double gamma) const +{ + return p/(rho*(gamma-1)); +} + +KOKKOS_INLINE_FUNCTION +double AcousticSolver::p(double rho, double e, double gamma) const +{ + return (gamma-1)*rho*e; +} + +typedef const double my_double; + +struct AcousticSolver::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 +double AcousticSolver:: +acoustic_dt(const Kokkos::View<const double*>& Vj, + const Kokkos::View<const double*>& cj) const +{ + 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::parallel_reduce(nj, ReduceMin(Vj_cj), dt); + + return dt; +} + + +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, + Kokkos::View<double*>& ur, + Kokkos::View<double*>& pr) const +{ + // calcul de ur + ur[0]=0; + const size_t nr = ur.size(); + const size_t nj = uj.size(); + + Kokkos::parallel_for(nj-1, KOKKOS_LAMBDA(const int& j) { + const int r = j+1; + const int k = r; + + const double ujr = uj[j]; + const double ukr = uj[k]; + const double pjr = pj[j]; + const double pkr = pj[k]; + + ur[r]=(rhoj[j]*cj[j]*ujr + rhoj[k]*cj[k]*ukr + pjr-pkr)/(rhoj[j]*cj[j]+rhoj[k]*cj[k]); + }); + ur[nr-1]=0; + + // calcul de pr + pr[0] = pj[0] + rhoj[0]*cj[0]*(ur[0] - uj[0]); + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j) { + const int r = j+1; + + const double ujr = uj[j]; + const double pjr = pj[j]; + + pr[r]=pjr+rhoj[j]*cj[j]*(ujr-ur[r]); + }); +} + + +AcousticSolver::AcousticSolver(const long int& nj) +{ + Kokkos::View<double*> xj("xj", nj); + Kokkos::View<double*> rhoj("rhoj", nj); + + Kokkos::View<double*> uj("uj", nj); + + 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); + + const int nr=nj+1; + + Kokkos::View<double*> xr("xr", nr); + + const double delta_x = 1./nj; + + Kokkos::parallel_for(nr, KOKKOS_LAMBDA(const int& r){ + xr[r] = r*delta_x; + }); + + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + xj[j] = 0.5*(xr[j]+xr[j+1]); + }); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + Vj[j] = xr[j+1]-xr[j]; + }); + + 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; + }); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + ej[j] = e(rhoj[j],pj[j],gammaj[j]); + }); + + 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){ + cj[j] = std::sqrt(gammaj[j]*pj[j]/rhoj[j]); + }); + + Kokkos::parallel_for(nj, KOKKOS_LAMBDA(const int& j){ + mj[j] = rhoj[j] * Vj[j]; + }); + + const double tmax=0.2; + double t=0; + + int itermax=std::numeric_limits<int>::max(); + int iteration=0; + + 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; + } + + // if (iteration%100 == 0) { + // std::cout << "dt=" << dt << " t=" << t << " i=" << iteration << std::endl; + // } + + Kokkos::View<double*> ur("ur", nr); + Kokkos::View<double*> pr("pr", nr); + + computeExplicitFluxes(xr, xj, + rhoj, uj, pj, cj, Vj, + ur, pr); + + 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){ + 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]); + }); + + 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::parallel_for(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]; + pj[j] = p(rhoj[j], ej[j], gammaj[j]); + cj[j] = std::sqrt(gammaj[j]*pj[j]/rhoj[j]); // inv_mj*vj + }); + + ++iteration; + } + + 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 new file mode 100644 index 0000000000000000000000000000000000000000..153d64f5603e3fb0e531af583f49f0912bec29a6 --- /dev/null +++ b/experimental/AcousticSolver.hpp @@ -0,0 +1,31 @@ +#ifndef ACOUSTIC_SOLVER_HPP +#define ACOUSTIC_SOLVER_HPP + +#include <Kokkos_Core.hpp> + +class AcousticSolver +{ +private: + + inline double e(double rho, double p, double gamma) const; + inline double p(double rho, double e, double gamma) 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, + Kokkos::View<double*>& ur, + Kokkos::View<double*>& pr) const; + + struct ReduceMin; +public: + AcousticSolver(const long int& nj); +}; + +#endif // ACOUSTIC_SOLVER_HPP diff --git a/experimental/CMakeLists.txt b/experimental/CMakeLists.txt index 30584083c0339ba99d4dd97fe02ea784b8e312fb..1625c89b3d68db3eff6445f69fc8dfb8971fd574 100644 --- a/experimental/CMakeLists.txt +++ b/experimental/CMakeLists.txt @@ -9,6 +9,7 @@ include_directories(${PASTIS_SOURCE_DIR}/packages/rang/include) add_library( PastisExperimental RawKokkosAcousticSolver.cpp + AcousticSolver.cpp ) diff --git a/experimental/RawKokkosAcousticSolver.cpp b/experimental/RawKokkosAcousticSolver.cpp index 77b68454c72d6bb461d2338f96279b81177a2447..b7369fde473d8d18286182edb7269fe26166dd19 100644 --- a/experimental/RawKokkosAcousticSolver.cpp +++ b/experimental/RawKokkosAcousticSolver.cpp @@ -199,10 +199,6 @@ void AcousticSolver(const long int& nj) dt=tmax-t; t=tmax; } - - if (iteration%100 == 0) { - std::cout << "dt=" << dt << " t=" << t << " i=" << iteration << std::endl; - } Kokkos::View<double*> ur("ur", nr); Kokkos::View<double*> pr("pr", nr); @@ -243,15 +239,6 @@ void AcousticSolver(const long int& nj) std::cout << "* " << rang::style::underline << "Final time" << rang::style::reset << ": " << rang::fgB::green << t << rang::fg::reset << " (" << iteration << " iterations)\n"; - - // { - // std::ofstream fout("rho"); - - // for (int j=0; j<nj; ++j) { - // fout << xj[j] << ' ' << rhoj[j] << '\n'; - // } - // } - } } diff --git a/main.cpp b/main.cpp index ee597d14fc257f02d98f576a9b985754e4201210..f1b143f4515009fc7d277b782d8780ba8d8a5eba 100644 --- a/main.cpp +++ b/main.cpp @@ -7,10 +7,12 @@ #include <ConsoleManager.hpp> #include <RawKokkosAcousticSolver.hpp> +#include <AcousticSolver.hpp> #include <CLI/CLI.hpp> #include <cassert> #include <limits> +#include <map> int main(int argc, char *argv[]) { @@ -73,13 +75,39 @@ int main(int argc, char *argv[]) Kokkos::initialize(argc, argv); Kokkos::DefaultExecutionSpace::print_configuration(std::cout); - Kokkos::Timer timer; - timer.reset(); - RawKokkos::AcousticSolver(number); - double count_time = timer.seconds(); - std::cout << "* Execution time: " << rang::style::bold << count_time << rang::style::reset << '\n'; + std::map<std::string, double> method_cost_map; + // { + // Kokkos::Timer timer; + // timer.reset(); + // RawKokkos::AcousticSolver(number); + // method_cost_map["RawKokkos"] = timer.seconds(); + // } + + { + Kokkos::Timer timer; + timer.reset(); + AcousticSolver acoustic_solver(number); + method_cost_map["Class"] = timer.seconds(); + } Kokkos::finalize(); + std::cout << "----------------------\n"; + + std::string::size_type size=0; + for (const auto& method_cost : method_cost_map) { + size = std::max(size, method_cost.first.size()); + } + size+=2; + + for (const auto& method_cost : method_cost_map) { + std::cout << "* [" << std::setw(size) << std::left + << method_cost.first + << " ] Execution time: " + << rang::style::bold + << method_cost.second + << rang::style::reset << '\n'; + } + return 0; }