ComputationalRadiationPhysics / picongpu

Performance-Portable Particle-in-Cell Simulations for the Exascale Era :sparkles:
https://picongpu.readthedocs.io
Other
704 stars 217 forks source link

FAQ Proposition #776

Open mxmlnkn opened 9 years ago

mxmlnkn commented 9 years ago

I think something like this would have helped me in the start.

Template for Datatypes FAQ:
    What is it?
    Which methods are provided by the class?
    In which contexts should it be used?
    Where can I get further in-depth details?

================= What Datatypes are used throughout PiConGPU? =================

What is Dataspace<DIM> ?
     It is a template vector of ints with exactly DIM elements
         class DataSpace : public math::Vector<int,DIM>
     constructors up to DIM==3 exist: Dataspace<DIM>(x,y,z)
     It is used for multi-dimensional (super) cell ids and to specify the super cell size
     See libPMacc/include/dimensions/DataSpace.hpp
     See also Vector

What is float3_X ?
     It is a 3-vector of float_X, float_X is a wrapper for floating point single precision or floating point double precision
        typedef ::PMacc::math::Vector<float_X, 3> float3_X;
     It has a constructor taking 3 arguments
     It is used for all physic calculations
     See picongpu/include/simulation_defines/unitless/precision.unitless
     See also Vector

What is Vector ?
    It's a template Vector class, meaning the number of elements are a compile time constant
    It shouldn't be used directly in code, instead used derived types, like Dataspace or float3_X
    Methods provided are available in CUDA device and host code:
        Access operator[] or x(),y(),z()
        productOfComponents()
        +=,-=,*=,/=,+,-,*,/ element-wise and broadcast from single floating point element
        %,==, !=, >= element-wise
        <<, toString, abs, abs2, dot
    not methods, but functions with vector parameters
        linearize(Vector size, Vector pos) (only DIM==2 and DIM==3)
        floor(Vector)
    double + Vector is not overloaded! Instead use Vector + double
    See libPMacc\include\math\vector

What is a ParticleBox ?
    It is a wrapper for DataBox, which provides methods for easier access to the linked list of frames in a supercell. A ParticleBox is a union of many supercells (all on that process ??? on that gpu ???)
        class ParticlesBox : protected DataBox<PitchedBox<SuperCell<FRAME>, DIM> >
    It is used as a parameter to CUDA kernels which then can do calculations on the particles in that particle box, by specifying the supercell wanted and then traversing the frames of that supercell
    Members provided are available in CUDA device and host code:
        getNextFrame, getPreviousFrame (FRAME &frame, bool &isValid)
        getLastFrame, getFirstFrame (const DataSpace<DIM> &supercellId, bool &isValid)
        setAsFirstFrame, setAsLastFrame (FRAME &frameIn, const DataSpace<DIM> &idx)
        removeLastFrame, getSupercell
    typdefs in namespace:
        FrameType, FramePtr, SuperCellType, BaseType
    See libPMacc/include/particles/memory/boxes/ParticlesBox.hpp

What is a Supercell ?
    A supercell is a conglomeration of simulation cells. The cells itself are not directly derivable. All particles in a supercell instead are saved in frames.
    The Supercellsize is defined in picongpu\include\simulation_defines\param\memory.param as a compile time vector (see boost::mpl::vector)
    The datatype itself is more like a container holding the data about the first and the last frame only:
        LastFramePtr,mustShift,setMustShift,getSizeLastFrame,setSizeLastFrame
    Pointers to the last and first frame are initialized NULL
    See libPMacc\include\particles\memory\dataTypes\SuperCell.hpp

What is a Frame ?

    COMING !!!

How many elements can a Frame hold ?
    As much as cells in a super cell, so SuperCellSize.productOfComponents() elements.

======================= Reusable Code Snippets explained =======================

How do I Add a new Particle attribute ?
    First you will need to create an identifier for that attribute in simulation_defines/speciesAttributes.param, e.g. by adding:
        value_identifier( float3_X, momentumChangeValue,float3_X(0.));
        value_identifier( <datatype>, <attributeName>, <default value> );
    The attribute will then be available in a kernel with
        particle[momentumChange()]
    or equivalently:
        particle[momentumChange_]
    Secondly you will need to add the attribute name to the compile-time list of attributes in DefaultParticleAttributes in simulation_defines/speciesDefinition.param
        typedef typename MakeSeq<
            position<position_pic>,
            momentum,
            weighting,
    ->      momentumChange
        >::type DefaultParticleAttributes;
    DefaultParticleAttributes will in turn be applied to all species. So if you want only one species to have that attribute
    The alias and the value obviously must have different names.
    When using the hdf5 plugin the Unit template functor in simulation_defines/speciesAttributes.unitless needs to be specialized for that new attribute by adding:template<>
        struct Unit<momentumChange>
        {
            static std::vector<double> get()
            {
                const uint32_t ndim = GetNComponents<typename momentumChange::type>::value;

                std::vector<double> unit(ndim);
                for( uint32_t i = 0; i < ndim ; ++i )
                    unit[i] = UNIT_MASS*UNIT_SPEED;

                return unit;
            }
        };

Why this roundabout approach with alias and value_identifier ?
     The reason for this two-step approach is, that it enables to assign different underlying types for different species, which can be accessed by the same alias.
     E.g. you could specify the underlying type for momentumChange to be single precision for electrons and double precision for ions:

     speciesAttribues.param
        typedef ::PMacc::math::Vector<float , 3> float3;
        typedef ::PMacc::math::Vector<double, 3> int3;
        alias( momentumChange );
        value_identifier( float3, momChangeValuef,float3(0.) );
        value_identifier( int3  , momChangeValuei,int3(0.)   );

     speciesDefinition.param
        /* define species electrons */
        typedef Particles<ParticleDescription<
            bmpl::string<'e'>,
            SuperCellSize,
            DefaultAttributesSeq,
            ParticleFlagsElectrons,
     ->     momentumChange<momChangeValuef>,
            typename MakeSeq<CommunicationId<PAR_ELECTRONS> >::type  >
        > PIC_Electrons;/*define specie ions*/

        /* define species ions */
        typedef Particles<ParticleDescription<
            bmpl::string<'i'>,
            SuperCellSize,
            DefaultAttributesSeq,
     ->     momentumChange<momChangeValuei>,
            ParticleFlagsIons,
            typename MakeSeq<CommunicationId<PAR_IONS> >::type >
        > PIC_Ions;

I now have different attributes for my species, how can I check which species I currently am working on in my kernel?
    To compare two species, it's possible to compare their frametypes with 'IsSameType<T1,T2>::result' as defined in libpmacc/include/traits/IsSameType.hpp
    E.g.: T_FrameBox::FrameType

How do I add a new particle ?
    COMING !!!

What is PMACC_AUTO ?
    Because of template meta programming 'particle' is a very complex particle type necessitating PMACC_AUTO which is a wrapper to BOOST_AUTO, e.g.:
        PMACC_AUTO( particle1, (*frame)[linThreadIdx] );
    BOOST_AUTO emulates the C++11 auto feature, which assign the datatype automatically if it can be derived from the assignment. This is similar to less type dependent languages like python

Why not use C++11 ?
    CUDA doesn't yet support C++11. It available in CUDA 7, which will be used after it has been field tested for some years

Why is my const array defined in *.param not accessible in my kernel ?
    Error-Message:
        error: identifier "_ZN8picongpu17InitParticleBetasE" is undefined
    CUDA only supports using simple const datatypes from global scope like const int. Arrays are not yet supported. A workaround has been implemented, use:
        CONST_VECTOR( <Datatype>, <Number_of_elements>, <Variable_Name>, <element0>, <element1>, ... );
    Beware: Datatype must have an empty constructor, to be usable in device code! Or else you'll get:
    Error-Message:
        can't generate code for non empty constructors or destructors on device

How large is a supercell?
    The supercell size is defined in simulation_defines/memory.param, e.g.
        typedef typename mCT::shrinkTo<mCT::Int<8, 8, 4>, simDim>::type SuperCellSize;
    It is a compile-time vector using meta template programming (boost::mpl)

SuperCellSize is a compile-time Vector, how do I use it in my code?
    use SuperCellSize::toRT() meaning toRuntime, converting the compile time vector (see boost::mpl::vector) to a normale template Vector base class, from which DataSpace and float3_X were derived.
    See also: libPMacc\include\math\vector\compile-time\Vector.hpp

How do I write a simple kernel for picongpu ?
    COMING !!!

How large is my simulation ?
    The number of simulation cells are specified as runtime parameters after the -g flag e.g. in your parametersetfolder/submit/*.cfg. This must be a multiple of supercells.
    The cellsize is set with CELL_WIDTH_SI, CELL_HEIGHT_SI and CELL_DEPTH_SI in simulation_defines/param/gridConfig.param:

What is a parameterset ?
    A parameterset is a compilation of user customized files, especially *.param files
    First all the source files from picongpu\src\picongpu\include will be copied to a temporary folder when building picongpu. In a second step all files from the paramsetfolder/include will also be copied into that temporary folder overwriting all files of the same name.
    Therefore it's possible to customize MySimulation.hpp and every source file in a parameter set
    Templates for *.param files can be found in picongpu\src\picongpu\include\simulation_defines\param
    #include "simulation_defines/param/species.param" vs. #include "pecies.param" !!!

What is the difference between *.param and *.unitless ?
    In *.param physical parameters are specified in SI Units. As it's not adviseable to use SI units in actual calculations the *.unitless files convert these values into internal units
    Therefore normally it should only be necessary to make adjustions in *.param

What restrictions are there on the grid size?
    The number of cells must be a multiple of the super cell size which right now by default is 8x8x4.
    Also because the core may not be empty the minimum grid size in each direction is 3 super cells!

I can't use a const variable I defined in my .params in my CUDA-kernel
    error: identifier "picongpu::SPEED_OF_LIGHT" is undefined in device code
    If you used something like:
        float3_X res = a * SPEED_OF_LIGHT;
    then firstly define SPEED_OF_LIGHT in device code, initializing it with the compile-time constant from physicalConstants.unitless:
        const float_X c = SPEED_OF_LIGHT;
        const float3_X = a * c;
PrometheusPi commented 9 years ago

:+1: great work

bussmann commented 9 years ago

Great idea!

psychocoderHPC commented 9 years ago

+1

ax3l commented 9 years ago

well done at @mxmlnkn :sparkles:

that's actually not a PIConGPU but a libPMacc FAQ to more than 50% and should be added in the wiki - libPMacc - developer guidelines

n01r commented 9 years ago

:+1: Great!

ax3l commented 7 years ago

documented PMACC_STRUCT in #1879 and #1880

important classes started in #1871 and #1880

tbg in #1883

ax3l commented 7 years ago