MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
SamplingData< nDim, SolverType > Class Template Reference

This base class is responsible for the sampling data feature that provides the required general methods needed for sampling data at distinct points. More...

#include <samplingdata.h>

Inheritance diagram for SamplingData< nDim, SolverType >:
[legend]
Collaboration diagram for SamplingData< nDim, SolverType >:
[legend]

Public Member Functions

 SamplingData (SolverType &solver)
 
void init ()
 
void save (MBool finalTimestep)
 
void setInputOutputProperties ()
 
MBool enabled () const
 
virtual MInt loadInputFile (const MString NotUsed(inputFileName), const MInt NotUsed(fileNo), std::vector< MFloat > &NotUsed(coordinates))
 
virtual MString getBaseName () const
 Return base name of derived class, e.g. used for naming properties and output file names. More...
 

Protected Member Functions

void init (SamplingDataSeries &timeSeries)
 
void save (SamplingDataSeries &timeSeries, MBool finalTimeStep)
 Saves sampling data Saves all states of conservative variables at specified points. Also writes sampling data files in specified intervals. More...
 
virtual MBool hasInputDataFile (const MInt fileNo) const
 Check if an input file exists, might be overwritten in derived class if points are generated. More...
 
virtual MBool generatePoints () const
 Default behaviour for point generation which can be overwritten in derived class. More...
 
virtual MInt noSamplingPoints (const MInt NotUsed(fileNo))
 Return the number of sampling points which are generated by the derived class (no input file) More...
 
virtual void getSamplingPoint (const MInt NotUsed(fileNo), const MInt NotUsed(pointId), MFloat *const NotUsed(coordinates))
 Return the coordinates of the sampling point with the given id when generating points. More...
 
void indexXD (const MInt index, const MInt *const nPoints, MInt *indexXD)
 Convert 1D index into 2D/3D index. More...
 
void saveSamplingPointCoordinates (SamplingDataSeries &timeSeries)
 Save point coordinates of time series. More...
 
virtual void readAdditionalProperties (const MInt NotUsed(fileNo))
 Read additional properties which are required by the derived class. More...
 
MInt solverId () const
 
MBool isMpiRoot () const
 
MPI_Comm mpiComm () const
 
MInt noVars () const
 Return total number of sampling variables. More...
 
MString getFileBaseName () const
 Return base name of files for used sampling feature. More...
 
SolverTypesolver ()
 Return reference to solver. More...
 
const SolverTypesolver () const
 

Protected Attributes

MBool m_enabled = false
 
MBool m_interpolatePointData
 
std::vector< SamplingDataSeriesm_timeSeries {}
 Holds all properties and buffers for each input file. More...
 
std::vector< MIntm_solverSamplingVarIds {}
 List of sampling variables. More...
 
std::vector< MIntm_noSolverSamplingVars {}
 Number of variables for each sampling variable. More...
 
std::vector< std::vector< MString > > m_solverSamplingVarNames {}
 List of variable names for each sampling variable. More...
 

Private Attributes

SolverTypem_solver
 

Detailed Description

template<MInt nDim, class SolverType>
class SamplingData< nDim, SolverType >
Author
Fabian Klemp f.kle.nosp@m.mp@a.nosp@m.ia.rw.nosp@m.th-a.nosp@m.achen.nosp@m..de
Date
2016-09-27

Definition at line 35 of file samplingdata.h.

Constructor & Destructor Documentation

◆ SamplingData()

template<MInt nDim, class SolverType >
SamplingData< nDim, SolverType >::SamplingData ( SolverType solver)
inline

Definition at line 37 of file samplingdata.h.

37: m_solver(solver) {}
SolverType & m_solver
Definition: samplingdata.h:150
SolverType & solver()
Return reference to solver.
Definition: samplingdata.h:129

Member Function Documentation

◆ enabled()

template<MInt nDim, class SolverType >
MBool SamplingData< nDim, SolverType >::enabled ( ) const
inline

Definition at line 42 of file samplingdata.h.

42{ return m_enabled; }

◆ generatePoints()

template<MInt nDim, class SolverType >
virtual MBool SamplingData< nDim, SolverType >::generatePoints ( ) const
inlineprotectedvirtual

◆ getBaseName()

◆ getFileBaseName()

template<MInt nDim, class SolverType >
MString SamplingData< nDim, SolverType >::getFileBaseName ( ) const
inlineprotected

Definition at line 126 of file samplingdata.h.

126{ return getBaseName() + "_data_"; }
virtual MString getBaseName() const
Return base name of derived class, e.g. used for naming properties and output file names.
Definition: samplingdata.h:53

◆ getSamplingPoint()

template<MInt nDim, class SolverType >
virtual void SamplingData< nDim, SolverType >::getSamplingPoint ( const MInt   NotUsedfileNo,
const MInt   NotUsedpointId,
MFloat *const   NotUsedcoordinates 
)
inlineprotectedvirtual

Definition at line 103 of file samplingdata.h.

104 {
105 TERMM(1, "Not implemented in derived class!");
106 }

◆ hasInputDataFile()

template<MInt nDim, class SolverType >
virtual MBool SamplingData< nDim, SolverType >::hasInputDataFile ( const MInt  fileNo) const
inlineprotectedvirtual

Reimplemented in VolumeData< nDim, SolverType >, VolumeData< nDim, DgCartesianSolver< nDim, SysEqn > >, VolumeData< nDim, FvCartesianSolverXD< nDim, SysEqn > >, and VolumeData< nDim, LbSolver >.

Definition at line 64 of file samplingdata.h.

64 {
65 const MString propName = getBaseName() + "DataFileName_" + std::to_string(fileNo);
66 if(Context::propertyExists(propName, solverId())) {
67 const MString fileName = Context::getSolverProperty<MString>(propName, solverId(), AT_);
68 return fileName != "";
69 } else {
70 return false;
71 }
72 }
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
Definition: context.cpp:494
MInt solverId() const
Definition: samplingdata.h:118
std::basic_string< char > MString
Definition: maiatypes.h:55

◆ indexXD()

template<MInt nDim, class SolverType >
void SamplingData< nDim, SolverType >::indexXD ( const MInt  index,
const MInt *const  nPoints,
MInt indexXD 
)
protected

Convert a one dimensional index into a 2D/3D index with the given number of points per direction (index of last dimension varies the fastest)

Definition at line 1023 of file samplingdata.h.

1023 {
1024 const MInt noPoints2D = nPoints[0] * nPoints[1];
1025 const MInt maxNoPoints = (nDim == 2) ? noPoints2D : noPoints2D * nPoints[2];
1026 if(index < 0 || index >= maxNoPoints) {
1027 TERMM(1, "invalid index: " + std::to_string(index));
1028 }
1029
1030 // Last index (varies fastest)
1031 indexXD[nDim - 1] = index % nPoints[nDim - 1];
1032 // First/second index in 2D/3D
1033 indexXD[nDim - 2] = ((index - indexXD[nDim - 1]) / nPoints[nDim - 1]) % nPoints[nDim - 2];
1034 IF_CONSTEXPR(nDim == 3) {
1035 // First index in 3D
1036 indexXD[0] = (index - indexXD[1] * nPoints[1] - indexXD[2]) / (nPoints[2] * nPoints[1]);
1037 }
1038}
void indexXD(const MInt index, const MInt *const nPoints, MInt *indexXD)
Convert 1D index into 2D/3D index.
int32_t MInt
Definition: maiatypes.h:62
IdType index(const FloatType *const x, const IdType level)
Return Hilbert index for given location and level in 2D or 3D.
Definition: hilbert.h:165

◆ init() [1/2]

template<MInt nDim, class SolverType >
void SamplingData< nDim, SolverType >::init

Definition at line 571 of file samplingdata.h.

571 {
572 if(!m_enabled || !solver().isActive()) {
573 return;
574 }
575
576 for(MUint i = 0; i < m_timeSeries.size(); i++) {
577 init(m_timeSeries[i]);
578 }
579}
std::vector< SamplingDataSeries > m_timeSeries
Holds all properties and buffers for each input file.
Definition: samplingdata.h:138
uint32_t MUint
Definition: maiatypes.h:63

◆ init() [2/2]

template<MInt nDim, class SolverType >
void SamplingData< nDim, SolverType >::init ( SamplingDataSeries timeSeries)
protected

Definition at line 590 of file samplingdata.h.

590 {
591 using namespace maia;
592 using namespace std;
593
594
595 // save points and corresponding data in this container for sorting
596 // tuple contains following data in that order:
597 // coordinates of point, element id of point, line index in input file
598 std::vector<std::tuple<std::array<MFloat, nDim>, MInt, MInt>> localTmpPoints;
599
600 m_log << "Solver #" << solverId() << ": ";
601 // Check for an input file
602 if(timeSeries.m_inputFileName != "") {
603 m_log << "Loading points for " << getBaseName() << " data class...";
604
605 std::vector<MFloat> tmpCoordinates{};
606
607 // read in file on root using the I/O method of the derived class
608 if(isMpiRoot()) {
609 timeSeries.m_noPoints = loadInputFile(timeSeries.m_inputFileName, timeSeries.m_fileNo, tmpCoordinates);
610 }
611
612 MPI_Bcast(&timeSeries.m_noPoints, 1, type_traits<MInt>::mpiType(), 0, mpiComm(), AT_, "timeSeries.m_noPoints");
613
614 if(timeSeries.m_noPoints <= 0) {
615 TERMM(1, "ERROR: no sampling points found for input file '" + timeSeries.m_inputFileName + "'");
616 m_log << "ERROR: no sampling points found for input file '" << timeSeries.m_inputFileName << "'" << std::endl;
617 return;
618 }
619
620 ScratchSpace<MFloat> coordinatesScratch(timeSeries.m_noPoints * nDim, FUN_, "coordinatesScratch");
621 if(isMpiRoot()) {
622 copy(tmpCoordinates.begin(), tmpCoordinates.end(), coordinatesScratch.begin());
623 }
624 MPI_Bcast(&coordinatesScratch[0], timeSeries.m_noPoints * nDim, type_traits<MFloat>::mpiType(), 0, mpiComm(), AT_,
625 "coordinatesScratch[0]");
626
627 localTmpPoints.resize(timeSeries.m_noPoints);
628
629 MFloatTensor tmpCoordinatesTensor(&coordinatesScratch[0], timeSeries.m_noPoints, nDim);
630 std::array<MFloat, nDim> curCoordinates{};
631 MInt curElementId = -1;
632 for(MInt i = 0; i < timeSeries.m_noPoints; i++) {
633 for(MInt j = 0; j < nDim; j++) {
634 curCoordinates[j] = tmpCoordinatesTensor(i, j);
635 }
636 // check if the point is relevant to this rank, each point should be globally unique, i.e.,
637 // appear only once
638 curElementId = solver().getIdAtPoint(&curCoordinates[0], true);
639
640 if(curElementId != -1) {
641 localTmpPoints[timeSeries.m_noLocalPoints] = make_tuple(curCoordinates, curElementId, i);
642 timeSeries.m_noLocalPoints++;
643
644 // Precompute interpolation information if possible/required
645 solver().initInterpolationForCell(curElementId);
646 }
647 }
648
649 // sanity check if each point ended up on exactly one rank:
650 ScratchSpace<MInt> loadedPointsVector(timeSeries.m_noPoints, FUN_, "loadedPointsVector");
651 loadedPointsVector.fill(0);
652 for(MInt i = 0; i < timeSeries.m_noLocalPoints; i++) {
653 loadedPointsVector[get<2>(localTmpPoints[i])]++;
654 }
655
656 if(isMpiRoot()) {
657 MPI_Reduce(MPI_IN_PLACE, &loadedPointsVector[0], loadedPointsVector.size(), type_traits<MInt>::mpiType(), MPI_SUM,
658 0, mpiComm(), AT_, "MPI_IN_PLACE", "loadedPointsVector[0]");
659 for(MUint i = 0; i < loadedPointsVector.size(); i++) {
660 if(loadedPointsVector[i] != 1) {
661 std::ostringstream err;
662 err << "Point at line " << i + 1 << " of file " // start line count at one
663 << timeSeries.m_inputFileName << " was loaded " << loadedPointsVector[i] << " times. Aborting."
664 << std::endl;
665 TERMM(1, err.str());
666 }
667 }
668 } else {
669 MPI_Reduce(&loadedPointsVector[0], nullptr, loadedPointsVector.size(), type_traits<MInt>::mpiType(), MPI_SUM, 0,
670 mpiComm(), AT_, "loadedPointsVector[0]", "nullptr");
671 }
672 } else if(timeSeries.m_generatePoints) {
673 m_log << "Generating points for " << getBaseName() << " data class...";
674 // Generate points based on given properties
675 // Get number of points to generate
676 const MInt noPoints = noSamplingPoints(timeSeries.m_fileNo);
677 timeSeries.m_noPoints = noPoints;
678
679 std::array<MFloat, nDim> coordinates{};
680 MLong checkSum = 0;
681
682 for(MInt i = 0; i < noPoints; i++) {
683 // Get the coordinates for this sampling point id
684 getSamplingPoint(timeSeries.m_fileNo, i, &coordinates[0]);
685
686 // Check if point is relevant for local rank
687 const MInt curElementId = solver().getIdAtPoint(&coordinates[0], true);
688 if(curElementId != -1) {
689 localTmpPoints.push_back(make_tuple(coordinates, curElementId, i));
690 timeSeries.m_noLocalPoints++;
691 checkSum += (i + 1);
692
693 // Precompute interpolation information if possible/required
694 solver().initInterpolationForCell(curElementId);
695 }
696 }
697
698 MInt globalNoPoints = timeSeries.m_noLocalPoints;
699 MPI_Allreduce(MPI_IN_PLACE, &globalNoPoints, 1, type_traits<MInt>::mpiType(), MPI_SUM, mpiComm(), AT_,
700 "MPI_IN_PLACE", "globalNoPoints");
701 if(globalNoPoints != noPoints) {
702 TERMM(1, "Global number of points does not match " + std::to_string(globalNoPoints)
703 + " != " + std::to_string(noPoints));
704 }
705
706 // Use Gauss sum equation to check if all points ended up on exactly one rank
707 // Note: this is a heuristic check but it should be very unlikely to get a false positive; this
708 // will work up to 2 billion sampling points
709 MPI_Allreduce(MPI_IN_PLACE, &checkSum, 1, type_traits<MLong>::mpiType(), MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE",
710 "checkSum");
711 const MLong noPointsTmp = noPoints;
712 if(2 * checkSum != (noPointsTmp * noPointsTmp + noPointsTmp)) {
713 TERMM(1, "Incorrect check sum for " + std::to_string(noPoints) + " points: " + std::to_string(checkSum));
714 }
715 } else {
716 m_log << "Warning: no sampling data input file specified and generation of points disabled." << std::endl;
717 return;
718 }
719
720 // Create a new MPI Communicator
721 ScratchSpace<MInt> pointDataScratch(globalNoDomains(), FUN_, "pointDataScratch");
722 std::fill_n(&pointDataScratch[0], globalNoDomains(), -1);
723
724 // Get Rank if points are relevant
725 MInt rank = -1;
726 if(timeSeries.m_noLocalPoints > 0) {
727 MPI_Comm_rank(mpiComm(), &rank);
728 }
729
730 // Combine all ranks to get relevant ranks
731 MPI_Allgather(&rank, 1, type_traits<MInt>::mpiType(), &pointDataScratch[0], 1, type_traits<MInt>::mpiType(),
732 mpiComm(), AT_, "rank", "pointDataScratch[0]");
733
734 // Check for relevant ranks and save them to create the new communicator
735 const MInt noPdDomains =
736 count_if(pointDataScratch.begin(), pointDataScratch.end(), [](const MInt a) { return a != -1; });
737 MIntScratchSpace pdDomains(noPdDomains, AT_, "pdDomains");
738 MInt position = 0;
739 for(MUint i = 0; i < pointDataScratch.size(); i++) {
740 if(pointDataScratch[i] != -1) {
741 pdDomains[position] = pointDataScratch[i];
742 position++;
743 }
744 }
745
746 // Create new point data mpi group
747 MPI_Group globalGroup, localGroup;
748 MPI_Comm_group(mpiComm(), &globalGroup, AT_, "globalGroup");
749 MPI_Group_incl(globalGroup, noPdDomains, &pdDomains[0], &localGroup, AT_);
750
751 // Create new communicator and clean up
752 MPI_Comm_create(mpiComm(), localGroup, &timeSeries.m_mpiComm, AT_, "timeSeries.m_mpiComm");
753 MPI_Group_free(&globalGroup, AT_);
754 MPI_Group_free(&localGroup, AT_);
755
756 // Set root for new communicator
757 if(timeSeries.m_noLocalPoints > 0) {
758 MInt subRank = -1;
759 MPI_Comm_rank(timeSeries.m_mpiComm, &subRank);
760 if(subRank == 0) {
761 timeSeries.m_isMpiRoot = true;
762 }
763 }
764
765
766 // sort points by global id
767 stable_sort(localTmpPoints.begin(),
768 localTmpPoints.begin() + timeSeries.m_noLocalPoints,
769 // Read all input files and save all points into one array
770 [this](const std::tuple<std::array<MFloat, nDim>, MInt, MInt>& a,
771 const std::tuple<std::array<MFloat, nDim>, MInt, MInt>& b) {
772 return solver().grid().tree().globalId(solver().getCellIdByIndex(get<1>(a)))
773 < solver().grid().tree().globalId(solver().getCellIdByIndex(get<1>(b)));
774 });
775
776 // split localTmpPoints for it to be easier to handle later on
777 if(timeSeries.m_noLocalPoints > 0) {
778 timeSeries.m_coordinates.resize(timeSeries.m_noLocalPoints * nDim);
779 MFloatTensor coordinatesTensor(&timeSeries.m_coordinates[0], timeSeries.m_noLocalPoints, nDim);
780 timeSeries.m_elementIds.resize(timeSeries.m_noLocalPoints);
781 timeSeries.m_sortIndex.resize(timeSeries.m_noLocalPoints);
782 for(MInt i = 0; i < timeSeries.m_noLocalPoints; i++) {
783 for(MInt j = 0; j < nDim; j++) {
784 coordinatesTensor(i, j) = get<0>(localTmpPoints[i])[j];
785 }
786 timeSeries.m_elementIds[i] = get<1>(localTmpPoints[i]);
787 timeSeries.m_sortIndex[i] = get<2>(localTmpPoints[i]);
788 }
789 }
790
791 // Save sampling point coordinates if they were not loaded from a file
792 if(timeSeries.m_inputFileName == "" && timeSeries.m_noLocalPoints > 0) {
794 }
795
796 // Allocate memory to save/buffer point data inbetween writes
797 timeSeries.m_maxNoSample = std::max(1, timeSeries.m_writeInterval / timeSeries.m_sampleInterval);
798 if(timeSeries.m_noLocalPoints > 0) {
799 // Note: +1 for initial data file containing also timestep 0
800 timeSeries.m_stateBuffer.resize(timeSeries.m_noLocalPoints * (timeSeries.m_maxNoSample + 1) * noVars());
801 }
802
803 // Allocate storage for the time step count and the simulation time
804 if(timeSeries.m_isMpiRoot) {
805 timeSeries.m_timeStepBuffer.resize(timeSeries.m_maxNoSample + 1);
806 timeSeries.m_timeBuffer.resize(timeSeries.m_maxNoSample + 1);
807 } else {
808 timeSeries.m_timeStepBuffer.resize(1);
809 timeSeries.m_timeBuffer.resize(1);
810 }
811
812 m_log << " done" << std::endl << "#" << timeSeries.m_fileNo;
813 if(timeSeries.m_inputFileName != "") {
814 m_log << " Loaded " << timeSeries.m_noPoints << " points from " << timeSeries.m_inputFileName << " for "
815 << getBaseName() << " sampling feature successfully." << std::endl;
816 } else if(timeSeries.m_generatePoints) {
817 m_log << " Generated " << timeSeries.m_noPoints << " points for " << getBaseName()
818 << " sampling feature successfully." << std::endl;
819 }
820 m_log << "sampleInterval = " << timeSeries.m_sampleInterval << "; startTimeStep = " << timeSeries.m_startTimeStep
821 << "; endTimeStep = " << timeSeries.m_endTimeStep << "; writeInterval = " << timeSeries.m_writeInterval
822 << std::endl;
823}
MBool isMpiRoot() const
Definition: samplingdata.h:119
virtual MInt loadInputFile(const MString NotUsed(inputFileName), const MInt NotUsed(fileNo), std::vector< MFloat > &NotUsed(coordinates))
Definition: samplingdata.h:46
MPI_Comm mpiComm() const
Definition: samplingdata.h:120
virtual void getSamplingPoint(const MInt NotUsed(fileNo), const MInt NotUsed(pointId), MFloat *const NotUsed(coordinates))
Return the coordinates of the sampling point with the given id when generating points.
Definition: samplingdata.h:103
virtual MInt noSamplingPoints(const MInt NotUsed(fileNo))
Return the number of sampling points which are generated by the derived class (no input file)
Definition: samplingdata.h:97
MInt noVars() const
Return total number of sampling variables.
Definition: samplingdata.h:124
void saveSamplingPointCoordinates(SamplingDataSeries &timeSeries)
Save point coordinates of time series.
std::vector< MInt > m_elementIds
Definition: samplingdata.h:311
std::vector< MFloat > m_coordinates
Definition: samplingdata.h:309
const MInt m_writeInterval
Definition: samplingdata.h:299
const MInt m_fileNo
Definition: samplingdata.h:335
std::vector< MInt > m_timeStepBuffer
Definition: samplingdata.h:319
std::vector< MFloat > m_stateBuffer
Definition: samplingdata.h:327
const MInt m_startTimeStep
Definition: samplingdata.h:301
std::vector< MInt > m_sortIndex
Definition: samplingdata.h:313
const MInt m_sampleInterval
Definition: samplingdata.h:297
const MInt m_endTimeStep
Definition: samplingdata.h:303
const MString m_inputFileName
Definition: samplingdata.h:293
const MBool m_generatePoints
Definition: samplingdata.h:295
std::vector< MFloat > m_timeBuffer
Definition: samplingdata.h:321
This class is a ScratchSpace.
Definition: scratch.h:758
MInt globalNoDomains()
Return global number of domains.
InfoOutFile m_log
int64_t MLong
Definition: maiatypes.h:64
int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newcomm, const MString &name, const MString &varname)
same as MPI_Comm_create, but updates the number of MPI communicators
int MPI_Group_incl(MPI_Group group, int n, const int ranks[], MPI_Group *newgroup, const MString &name)
same as MPI_Group_incl
int MPI_Comm_group(MPI_Comm comm, MPI_Group *group, const MString &name, const MString &varname)
same as MPI_Comm_group
int MPI_Reduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Reduce
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Bcast
int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgather
int MPI_Group_free(MPI_Group *group, const MString &name)
same as MPI_Group_free
Namespace for auxiliary functions/classes.
Definition: contexttypes.h:19

◆ isMpiRoot()

template<MInt nDim, class SolverType >
MBool SamplingData< nDim, SolverType >::isMpiRoot ( ) const
inlineprotected

Definition at line 119 of file samplingdata.h.

119{ return m_solver.domainId() == 0; }

◆ loadInputFile()

template<MInt nDim, class SolverType >
virtual MInt SamplingData< nDim, SolverType >::loadInputFile ( const MString   NotUsedinputFileName,
const MInt   NotUsedfileNo,
std::vector< MFloat > &  NotUsedcoordinates 
)
inlinevirtual

*** Virtual functions that need to be implemented in derived class *** Load input file and determine number of sampling points and point coordinates

Definition at line 46 of file samplingdata.h.

48 {
49 TERMM(1, "ERROR: not implemented in base class");
50 return -1;
51 }

◆ mpiComm()

template<MInt nDim, class SolverType >
MPI_Comm SamplingData< nDim, SolverType >::mpiComm ( ) const
inlineprotected

Definition at line 120 of file samplingdata.h.

120{ return m_solver.mpiComm(); }

◆ noSamplingPoints()

template<MInt nDim, class SolverType >
virtual MInt SamplingData< nDim, SolverType >::noSamplingPoints ( const MInt   NotUsedfileNo)
inlineprotectedvirtual

Definition at line 97 of file samplingdata.h.

97 {
98 TERMM(1, "Not implemented in derived class!");
99 return -1;
100 }

◆ noVars()

template<MInt nDim, class SolverType >
MInt SamplingData< nDim, SolverType >::noVars ( ) const
inlineprotected

Definition at line 124 of file samplingdata.h.

124{ return std::accumulate(m_noSolverSamplingVars.begin(), m_noSolverSamplingVars.end(), 0); }
std::vector< MInt > m_noSolverSamplingVars
Number of variables for each sampling variable.
Definition: samplingdata.h:143

◆ readAdditionalProperties()

template<MInt nDim, class SolverType >
virtual void SamplingData< nDim, SolverType >::readAdditionalProperties ( const MInt   NotUsedfileNo)
inlineprotectedvirtual

Definition at line 115 of file samplingdata.h.

115{};

◆ save() [1/2]

template<MInt nDim, class SolverType >
void SamplingData< nDim, SolverType >::save ( MBool  finalTimestep)

Definition at line 832 of file samplingdata.h.

832 {
833 if(!m_enabled) {
834 return;
835 }
836
837 for(MUint i = 0; i < m_timeSeries.size(); i++) {
838 save(m_timeSeries[i], finalTimeStep);
839 }
840}
void save(MBool finalTimestep)
Definition: samplingdata.h:832

◆ save() [2/2]

template<MInt nDim, class SolverType >
void SamplingData< nDim, SolverType >::save ( SamplingDataSeries timeSeries,
MBool  finalTimeStep 
)
protected
Author
Fabian Klemp f.kle.nosp@m.mp@a.nosp@m.ia.rw.nosp@m.th-a.nosp@m.achen.nosp@m..de
Date
2016-07-22

Assumes beeing called every timestep including timeStep 0 and the finalTimeStep.

Definition at line 855 of file samplingdata.h.

855 {
856 using namespace std;
857
858 // Check if time step inverval is reached
859 if(solver().getCurrentTimeStep() < timeSeries.m_startTimeStep
860 || solver().getCurrentTimeStep() > timeSeries.m_endTimeStep) {
861 return;
862 }
863
864 // Check for correct timestep interval
865 if(!(solver().getCurrentTimeStep() % timeSeries.m_sampleInterval == 0 || finalTimeStep)) {
866 return;
867 }
868
869 // Compute sampling variables and exchange data for interpolation (if not done already in this time step)
870 solver().calcSamplingVariables(m_solverSamplingVarIds, true);
871
872 // Check if rank belongs to an sampling data MPI communicator
873 // Note: sampling variables are computed by all ranks as the interpolation might require halo cell
874 // values
875 if(timeSeries.m_noLocalPoints < 1 || timeSeries.m_noPoints == 0) {
876 return;
877 }
878
879 // buffer time and timestep
880 if(timeSeries.m_isMpiRoot) {
881 timeSeries.m_timeStepBuffer[timeSeries.m_sampleIndex] = solver().getCurrentTimeStep();
882 timeSeries.m_timeBuffer[timeSeries.m_sampleIndex] = solver().time();
883 }
884
885 // buffer point data states
886 MFloatTensor coordinatesTensorBuf(&timeSeries.m_coordinates[0], timeSeries.m_noLocalPoints, nDim);
887 MFloatTensor stateTensorBuf(&timeSeries.m_stateBuffer[0], timeSeries.m_noLocalPoints, timeSeries.m_maxNoSample + 1,
888 noVars());
889
890 MBool interpolate = m_interpolatePointData;
891 for(MInt i = 0; i < timeSeries.m_noLocalPoints; i++) {
892 MInt offset = 0;
893 for(MUint var = 0; var < m_solverSamplingVarIds.size(); var++) {
894 solver().calcSamplingVarAtPoint(&coordinatesTensorBuf(i, 0), timeSeries.m_elementIds[i],
895 m_solverSamplingVarIds[var], &stateTensorBuf(i, timeSeries.m_sampleIndex, offset),
896 interpolate);
897 offset += m_noSolverSamplingVars[var];
898 }
899 }
900
901 // increment sample index
902 timeSeries.m_sampleIndex++;
903
904 MBool isFirstDataFile = false;
905 // Note: first data file for simulation starting at timestep 0 contains one value more than
906 // all other data files; at a restart the restart time step is not considered here even if it is
907 // equal to m_startTimeStep
908 // if (solver().getCurrentTimeStep() >= timeSeries.m_startTimeStep
909 // && solver().getCurrentTimeStep() <= timeSeries.m_startTimeStep + timeSeries.m_writeInterval) {
910 if(solver().getCurrentTimeStep() >= 0 && solver().getCurrentTimeStep() <= timeSeries.m_writeInterval) {
911 isFirstDataFile = true;
912 }
913
914 const MBool isRestartStep =
915 (solver().restartInterval() > 0 && solver().getCurrentTimeStep() % solver().restartInterval() == 0);
916 const MBool isFirstSample = (isFirstDataFile && timeSeries.m_sampleIndex == 1);
917 const MBool writeAtRestartStep = (isRestartStep && !isFirstSample);
918 const MBool writeFirstDataFile = (timeSeries.m_sampleIndex > timeSeries.m_maxNoSample && isFirstDataFile);
919 const MBool writeDataFile = ((timeSeries.m_sampleIndex + 1 > timeSeries.m_maxNoSample) && !isFirstDataFile);
920
921 // write file if it's time to do so otherwise return
922 if(!(writeDataFile || finalTimeStep || writeAtRestartStep || writeFirstDataFile)) {
923 return;
924 }
925
926 using namespace maia::parallel_io;
927
928 // calculate how many samples have been recorded in total
929 MInt sampleCount = (solver().getCurrentTimeStep() / timeSeries.m_sampleInterval) + 1; // also saving at timeStep 0
930
931 // Correct number of samples if finalTimeStep is not in the writeInterval
932 if(finalTimeStep && !(solver().getCurrentTimeStep() % timeSeries.m_writeInterval == 0)) {
933 sampleCount++;
934 }
935
936 MInt fileNo = 0;
937 if(!finalTimeStep || (solver().getCurrentTimeStep() % timeSeries.m_writeInterval == 0)) {
938 fileNo = (sampleCount - 1) / (timeSeries.m_writeInterval / timeSeries.m_sampleInterval);
939 } else {
940 fileNo = ceil((static_cast<MFloat>(sampleCount - 1)
941 / static_cast<MFloat>(timeSeries.m_writeInterval / timeSeries.m_sampleInterval)));
942 }
943
944 // Output file name
945 std::ostringstream fileName;
946 MString baseFileName = getFileBaseName();
947 fileName << solver().outputDir() << baseFileName << std::to_string(timeSeries.m_fileNo) << "_" << setw(8)
948 << setfill('0') << fileNo << ParallelIo::fileExt();
949
950 ParallelIo file(fileName.str(), PIO_REPLACE, timeSeries.m_mpiComm);
951
952 file.defineArray(PIO_INT, "timeStep", timeSeries.m_sampleIndex);
953 file.defineArray(PIO_FLOAT, "time", timeSeries.m_sampleIndex);
954 file.defineArray(PIO_INT, "sortIndex", timeSeries.m_noPoints);
955
956 file.setAttribute("si[i] = index in input", "description", "sortIndex");
957
958 ParallelIo::size_type dimSizes[] = {timeSeries.m_noPoints, timeSeries.m_sampleIndex, noVars()};
959 file.defineArray(PIO_FLOAT, "pointStates", 3, &dimSizes[0]);
960
961 std::ostringstream descPs;
962 // Please be aware that these attributes get parsed in the corresponding post
963 // processing script. So if you change them please check if it breaks the
964 // script
965 file.setAttribute(descPs.str(), "description", "pointStates");
966 file.setAttribute("point index", "dim_0", "pointStates");
967 file.setAttribute("sample index", "dim_1", "pointStates");
968 file.setAttribute("var index", "dim_2", "pointStates");
969 file.setAttribute(timeSeries.m_inputFileName, "inputFileName", "pointStates");
970
971 MInt varOffset = 0;
972 for(MUint var = 0; var < m_solverSamplingVarIds.size(); var++) {
973 for(MInt i = 0; i < m_noSolverSamplingVars[var]; i++) {
974 file.setAttribute(m_solverSamplingVarNames[var][i], "var_" + std::to_string(varOffset + i), "pointStates");
975 }
976 varOffset += m_noSolverSamplingVars[var];
977 }
978
979 // ensure data is consecutive in memory
980 if(timeSeries.m_sampleIndex < timeSeries.m_maxNoSample + 1) {
981 MFloatTensor stateTensor(&timeSeries.m_stateBuffer[0], timeSeries.m_noLocalPoints, timeSeries.m_maxNoSample + 1,
982 noVars());
983 MFloatMatrix finalStateTensor(&timeSeries.m_stateBuffer[0], timeSeries.m_noLocalPoints, timeSeries.m_sampleIndex,
984 noVars());
985 for(MInt i = 0; i < timeSeries.m_noLocalPoints; i++) {
986 for(MInt j = 0; j < timeSeries.m_sampleIndex; j++) {
987 for(MInt k = 0; k < noVars(); k++) {
988 finalStateTensor(i, j, k) = stateTensor(i, j, k);
989 }
990 }
991 }
992 }
993
994 // root writes timestep and time data
995 if(timeSeries.m_isMpiRoot) {
996 file.setOffset(timeSeries.m_sampleIndex, 0);
997 } else {
998 file.setOffset(0, 0);
999 }
1000 file.writeArray(&timeSeries.m_timeStepBuffer[0], "timeStep");
1001 file.writeArray(&timeSeries.m_timeBuffer[0], "time");
1002
1003 // calculate offset for reverse index and pointStates
1004 ParallelIo::size_type offset, totalCount;
1005 file.calcOffset(timeSeries.m_noLocalPoints, &offset, &totalCount, timeSeries.m_mpiComm);
1006
1007 // write sort index
1008 file.setOffset(timeSeries.m_noLocalPoints, offset);
1009 file.writeArray(&timeSeries.m_sortIndex[0], "sortIndex");
1010
1011 // write state data to file
1012 file.setOffset(timeSeries.m_noLocalPoints, offset, 3);
1013 file.writeArray(&timeSeries.m_stateBuffer[0], "pointStates");
1014
1015 // reset sample index
1016 timeSeries.m_sampleIndex = 0;
1017}
std::vector< MInt > m_solverSamplingVarIds
List of sampling variables.
Definition: samplingdata.h:141
MBool m_interpolatePointData
Definition: samplingdata.h:135
MString getFileBaseName() const
Return base name of files for used sampling feature.
Definition: samplingdata.h:126
std::vector< std::vector< MString > > m_solverSamplingVarNames
List of variable names for each sampling variable.
Definition: samplingdata.h:145
double MFloat
Definition: maiatypes.h:52
bool MBool
Definition: maiatypes.h:58
PARALLELIO_DEFAULT_BACKEND ParallelIo
Definition: parallelio.h:292

◆ saveSamplingPointCoordinates()

template<MInt nDim, class SolverType >
void SamplingData< nDim, SolverType >::saveSamplingPointCoordinates ( SamplingDataSeries timeSeries)
protected

Save the point coordinates of the given time series, needs to be called only by the active communicator

Definition at line 1044 of file samplingdata.h.

1044 {
1045 TRACE();
1046 using namespace maia::parallel_io;
1047
1048 std::ostringstream fileName;
1049 fileName << solver().outputDir() << getFileBaseName() << "coordinates_" << timeSeries.m_fileNo
1050 << ParallelIo::fileExt();
1051 ParallelIo file(fileName.str(), PIO_REPLACE, timeSeries.m_mpiComm);
1052
1053 // Add spatial dimensions
1054 file.setAttribute(nDim, "nDim");
1055
1056 file.defineArray(PIO_INT, "sortIndex", timeSeries.m_noPoints);
1057 file.setAttribute("si[i] = index in input", "description", "sortIndex");
1058
1059 ParallelIo::size_type dimSizes[] = {timeSeries.m_noPoints, nDim};
1060 file.defineArray(PIO_FLOAT, "coordinates", 2, &dimSizes[0]);
1061
1062 ParallelIo::size_type offset, totalCount;
1063 file.calcOffset(timeSeries.m_noLocalPoints, &offset, &totalCount, timeSeries.m_mpiComm);
1064
1065 // Write sort index
1066 file.setOffset(timeSeries.m_noLocalPoints, offset);
1067 file.writeArray(&timeSeries.m_sortIndex[0], "sortIndex");
1068
1069 // Write coordinates
1070 file.setOffset(timeSeries.m_noLocalPoints, offset, 2);
1071 file.writeArray(&timeSeries.m_coordinates[0], "coordinates");
1072}

◆ setInputOutputProperties()

template<MInt nDim, class SolverType >
void SamplingData< nDim, SolverType >::setInputOutputProperties ( )

◆ solver() [1/2]

template<MInt nDim, class SolverType >
SolverType & SamplingData< nDim, SolverType >::solver ( )
inlineprotected

Definition at line 129 of file samplingdata.h.

129{ return m_solver; }

◆ solver() [2/2]

template<MInt nDim, class SolverType >
const SolverType & SamplingData< nDim, SolverType >::solver ( ) const
inlineprotected

Definition at line 130 of file samplingdata.h.

130{ return m_solver; }

◆ solverId()

template<MInt nDim, class SolverType >
MInt SamplingData< nDim, SolverType >::solverId ( ) const
inlineprotected

Definition at line 118 of file samplingdata.h.

118{ return m_solver.solverId(); }

Member Data Documentation

◆ m_enabled

template<MInt nDim, class SolverType >
MBool SamplingData< nDim, SolverType >::m_enabled = false
protected

Definition at line 134 of file samplingdata.h.

◆ m_interpolatePointData

template<MInt nDim, class SolverType >
MBool SamplingData< nDim, SolverType >::m_interpolatePointData
protected

Definition at line 135 of file samplingdata.h.

◆ m_noSolverSamplingVars

template<MInt nDim, class SolverType >
std::vector<MInt> SamplingData< nDim, SolverType >::m_noSolverSamplingVars {}
protected

Definition at line 143 of file samplingdata.h.

◆ m_solver

template<MInt nDim, class SolverType >
SolverType& SamplingData< nDim, SolverType >::m_solver
private

Definition at line 150 of file samplingdata.h.

◆ m_solverSamplingVarIds

template<MInt nDim, class SolverType >
std::vector<MInt> SamplingData< nDim, SolverType >::m_solverSamplingVarIds {}
protected

Definition at line 141 of file samplingdata.h.

◆ m_solverSamplingVarNames

template<MInt nDim, class SolverType >
std::vector<std::vector<MString> > SamplingData< nDim, SolverType >::m_solverSamplingVarNames {}
protected

Definition at line 145 of file samplingdata.h.

◆ m_timeSeries

template<MInt nDim, class SolverType >
std::vector<SamplingDataSeries> SamplingData< nDim, SolverType >::m_timeSeries {}
protected

Definition at line 138 of file samplingdata.h.


The documentation for this class was generated from the following file: