Commit 13010606 authored by Paul Schütze's avatar Paul Schütze
Browse files

Merge branch 'custom_impact' into 'master'

Custom Impact Ionization Model

Closes #241

See merge request allpix-squared/allpix-squared!815
parents 9174aa6c ce0ada30
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -196,6 +196,42 @@ The parameter values implemented in Allpix Squared are taken from Table 1 of \[[

This model can be selected in the configuration file via the parameter `multiplication_model = "bologna"`.

## Custom Impact Ionization Models

Allpix Squared provides the possibility to use fully custom impact ionization models. In order to use a custom model, the
parameter `multiplication_model = "custom"` needs to be set in the configuration file. Additionally, the following
configuration keys have to be provided:

- `multiplication_function_electrons`:
  The formula describing the electron impact ionization gain.

- `multiplication_function_holes`:
  The formula describing the hole impact ionization gain.

The functions defined via these parameters can depend on the local electric field. In order to use the electric field
magnitude in the formula, an `x` has to be placed at the respective position.

Parameters of the functions can either be placed directly in the formulas in framework-internal units, or provided separately
as arrays via the `multiplication_parameters_electrons` and `multiplication_parameters_electrons`. Placeholders for
parameters in the formula are denoted with squared brackets and a parameter number, for example `[0]` for the first
parameter provided. Parameters specified separately from the formula can contain units which will be interpreted
automatically.

{{% alert title="Warning" color="warning" %}}
Parameters directly placed in the impact ionization formula have to be supplied in framework-internal units since the
function will be evaluated with both electric field strength and doping concentration in internal units. It is recommended
to use the possibility of separately configuring the parameters and to make use of units to avoid conversion mistakes.
{{% /alert %}}

{{% alert title="Warning" color="warning" %}}
It should be noted that the temperature passed via the module configuration is not evaluated for the custom impact ionization
model, but the model parameters need to be manually adjusted to the required temperature.
{{% /alert %}}

The interpretation of the custom impact ionization functions is based on the `ROOT::TFormula` class \[[@rootformula]\] and
supports all corresponding features, mathematical expressions and constants.


[@massey]: https://doi.org/10.1109/TED.2006.881010
[@overstraeten]: https://doi.org/10.1016/0038-1101(70)90139-5
[@okuto]: https://doi.org/10.1016/0038-1101(75)90099-4
+56 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
#include <limits>
#include <typeindex>

#include <TFormula.h>

#include "exceptions.h"

#include "core/config/Configuration.hpp"
@@ -222,6 +224,58 @@ namespace allpix {
        double hole_d_;
    };

    /**
     * @ingroup Models
     * @brief Custom mobility model for charge carriers
     */
    class CustomGain : public ImpactIonizationModel {
    public:
        CustomGain(const Configuration& config, double threshold) : ImpactIonizationModel(threshold) {
            electron_gain_ = configure_gain(config, CarrierType::ELECTRON);
            hole_gain_ = configure_gain(config, CarrierType::HOLE);
        };

        double gain_factor(const CarrierType& type, double efield_mag) const override {
            if(type == CarrierType::ELECTRON) {
                return electron_gain_->Eval(efield_mag);
            } else {
                return hole_gain_->Eval(efield_mag);
            }
        };

    private:
        std::unique_ptr<TFormula> electron_gain_;
        std::unique_ptr<TFormula> hole_gain_;

        std::unique_ptr<TFormula> configure_gain(const Configuration& config, const CarrierType type) {
            std::string name = (type == CarrierType::ELECTRON ? "electrons" : "holes");
            auto function = config.get<std::string>("multiplication_function_" + name);
            auto parameters = config.getArray<double>("multiplication_parameters_" + name, {});

            auto gain = std::make_unique<TFormula>(("multiplication_" + name).c_str(), function.c_str());

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

            // Check if number of parameters match up
            if(static_cast<size_t>(gain->GetNpar()) != parameters.size()) {
                throw InvalidValueError(config,
                                        "multiplication_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) {
                gain->SetParameter(static_cast<int>(n), parameters[n]);
            }

            return gain;
        };
    };

    /**
     * @brief Wrapper class and factory for impact ionization models.
     *
@@ -258,6 +312,8 @@ namespace allpix {
                } else if(model == "none") {
                    LOG(INFO) << "No impact ionization model chosen, charge multiplication not simulated";
                    model_ = std::make_unique<NoImpactIonization>();
                } else if(model == "custom") {
                    model_ = std::make_unique<CustomGain>(config, threshold);
                } else {
                    throw InvalidModelError(model);
                }