Options to implement multithinning in CORSIKA 8
Motivation
We definitely want to have the option to compare an unthinned shower to a thinned (“pruned”) version of it. We cannot directly compare an unthinned shower with a thinned one even with the same random-number seed because the thinning messes up the random-number stream. Even interactions in the early generations are affected when thinning starts in a late generation because of the depth-first traversal of the shower.
This is a rather special application that only few users are interested in, definitely not mainstream.
Possible implementations
Particles have N weights instead of 1 (or 0 for unthinned showers). The design question is how/where to handle this distinction w.r.t. output-generating modules (particle output file, long. profile, radio signal traces, histogramming modules like interaction counter, …)
-
Max (C7-inspired): “inner-loop approach”: the modules are aware of the multiple weights. They have to loop over all thinning modes and have e.g. N histograms, each one corresponding to a certain thinning mode. The modules need to be well aware that they are running in multi-thinning mode, so this is rather intrusive. This option is least computationally costly.
-
Lukas, Tim: “outer-loop approach”: the loop over thinning modes happens at a higher level. The modules are called N times, each time they see only the weight of the current thinning mode. If a particle is considered discarded in a particular thinning mode, the module is not called at all. The modules are to a large degree unaware of being in multi-thinning or not. The getWeight() method, when called inside a module, would point to one of the entries in the weight vector. Nevertheless, at least in the initialization phase they need to know about it so that they can setup N files/histograms/…. Some computational cost are incurred because the calculations in the modules are performed multiple times with same results.
-
Tanguy: “intermediate solution”: Modules can have the inner loop if the developer chooses to do that, but by default they just deal with one weight. Here, getWeight() is equivalent to getMultiweight(mode=0)
-
Max: emulate multi-thinning by having only one mode, but still keep discarded particles. Discarded particles are assigned a weight of 0. This way, the shower can be regenerated in another run to obtain a different thinned representation. Obviusly very computationally costly.
More advanced solutions
-
Lukas: One could run only the unthinned part of a thinned shower and “put aside” (stored on disk or another stack) all particles just when thinning sets in in a certain vertex. Only after these early generations are fully processed, the later generations are processed. This way, the disruption of the random-number stream does not interfere with the early generations. The simulations of the particles put-aside can be restarted from there to obtain another thinned representation of the same shower.
-
Augusto proposed a completely different approach based on resampling and weights that blows everybody’s minds.