Skip to content

Commit

Permalink
Merge pull request #3134 from pordyna/topic-saxsPlugin
Browse files Browse the repository at this point in the history
SAXS plugin implementation using electron density
  • Loading branch information
psychocoderHPC authored Sep 4, 2020
2 parents 8882958 + dfe8a99 commit 93a6e0e
Show file tree
Hide file tree
Showing 49 changed files with 4,435 additions and 6 deletions.
20 changes: 20 additions & 0 deletions docs/TBG_macros.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,26 @@ TBG_radiation="--<species>_radiation.period 1 --<species>_radiation.dump 2 --<sp
#--<species>_transRad.period Gives the number of time steps between which the radiation should be calculated.
TBG_transRad="--<species>_transRad.period 1000"

# The following flags are available for the xrayScattering plugin.
# For a full description, see the plugins section in the online documentation.
#--<species>_xrayScattering.period Period at which the plugin is enabled.
#--<species>_xrayScattering.outputPeriod Period at which the accumulated amplitude is written to the output file.
#--<species>_xrayScattering.qx_max Upper bound of reciprocal space range in qx direction.
#--<species>_xrayScattering.qy_max Upper bound of reciprocal space range in qy direction.
#--<species>_xrayScattering.qx_max Lower bound of reciprocal space range in qx direction.
#--<species>_xrayScattering.qy_max Lower bound of reciprocal space range in qy direction.
#--<species>_xrayScattering.n_qx Number of scattering vectors needed to be calculated in qx direction.
#--<species>_xrayScattering.n_qy Number of scattering vectors needed to be calculated in qy direction.
#--<species>_xrayScattering.file Output file name. Default is `<species>_xrayScatteringOutput`.
#--<species>_xrayScattering.ext `openPMD` filename extension. This controls the backend picked by the `openPMD` API. Default is `bp` for adios backend.
#--<species>_xrayScattering.compression Backend-specific `openPMD` compression method (e.g.) zlib.
#--<species>_xrayScattering.memoryLayout Possible values: `mirror` and `split`. Output can be mirrored on all Host+Device pairs or uniformly split, in chunks, over all nodes.
TBG_<species>_xrayScattering="--<species>_xrayScattering.period 1 --e_xrayScattering.outputPeriod 10 \
--e_xrayScattering.n_qx 512 --e_xrayScattering.n_qy 512 \
--e_xrayScattering.qx_min 0 --e_xrayScattering.qx_max 1 \
--e_xrayScattering.qy_min -1 --e_xrayScattering.qy_max 1 \
--e_xrayScattering.memoryLayout split"

# Create 2D images in PNG format every .period steps.
# The slice plane is defined using .axis [yx,yz] and .slicePoint (offset from origin
# as a float within [0.0,1.0].
Expand Down
1 change: 1 addition & 0 deletions docs/source/usage/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Plugin name
:ref:`slice field printer <usage-plugins-sliceFieldPrinter>` [#f5]_ print out a slice of the electric and/or magnetic and/or current field
:ref:`sum currents <usage-plugins-sumCurrents>` compute the total current summed over all cells
:ref:`transitionRadiation <usage-plugins-transitionRadiation>` compute emitted electromagnetic spectra
:ref:`xrayScattering <usage-plugins-xrayScattering>` compute SAXS scattering amplitude ( based on `FieldTmp` species density )
==================================================================================== =================================================================================

.. rubric:: Footnotes
Expand Down
142 changes: 142 additions & 0 deletions docs/source/usage/plugins/xrayScattering.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
.. _usage-plugins-xrayScattering:

xrayScattering
--------------

This plugin calculates Small Angle X-ray Scattering (SAXS) patterns from electron density.
( Using a density `FieldTmp` as an intermediate step and not directly the macro particle distribution. )
This is a species specific plugin and it has to be run separately for each scattering species.
Since the plugin output is the scattered complex amplitude, contributions from different species can be coherently summed later on.

.. math::
\Phi({\vec q}) &= \frac{r_e}{d} \int_{t} \mathrm{d}t \int_{V} \mathrm{d}V \phi({\vec r}, t) n({\vec r}, t) \\
I &= \left| \Phi \right|^2
============================== ================================================================================
Variable Meaning
============================== ================================================================================
:math:`\Phi` Scattered amplitude
:math:`\vec q` Scattering vector with :math:`|{\vec q}| = \frac{4 \pi \sin \theta}{\lambda}`
:math:`\theta` Scattering angle. :math:`2\theta` is the angle between the incoming and the scattered k-vectors.
:math:`\lambda` Probing beam wavelength
:math:`n` Electron density
:math:`\phi` Incoming wave amplitude
:math:`I` Scattering intensity
:math:`d` Screen distance
:math:`r_e` Classical electron radius

============================== ================================================================================


For the free electrons, the density :math:`n` is just their number density, for ions it is the bound electrons density of the species.
This plugin will automatically switch to bound electrons density for species having the `boundElectrons` property.

The volume integral is realized by a discrete sum over the simulation cells and the temporal integration reduces to accumulating the amplitude over simulation time steps.

.. note::
This calculation is based on the kinematic model of scattering. Multiple scattering CAN NOT be handled in this model.

.param file
^^^^^^^^^^^

The `xrayScattering.param` file sets the x-ray beam alignment as well as its temporal and transverse envelope.

.. note::
At the moment the translation (to the side center + offset) is not working correctly.
For that reason, the envelopes and the offset can't be set in the ``.param`` file yet.
The probe is always a plane wave.
Beam rotation works.

The alignment settings define a beam coordinate system with :math:`\hat{z} = \hat{k}` and :math:`\hat{x}`, :math:`\hat{y}` perpendicular to the x-ray propagation direction.
It is always a right-hand system. It is oriented in such way that for propagation parallel to the PIC x- or y-axis (`Side`: `X`, `XR`, `Y` or `YR`) :math:`\hat{x}_{\text{beam}} = - \hat{z}_{\text{PIC}}` holds and if :math:`{\vec k }` is parallel to the PIC z-axis (`Side`: `Z` or `ZR`), :math:`\hat{x}_{\text{beam}} = - \hat{y}_{\text{PIC}}` holds.
The orientation can be then fine adjusted with the `RotationParam` setting.
.. TODO: Figures showing the beam coordinate system orientation in the PIC system.
.. TODO: Add other parameters after the coordinate transform has been fixed and the settings have been moved back to the .param file.
================= ===============================================================================================================================
Setting Description
================= ===============================================================================================================================
``ProbingSide`` The side from which the x-ray is propagated.
Set `X`, `Y` or `Z` for propagation along one of the PIC coordinate system axes;
`XR`, `YR` or `ZR` for propagation in an opposite direction.

``RotationParam`` Rotation of the beam axis, :math:`z_{\text{beam}}`, from the default orientation ( perpendicular the the simulation box side ).
Set the beam yaw and pitch angles in radians.
================= ===============================================================================================================================

.. TODO: Add BEAM_OFFSET in between after the coordinate transform has been fixed.
The coordinate transfer from the PIC system to the beam system is performed in the following order:
rotation to one of the default orientations (``ProbingSide`` setting), additional rotation (``RotationParam`` ). This has to be taken into account when defining the experimental setup.


.cfg file
^^^^^^^^^

For a specific (charged) species ``<species>`` e.g. ``e``, the scattering can be computed by the following commands.

============================================ ============================================================================================================================================
Command line option Description
============================================ ============================================================================================================================================
``--<species>_xrayScattering.period`` Period at which the plugin is enabled (PIC period syntax). Only the intensity from this steps is accumulated.
Default is `0`, which means that the scattering intensity in never calculated and therefor off

``--<species>_xrayScattering.outputPeriod`` Period at which the accumulated amplitude is written to the output file (PIC period syntax). Usually set close to the x-ray coherence time.

``--<species>_xrayScattering.qx_max`` Upper bound of reciprocal space range in qx direction. The unit is :math:`Å^{-1}`. Default is `5`.

``--<species>_xrayScattering.qy_max`` Upper bound of reciprocal space range in qy direction. The unit is :math:`Å^{-1}` Default is `5`.

``--<species>_xrayScattering.qx_min`` Lower bound of reciprocal space range in qx direction. The unit is :math:`Å^{-1}` Default is `-5`.

``--<species>_xrayScattering.qy_min`` Lower bound of reciprocal space range in qy direction. The unit is :math:`Å^{-1}` Default is `-5`.

``--<species>_xrayScattering.n_qx`` Number of scattering vectors needed to be calculated in qx direction. Default is `100`,

``--<species>_xrayScattering.n_qy`` Number of scattering vectors needed to be calculated in qy direction. Default is '100'.

``--<species>_xrayScattering.file`` Output file name. Default is `<species>_xrayScatteringOutput`.

``--<species>_xrayScattering.ext`` `openPMD` filename extension. This controls the backend picked by the `openPMD` API. Default is `bp` for adios backend.

``--<species>_xrayScattering.compression`` Backend-specific `openPMD` compression method (e.g.) zlib.

``--<species>_xrayScattering.memoryLayout`` Possible values: `mirror` and `split`. Output can be mirrored on all Host+Device pairs or uniformly split, in chunks, over all nodes.
Use split when the output array is too big to store the complete computed q-space on one device.
For small output grids the `mirror` setting could turn out to be more efficient.
============================================ ============================================================================================================================================


Output
^^^^^^

``<species>_xrayScatteringOutput.<backend-specific extension>``

Output file in the `openPMD` standard. An example on how to access your data with the python reader:

.. code-block:: python

from picongpu.plugins.data import XrayScatteringData

simulation_path = '...' # dir containing simOutput, input, ..,
# Read output from the 0th step, for electrons, hdf5 backend.
data = XrayScatteringData( simulation_path, 'e', 'h5' )
amplitude = saxsData.get(iteration=0) * saxsData.get_unit()
del XrayScatteringData

When you don't want to use the python reader keep in mind that:
* All iterations are saved in a single file
* The mesh containing the output is called `'amplitude'`
* This mesh has 2 components, `'x'` is the real part and `'y'` is the imaginary part.

.. note::
The amplitude is not zeroed on ``outputPeriod`` so one has to subtract the output from the iteration one period before and then calculate :math:`\left|\Phi\right|^2` and sum it with the intensities from other coherence periods.


References
^^^^^^^^^^

- [1] Kluge, T., Rödel, C., Rödel, M., Pelka, A., McBride, E. E., Fletcher, L. B., … Cowan, T. E. (2017). Nanometer-scale characterization of laser-driven compression, shocks, and phase transitions, by x-ray scattering using free electron lasers. Physics of Plasmas, 24(10). https://doi.org/10.1063/1.5008289
3 changes: 3 additions & 0 deletions include/picongpu/_defaultParam.loader
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,6 @@
#include "picongpu/param/isaac.param"
#include "picongpu/param/radiationObserver.param"
#include "picongpu/param/particleMerger.param"
#if( ENABLE_OPENPMD == 1 )
# include "picongpu/param/xrayScattering.param"
#endif
5 changes: 5 additions & 0 deletions include/picongpu/param/physicalConstants.param
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ namespace picongpu
* doi:10.1088/0026-1394/52/2/360
*/
constexpr float_64 N_AVOGADRO = 6.02214076e23;

//! Classical electron radius in SI units
constexpr float_64 ELECTRON_RADIUS_SI = ELECTRON_CHARGE_SI *
ELECTRON_CHARGE_SI / ( 4.0 * PI * EPS0_SI * ELECTRON_MASS_SI *
SPEED_OF_LIGHT_SI * SPEED_OF_LIGHT_SI );
}

/** Unit of speed */
Expand Down
54 changes: 54 additions & 0 deletions include/picongpu/param/xrayScattering.param
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* Copyright 2020 Pawel Ordyna
*
* This file is part of PIConGPU.
*
* PIConGPU is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PIConGPU is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PIConGPU.
* If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "picongpu/simulation_defines.hpp"
#include "picongpu/plugins/xrayScattering/beam/Side.hpp"

/* preprocessor struct generator */
#include <pmacc/preprocessor/struct.hpp>

namespace picongpu
{
namespace plugins
{
namespace xrayScattering
{
namespace beam
{
using namespace picongpu::plugins::xrayScattering::beam;
/* Choose from:
* - ZSide
* - YSide
* - XSide
* - ZRSide
* - YRSide
* - XRSide
*/
using ProbingSide = ZSide;

PMACC_STRUCT( RotationParam,
( PMACC_C_VALUE ( float_X, yawAngle, 0 ) )
( PMACC_C_VALUE ( float_X, pitchAngle, 0 ) )
);
}// namespace beam
}// namespace xrayScattering
}// namespace plugins
}// namespace picongpu
4 changes: 4 additions & 0 deletions include/picongpu/plugins/PluginController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@

#if (ENABLE_OPENPMD == 1)
# include "picongpu/plugins/openPMD/openPMDWriter.hpp"
# include "picongpu/plugins/xrayScattering/XrayScattering.hpp"
#endif

#if( PMACC_CUDA_ENABLED == 1 )
Expand Down Expand Up @@ -227,6 +228,9 @@ class PluginController : public ILightweightPlugin
CountParticles<bmpl::_1>,
PngPlugin< Visualisation<bmpl::_1, PngCreator> >,
plugins::transitionRadiation::TransitionRadiation<bmpl::_1>
#if(ENABLE_OPENPMD == 1)
, plugins::xrayScattering::XrayScattering<bmpl::_1>
#endif
#if(ENABLE_HDF5 == 1)
, plugins::radiation::Radiation<bmpl::_1>
, plugins::multi::Master< ParticleCalorimeter<bmpl::_1> >
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/* Copyright 2020 Pawel Ordyna
*
* This file is part of PIConGPU.
*
* PIConGPU is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PIConGPU is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PIConGPU.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include "picongpu/simulation_defines.hpp"
#include <pmacc/traits/HasFlag.hpp>
#include "picongpu/particles/particleToGrid/derivedAttributes/DerivedAttributes.def"

namespace picongpu
{
namespace plugins
{
namespace xrayScattering
{
using namespace particles::particleToGrid;

template< typename T_ParticleType >
struct IsIon
{
using FrameType = typename T_ParticleType::FrameType;
using type = typename pmacc::traits::HasFlag<
FrameType,
boundElectrons
>::type;
};


/** Chose an electron density solver for a given particle type.
*
* Switches between a bound electron number density solver for particles
* with the boundElectrons attribute (ions) and a particle number density
* solver for other particle types (electrons).
*
* @tparam T_ParticleType Scattering particles
* @return ::type TmpField solver to be used
*/
template< typename T_ParticlesType >
struct DetermineElectronDensitySolver
{
using IonSolver = typename CreateFieldTmpOperation_t<
T_ParticlesType,
derivedAttributes::BoundElectronDensity
>::Solver;

using ElectronSolver = typename CreateFieldTmpOperation_t<
T_ParticlesType,
derivedAttributes::Density
>::Solver;

using type = typename boost::mpl::if_<
typename IsIon< T_ParticlesType >::type,
IonSolver,
ElectronSolver
>::type;
};
} // namespace xrayScattering
} // namespace plugins
} // namespace picongpu
Loading

0 comments on commit 93a6e0e

Please sign in to comment.