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

Merge branch 'status_bit' into 'master'

PropagatedCharge: Introduce CarrierState

See merge request allpix-squared/allpix-squared!591
parents c967f13d bee3b27b
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -44,6 +44,16 @@ The object should store the final \underline{local} position of the propagated c
This is either on the pixel implant (if the set of charge carriers are ready to be collected) or on any other position in the sensor if the set of charge carriers got trapped or was lost in another process.
Timing information giving the total time to arrive at the final location, from the start of the event, can also be stored.

The state of the charge carrier at the end of the propagation can be retrieved via the \parameter{getState()} method. The following values are available:

\begin{description}
\item[\parameter{CarrierState::UNKNOWN}] The final state of the charge carrier is unknown, it might not have been provided by the propagation algorithm, for example.
\item[\parameter{CarrierState::MOTION}] The charge carrier was still in motion when the propagation routine finished, for example when the configured integration time was reached.
\item[\parameter{CarrierState::RECOMBINED}] The charge carrier has recombined with the silicon lattice at the given position.
\item[\parameter{CarrierState::TRAPPED}] The charge carrier has been trapped by a lattice defect at the given position.
\item[\parameter{CarrierState::HALTED}] The motion of the charge carrier has stopped, for example because it has reached an implant or the sensor surface.
\end{description}

\nlparagraph{PixelCharge}
The set of charge carriers collected at a single pixel.
The pixel indices are stored in both the $x$ and $y$ direction, starting from zero for the first pixel.
+21 −14
Original line number Diff line number Diff line
@@ -623,10 +623,10 @@ void GenericPropagationModule::run(Event* event) {
            }

            // Propagate a single charge deposit
            auto [final_position, time, alive] = propagate(
            auto [final_position, time, state] = propagate(
                initial_position, deposit.getType(), deposit.getLocalTime(), event->getRandomEngine(), output_plot_points);

            if(!alive) {
            if(state == CarrierState::RECOMBINED) {
                LOG(DEBUG) << " Recombined " << charge_per_step << " at " << Units::display(final_position, {"mm", "um"})
                           << " in " << Units::display(time, "ns") << " time, removing";
                recombined_charges_count += charge_per_step;
@@ -644,6 +644,7 @@ void GenericPropagationModule::run(Event* event) {
                                               charge_per_step,
                                               deposit.getLocalTime() + time,
                                               deposit.getGlobalTime() + time,
                                               state,
                                               &deposit);

            propagated_charges.push_back(std::move(propagated_charge));
@@ -690,7 +691,7 @@ void GenericPropagationModule::run(Event* event) {
 * velocity at every point with help of the electric field map of the detector. An Runge-Kutta integration is applied in
 * multiple steps, adding a random diffusion to the propagating charge every step.
 */
std::tuple<ROOT::Math::XYZPoint, double, bool>
std::tuple<ROOT::Math::XYZPoint, double, CarrierState>
GenericPropagationModule::propagate(const ROOT::Math::XYZPoint& pos,
                                    const CarrierType& type,
                                    const double initial_time,
@@ -758,9 +759,8 @@ GenericPropagationModule::propagate(const ROOT::Math::XYZPoint& pos,
    Eigen::Vector3d last_position = position;
    double last_time = 0;
    size_t next_idx = 0;
    bool is_alive = true;
    while(detector_->getModel()->isWithinSensor(static_cast<ROOT::Math::XYZPoint>(position)) &&
          (initial_time + runge_kutta.getTime()) < integration_time_ && is_alive) {
    auto state = CarrierState::MOTION;
    while(state == CarrierState::MOTION && (initial_time + runge_kutta.getTime()) < integration_time_) {
        // Update output plots if necessary (depending on the plot step)
        if(output_linegraphs_) {
            auto time_idx = static_cast<size_t>(runge_kutta.getTime() / output_plots_step_);
@@ -790,16 +790,23 @@ GenericPropagationModule::propagate(const ROOT::Math::XYZPoint& pos,
        position += diffusion;
        runge_kutta.setValue(position);

        // Check if we are still in the sensor:
        if(!detector_->getModel()->isWithinSensor(static_cast<ROOT::Math::XYZPoint>(position))) {
            state = CarrierState::HALTED;
        }

        // Check if charge carrier is still alive:
        is_alive = !recombination_(type,
        if(recombination_(type,
                          detector_->getDopingConcentration(static_cast<ROOT::Math::XYZPoint>(position)),
                          survival(random_generator),
                                   timestep);
                          timestep)) {
            state = CarrierState::RECOMBINED;
        }

        LOG(TRACE) << "Step from " << Units::display(static_cast<ROOT::Math::XYZPoint>(last_position), {"um", "mm"})
                   << " to " << Units::display(static_cast<ROOT::Math::XYZPoint>(position), {"um", "mm"}) << " at "
                   << Units::display(initial_time + runge_kutta.getTime(), {"ps", "ns", "us"})
                   << (is_alive ? "" : ", recombined");
                   << ", state: " << allpix::to_string(state);
        // Adapt step size to match target precision
        double uncertainty = step.error.norm();

@@ -830,7 +837,7 @@ GenericPropagationModule::propagate(const ROOT::Math::XYZPoint& pos,

    // Find proper final position in the sensor
    auto time = runge_kutta.getTime();
    if(!detector_->getModel()->isWithinSensor(static_cast<ROOT::Math::XYZPoint>(position))) {
    if(state == CarrierState::HALTED) {
        auto check_position = position;
        check_position.z() = last_position.z();
        if(position.z() > 0 && detector_->getModel()->isWithinSensor(static_cast<ROOT::Math::XYZPoint>(check_position))) {
@@ -855,12 +862,12 @@ GenericPropagationModule::propagate(const ROOT::Math::XYZPoint& pos,
        }
    }

    if(!is_alive) {
    if(state == CarrierState::RECOMBINED) {
        LOG(DEBUG) << "Charge carrier recombined after " << Units::display(last_time, {"ns"});
    }

    // Return the final position of the propagated charge
    return std::make_tuple(static_cast<ROOT::Math::XYZPoint>(position), initial_time + time, is_alive);
    return std::make_tuple(static_cast<ROOT::Math::XYZPoint>(position), initial_time + time, state);
}

void GenericPropagationModule::finalize() {
+7 −7
Original line number Diff line number Diff line
@@ -88,10 +88,10 @@ namespace allpix {
         * @param initial_time Initial time passed before propagation starts in local time coordinates
         * @param random_generator Reference to the random number engine to be used
         * @param output_plot_points Reference to vector to hold points for line graph output plots
         * @return Tuple with the point where the deposit ended after propagation, the time the propagation took and a flag
         * whether it has recombined
         * @return Tuple with the point where the deposit ended after propagation, the time the propagation took and the
         * final state of the charge carrier at the end of processing
         */
        std::tuple<ROOT::Math::XYZPoint, double, bool> propagate(const ROOT::Math::XYZPoint& pos,
        std::tuple<ROOT::Math::XYZPoint, double, CarrierState> propagate(const ROOT::Math::XYZPoint& pos,
                                                                         const CarrierType& type,
                                                                         const double initial_time,
                                                                         RandomNumberGenerator& random_generator,
+8 −2
Original line number Diff line number Diff line
@@ -328,8 +328,14 @@ void ProjectionPropagationModule::run(Event* event) {
            auto global_position = detector_->getGlobalPosition(local_position);

            // Produce charge carrier at this position
            propagated_charges.emplace_back(
                local_position, global_position, deposit.getType(), charge_per_step, local_time, global_time, &deposit);
            propagated_charges.emplace_back(local_position,
                                            global_position,
                                            deposit.getType(),
                                            charge_per_step,
                                            local_time,
                                            global_time,
                                            CarrierState::HALTED,
                                            &deposit);

            LOG(DEBUG) << "Propagated " << charge_per_step << " " << type << " to "
                       << Units::display(local_position, {"mm", "um"}) << " in " << Units::display(global_time, "ns")
+15 −15
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@

#include "core/utils/distributions.h"
#include "core/utils/log.h"
#include "objects/PixelCharge.hpp"
#include "objects/PropagatedCharge.hpp"
#include "tools/runge_kutta.h"

using namespace allpix;
@@ -193,7 +191,7 @@ void TransientPropagationModule::run(Event* event) {
            std::map<Pixel::Index, Pulse> px_map;

            // Get position and propagate through sensor
            auto [local_position, time, alive] = propagate(
            auto [local_position, time, state] = propagate(
                event, deposit.getLocalPosition(), deposit.getType(), charge_per_step, deposit.getLocalTime(), px_map);

            // Create a new propagated charge and add it to the list
@@ -204,6 +202,7 @@ void TransientPropagationModule::run(Event* event) {
                                               std::move(px_map),
                                               deposit.getLocalTime() + time,
                                               deposit.getGlobalTime() + time,
                                               state,
                                               &deposit);

            LOG(DEBUG) << " Propagated " << charge_per_step << " to " << Units::display(local_position, {"mm", "um"})
@@ -212,7 +211,7 @@ void TransientPropagationModule::run(Event* event) {

            propagated_charges.push_back(std::move(propagated_charge));

            if(alive) {
            if(state != CarrierState::RECOMBINED) {
                propagated_charges_count += charge_per_step;
            } else {
                recombined_charges_count += charge_per_step;
@@ -241,7 +240,7 @@ void TransientPropagationModule::run(Event* event) {
 * velocity at every point with help of the electric field map of the detector. A Runge-Kutta integration is applied in
 * multiple steps, adding a random diffusion to the propagating charge every step.
 */
std::tuple<ROOT::Math::XYZPoint, double, bool>
std::tuple<ROOT::Math::XYZPoint, double, CarrierState>
TransientPropagationModule::propagate(Event* event,
                                      const ROOT::Math::XYZPoint& pos,
                                      const CarrierType& type,
@@ -307,9 +306,8 @@ TransientPropagationModule::propagate(Event* event,

    // Continue propagation until the deposit is outside the sensor
    Eigen::Vector3d last_position = position;
    bool within_sensor = true;
    bool is_alive = true;
    while(within_sensor && (initial_time + runge_kutta.getTime()) < integration_time_ && is_alive) {
    auto state = CarrierState::MOTION;
    while(state == CarrierState::MOTION && (initial_time + runge_kutta.getTime()) < integration_time_) {
        // Save previous position and time
        last_position = position;

@@ -329,10 +327,12 @@ TransientPropagationModule::propagate(Event* event,
        runge_kutta.setValue(position);

        // Check if charge carrier is still alive:
        is_alive = !recombination_(type,
        if(recombination_(type,
                          detector_->getDopingConcentration(static_cast<ROOT::Math::XYZPoint>(position)),
                          survival(event->getRandomEngine()),
                                   timestep_);
                          timestep_)) {
            state = CarrierState::RECOMBINED;
        }

        // Update step length histogram
        if(output_plots_) {
@@ -356,7 +356,7 @@ TransientPropagationModule::propagate(Event* event,
                    LOG(DEBUG) << "Not stopping carrier " << type << " at "
                               << Units::display(static_cast<ROOT::Math::XYZPoint>(position), {"um"});
                } else {
                    within_sensor = false;
                    state = CarrierState::HALTED;
                }

                // Carrier left sensor on top or bottom surface, interpolate
@@ -366,7 +366,7 @@ TransientPropagationModule::propagate(Event* event,
                position = (z_last_border / z_total) * position + (z_cur_border / z_total) * last_position;
                LOG(TRACE) << "Moved carrier to: " << Units::display(static_cast<ROOT::Math::XYZPoint>(position), {"nm"});
            } else {
                within_sensor = false;
                state = CarrierState::HALTED;
            }
        }

@@ -418,7 +418,7 @@ TransientPropagationModule::propagate(Event* event,
    }

    // Return the final position of the propagated charge
    return std::make_tuple(static_cast<ROOT::Math::XYZPoint>(position), initial_time + runge_kutta.getTime(), is_alive);
    return std::make_tuple(static_cast<ROOT::Math::XYZPoint>(position), initial_time + runge_kutta.getTime(), state);
}

void TransientPropagationModule::finalize() {
Loading