<commit_before>/**
 * @file   amici.cpp
 * @brief  core routines for integration
 */

#include "amici/amici.h"

#include "amici/backwardproblem.h"
#include "amici/forwardproblem.h"
#include "amici/misc.h"

#include <sundials/sundials_types.h> //realtype
#include <cvodes/cvodes.h> //return codes

#include <type_traits>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <cstdarg>
#include <memory>

// ensure definitions are in sync
static_assert(AMICI_SUCCESS == CV_SUCCESS, "AMICI_SUCCESS != CV_SUCCESS");
static_assert(AMICI_DATA_RETURN == CV_TSTOP_RETURN,
              "AMICI_DATA_RETURN != CV_TSTOP_RETURN");
static_assert(AMICI_ROOT_RETURN == CV_ROOT_RETURN,
              "AMICI_ROOT_RETURN != CV_ROOT_RETURN");
static_assert(AMICI_ILL_INPUT == CV_ILL_INPUT,
              "AMICI_ILL_INPUT != CV_ILL_INPUT");
static_assert(AMICI_NORMAL == CV_NORMAL, "AMICI_NORMAL != CV_NORMAL");
static_assert(AMICI_ONE_STEP == CV_ONE_STEP, "AMICI_ONE_STEP != CV_ONE_STEP");
static_assert(std::is_same<amici::realtype, realtype>::value, "Definition of realtype does not match");

namespace amici {

/** errMsgIdAndTxt is a function pointer for printErrMsgIdAndTxt  */
msgIdAndTxtFp errMsgIdAndTxt = &printErrMsgIdAndTxt;
/** warnMsgIdAndTxt is a function pointer for printWarnMsgIdAndTxt  */
msgIdAndTxtFp warnMsgIdAndTxt = &printWarnMsgIdAndTxt;
    

std::unique_ptr<ReturnData> runAmiciSimulation(Solver &solver, const ExpData *edata, Model &model) {
    
    std::unique_ptr<ReturnData> rdata;
    
    auto originalFixedParameters = model.getFixedParameters(); // to restore after simulation
    auto originalTimepoints = model.getTimepoints();
    if(edata) {
        if(!edata->fixedParameters.empty()) {
            // fixed parameter in model are superseded by those provided in edata
            if(edata->fixedParameters.size() != (unsigned) model.nk())
                throw AmiException("Number of fixed parameters (%d) in model does not match ExpData (%zd).",
                                   model.nk(), edata->fixedParameters.size());
            model.setFixedParameters(edata->fixedParameters);
        }
        if(edata->nt()) {
            // fixed parameter in model are superseded by those provided in edata
            model.setTimepoints(edata->getTimepoints());
        }
    }
    
    try{
        rdata = std::unique_ptr<ReturnData>(new ReturnData(solver,&model));
        if (model.nx_solver <= 0) {
            model.setFixedParameters(originalFixedParameters);
            model.setTimepoints(originalTimepoints);
            return rdata;
        }
        
        auto fwd = std::unique_ptr<ForwardProblem>(new ForwardProblem(rdata.get(),edata,&model,&solver));
        fwd->workForwardProblem();

        auto bwd = std::unique_ptr<BackwardProblem>(new BackwardProblem(fwd.get()));
        bwd->workBackwardProblem();
    
        rdata->status = AMICI_SUCCESS;
    } catch (amici::IntegrationFailure const& ex) {
        rdata->invalidate(ex.time);
        rdata->status = ex.error_code;
        amici::warnMsgIdAndTxt("AMICI:mex:simulation","AMICI forward simulation failed at t = %f:\n%s\n",ex.time,ex.what());
    } catch (amici::IntegrationFailureB const& ex) {
        rdata->invalidateLLH();
        rdata->status = ex.error_code;
        amici::warnMsgIdAndTxt("AMICI:mex:simulation","AMICI backward simulation failed at t = %f:\n%s\n",ex.time,ex.what());
    } catch (amici::AmiException const& ex) {
        rdata->invalidate(model.t0());
        rdata->status = AMICI_ERROR;
        amici::warnMsgIdAndTxt("AMICI:mex:simulation","AMICI simulation failed:\n%s\nError occured in:\n%s",ex.what(),ex.getBacktrace());
    } catch (std::exception const& ex) {
        model.setFixedParameters(originalFixedParameters);
        model.setTimepoints(originalTimepoints);
        throw;
    } catch (...) {
        model.setFixedParameters(originalFixedParameters);
        model.setTimepoints(originalTimepoints);
        throw std::runtime_error("Unknown internal error occured!");
    }
    model.setFixedParameters(originalFixedParameters);
    model.setTimepoints(originalTimepoints);
    rdata->applyChainRuleFactorToSimulationResults(&model);
    return rdata;
}

/*!
 * printErrMsgIdAndTxt prints a specified error message associated to the
 * specified identifier
 *
 * @param[in] identifier error identifier @type char
 * @param[in] format string with error message printf-style format
 * @param ... arguments to be formatted
 * @return void
 */
void printErrMsgIdAndTxt(const char *identifier, const char *format, ...) {
    if(identifier && *identifier != '\0')
        fprintf(stderr, "[Error] %s: ", identifier);
    else
        fprintf(stderr, "[Error] ");
    va_list argptr;
    va_start(argptr,format);
    vfprintf(stderr, format, argptr);
    va_end(argptr);
    fprintf(stderr, "\n");
}

/*!
 * printErrMsgIdAndTxt prints a specified warning message associated to the
 * specified identifier
 *
 * @param[in] identifier warning identifier @type char
 * @param[in] format string with error message printf-style format
 * @param ... arguments to be formatted
 * @return void
 */
void printWarnMsgIdAndTxt(const char *identifier, const char *format, ...) {
    if(identifier && *identifier != '\0')
        printf("[Warning] %s: ", identifier);
    else
        printf("[Warning] ");
    va_list argptr;
    va_start(argptr,format);
    vprintf(format, argptr);
    va_end(argptr);
    printf("\n");
}

std::vector<std::unique_ptr<ReturnData> > runAmiciSimulations(const Solver &solver,
                                                              const std::vector<ExpData*> &edatas,
                                                              const Model &model, int num_threads)
{
    std::vector<std::unique_ptr<ReturnData> > results(edatas.size());

    #pragma omp parallel for num_threads(num_threads)
    for(int i = 0; i < (int)edatas.size(); ++i) {
        auto mySolver = std::unique_ptr<Solver>(solver.clone());
        auto myModel = std::unique_ptr<Model>(model.clone());

        results[i] = runAmiciSimulation(*mySolver, edatas[i], *myModel);
    }

    return results;
}

} // namespace amici<commit_msg>Fix ignoring #pragma omp parallel<commit_after>/**
 * @file   amici.cpp
 * @brief  core routines for integration
 */

#include "amici/amici.h"

#include "amici/backwardproblem.h"
#include "amici/forwardproblem.h"
#include "amici/misc.h"

#include <sundials/sundials_types.h> //realtype
#include <cvodes/cvodes.h> //return codes

#include <type_traits>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <cstdarg>
#include <memory>

// ensure definitions are in sync
static_assert(AMICI_SUCCESS == CV_SUCCESS, "AMICI_SUCCESS != CV_SUCCESS");
static_assert(AMICI_DATA_RETURN == CV_TSTOP_RETURN,
              "AMICI_DATA_RETURN != CV_TSTOP_RETURN");
static_assert(AMICI_ROOT_RETURN == CV_ROOT_RETURN,
              "AMICI_ROOT_RETURN != CV_ROOT_RETURN");
static_assert(AMICI_ILL_INPUT == CV_ILL_INPUT,
              "AMICI_ILL_INPUT != CV_ILL_INPUT");
static_assert(AMICI_NORMAL == CV_NORMAL, "AMICI_NORMAL != CV_NORMAL");
static_assert(AMICI_ONE_STEP == CV_ONE_STEP, "AMICI_ONE_STEP != CV_ONE_STEP");
static_assert(std::is_same<amici::realtype, realtype>::value, "Definition of realtype does not match");

namespace amici {

/** errMsgIdAndTxt is a function pointer for printErrMsgIdAndTxt  */
msgIdAndTxtFp errMsgIdAndTxt = &printErrMsgIdAndTxt;
/** warnMsgIdAndTxt is a function pointer for printWarnMsgIdAndTxt  */
msgIdAndTxtFp warnMsgIdAndTxt = &printWarnMsgIdAndTxt;
    

std::unique_ptr<ReturnData> runAmiciSimulation(Solver &solver, const ExpData *edata, Model &model) {
    
    std::unique_ptr<ReturnData> rdata;
    
    auto originalFixedParameters = model.getFixedParameters(); // to restore after simulation
    auto originalTimepoints = model.getTimepoints();
    if(edata) {
        if(!edata->fixedParameters.empty()) {
            // fixed parameter in model are superseded by those provided in edata
            if(edata->fixedParameters.size() != (unsigned) model.nk())
                throw AmiException("Number of fixed parameters (%d) in model does not match ExpData (%zd).",
                                   model.nk(), edata->fixedParameters.size());
            model.setFixedParameters(edata->fixedParameters);
        }
        if(edata->nt()) {
            // fixed parameter in model are superseded by those provided in edata
            model.setTimepoints(edata->getTimepoints());
        }
    }
    
    try{
        rdata = std::unique_ptr<ReturnData>(new ReturnData(solver,&model));
        if (model.nx_solver <= 0) {
            model.setFixedParameters(originalFixedParameters);
            model.setTimepoints(originalTimepoints);
            return rdata;
        }
        
        auto fwd = std::unique_ptr<ForwardProblem>(new ForwardProblem(rdata.get(),edata,&model,&solver));
        fwd->workForwardProblem();

        auto bwd = std::unique_ptr<BackwardProblem>(new BackwardProblem(fwd.get()));
        bwd->workBackwardProblem();
    
        rdata->status = AMICI_SUCCESS;
    } catch (amici::IntegrationFailure const& ex) {
        rdata->invalidate(ex.time);
        rdata->status = ex.error_code;
        amici::warnMsgIdAndTxt("AMICI:mex:simulation","AMICI forward simulation failed at t = %f:\n%s\n",ex.time,ex.what());
    } catch (amici::IntegrationFailureB const& ex) {
        rdata->invalidateLLH();
        rdata->status = ex.error_code;
        amici::warnMsgIdAndTxt("AMICI:mex:simulation","AMICI backward simulation failed at t = %f:\n%s\n",ex.time,ex.what());
    } catch (amici::AmiException const& ex) {
        rdata->invalidate(model.t0());
        rdata->status = AMICI_ERROR;
        amici::warnMsgIdAndTxt("AMICI:mex:simulation","AMICI simulation failed:\n%s\nError occured in:\n%s",ex.what(),ex.getBacktrace());
    } catch (std::exception const& ex) {
        model.setFixedParameters(originalFixedParameters);
        model.setTimepoints(originalTimepoints);
        throw;
    } catch (...) {
        model.setFixedParameters(originalFixedParameters);
        model.setTimepoints(originalTimepoints);
        throw std::runtime_error("Unknown internal error occured!");
    }
    model.setFixedParameters(originalFixedParameters);
    model.setTimepoints(originalTimepoints);
    rdata->applyChainRuleFactorToSimulationResults(&model);
    return rdata;
}

/*!
 * printErrMsgIdAndTxt prints a specified error message associated to the
 * specified identifier
 *
 * @param[in] identifier error identifier @type char
 * @param[in] format string with error message printf-style format
 * @param ... arguments to be formatted
 * @return void
 */
void printErrMsgIdAndTxt(const char *identifier, const char *format, ...) {
    if(identifier && *identifier != '\0')
        fprintf(stderr, "[Error] %s: ", identifier);
    else
        fprintf(stderr, "[Error] ");
    va_list argptr;
    va_start(argptr,format);
    vfprintf(stderr, format, argptr);
    va_end(argptr);
    fprintf(stderr, "\n");
}

/*!
 * printErrMsgIdAndTxt prints a specified warning message associated to the
 * specified identifier
 *
 * @param[in] identifier warning identifier @type char
 * @param[in] format string with error message printf-style format
 * @param ... arguments to be formatted
 * @return void
 */
void printWarnMsgIdAndTxt(const char *identifier, const char *format, ...) {
    if(identifier && *identifier != '\0')
        printf("[Warning] %s: ", identifier);
    else
        printf("[Warning] ");
    va_list argptr;
    va_start(argptr,format);
    vprintf(format, argptr);
    va_end(argptr);
    printf("\n");
}

std::vector<std::unique_ptr<ReturnData> > runAmiciSimulations(const Solver &solver,
                                                              const std::vector<ExpData*> &edatas,
                                                              const Model &model,
#if defined(_OPENMP)
                                                              int num_threads
#else
                                                              int /* num_threads */
#endif
)
{
    std::vector<std::unique_ptr<ReturnData> > results(edatas.size());

#if defined(_OPENMP)
    #pragma omp parallel for num_threads(num_threads)
#endif
    for(int i = 0; i < (int)edatas.size(); ++i) {
        auto mySolver = std::unique_ptr<Solver>(solver.clone());
        auto myModel = std::unique_ptr<Model>(model.clone());

        results[i] = runAmiciSimulation(*mySolver, edatas[i], *myModel);
    }

    return results;
}

} // namespace amici
{'fraction_non_alphanumeric': 0.1251288557608437, 'fraction_numerical': 0.0007929585282689715, 'mean_word_length': 3.2421796165489405, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6666504', 'n_tokens_mistral': 3863, 'n_tokens_neox': 3827, 'n_words': 798}