Files
LBPM/common/Domain.h

351 lines
11 KiB
C
Raw Normal View History

#ifndef Domain_INC
#define Domain_INC
2018-05-05 22:52:55 -04:00
2013-09-03 14:46:57 -04:00
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <vector>
2013-09-03 14:46:57 -04:00
#include <math.h>
#include <time.h>
2018-05-15 10:01:14 -04:00
#include <exception>
#include <stdexcept>
#include "common/Array.h"
2014-02-21 15:08:49 -05:00
#include "common/Utilities.h"
2020-01-28 08:51:32 -05:00
#include "common/MPI.h"
#include "common/Communication.h"
2018-05-15 10:01:14 -04:00
#include "common/Database.h"
2021-10-03 19:56:26 -04:00
/**
* @file Domain.h
* \brief Parallel Domain data structures and helper functions
*/
/**
* \class Box
*
* @details
* information about a box
*/
2018-05-15 15:14:13 -04:00
class Box {
public:
int ifirst[3];
int ilast[3];
};
2021-10-03 19:56:26 -04:00
class Patch;
2018-05-15 15:14:13 -04:00
2021-10-03 19:56:26 -04:00
/**
* \class Domain
*
* @details
* the Domain class includes basic information to distribution 3D image data to multiple processes using MPI.
* A regular domain decomposision is performed, with each MPI process getting a [Nx,Ny,Nz] sub-domain.
* 8-bit image labels are retained internally.
* The domain class resides on the CPU and provides utilities to support CPU-based analysis.
* GPU-based data structures should be constructed separately but may utilize information that the Domain class provides.
*/
2018-05-15 15:14:13 -04:00
2018-05-15 10:01:14 -04:00
class Domain{
public:
2021-10-03 19:56:26 -04:00
/**
* \brief Constructor
* @param db input database
* @param Communicator MPI communicator
*/
2020-01-28 08:51:32 -05:00
Domain( std::shared_ptr<Database> db, const Utilities::MPI& Communicator);
2021-10-03 19:56:26 -04:00
/**
* \brief Obsolete constructor
*/
2018-05-15 10:01:14 -04:00
Domain( int nx, int ny, int nz, int rnk, int npx, int npy, int npz,
double lx, double ly, double lz, int BC);
2021-10-03 19:56:26 -04:00
/**
* \brief Empty constructor
*/
2018-05-15 10:01:14 -04:00
Domain() = delete;
2021-10-03 19:56:26 -04:00
/**
* \brief Copy constructor
*/
2018-05-15 10:01:14 -04:00
Domain( const Domain& ) = delete;
2021-10-03 19:56:26 -04:00
/**
* \brief Assignment operator
*/
2018-05-15 10:01:14 -04:00
Domain& operator=( const Domain& ) = delete;
2021-10-03 19:56:26 -04:00
/**
* \brief Destructor
*/
2018-05-16 14:00:35 -04:00
~Domain();
2021-10-03 19:56:26 -04:00
/**
* \brief Get the database
*/
2018-05-15 10:01:14 -04:00
inline std::shared_ptr<const Database> getDatabase() const { return d_db; }
2021-10-03 19:56:26 -04:00
/**
* \brief Get the domain box
*/
2018-05-15 15:14:13 -04:00
inline const Box& getBox() const { return d_box; }
2021-10-03 19:56:26 -04:00
/**
* \brief Get local patch
*/
2018-05-15 15:14:13 -04:00
inline const Patch& getLocalPatch() const { return *d_localPatch; }
2021-10-03 19:56:26 -04:00
/**
* \brief Get all patches
*/
2018-05-15 15:14:13 -04:00
inline const std::vector<Patch>& getAllPatch() const { return d_patches; }
2018-05-15 10:01:14 -04:00
private:
2021-10-03 19:56:26 -04:00
/**
* \brief initialize from database
*/
2018-05-15 10:01:14 -04:00
void initialize( std::shared_ptr<Database> db );
std::shared_ptr<Database> d_db;
2018-05-15 15:14:13 -04:00
Box d_box;
Patch *d_localPatch;
std::vector<Patch> d_patches;
2018-05-15 10:01:14 -04:00
2018-05-15 15:14:13 -04:00
public: // Public variables (need to create accessors instead)
std::shared_ptr<Database> database;
2019-04-19 10:48:18 -04:00
double Lx,Ly,Lz,Volume,voxel_length;
2018-05-16 14:00:35 -04:00
int Nx,Ny,Nz,N;
int inlet_layers_x, inlet_layers_y, inlet_layers_z;
2019-03-26 15:42:26 -04:00
int outlet_layers_x, outlet_layers_y, outlet_layers_z;
int inlet_layers_phase; //as usual: 1->n, 2->w
int outlet_layers_phase;
2019-04-04 20:22:48 -04:00
double porosity;
2018-05-16 14:00:35 -04:00
RankInfoStruct rank_info;
2020-01-28 08:51:32 -05:00
Utilities::MPI Comm; // MPI Communicator for this domain
2018-05-16 14:00:35 -04:00
int BoundaryCondition;
//**********************************
// MPI ranks for all 18 neighbors
//**********************************
2021-10-03 19:56:26 -04:00
/**
* \brief Compute the porosity based on the current domain id file
*/
2019-04-04 20:22:48 -04:00
inline double Porosity() const { return porosity; }
2018-05-16 14:00:35 -04:00
inline int iproc() const { return rank_info.ix; }
inline int jproc() const { return rank_info.jy; }
inline int kproc() const { return rank_info.kz; }
inline int nprocx() const { return rank_info.nx; }
inline int nprocy() const { return rank_info.ny; }
inline int nprocz() const { return rank_info.nz; }
inline int rank() const { return rank_info.rank[1][1][1]; }
inline int rank_X() const { return rank_info.rank[2][1][1]; }
inline int rank_x() const { return rank_info.rank[0][1][1]; }
inline int rank_Y() const { return rank_info.rank[1][2][1]; }
inline int rank_y() const { return rank_info.rank[1][0][1]; }
inline int rank_Z() const { return rank_info.rank[1][1][2]; }
inline int rank_z() const { return rank_info.rank[1][1][0]; }
inline int rank_XY() const { return rank_info.rank[2][2][1]; }
inline int rank_xy() const { return rank_info.rank[0][0][1]; }
inline int rank_Xy() const { return rank_info.rank[2][0][1]; }
inline int rank_xY() const { return rank_info.rank[0][2][1]; }
inline int rank_XZ() const { return rank_info.rank[2][1][2]; }
inline int rank_xz() const { return rank_info.rank[0][1][0]; }
inline int rank_Xz() const { return rank_info.rank[2][1][0]; }
inline int rank_xZ() const { return rank_info.rank[0][1][2]; }
inline int rank_YZ() const { return rank_info.rank[1][2][2]; }
inline int rank_yz() const { return rank_info.rank[1][0][0]; }
inline int rank_Yz() const { return rank_info.rank[1][2][0]; }
inline int rank_yZ() const { return rank_info.rank[1][0][2]; }
//**********************************
//......................................................................................
// Get the actual D3Q19 communication counts (based on location of solid phase)
// Discrete velocity set symmetry implies the sendcount = recvcount
//......................................................................................
inline int recvCount( const char* dir ) const { return getRecvList( dir ).size(); }
inline int sendCount( const char* dir ) const { return getSendList( dir ).size(); }
inline const int* recvList( const char* dir ) const { return getRecvList( dir ).data(); }
inline const int* sendList( const char* dir ) const { return getSendList( dir ).data(); }
2018-05-16 14:00:35 -04:00
//......................................................................................
// Solid indicator function
std::vector<signed char> id;
2018-05-16 14:00:35 -04:00
2021-10-03 19:56:26 -04:00
/**
* \brief Read domain IDs from file
*/
2018-05-18 20:53:49 -04:00
void ReadIDs();
2021-10-03 19:56:26 -04:00
/**
* \brief Compute the porosity
*/
void ComputePorosity();
2021-10-03 19:56:26 -04:00
/**
* \brief Read image and perform domain decomposition
* @param filename - name of file to read IDs
*/
2020-01-22 12:01:29 -05:00
void Decomp( const std::string& filename );
2021-10-03 19:56:26 -04:00
/**
* \brief Perform a halo exchange using MPI
* @param Mesh - array data that holds scalar values
*/
2018-05-16 14:00:35 -04:00
void CommunicateMeshHalo(DoubleArray &Mesh);
2021-10-03 19:56:26 -04:00
/**
* \brief Initialize communication data structures within Domain object.
* This routine needs to be called before the communication functionality will work
*/
2018-05-18 20:53:49 -04:00
void CommInit();
2021-10-03 19:56:26 -04:00
/**
* \brief Count number of pore nodes (labels > 1)
*/
2018-05-19 06:39:44 -04:00
int PoreCount();
2021-10-03 19:56:26 -04:00
/**
* \brief Read array data from a file and distribute to local arrays for each MPI process
* @param Filename - name of the file to read the data
* @param Datatype - data type to use
* @param UserData - Array to store the values that are read
*/
void ReadFromFile(const std::string& Filename,const std::string& Datatype, double *UserData);
2021-10-03 19:56:26 -04:00
/**
* \brief Aggregate labels from all MPI processes and write to a file
* @param filename - name of the file to write
*/
2020-01-22 12:01:29 -05:00
void AggregateLabels( const std::string& filename );
2021-10-03 19:56:26 -04:00
/**
* \brief Aggregate user provided array from all MPI processes and write to a single file
* @param filename - name of the file to write
* @param UserData - array data to aggregate and write
*/
void AggregateLabels( const std::string& filename, DoubleArray &UserData );
2018-05-15 15:14:13 -04:00
private:
2018-06-30 15:37:10 -04:00
2021-10-03 19:56:26 -04:00
/**
* \brief Pack halo data for 8-bit integer
* @param list - list of values in the halo
* @param count - count of values in the halo
* @param sendbuf - memory buffer to use to pack values for MPI
* @param ID - 8-bit values on mesh [Nx, Ny, Nz]
*/
2019-03-29 06:46:48 -04:00
void PackID(int *list, int count, signed char *sendbuf, signed char *ID);
2021-10-03 19:56:26 -04:00
/**
* \brief Unpack halo data for 8-bit integer
* @param list - list of values in the halo
* @param count - count of values in the halo
* @param recvbuf - memory buffer containing values recieved by MPI
* @param ID - 8-bit values on mesh [Nx, Ny, Nz]
*/
2019-03-29 06:46:48 -04:00
void UnpackID(int *list, int count, signed char *recvbuf, signed char *ID);
2018-06-30 15:37:10 -04:00
2018-05-18 20:53:49 -04:00
//......................................................................................
MPI_Request req1[18], req2[18];
2018-05-16 14:00:35 -04:00
//......................................................................................
std::vector<int> sendList_x, sendList_y, sendList_z, sendList_X, sendList_Y, sendList_Z;
std::vector<int> sendList_xy, sendList_yz, sendList_xz, sendList_Xy, sendList_Yz, sendList_xZ;
std::vector<int> sendList_xY, sendList_yZ, sendList_Xz, sendList_XY, sendList_YZ, sendList_XZ;
//......................................................................................
std::vector<int> recvList_x, recvList_y, recvList_z, recvList_X, recvList_Y, recvList_Z;
std::vector<int> recvList_xy, recvList_yz, recvList_xz, recvList_Xy, recvList_Yz, recvList_xZ;
std::vector<int> recvList_xY, recvList_yZ, recvList_Xz, recvList_XY, recvList_YZ, recvList_XZ;
2018-05-16 14:00:35 -04:00
//......................................................................................
const std::vector<int>& getRecvList( const char* dir ) const;
const std::vector<int>& getSendList( const char* dir ) const;
2018-05-15 15:14:13 -04:00
};
2014-06-26 13:57:27 -04:00
2021-10-03 19:56:26 -04:00
template<class TYPE> class PatchData;
enum class DataLocation { CPU, DEVICE };
/**
* \class Patch
*
* @details
* store patch data
*/
class Patch {
public:
//! Empty constructor
Patch() = delete;
//! Copy constructor
Patch( const Patch& ) = delete;
//! Assignment operator
Patch& operator=( const Patch& ) = delete;
//! Return the box for the patch
inline const Box& getBox() const { return d_box; }
//! Create patch data
template<class TYPE>
std::shared_ptr<PatchData<TYPE>> createPatchData( DataLocation location ) const;
private:
Box d_box;
int d_owner;
Domain *d_domain;
};
2014-06-26 13:57:27 -04:00
2018-05-15 15:14:13 -04:00
// Class to hold data on a patch
template<class TYPE>
class PatchData {
public:
2014-06-26 13:57:27 -04:00
2018-05-15 15:14:13 -04:00
//! Get the raw data pointer
TYPE* data() { return d_data; }
2014-06-26 13:57:27 -04:00
2018-05-15 15:14:13 -04:00
//! Get the raw data pointer
const TYPE* data() const { return d_data; }
//! Get the patch
const Patch& getPatch() const { return *d_patch; }
2014-06-26 13:57:27 -04:00
2018-05-15 15:14:13 -04:00
//! Start communication
void beginCommunication();
//! End communication
void endCommunication();
//! Access ghost values
TYPE operator()( int, int, int ) const;
//! Copy data from another PatchData
void copy( const PatchData& rhs );
private:
DataLocation d_location;
const Patch *d_patch;
TYPE *d_data;
TYPE *d_gcw;
2018-06-30 15:37:10 -04:00
2014-06-25 16:35:53 -04:00
};
2020-01-22 12:01:29 -05:00
void WriteCheckpoint(const char *FILENAME, const double *cDen, const double *cfq, size_t Np);
2018-05-15 10:01:14 -04:00
2020-01-22 12:01:29 -05:00
void ReadCheckpoint(char *FILENAME, double *cDen, double *cfq, size_t Np);
2018-05-15 10:01:14 -04:00
2020-01-22 12:01:29 -05:00
void ReadBinaryFile(char *FILENAME, double *Data, size_t N);
2018-05-15 15:14:13 -04:00
#endif