Ejemplo n.º 1
0
        /** Functor
         *
         * @param currentStep the current time step
         * @param speciesGroup naming for the group of species in T_SpeciesList
         */
        void operator()(
            uint32_t currentStep,
            std::string const & speciesGroup
        )
        {
            // generating a density requires at least one slot in FieldTmp
            PMACC_CASSERT_MSG(
                _please_allocate_at_least_one_FieldTmp_in_memory_param,
                fieldTmpNumSlots > 0
            );

            DataConnector &dc = Environment<>::get().DataConnector();

            // load FieldTmp without copy data to host and zero it
            auto fieldTmp = dc.get< FieldTmp >(
                FieldTmp::getUniqueId( 0 ),
                true
            );
            using DensityValueType = typename FieldTmp::ValueType;
            fieldTmp->getGridBuffer().getDeviceBuffer().setValue( DensityValueType::create(0.0) );

            // add density of each species in list to FieldTmp
            ForEach< SpeciesList, detail::AddSingleDensity< bmpl::_1 > > addSingleDensity;
            addSingleDensity( currentStep, forward( fieldTmp ) );

            /* create valid density in the BORDER region
             * note: for average != supercell multiples the GUARD of fieldTmp
             *       also needs to be filled in the communication above
             */
            EventTask fieldTmpEvent = fieldTmp->asyncCommunication(__getTransactionEvent());
            __setTransactionEvent(fieldTmpEvent);

            /* average summed density in FieldTmp down to local resolution and
             * write in new field
             */
            auto nlocal = dc.get< LocalDensity >(
                helperFields::LocalDensity::getName( speciesGroup ),
                true
            );
            constexpr uint32_t numWorkers = pmacc::traits::GetNumWorkers<
                pmacc::math::CT::volume< SuperCellSize >::type::value
            >::value;
            PMACC_KERNEL( helperFields::KernelAverageDensity< numWorkers >{ } )
            (
                // one block per averaged density value
                nlocal->getGridBuffer().getGridLayout().getDataSpaceWithoutGuarding(),
                numWorkers
            )
            (
                // start in border (jump over GUARD area)
                fieldTmp->getDeviceDataBox().shift( SuperCellSize::toRT() * GuardSize::toRT() ),
                // start in border (has no GUARD area)
                nlocal->getGridBuffer().getDeviceBuffer( ).getDataBox( )
            );

            // release fields
            dc.releaseData( FieldTmp::getUniqueId( 0 ) );
            dc.releaseData( helperFields::LocalDensity::getName( speciesGroup ) );
        }
Ejemplo n.º 2
0
            /* host constructor initializing member : random number generator */
            ThomasFermi_Impl(const uint32_t currentStep) : randomGen(RNGFactory::createRandom<Distribution>())
            {
                /* create handle for access to host and device data */
                DataConnector &dc = Environment<>::get().DataConnector();

                /* The compiler is allowed to evaluate an expression that does not depend on a template parameter
                 * even if the class is never instantiated. In that case static assert is always
                 * evaluated (e.g. with clang), this results in an error if the condition is false.
                 * http://www.boost.org/doc/libs/1_60_0/doc/html/boost_staticassert.html
                 *
                 * A workaround is to add a template dependency to the expression.
                 * `sizeof(ANY_TYPE) != 0` is always true and defers the evaluation.
                 */
                PMACC_CASSERT_MSG(
                    _please_allocate_at_least_two_FieldTmp_slots_in_memory_param,
                    ( fieldTmpNumSlots >= 2 ) && ( sizeof( T_IonizationAlgorithm ) != 0 )
                );
                /* initialize pointers on host-side density-/energy density field databoxes */
                auto density = dc.get< FieldTmp >( FieldTmp::getUniqueId( 0 ), true );
                auto eneKinDens = dc.get< FieldTmp >( FieldTmp::getUniqueId( 1 ), true );

                /* reset density and kinetic energy values to zero */
                density->getGridBuffer().getDeviceBuffer().setValue( FieldTmp::ValueType( 0. ) );
                eneKinDens->getGridBuffer().getDeviceBuffer().setValue( FieldTmp::ValueType( 0. ) );

                /* load species without copying the particle data to the host */
                auto srcSpecies = dc.get< SrcSpecies >( SrcSpecies::FrameType::getName(), true );

                /* kernel call for weighted ion density calculation */
                density->template computeValue< CORE + BORDER, DensitySolver >(*srcSpecies, currentStep);
                dc.releaseData( SrcSpecies::FrameType::getName() );
                EventTask densityEvent = density->asyncCommunication( __getTransactionEvent() );
                densityEvent += density->asyncCommunicationGather( densityEvent );

                /* load species without copying the particle data to the host */
                auto destSpecies = dc.get< DestSpecies >( DestSpecies::FrameType::getName(), true );

                /* kernel call for weighted electron energy density calculation */
                eneKinDens->template computeValue< CORE + BORDER, EnergyDensitySolver >(*destSpecies, currentStep);
                dc.releaseData( DestSpecies::FrameType::getName() );
                EventTask eneKinEvent = eneKinDens->asyncCommunication( __getTransactionEvent() );
                eneKinEvent += eneKinDens->asyncCommunicationGather( eneKinEvent );

                /* contributions from neighboring GPUs to our border area */
                __setTransactionEvent( densityEvent + eneKinEvent );

                /* initialize device-side density- and energy density field databox pointers */
                rhoBox = density->getDeviceDataBox();
                eneBox = eneKinDens->getDeviceDataBox();

            }
        /** Functor
         *
         * @param currentStep the current time step
         * @param speciesGroup naming for the group of species in T_SpeciesList
         * @param minEnergy minimum energy to account for (eV)
         * @param maxEnergy maximum energy to account for (eV)
         */
        void operator()(
            uint32_t currentStep,
            std::string const & speciesGroup,
            float_X const minEnergy,
            float_X const maxEnergy
        )
        {
            DataConnector &dc = Environment<>::get().DataConnector();

            /* load local energy histogram field without copy data to host and
             * zero it
             */
            auto eneHistLocal = dc.get< LocalEnergyHistogram >(
                helperFields::LocalEnergyHistogram::getName( speciesGroup ),
                true
            );

            // reset local energy histograms
            eneHistLocal->getGridBuffer().getDeviceBuffer().setValue( float_X( 0.0 ) );

            // add local energy histogram of each species in list
            ForEach< SpeciesList, detail::AddSingleEnergyHistogram< bmpl::_1 > > addSingleEnergyHistogram;
            addSingleEnergyHistogram( currentStep, forward( eneHistLocal ), minEnergy, maxEnergy );

            /* note: for average != supercell the BORDER region would need to be
             *       build up via communication accordingly
             */

            // release fields
            dc.releaseData( helperFields::LocalEnergyHistogram::getName( speciesGroup ) );
        }