Skip to content

Commit

Permalink
VelocityAbsProfile + Profile Doc
Browse files Browse the repository at this point in the history
git-svn-id: https://scm.projects.hlrs.de/authscm/sprinz/svn/ls1/MarDyn/trunk@6472 a63bd714-7e14-4b5e-94e7-302c8c8ff188
  • Loading branch information
kruegener committed Aug 30, 2018
1 parent 454fb9e commit 74973c1
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 40 deletions.
38 changes: 25 additions & 13 deletions src/plugins/KartesianProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
#include "KartesianProfile.h"

/**
* Read in Information about write/record frequencies and which profiles are enabled. Also create needed profiles and initialize them. New Profiles need to be handled via the XML here as well.
* @param xmlconfig
*/
* @brief Read in Information about write/record frequencies, Sampling Grid and which profiles are enabled.
* Also create needed profiles and initialize them. New Profiles need to be handled via the XML here as well.
* @param xmlconfig
*/
void KartesianProfile::readXML(XMLfileUnits &xmlconfig) {
global_log -> debug() << "[KartesianProfile] enabled" << std::endl;
xmlconfig.getNodeValue("writefrequency", _writeFrequency);
Expand Down Expand Up @@ -53,11 +54,16 @@ void KartesianProfile::readXML(XMLfileUnits &xmlconfig) {
if(_TEMPERATURE || _ALL){
// TODO
}
// TODO: Different XML for different velocity profiles
if(_VELOCITY || _ALL){
ProfileBase* profile = new Velocity3dProfile();
profile->init(this);
_profiles.push_back(profile);
_comms += profile->comms();
ProfileBase* profile_abs = new VelocityAbsProfile();
profile_abs->init(this);
_profiles.push_back(profile_abs);
_comms += profile_abs->comms();
}

xmlconfig.getNodeValue("timesteps/init", _initStatistics);
Expand All @@ -68,9 +74,11 @@ void KartesianProfile::readXML(XMLfileUnits &xmlconfig) {

}

/**
/**
*
* Initialize Arrays needed for calculating the profiles. Also get reference to domain for specific quantities. All profiles will be reset here before using.
* @brief Initialize Arrays needed for calculating the profiles. Also get reference to domain for specific quantities.
* All profiles will be reset here to 0 before starting the recording frame. The uIDs are can be calculated from the
* globalLength and the number of divisions specified for the Sampling grid.
*
* @param particleContainer
* @param domainDecomp
Expand All @@ -86,7 +94,7 @@ void KartesianProfile::init(ParticleContainer* particleContainer, DomainDecompBa
global_log->info() << "[KartesianProfile] universalInvProfileUnit " << universalInvProfileUnit[i] << "\n";
}
_uIDs = (unsigned long) (this->universalProfileUnit[0] * this->universalProfileUnit[1]
* this->universalProfileUnit[2]);
* this->universalProfileUnit[2]);
global_log->info() << "[KartesianProfile] number uID " << _uIDs << "\n";

segmentVolume = this->globalLength[0] * this->globalLength[1] * this->globalLength[2]
Expand All @@ -105,6 +113,7 @@ void KartesianProfile::init(ParticleContainer* particleContainer, DomainDecompBa
/**
* @brief Iterates over all molecules and passes them together with their Bin ID to the profiles for further processing.
* If the current timestep hits the writefrequency the profile writes/resets are triggered here.
* All of this only occurs after the initStatistics are passed.
* @param particleContainer
* @param domainDecomp
* @param domain
Expand All @@ -116,49 +125,52 @@ void KartesianProfile::endStep(ParticleContainer *particleContainer, DomainDecom

unsigned xun, yun, zun;
if ((simstep >= _initStatistics) && (simstep % _profileRecordingTimesteps == 0)) {
// TODO: RECORD PROFILES
long int uID;
// Loop over all particles and bin them
// Loop over all particles and bin them with uIDs
for(ParticleIterator thismol = particleContainer->iterator(); thismol.hasNext(); thismol.next()){
// Calculate uID
xun = (unsigned) floor(thismol->r(0) * this->universalInvProfileUnit[0]);
yun = (unsigned) floor(thismol->r(1) * this->universalInvProfileUnit[1]);
zun = (unsigned) floor(thismol->r(2) * this->universalInvProfileUnit[2]);
uID = (unsigned long) (xun * this->universalProfileUnit[1] * this->universalProfileUnit[2]
+ yun * this->universalProfileUnit[2] + zun);

+ yun * this->universalProfileUnit[2] + zun);
// pass mol + uID to all profiles
for(unsigned i = 0; i < _profiles.size(); i++){
_profiles[i]->record(&thismol, uID);
}
}
// Record number of Timesteps recorded since last output write
accumulatedDatasets++;
}
if ((simstep >= _initStatistics) && (simstep % _writeFrequency == 0)) {
// COLLECTIVE COMMUNICATION
global_log->info() << "[KartesianProfile] uIDs: " << _uIDs << " acc. Data: " << accumulatedDatasets << "\n";
// Initialize Communication with number of bins * number of total comms needed per bin by all profiles.
domainDecomp->collCommInit(_comms*_uIDs);
//global_log->info() << "[KartesianProfile] profile collectAppend" << std::endl;
for(unsigned long uID = 0; uID < _uIDs; uID++){
for(unsigned i = 0; i < _profiles.size(); i++){
_profiles[i]->collectAppend(domainDecomp, uID);
}
}
//global_log->info() << "[KartesianProfile] Allreduce" << std::endl;
// Reduction Communication to get global values
domainDecomp->collCommAllreduceSum();
//global_log->info() << "[KartesianProfile] profile collectRetrieve" << std::endl;
// Write global values in all bins in all profiles
for(unsigned long uID = 0; uID < _uIDs; uID++) {
for (unsigned i = 0; i < _profiles.size(); i++) {
_profiles[i]->collectRetrieve(domainDecomp, uID);
}
}
// Finalize Communication
domainDecomp->collCommFinalize();
// Initialize Output from rank 0 process
if (mpi_rank == 0) {
global_log->info() << "[KartesianProfile] Writing profile output" << std::endl;
for(unsigned i = 0; i < _profiles.size(); i++){
_profiles[i]->output(_outputPrefix + "_" + std::to_string(simstep));
}
}
//global_log->info() << "[KartesianProfile] profile reset" << std::endl;
// Reset profile arrays for next recording frame.
for(unsigned long uID = 0; uID < _uIDs; uID++) {
for (unsigned i = 0; i < _profiles.size(); i++) {
_profiles[i]->reset(uID);
Expand Down
30 changes: 16 additions & 14 deletions src/plugins/KartesianProfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

#include "PluginBase.h"
#include "Domain.h"
#include "profiles/DensityProfile.h"
#include "plugins/profiles/DensityProfile.h"
#include "plugins/profiles/Velocity3dProfile.h"
#include "plugins/profiles/VelocityAbsProfile.h"

#include "parallel/DomainDecompBase.h"
#include "particleContainer/ParticleContainer.h"
Expand Down Expand Up @@ -59,26 +60,27 @@ class KartesianProfile : public PluginBase{

static PluginBase* createInstance(){return new KartesianProfile();}

double universalInvProfileUnit[3];
double universalProfileUnit[3];
long accumulatedDatasets;
double globalLength[3];
double segmentVolume;
Domain* dom;
double universalInvProfileUnit[3]; // Inv. Bin Sizes
double universalProfileUnit[3]; // Bin Sizes
long accumulatedDatasets; // Number of Datasets between output writes / profile resets
double globalLength[3]; // Size of Domain
double segmentVolume; // Size of one Sampling grid bin
Domain* dom; // Reference to global Domain
ProfileBase* _densProfile; //!< Reference to DensityProfile as it is needed by most other profiles

private:
unsigned long _writeFrequency;
unsigned long _initStatistics;
unsigned long _profileRecordingTimesteps;
std::string _outputPrefix;
unsigned long _writeFrequency; // Write frequency for all profiles -> Length of recording frame before output
unsigned long _initStatistics; // Timesteps to skip at start of the simulation
unsigned long _profileRecordingTimesteps; // Record every Nth timestep during recording frame
std::string _outputPrefix; // File prefix for all profiles
std::string _mode;

unsigned long _uIDs; //!< Total number of unique IDs with the selected Grid. This is the number of total cells in the grid.
unsigned long _uIDs; //!< Total number of unique IDs with the selected Grid. This is the number of total bins in the Sampling grid.

vector<ProfileBase*> _profiles;
int _comms = 0;
vector<ProfileBase*> _profiles; // vector holding all enabled profiles
int _comms = 0; // total number of communications per bin needed by all profiles.

// Needed for XML check for enabled profiles.
bool _ALL = false;
bool _DENSITY = false;
bool _TEMPERATURE = false;
Expand Down
1 change: 1 addition & 0 deletions src/plugins/profiles/DensityProfile.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Created by Kruegener on 8/19/2018.
// Ported from Domain.cpp by Mheier.
//

#include "DensityProfile.h"
Expand Down
7 changes: 3 additions & 4 deletions src/plugins/profiles/DensityProfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
#include "ProfileBase.h"
#include "../KartesianProfile.h"


/**
* @brief Outputs the number density of molecules per bin specified by Sampling grid in KartesianProfile.
*/
class DensityProfile : public ProfileBase {
public:
~DensityProfile() final {};
Expand All @@ -17,18 +19,15 @@ class DensityProfile : public ProfileBase {
}
void collectAppend(DomainDecompBase *domainDecomp, unsigned long uID) final {
domainDecomp->collCommAppendLongDouble(_localProfile[uID]);
//global_log->info() << "[DensityProfile] localProfile " << uID << ": " << _localProfile[uID] << "\n";
}
void collectRetrieve(DomainDecompBase *domainDecomp, unsigned long uID) final {
_globalProfile[uID] = domainDecomp->collCommGetLongDouble();
//global_log->info() << "[DensityProfile] globalProfile " << uID << ": " << _globalProfile[uID] << "\n";
}
void output(string prefix) final;
void reset(unsigned long uID) final {
_localProfile[uID] = 0.0;
_globalProfile[uID] = 0.0;
}
// set correct number of communications needed for this profile
int comms() final {return 1;}
};

Expand Down
57 changes: 50 additions & 7 deletions src/plugins/profiles/ProfileBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,73 @@ class KartesianProfile;

/** @brief Base class for all Profile outputs used by KartesianProfile.
*
* The major steps for all profiles are recording the profile data, communication, output and reset. Each of these steps
* has a function associated with it that needs to be implemented by all profiles inheriting this class to be able to
* work with KartesianProfile. KartesianProfile also needs to know the number of items added to the communication per
* Molecule. So a DensityProfile should return 1 via comms(). A Velocity3dProfile should return 3.
* The major steps for all profiles are <b>recording</b> the profile data, <b>communication</b>, writing the <b>output file</b>
* and <b>resetting</b> everything for the next recording period. Each of these steps has a function associated with it that
* needs to be implemented by all profiles inheriting this class to be able to work with KartesianProfile.
* KartesianProfile also needs to know the number of items added to the communication per
* Molecule. So a DensityProfile should return 1 via Profile::comms(). A Velocity3dProfile should return 3. <br>
* A very simple <b>example</b> of how to use this class is the DensityProfile.
*
*/
class ProfileBase {

public:
virtual ~ProfileBase(){};
/** @brief Init function is given a pointer to the KartesianProfile object handling this profile. Same for all profiles.
*
* @param kartProf Pointer to KartesianProfile. Grants access to necessary global params.
*/
void init(KartesianProfile* kartProf) {_kartProf = kartProf;};
/** @brief The recording step defines what kind of data needs to be recorded for a single molecule with a corresponding uID.
*
* @param mol Reference to Molecule, needed to extract info such as velocity or Virial.
* @param uID uID of molecule in sampling grid, needed to put data in right spot in the profile arrays.
*/
virtual void record(ParticleIterator *mol, unsigned long uID) = 0;
/** @brief Append all necessary communication per bin to the DomainDecomposition. Append from e.g. _localProfile.
*
* @param domainDecomp DomainDecomposition handling the communication.
* @param uID uID of molecule in sampling grid, needed to put data in right spot in the profile arrays.
*/
virtual void collectAppend(DomainDecompBase *domainDecomp, unsigned long uID) = 0;
/** @brief Get global values after AllReduceSum per bin. Write to e.g. _globalProfile.
*
* @param domainDecomp DomainDecomposition handling the communication.
* @param uID uID of molecule in sampling grid, needed to put data in right spot in the profile arrays.
*/
virtual void collectRetrieve(DomainDecompBase *domainDecomp, unsigned long uID) = 0;
/** @brief Whatever is necessary to output for this profile.
*
* This function varies wildly between profiles. The Profile should output to its desired format here and handle all
* file IO for one profile writing step.
* @param prefix File prefix including the global _outputPrefix for all profiles and the current timestep. Should be
* appended by some specific file ending for this specific profile.
*/
virtual void output(string prefix) = 0;
/** @brief Used to reset all array contents for a specific uID in order to start the next recording timeframe.
*
* @param uID uID of molecule in sampling grid, needed to put data in right spot in the profile arrays.
*/
virtual void reset(unsigned long uID) = 0;
// number of needed communications
virtual int comms() = 0;

/** @brief 1D profiles like a number density profile should return 1 here. 3D profiles that have 3 entries per bin
* that need to be communicated would need to return 3. Adjust as needed. Same number as commAppends in collectAppend.
*
* @return Number of nedded communications per bin so the communicator can be setup correctly.
*/
virtual int comms() = 0;
/** @brief 1D Profile access. Some Profiles need information from others, so this enables sharing arrays between profiles.
*
* @return Internal Global Arrays after communication.
*/
std::map<unsigned, long double> getProfile(){return _globalProfile;};
/** @brief 3D Profile access. Some Profiles need information from others, so this enables sharing arrays between profiles.
*
* @return Internal Global Arrays after communication.
*/
std::map<unsigned, long double>* get3dProfile(){return _global3dProfile;};

protected:
// TODO: Add necessary maps for profiles
// Local 1D Profile
std::map<unsigned, long double> _localProfile;
// Global 1D Profile
Expand Down
5 changes: 4 additions & 1 deletion src/plugins/profiles/Velocity3dProfile.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Created by Kruegener on 8/27/2018.
// Ported from Domain.cpp by Mheier.
//

#include "Velocity3dProfile.h"
Expand All @@ -9,13 +10,14 @@ void Velocity3dProfile::output(string prefix) {
_profilePrefix = prefix;
_profilePrefix += "_kartesian.V3Dpr";

// Need to get DensityProfile to calculate average velocities per bin independent of number density.
std::map<unsigned, long double> dens = _kartProf->_densProfile->getProfile();

ofstream outfile(_profilePrefix.c_str());
outfile.precision(6);

outfile << "//Segment volume: " << _kartProf->segmentVolume << "\n//Accumulated data sets: " << _kartProf->accumulatedDatasets << "\n//Local profile of X-Y-Z components of velocity. Output file generated by the \"Velocity3dProfile\" method, plugins/profiles. \n";
outfile << "//local velocity profile: Y - Z || X-projection\n";
outfile << "//local velocity component profile: Y - Z || X-projection\n";
// TODO: more info
outfile << "// \t dX \t dY \t dZ \n";
outfile << "\t" << 1/_kartProf->universalInvProfileUnit[0] << "\t" << 1/_kartProf->universalInvProfileUnit[1] << "\t" << 1/_kartProf->universalInvProfileUnit[2]<< "\n";
Expand All @@ -36,6 +38,7 @@ void Velocity3dProfile::output(string prefix) {
long unID = (long) (x * _kartProf->universalProfileUnit[0] * _kartProf->universalProfileUnit[2] + y * _kartProf->universalProfileUnit[1] + z);
// X - Y - Z output
for(unsigned d = 0; d < 3; d++){
// Check for division by 0
if(dens[unID] != 0){
vd = _global3dProfile[d][unID] / dens[unID];
}
Expand Down
4 changes: 3 additions & 1 deletion src/plugins/profiles/Velocity3dProfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
#include "ProfileBase.h"
#include "../KartesianProfile.h"


/**
* @brief Outputs the XYZ velocity components per bin specified by Sampling grid in KartesianProfile.
*/
class Velocity3dProfile : public ProfileBase {
public:
~Velocity3dProfile() final = default;
Expand Down
52 changes: 52 additions & 0 deletions src/plugins/profiles/VelocityAbsProfile.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// Created by Kruegener on 8/29/2018.
//

#include "VelocityAbsProfile.h"

void VelocityAbsProfile::output(string prefix) {
global_log->info() << "[VelocityAbsProfile] output" << std::endl;
_profilePrefix = prefix;
_profilePrefix += "_kartesian.VAbspr";

// Need to get DensityProfile to calculate average velocities per bin independent of number density.
std::map<unsigned, long double> dens = _kartProf->_densProfile->getProfile();

ofstream outfile(_profilePrefix.c_str());
outfile.precision(6);

outfile << "//Segment volume: " << _kartProf->segmentVolume << "\n//Accumulated data sets: " << _kartProf->accumulatedDatasets << "\n//Local profile of magnitude of velocity. Output file generated by the \"VelocityAbsProfile\" method, plugins/profiles. \n";
outfile << "//local velocity magnitude profile: Y - Z || X-projection\n";
// TODO: more info
outfile << "// \t dX \t dY \t dZ \n";
outfile << "\t" << 1/_kartProf->universalInvProfileUnit[0] << "\t" << 1/_kartProf->universalInvProfileUnit[1] << "\t" << 1/_kartProf->universalInvProfileUnit[2]<< "\n";
outfile << "0 \t";

for(unsigned z = 0; z < _kartProf->universalProfileUnit[2]; z++){
outfile << (z+0.5) / _kartProf->universalInvProfileUnit[2] <<" \t\t\t"; // Eintragen der z Koordinaten in Header
}
outfile << "\n";
long double vd;
// Y - axis label
for(unsigned y = 0; y < _kartProf->universalProfileUnit[1]; y++){
double hval = (y + 0.5) / _kartProf->universalInvProfileUnit[1];
outfile << hval << "\t";
// number density values
for(unsigned z = 0; z < _kartProf->universalProfileUnit[2]; z++){
for(unsigned x = 0; x < _kartProf->universalProfileUnit[0]; x++){
long unID = (long) (x * _kartProf->universalProfileUnit[0] * _kartProf->universalProfileUnit[2] + y * _kartProf->universalProfileUnit[1] + z);
// Abs output
// Check for division by 0
if(dens[unID] != 0){
vd = _globalProfile[unID] / dens[unID];
}
else{
vd = 0;
}
outfile << vd << "\t";
}
}
outfile << "\n";
}
outfile.close();
}

0 comments on commit 74973c1

Please sign in to comment.