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

Separate Trapping and Detrapping models

parent 27e6c1b6
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