Commit 378d5f23 authored by Simon Spannagel's avatar Simon Spannagel
Browse files

Mobility: add possibility to define custom model

(cherry picked from commit bf2e28a98152002d6a70a1215af8dc28cd0450ec)
parent d54167b8
Loading
Loading
Loading
Loading
+60 −0
Original line number Diff line number Diff line
@@ -11,6 +11,8 @@
#ifndef ALLPIX_MOBILITY_MODELS_H
#define ALLPIX_MOBILITY_MODELS_H

#include <TF2.h>

#include "exceptions.h"

#include "core/utils/unit.h"
@@ -276,6 +278,62 @@ namespace allpix {
        double alpha_;
    };

    /**
     * @ingroup Models
     * @brief Custom mobility model for charge carriers
     */
    class Custom : public MobilityModel {
    public:
        Custom(const Configuration& config, bool doping) {
            electron_mobility_ = configure_mobility(config, CarrierType::ELECTRON, doping);
            hole_mobility_ = configure_mobility(config, CarrierType::HOLE, doping);
        };

        double operator()(const CarrierType& type, double efield_mag, double doping) const override {
            if(type == CarrierType::ELECTRON) {
                return electron_mobility_->Eval(efield_mag, doping);
            } else {
                return hole_mobility_->Eval(efield_mag, doping);
            }
        };

    private:
        std::unique_ptr<TF2> electron_mobility_;
        std::unique_ptr<TF2> hole_mobility_;

        std::unique_ptr<TF2> configure_mobility(const Configuration& config, const CarrierType type, bool doping) {
            std::string name = (type == CarrierType::ELECTRON ? "electrons" : "holes");
            auto function = config.get<std::string>("mobility_function_" + name);
            auto parameters = config.getArray<double>("mobility_parameters_" + name);

            auto mobility = std::make_unique<TF2>(("mobility_" + name).c_str(), function.c_str(), 0, 1, 0, 1);

            if(!mobility->IsValid()) {
                throw InvalidValueError(
                    config, "mobility_function_" + name, "The provided model is not a valid ROOT::TFormula expression");
            }

            // Check if number of parameters match up
            if(static_cast<size_t>(mobility->GetNumberFreeParameters()) != parameters.size()) {
                throw InvalidValueError(config,
                                        "mobility_parameters_" + name,
                                        "The number of provided parameters and parameters in the function do not match");
            }

            // Set the parameters
            for(size_t n = 0; n < parameters.size(); ++n) {
                mobility->SetParameter(static_cast<int>(n), parameters[n]);
            }

            // Check if a doping concentration dependency can be detected by comparing min and max of the function in Y:
            if(!doping && (mobility->GetYmin() != mobility->GetYmax())) {
                throw ModelUnsuitable("No doping profile available but doping dependence found");
            }

            return mobility;
        };
    };

    /**
     * @brief Wrapper class and factory for mobility models.
     *
@@ -314,6 +372,8 @@ namespace allpix {
                    model_ = std::make_unique<MasettiCanali>(temperature, doping);
                } else if(model == "arora") {
                    model_ = std::make_unique<Arora>(temperature, doping);
                } else if(model == "custom") {
                    model_ = std::make_unique<Custom>(config, doping);
                } else {
                    throw InvalidModelError(model);
                }