/** 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 ) ); }
/* 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 ) ); }