Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ struct Hydrogen
*
* - None : no particle is ionized
* - BSIHydrogenLike : simple barrier suppression ionization
* - ADK : Ammosov-Delone-Krainov tunneling ionization (H-like)
* - ADKLinPol : Ammosov-Delone-Krainov tunneling ionization (H-like)
* -> linearly polarized lasers
* - ADKCircPol : Ammosov-Delone-Krainov tunneling ionization (H-like)
* -> circularly polarized lasers
*
* Research and development: ----------------------------------------------
* - BSIEffectiveZ : BSI taking electron shielding into account via an effective
Expand Down
42 changes: 34 additions & 8 deletions src/picongpu/include/particles/ionization/byField/ADK/ADK.def
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,44 @@ namespace particles
namespace ionization
{

/** \struct ADK_Impl
*
* \brief Ammosov-Delone-Krainov tunneling model
/** Ammosov-Delone-Krainov tunneling model
*
* \tparam T_DestSpecies electron species to be created
* \tparam T_SrcSpecies ion species to be ionized
* default is boost::mpl placeholder because specialization
* cannot be known in list of particle species' flags
* \see speciesDefinition.param
*/
template<typename T_DestSpecies, typename T_SrcSpecies = bmpl::_1>
template<typename T_IonizationAlgorithm, typename T_DestSpecies, typename T_SrcSpecies = bmpl::_1>
struct ADK_Impl;

/** \struct ADK
/** Ammosov-Delone-Krainov tunneling model - linear laser polarization
*
* - takes the ionization energies of the various charge states of ions
* - calculates the ionization rates and then the ionization probabilities from them
* - ATTENTION: this approach is not very applicable for rapidly changing high intensity laser fields
* - this is a Monte Carlo method: if a random number is smaller
* or equal than the ionization probability -> increase the charge state
* - see for example: Delone, N. B.; Krainov, V. P. (1998).
* "Tunneling and barrier-suppression ionization of atoms and ions in a laser radiation field"
* doi:10.1070/PU1998v041n05ABEH000393
*
* \brief Ammosov-Delone-Krainov tunneling model
* wrapper class,
* needed because the SrcSpecies cannot be known during the
* first specialization of the ionization model in the particle definition
* \see speciesDefinition.param
*/
template<typename T_DestSpecies>
struct ADKLinPol
{
/* Boolean value that results in an additional polarization factor in
* the ionization rate for linear polarization */
BOOST_STATIC_CONSTEXPR bool linPol = true;
typedef particles::ionization::AlgorithmADK<linPol> IonizationAlgorithm;
typedef ADK_Impl<IonizationAlgorithm, T_DestSpecies> type;
};

/** Ammosov-Delone-Krainov tunneling model - circular laser polarization
*
* - takes the ionization energies of the various charge states of ions
* - calculates the ionization rates and then the ionization probabilities from them
Expand All @@ -61,9 +83,13 @@ namespace ionization
* \see speciesDefinition.param
*/
template<typename T_DestSpecies>
struct ADK
struct ADKCircPol
{
typedef ADK_Impl<T_DestSpecies> type;
/* Boolean value that results in an additional polarization factor in
* the ionization rate for linear polarization */
BOOST_STATIC_CONSTEXPR bool linPol = false;
typedef particles::ionization::AlgorithmADK<linPol> IonizationAlgorithm;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please give a struct with the float value of the polarization factor instead of a bool.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the value has to be calculated during runtime -- see above

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, thanks for clarifying. 👍

typedef ADK_Impl<IonizationAlgorithm, T_DestSpecies> type;
};

} // namespace ionization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace ionization
* \tparam T_DestSpecies electron species to be created
* \tparam T_SrcSpecies particle species that is ionized
*/
template<typename T_DestSpecies, typename T_SrcSpecies>
template<typename T_IonizationAlgorithm, typename T_DestSpecies, typename T_SrcSpecies>
struct ADK_Impl
{

Expand Down Expand Up @@ -81,7 +81,7 @@ namespace ionization
private:

/* define ionization ALGORITHM (calculation) for ionization MODEL */
typedef particles::ionization::AlgorithmADK IonizationAlgorithm;
typedef T_IonizationAlgorithm IonizationAlgorithm;

/* random number generator for Monte Carlo */
typedef particles::ionization::RandomNrForMonteCarlo<SrcSpecies> RandomGen;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ namespace particles
namespace ionization
{

/** \struct AlgorithmADK
/** Calculation for the Ammosov-Delone-Krainov tunneling model
*
* \brief calculation for the Ammosov-Delone-Krainov tunneling model */
* for either linear or circular laser polarization
*
* \tparam T_linPol boolean value that is true for lin. pol. and false for circ. pol.
*/
template<bool T_linPol>
struct AlgorithmADK
{

/** Functor implementation
* \tparam EType type of electric field
* \tparam BType type of magnetic field
Expand Down Expand Up @@ -82,11 +85,19 @@ namespace ionization
float_X dBase = float_X(4.0) * util::cube(protonNumber) / (eInAU * util::quad(nEff)) ;
float_X dFromADK = math::pow(dBase,nEff);

/* ionization rate */
float_X rateADK = math::sqrt(float_X(3.0) * util::cube(nEff) * eInAU / (pi * util::cube(protonNumber))) \
* eInAU * util::square(dFromADK) / (float_X(8.0) * pi * protonNumber) \
/* ionization rate (for CIRCULAR polarization)*/
float_X rateADK = eInAU * util::square(dFromADK) / (float_X(8.0) * pi * protonNumber) \
* math::exp(float_X(-2.0) * util::cube(protonNumber) / (float_X(3.0) * util::cube(nEff) * eInAU));

/* in case of linear polarization the rate is modified by an additional factor */
if(T_linPol)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still a run-time decision thus is not as efficient as possible.
Just use:

float_X polarizationFactor = TEMPLATE_PARAM::polarizationFactor;

with a struct containing the value not just a bool.

Copy link
Member Author

@n01r n01r Aug 5, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value is not const so I cannot just calculate it during compile time (it depends on the ionization potential and the electric field strength). Nevertheless, it is known if the bool is true or false during compile time. Therefore the compiler should optimize the code in such a way that the unnecessary code vanishes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@psychocoderHPC
your verdict?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PrometheusPi Your suggestion is not possible because like @n01r said the factor is only known at runtime.

A possible solution would be to add a functor for the factor calculation but it is a little bit complicated because of the needed input values.

My suggestion: (small design change)

/* ionization rate */
float_X rateADK = polarizationFactor \
                * eInAU * util::square(dFromADK) / (float_X(8.0) * pi * protonNumber) \
                * math::exp(float_X(-2.0) * util::cube(protonNumber) / (float_X(3.0) * util::cube(nEff) * eInAU));

if(T_linPol)
{
    /* factor from averaging over one laser cycle with LINEAR polarization */
    const float_X polarizationFactor = math::sqrt(float_X(3.0) * util::cube(nEff) * eInAU / (pi * util::cube(protonNumber)));
    rateADK *= polarizationFactor;
}

Then the code is better readable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Yep, looks good to me. I think it's okay to stay away from overcomplicating things and not introduce a new functor for this.

{
/* factor from averaging over one laser cycle with LINEAR polarization */
const float_X polarizationFactor = math::sqrt(float_X(3.0) * util::cube(nEff) * eInAU / (pi * util::cube(protonNumber)));

rateADK *= polarizationFactor;
}

/* simulation time step in atomic units */
const float_X timeStepAU = float_X(DELTA_T / ATOMIC_UNIT_TIME);
/* ionization probability
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace ionization

struct AlgorithmNone;

template<bool T_polarizationType>
struct AlgorithmADK;

struct AlgorithmBSIHydrogenLike;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@
* These includes contain forward declarations of < Ionization Models >
*/

/** contains definitions for:
* - ADKLinPol
* - ADKCircPol
*/
#include "particles/ionization/byField/ADK/ADK.def"
/** contains BSI definitions for:
/** contains definitions for:
* - BSIHydrogenLike
* - BSIEffectiveZ
* - BSIStarkShifted
Expand Down