Program Listing for File amiciSimulationRunner.h

Return to documentation for file (include/parpeamici/amiciSimulationRunner.h)

#ifndef PARPE_AMICI_SIMULATIONRUNNER_H
#define PARPE_AMICI_SIMULATIONRUNNER_H

#include <parpecommon/parpeConfig.h>

#ifdef PARPE_ENABLE_MPI
#include <parpeloadbalancer/loadBalancerWorker.h>
#endif

#include <parpecommon/misc.h>

#include <amici/amici.h>
#include <amici/rdata.h>
#include <amici/serialization.h>

#include <functional>
#include <vector>
#include <mutex>
#include <condition_variable>

#include <boost/serialization/array.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/vector.hpp>

#include <gsl/gsl-lite.hpp>

namespace parpe {

class JobData;
#ifdef PARPE_ENABLE_MPI
class LoadBalancerMaster;
#else
// Workaround to allow building without MPI. Should be cleaned up.
using LoadBalancerMaster = int;
#endif

class AmiciSimulationRunner
{
  public:
    using messageHandlerFunc =
      std::function<void(std::vector<char>& buffer, int jobId)>;

    struct AmiciWorkPackageSimple
    {
        AmiciWorkPackageSimple() = default;
        std::vector<double> optimizationParameters;
        amici::SensitivityOrder sensitivityOrder;
        std::vector<int> conditionIndices;
        std::string logPrefix;
        // TODO bool sendY, ...
    };

    struct AmiciResultPackageSimple
    {
        AmiciResultPackageSimple() = default;
        double llh;
        double simulationTimeSeconds;
        std::vector<double> gradient;
        std::vector<double> modelOutput;
        std::vector<double> modelSigmas;
        std::vector<double> modelStates;
        int status;
    };

    using callbackJobFinishedType = std::function<void(JobData*, int)>;

    using callbackAllFinishedType = std::function<int(std::vector<JobData>&)>;

    AmiciSimulationRunner(const std::vector<double>& optimizationParameters,
                          amici::SensitivityOrder sensitivityOrder,
                          const std::vector<int>& conditionIndices,
                          callbackJobFinishedType callbackJobFinished = nullptr,
                          callbackAllFinishedType aggregate = nullptr,
                          std::string logPrefix = "");

    AmiciSimulationRunner(AmiciSimulationRunner const& other) = delete;

#ifdef PARPE_ENABLE_MPI
    int runDistributedMemory(LoadBalancerMaster* loadBalancer,
                             const int maxSimulationsPerPackage = 1);
#endif

    int runSharedMemory(const messageHandlerFunc& messageHandler,
                        bool sequential = false);

  private:
#ifdef PARPE_ENABLE_MPI
    void queueSimulation(LoadBalancerMaster* loadBalancer,
                         JobData* d,
                         int* jobDone,
                         std::condition_variable* jobDoneChangedCondition,
                         std::mutex* jobDoneChangedMutex,
                         int jobIdx,
                         const std::vector<double>& optimizationParameters,
                         amici::SensitivityOrder sensitivityOrder,
                         const std::vector<int>& conditionIndices) const;
#endif

    std::vector<double> const& optimization_parameters_;
    amici::SensitivityOrder sensitivity_order_;
    std::vector<int> const& condition_indices_;

    callbackJobFinishedType callback_job_finished_ = nullptr;
    callbackAllFinishedType aggregate_ = nullptr;
    int errors_ = 0;
    std::string log_prefix_;
};

void
swap(AmiciSimulationRunner::AmiciResultPackageSimple& first,
     AmiciSimulationRunner::AmiciResultPackageSimple& second) noexcept;

bool
operator==(AmiciSimulationRunner::AmiciResultPackageSimple const& lhs,
           AmiciSimulationRunner::AmiciResultPackageSimple const& rhs);

} // namespace parpe

namespace boost::serialization {

template<class Archive>
void
serialize(Archive& ar,
          parpe::AmiciSimulationRunner::AmiciWorkPackageSimple& u,
          const unsigned int /*version*/)
{
    ar& u.optimizationParameters;
    ar& u.sensitivityOrder;
    ar& u.conditionIndices;
    ar& u.logPrefix;
}

template<class Archive>
void
serialize(Archive& ar,
          parpe::AmiciSimulationRunner::AmiciResultPackageSimple& u,
          const unsigned int /*version*/)
{
    ar& u.llh;
    ar& u.simulationTimeSeconds;
    ar& u.gradient;
    ar& u.modelOutput;
    ar& u.modelSigmas;
    ar& u.modelStates;
    ar& u.status;
}

} // namespace boost::serialization

#endif // PARPE_AMICI_SIMULATIONRUNNER_H