It would be great to have a feature that would allow setting the number of particles per cell (NPPC) that are initialized for each species.
For instance in ion acceleration cases where a high-Z material (copper, gold, ...), as well as organic contaminants (hydrogen + carbon + oxygen ...), are modeled together, the computational cost would be high due to all the electrons that are created by ionization. Ideally, we would choose a low NPPC for the high-Z material and a higher NPPC for the source of our accelerated protons.
Currently, different methods are available:
startPosition/RandomImpl.hpp and change the number of particles per cell based on arbitrary conditionsmultiMask to 0Quiet start and randomize the in-cell-position later with manipulators::unary::RandomPosition We could pin the NPPC to the species with a flag a read it for initialization but we still need the TYPICAL_PARTICLES_PER_CELL to normalize the weighting to a good value for floating point precision.
One could also define a particlesPerCellRatio but rounding rules would be necessary to arrive at an integer number of macroparticles.
Also the question arises to which NPPC we set the TYPICAL_PARTICLES_PER_CELL in order to get good normalized values close to 1 for all species.
Ha! Okay ... foolish me :fish:
struct RandomParameter
{
/** Count of particles per cell at initial state
*
* unit: none */
static constexpr uint32_t numParticlesPerCell = TYPICAL_PARTICLES_PER_CELL;
};
/** definition of random particle start */
using Random = RandomImpl< RandomParameter >;
Defining one Random for each species and then handing it to the speciesInitialization pipeline should actually work fine.
Leaving this issue open for a bit more discussion if the feature should be realized differently but the basic functionality is already available.
the basic functionality is already available.
Actually the full functionality is available already ;)
An extended example for a particle.param:
namespace startPosition
{
struct RandomParameterCarbon1PPC
{
static constexpr uint32_t numParticlesPerCell = 1u;
};
using RandomCarbon1PPC = RandomImpl< RandomParameterCarbon1PPC >;
struct RandomParameterHydrogen3PPC
{
static constexpr uint32_t numParticlesPerCell = 3u;
};
using RandomHydrogen3PPC = RandomImpl< RandomParameterHydrogen3PPC >;
} // namespace startPosition
and a speciesInitalization.param:
namespace picongpu
{
namespace particles
{
using InitPipeline = mpl::vector<
CreateDensity<
densityProfiles::Homogenous,
startPosition::RandomCarbon1PPC,
Carbon
>,
CreateDensity<
densityProfiles::Homogenous,
startPosition::RandomHydrogen3PPC,
Hydrogen
>
>;
} // namespace particles
} // namespace picongpu
Yeah ^^; that's what I used now. Should what you just wrote maybe be rather put into the composite materials workflow in the docs?
I think that is a bit redundant to the examples and quickly and overloads the composite materials how-to and becomes quickly out of date but I can update a few of the examples that only use one method anyway. We can still add a note tough!
But I currently have a look on the examples to only provide one method in each particle.param so it becomes more clear.
While checking multi-component targets such as FoilLCT, it might also make sense to expose MIN_WEIGHTING per species to avoid low-density sections with missing components when reaching below that threshold with one species but not an other.
Yes, that's a very valid point which we will have to check from setup to setup.
The usual workflow as it is also recommended and documented is to initialize one ion species first and derive the others from it in order to always have the same ratio of macro particles in a cell, even for low-density regions. by that, a MIN_WEIGHTING per species is not needed. of course, if one wants to vary the ppc per ion species, one would need that or could control the lower-dens cutoff via a well-defined density profile with lower bound (per species) which is above the weighting in the (global) MIN_WEIGHTING.
Is there more to document in this issue than what we added in #2412?
Hmm, I can't think of anything at the moment. I think so far we're good :+1:
All right, feel free to reopen or open a new issue if something is not documented!