diff --git a/detector_input.txt b/detector_input.txt new file mode 100644 index 0000000..775494d --- /dev/null +++ b/detector_input.txt @@ -0,0 +1,5 @@ +InputDataFile: /media/data/gwm17/mask_tests/10B3Hea_16800keV_5Lia_74B.root +OutputDataFile: /media/data/gwm17/mask_tests/10B3Hea_16800keV_5Lia_74B_Sabre.root +DeadChannelFile: etc/sabreDeadChannels_May2022.txt +NumberOfThreads: 5 +ArrayType: Sabre \ No newline at end of file diff --git a/kinematics_input.txt b/kinematics_input.txt new file mode 100644 index 0000000..fdbe62c --- /dev/null +++ b/kinematics_input.txt @@ -0,0 +1,45 @@ +----------Data Information---------- +OutputFile: /media/data/gwm17/mask_tests/10B3Hea_16800keV_5Lia_74B.root +NumberOfThreads: 6 +----------Reaction Information---------- +NumberOfSamples: 1000000 +begin_chain + begin_step + Type: Reaction + begin_nuclei + 5 10 + 2 3 + 2 4 + end_nuclei + BeamEnergyMean(MeV): 24.0 + BeamEnergySigma(MeV): 0.0 + ThetaType: Lab + ThetaMin(deg): 15.0 + ThetaMax(deg): 15.0 + PhiMin(deg): 0.0 + PhMax(deg): 0.0 + ResidualExcitationMean(MeV): 16.8 + ResidualExcitationSigma(MeV): 0.023 + end_step + begin_step + Type: Decay + begin_nuclei + 5 9 + 2 4 + end_nuclei + PhiMin(deg): 0.0 + PhMax(deg): 360.0 + ResidualExcitationMean(MeV): 0.0 + ResidualExcitationSigma(MeV): 0.0 + AngularDistributionFile: ./etc/isotropic_dist.txt + end_step +end_chain +----------Target Information---------- +NumberOfLayers: 1 +begin_layer + Thickness(ug/cm^2): 74 + begin_elements (Z, A, Stoich.) + element 5 10 1 + end_elements +end_layer +-------------------------------------- diff --git a/src/Detectors/AnasenArray.cpp b/src/Detectors/AnasenArray.cpp index 7e31045..56598db 100644 --- a/src/Detectors/AnasenArray.cpp +++ b/src/Detectors/AnasenArray.cpp @@ -230,7 +230,7 @@ double AnasenArray::RunConsistencyCheck() } -DetectorResult AnasenArray::IsRing1(Mask::Nucleus& nucleus) +DetectorResult AnasenArray::IsRing1(const Mask::Nucleus& nucleus) { DetectorResult observation; double thetaIncident; @@ -255,7 +255,7 @@ DetectorResult AnasenArray::IsRing1(Mask::Nucleus& nucleus) return observation; } -DetectorResult AnasenArray::IsRing2(Mask::Nucleus& nucleus) +DetectorResult AnasenArray::IsRing2(const Mask::Nucleus& nucleus) { DetectorResult observation; double thetaIncident; @@ -280,7 +280,7 @@ DetectorResult AnasenArray::IsRing2(Mask::Nucleus& nucleus) return observation; } -DetectorResult AnasenArray::IsQQQ(Mask::Nucleus& nucleus) +DetectorResult AnasenArray::IsQQQ(const Mask::Nucleus& nucleus) { DetectorResult observation; double thetaIncident; @@ -324,7 +324,7 @@ DetectorResult AnasenArray::IsQQQ(Mask::Nucleus& nucleus) return observation; } -DetectorResult AnasenArray::IsAnasen(Mask::Nucleus& nucleus) +DetectorResult AnasenArray::IsDetected(const Mask::Nucleus& nucleus) { DetectorResult result; if(nucleus.GetKE() <= s_energyThreshold) @@ -337,236 +337,4 @@ DetectorResult AnasenArray::IsAnasen(Mask::Nucleus& nucleus) if(!result.detectFlag) result = IsQQQ(nucleus); return result; -} - -void AnasenArray::CountCoincidences(const std::vector& data, std::vector& counts) -{ - if (data.size() == 3 && data[1].isDetected && data[2].isDetected) - { - counts[0]++; - } - else if (data.size() == 4 && data[2].isDetected && data[3].isDetected) - { - counts[0]++; - } - else if(data.size() == 6) - { - if(data[2].isDetected && data[4].isDetected) - { - counts[0]++; - } - if(data[2].isDetected && data[5].isDetected) - { - counts[1]++; - } - if(data[4].isDetected && data[5].isDetected) - { - counts[2]++; - } - if(data[2].isDetected && data[4].isDetected && data[5].isDetected) - { - counts[3]++; - } - } - else if(data.size() == 8) - { - if(data[2].isDetected && data[4].isDetected) - { - counts[0]++; - } - if(data[2].isDetected && data[6].isDetected) - { - counts[1]++; - } - if(data[2].isDetected && data[7].isDetected) - { - counts[2]++; - } - if(data[4].isDetected && data[6].isDetected) - { - counts[3]++; - } - if(data[4].isDetected && data[7].isDetected) - { - counts[4]++; - } - if(data[6].isDetected && data[7].isDetected) - { - counts[5]++; - } - if(data[2].isDetected && data[4].isDetected && data[6].isDetected) - { - counts[6]++; - } - if(data[2].isDetected && data[4].isDetected && data[7].isDetected) - { - counts[7]++; - } - if(data[2].isDetected && data[6].isDetected && data[7].isDetected) - { - counts[8]++; - } - if(data[4].isDetected && data[6].isDetected && data[7].isDetected) - { - counts[9]++; - } - if(data[2].isDetected && data[4].isDetected && data[6].isDetected && data[7].isDetected) - { - counts[10]++; - } - } -} - -void AnasenArray::CalculateEfficiency(const std::string& inputname, const std::string& outputname, const std::string& statsname) { - - if(!dmap.IsValid()) - { - std::cerr<<"Invalid Dead Channel Map at AnasenArray::CalculateEfficiency()! If you want to run with all possible"; - std::cerr<<"channels active, simply load an empty file."<Get("SimTree"); - std::vector* dataHandle = new std::vector(); - intree->SetBranchAddress("nuclei", &dataHandle); - - output->cd(); - TTree* outtree = new TTree("SimTree", "SimTree"); - outtree->Branch("nuclei", dataHandle); - - input->cd(); - - stats<<"Efficiency statistics for data from "<GetEntry(1); - std::vector counts; - std::vector coinc_counts; - counts.resize(dataHandle->size()); - switch(counts.size()) - { - case 3: coinc_counts.resize(1, 0); break; - case 4: coinc_counts.resize(1, 0); break; - case 6: coinc_counts.resize(4, 0); break; - case 8: coinc_counts.resize(11, 0); break; - default: - { - std::cerr<<"Bad reaction type at AnasenArray::CalculateEfficiency (given value: "<Close(); - output->Close(); - stats.close(); - return; - } - } - - uint64_t nentries = intree->GetEntries(); - uint64_t percent5 = nentries*0.05; - uint64_t count = 0; - uint64_t npercent = 0; - - Mask::Nucleus nucleus; - for(uint64_t i=0; iGetEntry(i); - if(++count == percent5) - {//Show progress every 5% - npercent++; - count = 0; - std::cout<<"\rPercent completed: "<size(); j++) - { - Mask::Nucleus& nucleus = (*dataHandle)[j]; - DetectorResult result = IsAnasen(nucleus); - if(result.detectFlag) - { - nucleus.isDetected = true; - nucleus.detectedKE = result.energy_deposited; - nucleus.detectedTheta = result.direction.Theta(); - nucleus.detectedPhi = result.direction.Phi(); - counts[j]++; - } - } - - CountCoincidences(*dataHandle, coinc_counts); - - outtree->Fill(); - } - input->Close(); - output->cd(); - outtree->Write(outtree->GetName(), TObject::kOverwrite); - output->Close(); - - delete dataHandle; - - stats<size() == 3) - { - stats<size() == 4) - { - stats<size() == 6) - { - stats<size() == 8) - { - stats<& data, std::vector& counts); + DetectorResult IsRing1(const Mask::Nucleus& nucleus); + DetectorResult IsRing2(const Mask::Nucleus& nucleus); + DetectorResult IsQQQ(const Mask::Nucleus& nucleus); std::vector m_Ring1; std::vector m_Ring2; diff --git a/src/Detectors/CMakeLists.txt b/src/Detectors/CMakeLists.txt index 12cb098..b556f58 100644 --- a/src/Detectors/CMakeLists.txt +++ b/src/Detectors/CMakeLists.txt @@ -18,6 +18,9 @@ target_sources(Detectors PUBLIC SabreArray.h SX3Detector.cpp SX3Detector.h + DetectorApp.h + DetectorApp.cpp + DetectorArray.cpp ) target_link_libraries(Detectors diff --git a/src/Detectors/DetectorApp.cpp b/src/Detectors/DetectorApp.cpp new file mode 100644 index 0000000..83e3f74 --- /dev/null +++ b/src/Detectors/DetectorApp.cpp @@ -0,0 +1,144 @@ +#include "DetectorApp.h" +#include +#include + +DetectorApp::DetectorApp() : + m_resources(nullptr) +{ +} + +DetectorApp::~DetectorApp() +{ + for(std::size_t i=0; i> junk >> m_inputFileName; + input >> junk >> m_outputFileName; + input >> junk >> m_deadChannelFileName; + + input >> junk >> m_nthreads; + input >> junk >> typeName; + + std::cout << "Creating " << m_nthreads << " detector arrays..." << std::endl; + ArrayType type = StringToArrayType(typeName); + for(uint64_t i=0; iSetDeadChannelMap(m_deadChannelFileName); + } + std::cout << "Done" << std::endl; + + std::cout << "Allocating " << m_nthreads << " threads..." << std::endl; + m_resources = std::make_unique>(m_nthreads); + std::cout << "Done" << std::endl; + + std::cout << "Opening input data file " << m_inputFileName << "..." << std::endl; + m_fileReader.Open(m_inputFileName, "SimTree"); + if(!m_fileReader.IsOpen() || !m_fileReader.IsTree()) + { + std::cerr << "Unable to open input data file " << m_inputFileName << std::endl; + return false; + } + m_nentries = m_fileReader.GetSize(); + std::cout << "Done. Detected " << m_nentries << " events in the file." << std::endl; + + //Little bit of integer division mangling to make sure we read every event in file + uint64_t quotient = m_nentries / m_nthreads; + uint64_t remainder = m_nentries % m_nthreads; + m_chunkSamples.push_back(quotient + remainder); + for(uint64_t i=1; iPushJob({[this](DetectorArray* array, uint64_t chunkSamples) + { + if(system == nullptr) + return; + + std::vector data; + DetectorResult result; + for(uint64_t i=0; iIsDetected(nucleus); + if(result.detectFlag) + { + nucleus.isDetected = true; + nucleus.detectedKE = result.energy_deposited; + nucleus.detectedTheta = result.direction.Theta(); + nucleus.detectedPhi = result.direction.Phi(); + } + } + m_fileWriter.PushData(data); + } + }, + {m_detectorList[i], m_chunkSamples[i]} //arguments to function, in order + } + ); + } + + uint64_t size = m_fileReader.GetSize(); + uint64_t count = 0; + double percent = 0.05; + uint64_t flushVal = size*percent; + uint64_t flushCount = 0; + + while(true) + { + if(count == flushVal) + { + count = 0; + ++flushCount; + std::cout<<"\rPercent of data written to disk: "<IsFinished() && m_fileWriter.GetQueueSize() == 0) + break; + else if(m_fileWriter.Write()) + ++count; + } + +} \ No newline at end of file diff --git a/src/Detectors/DetectorApp.h b/src/Detectors/DetectorApp.h new file mode 100644 index 0000000..e444dc2 --- /dev/null +++ b/src/Detectors/DetectorApp.h @@ -0,0 +1,40 @@ +#ifndef DETECTOR_APP_H +#define DETECTOR_APP_H + +#include "DetectorArray.h" +#include "Mask/FileWriter.h" +#include "Mask/FileReader.h" +#include "Mask/ThreadPool.h" + +#include +#include +#include + +class DetectorApp +{ +public: + DetectorApp(); + ~DetectorApp(); + + bool LoadConfig(const std::string& filename); + + void Run(); + +private: + + std::vector m_detectorList; //One array per thread + std::vector m_chunkSamples; + Mask::FileWriter m_fileWriter; + Mask::FileReader m_fileReader; + + std::string m_inputFileName; + std::string m_outputFileName; + std::string m_deadChannelFileName; + + uint64_t m_nthreads; + uint64_t m_nentries; + + std::unique_ptr> m_resources; +}; + +#endif \ No newline at end of file diff --git a/src/Detectors/DetectorArray.cpp b/src/Detectors/DetectorArray.cpp new file mode 100644 index 0000000..bd7ddab --- /dev/null +++ b/src/Detectors/DetectorArray.cpp @@ -0,0 +1,35 @@ +#include "DetectorArray.h" +#include "AnasenArray.h" +#include "SabreArray.h" + +DetectorArray* CreateDetectorArray(ArrayType type) +{ + switch(type) + { + case ArrayType::None: return nullptr; + case ArrayType::Anasen: return new AnasenArray(); + case ArrayType::Sabre: return new SabreArray(); + } + return nullptr; +} + +std::string ArrayTypeToString(ArrayType type) +{ + switch(type) + { + case ArrayType::None: return "None"; + case ArrayType::Anasen: return "Anasen"; + case ArrayType::Sabre: return "Sabre"; + } + return "None"; +} + +ArrayType StringToArrayType(const std::string& value) +{ + if (value == "Anasen") + return ArrayType::Anasen; + else if (value == "Sabre") + return ArrayType::Sabre; + else + return ArrayType::None; +} \ No newline at end of file diff --git a/src/Detectors/DetectorArray.h b/src/Detectors/DetectorArray.h index 5e7f37c..baf8b57 100644 --- a/src/Detectors/DetectorArray.h +++ b/src/Detectors/DetectorArray.h @@ -5,6 +5,7 @@ #include #include "Math/Point3D.h" +#include "Mask/Nucleus.h" struct DetectorResult { @@ -14,15 +15,23 @@ struct DetectorResult std::string det_name = ""; }; +enum class ArrayType +{ + None, + Anasen, + Sabre +}; + class DetectorArray { public: DetectorArray() {}; virtual ~DetectorArray() {}; - virtual void CalculateEfficiency(const std::string& inputname, const std::string& outputname, const std::string& statsname) = 0; + virtual DetectorResult IsDetected(const Mask::Nucleus& nucleus) = 0; virtual void DrawDetectorSystem(const std::string& filename) = 0; virtual double RunConsistencyCheck() = 0; + virtual void SetDeadChannelMap(const std::string& filename) = 0; protected: bool IsDoubleEqual(double x, double y) { return std::fabs(x-y) < s_epsilon ? true : false; }; @@ -30,4 +39,10 @@ protected: static constexpr double s_epsilon = 1.0e-6; }; +DetectorArray* CreateDetectorArray(ArrayType type); + +std::string ArrayTypeToString(ArrayType type); + +ArrayType StringToArrayType(const std::string& value); + #endif \ No newline at end of file diff --git a/src/Detectors/SabreArray.cpp b/src/Detectors/SabreArray.cpp index 01a41ae..49c9a01 100644 --- a/src/Detectors/SabreArray.cpp +++ b/src/Detectors/SabreArray.cpp @@ -31,161 +31,6 @@ SabreArray::SabreArray() : SabreArray::~SabreArray() {} -void SabreArray::CalculateEfficiency(const std::string& inputname, const std::string& outputname, const std::string& statsname) -{ - std::cout<<"----------SABRE Efficiency Calculation----------"<Get("SimTree"); - std::vector* dataHandle = new std::vector(); - intree->SetBranchAddress("nuclei", &dataHandle); - - output->cd(); - TTree* outtree = new TTree("SimTree", "SimTree"); - outtree->Branch("nuclei", dataHandle); - - input->cd(); - - stats<<"Efficiency statistics for data from "<GetEntry(1); - std::vector counts; - std::vector coinc_counts; - counts.resize(dataHandle->size()); - switch(counts.size()) - { - case 3: coinc_counts.resize(1, 0); break; - case 4: coinc_counts.resize(1, 0); break; - case 6: coinc_counts.resize(4, 0); break; - case 8: coinc_counts.resize(11, 0); break; - default: - { - std::cerr<<"Bad reaction type at AnasenEfficiency::CalculateEfficiency (given value: "<Close(); - output->Close(); - stats.close(); - return; - } - } - - uint64_t nentries = intree->GetEntries(); - uint64_t percent5 = nentries*0.05; - uint64_t count = 0; - uint64_t npercent = 0; - - Mask::Nucleus nucleus; - for(uint64_t i=0; iGetEntry(i); - if(++count == percent5) - {//Show progress every 5% - npercent++; - count = 0; - std::cout<<"\rPercent completed: "<size(); j++) - { - Mask::Nucleus& nucleus = (*dataHandle)[j]; - DetectorResult result = IsSabre(nucleus); - if(result.detectFlag) - { - nucleus.isDetected = true; - nucleus.detectedKE = result.energy_deposited; - nucleus.detectedTheta = result.direction.Theta(); - nucleus.detectedPhi = result.direction.Phi(); - counts[j]++; - } - } - - CountCoincidences(*dataHandle, coinc_counts); - - outtree->Fill(); - } - input->Close(); - output->cd(); - outtree->Write(outtree->GetName(), TObject::kOverwrite); - output->Close(); - - delete dataHandle; - - stats<& data, std::vector& counts) -{ - if (data.size() == 3 && data[1].isDetected && data[2].isDetected) - { - counts[0]++; - } - else if (data.size() == 4 && data[2].isDetected && data[3].isDetected) - { - counts[0]++; - } - else if(data.size() == 6) - { - if(data[2].isDetected && data[4].isDetected) - { - counts[0]++; - } - if(data[2].isDetected && data[5].isDetected) - { - counts[1]++; - } - if(data[4].isDetected && data[5].isDetected) - { - counts[2]++; - } - if(data[2].isDetected && data[4].isDetected && data[5].isDetected) - { - counts[3]++; - } - } - else if(data.size() == 8) - { - if(data[2].isDetected && data[4].isDetected) - { - counts[0]++; - } - if(data[2].isDetected && data[6].isDetected) - { - counts[1]++; - } - if(data[2].isDetected && data[7].isDetected) - { - counts[2]++; - } - if(data[4].isDetected && data[6].isDetected) - { - counts[3]++; - } - if(data[4].isDetected && data[7].isDetected) - { - counts[4]++; - } - if(data[6].isDetected && data[7].isDetected) - { - counts[5]++; - } - if(data[2].isDetected && data[4].isDetected && data[6].isDetected) - { - counts[6]++; - } - if(data[2].isDetected && data[4].isDetected && data[7].isDetected) - { - counts[7]++; - } - if(data[2].isDetected && data[6].isDetected && data[7].isDetected) - { - counts[8]++; - } - if(data[4].isDetected && data[6].isDetected && data[7].isDetected) - { - counts[9]++; - } - if(data[2].isDetected && data[4].isDetected && data[6].isDetected && data[7].isDetected) - { - counts[10]++; - } - } -} +} \ No newline at end of file diff --git a/src/Detectors/SabreArray.h b/src/Detectors/SabreArray.h index 2ae54bc..b32ca6c 100644 --- a/src/Detectors/SabreArray.h +++ b/src/Detectors/SabreArray.h @@ -3,7 +3,7 @@ #include "DetectorArray.h" #include "SabreDetector.h" -#include "Target.h" +#include "Mask/Target.h" #include "SabreDeadChannelMap.h" #include "Mask/Nucleus.h" @@ -12,14 +12,12 @@ class SabreArray : public DetectorArray public: SabreArray(); ~SabreArray(); - void SetDeadChannelMap(const std::string& filename) { m_deadMap.LoadMapfile(filename); }; - void CalculateEfficiency(const std::string& inputname, const std::string& outputname, const std::string& statsname) override; + virtual void SetDeadChannelMap(const std::string& filename) override { m_deadMap.LoadMapfile(filename); }; + virtual DetectorResult IsDetected(const Mask::Nucleus& nucleus) override; void DrawDetectorSystem(const std::string& filename) override; double RunConsistencyCheck() override; private: - DetectorResult IsSabre(Mask::Nucleus& nucleus); - void CountCoincidences(const std::vector& data, std::vector& counts); std::vector m_detectors; diff --git a/src/Detectors/main.cpp b/src/Detectors/main.cpp index 8cfb3b0..6c06e87 100644 --- a/src/Detectors/main.cpp +++ b/src/Detectors/main.cpp @@ -1,5 +1,4 @@ -#include "SabreArray.h" -#include "AnasenArray.h" +#include "DetectorApp.h" #include "KinematicsExceptions.h" #include #include @@ -7,7 +6,7 @@ int main(int argc, char** argv) { - if(argc != 4) + if(argc != 2) { std::cerr<<"Incorrect number of commandline arguments! Returning."<IsOpen()) + { + m_tree = (TTree*) m_file->Get(treename.c_str()); + if(m_tree == nullptr) + { + m_file->Close(); + delete m_file; + m_file = nullptr; + } + m_branchHandle = new std::vector(); + m_tree->SetBranchAddress("nuclei", &m_branchHandle); + m_size = m_tree->GetEntries(); + m_currentEntry = 0; //Reset file position + } + } + + void FileReader::Close() + { + if(m_file != nullptr && m_file->IsOpen()) + { + m_file->Close(); + delete m_file; + m_file = nullptr; + } + } + + bool FileReader::Read(std::vector& dataHandle) + { + std::scoped_lock guard(m_fileMutex); + int bytes = m_tree->GetEntry(m_currentEntry); + if(bytes != 0) + { + dataHandle = *m_branchHandle; + m_currentEntry++; + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/Mask/FileReader.h b/src/Mask/FileReader.h new file mode 100644 index 0000000..88051bb --- /dev/null +++ b/src/Mask/FileReader.h @@ -0,0 +1,46 @@ +#ifndef FILE_READER_H +#define FILE_READER_H + +#include "Nucleus.h" + +#include "TFile.h" +#include "TTree.h" + +#include +#include +#include +#include + +namespace Mask { + + class FileReader + { + public: + FileReader(); + FileReader(const std::string& filename, const std::string& treename); + ~FileReader(); + + void Open(const std::string& filename, const std::string& treename); //Not thread safe + void Close(); //Not thread safe + + /* + Read: fills entry to given dataHandle. Returns true if data was successfully filled, otherwise returns false + */ + bool Read(std::vector& dataHandle); //Thread safe + uint64_t GetSize() { return m_size; }//In entries (implicitly thread safe) + bool IsOpen() { return m_file == nullptr ? false : m_file->IsOpen(); } //Should be safe? + bool IsTree() { return m_tree != nullptr; } //Should be safe? + + private: + TFile* m_file; + TTree* m_tree; + + std::vector* m_branchHandle; + + std::mutex m_fileMutex; + std::atomic m_currentEntry; + std::atomic m_size; //in entries + }; +} + +#endif \ No newline at end of file diff --git a/src/Mask/FileWriter.h b/src/Mask/FileWriter.h index c424965..7ed188f 100644 --- a/src/Mask/FileWriter.h +++ b/src/Mask/FileWriter.h @@ -19,15 +19,15 @@ namespace Mask { FileWriter(const std::string& filename, const std::string& treename); ~FileWriter(); - bool IsOpen() const { return m_file->IsOpen(); } + bool IsOpen() const { return m_file == nullptr ? false : m_file->IsOpen(); } bool IsTree() const { return m_tree == nullptr ? false : true; } std::size_t GetQueueSize() const { return m_queueSize; } //Implicitly thread-safe void PushData(const std::vector& data); //Thread-safe - bool Write(); //Not thread safe! + bool Write(); //Not completely thread-safe, should only be used by main application loop (acess to queue is safe, but all else not) - void Open(const std::string& filename, const std::string& treename); + void Open(const std::string& filename, const std::string& treename); //Not thread safe! void Close(); //Not thread safe! private: diff --git a/src/Mask/MaskApp.cpp b/src/Mask/MaskApp.cpp index 32fdf31..7e76d14 100644 --- a/src/Mask/MaskApp.cpp +++ b/src/Mask/MaskApp.cpp @@ -39,9 +39,16 @@ namespace Mask { input>>junk>>m_nsamples; std::cout<<"Allocating resources... Asking for " << m_nthreads << " threads..."; - m_resources = std::make_unique(m_nthreads); + m_resources = std::make_unique>(m_nthreads); std::cout<<" Complete."<PushJob({std::bind(&MaskApp::RunChunk, std::ref(*this), std::placeholders::_1), system}); + for(std::size_t i=0; iPushJob({[this](ReactionSystem* system, uint64_t chunkSamples) + { + if(system == nullptr) + return; + + for(uint64_t i=0; iRunSystem(); + m_fileWriter.PushData(*(system->GetNuclei())); + } + }, + {m_systemList[i], m_chunkSamples[i]}}); + } uint64_t count = 0; double percent = 0.05; @@ -243,18 +265,4 @@ namespace Mask { std::cout<<"---------------------------------------------"<RunSystem(); - m_fileWriter.PushData(*(system->GetNuclei())); - } - } - } diff --git a/src/Mask/MaskApp.h b/src/Mask/MaskApp.h index 8b86cf5..d5457fd 100644 --- a/src/Mask/MaskApp.h +++ b/src/Mask/MaskApp.h @@ -36,8 +36,9 @@ namespace Mask { uint32_t m_nthreads; std::vector m_systemList; //One system for each thread + std::vector m_chunkSamples; FileWriter m_fileWriter; - std::unique_ptr m_resources; + std::unique_ptr> m_resources; }; diff --git a/src/Mask/ThreadPool.h b/src/Mask/ThreadPool.h index babfaa4..aa09978 100644 --- a/src/Mask/ThreadPool.h +++ b/src/Mask/ThreadPool.h @@ -20,16 +20,19 @@ namespace Mask { - using JobFunction = std::function; - struct Job - { - JobFunction func; - ReactionSystem* argument; - }; - + template class ThreadPool { public: + + using JobFunction = std::function; + struct Job + { + JobFunction func; + std::tuple argument; + }; + + ThreadPool(uint32_t nthreads) : m_isStopped(false), m_numberRunning(0), m_queueSize(0), m_initShutdown(false) { @@ -94,7 +97,7 @@ namespace Mask { m_numberRunning++; m_queueSize--; - job.func(job.argument); + std::apply(job.func, job.argument); m_numberRunning--; }