merge dox
This commit is contained in:
commit
3cf0bc67d8
@ -1,5 +1,6 @@
|
|||||||
#include "analysis/ElectroChemistry.h"
|
#include "analysis/ElectroChemistry.h"
|
||||||
|
|
||||||
|
|
||||||
ElectroChemistryAnalyzer::ElectroChemistryAnalyzer(std::shared_ptr <Domain> dm):
|
ElectroChemistryAnalyzer::ElectroChemistryAnalyzer(std::shared_ptr <Domain> dm):
|
||||||
Dm(dm)
|
Dm(dm)
|
||||||
{
|
{
|
||||||
|
@ -12,15 +12,74 @@
|
|||||||
|
|
||||||
#include "models/ColorModel.h"
|
#include "models/ColorModel.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class FlowAdaptor
|
||||||
|
*
|
||||||
|
* @brief
|
||||||
|
* The FlowAdaptor class operates on a lattice Boltzmann model to alter the flow conditions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
class FlowAdaptor{
|
class FlowAdaptor{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Create a flow adaptor to operate on the LB model
|
||||||
|
* @param M ScaLBL_ColorModel
|
||||||
|
*/
|
||||||
FlowAdaptor(ScaLBL_ColorModel &M);
|
FlowAdaptor(ScaLBL_ColorModel &M);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Destructor
|
||||||
|
*/
|
||||||
~FlowAdaptor();
|
~FlowAdaptor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Fast-forward interface motion
|
||||||
|
* \details Accelerate the movement of interfaces based on the time derivative
|
||||||
|
* Optional keys to control behavior can be specified in the input database:
|
||||||
|
* move_interface_cutoff -- identifies the diffuse interface region
|
||||||
|
* move_interface_factor -- determines how much to ``fast forward"
|
||||||
|
* @param M ScaLBL_ColorModel
|
||||||
|
*/
|
||||||
double MoveInterface(ScaLBL_ColorModel &M);
|
double MoveInterface(ScaLBL_ColorModel &M);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Image re-initialization
|
||||||
|
* \details Re-initialize LB simulation from image data
|
||||||
|
* @param M ScaLBL_ColorModel
|
||||||
|
* @param Filename name of input file to be used to read image
|
||||||
|
*/
|
||||||
double ImageInit(ScaLBL_ColorModel &M, std::string Filename);
|
double ImageInit(ScaLBL_ColorModel &M, std::string Filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \details Update volume fraction based on morphological algorithm. Dilation / erosion algorithm will be applied to
|
||||||
|
* grow / shrink the phase regions
|
||||||
|
* @param M ScaLBL_ColorModel
|
||||||
|
* @param delta_volume target change in volume fraction
|
||||||
|
*/
|
||||||
double ShellAggregation(ScaLBL_ColorModel &M, const double delta_volume);
|
double ShellAggregation(ScaLBL_ColorModel &M, const double delta_volume);
|
||||||
double UpdateFractionalFlow(ScaLBL_ColorModel &M);
|
|
||||||
|
/**
|
||||||
|
* \details Update fractional flow condition. Mass will be preferentially added or removed from
|
||||||
|
* phase regions based on where flow is occurring
|
||||||
|
* @param M ScaLBL_ColorModel
|
||||||
|
*/ double UpdateFractionalFlow(ScaLBL_ColorModel &M);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief image re-initialization
|
||||||
|
* \details Re-initialize LB simulation from image data
|
||||||
|
* @param M ScaLBL_ColorModel
|
||||||
|
* @param seed_water_in_oil controls amount of mass to randomly seed into fluids
|
||||||
|
*/
|
||||||
double SeedPhaseField(ScaLBL_ColorModel &M, const double seed_water_in_oil);
|
double SeedPhaseField(ScaLBL_ColorModel &M, const double seed_water_in_oil);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Re-initialize LB simulation
|
||||||
|
* @param M ScaLBL_ColorModel
|
||||||
|
*/
|
||||||
void Flatten(ScaLBL_ColorModel &M);
|
void Flatten(ScaLBL_ColorModel &M);
|
||||||
DoubleArray phi;
|
DoubleArray phi;
|
||||||
DoubleArray phi_t;
|
DoubleArray phi_t;
|
||||||
|
@ -19,6 +19,14 @@
|
|||||||
#include "IO/Writer.h"
|
#include "IO/Writer.h"
|
||||||
#include "models/FreeLeeModel.h"
|
#include "models/FreeLeeModel.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class FreeEnergyAnalyzer
|
||||||
|
*
|
||||||
|
* @brief
|
||||||
|
* The FreeEnergyAnalyzer class is constructed to analyze the LBPM free energy model for liquid-gas systems
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
class FreeEnergyAnalyzer{
|
class FreeEnergyAnalyzer{
|
||||||
public:
|
public:
|
||||||
std::shared_ptr <Domain> Dm;
|
std::shared_ptr <Domain> Dm;
|
||||||
|
@ -15,6 +15,14 @@
|
|||||||
#include "IO/Reader.h"
|
#include "IO/Reader.h"
|
||||||
#include "IO/Writer.h"
|
#include "IO/Writer.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class GreyPhase
|
||||||
|
*
|
||||||
|
* @brief
|
||||||
|
* The GreyPhase class tracks pressure, mass and momentum within a grey phase
|
||||||
|
*
|
||||||
|
*/
|
||||||
class GreyPhase{
|
class GreyPhase{
|
||||||
public:
|
public:
|
||||||
double p;
|
double p;
|
||||||
@ -26,6 +34,14 @@ class GreyPhase{
|
|||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class GreyPhaseAnalysis
|
||||||
|
*
|
||||||
|
* @brief
|
||||||
|
* The GreyPhaseAnalysis class is constructed to analyze the LBPM greyscale model
|
||||||
|
*
|
||||||
|
*/
|
||||||
class GreyPhaseAnalysis{
|
class GreyPhaseAnalysis{
|
||||||
public:
|
public:
|
||||||
std::shared_ptr <Domain> Dm;
|
std::shared_ptr <Domain> Dm;
|
||||||
|
@ -66,7 +66,7 @@ void Minkowski::ComputeScalar(const DoubleArray& Field, const double isovalue)
|
|||||||
{
|
{
|
||||||
PROFILE_START("ComputeScalar");
|
PROFILE_START("ComputeScalar");
|
||||||
Xi = Ji = Ai = 0.0;
|
Xi = Ji = Ai = 0.0;
|
||||||
DECL object;
|
DCEL object;
|
||||||
int e1,e2,e3;
|
int e1,e2,e3;
|
||||||
double s,s1,s2,s3;
|
double s,s1,s2,s3;
|
||||||
double a1,a2,a3;
|
double a1,a2,a3;
|
||||||
|
@ -34,6 +34,14 @@
|
|||||||
#include "IO/Reader.h"
|
#include "IO/Reader.h"
|
||||||
#include "IO/Writer.h"
|
#include "IO/Writer.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class Minkowski
|
||||||
|
*
|
||||||
|
* @brief
|
||||||
|
* The Minkowski class is constructed to analyze the geometric properties of structures based on the Minkowski functionals
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
class Minkowski{
|
class Minkowski{
|
||||||
//...........................................................................
|
//...........................................................................
|
||||||
@ -61,6 +69,7 @@ public:
|
|||||||
int n_connected_components;
|
int n_connected_components;
|
||||||
//...........................................................................
|
//...........................................................................
|
||||||
int Nx,Ny,Nz;
|
int Nx,Ny,Nz;
|
||||||
|
|
||||||
double V(){
|
double V(){
|
||||||
return Vi;
|
return Vi;
|
||||||
}
|
}
|
||||||
@ -75,15 +84,56 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//..........................................................................
|
//..........................................................................
|
||||||
|
/**
|
||||||
|
* \brief Null constructor
|
||||||
|
*/
|
||||||
Minkowski(){};//NULL CONSTRUCTOR
|
Minkowski(){};//NULL CONSTRUCTOR
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Constructor based on an existing Domain
|
||||||
|
* @param Dm - Domain structure
|
||||||
|
*/
|
||||||
Minkowski(std::shared_ptr <Domain> Dm);
|
Minkowski(std::shared_ptr <Domain> Dm);
|
||||||
~Minkowski();
|
~Minkowski();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compute scalar minkowski functionals
|
||||||
|
* step 1. compute the distance to an object
|
||||||
|
* step 2. construct dcel to represent the isosurface
|
||||||
|
* step 3. compute the scalar Minkowski functionals
|
||||||
|
* THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects
|
||||||
|
* 0 - labels the object
|
||||||
|
* 1 - labels everything else
|
||||||
|
*/
|
||||||
void MeasureObject();
|
void MeasureObject();
|
||||||
|
|
||||||
void MeasureObject(double factor, const DoubleArray &Phi);
|
void MeasureObject(double factor, const DoubleArray &Phi);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \details Compute scalar minkowski functionals for connected part of a structure
|
||||||
|
* step 1. compute connected components and extract largest region by volume
|
||||||
|
* step 2. compute the distance to the connected part of the structure
|
||||||
|
* step 3. construct dcel to represent the isosurface
|
||||||
|
* step 4. compute the scalar Minkowski functionals
|
||||||
|
* THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects
|
||||||
|
* 0 - labels the object
|
||||||
|
* 1 - labels everything else
|
||||||
|
*/
|
||||||
int MeasureConnectedPathway();
|
int MeasureConnectedPathway();
|
||||||
|
|
||||||
int MeasureConnectedPathway(double factor, const DoubleArray &Phi);
|
int MeasureConnectedPathway(double factor, const DoubleArray &Phi);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compute scalar minkowski functionals
|
||||||
|
* \details Construct an isosurface and return the geometric invariants based on the triangulated list
|
||||||
|
* @param isovalue - threshold value to use to determine iso-surface
|
||||||
|
* @param Field - DoubleArray containing the field to threshold
|
||||||
|
*/
|
||||||
void ComputeScalar(const DoubleArray& Field, const double isovalue);
|
void ComputeScalar(const DoubleArray& Field, const double isovalue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief print the scalar invariants
|
||||||
|
*/
|
||||||
void PrintAll();
|
void PrintAll();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
#include "analysis/dcel.h"
|
#include "analysis/dcel.h"
|
||||||
|
|
||||||
DECL::DECL(){
|
DCEL::DCEL(){
|
||||||
}
|
}
|
||||||
|
|
||||||
DECL::~DECL(){
|
DCEL::~DCEL(){
|
||||||
TriangleCount=0;
|
TriangleCount=0;
|
||||||
VertexCount=0;
|
VertexCount=0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int DECL::Face(int index){
|
int DCEL::Face(int index){
|
||||||
return FaceData[index];
|
return FaceData[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void DECL::Write(){
|
void DCEL::Write(){
|
||||||
int e1,e2,e3;
|
int e1,e2,e3;
|
||||||
FILE *TRIANGLES;
|
FILE *TRIANGLES;
|
||||||
TRIANGLES = fopen("triangles.stl","w");
|
TRIANGLES = fopen("triangles.stl","w");
|
||||||
@ -32,7 +32,7 @@ void DECL::Write(){
|
|||||||
fclose(TRIANGLES);
|
fclose(TRIANGLES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DECL::LocalIsosurface(const DoubleArray& A, double value, const int i, const int j, const int k){
|
void DCEL::LocalIsosurface(const DoubleArray& A, double value, const int i, const int j, const int k){
|
||||||
Point P,Q;
|
Point P,Q;
|
||||||
Point PlaceHolder;
|
Point PlaceHolder;
|
||||||
Point C0,C1,C2,C3,C4,C5,C6,C7;
|
Point C0,C1,C2,C3,C4,C5,C6,C7;
|
||||||
@ -174,7 +174,7 @@ void DECL::LocalIsosurface(const DoubleArray& A, double value, const int i, cons
|
|||||||
}
|
}
|
||||||
int nTris = TriangleCount;
|
int nTris = TriangleCount;
|
||||||
|
|
||||||
// Now add the local values to the DECL data structure
|
// Now add the local values to the DCEL data structure
|
||||||
if (nTris>0){
|
if (nTris>0){
|
||||||
FaceData.resize(TriangleCount);
|
FaceData.resize(TriangleCount);
|
||||||
//printf("Construct halfedge structure... \n");
|
//printf("Construct halfedge structure... \n");
|
||||||
@ -250,7 +250,7 @@ void DECL::LocalIsosurface(const DoubleArray& A, double value, const int i, cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Point DECL::TriNormal(int edge)
|
Point DCEL::TriNormal(int edge)
|
||||||
{
|
{
|
||||||
Point P,Q,R;
|
Point P,Q,R;
|
||||||
Point U,V,W;
|
Point U,V,W;
|
||||||
@ -294,7 +294,7 @@ Point DECL::TriNormal(int edge)
|
|||||||
return W;
|
return W;
|
||||||
}
|
}
|
||||||
|
|
||||||
double DECL::EdgeAngle(int edge)
|
double DCEL::EdgeAngle(int edge)
|
||||||
{
|
{
|
||||||
double angle;
|
double angle;
|
||||||
double dotprod;
|
double dotprod;
|
||||||
@ -369,7 +369,7 @@ double DECL::EdgeAngle(int edge)
|
|||||||
|
|
||||||
void iso_surface(const Array<double>&Field, const double isovalue)
|
void iso_surface(const Array<double>&Field, const double isovalue)
|
||||||
{
|
{
|
||||||
DECL object;
|
DCEL object;
|
||||||
int e1,e2,e3;
|
int e1,e2,e3;
|
||||||
FILE *TRIANGLES;
|
FILE *TRIANGLES;
|
||||||
TRIANGLES = fopen("isosurface.stl","w");
|
TRIANGLES = fopen("isosurface.stl","w");
|
||||||
|
@ -4,8 +4,9 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "analysis/pmmc.h"
|
#include "analysis/pmmc.h"
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Doubly-connected edge list (DECL)
|
* \class Vertex
|
||||||
|
* @brief store vertex for DCEL data structure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Vertex structure
|
// Vertex structure
|
||||||
@ -34,8 +35,10 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Halfedge structure
|
/**
|
||||||
// Face
|
* \class Halfedge
|
||||||
|
* @brief store half edge for DCEL data structure
|
||||||
|
*/
|
||||||
class Halfedge{
|
class Halfedge{
|
||||||
public:
|
public:
|
||||||
Halfedge() = default;
|
Halfedge() = default;
|
||||||
@ -60,11 +63,14 @@ private:
|
|||||||
std::vector<std::array<int,6>> d_data;
|
std::vector<std::array<int,6>> d_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// DECL
|
/**
|
||||||
class DECL{
|
* \class DCEL
|
||||||
|
* @details doubly connected edge list data structure
|
||||||
|
*/
|
||||||
|
class DCEL{
|
||||||
public:
|
public:
|
||||||
DECL();
|
DCEL();
|
||||||
~DECL();
|
~DCEL();
|
||||||
|
|
||||||
int face();
|
int face();
|
||||||
Vertex vertex;
|
Vertex vertex;
|
||||||
|
353
common/ScaLBL.h
353
common/ScaLBL.h
@ -14,8 +14,8 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
/* ScaLBL.h
|
/** @file ScaLBL.h */
|
||||||
* Header file for Scalable Lattice Boltzmann Library
|
/* \detail Header file for Scalable Lattice Boltzmann Library
|
||||||
* Separate implementations for GPU and CPU must both follow the conventions defined in this header
|
* Separate implementations for GPU and CPU must both follow the conventions defined in this header
|
||||||
* This libarry contains the essential components of the LBM
|
* This libarry contains the essential components of the LBM
|
||||||
* - streaming implementations
|
* - streaming implementations
|
||||||
@ -27,48 +27,194 @@
|
|||||||
#define ScalLBL_H
|
#define ScalLBL_H
|
||||||
#include "common/Domain.h"
|
#include "common/Domain.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set compute device
|
||||||
|
* @param rank rank of MPI process
|
||||||
|
*/
|
||||||
extern "C" int ScaLBL_SetDevice(int rank);
|
extern "C" int ScaLBL_SetDevice(int rank);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Allocate memory
|
||||||
|
* @param address memory address
|
||||||
|
* @param size size in bytes
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_AllocateDeviceMemory(void** address, size_t size);
|
extern "C" void ScaLBL_AllocateDeviceMemory(void** address, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Free memory
|
||||||
|
* @param pointer pointer to memory to free
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_FreeDeviceMemory(void* pointer);
|
extern "C" void ScaLBL_FreeDeviceMemory(void* pointer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Copy memory from host to device
|
||||||
|
* \detail Device memory should be close to simulation (based on NUMA cost)
|
||||||
|
* Host memory may be a shared memory region (with possibly higher NUMA cost for simulation)
|
||||||
|
* Analysis routine should minimize NUMA for host memory (based on process placement)
|
||||||
|
* @param dest memory location to copy to
|
||||||
|
* @param source memory region to copy from
|
||||||
|
* @param size size of the region to copy in bytes
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_CopyToDevice(void* dest, const void* source, size_t size);
|
extern "C" void ScaLBL_CopyToDevice(void* dest, const void* source, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Copy memory from device to host
|
||||||
|
* \detail Device memory should be close to simulation (based on NUMA cost)
|
||||||
|
* Host memory may be a shared memory region (with possibly higher NUMA cost for simulation)
|
||||||
|
* Analysis routine should minimize NUMA for host memory (based on process placement)
|
||||||
|
* @param dest memory location to copy to
|
||||||
|
* @param source memory region to copy from
|
||||||
|
* @param size size of the region to copy in bytes
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_CopyToHost(void* dest, const void* source, size_t size);
|
extern "C" void ScaLBL_CopyToHost(void* dest, const void* source, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
=* \brief Allocate zero copy memory buffer (i.e. shared memory)
|
||||||
|
* @param address memory address
|
||||||
|
* @param size size in bytes
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_AllocateZeroCopy(void** address, size_t size);
|
extern "C" void ScaLBL_AllocateZeroCopy(void** address, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Copy memory from host to zero copy buffer
|
||||||
|
* \detail Device memory should be close to simulation (based on NUMA cost)
|
||||||
|
* Host memory may be a shared memory region (with possibly higher NUMA cost for simulation)
|
||||||
|
* Analysis routine should minimize NUMA for host memory (based on process placement)
|
||||||
|
* @param dest memory location to copy to
|
||||||
|
* @param source memory region to copy from
|
||||||
|
* @param size size of the region to copy in bytes
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_CopyToZeroCopy(void* dest, const void* source, size_t size);
|
extern "C" void ScaLBL_CopyToZeroCopy(void* dest, const void* source, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Device barrier routine
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_DeviceBarrier();
|
extern "C" void ScaLBL_DeviceBarrier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Pack D3Q19 distributions for communication
|
||||||
|
* @param q - index for distribution based on D3Q19 discrete velocity structure
|
||||||
|
* @param list - list of distributions to communicate
|
||||||
|
* @param start - index to start parsing the list
|
||||||
|
* @param count - number of values to pack
|
||||||
|
* @param sendbuf - memory buffer to hold values that will be sent
|
||||||
|
* @param dist - memory buffer to hold the distributions
|
||||||
|
* @param N - size of the distributions (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q19_Pack(int q, int *list, int start, int count, double *sendbuf, double *dist, int N);
|
extern "C" void ScaLBL_D3Q19_Pack(int q, int *list, int start, int count, double *sendbuf, double *dist, int N);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Unpack D3Q19 distributions after communication
|
||||||
|
* @param q - index for distribution based on D3Q19 discrete velocity structure
|
||||||
|
* @param list - list of distributions to communicate
|
||||||
|
* @param start - index to start parsing the list
|
||||||
|
* @param count - number of values to unppack
|
||||||
|
* @param revbuf - memory buffer where recieved values have been stored
|
||||||
|
* @param dist - memory buffer to hold the distributions
|
||||||
|
* @param N - size of the distributions (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q19_Unpack(int q, int *list, int start, int count, double *recvbuf, double *dist, int N);
|
extern "C" void ScaLBL_D3Q19_Unpack(int q, int *list, int start, int count, double *recvbuf, double *dist, int N);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Unpack D3Q7 distributions after communication
|
||||||
|
* @param q - index for distribution based on D3Q19 discrete velocity structure
|
||||||
|
* @param list - list of distributions to communicate
|
||||||
|
* @param start - index to start parsing the list
|
||||||
|
* @param count - number of values to unppack
|
||||||
|
* @param revbuf - memory buffer where recieved values have been stored
|
||||||
|
* @param dist - memory buffer to hold the distributions
|
||||||
|
* @param N - size of the distributions (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q7_Unpack(int q, int *list, int start, int count, double *recvbuf, double *dist, int N);
|
extern "C" void ScaLBL_D3Q7_Unpack(int q, int *list, int start, int count, double *recvbuf, double *dist, int N);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Pack halo for scalar field to be prepare for communication
|
||||||
|
* @param list - list of distributions to communicate
|
||||||
|
* @param count - number of values to ppack
|
||||||
|
* @param sendbuf - memory buffer to pack values into
|
||||||
|
* @param Data - scalar field
|
||||||
|
* @param N - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_Scalar_Pack(int *list, int count, double *sendbuf, double *Data, int N);
|
extern "C" void ScaLBL_Scalar_Pack(int *list, int count, double *sendbuf, double *Data, int N);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Pack halo for scalar field to be prepare for communication
|
||||||
|
* @param list - list of distributions to communicate
|
||||||
|
* @param count - number of values to unppack
|
||||||
|
* @param recvbuf - memory buffer where recieved values have been stored
|
||||||
|
* @param Data - scalar field
|
||||||
|
* @param N - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_Scalar_Unpack(int *list, int count, double *recvbuf, double *Data, int N);
|
extern "C" void ScaLBL_Scalar_Unpack(int *list, int count, double *recvbuf, double *Data, int N);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Unpack values and compute Shan-Chen type of gradient
|
||||||
|
* @param weight - weight value for gradient sum
|
||||||
|
* @param Cqx - contribution to x-part of gradient
|
||||||
|
* @param Cqy - contribution to y-part of gradient
|
||||||
|
* @param Cqz - contribution to z-part of gradient
|
||||||
|
* @param list - list of distributions to communicate
|
||||||
|
* @param start - location to start reading the list
|
||||||
|
* @param count - number of values to unppack
|
||||||
|
* @param recvbuf - memory buffer where recieved values have been stored
|
||||||
|
* @param phi - scalar field
|
||||||
|
* @param grad - gradient
|
||||||
|
* @param N - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_Gradient_Unpack(double weight, double Cqx, double Cqy, double Cqz,
|
extern "C" void ScaLBL_Gradient_Unpack(double weight, double Cqx, double Cqy, double Cqz,
|
||||||
int *list, int start, int count, double *recvbuf, double *phi, double *grad, int N);
|
int *list, int start, int count, double *recvbuf, double *phi, double *grad, int N);
|
||||||
|
|
||||||
extern "C" void ScaLBL_PackDenD3Q7(int *list, int count, double *sendbuf, int number, double *Data, int N);
|
|
||||||
|
|
||||||
extern "C" void ScaLBL_UnpackDenD3Q7(int *list, int count, double *recvbuf, int number, double *Data, int N);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize D3Q19 distributions
|
||||||
|
* @param Dist - D3Q19 distributions
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q19_Init(double *Dist, int Np);
|
extern "C" void ScaLBL_D3Q19_Init(double *Dist, int Np);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compute momentum from D3Q19 distribution
|
||||||
|
* @param Dist - D3Q19 distributions
|
||||||
|
* @param vel - memory buffer to store the momentum that is computed
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q19_Momentum(double *dist, double *vel, int Np);
|
extern "C" void ScaLBL_D3Q19_Momentum(double *dist, double *vel, int Np);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compute pressure from D3Q19 distribution
|
||||||
|
* @param Dist - D3Q19 distributions
|
||||||
|
* @param press - memory buffer to store the pressure field that is computed
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q19_Pressure(double *dist, double *press, int Np);
|
extern "C" void ScaLBL_D3Q19_Pressure(double *dist, double *press, int Np);
|
||||||
|
|
||||||
// BGK MODEL
|
// BGK MODEL
|
||||||
|
/**
|
||||||
|
* \brief BGK collision based on AA even access pattern for D3Q19
|
||||||
|
* @param dist - D3Q19 distributions
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
* @param rlx - relaxation parameter
|
||||||
|
* @param Fx - force in x direction
|
||||||
|
* @param Fy - force in y direction
|
||||||
|
* @param Fz - force in z direction
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q19_AAeven_BGK(double *dist, int start, int finish, int Np, double rlx, double Fx, double Fy, double Fz);
|
extern "C" void ScaLBL_D3Q19_AAeven_BGK(double *dist, int start, int finish, int Np, double rlx, double Fx, double Fy, double Fz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief BGK collision based on AA odd access pattern for D3Q19
|
||||||
|
* @param neighborList - neighbors based on D3Q19 lattice structure
|
||||||
|
* @param dist - D3Q19 distributions
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
* @param rlx - relaxation parameter
|
||||||
|
* @param Fx - force in x direction
|
||||||
|
* @param Fy - force in y direction
|
||||||
|
* @param Fz - force in z direction
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q19_AAodd_BGK(int *neighborList, double *dist, int start, int finish, int Np, double rlx, double Fx, double Fy, double Fz);
|
extern "C" void ScaLBL_D3Q19_AAodd_BGK(int *neighborList, double *dist, int start, int finish, int Np, double rlx, double Fx, double Fy, double Fz);
|
||||||
|
|
||||||
// GREYSCALE MODEL (Single-component)
|
// GREYSCALE MODEL (Single-component)
|
||||||
@ -136,26 +282,73 @@ extern "C" void ScaLBL_D3Q7_Ion_ChargeDensity(double *Den, double *ChargeDensity
|
|||||||
|
|
||||||
// LBM Poisson solver
|
// LBM Poisson solver
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Poisson-Boltzmann collision based on AA odd access pattern for D3Q19
|
||||||
|
* @param neighborList - neighbors based on D3Q19 lattice structure
|
||||||
|
* @param Map - mapping between sparse and dense representations
|
||||||
|
* @param dist - D3Q7 distributions
|
||||||
|
* @param Den_charge - charge density
|
||||||
|
* @param Psi -
|
||||||
|
* @param ElectricField - electric field
|
||||||
|
* @param tau - relaxation time
|
||||||
|
* @param epsilon_LB -
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q7_AAodd_Poisson(int *neighborList,int *Map, double *dist, double *Den_charge, double *Psi, double *ElectricField, double tau, double epsilon_LB,
|
extern "C" void ScaLBL_D3Q7_AAodd_Poisson(int *neighborList,int *Map, double *dist, double *Den_charge, double *Psi, double *ElectricField, double tau, double epsilon_LB,
|
||||||
int start, int finish, int Np);
|
int start, int finish, int Np);
|
||||||
|
|
||||||
extern "C" void ScaLBL_D3Q7_AAeven_Poisson(int *Map, double *dist, double *Den_charge, double *Psi, double *ElectricField, double tau, double epsilon_LB,
|
/**
|
||||||
int start, int finish, int Np);
|
* \brief Poisson-Boltzmann collision based on AA even access pattern for D3Q7
|
||||||
|
* @param Map - mapping between sparse and dense representations
|
||||||
|
* @param dist - D3Q7 distributions
|
||||||
|
* @param Den_charge - charge density
|
||||||
|
* @param Psi -
|
||||||
|
* @param ElectricField - electric field
|
||||||
|
* @param tau - relaxation time
|
||||||
|
* @param epsilon_LB -
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
|
extern "C" void ScaLBL_D3Q7_AAeven_Poisson(int *Map, double *dist, double *Den_charge, double *Psi, double *ElectricField, double tau,
|
||||||
|
double epsilon_LB, int start, int finish, int Np);
|
||||||
|
/**
|
||||||
|
* \brief Poisson-Boltzmann solver / solve electric potential based on AA odd access pattern for D3Q7
|
||||||
|
* @param neighborList - neighbors based on D3Q19 lattice structure
|
||||||
|
* @param Map - mapping between sparse and dense representations
|
||||||
|
* @param dist - D3Q7 distributions
|
||||||
|
* @param Psi -
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q7_AAodd_Poisson_ElectricPotential(int *neighborList,int *Map, double *dist, double *Psi, int start, int finish, int Np);
|
extern "C" void ScaLBL_D3Q7_AAodd_Poisson_ElectricPotential(int *neighborList,int *Map, double *dist, double *Psi, int start, int finish, int Np);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Poisson-Boltzmann solver / solve electric potential based on AA odd access pattern for D3Q7
|
||||||
|
* @param Map - mapping between sparse and dense representations
|
||||||
|
* @param dist - D3Q7 distributions
|
||||||
|
* @param Psi -
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q7_AAeven_Poisson_ElectricPotential(int *Map, double *dist, double *Psi, int start, int finish, int Np);
|
extern "C" void ScaLBL_D3Q7_AAeven_Poisson_ElectricPotential(int *Map, double *dist, double *Psi, int start, int finish, int Np);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize Poisson-Boltzmann solver
|
||||||
|
* @param Map - mapping between sparse and dense representations
|
||||||
|
* @param dist - D3Q7 distributions
|
||||||
|
* @param Psi -
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q7_Poisson_Init(int *Map, double *dist, double *Psi, int start, int finish, int Np);
|
extern "C" void ScaLBL_D3Q7_Poisson_Init(int *Map, double *dist, double *Psi, int start, int finish, int Np);
|
||||||
|
|
||||||
//extern "C" void ScaLBL_D3Q7_PoissonResidualError(int *neighborList, int *Map, double *ResidualError, double *Psi, double *Den_charge, double epsilon_LB,int strideY, int strideZ,int start, int finish);
|
|
||||||
|
|
||||||
//maybe deprecated
|
|
||||||
//extern "C" void ScaLBL_D3Q7_Poisson_ElectricField(int *neighborList, int *Map, signed char *ID, double *Psi, double *ElectricField, int SolidBC,
|
|
||||||
// int strideY, int strideZ,int start, int finish, int Np);
|
|
||||||
|
|
||||||
// LBM Stokes Model (adapted from MRT model)
|
// LBM Stokes Model (adapted from MRT model)
|
||||||
|
|
||||||
extern "C" void ScaLBL_D3Q19_AAeven_StokesMRT(double *dist, double *Velocity, double *ChargeDensity, double *ElectricField, double rlx_setA, double rlx_setB,
|
extern "C" void ScaLBL_D3Q19_AAeven_StokesMRT(double *dist, double *Velocity, double *ChargeDensity, double *ElectricField, double rlx_setA, double rlx_setB,
|
||||||
double Gx, double Gy, double Gz,double rho0, double den_scale, double h, double time_conv, int start, int finish, int Np);
|
double Gx, double Gy, double Gz,double rho0, double den_scale, double h, double time_conv, int start, int finish, int Np);
|
||||||
|
|
||||||
@ -165,27 +358,138 @@ extern "C" void ScaLBL_D3Q19_AAodd_StokesMRT(int *neighborList, double *dist, do
|
|||||||
extern "C" void ScaLBL_PhaseField_InitFromRestart(double *Den, double *Aq, double *Bq, int start, int finish, int Np);
|
extern "C" void ScaLBL_PhaseField_InitFromRestart(double *Den, double *Aq, double *Bq, int start, int finish, int Np);
|
||||||
|
|
||||||
// MRT MODEL
|
// MRT MODEL
|
||||||
|
/**
|
||||||
|
* \brief MRT collision based on AA even access pattern for D3Q19
|
||||||
|
* @param dist - D3Q19 distributions
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
* @param rlx_setA - relaxation parameter for viscous modes
|
||||||
|
* @param rlx_setB - relaxation parameter for non-viscous modes
|
||||||
|
* @param Fx - force in x direction
|
||||||
|
* @param Fy - force in y direction
|
||||||
|
* @param Fz - force in z direction
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q19_AAeven_MRT(double *dist, int start, int finish, int Np, double rlx_setA, double rlx_setB, double Fx,
|
extern "C" void ScaLBL_D3Q19_AAeven_MRT(double *dist, int start, int finish, int Np, double rlx_setA, double rlx_setB, double Fx,
|
||||||
double Fy, double Fz);
|
double Fy, double Fz);
|
||||||
|
|
||||||
extern "C" void ScaLBL_D3Q19_AAodd_MRT(int *d_neighborList, double *dist, int start, int finish, int Np,
|
/**
|
||||||
|
* \brief MRT collision based on AA even access pattern for D3Q19
|
||||||
|
* @param neighborList - index of neighbors based on D3Q19 lattice structure
|
||||||
|
* @param dist - D3Q19 distributions
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
* @param rlx_setA - relaxation parameter for viscous modes
|
||||||
|
* @param rlx_setB - relaxation parameter for non-viscous modes
|
||||||
|
* @param Fx - force in x direction
|
||||||
|
* @param Fy - force in y direction
|
||||||
|
* @param Fz - force in z direction
|
||||||
|
*/
|
||||||
|
extern "C" void ScaLBL_D3Q19_AAodd_MRT(int *neighborList, double *dist, int start, int finish, int Np,
|
||||||
double rlx_setA, double rlx_setB, double Fx, double Fy, double Fz);
|
double rlx_setA, double rlx_setB, double Fx, double Fy, double Fz);
|
||||||
|
|
||||||
// COLOR MODEL
|
// COLOR MODEL
|
||||||
|
/**
|
||||||
|
* \brief Color model collision based on AA even access pattern for D3Q19
|
||||||
|
* @param Map - mapping between sparse and dense data structures
|
||||||
|
* @param dist - D3Q19 distributions
|
||||||
|
* @param Aq - D3Q7 distribution for component A
|
||||||
|
* @param Bq - D3Q7 distribution for component B
|
||||||
|
* @param Den - density field
|
||||||
|
* @param Phi - phase indicator field
|
||||||
|
* @param Vel - velocity field
|
||||||
|
* @param rhoA - density of component A
|
||||||
|
* @param rhoB - density of component B
|
||||||
|
* @param tauA - relaxation time for component A
|
||||||
|
* @param tauB - relaxation time for component B
|
||||||
|
* @param alpha - parameter to control interfacial tension
|
||||||
|
* @param beta - parameter to control interface width
|
||||||
|
* @param Fx - force in x direction
|
||||||
|
* @param Fy - force in y direction
|
||||||
|
* @param Fz - force in z direction
|
||||||
|
* @param strideY - stride in y-direction for gradient computation
|
||||||
|
* @param strideZ - stride in z-direction for gradient computation
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q19_AAeven_Color(int *Map, double *dist, double *Aq, double *Bq, double *Den, double *Phi,
|
extern "C" void ScaLBL_D3Q19_AAeven_Color(int *Map, double *dist, double *Aq, double *Bq, double *Den, double *Phi,
|
||||||
double *Vel, double rhoA, double rhoB, double tauA, double tauB, double alpha, double beta,
|
double *Vel, double rhoA, double rhoB, double tauA, double tauB, double alpha, double beta,
|
||||||
double Fx, double Fy, double Fz, int strideY, int strideZ, int start, int finish, int Np);
|
double Fx, double Fy, double Fz, int strideY, int strideZ, int start, int finish, int Np);
|
||||||
|
|
||||||
extern "C" void ScaLBL_D3Q19_AAodd_Color(int *d_neighborList, int *Map, double *dist, double *Aq, double *Bq, double *Den,
|
/**
|
||||||
|
* \brief Color model collision based on AA even access pattern for D3Q19
|
||||||
|
* @param NeighborList - neighbors based on D3Q19 lattice structure
|
||||||
|
* @param Map - mapping between sparse and dense data structures
|
||||||
|
* @param dist - D3Q19 distributions
|
||||||
|
* @param Aq - D3Q7 distribution for component A
|
||||||
|
* @param Bq - D3Q7 distribution for component B
|
||||||
|
* @param Den - density field
|
||||||
|
* @param Phi - phase indicator field
|
||||||
|
* @param Vel - velocity field
|
||||||
|
* @param rhoA - density of component A
|
||||||
|
* @param rhoB - density of component B
|
||||||
|
* @param tauA - relaxation time for component A
|
||||||
|
* @param tauB - relaxation time for component B
|
||||||
|
* @param alpha - parameter to control interfacial tension
|
||||||
|
* @param beta - parameter to control interface width
|
||||||
|
* @param Fx - force in x direction
|
||||||
|
* @param Fy - force in y direction
|
||||||
|
* @param Fz - force in z direction
|
||||||
|
* @param strideY - stride in y-direction for gradient computation
|
||||||
|
* @param strideZ - stride in z-direction for gradient computation
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
|
extern "C" void ScaLBL_D3Q19_AAodd_Color(int *NeighborList, int *Map, double *dist, double *Aq, double *Bq, double *Den,
|
||||||
double *Phi, double *Vel, double rhoA, double rhoB, double tauA, double tauB, double alpha, double beta,
|
double *Phi, double *Vel, double rhoA, double rhoB, double tauA, double tauB, double alpha, double beta,
|
||||||
double Fx, double Fy, double Fz, int strideY, int strideZ, int start, int finish, int Np);
|
double Fx, double Fy, double Fz, int strideY, int strideZ, int start, int finish, int Np);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compute phase field based on AA odd access pattern for D3Q19
|
||||||
|
* @param NeighborList - neighbors based on D3Q19 lattice structure
|
||||||
|
* @param Map - mapping between sparse and dense data structures
|
||||||
|
* @param Aq - D3Q7 distribution for component A
|
||||||
|
* @param Bq - D3Q7 distribution for component B
|
||||||
|
* @param Den - density field
|
||||||
|
* @param Phi - phase indicator field
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q7_AAodd_PhaseField(int *NeighborList, int *Map, double *Aq, double *Bq,
|
extern "C" void ScaLBL_D3Q7_AAodd_PhaseField(int *NeighborList, int *Map, double *Aq, double *Bq,
|
||||||
double *Den, double *Phi, int start, int finish, int Np);
|
double *Den, double *Phi, int start, int finish, int Np);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compute phase field based on AA even access pattern for D3Q19
|
||||||
|
* @param Map - mapping between sparse and dense data structures
|
||||||
|
* @param Aq - D3Q7 distribution for component A
|
||||||
|
* @param Bq - D3Q7 distribution for component B
|
||||||
|
* @param Den - density field
|
||||||
|
* @param Phi - phase indicator field
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
extern "C" void ScaLBL_D3Q7_AAeven_PhaseField(int *Map, double *Aq, double *Bq, double *Den, double *Phi,
|
extern "C" void ScaLBL_D3Q7_AAeven_PhaseField(int *Map, double *Aq, double *Bq, double *Den, double *Phi,
|
||||||
int start, int finish, int Np);
|
int start, int finish, int Np);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize phase field for color model
|
||||||
|
* @param Map - mapping between sparse and dense data structures
|
||||||
|
* @param Phi - phase indicator field
|
||||||
|
* @param Den - density field
|
||||||
|
* @param Aq - D3Q7 distribution for component A
|
||||||
|
* @param Bq - D3Q7 distribution for component B
|
||||||
|
* @param start - lattice node to start loop
|
||||||
|
* @param finish - lattice node to finish loop
|
||||||
|
* @param Np - size of local sub-domain (derived from Domain structure)
|
||||||
|
*/
|
||||||
|
extern "C" void ScaLBL_PhaseField_Init(int *Map, double *Phi, double *Den, double *Aq, double *Bq, int start, int finish, int Np);
|
||||||
|
|
||||||
|
|
||||||
extern "C" void ScaLBL_D3Q7_AAodd_Color(int *neighborList, int *Map, double *Aq, double *Bq, double *Den,
|
extern "C" void ScaLBL_D3Q7_AAodd_Color(int *neighborList, int *Map, double *Aq, double *Bq, double *Den,
|
||||||
double *Phi, double *ColorGrad, double *Vel, double rhoA, double rhoB, double beta, int start, int finish, int Np);
|
double *Phi, double *ColorGrad, double *Vel, double rhoA, double rhoB, double beta, int start, int finish, int Np);
|
||||||
|
|
||||||
@ -196,7 +500,6 @@ extern "C" void ScaLBL_D3Q19_Gradient(int *Map, double *Phi, double *ColorGrad,
|
|||||||
|
|
||||||
extern "C" void ScaLBL_D3Q19_MixedGradient(int *Map, double *Phi, double *Gradient, int start, int finish, int Np, int Nx, int Ny, int Nz);
|
extern "C" void ScaLBL_D3Q19_MixedGradient(int *Map, double *Phi, double *Gradient, int start, int finish, int Np, int Nx, int Ny, int Nz);
|
||||||
|
|
||||||
extern "C" void ScaLBL_PhaseField_Init(int *Map, double *Phi, double *Den, double *Aq, double *Bq, int start, int finish, int Np);
|
|
||||||
|
|
||||||
// Density functional hydrodynamics LBM
|
// Density functional hydrodynamics LBM
|
||||||
extern "C" void ScaLBL_DFH_Init(double *Phi, double *Den, double *Aq, double *Bq, int start, int finish, int Np);
|
extern "C" void ScaLBL_DFH_Init(double *Phi, double *Den, double *Aq, double *Bq, int start, int finish, int Np);
|
||||||
@ -347,12 +650,24 @@ extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvcElec_BC_Z(int *list, double
|
|||||||
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvcElec_BC_z(int *d_neighborList, int *list, double *dist, double Cin, double tau, double *VelocityZ,double *ElectricField,double Di,double zi,double Vt, int count, int Np);
|
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvcElec_BC_z(int *d_neighborList, int *list, double *dist, double Cin, double tau, double *VelocityZ,double *ElectricField,double Di,double zi,double Vt, int count, int Np);
|
||||||
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvcElec_BC_Z(int *d_neighborList, int *list, double *dist, double Cout, double tau, double *VelocityZ,double *ElectricField,double Di,double zi,double Vt, int count, int Np);
|
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvcElec_BC_Z(int *d_neighborList, int *list, double *dist, double Cout, double tau, double *VelocityZ,double *ElectricField,double Di,double zi,double Vt, int count, int Np);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class ScaLBL_Communicator
|
||||||
|
*
|
||||||
|
* @brief Generalized communication routines for lattice Boltzmann methods.
|
||||||
|
*
|
||||||
|
*/
|
||||||
class ScaLBL_Communicator{
|
class ScaLBL_Communicator{
|
||||||
public:
|
public:
|
||||||
//......................................................................................
|
//......................................................................................
|
||||||
|
/**
|
||||||
|
*\brief Constructor
|
||||||
|
* @param Dm - Domain information
|
||||||
|
*/
|
||||||
ScaLBL_Communicator(std::shared_ptr <Domain> Dm);
|
ScaLBL_Communicator(std::shared_ptr <Domain> Dm);
|
||||||
|
|
||||||
//ScaLBL_Communicator(Domain &Dm, IntArray &Map);
|
/**
|
||||||
|
*\brief Destructor
|
||||||
|
*/
|
||||||
~ScaLBL_Communicator();
|
~ScaLBL_Communicator();
|
||||||
//......................................................................................
|
//......................................................................................
|
||||||
unsigned long int CommunicationCount,SendCount,RecvCount;
|
unsigned long int CommunicationCount,SendCount,RecvCount;
|
||||||
|
@ -1173,7 +1173,7 @@ HIDE_UNDOC_RELATIONS = YES
|
|||||||
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
|
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
|
||||||
# have no effect if this option is set to NO (the default)
|
# have no effect if this option is set to NO (the default)
|
||||||
|
|
||||||
HAVE_DOT = YES
|
HAVE_DOT = NO
|
||||||
|
|
||||||
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
|
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
|
||||||
# will generate a graph for each documented class showing the direct and
|
# will generate a graph for each documented class showing the direct and
|
||||||
|
@ -1,9 +1,17 @@
|
|||||||
/** \mainpage LBPM
|
/** \mainpage LBPM
|
||||||
*
|
*
|
||||||
* This is the documentation for LBPM
|
* C/C++ routines
|
||||||
*
|
*
|
||||||
|
* - \ref ScaLBL.h "Scalable Lattice Boltzmann Library (ScaLBL)"
|
||||||
|
* - \ref models "Lattice Boltzmann models"
|
||||||
|
* - \ref ColorModel "Color model"
|
||||||
|
* - \ref analysis "Analysis routines"
|
||||||
|
* - \ref FlowAdaptor "FlowAdaptor"
|
||||||
|
* - \ref DCEL "Doubly connected edge list"
|
||||||
|
* - \ref Minkowski "Minkowski functionals"
|
||||||
* - \ref IO "IO routines"
|
* - \ref IO "IO routines"
|
||||||
* - \ref Utilities "Utility routines"
|
* - \ref Utilities "Utility routines"
|
||||||
|
* - \ref tests "Unit tests"
|
||||||
*
|
*
|
||||||
* \author James McClure
|
* \author J.E. McClure, M. Berrill
|
||||||
*/
|
*/
|
||||||
|
@ -959,7 +959,11 @@ double ScaLBL_ColorModel::Run(int returntime){
|
|||||||
void ScaLBL_ColorModel::Run(){
|
void ScaLBL_ColorModel::Run(){
|
||||||
int nprocs=nprocx*nprocy*nprocz;
|
int nprocs=nprocx*nprocy*nprocz;
|
||||||
const RankInfoStruct rank_info(rank,nprocx,nprocy,nprocz);
|
const RankInfoStruct rank_info(rank,nprocx,nprocy,nprocz);
|
||||||
|
int analysis_interval = 1000; // number of timesteps in between in situ analysis
|
||||||
|
if (analysis_db->keyExists( "analysis_interval" )){
|
||||||
|
analysis_interval = analysis_db->getScalar<int>( "analysis_interval" );
|
||||||
|
}
|
||||||
|
/*
|
||||||
int IMAGE_INDEX = 0;
|
int IMAGE_INDEX = 0;
|
||||||
int IMAGE_COUNT = 0;
|
int IMAGE_COUNT = 0;
|
||||||
std::vector<std::string> ImageList;
|
std::vector<std::string> ImageList;
|
||||||
@ -978,7 +982,6 @@ void ScaLBL_ColorModel::Run(){
|
|||||||
int CURRENT_MORPH_TIMESTEPS=0; // counter for number of timesteps spent in morphological adaptation routine (reset each time)
|
int CURRENT_MORPH_TIMESTEPS=0; // counter for number of timesteps spent in morphological adaptation routine (reset each time)
|
||||||
int CURRENT_STEADY_TIMESTEPS=0; // counter for number of timesteps spent in morphological adaptation routine (reset each time)
|
int CURRENT_STEADY_TIMESTEPS=0; // counter for number of timesteps spent in morphological adaptation routine (reset each time)
|
||||||
int morph_interval = 100000;
|
int morph_interval = 100000;
|
||||||
int analysis_interval = 1000; // number of timesteps in between in situ analysis
|
|
||||||
int morph_timesteps = 0;
|
int morph_timesteps = 0;
|
||||||
double morph_delta = 0.0;
|
double morph_delta = 0.0;
|
||||||
double seed_water = 0.0;
|
double seed_water = 0.0;
|
||||||
@ -989,7 +992,6 @@ void ScaLBL_ColorModel::Run(){
|
|||||||
double delta_volume = 0.0;
|
double delta_volume = 0.0;
|
||||||
double delta_volume_target = 0.0;
|
double delta_volume_target = 0.0;
|
||||||
|
|
||||||
/* history for morphological algoirthm */
|
|
||||||
double KRA_MORPH_FACTOR=0.5;
|
double KRA_MORPH_FACTOR=0.5;
|
||||||
double volA_prev = 0.0;
|
double volA_prev = 0.0;
|
||||||
double log_krA_prev = 1.0;
|
double log_krA_prev = 1.0;
|
||||||
@ -1041,9 +1043,7 @@ void ScaLBL_ColorModel::Run(){
|
|||||||
if (analysis_db->keyExists( "tolerance" )){
|
if (analysis_db->keyExists( "tolerance" )){
|
||||||
tolerance = analysis_db->getScalar<double>( "tolerance" );
|
tolerance = analysis_db->getScalar<double>( "tolerance" );
|
||||||
}
|
}
|
||||||
if (analysis_db->keyExists( "analysis_interval" )){
|
|
||||||
analysis_interval = analysis_db->getScalar<int>( "analysis_interval" );
|
|
||||||
}
|
|
||||||
if (analysis_db->keyExists( "min_steady_timesteps" )){
|
if (analysis_db->keyExists( "min_steady_timesteps" )){
|
||||||
MIN_STEADY_TIMESTEPS = analysis_db->getScalar<int>( "min_steady_timesteps" );
|
MIN_STEADY_TIMESTEPS = analysis_db->getScalar<int>( "min_steady_timesteps" );
|
||||||
}
|
}
|
||||||
@ -1054,7 +1054,6 @@ void ScaLBL_ColorModel::Run(){
|
|||||||
MAX_MORPH_TIMESTEPS = analysis_db->getScalar<int>( "max_morph_timesteps" );
|
MAX_MORPH_TIMESTEPS = analysis_db->getScalar<int>( "max_morph_timesteps" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* defaults for simulation protocols */
|
|
||||||
auto protocol = color_db->getWithDefault<std::string>( "protocol", "none" );
|
auto protocol = color_db->getWithDefault<std::string>( "protocol", "none" );
|
||||||
if (protocol == "image sequence"){
|
if (protocol == "image sequence"){
|
||||||
// Get the list of images
|
// Get the list of images
|
||||||
@ -1100,8 +1099,7 @@ void ScaLBL_ColorModel::Run(){
|
|||||||
double CrossSectionalArea = (double) (nprocx*(Nx-2)*nprocy*(Ny-2));
|
double CrossSectionalArea = (double) (nprocx*(Nx-2)*nprocy*(Ny-2));
|
||||||
flux = Dm->Porosity()*CrossSectionalArea*IFT*capillary_number/MuB;
|
flux = Dm->Porosity()*CrossSectionalArea*IFT*capillary_number/MuB;
|
||||||
}
|
}
|
||||||
}
|
} if (rank==0){
|
||||||
if (rank==0){
|
|
||||||
printf("********************************************************\n");
|
printf("********************************************************\n");
|
||||||
if (protocol == "image sequence"){
|
if (protocol == "image sequence"){
|
||||||
printf(" using protocol = image sequence \n");
|
printf(" using protocol = image sequence \n");
|
||||||
@ -1156,7 +1154,7 @@ void ScaLBL_ColorModel::Run(){
|
|||||||
printf("No. of timesteps: %i \n", timestepMax);
|
printf("No. of timesteps: %i \n", timestepMax);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
//************ MAIN ITERATION LOOP ***************************************/
|
//************ MAIN ITERATION LOOP ***************************************/
|
||||||
comm.barrier();
|
comm.barrier();
|
||||||
PROFILE_START("Loop");
|
PROFILE_START("Loop");
|
||||||
@ -1256,242 +1254,6 @@ void ScaLBL_ColorModel::Run(){
|
|||||||
}
|
}
|
||||||
// Run the analysis
|
// Run the analysis
|
||||||
analysis.basic(timestep, current_db, *Averages, Phi, Pressure, Velocity, fq, Den );
|
analysis.basic(timestep, current_db, *Averages, Phi, Pressure, Velocity, fq, Den );
|
||||||
|
|
||||||
// allow initial ramp-up to get closer to steady state
|
|
||||||
if (timestep > RAMP_TIMESTEPS && timestep%analysis_interval == 0 && USE_MORPH){
|
|
||||||
analysis.finish();
|
|
||||||
CURRENT_STEADY_TIMESTEPS += analysis_interval;
|
|
||||||
|
|
||||||
double volB = Averages->gwb.V;
|
|
||||||
double volA = Averages->gnb.V;
|
|
||||||
volA /= Dm->Volume;
|
|
||||||
volB /= Dm->Volume;
|
|
||||||
//initial_volume = volA*Dm->Volume;
|
|
||||||
double vA_x = Averages->gnb.Px/Averages->gnb.M;
|
|
||||||
double vA_y = Averages->gnb.Py/Averages->gnb.M;
|
|
||||||
double vA_z = Averages->gnb.Pz/Averages->gnb.M;
|
|
||||||
double vB_x = Averages->gwb.Px/Averages->gwb.M;
|
|
||||||
double vB_y = Averages->gwb.Py/Averages->gwb.M;
|
|
||||||
double vB_z = Averages->gwb.Pz/Averages->gwb.M;
|
|
||||||
double muA = rhoA*(tauA-0.5)/3.f;
|
|
||||||
double muB = rhoB*(tauB-0.5)/3.f;
|
|
||||||
double force_mag = sqrt(Fx*Fx+Fy*Fy+Fz*Fz);
|
|
||||||
double dir_x = Fx/force_mag;
|
|
||||||
double dir_y = Fy/force_mag;
|
|
||||||
double dir_z = Fz/force_mag;
|
|
||||||
if (force_mag == 0.0){
|
|
||||||
// default to z direction
|
|
||||||
dir_x = 0.0;
|
|
||||||
dir_y = 0.0;
|
|
||||||
dir_z = 1.0;
|
|
||||||
force_mag = 1.0;
|
|
||||||
}
|
|
||||||
double current_saturation = volB/(volA+volB);
|
|
||||||
double flow_rate_A = volA*(vA_x*dir_x + vA_y*dir_y + vA_z*dir_z);
|
|
||||||
double flow_rate_B = volB*(vB_x*dir_x + vB_y*dir_y + vB_z*dir_z);
|
|
||||||
double Ca = fabs(muA*flow_rate_A + muB*flow_rate_B)/(5.796*alpha);
|
|
||||||
|
|
||||||
if ( morph_timesteps > morph_interval ){
|
|
||||||
|
|
||||||
bool isSteady = false;
|
|
||||||
if ( (fabs((Ca - Ca_previous)/Ca) < tolerance && CURRENT_STEADY_TIMESTEPS > MIN_STEADY_TIMESTEPS))
|
|
||||||
isSteady = true;
|
|
||||||
if (CURRENT_STEADY_TIMESTEPS > MAX_STEADY_TIMESTEPS)
|
|
||||||
isSteady = true;
|
|
||||||
if (RESCALE_FORCE == true && SET_CAPILLARY_NUMBER == true && CURRENT_STEADY_TIMESTEPS > RESCALE_FORCE_AFTER_TIMESTEP){
|
|
||||||
RESCALE_FORCE = false;
|
|
||||||
double RESCALE_FORCE_FACTOR = capillary_number / Ca;
|
|
||||||
if (RESCALE_FORCE_FACTOR > 2.0) RESCALE_FORCE_FACTOR = 2.0;
|
|
||||||
if (RESCALE_FORCE_FACTOR < 0.5) RESCALE_FORCE_FACTOR = 0.5;
|
|
||||||
Fx *= RESCALE_FORCE_FACTOR;
|
|
||||||
Fy *= RESCALE_FORCE_FACTOR;
|
|
||||||
Fz *= RESCALE_FORCE_FACTOR;
|
|
||||||
force_mag = sqrt(Fx*Fx+Fy*Fy+Fz*Fz);
|
|
||||||
if (force_mag > 1e-3){
|
|
||||||
Fx *= 1e-3/force_mag; // impose ceiling for stability
|
|
||||||
Fy *= 1e-3/force_mag;
|
|
||||||
Fz *= 1e-3/force_mag;
|
|
||||||
}
|
|
||||||
if (rank == 0) printf(" -- adjust force by factor %f \n ",capillary_number / Ca);
|
|
||||||
Averages->SetParams(rhoA,rhoB,tauA,tauB,Fx,Fy,Fz,alpha,beta);
|
|
||||||
color_db->putVector<double>("F",{Fx,Fy,Fz});
|
|
||||||
}
|
|
||||||
if ( isSteady ){
|
|
||||||
MORPH_ADAPT = true;
|
|
||||||
CURRENT_MORPH_TIMESTEPS=0;
|
|
||||||
delta_volume_target = Dm->Volume*volA *morph_delta; // set target volume change
|
|
||||||
//****** ENDPOINT ADAPTATION ********/
|
|
||||||
double krA_TMP= fabs(muA*flow_rate_A / force_mag);
|
|
||||||
double krB_TMP= fabs(muB*flow_rate_B / force_mag);
|
|
||||||
log_krA = log(krA_TMP);
|
|
||||||
if (krA_TMP < 0.0){
|
|
||||||
// cannot do endpoint adaptation if kr is negative
|
|
||||||
log_krA = log_krA_prev;
|
|
||||||
}
|
|
||||||
else if (krA_TMP < krB_TMP && morph_delta > 0.0){
|
|
||||||
/** morphological target based on relative permeability for A **/
|
|
||||||
log_krA_target = log(KRA_MORPH_FACTOR*(krA_TMP));
|
|
||||||
slope_krA_volume = (log_krA - log_krA_prev)/(Dm->Volume*(volA - volA_prev));
|
|
||||||
delta_volume_target=min(delta_volume_target,Dm->Volume*(volA+(log_krA_target - log_krA)/slope_krA_volume));
|
|
||||||
if (rank==0){
|
|
||||||
printf(" Enabling endpoint adaptation: krA = %f, krB = %f \n",krA_TMP,krB_TMP);
|
|
||||||
printf(" log(kr)=%f, volume=%f, TARGET log(kr)=%f, volume change=%f \n",log_krA, volA, log_krA_target, delta_volume_target/(volA*Dm->Volume));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log_krA_prev = log_krA;
|
|
||||||
volA_prev = volA;
|
|
||||||
//******************************** **/
|
|
||||||
/** compute averages & write data **/
|
|
||||||
Averages->Full();
|
|
||||||
Averages->Write(timestep);
|
|
||||||
analysis.WriteVisData(timestep, current_db, *Averages, Phi, Pressure, Velocity, fq, Den );
|
|
||||||
analysis.finish();
|
|
||||||
|
|
||||||
if (rank==0){
|
|
||||||
printf("** WRITE STEADY POINT *** ");
|
|
||||||
printf("Ca = %f, (previous = %f) \n",Ca,Ca_previous);
|
|
||||||
double h = Dm->voxel_length;
|
|
||||||
// pressures
|
|
||||||
double pA = Averages->gnb.p;
|
|
||||||
double pB = Averages->gwb.p;
|
|
||||||
double pAc = Averages->gnc.p;
|
|
||||||
double pBc = Averages->gwc.p;
|
|
||||||
double pAB = (pA-pB)/(h*6.0*alpha);
|
|
||||||
double pAB_connected = (pAc-pBc)/(h*6.0*alpha);
|
|
||||||
// connected contribution
|
|
||||||
double Vol_nc = Averages->gnc.V/Dm->Volume;
|
|
||||||
double Vol_wc = Averages->gwc.V/Dm->Volume;
|
|
||||||
double Vol_nd = Averages->gnd.V/Dm->Volume;
|
|
||||||
double Vol_wd = Averages->gwd.V/Dm->Volume;
|
|
||||||
double Mass_n = Averages->gnc.M + Averages->gnd.M;
|
|
||||||
double Mass_w = Averages->gwc.M + Averages->gwd.M;
|
|
||||||
double vAc_x = Averages->gnc.Px/Mass_n;
|
|
||||||
double vAc_y = Averages->gnc.Py/Mass_n;
|
|
||||||
double vAc_z = Averages->gnc.Pz/Mass_n;
|
|
||||||
double vBc_x = Averages->gwc.Px/Mass_w;
|
|
||||||
double vBc_y = Averages->gwc.Py/Mass_w;
|
|
||||||
double vBc_z = Averages->gwc.Pz/Mass_w;
|
|
||||||
// disconnected contribution
|
|
||||||
double vAd_x = Averages->gnd.Px/Mass_n;
|
|
||||||
double vAd_y = Averages->gnd.Py/Mass_n;
|
|
||||||
double vAd_z = Averages->gnd.Pz/Mass_n;
|
|
||||||
double vBd_x = Averages->gwd.Px/Mass_w;
|
|
||||||
double vBd_y = Averages->gwd.Py/Mass_w;
|
|
||||||
double vBd_z = Averages->gwd.Pz/Mass_w;
|
|
||||||
|
|
||||||
double flow_rate_A_connected = Vol_nc*(vAc_x*dir_x + vAc_y*dir_y + vAc_z*dir_z);
|
|
||||||
double flow_rate_B_connected = Vol_wc*(vBc_x*dir_x + vBc_y*dir_y + vBc_z*dir_z);
|
|
||||||
double flow_rate_A_disconnected = (Vol_nd)*(vAd_x*dir_x + vAd_y*dir_y + vAd_z*dir_z);
|
|
||||||
double flow_rate_B_disconnected = (Vol_wd)*(vBd_x*dir_x + vBd_y*dir_y + vBd_z*dir_z);
|
|
||||||
|
|
||||||
double kAeff_connected = h*h*muA*flow_rate_A_connected/(force_mag);
|
|
||||||
double kBeff_connected = h*h*muB*flow_rate_B_connected/(force_mag);
|
|
||||||
|
|
||||||
double kAeff_disconnected = h*h*muA*flow_rate_A_disconnected/(force_mag);
|
|
||||||
double kBeff_disconnected = h*h*muB*flow_rate_B_disconnected/(force_mag);
|
|
||||||
|
|
||||||
double kAeff = h*h*muA*(flow_rate_A)/(force_mag);
|
|
||||||
double kBeff = h*h*muB*(flow_rate_B)/(force_mag);
|
|
||||||
|
|
||||||
double viscous_pressure_drop = (rhoA*volA + rhoB*volB)*force_mag;
|
|
||||||
double Mobility = muA/muB;
|
|
||||||
|
|
||||||
bool WriteHeader=false;
|
|
||||||
FILE * kr_log_file = fopen("relperm.csv","r");
|
|
||||||
if (kr_log_file != NULL)
|
|
||||||
fclose(kr_log_file);
|
|
||||||
else
|
|
||||||
WriteHeader=true;
|
|
||||||
kr_log_file = fopen("relperm.csv","a");
|
|
||||||
if (WriteHeader)
|
|
||||||
fprintf(kr_log_file,"timesteps sat.water eff.perm.oil eff.perm.water eff.perm.oil.connected eff.perm.water.connected eff.perm.oil.disconnected eff.perm.water.disconnected cap.pressure cap.pressure.connected pressure.drop Ca M\n");
|
|
||||||
|
|
||||||
fprintf(kr_log_file,"%i %.5g %.5g %.5g %.5g %.5g %.5g %.5g %.5g %.5g %.5g %.5g %.5g\n",CURRENT_STEADY_TIMESTEPS,current_saturation,kAeff,kBeff,kAeff_connected,kBeff_connected,kAeff_disconnected,kBeff_disconnected,pAB,pAB_connected,viscous_pressure_drop,Ca,Mobility);
|
|
||||||
fclose(kr_log_file);
|
|
||||||
|
|
||||||
printf(" Measured capillary number %f \n ",Ca);
|
|
||||||
}
|
|
||||||
if (SET_CAPILLARY_NUMBER ){
|
|
||||||
Fx *= capillary_number / Ca;
|
|
||||||
Fy *= capillary_number / Ca;
|
|
||||||
Fz *= capillary_number / Ca;
|
|
||||||
if (force_mag > 1e-3){
|
|
||||||
Fx *= 1e-3/force_mag; // impose ceiling for stability
|
|
||||||
Fy *= 1e-3/force_mag;
|
|
||||||
Fz *= 1e-3/force_mag;
|
|
||||||
}
|
|
||||||
if (rank == 0) printf(" -- adjust force by factor %f \n ",capillary_number / Ca);
|
|
||||||
Averages->SetParams(rhoA,rhoB,tauA,tauB,Fx,Fy,Fz,alpha,beta);
|
|
||||||
color_db->putVector<double>("F",{Fx,Fy,Fz});
|
|
||||||
}
|
|
||||||
|
|
||||||
CURRENT_STEADY_TIMESTEPS = 0;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if (rank==0){
|
|
||||||
printf("** Continue to simulate steady *** \n ");
|
|
||||||
printf("Ca = %f, (previous = %f) \n",Ca,Ca_previous);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
morph_timesteps=0;
|
|
||||||
Ca_previous = Ca;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MORPH_ADAPT ){
|
|
||||||
CURRENT_MORPH_TIMESTEPS += analysis_interval;
|
|
||||||
if (USE_DIRECT){
|
|
||||||
// Use image sequence
|
|
||||||
IMAGE_INDEX++;
|
|
||||||
MORPH_ADAPT = false;
|
|
||||||
if (IMAGE_INDEX < IMAGE_COUNT){
|
|
||||||
std::string next_image = ImageList[IMAGE_INDEX];
|
|
||||||
if (rank==0) printf("***Loading next image in sequence (%i) ***\n",IMAGE_INDEX);
|
|
||||||
color_db->putScalar<int>("image_index",IMAGE_INDEX);
|
|
||||||
ImageInit(next_image);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if (rank==0) printf("Finished simulating image sequence \n");
|
|
||||||
timestep = timestepMax;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (USE_SEED){
|
|
||||||
delta_volume = volA*Dm->Volume - initial_volume;
|
|
||||||
CURRENT_MORPH_TIMESTEPS += analysis_interval;
|
|
||||||
double massChange = SeedPhaseField(seed_water);
|
|
||||||
if (rank==0) printf("***Seed water in oil %f, volume change %f / %f ***\n", massChange, delta_volume, delta_volume_target);
|
|
||||||
}
|
|
||||||
else if (USE_MORPHOPEN_OIL){
|
|
||||||
delta_volume = volA*Dm->Volume - initial_volume;
|
|
||||||
if (rank==0) printf("***Morphological opening of connected oil, target volume change %f ***\n", delta_volume_target);
|
|
||||||
MorphOpenConnected(delta_volume_target);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (rank==0) printf("***Shell aggregation, target volume change %f ***\n", delta_volume_target);
|
|
||||||
//double delta_volume_target = volB - (volA + volB)*TARGET_SATURATION; // change in volume to A
|
|
||||||
delta_volume += MorphInit(beta,delta_volume_target-delta_volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (delta_volume - delta_volume_target)/delta_volume_target > 0.0 ){
|
|
||||||
MORPH_ADAPT = false;
|
|
||||||
CURRENT_STEADY_TIMESTEPS=0;
|
|
||||||
initial_volume = volA*Dm->Volume;
|
|
||||||
delta_volume = 0.0;
|
|
||||||
if (RESCALE_FORCE_AFTER_TIMESTEP > 0)
|
|
||||||
RESCALE_FORCE = true;
|
|
||||||
}
|
|
||||||
else if (!(USE_DIRECT) && CURRENT_MORPH_TIMESTEPS > MAX_MORPH_TIMESTEPS) {
|
|
||||||
MORPH_ADAPT = false;
|
|
||||||
CURRENT_STEADY_TIMESTEPS=0;
|
|
||||||
initial_volume = volA*Dm->Volume;
|
|
||||||
delta_volume = 0.0;
|
|
||||||
RESCALE_FORCE = true;
|
|
||||||
if (RESCALE_FORCE_AFTER_TIMESTEP > 0)
|
|
||||||
RESCALE_FORCE = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
morph_timesteps += analysis_interval;
|
|
||||||
}
|
|
||||||
comm.barrier();
|
|
||||||
}
|
}
|
||||||
analysis.finish();
|
analysis.finish();
|
||||||
PROFILE_STOP("Loop");
|
PROFILE_STOP("Loop");
|
||||||
@ -1515,486 +1277,6 @@ void ScaLBL_ColorModel::Run(){
|
|||||||
// ************************************************************************
|
// ************************************************************************
|
||||||
}
|
}
|
||||||
|
|
||||||
double ScaLBL_ColorModel::ImageInit(std::string Filename){
|
|
||||||
|
|
||||||
if (rank==0) printf("Re-initializing fluids from file: %s \n", Filename.c_str());
|
|
||||||
Mask->Decomp(Filename);
|
|
||||||
for (int i=0; i<Nx*Ny*Nz; i++) id[i] = Mask->id[i]; // save what was read
|
|
||||||
for (int i=0; i<Nx*Ny*Nz; i++) Dm->id[i] = Mask->id[i]; // save what was read
|
|
||||||
|
|
||||||
double *PhaseLabel;
|
|
||||||
PhaseLabel = new double[Nx*Ny*Nz];
|
|
||||||
AssignComponentLabels(PhaseLabel);
|
|
||||||
|
|
||||||
double Count = 0.0;
|
|
||||||
double PoreCount = 0.0;
|
|
||||||
for (int k=1; k<Nz-1; k++){
|
|
||||||
for (int j=1; j<Ny-1; j++){
|
|
||||||
for (int i=1; i<Nx-1; i++){
|
|
||||||
if (id[Nx*Ny*k+Nx*j+i] == 2){
|
|
||||||
PoreCount++;
|
|
||||||
Count++;
|
|
||||||
}
|
|
||||||
else if (id[Nx*Ny*k+Nx*j+i] == 1){
|
|
||||||
PoreCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Count=Dm->Comm.sumReduce( Count);
|
|
||||||
PoreCount=Dm->Comm.sumReduce( PoreCount);
|
|
||||||
|
|
||||||
if (rank==0) printf(" new saturation: %f (%f / %f) \n", Count / PoreCount, Count, PoreCount);
|
|
||||||
ScaLBL_CopyToDevice(Phi, PhaseLabel, Nx*Ny*Nz*sizeof(double));
|
|
||||||
comm.barrier();
|
|
||||||
|
|
||||||
ScaLBL_D3Q19_Init(fq, Np);
|
|
||||||
ScaLBL_PhaseField_Init(dvcMap, Phi, Den, Aq, Bq, 0, ScaLBL_Comm->LastExterior(), Np);
|
|
||||||
ScaLBL_PhaseField_Init(dvcMap, Phi, Den, Aq, Bq, ScaLBL_Comm->FirstInterior(), ScaLBL_Comm->LastInterior(), Np);
|
|
||||||
comm.barrier();
|
|
||||||
|
|
||||||
ScaLBL_CopyToHost(Averages->Phi.data(),Phi,Nx*Ny*Nz*sizeof(double));
|
|
||||||
|
|
||||||
double saturation = Count/PoreCount;
|
|
||||||
return saturation;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
double ScaLBL_ColorModel::MorphOpenConnected(double target_volume_change){
|
|
||||||
|
|
||||||
int nx = Nx;
|
|
||||||
int ny = Ny;
|
|
||||||
int nz = Nz;
|
|
||||||
int n;
|
|
||||||
int N = nx*ny*nz;
|
|
||||||
double volume_change=0.0;
|
|
||||||
|
|
||||||
if (target_volume_change < 0.0){
|
|
||||||
Array<char> id_solid(nx,ny,nz);
|
|
||||||
Array<int> phase_label(nx,ny,nz);
|
|
||||||
DoubleArray distance(Nx,Ny,Nz);
|
|
||||||
DoubleArray phase(nx,ny,nz);
|
|
||||||
signed char *id_connected;
|
|
||||||
id_connected = new signed char [nx*ny*nz];
|
|
||||||
|
|
||||||
ScaLBL_CopyToHost(phase.data(), Phi, N*sizeof(double));
|
|
||||||
|
|
||||||
// Extract only the connected part of NWP
|
|
||||||
double vF=0.0; double vS=0.0;
|
|
||||||
ComputeGlobalBlobIDs(nx-2,ny-2,nz-2,Dm->rank_info,phase,Averages->SDs,vF,vS,phase_label,Dm->Comm);
|
|
||||||
comm.barrier();
|
|
||||||
|
|
||||||
long long count_connected=0;
|
|
||||||
long long count_porespace=0;
|
|
||||||
long long count_water=0;
|
|
||||||
for (int k=1; k<nz-1; k++){
|
|
||||||
for (int j=1; j<ny-1; j++){
|
|
||||||
for (int i=1; i<nx-1; i++){
|
|
||||||
n=k*nx*ny+j*nx+i;
|
|
||||||
// only apply opening to connected component
|
|
||||||
if ( phase_label(i,j,k) == 0){
|
|
||||||
count_connected++;
|
|
||||||
}
|
|
||||||
if (id[n] > 0){
|
|
||||||
count_porespace++;
|
|
||||||
}
|
|
||||||
if (id[n] == 2){
|
|
||||||
count_water++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
count_connected=Dm->Comm.sumReduce( count_connected);
|
|
||||||
count_porespace=Dm->Comm.sumReduce( count_porespace);
|
|
||||||
count_water=Dm->Comm.sumReduce( count_water);
|
|
||||||
|
|
||||||
for (int k=0; k<nz; k++){
|
|
||||||
for (int j=0; j<ny; j++){
|
|
||||||
for (int i=0; i<nx; i++){
|
|
||||||
n=k*nx*ny+j*nx+i;
|
|
||||||
// only apply opening to connected component
|
|
||||||
if ( phase_label(i,j,k) == 0){
|
|
||||||
id_solid(i,j,k) = 1;
|
|
||||||
id_connected[n] = 2;
|
|
||||||
id[n] = 2;
|
|
||||||
/* delete the connected component */
|
|
||||||
phase(i,j,k) = -1.0;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
id_solid(i,j,k) = 0;
|
|
||||||
id_connected[n] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CalcDist(distance,id_solid,*Dm);
|
|
||||||
|
|
||||||
signed char water=2;
|
|
||||||
signed char notwater=1;
|
|
||||||
double SW=-(target_volume_change)/count_connected;
|
|
||||||
MorphOpen(distance, id_connected, Dm, SW, water, notwater);
|
|
||||||
|
|
||||||
for (int k=0; k<nz; k++){
|
|
||||||
for (int j=0; j<ny; j++){
|
|
||||||
for (int i=0; i<nx; i++){
|
|
||||||
n=k*nx*ny+j*nx+i;
|
|
||||||
// only apply opening to connected component
|
|
||||||
if ( id_connected[n] == 1){
|
|
||||||
id_solid(i,j,k) = 0;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
id_solid(i,j,k) = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CalcDist(distance,id_solid,*Dm);
|
|
||||||
|
|
||||||
// re-initialize
|
|
||||||
double beta = 0.95;
|
|
||||||
for (int k=0; k<nz; k++){
|
|
||||||
for (int j=0; j<ny; j++){
|
|
||||||
for (int i=0; i<nx; i++){
|
|
||||||
n=k*nx*ny+j*nx+i;
|
|
||||||
double d = distance(i,j,k);
|
|
||||||
if (Averages->SDs(i,j,k) > 0.f){
|
|
||||||
if (d < 3.f){
|
|
||||||
phase(i,j,k) = (2.f*(exp(-2.f*beta*d))/(1.f+exp(-2.f*beta*d))-1.f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int count_morphopen=0.0;
|
|
||||||
for (int k=1; k<nz-1; k++){
|
|
||||||
for (int j=1; j<ny-1; j++){
|
|
||||||
for (int i=1; i<nx-1; i++){
|
|
||||||
n=k*nx*ny+j*nx+i;
|
|
||||||
// only apply opening to connected component
|
|
||||||
if ( id_connected[n] == 1){
|
|
||||||
count_morphopen++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
count_morphopen=Dm->Comm.sumReduce( count_morphopen);
|
|
||||||
volume_change = double(count_morphopen - count_connected);
|
|
||||||
|
|
||||||
if (rank==0) printf(" opening of connected oil %f \n",volume_change/count_connected);
|
|
||||||
|
|
||||||
ScaLBL_CopyToDevice(Phi,phase.data(),N*sizeof(double));
|
|
||||||
ScaLBL_PhaseField_Init(dvcMap, Phi, Den, Aq, Bq, 0, ScaLBL_Comm->LastExterior(), Np);
|
|
||||||
ScaLBL_PhaseField_Init(dvcMap, Phi, Den, Aq, Bq, ScaLBL_Comm->FirstInterior(), ScaLBL_Comm->LastInterior(), Np);
|
|
||||||
if (BoundaryCondition == 1 || BoundaryCondition == 2 || BoundaryCondition == 3 || BoundaryCondition == 4){
|
|
||||||
if (Dm->kproc()==0){
|
|
||||||
ScaLBL_SetSlice_z(Phi,1.0,Nx,Ny,Nz,0);
|
|
||||||
ScaLBL_SetSlice_z(Phi,1.0,Nx,Ny,Nz,1);
|
|
||||||
ScaLBL_SetSlice_z(Phi,1.0,Nx,Ny,Nz,2);
|
|
||||||
}
|
|
||||||
if (Dm->kproc() == nprocz-1){
|
|
||||||
ScaLBL_SetSlice_z(Phi,-1.0,Nx,Ny,Nz,Nz-1);
|
|
||||||
ScaLBL_SetSlice_z(Phi,-1.0,Nx,Ny,Nz,Nz-2);
|
|
||||||
ScaLBL_SetSlice_z(Phi,-1.0,Nx,Ny,Nz,Nz-3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(volume_change);
|
|
||||||
}
|
|
||||||
|
|
||||||
double ScaLBL_ColorModel::SeedPhaseField(const double seed_water_in_oil){
|
|
||||||
srand(time(NULL));
|
|
||||||
double mass_loss =0.f;
|
|
||||||
double count =0.f;
|
|
||||||
double *Aq_tmp, *Bq_tmp;
|
|
||||||
|
|
||||||
Aq_tmp = new double [7*Np];
|
|
||||||
Bq_tmp = new double [7*Np];
|
|
||||||
|
|
||||||
ScaLBL_CopyToHost(Aq_tmp, Aq, 7*Np*sizeof(double));
|
|
||||||
ScaLBL_CopyToHost(Bq_tmp, Bq, 7*Np*sizeof(double));
|
|
||||||
|
|
||||||
|
|
||||||
for (int n=0; n < ScaLBL_Comm->LastExterior(); n++){
|
|
||||||
double random_value = seed_water_in_oil*double(rand())/ RAND_MAX;
|
|
||||||
double dA = Aq_tmp[n] + Aq_tmp[n+Np] + Aq_tmp[n+2*Np] + Aq_tmp[n+3*Np] + Aq_tmp[n+4*Np] + Aq_tmp[n+5*Np] + Aq_tmp[n+6*Np];
|
|
||||||
double dB = Bq_tmp[n] + Bq_tmp[n+Np] + Bq_tmp[n+2*Np] + Bq_tmp[n+3*Np] + Bq_tmp[n+4*Np] + Bq_tmp[n+5*Np] + Bq_tmp[n+6*Np];
|
|
||||||
double phase_id = (dA - dB) / (dA + dB);
|
|
||||||
if (phase_id > 0.0){
|
|
||||||
Aq_tmp[n] -= 0.3333333333333333*random_value;
|
|
||||||
Aq_tmp[n+Np] -= 0.1111111111111111*random_value;
|
|
||||||
Aq_tmp[n+2*Np] -= 0.1111111111111111*random_value;
|
|
||||||
Aq_tmp[n+3*Np] -= 0.1111111111111111*random_value;
|
|
||||||
Aq_tmp[n+4*Np] -= 0.1111111111111111*random_value;
|
|
||||||
Aq_tmp[n+5*Np] -= 0.1111111111111111*random_value;
|
|
||||||
Aq_tmp[n+6*Np] -= 0.1111111111111111*random_value;
|
|
||||||
|
|
||||||
Bq_tmp[n] += 0.3333333333333333*random_value;
|
|
||||||
Bq_tmp[n+Np] += 0.1111111111111111*random_value;
|
|
||||||
Bq_tmp[n+2*Np] += 0.1111111111111111*random_value;
|
|
||||||
Bq_tmp[n+3*Np] += 0.1111111111111111*random_value;
|
|
||||||
Bq_tmp[n+4*Np] += 0.1111111111111111*random_value;
|
|
||||||
Bq_tmp[n+5*Np] += 0.1111111111111111*random_value;
|
|
||||||
Bq_tmp[n+6*Np] += 0.1111111111111111*random_value;
|
|
||||||
}
|
|
||||||
mass_loss += random_value*seed_water_in_oil;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int n=ScaLBL_Comm->FirstInterior(); n < ScaLBL_Comm->LastInterior(); n++){
|
|
||||||
double random_value = seed_water_in_oil*double(rand())/ RAND_MAX;
|
|
||||||
double dA = Aq_tmp[n] + Aq_tmp[n+Np] + Aq_tmp[n+2*Np] + Aq_tmp[n+3*Np] + Aq_tmp[n+4*Np] + Aq_tmp[n+5*Np] + Aq_tmp[n+6*Np];
|
|
||||||
double dB = Bq_tmp[n] + Bq_tmp[n+Np] + Bq_tmp[n+2*Np] + Bq_tmp[n+3*Np] + Bq_tmp[n+4*Np] + Bq_tmp[n+5*Np] + Bq_tmp[n+6*Np];
|
|
||||||
double phase_id = (dA - dB) / (dA + dB);
|
|
||||||
if (phase_id > 0.0){
|
|
||||||
Aq_tmp[n] -= 0.3333333333333333*random_value;
|
|
||||||
Aq_tmp[n+Np] -= 0.1111111111111111*random_value;
|
|
||||||
Aq_tmp[n+2*Np] -= 0.1111111111111111*random_value;
|
|
||||||
Aq_tmp[n+3*Np] -= 0.1111111111111111*random_value;
|
|
||||||
Aq_tmp[n+4*Np] -= 0.1111111111111111*random_value;
|
|
||||||
Aq_tmp[n+5*Np] -= 0.1111111111111111*random_value;
|
|
||||||
Aq_tmp[n+6*Np] -= 0.1111111111111111*random_value;
|
|
||||||
|
|
||||||
Bq_tmp[n] += 0.3333333333333333*random_value;
|
|
||||||
Bq_tmp[n+Np] += 0.1111111111111111*random_value;
|
|
||||||
Bq_tmp[n+2*Np] += 0.1111111111111111*random_value;
|
|
||||||
Bq_tmp[n+3*Np] += 0.1111111111111111*random_value;
|
|
||||||
Bq_tmp[n+4*Np] += 0.1111111111111111*random_value;
|
|
||||||
Bq_tmp[n+5*Np] += 0.1111111111111111*random_value;
|
|
||||||
Bq_tmp[n+6*Np] += 0.1111111111111111*random_value;
|
|
||||||
}
|
|
||||||
mass_loss += random_value*seed_water_in_oil;
|
|
||||||
}
|
|
||||||
|
|
||||||
count= Dm->Comm.sumReduce( count);
|
|
||||||
mass_loss= Dm->Comm.sumReduce( mass_loss);
|
|
||||||
if (rank == 0) printf("Remove mass %f from %f voxels \n",mass_loss,count);
|
|
||||||
|
|
||||||
// Need to initialize Aq, Bq, Den, Phi directly
|
|
||||||
//ScaLBL_CopyToDevice(Phi,phase.data(),7*Np*sizeof(double));
|
|
||||||
ScaLBL_CopyToDevice(Aq, Aq_tmp, 7*Np*sizeof(double));
|
|
||||||
ScaLBL_CopyToDevice(Bq, Bq_tmp, 7*Np*sizeof(double));
|
|
||||||
|
|
||||||
return(mass_loss);
|
|
||||||
}
|
|
||||||
|
|
||||||
double ScaLBL_ColorModel::MorphInit(const double beta, const double target_delta_volume){
|
|
||||||
const RankInfoStruct rank_info(rank,nprocx,nprocy,nprocz);
|
|
||||||
|
|
||||||
double vF = 0.f;
|
|
||||||
double vS = 0.f;
|
|
||||||
double delta_volume;
|
|
||||||
double WallFactor = 1.0;
|
|
||||||
bool USE_CONNECTED_NWP = false;
|
|
||||||
|
|
||||||
DoubleArray phase(Nx,Ny,Nz);
|
|
||||||
IntArray phase_label(Nx,Ny,Nz);;
|
|
||||||
DoubleArray phase_distance(Nx,Ny,Nz);
|
|
||||||
Array<char> phase_id(Nx,Ny,Nz);
|
|
||||||
fillHalo<double> fillDouble(Dm->Comm,Dm->rank_info,{Nx-2,Ny-2,Nz-2},{1,1,1},0,1);
|
|
||||||
|
|
||||||
|
|
||||||
// Basic algorithm to
|
|
||||||
// 1. Copy phase field to CPU
|
|
||||||
ScaLBL_CopyToHost(phase.data(), Phi, N*sizeof(double));
|
|
||||||
|
|
||||||
double count = 0.f;
|
|
||||||
for (int k=1; k<Nz-1; k++){
|
|
||||||
for (int j=1; j<Ny-1; j++){
|
|
||||||
for (int i=1; i<Nx-1; i++){
|
|
||||||
if (phase(i,j,k) > 0.f && Averages->SDs(i,j,k) > 0.f) count+=1.f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
double volume_initial = Dm->Comm.sumReduce( count);
|
|
||||||
double PoreVolume = Dm->Volume*Dm->Porosity();
|
|
||||||
/*ensure target isn't an absurdly small fraction of pore volume */
|
|
||||||
if (volume_initial < target_delta_volume*PoreVolume){
|
|
||||||
volume_initial = target_delta_volume*PoreVolume;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
sprintf(LocalRankFilename,"phi_initial.%05i.raw",rank);
|
|
||||||
FILE *INPUT = fopen(LocalRankFilename,"wb");
|
|
||||||
fwrite(phase.data(),8,N,INPUT);
|
|
||||||
fclose(INPUT);
|
|
||||||
*/
|
|
||||||
// 2. Identify connected components of phase field -> phase_label
|
|
||||||
|
|
||||||
double volume_connected = 0.0;
|
|
||||||
double second_biggest = 0.0;
|
|
||||||
if (USE_CONNECTED_NWP){
|
|
||||||
ComputeGlobalBlobIDs(Nx-2,Ny-2,Nz-2,rank_info,phase,Averages->SDs,vF,vS,phase_label,comm);
|
|
||||||
comm.barrier();
|
|
||||||
|
|
||||||
// only operate on component "0"
|
|
||||||
count = 0.0;
|
|
||||||
|
|
||||||
for (int k=0; k<Nz; k++){
|
|
||||||
for (int j=0; j<Ny; j++){
|
|
||||||
for (int i=0; i<Nx; i++){
|
|
||||||
int label = phase_label(i,j,k);
|
|
||||||
if (label == 0 ){
|
|
||||||
phase_id(i,j,k) = 0;
|
|
||||||
count += 1.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
phase_id(i,j,k) = 1;
|
|
||||||
if (label == 1 ){
|
|
||||||
second_biggest += 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
volume_connected = Dm->Comm.sumReduce( count);
|
|
||||||
second_biggest = Dm->Comm.sumReduce( second_biggest);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// use the whole NWP
|
|
||||||
for (int k=0; k<Nz; k++){
|
|
||||||
for (int j=0; j<Ny; j++){
|
|
||||||
for (int i=0; i<Nx; i++){
|
|
||||||
if (Averages->SDs(i,j,k) > 0.f){
|
|
||||||
if (phase(i,j,k) > 0.f ){
|
|
||||||
phase_id(i,j,k) = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
phase_id(i,j,k) = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
phase_id(i,j,k) = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*int reach_x, reach_y, reach_z;
|
|
||||||
for (int k=0; k<Nz; k++){
|
|
||||||
for (int j=0; j<Ny; j++){
|
|
||||||
for (int i=0; i<Nx; i++){
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// 3. Generate a distance map to the largest object -> phase_distance
|
|
||||||
CalcDist(phase_distance,phase_id,*Dm);
|
|
||||||
|
|
||||||
double temp,value;
|
|
||||||
double factor=0.5/beta;
|
|
||||||
for (int k=0; k<Nz; k++){
|
|
||||||
for (int j=0; j<Ny; j++){
|
|
||||||
for (int i=0; i<Nx; i++){
|
|
||||||
if (phase_distance(i,j,k) < 3.f ){
|
|
||||||
value = phase(i,j,k);
|
|
||||||
if (value > 1.f) value=1.f;
|
|
||||||
if (value < -1.f) value=-1.f;
|
|
||||||
// temp -- distance based on analytical form McClure, Prins et al, Comp. Phys. Comm.
|
|
||||||
temp = -factor*log((1.0+value)/(1.0-value));
|
|
||||||
/// use this approximation close to the object
|
|
||||||
if (fabs(value) < 0.8 && Averages->SDs(i,j,k) > 1.f ){
|
|
||||||
phase_distance(i,j,k) = temp;
|
|
||||||
}
|
|
||||||
// erase the original object
|
|
||||||
phase(i,j,k) = -1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (USE_CONNECTED_NWP){
|
|
||||||
if (volume_connected - second_biggest < 2.0*fabs(target_delta_volume) && target_delta_volume < 0.0){
|
|
||||||
// if connected volume is less than 2% just delete the whole thing
|
|
||||||
if (rank==0) printf("Connected region has shrunk! \n");
|
|
||||||
REVERSE_FLOW_DIRECTION = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* else{*/
|
|
||||||
if (rank==0) printf("Pathway volume / next largest ganglion %f \n",volume_connected/second_biggest );
|
|
||||||
}
|
|
||||||
if (rank==0) printf("MorphGrow with target volume fraction change %f \n", target_delta_volume/volume_initial);
|
|
||||||
double target_delta_volume_incremental = target_delta_volume;
|
|
||||||
if (fabs(target_delta_volume) > 0.01*volume_initial)
|
|
||||||
target_delta_volume_incremental = 0.01*volume_initial*target_delta_volume/fabs(target_delta_volume);
|
|
||||||
delta_volume = MorphGrow(Averages->SDs,phase_distance,phase_id,Averages->Dm, target_delta_volume_incremental, WallFactor);
|
|
||||||
|
|
||||||
for (int k=0; k<Nz; k++){
|
|
||||||
for (int j=0; j<Ny; j++){
|
|
||||||
for (int i=0; i<Nx; i++){
|
|
||||||
if (phase_distance(i,j,k) < 0.0 ) phase_id(i,j,k) = 0;
|
|
||||||
else phase_id(i,j,k) = 1;
|
|
||||||
//if (phase_distance(i,j,k) < 0.0 ) phase(i,j,k) = 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CalcDist(phase_distance,phase_id,*Dm); // re-calculate distance
|
|
||||||
|
|
||||||
// 5. Update phase indicator field based on new distnace
|
|
||||||
for (int k=0; k<Nz; k++){
|
|
||||||
for (int j=0; j<Ny; j++){
|
|
||||||
for (int i=0; i<Nx; i++){
|
|
||||||
double d = phase_distance(i,j,k);
|
|
||||||
if (Averages->SDs(i,j,k) > 0.f){
|
|
||||||
if (d < 3.f){
|
|
||||||
//phase(i,j,k) = -1.0;
|
|
||||||
phase(i,j,k) = (2.f*(exp(-2.f*beta*d))/(1.f+exp(-2.f*beta*d))-1.f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fillDouble.fill(phase);
|
|
||||||
//}
|
|
||||||
|
|
||||||
count = 0.f;
|
|
||||||
for (int k=1; k<Nz-1; k++){
|
|
||||||
for (int j=1; j<Ny-1; j++){
|
|
||||||
for (int i=1; i<Nx-1; i++){
|
|
||||||
if (phase(i,j,k) > 0.f && Averages->SDs(i,j,k) > 0.f){
|
|
||||||
count+=1.f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
double volume_final= Dm->Comm.sumReduce( count);
|
|
||||||
|
|
||||||
delta_volume = (volume_final-volume_initial);
|
|
||||||
if (rank == 0) printf("MorphInit: change fluid volume fraction by %f \n", delta_volume/volume_initial);
|
|
||||||
if (rank == 0) printf(" new saturation = %f \n", volume_final/(Mask->Porosity()*double((Nx-2)*(Ny-2)*(Nz-2)*nprocs)));
|
|
||||||
|
|
||||||
// 6. copy back to the device
|
|
||||||
//if (rank==0) printf("MorphInit: copy data back to device\n");
|
|
||||||
ScaLBL_CopyToDevice(Phi,phase.data(),N*sizeof(double));
|
|
||||||
/*
|
|
||||||
sprintf(LocalRankFilename,"dist_final.%05i.raw",rank);
|
|
||||||
FILE *DIST = fopen(LocalRankFilename,"wb");
|
|
||||||
fwrite(phase_distance.data(),8,N,DIST);
|
|
||||||
fclose(DIST);
|
|
||||||
|
|
||||||
sprintf(LocalRankFilename,"phi_final.%05i.raw",rank);
|
|
||||||
FILE *PHI = fopen(LocalRankFilename,"wb");
|
|
||||||
fwrite(phase.data(),8,N,PHI);
|
|
||||||
fclose(PHI);
|
|
||||||
*/
|
|
||||||
// 7. Re-initialize phase field and density
|
|
||||||
ScaLBL_PhaseField_Init(dvcMap, Phi, Den, Aq, Bq, 0, ScaLBL_Comm->LastExterior(), Np);
|
|
||||||
ScaLBL_PhaseField_Init(dvcMap, Phi, Den, Aq, Bq, ScaLBL_Comm->FirstInterior(), ScaLBL_Comm->LastInterior(), Np);
|
|
||||||
if (BoundaryCondition == 1 || BoundaryCondition == 2 || BoundaryCondition == 3 || BoundaryCondition == 4){
|
|
||||||
if (Dm->kproc()==0){
|
|
||||||
ScaLBL_SetSlice_z(Phi,1.0,Nx,Ny,Nz,0);
|
|
||||||
ScaLBL_SetSlice_z(Phi,1.0,Nx,Ny,Nz,1);
|
|
||||||
ScaLBL_SetSlice_z(Phi,1.0,Nx,Ny,Nz,2);
|
|
||||||
}
|
|
||||||
if (Dm->kproc() == nprocz-1){
|
|
||||||
ScaLBL_SetSlice_z(Phi,-1.0,Nx,Ny,Nz,Nz-1);
|
|
||||||
ScaLBL_SetSlice_z(Phi,-1.0,Nx,Ny,Nz,Nz-2);
|
|
||||||
ScaLBL_SetSlice_z(Phi,-1.0,Nx,Ny,Nz,Nz-3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return delta_volume;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScaLBL_ColorModel::WriteDebug(){
|
void ScaLBL_ColorModel::WriteDebug(){
|
||||||
// Copy back final phase indicator field and convert to regular layout
|
// Copy back final phase indicator field and convert to regular layout
|
||||||
DoubleArray PhaseField(Nx,Ny,Nz);
|
DoubleArray PhaseField(Nx,Ny,Nz);
|
||||||
|
@ -37,21 +37,78 @@ Implementation of color lattice boltzmann model
|
|||||||
#ifndef ScaLBL_ColorModel_INC
|
#ifndef ScaLBL_ColorModel_INC
|
||||||
#define ScaLBL_ColorModel_INC
|
#define ScaLBL_ColorModel_INC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class ScaLBL_ColorModel
|
||||||
|
*
|
||||||
|
* @details
|
||||||
|
* The ScaLBL_ColorModel class contains routines to initialize and run a two-component color lattice Boltzmann model
|
||||||
|
* Momentum transport equations are described by a D3Q19 scheme
|
||||||
|
* Mass transport equations are described by D3Q7 scheme
|
||||||
|
*/
|
||||||
|
|
||||||
class ScaLBL_ColorModel{
|
class ScaLBL_ColorModel{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* \brief Constructor
|
||||||
|
* @param RANK processor rank
|
||||||
|
* @param NP number of processors
|
||||||
|
* @param COMM MPI communicator
|
||||||
|
*/
|
||||||
ScaLBL_ColorModel(int RANK, int NP, const Utilities::MPI& COMM);
|
ScaLBL_ColorModel(int RANK, int NP, const Utilities::MPI& COMM);
|
||||||
~ScaLBL_ColorModel();
|
~ScaLBL_ColorModel();
|
||||||
|
|
||||||
// functions in they should be run
|
/**
|
||||||
|
* \brief Read simulation parameters
|
||||||
|
* @param filename input database file that includes "Color" section
|
||||||
|
*/
|
||||||
void ReadParams(string filename);
|
void ReadParams(string filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Read simulation parameters
|
||||||
|
* @param db0 input database that includes "Color" section
|
||||||
|
*/
|
||||||
void ReadParams(std::shared_ptr<Database> db0);
|
void ReadParams(std::shared_ptr<Database> db0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Create domain data structures
|
||||||
|
*/
|
||||||
void SetDomain();
|
void SetDomain();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Read image data
|
||||||
|
*/
|
||||||
void ReadInput();
|
void ReadInput();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Create color model data structures
|
||||||
|
*/
|
||||||
void Create();
|
void Create();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize the simulation
|
||||||
|
*/
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Run the simulation
|
||||||
|
*/
|
||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Run the simulation
|
||||||
|
* @param returntime - timestep at which the routine will return
|
||||||
|
*/
|
||||||
double Run(int returntime);
|
double Run(int returntime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Debugging function to dump simulation state to disk
|
||||||
|
*/
|
||||||
void WriteDebug();
|
void WriteDebug();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Copy the phase field for use by external methods
|
||||||
|
* @param f - DoubleArray to hold the phase field
|
||||||
|
*/
|
||||||
void getPhaseField(DoubleArray &f);
|
void getPhaseField(DoubleArray &f);
|
||||||
|
|
||||||
bool Restart,pBC;
|
bool Restart,pBC;
|
||||||
@ -90,6 +147,9 @@ public:
|
|||||||
double *Velocity;
|
double *Velocity;
|
||||||
double *Pressure;
|
double *Pressure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assign wetting affinity values
|
||||||
|
*/
|
||||||
void AssignComponentLabels(double *phase);
|
void AssignComponentLabels(double *phase);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -104,10 +164,6 @@ private:
|
|||||||
|
|
||||||
//int rank,nprocs;
|
//int rank,nprocs;
|
||||||
void LoadParams(std::shared_ptr<Database> db0);
|
void LoadParams(std::shared_ptr<Database> db0);
|
||||||
double ImageInit(std::string filename);
|
|
||||||
double MorphInit(const double beta, const double morph_delta);
|
|
||||||
double SeedPhaseField(const double seed_water_in_oil);
|
|
||||||
double MorphOpenConnected(double target_volume_change);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,7 +54,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
pmmc_MeshGradient(SDs,SDs_x,SDs_y,SDs_z,Nx,Ny,Nz);
|
pmmc_MeshGradient(SDs,SDs_x,SDs_y,SDs_z,Nx,Ny,Nz);
|
||||||
|
|
||||||
DECL object;
|
DCEL object;
|
||||||
Point P1,P2,P3;
|
Point P1,P2,P3;
|
||||||
Point U,V,W;
|
Point U,V,W;
|
||||||
int e1,e2,e3;
|
int e1,e2,e3;
|
||||||
|
Loading…
Reference in New Issue
Block a user