Commit 095cff8f authored by Paul Schütze's avatar Paul Schütze Committed by Simon Spannagel
Browse files

Separate Trapping and Detrapping models

(cherry picked from commit c6e661ff)
parent 2fa0a389
Loading
Loading
Loading
Loading
+129 −0
Original line number Diff line number Diff line
/**
 * @file
 * @brief Definition of charge carrier detrapping models
 *
 * @copyright Copyright (c) 2021 CERN and the Allpix Squared authors.
 * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
 * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
 * Intergovernmental Organization or submit itself to any jurisdiction.
 * SPDX-License-Identifier: MIT
 */

#ifndef ALLPIX_DETRAPPING_MODELS_H
#define ALLPIX_DETRAPPING_MODELS_H

#include <TFormula.h>

#include "exceptions.h"

#include "core/config/Configuration.hpp"
#include "core/utils/log.h"
#include "core/utils/unit.h"
#include "objects/SensorCharge.hpp"

namespace allpix {

    /**
     * @ingroup Models
     * @brief Charge carrier detrapping time models
     */
    class DetrappingModel {
    public:
        /**
         * Default constructor
         */
        DetrappingModel() = default;

        /**
         * Default virtual destructor
         */
        virtual ~DetrappingModel() = default;

        /**
         * Function call operator to obtain detrapping time for the given carrier
         * @param type Type of charge carrier (electron or hole)
         * @param probability Current detrapping probability for this charge carrier
         * @param efield_mag Magnitude of the electric field
         * @return Expected time of the charge carrier being detrapped
         */
        virtual double operator()(const CarrierType& type, double probability, double efield_mag) const = 0;
    };

    /**
     * @ingroup Models
     * @brief No detrapping
     */
    class NoDetrapping : virtual public DetrappingModel {
    public:
        double operator()(const CarrierType&, double, double) const override { return std::numeric_limits<double>::max(); };
    };

    /**
     * @ingroup Models
     * @brief Constant detrapping rate of charge carriers
     */
    class ConstantDetrapping : virtual public DetrappingModel {
    public:
        ConstantDetrapping(double electron_lifetime, double hole_lifetime)
            : tau_eff_electron_(electron_lifetime), tau_eff_hole_(hole_lifetime){};

        double operator()(const CarrierType& type, double probability, double) const override {
            return -1 * log(1 - probability) * (type == CarrierType::ELECTRON ? tau_eff_electron_ : tau_eff_hole_);
        }

    protected:
        double tau_eff_electron_{std::numeric_limits<double>::max()};
        double tau_eff_hole_{std::numeric_limits<double>::max()};
    };

    /**
     * @brief Wrapper class and factory for detrapping models.
     *
     * This class allows to store detrapping  objects independently of the model chosen and simplifies access to the
     * function call operator. The constructor acts as factory, generating model objects from the model name provided, e.g.
     * from a configuration file.
     */
    class Detrapping {
    public:
        /**
         * Default constructor
         */
        Detrapping() = default;

        /**
         * Detrapping model constructor
         * @param config Configuration of the calling module
         */
        explicit Detrapping(const Configuration& config) {
            try {
                auto model = config.get<std::string>("detrapping_model", "none");

                if(model == "constant") {
                    model_ = std::make_unique<ConstantDetrapping>(config.get<double>("detrapping_time_electron"),
                                                                  config.get<double>("detrapping_time_hole"));
                } else if(model == "none") {
                    LOG(INFO) << "No charge carrier detrapping model chosen, no detrapping simulated";
                    model_ = std::make_unique<NoDetrapping>();
                } else {
                    throw InvalidModelError(model);
                }
            } catch(const ModelError& e) {
                throw InvalidValueError(config, "detrapping_model", e.what());
            }
        }

        /**
         * Function call operator forwarded to the detrapping model
         * @return Detrapping time
         */
        template <class... ARGS> double operator()(ARGS&&... args) const {
            return model_->operator()(std::forward<ARGS>(args)...);
        }

    private:
        std::unique_ptr<DetrappingModel> model_{};
    };

} // namespace allpix

#endif
+13 −86
Original line number Diff line number Diff line
@@ -57,32 +57,6 @@ namespace allpix {
        double tau_eff_hole_{std::numeric_limits<double>::max()};
    };

    /**
     * @ingroup Models
     * @brief Charge carrier detrapping time models
     */
    class DetrappingModel {
    public:
        /**
         * Default constructor
         */
        DetrappingModel() = default;

        /**
         * Default virtual destructor
         */
        virtual ~DetrappingModel() = default;

        /**
         * Function call operator to obtain trapping time for the given carrier
         * @param type Type of charge carrier (electron or hole)
         * @param probability Current trapping probability for this charge carrier
         * @param efield_mag Magnitude of the electric field
         * @return Expected time of the charge carrier being trapped
         */
        virtual double operator()(const CarrierType& type, double probability, double, double efield_mag) const = 0;
    };

    /**
     * @ingroup Models
     * @brief No trapping
@@ -92,17 +66,6 @@ namespace allpix {
        bool operator()(const CarrierType&, double, double, double) const override { return false; };
    };

    /**
     * @ingroup Models
     * @brief No detrapping
     */
    class NoDetrapping : virtual public DetrappingModel {
    public:
        double operator()(const CarrierType&, double, double, double) const override {
            return std::numeric_limits<double>::max();
        };
    };

    /**
     * @ingroup Models
     * @brief Constant trapping rate of charge carriers
@@ -115,24 +78,6 @@ namespace allpix {
        }
    };

    /**
     * @ingroup Models
     * @brief Constant trapping rate of charge carriers
     */
    class ConstantDetrapping : virtual public DetrappingModel {
    public:
        ConstantDetrapping(double electron_lifetime, double hole_lifetime)
            : tau_eff_electron_(electron_lifetime), tau_eff_hole_(hole_lifetime){};

        double operator()(const CarrierType& type, double probability, double, double) const override {
            return -1 * log(1 - probability) * (type == CarrierType::ELECTRON ? tau_eff_electron_ : tau_eff_hole_);
        }

    protected:
        double tau_eff_electron_{std::numeric_limits<double>::max()};
        double tau_eff_hole_{std::numeric_limits<double>::max()};
    };

    /**
     * @ingroup Models
     * @brief Ljubljana / Kramberger effective trapping model for charge carriers in silicon
@@ -277,21 +222,21 @@ namespace allpix {
                }

                if(model == "ljubljana" || model == "kramberger") {
                    model_trap_ = std::make_unique<Ljubljana>(temperature, fluence);
                    model_ = std::make_unique<Ljubljana>(temperature, fluence);
                } else if(model == "dortmund" || model == "krasel") {
                    model_trap_ = std::make_unique<Dortmund>(fluence);
                    model_ = std::make_unique<Dortmund>(fluence);
                } else if(model == "cmstracker") {
                    model_trap_ = std::make_unique<CMSTracker>(fluence);
                    model_ = std::make_unique<CMSTracker>(fluence);
                } else if(model == "mandic") {
                    model_trap_ = std::make_unique<Mandic>(fluence);
                    model_ = std::make_unique<Mandic>(fluence);
                } else if(model == "constant") {
                    model_trap_ = std::make_unique<ConstantTrapping>(config.get<double>("trapping_time_electron"),
                    model_ = std::make_unique<ConstantTrapping>(config.get<double>("trapping_time_electron"),
                                                                config.get<double>("trapping_time_hole"));
                } else if(model == "none") {
                    LOG(INFO) << "No charge carrier trapping model chosen, no trapping simulated";
                    model_trap_ = std::make_unique<NoTrapping>();
                    model_ = std::make_unique<NoTrapping>();
                } else if(model == "custom") {
                    model_trap_ = std::make_unique<CustomTrapping>(config);
                    model_ = std::make_unique<CustomTrapping>(config);
                } else {
                    throw InvalidModelError(model);
                }
@@ -299,36 +244,18 @@ namespace allpix {
            } catch(const ModelError& e) {
                throw InvalidValueError(config, "trapping_model", e.what());
            }

            try {
                auto model = config.get<std::string>("detrapping_model", "none");

                if(model == "constant") {
                    model_detrap_ = std::make_unique<ConstantDetrapping>(config.get<double>("detrapping_time_electron"),
                                                                         config.get<double>("detrapping_time_hole"));
                } else if(model == "none") {
                    LOG(INFO) << "No charge carrier detrapping model chosen, no detrapping simulated";
                    model_detrap_ = std::make_unique<NoDetrapping>();
                } else {
                    throw InvalidModelError(model);
                }
            } catch(const ModelError& e) {
                throw InvalidValueError(config, "detrapping_model", e.what());
            }
        }

        /**
         * Function call operator forwarded to the trapping and detrapping model
         * @return Trapping state and detrapping time
         * Function call operator forwarded to the trapping model
         * @return Trapping state
         */
        template <class... ARGS> std::pair<bool, double> operator()(ARGS&&... args) const {
            return {model_trap_->operator()(std::forward<ARGS>(args)...),
                    model_detrap_->operator()(std::forward<ARGS>(args)...)};
        template <class... ARGS> bool operator()(ARGS&&... args) const {
            return model_->operator()(std::forward<ARGS>(args)...);
        }

    private:
        std::unique_ptr<TrappingModel> model_trap_{};
        std::unique_ptr<DetrappingModel> model_detrap_{};
        std::unique_ptr<TrappingModel> model_{};
    };

} // namespace allpix