aboutsummaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/Make.WarpX17
-rw-r--r--Source/Particles/MultiParticleContainer.H14
-rw-r--r--Source/Particles/MultiParticleContainer.cpp59
-rw-r--r--Source/Particles/PhysicalParticleContainer.H1
-rw-r--r--Source/QED/BreitWheelerEngineTableBuilder.H11
-rw-r--r--Source/QED/BreitWheelerEngineTableBuilder.cpp14
-rw-r--r--Source/QED/BreitWheelerEngineWrapper.H176
-rw-r--r--Source/QED/BreitWheelerEngineWrapper.cpp199
-rw-r--r--Source/QED/Make.package11
-rw-r--r--Source/QED/QedChiFunctions.H38
-rw-r--r--Source/QED/QedTableParserHelperFunctions.H44
-rw-r--r--Source/QED/QedWrapperCommons.H32
-rw-r--r--Source/QED/QuantumSyncEngineTableBuilder.H6
-rw-r--r--Source/QED/QuantumSyncEngineTableBuilder.cpp13
-rw-r--r--Source/QED/QuantumSyncEngineWrapper.H168
-rw-r--r--Source/QED/QuantumSyncEngineWrapper.cpp149
16 files changed, 930 insertions, 22 deletions
diff --git a/Source/Make.WarpX b/Source/Make.WarpX
index 54baecbf6..b9fe0a258 100644
--- a/Source/Make.WarpX
+++ b/Source/Make.WarpX
@@ -83,11 +83,6 @@ ifeq ($(USE_SENSEI_INSITU),TRUE)
endif
ifeq ($(QED),TRUE)
- BOOST_ROOT ?= NOT_SET
- ifneq ($(BOOST_ROOT),NOT_SET)
- VPATH_LOCATIONS += $(BOOST_ROOT)
- INCLUDE_LOCATIONS += $(BOOST_ROOT)
- endif
INCLUDE_LOCATIONS += $(PICSAR_HOME)/src/multi_physics/QED/src
CXXFLAGS += -DWARPX_QED
CFLAGS += -DWARPX_QED
@@ -95,8 +90,20 @@ ifeq ($(QED),TRUE)
F90FLAGS += -DWARPX_QED
include $(WARPX_HOME)/Source/QED/Make.package
USERSuffix := $(USERSuffix).QED
+
+ ifeq ($(QED_TABLE_GEN),TRUE)
+ BOOST_ROOT ?= NOT_SET
+ ifneq ($(BOOST_ROOT),NOT_SET)
+ VPATH_LOCATIONS += $(BOOST_ROOT)
+ INCLUDE_LOCATIONS += $(BOOST_ROOT)
+ CXXFLAGS += -DWARPX_QED_TABLE_GEN
+ CFLAGS += -DWARPX_QED_TABLE_GEN
+ FFLAGS += -DWARPX_QED_TABLE_GEN
+ F90FLAGS += -DWARPX_QED_TABLE_GEN
+ endif
endif
+endif
include $(PICSAR_HOME)/src/Make.package
diff --git a/Source/Particles/MultiParticleContainer.H b/Source/Particles/MultiParticleContainer.H
index 58546a106..9f52dd0a5 100644
--- a/Source/Particles/MultiParticleContainer.H
+++ b/Source/Particles/MultiParticleContainer.H
@@ -3,6 +3,7 @@
#define WARPX_ParticleContainer_H_
#include <AMReX_Particles.H>
+#include <AMReX_ParallelDescriptor.H>
#include <WarpXParticleContainer.H>
#include <PhysicalParticleContainer.H>
#include <RigidInjectedParticleContainer.H>
@@ -18,6 +19,8 @@
#include <map>
#include <string>
#include <algorithm>
+#include <utility>
+#include <tuple>
//
// MultiParticleContainer holds multiple (nspecies or npsecies+1 when
@@ -222,6 +225,17 @@ protected:
//Initialize QED engines and provides smart pointers
//to species who need QED processes
void InitQED ();
+
+ bool someone_has_quantum_sync = false;
+ bool someone_has_breit_wheeler = false;
+
+ void InitQuantumSync ();
+ void InitBreitWheeler ();
+
+ std::tuple<bool, std::string, PicsarQuantumSynchrotronCtrl>
+ ParseQuantumSyncParams ();
+ std::tuple<bool, std::string, PicsarBreitWheelerCtrl>
+ ParseBreitWheelerParams ();
#endif
private:
diff --git a/Source/Particles/MultiParticleContainer.cpp b/Source/Particles/MultiParticleContainer.cpp
index c860d21f5..afeac1abd 100644
--- a/Source/Particles/MultiParticleContainer.cpp
+++ b/Source/Particles/MultiParticleContainer.cpp
@@ -5,7 +5,6 @@
#include <limits>
#include <algorithm>
#include <string>
-#include <memory>
using namespace amrex;
@@ -740,11 +739,69 @@ void MultiParticleContainer::InitQED ()
if(pc->has_quantum_sync()){
pc->set_quantum_sync_engine_ptr
(std::make_shared<QuantumSynchrotronEngine>(qs_engine));
+ someone_has_quantum_sync = true;
}
if(pc->has_breit_wheeler()){
pc->set_breit_wheeler_engine_ptr
(std::make_shared<BreitWheelerEngine>(bw_engine));
+ someone_has_breit_wheeler = true;
}
}
+
+ if(someone_has_quantum_sync)
+ InitQuantumSync();
+
+ if(someone_has_breit_wheeler)
+ InitBreitWheeler();
+
+}
+
+void MultiParticleContainer::InitQuantumSync ()
+{
+ bool is_custom;
+ PicsarQuantumSynchrotronCtrl ctrl;
+ std::string filename;
+ std::tie(is_custom, filename, ctrl) = ParseQuantumSyncParams();
+
+ // if(ParallelDescriptor::IOProcessor()){
+ // qs_engine.compute_lookup_tables_default();
+ // qs_engine.write_lookup_tables("qed_qs_lookup.bin");
+ // }
+ // amrex::ParallelDescriptor::Barrier();
+ // qs_engine.read_lookup_tables("qed_qs_lookup.bin");
+}
+
+void MultiParticleContainer::InitBreitWheeler ()
+{
+ bool is_custom;
+ PicsarBreitWheelerCtrl ctrl;
+ std::string filename;
+ std::tie(is_custom, filename, ctrl) = ParseBreitWheelerParams();
+
+ // if(ParallelDescriptor::IOProcessor()){
+ // bw_engine.compute_lookup_tables_default();
+ // bw_engine.write_lookup_tables("qed_bw_lookup.bin");
+ // }
+ // amrex::ParallelDescriptor::Barrier();
+ // bw_engine.read_lookup_tables("qed_bw_lookup.bin");
+
+}
+
+std::tuple<bool,std::string,PicsarQuantumSynchrotronCtrl>
+MultiParticleContainer::ParseQuantumSyncParams ()
+{
+ PicsarQuantumSynchrotronCtrl ctrl;
+ bool is_custom{false};
+
+ return std::make_tuple(is_custom, std::string(""), ctrl);
+}
+
+std::tuple<bool,std::string,PicsarBreitWheelerCtrl>
+MultiParticleContainer::ParseBreitWheelerParams ()
+{
+ PicsarBreitWheelerCtrl ctrl;
+ bool is_custom{false};
+
+ return std::make_tuple(is_custom, std::string(""), ctrl);
}
#endif
diff --git a/Source/Particles/PhysicalParticleContainer.H b/Source/Particles/PhysicalParticleContainer.H
index c953aa2d7..08493edcd 100644
--- a/Source/Particles/PhysicalParticleContainer.H
+++ b/Source/Particles/PhysicalParticleContainer.H
@@ -10,6 +10,7 @@
#ifdef WARPX_QED
#include <QuantumSyncEngineWrapper.H>
#include <BreitWheelerEngineWrapper.H>
+ #include <QedChiFunctions.H>
#endif
#include <map>
diff --git a/Source/QED/BreitWheelerEngineTableBuilder.H b/Source/QED/BreitWheelerEngineTableBuilder.H
new file mode 100644
index 000000000..0e3e45064
--- /dev/null
+++ b/Source/QED/BreitWheelerEngineTableBuilder.H
@@ -0,0 +1,11 @@
+#ifndef WARPX_breit_wheeler_engine_table_builder_h_
+#define WARPX_breit_wheeler_engine_table_builder_h_
+
+#include "QedWrapperCommons.H"
+
+class BreitWheelerEngineTableBuilder{
+ public:
+
+};
+
+#endif //WARPX_breit_wheeler_engine_table_builder_h_
diff --git a/Source/QED/BreitWheelerEngineTableBuilder.cpp b/Source/QED/BreitWheelerEngineTableBuilder.cpp
new file mode 100644
index 000000000..e85bfd523
--- /dev/null
+++ b/Source/QED/BreitWheelerEngineTableBuilder.cpp
@@ -0,0 +1,14 @@
+#include "BreitWheelerEngineTableBuilder.H"
+
+
+//Include the full BW engine with table generation support
+//(after some consistency tests)
+#ifdef PXRMP_CORE_ONLY
+ #error The Table Builder is incompatible with PXRMP_CORE_ONLY
+#endif
+
+#ifdef __PICSAR_MULTIPHYSICS_BREIT_WHEELER_ENGINE__
+ #warning breit_wheeler_engine.hpp should not have been included before reaching this point.
+#endif
+#include "breit_wheeler_engine.hpp"
+//_______________________________________________
diff --git a/Source/QED/BreitWheelerEngineWrapper.H b/Source/QED/BreitWheelerEngineWrapper.H
index 7cdc66b44..d42150154 100644
--- a/Source/QED/BreitWheelerEngineWrapper.H
+++ b/Source/QED/BreitWheelerEngineWrapper.H
@@ -3,12 +3,43 @@
#include "QedWrapperCommons.H"
+#include <AMReX_Array.H>
+#include <AMReX_Gpu.H>
+
+#include <string>
+#include <fstream>
+
//BW ENGINE from PICSAR
+//Include only essential parts of the library in this file
#define PXRMP_CORE_ONLY
-#include "breit_wheeler_engine.hpp"
+#include <breit_wheeler_engine.hpp>
+
+#ifdef WARPX_QED_TABLE_GEN
+ #include "BreitWheelerEngineTableBuilder.H"
+#endif
+
+using PicsarBreitWheelerEngine = picsar::multi_physics::
+ breit_wheeler_engine<amrex::Real, QedUtils::DummyStruct>;
-using WarpXBreitWheelerWrapper =
- picsar::multi_physics::breit_wheeler_engine<amrex::Real, DummyStruct>;
+using PicsarBreitWheelerCtrl =
+ picsar::multi_physics::breit_wheeler_engine_ctrl<amrex::Real>;
+
+// Struct to hold engine data ================
+
+struct BreitWheelerEngineInnards
+{
+ // Control parameters
+ PicsarBreitWheelerCtrl ctrl;
+
+ //Lookup table data
+ amrex::Gpu::ManagedVector<amrex::Real> TTfunc_coords;
+ amrex::Gpu::ManagedVector<amrex::Real> TTfunc_data;
+
+ amrex::Gpu::ManagedVector<amrex::Real> cum_distrib_coords_1;
+ amrex::Gpu::ManagedVector<amrex::Real> cum_distrib_coords_2;
+ amrex::Gpu::ManagedVector<amrex::Real> cum_distrib_data;
+ //______
+};
// Functors ==================================
@@ -29,12 +60,111 @@ public:
AMREX_FORCE_INLINE
amrex::Real operator() () const
{
- return WarpXBreitWheelerWrapper::
+ return PicsarBreitWheelerEngine::
internal_get_optical_depth(amrex::Random());
}
};
//____________________________________________
+// Evolution of the optical depth (returns true if
+// an event occurs)
+class BreitWheelerEvolveOpticalDepth
+{
+public:
+ BreitWheelerEvolveOpticalDepth(
+ BreitWheelerEngineInnards* t_innards):
+ p_innards{t_innards}{};
+
+ AMREX_GPU_DEVICE
+ AMREX_FORCE_INLINE
+ bool operator()(
+ amrex::Real px, amrex::Real py, amrex::Real pz,
+ amrex::Real ex, amrex::Real ey, amrex::Real ez,
+ amrex::Real bx, amrex::Real by, amrex::Real bz,
+ amrex::Real dt, amrex::Real& opt_depth) const
+ {
+ bool has_event_happend{false};
+ amrex::Real dummy_lambda{1.0};
+ amrex::Real unused_event_time{0.0};
+
+ const auto table = picsar::multi_physics::lookup_1d<amrex::Real>
+ (p_innards->TTfunc_data.size(),
+ p_innards->TTfunc_coords.data(),
+ p_innards->TTfunc_data.data());
+
+ PicsarBreitWheelerEngine::
+ internal_evolve_opt_depth_and_determine_event(
+ px, py, pz,
+ ex, ey, ez,
+ bx, by, bz,
+ dt, opt_depth,
+ has_event_happend, unused_event_time,
+ dummy_lambda,
+ table,
+ p_innards->ctrl);
+
+ return has_event_happend;
+ }
+
+private:
+ BreitWheelerEngineInnards* p_innards;
+};
+
+// Generates an electron-positron pair via the Breit-Wheeler process
+// (returns false if errors occur)
+class BreitWheelerGeneratePairs
+{
+public:
+ BreitWheelerGeneratePairs(
+ BreitWheelerEngineInnards* t_innards):
+ p_innards{t_innards}{};
+
+ template <size_t sampling>
+ AMREX_GPU_DEVICE
+ AMREX_FORCE_INLINE
+ bool operator()(
+ amrex::Real px, amrex::Real py, amrex::Real pz,
+ amrex::Real ex, amrex::Real ey, amrex::Real ez,
+ amrex::Real bx, amrex::Real by, amrex::Real bz,
+ amrex::Real weight,
+ amrex::Real* e_px, amrex::Real* e_py, amrex::Real* e_pz,
+ amrex::Real* p_px, amrex::Real* p_py, amrex::Real* p_pz,
+ amrex::Real* e_weight, amrex::Real* p_weight) const
+ {
+ amrex::Real dummy_lambda{1.0};
+ picsar::multi_physics::picsar_array<amrex::Real, sampling>
+ rand_zero_one_minus_epsi;
+ for(auto& el : rand_zero_one_minus_epsi)
+ el = amrex::Random();
+
+ const auto table = picsar::multi_physics::lookup_2d<amrex::Real>
+ (p_innards->cum_distrib_coords_1.size(),
+ p_innards->cum_distrib_coords_1.data(),
+ p_innards->cum_distrib_coords_2.size(),
+ p_innards->cum_distrib_coords_2.data(),
+ p_innards->cum_distrib_data.data());
+
+ bool stat = PicsarBreitWheelerEngine::
+ internal_generate_breit_wheeler_pairs(
+ px, py, pz,
+ ex, ey, ez,
+ bx, by, bz,
+ weight, sampling,
+ e_px, e_py, e_pz,
+ p_px, p_py, p_pz,
+ e_weight, p_weight,
+ dummy_lambda,
+ table,
+ p_innards->ctrl,
+ rand_zero_one_minus_epsi.data());
+
+ return stat;
+ }
+
+private:
+ BreitWheelerEngineInnards* p_innards;
+};
+
// Factory class =============================
/**
@@ -49,6 +179,44 @@ public:
* \brief Builds the functor to initialize the optical depth
*/
BreitWheelerGetOpticalDepth build_optical_depth_functor ();
+
+ /* \brief Builds the functor to evolve the optical depth */
+ BreitWheelerEvolveOpticalDepth build_evolve_functor ();
+
+ /* \brief Builds the functor to generate the pairs */
+ BreitWheelerGeneratePairs build_pair_functor ();
+
+ /* \brief Checks if lookup tables are properly initialized */
+ bool are_lookup_tables_initialized () const;
+
+ /* \brief Reads lookup tables from 'file' on disk */
+ bool init_lookup_tables_from_raw_data (const std::vector<char>& raw_data);
+
+ /* \brief Writes lookup tables on disk in 'file'
+ * return false if it fails. */
+ std::vector<char> export_lookup_tables_data () const;
+
+ /* \brief Computes the Lookup tables using the default settings
+ * provided by the PICSAR library */
+ void compute_lookup_tables_default ();
+
+ /* \brief Computes the Lookup tables using user-defined settings */
+ void compute_custom_lookup_tables (PicsarBreitWheelerCtrl ctrl);
+
+private:
+ bool lookup_tables_initialized = false;
+
+ BreitWheelerEngineInnards innards;
+
+#ifdef WARPX_QED_TABLE_GEN
+
+ BreitWheelerEngineTableBuilder table_builder;
+
+ //Private function which actually computes the lookup tables
+ void computes_lookup_tables (
+ PicsarBreitWheelerCtrl ctrl);
+
+#endif
};
//============================================
diff --git a/Source/QED/BreitWheelerEngineWrapper.cpp b/Source/QED/BreitWheelerEngineWrapper.cpp
index 33e6d48d7..327b76411 100644
--- a/Source/QED/BreitWheelerEngineWrapper.cpp
+++ b/Source/QED/BreitWheelerEngineWrapper.cpp
@@ -1,16 +1,209 @@
#include "BreitWheelerEngineWrapper.H"
+
+#include "QedTableParserHelperFunctions.H"
+
+#include <utility>
+
+using namespace std;
+using namespace QedUtils;
+using namespace amrex;
+
//This file provides a wrapper aroud the breit_wheeler engine
//provided by the PICSAR library
-using namespace picsar::multi_physics;
-
// Factory class =============================
BreitWheelerEngine::BreitWheelerEngine (){}
-BreitWheelerGetOpticalDepth BreitWheelerEngine::build_optical_depth_functor ()
+//Builds the functor to initialize the optical depth
+BreitWheelerGetOpticalDepth
+BreitWheelerEngine::build_optical_depth_functor ()
{
return BreitWheelerGetOpticalDepth();
}
+//Builds the functor to evolve the optical depth
+BreitWheelerEvolveOpticalDepth
+BreitWheelerEngine::build_evolve_functor ()
+{
+ AMREX_ALWAYS_ASSERT(lookup_tables_initialized);
+
+ return BreitWheelerEvolveOpticalDepth(&innards);
+}
+
+//Builds the functor to generate the pairs
+BreitWheelerGeneratePairs
+BreitWheelerEngine::build_pair_functor ()
+{
+ AMREX_ALWAYS_ASSERT(lookup_tables_initialized);
+
+ return BreitWheelerGeneratePairs(&innards);
+}
+
+bool BreitWheelerEngine::are_lookup_tables_initialized () const
+{
+ return lookup_tables_initialized;
+}
+
+/* \brief Reads lookup tables from 'file' on disk */
+bool
+BreitWheelerEngine::init_lookup_tables_from_raw_data (
+ const vector<char>& raw_data)
+{
+ const char* p_data = raw_data.data();
+ const char* const p_last = &raw_data.back();
+ bool is_ok;
+
+ //Header (control parameters)
+ tie(is_ok, innards.ctrl.chi_phot_min, p_data) =
+ parse_raw_data<decltype(innards.ctrl.chi_phot_min)>(
+ p_data, p_last);
+ if(!is_ok) return false;
+
+ tie(is_ok, innards.ctrl.chi_phot_tdndt_min, p_data) =
+ parse_raw_data<decltype(innards.ctrl.chi_phot_tdndt_min)>(
+ p_data, p_last);
+ if(!is_ok) return false;
+
+ tie(is_ok, innards.ctrl.chi_phot_tdndt_max, p_data) =
+ parse_raw_data<decltype(innards.ctrl.chi_phot_tdndt_max)>(
+ p_data, p_last);
+ if(!is_ok) return false;
+
+ tie(is_ok, innards.ctrl.chi_phot_tdndt_how_many, p_data) =
+ parse_raw_data<decltype(innards.ctrl.chi_phot_tdndt_how_many)>(
+ p_data, p_last);
+ if(!is_ok) return false;
+
+ tie(is_ok, innards.ctrl.chi_phot_tpair_min, p_data) =
+ parse_raw_data<decltype(innards.ctrl.chi_phot_tpair_min)>(
+ p_data, p_last);
+ if(!is_ok) return false;
+
+ tie(is_ok, innards.ctrl.chi_phot_tpair_max, p_data) =
+ parse_raw_data<decltype(innards.ctrl.chi_phot_tpair_max)>(
+ p_data, p_last);
+ if(!is_ok) return false;
+
+ tie(is_ok, innards.ctrl.chi_phot_tpair_how_many, p_data) =
+ parse_raw_data<decltype(innards.ctrl.chi_phot_tpair_how_many)>(
+ p_data, p_last);
+ if(!is_ok) return false;
+
+ tie(is_ok, innards.ctrl.chi_frac_tpair_how_many, p_data) =
+ parse_raw_data<decltype(innards.ctrl.chi_frac_tpair_how_many)>(
+ p_data, p_last);
+ if(!is_ok) return false;
+
+ //___________________________
+
+ //Data
+ vector<Real> tndt_coords(innards.ctrl.chi_phot_tdndt_how_many);
+ vector<Real> tndt_data(innards.ctrl.chi_phot_tdndt_how_many);
+ vector<Real> cum_tab_coords1(innards.ctrl.chi_phot_tpair_how_many);
+ vector<Real> cum_tab_coords2(innards.ctrl.chi_frac_tpair_how_many);
+ vector<Real> cum_tab_data(innards.ctrl.chi_phot_tpair_how_many*
+ innards.ctrl.chi_frac_tpair_how_many);
+
+ tie(is_ok, tndt_coords, p_data) =
+ parse_raw_data_vec<Real>(
+ p_data, tndt_coords.size(), p_last);
+ if(!is_ok) return false;
+ innards.TTfunc_coords.assign(tndt_coords.begin(), tndt_coords.end());
+
+ tie(is_ok, tndt_data, p_data) =
+ parse_raw_data_vec<Real>(
+ p_data, tndt_data.size(), p_last);
+ if(!is_ok) return false;
+ innards.TTfunc_data.assign(tndt_data.begin(), tndt_data.end());
+
+ tie(is_ok, cum_tab_coords1, p_data) =
+ parse_raw_data_vec<Real>(
+ p_data, cum_tab_coords1.size(), p_last);
+ if(!is_ok) return false;
+ innards.cum_distrib_coords_1.assign(
+ cum_tab_coords1.begin(), cum_tab_coords1.end());
+
+ tie(is_ok, cum_tab_coords2, p_data) =
+ parse_raw_data_vec<Real>(
+ p_data, cum_tab_coords2.size(), p_last);
+ if(!is_ok) return false;
+ innards.cum_distrib_coords_2.assign(
+ cum_tab_coords2.begin(), cum_tab_coords2.end());
+
+ tie(is_ok, cum_tab_data, p_data) =
+ parse_raw_data_vec<Real>(
+ p_data, cum_tab_data.size(), p_last);
+ if(!is_ok) return false;
+ innards.cum_distrib_data.assign(
+ cum_tab_data.begin(), cum_tab_data.end());
+
+ //___________________________
+ lookup_tables_initialized = true;
+
+ return true;
+}
+
+
+#ifdef WARPX_QED_TABLE_GEN
+//Initializes the Lookup tables using the default settings
+//provided by the library
+void BreitWheelerEngine::compute_lookup_tables_default ()
+{
+ //A control parameters structure
+ //with the default values provided by the library
+ WarpXBreitWheelerWrapperCtrl ctrl_default;
+
+ computes_lookup_tables(ctrl_default);
+
+ lookup_tables_initialized = true;
+}
+
+// Computes the Lookup tables using user-defined settings
+void BreitWheelerEngine::compute_custom_lookup_tables (
+ WarpXBreitWheelerWrapperCtrl ctrl)
+{
+ computes_lookup_tables(ctrl);
+
+ lookup_tables_initialized = true;
+}
+
+
+/* \brief Writes lookup tables on disk in 'file'
+ * return false if it fails. */
+std::vector<char> export_lookup_tables_data () const
+{
+ if(!lookup_tables_initialized)
+ return std::vector<char>;
+
+ //TODO
+ return std::vector<char>;
+}
+
+//Private function which actually computes the lookup tables
+void BreitWheelerEngine::computes_lookup_tables (
+ PicsarBreitWheelerCtrl ctrl)
+{
+ //Lambda is not actually used if S.I. units are enabled
+ PicsarBreitWheelerEngine bw_engine(
+ std::move(QedUtils::DummyStruct()), 1.0, ctrl);
+
+ bw_engine.compute_dN_dt_lookup_table();
+ bw_engine.compute_cumulative_pair_table();
+
+ auto bw_innards_picsar = bw_engine.export_innards();
+
+ //Copy data in a GPU-friendly data-structure
+ innards.ctrl = bw_innards_picsar.bw_ctrl;
+ innards.TTfunc_coords.assign(bw_innards_picsar.TTfunc_table_coords_ptr,
+ bw_innards_picsar.TTfunc_table_coords_ptr +
+ bw_innards_picsar.TTfunc_table_coords_how_many);
+ innards.TTfunc_data.assign(bw_innards_picsar.TTfunc_table_data_ptr,
+ bw_innards_picsar.TTfunc_table_data_ptr +
+ bw_innards_picsar.TTfunc_table_data_how_many);
+ //____
+}
+
+#endif
+
//============================================
diff --git a/Source/QED/Make.package b/Source/QED/Make.package
index d4bad3f18..23e50b9d1 100644
--- a/Source/QED/Make.package
+++ b/Source/QED/Make.package
@@ -1,8 +1,19 @@
CEXE_headers += QedWrapperCommons.H
+CEXE_headers += QedChiFunctions.H
+CEXE_headers += QedTableParserHelperFunctions.H
CEXE_headers += BreitWheelerEngineWrapper.H
CEXE_headers += QuantumSyncsEngineWrapper.H
CEXE_sources += BreitWheelerEngineWrapper.cpp
CEXE_sources += QuantumSyncEngineWrapper.cpp
+#Table generation is enabled only if QED_TABLE_GEN is
+#set to true
+ifeq ($(QED_TABLE_GEN),TRUE)
+ CEXE_headers += BreitWheelerEngineTableBuilder.H
+ CEXE_headers += QuantumSyncEngineTableBuilder.H
+ CEXE_sources += BreitWheelerEngineTableBuilder.cpp
+ CEXE_sources += QuantumSyncEngineTableBuilder.cpp
+endif
+
INCLUDE_LOCATIONS += $(WARPX_HOME)/Source/QED
VPATH_LOCATIONS += $(WARPX_HOME)/Source/QED
diff --git a/Source/QED/QedChiFunctions.H b/Source/QED/QedChiFunctions.H
new file mode 100644
index 000000000..b150aae6b
--- /dev/null
+++ b/Source/QED/QedChiFunctions.H
@@ -0,0 +1,38 @@
+#ifndef WARPX_amrex_qed_chi_functions_h_
+#define WARPX_amrex_qed_chi_functions_h_
+
+#include "QedWrapperCommons.H"
+
+#define PXRMP_CORE_ONLY
+#include <chi_functions.hpp>
+
+namespace QedUtils{
+ //Thin wrappers around functions used to calculate chi parameters
+
+ AMREX_GPU_DEVICE
+ AMREX_FORCE_INLINE
+ amrex::Real chi_photon(
+ amrex::Real px, amrex::Real py, amrex::Real pz,
+ amrex::Real ex, amrex::Real ey, amrex::Real ez,
+ amrex::Real bx, amrex::Real by, amrex::Real bz)
+ {
+ const amrex::Real dummy_lambda = 1.0;
+ return picsar::multi_physics::chi_photon(
+ px, py, pz, ex, ey, ez, bx, by, bz, dummy_lambda);
+ }
+
+ AMREX_GPU_DEVICE
+ AMREX_FORCE_INLINE
+ amrex::Real chi_lepton(
+ amrex::Real px, amrex::Real py, amrex::Real pz,
+ amrex::Real ex, amrex::Real ey, amrex::Real ez,
+ amrex::Real bx, amrex::Real by, amrex::Real bz)
+ {
+ const amrex::Real dummy_lambda = 1.0;
+ return picsar::multi_physics::chi_lepton(
+ px, py, pz, ex, ey, ez, bx, by, bz, dummy_lambda);
+ }
+ //_________
+};
+
+#endif //WARPX_amrex_qed_chi_functions_h_ \ No newline at end of file
diff --git a/Source/QED/QedTableParserHelperFunctions.H b/Source/QED/QedTableParserHelperFunctions.H
new file mode 100644
index 000000000..a4c73adc4
--- /dev/null
+++ b/Source/QED/QedTableParserHelperFunctions.H
@@ -0,0 +1,44 @@
+#ifndef WARPX_amrex_qed_table_parser_helper_functions_h_
+#define WARPX_amrex_qed_table_parser_helper_functions_h_
+
+//This file contains helper functions to parse a char* array
+//into a lookup table
+
+#include <vector>
+#include <tuple>
+
+namespace QedUtils{
+ template <class T>
+ std::tuple<bool, std::vector<T>, const char*>parse_raw_data_vec(
+ const char* p_data, size_t how_many, const char* const p_last)
+ {
+ std::vector<T> res;
+ if(p_data + sizeof(T)*how_many > p_last)
+ return std::make_tuple(false, res, nullptr);
+
+ auto r_data = reinterpret_cast<const T*>(p_data);
+
+ res.assign(r_data, r_data + how_many);
+
+ p_data += sizeof(T)*how_many;
+ return std::make_tuple(true, res, p_data);
+ }
+
+ template <class T>
+ std::tuple<bool, T, const char*> parse_raw_data(
+ const char* p_data, const char* const p_last)
+ {
+ T res;
+ if(p_data + sizeof(T) > p_last)
+ return std::make_tuple(false, res, nullptr);
+
+ auto r_data = reinterpret_cast<const T*>(p_data);
+
+ res = *r_data;
+
+ p_data += sizeof(T);
+ return std::make_tuple(true, res, p_data);
+ }
+};
+
+#endif //WARPX_amrex_qed_table_parser_helper_functions_h_
diff --git a/Source/QED/QedWrapperCommons.H b/Source/QED/QedWrapperCommons.H
index 821034c06..a972b8869 100644
--- a/Source/QED/QedWrapperCommons.H
+++ b/Source/QED/QedWrapperCommons.H
@@ -1,16 +1,42 @@
#ifndef WARPX_amrex_qed_wrapper_commons_h_
#define WARPX_amrex_qed_wrapper_commons_h_
-//Common definitions for the QED library wrappers
+//Common definitions for the QED library wrappers and table builders
#include <AMReX_AmrCore.H>
+#include <AMReX_GpuQualifiers.H>
//Sets the decorator for GPU
#define PXRMP_GPU AMREX_GPU_DEVICE
//Sets SI units in the library
#define PXRMP_WITH_SI_UNITS
-//An empty data type
-struct DummyStruct{};
+namespace QedUtils{
+ //An empty data type
+ struct DummyStruct{};
+};
+
+//Control structures used by the engines
+struct PicsarBreitWheelerCtrl
+{
+ _REAL chi_phot_min =
+ static_cast<_REAL>(__breit_wheeler_min_chi_phot);
+
+ _REAL chi_phot_tdndt_min =
+ static_cast<_REAL>(__breit_wheeler_min_tdndt_chi_phot);
+ _REAL chi_phot_tdndt_max =
+ static_cast<_REAL>(__breit_wheeler_max_tdndt_chi_phot);
+ size_t chi_phot_tdndt_how_many =
+ __breit_wheeler_how_many_tdndt_chi_phot;
+
+ _REAL chi_phot_tpair_min =
+ static_cast<_REAL>(__breit_wheeler_min_tpair_chi_phot);
+ _REAL chi_phot_tpair_max =
+ static_cast<_REAL>(__breit_wheeler_max_tpair_chi_phot);
+ size_t chi_phot_tpair_how_many =
+ __breit_wheeler_how_many_tpair_chi_phot;
+ size_t chi_frac_tpair_how_many =
+ __breit_wheeler_chi_frac_tpair_how_many;
+};
#endif //WARPX_amrex_qed_wrapper_commons_h_
diff --git a/Source/QED/QuantumSyncEngineTableBuilder.H b/Source/QED/QuantumSyncEngineTableBuilder.H
new file mode 100644
index 000000000..f555f9212
--- /dev/null
+++ b/Source/QED/QuantumSyncEngineTableBuilder.H
@@ -0,0 +1,6 @@
+#ifndef WARPX_quantum_sync_engine_table_builder_h_
+#define WARPX_quantum_sync_engine_table_builder_h_
+
+class QuantumSynchrotronEngineTableBuilder{};
+
+#endif //WARPX_quantum_sync_engine_table_builder_h_
diff --git a/Source/QED/QuantumSyncEngineTableBuilder.cpp b/Source/QED/QuantumSyncEngineTableBuilder.cpp
new file mode 100644
index 000000000..68dbe5a36
--- /dev/null
+++ b/Source/QED/QuantumSyncEngineTableBuilder.cpp
@@ -0,0 +1,13 @@
+#include "QuantumSyncEngineTableBuilder.H"
+
+//Include the full QS engine with table generation support
+//(after some consistency tests)
+#ifdef PXRMP_CORE_ONLY
+ #error The Table Builder is incompatible with PXRMP_CORE_ONLY
+#endif
+
+#ifdef __PICSAR_MULTIPHYSICS_BREIT_WHEELER_ENGINE__
+ #warning quantum_sync_engine.hpp should not have been included before reaching this point.
+#endif
+#include "quantum_sync_engine.hpp"
+//_______________________________________________
diff --git a/Source/QED/QuantumSyncEngineWrapper.H b/Source/QED/QuantumSyncEngineWrapper.H
index a285dc8b6..5c61894a6 100644
--- a/Source/QED/QuantumSyncEngineWrapper.H
+++ b/Source/QED/QuantumSyncEngineWrapper.H
@@ -3,12 +3,40 @@
#include "QedWrapperCommons.H"
+#include <AMReX_Array.H>
+#include <AMReX_Gpu.H>
+
+
+#include <string>
+#include <fstream>
+
//QS ENGINE from PICSAR
+//Include only essential parts of the library in this file
#define PXRMP_CORE_ONLY
-#include "quantum_sync_engine.hpp"
+#include <quantum_sync_engine.hpp>
+
+using PicsarQuantumSynchrotronEngine = picsar::multi_physics::
+ quantum_synchrotron_engine<amrex::Real, QedUtils::DummyStruct>;
+
+using PicsarQuantumSynchrotronCtrl =
+ picsar::multi_physics::quantum_synchrotron_engine_ctrl<amrex::Real>;
+
+// Struct to hold engine data ================
-using WarpXQuantumSynchrotronWrapper =
- picsar::multi_physics::quantum_synchrotron_engine<amrex::Real, DummyStruct>;
+struct QuantumSynchrotronEngineInnards
+{
+ // Control parameters
+ PicsarQuantumSynchrotronCtrl ctrl;
+
+ //Lookup table data
+ amrex::Gpu::ManagedDeviceVector<amrex::Real> KKfunc_coords;
+ amrex::Gpu::ManagedDeviceVector<amrex::Real> KKfunc_data;
+
+ amrex::Gpu::ManagedVector<amrex::Real> cum_distrib_coords_1;
+ amrex::Gpu::ManagedVector<amrex::Real> cum_distrib_coords_2;
+ amrex::Gpu::ManagedVector<amrex::Real> cum_distrib_data;
+ //______
+};
// Functors ==================================
@@ -29,12 +57,110 @@ public:
AMREX_FORCE_INLINE
amrex::Real operator() () const
{
- return WarpXQuantumSynchrotronWrapper::
+ return PicsarQuantumSynchrotronEngine::
internal_get_optical_depth(amrex::Random());
}
};
//____________________________________________
+// Evolution of the optical depth (returns true if
+// an event occurs)
+class QuantumSynchrotronEvolveOpticalDepth
+{
+public:
+ QuantumSynchrotronEvolveOpticalDepth(
+ QuantumSynchrotronEngineInnards* t_innards):
+ p_innards{t_innards}{};
+
+ AMREX_GPU_DEVICE
+ AMREX_FORCE_INLINE
+ bool operator()(
+ amrex::Real px, amrex::Real py, amrex::Real pz,
+ amrex::Real ex, amrex::Real ey, amrex::Real ez,
+ amrex::Real bx, amrex::Real by, amrex::Real bz,
+ amrex::Real dt, amrex::Real& opt_depth) const
+ {
+ bool has_event_happend{false};
+ amrex::Real dummy_lambda{1.0};
+ amrex::Real unused_event_time{0.0};
+
+ const auto table = picsar::multi_physics
+ ::lookup_1d<amrex::Real>(
+ p_innards->KKfunc_data.size(),
+ p_innards->KKfunc_coords.data(),
+ p_innards->KKfunc_data.data());
+
+ PicsarQuantumSynchrotronEngine::
+ internal_evolve_opt_depth_and_determine_event(
+ px, py, pz,
+ ex, ey, ez,
+ bx, by, bz,
+ dt, opt_depth,
+ has_event_happend, unused_event_time,
+ dummy_lambda,
+ table,
+ p_innards->ctrl);
+
+ return has_event_happend;
+ }
+
+private:
+ QuantumSynchrotronEngineInnards* p_innards;
+};
+
+// Generates a photon via the Quantum Synchrotron process
+// and updates momentum accordingly (returns false if errors occur)
+class QuantumSynchrotronGeneratePhotonAndUpdateMomentum
+{
+public:
+ QuantumSynchrotronGeneratePhotonAndUpdateMomentum(
+ QuantumSynchrotronEngineInnards* t_innards):
+ p_innards{t_innards}{};
+
+ template <size_t sampling>
+ AMREX_GPU_DEVICE
+ AMREX_FORCE_INLINE
+ bool operator()(
+ amrex::Real* px, amrex::Real* py, amrex::Real* pz,
+ amrex::Real ex, amrex::Real ey, amrex::Real ez,
+ amrex::Real bx, amrex::Real by, amrex::Real bz,
+ amrex::Real weight,
+ amrex::Real* g_px, amrex::Real* g_py, amrex::Real* g_pz,
+ amrex::Real* g_weight) const
+ {
+ amrex::Real dummy_lambda{1.0};
+ amrex::GpuArray<amrex::Real, sampling>
+ rand_zero_one_minus_epsi;
+ for(auto& el : rand_zero_one_minus_epsi)
+ el = amrex::Random();
+
+ const auto table = picsar::multi_physics::lookup_2d<amrex::Real>
+ (p_innards->cum_distrib_coords_1.size(),
+ p_innards->cum_distrib_coords_1.data(),
+ p_innards->cum_distrib_coords_2.size(),
+ p_innards->cum_distrib_coords_2.data(),
+ p_innards->cum_distrib_data.data());
+
+ bool stat = PicsarQuantumSynchrotronEngine::
+ internal_generate_photons_and_update_momentum(
+ *px, *py, *pz,
+ ex, ey, ez,
+ bx, by, bz,
+ weight, sampling,
+ *g_px, *g_py, *g_pz,
+ *g_weight,
+ dummy_lambda,
+ table,
+ p_innards->ctrl,
+ rand_zero_one_minus_epsi.data());
+
+ return stat;
+ }
+
+private:
+ QuantumSynchrotronEngineInnards* p_innards;
+};
+
// Factory class =============================
/**
@@ -49,6 +175,40 @@ public:
* \brief Builds the functor to initialize the optical depth
*/
QuantumSynchrotronGetOpticalDepth build_optical_depth_functor ();
+
+ /* \brief Builds the functor to evolve the optical depth */
+ QuantumSynchrotronEvolveOpticalDepth build_evolve_functor ();
+
+
+ /* \brief Checks if lookup tables are properly initialized */
+ bool are_lookup_tables_initialized () const;
+
+ /* \brief Reads lookup tables from 'file' on disk */
+ void read_lookup_tables (std::string file);
+
+private:
+ bool lookup_tables_initialized = false;
+
+ QuantumSynchrotronEngineInnards innards;
+
+#ifdef WARPX_QED_TABLE_GEN
+public:
+ /* \brief Computes the Lookup tables using the default settings
+ * provided by the PICSAR library */
+ void compute_lookup_tables_default ();
+
+ /* \brief Computes the Lookup tables using user-defined settings */
+ void compute_custom_lookup_tables (WarpXQuantumSynchrotronWrapperCtrl ctrl);
+ /* \brief Writes lookup tables on disk in 'file'
+ * return false if it fails. */
+ bool write_lookup_tables (std::string file) const;
+
+private:
+ //Private function which actually computes the lookup tables
+ void computes_lookup_tables (
+ WarpXQuantumSynchrotronWrapperCtrl ctrl);
+
+#endif
};
//============================================
diff --git a/Source/QED/QuantumSyncEngineWrapper.cpp b/Source/QED/QuantumSyncEngineWrapper.cpp
index b55149187..c362bded3 100644
--- a/Source/QED/QuantumSyncEngineWrapper.cpp
+++ b/Source/QED/QuantumSyncEngineWrapper.cpp
@@ -2,16 +2,161 @@
//This file provides a wrapper aroud the quantum_sync engine
//provided by the PICSAR library
-using namespace picsar::multi_physics;
-
// Factory class =============================
QuantumSynchrotronEngine::QuantumSynchrotronEngine (){}
+//Builds the functor to evolve the optical depth
QuantumSynchrotronGetOpticalDepth
QuantumSynchrotronEngine::build_optical_depth_functor ()
{
return QuantumSynchrotronGetOpticalDepth();
}
+//Builds the functor to evolve the optical depth
+QuantumSynchrotronEvolveOpticalDepth QuantumSynchrotronEngine::build_evolve_functor ()
+{
+ AMREX_ALWAYS_ASSERT(lookup_tables_initialized);
+
+ return QuantumSynchrotronEvolveOpticalDepth(&innards);
+}
+
+bool QuantumSynchrotronEngine::are_lookup_tables_initialized () const
+{
+ return lookup_tables_initialized;
+}
+
+/* \brief Reads lookup tables from 'file' on disk */
+void QuantumSynchrotronEngine::read_lookup_tables (std::string file)
+{
+ std::ifstream ifile(file, std::ios::in | std::ios::binary);
+
+ //Header (control parameters)
+ ifile.read(reinterpret_cast<char*>(&innards.ctrl.chi_part_min),
+ sizeof(innards.ctrl.chi_part_min));
+ ifile.read(reinterpret_cast<char*>(&innards.ctrl.chi_part_tdndt_min),
+ sizeof(innards.ctrl.chi_part_tdndt_min));
+ ifile.read(reinterpret_cast<char*>(&innards.ctrl.chi_part_tdndt_max),
+ sizeof(innards.ctrl.chi_part_tdndt_max));
+ ifile.read(reinterpret_cast<char*>(&innards.ctrl.chi_part_tdndt_how_many),
+ sizeof(innards.ctrl.chi_part_tdndt_how_many));
+ ifile.read(reinterpret_cast<char*>(&innards.ctrl.chi_part_tem_min),
+ sizeof(innards.ctrl.chi_part_tem_min));
+ ifile.read(reinterpret_cast<char*>(&innards.ctrl.chi_part_tem_max),
+ sizeof(innards.ctrl.chi_part_tem_max));
+ ifile.read(reinterpret_cast<char*>(&innards.ctrl.chi_part_tem_how_many),
+ sizeof(innards.ctrl.chi_part_tem_how_many));
+ ifile.read(reinterpret_cast<char*>(&innards.ctrl.prob_tem_how_many),
+ sizeof(innards.ctrl.prob_tem_how_many));
+ //_______
+
+ //Data
+ size_t size_buf = sizeof(amrex::Real)*innards.ctrl.chi_part_tdndt_how_many;
+ char* data_buf = new char(size_buf);
+ ifile.read(data_buf, size_buf);
+ innards.KKfunc_coords.assign((amrex::Real*)data_buf,
+ (amrex::Real*)data_buf + size_buf);
+ ifile.read(data_buf, size_buf);
+ innards.KKfunc_data.assign((amrex::Real*)data_buf,
+ (amrex::Real*)data_buf + size_buf);
+ delete[] data_buf;
+ //_______
+
+ ifile.close();
+
+ lookup_tables_initialized = true;
+}
+
+#ifdef WARPX_QED_TABLE_GEN
+
+//Initializes the Lookup tables using the default settings
+//provided by the library
+void QuantumSynchrotronEngine::compute_lookup_tables_default ()
+{
+ //A control parameters structure
+ //with the default values provided by the library
+ WarpXQuantumSynchrotronWrapperCtrl ctrl_default;
+
+ computes_lookup_tables(ctrl_default);
+
+ lookup_tables_initialized = true;
+}
+
+// Computes the Lookup tables using user-defined settings
+void QuantumSynchrotronEngine::compute_custom_lookup_tables (
+ WarpXQuantumSynchrotronWrapperCtrl ctrl)
+{
+ computes_lookup_tables(ctrl);
+
+ lookup_tables_initialized = true;
+}
+
+
+/* \brief Writes lookup tables on disk in 'file'
+ * return false if it fails. */
+bool QuantumSynchrotronEngine::write_lookup_tables (
+ std::string file) const
+{
+ if(!lookup_tables_initialized)
+ return false;
+
+ std::ofstream of(file, std::ios::out | std::ios::binary);
+
+ //Header (control parameters)
+ of.write(reinterpret_cast<const char*>(&innards.ctrl.chi_part_min),
+ sizeof(innards.ctrl.chi_part_min));
+ of.write(reinterpret_cast<const char*>(&innards.ctrl.chi_part_tdndt_min),
+ sizeof(innards.ctrl.chi_part_tdndt_min));
+ of.write(reinterpret_cast<const char*>(&innards.ctrl.chi_part_tdndt_max),
+ sizeof(innards.ctrl.chi_part_tdndt_max));
+ of.write(reinterpret_cast<const char*>(&innards.ctrl.chi_part_tdndt_how_many),
+ sizeof(innards.ctrl.chi_part_tdndt_how_many));
+ of.write(reinterpret_cast<const char*>(&innards.ctrl.chi_part_tem_min),
+ sizeof(innards.ctrl.chi_part_tem_max));
+ of.write(reinterpret_cast<const char*>(&innards.ctrl.chi_part_tem_max),
+ sizeof(innards.ctrl.chi_part_tem_max));
+ of.write(reinterpret_cast<const char*>(&innards.ctrl.chi_part_tem_how_many),
+ sizeof(innards.ctrl.chi_part_tem_how_many));
+ of.write(reinterpret_cast<const char*>(&innards.ctrl.prob_tem_how_many),
+ sizeof(innards.ctrl.prob_tem_how_many));
+ //_______
+
+ //Data
+ of.write(reinterpret_cast<const char*>(innards.KKfunc_coords.dataPtr()),
+ sizeof(amrex::Real)*innards.KKfunc_coords.size());
+ of.write(reinterpret_cast<const char*>(innards.KKfunc_data.dataPtr()),
+ sizeof(amrex::Real)*innards.KKfunc_data.size());
+ // TODO: add other table
+ //_______
+
+ of.close();
+
+ return true;
+}
+
+ //Private function which actually computes the lookup tables
+void QuantumSynchrotronEngine::computes_lookup_tables (
+ WarpXQuantumSynchrotronWrapperCtrl ctrl)
+{
+ //Lambda is not actually used if S.I. units are enabled
+ WarpXQuantumSynchrotronWrapper qs_engine(
+ std::move(QedUtils::DummyStruct()), 1.0, ctrl);
+
+ qs_engine.compute_dN_dt_lookup_table();
+ //qs_engine.compute_cumulative_pair_table();
+
+ auto qs_innards_picsar = qs_engine.export_innards();
+
+ //Copy data in a GPU-friendly data-structure
+ innards.ctrl = qs_innards_picsar.qs_ctrl;
+ innards.KKfunc_coords.assign(qs_innards_picsar.KKfunc_table_coords_ptr,
+ qs_innards_picsar.KKfunc_table_coords_ptr +
+ qs_innards_picsar.KKfunc_table_coords_how_many);
+ innards.KKfunc_data.assign(qs_innards_picsar.KKfunc_table_data_ptr,
+ qs_innards_picsar.KKfunc_table_data_ptr +
+ qs_innards_picsar.KKfunc_table_data_how_many);
+ //____
+}
+#endif
+
//============================================