Clang format (#55)

Run clang-format on modules of code
This commit is contained in:
Thomas Ramstad 2021-11-08 22:58:37 +01:00 committed by GitHub
parent f29ae0b0bc
commit 23189f5577
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
104 changed files with 56746 additions and 49196 deletions

View File

@ -1,108 +1,13 @@
# To run clang tools: # clang-format
# cd to root directory
# To update format only:
# find . -name "*.cpp" -or -name "*.cc" -or -name "*.h" -or -name "*.hpp" -or -name "*.I" | xargs -I{} clang-format -i {}
# git status -s . | sed s/^...// | grep -E "(\.cpp|\.h|\.cc|\.hpp|\.I)" | xargs -I{} clang-format -i {}
# To run modernize
# export CLANG_PATH=/packages/llvm/build/llvm-60
# export PATH=${CLANG_PATH}/bin:${CLANG_PATH}/share/clang:$PATH
# find src -name "*.cpp" -or -name "*.cc" | xargs -I{} clang-tidy -checks=modernize* -p=/projects/AtomicModel/build/debug -fix {}
# find src -name "*.cpp" -or -name "*.cc" -or -name "*.h" -or -name "*.hpp" -or -name "*.I" | xargs -I{} clang-format -i {}
--- ---
Language: Cpp Language: Cpp
# BasedOnStyle: LLVM BasedOnStyle: LLVM
AccessModifierOffset: -4 AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign IndentWidth: 4
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: true
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
#BreakBeforeBraces: Stroustrup
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: true
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: Never
...
# Our includes are not order-agnostic
SortIncludes: false
# Some of our comments include insightful insight
ReflowComments: false
...

View File

@ -1,150 +1,177 @@
#include "analysis/ElectroChemistry.h" #include "analysis/ElectroChemistry.h"
ElectroChemistryAnalyzer::ElectroChemistryAnalyzer(std::shared_ptr<Domain> dm)
: Dm(dm) {
ElectroChemistryAnalyzer::ElectroChemistryAnalyzer(std::shared_ptr <Domain> dm): Nx = dm->Nx;
Dm(dm) Ny = dm->Ny;
{ Nz = dm->Nz;
Volume = (Nx - 2) * (Ny - 2) * (Nz - 2) * Dm->nprocx() * Dm->nprocy() *
Nx=dm->Nx; Ny=dm->Ny; Nz=dm->Nz; Dm->nprocz() * 1.0;
Volume=(Nx-2)*(Ny-2)*(Nz-2)*Dm->nprocx()*Dm->nprocy()*Dm->nprocz()*1.0;
ChemicalPotential.resize(Nx,Ny,Nz); ChemicalPotential.fill(0);
ElectricalPotential.resize(Nx,Ny,Nz); ElectricalPotential.fill(0);
ElectricalField_x.resize(Nx,Ny,Nz); ElectricalField_x.fill(0);
ElectricalField_y.resize(Nx,Ny,Nz); ElectricalField_y.fill(0);
ElectricalField_z.resize(Nx,Ny,Nz); ElectricalField_z.fill(0);
Pressure.resize(Nx,Ny,Nz); Pressure.fill(0);
Rho.resize(Nx,Ny,Nz); Rho.fill(0);
Vel_x.resize(Nx,Ny,Nz); Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx,Ny,Nz); Vel_y.fill(0);
Vel_z.resize(Nx,Ny,Nz); Vel_z.fill(0);
SDs.resize(Nx,Ny,Nz); SDs.fill(0);
IonFluxDiffusive_x.resize(Nx,Ny,Nz); IonFluxDiffusive_x.fill(0);
IonFluxDiffusive_y.resize(Nx,Ny,Nz); IonFluxDiffusive_y.fill(0);
IonFluxDiffusive_z.resize(Nx,Ny,Nz); IonFluxDiffusive_z.fill(0);
IonFluxAdvective_x.resize(Nx,Ny,Nz); IonFluxAdvective_x.fill(0);
IonFluxAdvective_y.resize(Nx,Ny,Nz); IonFluxAdvective_y.fill(0);
IonFluxAdvective_z.resize(Nx,Ny,Nz); IonFluxAdvective_z.fill(0);
IonFluxElectrical_x.resize(Nx,Ny,Nz); IonFluxElectrical_x.fill(0);
IonFluxElectrical_y.resize(Nx,Ny,Nz); IonFluxElectrical_y.fill(0);
IonFluxElectrical_z.resize(Nx,Ny,Nz); IonFluxElectrical_z.fill(0);
if (Dm->rank()==0){ ChemicalPotential.resize(Nx, Ny, Nz);
bool WriteHeader=false; ChemicalPotential.fill(0);
TIMELOG = fopen("electrokinetic.csv","r"); ElectricalPotential.resize(Nx, Ny, Nz);
if (TIMELOG != NULL) ElectricalPotential.fill(0);
fclose(TIMELOG); ElectricalField_x.resize(Nx, Ny, Nz);
else ElectricalField_x.fill(0);
WriteHeader=true; ElectricalField_y.resize(Nx, Ny, Nz);
ElectricalField_y.fill(0);
ElectricalField_z.resize(Nx, Ny, Nz);
ElectricalField_z.fill(0);
Pressure.resize(Nx, Ny, Nz);
Pressure.fill(0);
Rho.resize(Nx, Ny, Nz);
Rho.fill(0);
Vel_x.resize(Nx, Ny, Nz);
Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx, Ny, Nz);
Vel_y.fill(0);
Vel_z.resize(Nx, Ny, Nz);
Vel_z.fill(0);
SDs.resize(Nx, Ny, Nz);
SDs.fill(0);
IonFluxDiffusive_x.resize(Nx, Ny, Nz);
IonFluxDiffusive_x.fill(0);
IonFluxDiffusive_y.resize(Nx, Ny, Nz);
IonFluxDiffusive_y.fill(0);
IonFluxDiffusive_z.resize(Nx, Ny, Nz);
IonFluxDiffusive_z.fill(0);
IonFluxAdvective_x.resize(Nx, Ny, Nz);
IonFluxAdvective_x.fill(0);
IonFluxAdvective_y.resize(Nx, Ny, Nz);
IonFluxAdvective_y.fill(0);
IonFluxAdvective_z.resize(Nx, Ny, Nz);
IonFluxAdvective_z.fill(0);
IonFluxElectrical_x.resize(Nx, Ny, Nz);
IonFluxElectrical_x.fill(0);
IonFluxElectrical_y.resize(Nx, Ny, Nz);
IonFluxElectrical_y.fill(0);
IonFluxElectrical_z.resize(Nx, Ny, Nz);
IonFluxElectrical_z.fill(0);
TIMELOG = fopen("electrokinetic.csv","a+"); if (Dm->rank() == 0) {
if (WriteHeader) bool WriteHeader = false;
{ TIMELOG = fopen("electrokinetic.csv", "r");
// If timelog is empty, write a short header to list the averages if (TIMELOG != NULL)
//fprintf(TIMELOG,"--------------------------------------------------------------------------------------\n"); fclose(TIMELOG);
fprintf(TIMELOG,"TBD TBD\n"); else
} WriteHeader = true;
}
TIMELOG = fopen("electrokinetic.csv", "a+");
if (WriteHeader) {
// If timelog is empty, write a short header to list the averages
//fprintf(TIMELOG,"--------------------------------------------------------------------------------------\n");
fprintf(TIMELOG, "TBD TBD\n");
}
}
} }
ElectroChemistryAnalyzer::~ElectroChemistryAnalyzer(){ ElectroChemistryAnalyzer::~ElectroChemistryAnalyzer() {
if (Dm->rank()==0){ if (Dm->rank() == 0) {
fclose(TIMELOG); fclose(TIMELOG);
} }
} }
void ElectroChemistryAnalyzer::SetParams(){ void ElectroChemistryAnalyzer::SetParams() {}
}
void ElectroChemistryAnalyzer::Basic(ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poisson, ScaLBL_StokesModel &Stokes, int timestep){ void ElectroChemistryAnalyzer::Basic(ScaLBL_IonModel &Ion,
ScaLBL_Poisson &Poisson,
ScaLBL_StokesModel &Stokes, int timestep) {
int i,j,k; int i, j, k;
double Vin=0.0; double Vin = 0.0;
double Vout=0.0; double Vout = 0.0;
Poisson.getElectricPotential(ElectricalPotential); Poisson.getElectricPotential(ElectricalPotential);
/* local sub-domain averages */
double *rho_avg_local;
double *rho_mu_avg_local;
double *rho_mu_fluctuation_local;
double *rho_psi_avg_local;
double *rho_psi_fluctuation_local;
/* global averages */
double *rho_avg_global;
double *rho_mu_avg_global;
double *rho_mu_fluctuation_global;
double *rho_psi_avg_global;
double *rho_psi_fluctuation_global;
/* local sub-domain averages */
rho_avg_local = new double [Ion.number_ion_species];
rho_mu_avg_local = new double [Ion.number_ion_species];
rho_mu_fluctuation_local = new double [Ion.number_ion_species];
rho_psi_avg_local = new double [Ion.number_ion_species];
rho_psi_fluctuation_local = new double [Ion.number_ion_species];
/* global averages */
rho_avg_global = new double [Ion.number_ion_species];
rho_mu_avg_global = new double [Ion.number_ion_species];
rho_mu_fluctuation_global = new double [Ion.number_ion_species];
rho_psi_avg_global = new double [Ion.number_ion_species];
rho_psi_fluctuation_global = new double [Ion.number_ion_species];
for (size_t ion=0; ion<Ion.number_ion_species; ion++){
rho_avg_local[ion] = 0.0;
rho_mu_avg_local[ion] = 0.0;
rho_psi_avg_local[ion] = 0.0;
Ion.getIonConcentration(Rho,ion);
/* Compute averages for each ion */
for (k=1; k<Nz; k++){
for (j=1; j<Ny; j++){
for (i=1; i<Nx; i++){
rho_avg_local[ion] += Rho(i,j,k);
rho_mu_avg_local[ion] += Rho(i,j,k)*Rho(i,j,k);
rho_psi_avg_local[ion] += Rho(i,j,k)*ElectricalPotential(i,j,k);
}
}
}
rho_avg_global[ion]=Dm->Comm.sumReduce( rho_avg_local[ion]) / Volume;
rho_mu_avg_global[ion]=Dm->Comm.sumReduce( rho_mu_avg_local[ion]) / Volume;
rho_psi_avg_global[ion]=Dm->Comm.sumReduce( rho_psi_avg_local[ion]) / Volume;
if (rho_avg_global[ion] > 0.0){ /* local sub-domain averages */
rho_mu_avg_global[ion] /= rho_avg_global[ion]; double *rho_avg_local;
rho_psi_avg_global[ion] /= rho_avg_global[ion]; double *rho_mu_avg_local;
} double *rho_mu_fluctuation_local;
} double *rho_psi_avg_local;
double *rho_psi_fluctuation_local;
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ /* global averages */
rho_mu_fluctuation_local[ion] = 0.0; double *rho_avg_global;
rho_psi_fluctuation_local[ion] = 0.0; double *rho_mu_avg_global;
/* Compute averages for each ion */ double *rho_mu_fluctuation_global;
for (k=1; k<Nz; k++){ double *rho_psi_avg_global;
for (j=1; j<Ny; j++){ double *rho_psi_fluctuation_global;
for (i=1; i<Nx; i++){
rho_mu_fluctuation_local[ion] += (Rho(i,j,k)*Rho(i,j,k) - rho_mu_avg_global[ion]); /* local sub-domain averages */
rho_psi_fluctuation_local[ion] += (Rho(i,j,k)*ElectricalPotential(i,j,k) - rho_psi_avg_global[ion]); rho_avg_local = new double[Ion.number_ion_species];
} rho_mu_avg_local = new double[Ion.number_ion_species];
} rho_mu_fluctuation_local = new double[Ion.number_ion_species];
} rho_psi_avg_local = new double[Ion.number_ion_species];
rho_mu_fluctuation_global[ion]=Dm->Comm.sumReduce( rho_mu_fluctuation_local[ion]); rho_psi_fluctuation_local = new double[Ion.number_ion_species];
rho_psi_fluctuation_global[ion]=Dm->Comm.sumReduce( rho_psi_fluctuation_local[ion]); /* global averages */
} rho_avg_global = new double[Ion.number_ion_species];
rho_mu_avg_global = new double[Ion.number_ion_species];
if (Dm->rank()==0){ rho_mu_fluctuation_global = new double[Ion.number_ion_species];
fprintf(TIMELOG,"%i ",timestep); rho_psi_avg_global = new double[Ion.number_ion_species];
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ rho_psi_fluctuation_global = new double[Ion.number_ion_species];
fprintf(TIMELOG,"%.8g ",rho_avg_global[ion]);
fprintf(TIMELOG,"%.8g ",rho_mu_avg_global[ion]); for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
fprintf(TIMELOG,"%.8g ",rho_psi_avg_global[ion]); rho_avg_local[ion] = 0.0;
fprintf(TIMELOG,"%.8g ",rho_mu_fluctuation_global[ion]); rho_mu_avg_local[ion] = 0.0;
fprintf(TIMELOG,"%.8g ",rho_psi_fluctuation_global[ion]); rho_psi_avg_local[ion] = 0.0;
} Ion.getIonConcentration(Rho, ion);
fprintf(TIMELOG,"%.8g %.8g\n",Vin,Vout); /* Compute averages for each ion */
fflush(TIMELOG); for (k = 1; k < Nz; k++) {
} for (j = 1; j < Ny; j++) {
/* else{ for (i = 1; i < Nx; i++) {
rho_avg_local[ion] += Rho(i, j, k);
rho_mu_avg_local[ion] += Rho(i, j, k) * Rho(i, j, k);
rho_psi_avg_local[ion] +=
Rho(i, j, k) * ElectricalPotential(i, j, k);
}
}
}
rho_avg_global[ion] = Dm->Comm.sumReduce(rho_avg_local[ion]) / Volume;
rho_mu_avg_global[ion] =
Dm->Comm.sumReduce(rho_mu_avg_local[ion]) / Volume;
rho_psi_avg_global[ion] =
Dm->Comm.sumReduce(rho_psi_avg_local[ion]) / Volume;
if (rho_avg_global[ion] > 0.0) {
rho_mu_avg_global[ion] /= rho_avg_global[ion];
rho_psi_avg_global[ion] /= rho_avg_global[ion];
}
}
for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
rho_mu_fluctuation_local[ion] = 0.0;
rho_psi_fluctuation_local[ion] = 0.0;
/* Compute averages for each ion */
for (k = 1; k < Nz; k++) {
for (j = 1; j < Ny; j++) {
for (i = 1; i < Nx; i++) {
rho_mu_fluctuation_local[ion] +=
(Rho(i, j, k) * Rho(i, j, k) - rho_mu_avg_global[ion]);
rho_psi_fluctuation_local[ion] +=
(Rho(i, j, k) * ElectricalPotential(i, j, k) -
rho_psi_avg_global[ion]);
}
}
}
rho_mu_fluctuation_global[ion] =
Dm->Comm.sumReduce(rho_mu_fluctuation_local[ion]);
rho_psi_fluctuation_global[ion] =
Dm->Comm.sumReduce(rho_psi_fluctuation_local[ion]);
}
if (Dm->rank() == 0) {
fprintf(TIMELOG, "%i ", timestep);
for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
fprintf(TIMELOG, "%.8g ", rho_avg_global[ion]);
fprintf(TIMELOG, "%.8g ", rho_mu_avg_global[ion]);
fprintf(TIMELOG, "%.8g ", rho_psi_avg_global[ion]);
fprintf(TIMELOG, "%.8g ", rho_mu_fluctuation_global[ion]);
fprintf(TIMELOG, "%.8g ", rho_psi_fluctuation_global[ion]);
}
fprintf(TIMELOG, "%.8g %.8g\n", Vin, Vout);
fflush(TIMELOG);
}
/* else{
fprintf(TIMELOG,"%i ",timestep); fprintf(TIMELOG,"%i ",timestep);
for (int ion=0; ion<Ion.number_ion_species; ion++){ for (int ion=0; ion<Ion.number_ion_species; ion++){
fprintf(TIMELOG,"%.8g ",rho_avg_local[ion]); fprintf(TIMELOG,"%.8g ",rho_avg_local[ion]);
@ -157,20 +184,28 @@ void ElectroChemistryAnalyzer::Basic(ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poiss
} */ } */
} }
void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poisson, ScaLBL_StokesModel &Stokes, std::shared_ptr<Database> input_db, int timestep){ void ElectroChemistryAnalyzer::WriteVis(ScaLBL_IonModel &Ion,
ScaLBL_Poisson &Poisson,
auto vis_db = input_db->getDatabase( "Visualization" ); ScaLBL_StokesModel &Stokes,
char VisName[40]; std::shared_ptr<Database> input_db,
int timestep) {
std::vector<IO::MeshDataStruct> visData;
fillHalo<double> fillData(Dm->Comm,Dm->rank_info,{Dm->Nx-2,Dm->Ny-2,Dm->Nz-2},{1,1,1},0,1);
IO::initialize("","silo","false"); auto vis_db = input_db->getDatabase("Visualization");
// Create the MeshDataStruct char VisName[40];
std::vector<IO::MeshDataStruct> visData;
fillHalo<double> fillData(Dm->Comm, Dm->rank_info,
{Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2}, {1, 1, 1},
0, 1);
IO::initialize("", "silo", "false");
// Create the MeshDataStruct
visData.resize(1); visData.resize(1);
visData[0].meshName = "domain"; visData[0].meshName = "domain";
visData[0].mesh = std::make_shared<IO::DomainMesh>( Dm->rank_info,Dm->Nx-2,Dm->Ny-2,Dm->Nz-2,Dm->Lx,Dm->Ly,Dm->Lz ); visData[0].mesh =
std::make_shared<IO::DomainMesh>(Dm->rank_info, Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2, Dm->Lx, Dm->Ly, Dm->Lz);
//electric potential //electric potential
auto ElectricPotentialVar = std::make_shared<IO::Variable>(); auto ElectricPotentialVar = std::make_shared<IO::Variable>();
//electric field //electric field
@ -180,7 +215,7 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
//ion concentration //ion concentration
std::vector<shared_ptr<IO::Variable>> IonConcentration; std::vector<shared_ptr<IO::Variable>> IonConcentration;
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
IonConcentration.push_back(std::make_shared<IO::Variable>()); IonConcentration.push_back(std::make_shared<IO::Variable>());
} }
//fluid velocity //fluid velocity
@ -189,7 +224,7 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
auto VzVar = std::make_shared<IO::Variable>(); auto VzVar = std::make_shared<IO::Variable>();
// diffusive ion flux // diffusive ion flux
std::vector<shared_ptr<IO::Variable>> IonFluxDiffusive; std::vector<shared_ptr<IO::Variable>> IonFluxDiffusive;
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
//push in x-,y-, and z-component for each ion species //push in x-,y-, and z-component for each ion species
IonFluxDiffusive.push_back(std::make_shared<IO::Variable>()); IonFluxDiffusive.push_back(std::make_shared<IO::Variable>());
IonFluxDiffusive.push_back(std::make_shared<IO::Variable>()); IonFluxDiffusive.push_back(std::make_shared<IO::Variable>());
@ -197,7 +232,7 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
} }
// advective ion flux // advective ion flux
std::vector<shared_ptr<IO::Variable>> IonFluxAdvective; std::vector<shared_ptr<IO::Variable>> IonFluxAdvective;
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
//push in x-,y-, and z-component for each ion species //push in x-,y-, and z-component for each ion species
IonFluxAdvective.push_back(std::make_shared<IO::Variable>()); IonFluxAdvective.push_back(std::make_shared<IO::Variable>());
IonFluxAdvective.push_back(std::make_shared<IO::Variable>()); IonFluxAdvective.push_back(std::make_shared<IO::Variable>());
@ -205,7 +240,7 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
} }
// electro-migrational ion flux // electro-migrational ion flux
std::vector<shared_ptr<IO::Variable>> IonFluxElectrical; std::vector<shared_ptr<IO::Variable>> IonFluxElectrical;
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
//push in x-,y-, and z-component for each ion species //push in x-,y-, and z-component for each ion species
IonFluxElectrical.push_back(std::make_shared<IO::Variable>()); IonFluxElectrical.push_back(std::make_shared<IO::Variable>());
IonFluxElectrical.push_back(std::make_shared<IO::Variable>()); IonFluxElectrical.push_back(std::make_shared<IO::Variable>());
@ -214,270 +249,348 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
//-------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------
//-------------------------------------Create Names for Variables------------------------------------------------------ //-------------------------------------Create Names for Variables------------------------------------------------------
if (vis_db->getWithDefault<bool>( "save_electric_potential", true )){ if (vis_db->getWithDefault<bool>("save_electric_potential", true)) {
ElectricPotentialVar->name = "ElectricPotential"; ElectricPotentialVar->name = "ElectricPotential";
ElectricPotentialVar->type = IO::VariableType::VolumeVariable; ElectricPotentialVar->type = IO::VariableType::VolumeVariable;
ElectricPotentialVar->dim = 1; ElectricPotentialVar->dim = 1;
ElectricPotentialVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); ElectricPotentialVar->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(ElectricPotentialVar); visData[0].vars.push_back(ElectricPotentialVar);
} }
if (vis_db->getWithDefault<bool>( "save_concentration", true )){ if (vis_db->getWithDefault<bool>("save_concentration", true)) {
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
sprintf(VisName,"IonConcentration_%zu",ion+1); sprintf(VisName, "IonConcentration_%zu", ion + 1);
IonConcentration[ion]->name = VisName; IonConcentration[ion]->name = VisName;
IonConcentration[ion]->type = IO::VariableType::VolumeVariable; IonConcentration[ion]->type = IO::VariableType::VolumeVariable;
IonConcentration[ion]->dim = 1; IonConcentration[ion]->dim = 1;
IonConcentration[ion]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); IonConcentration[ion]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
visData[0].vars.push_back(IonConcentration[ion]); Dm->Nz - 2);
} visData[0].vars.push_back(IonConcentration[ion]);
}
} }
if (vis_db->getWithDefault<bool>( "save_velocity", false )){ if (vis_db->getWithDefault<bool>("save_velocity", false)) {
VxVar->name = "Velocity_x"; VxVar->name = "Velocity_x";
VxVar->type = IO::VariableType::VolumeVariable; VxVar->type = IO::VariableType::VolumeVariable;
VxVar->dim = 1; VxVar->dim = 1;
VxVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); VxVar->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(VxVar); visData[0].vars.push_back(VxVar);
VyVar->name = "Velocity_y"; VyVar->name = "Velocity_y";
VyVar->type = IO::VariableType::VolumeVariable; VyVar->type = IO::VariableType::VolumeVariable;
VyVar->dim = 1; VyVar->dim = 1;
VyVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); VyVar->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(VyVar); visData[0].vars.push_back(VyVar);
VzVar->name = "Velocity_z"; VzVar->name = "Velocity_z";
VzVar->type = IO::VariableType::VolumeVariable; VzVar->type = IO::VariableType::VolumeVariable;
VzVar->dim = 1; VzVar->dim = 1;
VzVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); VzVar->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(VzVar); visData[0].vars.push_back(VzVar);
} }
if (vis_db->getWithDefault<bool>( "save_ion_flux_diffusive", false )){ if (vis_db->getWithDefault<bool>("save_ion_flux_diffusive", false)) {
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
// x-component of diffusive flux // x-component of diffusive flux
sprintf(VisName,"Ion%zu_FluxDiffusive_x",ion+1); sprintf(VisName, "Ion%zu_FluxDiffusive_x", ion + 1);
IonFluxDiffusive[3*ion+0]->name = VisName; IonFluxDiffusive[3 * ion + 0]->name = VisName;
IonFluxDiffusive[3*ion+0]->type = IO::VariableType::VolumeVariable; IonFluxDiffusive[3 * ion + 0]->type =
IonFluxDiffusive[3*ion+0]->dim = 1; IO::VariableType::VolumeVariable;
IonFluxDiffusive[3*ion+0]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); IonFluxDiffusive[3 * ion + 0]->dim = 1;
visData[0].vars.push_back(IonFluxDiffusive[3*ion+0]); IonFluxDiffusive[3 * ion + 0]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxDiffusive[3 * ion + 0]);
// y-component of diffusive flux // y-component of diffusive flux
sprintf(VisName,"Ion%zu_FluxDiffusive_y",ion+1); sprintf(VisName, "Ion%zu_FluxDiffusive_y", ion + 1);
IonFluxDiffusive[3*ion+1]->name = VisName; IonFluxDiffusive[3 * ion + 1]->name = VisName;
IonFluxDiffusive[3*ion+1]->type = IO::VariableType::VolumeVariable; IonFluxDiffusive[3 * ion + 1]->type =
IonFluxDiffusive[3*ion+1]->dim = 1; IO::VariableType::VolumeVariable;
IonFluxDiffusive[3*ion+1]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); IonFluxDiffusive[3 * ion + 1]->dim = 1;
visData[0].vars.push_back(IonFluxDiffusive[3*ion+1]); IonFluxDiffusive[3 * ion + 1]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxDiffusive[3 * ion + 1]);
// z-component of diffusive flux // z-component of diffusive flux
sprintf(VisName,"Ion%zu_FluxDiffusive_z",ion+1); sprintf(VisName, "Ion%zu_FluxDiffusive_z", ion + 1);
IonFluxDiffusive[3*ion+2]->name = VisName; IonFluxDiffusive[3 * ion + 2]->name = VisName;
IonFluxDiffusive[3*ion+2]->type = IO::VariableType::VolumeVariable; IonFluxDiffusive[3 * ion + 2]->type =
IonFluxDiffusive[3*ion+2]->dim = 1; IO::VariableType::VolumeVariable;
IonFluxDiffusive[3*ion+2]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); IonFluxDiffusive[3 * ion + 2]->dim = 1;
visData[0].vars.push_back(IonFluxDiffusive[3*ion+2]); IonFluxDiffusive[3 * ion + 2]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
} Dm->Nz - 2);
visData[0].vars.push_back(IonFluxDiffusive[3 * ion + 2]);
}
} }
if (vis_db->getWithDefault<bool>( "save_ion_flux_advective", false )){ if (vis_db->getWithDefault<bool>("save_ion_flux_advective", false)) {
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
// x-component of advective flux // x-component of advective flux
sprintf(VisName,"Ion%zu_FluxAdvective_x",ion+1); sprintf(VisName, "Ion%zu_FluxAdvective_x", ion + 1);
IonFluxAdvective[3*ion+0]->name = VisName; IonFluxAdvective[3 * ion + 0]->name = VisName;
IonFluxAdvective[3*ion+0]->type = IO::VariableType::VolumeVariable; IonFluxAdvective[3 * ion + 0]->type =
IonFluxAdvective[3*ion+0]->dim = 1; IO::VariableType::VolumeVariable;
IonFluxAdvective[3*ion+0]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); IonFluxAdvective[3 * ion + 0]->dim = 1;
visData[0].vars.push_back(IonFluxAdvective[3*ion+0]); IonFluxAdvective[3 * ion + 0]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxAdvective[3 * ion + 0]);
// y-component of advective flux // y-component of advective flux
sprintf(VisName,"Ion%zu_FluxAdvective_y",ion+1); sprintf(VisName, "Ion%zu_FluxAdvective_y", ion + 1);
IonFluxAdvective[3*ion+1]->name = VisName; IonFluxAdvective[3 * ion + 1]->name = VisName;
IonFluxAdvective[3*ion+1]->type = IO::VariableType::VolumeVariable; IonFluxAdvective[3 * ion + 1]->type =
IonFluxAdvective[3*ion+1]->dim = 1; IO::VariableType::VolumeVariable;
IonFluxAdvective[3*ion+1]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); IonFluxAdvective[3 * ion + 1]->dim = 1;
visData[0].vars.push_back(IonFluxAdvective[3*ion+1]); IonFluxAdvective[3 * ion + 1]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxAdvective[3 * ion + 1]);
// z-component of advective flux // z-component of advective flux
sprintf(VisName,"Ion%zu_FluxAdvective_z",ion+1); sprintf(VisName, "Ion%zu_FluxAdvective_z", ion + 1);
IonFluxAdvective[3*ion+2]->name = VisName; IonFluxAdvective[3 * ion + 2]->name = VisName;
IonFluxAdvective[3*ion+2]->type = IO::VariableType::VolumeVariable; IonFluxAdvective[3 * ion + 2]->type =
IonFluxAdvective[3*ion+2]->dim = 1; IO::VariableType::VolumeVariable;
IonFluxAdvective[3*ion+2]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); IonFluxAdvective[3 * ion + 2]->dim = 1;
visData[0].vars.push_back(IonFluxAdvective[3*ion+2]); IonFluxAdvective[3 * ion + 2]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
} Dm->Nz - 2);
visData[0].vars.push_back(IonFluxAdvective[3 * ion + 2]);
}
} }
if (vis_db->getWithDefault<bool>( "save_ion_flux_electrical", false )){ if (vis_db->getWithDefault<bool>("save_ion_flux_electrical", false)) {
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
// x-component of electro-migrational flux // x-component of electro-migrational flux
sprintf(VisName,"Ion%zu_FluxElectrical_x",ion+1); sprintf(VisName, "Ion%zu_FluxElectrical_x", ion + 1);
IonFluxElectrical[3*ion+0]->name = VisName; IonFluxElectrical[3 * ion + 0]->name = VisName;
IonFluxElectrical[3*ion+0]->type = IO::VariableType::VolumeVariable; IonFluxElectrical[3 * ion + 0]->type =
IonFluxElectrical[3*ion+0]->dim = 1; IO::VariableType::VolumeVariable;
IonFluxElectrical[3*ion+0]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); IonFluxElectrical[3 * ion + 0]->dim = 1;
visData[0].vars.push_back(IonFluxElectrical[3*ion+0]); IonFluxElectrical[3 * ion + 0]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxElectrical[3 * ion + 0]);
// y-component of electro-migrational flux // y-component of electro-migrational flux
sprintf(VisName,"Ion%zu_FluxElectrical_y",ion+1); sprintf(VisName, "Ion%zu_FluxElectrical_y", ion + 1);
IonFluxElectrical[3*ion+1]->name = VisName; IonFluxElectrical[3 * ion + 1]->name = VisName;
IonFluxElectrical[3*ion+1]->type = IO::VariableType::VolumeVariable; IonFluxElectrical[3 * ion + 1]->type =
IonFluxElectrical[3*ion+1]->dim = 1; IO::VariableType::VolumeVariable;
IonFluxElectrical[3*ion+1]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); IonFluxElectrical[3 * ion + 1]->dim = 1;
visData[0].vars.push_back(IonFluxElectrical[3*ion+1]); IonFluxElectrical[3 * ion + 1]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxElectrical[3 * ion + 1]);
// z-component of electro-migrational flux // z-component of electro-migrational flux
sprintf(VisName,"Ion%zu_FluxElectrical_z",ion+1); sprintf(VisName, "Ion%zu_FluxElectrical_z", ion + 1);
IonFluxElectrical[3*ion+2]->name = VisName; IonFluxElectrical[3 * ion + 2]->name = VisName;
IonFluxElectrical[3*ion+2]->type = IO::VariableType::VolumeVariable; IonFluxElectrical[3 * ion + 2]->type =
IonFluxElectrical[3*ion+2]->dim = 1; IO::VariableType::VolumeVariable;
IonFluxElectrical[3*ion+2]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); IonFluxElectrical[3 * ion + 2]->dim = 1;
visData[0].vars.push_back(IonFluxElectrical[3*ion+2]); IonFluxElectrical[3 * ion + 2]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
} Dm->Nz - 2);
visData[0].vars.push_back(IonFluxElectrical[3 * ion + 2]);
}
} }
if (vis_db->getWithDefault<bool>( "save_electric_field", false )){ if (vis_db->getWithDefault<bool>("save_electric_field", false)) {
ElectricFieldVar_x->name = "ElectricField_x"; ElectricFieldVar_x->name = "ElectricField_x";
ElectricFieldVar_x->type = IO::VariableType::VolumeVariable; ElectricFieldVar_x->type = IO::VariableType::VolumeVariable;
ElectricFieldVar_x->dim = 1; ElectricFieldVar_x->dim = 1;
ElectricFieldVar_x->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); ElectricFieldVar_x->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(ElectricFieldVar_x); visData[0].vars.push_back(ElectricFieldVar_x);
ElectricFieldVar_y->name = "ElectricField_y"; ElectricFieldVar_y->name = "ElectricField_y";
ElectricFieldVar_y->type = IO::VariableType::VolumeVariable; ElectricFieldVar_y->type = IO::VariableType::VolumeVariable;
ElectricFieldVar_y->dim = 1; ElectricFieldVar_y->dim = 1;
ElectricFieldVar_y->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); ElectricFieldVar_y->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(ElectricFieldVar_y); visData[0].vars.push_back(ElectricFieldVar_y);
ElectricFieldVar_z->name = "ElectricField_z"; ElectricFieldVar_z->name = "ElectricField_z";
ElectricFieldVar_z->type = IO::VariableType::VolumeVariable; ElectricFieldVar_z->type = IO::VariableType::VolumeVariable;
ElectricFieldVar_z->dim = 1; ElectricFieldVar_z->dim = 1;
ElectricFieldVar_z->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); ElectricFieldVar_z->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(ElectricFieldVar_z); visData[0].vars.push_back(ElectricFieldVar_z);
} }
//-------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------
//------------------------------------Save All Variables-------------------------------------------------------------- //------------------------------------Save All Variables--------------------------------------------------------------
if (vis_db->getWithDefault<bool>( "save_electric_potential", true )){ if (vis_db->getWithDefault<bool>("save_electric_potential", true)) {
ASSERT(visData[0].vars[0]->name=="ElectricPotential"); ASSERT(visData[0].vars[0]->name == "ElectricPotential");
Poisson.getElectricPotential(ElectricalPotential); Poisson.getElectricPotential(ElectricalPotential);
Array<double>& ElectricPotentialData = visData[0].vars[0]->data; Array<double> &ElectricPotentialData = visData[0].vars[0]->data;
fillData.copy(ElectricalPotential,ElectricPotentialData); fillData.copy(ElectricalPotential, ElectricPotentialData);
} }
if (vis_db->getWithDefault<bool>( "save_concentration", true )){ if (vis_db->getWithDefault<bool>("save_concentration", true)) {
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
sprintf(VisName,"IonConcentration_%zu",ion+1); sprintf(VisName, "IonConcentration_%zu", ion + 1);
//IonConcentration[ion]->name = VisName; //IonConcentration[ion]->name = VisName;
ASSERT(visData[0].vars[1+ion]->name==VisName); ASSERT(visData[0].vars[1 + ion]->name == VisName);
Array<double>& IonConcentrationData = visData[0].vars[1+ion]->data; Array<double> &IonConcentrationData =
Ion.getIonConcentration(Rho,ion); visData[0].vars[1 + ion]->data;
fillData.copy(Rho,IonConcentrationData); Ion.getIonConcentration(Rho, ion);
} fillData.copy(Rho, IonConcentrationData);
}
} }
if (vis_db->getWithDefault<bool>( "save_velocity", false )){ if (vis_db->getWithDefault<bool>("save_velocity", false)) {
ASSERT(visData[0].vars[1+Ion.number_ion_species+0]->name=="Velocity_x"); ASSERT(visData[0].vars[1 + Ion.number_ion_species + 0]->name ==
ASSERT(visData[0].vars[1+Ion.number_ion_species+1]->name=="Velocity_y"); "Velocity_x");
ASSERT(visData[0].vars[1+Ion.number_ion_species+2]->name=="Velocity_z"); ASSERT(visData[0].vars[1 + Ion.number_ion_species + 1]->name ==
Stokes.getVelocity(Vel_x,Vel_y,Vel_z); "Velocity_y");
Array<double>& VelxData = visData[0].vars[1+Ion.number_ion_species+0]->data; ASSERT(visData[0].vars[1 + Ion.number_ion_species + 2]->name ==
Array<double>& VelyData = visData[0].vars[1+Ion.number_ion_species+1]->data; "Velocity_z");
Array<double>& VelzData = visData[0].vars[1+Ion.number_ion_species+2]->data; Stokes.getVelocity(Vel_x, Vel_y, Vel_z);
fillData.copy(Vel_x,VelxData); Array<double> &VelxData =
fillData.copy(Vel_y,VelyData); visData[0].vars[1 + Ion.number_ion_species + 0]->data;
fillData.copy(Vel_z,VelzData); Array<double> &VelyData =
visData[0].vars[1 + Ion.number_ion_species + 1]->data;
Array<double> &VelzData =
visData[0].vars[1 + Ion.number_ion_species + 2]->data;
fillData.copy(Vel_x, VelxData);
fillData.copy(Vel_y, VelyData);
fillData.copy(Vel_z, VelzData);
} }
if (vis_db->getWithDefault<bool>( "save_ion_flux_diffusive", false )){ if (vis_db->getWithDefault<bool>("save_ion_flux_diffusive", false)) {
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
// x-component of diffusive flux // x-component of diffusive flux
sprintf(VisName,"Ion%zu_FluxDiffusive_x",ion+1); sprintf(VisName, "Ion%zu_FluxDiffusive_x", ion + 1);
//IonFluxDiffusive[3*ion+0]->name = VisName; //IonFluxDiffusive[3*ion+0]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species+3*ion+0]->name==VisName); ASSERT(visData[0]
.vars[4 + Ion.number_ion_species + 3 * ion + 0]
->name == VisName);
// y-component of diffusive flux // y-component of diffusive flux
sprintf(VisName,"Ion%zu_FluxDiffusive_y",ion+1); sprintf(VisName, "Ion%zu_FluxDiffusive_y", ion + 1);
//IonFluxDiffusive[3*ion+1]->name = VisName; //IonFluxDiffusive[3*ion+1]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species+3*ion+1]->name==VisName); ASSERT(visData[0]
.vars[4 + Ion.number_ion_species + 3 * ion + 1]
->name == VisName);
// z-component of diffusive flux // z-component of diffusive flux
sprintf(VisName,"Ion%zu_FluxDiffusive_z",ion+1); sprintf(VisName, "Ion%zu_FluxDiffusive_z", ion + 1);
//IonFluxDiffusive[3*ion+2]->name = VisName; //IonFluxDiffusive[3*ion+2]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species+3*ion+2]->name==VisName); ASSERT(visData[0]
.vars[4 + Ion.number_ion_species + 3 * ion + 2]
->name == VisName);
Array<double>& IonFluxData_x = visData[0].vars[4+Ion.number_ion_species+3*ion+0]->data; Array<double> &IonFluxData_x =
Array<double>& IonFluxData_y = visData[0].vars[4+Ion.number_ion_species+3*ion+1]->data; visData[0].vars[4 + Ion.number_ion_species + 3 * ion + 0]->data;
Array<double>& IonFluxData_z = visData[0].vars[4+Ion.number_ion_species+3*ion+2]->data; Array<double> &IonFluxData_y =
Ion.getIonFluxDiffusive(IonFluxDiffusive_x,IonFluxDiffusive_y,IonFluxDiffusive_z,ion); visData[0].vars[4 + Ion.number_ion_species + 3 * ion + 1]->data;
fillData.copy(IonFluxDiffusive_x,IonFluxData_x); Array<double> &IonFluxData_z =
fillData.copy(IonFluxDiffusive_y,IonFluxData_y); visData[0].vars[4 + Ion.number_ion_species + 3 * ion + 2]->data;
fillData.copy(IonFluxDiffusive_z,IonFluxData_z); Ion.getIonFluxDiffusive(IonFluxDiffusive_x, IonFluxDiffusive_y,
} IonFluxDiffusive_z, ion);
fillData.copy(IonFluxDiffusive_x, IonFluxData_x);
fillData.copy(IonFluxDiffusive_y, IonFluxData_y);
fillData.copy(IonFluxDiffusive_z, IonFluxData_z);
}
} }
if (vis_db->getWithDefault<bool>( "save_ion_flux_advective", false )){ if (vis_db->getWithDefault<bool>("save_ion_flux_advective", false)) {
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
// x-component of diffusive flux // x-component of diffusive flux
sprintf(VisName,"Ion%zu_FluxAdvective_x",ion+1); sprintf(VisName, "Ion%zu_FluxAdvective_x", ion + 1);
//IonFluxDiffusive[3*ion+0]->name = VisName; //IonFluxDiffusive[3*ion+0]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+3)+3*ion+0]->name==VisName); ASSERT(visData[0]
.vars[4 + Ion.number_ion_species * (1 + 3) + 3 * ion + 0]
->name == VisName);
// y-component of diffusive flux // y-component of diffusive flux
sprintf(VisName,"Ion%zu_FluxAdvective_y",ion+1); sprintf(VisName, "Ion%zu_FluxAdvective_y", ion + 1);
//IonFluxDiffusive[3*ion+1]->name = VisName; //IonFluxDiffusive[3*ion+1]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+3)+3*ion+1]->name==VisName); ASSERT(visData[0]
.vars[4 + Ion.number_ion_species * (1 + 3) + 3 * ion + 1]
->name == VisName);
// z-component of diffusive flux // z-component of diffusive flux
sprintf(VisName,"Ion%zu_FluxAdvective_z",ion+1); sprintf(VisName, "Ion%zu_FluxAdvective_z", ion + 1);
//IonFluxDiffusive[3*ion+2]->name = VisName; //IonFluxDiffusive[3*ion+2]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+3)+3*ion+2]->name==VisName); ASSERT(visData[0]
.vars[4 + Ion.number_ion_species * (1 + 3) + 3 * ion + 2]
->name == VisName);
Array<double>& IonFluxData_x = visData[0].vars[4+Ion.number_ion_species*(1+3)+3*ion+0]->data; Array<double> &IonFluxData_x =
Array<double>& IonFluxData_y = visData[0].vars[4+Ion.number_ion_species*(1+3)+3*ion+1]->data; visData[0]
Array<double>& IonFluxData_z = visData[0].vars[4+Ion.number_ion_species*(1+3)+3*ion+2]->data; .vars[4 + Ion.number_ion_species * (1 + 3) + 3 * ion + 0]
Ion.getIonFluxAdvective(IonFluxAdvective_x,IonFluxAdvective_y,IonFluxAdvective_z,ion); ->data;
fillData.copy(IonFluxAdvective_x,IonFluxData_x); Array<double> &IonFluxData_y =
fillData.copy(IonFluxAdvective_y,IonFluxData_y); visData[0]
fillData.copy(IonFluxAdvective_z,IonFluxData_z); .vars[4 + Ion.number_ion_species * (1 + 3) + 3 * ion + 1]
} ->data;
Array<double> &IonFluxData_z =
visData[0]
.vars[4 + Ion.number_ion_species * (1 + 3) + 3 * ion + 2]
->data;
Ion.getIonFluxAdvective(IonFluxAdvective_x, IonFluxAdvective_y,
IonFluxAdvective_z, ion);
fillData.copy(IonFluxAdvective_x, IonFluxData_x);
fillData.copy(IonFluxAdvective_y, IonFluxData_y);
fillData.copy(IonFluxAdvective_z, IonFluxData_z);
}
} }
if (vis_db->getWithDefault<bool>( "save_ion_flux_electrical", false )){ if (vis_db->getWithDefault<bool>("save_ion_flux_electrical", false)) {
for (size_t ion=0; ion<Ion.number_ion_species; ion++){ for (size_t ion = 0; ion < Ion.number_ion_species; ion++) {
// x-component of diffusive flux // x-component of diffusive flux
sprintf(VisName,"Ion%zu_FluxElectrical_x",ion+1); sprintf(VisName, "Ion%zu_FluxElectrical_x", ion + 1);
//IonFluxDiffusive[3*ion+0]->name = VisName; //IonFluxDiffusive[3*ion+0]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+6)+3*ion+0]->name==VisName); ASSERT(visData[0]
.vars[4 + Ion.number_ion_species * (1 + 6) + 3 * ion + 0]
->name == VisName);
// y-component of diffusive flux // y-component of diffusive flux
sprintf(VisName,"Ion%zu_FluxElectrical_y",ion+1); sprintf(VisName, "Ion%zu_FluxElectrical_y", ion + 1);
//IonFluxDiffusive[3*ion+1]->name = VisName; //IonFluxDiffusive[3*ion+1]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+6)+3*ion+1]->name==VisName); ASSERT(visData[0]
.vars[4 + Ion.number_ion_species * (1 + 6) + 3 * ion + 1]
->name == VisName);
// z-component of diffusive flux // z-component of diffusive flux
sprintf(VisName,"Ion%zu_FluxElectrical_z",ion+1); sprintf(VisName, "Ion%zu_FluxElectrical_z", ion + 1);
//IonFluxDiffusive[3*ion+2]->name = VisName; //IonFluxDiffusive[3*ion+2]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+6)+3*ion+2]->name==VisName); ASSERT(visData[0]
.vars[4 + Ion.number_ion_species * (1 + 6) + 3 * ion + 2]
->name == VisName);
Array<double>& IonFluxData_x = visData[0].vars[4+Ion.number_ion_species*(1+6)+3*ion+0]->data; Array<double> &IonFluxData_x =
Array<double>& IonFluxData_y = visData[0].vars[4+Ion.number_ion_species*(1+6)+3*ion+1]->data; visData[0]
Array<double>& IonFluxData_z = visData[0].vars[4+Ion.number_ion_species*(1+6)+3*ion+2]->data; .vars[4 + Ion.number_ion_species * (1 + 6) + 3 * ion + 0]
Ion.getIonFluxElectrical(IonFluxElectrical_x,IonFluxElectrical_y,IonFluxElectrical_z,ion); ->data;
fillData.copy(IonFluxElectrical_x,IonFluxData_x); Array<double> &IonFluxData_y =
fillData.copy(IonFluxElectrical_y,IonFluxData_y); visData[0]
fillData.copy(IonFluxElectrical_z,IonFluxData_z); .vars[4 + Ion.number_ion_species * (1 + 6) + 3 * ion + 1]
} ->data;
Array<double> &IonFluxData_z =
visData[0]
.vars[4 + Ion.number_ion_species * (1 + 6) + 3 * ion + 2]
->data;
Ion.getIonFluxElectrical(IonFluxElectrical_x, IonFluxElectrical_y,
IonFluxElectrical_z, ion);
fillData.copy(IonFluxElectrical_x, IonFluxData_x);
fillData.copy(IonFluxElectrical_y, IonFluxData_y);
fillData.copy(IonFluxElectrical_z, IonFluxData_z);
}
} }
if (vis_db->getWithDefault<bool>( "save_electric_field", false )){ if (vis_db->getWithDefault<bool>("save_electric_field", false)) {
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+9)+0]->name=="ElectricField_x"); ASSERT(
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+9)+1]->name=="ElectricField_y"); visData[0].vars[4 + Ion.number_ion_species * (1 + 9) + 0]->name ==
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+9)+2]->name=="ElectricField_z"); "ElectricField_x");
Poisson.getElectricField(ElectricalField_x, ElectricalField_y, ElectricalField_z); ASSERT(
Array<double>& ElectricalFieldxData = visData[0].vars[4+Ion.number_ion_species*(1+9)+0]->data; visData[0].vars[4 + Ion.number_ion_species * (1 + 9) + 1]->name ==
Array<double>& ElectricalFieldyData = visData[0].vars[4+Ion.number_ion_species*(1+9)+1]->data; "ElectricField_y");
Array<double>& ElectricalFieldzData = visData[0].vars[4+Ion.number_ion_species*(1+9)+2]->data; ASSERT(
fillData.copy(ElectricalField_x,ElectricalFieldxData); visData[0].vars[4 + Ion.number_ion_species * (1 + 9) + 2]->name ==
fillData.copy(ElectricalField_y,ElectricalFieldyData); "ElectricField_z");
fillData.copy(ElectricalField_z,ElectricalFieldzData); Poisson.getElectricField(ElectricalField_x, ElectricalField_y,
ElectricalField_z);
Array<double> &ElectricalFieldxData =
visData[0].vars[4 + Ion.number_ion_species * (1 + 9) + 0]->data;
Array<double> &ElectricalFieldyData =
visData[0].vars[4 + Ion.number_ion_species * (1 + 9) + 1]->data;
Array<double> &ElectricalFieldzData =
visData[0].vars[4 + Ion.number_ion_species * (1 + 9) + 2]->data;
fillData.copy(ElectricalField_x, ElectricalFieldxData);
fillData.copy(ElectricalField_y, ElectricalFieldyData);
fillData.copy(ElectricalField_z, ElectricalFieldzData);
} }
if (vis_db->getWithDefault<bool>( "write_silo", true )) if (vis_db->getWithDefault<bool>("write_silo", true))
IO::writeData( timestep, visData, Dm->Comm ); IO::writeData(timestep, visData, Dm->Comm);
//-------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------
/* if (vis_db->getWithDefault<bool>( "save_8bit_raw", true )){ /* if (vis_db->getWithDefault<bool>( "save_8bit_raw", true )){
char CurrentIDFilename[40]; char CurrentIDFilename[40];
sprintf(CurrentIDFilename,"id_t%d.raw",timestep); sprintf(CurrentIDFilename,"id_t%d.raw",timestep);
Averages.AggregateLabels(CurrentIDFilename); Averages.AggregateLabels(CurrentIDFilename);
} }
*/ */
} }

View File

@ -20,29 +20,29 @@
#include "models/PoissonSolver.h" #include "models/PoissonSolver.h"
#include "models/StokesModel.h" #include "models/StokesModel.h"
class ElectroChemistryAnalyzer{ class ElectroChemistryAnalyzer {
public: public:
std::shared_ptr <Domain> Dm; std::shared_ptr<Domain> Dm;
double Volume; double Volume;
// input variables // input variables
double rho_n, rho_w; double rho_n, rho_w;
double nu_n, nu_w; double nu_n, nu_w;
double gamma_wn, beta; double gamma_wn, beta;
double Fx, Fy, Fz; double Fx, Fy, Fz;
//........................................................................... //...........................................................................
int Nx,Ny,Nz; int Nx, Ny, Nz;
DoubleArray Rho; // density field DoubleArray Rho; // density field
DoubleArray ChemicalPotential; // density field DoubleArray ChemicalPotential; // density field
DoubleArray ElectricalPotential; // density field DoubleArray ElectricalPotential; // density field
DoubleArray ElectricalField_x; // density field DoubleArray ElectricalField_x; // density field
DoubleArray ElectricalField_y; // density field DoubleArray ElectricalField_y; // density field
DoubleArray ElectricalField_z; // density field DoubleArray ElectricalField_z; // density field
DoubleArray Pressure; // pressure field DoubleArray Pressure; // pressure field
DoubleArray Vel_x; // velocity field DoubleArray Vel_x; // velocity field
DoubleArray Vel_y; DoubleArray Vel_y;
DoubleArray Vel_z; DoubleArray Vel_z;
DoubleArray SDs; DoubleArray SDs;
DoubleArray IonFluxDiffusive_x; //ion diffusive flux components DoubleArray IonFluxDiffusive_x; //ion diffusive flux components
DoubleArray IonFluxDiffusive_y; DoubleArray IonFluxDiffusive_y;
DoubleArray IonFluxDiffusive_z; DoubleArray IonFluxDiffusive_z;
@ -53,15 +53,17 @@ public:
DoubleArray IonFluxElectrical_y; DoubleArray IonFluxElectrical_y;
DoubleArray IonFluxElectrical_z; DoubleArray IonFluxElectrical_z;
ElectroChemistryAnalyzer(std::shared_ptr <Domain> Dm); ElectroChemistryAnalyzer(std::shared_ptr<Domain> Dm);
~ElectroChemistryAnalyzer(); ~ElectroChemistryAnalyzer();
void SetParams(); void SetParams();
void Basic( ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poisson, ScaLBL_StokesModel &Stokes, int timestep); void Basic(ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poisson,
void WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poisson, ScaLBL_StokesModel &Stokes, std::shared_ptr<Database> input_db, int timestep); ScaLBL_StokesModel &Stokes, int timestep);
void WriteVis(ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poisson,
ScaLBL_StokesModel &Stokes,
std::shared_ptr<Database> input_db, int timestep);
private: private:
FILE *TIMELOG; FILE *TIMELOG;
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,6 @@
#include "models/ColorModel.h" #include "models/ColorModel.h"
/** /**
* \class FlowAdaptor * \class FlowAdaptor
* @brief * @brief
@ -20,21 +19,19 @@
* *
*/ */
class FlowAdaptor{ class FlowAdaptor {
public: public:
/** /**
* \brief Create a flow adaptor to operate on the LB model * \brief Create a flow adaptor to operate on the LB model
* @param M ScaLBL_ColorModel * @param M ScaLBL_ColorModel
*/ */
FlowAdaptor(ScaLBL_ColorModel &M); FlowAdaptor(ScaLBL_ColorModel &M);
/** /**
* \brief Destructor * \brief Destructor
*/ */
~FlowAdaptor(); ~FlowAdaptor();
/** /**
* \brief Fast-forward interface motion * \brief Fast-forward interface motion
* \details Accelerate the movement of interfaces based on the time derivative * \details Accelerate the movement of interfaces based on the time derivative
@ -43,29 +40,30 @@ public:
* move_interface_factor -- determines how much to ``fast forward" * move_interface_factor -- determines how much to ``fast forward"
* @param M ScaLBL_ColorModel * @param M ScaLBL_ColorModel
*/ */
double MoveInterface(ScaLBL_ColorModel &M); double MoveInterface(ScaLBL_ColorModel &M);
/** /**
* \brief Image re-initialization * \brief Image re-initialization
* \details Re-initialize LB simulation from image data * \details Re-initialize LB simulation from image data
* @param M ScaLBL_ColorModel * @param M ScaLBL_ColorModel
* @param Filename name of input file to be used to read image * @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 * \details Update volume fraction based on morphological algorithm. Dilation / erosion algorithm will be applied to
* grow / shrink the phase regions * grow / shrink the phase regions
* @param M ScaLBL_ColorModel * @param M ScaLBL_ColorModel
* @param delta_volume target change in volume fraction * @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);
/** /**
* \details Update fractional flow condition. Mass will be preferentially added or removed from * \details Update fractional flow condition. Mass will be preferentially added or removed from
* phase regions based on where flow is occurring * phase regions based on where flow is occurring
* @param M ScaLBL_ColorModel * @param M ScaLBL_ColorModel
*/ double UpdateFractionalFlow(ScaLBL_ColorModel &M); */
double UpdateFractionalFlow(ScaLBL_ColorModel &M);
/** /**
* \brief image re-initialization * \brief image re-initialization
@ -73,18 +71,19 @@ public:
* @param M ScaLBL_ColorModel * @param M ScaLBL_ColorModel
* @param seed_water_in_oil controls amount of mass to randomly seed into fluids * @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 * \brief Re-initialize LB simulation
* @param M ScaLBL_ColorModel * @param M ScaLBL_ColorModel
*/ */
void Flatten(ScaLBL_ColorModel &M); void Flatten(ScaLBL_ColorModel &M);
DoubleArray phi; DoubleArray phi;
DoubleArray phi_t; DoubleArray phi_t;
private: private:
int Nx, Ny, Nz; int Nx, Ny, Nz;
int timestep; int timestep;
int timestep_previous; int timestep_previous;
}; };
#endif #endif

View File

@ -1,55 +1,60 @@
#include "analysis/FreeEnergy.h" #include "analysis/FreeEnergy.h"
FreeEnergyAnalyzer::FreeEnergyAnalyzer(std::shared_ptr <Domain> dm): FreeEnergyAnalyzer::FreeEnergyAnalyzer(std::shared_ptr<Domain> dm) : Dm(dm) {
Dm(dm)
{
Nx=dm->Nx; Ny=dm->Ny; Nz=dm->Nz;
Volume=(Nx-2)*(Ny-2)*(Nz-2)*Dm->nprocx()*Dm->nprocy()*Dm->nprocz()*1.0;
ChemicalPotential.resize(Nx,Ny,Nz); ChemicalPotential.fill(0);
Phi.resize(Nx,Ny,Nz); Phi.fill(0);
Pressure.resize(Nx,Ny,Nz); Pressure.fill(0);
Rho.resize(Nx,Ny,Nz); Rho.fill(0);
Vel_x.resize(Nx,Ny,Nz); Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx,Ny,Nz); Vel_y.fill(0);
Vel_z.resize(Nx,Ny,Nz); Vel_z.fill(0);
SDs.resize(Nx,Ny,Nz); SDs.fill(0);
if (Dm->rank()==0){
bool WriteHeader=false;
TIMELOG = fopen("free.csv","r");
if (TIMELOG != NULL)
fclose(TIMELOG);
else
WriteHeader=true;
TIMELOG = fopen("free.csv","a+"); Nx = dm->Nx;
if (WriteHeader) Ny = dm->Ny;
{ Nz = dm->Nz;
// If timelog is empty, write a short header to list the averages Volume = (Nx - 2) * (Ny - 2) * (Nz - 2) * Dm->nprocx() * Dm->nprocy() *
//fprintf(TIMELOG,"--------------------------------------------------------------------------------------\n"); Dm->nprocz() * 1.0;
fprintf(TIMELOG,"timestep\n");
}
}
ChemicalPotential.resize(Nx, Ny, Nz);
ChemicalPotential.fill(0);
Phi.resize(Nx, Ny, Nz);
Phi.fill(0);
Pressure.resize(Nx, Ny, Nz);
Pressure.fill(0);
Rho.resize(Nx, Ny, Nz);
Rho.fill(0);
Vel_x.resize(Nx, Ny, Nz);
Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx, Ny, Nz);
Vel_y.fill(0);
Vel_z.resize(Nx, Ny, Nz);
Vel_z.fill(0);
SDs.resize(Nx, Ny, Nz);
SDs.fill(0);
if (Dm->rank() == 0) {
bool WriteHeader = false;
TIMELOG = fopen("free.csv", "r");
if (TIMELOG != NULL)
fclose(TIMELOG);
else
WriteHeader = true;
TIMELOG = fopen("free.csv", "a+");
if (WriteHeader) {
// If timelog is empty, write a short header to list the averages
//fprintf(TIMELOG,"--------------------------------------------------------------------------------------\n");
fprintf(TIMELOG, "timestep\n");
}
}
} }
FreeEnergyAnalyzer::~FreeEnergyAnalyzer(){ FreeEnergyAnalyzer::~FreeEnergyAnalyzer() {
if (Dm->rank()==0){ if (Dm->rank() == 0) {
fclose(TIMELOG); fclose(TIMELOG);
} }
} }
void FreeEnergyAnalyzer::SetParams(){ void FreeEnergyAnalyzer::SetParams() {}
}
void FreeEnergyAnalyzer::Basic(ScaLBL_FreeLeeModel &LeeModel, int timestep){ void FreeEnergyAnalyzer::Basic(ScaLBL_FreeLeeModel &LeeModel, int timestep) {
if (Dm->rank()==0){ if (Dm->rank() == 0) {
fprintf(TIMELOG,"%i ",timestep); fprintf(TIMELOG, "%i ", timestep);
/*for (int ion=0; ion<Ion.number_ion_species; ion++){ /*for (int ion=0; ion<Ion.number_ion_species; ion++){
fprintf(TIMELOG,"%.8g ",rho_avg_global[ion]); fprintf(TIMELOG,"%.8g ",rho_avg_global[ion]);
fprintf(TIMELOG,"%.8g ",rho_mu_avg_global[ion]); fprintf(TIMELOG,"%.8g ",rho_mu_avg_global[ion]);
fprintf(TIMELOG,"%.8g ",rho_psi_avg_global[ion]); fprintf(TIMELOG,"%.8g ",rho_psi_avg_global[ion]);
@ -57,10 +62,10 @@ void FreeEnergyAnalyzer::Basic(ScaLBL_FreeLeeModel &LeeModel, int timestep){
fprintf(TIMELOG,"%.8g ",rho_psi_fluctuation_global[ion]); fprintf(TIMELOG,"%.8g ",rho_psi_fluctuation_global[ion]);
} }
*/ */
fprintf(TIMELOG,"\n"); fprintf(TIMELOG, "\n");
fflush(TIMELOG); fflush(TIMELOG);
} }
/* else{ /* else{
fprintf(TIMELOG,"%i ",timestep); fprintf(TIMELOG,"%i ",timestep);
for (int ion=0; ion<Ion.number_ion_species; ion++){ for (int ion=0; ion<Ion.number_ion_species; ion++){
fprintf(TIMELOG,"%.8g ",rho_avg_local[ion]); fprintf(TIMELOG,"%.8g ",rho_avg_local[ion]);
@ -73,106 +78,111 @@ void FreeEnergyAnalyzer::Basic(ScaLBL_FreeLeeModel &LeeModel, int timestep){
} */ } */
} }
void FreeEnergyAnalyzer::WriteVis( ScaLBL_FreeLeeModel &LeeModel, std::shared_ptr<Database> input_db, int timestep){ void FreeEnergyAnalyzer::WriteVis(ScaLBL_FreeLeeModel &LeeModel,
std::shared_ptr<Database> input_db,
auto vis_db = input_db->getDatabase( "Visualization" ); int timestep) {
std::vector<IO::MeshDataStruct> visData;
fillHalo<double> fillData(Dm->Comm,Dm->rank_info,{Dm->Nx-2,Dm->Ny-2,Dm->Nz-2},{1,1,1},0,1);
IO::initialize("","silo","false"); auto vis_db = input_db->getDatabase("Visualization");
// Create the MeshDataStruct
std::vector<IO::MeshDataStruct> visData;
fillHalo<double> fillData(Dm->Comm, Dm->rank_info,
{Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2}, {1, 1, 1},
0, 1);
IO::initialize("", "silo", "false");
// Create the MeshDataStruct
visData.resize(1); visData.resize(1);
visData[0].meshName = "domain"; visData[0].meshName = "domain";
visData[0].mesh = std::make_shared<IO::DomainMesh>( Dm->rank_info,Dm->Nx-2,Dm->Ny-2,Dm->Nz-2,Dm->Lx,Dm->Ly,Dm->Lz ); visData[0].mesh =
std::make_shared<IO::DomainMesh>(Dm->rank_info, Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2, Dm->Lx, Dm->Ly, Dm->Lz);
auto VisPhase = std::make_shared<IO::Variable>(); auto VisPhase = std::make_shared<IO::Variable>();
auto VisPressure = std::make_shared<IO::Variable>(); auto VisPressure = std::make_shared<IO::Variable>();
auto VisChemicalPotential = std::make_shared<IO::Variable>(); auto VisChemicalPotential = std::make_shared<IO::Variable>();
auto VxVar = std::make_shared<IO::Variable>(); auto VxVar = std::make_shared<IO::Variable>();
auto VyVar = std::make_shared<IO::Variable>(); auto VyVar = std::make_shared<IO::Variable>();
auto VzVar = std::make_shared<IO::Variable>(); auto VzVar = std::make_shared<IO::Variable>();
if (vis_db->getWithDefault<bool>( "save_phase_field", true )){ if (vis_db->getWithDefault<bool>("save_phase_field", true)) {
VisPhase->name = "Phase"; VisPhase->name = "Phase";
VisPhase->type = IO::VariableType::VolumeVariable; VisPhase->type = IO::VariableType::VolumeVariable;
VisPhase->dim = 1; VisPhase->dim = 1;
VisPhase->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); VisPhase->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(VisPhase); visData[0].vars.push_back(VisPhase);
} }
if (vis_db->getWithDefault<bool>( "save_potential", true )){ if (vis_db->getWithDefault<bool>("save_potential", true)) {
VisPressure->name = "Pressure"; VisPressure->name = "Pressure";
VisPressure->type = IO::VariableType::VolumeVariable; VisPressure->type = IO::VariableType::VolumeVariable;
VisPressure->dim = 1; VisPressure->dim = 1;
VisPressure->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); VisPressure->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(VisPressure); visData[0].vars.push_back(VisPressure);
VisChemicalPotential->name = "ChemicalPotential"; VisChemicalPotential->name = "ChemicalPotential";
VisChemicalPotential->type = IO::VariableType::VolumeVariable; VisChemicalPotential->type = IO::VariableType::VolumeVariable;
VisChemicalPotential->dim = 1; VisChemicalPotential->dim = 1;
VisChemicalPotential->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); VisChemicalPotential->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(VisChemicalPotential); visData[0].vars.push_back(VisChemicalPotential);
} }
if (vis_db->getWithDefault<bool>( "save_velocity", false )){ if (vis_db->getWithDefault<bool>("save_velocity", false)) {
VxVar->name = "Velocity_x"; VxVar->name = "Velocity_x";
VxVar->type = IO::VariableType::VolumeVariable; VxVar->type = IO::VariableType::VolumeVariable;
VxVar->dim = 1; VxVar->dim = 1;
VxVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); VxVar->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(VxVar); visData[0].vars.push_back(VxVar);
VyVar->name = "Velocity_y"; VyVar->name = "Velocity_y";
VyVar->type = IO::VariableType::VolumeVariable; VyVar->type = IO::VariableType::VolumeVariable;
VyVar->dim = 1; VyVar->dim = 1;
VyVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); VyVar->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(VyVar); visData[0].vars.push_back(VyVar);
VzVar->name = "Velocity_z"; VzVar->name = "Velocity_z";
VzVar->type = IO::VariableType::VolumeVariable; VzVar->type = IO::VariableType::VolumeVariable;
VzVar->dim = 1; VzVar->dim = 1;
VzVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); VzVar->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
visData[0].vars.push_back(VzVar); visData[0].vars.push_back(VzVar);
} }
if (vis_db->getWithDefault<bool>( "save_phase", true )){ if (vis_db->getWithDefault<bool>("save_phase", true)) {
ASSERT(visData[0].vars[0]->name=="Phase"); ASSERT(visData[0].vars[0]->name == "Phase");
LeeModel.getPhase(Phi); LeeModel.getPhase(Phi);
Array<double>& PhaseData = visData[0].vars[0]->data; Array<double> &PhaseData = visData[0].vars[0]->data;
fillData.copy(Phi,PhaseData); fillData.copy(Phi, PhaseData);
} }
if (vis_db->getWithDefault<bool>( "save_potential", true )){ if (vis_db->getWithDefault<bool>("save_potential", true)) {
ASSERT(visData[0].vars[1]->name=="Pressure"); ASSERT(visData[0].vars[1]->name == "Pressure");
LeeModel.getPotential(Pressure, ChemicalPotential); LeeModel.getPotential(Pressure, ChemicalPotential);
Array<double>& PressureData = visData[0].vars[1]->data; Array<double> &PressureData = visData[0].vars[1]->data;
fillData.copy(Pressure,PressureData); fillData.copy(Pressure, PressureData);
ASSERT(visData[0].vars[2]->name=="ChemicalPotential");
Array<double>& ChemicalPotentialData = visData[0].vars[2]->data;
fillData.copy(ChemicalPotential,ChemicalPotentialData);
}
if (vis_db->getWithDefault<bool>( "save_velocity", false )){
ASSERT(visData[0].vars[3]->name=="Velocity_x");
ASSERT(visData[0].vars[4]->name=="Velocity_y");
ASSERT(visData[0].vars[5]->name=="Velocity_z");
LeeModel.getVelocity(Vel_x,Vel_y,Vel_z);
Array<double>& VelxData = visData[0].vars[3]->data;
Array<double>& VelyData = visData[0].vars[4]->data;
Array<double>& VelzData = visData[0].vars[5]->data;
fillData.copy(Vel_x,VelxData);
fillData.copy(Vel_y,VelyData);
fillData.copy(Vel_z,VelzData);
}
if (vis_db->getWithDefault<bool>( "write_silo", true ))
IO::writeData( timestep, visData, Dm->Comm );
/* if (vis_db->getWithDefault<bool>( "save_8bit_raw", true )){ ASSERT(visData[0].vars[2]->name == "ChemicalPotential");
Array<double> &ChemicalPotentialData = visData[0].vars[2]->data;
fillData.copy(ChemicalPotential, ChemicalPotentialData);
}
if (vis_db->getWithDefault<bool>("save_velocity", false)) {
ASSERT(visData[0].vars[3]->name == "Velocity_x");
ASSERT(visData[0].vars[4]->name == "Velocity_y");
ASSERT(visData[0].vars[5]->name == "Velocity_z");
LeeModel.getVelocity(Vel_x, Vel_y, Vel_z);
Array<double> &VelxData = visData[0].vars[3]->data;
Array<double> &VelyData = visData[0].vars[4]->data;
Array<double> &VelzData = visData[0].vars[5]->data;
fillData.copy(Vel_x, VelxData);
fillData.copy(Vel_y, VelyData);
fillData.copy(Vel_z, VelzData);
}
if (vis_db->getWithDefault<bool>("write_silo", true))
IO::writeData(timestep, visData, Dm->Comm);
/* if (vis_db->getWithDefault<bool>( "save_8bit_raw", true )){
char CurrentIDFilename[40]; char CurrentIDFilename[40];
sprintf(CurrentIDFilename,"id_t%d.raw",timestep); sprintf(CurrentIDFilename,"id_t%d.raw",timestep);
Averages.AggregateLabels(CurrentIDFilename); Averages.AggregateLabels(CurrentIDFilename);
} }
*/ */
} }

View File

@ -27,36 +27,36 @@
* *
*/ */
class FreeEnergyAnalyzer{ class FreeEnergyAnalyzer {
public: public:
std::shared_ptr <Domain> Dm; std::shared_ptr<Domain> Dm;
double Volume; double Volume;
// input variables // input variables
double rho_n, rho_w; double rho_n, rho_w;
double nu_n, nu_w; double nu_n, nu_w;
double gamma_wn, beta; double gamma_wn, beta;
double Fx, Fy, Fz; double Fx, Fy, Fz;
//........................................................................... //...........................................................................
int Nx,Ny,Nz; int Nx, Ny, Nz;
DoubleArray Rho; DoubleArray Rho;
DoubleArray Phi; DoubleArray Phi;
DoubleArray ChemicalPotential; DoubleArray ChemicalPotential;
DoubleArray Pressure; DoubleArray Pressure;
DoubleArray Vel_x; DoubleArray Vel_x;
DoubleArray Vel_y; DoubleArray Vel_y;
DoubleArray Vel_z; DoubleArray Vel_z;
DoubleArray SDs; DoubleArray SDs;
FreeEnergyAnalyzer(std::shared_ptr <Domain> Dm); FreeEnergyAnalyzer(std::shared_ptr<Domain> Dm);
~FreeEnergyAnalyzer(); ~FreeEnergyAnalyzer();
void SetParams(); void SetParams();
void Basic( ScaLBL_FreeLeeModel &LeeModel, int timestep); void Basic(ScaLBL_FreeLeeModel &LeeModel, int timestep);
void WriteVis( ScaLBL_FreeLeeModel &LeeModel, std::shared_ptr<Database> input_db, int timestep); void WriteVis(ScaLBL_FreeLeeModel &LeeModel,
std::shared_ptr<Database> input_db, int timestep);
private: private:
FILE *TIMELOG; FILE *TIMELOG;
}; };
#endif #endif

View File

@ -1,206 +1,234 @@
#include "analysis/GreyPhase.h" #include "analysis/GreyPhase.h"
// Constructor // Constructor
GreyPhaseAnalysis::GreyPhaseAnalysis(std::shared_ptr <Domain> dm): GreyPhaseAnalysis::GreyPhaseAnalysis(std::shared_ptr<Domain> dm) : Dm(dm) {
Dm(dm) Nx = dm->Nx;
{ Ny = dm->Ny;
Nx=dm->Nx; Ny=dm->Ny; Nz=dm->Nz; Nz = dm->Nz;
Volume=(Nx-2)*(Ny-2)*(Nz-2)*Dm->nprocx()*Dm->nprocy()*Dm->nprocz()*1.0; Volume = (Nx - 2) * (Ny - 2) * (Nz - 2) * Dm->nprocx() * Dm->nprocy() *
Dm->nprocz() * 1.0;
// Global arrays
SDs.resize(Nx,Ny,Nz); SDs.fill(0);
Porosity.resize(Nx,Ny,Nz); Porosity.fill(0);
//PhaseID.resize(Nx,Ny,Nz); PhaseID.fill(0);
Rho_n.resize(Nx,Ny,Nz); Rho_n.fill(0);
Rho_w.resize(Nx,Ny,Nz); Rho_w.fill(0);
Pressure.resize(Nx,Ny,Nz); Pressure.fill(0);
//Phi.resize(Nx,Ny,Nz); Phi.fill(0);
//DelPhi.resize(Nx,Ny,Nz); DelPhi.fill(0);
Vel_x.resize(Nx,Ny,Nz); Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx,Ny,Nz); Vel_y.fill(0);
Vel_z.resize(Nx,Ny,Nz); Vel_z.fill(0);
MobilityRatio.resize(Nx,Ny,Nz); MobilityRatio.fill(0);
//.........................................
if (Dm->rank()==0){
bool WriteHeader=false;
TIMELOG = fopen("timelog.csv","r");
if (TIMELOG != NULL)
fclose(TIMELOG);
else
WriteHeader=true;
TIMELOG = fopen("timelog.csv","a+"); // Global arrays
if (WriteHeader) SDs.resize(Nx, Ny, Nz);
{ SDs.fill(0);
// If timelog is empty, write a short header to list the averages Porosity.resize(Nx, Ny, Nz);
//fprintf(TIMELOG,"--------------------------------------------------------------------------------------\n"); Porosity.fill(0);
fprintf(TIMELOG,"sw krw krn vw vn pw pn\n"); //PhaseID.resize(Nx,Ny,Nz); PhaseID.fill(0);
} Rho_n.resize(Nx, Ny, Nz);
} Rho_n.fill(0);
Rho_w.resize(Nx, Ny, Nz);
Rho_w.fill(0);
Pressure.resize(Nx, Ny, Nz);
Pressure.fill(0);
//Phi.resize(Nx,Ny,Nz); Phi.fill(0);
//DelPhi.resize(Nx,Ny,Nz); DelPhi.fill(0);
Vel_x.resize(Nx, Ny, Nz);
Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx, Ny, Nz);
Vel_y.fill(0);
Vel_z.resize(Nx, Ny, Nz);
Vel_z.fill(0);
MobilityRatio.resize(Nx, Ny, Nz);
MobilityRatio.fill(0);
//.........................................
if (Dm->rank() == 0) {
bool WriteHeader = false;
TIMELOG = fopen("timelog.csv", "r");
if (TIMELOG != NULL)
fclose(TIMELOG);
else
WriteHeader = true;
TIMELOG = fopen("timelog.csv", "a+");
if (WriteHeader) {
// If timelog is empty, write a short header to list the averages
//fprintf(TIMELOG,"--------------------------------------------------------------------------------------\n");
fprintf(TIMELOG, "sw krw krn vw vn pw pn\n");
}
}
} }
// Destructor // Destructor
GreyPhaseAnalysis::~GreyPhaseAnalysis() GreyPhaseAnalysis::~GreyPhaseAnalysis() {}
{
} void GreyPhaseAnalysis::Write(int timestep) {}
void GreyPhaseAnalysis::Write(int timestep) void GreyPhaseAnalysis::SetParams(double rhoA, double rhoB, double tauA,
{ double tauB, double force_x, double force_y,
double force_z, double alpha, double B,
} double GreyPorosity) {
Fx = force_x;
void GreyPhaseAnalysis::SetParams(double rhoA, double rhoB, double tauA, double tauB, double force_x, double force_y, double force_z, double alpha, double B, double GreyPorosity) Fy = force_y;
{ Fz = force_z;
Fx = force_x; rho_n = rhoA;
Fy = force_y; rho_w = rhoB;
Fz = force_z; nu_n = (tauA - 0.5) / 3.f;
rho_n = rhoA; nu_w = (tauB - 0.5) / 3.f;
rho_w = rhoB; gamma_wn = 6.0 * alpha;
nu_n = (tauA-0.5)/3.f; beta = B;
nu_w = (tauB-0.5)/3.f;
gamma_wn = 6.0*alpha;
beta = B;
grey_porosity = GreyPorosity; grey_porosity = GreyPorosity;
} }
void GreyPhaseAnalysis::Basic(){ void GreyPhaseAnalysis::Basic() {
int i,j,k,n,imin,jmin,kmin,kmax; int i, j, k, n, imin, jmin, kmin, kmax;
// If external boundary conditions are set, do not average over the inlet // If external boundary conditions are set, do not average over the inlet
kmin=1; kmax=Nz-1; kmin = 1;
imin=jmin=1; kmax = Nz - 1;
if (Dm->inlet_layers_z > 0 && Dm->kproc() == 0) kmin += Dm->inlet_layers_z; imin = jmin = 1;
if (Dm->outlet_layers_z > 0 && Dm->kproc() == Dm->nprocz()-1) kmax -= Dm->outlet_layers_z; if (Dm->inlet_layers_z > 0 && Dm->kproc() == 0)
kmin += Dm->inlet_layers_z;
if (Dm->outlet_layers_z > 0 && Dm->kproc() == Dm->nprocz() - 1)
kmax -= Dm->outlet_layers_z;
Water_local.reset(); Water_local.reset();
Oil_local.reset(); Oil_local.reset();
double count_w = 0.0; double count_w = 0.0;
double count_n = 0.0; double count_n = 0.0;
for (k=kmin; k<kmax; k++){ for (k = kmin; k < kmax; k++) {
for (j=jmin; j<Ny-1; j++){ for (j = jmin; j < Ny - 1; j++) {
for (i=imin; i<Nx-1; i++){ for (i = imin; i < Nx - 1; i++) {
n = k*Nx*Ny + j*Nx + i; n = k * Nx * Ny + j * Nx + i;
// Compute volume averages // Compute volume averages
if ( Dm->id[n] > 0 ){ if (Dm->id[n] > 0) {
// compute density // compute density
double nA = Rho_n(n); double nA = Rho_n(n);
double nB = Rho_w(n); double nB = Rho_w(n);
double phi = (nA-nB)/(nA+nB); double phi = (nA - nB) / (nA + nB);
double porosity = Porosity(n); double porosity = Porosity(n);
double mobility_ratio = MobilityRatio(n); double mobility_ratio = MobilityRatio(n);
Water_local.M += nB*porosity;
Water_local.Px += porosity*(nA+nB)*Vel_x(n)*0.5*(1.0-mobility_ratio);
Water_local.Py += porosity*(nA+nB)*Vel_y(n)*0.5*(1.0-mobility_ratio);
Water_local.Pz += porosity*(nA+nB)*Vel_z(n)*0.5*(1.0-mobility_ratio);
Oil_local.M += nA*porosity;
Oil_local.Px += porosity*(nA+nB)*Vel_x(n)*0.5*(1.0+mobility_ratio);
Oil_local.Py += porosity*(nA+nB)*Vel_y(n)*0.5*(1.0+mobility_ratio);
Oil_local.Pz += porosity*(nA+nB)*Vel_z(n)*0.5*(1.0+mobility_ratio);
if ( phi > 0.99 ){ Water_local.M += nB * porosity;
Oil_local.p += Pressure(n); Water_local.Px += porosity * (nA + nB) * Vel_x(n) * 0.5 *
//Oil_local.p += pressure*(rho_n*nA)/(rho_n*nA+rho_w*nB); (1.0 - mobility_ratio);
count_n += 1.0; Water_local.Py += porosity * (nA + nB) * Vel_y(n) * 0.5 *
} (1.0 - mobility_ratio);
else if ( phi < -0.99 ){ Water_local.Pz += porosity * (nA + nB) * Vel_z(n) * 0.5 *
Water_local.p += Pressure(n); (1.0 - mobility_ratio);
//Water_local.p += pressure*(rho_w*nB)/(rho_n*nA+rho_w*nB);
count_w += 1.0;
}
}
}
}
}
Oil.M=Dm->Comm.sumReduce( Oil_local.M);
Oil.Px=Dm->Comm.sumReduce( Oil_local.Px);
Oil.Py=Dm->Comm.sumReduce( Oil_local.Py);
Oil.Pz=Dm->Comm.sumReduce( Oil_local.Pz);
Water.M=Dm->Comm.sumReduce( Water_local.M);
Water.Px=Dm->Comm.sumReduce( Water_local.Px);
Water.Py=Dm->Comm.sumReduce( Water_local.Py);
Water.Pz=Dm->Comm.sumReduce( Water_local.Pz);
Oil_local.M += nA * porosity;
Oil_local.Px += porosity * (nA + nB) * Vel_x(n) * 0.5 *
(1.0 + mobility_ratio);
Oil_local.Py += porosity * (nA + nB) * Vel_y(n) * 0.5 *
(1.0 + mobility_ratio);
Oil_local.Pz += porosity * (nA + nB) * Vel_z(n) * 0.5 *
(1.0 + mobility_ratio);
//Oil.p /= Oil.M; if (phi > 0.99) {
//Water.p /= Water.M; Oil_local.p += Pressure(n);
count_w=Dm->Comm.sumReduce( count_w); //Oil_local.p += pressure*(rho_n*nA)/(rho_n*nA+rho_w*nB);
count_n=Dm->Comm.sumReduce( count_n); count_n += 1.0;
if (count_w > 0.0) } else if (phi < -0.99) {
Water.p=Dm->Comm.sumReduce( Water_local.p) / count_w; Water_local.p += Pressure(n);
else //Water_local.p += pressure*(rho_w*nB)/(rho_n*nA+rho_w*nB);
Water.p = 0.0; count_w += 1.0;
if (count_n > 0.0) }
Oil.p=Dm->Comm.sumReduce( Oil_local.p) / count_n; }
else }
Oil.p = 0.0; }
}
Oil.M = Dm->Comm.sumReduce(Oil_local.M);
Oil.Px = Dm->Comm.sumReduce(Oil_local.Px);
Oil.Py = Dm->Comm.sumReduce(Oil_local.Py);
Oil.Pz = Dm->Comm.sumReduce(Oil_local.Pz);
// check for NaN Water.M = Dm->Comm.sumReduce(Water_local.M);
bool err=false; Water.Px = Dm->Comm.sumReduce(Water_local.Px);
if (Water.M != Water.M) err=true; Water.Py = Dm->Comm.sumReduce(Water_local.Py);
if (Water.p != Water.p) err=true; Water.Pz = Dm->Comm.sumReduce(Water_local.Pz);
if (Water.Px != Water.Px) err=true;
if (Water.Py != Water.Py) err=true;
if (Water.Pz != Water.Pz) err=true;
if (Oil.M != Oil.M) err=true; //Oil.p /= Oil.M;
if (Oil.p != Oil.p) err=true; //Water.p /= Water.M;
if (Oil.Px != Oil.Px) err=true; count_w = Dm->Comm.sumReduce(count_w);
if (Oil.Py != Oil.Py) err=true; count_n = Dm->Comm.sumReduce(count_n);
if (Oil.Pz != Oil.Pz) err=true; if (count_w > 0.0)
Water.p = Dm->Comm.sumReduce(Water_local.p) / count_w;
if (Dm->rank() == 0){ else
double force_mag = sqrt(Fx*Fx+Fy*Fy+Fz*Fz); Water.p = 0.0;
double dir_x = 0.0; if (count_n > 0.0)
double dir_y = 0.0; Oil.p = Dm->Comm.sumReduce(Oil_local.p) / count_n;
double dir_z = 0.0; else
if (force_mag > 0.0){ Oil.p = 0.0;
dir_x = Fx/force_mag;
dir_y = Fy/force_mag;
dir_z = Fz/force_mag;
}
else {
// default to z direction
dir_x = 0.0;
dir_y = 0.0;
dir_z = 1.0;
}
if (Dm->BoundaryCondition == 1 || Dm->BoundaryCondition == 2 || Dm->BoundaryCondition == 3 || Dm->BoundaryCondition == 4 ){
// compute the pressure drop
double pressure_drop = (Pressure(Nx*Ny + Nx + 1) - 1.0) / 3.0;
double length = ((Nz-2)*Dm->nprocz());
force_mag -= pressure_drop/length;
}
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;
}
saturation=Water.M/(Water.M + Oil.M); // assume constant density
water_flow_rate=grey_porosity*saturation*(Water.Px*dir_x + Water.Py*dir_y + Water.Pz*dir_z)/Water.M;
oil_flow_rate =grey_porosity*(1.0-saturation)*(Oil.Px*dir_x + Oil.Py*dir_y + Oil.Pz*dir_z)/Oil.M;
double h = Dm->voxel_length; // check for NaN
bool err = false;
if (Water.M != Water.M)
err = true;
if (Water.p != Water.p)
err = true;
if (Water.Px != Water.Px)
err = true;
if (Water.Py != Water.Py)
err = true;
if (Water.Pz != Water.Pz)
err = true;
if (Oil.M != Oil.M)
err = true;
if (Oil.p != Oil.p)
err = true;
if (Oil.Px != Oil.Px)
err = true;
if (Oil.Py != Oil.Py)
err = true;
if (Oil.Pz != Oil.Pz)
err = true;
if (Dm->rank() == 0) {
double force_mag = sqrt(Fx * Fx + Fy * Fy + Fz * Fz);
double dir_x = 0.0;
double dir_y = 0.0;
double dir_z = 0.0;
if (force_mag > 0.0) {
dir_x = Fx / force_mag;
dir_y = Fy / force_mag;
dir_z = Fz / force_mag;
} else {
// default to z direction
dir_x = 0.0;
dir_y = 0.0;
dir_z = 1.0;
}
if (Dm->BoundaryCondition == 1 || Dm->BoundaryCondition == 2 ||
Dm->BoundaryCondition == 3 || Dm->BoundaryCondition == 4) {
// compute the pressure drop
double pressure_drop = (Pressure(Nx * Ny + Nx + 1) - 1.0) / 3.0;
double length = ((Nz - 2) * Dm->nprocz());
force_mag -= pressure_drop / length;
}
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;
}
saturation = Water.M / (Water.M + Oil.M); // assume constant density
water_flow_rate =
grey_porosity * saturation *
(Water.Px * dir_x + Water.Py * dir_y + Water.Pz * dir_z) / Water.M;
oil_flow_rate = grey_porosity * (1.0 - saturation) *
(Oil.Px * dir_x + Oil.Py * dir_y + Oil.Pz * dir_z) /
Oil.M;
double h = Dm->voxel_length;
//TODO check if need greyporosity or domain porosity ? - compare to analytical solution //TODO check if need greyporosity or domain porosity ? - compare to analytical solution
double krn = h*h*nu_n*oil_flow_rate / force_mag ; double krn = h * h * nu_n * oil_flow_rate / force_mag;
double krw = h*h*nu_w*water_flow_rate / force_mag; double krw = h * h * nu_w * water_flow_rate / force_mag;
//printf(" water saturation = %f, fractional flow =%f \n",saturation,fractional_flow); //printf(" water saturation = %f, fractional flow =%f \n",saturation,fractional_flow);
fprintf(TIMELOG,"%.5g %.5g %.5g %.5g %.5g %.5g %.5g\n",saturation,krw,krn,h*water_flow_rate,h*oil_flow_rate, Water.p, Oil.p); fprintf(TIMELOG, "%.5g %.5g %.5g %.5g %.5g %.5g %.5g\n", saturation,
fflush(TIMELOG); krw, krn, h * water_flow_rate, h * oil_flow_rate, Water.p,
} Oil.p);
fflush(TIMELOG);
}
if (err==true){ if (err == true) {
// exception if simulation produceds NaN // exception if simulation produceds NaN
printf("GreyPhaseAnalysis.cpp: NaN encountered, may need to check simulation parameters \n"); printf("GreyPhaseAnalysis.cpp: NaN encountered, may need to check "
} "simulation parameters \n");
ASSERT(err==false); }
ASSERT(err == false);
} }
/* /*
inline void InterfaceTransportMeasures( double beta, double rA, double rB, double nA, double nB, inline void InterfaceTransportMeasures( double beta, double rA, double rB, double nA, double nB,

View File

@ -15,7 +15,6 @@
#include "IO/Reader.h" #include "IO/Reader.h"
#include "IO/Writer.h" #include "IO/Writer.h"
/** /**
* \class GreyPhase * \class GreyPhase
* *
@ -23,18 +22,15 @@
* The GreyPhase class tracks pressure, mass and momentum within a grey phase * The GreyPhase class tracks pressure, mass and momentum within a grey phase
* *
*/ */
class GreyPhase{ class GreyPhase {
public: public:
double p; double p;
double M,Px,Py,Pz; double M, Px, Py, Pz;
void reset(){ void reset() { p = M = Px = Py = Pz = 0.0; }
p=M=Px=Py=Pz=0.0;
}
private: private:
}; };
/** /**
* \class GreyPhaseAnalysis * \class GreyPhaseAnalysis
* *
@ -42,47 +38,48 @@ class GreyPhase{
* The GreyPhaseAnalysis class is constructed to analyze the LBPM greyscale model * 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;
double Volume; double Volume;
// input variables // input variables
double rho_n, rho_w; double rho_n, rho_w;
double nu_n, nu_w; double nu_n, nu_w;
double gamma_wn, beta; double gamma_wn, beta;
double Fx, Fy, Fz; double Fx, Fy, Fz;
double grey_porosity; double grey_porosity;
// outputs // outputs
double saturation,water_flow_rate, oil_flow_rate; double saturation, water_flow_rate, oil_flow_rate;
//simulation outputs (averaged values) //simulation outputs (averaged values)
GreyPhase Water, Oil; GreyPhase Water, Oil;
GreyPhase Water_local, Oil_local; GreyPhase Water_local, Oil_local;
//........................................................................... //...........................................................................
int Nx,Ny,Nz; int Nx, Ny, Nz;
//IntArray PhaseID; // Phase ID array //IntArray PhaseID; // Phase ID array
DoubleArray SDs; // contains porosity map DoubleArray SDs; // contains porosity map
DoubleArray Porosity; // contains porosity map DoubleArray Porosity; // contains porosity map
DoubleArray Rho_n; // density field DoubleArray Rho_n; // density field
DoubleArray Rho_w; // density field DoubleArray Rho_w; // density field
//DoubleArray Phi; // phase indicator field //DoubleArray Phi; // phase indicator field
//DoubleArray DelPhi; // Magnitude of Gradient of the phase indicator field //DoubleArray DelPhi; // Magnitude of Gradient of the phase indicator field
DoubleArray Pressure; // pressure field DoubleArray Pressure; // pressure field
DoubleArray Vel_x; // velocity field DoubleArray Vel_x; // velocity field
DoubleArray Vel_y; DoubleArray Vel_y;
DoubleArray Vel_z; DoubleArray Vel_z;
DoubleArray MobilityRatio; DoubleArray MobilityRatio;
GreyPhaseAnalysis(std::shared_ptr <Domain> Dm); GreyPhaseAnalysis(std::shared_ptr<Domain> Dm);
~GreyPhaseAnalysis(); ~GreyPhaseAnalysis();
void SetParams(double rhoA, double rhoB, double tauA, double tauB, double force_x, double force_y, double force_z, double alpha, double beta, double GreyPorosity); void SetParams(double rhoA, double rhoB, double tauA, double tauB,
void Basic(); double force_x, double force_y, double force_z, double alpha,
void Write(int time); double beta, double GreyPorosity);
void Basic();
void Write(int time);
private: private:
FILE *TIMELOG; FILE *TIMELOG;
}; };
#endif #endif

View File

@ -29,282 +29,278 @@
#include <memory> #include <memory>
#define PI 3.14159265359 #define PI 3.14159265359
// Constructor // Constructor
Minkowski::Minkowski(std::shared_ptr <Domain> dm): Minkowski::Minkowski(std::shared_ptr<Domain> dm)
kstart(0), kfinish(0), isovalue(0), Volume(0), : kstart(0), kfinish(0), isovalue(0), Volume(0), LOGFILE(NULL), Dm(dm),
LOGFILE(NULL), Dm(dm), Vi(0), Vi_global(0) Vi(0), Vi_global(0) {
{ Nx = dm->Nx;
Nx=dm->Nx; Ny=dm->Ny; Nz=dm->Nz; Ny = dm->Ny;
Volume=double((Nx-2)*(Ny-2)*(Nz-2))*double(Dm->nprocx()*Dm->nprocy()*Dm->nprocz()); Nz = dm->Nz;
Volume = double((Nx - 2) * (Ny - 2) * (Nz - 2)) *
id.resize(Nx,Ny,Nz); id.fill(0); double(Dm->nprocx() * Dm->nprocy() * Dm->nprocz());
label.resize(Nx,Ny,Nz); label.fill(0);
distance.resize(Nx,Ny,Nz); distance.fill(0);
if (Dm->rank()==0){ id.resize(Nx, Ny, Nz);
LOGFILE = fopen("minkowski.csv","a+"); id.fill(0);
if (fseek(LOGFILE,0,SEEK_SET) == fseek(LOGFILE,0,SEEK_CUR)) label.resize(Nx, Ny, Nz);
{ label.fill(0);
// If LOGFILE is empty, write a short header to list the averages distance.resize(Nx, Ny, Nz);
//fprintf(LOGFILE,"--------------------------------------------------------------------------------------\n"); distance.fill(0);
fprintf(LOGFILE,"Vn An Jn Xn\n"); //miknowski measures,
} if (Dm->rank() == 0) {
} LOGFILE = fopen("minkowski.csv", "a+");
if (fseek(LOGFILE, 0, SEEK_SET) == fseek(LOGFILE, 0, SEEK_CUR)) {
// If LOGFILE is empty, write a short header to list the averages
//fprintf(LOGFILE,"--------------------------------------------------------------------------------------\n");
fprintf(LOGFILE, "Vn An Jn Xn\n"); //miknowski measures,
}
}
} }
// Destructor // Destructor
Minkowski::~Minkowski() Minkowski::~Minkowski() {
{ if (LOGFILE != NULL) {
if ( LOGFILE!=NULL ) { fclose(LOGFILE); } fclose(LOGFILE);
}
} }
void Minkowski::ComputeScalar(const DoubleArray& Field, const double isovalue) 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;
DCEL 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;
//double Vx,Vy,Vz,Wx,Wy,Wz,nx,ny,nz,norm; //double Vx,Vy,Vz,Wx,Wy,Wz,nx,ny,nz,norm;
//int Nx = Field.size(0); //int Nx = Field.size(0);
//int Ny = Field.size(1); //int Ny = Field.size(1);
//int Nz = Field.size(2); //int Nz = Field.size(2);
for (int k=1; k<Nz-1; k++){ for (int k = 1; k < Nz - 1; k++) {
for (int j=1; j<Ny-1; j++){ for (int j = 1; j < Ny - 1; j++) {
for (int i=1; i<Nx-1; i++){ for (int i = 1; i < Nx - 1; i++) {
object.LocalIsosurface(Field,isovalue,i,j,k); object.LocalIsosurface(Field, isovalue, i, j, k);
for (int idx=0; idx<object.TriangleCount; idx++){ for (int idx = 0; idx < object.TriangleCount; idx++) {
e1 = object.Face(idx); e1 = object.Face(idx);
e2 = object.halfedge.next(e1); e2 = object.halfedge.next(e1);
e3 = object.halfedge.next(e2); e3 = object.halfedge.next(e2);
auto P1 = object.vertex.coords(object.halfedge.v1(e1)); auto P1 = object.vertex.coords(object.halfedge.v1(e1));
auto P2 = object.vertex.coords(object.halfedge.v1(e2)); auto P2 = object.vertex.coords(object.halfedge.v1(e2));
auto P3 = object.vertex.coords(object.halfedge.v1(e3)); auto P3 = object.vertex.coords(object.halfedge.v1(e3));
// Surface area // Surface area
s1 = Distance( P1, P2 ); s1 = Distance(P1, P2);
s2 = Distance( P2, P3 ); s2 = Distance(P2, P3);
s3 = Distance( P1, P3 ); s3 = Distance(P1, P3);
s = 0.5*(s1+s2+s3); s = 0.5 * (s1 + s2 + s3);
Ai += sqrt(s*(s-s1)*(s-s2)*(s-s3)); Ai += sqrt(s * (s - s1) * (s - s2) * (s - s3));
// Mean curvature based on half edge angle // Mean curvature based on half edge angle
a1 = object.EdgeAngle(e1); a1 = object.EdgeAngle(e1);
a2 = object.EdgeAngle(e2); a2 = object.EdgeAngle(e2);
a3 = object.EdgeAngle(e3); a3 = object.EdgeAngle(e3);
Ji += (a1*s1+a2*s2+a3*s3); Ji += (a1 * s1 + a2 * s2 + a3 * s3);
//if (0.08333333333333*(a1*s1+a2*s2+a3*s3) < 0.f){ //if (0.08333333333333*(a1*s1+a2*s2+a3*s3) < 0.f){
//double intcurv=0.08333333333333*(a1*s1+a2*s2+a3*s3); //double intcurv=0.08333333333333*(a1*s1+a2*s2+a3*s3);
//double surfarea=sqrt(s*(s-s1)*(s-s2)*(s-s3)); //double surfarea=sqrt(s*(s-s1)*(s-s2)*(s-s3));
//printf(" (%i,%i,%i) PQ(%i,%i)={%f,%f,%f} {%f,%f,%f} a=%f l=%f \n",i,j,k,e1,object.halfedge.twin(e1),P1.x,P1.y,P1.z,P2.x,P2.y,P2.z,a1,s1); //printf(" (%i,%i,%i) PQ(%i,%i)={%f,%f,%f} {%f,%f,%f} a=%f l=%f \n",i,j,k,e1,object.halfedge.twin(e1),P1.x,P1.y,P1.z,P2.x,P2.y,P2.z,a1,s1);
// printf(" (%i,%i,%i) QR(%i,%i)={%f,%f,%f} {%f,%f,%f} a=%f l=%f \n",i,j,k,e2,object.halfedge.twin(e2),P2.x,P2.y,P2.z,P3.x,P3.y,P3.z,a2,s2); // printf(" (%i,%i,%i) QR(%i,%i)={%f,%f,%f} {%f,%f,%f} a=%f l=%f \n",i,j,k,e2,object.halfedge.twin(e2),P2.x,P2.y,P2.z,P3.x,P3.y,P3.z,a2,s2);
// printf(" (%i,%i,%i) RP(%i,%i)={%f,%f,%f} {%f,%f,%f} a=%f l=%f \n",i,j,k,e3,object.halfedge.twin(e3),P3.x,P3.y,P3.z,P1.x,P1.y,P1.z,a3,s3); // printf(" (%i,%i,%i) RP(%i,%i)={%f,%f,%f} {%f,%f,%f} a=%f l=%f \n",i,j,k,e3,object.halfedge.twin(e3),P3.x,P3.y,P3.z,P1.x,P1.y,P1.z,a3,s3);
//} //}
// Euler characteristic (half edge rule: one face - 0.5*(three edges)) // Euler characteristic (half edge rule: one face - 0.5*(three edges))
Xi -= 0.5; Xi -= 0.5;
} }
// Euler characteristic -- each vertex shared by four cubes // Euler characteristic -- each vertex shared by four cubes
//Xi += 0.25*double(object.VertexCount); //Xi += 0.25*double(object.VertexCount);
// check if vertices are at corners // check if vertices are at corners
for (int idx=0; idx<object.VertexCount; idx++){ for (int idx = 0; idx < object.VertexCount; idx++) {
/*auto P1 = object.vertex.coords(idx); /*auto P1 = object.vertex.coords(idx);
if ( remainder(P1.x,1.0)==0.0 && remainder(P1.y,1.0)==0.0 && remainder(P1.z,1.0)==0.0 ){ if ( remainder(P1.x,1.0)==0.0 && remainder(P1.y,1.0)==0.0 && remainder(P1.z,1.0)==0.0 ){
Xi += 0.125; Xi += 0.125;
} }
else else
*/ */
Xi += 0.25; Xi += 0.25;
} }
/*double nside_extern = double(npts); /*double nside_extern = double(npts);
double nside_intern = double(npts)-3.0; double nside_intern = double(npts)-3.0;
EulerChar=0.0; EulerChar=0.0;
if (npts > 0) EulerChar = (0.25*nvert - nside_intern - 0.5*nside_extern + nface); */ if (npts > 0) EulerChar = (0.25*nvert - nside_intern - 0.5*nside_extern + nface); */
} }
} }
} }
// Voxel counting for volume fraction // Voxel counting for volume fraction
Vi = 0.f; Vi = 0.f;
for (int k=1; k<Nz-1; k++){ for (int k = 1; k < Nz - 1; k++) {
for (int j=1; j<Ny-1; j++){ for (int j = 1; j < Ny - 1; j++) {
for (int i=1; i<Nx-1; i++){ for (int i = 1; i < Nx - 1; i++) {
if (Field(i,j,k) < isovalue){ if (Field(i, j, k) < isovalue) {
Vi += 1.0; Vi += 1.0;
} }
} }
} }
} }
// convert X for 2D manifold to 3D object // convert X for 2D manifold to 3D object
Xi *= 0.5; Xi *= 0.5;
Dm->Comm.barrier(); Dm->Comm.barrier();
// Phase averages // Phase averages
Vi_global = Dm->Comm.sumReduce( Vi ); Vi_global = Dm->Comm.sumReduce(Vi);
Xi_global = Dm->Comm.sumReduce( Xi ); Xi_global = Dm->Comm.sumReduce(Xi);
Ai_global = Dm->Comm.sumReduce( Ai ); Ai_global = Dm->Comm.sumReduce(Ai);
Ji_global = Dm->Comm.sumReduce( Ji ); Ji_global = Dm->Comm.sumReduce(Ji);
Dm->Comm.barrier(); Dm->Comm.barrier();
PROFILE_STOP("ComputeScalar"); PROFILE_STOP("ComputeScalar");
} }
void Minkowski::MeasureObject() {
void Minkowski::MeasureObject(){ /*
/*
* compute the distance to an object * compute the distance to an object
* *
* THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects * THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects
* 0 - labels the object * 0 - labels the object
* 1 - labels the rest of the * 1 - labels the rest of the
*/ */
//DoubleArray smooth_distance(Nx,Ny,Nz); //DoubleArray smooth_distance(Nx,Ny,Nz);
for (int k=0; k<Nz; k++){ for (int k = 0; k < Nz; k++) {
for (int j=0; j<Ny; j++){ for (int j = 0; j < Ny; j++) {
for (int i=0; i<Nx; i++){ for (int i = 0; i < Nx; i++) {
distance(i,j,k) =2.0*double(id(i,j,k))-1.0; distance(i, j, k) = 2.0 * double(id(i, j, k)) - 1.0;
} }
} }
} }
CalcDist(distance,id,*Dm); CalcDist(distance, id, *Dm);
//Mean3D(distance,smooth_distance); //Mean3D(distance,smooth_distance);
//Eikonal(distance, id, *Dm, 20, {true, true, true}); //Eikonal(distance, id, *Dm, 20, {true, true, true});
ComputeScalar(distance,0.0); ComputeScalar(distance, 0.0);
} }
void Minkowski::MeasureObject(double factor, const DoubleArray &Phi) {
void Minkowski::MeasureObject(double factor, const DoubleArray &Phi){ /*
/*
* compute the distance to an object * compute the distance to an object
* *
* THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects * THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects
* 0 - labels the object * 0 - labels the object
* 1 - labels the rest of the * 1 - labels the rest of the
*/ */
for (int k=0; k<Nz; k++){ for (int k = 0; k < Nz; k++) {
for (int j=0; j<Ny; j++){ for (int j = 0; j < Ny; j++) {
for (int i=0; i<Nx; i++){ for (int i = 0; i < Nx; i++) {
distance(i,j,k) =2.0*double(id(i,j,k))-1.0; distance(i, j, k) = 2.0 * double(id(i, j, k)) - 1.0;
} }
} }
} }
CalcDist(distance,id,*Dm); CalcDist(distance, id, *Dm);
for (int k=0; k<Nz; k++){
for (int j=0; j<Ny; j++){
for (int i=0; i<Nx; i++){
double value = Phi(i,j,k);
double dist_value = distance(i,j,k);
if (dist_value < 2.5 && dist_value > -2.5) {
double new_distance = factor*log((1.0+value)/(1.0-value));
if (dist_value*new_distance < 0.0 )
new_distance = (-1.0)*new_distance;
distance(i,j,k) = new_distance;
}
}
}
}
ComputeScalar(distance,0.0);
for (int k = 0; k < Nz; k++) {
for (int j = 0; j < Ny; j++) {
for (int i = 0; i < Nx; i++) {
double value = Phi(i, j, k);
double dist_value = distance(i, j, k);
if (dist_value < 2.5 && dist_value > -2.5) {
double new_distance =
factor * log((1.0 + value) / (1.0 - value));
if (dist_value * new_distance < 0.0)
new_distance = (-1.0) * new_distance;
distance(i, j, k) = new_distance;
}
}
}
}
ComputeScalar(distance, 0.0);
} }
int Minkowski::MeasureConnectedPathway() {
int Minkowski::MeasureConnectedPathway(){ /*
/*
* compute the connected pathway for object with LABEL in id field * compute the connected pathway for object with LABEL in id field
* compute the labels for connected components * compute the labels for connected components
* compute the distance to the connected pathway * compute the distance to the connected pathway
* *
* THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects * THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects
*/ */
char LABEL = 0; char LABEL = 0;
for (int k=0; k<Nz; k++){ for (int k = 0; k < Nz; k++) {
for (int j=0; j<Ny; j++){ for (int j = 0; j < Ny; j++) {
for (int i=0; i<Nx; i++){ for (int i = 0; i < Nx; i++) {
if (id(i,j,k) == LABEL){ if (id(i, j, k) == LABEL) {
distance(i,j,k) = 1.0; distance(i, j, k) = 1.0;
} } else
else distance(i, j, k) = -1.0;
distance(i,j,k) = -1.0; }
} }
} }
}
// Extract only the connected part of NWP
// Extract only the connected part of NWP double vF = 0.0;
double vF=0.0; n_connected_components =
n_connected_components = ComputeGlobalBlobIDs(Nx-2,Ny-2,Nz-2,Dm->rank_info,distance,distance,vF,vF,label,Dm->Comm); ComputeGlobalBlobIDs(Nx - 2, Ny - 2, Nz - 2, Dm->rank_info, distance,
// int n_connected_components = ComputeGlobalPhaseComponent(Nx-2,Ny-2,Nz-2,Dm->rank_info,const IntArray &PhaseID, int &VALUE, BlobIDArray &GlobalBlobID, Dm->Comm ) distance, vF, vF, label, Dm->Comm);
Dm->Comm.barrier(); // int n_connected_components = ComputeGlobalPhaseComponent(Nx-2,Ny-2,Nz-2,Dm->rank_info,const IntArray &PhaseID, int &VALUE, BlobIDArray &GlobalBlobID, Dm->Comm )
Dm->Comm.barrier();
for (int k=0; k<Nz; k++){
for (int j=0; j<Ny; j++){ for (int k = 0; k < Nz; k++) {
for (int i=0; i<Nx; i++){ for (int j = 0; j < Ny; j++) {
if ( label(i,j,k) == 0){ for (int i = 0; i < Nx; i++) {
id(i,j,k) = 0; if (label(i, j, k) == 0) {
} id(i, j, k) = 0;
else{ } else {
id(i,j,k) = 1; id(i, j, k) = 1;
} }
} }
} }
} }
MeasureObject(); MeasureObject();
return n_connected_components; return n_connected_components;
} }
int Minkowski::MeasureConnectedPathway(double factor, const DoubleArray &Phi){ int Minkowski::MeasureConnectedPathway(double factor, const DoubleArray &Phi) {
/* /*
* compute the connected pathway for object with LABEL in id field * compute the connected pathway for object with LABEL in id field
* compute the labels for connected components * compute the labels for connected components
* compute the distance to the connected pathway * compute the distance to the connected pathway
* *
* THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects * THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects
*/ */
char LABEL = 0;
for (int k=0; k<Nz; k++){
for (int j=0; j<Ny; j++){
for (int i=0; i<Nx; i++){
if (id(i,j,k) == LABEL){
distance(i,j,k) = 1.0;
}
else
distance(i,j,k) = -1.0;
}
}
}
// Extract only the connected part of NWP
double vF=0.0;
n_connected_components = ComputeGlobalBlobIDs(Nx-2,Ny-2,Nz-2,Dm->rank_info,distance,distance,vF,vF,label,Dm->Comm);
// int n_connected_components = ComputeGlobalPhaseComponent(Nx-2,Ny-2,Nz-2,Dm->rank_info,const IntArray &PhaseID, int &VALUE, BlobIDArray &GlobalBlobID, Dm->Comm )
Dm->Comm.barrier();
char LABEL = 0;
for (int k=0; k<Nz; k++){ for (int k = 0; k < Nz; k++) {
for (int j=0; j<Ny; j++){ for (int j = 0; j < Ny; j++) {
for (int i=0; i<Nx; i++){ for (int i = 0; i < Nx; i++) {
if ( label(i,j,k) == 0){ if (id(i, j, k) == LABEL) {
id(i,j,k) = 0; distance(i, j, k) = 1.0;
} } else
else{ distance(i, j, k) = -1.0;
id(i,j,k) = 1; }
} }
} }
}
} // Extract only the connected part of NWP
MeasureObject(factor,Phi); double vF = 0.0;
return n_connected_components; n_connected_components =
ComputeGlobalBlobIDs(Nx - 2, Ny - 2, Nz - 2, Dm->rank_info, distance,
distance, vF, vF, label, Dm->Comm);
// int n_connected_components = ComputeGlobalPhaseComponent(Nx-2,Ny-2,Nz-2,Dm->rank_info,const IntArray &PhaseID, int &VALUE, BlobIDArray &GlobalBlobID, Dm->Comm )
Dm->Comm.barrier();
for (int k = 0; k < Nz; k++) {
for (int j = 0; j < Ny; j++) {
for (int i = 0; i < Nx; i++) {
if (label(i, j, k) == 0) {
id(i, j, k) = 0;
} else {
id(i, j, k) = 1;
}
}
}
}
MeasureObject(factor, Phi);
return n_connected_components;
} }
void Minkowski::PrintAll() {
void Minkowski::PrintAll() if (Dm->rank() == 0) {
{ fprintf(LOGFILE, "%.5g %.5g %.5g %.5g\n", Vi_global, Ai_global,
if (Dm->rank()==0){ Ji_global, Xi_global); // minkowski measures
fprintf(LOGFILE,"%.5g %.5g %.5g %.5g\n",Vi_global, Ai_global, Ji_global, Xi_global); // minkowski measures fflush(LOGFILE);
fflush(LOGFILE); }
}
} }

View File

@ -42,60 +42,51 @@
* *
*/ */
class Minkowski {
//...........................................................................
int kstart, kfinish;
class Minkowski{ double isovalue;
//........................................................................... double Volume;
int kstart,kfinish;
double isovalue; // CSV / text file where time history of averages is saved
double Volume; FILE *LOGFILE;
// CSV / text file where time history of averages is saved
FILE *LOGFILE;
public: public:
//........................................................................... //...........................................................................
std::shared_ptr <Domain> Dm; std::shared_ptr<Domain> Dm;
Array <char> id; Array<char> id;
Array <int> label; Array<int> label;
Array <double> distance; Array<double> distance;
//........................................................................... //...........................................................................
// Averaging variables // Averaging variables
//........................................................................... //...........................................................................
// local averages (to each MPI process) // local averages (to each MPI process)
double Ai,Ji,Xi,Vi; double Ai, Ji, Xi, Vi;
// Global averages (all processes) // Global averages (all processes)
double Ai_global,Ji_global,Xi_global,Vi_global; double Ai_global, Ji_global, Xi_global, Vi_global;
int n_connected_components; int n_connected_components;
//........................................................................... //...........................................................................
int Nx,Ny,Nz; int Nx, Ny, Nz;
double V(){ double V() { return Vi; }
return Vi; double A() { return Ai; }
} double H() { return Ji; }
double A(){ double X() { return Xi; }
return Ai;
} //..........................................................................
double H(){
return Ji;
}
double X(){
return Xi;
}
//..........................................................................
/** /**
* \brief Null constructor * \brief Null constructor
*/ */
Minkowski(){};//NULL CONSTRUCTOR Minkowski(){}; //NULL CONSTRUCTOR
/** /**
* \brief Constructor based on an existing Domain * \brief Constructor based on an existing Domain
* @param Dm - Domain structure * @param Dm - Domain structure
*/ */
Minkowski(std::shared_ptr <Domain> Dm); Minkowski(std::shared_ptr<Domain> Dm);
~Minkowski(); ~Minkowski();
/** /**
* \brief Compute scalar minkowski functionals * \brief Compute scalar minkowski functionals
* step 1. compute the distance to an object * step 1. compute the distance to an object
@ -104,11 +95,11 @@ public:
* THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects * THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects
* 0 - labels the object * 0 - labels the object
* 1 - labels everything else * 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 * \details Compute scalar minkowski functionals for connected part of a structure
* step 1. compute connected components and extract largest region by volume * step 1. compute connected components and extract largest region by volume
@ -118,25 +109,23 @@ public:
* THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects * THIS ALGORITHM ASSUMES THAT id() is populated with phase id to distinguish objects
* 0 - labels the object * 0 - labels the object
* 1 - labels everything else * 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 * \brief Compute scalar minkowski functionals
* \details Construct an isosurface and return the geometric invariants based on the triangulated list * \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 isovalue - threshold value to use to determine iso-surface
* @param Field - DoubleArray containing the field to threshold * @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 * \brief print the scalar invariants
*/ */
void PrintAll(); void PrintAll();
}; };
#endif #endif

View File

@ -21,25 +21,49 @@
struct LBPM_Point { struct LBPM_Point {
LBPM_Point() : x(0.0), y(0.0), z(0.0) {} LBPM_Point() : x(0.0), y(0.0), z(0.0) {}
LBPM_Point(double xv,double yv,double zv) : x(xv), y(yv), z(zv) {} LBPM_Point(double xv, double yv, double zv) : x(xv), y(yv), z(zv) {}
double x,y,z; double x, y, z;
}; };
typedef LBPM_Point Point; typedef LBPM_Point Point;
inline Point operator+(const Point &A,const Point &B) {return Point(A.x+B.x,A.y+B.y,A.z+B.z);} inline Point operator+(const Point &A, const Point &B) {
inline Point operator-(const Point &A,const Point &B) {return Point(A.x-B.x,A.y-B.y,A.z-B.z);} return Point(A.x + B.x, A.y + B.y, A.z + B.z);
inline Point operator*(const Point &A,double v) {return Point(A.x*v,A.y*v,A.z*v);} }
inline Point operator*(double v,const Point &A) {return Point(A.x*v,A.y*v,A.z*v);} inline Point operator-(const Point &A, const Point &B) {
inline Point operator/(const Point &A,double v) {return Point(A.x/v,A.y/v,A.z/v);} return Point(A.x - B.x, A.y - B.y, A.z - B.z);
inline Point operator-(const Point &A) {return Point(-A.x,-A.y,-A.z);} }
inline Point operator*(const Point &A, double v) {
return Point(A.x * v, A.y * v, A.z * v);
}
inline Point operator*(double v, const Point &A) {
return Point(A.x * v, A.y * v, A.z * v);
}
inline Point operator/(const Point &A, double v) {
return Point(A.x / v, A.y / v, A.z / v);
}
inline Point operator-(const Point &A) { return Point(-A.x, -A.y, -A.z); }
inline bool operator==(const Point &A,const Point &B) {return (A.x==B.x && A.y==B.y && A.z==B.z);} inline bool operator==(const Point &A, const Point &B) {
inline bool operator!=(const Point &A,const Point &B) {return (A.x!=B.x || A.y!=B.y || A.z!=B.z);} return (A.x == B.x && A.y == B.y && A.z == B.z);
}
inline bool operator!=(const Point &A, const Point &B) {
return (A.x != B.x || A.y != B.y || A.z != B.z);
}
inline double Norm(const Point &A) {return sqrt(A.x*A.x+A.y*A.y+A.z*A.z);} inline double Norm(const Point &A) {
inline Point Cross(const Point &A,const Point &B) {return Point(A.y*B.z-A.z*B.y,B.x*A.z-A.x*B.z,A.x*B.y-A.y*B.x);} return sqrt(A.x * A.x + A.y * A.y + A.z * A.z);
inline double Dot(const Point &A,const Point &B) {return (A.x*B.x+A.y*B.y+A.z*B.z);} }
inline double Distance(const Point &A,const Point &B) {return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));} inline Point Cross(const Point &A, const Point &B) {
return Point(A.y * B.z - A.z * B.y, B.x * A.z - A.x * B.z,
A.x * B.y - A.y * B.x);
}
inline double Dot(const Point &A, const Point &B) {
return (A.x * B.x + A.y * B.y + A.z * B.z);
}
inline double Distance(const Point &A, const Point &B) {
return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y) +
(A.z - B.z) * (A.z - B.z));
}
/* /*
class PointList{ class PointList{
@ -104,25 +128,38 @@ PointList::~PointList()
delete data; delete data;
} }
*/ */
template <class T> template <class T> class DTList {
class DTList {
public: public:
DTList() : Data(0), length(0), refCount(new size_t(1)), outOfRange() {} DTList() : Data(0), length(0), refCount(new size_t(1)), outOfRange() {}
DTList(const DTList<T> &A) : Data(A.Data), length(A.length), refCount(A.refCount), outOfRange() {++(*refCount);} DTList(const DTList<T> &A)
protected: : Data(A.Data), length(A.length), refCount(A.refCount), outOfRange() {
DTList(size_t len) : Data(len<=0 ? 0 : new T[len]), length(len<=0 ? 0 : len), refCount(new size_t(1)), outOfRange() {} ++(*refCount);
public:
virtual ~DTList() {
--(*refCount);
if (*refCount==0) {delete [] Data; delete refCount;}
Data = 0; refCount = 0; length=0;
} }
protected:
DTList(size_t len)
: Data(len <= 0 ? 0 : new T[len]), length(len <= 0 ? 0 : len),
refCount(new size_t(1)), outOfRange() {}
public:
virtual ~DTList() {
--(*refCount);
if (*refCount == 0) {
delete[] Data;
delete refCount;
}
Data = 0;
refCount = 0;
length = 0;
}
DTList<T> &operator=(const DTList<T> &A) { DTList<T> &operator=(const DTList<T> &A) {
if (A.refCount!=refCount) { // Otherwise doing A=A. if (A.refCount != refCount) { // Otherwise doing A=A.
--(*refCount); --(*refCount);
if (*refCount==0) {delete [] Data; delete refCount;} if (*refCount == 0) {
delete[] Data;
delete refCount;
}
refCount = A.refCount; refCount = A.refCount;
++(*refCount); ++(*refCount);
length = A.length; length = A.length;
@ -130,62 +167,69 @@ public:
} }
return *this; return *this;
} }
size_t MemoryUsed(void) const {return length*sizeof(T);}
const T *Pointer(void) const {return Data;}
size_t IsEmpty(void) const {return (Data==0);}
size_t Length(void) const {return length;}
const T operator()(size_t i) const {return Data[i];} size_t MemoryUsed(void) const { return length * sizeof(T); }
const T *Pointer(void) const { return Data; }
size_t IsEmpty(void) const { return (Data == 0); }
size_t Length(void) const { return length; }
const T operator()(size_t i) const { return Data[i]; }
protected: protected:
T *Data; T *Data;
size_t length; size_t length;
size_t *refCount; size_t *refCount;
// Should be static. // Should be static.
T outOfRange; T outOfRange;
}; };
template <class T> template <class T> class DTMutableList : public DTList<T> {
class DTMutableList : public DTList<T> {
public: public:
DTMutableList() : DTList<T>() {} DTMutableList() : DTList<T>() {}
DTMutableList(size_t len) : DTList<T>(len) {} DTMutableList(size_t len) : DTList<T>(len) {}
DTMutableList(const DTMutableList<T> &A) : DTList<T>(A) {} DTMutableList(const DTMutableList<T> &A) : DTList<T>(A) {}
DTMutableList<T> &operator=(const DTMutableList<T> &A) {DTList<T>::operator=(A); return *this;} DTMutableList<T> &operator=(const DTMutableList<T> &A) {
DTList<T>::operator=(A);
T *Pointer(void) {return DTList<T>::Data;} return *this;
const T *Pointer(void) const {return DTList<T>::Data;} }
T &operator()(size_t i) {return DTList<T>::Data[i];}
T operator()(size_t i) const {return DTList<T>::Data[i];} T *Pointer(void) { return DTList<T>::Data; }
const T *Pointer(void) const { return DTList<T>::Data; }
DTMutableList<T> &operator=(T v) {for (size_t i=0;i<DTList<T>::length;i++) DTList<T>::Data[i] = v; return *this;} T &operator()(size_t i) { return DTList<T>::Data[i]; }
T operator()(size_t i) const { return DTList<T>::Data[i]; }
DTMutableList<T> &operator=(T v) {
for (size_t i = 0; i < DTList<T>::length; i++)
DTList<T>::Data[i] = v;
return *this;
}
}; };
template <class T> DTMutableList<T> TruncateSize(const DTList<T> &A,size_t length) template <class T>
{ DTMutableList<T> TruncateSize(const DTList<T> &A, size_t length) {
if (length>A.Length()) length = A.Length(); if (length > A.Length())
length = A.Length();
DTMutableList<T> toReturn(length); DTMutableList<T> toReturn(length);
const T *fromP = A.Pointer(); const T *fromP = A.Pointer();
T *toP = toReturn.Pointer(); T *toP = toReturn.Pointer();
for (size_t i=0;i<length;i++) toP[i] = fromP[i]; for (size_t i = 0; i < length; i++)
toP[i] = fromP[i];
return toReturn; return toReturn;
} }
template <class T> DTMutableList<T> IncreaseSize(const DTList<T> &A,size_t addLength) template <class T>
{ DTMutableList<T> IncreaseSize(const DTList<T> &A, size_t addLength) {
DTMutableList<T> toReturn(A.Length()+(addLength>=0 ? addLength : 0)); DTMutableList<T> toReturn(A.Length() + (addLength >= 0 ? addLength : 0));
size_t len = A.Length(); size_t len = A.Length();
const T *fromP = A.Pointer(); const T *fromP = A.Pointer();
T *toP = toReturn.Pointer(); T *toP = toReturn.Pointer();
for (size_t i=0;i<len;i++) toP[i] = fromP[i]; for (size_t i = 0; i < len; i++)
toP[i] = fromP[i];
return toReturn; return toReturn;
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -17,49 +17,48 @@
#include "IO/Reader.h" #include "IO/Reader.h"
#include "IO/Writer.h" #include "IO/Writer.h"
class phase {
class phase{
public: public:
int Nc; int Nc;
double p; double p;
double M,Px,Py,Pz,K,visc; double M, Px, Py, Pz, K, visc;
double V,A,H,X; double V, A, H, X;
void reset(){ void reset() {
p=M=Px=Py=Pz=K=0.0; p = M = Px = Py = Pz = K = 0.0;
visc=0.0; visc = 0.0;
V=A=H=X=0.0; V = A = H = X = 0.0;
Nc=1; Nc = 1;
} }
private: private:
}; };
class interface{ class interface {
public: public:
int Nc; int Nc;
double M,Px,Py,Pz,K; double M, Px, Py, Pz, K;
double Mw,Mn,Pnx,Pny,Pnz,Pwx,Pwy,Pwz,Kw,Kn; double Mw, Mn, Pnx, Pny, Pnz, Pwx, Pwy, Pwz, Kw, Kn;
double V,A,H,X; double V, A, H, X;
void reset(){ void reset() {
Nc = 0; Nc = 0;
M=Px=Py=Pz=K=0.0; M = Px = Py = Pz = K = 0.0;
V=A=H=X=0.0; V = A = H = X = 0.0;
Mw=Mn=Pnx=Pny=Pnz=Pwx=Pwy=Pwz=Kw=Kn=0.0; Mw = Mn = Pnx = Pny = Pnz = Pwx = Pwy = Pwz = Kw = Kn = 0.0;
} }
private: private:
}; };
class SubPhase{ class SubPhase {
public: public:
std::shared_ptr <Domain> Dm; std::shared_ptr<Domain> Dm;
double Volume; double Volume;
// input variables // input variables
double rho_n, rho_w; double rho_n, rho_w;
double nu_n, nu_w; double nu_n, nu_w;
double gamma_wn, beta; double gamma_wn, beta;
double Fx, Fy, Fz; double Fx, Fy, Fz;
/* /*
* indices * indices
* w - water phase * w - water phase
* n - not water phase * n - not water phase
@ -68,53 +67,55 @@ public:
* i - interface region * i - interface region
* b - bulk (total) * b - bulk (total)
*/ */
// local entities // local entities
phase wc,wd,wb,nc,nd,nb,solid; phase wc, wd, wb, nc, nd, nb, solid;
interface iwn,iwnc; interface iwn, iwnc;
interface ifs; interface ifs;
// global entities
phase gwc,gwd,gwb,gnc,gnd,gnb,gsolid;
interface giwn,giwnc;
interface gifs;
/* fluid-solid wetting interaction */
double total_wetting_interaction, count_wetting_interaction;
double total_wetting_interaction_global, count_wetting_interaction_global;
//...........................................................................
int Nx,Ny,Nz;
IntArray PhaseID; // Phase ID array (solid=0, non-wetting=1, wetting=2)
BlobIDArray Label_WP; // Wetting phase label
BlobIDArray Label_NWP; // Non-wetting phase label index (0:nblobs-1)
std::vector<BlobIDType> Label_NWP_map; // Non-wetting phase label for each index
DoubleArray Rho_n; // density field
DoubleArray Rho_w; // density field
DoubleArray Phi; // phase indicator field
DoubleArray DelPhi; // Magnitude of Gradient of the phase indicator field
DoubleArray Pressure; // pressure field
DoubleArray Vel_x; // velocity field
DoubleArray Vel_y;
DoubleArray Vel_z;
DoubleArray Dissipation;
DoubleArray SDs;
std::shared_ptr<Minkowski> morph_w; // global entities
std::shared_ptr<Minkowski> morph_n; phase gwc, gwd, gwb, gnc, gnd, gnb, gsolid;
std::shared_ptr<Minkowski> morph_i; interface giwn, giwnc;
interface gifs;
/* fluid-solid wetting interaction */
double total_wetting_interaction, count_wetting_interaction;
double total_wetting_interaction_global, count_wetting_interaction_global;
SubPhase(std::shared_ptr <Domain> Dm); //...........................................................................
~SubPhase(); int Nx, Ny, Nz;
IntArray PhaseID; // Phase ID array (solid=0, non-wetting=1, wetting=2)
void SetParams(double rhoA, double rhoB, double tauA, double tauB, double force_x, double force_y, double force_z, double alpha, double beta); BlobIDArray Label_WP; // Wetting phase label
void Basic(); BlobIDArray Label_NWP; // Non-wetting phase label index (0:nblobs-1)
void Full(); std::vector<BlobIDType>
void Write(int time); Label_NWP_map; // Non-wetting phase label for each index
void AggregateLabels( const std::string& filename ); DoubleArray Rho_n; // density field
DoubleArray Rho_w; // density field
DoubleArray Phi; // phase indicator field
DoubleArray DelPhi; // Magnitude of Gradient of the phase indicator field
DoubleArray Pressure; // pressure field
DoubleArray Vel_x; // velocity field
DoubleArray Vel_y;
DoubleArray Vel_z;
DoubleArray Dissipation;
DoubleArray SDs;
std::shared_ptr<Minkowski> morph_w;
std::shared_ptr<Minkowski> morph_n;
std::shared_ptr<Minkowski> morph_i;
SubPhase(std::shared_ptr<Domain> Dm);
~SubPhase();
void SetParams(double rhoA, double rhoB, double tauA, double tauB,
double force_x, double force_y, double force_z, double alpha,
double beta);
void Basic();
void Full();
void Write(int time);
void AggregateLabels(const std::string &filename);
private: private:
FILE *TIMELOG; FILE *TIMELOG;
FILE *SUBPHASE; FILE *SUBPHASE;
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -33,171 +33,170 @@
#include "IO/Reader.h" #include "IO/Reader.h"
#include "IO/Writer.h" #include "IO/Writer.h"
class TwoPhase {
class TwoPhase{ //...........................................................................
int n_nw_pts, n_ns_pts, n_ws_pts, n_nws_pts, n_local_sol_pts,
n_local_nws_pts;
int n_nw_tris, n_ns_tris, n_ws_tris, n_nws_seg, n_local_sol_tris;
//...........................................................................
int nc;
int kstart, kfinish;
//........................................................................... double fluid_isovalue, solid_isovalue;
int n_nw_pts,n_ns_pts,n_ws_pts,n_nws_pts,n_local_sol_pts,n_local_nws_pts; double Volume;
int n_nw_tris,n_ns_tris,n_ws_tris,n_nws_seg,n_local_sol_tris; // initialize lists for vertices for surfaces, common line
//........................................................................... DTMutableList<Point> nw_pts;
int nc; DTMutableList<Point> ns_pts;
int kstart,kfinish; DTMutableList<Point> ws_pts;
DTMutableList<Point> nws_pts;
DTMutableList<Point> local_sol_pts;
DTMutableList<Point> local_nws_pts;
DTMutableList<Point> tmp;
double fluid_isovalue, solid_isovalue; // initialize triangle lists for surfaces
double Volume; IntArray nw_tris;
// initialize lists for vertices for surfaces, common line IntArray ns_tris;
DTMutableList<Point> nw_pts; IntArray ws_tris;
DTMutableList<Point> ns_pts; IntArray nws_seg;
DTMutableList<Point> ws_pts; IntArray local_sol_tris;
DTMutableList<Point> nws_pts;
DTMutableList<Point> local_sol_pts;
DTMutableList<Point> local_nws_pts;
DTMutableList<Point> tmp;
// initialize triangle lists for surfaces // Temporary storage arrays
IntArray nw_tris; DoubleArray CubeValues;
IntArray ns_tris; DoubleArray Values;
IntArray ws_tris; DoubleArray DistanceValues;
IntArray nws_seg; DoubleArray KGwns_values;
IntArray local_sol_tris; DoubleArray KNwns_values;
DoubleArray InterfaceSpeed;
DoubleArray NormalVector;
// Temporary storage arrays DoubleArray RecvBuffer;
DoubleArray CubeValues;
DoubleArray Values;
DoubleArray DistanceValues;
DoubleArray KGwns_values;
DoubleArray KNwns_values;
DoubleArray InterfaceSpeed;
DoubleArray NormalVector;
DoubleArray RecvBuffer; char *TempID;
char *TempID; // CSV / text file where time history of averages is saved
FILE *TIMELOG;
// CSV / text file where time history of averages is saved FILE *NWPLOG;
FILE *TIMELOG; FILE *WPLOG;
FILE *NWPLOG;
FILE *WPLOG;
public: public:
//........................................................................... //...........................................................................
std::shared_ptr <Domain> Dm; std::shared_ptr<Domain> Dm;
int NumberComponents_WP,NumberComponents_NWP; int NumberComponents_WP, NumberComponents_NWP;
//........................................................................... //...........................................................................
// Averaging variables // Averaging variables
//........................................................................... //...........................................................................
// local averages (to each MPI process) // local averages (to each MPI process)
double trimdist; // pixel distance to trim surface for specified averages double trimdist; // pixel distance to trim surface for specified averages
double porosity,poreVol; double porosity, poreVol;
double awn,ans,aws,lwns; double awn, ans, aws, lwns;
double wp_volume,nwp_volume; double wp_volume, nwp_volume;
double As, dummy; double As, dummy;
double vol_w, vol_n; // volumes the exclude the interfacial region double vol_w, vol_n; // volumes the exclude the interfacial region
double sat_w, sat_w_previous; double sat_w, sat_w_previous;
double pan,paw; // local phase averaged pressure double pan, paw; // local phase averaged pressure
// Global averages (all processes) // Global averages (all processes)
double pan_global,paw_global; // local phase averaged pressure double pan_global, paw_global; // local phase averaged pressure
double vol_w_global, vol_n_global; // volumes the exclude the interfacial region double vol_w_global,
double awn_global,ans_global,aws_global; vol_n_global; // volumes the exclude the interfacial region
double lwns_global; double awn_global, ans_global, aws_global;
double efawns,efawns_global; // averaged contact angle double lwns_global;
double euler,Kn,Jn,An; double efawns, efawns_global; // averaged contact angle
double euler_global,Kn_global,Jn_global,An_global; double euler, Kn, Jn, An;
double euler_global, Kn_global, Jn_global, An_global;
double rho_n, rho_w;
double nu_n, nu_w;
double gamma_wn;
double Fx, Fy, Fz;
double Jwn,Jwn_global; // average mean curavture - wn interface double rho_n, rho_w;
double Kwn,Kwn_global; // average Gaussian curavture - wn interface double nu_n, nu_w;
double KNwns,KNwns_global; // wns common curve normal curavture double gamma_wn;
double KGwns,KGwns_global; // wns common curve geodesic curavture double Fx, Fy, Fz;
double trawn,trawn_global; // trimmed interfacial area
double trJwn,trJwn_global; // trimmed interfacial area
double trRwn,trRwn_global; // trimmed interfacial area
double nwp_volume_global; // volume for the non-wetting phase
double wp_volume_global; // volume for the wetting phase
double As_global;
double wwndnw, wwndnw_global;
double wwnsdnwn, wwnsdnwn_global;
double Jwnwwndnw, Jwnwwndnw_global;
double dEs,dAwn,dAns; // Global surface energy (calculated by rank=0)
DoubleArray van;
DoubleArray vaw;
DoubleArray vawn;
DoubleArray vawns;
DoubleArray Gwn;
DoubleArray Gns;
DoubleArray Gws;
DoubleArray van_global;
DoubleArray vaw_global;
DoubleArray vawn_global;
DoubleArray vawns_global;
DoubleArray Gwn_global;
DoubleArray Gns_global;
DoubleArray Gws_global;
//...........................................................................
//...........................................................................
int Nx,Ny,Nz;
IntArray PhaseID; // Phase ID array (solid=0, non-wetting=1, wetting=2)
BlobIDArray Label_WP; // Wetting phase label
BlobIDArray Label_NWP; // Non-wetting phase label index (0:nblobs-1)
std::vector<BlobIDType> Label_NWP_map; // Non-wetting phase label for each index
DoubleArray SDn;
DoubleArray SDs;
DoubleArray Phase;
DoubleArray Press;
DoubleArray dPdt;
DoubleArray MeanCurvature;
DoubleArray GaussCurvature;
DoubleArray SDs_x; // Gradient of the signed distance
DoubleArray SDs_y;
DoubleArray SDs_z;
DoubleArray SDn_x; // Gradient of the signed distance
DoubleArray SDn_y;
DoubleArray SDn_z;
DoubleArray DelPhi; // Magnitude of Gradient of the phase indicator field
DoubleArray Phase_tplus;
DoubleArray Phase_tminus;
DoubleArray Vel_x; // Velocity
DoubleArray Vel_y;
DoubleArray Vel_z;
DoubleArray PhaseDistance;
std::shared_ptr<Minkowski> wet_morph; double Jwn, Jwn_global; // average mean curavture - wn interface
std::shared_ptr<Minkowski> nonwet_morph; double Kwn, Kwn_global; // average Gaussian curavture - wn interface
double KNwns, KNwns_global; // wns common curve normal curavture
// Container for averages; double KGwns, KGwns_global; // wns common curve geodesic curavture
DoubleArray ComponentAverages_WP; double trawn, trawn_global; // trimmed interfacial area
DoubleArray ComponentAverages_NWP; double trJwn, trJwn_global; // trimmed interfacial area
//........................................................................... double trRwn, trRwn_global; // trimmed interfacial area
TwoPhase(std::shared_ptr <Domain> Dm); double nwp_volume_global; // volume for the non-wetting phase
~TwoPhase(); double wp_volume_global; // volume for the wetting phase
void Initialize(); double As_global;
// void SetupCubes(Domain &Dm); double wwndnw, wwndnw_global;
void UpdateMeshValues(); double wwnsdnwn, wwnsdnwn_global;
void UpdateSolid(); double Jwnwwndnw, Jwnwwndnw_global;
void ComputeDelPhi(); double dEs, dAwn, dAns; // Global surface energy (calculated by rank=0)
void ColorToSignedDistance(double Beta, DoubleArray &ColorData, DoubleArray &DistData); DoubleArray van;
void ComputeLocal(); DoubleArray vaw;
void AssignComponentLabels(); DoubleArray vawn;
void ComponentAverages(); DoubleArray vawns;
void Reduce(); DoubleArray Gwn;
void NonDimensionalize(double D, double viscosity, double IFT); DoubleArray Gns;
void PrintAll(int timestep); DoubleArray Gws;
int GetCubeLabel(int i, int j, int k, IntArray &BlobLabel); DoubleArray van_global;
void SortBlobs(); DoubleArray vaw_global;
void PrintComponents(int timestep); DoubleArray vawn_global;
void SetParams(double rhoA, double rhoB, double tauA, double tauB, double force_x, double force_y, double force_z, double alpha); DoubleArray vawns_global;
double Volume_w(){ DoubleArray Gwn_global;
return wp_volume_global; DoubleArray Gns_global;
} DoubleArray Gws_global;
double Volume_n(){ //...........................................................................
return nwp_volume_global; //...........................................................................
} int Nx, Ny, Nz;
IntArray PhaseID; // Phase ID array (solid=0, non-wetting=1, wetting=2)
BlobIDArray Label_WP; // Wetting phase label
BlobIDArray Label_NWP; // Non-wetting phase label index (0:nblobs-1)
std::vector<BlobIDType>
Label_NWP_map; // Non-wetting phase label for each index
DoubleArray SDn;
DoubleArray SDs;
DoubleArray Phase;
DoubleArray Press;
DoubleArray dPdt;
DoubleArray MeanCurvature;
DoubleArray GaussCurvature;
DoubleArray SDs_x; // Gradient of the signed distance
DoubleArray SDs_y;
DoubleArray SDs_z;
DoubleArray SDn_x; // Gradient of the signed distance
DoubleArray SDn_y;
DoubleArray SDn_z;
DoubleArray DelPhi; // Magnitude of Gradient of the phase indicator field
DoubleArray Phase_tplus;
DoubleArray Phase_tminus;
DoubleArray Vel_x; // Velocity
DoubleArray Vel_y;
DoubleArray Vel_z;
DoubleArray PhaseDistance;
std::shared_ptr<Minkowski> wet_morph;
std::shared_ptr<Minkowski> nonwet_morph;
// Container for averages;
DoubleArray ComponentAverages_WP;
DoubleArray ComponentAverages_NWP;
//...........................................................................
TwoPhase(std::shared_ptr<Domain> Dm);
~TwoPhase();
void Initialize();
// void SetupCubes(Domain &Dm);
void UpdateMeshValues();
void UpdateSolid();
void ComputeDelPhi();
void ColorToSignedDistance(double Beta, DoubleArray &ColorData,
DoubleArray &DistData);
void ComputeLocal();
void AssignComponentLabels();
void ComponentAverages();
void Reduce();
void NonDimensionalize(double D, double viscosity, double IFT);
void PrintAll(int timestep);
int GetCubeLabel(int i, int j, int k, IntArray &BlobLabel);
void SortBlobs();
void PrintComponents(int timestep);
void SetParams(double rhoA, double rhoB, double tauA, double tauB,
double force_x, double force_y, double force_z,
double alpha);
double Volume_w() { return wp_volume_global; }
double Volume_n() { return nwp_volume_global; }
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -24,12 +24,10 @@
#include <map> #include <map>
#include <vector> #include <vector>
// Define types to use for blob ids // Define types to use for blob ids
typedef int32_t BlobIDType; typedef int32_t BlobIDType;
typedef Array<BlobIDType> BlobIDArray; typedef Array<BlobIDType> BlobIDArray;
/*! /*!
* @brief Compute the blob * @brief Compute the blob
* @details Compute the blob (F>vf|S>vs) starting from (i,j,k) - oil blob * @details Compute the blob (F>vf|S>vs) starting from (i,j,k) - oil blob
@ -42,8 +40,9 @@ typedef Array<BlobIDType> BlobIDArray;
* @param[in] periodic Optional value * @param[in] periodic Optional value
* @return Returns the number of blobs * @return Returns the number of blobs
*/ */
int ComputeLocalBlobIDs( const DoubleArray& Phase, const DoubleArray& SignDist, int ComputeLocalBlobIDs(const DoubleArray &Phase, const DoubleArray &SignDist,
double vF, double vS, BlobIDArray& LocalBlobID, bool periodic=true ); double vF, double vS, BlobIDArray &LocalBlobID,
bool periodic = true);
/*! /*!
* @brief Compute blob of an arbitrary phase * @brief Compute blob of an arbitrary phase
@ -54,8 +53,8 @@ int ComputeLocalBlobIDs( const DoubleArray& Phase, const DoubleArray& SignDist,
* @param[out] ComponentLabel * @param[out] ComponentLabel
* @param[in] periodic * @param[in] periodic
*/ */
int ComputeLocalPhaseComponent( const IntArray &PhaseID, int &VALUE, IntArray &ComponentLabel, bool periodic ); int ComputeLocalPhaseComponent(const IntArray &PhaseID, int &VALUE,
IntArray &ComponentLabel, bool periodic);
/*! /*!
* @brief Compute the blob * @brief Compute the blob
@ -73,10 +72,11 @@ int ComputeLocalPhaseComponent( const IntArray &PhaseID, int &VALUE, IntArray &C
* @param[in] comm MPI communicator * @param[in] comm MPI communicator
* @return Returns the number of blobs * @return Returns the number of blobs
*/ */
int ComputeGlobalBlobIDs( int nx, int ny, int nz, const RankInfoStruct& rank_info, int ComputeGlobalBlobIDs(int nx, int ny, int nz,
const DoubleArray& Phase, const DoubleArray& SignDist, double vF, double vS, const RankInfoStruct &rank_info,
BlobIDArray& GlobalBlobID, const Utilities::MPI& comm ); const DoubleArray &Phase, const DoubleArray &SignDist,
double vF, double vS, BlobIDArray &GlobalBlobID,
const Utilities::MPI &comm);
/*! /*!
* @brief Compute component of the specified phase * @brief Compute component of the specified phase
@ -92,9 +92,11 @@ int ComputeGlobalBlobIDs( int nx, int ny, int nz, const RankInfoStruct& rank_inf
* @param[in] comm The communicator to use * @param[in] comm The communicator to use
* @return Return the number of components in the specified phase * @return Return the number of components in the specified phase
*/ */
int ComputeGlobalPhaseComponent( int nx, int ny, int nz, const RankInfoStruct& rank_info, int ComputeGlobalPhaseComponent(int nx, int ny, int nz,
const IntArray &PhaseID, int &VALUE, BlobIDArray &GlobalBlobID, const Utilities::MPI& comm ); const RankInfoStruct &rank_info,
const IntArray &PhaseID, int &VALUE,
BlobIDArray &GlobalBlobID,
const Utilities::MPI &comm);
/*! /*!
* @brief Reorder the blobs * @brief Reorder the blobs
@ -103,31 +105,35 @@ int ComputeGlobalPhaseComponent( int nx, int ny, int nz, const RankInfoStruct& r
* @param[in,out] ID The ids of the blobs * @param[in,out] ID The ids of the blobs
* @param[in] comm MPI communicator * @param[in] comm MPI communicator
*/ */
void ReorderBlobIDs( BlobIDArray& ID, const Utilities::MPI& comm ); void ReorderBlobIDs(BlobIDArray &ID, const Utilities::MPI &comm);
typedef std::pair<BlobIDType, std::vector<BlobIDType>> BlobIDSplitStruct;
typedef std::pair<BlobIDType,std::vector<BlobIDType> > BlobIDSplitStruct; typedef std::pair<std::vector<BlobIDType>, BlobIDType> BlobIDMergeStruct;
typedef std::pair<std::vector<BlobIDType>,BlobIDType> BlobIDMergeStruct; typedef std::pair<std::vector<BlobIDType>, std::vector<BlobIDType>>
typedef std::pair<std::vector<BlobIDType>,std::vector<BlobIDType> > BlobIDMergeSplitStruct; BlobIDMergeSplitStruct;
typedef std::pair<BlobIDType,BlobIDType> OverlapID; typedef std::pair<BlobIDType, BlobIDType> OverlapID;
struct ID_map_struct { struct ID_map_struct {
std::vector<BlobIDType> created; // list of new blobs that were created std::vector<BlobIDType> created; // list of new blobs that were created
std::vector<BlobIDType> destroyed; // list of blobs that disappeared std::vector<BlobIDType> destroyed; // list of blobs that disappeared
std::vector<std::pair<BlobIDType,BlobIDType> > src_dst; // one-one mapping of blobs (first,second timestep id) std::vector<std::pair<BlobIDType, BlobIDType>>
std::vector<BlobIDSplitStruct> split; // list of blobs that split src_dst; // one-one mapping of blobs (first,second timestep id)
std::vector<BlobIDMergeStruct> merge; // list of blobs that merged std::vector<BlobIDSplitStruct> split; // list of blobs that split
std::vector<BlobIDMergeSplitStruct> merge_split; // list of blobs that both merged and split std::vector<BlobIDMergeStruct> merge; // list of blobs that merged
std::map<OverlapID,int64_t> overlap; // for ids that are not a 1-1 mapping, this is a list of the overlaps <src,dst> std::vector<BlobIDMergeSplitStruct>
merge_split; // list of blobs that both merged and split
std::map<OverlapID, int64_t>
overlap; // for ids that are not a 1-1 mapping, this is a list of the overlaps <src,dst>
//! Empty constructor //! Empty constructor
ID_map_struct() {} ID_map_struct() {}
//! Create initial map from N blobs (ordered 1:N-1) //! Create initial map from N blobs (ordered 1:N-1)
ID_map_struct( int N ) { ID_map_struct(int N) {
created.resize(N); created.resize(N);
for (int i=0; i<N; i++) { created[i]=i; } for (int i = 0; i < N; i++) {
created[i] = i;
}
} }
}; };
/*! /*!
* @brief Get the mapping of blob ids between iterations * @brief Get the mapping of blob ids between iterations
* @details This functions computes the map of blob ids between iterations * @details This functions computes the map of blob ids between iterations
@ -140,8 +146,8 @@ struct ID_map_struct {
* @param[in] ID2 The blob ids at the second timestep * @param[in] ID2 The blob ids at the second timestep
* @param[in] comm The communicator to use * @param[in] comm The communicator to use
*/ */
ID_map_struct computeIDMap( int nx, int ny, int nz, const BlobIDArray& ID1, const BlobIDArray& ID2, const Utilities::MPI& comm ); ID_map_struct computeIDMap(int nx, int ny, int nz, const BlobIDArray &ID1,
const BlobIDArray &ID2, const Utilities::MPI &comm);
/*! /*!
* @brief Compute the new global ids based on the map * @brief Compute the new global ids based on the map
@ -151,8 +157,8 @@ ID_map_struct computeIDMap( int nx, int ny, int nz, const BlobIDArray& ID1, cons
* @param[in] id_max The globally largest id used previously * @param[in] id_max The globally largest id used previously
* @param[out] new_ids The newly renumbered blob ids (0:ids.max()) * @param[out] new_ids The newly renumbered blob ids (0:ids.max())
*/ */
void getNewIDs( ID_map_struct& map, BlobIDType& id_max, std::vector<BlobIDType>& new_ids ); void getNewIDs(ID_map_struct &map, BlobIDType &id_max,
std::vector<BlobIDType> &new_ids);
/*! /*!
* @brief Update the blob ids based on mapping * @brief Update the blob ids based on mapping
@ -161,8 +167,7 @@ void getNewIDs( ID_map_struct& map, BlobIDType& id_max, std::vector<BlobIDType>&
* @param[out] new_ids The newly renumbered blob ids (0:ids.max()) * @param[out] new_ids The newly renumbered blob ids (0:ids.max())
* @param[in,out] IDs The blob ids to renumber * @param[in,out] IDs The blob ids to renumber
*/ */
void renumberIDs( const std::vector<BlobIDType>& new_ids, BlobIDArray& IDs ); void renumberIDs(const std::vector<BlobIDType> &new_ids, BlobIDArray &IDs);
/*! /*!
* @brief Write the ID map * @brief Write the ID map
@ -173,8 +178,7 @@ void renumberIDs( const std::vector<BlobIDType>& new_ids, BlobIDArray& IDs );
* @param[in] timestep The current timestep (timestep 0 creates the file) * @param[in] timestep The current timestep (timestep 0 creates the file)
* @param[in] filename The filename to write/append * @param[in] filename The filename to write/append
*/ */
void writeIDMap( const ID_map_struct& map, long long int timestep, const std::string& filename ); void writeIDMap(const ID_map_struct &map, long long int timestep,
const std::string &filename);
#endif #endif

View File

@ -1,337 +1,377 @@
#include "analysis/dcel.h" #include "analysis/dcel.h"
DCEL::DCEL(){ DCEL::DCEL() {}
DCEL::~DCEL() {
TriangleCount = 0;
VertexCount = 0;
} }
DCEL::~DCEL(){ int DCEL::Face(int index) { return FaceData[index]; }
TriangleCount=0;
VertexCount=0; void DCEL::Write() {
int e1, e2, e3;
FILE *TRIANGLES;
TRIANGLES = fopen("triangles.stl", "w");
fprintf(TRIANGLES, "solid \n");
for (int idx = 0; idx < TriangleCount; idx++) {
e1 = Face(idx);
e2 = halfedge.next(e1);
e3 = halfedge.next(e2);
auto P1 = vertex.coords(halfedge.v1(e1));
auto P2 = vertex.coords(halfedge.v1(e2));
auto P3 = vertex.coords(halfedge.v1(e3));
fprintf(TRIANGLES, "vertex %f %f %f\n", P1.x, P1.y, P1.z);
fprintf(TRIANGLES, "vertex %f %f %f\n", P2.x, P2.y, P2.z);
fprintf(TRIANGLES, "vertex %f %f %f\n", P3.x, P3.y, P3.z);
}
fclose(TRIANGLES);
} }
int DCEL::Face(int index){ void DCEL::LocalIsosurface(const DoubleArray &A, double value, const int i,
return FaceData[index]; const int j, const int k) {
Point P, Q;
Point PlaceHolder;
Point C0, C1, C2, C3, C4, C5, C6, C7;
Point VertexList[12];
Point NewVertexList[12];
int LocalRemap[12];
Point cellvertices[20];
std::array<std::array<int, 3>, 20> Triangles;
// Values from array 'A' at the cube corners
double CubeValues[8];
// Points corresponding to cube corners
C0.x = 0.0;
C0.y = 0.0;
C0.z = 0.0;
C1.x = 1.0;
C1.y = 0.0;
C1.z = 0.0;
C2.x = 1.0;
C2.y = 1.0;
C2.z = 0.0;
C3.x = 0.0;
C3.y = 1.0;
C3.z = 0.0;
C4.x = 0.0;
C4.y = 0.0;
C4.z = 1.0;
C5.x = 1.0;
C5.y = 0.0;
C5.z = 1.0;
C6.x = 1.0;
C6.y = 1.0;
C6.z = 1.0;
C7.x = 0.0;
C7.y = 1.0;
C7.z = 1.0;
CubeValues[0] = A(i, j, k) - value;
CubeValues[1] = A(i + 1, j, k) - value;
CubeValues[2] = A(i + 1, j + 1, k) - value;
CubeValues[3] = A(i, j + 1, k) - value;
CubeValues[4] = A(i, j, k + 1) - value;
CubeValues[5] = A(i + 1, j, k + 1) - value;
CubeValues[6] = A(i + 1, j + 1, k + 1) - value;
CubeValues[7] = A(i, j + 1, k + 1) - value;
//printf("Set cube values: %i, %i, %i \n",i,j,k);
//Determine the index into the edge table which
//tells us which vertices are inside of the surface
int CubeIndex = 0;
if (CubeValues[0] < 0.0f)
CubeIndex |= 1;
if (CubeValues[1] < 0.0f)
CubeIndex |= 2;
if (CubeValues[2] < 0.0f)
CubeIndex |= 4;
if (CubeValues[3] < 0.0f)
CubeIndex |= 8;
if (CubeValues[4] < 0.0f)
CubeIndex |= 16;
if (CubeValues[5] < 0.0f)
CubeIndex |= 32;
if (CubeValues[6] < 0.0f)
CubeIndex |= 64;
if (CubeValues[7] < 0.0f)
CubeIndex |= 128;
//Find the vertices where the surface intersects the cube
if (edgeTable[CubeIndex] & 1) {
P = VertexInterp(C0, C1, CubeValues[0], CubeValues[1]);
VertexList[0] = P;
Q = C0;
}
if (edgeTable[CubeIndex] & 2) {
P = VertexInterp(C1, C2, CubeValues[1], CubeValues[2]);
VertexList[1] = P;
Q = C1;
}
if (edgeTable[CubeIndex] & 4) {
P = VertexInterp(C2, C3, CubeValues[2], CubeValues[3]);
VertexList[2] = P;
Q = C2;
}
if (edgeTable[CubeIndex] & 8) {
P = VertexInterp(C3, C0, CubeValues[3], CubeValues[0]);
VertexList[3] = P;
Q = C3;
}
if (edgeTable[CubeIndex] & 16) {
P = VertexInterp(C4, C5, CubeValues[4], CubeValues[5]);
VertexList[4] = P;
Q = C4;
}
if (edgeTable[CubeIndex] & 32) {
P = VertexInterp(C5, C6, CubeValues[5], CubeValues[6]);
VertexList[5] = P;
Q = C5;
}
if (edgeTable[CubeIndex] & 64) {
P = VertexInterp(C6, C7, CubeValues[6], CubeValues[7]);
VertexList[6] = P;
Q = C6;
}
if (edgeTable[CubeIndex] & 128) {
P = VertexInterp(C7, C4, CubeValues[7], CubeValues[4]);
VertexList[7] = P;
Q = C7;
}
if (edgeTable[CubeIndex] & 256) {
P = VertexInterp(C0, C4, CubeValues[0], CubeValues[4]);
VertexList[8] = P;
Q = C0;
}
if (edgeTable[CubeIndex] & 512) {
P = VertexInterp(C1, C5, CubeValues[1], CubeValues[5]);
VertexList[9] = P;
Q = C1;
}
if (edgeTable[CubeIndex] & 1024) {
P = VertexInterp(C2, C6, CubeValues[2], CubeValues[6]);
VertexList[10] = P;
Q = C2;
}
if (edgeTable[CubeIndex] & 2048) {
P = VertexInterp(C3, C7, CubeValues[3], CubeValues[7]);
VertexList[11] = P;
Q = C3;
}
VertexCount = 0;
for (int idx = 0; idx < 12; idx++)
LocalRemap[idx] = -1;
for (int idx = 0; triTable[CubeIndex][idx] != -1; idx++) {
if (LocalRemap[triTable[CubeIndex][idx]] == -1) {
NewVertexList[VertexCount] = VertexList[triTable[CubeIndex][idx]];
LocalRemap[triTable[CubeIndex][idx]] = VertexCount;
VertexCount++;
}
}
//printf("Found %i vertices \n",VertexCount);
for (int idx = 0; idx < VertexCount; idx++) {
P = NewVertexList[idx];
//P.x += i;
//P.y += j;
//P.z += k;
cellvertices[idx] = P;
}
TriangleCount = 0;
for (int idx = 0; triTable[CubeIndex][idx] != -1; idx += 3) {
Triangles[TriangleCount][0] = LocalRemap[triTable[CubeIndex][idx + 0]];
Triangles[TriangleCount][1] = LocalRemap[triTable[CubeIndex][idx + 1]];
Triangles[TriangleCount][2] = LocalRemap[triTable[CubeIndex][idx + 2]];
TriangleCount++;
}
int nTris = TriangleCount;
// Now add the local values to the DCEL data structure
if (nTris > 0) {
FaceData.resize(TriangleCount);
//printf("Construct halfedge structure... \n");
//printf(" Construct %i triangles \n",nTris);
halfedge.resize(nTris * 3);
int idx_edge = 0;
for (int idx = 0; idx < TriangleCount; idx++) {
int V1 = Triangles[idx][0];
int V2 = Triangles[idx][1];
int V3 = Triangles[idx][2];
FaceData[idx] = idx_edge;
// first edge: V1->V2
halfedge.data(0, idx_edge) = V1; // first vertex
halfedge.data(1, idx_edge) = V2; // second vertex
halfedge.data(2, idx_edge) = idx; // triangle
halfedge.data(3, idx_edge) = -1; // twin
halfedge.data(4, idx_edge) = idx_edge + 2; // previous edge
halfedge.data(5, idx_edge) = idx_edge + 1; // next edge
idx_edge++;
// second edge: V2->V3
halfedge.data(0, idx_edge) = V2; // first vertex
halfedge.data(1, idx_edge) = V3; // second vertex
halfedge.data(2, idx_edge) = idx; // triangle
halfedge.data(3, idx_edge) = -1; // twin
halfedge.data(4, idx_edge) = idx_edge - 1; // previous edge
halfedge.data(5, idx_edge) = idx_edge + 1; // next edge
idx_edge++;
// third edge: V3->V1
halfedge.data(0, idx_edge) = V3; // first vertex
halfedge.data(1, idx_edge) = V1; // second vertex
halfedge.data(2, idx_edge) = idx; // triangle
halfedge.data(3, idx_edge) = -1; // twin
halfedge.data(4, idx_edge) = idx_edge - 1; // previous edge
halfedge.data(5, idx_edge) = idx_edge - 2; // next edge
idx_edge++;
//printf(" ***tri %i ***edge %i *** \n",idx, idx_edge);
}
//printf(" parsing halfedge structure\n");
int EdgeCount = idx_edge;
for (int idx = 0; idx < EdgeCount; idx++) {
int V1 = halfedge.data(0, idx);
int V2 = halfedge.data(1, idx);
// Find all the twins within the cube
for (int jdx = 0; jdx < EdgeCount; jdx++) {
if (halfedge.data(1, jdx) == V1 &&
halfedge.data(0, jdx) == V2) {
// this is the pair
halfedge.data(3, idx) = jdx;
halfedge.data(3, jdx) = idx;
}
if (halfedge.data(1, jdx) == V2 &&
halfedge.data(0, jdx) == V1 && !(idx == jdx)) {
std::printf(
"WARNING: half edges with identical orientation! \n");
}
}
// Use "ghost" twins if edge is on a cube face
P = cellvertices[V1];
Q = cellvertices[V2];
if (P.x == 0.0 && Q.x == 0.0)
halfedge.data(3, idx) = -1; // ghost twin for x=0 face
if (P.x == 1.0 && Q.x == 1.0)
halfedge.data(3, idx) = -4; // ghost twin for x=1 face
if (P.y == 0.0 && Q.y == 0.0)
halfedge.data(3, idx) = -2; // ghost twin for y=0 face
if (P.y == 1.0 && Q.y == 1.0)
halfedge.data(3, idx) = -5; // ghost twin for y=1 face
if (P.z == 0.0 && Q.z == 0.0)
halfedge.data(3, idx) = -3; // ghost twin for z=0 face
if (P.z == 1.0 && Q.z == 1.0)
halfedge.data(3, idx) = -6; // ghost twin for z=1 face
}
}
// Map vertices to global coordinates
for (int idx = 0; idx < VertexCount; idx++) {
P = cellvertices[idx];
P.x += i;
P.y += j;
P.z += k;
vertex.assign(idx, P);
}
} }
void DCEL::Write(){ Point DCEL::TriNormal(int edge) {
int e1,e2,e3; Point P, Q, R;
FILE *TRIANGLES; Point U, V, W;
TRIANGLES = fopen("triangles.stl","w"); double nx, ny, nz, len;
fprintf(TRIANGLES,"solid \n"); // at cube faces define outward normal to cube
for (int idx=0; idx<TriangleCount; idx++){ if (edge == -1) {
e1 = Face(idx); W.x = -1.0;
e2 = halfedge.next(e1); W.y = 0.0;
e3 = halfedge.next(e2); W.z = 0.0; // x cube face
auto P1 = vertex.coords(halfedge.v1(e1)); } else if (edge == -2) {
auto P2 = vertex.coords(halfedge.v1(e2)); W.x = 0.0;
auto P3 = vertex.coords(halfedge.v1(e3)); W.y = -1.0;
fprintf(TRIANGLES,"vertex %f %f %f\n",P1.x,P1.y,P1.z); W.z = 0.0; // y cube face
fprintf(TRIANGLES,"vertex %f %f %f\n",P2.x,P2.y,P2.z); } else if (edge == -3) {
fprintf(TRIANGLES,"vertex %f %f %f\n",P3.x,P3.y,P3.z); W.x = 0.0;
} W.y = 0.0;
fclose(TRIANGLES); W.z = -1.0; // z cube face
} else if (edge == -4) {
W.x = 1.0;
W.y = 0.0;
W.z = 0.0; // x cube face
} else if (edge == -5) {
W.x = 0.0;
W.y = 1.0;
W.z = 0.0; // y cube face
} else if (edge == -6) {
W.x = 0.0;
W.y = 0.0;
W.z = 1.0; // z cube face
} else {
// vertices for triange
int e2 = halfedge.next(edge);
int e3 = halfedge.next(e2);
P = vertex.coords(halfedge.v1(edge));
Q = vertex.coords(halfedge.v1(e2));
R = vertex.coords(halfedge.v1(e3));
// edge vectors
U = Q - P;
V = R - Q;
// normal vector
nx = U.y * V.z - U.z * V.y;
ny = U.z * V.x - U.x * V.z;
nz = U.x * V.y - U.y * V.x;
len = sqrt(nx * nx + ny * ny + nz * nz);
W.x = nx / len;
W.y = ny / len;
W.z = nz / len;
}
return W;
} }
void DCEL::LocalIsosurface(const DoubleArray& A, double value, const int i, const int j, const int k){ double DCEL::EdgeAngle(int edge) {
Point P,Q; double angle;
Point PlaceHolder; double dotprod;
Point C0,C1,C2,C3,C4,C5,C6,C7; Point P, Q, R; // triangle vertices
Point U, V, W; // normal vectors
int e2 = halfedge.next(edge);
int e3 = halfedge.next(e2);
P = vertex.coords(halfedge.v1(edge));
Q = vertex.coords(halfedge.v1(e2));
R = vertex.coords(halfedge.v1(e3));
U = TriNormal(edge);
V = TriNormal(halfedge.twin(edge));
if (halfedge.twin(edge) < 0) {
// compute edge normal in plane of cube face
W = P - Q; // edge tangent vector
double length = sqrt(W.x * W.x + W.y * W.y + W.z * W.z);
W.x /= length;
W.y /= length;
W.z /= length;
// edge normal within the plane of the cube face
double nx = W.y * V.z - W.z * V.y;
double ny = W.z * V.x - W.x * V.z;
double nz = W.x * V.y - W.y * V.x;
length = sqrt(nx * nx + ny * ny + nz * nz);
// new value for V is this normal vector
V.x = nx / length;
V.y = ny / length;
V.z = nz / length;
dotprod = U.x * V.x + U.y * V.y + U.z * V.z;
if (dotprod < 0.f) {
//printf("negative dot product on face\n");
dotprod = -dotprod;
V.x = -V.x;
V.y = -V.y;
V.z = -V.z;
}
Point VertexList[12]; if (dotprod > 1.f)
Point NewVertexList[12]; dotprod = 1.f;
int LocalRemap[12]; if (dotprod < -1.f)
dotprod = -1.f;
Point cellvertices[20]; angle = acos(dotprod);
std::array<std::array<int,3>,20> Triangles; /* project onto plane of cube face also works
// Values from array 'A' at the cube corners
double CubeValues[8];
// Points corresponding to cube corners
C0.x = 0.0; C0.y = 0.0; C0.z = 0.0;
C1.x = 1.0; C1.y = 0.0; C1.z = 0.0;
C2.x = 1.0; C2.y = 1.0; C2.z = 0.0;
C3.x = 0.0; C3.y = 1.0; C3.z = 0.0;
C4.x = 0.0; C4.y = 0.0; C4.z = 1.0;
C5.x = 1.0; C5.y = 0.0; C5.z = 1.0;
C6.x = 1.0; C6.y = 1.0; C6.z = 1.0;
C7.x = 0.0; C7.y = 1.0; C7.z = 1.0;
CubeValues[0] = A(i,j,k) - value;
CubeValues[1] = A(i+1,j,k) - value;
CubeValues[2] = A(i+1,j+1,k) - value;
CubeValues[3] = A(i,j+1,k) - value;
CubeValues[4] = A(i,j,k+1) - value;
CubeValues[5] = A(i+1,j,k+1) - value;
CubeValues[6] = A(i+1,j+1,k+1) - value;
CubeValues[7] = A(i,j+1,k+1) -value;
//printf("Set cube values: %i, %i, %i \n",i,j,k);
//Determine the index into the edge table which
//tells us which vertices are inside of the surface
int CubeIndex = 0;
if (CubeValues[0] < 0.0f) CubeIndex |= 1;
if (CubeValues[1] < 0.0f) CubeIndex |= 2;
if (CubeValues[2] < 0.0f) CubeIndex |= 4;
if (CubeValues[3] < 0.0f) CubeIndex |= 8;
if (CubeValues[4] < 0.0f) CubeIndex |= 16;
if (CubeValues[5] < 0.0f) CubeIndex |= 32;
if (CubeValues[6] < 0.0f) CubeIndex |= 64;
if (CubeValues[7] < 0.0f) CubeIndex |= 128;
//Find the vertices where the surface intersects the cube
if (edgeTable[CubeIndex] & 1){
P = VertexInterp(C0,C1,CubeValues[0],CubeValues[1]);
VertexList[0] = P;
Q = C0;
}
if (edgeTable[CubeIndex] & 2){
P = VertexInterp(C1,C2,CubeValues[1],CubeValues[2]);
VertexList[1] = P;
Q = C1;
}
if (edgeTable[CubeIndex] & 4){
P = VertexInterp(C2,C3,CubeValues[2],CubeValues[3]);
VertexList[2] = P;
Q = C2;
}
if (edgeTable[CubeIndex] & 8){
P = VertexInterp(C3,C0,CubeValues[3],CubeValues[0]);
VertexList[3] = P;
Q = C3;
}
if (edgeTable[CubeIndex] & 16){
P = VertexInterp(C4,C5,CubeValues[4],CubeValues[5]);
VertexList[4] = P;
Q = C4;
}
if (edgeTable[CubeIndex] & 32){
P = VertexInterp(C5,C6,CubeValues[5],CubeValues[6]);
VertexList[5] = P;
Q = C5;
}
if (edgeTable[CubeIndex] & 64){
P = VertexInterp(C6,C7,CubeValues[6],CubeValues[7]);
VertexList[6] = P;
Q = C6;
}
if (edgeTable[CubeIndex] & 128){
P = VertexInterp(C7,C4,CubeValues[7],CubeValues[4]);
VertexList[7] = P;
Q = C7;
}
if (edgeTable[CubeIndex] & 256){
P = VertexInterp(C0,C4,CubeValues[0],CubeValues[4]);
VertexList[8] = P;
Q = C0;
}
if (edgeTable[CubeIndex] & 512){
P = VertexInterp(C1,C5,CubeValues[1],CubeValues[5]);
VertexList[9] = P;
Q = C1;
}
if (edgeTable[CubeIndex] & 1024){
P = VertexInterp(C2,C6,CubeValues[2],CubeValues[6]);
VertexList[10] = P;
Q = C2;
}
if (edgeTable[CubeIndex] & 2048){
P = VertexInterp(C3,C7,CubeValues[3],CubeValues[7]);
VertexList[11] = P;
Q = C3;
}
VertexCount=0;
for (int idx=0;idx<12;idx++)
LocalRemap[idx] = -1;
for (int idx=0;triTable[CubeIndex][idx]!=-1;idx++)
{
if(LocalRemap[triTable[CubeIndex][idx]] == -1)
{
NewVertexList[VertexCount] = VertexList[triTable[CubeIndex][idx]];
LocalRemap[triTable[CubeIndex][idx]] = VertexCount;
VertexCount++;
}
}
//printf("Found %i vertices \n",VertexCount);
for (int idx=0;idx<VertexCount;idx++) {
P = NewVertexList[idx];
//P.x += i;
//P.y += j;
//P.z += k;
cellvertices[idx] = P;
}
TriangleCount = 0;
for (int idx=0;triTable[CubeIndex][idx]!=-1;idx+=3) {
Triangles[TriangleCount][0] = LocalRemap[triTable[CubeIndex][idx+0]];
Triangles[TriangleCount][1] = LocalRemap[triTable[CubeIndex][idx+1]];
Triangles[TriangleCount][2] = LocalRemap[triTable[CubeIndex][idx+2]];
TriangleCount++;
}
int nTris = TriangleCount;
// Now add the local values to the DCEL data structure
if (nTris>0){
FaceData.resize(TriangleCount);
//printf("Construct halfedge structure... \n");
//printf(" Construct %i triangles \n",nTris);
halfedge.resize(nTris*3);
int idx_edge=0;
for (int idx=0; idx<TriangleCount; idx++){
int V1 = Triangles[idx][0];
int V2 = Triangles[idx][1];
int V3 = Triangles[idx][2];
FaceData[idx] = idx_edge;
// first edge: V1->V2
halfedge.data(0,idx_edge) = V1; // first vertex
halfedge.data(1,idx_edge) = V2; // second vertex
halfedge.data(2,idx_edge) = idx; // triangle
halfedge.data(3,idx_edge) = -1; // twin
halfedge.data(4,idx_edge) = idx_edge+2; // previous edge
halfedge.data(5,idx_edge) = idx_edge+1; // next edge
idx_edge++;
// second edge: V2->V3
halfedge.data(0,idx_edge) = V2; // first vertex
halfedge.data(1,idx_edge) = V3; // second vertex
halfedge.data(2,idx_edge) = idx; // triangle
halfedge.data(3,idx_edge) = -1; // twin
halfedge.data(4,idx_edge) = idx_edge-1; // previous edge
halfedge.data(5,idx_edge) = idx_edge+1; // next edge
idx_edge++;
// third edge: V3->V1
halfedge.data(0,idx_edge) = V3; // first vertex
halfedge.data(1,idx_edge) = V1; // second vertex
halfedge.data(2,idx_edge) = idx; // triangle
halfedge.data(3,idx_edge) = -1; // twin
halfedge.data(4,idx_edge) = idx_edge-1; // previous edge
halfedge.data(5,idx_edge) = idx_edge-2; // next edge
idx_edge++;
//printf(" ***tri %i ***edge %i *** \n",idx, idx_edge);
}
//printf(" parsing halfedge structure\n");
int EdgeCount=idx_edge;
for (int idx=0; idx<EdgeCount; idx++){
int V1=halfedge.data(0,idx);
int V2=halfedge.data(1,idx);
// Find all the twins within the cube
for (int jdx=0; jdx<EdgeCount; jdx++){
if (halfedge.data(1,jdx) == V1 && halfedge.data(0,jdx) == V2){
// this is the pair
halfedge.data(3,idx) = jdx;
halfedge.data(3,jdx) = idx;
}
if (halfedge.data(1,jdx) == V2 && halfedge.data(0,jdx) == V1 && !(idx==jdx)){
std::printf("WARNING: half edges with identical orientation! \n");
}
}
// Use "ghost" twins if edge is on a cube face
P = cellvertices[V1];
Q = cellvertices[V2];
if (P.x == 0.0 && Q.x == 0.0) halfedge.data(3,idx) = -1; // ghost twin for x=0 face
if (P.x == 1.0 && Q.x == 1.0) halfedge.data(3,idx) = -4; // ghost twin for x=1 face
if (P.y == 0.0 && Q.y == 0.0) halfedge.data(3,idx) = -2; // ghost twin for y=0 face
if (P.y == 1.0 && Q.y == 1.0) halfedge.data(3,idx) = -5; // ghost twin for y=1 face
if (P.z == 0.0 && Q.z == 0.0) halfedge.data(3,idx) = -3; // ghost twin for z=0 face
if (P.z == 1.0 && Q.z == 1.0) halfedge.data(3,idx) = -6; // ghost twin for z=1 face
}
}
// Map vertices to global coordinates
for (int idx=0;idx<VertexCount;idx++) {
P = cellvertices[idx];
P.x += i;
P.y += j;
P.z += k;
vertex.assign(idx,P);
}
}
Point DCEL::TriNormal(int edge)
{
Point P,Q,R;
Point U,V,W;
double nx,ny,nz,len;
// at cube faces define outward normal to cube
if (edge == -1){
W.x = -1.0; W.y = 0.0; W.z = 0.0; // x cube face
}
else if (edge == -2){
W.x = 0.0; W.y = -1.0; W.z = 0.0; // y cube face
}
else if (edge == -3){
W.x = 0.0; W.y = 0.0; W.z = -1.0; // z cube face
}
else if (edge == -4){
W.x = 1.0; W.y = 0.0; W.z = 0.0; // x cube face
}
else if (edge == -5){
W.x = 0.0; W.y = 1.0; W.z = 0.0; // y cube face
}
else if (edge == -6){
W.x = 0.0; W.y = 0.0; W.z = 1.0; // z cube face
}
else{
// vertices for triange
int e2 = halfedge.next(edge);
int e3 = halfedge.next(e2);
P=vertex.coords(halfedge.v1(edge));
Q=vertex.coords(halfedge.v1(e2));
R=vertex.coords(halfedge.v1(e3));
// edge vectors
U = Q-P;
V = R-Q;
// normal vector
nx = U.y*V.z - U.z*V.y;
ny = U.z*V.x - U.x*V.z;
nz = U.x*V.y - U.y*V.x;
len = sqrt(nx*nx+ny*ny+nz*nz);
W.x = nx/len; W.y = ny/len; W.z = nz/len;
}
return W;
}
double DCEL::EdgeAngle(int edge)
{
double angle;
double dotprod;
Point P,Q,R; // triangle vertices
Point U,V,W; // normal vectors
int e2 = halfedge.next(edge);
int e3 = halfedge.next(e2);
P=vertex.coords(halfedge.v1(edge));
Q=vertex.coords(halfedge.v1(e2));
R=vertex.coords(halfedge.v1(e3));
U = TriNormal(edge);
V = TriNormal(halfedge.twin(edge));
if (halfedge.twin(edge) < 0 ){
// compute edge normal in plane of cube face
W = P - Q; // edge tangent vector
double length = sqrt(W.x*W.x+W.y*W.y+W.z*W.z);
W.x /= length;
W.y /= length;
W.z /= length;
// edge normal within the plane of the cube face
double nx = W.y*V.z - W.z*V.y;
double ny = W.z*V.x - W.x*V.z;
double nz = W.x*V.y - W.y*V.x;
length = sqrt(nx*nx+ny*ny+nz*nz);
// new value for V is this normal vector
V.x = nx/length; V.y = ny/length; V.z = nz/length;
dotprod = U.x*V.x + U.y*V.y + U.z*V.z;
if (dotprod < 0.f){
//printf("negative dot product on face\n");
dotprod=-dotprod;
V.x = -V.x; V.y = -V.y; V.z = -V.z;
}
if (dotprod > 1.f) dotprod=1.f;
if (dotprod < -1.f) dotprod=-1.f;
angle = acos(dotprod);
/* project onto plane of cube face also works
W = U - dotprod*V; W = U - dotprod*V;
length = sqrt(W.x*W.x+W.y*W.y+W.z*W.z); // for normalization length = sqrt(W.x*W.x+W.y*W.y+W.z*W.z); // for normalization
dotprod = (U.x*W.x + U.y*W.y + U.z*W.z)/length; dotprod = (U.x*W.x + U.y*W.y + U.z*W.z)/length;
@ -339,71 +379,75 @@ double DCEL::EdgeAngle(int edge)
if (dotprod < -1.f) dotprod=-1.f; if (dotprod < -1.f) dotprod=-1.f;
angle = acos(dotprod); angle = acos(dotprod);
*/ */
} } else {
else{ dotprod = U.x * V.x + U.y * V.y + U.z * V.z;
dotprod=U.x*V.x + U.y*V.y + U.z*V.z; if (dotprod > 1.f)
if (dotprod > 1.f) dotprod=1.f; dotprod = 1.f;
if (dotprod < -1.f) dotprod=-1.f; if (dotprod < -1.f)
angle = 0.5*acos(dotprod); dotprod = -1.f;
} angle = 0.5 * acos(dotprod);
// determine if angle is concave or convex based on edge normal
W.x = (P.y-Q.y)*U.z - (P.z-Q.z)*U.y;
W.y = (P.z-Q.z)*U.x - (P.x-Q.x)*U.z;
W.z = (P.x-Q.x)*U.y - (P.y-Q.y)*U.x;
//length = sqrt(nx*nx+ny*ny+nz*nz);
Point w=0.5*(P+Q)-R;
if (W.x*w.x + W.y*w.y + W.z*w.z < 0.f){
//printf("flip edge normal \n");
W.x = -W.x;
W.y = -W.y;
W.z = -W.z;
}
if (W.x*V.x + W.y*V.y + W.z*V.z > 0.f){
// concave
angle = -angle;
}
if (angle != angle) angle = 0.0;
//printf("angle=%f,dot=%f (Edge=%i, twin=%i): P={%f, %f, %f}, Q={%f, %f, %f} U={%f, %f, %f}, V={%f, %f, %f}\n",angle,dotprod,edge,halfedge.twin(edge),P.x,P.y,P.z,Q.x,Q.y,Q.z,U.x,U.y,U.z,V.x,V.y,V.z);
return angle;
}
void iso_surface(const Array<double>&Field, const double isovalue)
{
DCEL object;
int e1,e2,e3;
FILE *TRIANGLES;
TRIANGLES = fopen("isosurface.stl","w");
fprintf(TRIANGLES,"solid isosurface\n");
int Nx = Field.size(0);
int Ny = Field.size(1);
int Nz = Field.size(2);
for (int k=1; k<Nz-1; k++){
for (int j=1; j<Ny-1; j++){
for (int i=1; i<Nx-1; i++){
object.LocalIsosurface(Field,isovalue,i,j,k);
for (int idx=0; idx<object.TriangleCount; idx++){
e1 = object.Face(idx);
e2 = object.halfedge.next(e1);
e3 = object.halfedge.next(e2);
auto P1 = object.vertex.coords(object.halfedge.v1(e1));
auto P2 = object.vertex.coords(object.halfedge.v1(e2));
auto P3 = object.vertex.coords(object.halfedge.v1(e3));
auto Normal = object.TriNormal(e1);
// P1.x += 1.0*i; P1.y += 1.0*j; P1.z +=1.0*k;
//P2.x += 1.0*i; P2.y += 1.0*j; P2.z +=1.0*k;
//P3.x += 1.0*i; P3.y += 1.0*j; P3.z +=1.0*k;
fprintf(TRIANGLES,"facet normal %f %f %f\n",Normal.x,Normal.y,Normal.z);
fprintf(TRIANGLES," outer loop\n");
fprintf(TRIANGLES," vertex %f %f %f\n",P1.x,P1.y,P1.z);
fprintf(TRIANGLES," vertex %f %f %f\n",P2.x,P2.y,P2.z);
fprintf(TRIANGLES," vertex %f %f %f\n",P3.x,P3.y,P3.z);
fprintf(TRIANGLES," endloop\n");
fprintf(TRIANGLES,"endfacet\n");
}
}
} }
} // determine if angle is concave or convex based on edge normal
fprintf(TRIANGLES,"endsolid isosurface\n"); W.x = (P.y - Q.y) * U.z - (P.z - Q.z) * U.y;
fclose(TRIANGLES); W.y = (P.z - Q.z) * U.x - (P.x - Q.x) * U.z;
W.z = (P.x - Q.x) * U.y - (P.y - Q.y) * U.x;
//length = sqrt(nx*nx+ny*ny+nz*nz);
Point w = 0.5 * (P + Q) - R;
if (W.x * w.x + W.y * w.y + W.z * w.z < 0.f) {
//printf("flip edge normal \n");
W.x = -W.x;
W.y = -W.y;
W.z = -W.z;
}
if (W.x * V.x + W.y * V.y + W.z * V.z > 0.f) {
// concave
angle = -angle;
}
if (angle != angle)
angle = 0.0;
//printf("angle=%f,dot=%f (Edge=%i, twin=%i): P={%f, %f, %f}, Q={%f, %f, %f} U={%f, %f, %f}, V={%f, %f, %f}\n",angle,dotprod,edge,halfedge.twin(edge),P.x,P.y,P.z,Q.x,Q.y,Q.z,U.x,U.y,U.z,V.x,V.y,V.z);
return angle;
}
void iso_surface(const Array<double> &Field, const double isovalue) {
DCEL object;
int e1, e2, e3;
FILE *TRIANGLES;
TRIANGLES = fopen("isosurface.stl", "w");
fprintf(TRIANGLES, "solid isosurface\n");
int Nx = Field.size(0);
int Ny = Field.size(1);
int Nz = Field.size(2);
for (int k = 1; k < Nz - 1; k++) {
for (int j = 1; j < Ny - 1; j++) {
for (int i = 1; i < Nx - 1; i++) {
object.LocalIsosurface(Field, isovalue, i, j, k);
for (int idx = 0; idx < object.TriangleCount; idx++) {
e1 = object.Face(idx);
e2 = object.halfedge.next(e1);
e3 = object.halfedge.next(e2);
auto P1 = object.vertex.coords(object.halfedge.v1(e1));
auto P2 = object.vertex.coords(object.halfedge.v1(e2));
auto P3 = object.vertex.coords(object.halfedge.v1(e3));
auto Normal = object.TriNormal(e1);
// P1.x += 1.0*i; P1.y += 1.0*j; P1.z +=1.0*k;
//P2.x += 1.0*i; P2.y += 1.0*j; P2.z +=1.0*k;
//P3.x += 1.0*i; P3.y += 1.0*j; P3.z +=1.0*k;
fprintf(TRIANGLES, "facet normal %f %f %f\n", Normal.x,
Normal.y, Normal.z);
fprintf(TRIANGLES, " outer loop\n");
fprintf(TRIANGLES, " vertex %f %f %f\n", P1.x, P1.y,
P1.z);
fprintf(TRIANGLES, " vertex %f %f %f\n", P2.x, P2.y,
P2.z);
fprintf(TRIANGLES, " vertex %f %f %f\n", P3.x, P3.y,
P3.z);
fprintf(TRIANGLES, " endloop\n");
fprintf(TRIANGLES, "endfacet\n");
}
}
}
}
fprintf(TRIANGLES, "endsolid isosurface\n");
fclose(TRIANGLES);
} }

View File

@ -10,85 +10,85 @@
*/ */
// Vertex structure // Vertex structure
class Vertex{ class Vertex {
public: public:
Vertex() { d_data.resize(12); } Vertex() { d_data.resize(12); }
~Vertex() = default; ~Vertex() = default;
Vertex( const Vertex& ) = delete; Vertex(const Vertex &) = delete;
Vertex operator=( const Vertex& ) = delete; Vertex operator=(const Vertex &) = delete;
// Add/assign a point // Add/assign a point
inline void add( const Point& P ) { d_data.push_back( P ); } inline void add(const Point &P) { d_data.push_back(P); }
inline void assign( int idx, const Point& P ) { d_data[idx] = P; } inline void assign(int idx, const Point &P) { d_data[idx] = P; }
// Get a point // Get a point
inline Point& coords( int idx ) { return d_data[idx]; } inline Point &coords(int idx) { return d_data[idx]; }
inline const Point& coords( int idx ) const { return d_data[idx]; } inline const Point &coords(int idx) const { return d_data[idx]; }
int IncidentEdge(); int IncidentEdge();
// Return the number of points // Return the number of points
inline int size() const { return d_data.size(); } inline int size() const { return d_data.size(); }
private: private:
std::vector<Point> d_data; std::vector<Point> d_data;
}; };
/** /**
* \class Halfedge * \class Halfedge
* @brief store half edge for DCEL data structure * @brief store half edge for DCEL data structure
*/ */
class Halfedge{ class Halfedge {
public: public:
Halfedge() = default; Halfedge() = default;
~Halfedge() = default; ~Halfedge() = default;
Halfedge( const Halfedge& ) = delete; Halfedge(const Halfedge &) = delete;
Halfedge operator=( const Halfedge& ) = delete; Halfedge operator=(const Halfedge &) = delete;
inline int v1(int edge) const { return d_data[edge][0]; } inline int v1(int edge) const { return d_data[edge][0]; }
inline int v2(int edge) const { return d_data[edge][1]; } inline int v2(int edge) const { return d_data[edge][1]; }
inline int face(int edge) const { return d_data[edge][2]; } inline int face(int edge) const { return d_data[edge][2]; }
inline int twin(int edge) const { return d_data[edge][3]; } inline int twin(int edge) const { return d_data[edge][3]; }
inline int prev(int edge) const { return d_data[edge][4]; } inline int prev(int edge) const { return d_data[edge][4]; }
inline int next(int edge) const { return d_data[edge][5]; } inline int next(int edge) const { return d_data[edge][5]; }
inline int size() const { return d_data.size(); } inline int size() const { return d_data.size(); }
inline void resize( int N ) { d_data.resize( N ); } inline void resize(int N) { d_data.resize(N); }
inline int& data( int i, int j ) { return d_data[j][i]; } inline int &data(int i, int j) { return d_data[j][i]; }
inline const int& data( int i, int j ) const { return d_data[j][i]; } inline const int &data(int i, int j) const { return d_data[j][i]; }
private: private:
std::vector<std::array<int,6>> d_data; std::vector<std::array<int, 6>> d_data;
}; };
/** /**
* \class DCEL * \class DCEL
* @details doubly connected edge list data structure * @details doubly connected edge list data structure
*/ */
class DCEL{ class DCEL {
public: public:
DCEL(); DCEL();
~DCEL(); ~DCEL();
int face(); int face();
Vertex vertex; Vertex vertex;
Halfedge halfedge; Halfedge halfedge;
void LocalIsosurface(const DoubleArray& A, double value, int i, int j, int k); void LocalIsosurface(const DoubleArray &A, double value, int i, int j,
void Write(); int k);
int Face(int index); void Write();
int Face(int index);
double origin(int edge);
double EdgeAngle(int edge); double origin(int edge);
Point TriNormal(int edge); double EdgeAngle(int edge);
int TriangleCount; Point TriNormal(int edge);
int VertexCount; int TriangleCount;
int VertexCount;
private: private:
std::vector<int> FaceData; std::vector<int> FaceData;
}; };
void iso_surface(const Array<double>&Field, const double isovalue); void iso_surface(const Array<double> &Field, const double isovalue);
#endif #endif

View File

@ -16,39 +16,37 @@
*/ */
#include "analysis/distance.h" #include "analysis/distance.h"
/****************************************************************** /******************************************************************
* A fast distance calculation * * A fast distance calculation *
******************************************************************/ ******************************************************************/
template<class TYPE> template <class TYPE>
void CalcDist( Array<TYPE> &Distance, const Array<char> &ID, const Domain &Dm, void CalcDist(Array<TYPE> &Distance, const Array<char> &ID, const Domain &Dm,
const std::array<bool,3>& periodic, const std::array<double,3>& dx ) const std::array<bool, 3> &periodic,
{ const std::array<double, 3> &dx) {
ASSERT( Distance.size() == ID.size() ); ASSERT(Distance.size() == ID.size());
std::array<int,3> n = { Dm.Nx-2, Dm.Ny-2, Dm.Nz-2 }; std::array<int, 3> n = {Dm.Nx - 2, Dm.Ny - 2, Dm.Nz - 2};
fillHalo<int> fillData( Dm.Comm, Dm.rank_info, n, {1,1,1}, 50, 1, {true,false,false}, periodic ); fillHalo<int> fillData(Dm.Comm, Dm.rank_info, n, {1, 1, 1}, 50, 1,
{true, false, false}, periodic);
Array<int> id(ID.size()); Array<int> id(ID.size());
Array<Vec> vecDist(Distance.size()); Array<Vec> vecDist(Distance.size());
for (size_t i=0; i<ID.length(); i++) for (size_t i = 0; i < ID.length(); i++)
id(i) = ID(i) == 0 ? -1:1; id(i) = ID(i) == 0 ? -1 : 1;
fillData.fill( id ); fillData.fill(id);
CalcVecDist( vecDist, id, Dm, periodic, dx ); CalcVecDist(vecDist, id, Dm, periodic, dx);
for (size_t i=0; i<Distance.length(); i++) for (size_t i = 0; i < Distance.length(); i++)
Distance(i) = id(i)*vecDist(i).norm(); Distance(i) = id(i) * vecDist(i).norm();
} }
/****************************************************************** /******************************************************************
* Vector-based distance calculation * * Vector-based distance calculation *
* Initialize cells adjacent to boundaries * * Initialize cells adjacent to boundaries *
******************************************************************/ ******************************************************************/
static void calcVecInitialize( Array<Vec> &d, const Array<int> &ID, double dx, double dy, double dz ) static void calcVecInitialize(Array<Vec> &d, const Array<int> &ID, double dx,
{ double dy, double dz) {
d.fill( Vec( 1e50, 1e50, 1e50 ) ); d.fill(Vec(1e50, 1e50, 1e50));
const double dx0 = 0.5*dx; const double dx0 = 0.5 * dx;
const double dy0 = 0.5*dy; const double dy0 = 0.5 * dy;
const double dz0 = 0.5*dz; const double dz0 = 0.5 * dz;
//const double dxy0 = 0.25*sqrt( dx*dx + dy*dy ); //const double dxy0 = 0.25*sqrt( dx*dx + dy*dy );
//const double dxz0 = 0.25*sqrt( dx*dx + dz*dz ); //const double dxz0 = 0.25*sqrt( dx*dx + dz*dz );
//const double dyz0 = 0.25*sqrt( dy*dy + dz*dz ); //const double dyz0 = 0.25*sqrt( dy*dy + dz*dz );
@ -56,19 +54,25 @@ static void calcVecInitialize( Array<Vec> &d, const Array<int> &ID, double dx, d
int Nx = d.size(0); int Nx = d.size(0);
int Ny = d.size(1); int Ny = d.size(1);
int Nz = d.size(2); int Nz = d.size(2);
for (int k=1; k<Nz-1; k++) { for (int k = 1; k < Nz - 1; k++) {
for (int j=1; j<Ny-1; j++) { for (int j = 1; j < Ny - 1; j++) {
for (int i=1; i<Nx-1; i++) { for (int i = 1; i < Nx - 1; i++) {
int id = ID(i,j,k); int id = ID(i, j, k);
bool x[2] = { id != ID(i-1,j,k), id != ID(i+1,j,k) }; bool x[2] = {id != ID(i - 1, j, k), id != ID(i + 1, j, k)};
bool y[2] = { id != ID(i,j-1,k), id != ID(i,j+1,k) }; bool y[2] = {id != ID(i, j - 1, k), id != ID(i, j + 1, k)};
bool z[2] = { id != ID(i,j,k-1), id != ID(i,j,k+1) }; bool z[2] = {id != ID(i, j, k - 1), id != ID(i, j, k + 1)};
if ( x[0] ) d(i,j,k) = Vec( dx0, 0, 0 ); if (x[0])
if ( x[1] ) d(i,j,k) = Vec( -dx0, 0, 0 ); d(i, j, k) = Vec(dx0, 0, 0);
if ( y[0] ) d(i,j,k) = Vec( 0, dy0, 0 ); if (x[1])
if ( y[1] ) d(i,j,k) = Vec( 0, -dy0, 0 ); d(i, j, k) = Vec(-dx0, 0, 0);
if ( z[0] ) d(i,j,k) = Vec( 0, 0, dz0 ); if (y[0])
if ( z[1] ) d(i,j,k) = Vec( 0, 0, -dz0 ); d(i, j, k) = Vec(0, dy0, 0);
if (y[1])
d(i, j, k) = Vec(0, -dy0, 0);
if (z[0])
d(i, j, k) = Vec(0, 0, dz0);
if (z[1])
d(i, j, k) = Vec(0, 0, -dz0);
/*if ( x[0] && y[0] ) d(i,j,k) = Vec( dxy0, dxy0, 0 ); /*if ( x[0] && y[0] ) d(i,j,k) = Vec( dxy0, dxy0, 0 );
if ( x[0] && y[1] ) d(i,j,k) = Vec( dxy0, -dxy0, 0 ); if ( x[0] && y[1] ) d(i,j,k) = Vec( dxy0, -dxy0, 0 );
if ( x[1] && y[0] ) d(i,j,k) = Vec( -dxy0, dxy0, 0 ); if ( x[1] && y[0] ) d(i,j,k) = Vec( -dxy0, dxy0, 0 );
@ -84,56 +88,54 @@ static void calcVecInitialize( Array<Vec> &d, const Array<int> &ID, double dx, d
} }
} }
} }
} }
/****************************************************************** /******************************************************************
* Vector-based distance calculation * * Vector-based distance calculation *
* Update interior cells * * Update interior cells *
******************************************************************/ ******************************************************************/
static double calcVecUpdateInterior( Array<Vec> &d, double dx, double dy, double dz ) static double calcVecUpdateInterior(Array<Vec> &d, double dx, double dy,
{ double dz) {
double err = 0; double err = 0;
int Nx = d.size(0); int Nx = d.size(0);
int Ny = d.size(1); int Ny = d.size(1);
int Nz = d.size(2); int Nz = d.size(2);
// Propagate (+,+,+) // Propagate (+,+,+)
for (int k=1; k<Nz; k++) { for (int k = 1; k < Nz; k++) {
for (int j=1; j<Ny; j++) { for (int j = 1; j < Ny; j++) {
for (int i=1; i<Nx; i++) { for (int i = 1; i < Nx; i++) {
auto vx = d(i-1,j,k); auto vx = d(i - 1, j, k);
auto vy = d(i,j-1,k); auto vy = d(i, j - 1, k);
auto vz = d(i,j,k-1); auto vz = d(i, j, k - 1);
vx.x += dx; vx.x += dx;
vy.y += dy; vy.y += dy;
vz.z += dz; vz.z += dz;
auto v = std::min( std::min(vx,vy), vz ); auto v = std::min(std::min(vx, vy), vz);
double d1 = v.norm2(); double d1 = v.norm2();
double d2 = d(i,j,k).norm2(); double d2 = d(i, j, k).norm2();
if ( d1 < d2 ) { if (d1 < d2) {
d(i,j,k) = v; d(i, j, k) = v;
err = std::max( err, sqrt(d2)-sqrt(d1) ); err = std::max(err, sqrt(d2) - sqrt(d1));
} }
} }
} }
} }
// Propagate (-,-,-) // Propagate (-,-,-)
for (int k=Nz-2; k>=0; k--) { for (int k = Nz - 2; k >= 0; k--) {
for (int j=Ny-2; j>=0; j--) { for (int j = Ny - 2; j >= 0; j--) {
for (int i=Nx-2; i>=0; i--) { for (int i = Nx - 2; i >= 0; i--) {
auto vx = d(i+1,j,k); auto vx = d(i + 1, j, k);
auto vy = d(i,j+1,k); auto vy = d(i, j + 1, k);
auto vz = d(i,j,k+1); auto vz = d(i, j, k + 1);
vx.x -= dx; vx.x -= dx;
vy.y -= dy; vy.y -= dy;
vz.z -= dz; vz.z -= dz;
auto v = std::min( std::min(vx,vy), vz ); auto v = std::min(std::min(vx, vy), vz);
double d1 = v.norm2(); double d1 = v.norm2();
double d2 = d(i,j,k).norm2(); double d2 = d(i, j, k).norm2();
if ( d1 < d2 ) { if (d1 < d2) {
d(i,j,k) = v; d(i, j, k) = v;
err = std::max( err, sqrt(d2)-sqrt(d1) ); err = std::max(err, sqrt(d2) - sqrt(d1));
} }
} }
} }
@ -141,66 +143,68 @@ static double calcVecUpdateInterior( Array<Vec> &d, double dx, double dy, double
return err; return err;
} }
/****************************************************************** /******************************************************************
* Vector-based distance calculation * * Vector-based distance calculation *
******************************************************************/ ******************************************************************/
void CalcVecDist( Array<Vec> &d, const Array<int> &ID0, const Domain &Dm, void CalcVecDist(Array<Vec> &d, const Array<int> &ID0, const Domain &Dm,
const std::array<bool,3>& periodic, const std::array<double,3>& dx ) const std::array<bool, 3> &periodic,
{ const std::array<double, 3> &dx) {
std::array<int,3> N = { Dm.Nx, Dm.Ny, Dm.Nz }; std::array<int, 3> N = {Dm.Nx, Dm.Ny, Dm.Nz};
std::array<int,3> n = { Dm.Nx-2, Dm.Ny-2, Dm.Nz-2 }; std::array<int, 3> n = {Dm.Nx - 2, Dm.Ny - 2, Dm.Nz - 2};
// Create ID with ghosts // Create ID with ghosts
Array<int> ID(N[0],N[1],N[2]); Array<int> ID(N[0], N[1], N[2]);
fillHalo<int> fillDataID( Dm.Comm, Dm.rank_info, n, {1,1,1}, 50, 1, {true,true,true}, periodic ); fillHalo<int> fillDataID(Dm.Comm, Dm.rank_info, n, {1, 1, 1}, 50, 1,
fillDataID.copy( ID0, ID ); {true, true, true}, periodic);
fillDataID.copy(ID0, ID);
// Fill ghosts with nearest neighbor // Fill ghosts with nearest neighbor
for (int k=1; k<N[2]-1; k++) { for (int k = 1; k < N[2] - 1; k++) {
for (int j=1; j<N[1]-1; j++) { for (int j = 1; j < N[1] - 1; j++) {
ID(0,j,k) = ID(1,j,k); ID(0, j, k) = ID(1, j, k);
ID(N[0]-1,j,k) = ID(N[0]-2,j,k); ID(N[0] - 1, j, k) = ID(N[0] - 2, j, k);
} }
} }
for (int k=1; k<N[2]-1; k++) { for (int k = 1; k < N[2] - 1; k++) {
for (int i=0; i<N[0]; i++) { for (int i = 0; i < N[0]; i++) {
ID(i,0,k) = ID(i,1,k); ID(i, 0, k) = ID(i, 1, k);
ID(i,N[1]-1,k) = ID(i,N[1]-2,k); ID(i, N[1] - 1, k) = ID(i, N[1] - 2, k);
} }
} }
for (int i=0; i<N[0]; i++) { for (int i = 0; i < N[0]; i++) {
for (int j=0; j<N[1]; j++) { for (int j = 0; j < N[1]; j++) {
ID(i,j,0) = ID(i,j,1); ID(i, j, 0) = ID(i, j, 1);
ID(i,j,N[2]-1) = ID(i,j,N[2]-2); ID(i, j, N[2] - 1) = ID(i, j, N[2] - 2);
} }
} }
// Communicate ghosts // Communicate ghosts
fillDataID.fill( ID ); fillDataID.fill(ID);
// Create communicator for distance // Create communicator for distance
fillHalo<Vec> fillData( Dm.Comm, Dm.rank_info, n, {1,1,1}, 50, 1, {true,false,false}, periodic ); fillHalo<Vec> fillData(Dm.Comm, Dm.rank_info, n, {1, 1, 1}, 50, 1,
{true, false, false}, periodic);
// Calculate the local distances // Calculate the local distances
calcVecInitialize( d, ID, dx[0], dx[1], dx[2] ); calcVecInitialize(d, ID, dx[0], dx[1], dx[2]);
double err = 1e100; double err = 1e100;
double tol = 0.5 * std::min( std::min(dx[0],dx[1]), dx[2] ); double tol = 0.5 * std::min(std::min(dx[0], dx[1]), dx[2]);
for (int it=0; it<=50 && err>tol; it++) { for (int it = 0; it <= 50 && err > tol; it++) {
err = calcVecUpdateInterior( d, dx[0], dx[1], dx[2] ); err = calcVecUpdateInterior(d, dx[0], dx[1], dx[2]);
} }
// Calculate the global distances // Calculate the global distances
int N_it = Dm.nprocx() + Dm.nprocy() + Dm.nprocz() + 100; int N_it = Dm.nprocx() + Dm.nprocy() + Dm.nprocz() + 100;
for ( int it=0; it<N_it; it++ ) { for (int it = 0; it < N_it; it++) {
// Update ghosts // Update ghosts
fillData.fill( d ); fillData.fill(d);
// Update distance // Update distance
double err = calcVecUpdateInterior( d, dx[0], dx[1], dx[2] ); double err = calcVecUpdateInterior(d, dx[0], dx[1], dx[2]);
// Check if we are finished // Check if we are finished
err = Dm.Comm.maxReduce( err ); err = Dm.Comm.maxReduce(err);
if ( err < tol ) if (err < tol)
break; break;
} }
} }
// Explicit instantiations // Explicit instantiations
template void CalcDist<float>( Array<float>&, const Array<char>&, const Domain&, const std::array<bool,3>&, const std::array<double,3>& ); template void CalcDist<float>(Array<float> &, const Array<char> &,
template void CalcDist<double>( Array<double>&, const Array<char>&, const Domain&, const std::array<bool,3>&, const std::array<double,3>& ); const Domain &, const std::array<bool, 3> &,
const std::array<double, 3> &);
template void CalcDist<double>(Array<double> &, const Array<char> &,
const Domain &, const std::array<bool, 3> &,
const std::array<double, 3> &);

View File

@ -20,18 +20,19 @@
#include "common/Domain.h" #include "common/Domain.h"
#include "common/Array.hpp" #include "common/Array.hpp"
struct Vec { struct Vec {
double x; double x;
double y; double y;
double z; double z;
inline Vec(): x(0), y(0), z(0) {} inline Vec() : x(0), y(0), z(0) {}
inline Vec( double x_, double y_, double z_ ): x(x_), y(y_), z(z_) {} inline Vec(double x_, double y_, double z_) : x(x_), y(y_), z(z_) {}
inline double norm() const { return sqrt(x*x+y*y+z*z); } inline double norm() const { return sqrt(x * x + y * y + z * z); }
inline double norm2() const { return x*x+y*y+z*z; } inline double norm2() const { return x * x + y * y + z * z; }
}; };
inline bool operator<(const Vec& l, const Vec& r){ return l.x*l.x+l.y*l.y+l.z*l.z < r.x*r.x+r.y*r.y+r.z*r.z; } inline bool operator<(const Vec &l, const Vec &r) {
return l.x * l.x + l.y * l.y + l.z * l.z <
r.x * r.x + r.y * r.y + r.z * r.z;
}
/*! /*!
* @brief Calculate the distance using a simple method * @brief Calculate the distance using a simple method
@ -42,9 +43,10 @@ inline bool operator<(const Vec& l, const Vec& r){ return l.x*l.x+l.y*l.y+l.z*l.
* @param[in] periodic Directions that are periodic * @param[in] periodic Directions that are periodic
* @param[in] dx Cell size * @param[in] dx Cell size
*/ */
template<class TYPE> template <class TYPE>
void CalcDist( Array<TYPE> &Distance, const Array<char> &ID, const Domain &Dm, void CalcDist(Array<TYPE> &Distance, const Array<char> &ID, const Domain &Dm,
const std::array<bool,3>& periodic = {true,true,true}, const std::array<double,3>& dx = {1,1,1} ); const std::array<bool, 3> &periodic = {true, true, true},
const std::array<double, 3> &dx = {1, 1, 1});
/*! /*!
* @brief Calculate the distance using a simple method * @brief Calculate the distance using a simple method
@ -55,7 +57,8 @@ void CalcDist( Array<TYPE> &Distance, const Array<char> &ID, const Domain &Dm,
* @param[in] periodic Directions that are periodic * @param[in] periodic Directions that are periodic
* @param[in] dx Cell size * @param[in] dx Cell size
*/ */
void CalcVecDist( Array<Vec> &Distance, const Array<int> &ID, const Domain &Dm, void CalcVecDist(Array<Vec> &Distance, const Array<int> &ID, const Domain &Dm,
const std::array<bool,3>& periodic = {true,true,true}, const std::array<double,3>& dx = {1,1,1} ); const std::array<bool, 3> &periodic = {true, true, true},
const std::array<double, 3> &dx = {1, 1, 1});
#endif #endif

View File

@ -18,175 +18,181 @@
#include "math.h" #include "math.h"
#include "ProfilerApp.h" #include "ProfilerApp.h"
void Mean3D( const Array<double> &Input, Array<double> &Output ) void Mean3D(const Array<double> &Input, Array<double> &Output) {
{ PROFILE_START("Mean3D");
PROFILE_START("Mean3D"); // Perform a 3D Mean filter on Input array
// Perform a 3D Mean filter on Input array int i, j, k;
int i,j,k;
int Nx = int(Input.size(0)); int Nx = int(Input.size(0));
int Ny = int(Input.size(1)); int Ny = int(Input.size(1));
int Nz = int(Input.size(2)); int Nz = int(Input.size(2));
for (k=1; k<Nz-1; k++){ for (k = 1; k < Nz - 1; k++) {
for (j=1; j<Ny-1; j++){ for (j = 1; j < Ny - 1; j++) {
for (i=1; i<Nx-1; i++){ for (i = 1; i < Nx - 1; i++) {
double MeanValue = Input(i,j,k); double MeanValue = Input(i, j, k);
// next neighbors // next neighbors
MeanValue += Input(i+1,j,k)+Input(i,j+1,k)+Input(i,j,k+1)+Input(i-1,j,k)+Input(i,j-1,k)+Input(i,j,k-1); MeanValue += Input(i + 1, j, k) + Input(i, j + 1, k) +
MeanValue += Input(i+1,j+1,k)+Input(i-1,j+1,k)+Input(i+1,j-1,k)+Input(i-1,j-1,k); Input(i, j, k + 1) + Input(i - 1, j, k) +
MeanValue += Input(i+1,j,k+1)+Input(i-1,j,k+1)+Input(i+1,j,k-1)+Input(i-1,j,k-1); Input(i, j - 1, k) + Input(i, j, k - 1);
MeanValue += Input(i,j+1,k+1)+Input(i,j-1,k+1)+Input(i,j+1,k-1)+Input(i,j-1,k-1); MeanValue += Input(i + 1, j + 1, k) + Input(i - 1, j + 1, k) +
MeanValue += Input(i+1,j+1,k+1)+Input(i-1,j+1,k+1)+Input(i+1,j-1,k+1)+Input(i-1,j-1,k+1); Input(i + 1, j - 1, k) + Input(i - 1, j - 1, k);
MeanValue += Input(i+1,j+1,k-1)+Input(i-1,j+1,k-1)+Input(i+1,j-1,k-1)+Input(i-1,j-1,k-1); MeanValue += Input(i + 1, j, k + 1) + Input(i - 1, j, k + 1) +
Output(i,j,k) = MeanValue/27.0; Input(i + 1, j, k - 1) + Input(i - 1, j, k - 1);
} MeanValue += Input(i, j + 1, k + 1) + Input(i, j - 1, k + 1) +
} Input(i, j + 1, k - 1) + Input(i, j - 1, k - 1);
} MeanValue +=
PROFILE_STOP("Mean3D"); Input(i + 1, j + 1, k + 1) + Input(i - 1, j + 1, k + 1) +
Input(i + 1, j - 1, k + 1) + Input(i - 1, j - 1, k + 1);
MeanValue +=
Input(i + 1, j + 1, k - 1) + Input(i - 1, j + 1, k - 1) +
Input(i + 1, j - 1, k - 1) + Input(i - 1, j - 1, k - 1);
Output(i, j, k) = MeanValue / 27.0;
}
}
}
PROFILE_STOP("Mean3D");
} }
void Med3D( const Array<float> &Input, Array<float> &Output ) void Med3D(const Array<float> &Input, Array<float> &Output) {
{ PROFILE_START("Med3D");
PROFILE_START("Med3D"); // Perform a 3D Median filter on Input array with specified width
// Perform a 3D Median filter on Input array with specified width int i, j, k, ii, jj, kk;
int i,j,k,ii,jj,kk; int imin, jmin, kmin, imax, jmax, kmax;
int imin,jmin,kmin,imax,jmax,kmax;
float *List; float *List;
List=new float[27]; List = new float[27];
int Nx = int(Input.size(0)); int Nx = int(Input.size(0));
int Ny = int(Input.size(1)); int Ny = int(Input.size(1));
int Nz = int(Input.size(2)); int Nz = int(Input.size(2));
for (k=1; k<Nz-1; k++){ for (k = 1; k < Nz - 1; k++) {
for (j=1; j<Ny-1; j++){ for (j = 1; j < Ny - 1; j++) {
for (i=1; i<Nx-1; i++){ for (i = 1; i < Nx - 1; i++) {
// Just use a 3x3x3 window (hit recursively if needed) // Just use a 3x3x3 window (hit recursively if needed)
imin = i-1; imin = i - 1;
jmin = j-1; jmin = j - 1;
kmin = k-1; kmin = k - 1;
imax = i+2; imax = i + 2;
jmax = j+2; jmax = j + 2;
kmax = k+2; kmax = k + 2;
// Populate the list with values in the window // Populate the list with values in the window
int Number=0; int Number = 0;
for (kk=kmin; kk<kmax; kk++){ for (kk = kmin; kk < kmax; kk++) {
for (jj=jmin; jj<jmax; jj++){ for (jj = jmin; jj < jmax; jj++) {
for (ii=imin; ii<imax; ii++){ for (ii = imin; ii < imax; ii++) {
List[Number++] = Input(ii,jj,kk); List[Number++] = Input(ii, jj, kk);
} }
} }
} }
// Sort the first 5 entries and return the median // Sort the first 5 entries and return the median
for (ii=0; ii<14; ii++){ for (ii = 0; ii < 14; ii++) {
for (jj=ii+1; jj<27; jj++){ for (jj = ii + 1; jj < 27; jj++) {
if (List[jj] < List[ii]){ if (List[jj] < List[ii]) {
float tmp = List[ii]; float tmp = List[ii];
List[ii] = List[jj]; List[ii] = List[jj];
List[jj] = tmp; List[jj] = tmp;
} }
} }
} }
// Return the median // Return the median
Output(i,j,k) = List[13]; Output(i, j, k) = List[13];
} }
} }
} }
PROFILE_STOP("Med3D"); PROFILE_STOP("Med3D");
} }
int NLM3D(const Array<float> &Input, Array<float> &Mean,
const Array<float> &Distance, Array<float> &Output, const int d,
const float h) {
PROFILE_START("NLM3D");
// Implemenation of 3D non-local means filter
// d determines the width of the search volume
// h is a free parameter for non-local means (i.e. 1/sigma^2)
// Distance is the signed distance function
// If Distance(i,j,k) > THRESHOLD_DIST then don't compute NLM
int NLM3D( const Array<float> &Input, Array<float> &Mean, float THRESHOLD_DIST = float(d);
const Array<float> &Distance, Array<float> &Output, const int d, const float h) float weight, sum;
{ int i, j, k, ii, jj, kk;
PROFILE_START("NLM3D"); int imin, jmin, kmin, imax, jmax, kmax;
// Implemenation of 3D non-local means filter int returnCount = 0;
// d determines the width of the search volume
// h is a free parameter for non-local means (i.e. 1/sigma^2)
// Distance is the signed distance function
// If Distance(i,j,k) > THRESHOLD_DIST then don't compute NLM
float THRESHOLD_DIST = float(d); int Nx = int(Input.size(0));
float weight, sum; int Ny = int(Input.size(1));
int i,j,k,ii,jj,kk; int Nz = int(Input.size(2));
int imin,jmin,kmin,imax,jmax,kmax;
int returnCount=0;
int Nx = int(Input.size(0)); // Compute the local means
int Ny = int(Input.size(1)); for (k = 1; k < Nz - 1; k++) {
int Nz = int(Input.size(2)); for (j = 1; j < Ny - 1; j++) {
for (i = 1; i < Nx - 1; i++) {
// Compute the local means imin = std::max(0, i - d);
for (k=1; k<Nz-1; k++){ jmin = std::max(0, j - d);
for (j=1; j<Ny-1; j++){ kmin = std::max(0, k - d);
for (i=1; i<Nx-1; i++){ imax = std::min(Nx - 1, i + d);
jmax = std::min(Ny - 1, j + d);
kmax = std::min(Nz - 1, k + d);
imin = std::max(0,i-d); // Populate the list with values in the window
jmin = std::max(0,j-d); sum = 0;
kmin = std::max(0,k-d); weight = 0;
imax = std::min(Nx-1,i+d); for (kk = kmin; kk < kmax; kk++) {
jmax = std::min(Ny-1,j+d); for (jj = jmin; jj < jmax; jj++) {
kmax = std::min(Nz-1,k+d); for (ii = imin; ii < imax; ii++) {
sum += Input(ii, jj, kk);
weight++;
}
}
}
// Populate the list with values in the window Mean(i, j, k) = sum / weight;
sum = 0; weight=0; }
for (kk=kmin; kk<kmax; kk++){ }
for (jj=jmin; jj<jmax; jj++){ }
for (ii=imin; ii<imax; ii++){
sum += Input(ii,jj,kk);
weight++;
}
}
}
Mean(i,j,k) = sum / weight; // Compute the non-local means
} for (k = 1; k < Nz - 1; k++) {
} for (j = 1; j < Ny - 1; j++) {
} for (i = 1; i < Nx - 1; i++) {
// Compute the non-local means if (fabs(Distance(i, j, k)) < THRESHOLD_DIST) {
for (k=1; k<Nz-1; k++){ // compute the expensive non-local means
for (j=1; j<Ny-1; j++){ sum = 0;
for (i=1; i<Nx-1; i++){ weight = 0;
imin = std::max(0, i - d);
jmin = std::max(0, j - d);
kmin = std::max(0, k - d);
imax = std::min(Nx - 1, i + d);
jmax = std::min(Ny - 1, j + d);
kmax = std::min(Nz - 1, k + d);
if (fabs(Distance(i,j,k)) < THRESHOLD_DIST){ for (kk = kmin; kk < kmax; kk++) {
// compute the expensive non-local means for (jj = jmin; jj < jmax; jj++) {
sum = 0; weight=0; for (ii = imin; ii < imax; ii++) {
float tmp = Mean(i, j, k) - Mean(ii, jj, kk);
sum += exp(-tmp * tmp * h) * Input(ii, jj, kk);
weight += exp(-tmp * tmp * h);
}
}
}
imin = std::max(0,i-d); returnCount++;
jmin = std::max(0,j-d); //Output(i,j,k) = Mean(i,j,k);
kmin = std::max(0,k-d); Output(i, j, k) = sum / weight;
imax = std::min(Nx-1,i+d); } else {
jmax = std::min(Ny-1,j+d); // Just return the mean
kmax = std::min(Nz-1,k+d); Output(i, j, k) = Mean(i, j, k);
}
for (kk=kmin; kk<kmax; kk++){ }
for (jj=jmin; jj<jmax; jj++){ }
for (ii=imin; ii<imax; ii++){ }
float tmp = Mean(i,j,k) - Mean(ii,jj,kk); // Return the number of sites where NLM was applied
sum += exp(-tmp*tmp*h)*Input(ii,jj,kk); PROFILE_STOP("NLM3D");
weight += exp(-tmp*tmp*h); return returnCount;
}
}
}
returnCount++;
//Output(i,j,k) = Mean(i,j,k);
Output(i,j,k) = sum / weight;
}
else{
// Just return the mean
Output(i,j,k) = Mean(i,j,k);
}
}
}
}
// Return the number of sites where NLM was applied
PROFILE_STOP("NLM3D");
return returnCount;
} }

View File

@ -17,7 +17,6 @@
#ifndef Filters_H_INC #ifndef Filters_H_INC
#define Filters_H_INC #define Filters_H_INC
#include "common/Array.h" #include "common/Array.h"
/*! /*!
@ -26,7 +25,7 @@
* @param[in] Input Input image * @param[in] Input Input image
* @param[out] Output Output image * @param[out] Output Output image
*/ */
void Mean3D( const Array<double> &Input, Array<double> &Output ); void Mean3D(const Array<double> &Input, Array<double> &Output);
/*! /*!
* @brief Filter image * @brief Filter image
@ -34,7 +33,7 @@ void Mean3D( const Array<double> &Input, Array<double> &Output );
* @param[in] Input Input image * @param[in] Input Input image
* @param[out] Output Output image * @param[out] Output Output image
*/ */
void Med3D( const Array<float> &Input, Array<float> &Output ); void Med3D(const Array<float> &Input, Array<float> &Output);
/*! /*!
* @brief Filter image * @brief Filter image
@ -46,8 +45,8 @@ void Med3D( const Array<float> &Input, Array<float> &Output );
* @param[in] d * @param[in] d
* @param[in] h * @param[in] h
*/ */
int NLM3D( const Array<float> &Input, Array<float> &Mean, int NLM3D(const Array<float> &Input, Array<float> &Mean,
const Array<float> &Distance, Array<float> &Output, const int d, const float h); const Array<float> &Distance, Array<float> &Output, const int d,
const float h);
#endif #endif

View File

@ -21,43 +21,45 @@
#define HISTOGRAM_RESOLUTION 1000 #define HISTOGRAM_RESOLUTION 1000
struct Histogram{ struct Histogram {
Histogram(double v1, double v2){ Histogram(double v1, double v2) {
data = new double[HISTOGRAM_RESOLUTION]; data = new double[HISTOGRAM_RESOLUTION];
minimum = v1; minimum = v1;
maximum = v2; maximum = v2;
delta = (maximum-minimum)/HISTOGRAM_RESOLUTION; delta = (maximum - minimum) / HISTOGRAM_RESOLUTION;
} }
~Histogram{ ~Histogram { delete *data; }
delete *data; double *data;
} double minimum, maximum, delta;
double *data;
double minimum,maximum,delta; // Adds value into the histogram
void IncludeValue(double value, double weight) {
// Adds value into the histogram idx = floor((value - min) / delta);
void IncludeValue(double value, double weight){ if (idx > HISTOGRAM_RESOLUTION)
idx = floor((value-min)/delta); ;
if (idx > HISTOGRAM_RESOLUTION) ; else if (idx < 0)
else if (idx < 0) ; ;
else data[idx] += weight; else
} data[idx] += weight;
}
// Returns the maximum value in the histogram
void GetMax(){ // Returns the maximum value in the histogram
max = minimum; void GetMax() {
for (idx=1; idx<HISTOGRAM_RESOLUTION; idx++){ max = minimum;
if (data[idx] > max){ for (idx = 1; idx < HISTOGRAM_RESOLUTION; idx++) {
max = minimum+idx*delta; if (data[idx] > max) {
} max = minimum + idx * delta;
} }
} }
}
// Resets the histogram to zero
void Reset(){ // Resets the histogram to zero
for (idx=0; idx<HISTOGRAM_RESOLUTION; idx++) data[idx] = 0.0; void Reset() {
} for (idx = 0; idx < HISTOGRAM_RESOLUTION; idx++)
data[idx] = 0.0;
}
private: private:
int idx; int idx;
double max,min; double max, min;
}; };

View File

@ -22,13 +22,10 @@
#include "common/Array.h" #include "common/Array.h"
#include <vector> #include <vector>
namespace imfilter { namespace imfilter {
//! enum to store the BC type //! enum to store the BC type
enum class BC { fixed=0, symmetric=1, replicate=2, circular=3 }; enum class BC { fixed = 0, symmetric = 1, replicate = 2, circular = 3 };
/*! /*!
* @brief N-D filtering of multidimensional images * @brief N-D filtering of multidimensional images
@ -47,9 +44,10 @@ enum class BC { fixed=0, symmetric=1, replicate=2, circular=3 };
* computed by implicitly assuming the input array is periodic. * computed by implicitly assuming the input array is periodic.
* @param[in] X The value to use for boundary conditions (only used if boundary==fixed) * @param[in] X The value to use for boundary conditions (only used if boundary==fixed)
*/ */
template<class TYPE> template <class TYPE>
Array<TYPE> imfilter( const Array<TYPE>& A, const Array<TYPE>& H, const std::vector<imfilter::BC>& boundary, const TYPE X=0 ); Array<TYPE> imfilter(const Array<TYPE> &A, const Array<TYPE> &H,
const std::vector<imfilter::BC> &boundary,
const TYPE X = 0);
/*! /*!
* @brief N-D filtering of multidimensional images * @brief N-D filtering of multidimensional images
@ -70,11 +68,11 @@ Array<TYPE> imfilter( const Array<TYPE>& A, const Array<TYPE>& H, const std::vec
* computed by implicitly assuming the input array is periodic. * computed by implicitly assuming the input array is periodic.
* @param[in] X The value to use for boundary conditions (only used if boundary==fixed) * @param[in] X The value to use for boundary conditions (only used if boundary==fixed)
*/ */
template<class TYPE> template <class TYPE>
Array<TYPE> imfilter( const Array<TYPE>& A, const std::vector<int>& Nh, Array<TYPE> imfilter(const Array<TYPE> &A, const std::vector<int> &Nh,
std::function<TYPE(const Array<TYPE>&)> H, std::function<TYPE(const Array<TYPE> &)> H,
const std::vector<imfilter::BC>& boundary, const TYPE X=0 ); const std::vector<imfilter::BC> &boundary,
const TYPE X = 0);
/*! /*!
* @brief N-D filtering of multidimensional images * @brief N-D filtering of multidimensional images
@ -94,10 +92,10 @@ Array<TYPE> imfilter( const Array<TYPE>& A, const std::vector<int>& Nh,
* computed by implicitly assuming the input array is periodic. * computed by implicitly assuming the input array is periodic.
* @param[in] X The value to use for boundary conditions (only used if boundary==fixed) * @param[in] X The value to use for boundary conditions (only used if boundary==fixed)
*/ */
template<class TYPE> template <class TYPE>
Array<TYPE> imfilter_separable( const Array<TYPE>& A, const std::vector<Array<TYPE>>& H, Array<TYPE>
const std::vector<imfilter::BC>& boundary, const TYPE X=0 ); imfilter_separable(const Array<TYPE> &A, const std::vector<Array<TYPE>> &H,
const std::vector<imfilter::BC> &boundary, const TYPE X = 0);
/*! /*!
* @brief N-D filtering of multidimensional images * @brief N-D filtering of multidimensional images
@ -117,11 +115,11 @@ Array<TYPE> imfilter_separable( const Array<TYPE>& A, const std::vector<Array<TY
* computed by implicitly assuming the input array is periodic. * computed by implicitly assuming the input array is periodic.
* @param[in] X The value to use for boundary conditions (only used if boundary==fixed) * @param[in] X The value to use for boundary conditions (only used if boundary==fixed)
*/ */
template<class TYPE> template <class TYPE>
Array<TYPE> imfilter_separable( const Array<TYPE>& A, const std::vector<int>& Nh, Array<TYPE>
std::vector<std::function<TYPE(const Array<TYPE>&)>> H, imfilter_separable(const Array<TYPE> &A, const std::vector<int> &Nh,
const std::vector<imfilter::BC>& boundary, const TYPE X=0 ); std::vector<std::function<TYPE(const Array<TYPE> &)>> H,
const std::vector<imfilter::BC> &boundary, const TYPE X = 0);
/*! /*!
* @brief N-D filtering of multidimensional images * @brief N-D filtering of multidimensional images
@ -142,11 +140,11 @@ Array<TYPE> imfilter_separable( const Array<TYPE>& A, const std::vector<int>& Nh
* computed by implicitly assuming the input array is periodic. * computed by implicitly assuming the input array is periodic.
* @param[in] X The value to use for boundary conditions (only used if boundary==fixed) * @param[in] X The value to use for boundary conditions (only used if boundary==fixed)
*/ */
template<class TYPE> template <class TYPE>
Array<TYPE> imfilter_separable( const Array<TYPE>& A, const std::vector<int>& Nh, Array<TYPE>
std::vector<std::function<TYPE(int, const TYPE*)>> H, imfilter_separable(const Array<TYPE> &A, const std::vector<int> &Nh,
const std::vector<imfilter::BC>& boundary, const TYPE X=0 ); std::vector<std::function<TYPE(int, const TYPE *)>> H,
const std::vector<imfilter::BC> &boundary, const TYPE X = 0);
/** /**
* @brief Create a filter to use with imfilter * @brief Create a filter to use with imfilter
@ -163,14 +161,12 @@ Array<TYPE> imfilter_separable( const Array<TYPE>& A, const std::vector<int>& Nh
* A default value of 0.5 is used if not provided. * A default value of 0.5 is used if not provided.
* \param[in] args An optional argument that some of the filters use * \param[in] args An optional argument that some of the filters use
*/ */
template<class TYPE> template <class TYPE>
Array<TYPE> create_filter( const std::vector<int>& N, const std::string &type, const void *args = NULL ); Array<TYPE> create_filter(const std::vector<int> &N, const std::string &type,
const void *args = NULL);
}
} // namespace imfilter
#include "analysis/imfilter.hpp" #include "analysis/imfilter.hpp"
#endif #endif

View File

@ -35,185 +35,176 @@
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#define IMFILTER_INSIST INSIST #define IMFILTER_INSIST INSIST
#define IMFILTER_ASSERT ASSERT #define IMFILTER_ASSERT ASSERT
#define IMFILTER_ERROR ERROR #define IMFILTER_ERROR ERROR
// Function to convert an index // Function to convert an index
static inline int imfilter_index( int index, const int N, const imfilter::BC bc ) static inline int imfilter_index(int index, const int N,
{ const imfilter::BC bc) {
if ( index < 0 || index >= N ) { if (index < 0 || index >= N) {
if ( bc == imfilter::BC::symmetric ) { if (bc == imfilter::BC::symmetric) {
index = ( 2 * N - index ) % N; index = (2 * N - index) % N;
} else if ( bc == imfilter::BC::replicate ) { } else if (bc == imfilter::BC::replicate) {
index = index < 0 ? 0 : N - 1; index = index < 0 ? 0 : N - 1;
} else if ( bc == imfilter::BC::circular ) { } else if (bc == imfilter::BC::circular) {
index = ( index + N ) % N; index = (index + N) % N;
} else if ( bc == imfilter::BC::fixed ) { } else if (bc == imfilter::BC::fixed) {
index = -1; index = -1;
} }
} }
return index; return index;
} }
// Function to copy a 1D array and pad with the appropriate BC // Function to copy a 1D array and pad with the appropriate BC
template<class TYPE> template <class TYPE>
static inline void copy_array( const int N, const int Ns, const int Nh, static inline void copy_array(const int N, const int Ns, const int Nh,
const TYPE *A, const imfilter::BC BC, const TYPE X, TYPE *B ) const TYPE *A, const imfilter::BC BC,
{ const TYPE X, TYPE *B) {
// Fill the center with a memcpy // Fill the center with a memcpy
for (int i=0; i<N; i++ ) for (int i = 0; i < N; i++)
B[i+Nh] = A[i*Ns]; B[i + Nh] = A[i * Ns];
// Fill the boundaries // Fill the boundaries
for (int i=0; i<Nh; i++ ) { for (int i = 0; i < Nh; i++) {
int j1 = imfilter_index( -(i+1), N, BC ); int j1 = imfilter_index(-(i + 1), N, BC);
int j2 = imfilter_index( N+i, N, BC ); int j2 = imfilter_index(N + i, N, BC);
B[Nh-i-1] = j1==-1 ? X : B[Nh+j1]; B[Nh - i - 1] = j1 == -1 ? X : B[Nh + j1];
B[N+Nh+i] = j2==-1 ? X : B[Nh+j2]; B[N + Nh + i] = j2 == -1 ? X : B[Nh + j2];
} }
} }
/******************************************************** /********************************************************
* Perform a 1D filter in a single direction * * Perform a 1D filter in a single direction *
********************************************************/ ********************************************************/
template<class TYPE> template <class TYPE>
static void filter_direction( int Ns, int N, int Ne, int Nh, const TYPE *H, static void filter_direction(int Ns, int N, int Ne, int Nh, const TYPE *H,
imfilter::BC boundary, TYPE X, TYPE *A ) imfilter::BC boundary, TYPE X, TYPE *A) {
{ if (Nh < 0)
if ( Nh < 0 )
IMFILTER_ERROR("Invalid filter size"); IMFILTER_ERROR("Invalid filter size");
if ( Nh == 0 ) { if (Nh == 0) {
for (int i=0; i<Ns*N*Ne; i++) for (int i = 0; i < Ns * N * Ne; i++)
A[i] *= H[0]; A[i] *= H[0];
return; return;
} }
TYPE *tmp = new TYPE[N+2*Nh]; TYPE *tmp = new TYPE[N + 2 * Nh];
for (int j=0; j<Ne; j++) { for (int j = 0; j < Ne; j++) {
for (int i=0; i<Ns; i++) { for (int i = 0; i < Ns; i++) {
copy_array( N, Ns, Nh, &A[i+j*Ns*N], boundary, X, tmp ); copy_array(N, Ns, Nh, &A[i + j * Ns * N], boundary, X, tmp);
for (int k=0; k<N; k++) { for (int k = 0; k < N; k++) {
TYPE tmp2 = 0; TYPE tmp2 = 0;
for (int m=0; m<=2*Nh; m++) for (int m = 0; m <= 2 * Nh; m++)
tmp2 += H[m] * tmp[k+m]; tmp2 += H[m] * tmp[k + m];
A[i+k*Ns+j*Ns*N] = tmp2; A[i + k * Ns + j * Ns * N] = tmp2;
} }
} }
} }
delete[] tmp; delete[] tmp;
} }
template<class TYPE> template <class TYPE>
static void filter_direction( int Ns, int N, int Ne, int Nh, static void filter_direction(int Ns, int N, int Ne, int Nh,
std::function<TYPE(const Array<TYPE>&)> H, imfilter::BC boundary, TYPE X, TYPE *A ) std::function<TYPE(const Array<TYPE> &)> H,
{ imfilter::BC boundary, TYPE X, TYPE *A) {
if ( Nh < 0 ) if (Nh < 0)
IMFILTER_ERROR("Invalid filter size"); IMFILTER_ERROR("Invalid filter size");
TYPE *tmp = new TYPE[N+2*Nh]; TYPE *tmp = new TYPE[N + 2 * Nh];
Array<TYPE> tmp2(2*Nh+1); Array<TYPE> tmp2(2 * Nh + 1);
for (int j=0; j<Ne; j++) { for (int j = 0; j < Ne; j++) {
for (int i=0; i<Ns; i++) { for (int i = 0; i < Ns; i++) {
copy_array( N, Ns, Nh, &A[i+j*Ns*N], boundary, X, tmp ); copy_array(N, Ns, Nh, &A[i + j * Ns * N], boundary, X, tmp);
for (int k=0; k<N; k++) { for (int k = 0; k < N; k++) {
for (int m=0; m<=2*Nh; m++) for (int m = 0; m <= 2 * Nh; m++)
tmp2(m) = tmp[k+m]; tmp2(m) = tmp[k + m];
A[i+k*Ns+j*Ns*N] = H(tmp2); A[i + k * Ns + j * Ns * N] = H(tmp2);
} }
} }
} }
delete[] tmp; delete[] tmp;
} }
template<class TYPE> template <class TYPE>
static void filter_direction( int Ns, int N, int Ne, int Nh, static void filter_direction(int Ns, int N, int Ne, int Nh,
std::function<TYPE(int, const TYPE*)> H, imfilter::BC boundary, TYPE X, TYPE *A ) std::function<TYPE(int, const TYPE *)> H,
{ imfilter::BC boundary, TYPE X, TYPE *A) {
if ( Nh < 0 ) if (Nh < 0)
IMFILTER_ERROR("Invalid filter size"); IMFILTER_ERROR("Invalid filter size");
TYPE *tmp = new TYPE[N+2*Nh]; TYPE *tmp = new TYPE[N + 2 * Nh];
int Nh2 = 2*Nh+1; int Nh2 = 2 * Nh + 1;
for (int j=0; j<Ne; j++) { for (int j = 0; j < Ne; j++) {
for (int i=0; i<Ns; i++) { for (int i = 0; i < Ns; i++) {
copy_array( N, Ns, Nh, &A[i+j*Ns*N], boundary, X, tmp ); copy_array(N, Ns, Nh, &A[i + j * Ns * N], boundary, X, tmp);
for (int k=0; k<N; k++) for (int k = 0; k < N; k++)
A[i+k*Ns+j*Ns*N] = H(Nh2,&tmp[k]); A[i + k * Ns + j * Ns * N] = H(Nh2, &tmp[k]);
} }
} }
delete[] tmp; delete[] tmp;
} }
/******************************************************** /********************************************************
* Create a filter * * Create a filter *
********************************************************/ ********************************************************/
template<class TYPE> template <class TYPE>
Array<TYPE> imfilter::create_filter( const std::vector<int>& N0, const std::string &type, const void *args ) Array<TYPE> imfilter::create_filter(const std::vector<int> &N0,
{ const std::string &type, const void *args) {
std::vector<size_t> N2(N0.size()); std::vector<size_t> N2(N0.size());
for (size_t i=0; i<N2.size(); i++) for (size_t i = 0; i < N2.size(); i++)
N2[i] = 2*N0[i]+1; N2[i] = 2 * N0[i] + 1;
Array<TYPE> h(N2); Array<TYPE> h(N2);
h.fill(0); h.fill(0);
if ( type == "average" ) { if (type == "average") {
// average // average
h.fill( 1.0 / static_cast<TYPE>( h.length() ) ); h.fill(1.0 / static_cast<TYPE>(h.length()));
} else if ( type == "gaussian" ) { } else if (type == "gaussian") {
// gaussian // gaussian
if ( N0.size() > 3 ) if (N0.size() > 3)
IMFILTER_ERROR( "Not implimented for dimensions > 3" ); IMFILTER_ERROR("Not implimented for dimensions > 3");
TYPE std[3] = { 0.5, 0.5, 0.5 }; TYPE std[3] = {0.5, 0.5, 0.5};
if ( args != NULL ) { if (args != NULL) {
const TYPE *args2 = reinterpret_cast<const TYPE*>( args ); const TYPE *args2 = reinterpret_cast<const TYPE *>(args);
for ( size_t d = 0; d < N0.size(); d++ ) for (size_t d = 0; d < N0.size(); d++)
std[d] = args2[d]; std[d] = args2[d];
} }
auto N = N0; auto N = N0;
N.resize(3,0); N.resize(3, 0);
for ( int k = -N[2]; k <= N[2]; k++ ) { for (int k = -N[2]; k <= N[2]; k++) {
for ( int j = -N[1]; j <= N[1]; j++ ) { for (int j = -N[1]; j <= N[1]; j++) {
for ( int i = -N[0]; i <= N[0]; i++ ) { for (int i = -N[0]; i <= N[0]; i++) {
h(i+N[0],j+N[1],k+N[2]) = h(i + N[0], j + N[1], k + N[2]) =
exp( -i * i / ( 2 * std[0] * std[0] ) ) * exp(-i * i / (2 * std[0] * std[0])) *
exp( -j * j / ( 2 * std[1] * std[1] ) ) * exp(-j * j / (2 * std[1] * std[1])) *
exp( -k * k / ( 2 * std[2] * std[2] ) ); exp(-k * k / (2 * std[2] * std[2]));
} }
} }
} }
h.scale( 1.0/h.sum() ); h.scale(1.0 / h.sum());
} else { } else {
IMFILTER_ERROR( "Unknown filter" ); IMFILTER_ERROR("Unknown filter");
} }
return h; return h;
} }
// Perform 2-D filtering // Perform 2-D filtering
template<class TYPE> template <class TYPE>
void imfilter_2D( int Nx, int Ny, const TYPE *A, int Nhx, int Nhy, const TYPE *H, void imfilter_2D(int Nx, int Ny, const TYPE *A, int Nhx, int Nhy, const TYPE *H,
imfilter::BC BCx, imfilter::BC BCy, const TYPE X, TYPE *B ) imfilter::BC BCx, imfilter::BC BCy, const TYPE X, TYPE *B) {
{ IMFILTER_ASSERT(A != B);
IMFILTER_ASSERT( A != B ); PROFILE_START("imfilter_2D");
PROFILE_START( "imfilter_2D" ); memset(B, 0, Nx * Ny * sizeof(TYPE));
memset( B, 0, Nx * Ny * sizeof( TYPE ) ); for (int j1 = 0; j1 < Ny; j1++) {
for ( int j1 = 0; j1 < Ny; j1++ ) { for (int i1 = 0; i1 < Nx; i1++) {
for ( int i1 = 0; i1 < Nx; i1++ ) {
TYPE tmp = 0; TYPE tmp = 0;
if ( i1 >= Nhx && i1 < Nx - Nhx && j1 >= Nhy && j1 < Ny - Nhy ) { if (i1 >= Nhx && i1 < Nx - Nhx && j1 >= Nhy && j1 < Ny - Nhy) {
int ijkh = 0; int ijkh = 0;
for ( int j2 = j1 - Nhy; j2 <= j1 + Nhy; j2++ ) { for (int j2 = j1 - Nhy; j2 <= j1 + Nhy; j2++) {
for ( int i2 = i1 - Nhx; i2 <= i1 + Nhx; i2++, ijkh++ ) for (int i2 = i1 - Nhx; i2 <= i1 + Nhx; i2++, ijkh++)
tmp += H[ijkh] * A[i2 + j2 * Nx]; tmp += H[ijkh] * A[i2 + j2 * Nx];
} }
} else { } else {
int ijkh = 0; int ijkh = 0;
for ( int jh = -Nhy; jh <= Nhy; jh++ ) { for (int jh = -Nhy; jh <= Nhy; jh++) {
int j2 = imfilter_index( j1+jh, Ny, BCy ); int j2 = imfilter_index(j1 + jh, Ny, BCy);
for ( int ih = -Nhx; ih <= Nhx; ih++ ) { for (int ih = -Nhx; ih <= Nhx; ih++) {
int i2 = imfilter_index( i1+ih, Nx, BCx ); int i2 = imfilter_index(i1 + ih, Nx, BCx);
bool fixed = i2 == -1 || j2 == -1; bool fixed = i2 == -1 || j2 == -1;
TYPE A2 = fixed ? X : A[i2 + j2 * Nx]; TYPE A2 = fixed ? X : A[i2 + j2 * Nx];
tmp += H[ijkh] * A2; tmp += H[ijkh] * A2;
ijkh++; ijkh++;
} }
@ -222,32 +213,31 @@ void imfilter_2D( int Nx, int Ny, const TYPE *A, int Nhx, int Nhy, const TYPE *H
B[i1 + j1 * Nx] = tmp; B[i1 + j1 * Nx] = tmp;
} }
} }
PROFILE_STOP( "imfilter_2D" ); PROFILE_STOP("imfilter_2D");
} }
// Perform 3-D filtering // Perform 3-D filtering
template<class TYPE> template <class TYPE>
void imfilter_3D( int Nx, int Ny, int Nz, const TYPE *A, int Nhx, int Nhy, int Nhz, void imfilter_3D(int Nx, int Ny, int Nz, const TYPE *A, int Nhx, int Nhy,
const TYPE *H, imfilter::BC BCx, imfilter::BC BCy, imfilter::BC BCz, int Nhz, const TYPE *H, imfilter::BC BCx, imfilter::BC BCy,
const TYPE X, TYPE *B ) imfilter::BC BCz, const TYPE X, TYPE *B) {
{ IMFILTER_ASSERT(A != B);
IMFILTER_ASSERT( A != B ); PROFILE_START("imfilter_3D");
PROFILE_START( "imfilter_3D" ); memset(B, 0, Nx * Ny * Nz * sizeof(TYPE));
memset( B, 0, Nx * Ny * Nz * sizeof( TYPE ) ); for (int k1 = 0; k1 < Nz; k1++) {
for ( int k1 = 0; k1 < Nz; k1++ ) { for (int j1 = 0; j1 < Ny; j1++) {
for ( int j1 = 0; j1 < Ny; j1++ ) { for (int i1 = 0; i1 < Nx; i1++) {
for ( int i1 = 0; i1 < Nx; i1++ ) {
TYPE tmp = 0; TYPE tmp = 0;
int ijkh = 0; int ijkh = 0;
for ( int kh = -Nhz; kh <= Nhz; kh++ ) { for (int kh = -Nhz; kh <= Nhz; kh++) {
int k2 = imfilter_index( k1+kh, Nz, BCz ); int k2 = imfilter_index(k1 + kh, Nz, BCz);
for ( int jh = -Nhy; jh <= Nhy; jh++ ) { for (int jh = -Nhy; jh <= Nhy; jh++) {
int j2 = imfilter_index( j1+jh, Ny, BCy ); int j2 = imfilter_index(j1 + jh, Ny, BCy);
for ( int ih = -Nhx; ih <= Nhx; ih++ ) { for (int ih = -Nhx; ih <= Nhx; ih++) {
int i2 = imfilter_index( i1+ih, Nx, BCx ); int i2 = imfilter_index(i1 + ih, Nx, BCx);
bool fixed = i2 == -1 || j2 == -1 || k2 == -1; bool fixed = i2 == -1 || j2 == -1 || k2 == -1;
TYPE A2 = fixed ? X : A[i2 + j2 * Nx + k2 * Nx * Ny]; TYPE A2 =
fixed ? X : A[i2 + j2 * Nx + k2 * Nx * Ny];
tmp += H[ijkh] * A2; tmp += H[ijkh] * A2;
ijkh++; ijkh++;
} }
@ -257,154 +247,155 @@ void imfilter_3D( int Nx, int Ny, int Nz, const TYPE *A, int Nhx, int Nhy, int N
} }
} }
} }
PROFILE_STOP( "imfilter_3D" ); PROFILE_STOP("imfilter_3D");
} }
/******************************************************** /********************************************************
* Perform N-D filtering * * Perform N-D filtering *
********************************************************/ ********************************************************/
template<class TYPE> template <class TYPE>
Array<TYPE> imfilter::imfilter( const Array<TYPE>& A, Array<TYPE> imfilter::imfilter(const Array<TYPE> &A, const Array<TYPE> &H,
const Array<TYPE>& H, const std::vector<imfilter::BC>& BC, const TYPE X ) const std::vector<imfilter::BC> &BC,
{ const TYPE X) {
IMFILTER_ASSERT( A.ndim() == H.ndim() ); IMFILTER_ASSERT(A.ndim() == H.ndim());
IMFILTER_ASSERT( A.ndim() == BC.size() ); IMFILTER_ASSERT(A.ndim() == BC.size());
std::vector<size_t> Nh = H.size(); std::vector<size_t> Nh = H.size();
for (int d=0; d<A.ndim(); d++) { for (int d = 0; d < A.ndim(); d++) {
Nh[d] = (H.size(d)-1)/2; Nh[d] = (H.size(d) - 1) / 2;
IMFILTER_INSIST(2*Nh[d]+1==H.size(d),"Filter must be of size 2*N+1"); IMFILTER_INSIST(2 * Nh[d] + 1 == H.size(d),
"Filter must be of size 2*N+1");
} }
auto B = A; auto B = A;
if ( A.ndim() == 1 ) { if (A.ndim() == 1) {
PROFILE_START( "imfilter_1D" ); PROFILE_START("imfilter_1D");
filter_direction( 1, A.size(0), 1, Nh[0], H.data(), BC[0], X, B.data() ); filter_direction(1, A.size(0), 1, Nh[0], H.data(), BC[0], X, B.data());
PROFILE_STOP( "imfilter_1D" ); PROFILE_STOP("imfilter_1D");
} else if ( A.ndim() == 2 ) { } else if (A.ndim() == 2) {
imfilter_2D( A.size(0), A.size(1), A.data(), Nh[0], Nh[1], H.data(), BC[0], BC[1], X, B.data() ); imfilter_2D(A.size(0), A.size(1), A.data(), Nh[0], Nh[1], H.data(),
} else if ( A.ndim() == 3 ) { BC[0], BC[1], X, B.data());
imfilter_3D( A.size(0), A.size(1), A.size(2), A.data(), } else if (A.ndim() == 3) {
Nh[0], Nh[1], Nh[2], H.data(), BC[0], BC[1], BC[2], X, B.data() ); imfilter_3D(A.size(0), A.size(1), A.size(2), A.data(), Nh[0], Nh[1],
Nh[2], H.data(), BC[0], BC[1], BC[2], X, B.data());
} else { } else {
IMFILTER_ERROR( "Arbitrary dimension not yet supported" ); IMFILTER_ERROR("Arbitrary dimension not yet supported");
} }
return B; return B;
} }
template<class TYPE> template <class TYPE>
Array<TYPE> imfilter::imfilter( const Array<TYPE>& A, const std::vector<int>& Nh0, Array<TYPE>
std::function<TYPE(const Array<TYPE>&)> H, imfilter::imfilter(const Array<TYPE> &A, const std::vector<int> &Nh0,
const std::vector<imfilter::BC>& BC0, const TYPE X ) std::function<TYPE(const Array<TYPE> &)> H,
{ const std::vector<imfilter::BC> &BC0, const TYPE X) {
PROFILE_START( "imfilter (lambda)" ); PROFILE_START("imfilter (lambda)");
IMFILTER_ASSERT( A.ndim() == Nh0.size() ); IMFILTER_ASSERT(A.ndim() == Nh0.size());
IMFILTER_ASSERT( A.ndim() == BC0.size() ); IMFILTER_ASSERT(A.ndim() == BC0.size());
std::vector<size_t> Nh2( A.size() ); std::vector<size_t> Nh2(A.size());
for (int d=0; d<A.ndim(); d++) for (int d = 0; d < A.ndim(); d++)
Nh2[d] = 2*Nh0[d]+1; Nh2[d] = 2 * Nh0[d] + 1;
auto B = A; auto B = A;
Array<TYPE> data(Nh2); Array<TYPE> data(Nh2);
IMFILTER_INSIST(A.ndim()<=3,"Not programmed for more than 3 dimensions yet"); IMFILTER_INSIST(A.ndim() <= 3,
"Not programmed for more than 3 dimensions yet");
auto N = A.size(); auto N = A.size();
auto Nh = Nh0; auto Nh = Nh0;
auto BC = BC0; auto BC = BC0;
N.resize(3,1); N.resize(3, 1);
Nh.resize(3,0); Nh.resize(3, 0);
BC.resize(3,imfilter::BC::fixed); BC.resize(3, imfilter::BC::fixed);
for ( int k1 = 0; k1 < N[2]; k1++ ) { for (int k1 = 0; k1 < N[2]; k1++) {
for ( int j1 = 0; j1 < N[1]; j1++ ) { for (int j1 = 0; j1 < N[1]; j1++) {
for ( int i1 = 0; i1 < N[0]; i1++ ) { for (int i1 = 0; i1 < N[0]; i1++) {
for ( int kh = -Nh[2]; kh <= Nh[2]; kh++ ) { for (int kh = -Nh[2]; kh <= Nh[2]; kh++) {
int k2 = imfilter_index( k1+kh, N[2], BC[2] ); int k2 = imfilter_index(k1 + kh, N[2], BC[2]);
for ( int jh = -Nh[1]; jh <= Nh[1]; jh++ ) { for (int jh = -Nh[1]; jh <= Nh[1]; jh++) {
int j2 = imfilter_index( j1+jh, N[1], BC[1] ); int j2 = imfilter_index(j1 + jh, N[1], BC[1]);
for ( int ih = -Nh[0]; ih <= Nh[0]; ih++ ) { for (int ih = -Nh[0]; ih <= Nh[0]; ih++) {
int i2 = imfilter_index( i1+ih, N[0], BC[0] ); int i2 = imfilter_index(i1 + ih, N[0], BC[0]);
bool fixed = i2 == -1 || j2 == -1 || k2 == -1; bool fixed = i2 == -1 || j2 == -1 || k2 == -1;
data(ih+Nh[0],jh+Nh[1],kh+Nh[2]) = fixed ? X : A(i2,j2,k2); data(ih + Nh[0], jh + Nh[1], kh + Nh[2]) =
fixed ? X : A(i2, j2, k2);
} }
} }
} }
B(i1,j1,k1) = H( data ); B(i1, j1, k1) = H(data);
} }
} }
} }
PROFILE_STOP( "imfilter (lambda)" ); PROFILE_STOP("imfilter (lambda)");
return B; return B;
} }
/******************************************************** /********************************************************
* imfilter with separable filter functions * * imfilter with separable filter functions *
********************************************************/ ********************************************************/
template<class TYPE> template <class TYPE>
Array<TYPE> imfilter::imfilter_separable( const Array<TYPE>& A, Array<TYPE> imfilter::imfilter_separable(
const std::vector<Array<TYPE>>& H, const Array<TYPE> &A, const std::vector<Array<TYPE>> &H,
const std::vector<imfilter::BC>& boundary, const TYPE X ) const std::vector<imfilter::BC> &boundary, const TYPE X) {
{ PROFILE_START("imfilter_separable");
PROFILE_START( "imfilter_separable" ); IMFILTER_ASSERT(A.ndim() == (int)H.size());
IMFILTER_ASSERT( A.ndim() == (int) H.size() ); IMFILTER_ASSERT(A.ndim() == (int)boundary.size());
IMFILTER_ASSERT( A.ndim() == (int) boundary.size() ); std::vector<size_t> Nh(H.size());
std::vector<size_t> Nh( H.size() ); for (int d = 0; d < A.ndim(); d++) {
for (int d=0; d<A.ndim(); d++) { IMFILTER_ASSERT(H[d].ndim() == 1);
IMFILTER_ASSERT(H[d].ndim()==1); Nh[d] = (H[d].length() - 1) / 2;
Nh[d] = (H[d].length()-1)/2; IMFILTER_INSIST(2 * Nh[d] + 1 == H[d].length(),
IMFILTER_INSIST(2*Nh[d]+1==H[d].length(),"Filter must be of size 2*N+1"); "Filter must be of size 2*N+1");
} }
auto B = A; auto B = A;
for ( int d = 0; d < A.ndim(); d++ ) { for (int d = 0; d < A.ndim(); d++) {
int N = A.size(d); int N = A.size(d);
int Ns = 1; int Ns = 1;
int Ne = 1; int Ne = 1;
for ( int d2 = 0; d2 < d; d2++ ) for (int d2 = 0; d2 < d; d2++)
Ns *= A.size(d2); Ns *= A.size(d2);
for ( int d2 = d+1; d2 < A.ndim(); d2++ ) for (int d2 = d + 1; d2 < A.ndim(); d2++)
Ne *= A.size(d2); Ne *= A.size(d2);
filter_direction( Ns, N, Ne, Nh[d], H[d].data(), boundary[d], X, B.data() ); filter_direction(Ns, N, Ne, Nh[d], H[d].data(), boundary[d], X,
B.data());
} }
PROFILE_STOP( "imfilter_separable" ); PROFILE_STOP("imfilter_separable");
return B; return B;
} }
template<class TYPE> template <class TYPE>
Array<TYPE> imfilter::imfilter_separable( const Array<TYPE>& A, const std::vector<int>& Nh, Array<TYPE> imfilter::imfilter_separable(
std::vector<std::function<TYPE(const Array<TYPE>&)>> H, const Array<TYPE> &A, const std::vector<int> &Nh,
const std::vector<imfilter::BC>& boundary, const TYPE X ) std::vector<std::function<TYPE(const Array<TYPE> &)>> H,
{ const std::vector<imfilter::BC> &boundary, const TYPE X) {
PROFILE_START( "imfilter_separable (lambda)" ); PROFILE_START("imfilter_separable (lambda)");
IMFILTER_ASSERT( A.ndim() == (int) boundary.size() ); IMFILTER_ASSERT(A.ndim() == (int)boundary.size());
auto B = A; auto B = A;
for ( int d = 0; d < A.ndim(); d++ ) { for (int d = 0; d < A.ndim(); d++) {
int N = A.size(d); int N = A.size(d);
int Ns = 1; int Ns = 1;
int Ne = 1; int Ne = 1;
for ( int d2 = 0; d2 < d; d2++ ) for (int d2 = 0; d2 < d; d2++)
Ns *= A.size(d2); Ns *= A.size(d2);
for ( int d2 = d+1; d2 < A.ndim(); d2++ ) for (int d2 = d + 1; d2 < A.ndim(); d2++)
Ne *= A.size(d2); Ne *= A.size(d2);
filter_direction( Ns, N, Ne, Nh[d], H[d], boundary[d], X, B.data() ); filter_direction(Ns, N, Ne, Nh[d], H[d], boundary[d], X, B.data());
} }
PROFILE_STOP( "imfilter_separable (lambda)" ); PROFILE_STOP("imfilter_separable (lambda)");
return B; return B;
} }
template<class TYPE> template <class TYPE>
Array<TYPE> imfilter::imfilter_separable( const Array<TYPE>& A, const std::vector<int>& Nh, Array<TYPE> imfilter::imfilter_separable(
std::vector<std::function<TYPE(int, const TYPE*)>> H, const Array<TYPE> &A, const std::vector<int> &Nh,
const std::vector<imfilter::BC>& boundary, const TYPE X ) std::vector<std::function<TYPE(int, const TYPE *)>> H,
{ const std::vector<imfilter::BC> &boundary, const TYPE X) {
PROFILE_START( "imfilter_separable (function)" ); PROFILE_START("imfilter_separable (function)");
IMFILTER_ASSERT( A.ndim() == (int) boundary.size() ); IMFILTER_ASSERT(A.ndim() == (int)boundary.size());
auto B = A; auto B = A;
for ( int d = 0; d < A.ndim(); d++ ) { for (int d = 0; d < A.ndim(); d++) {
int N = A.size(d); int N = A.size(d);
int Ns = 1; int Ns = 1;
int Ne = 1; int Ne = 1;
for ( int d2 = 0; d2 < d; d2++ ) for (int d2 = 0; d2 < d; d2++)
Ns *= A.size(d2); Ns *= A.size(d2);
for ( int d2 = d+1; d2 < A.ndim(); d2++ ) for (int d2 = d + 1; d2 < A.ndim(); d2++)
Ne *= A.size(d2); Ne *= A.size(d2);
filter_direction( Ns, N, Ne, Nh[d], H[d], boundary[d], X, B.data() ); filter_direction(Ns, N, Ne, Nh[d], H[d], boundary[d], X, B.data());
} }
PROFILE_STOP( "imfilter_separable (function)" ); PROFILE_STOP("imfilter_separable (function)");
return B; return B;
} }

File diff suppressed because it is too large Load Diff

View File

@ -3,9 +3,14 @@
#include "common/Domain.h" #include "common/Domain.h"
#include "analysis/runAnalysis.h" #include "analysis/runAnalysis.h"
double MorphOpen(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain> Dm, double VoidFraction, signed char ErodeLabel, signed char ReplaceLabel); double MorphOpen(DoubleArray &SignDist, signed char *id,
double MorphDrain(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain> Dm, double VoidFraction); std::shared_ptr<Domain> Dm, double VoidFraction,
double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id, std::shared_ptr<Domain> Dm, double TargetVol, double WallFactor); signed char ErodeLabel, signed char ReplaceLabel);
double MorphDrain(DoubleArray &SignDist, signed char *id,
std::shared_ptr<Domain> Dm, double VoidFraction);
double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id,
std::shared_ptr<Domain> Dm, double TargetVol,
double WallFactor);
#ifndef MORPHOLOGY_INC #ifndef MORPHOLOGY_INC
#define MORPHOLOGY_INC #define MORPHOLOGY_INC
@ -15,84 +20,103 @@ double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id,
* The Morphology class supports morphological operations on complex structures * The Morphology class supports morphological operations on complex structures
* *
*/ */
class Morphology{ class Morphology {
public: public:
/** /**
* \brief Create a flow adaptor to operate on the LB model * \brief Create a flow adaptor to operate on the LB model
*/ */
Morphology(); Morphology();
/** /**
* \brief Destructor * \brief Destructor
*/ */
~Morphology(); ~Morphology();
/** /**
* \brief Initialize morphology structure from distance map * \brief Initialize morphology structure from distance map
* @param Dm Domain structure * @param Dm Domain structure
* @param Distance Signed distance to boundary of structure * @param Distance Signed distance to boundary of structure
*/ */
void Initialize(std::shared_ptr <Domain> Dm, DoubleArray &Distance); void Initialize(std::shared_ptr<Domain> Dm, DoubleArray &Distance);
/** /**
* \brief Find all sites such that the reach of the signed distance at the site overlaps with a sub-domain boundary * \brief Find all sites such that the reach of the signed distance at the site overlaps with a sub-domain boundary
* @param Dm Domain structure * @param Dm Domain structure
* @param id image labels * @param id image labels
* @param ErodeLabel label to erode based on morphological operation * @param ErodeLabel label to erode based on morphological operation
* @param NewLabel label to assign based on morphological operation * @param NewLabel label to assign based on morphological operation
*/ */
int GetOverlaps(std::shared_ptr <Domain> Dm, signed char *id, const signed char ErodeLabel, const signed char NewLabel); int GetOverlaps(std::shared_ptr<Domain> Dm, signed char *id,
const signed char ErodeLabel, const signed char NewLabel);
/* /*
* data structures to store non-local morphological information * data structures to store non-local morphological information
*/ */
std::vector<int> xShift, yShift, zShift; std::vector<int> xShift, yShift, zShift;
std::vector<int> sendID; std::vector<int> sendID;
std::vector<double> morphRadius; std::vector<double> morphRadius;
std::vector<unsigned char> localID; std::vector<unsigned char> localID;
std::vector<unsigned char> nonlocalID; std::vector<unsigned char> nonlocalID;
private: private:
int sendtag,recvtag; int sendtag, recvtag;
//...................................................................................... //......................................................................................
int sendCount, recvCount; int sendCount, recvCount;
//...................................................................................... //......................................................................................
int sendOffset_x, sendOffset_y, sendOffset_z, sendOffset_X, sendOffset_Y, sendOffset_Z; int sendOffset_x, sendOffset_y, sendOffset_z, sendOffset_X, sendOffset_Y,
int sendOffset_xy, sendOffset_yz, sendOffset_xz, sendOffset_Xy, sendOffset_Yz, sendOffset_xZ; sendOffset_Z;
int sendOffset_xY, sendOffset_yZ, sendOffset_Xz, sendOffset_XY, sendOffset_YZ, sendOffset_XZ; int sendOffset_xy, sendOffset_yz, sendOffset_xz, sendOffset_Xy,
sendOffset_Yz, sendOffset_xZ;
int sendOffset_xY, sendOffset_yZ, sendOffset_Xz, sendOffset_XY,
sendOffset_YZ, sendOffset_XZ;
int sendOffset_xyz, sendOffset_XYZ, sendOffset_xYz, sendOffset_XyZ; int sendOffset_xyz, sendOffset_XYZ, sendOffset_xYz, sendOffset_XyZ;
int sendOffset_Xyz, sendOffset_xYZ, sendOffset_xyZ, sendOffset_XYz; int sendOffset_Xyz, sendOffset_xYZ, sendOffset_xyZ, sendOffset_XYz;
//...................................................................................... //......................................................................................
int recvOffset_x, recvOffset_y, recvOffset_z, recvOffset_X, recvOffset_Y, recvOffset_Z; int recvOffset_x, recvOffset_y, recvOffset_z, recvOffset_X, recvOffset_Y,
int recvOffset_xy, recvOffset_yz, recvOffset_xz, recvOffset_Xy, recvOffset_Yz, recvOffset_xZ; recvOffset_Z;
int recvOffset_xY, recvOffset_yZ, recvOffset_Xz, recvOffset_XY, recvOffset_YZ, recvOffset_XZ; int recvOffset_xy, recvOffset_yz, recvOffset_xz, recvOffset_Xy,
recvOffset_Yz, recvOffset_xZ;
int recvOffset_xY, recvOffset_yZ, recvOffset_Xz, recvOffset_XY,
recvOffset_YZ, recvOffset_XZ;
int recvOffset_xyz, recvOffset_XYZ, recvOffset_xYz, recvOffset_XyZ; int recvOffset_xyz, recvOffset_XYZ, recvOffset_xYz, recvOffset_XyZ;
int recvOffset_Xyz, recvOffset_xYZ, recvOffset_xyZ, recvOffset_XYz; int recvOffset_Xyz, recvOffset_xYZ, recvOffset_xyZ, recvOffset_XYz;
//...................................................................................... //......................................................................................
int sendCount_x, sendCount_y, sendCount_z, sendCount_X, sendCount_Y, sendCount_Z; int sendCount_x, sendCount_y, sendCount_z, sendCount_X, sendCount_Y,
int sendCount_xy, sendCount_yz, sendCount_xz, sendCount_Xy, sendCount_Yz, sendCount_xZ; sendCount_Z;
int sendCount_xY, sendCount_yZ, sendCount_Xz, sendCount_XY, sendCount_YZ, sendCount_XZ; int sendCount_xy, sendCount_yz, sendCount_xz, sendCount_Xy, sendCount_Yz,
sendCount_xZ;
int sendCount_xY, sendCount_yZ, sendCount_Xz, sendCount_XY, sendCount_YZ,
sendCount_XZ;
int sendCount_xyz, sendCount_XYZ, sendCount_xYz, sendCount_XyZ; int sendCount_xyz, sendCount_XYZ, sendCount_xYz, sendCount_XyZ;
int sendCount_Xyz, sendCount_xYZ, sendCount_xyZ, sendCount_XYz; int sendCount_Xyz, sendCount_xYZ, sendCount_xyZ, sendCount_XYz;
//...................................................................................... //......................................................................................
int recvCount_x, recvCount_y, recvCount_z, recvCount_X, recvCount_Y, recvCount_Z; int recvCount_x, recvCount_y, recvCount_z, recvCount_X, recvCount_Y,
int recvCount_xy, recvCount_yz, recvCount_xz, recvCount_Xy, recvCount_Yz, recvCount_xZ; recvCount_Z;
int recvCount_xY, recvCount_yZ, recvCount_Xz, recvCount_XY, recvCount_YZ, recvCount_XZ; int recvCount_xy, recvCount_yz, recvCount_xz, recvCount_Xy, recvCount_Yz,
recvCount_xZ;
int recvCount_xY, recvCount_yZ, recvCount_Xz, recvCount_XY, recvCount_YZ,
recvCount_XZ;
int recvCount_xyz, recvCount_XYZ, recvCount_xYz, recvCount_XyZ; int recvCount_xyz, recvCount_XYZ, recvCount_xYz, recvCount_XyZ;
int recvCount_Xyz, recvCount_xYZ, recvCount_xyZ, recvCount_XYz; int recvCount_Xyz, recvCount_xYZ, recvCount_xyZ, recvCount_XYz;
//...................................................................................... //......................................................................................
std::vector<char> sendList; std::vector<char> sendList;
std::vector<char> recvList; std::vector<char> recvList;
//...................................................................................... //......................................................................................
// Communication buffers // Communication buffers
signed char *sendID_x, *sendID_y, *sendID_z, *sendID_X, *sendID_Y, *sendID_Z; signed char *sendID_x, *sendID_y, *sendID_z, *sendID_X, *sendID_Y,
signed char *sendID_xy, *sendID_yz, *sendID_xz, *sendID_Xy, *sendID_Yz, *sendID_xZ; *sendID_Z;
signed char *sendID_xY, *sendID_yZ, *sendID_Xz, *sendID_XY, *sendID_YZ, *sendID_XZ; signed char *sendID_xy, *sendID_yz, *sendID_xz, *sendID_Xy, *sendID_Yz,
signed char *recvID_x, *recvID_y, *recvID_z, *recvID_X, *recvID_Y, *recvID_Z; *sendID_xZ;
signed char *recvID_xy, *recvID_yz, *recvID_xz, *recvID_Xy, *recvID_Yz, *recvID_xZ; signed char *sendID_xY, *sendID_yZ, *sendID_Xz, *sendID_XY, *sendID_YZ,
signed char *recvID_xY, *recvID_yZ, *recvID_Xz, *recvID_XY, *recvID_YZ, *recvID_XZ; *sendID_XZ;
signed char *recvID_x, *recvID_y, *recvID_z, *recvID_X, *recvID_Y,
*recvID_Z;
signed char *recvID_xy, *recvID_yz, *recvID_xz, *recvID_Xy, *recvID_Yz,
*recvID_xZ;
signed char *recvID_xY, *recvID_yZ, *recvID_Xz, *recvID_XY, *recvID_YZ,
*recvID_XZ;
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -26,42 +26,42 @@
#include "models/ColorModel.h" #include "models/ColorModel.h"
#include <limits.h> #include <limits.h>
// Types of analysis // Types of analysis
enum class AnalysisType : uint64_t { enum class AnalysisType : uint64_t {
AnalyzeNone = 0, AnalyzeNone = 0,
IdentifyBlobs = 0x01, IdentifyBlobs = 0x01,
CopyPhaseIndicator = 0x02, CopyPhaseIndicator = 0x02,
CopySimState = 0x04, CopySimState = 0x04,
ComputeAverages = 0x08, ComputeAverages = 0x08,
CreateRestart = 0x10, CreateRestart = 0x10,
WriteVis = 0x20, WriteVis = 0x20,
ComputeSubphase = 0x40 ComputeSubphase = 0x40
}; };
//! Class to run the analysis in multiple threads //! Class to run the analysis in multiple threads
class runAnalysis class runAnalysis {
{
public: public:
//! Constructor //! Constructor
runAnalysis( std::shared_ptr<Database> db, const RankInfoStruct &rank_info, runAnalysis(std::shared_ptr<Database> db, const RankInfoStruct &rank_info,
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm, std::shared_ptr<Domain> dm, int Np, std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm,
bool Regular, IntArray Map ); std::shared_ptr<Domain> dm, int Np, bool Regular, IntArray Map);
runAnalysis( ScaLBL_ColorModel &ColorModel); runAnalysis(ScaLBL_ColorModel &ColorModel);
//! Destructor //! Destructor
~runAnalysis(); ~runAnalysis();
//! Run the next analysis //! Run the next analysis
void run( int timestep, std::shared_ptr<Database> db, TwoPhase &Averages, const double *Phi, void run(int timestep, std::shared_ptr<Database> db, TwoPhase &Averages,
double *Pressure, double *Velocity, double *fq, double *Den ); const double *Phi, double *Pressure, double *Velocity, double *fq,
double *Den);
void basic( int timestep, std::shared_ptr<Database> db, SubPhase &Averages, const double *Phi, void basic(int timestep, std::shared_ptr<Database> db, SubPhase &Averages,
double *Pressure, double *Velocity, double *fq, double *Den ); const double *Phi, double *Pressure, double *Velocity,
void WriteVisData( int timestep, std::shared_ptr<Database> vis_db, SubPhase &Averages, double *fq, double *Den);
const double *Phi, double *Pressure, double *Velocity, double *fq, double *Den ); void WriteVisData(int timestep, std::shared_ptr<Database> vis_db,
SubPhase &Averages, const double *Phi, double *Pressure,
double *Velocity, double *fq, double *Den);
//! Finish all active analysis //! Finish all active analysis
void finish(); void finish();
@ -80,27 +80,26 @@ public:
* that all threads run on independent cores * that all threads run on independent cores
* @param[in] N_threads Number of threads, only used by some of the methods * @param[in] N_threads Number of threads, only used by some of the methods
*/ */
void createThreads( const std::string &method = "default", int N_threads = 4 ); void createThreads(const std::string &method = "default",
int N_threads = 4);
private: private:
runAnalysis(); runAnalysis();
// Determine the analysis to perform // Determine the analysis to perform
AnalysisType computeAnalysisType( int timestep ); AnalysisType computeAnalysisType(int timestep);
public: public:
class commWrapper class commWrapper {
{
public: public:
Utilities::MPI comm; Utilities::MPI comm;
int tag; int tag;
runAnalysis *analysis; runAnalysis *analysis;
commWrapper( int tag, const Utilities::MPI &comm, runAnalysis *analysis ); commWrapper(int tag, const Utilities::MPI &comm, runAnalysis *analysis);
commWrapper() = delete; commWrapper() = delete;
commWrapper( const commWrapper &rhs ) = delete; commWrapper(const commWrapper &rhs) = delete;
commWrapper &operator=( const commWrapper &rhs ) = delete; commWrapper &operator=(const commWrapper &rhs) = delete;
commWrapper( commWrapper &&rhs ); commWrapper(commWrapper &&rhs);
~commWrapper(); ~commWrapper();
}; };
@ -112,12 +111,13 @@ private:
std::array<int, 3> d_N; // Number of local cells with ghosts std::array<int, 3> d_N; // Number of local cells with ghosts
int d_Np; int d_Np;
int d_rank; int d_rank;
int d_restart_interval, d_analysis_interval, d_blobid_interval, d_visualization_interval; int d_restart_interval, d_analysis_interval, d_blobid_interval,
d_visualization_interval;
int d_subphase_analysis_interval; int d_subphase_analysis_interval;
double d_beta; double d_beta;
bool d_regular; bool d_regular;
std::string format; // IO format string "silo" or "hdf5" std::string format; // IO format string "silo" or "hdf5"
ThreadPool d_tpool; ThreadPool d_tpool;
RankInfoStruct d_rank_info; RankInfoStruct d_rank_info;
IntArray d_Map; IntArray d_Map;

View File

@ -20,316 +20,312 @@
#include "analysis/filters.h" #include "analysis/filters.h"
#include "analysis/imfilter.h" #include "analysis/imfilter.h"
template <class T> inline int sign(T x) {
template<class T> if (x == 0)
inline int sign( T x )
{
if ( x==0 )
return 0; return 0;
return x>0 ? 1:-1; return x > 0 ? 1 : -1;
} }
inline float trilinear(float dx, float dy, float dz, float f1, float f2,
inline float trilinear( float dx, float dy, float dz, float f1, float f2, float f3, float f4, float f5, float f6, float f7,
float f3, float f4, float f5, float f6, float f7, float f8 ) float f8) {
{
double f, dx2, dy2, dz2, h0, h1; double f, dx2, dy2, dz2, h0, h1;
dx2 = 1.0 - dx; dx2 = 1.0 - dx;
dy2 = 1.0 - dy; dy2 = 1.0 - dy;
dz2 = 1.0 - dz; dz2 = 1.0 - dz;
h0 = ( dx * f2 + dx2 * f1 ) * dy2 + ( dx * f4 + dx2 * f3 ) * dy; h0 = (dx * f2 + dx2 * f1) * dy2 + (dx * f4 + dx2 * f3) * dy;
h1 = ( dx * f6 + dx2 * f5 ) * dy2 + ( dx * f8 + dx2 * f7 ) * dy; h1 = (dx * f6 + dx2 * f5) * dy2 + (dx * f8 + dx2 * f7) * dy;
f = h0 * dz2 + h1 * dz; f = h0 * dz2 + h1 * dz;
return ( f ); return (f);
} }
void InterpolateMesh(const Array<float> &Coarse, Array<float> &Fine) {
PROFILE_START("InterpolateMesh");
void InterpolateMesh( const Array<float> &Coarse, Array<float> &Fine ) // Interpolate values from a Coarse mesh to a fine one
{ // This routine assumes cell-centered meshes with 1 ghost cell
PROFILE_START("InterpolateMesh");
// Interpolate values from a Coarse mesh to a fine one // Fine mesh
// This routine assumes cell-centered meshes with 1 ghost cell int Nx = int(Fine.size(0)) - 2;
int Ny = int(Fine.size(1)) - 2;
int Nz = int(Fine.size(2)) - 2;
// Fine mesh // Coarse mesh
int Nx = int(Fine.size(0))-2; int nx = int(Coarse.size(0)) - 2;
int Ny = int(Fine.size(1))-2; int ny = int(Coarse.size(1)) - 2;
int Nz = int(Fine.size(2))-2; int nz = int(Coarse.size(2)) - 2;
// Coarse mesh // compute the stride
int nx = int(Coarse.size(0))-2; int hx = Nx / nx;
int ny = int(Coarse.size(1))-2; int hy = Ny / ny;
int nz = int(Coarse.size(2))-2; int hz = Nz / nz;
ASSERT(nx * hx == Nx);
ASSERT(ny * hy == Ny);
ASSERT(nz * hz == Nz);
// compute the stride // value to map distance between meshes (since distance is in voxels)
int hx = Nx/nx; // usually hx=hy=hz (or something very close)
int hy = Ny/ny; // the mapping is not exact
int hz = Nz/nz; // however, it's assumed the coarse solution will be refined
ASSERT(nx*hx==Nx); // a good guess is the goal here!
ASSERT(ny*hy==Ny); float mapvalue = sqrt(hx * hx + hy * hy + hz * hz);
ASSERT(nz*hz==Nz);
// value to map distance between meshes (since distance is in voxels) // Interpolate to the fine mesh
// usually hx=hy=hz (or something very close) for (int k = -1; k < Nz + 1; k++) {
// the mapping is not exact int k0 = floor((k - 0.5 * hz) / hz);
// however, it's assumed the coarse solution will be refined int k1 = k0 + 1;
// a good guess is the goal here! int k2 = k0 + 2;
float mapvalue = sqrt(hx*hx+hy*hy+hz*hz); float dz = ((k + 0.5) - (k0 + 0.5) * hz) / hz;
ASSERT(k0 >= -1 && k0 < nz + 1 && dz >= 0 && dz <= 1);
// Interpolate to the fine mesh for (int j = -1; j < Ny + 1; j++) {
for (int k=-1; k<Nz+1; k++){ int j0 = floor((j - 0.5 * hy) / hy);
int k0 = floor((k-0.5*hz)/hz); int j1 = j0 + 1;
int k1 = k0+1; int j2 = j0 + 2;
int k2 = k0+2; float dy = ((j + 0.5) - (j0 + 0.5) * hy) / hy;
float dz = ( (k+0.5) - (k0+0.5)*hz ) / hz; ASSERT(j0 >= -1 && j0 < ny + 1 && dy >= 0 && dy <= 1);
ASSERT(k0>=-1&&k0<nz+1&&dz>=0&&dz<=1); for (int i = -1; i < Nx + 1; i++) {
for (int j=-1; j<Ny+1; j++){ int i0 = floor((i - 0.5 * hx) / hx);
int j0 = floor((j-0.5*hy)/hy); int i1 = i0 + 1;
int j1 = j0+1; int i2 = i0 + 2;
int j2 = j0+2; float dx = ((i + 0.5) - (i0 + 0.5) * hx) / hx;
float dy = ( (j+0.5) - (j0+0.5)*hy ) / hy; ASSERT(i0 >= -1 && i0 < nx + 1 && dx >= 0 && dx <= 1);
ASSERT(j0>=-1&&j0<ny+1&&dy>=0&&dy<=1); float val = trilinear(
for (int i=-1; i<Nx+1; i++){ dx, dy, dz, Coarse(i1, j1, k1), Coarse(i2, j1, k1),
int i0 = floor((i-0.5*hx)/hx); Coarse(i1, j2, k1), Coarse(i2, j2, k1), Coarse(i1, j1, k2),
int i1 = i0+1; Coarse(i2, j1, k2), Coarse(i1, j2, k2), Coarse(i2, j2, k2));
int i2 = i0+2; Fine(i + 1, j + 1, k + 1) = mapvalue * val;
float dx = ( (i+0.5) - (i0+0.5)*hx ) / hx; }
ASSERT(i0>=-1&&i0<nx+1&&dx>=0&&dx<=1); }
float val = trilinear( dx, dy, dz, }
Coarse(i1,j1,k1), Coarse(i2,j1,k1), Coarse(i1,j2,k1), Coarse(i2,j2,k1), PROFILE_STOP("InterpolateMesh");
Coarse(i1,j1,k2), Coarse(i2,j1,k2), Coarse(i1,j2,k2), Coarse(i2,j2,k2) );
Fine(i+1,j+1,k+1) = mapvalue*val;
}
}
}
PROFILE_STOP("InterpolateMesh");
} }
// Smooth the data using the distance // Smooth the data using the distance
void smooth( const Array<float>& VOL, const Array<float>& Dist, float sigma, Array<float>& MultiScaleSmooth, fillHalo<float>& fillFloat ) void smooth(const Array<float> &VOL, const Array<float> &Dist, float sigma,
{ Array<float> &MultiScaleSmooth, fillHalo<float> &fillFloat) {
for (size_t i=0; i<VOL.length(); i++) { for (size_t i = 0; i < VOL.length(); i++) {
// use exponential weight based on the distance // use exponential weight based on the distance
float dst = Dist(i); float dst = Dist(i);
float tmp = exp(-(dst*dst)/(sigma*sigma)); float tmp = exp(-(dst * dst) / (sigma * sigma));
float value = dst>0 ? -1:1; float value = dst > 0 ? -1 : 1;
MultiScaleSmooth(i) = tmp*VOL(i) + (1-tmp)*value; MultiScaleSmooth(i) = tmp * VOL(i) + (1 - tmp) * value;
} }
fillFloat.fill(MultiScaleSmooth); fillFloat.fill(MultiScaleSmooth);
} }
// Segment the data // Segment the data
void segment( const Array<float>& data, Array<char>& ID, float tol ) void segment(const Array<float> &data, Array<char> &ID, float tol) {
{ ASSERT(data.size() == ID.size());
ASSERT(data.size()==ID.size()); for (size_t i = 0; i < data.length(); i++) {
for (size_t i=0; i<data.length(); i++) { if (data(i) > tol)
if ( data(i) > tol )
ID(i) = 0; ID(i) = 0;
else else
ID(i) = 1; ID(i) = 1;
} }
} }
// Remove disconnected phases // Remove disconnected phases
void removeDisconnected( Array<char>& ID, const Domain& Dm ) void removeDisconnected(Array<char> &ID, const Domain &Dm) {
{
// Run blob identification to remove disconnected volumes // Run blob identification to remove disconnected volumes
BlobIDArray GlobalBlobID; BlobIDArray GlobalBlobID;
DoubleArray SignDist(ID.size()); DoubleArray SignDist(ID.size());
DoubleArray Phase(ID.size()); DoubleArray Phase(ID.size());
for (size_t i=0; i<ID.length(); i++) { for (size_t i = 0; i < ID.length(); i++) {
SignDist(i) = (2*ID(i)-1); SignDist(i) = (2 * ID(i) - 1);
Phase(i) = 1; Phase(i) = 1;
} }
ComputeGlobalBlobIDs( ID.size(0)-2, ID.size(1)-2, ID.size(2)-2, ComputeGlobalBlobIDs(ID.size(0) - 2, ID.size(1) - 2, ID.size(2) - 2,
Dm.rank_info, Phase, SignDist, 0, 0, GlobalBlobID, Dm.Comm ); Dm.rank_info, Phase, SignDist, 0, 0, GlobalBlobID,
for (size_t i=0; i<ID.length(); i++) { Dm.Comm);
if ( GlobalBlobID(i) > 0 ) for (size_t i = 0; i < ID.length(); i++) {
if (GlobalBlobID(i) > 0)
ID(i) = 0; ID(i) = 0;
ID(i) = GlobalBlobID(i); ID(i) = GlobalBlobID(i);
} }
} }
// Solve a level (without any coarse level information) // Solve a level (without any coarse level information)
void solve( const Array<float>& VOL, Array<float>& Mean, Array<char>& ID, void solve(const Array<float> &VOL, Array<float> &Mean, Array<char> &ID,
Array<float>& Dist, Array<float>& MultiScaleSmooth, Array<float>& NonLocalMean, Array<float> &Dist, Array<float> &MultiScaleSmooth,
fillHalo<float>& fillFloat, const Domain& Dm, int nprocx, Array<float> &NonLocalMean, fillHalo<float> &fillFloat,
float threshold, float lamda, float sigsq, int depth) const Domain &Dm, int nprocx, float threshold, float lamda,
{ float sigsq, int depth) {
PROFILE_SCOPED(timer,"solve"); PROFILE_SCOPED(timer, "solve");
// Compute the median filter on the sparse array // Compute the median filter on the sparse array
Med3D( VOL, Mean ); Med3D(VOL, Mean);
fillFloat.fill( Mean ); fillFloat.fill(Mean);
segment( Mean, ID, threshold ); segment(Mean, ID, threshold);
// Compute the distance using the segmented volume // Compute the distance using the segmented volume
CalcDist( Dist, ID, Dm ); CalcDist(Dist, ID, Dm);
fillFloat.fill(Dist); fillFloat.fill(Dist);
smooth( VOL, Dist, 2.0, MultiScaleSmooth, fillFloat ); smooth(VOL, Dist, 2.0, MultiScaleSmooth, fillFloat);
// Compute non-local mean // Compute non-local mean
// int depth = 5; // int depth = 5;
// float sigsq=0.1; // float sigsq=0.1;
int nlm_count = NLM3D( MultiScaleSmooth, Mean, Dist, NonLocalMean, depth, sigsq); int nlm_count =
NULL_USE( nlm_count ); NLM3D(MultiScaleSmooth, Mean, Dist, NonLocalMean, depth, sigsq);
fillFloat.fill(NonLocalMean); NULL_USE(nlm_count);
fillFloat.fill(NonLocalMean);
} }
// Refine a solution from a coarse grid to a fine grid // Refine a solution from a coarse grid to a fine grid
void refine( const Array<float>& Dist_coarse, void refine(const Array<float> &Dist_coarse, const Array<float> &VOL,
const Array<float>& VOL, Array<float>& Mean, Array<char>& ID, Array<float> &Mean, Array<char> &ID, Array<float> &Dist,
Array<float>& Dist, Array<float>& MultiScaleSmooth, Array<float>& NonLocalMean, Array<float> &MultiScaleSmooth, Array<float> &NonLocalMean,
fillHalo<float>& fillFloat, const Domain& Dm, int nprocx, int level, fillHalo<float> &fillFloat, const Domain &Dm, int nprocx, int level,
float threshold, float lamda, float sigsq, int depth) float threshold, float lamda, float sigsq, int depth) {
{ PROFILE_SCOPED(timer, "refine");
PROFILE_SCOPED(timer,"refine"); int ratio[3] = {int(Dist.size(0) / Dist_coarse.size(0)),
int ratio[3] = { int(Dist.size(0)/Dist_coarse.size(0)), int(Dist.size(1) / Dist_coarse.size(1)),
int(Dist.size(1)/Dist_coarse.size(1)), int(Dist.size(2) / Dist_coarse.size(2))};
int(Dist.size(2)/Dist_coarse.size(2)) };
// Interpolate the distance from the coarse to fine grid // Interpolate the distance from the coarse to fine grid
InterpolateMesh( Dist_coarse, Dist ); InterpolateMesh(Dist_coarse, Dist);
// Compute the median filter on the array and segment // Compute the median filter on the array and segment
Med3D( VOL, Mean ); Med3D(VOL, Mean);
fillFloat.fill( Mean ); fillFloat.fill(Mean);
segment( Mean, ID, threshold ); segment(Mean, ID, threshold);
// If the ID has the wrong distance, set the distance to 0 and run a simple filter to set neighbors to 0 // If the ID has the wrong distance, set the distance to 0 and run a simple filter to set neighbors to 0
for (size_t i=0; i<ID.length(); i++) { for (size_t i = 0; i < ID.length(); i++) {
char id = Dist(i)>0 ? 1:0; char id = Dist(i) > 0 ? 1 : 0;
if ( id != ID(i) ) if (id != ID(i))
Dist(i) = 0; Dist(i) = 0;
} }
fillFloat.fill( Dist ); fillFloat.fill(Dist);
std::function<float(int,const float*)> filter_1D = []( int N, const float* data ) std::function<float(int, const float *)> filter_1D = [](int N,
{ const float *data) {
bool zero = data[0]==0 || data[2]==0; bool zero = data[0] == 0 || data[2] == 0;
return zero ? data[1]*1e-12 : data[1]; return zero ? data[1] * 1e-12 : data[1];
}; };
std::vector<imfilter::BC> BC(3,imfilter::BC::replicate); std::vector<imfilter::BC> BC(3, imfilter::BC::replicate);
std::vector<std::function<float(int,const float*)>> filter_set(3,filter_1D); std::vector<std::function<float(int, const float *)>> filter_set(3,
Dist = imfilter::imfilter_separable<float>( Dist, {1,1,1}, filter_set, BC ); filter_1D);
fillFloat.fill( Dist ); Dist = imfilter::imfilter_separable<float>(Dist, {1, 1, 1}, filter_set, BC);
fillFloat.fill(Dist);
// Smooth the volume data // Smooth the volume data
float h = 2*lamda*sqrt(double(ratio[0]*ratio[0]+ratio[1]*ratio[1]+ratio[2]*ratio[2])); float h = 2 * lamda *
smooth( VOL, Dist, h, MultiScaleSmooth, fillFloat ); sqrt(double(ratio[0] * ratio[0] + ratio[1] * ratio[1] +
ratio[2] * ratio[2]));
smooth(VOL, Dist, h, MultiScaleSmooth, fillFloat);
// Compute non-local mean // Compute non-local mean
// int depth = 3; // int depth = 3;
// float sigsq = 0.1; // float sigsq = 0.1;
int nlm_count = NLM3D( MultiScaleSmooth, Mean, Dist, NonLocalMean, depth, sigsq); int nlm_count =
NULL_USE( nlm_count ); NLM3D(MultiScaleSmooth, Mean, Dist, NonLocalMean, depth, sigsq);
fillFloat.fill(NonLocalMean); NULL_USE(nlm_count);
segment( NonLocalMean, ID, 0.001 ); fillFloat.fill(NonLocalMean);
for (size_t i=0; i<ID.length(); i++) { segment(NonLocalMean, ID, 0.001);
char id = Dist(i)>0 ? 1:0; for (size_t i = 0; i < ID.length(); i++) {
if ( id!=ID(i) || fabs(Dist(i))<1 ) char id = Dist(i) > 0 ? 1 : 0;
Dist(i) = 2.0*ID(i)-1.0; if (id != ID(i) || fabs(Dist(i)) < 1)
Dist(i) = 2.0 * ID(i) - 1.0;
} }
// Remove disconnected domains // Remove disconnected domains
//removeDisconnected( ID, Dm ); //removeDisconnected( ID, Dm );
// Compute the distance using the segmented volume // Compute the distance using the segmented volume
if ( level > 0 ) { if (level > 0) {
CalcDist( Dist, ID, Dm ); CalcDist(Dist, ID, Dm);
fillFloat.fill(Dist); fillFloat.fill(Dist);
} }
} }
// Remove regions that are likely noise by shrinking the volumes by dx, // Remove regions that are likely noise by shrinking the volumes by dx,
// removing all values that are more than dx+delta from the surface, and then // removing all values that are more than dx+delta from the surface, and then
// growing by dx+delta and intersecting with the original data // growing by dx+delta and intersecting with the original data
void filter_final( Array<char>& ID, Array<float>& Dist, void filter_final(Array<char> &ID, Array<float> &Dist,
fillHalo<float>& fillFloat, const Domain& Dm, fillHalo<float> &fillFloat, const Domain &Dm,
Array<float>& Mean, Array<float>& Dist1, Array<float>& Dist2 ) Array<float> &Mean, Array<float> &Dist1,
{ Array<float> &Dist2) {
PROFILE_SCOPED(timer,"filter_final"); PROFILE_SCOPED(timer, "filter_final");
int rank = Dm.Comm.getRank(); int rank = Dm.Comm.getRank();
int Nx = Dm.Nx-2; int Nx = Dm.Nx - 2;
int Ny = Dm.Ny-2; int Ny = Dm.Ny - 2;
int Nz = Dm.Nz-2; int Nz = Dm.Nz - 2;
// Calculate the distance // Calculate the distance
CalcDist( Dist, ID, Dm ); CalcDist(Dist, ID, Dm);
fillFloat.fill(Dist); fillFloat.fill(Dist);
// Compute the range to shrink the volume based on the L2 norm of the distance // Compute the range to shrink the volume based on the L2 norm of the distance
Array<float> Dist0(Nx,Ny,Nz); Array<float> Dist0(Nx, Ny, Nz);
fillFloat.copy(Dist,Dist0); fillFloat.copy(Dist, Dist0);
float tmp = 0; float tmp = 0;
for (size_t i=0; i<Dist0.length(); i++) for (size_t i = 0; i < Dist0.length(); i++)
tmp += Dist0(i)*Dist0(i); tmp += Dist0(i) * Dist0(i);
tmp = sqrt( Dm.Comm.sumReduce(tmp) / Dm.Comm.sumReduce<float>(Dist0.length()) ); tmp =
const float dx1 = 0.3*tmp; sqrt(Dm.Comm.sumReduce(tmp) / Dm.Comm.sumReduce<float>(Dist0.length()));
const float dx2 = 1.05*dx1; const float dx1 = 0.3 * tmp;
if (rank==0) const float dx2 = 1.05 * dx1;
printf(" %0.1f %0.1f %0.1f\n",tmp,dx1,dx2); if (rank == 0)
printf(" %0.1f %0.1f %0.1f\n", tmp, dx1, dx2);
// Update the IDs/Distance removing regions that are < dx of the range // Update the IDs/Distance removing regions that are < dx of the range
Dist1 = Dist; Dist1 = Dist;
Dist2 = Dist; Dist2 = Dist;
Array<char> ID1 = ID; Array<char> ID1 = ID;
Array<char> ID2 = ID; Array<char> ID2 = ID;
for (size_t i=0; i<ID.length(); i++) { for (size_t i = 0; i < ID.length(); i++) {
ID1(i) = Dist(i)<-dx1 ? 1:0; ID1(i) = Dist(i) < -dx1 ? 1 : 0;
ID2(i) = Dist(i)> dx1 ? 1:0; ID2(i) = Dist(i) > dx1 ? 1 : 0;
} }
//Array<float> Dist1 = Dist; //Array<float> Dist1 = Dist;
//Array<float> Dist2 = Dist; //Array<float> Dist2 = Dist;
CalcDist( Dist1, ID1, Dm ); CalcDist(Dist1, ID1, Dm);
CalcDist( Dist2, ID2, Dm ); CalcDist(Dist2, ID2, Dm);
fillFloat.fill(Dist1); fillFloat.fill(Dist1);
fillFloat.fill(Dist2); fillFloat.fill(Dist2);
// Keep those regions that are within dx2 of the new volumes // Keep those regions that are within dx2 of the new volumes
Mean = Dist; Mean = Dist;
for (size_t i=0; i<ID.length(); i++) { for (size_t i = 0; i < ID.length(); i++) {
if ( Dist1(i)+dx2>0 && ID(i)<=0 ) { if (Dist1(i) + dx2 > 0 && ID(i) <= 0) {
Mean(i) = -1; Mean(i) = -1;
} else if ( Dist2(i)+dx2>0 && ID(i)>0 ) { } else if (Dist2(i) + dx2 > 0 && ID(i) > 0) {
Mean(i) = 1; Mean(i) = 1;
} else { } else {
Mean(i) = Dist(i)>0 ? 0.5:-0.5; Mean(i) = Dist(i) > 0 ? 0.5 : -0.5;
} }
} }
// Find regions of uncertainty that are entirely contained within another region // Find regions of uncertainty that are entirely contained within another region
fillHalo<double> fillDouble(Dm.Comm,Dm.rank_info,{Nx,Ny,Nz},{1,1,1},0,1); fillHalo<double> fillDouble(Dm.Comm, Dm.rank_info, {Nx, Ny, Nz}, {1, 1, 1},
fillHalo<BlobIDType> fillInt(Dm.Comm,Dm.rank_info,{Nx,Ny,Nz},{1,1,1},0,1); 0, 1);
fillHalo<BlobIDType> fillInt(Dm.Comm, Dm.rank_info, {Nx, Ny, Nz}, {1, 1, 1},
0, 1);
BlobIDArray GlobalBlobID; BlobIDArray GlobalBlobID;
DoubleArray SignDist(ID.size()); DoubleArray SignDist(ID.size());
for (size_t i=0; i<ID.length(); i++) for (size_t i = 0; i < ID.length(); i++)
SignDist(i) = fabs(Mean(i))==1 ? -1:1; SignDist(i) = fabs(Mean(i)) == 1 ? -1 : 1;
fillDouble.fill(SignDist); fillDouble.fill(SignDist);
DoubleArray Phase(ID.size()); DoubleArray Phase(ID.size());
Phase.fill(1); Phase.fill(1);
ComputeGlobalBlobIDs( Nx, Ny, Nz, Dm.rank_info, Phase, SignDist, 0, 0, GlobalBlobID, Dm.Comm ); ComputeGlobalBlobIDs(Nx, Ny, Nz, Dm.rank_info, Phase, SignDist, 0, 0,
GlobalBlobID, Dm.Comm);
fillInt.fill(GlobalBlobID); fillInt.fill(GlobalBlobID);
int N_blobs = Dm.Comm.maxReduce(GlobalBlobID.max()+1); int N_blobs = Dm.Comm.maxReduce(GlobalBlobID.max() + 1);
std::vector<float> mean(N_blobs,0); std::vector<float> mean(N_blobs, 0);
std::vector<int> count(N_blobs,0); std::vector<int> count(N_blobs, 0);
for (int k=1; k<=Nz; k++) { for (int k = 1; k <= Nz; k++) {
for (int j=1; j<=Ny; j++) { for (int j = 1; j <= Ny; j++) {
for (int i=1; i<=Nx; i++) { for (int i = 1; i <= Nx; i++) {
int id = GlobalBlobID(i,j,k); int id = GlobalBlobID(i, j, k);
if ( id >= 0 ) { if (id >= 0) {
if ( GlobalBlobID(i-1,j,k)<0 ) { if (GlobalBlobID(i - 1, j, k) < 0) {
mean[id] += Mean(i-1,j,k); mean[id] += Mean(i - 1, j, k);
count[id]++; count[id]++;
} }
if ( GlobalBlobID(i+1,j,k)<0 ) { if (GlobalBlobID(i + 1, j, k) < 0) {
mean[id] += Mean(i+1,j,k); mean[id] += Mean(i + 1, j, k);
count[id]++; count[id]++;
} }
if ( GlobalBlobID(i,j-1,k)<0 ) { if (GlobalBlobID(i, j - 1, k) < 0) {
mean[id] += Mean(i,j-1,k); mean[id] += Mean(i, j - 1, k);
count[id]++; count[id]++;
} }
if ( GlobalBlobID(i,j+1,k)<0 ) { if (GlobalBlobID(i, j + 1, k) < 0) {
mean[id] += Mean(i,j+1,k); mean[id] += Mean(i, j + 1, k);
count[id]++; count[id]++;
} }
if ( GlobalBlobID(i,j,k-1)<0 ) { if (GlobalBlobID(i, j, k - 1) < 0) {
mean[id] += Mean(i,j,k-1); mean[id] += Mean(i, j, k - 1);
count[id]++; count[id]++;
} }
if ( GlobalBlobID(i,j,k+1)<0 ) { if (GlobalBlobID(i, j, k + 1) < 0) {
mean[id] += Mean(i,j,k+1); mean[id] += Mean(i, j, k + 1);
count[id]++; count[id]++;
} }
} }
@ -338,16 +334,16 @@ void filter_final( Array<char>& ID, Array<float>& Dist,
} }
mean = Dm.Comm.sumReduce(mean); mean = Dm.Comm.sumReduce(mean);
count = Dm.Comm.sumReduce(count); count = Dm.Comm.sumReduce(count);
for (size_t i=0; i<mean.size(); i++) for (size_t i = 0; i < mean.size(); i++)
mean[i] /= count[i]; mean[i] /= count[i];
/*if (rank==0) { /*if (rank==0) {
for (size_t i=0; i<mean.size(); i++) for (size_t i=0; i<mean.size(); i++)
printf("%i %0.4f\n",i,mean[i]); printf("%i %0.4f\n",i,mean[i]);
}*/ }*/
for (size_t i=0; i<Mean.length(); i++) { for (size_t i = 0; i < Mean.length(); i++) {
int id = GlobalBlobID(i); int id = GlobalBlobID(i);
if ( id >= 0 ) { if (id >= 0) {
if ( fabs(mean[id]) > 0.95 ) { if (fabs(mean[id]) > 0.95) {
// Isolated domain surrounded by one domain // Isolated domain surrounded by one domain
GlobalBlobID(i) = -2; GlobalBlobID(i) = -2;
Mean(i) = sign(mean[id]); Mean(i) = sign(mean[id]);
@ -359,53 +355,54 @@ void filter_final( Array<char>& ID, Array<float>& Dist,
} }
// Perform the final segmentation and update the distance // Perform the final segmentation and update the distance
fillFloat.fill(Mean); fillFloat.fill(Mean);
segment( Mean, ID, 0.01 ); segment(Mean, ID, 0.01);
CalcDist( Dist, ID, Dm ); CalcDist(Dist, ID, Dm);
fillFloat.fill(Dist); fillFloat.fill(Dist);
} }
// Filter the original data // Filter the original data
void filter_src( const Domain& Dm, Array<float>& src ) void filter_src(const Domain &Dm, Array<float> &src) {
{ PROFILE_START("Filter source data");
PROFILE_START("Filter source data"); int Nx = Dm.Nx - 2;
int Nx = Dm.Nx-2; int Ny = Dm.Ny - 2;
int Ny = Dm.Ny-2; int Nz = Dm.Nz - 2;
int Nz = Dm.Nz-2; fillHalo<float> fillFloat(Dm.Comm, Dm.rank_info, {Nx, Ny, Nz}, {1, 1, 1}, 0,
fillHalo<float> fillFloat(Dm.Comm,Dm.rank_info,{Nx,Ny,Nz},{1,1,1},0,1); 1);
// Perform a hot-spot filter on the data // Perform a hot-spot filter on the data
std::vector<imfilter::BC> BC = { imfilter::BC::replicate, imfilter::BC::replicate, imfilter::BC::replicate }; std::vector<imfilter::BC> BC = {imfilter::BC::replicate,
std::function<float(const Array<float>&)> filter_3D = []( const Array<float>& data ) imfilter::BC::replicate,
{ imfilter::BC::replicate};
float min1 = std::min(data(0,1,1),data(2,1,1)); std::function<float(const Array<float> &)> filter_3D =
float min2 = std::min(data(1,0,1),data(1,2,1)); [](const Array<float> &data) {
float min3 = std::min(data(1,1,0),data(1,1,2)); float min1 = std::min(data(0, 1, 1), data(2, 1, 1));
float max1 = std::max(data(0,1,1),data(2,1,1)); float min2 = std::min(data(1, 0, 1), data(1, 2, 1));
float max2 = std::max(data(1,0,1),data(1,2,1)); float min3 = std::min(data(1, 1, 0), data(1, 1, 2));
float max3 = std::max(data(1,1,0),data(1,1,2)); float max1 = std::max(data(0, 1, 1), data(2, 1, 1));
float min = std::min(min1,std::min(min2,min3)); float max2 = std::max(data(1, 0, 1), data(1, 2, 1));
float max = std::max(max1,std::max(max2,max3)); float max3 = std::max(data(1, 1, 0), data(1, 1, 2));
return std::max(std::min(data(1,1,1),max),min); float min = std::min(min1, std::min(min2, min3));
}; float max = std::max(max1, std::max(max2, max3));
std::function<float(const Array<float>&)> filter_1D = []( const Array<float>& data ) return std::max(std::min(data(1, 1, 1), max), min);
{ };
float min = std::min(data(0),data(2)); std::function<float(const Array<float> &)> filter_1D =
float max = std::max(data(0),data(2)); [](const Array<float> &data) {
return std::max(std::min(data(1),max),min); float min = std::min(data(0), data(2));
}; float max = std::max(data(0), data(2));
return std::max(std::min(data(1), max), min);
};
//LOCVOL[0] = imfilter::imfilter<float>( LOCVOL[0], {1,1,1}, filter_3D, BC ); //LOCVOL[0] = imfilter::imfilter<float>( LOCVOL[0], {1,1,1}, filter_3D, BC );
std::vector<std::function<float(const Array<float>&)>> filter_set(3,filter_1D); std::vector<std::function<float(const Array<float> &)>> filter_set(
src = imfilter::imfilter_separable<float>( src, {1,1,1}, filter_set, BC ); 3, filter_1D);
fillFloat.fill( src ); src = imfilter::imfilter_separable<float>(src, {1, 1, 1}, filter_set, BC);
fillFloat.fill(src);
// Perform a gaussian filter on the data // Perform a gaussian filter on the data
int Nh[3] = { 2, 2, 2 }; int Nh[3] = {2, 2, 2};
float sigma[3] = { 1.0, 1.0, 1.0 }; float sigma[3] = {1.0, 1.0, 1.0};
std::vector<Array<float>> H(3); std::vector<Array<float>> H(3);
H[0] = imfilter::create_filter<float>( { Nh[0] }, "gaussian", &sigma[0] ); H[0] = imfilter::create_filter<float>({Nh[0]}, "gaussian", &sigma[0]);
H[1] = imfilter::create_filter<float>( { Nh[1] }, "gaussian", &sigma[1] ); H[1] = imfilter::create_filter<float>({Nh[1]}, "gaussian", &sigma[1]);
H[2] = imfilter::create_filter<float>( { Nh[2] }, "gaussian", &sigma[2] ); H[2] = imfilter::create_filter<float>({Nh[2]}, "gaussian", &sigma[2]);
src = imfilter::imfilter_separable( src, H, BC ); src = imfilter::imfilter_separable(src, H, BC);
fillFloat.fill( src ); fillFloat.fill(src);
PROFILE_STOP("Filter source data"); PROFILE_STOP("Filter source data");
} }

View File

@ -21,54 +21,46 @@
#include "common/Domain.h" #include "common/Domain.h"
#include "common/Communication.h" #include "common/Communication.h"
/*! /*!
* @brief Interpolate between meshes * @brief Interpolate between meshes
* @details This routine interpolates from a coarse to a fine mesh * @details This routine interpolates from a coarse to a fine mesh
* @param[in] Coarse Coarse mesh solution * @param[in] Coarse Coarse mesh solution
* @param[out] Fine Fine mesh solution * @param[out] Fine Fine mesh solution
*/ */
void InterpolateMesh( const Array<float> &Coarse, Array<float> &Fine ); void InterpolateMesh(const Array<float> &Coarse, Array<float> &Fine);
// Smooth the data using the distance // Smooth the data using the distance
void smooth( const Array<float>& VOL, const Array<float>& Dist, float sigma, Array<float>& MultiScaleSmooth, fillHalo<float>& fillFloat ); void smooth(const Array<float> &VOL, const Array<float> &Dist, float sigma,
Array<float> &MultiScaleSmooth, fillHalo<float> &fillFloat);
// Segment the data // Segment the data
void segment( const Array<float>& data, Array<char>& ID, float tol ); void segment(const Array<float> &data, Array<char> &ID, float tol);
// Remove disconnected phases // Remove disconnected phases
void removeDisconnected( Array<char>& ID, const Domain& Dm ); void removeDisconnected(Array<char> &ID, const Domain &Dm);
// Solve a level (without any coarse level information) // Solve a level (without any coarse level information)
void solve( const Array<float>& VOL, Array<float>& Mean, Array<char>& ID, void solve(const Array<float> &VOL, Array<float> &Mean, Array<char> &ID,
Array<float>& Dist, Array<float>& MultiScaleSmooth, Array<float>& NonLocalMean, Array<float> &Dist, Array<float> &MultiScaleSmooth,
fillHalo<float>& fillFloat, const Domain& Dm, int nprocx, Array<float> &NonLocalMean, fillHalo<float> &fillFloat,
float threshold, float lamda, float sigsq, int depth); const Domain &Dm, int nprocx, float threshold, float lamda,
float sigsq, int depth);
// Refine a solution from a coarse grid to a fine grid // Refine a solution from a coarse grid to a fine grid
void refine( const Array<float>& Dist_coarse, void refine(const Array<float> &Dist_coarse, const Array<float> &VOL,
const Array<float>& VOL, Array<float>& Mean, Array<char>& ID, Array<float> &Mean, Array<char> &ID, Array<float> &Dist,
Array<float>& Dist, Array<float>& MultiScaleSmooth, Array<float>& NonLocalMean, Array<float> &MultiScaleSmooth, Array<float> &NonLocalMean,
fillHalo<float>& fillFloat, const Domain& Dm, int nprocx, int level, fillHalo<float> &fillFloat, const Domain &Dm, int nprocx, int level,
float threshold, float lamda, float sigsq, int depth); float threshold, float lamda, float sigsq, int depth);
// Remove regions that are likely noise by shrinking the volumes by dx, // Remove regions that are likely noise by shrinking the volumes by dx,
// removing all values that are more than dx+delta from the surface, and then // removing all values that are more than dx+delta from the surface, and then
// growing by dx+delta and intersecting with the original data // growing by dx+delta and intersecting with the original data
void filter_final( Array<char>& ID, Array<float>& Dist, void filter_final(Array<char> &ID, Array<float> &Dist,
fillHalo<float>& fillFloat, const Domain& Dm, fillHalo<float> &fillFloat, const Domain &Dm,
Array<float>& Mean, Array<float>& Dist1, Array<float>& Dist2 ); Array<float> &Mean, Array<float> &Dist1, Array<float> &Dist2);
// Filter the original data // Filter the original data
void filter_src( const Domain& Dm, Array<float>& src ); void filter_src(const Domain &Dm, Array<float> &src);
#endif #endif

View File

@ -27,13 +27,10 @@
#include <string> #include <string>
#include <vector> #include <vector>
/*! /*!
* Class Array is a multi-dimensional array class written by Mark Berrill * Class Array is a multi-dimensional array class written by Mark Berrill
*/ */
template<class TYPE, class FUN, class Allocator> template <class TYPE, class FUN, class Allocator> class Array final {
class Array final
{
public: // Constructors / assignment operators public: // Constructors / assignment operators
/*! /*!
* Create a new empty Array * Create a new empty Array
@ -44,20 +41,20 @@ public: // Constructors / assignment operators
* Create an Array with the given size * Create an Array with the given size
* @param N Size of the array * @param N Size of the array
*/ */
explicit Array( const ArraySize &N ); explicit Array(const ArraySize &N);
/*! /*!
* Create a new 1D Array with the given number of elements * Create a new 1D Array with the given number of elements
* @param N Number of elements in the array * @param N Number of elements in the array
*/ */
explicit Array( size_t N ); explicit Array(size_t N);
/*! /*!
* Create a new 2D Array with the given number of rows and columns * Create a new 2D Array with the given number of rows and columns
* @param N_rows Number of rows * @param N_rows Number of rows
* @param N_columns Number of columns * @param N_columns Number of columns
*/ */
explicit Array( size_t N_rows, size_t N_columns ); explicit Array(size_t N_rows, size_t N_columns);
/*! /*!
* Create a new 3D Array with the given number of rows and columns * Create a new 3D Array with the given number of rows and columns
@ -65,7 +62,7 @@ public: // Constructors / assignment operators
* @param N2 Number of columns * @param N2 Number of columns
* @param N3 Number of elements in the third dimension * @param N3 Number of elements in the third dimension
*/ */
explicit Array( size_t N1, size_t N2, size_t N3 ); explicit Array(size_t N1, size_t N2, size_t N3);
/*! /*!
* Create a new 4D Array with the given number of rows and columns * Create a new 4D Array with the given number of rows and columns
@ -74,7 +71,7 @@ public: // Constructors / assignment operators
* @param N3 Number of elements in the third dimension * @param N3 Number of elements in the third dimension
* @param N4 Number of elements in the fourth dimension * @param N4 Number of elements in the fourth dimension
*/ */
explicit Array( size_t N1, size_t N2, size_t N3, size_t N4 ); explicit Array(size_t N1, size_t N2, size_t N3, size_t N4);
/*! /*!
* Create a new 4D Array with the given number of rows and columns * Create a new 4D Array with the given number of rows and columns
@ -84,76 +81,74 @@ public: // Constructors / assignment operators
* @param N4 Number of elements in the fourth dimension * @param N4 Number of elements in the fourth dimension
* @param N5 Number of elements in the fifth dimension * @param N5 Number of elements in the fifth dimension
*/ */
explicit Array( size_t N1, size_t N2, size_t N3, size_t N4, size_t N5 ); explicit Array(size_t N1, size_t N2, size_t N3, size_t N4, size_t N5);
/*! /*!
* Create a multi-dimensional Array with the given number of elements * Create a multi-dimensional Array with the given number of elements
* @param N Number of elements in each dimension * @param N Number of elements in each dimension
* @param data Optional raw array to copy the src data * @param data Optional raw array to copy the src data
*/ */
explicit Array( const std::vector<size_t> &N, const TYPE *data = nullptr ); explicit Array(const std::vector<size_t> &N, const TYPE *data = nullptr);
/*! /*!
* Create a 1D Array using a string that mimic's MATLAB * Create a 1D Array using a string that mimic's MATLAB
* @param range Range of the data * @param range Range of the data
*/ */
explicit Array( std::string range ); explicit Array(std::string range);
/*! /*!
* Create a 1D Array with the given initializer list * Create a 1D Array with the given initializer list
* @param data Input data * @param data Input data
*/ */
Array( std::initializer_list<TYPE> data ); Array(std::initializer_list<TYPE> data);
/*! /*!
* Create a 2D Array with the given initializer lists * Create a 2D Array with the given initializer lists
* @param data Input data * @param data Input data
*/ */
Array( std::initializer_list<std::initializer_list<TYPE>> data ); Array(std::initializer_list<std::initializer_list<TYPE>> data);
/*! /*!
* Copy constructor * Copy constructor
* @param rhs Array to copy * @param rhs Array to copy
*/ */
Array( const Array &rhs ); Array(const Array &rhs);
/*! /*!
* Move constructor * Move constructor
* @param rhs Array to copy * @param rhs Array to copy
*/ */
Array( Array &&rhs ); Array(Array &&rhs);
/*! /*!
* Assignment operator * Assignment operator
* @param rhs Array to copy * @param rhs Array to copy
*/ */
Array &operator=( const Array &rhs ); Array &operator=(const Array &rhs);
/*! /*!
* Move assignment operator * Move assignment operator
* @param rhs Array to copy * @param rhs Array to copy
*/ */
Array &operator=( Array &&rhs ); Array &operator=(Array &&rhs);
/*! /*!
* Assignment operator * Assignment operator
* @param rhs std::vector to copy * @param rhs std::vector to copy
*/ */
Array &operator=( const std::vector<TYPE> &rhs ); Array &operator=(const std::vector<TYPE> &rhs);
//! Is copyable? //! Is copyable?
inline bool isCopyable() const { return d_isCopyable; } inline bool isCopyable() const { return d_isCopyable; }
//! Set is copyable //! Set is copyable
inline void setCopyable( bool flag ) { d_isCopyable = flag; } inline void setCopyable(bool flag) { d_isCopyable = flag; }
//! Is fixed size? //! Is fixed size?
inline bool isFixedSize() const { return d_isFixedSize; } inline bool isFixedSize() const { return d_isFixedSize; }
//! Set is copyable //! Set is copyable
inline void setFixedSize( bool flag ) { d_isFixedSize = flag; } inline void setFixedSize(bool flag) { d_isFixedSize = flag; }
public: // Views/copies/subset public: // Views/copies/subset
/*! /*!
@ -161,30 +156,29 @@ public: // Views/copies/subset
* @param N Number of elements in each dimension * @param N Number of elements in each dimension
* @param data Pointer to the data * @param data Pointer to the data
*/ */
static std::unique_ptr<Array> view( const ArraySize &N, std::shared_ptr<TYPE> data ); static std::unique_ptr<Array> view(const ArraySize &N,
std::shared_ptr<TYPE> data);
/*! /*!
* Create a multi-dimensional Array view to a raw block of data * Create a multi-dimensional Array view to a raw block of data
* @param N Number of elements in each dimension * @param N Number of elements in each dimension
* @param data Pointer to the data * @param data Pointer to the data
*/ */
static std::unique_ptr<const Array> constView( const ArraySize &N, static std::unique_ptr<const Array>
std::shared_ptr<const TYPE> const &data ); constView(const ArraySize &N, std::shared_ptr<const TYPE> const &data);
/*! /*!
* Make this object a view of the src * Make this object a view of the src
* @param src Source vector to take the view of * @param src Source vector to take the view of
*/ */
void view2( Array &src ); void view2(Array &src);
/*! /*!
* Make this object a view of the data * Make this object a view of the data
* @param N Number of elements in each dimension * @param N Number of elements in each dimension
* @param data Pointer to the data * @param data Pointer to the data
*/ */
void view2( const ArraySize &N, std::shared_ptr<TYPE> data ); void view2(const ArraySize &N, std::shared_ptr<TYPE> data);
/*! /*!
* Make this object a view of the raw data (expert use only). * Make this object a view of the raw data (expert use only).
@ -199,10 +193,9 @@ public: // Views/copies/subset
* @param isCopyable Once the view is created, can the array be copied * @param isCopyable Once the view is created, can the array be copied
* @param isFixedSize Once the view is created, is the array size fixed * @param isFixedSize Once the view is created, is the array size fixed
*/ */
inline void viewRaw( inline void viewRaw(int ndim, const size_t *dims, TYPE *data,
int ndim, const size_t *dims, TYPE *data, bool isCopyable = true, bool isFixedSize = true ) bool isCopyable = true, bool isFixedSize = true) {
{ viewRaw(ArraySize(ndim, dims), data, isCopyable, isFixedSize);
viewRaw( ArraySize( ndim, dims ), data, isCopyable, isFixedSize );
} }
/*! /*!
@ -217,7 +210,8 @@ public: // Views/copies/subset
* @param isCopyable Once the view is created, can the array be copied * @param isCopyable Once the view is created, can the array be copied
* @param isFixedSize Once the view is created, is the array size fixed * @param isFixedSize Once the view is created, is the array size fixed
*/ */
void viewRaw( const ArraySize &N, TYPE *data, bool isCopyable = true, bool isFixedSize = true ); void viewRaw(const ArraySize &N, TYPE *data, bool isCopyable = true,
bool isFixedSize = true);
/*! /*!
* Create an array view of the given data (expert use only). * Create an array view of the given data (expert use only).
@ -229,10 +223,9 @@ public: // Views/copies/subset
* @param N Number of elements in each dimension * @param N Number of elements in each dimension
* @param data Pointer to the data * @param data Pointer to the data
*/ */
static inline Array staticView( const ArraySize &N, TYPE *data ) static inline Array staticView(const ArraySize &N, TYPE *data) {
{
Array x; Array x;
x.viewRaw( N, data, true, true ); x.viewRaw(N, data, true, true);
return x; return x;
} }
@ -240,39 +233,34 @@ public: // Views/copies/subset
* Convert an array of one type to another. This may or may not allocate new memory. * Convert an array of one type to another. This may or may not allocate new memory.
* @param array Input array * @param array Input array
*/ */
template<class TYPE2> template <class TYPE2>
static inline std::unique_ptr<Array<TYPE2, FUN, Allocator>> static inline std::unique_ptr<Array<TYPE2, FUN, Allocator>>
convert( std::shared_ptr<Array<TYPE, FUN, Allocator>> array ) convert(std::shared_ptr<Array<TYPE, FUN, Allocator>> array) {
{ auto array2 = std::make_unique<Array<TYPE2>>(array->size());
auto array2 = std::make_unique<Array<TYPE2>>( array->size() ); array2.copy(*array);
array2.copy( *array );
return array2; return array2;
} }
/*! /*!
* Convert an array of one type to another. This may or may not allocate new memory. * Convert an array of one type to another. This may or may not allocate new memory.
* @param array Input array * @param array Input array
*/ */
template<class TYPE2> template <class TYPE2>
static inline std::unique_ptr<const Array<TYPE2, FUN, Allocator>> static inline std::unique_ptr<const Array<TYPE2, FUN, Allocator>>
convert( std::shared_ptr<const Array<TYPE, FUN, Allocator>> array ) convert(std::shared_ptr<const Array<TYPE, FUN, Allocator>> array) {
{ auto array2 = std::make_unique<Array<TYPE2>>(array->size());
auto array2 = std::make_unique<Array<TYPE2>>( array->size() ); array2.copy(*array);
array2.copy( *array );
return array2; return array2;
} }
/*! /*!
* Copy and convert data from another array to this array * Copy and convert data from another array to this array
* @param array Source array * @param array Source array
*/ */
template<class TYPE2, class FUN2, class Allocator2> template <class TYPE2, class FUN2, class Allocator2>
void inline copy( const Array<TYPE2, FUN2, Allocator2> &array ) void inline copy(const Array<TYPE2, FUN2, Allocator2> &array) {
{ resize(array.size());
resize( array.size() ); copy(array.data());
copy( array.data() );
} }
/*! /*!
@ -280,39 +268,33 @@ public: // Views/copies/subset
* Note: The current array must be allocated to the proper size first. * Note: The current array must be allocated to the proper size first.
* @param data Source data * @param data Source data
*/ */
template<class TYPE2> template <class TYPE2> inline void copy(const TYPE2 *data);
inline void copy( const TYPE2 *data );
/*! /*!
* Copy and convert data from this array to a raw vector. * Copy and convert data from this array to a raw vector.
* @param data Source data * @param data Source data
*/ */
template<class TYPE2> template <class TYPE2> inline void copyTo(TYPE2 *data) const;
inline void copyTo( TYPE2 *data ) const;
/*! /*!
* Copy and convert data from this array to a new array * Copy and convert data from this array to a new array
*/ */
template<class TYPE2> template <class TYPE2>
Array<TYPE2, FUN, std::allocator<TYPE2>> inline cloneTo() const Array<TYPE2, FUN, std::allocator<TYPE2>> inline cloneTo() const {
{ Array<TYPE2, FUN, std::allocator<TYPE2>> dst(this->size());
Array<TYPE2, FUN, std::allocator<TYPE2>> dst( this->size() ); copyTo(dst.data());
copyTo( dst.data() );
return dst; return dst;
} }
/*! swap the raw data pointers for the Arrays after checking for compatibility */ /*! swap the raw data pointers for the Arrays after checking for compatibility */
void swap( Array &other ); void swap(Array &other);
/*! /*!
* Fill the array with the given value * Fill the array with the given value
* @param y Value to fill * @param y Value to fill
*/ */
inline void fill( const TYPE &y ) inline void fill(const TYPE &y) {
{ for (auto &x : *this)
for ( auto &x : *this )
x = y; x = y;
} }
@ -320,67 +302,56 @@ public: // Views/copies/subset
* Scale the array by the given value * Scale the array by the given value
* @param y Value to scale by * @param y Value to scale by
*/ */
template<class TYPE2> template <class TYPE2> inline void scale(const TYPE2 &y) {
inline void scale( const TYPE2 &y ) for (auto &x : *this)
{
for ( auto &x : *this )
x *= y; x *= y;
} }
/*! /*!
* Set the values of this array to pow(base, exp) * Set the values of this array to pow(base, exp)
* @param base Base array * @param base Base array
* @param exp Exponent value * @param exp Exponent value
*/ */
void pow( const Array &base, const TYPE &exp ); void pow(const Array &base, const TYPE &exp);
//! Destructor //! Destructor
~Array(); ~Array();
//! Clear the data in the array //! Clear the data in the array
void clear(); void clear();
//! Return the size of the Array //! Return the size of the Array
inline int ndim() const { return d_size.ndim(); } inline int ndim() const { return d_size.ndim(); }
//! Return the size of the Array //! Return the size of the Array
inline const ArraySize &size() const { return d_size; } inline const ArraySize &size() const { return d_size; }
//! Return the size of the Array //! Return the size of the Array
inline size_t size( int d ) const { return d_size[d]; } inline size_t size(int d) const { return d_size[d]; }
//! Return the size of the Array //! Return the size of the Array
inline size_t length() const { return d_size.length(); } inline size_t length() const { return d_size.length(); }
//! Return true if the Array is empty //! Return true if the Array is empty
inline bool empty() const { return d_size.length() == 0; } inline bool empty() const { return d_size.length() == 0; }
//! Return true if the Array is not empty //! Return true if the Array is not empty
inline operator bool() const { return d_size.length() != 0; } inline operator bool() const { return d_size.length() != 0; }
/*! /*!
* Resize the Array * Resize the Array
* @param N NUmber of elements * @param N NUmber of elements
*/ */
inline void resize( size_t N ) { resize( ArraySize( N ) ); } inline void resize(size_t N) { resize(ArraySize(N)); }
/*! /*!
* Resize the Array * Resize the Array
* @param N_row Number of rows * @param N_row Number of rows
* @param N_col Number of columns * @param N_col Number of columns
*/ */
inline void resize( size_t N_row, size_t N_col ) { resize( ArraySize( N_row, N_col ) ); } inline void resize(size_t N_row, size_t N_col) {
resize(ArraySize(N_row, N_col));
}
/*! /*!
* Resize the Array * Resize the Array
@ -388,14 +359,15 @@ public: // Views/copies/subset
* @param N2 Number of columns * @param N2 Number of columns
* @param N3 Number of elements in the third dimension * @param N3 Number of elements in the third dimension
*/ */
inline void resize( size_t N1, size_t N2, size_t N3 ) { resize( ArraySize( N1, N2, N3 ) ); } inline void resize(size_t N1, size_t N2, size_t N3) {
resize(ArraySize(N1, N2, N3));
}
/*! /*!
* Resize the Array * Resize the Array
* @param N Number of elements in each dimension * @param N Number of elements in each dimension
*/ */
void resize( const ArraySize &N ); void resize(const ArraySize &N);
/*! /*!
* Resize the given dimension of the array * Resize the given dimension of the array
@ -403,87 +375,83 @@ public: // Views/copies/subset
* @param N Number of elements for the given dimension * @param N Number of elements for the given dimension
* @param value Value to initialize new elements * @param value Value to initialize new elements
*/ */
void resizeDim( int dim, size_t N, const TYPE &value ); void resizeDim(int dim, size_t N, const TYPE &value);
/*! /*!
* Reshape the Array (total size of array will not change) * Reshape the Array (total size of array will not change)
* @param N Number of elements in each dimension * @param N Number of elements in each dimension
*/ */
void reshape( const ArraySize &N ); void reshape(const ArraySize &N);
/*! /*!
* Remove singleton dimensions. * Remove singleton dimensions.
*/ */
void squeeze(); void squeeze();
/*! /*!
* Reshape the Array so that the number of dimensions is the * Reshape the Array so that the number of dimensions is the
* max of ndim and the largest dim>1. * max of ndim and the largest dim>1.
* @param ndim Desired number of dimensions * @param ndim Desired number of dimensions
*/ */
inline void setNdim( int ndim ) { d_size.setNdim( ndim ); } inline void setNdim(int ndim) { d_size.setNdim(ndim); }
/*! /*!
* Subset the Array * Subset the Array
* @param index Index to subset (imin,imax,jmin,jmax,kmin,kmax,...) * @param index Index to subset (imin,imax,jmin,jmax,kmin,kmax,...)
*/ */
Array subset( const std::vector<size_t> &index ) const; Array subset(const std::vector<size_t> &index) const;
/*! /*!
* Subset the Array * Subset the Array
* @param index Index to subset (ix:kx:jx,iy:ky:jy,...) * @param index Index to subset (ix:kx:jx,iy:ky:jy,...)
*/ */
Array subset( const std::vector<Range<size_t>> &index ) const; Array subset(const std::vector<Range<size_t>> &index) const;
/*! /*!
* Copy data from an array into a subset of this array * Copy data from an array into a subset of this array
* @param index Index of the subset (imin,imax,jmin,jmax,kmin,kmax,...) * @param index Index of the subset (imin,imax,jmin,jmax,kmin,kmax,...)
* @param subset The subset array to copy from * @param subset The subset array to copy from
*/ */
void copySubset( const std::vector<size_t> &index, const Array &subset ); void copySubset(const std::vector<size_t> &index, const Array &subset);
/*! /*!
* Copy data from an array into a subset of this array * Copy data from an array into a subset of this array
* @param index Index of the subset * @param index Index of the subset
* @param subset The subset array to copy from * @param subset The subset array to copy from
*/ */
void copySubset( const std::vector<Range<size_t>> &index, const Array &subset ); void copySubset(const std::vector<Range<size_t>> &index,
const Array &subset);
/*! /*!
* Add data from an array into a subset of this array * Add data from an array into a subset of this array
* @param index Index of the subset (imin,imax,jmin,jmax,kmin,kmax,...) * @param index Index of the subset (imin,imax,jmin,jmax,kmin,kmax,...)
* @param subset The subset array to add from * @param subset The subset array to add from
*/ */
void addSubset( const std::vector<size_t> &index, const Array &subset ); void addSubset(const std::vector<size_t> &index, const Array &subset);
/*! /*!
* Add data from an array into a subset of this array * Add data from an array into a subset of this array
* @param index Index of the subset * @param index Index of the subset
* @param subset The subset array to add from * @param subset The subset array to add from
*/ */
void addSubset( const std::vector<Range<size_t>> &index, const Array &subset ); void addSubset(const std::vector<Range<size_t>> &index,
const Array &subset);
public: // Accessors public: // Accessors
/*! /*!
* Access the desired element * Access the desired element
* @param i The row index * @param i The row index
*/ */
ARRAY_ATTRIBUTE inline TYPE &operator()( size_t i ) { return d_data[d_size.index( i )]; } ARRAY_ATTRIBUTE inline TYPE &operator()(size_t i) {
return d_data[d_size.index(i)];
}
/*! /*!
* Access the desired element * Access the desired element
* @param i The row index * @param i The row index
*/ */
ARRAY_ATTRIBUTE inline const TYPE &operator()( size_t i ) const ARRAY_ATTRIBUTE inline const TYPE &operator()(size_t i) const {
{ return d_data[d_size.index(i)];
return d_data[d_size.index( i )];
} }
/*! /*!
@ -491,9 +459,8 @@ public: // Accessors
* @param i The row index * @param i The row index
* @param j The column index * @param j The column index
*/ */
ARRAY_ATTRIBUTE inline TYPE &operator()( size_t i, size_t j ) ARRAY_ATTRIBUTE inline TYPE &operator()(size_t i, size_t j) {
{ return d_data[d_size.index(i, j)];
return d_data[d_size.index( i, j )];
} }
/*! /*!
@ -501,9 +468,8 @@ public: // Accessors
* @param i The row index * @param i The row index
* @param j The column index * @param j The column index
*/ */
ARRAY_ATTRIBUTE inline const TYPE &operator()( size_t i, size_t j ) const ARRAY_ATTRIBUTE inline const TYPE &operator()(size_t i, size_t j) const {
{ return d_data[d_size.index(i, j)];
return d_data[d_size.index( i, j )];
} }
/*! /*!
@ -512,9 +478,8 @@ public: // Accessors
* @param j The column index * @param j The column index
* @param k The third index * @param k The third index
*/ */
ARRAY_ATTRIBUTE inline TYPE &operator()( size_t i, size_t j, size_t k ) ARRAY_ATTRIBUTE inline TYPE &operator()(size_t i, size_t j, size_t k) {
{ return d_data[d_size.index(i, j, k)];
return d_data[d_size.index( i, j, k )];
} }
/*! /*!
@ -523,9 +488,9 @@ public: // Accessors
* @param j The column index * @param j The column index
* @param k The third index * @param k The third index
*/ */
ARRAY_ATTRIBUTE inline const TYPE &operator()( size_t i, size_t j, size_t k ) const ARRAY_ATTRIBUTE inline const TYPE &operator()(size_t i, size_t j,
{ size_t k) const {
return d_data[d_size.index( i, j, k )]; return d_data[d_size.index(i, j, k)];
} }
/*! /*!
@ -535,9 +500,9 @@ public: // Accessors
* @param i3 The third index * @param i3 The third index
* @param i4 The fourth index * @param i4 The fourth index
*/ */
ARRAY_ATTRIBUTE inline TYPE &operator()( size_t i1, size_t i2, size_t i3, size_t i4 ) ARRAY_ATTRIBUTE inline TYPE &operator()(size_t i1, size_t i2, size_t i3,
{ size_t i4) {
return d_data[d_size.index( i1, i2, i3, i4 )]; return d_data[d_size.index(i1, i2, i3, i4)];
} }
/*! /*!
@ -547,10 +512,9 @@ public: // Accessors
* @param i3 The third index * @param i3 The third index
* @param i4 The fourth index * @param i4 The fourth index
*/ */
ARRAY_ATTRIBUTE inline const TYPE & ARRAY_ATTRIBUTE inline const TYPE &operator()(size_t i1, size_t i2,
operator()( size_t i1, size_t i2, size_t i3, size_t i4 ) const size_t i3, size_t i4) const {
{ return d_data[d_size.index(i1, i2, i3, i4)];
return d_data[d_size.index( i1, i2, i3, i4 )];
} }
/*! /*!
@ -561,9 +525,9 @@ public: // Accessors
* @param i4 The fourth index * @param i4 The fourth index
* @param i5 The fifth index * @param i5 The fifth index
*/ */
ARRAY_ATTRIBUTE inline TYPE &operator()( size_t i1, size_t i2, size_t i3, size_t i4, size_t i5 ) ARRAY_ATTRIBUTE inline TYPE &operator()(size_t i1, size_t i2, size_t i3,
{ size_t i4, size_t i5) {
return d_data[d_size.index( i1, i2, i3, i4, i5 )]; return d_data[d_size.index(i1, i2, i3, i4, i5)];
} }
/*! /*!
@ -575,17 +539,15 @@ public: // Accessors
* @param i5 The fifth index * @param i5 The fifth index
*/ */
ARRAY_ATTRIBUTE inline const TYPE & ARRAY_ATTRIBUTE inline const TYPE &
operator()( size_t i1, size_t i2, size_t i3, size_t i4, size_t i5 ) const operator()(size_t i1, size_t i2, size_t i3, size_t i4, size_t i5) const {
{ return d_data[d_size.index(i1, i2, i3, i4, i5)];
return d_data[d_size.index( i1, i2, i3, i4, i5 )];
} }
/*! /*!
* Access the desired element as a raw pointer * Access the desired element as a raw pointer
* @param i The global index * @param i The global index
*/ */
ARRAY_ATTRIBUTE inline TYPE *ptr( size_t i ) ARRAY_ATTRIBUTE inline TYPE *ptr(size_t i) {
{
return i >= d_size.length() ? nullptr : &d_data[i]; return i >= d_size.length() ? nullptr : &d_data[i];
} }
@ -593,8 +555,7 @@ public: // Accessors
* Access the desired element as a raw pointer * Access the desired element as a raw pointer
* @param i The global index * @param i The global index
*/ */
ARRAY_ATTRIBUTE inline const TYPE *ptr( size_t i ) const ARRAY_ATTRIBUTE inline const TYPE *ptr(size_t i) const {
{
return i >= d_size.length() ? nullptr : &d_data[i]; return i >= d_size.length() ? nullptr : &d_data[i];
} }
@ -622,40 +583,40 @@ public: // Accessors
//! Return the pointer to the raw data //! Return the pointer to the raw data
ARRAY_ATTRIBUTE inline const TYPE *data() const { return d_data; } ARRAY_ATTRIBUTE inline const TYPE *data() const { return d_data; }
public: // Operator overloading public: // Operator overloading
//! Check if two matrices are equal //! Check if two matrices are equal
// Equality means the dimensions and data have to be identical // Equality means the dimensions and data have to be identical
bool operator==( const Array &rhs ) const; bool operator==(const Array &rhs) const;
//! Check if two matrices are not equal //! Check if two matrices are not equal
inline bool operator!=( const Array &rhs ) const { return !this->operator==( rhs ); } inline bool operator!=(const Array &rhs) const {
return !this->operator==(rhs);
}
//! Add another array //! Add another array
Array &operator+=( const Array &rhs ); Array &operator+=(const Array &rhs);
//! Subtract another array //! Subtract another array
Array &operator-=( const Array &rhs ); Array &operator-=(const Array &rhs);
//! Add a scalar //! Add a scalar
Array &operator+=( const TYPE &rhs ); Array &operator+=(const TYPE &rhs);
//! Subtract a scalar //! Subtract a scalar
Array &operator-=( const TYPE &rhs ); Array &operator-=(const TYPE &rhs);
public: // Math operations public: // Math operations
//! Concatenates the arrays along the dimension dim. //! Concatenates the arrays along the dimension dim.
static Array cat( const std::vector<Array> &x, int dim = 0 ); static Array cat(const std::vector<Array> &x, int dim = 0);
//! Concatenates the arrays along the dimension dim. //! Concatenates the arrays along the dimension dim.
static Array cat( const std::initializer_list<Array> &x, int dim = 0 ); static Array cat(const std::initializer_list<Array> &x, int dim = 0);
//! Concatenates the arrays along the dimension dim. //! Concatenates the arrays along the dimension dim.
static Array cat( size_t N_array, const Array *x, int dim ); static Array cat(size_t N_array, const Array *x, int dim);
//! Concatenates a given array with the current array //! Concatenates a given array with the current array
void cat( const Array &x, int dim = 0 ); void cat(const Array &x, int dim = 0);
//! Initialize the array with random values (defined from the function table) //! Initialize the array with random values (defined from the function table)
//void rand(); //void rand();
@ -676,46 +637,46 @@ public: // Math operations
TYPE mean() const; TYPE mean() const;
//! Return the min of all elements in a given direction //! Return the min of all elements in a given direction
Array min( int dir ) const; Array min(int dir) const;
//! Return the max of all elements in a given direction //! Return the max of all elements in a given direction
Array max( int dir ) const; Array max(int dir) const;
//! Return the sum of all elements in a given direction //! Return the sum of all elements in a given direction
Array sum( int dir ) const; Array sum(int dir) const;
//! Return the smallest value //! Return the smallest value
TYPE min( const std::vector<size_t> &index ) const; TYPE min(const std::vector<size_t> &index) const;
//! Return the largest value //! Return the largest value
TYPE max( const std::vector<size_t> &index ) const; TYPE max(const std::vector<size_t> &index) const;
//! Return the sum of all elements //! Return the sum of all elements
TYPE sum( const std::vector<size_t> &index ) const; TYPE sum(const std::vector<size_t> &index) const;
//! Return the mean of all elements //! Return the mean of all elements
TYPE mean( const std::vector<size_t> &index ) const; TYPE mean(const std::vector<size_t> &index) const;
//! Return the smallest value //! Return the smallest value
TYPE min( const std::vector<Range<size_t>> &index ) const; TYPE min(const std::vector<Range<size_t>> &index) const;
//! Return the largest value //! Return the largest value
TYPE max( const std::vector<Range<size_t>> &index ) const; TYPE max(const std::vector<Range<size_t>> &index) const;
//! Return the sum of all elements //! Return the sum of all elements
TYPE sum( const std::vector<Range<size_t>> &index ) const; TYPE sum(const std::vector<Range<size_t>> &index) const;
//! Return the mean of all elements //! Return the mean of all elements
TYPE mean( const std::vector<Range<size_t>> &index ) const; TYPE mean(const std::vector<Range<size_t>> &index) const;
//! Find all elements that match the operator //! Find all elements that match the operator
std::vector<size_t> find( const TYPE &value, std::vector<size_t>
std::function<bool( const TYPE &, const TYPE & )> compare ) const; find(const TYPE &value,
std::function<bool(const TYPE &, const TYPE &)> compare) const;
//! Print an array //! Print an array
void void print(std::ostream &os, const std::string &name = "A",
print( std::ostream &os, const std::string &name = "A", const std::string &prefix = "" ) const; const std::string &prefix = "") const;
//! Transpose an array //! Transpose an array
Array reverseDim() const; Array reverseDim() const;
@ -728,7 +689,7 @@ public: // Math operations
* shiftDim shifts the dimensions to the right and pads with singletons. * shiftDim shifts the dimensions to the right and pads with singletons.
* @param N Desired shift * @param N Desired shift
*/ */
Array shiftDim( int N ) const; Array shiftDim(int N) const;
/*! /*!
* @brief Permute array dimensions * @brief Permute array dimensions
@ -738,24 +699,25 @@ public: // Math operations
* needed to access any particular element are rearranged as specified. * needed to access any particular element are rearranged as specified.
* @param index Desired order of the subscripts * @param index Desired order of the subscripts
*/ */
Array permute( const std::vector<uint8_t> &index ) const; Array permute(const std::vector<uint8_t> &index) const;
//! Replicate an array a given number of times in each direction //! Replicate an array a given number of times in each direction
Array repmat( const std::vector<size_t> &N ) const; Array repmat(const std::vector<size_t> &N) const;
//! Coarsen an array using the given filter //! Coarsen an array using the given filter
Array coarsen( const Array &filter ) const; Array coarsen(const Array &filter) const;
//! Coarsen an array using the given filter //! Coarsen an array using the given filter
Array coarsen( const std::vector<size_t> &ratio, Array coarsen(const std::vector<size_t> &ratio,
std::function<TYPE( const Array & )> filter ) const; std::function<TYPE(const Array &)> filter) const;
/*! /*!
* Perform a element-wise operation y = f(x) * Perform a element-wise operation y = f(x)
* @param[in] fun The function operation * @param[in] fun The function operation
* @param[in] x The input array * @param[in] x The input array
*/ */
static Array transform( std::function<TYPE( const TYPE & )> fun, const Array &x ); static Array transform(std::function<TYPE(const TYPE &)> fun,
const Array &x);
/*! /*!
* Perform a element-wise operation z = f(x,y) * Perform a element-wise operation z = f(x,y)
@ -763,9 +725,8 @@ public: // Math operations
* @param[in] x The first array * @param[in] x The first array
* @param[in] y The second array * @param[in] y The second array
*/ */
static Array transform( std::function<TYPE( const TYPE &, const TYPE & )> fun, static Array transform(std::function<TYPE(const TYPE &, const TYPE &)> fun,
const Array &x, const Array &x, const Array &y);
const Array &y );
/*! /*!
* axpby operation: this = alpha*x + beta*this * axpby operation: this = alpha*x + beta*this
@ -773,19 +734,21 @@ public: // Math operations
* @param[in] x x * @param[in] x x
* @param[in] beta beta * @param[in] beta beta
*/ */
void axpby( const TYPE &alpha, const Array &x, const TYPE &beta ); void axpby(const TYPE &alpha, const Array &x, const TYPE &beta);
/*! /*!
* Linear interpolation * Linear interpolation
* @param[in] x Position as a decimal index * @param[in] x Position as a decimal index
*/ */
inline TYPE interp( const std::vector<double> &x ) const { return interp( x.data() ); } inline TYPE interp(const std::vector<double> &x) const {
return interp(x.data());
}
/*! /*!
* Linear interpolation * Linear interpolation
* @param[in] x Position as a decimal index * @param[in] x Position as a decimal index
*/ */
TYPE interp( const double *x ) const; TYPE interp(const double *x) const;
/** /**
* \fn equals (Array & const rhs, TYPE tol ) * \fn equals (Array & const rhs, TYPE tol )
@ -794,7 +757,7 @@ public: // Math operations
* \param[in] tol Tolerance of comparison * \param[in] tol Tolerance of comparison
* \return True iff \f$||\mathit{rhs} - x||_\infty < \mathit{tol}\f$ * \return True iff \f$||\mathit{rhs} - x||_\infty < \mathit{tol}\f$
*/ */
bool equals( const Array &rhs, TYPE tol = 0.000001 ) const; bool equals(const Array &rhs, TYPE tol = 0.000001) const;
private: private:
bool d_isCopyable; // Can the array be copied bool d_isCopyable; // Can the array be copied
@ -802,115 +765,106 @@ private:
ArraySize d_size; // Size of each dimension ArraySize d_size; // Size of each dimension
TYPE *d_data; // Raw pointer to data in array TYPE *d_data; // Raw pointer to data in array
std::shared_ptr<TYPE> d_ptr; // Shared pointer to data in array std::shared_ptr<TYPE> d_ptr; // Shared pointer to data in array
void allocate( const ArraySize &N ); void allocate(const ArraySize &N);
private: private:
inline void checkSubsetIndex( const std::vector<Range<size_t>> &range ) const; inline void checkSubsetIndex(const std::vector<Range<size_t>> &range) const;
inline std::vector<Range<size_t>> convert( const std::vector<size_t> &index ) const; inline std::vector<Range<size_t>>
static inline void getSubsetArrays( const std::vector<Range<size_t>> &range, convert(const std::vector<size_t> &index) const;
std::array<size_t, 5> &first, static inline void getSubsetArrays(const std::vector<Range<size_t>> &range,
std::array<size_t, 5> &last, std::array<size_t, 5> &first,
std::array<size_t, 5> &inc, std::array<size_t, 5> &last,
std::array<size_t, 5> &N ); std::array<size_t, 5> &inc,
std::array<size_t, 5> &N);
}; };
/******************************************************** /********************************************************
* ostream operator * * ostream operator *
********************************************************/ ********************************************************/
inline std::ostream &operator<<( std::ostream &out, const ArraySize &s ) inline std::ostream &operator<<(std::ostream &out, const ArraySize &s) {
{
out << "[" << s[0]; out << "[" << s[0];
for ( size_t i = 1; i < s.ndim(); i++ ) for (size_t i = 1; i < s.ndim(); i++)
out << "," << s[i]; out << "," << s[i];
out << "]"; out << "]";
return out; return out;
} }
/******************************************************** /********************************************************
* Math operations * * Math operations *
********************************************************/ ********************************************************/
template<class TYPE, class FUN, class Allocator> template <class TYPE, class FUN, class Allocator>
inline Array<TYPE, FUN, Allocator> operator+( inline Array<TYPE, FUN, Allocator>
const Array<TYPE, FUN, Allocator> &a, const Array<TYPE, FUN, Allocator> &b ) operator+(const Array<TYPE, FUN, Allocator> &a,
{ const Array<TYPE, FUN, Allocator> &b) {
Array<TYPE, FUN, Allocator> c; Array<TYPE, FUN, Allocator> c;
const auto &op = []( const TYPE &a, const TYPE &b ) { return a + b; }; const auto &op = [](const TYPE &a, const TYPE &b) { return a + b; };
FUN::transform( op, a, b, c ); FUN::transform(op, a, b, c);
return c; return c;
} }
template<class TYPE, class FUN, class Allocator> template <class TYPE, class FUN, class Allocator>
inline Array<TYPE, FUN, Allocator> operator-( inline Array<TYPE, FUN, Allocator>
const Array<TYPE, FUN, Allocator> &a, const Array<TYPE, FUN, Allocator> &b ) operator-(const Array<TYPE, FUN, Allocator> &a,
{ const Array<TYPE, FUN, Allocator> &b) {
Array<TYPE, FUN, Allocator> c; Array<TYPE, FUN, Allocator> c;
const auto &op = []( const TYPE &a, const TYPE &b ) { return a - b; }; const auto &op = [](const TYPE &a, const TYPE &b) { return a - b; };
FUN::transform( op, a, b, c ); FUN::transform(op, a, b, c);
return c; return c;
} }
template<class TYPE, class FUN, class Allocator> template <class TYPE, class FUN, class Allocator>
inline Array<TYPE, FUN, Allocator> operator*( inline Array<TYPE, FUN, Allocator>
const Array<TYPE, FUN, Allocator> &a, const Array<TYPE, FUN, Allocator> &b ) operator*(const Array<TYPE, FUN, Allocator> &a,
{ const Array<TYPE, FUN, Allocator> &b) {
Array<TYPE, FUN, Allocator> c; Array<TYPE, FUN, Allocator> c;
FUN::multiply( a, b, c ); FUN::multiply(a, b, c);
return c; return c;
} }
template<class TYPE, class FUN, class Allocator> template <class TYPE, class FUN, class Allocator>
inline Array<TYPE, FUN, Allocator> operator*( inline Array<TYPE, FUN, Allocator>
const Array<TYPE, FUN, Allocator> &a, const std::vector<TYPE> &b ) operator*(const Array<TYPE, FUN, Allocator> &a, const std::vector<TYPE> &b) {
{
Array<TYPE, FUN, Allocator> b2, c; Array<TYPE, FUN, Allocator> b2, c;
b2.viewRaw( { b.size() }, const_cast<TYPE *>( b.data() ) ); b2.viewRaw({b.size()}, const_cast<TYPE *>(b.data()));
FUN::multiply( a, b2, c ); FUN::multiply(a, b2, c);
return c; return c;
} }
template<class TYPE, class FUN, class Allocator> template <class TYPE, class FUN, class Allocator>
inline Array<TYPE, FUN, Allocator> operator*( const TYPE &a, inline Array<TYPE, FUN, Allocator>
const Array<TYPE, FUN, Allocator> &b ) operator*(const TYPE &a, const Array<TYPE, FUN, Allocator> &b) {
{
auto c = b; auto c = b;
c.scale( a ); c.scale(a);
return c; return c;
} }
template<class TYPE, class FUN, class Allocator> template <class TYPE, class FUN, class Allocator>
inline Array<TYPE, FUN, Allocator> operator*( const Array<TYPE, FUN, Allocator> &a, inline Array<TYPE, FUN, Allocator>
const TYPE &b ) operator*(const Array<TYPE, FUN, Allocator> &a, const TYPE &b) {
{
auto c = a; auto c = a;
c.scale( b ); c.scale(b);
return c; return c;
} }
/******************************************************** /********************************************************
* Copy array * * Copy array *
********************************************************/ ********************************************************/
template<class TYPE, class FUN, class Allocator> template <class TYPE, class FUN, class Allocator>
template<class TYPE2> template <class TYPE2>
inline void Array<TYPE, FUN, Allocator>::copy( const TYPE2 *data ) inline void Array<TYPE, FUN, Allocator>::copy(const TYPE2 *data) {
{ if (std::is_same<TYPE, TYPE2>::value) {
if ( std::is_same<TYPE, TYPE2>::value ) { std::copy(data, data + d_size.length(), d_data);
std::copy( data, data + d_size.length(), d_data );
} else { } else {
for ( size_t i = 0; i < d_size.length(); i++ ) for (size_t i = 0; i < d_size.length(); i++)
d_data[i] = static_cast<TYPE>( data[i] ); d_data[i] = static_cast<TYPE>(data[i]);
} }
} }
template<class TYPE, class FUN, class Allocator> template <class TYPE, class FUN, class Allocator>
template<class TYPE2> template <class TYPE2>
inline void Array<TYPE, FUN, Allocator>::copyTo( TYPE2 *data ) const inline void Array<TYPE, FUN, Allocator>::copyTo(TYPE2 *data) const {
{ if (std::is_same<TYPE, TYPE2>::value) {
if ( std::is_same<TYPE, TYPE2>::value ) { std::copy(d_data, d_data + d_size.length(), data);
std::copy( d_data, d_data + d_size.length(), data );
} else { } else {
for ( size_t i = 0; i < d_size.length(); i++ ) for (size_t i = 0; i < d_size.length(); i++)
data[i] = static_cast<TYPE2>( d_data[i] ); data[i] = static_cast<TYPE2>(d_data[i]);
} }
} }
/******************************************************** /********************************************************
* Convience typedefs * * Convience typedefs *
* Copy array * * Copy array *
@ -918,5 +872,4 @@ inline void Array<TYPE, FUN, Allocator>::copyTo( TYPE2 *data ) const
typedef Array<double> DoubleArray; typedef Array<double> DoubleArray;
typedef Array<int> IntArray; typedef Array<int> IntArray;
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -11,47 +11,41 @@
#include <initializer_list> #include <initializer_list>
#include <vector> #include <vector>
#if defined(__CUDA_ARCH__)
#if defined( __CUDA_ARCH__ )
#include <cuda.h> #include <cuda.h>
#define HOST_DEVICE __host__ __device__ #define HOST_DEVICE __host__ __device__
#else #else
#define HOST_DEVICE #define HOST_DEVICE
#endif #endif
#if defined( USING_GCC ) || defined( USING_CLANG ) #if defined(USING_GCC) || defined(USING_CLANG)
#define ARRAY_ATTRIBUTE HOST_DEVICE __attribute__( ( always_inline ) ) #define ARRAY_ATTRIBUTE HOST_DEVICE __attribute__((always_inline))
#else #else
#define ARRAY_ATTRIBUTE HOST_DEVICE #define ARRAY_ATTRIBUTE HOST_DEVICE
#endif #endif
#if (defined(DEBUG) || defined(_DEBUG)) && !defined(NDEBUG)
#if ( defined( DEBUG ) || defined( _DEBUG ) ) && !defined( NDEBUG ) #define CHECK_ARRAY_LENGTH(i, length) \
#define CHECK_ARRAY_LENGTH( i, length ) \ do { \
do { \ if (i >= length) \
if ( i >= length ) \ throw std::out_of_range("Index exceeds array bounds"); \
throw std::out_of_range( "Index exceeds array bounds" ); \ } while (0)
} while ( 0 )
#else #else
#define CHECK_ARRAY_LENGTH( i, length ) \ #define CHECK_ARRAY_LENGTH(i, length) \
do { \ do { \
} while ( 0 ) } while (0)
#endif #endif
// Forward declerations // Forward declerations
class FunctionTable; class FunctionTable;
template<class TYPE, class FUN = FunctionTable, class Allocator = std::allocator<TYPE>> template <class TYPE, class FUN = FunctionTable,
class Allocator = std::allocator<TYPE>>
class Array; class Array;
//! Simple range class //! Simple range class
template<class TYPE = size_t> template <class TYPE = size_t> class Range final {
class Range final
{
public: public:
//! Empty constructor //! Empty constructor
Range() : i( 0 ), j( -1 ), k( 1 ) {} Range() : i(0), j(-1), k(1) {}
/*! /*!
* Create a range i:k:j (or i:j) * Create a range i:k:j (or i:j)
@ -59,26 +53,23 @@ public:
* @param j_ Ending value * @param j_ Ending value
* @param k_ Increment value * @param k_ Increment value
*/ */
Range( const TYPE &i_, const TYPE &j_, const TYPE &k_ = 1 ) Range(const TYPE &i_, const TYPE &j_, const TYPE &k_ = 1)
: i( i_ ), j( j_ ), k( k_ ) : i(i_), j(j_), k(k_) {}
{
}
//! Get the number of values in the range //! Get the number of values in the range
size_t size() const size_t size() const {
{ if (std::is_integral<TYPE>::value) {
if ( std::is_integral<TYPE>::value ) { return (static_cast<int64_t>(j) - static_cast<int64_t>(i)) /
return ( static_cast<int64_t>( j ) - static_cast<int64_t>( i ) ) / static_cast<int64_t>(k);
static_cast<int64_t>( k ); } else if (std::is_floating_point<TYPE>::value) {
} else if ( std::is_floating_point<TYPE>::value ) { double tmp = static_cast<double>((j - i)) / static_cast<double>(k);
double tmp = static_cast<double>( ( j - i ) ) / static_cast<double>( k ); return static_cast<size_t>(floor(tmp + 1e-12) + 1);
return static_cast<size_t>( floor( tmp + 1e-12 ) + 1 ); } else if (std::is_same<TYPE, std::complex<float>>::value ||
} else if ( std::is_same<TYPE, std::complex<float>>::value || std::is_same<TYPE, std::complex<double>>::value) {
std::is_same<TYPE, std::complex<double>>::value ) { double tmp = std::real((j - i) / (k));
double tmp = std::real( ( j - i ) / ( k ) ); return static_cast<size_t>(floor(tmp + 1e-12) + 1);
return static_cast<size_t>( floor( tmp + 1e-12 ) + 1 );
} else { } else {
ERROR( "Unsupported type for range" ); ERROR("Unsupported type for range");
} }
} }
@ -86,29 +77,25 @@ public:
TYPE i, j, k; TYPE i, j, k;
}; };
//! Simple class to store the array dimensions //! Simple class to store the array dimensions
class ArraySize final class ArraySize final {
{
public: public:
//! Empty constructor //! Empty constructor
ArraySize() : d_ndim( 1 ), d_length( 0 ), d_N{ 0, 1, 1, 1, 1 } {} ArraySize() : d_ndim(1), d_length(0), d_N{0, 1, 1, 1, 1} {}
/*! /*!
* Create the vector size * Create the vector size
* @param N1 Number of elements in the first dimension * @param N1 Number of elements in the first dimension
*/ */
ArraySize( size_t N1 ) : d_ndim( 1 ), d_length( N1 ), d_N{ N1, 1, 1, 1, 1 } {} ArraySize(size_t N1) : d_ndim(1), d_length(N1), d_N{N1, 1, 1, 1, 1} {}
/*! /*!
* Create the vector size * Create the vector size
* @param N1 Number of elements in the first dimension * @param N1 Number of elements in the first dimension
* @param N2 Number of elements in the second dimension * @param N2 Number of elements in the second dimension
*/ */
ArraySize( size_t N1, size_t N2 ) ArraySize(size_t N1, size_t N2)
: d_ndim( 2 ), d_length( N1 * N2 ), d_N{ N1, N2, 1, 1, 1 } : d_ndim(2), d_length(N1 * N2), d_N{N1, N2, 1, 1, 1} {}
{
}
/*! /*!
* Create the vector size * Create the vector size
@ -116,10 +103,8 @@ public:
* @param N2 Number of elements in the second dimension * @param N2 Number of elements in the second dimension
* @param N3 Number of elements in the third dimension * @param N3 Number of elements in the third dimension
*/ */
ArraySize( size_t N1, size_t N2, size_t N3 ) ArraySize(size_t N1, size_t N2, size_t N3)
: d_ndim( 3 ), d_length( N1 * N2 * N3 ), d_N{ N1, N2, N3, 1, 1 } : d_ndim(3), d_length(N1 * N2 * N3), d_N{N1, N2, N3, 1, 1} {}
{
}
/*! /*!
* Create the vector size * Create the vector size
@ -128,10 +113,8 @@ public:
* @param N3 Number of elements in the third dimension * @param N3 Number of elements in the third dimension
* @param N4 Number of elements in the fourth dimension * @param N4 Number of elements in the fourth dimension
*/ */
ArraySize( size_t N1, size_t N2, size_t N3, size_t N4 ) ArraySize(size_t N1, size_t N2, size_t N3, size_t N4)
: d_ndim( 4 ), d_length( N1 * N2 * N3 * N4 ), d_N{ N1, N2, N3, N4, 1 } : d_ndim(4), d_length(N1 * N2 * N3 * N4), d_N{N1, N2, N3, N4, 1} {}
{
}
/*! /*!
* Create the vector size * Create the vector size
@ -141,9 +124,8 @@ public:
* @param N4 Number of elements in the fourth dimension * @param N4 Number of elements in the fourth dimension
* @param N5 Number of elements in the fifth dimension * @param N5 Number of elements in the fifth dimension
*/ */
ArraySize( size_t N1, size_t N2, size_t N3, size_t N4, size_t N5 ) ArraySize(size_t N1, size_t N2, size_t N3, size_t N4, size_t N5)
: d_ndim( 5 ), d_length( N1 * N2 * N3 * N4 * N5 ), d_N{ N1, N2, N3, N4, N5 } : d_ndim(5), d_length(N1 * N2 * N3 * N4 * N5), d_N{N1, N2, N3, N4, N5} {
{
} }
/*! /*!
@ -151,40 +133,37 @@ public:
* @param N Size of the array * @param N Size of the array
* @param ndim Number of dimensions * @param ndim Number of dimensions
*/ */
ArraySize( std::initializer_list<size_t> N, int ndim = -1 ) ArraySize(std::initializer_list<size_t> N, int ndim = -1)
: d_ndim( N.size() ), d_length( 0 ), d_N{ 0, 1, 1, 1, 1 } : d_ndim(N.size()), d_length(0), d_N{0, 1, 1, 1, 1} {
{ if (ndim >= 0)
if ( ndim >= 0 )
d_ndim = ndim; d_ndim = ndim;
if ( d_ndim > 5 ) if (d_ndim > 5)
throw std::out_of_range( "Maximum number of dimensions exceeded" ); throw std::out_of_range("Maximum number of dimensions exceeded");
auto it = N.begin(); auto it = N.begin();
for ( size_t i = 0; i < d_ndim; i++, ++it ) for (size_t i = 0; i < d_ndim; i++, ++it)
d_N[i] = *it; d_N[i] = *it;
d_length = 1; d_length = 1;
for ( unsigned long i : d_N ) for (unsigned long i : d_N)
d_length *= i; d_length *= i;
if ( d_ndim == 0 ) if (d_ndim == 0)
d_length = 0; d_length = 0;
} }
/*! /*!
* Create from raw pointer * Create from raw pointer
* @param ndim Number of dimensions * @param ndim Number of dimensions
* @param dims Dimensions * @param dims Dimensions
*/ */
ArraySize( size_t ndim, const size_t *dims ) ArraySize(size_t ndim, const size_t *dims)
: d_ndim( ndim ), d_length( 0 ), d_N{ 0, 1, 1, 1, 1 } : d_ndim(ndim), d_length(0), d_N{0, 1, 1, 1, 1} {
{ if (d_ndim > 5)
if ( d_ndim > 5 ) throw std::out_of_range("Maximum number of dimensions exceeded");
throw std::out_of_range( "Maximum number of dimensions exceeded" ); for (size_t i = 0; i < ndim; i++)
for ( size_t i = 0; i < ndim; i++ )
d_N[i] = dims[i]; d_N[i] = dims[i];
d_length = 1; d_length = 1;
for ( unsigned long i : d_N ) for (unsigned long i : d_N)
d_length *= i; d_length *= i;
if ( d_ndim == 0 ) if (d_ndim == 0)
d_length = 0; d_length = 0;
} }
@ -192,28 +171,27 @@ public:
* Create from std::array * Create from std::array
* @param N Size of the array * @param N Size of the array
*/ */
template<std::size_t NDIM> template <std::size_t NDIM>
ArraySize( const std::array<size_t, NDIM> &N ) : ArraySize( NDIM, N.data() ) ArraySize(const std::array<size_t, NDIM> &N) : ArraySize(NDIM, N.data()) {}
{
}
/*! /*!
* Create from std::vector * Create from std::vector
* @param N Size of the array * @param N Size of the array
*/ */
inline ArraySize( const std::vector<size_t> &N ) : ArraySize( N.size(), N.data() ) {} inline ArraySize(const std::vector<size_t> &N)
: ArraySize(N.size(), N.data()) {}
// Copy/assignment constructors // Copy/assignment constructors
ArraySize( ArraySize &&rhs ) = default; ArraySize(ArraySize &&rhs) = default;
ArraySize( const ArraySize &rhs ) = default; ArraySize(const ArraySize &rhs) = default;
ArraySize &operator=( ArraySize &&rhs ) = default; ArraySize &operator=(ArraySize &&rhs) = default;
ArraySize &operator=( const ArraySize &rhs ) = default; ArraySize &operator=(const ArraySize &rhs) = default;
/*! /*!
* Access the ith dimension * Access the ith dimension
* @param i Index to access * @param i Index to access
*/ */
ARRAY_ATTRIBUTE size_t operator[]( size_t i ) const { return d_N[i]; } ARRAY_ATTRIBUTE size_t operator[](size_t i) const { return d_N[i]; }
//! Return the number of dimensions //! Return the number of dimensions
ARRAY_ATTRIBUTE uint8_t ndim() const { return d_ndim; } ARRAY_ATTRIBUTE uint8_t ndim() const { return d_ndim; }
@ -225,13 +203,12 @@ public:
ARRAY_ATTRIBUTE size_t length() const { return d_length; } ARRAY_ATTRIBUTE size_t length() const { return d_length; }
//! Resize the dimension //! Resize the dimension
void resize( uint8_t dim, size_t N ) void resize(uint8_t dim, size_t N) {
{ if (dim >= d_ndim)
if ( dim >= d_ndim ) throw std::out_of_range("Invalid dimension");
throw std::out_of_range( "Invalid dimension" );
d_N[dim] = N; d_N[dim] = N;
d_length = 1; d_length = 1;
for ( unsigned long i : d_N ) for (unsigned long i : d_N)
d_length *= i; d_length *= i;
} }
@ -240,16 +217,15 @@ public:
* max of ndim and the largest dim>1. * max of ndim and the largest dim>1.
* @param ndim Desired number of dimensions * @param ndim Desired number of dimensions
*/ */
void setNdim( uint8_t ndim ) { d_ndim = std::max( ndim, d_ndim ); } void setNdim(uint8_t ndim) { d_ndim = std::max(ndim, d_ndim); }
/*! /*!
* Remove singleton dimensions * Remove singleton dimensions
*/ */
void squeeze() void squeeze() {
{
d_ndim = 0; d_ndim = 0;
for ( uint8_t i = 0; i < maxDim(); i++ ) { for (uint8_t i = 0; i < maxDim(); i++) {
if ( d_N[i] != 1 ) if (d_N[i] != 1)
d_N[d_ndim++] = d_N[i]; d_N[d_ndim++] = d_N[i];
} }
} }
@ -261,71 +237,65 @@ public:
const size_t *end() const { return d_N + d_ndim; } const size_t *end() const { return d_N + d_ndim; }
// Check if two array sizes are equal // Check if two array sizes are equal
ARRAY_ATTRIBUTE bool operator==( const ArraySize &rhs ) const ARRAY_ATTRIBUTE bool operator==(const ArraySize &rhs) const {
{ return d_ndim == rhs.d_ndim && memcmp(d_N, rhs.d_N, sizeof(d_N)) == 0;
return d_ndim == rhs.d_ndim && memcmp( d_N, rhs.d_N, sizeof( d_N ) ) == 0;
} }
// Check if two array sizes are equal (ignoring the dimension) // Check if two array sizes are equal (ignoring the dimension)
ARRAY_ATTRIBUTE bool approxEqual( const ArraySize &rhs ) const ARRAY_ATTRIBUTE bool approxEqual(const ArraySize &rhs) const {
{ return (length() == 0 && rhs.length() == 0) ||
return ( length() == 0 && rhs.length() == 0 ) || memcmp( d_N, rhs.d_N, sizeof( d_N ) ) == 0; memcmp(d_N, rhs.d_N, sizeof(d_N)) == 0;
} }
//! Check if two matrices are not equal //! Check if two matrices are not equal
ARRAY_ATTRIBUTE bool operator!=( const ArraySize &rhs ) const ARRAY_ATTRIBUTE bool operator!=(const ArraySize &rhs) const {
{ return d_ndim != rhs.d_ndim || memcmp(d_N, rhs.d_N, sizeof(d_N)) != 0;
return d_ndim != rhs.d_ndim || memcmp( d_N, rhs.d_N, sizeof( d_N ) ) != 0;
} }
//! Maximum supported dimension //! Maximum supported dimension
ARRAY_ATTRIBUTE static uint8_t maxDim() { return 5; } ARRAY_ATTRIBUTE static uint8_t maxDim() { return 5; }
//! Get the index //! Get the index
ARRAY_ATTRIBUTE size_t index( size_t i ) const ARRAY_ATTRIBUTE size_t index(size_t i) const {
{ CHECK_ARRAY_LENGTH(i, d_length);
CHECK_ARRAY_LENGTH( i, d_length );
return i; return i;
} }
//! Get the index //! Get the index
ARRAY_ATTRIBUTE size_t index( size_t i1, size_t i2 ) const ARRAY_ATTRIBUTE size_t index(size_t i1, size_t i2) const {
{
size_t index = i1 + i2 * d_N[0]; size_t index = i1 + i2 * d_N[0];
CHECK_ARRAY_LENGTH( index, d_length ); CHECK_ARRAY_LENGTH(index, d_length);
return index; return index;
} }
//! Get the index //! Get the index
ARRAY_ATTRIBUTE size_t index( size_t i1, size_t i2, size_t i3 ) const ARRAY_ATTRIBUTE size_t index(size_t i1, size_t i2, size_t i3) const {
{ size_t index = i1 + d_N[0] * (i2 + d_N[1] * i3);
size_t index = i1 + d_N[0] * ( i2 + d_N[1] * i3 ); CHECK_ARRAY_LENGTH(index, d_length);
CHECK_ARRAY_LENGTH( index, d_length );
return index; return index;
} }
//! Get the index //! Get the index
ARRAY_ATTRIBUTE size_t index( size_t i1, size_t i2, size_t i3, size_t i4 ) const ARRAY_ATTRIBUTE size_t index(size_t i1, size_t i2, size_t i3,
{ size_t i4) const {
size_t index = i1 + d_N[0] * ( i2 + d_N[1] * ( i3 + d_N[2] * i4 ) ); size_t index = i1 + d_N[0] * (i2 + d_N[1] * (i3 + d_N[2] * i4));
CHECK_ARRAY_LENGTH( index, d_length ); CHECK_ARRAY_LENGTH(index, d_length);
return index; return index;
} }
//! Get the index //! Get the index
ARRAY_ATTRIBUTE size_t ARRAY_ATTRIBUTE size_t index(size_t i1, size_t i2, size_t i3, size_t i4,
index( size_t i1, size_t i2, size_t i3, size_t i4, size_t i5 ) const size_t i5) const {
{ size_t index =
size_t index = i1 + d_N[0] * ( i2 + d_N[1] * ( i3 + d_N[2] * ( i4 + d_N[3] * i5 ) ) ); i1 + d_N[0] * (i2 + d_N[1] * (i3 + d_N[2] * (i4 + d_N[3] * i5)));
CHECK_ARRAY_LENGTH( index, d_length ); CHECK_ARRAY_LENGTH(index, d_length);
return index; return index;
} }
//! Get the index //! Get the index
size_t index( const std::array<size_t, 5> &i ) const size_t index(const std::array<size_t, 5> &i) const {
{
size_t j = 0; size_t j = 0;
for ( size_t m = 0, N = 1; m < 5; m++ ) { for (size_t m = 0, N = 1; m < 5; m++) {
j += i[m] * N; j += i[m] * N;
N *= d_N[m]; N *= d_N[m];
} }
@ -333,12 +303,11 @@ public:
} }
//! Get the index //! Get the index
size_t index( std::initializer_list<size_t> i ) const size_t index(std::initializer_list<size_t> i) const {
{
size_t N = 1; size_t N = 1;
size_t j = 0; size_t j = 0;
size_t m = 0; size_t m = 0;
for ( size_t k : i ) { for (size_t k : i) {
j += k * N; j += k * N;
N *= d_N[m++]; N *= d_N[m++];
} }
@ -346,33 +315,31 @@ public:
} }
//! Convert the index to ijk values //! Convert the index to ijk values
std::array<size_t, 5> ijk( size_t index ) const std::array<size_t, 5> ijk(size_t index) const {
{ CHECK_ARRAY_LENGTH(index, d_length);
CHECK_ARRAY_LENGTH( index, d_length );
size_t i0 = index % d_N[0]; size_t i0 = index % d_N[0];
index = index / d_N[0]; index = index / d_N[0];
size_t i1 = index % d_N[1]; size_t i1 = index % d_N[1];
index = index / d_N[1]; index = index / d_N[1];
size_t i2 = index % d_N[2]; size_t i2 = index % d_N[2];
index = index / d_N[2]; index = index / d_N[2];
size_t i3 = index % d_N[3]; size_t i3 = index % d_N[3];
index = index / d_N[3]; index = index / d_N[3];
return { i0, i1, i2, i3, index }; return {i0, i1, i2, i3, index};
} }
//! Convert the index to ijk values //! Convert the index to ijk values
void ijk( size_t index, size_t *x ) const void ijk(size_t index, size_t *x) const {
{ CHECK_ARRAY_LENGTH(index, d_length);
CHECK_ARRAY_LENGTH( index, d_length ); x[0] = index % d_N[0];
x[0] = index % d_N[0];
index = index / d_N[0]; index = index / d_N[0];
x[1] = index % d_N[1]; x[1] = index % d_N[1];
index = index / d_N[1]; index = index / d_N[1];
x[2] = index % d_N[2]; x[2] = index % d_N[2];
index = index / d_N[2]; index = index / d_N[2];
x[3] = index % d_N[3]; x[3] = index % d_N[3];
index = index / d_N[3]; index = index / d_N[3];
x[4] = index; x[4] = index;
} }
private: private:
@ -381,51 +348,42 @@ private:
size_t d_N[5]; size_t d_N[5];
}; };
// Function to concatenate dimensions of two array sizes // Function to concatenate dimensions of two array sizes
inline ArraySize cat( const ArraySize &x, const ArraySize &y ) inline ArraySize cat(const ArraySize &x, const ArraySize &y) {
{ if (x.ndim() + y.ndim() > 5)
if ( x.ndim() + y.ndim() > 5 ) throw std::out_of_range("Maximum number of dimensions exceeded");
throw std::out_of_range( "Maximum number of dimensions exceeded" ); size_t N[5] = {0};
size_t N[5] = { 0 }; for (int i = 0; i < x.ndim(); i++)
for ( int i = 0; i < x.ndim(); i++ )
N[i] = x[i]; N[i] = x[i];
for ( int i = 0; i < y.ndim(); i++ ) for (int i = 0; i < y.ndim(); i++)
N[i + x.ndim()] = y[i]; N[i + x.ndim()] = y[i];
return ArraySize( x.ndim() + y.ndim(), N ); return ArraySize(x.ndim() + y.ndim(), N);
} }
// Operator overloads // Operator overloads
inline ArraySize operator*( size_t v, const ArraySize &x ) inline ArraySize operator*(size_t v, const ArraySize &x) {
{ size_t N[5] = {v * x[0], v * x[1], v * x[2], v * x[3], v * x[4]};
size_t N[5] = { v * x[0], v * x[1], v * x[2], v * x[3], v * x[4] }; return ArraySize(x.ndim(), N);
return ArraySize( x.ndim(), N );
} }
inline ArraySize operator*( const ArraySize &x, size_t v ) inline ArraySize operator*(const ArraySize &x, size_t v) {
{ size_t N[5] = {v * x[0], v * x[1], v * x[2], v * x[3], v * x[4]};
size_t N[5] = { v * x[0], v * x[1], v * x[2], v * x[3], v * x[4] }; return ArraySize(x.ndim(), N);
return ArraySize( x.ndim(), N );
} }
inline ArraySize operator-( const ArraySize &x, size_t v ) inline ArraySize operator-(const ArraySize &x, size_t v) {
{ size_t N[5] = {x[0] - v, x[1] - v, x[2] - v, x[3] - v, x[4] - v};
size_t N[5] = { x[0] - v, x[1] - v, x[2] - v, x[3] - v, x[4] - v }; return ArraySize(x.ndim(), N);
return ArraySize( x.ndim(), N );
} }
inline ArraySize operator+( const ArraySize &x, size_t v ) inline ArraySize operator+(const ArraySize &x, size_t v) {
{ size_t N[5] = {x[0] + v, x[1] + v, x[2] + v, x[3] + v, x[4] + v};
size_t N[5] = { x[0] + v, x[1] + v, x[2] + v, x[3] + v, x[4] + v }; return ArraySize(x.ndim(), N);
return ArraySize( x.ndim(), N );
} }
inline ArraySize operator+( size_t v, const ArraySize &x ) inline ArraySize operator+(size_t v, const ArraySize &x) {
{ size_t N[5] = {x[0] + v, x[1] + v, x[2] + v, x[3] + v, x[4] + v};
size_t N[5] = { x[0] + v, x[1] + v, x[2] + v, x[3] + v, x[4] + v }; return ArraySize(x.ndim(), N);
return ArraySize( x.ndim(), N );
} }
#if defined( USING_ICC ) #if defined(USING_ICC)
ENABLE_WARNINGS ENABLE_WARNINGS
#endif #endif
#endif #endif

View File

@ -16,100 +16,92 @@
*/ */
#include "common/Communication.h" #include "common/Communication.h"
/******************************************************** /********************************************************
* Structure to store the rank info * * Structure to store the rank info *
********************************************************/ ********************************************************/
int RankInfoStruct::getRankForBlock( int i, int j, int k ) const int RankInfoStruct::getRankForBlock(int i, int j, int k) const {
{ int i2 = (i + nx) % nx;
int i2 = (i+nx)%nx; int j2 = (j + ny) % ny;
int j2 = (j+ny)%ny; int k2 = (k + nz) % nz;
int k2 = (k+nz)%nz; return i2 + j2 * nx + k2 * nx * ny;
return i2 + j2*nx + k2*nx*ny;
} }
RankInfoStruct::RankInfoStruct() RankInfoStruct::RankInfoStruct() {
{
nx = 0; nx = 0;
ny = 0; ny = 0;
nz = 0; nz = 0;
ix = -1; ix = -1;
jy = -1; jy = -1;
kz = -1; kz = -1;
for (int i=-1; i<=1; i++) { for (int i = -1; i <= 1; i++) {
for (int j=-1; j<=1; j++) { for (int j = -1; j <= 1; j++) {
for (int k=-1; k<=1; k++) { for (int k = -1; k <= 1; k++) {
rank[i+1][j+1][k+1] = -1; rank[i + 1][j + 1][k + 1] = -1;
} }
} }
} }
} }
RankInfoStruct::RankInfoStruct( int rank0, int nprocx, int nprocy, int nprocz ) RankInfoStruct::RankInfoStruct(int rank0, int nprocx, int nprocy, int nprocz) {
{ memset(this, 0, sizeof(RankInfoStruct));
memset(this,0,sizeof(RankInfoStruct));
nx = nprocx; nx = nprocx;
ny = nprocy; ny = nprocy;
nz = nprocz; nz = nprocz;
if ( rank0 >= nprocx * nprocy * nprocz ) { if (rank0 >= nprocx * nprocy * nprocz) {
ix = -1; ix = -1;
jy = -1; jy = -1;
kz = -1; kz = -1;
for (int i=-1; i<=1; i++) { for (int i = -1; i <= 1; i++) {
for (int j=-1; j<=1; j++) { for (int j = -1; j <= 1; j++) {
for (int k=-1; k<=1; k++) { for (int k = -1; k <= 1; k++) {
rank[i+1][j+1][k+1] = -1; rank[i + 1][j + 1][k + 1] = -1;
} }
} }
} }
} else { } else {
ix = rank0%nprocx; ix = rank0 % nprocx;
jy = (rank0/nprocx)%nprocy; jy = (rank0 / nprocx) % nprocy;
kz = rank0/(nprocx*nprocy); kz = rank0 / (nprocx * nprocy);
for (int i=-1; i<=1; i++) { for (int i = -1; i <= 1; i++) {
for (int j=-1; j<=1; j++) { for (int j = -1; j <= 1; j++) {
for (int k=-1; k<=1; k++) { for (int k = -1; k <= 1; k++) {
rank[i+1][j+1][k+1] = getRankForBlock(ix+i,jy+j,kz+k); rank[i + 1][j + 1][k + 1] =
getRankForBlock(ix + i, jy + j, kz + k);
} }
} }
} }
ASSERT(rank[1][1][1]==rank0); ASSERT(rank[1][1][1] == rank0);
} }
} }
/******************************************************** /********************************************************
* Deprecated functions * * Deprecated functions *
********************************************************/ ********************************************************/
void InitializeRanks( const int rank, const int nprocx, const int nprocy, const int nprocz, void InitializeRanks(const int rank, const int nprocx, const int nprocy,
int& iproc, int& jproc, int& kproc, const int nprocz, int &iproc, int &jproc, int &kproc,
int& rank_x, int& rank_y, int& rank_z, int &rank_x, int &rank_y, int &rank_z, int &rank_X,
int& rank_X, int& rank_Y, int& rank_Z, int &rank_Y, int &rank_Z, int &rank_xy, int &rank_XY,
int& rank_xy, int& rank_XY, int& rank_xY, int& rank_Xy, int &rank_xY, int &rank_Xy, int &rank_xz, int &rank_XZ,
int& rank_xz, int& rank_XZ, int& rank_xZ, int& rank_Xz, int &rank_xZ, int &rank_Xz, int &rank_yz, int &rank_YZ,
int& rank_yz, int& rank_YZ, int& rank_yZ, int& rank_Yz ) int &rank_yZ, int &rank_Yz) {
{ const RankInfoStruct data(rank, nprocx, nprocy, nprocz);
const RankInfoStruct data(rank,nprocx,nprocy,nprocz); iproc = data.ix;
iproc = data.ix;
jproc = data.jy; jproc = data.jy;
kproc = data.kz; kproc = data.kz;
rank_X = data.rank[2][1][1]; rank_X = data.rank[2][1][1];
rank_x = data.rank[0][1][1]; rank_x = data.rank[0][1][1];
rank_Y = data.rank[1][2][1]; rank_Y = data.rank[1][2][1];
rank_y = data.rank[1][0][1]; rank_y = data.rank[1][0][1];
rank_Z = data.rank[1][1][2]; rank_Z = data.rank[1][1][2];
rank_z = data.rank[1][1][0]; rank_z = data.rank[1][1][0];
rank_XY = data.rank[2][2][1]; rank_XY = data.rank[2][2][1];
rank_xy = data.rank[0][0][1]; rank_xy = data.rank[0][0][1];
rank_Xy = data.rank[2][0][1]; rank_Xy = data.rank[2][0][1];
rank_xY = data.rank[0][2][1]; rank_xY = data.rank[0][2][1];
rank_XZ = data.rank[2][1][2]; rank_XZ = data.rank[2][1][2];
rank_xz = data.rank[0][1][0]; rank_xz = data.rank[0][1][0];
rank_Xz = data.rank[2][1][0]; rank_Xz = data.rank[2][1][0];
rank_xZ = data.rank[0][1][2]; rank_xZ = data.rank[0][1][2];
rank_YZ = data.rank[1][2][2]; rank_YZ = data.rank[1][2][2];
rank_yz = data.rank[1][0][0]; rank_yz = data.rank[1][0][0];
rank_Yz = data.rank[1][2][0]; rank_Yz = data.rank[1][2][0];
rank_yZ = data.rank[1][0][2]; rank_yZ = data.rank[1][0][2];
} }

View File

@ -32,38 +32,35 @@
using namespace std; using namespace std;
/*! /*!
* @brief Rank info structure * @brief Rank info structure
* @details Structure used to hold the ranks for the current process and it's neighbors * @details Structure used to hold the ranks for the current process and it's neighbors
*/ */
struct RankInfoStruct { struct RankInfoStruct {
int nx; //!< The number of processors in the x direction int nx; //!< The number of processors in the x direction
int ny; //!< The number of processors in the y direction int ny; //!< The number of processors in the y direction
int nz; //!< The number of processors in the z direction int nz; //!< The number of processors in the z direction
int ix; //!< The index of the current process in the x direction int ix; //!< The index of the current process in the x direction
int jy; //!< The index of the current process in the y direction int jy; //!< The index of the current process in the y direction
int kz; //!< The index of the current process in the z direction int kz; //!< The index of the current process in the z direction
int rank[3][3][3]; //!< The rank for the neighbor [i][j][k] int rank[3][3][3]; //!< The rank for the neighbor [i][j][k]
RankInfoStruct(); RankInfoStruct();
RankInfoStruct( int rank, int nprocx, int nprocy, int nprocz ); RankInfoStruct(int rank, int nprocx, int nprocy, int nprocz);
int getRankForBlock( int i, int j, int k ) const; int getRankForBlock(int i, int j, int k) const;
}; };
//! Redistribute domain data (dst may be smaller than the src) //! Redistribute domain data (dst may be smaller than the src)
template<class TYPE> template <class TYPE>
Array<TYPE> redistribute( const RankInfoStruct& src_rank, const Array<TYPE>& src_data, Array<TYPE>
const RankInfoStruct& dst_rank, std::array<int,3> dst_size, const Utilities::MPI& comm ); redistribute(const RankInfoStruct &src_rank, const Array<TYPE> &src_data,
const RankInfoStruct &dst_rank, std::array<int, 3> dst_size,
const Utilities::MPI &comm);
/*! /*!
* @brief Communicate halo * @brief Communicate halo
* @details Fill the halo cells in an array from the neighboring processes * @details Fill the halo cells in an array from the neighboring processes
*/ */
template<class TYPE> template <class TYPE> class fillHalo {
class fillHalo
{
public: public:
/*! /*!
* @brief Default constructor * @brief Default constructor
@ -76,37 +73,36 @@ public:
* @param[in] fill Fill {faces,edges,corners} * @param[in] fill Fill {faces,edges,corners}
* @param[in] periodic Periodic dimensions * @param[in] periodic Periodic dimensions
*/ */
fillHalo( const Utilities::MPI& comm, const RankInfoStruct& info, fillHalo(const Utilities::MPI &comm, const RankInfoStruct &info,
std::array<int,3> n, std::array<int,3> ng, int tag, int depth, std::array<int, 3> n, std::array<int, 3> ng, int tag, int depth,
std::array<bool,3> fill = {true,true,true}, std::array<bool, 3> fill = {true, true, true},
std::array<bool,3> periodic = {true,true,true} ); std::array<bool, 3> periodic = {true, true, true});
//! Destructor //! Destructor
~fillHalo( ); ~fillHalo();
fillHalo() = delete; fillHalo() = delete;
fillHalo(const fillHalo&) = delete; fillHalo(const fillHalo &) = delete;
fillHalo& operator=(const fillHalo&) = delete; fillHalo &operator=(const fillHalo &) = delete;
/*! /*!
* @brief Communicate the halos * @brief Communicate the halos
* @param[in] array The array on which we fill the halos * @param[in] array The array on which we fill the halos
*/ */
void fill( Array<TYPE>& array ); void fill(Array<TYPE> &array);
/*! /*!
* @brief Copy data from the src array to the dst array * @brief Copy data from the src array to the dst array
* @param[in] src The src array with or without halos * @param[in] src The src array with or without halos
* @param[in] dst The dst array with or without halos * @param[in] dst The dst array with or without halos
*/ */
template<class TYPE1, class TYPE2> template <class TYPE1, class TYPE2>
void copy( const Array<TYPE1>& src, Array<TYPE2>& dst ); void copy(const Array<TYPE1> &src, Array<TYPE2> &dst);
private: private:
Utilities::MPI comm; Utilities::MPI comm;
RankInfoStruct info; RankInfoStruct info;
std::array<int,3> n, ng; std::array<int, 3> n, ng;
int depth; int depth;
bool fill_pattern[3][3][3]; bool fill_pattern[3][3][3];
int tag[3][3][3]; int tag[3][3][3];
@ -114,266 +110,286 @@ private:
TYPE *mem; TYPE *mem;
TYPE *send[3][3][3], *recv[3][3][3]; TYPE *send[3][3][3], *recv[3][3][3];
MPI_Request send_req[3][3][3], recv_req[3][3][3]; MPI_Request send_req[3][3][3], recv_req[3][3][3];
void pack( const Array<TYPE>& array, int i, int j, int k, TYPE *buffer ); void pack(const Array<TYPE> &array, int i, int j, int k, TYPE *buffer);
void unpack( Array<TYPE>& array, int i, int j, int k, const TYPE *buffer ); void unpack(Array<TYPE> &array, int i, int j, int k, const TYPE *buffer);
}; };
//*************************************************************************************** //***************************************************************************************
inline void PackMeshData(const int *list, int count, double *sendbuf, double *data){ inline void PackMeshData(const int *list, int count, double *sendbuf,
// Fill in the phase ID values from neighboring processors double *data) {
// This packs up the values that need to be sent from one processor to another // Fill in the phase ID values from neighboring processors
int idx,n; // This packs up the values that need to be sent from one processor to another
for (idx=0; idx<count; idx++){ int idx, n;
n = list[idx]; for (idx = 0; idx < count; idx++) {
sendbuf[idx] = data[n]; n = list[idx];
} sendbuf[idx] = data[n];
}
} }
inline void UnpackMeshData(const int *list, int count, double *recvbuf, double *data){ inline void UnpackMeshData(const int *list, int count, double *recvbuf,
// Fill in the phase ID values from neighboring processors double *data) {
// This unpacks the values once they have been recieved from neighbors // Fill in the phase ID values from neighboring processors
int idx,n; // This unpacks the values once they have been recieved from neighbors
int idx, n;
for (idx=0; idx<count; idx++){ for (idx = 0; idx < count; idx++) {
n = list[idx]; n = list[idx];
data[n] = recvbuf[idx]; data[n] = recvbuf[idx];
} }
} }
// Initialize the ranks (this is deprecated, see RankInfoStruct) // Initialize the ranks (this is deprecated, see RankInfoStruct)
void InitializeRanks( const int rank, const int nprocx, const int nprocy, const int nprocz, void InitializeRanks(const int rank, const int nprocx, const int nprocy,
int& iproc, int& jproc, int& kproc, const int nprocz, int &iproc, int &jproc, int &kproc,
int& rank_x, int& rank_y, int& rank_z, int &rank_x, int &rank_y, int &rank_z, int &rank_X,
int& rank_X, int& rank_Y, int& rank_Z, int &rank_Y, int &rank_Z, int &rank_xy, int &rank_XY,
int& rank_xy, int& rank_XY, int& rank_xY, int& rank_Xy, int &rank_xY, int &rank_Xy, int &rank_xz, int &rank_XZ,
int& rank_xz, int& rank_XZ, int& rank_xZ, int& rank_Xz, int &rank_xZ, int &rank_Xz, int &rank_yz, int &rank_YZ,
int& rank_yz, int& rank_YZ, int& rank_yZ, int& rank_Yz ); int &rank_yZ, int &rank_Yz);
//*************************************************************************************** //***************************************************************************************
inline void CommunicateSendRecvCounts( const Utilities::MPI& comm, int sendtag, int recvtag, inline void CommunicateSendRecvCounts(
int rank_x, int rank_y, int rank_z, const Utilities::MPI &comm, int sendtag, int recvtag, int rank_x,
int rank_X, int rank_Y, int rank_Z, int rank_y, int rank_z, int rank_X, int rank_Y, int rank_Z, int rank_xy,
int rank_xy, int rank_XY, int rank_xY, int rank_Xy, int rank_XY, int rank_xY, int rank_Xy, int rank_xz, int rank_XZ,
int rank_xz, int rank_XZ, int rank_xZ, int rank_Xz, int rank_xZ, int rank_Xz, int rank_yz, int rank_YZ, int rank_yZ,
int rank_yz, int rank_YZ, int rank_yZ, int rank_Yz, int rank_Yz, int sendCount_x, int sendCount_y, int sendCount_z,
int sendCount_x, int sendCount_y, int sendCount_z, int sendCount_X, int sendCount_Y, int sendCount_Z, int sendCount_xy,
int sendCount_X, int sendCount_Y, int sendCount_Z, int sendCount_XY, int sendCount_xY, int sendCount_Xy, int sendCount_xz,
int sendCount_xy, int sendCount_XY, int sendCount_xY, int sendCount_Xy, int sendCount_XZ, int sendCount_xZ, int sendCount_Xz, int sendCount_yz,
int sendCount_xz, int sendCount_XZ, int sendCount_xZ, int sendCount_Xz, int sendCount_YZ, int sendCount_yZ, int sendCount_Yz, int &recvCount_x,
int sendCount_yz, int sendCount_YZ, int sendCount_yZ, int sendCount_Yz, int &recvCount_y, int &recvCount_z, int &recvCount_X, int &recvCount_Y,
int& recvCount_x, int& recvCount_y, int& recvCount_z, int &recvCount_Z, int &recvCount_xy, int &recvCount_XY, int &recvCount_xY,
int& recvCount_X, int& recvCount_Y, int& recvCount_Z, int &recvCount_Xy, int &recvCount_xz, int &recvCount_XZ, int &recvCount_xZ,
int& recvCount_xy, int& recvCount_XY, int& recvCount_xY, int& recvCount_Xy, int &recvCount_Xz, int &recvCount_yz, int &recvCount_YZ, int &recvCount_yZ,
int& recvCount_xz, int& recvCount_XZ, int& recvCount_xZ, int& recvCount_Xz, int &recvCount_Yz) {
int& recvCount_yz, int& recvCount_YZ, int& recvCount_yZ, int& recvCount_Yz ) MPI_Request req1[18], req2[18];
{ req1[0] = comm.Isend(&sendCount_x, 1, rank_x, sendtag + 0);
MPI_Request req1[18], req2[18]; req2[0] = comm.Irecv(&recvCount_X, 1, rank_X, recvtag + 0);
req1[0] = comm.Isend(&sendCount_x,1,rank_x,sendtag+0); req1[1] = comm.Isend(&sendCount_X, 1, rank_X, sendtag + 1);
req2[0] = comm.Irecv(&recvCount_X,1,rank_X,recvtag+0); req2[1] = comm.Irecv(&recvCount_x, 1, rank_x, recvtag + 1);
req1[1] = comm.Isend(&sendCount_X,1,rank_X,sendtag+1); req1[2] = comm.Isend(&sendCount_y, 1, rank_y, sendtag + 2);
req2[1] = comm.Irecv(&recvCount_x,1,rank_x,recvtag+1); req2[2] = comm.Irecv(&recvCount_Y, 1, rank_Y, recvtag + 2);
req1[2] = comm.Isend(&sendCount_y,1,rank_y,sendtag+2); req1[3] = comm.Isend(&sendCount_Y, 1, rank_Y, sendtag + 3);
req2[2] = comm.Irecv(&recvCount_Y,1,rank_Y,recvtag+2); req2[3] = comm.Irecv(&recvCount_y, 1, rank_y, recvtag + 3);
req1[3] = comm.Isend(&sendCount_Y,1,rank_Y,sendtag+3); req1[4] = comm.Isend(&sendCount_z, 1, rank_z, sendtag + 4);
req2[3] = comm.Irecv(&recvCount_y,1,rank_y,recvtag+3); req2[4] = comm.Irecv(&recvCount_Z, 1, rank_Z, recvtag + 4);
req1[4] = comm.Isend(&sendCount_z,1,rank_z,sendtag+4); req1[5] = comm.Isend(&sendCount_Z, 1, rank_Z, sendtag + 5);
req2[4] = comm.Irecv(&recvCount_Z,1,rank_Z,recvtag+4); req2[5] = comm.Irecv(&recvCount_z, 1, rank_z, recvtag + 5);
req1[5] = comm.Isend(&sendCount_Z,1,rank_Z,sendtag+5);
req2[5] = comm.Irecv(&recvCount_z,1,rank_z,recvtag+5);
req1[6] = comm.Isend(&sendCount_xy,1,rank_xy,sendtag+6); req1[6] = comm.Isend(&sendCount_xy, 1, rank_xy, sendtag + 6);
req2[6] = comm.Irecv(&recvCount_XY,1,rank_XY,recvtag+6); req2[6] = comm.Irecv(&recvCount_XY, 1, rank_XY, recvtag + 6);
req1[7] = comm.Isend(&sendCount_XY,1,rank_XY,sendtag+7); req1[7] = comm.Isend(&sendCount_XY, 1, rank_XY, sendtag + 7);
req2[7] = comm.Irecv(&recvCount_xy,1,rank_xy,recvtag+7); req2[7] = comm.Irecv(&recvCount_xy, 1, rank_xy, recvtag + 7);
req1[8] = comm.Isend(&sendCount_Xy,1,rank_Xy,sendtag+8); req1[8] = comm.Isend(&sendCount_Xy, 1, rank_Xy, sendtag + 8);
req2[8] = comm.Irecv(&recvCount_xY,1,rank_xY,recvtag+8); req2[8] = comm.Irecv(&recvCount_xY, 1, rank_xY, recvtag + 8);
req1[9] = comm.Isend(&sendCount_xY,1,rank_xY,sendtag+9); req1[9] = comm.Isend(&sendCount_xY, 1, rank_xY, sendtag + 9);
req2[9] = comm.Irecv(&recvCount_Xy,1,rank_Xy,recvtag+9); req2[9] = comm.Irecv(&recvCount_Xy, 1, rank_Xy, recvtag + 9);
req1[10] = comm.Isend(&sendCount_xz,1,rank_xz,sendtag+10); req1[10] = comm.Isend(&sendCount_xz, 1, rank_xz, sendtag + 10);
req2[10] = comm.Irecv(&recvCount_XZ,1,rank_XZ,recvtag+10); req2[10] = comm.Irecv(&recvCount_XZ, 1, rank_XZ, recvtag + 10);
req1[11] = comm.Isend(&sendCount_XZ,1,rank_XZ,sendtag+11); req1[11] = comm.Isend(&sendCount_XZ, 1, rank_XZ, sendtag + 11);
req2[11] = comm.Irecv(&recvCount_xz,1,rank_xz,recvtag+11); req2[11] = comm.Irecv(&recvCount_xz, 1, rank_xz, recvtag + 11);
req1[12] = comm.Isend(&sendCount_Xz,1,rank_Xz,sendtag+12); req1[12] = comm.Isend(&sendCount_Xz, 1, rank_Xz, sendtag + 12);
req2[12] = comm.Irecv(&recvCount_xZ,1,rank_xZ,recvtag+12); req2[12] = comm.Irecv(&recvCount_xZ, 1, rank_xZ, recvtag + 12);
req1[13] = comm.Isend(&sendCount_xZ,1,rank_xZ,sendtag+13); req1[13] = comm.Isend(&sendCount_xZ, 1, rank_xZ, sendtag + 13);
req2[13] = comm.Irecv(&recvCount_Xz,1,rank_Xz,recvtag+13); req2[13] = comm.Irecv(&recvCount_Xz, 1, rank_Xz, recvtag + 13);
req1[14] = comm.Isend(&sendCount_yz,1,rank_yz,sendtag+14); req1[14] = comm.Isend(&sendCount_yz, 1, rank_yz, sendtag + 14);
req2[14] = comm.Irecv(&recvCount_YZ,1,rank_YZ,recvtag+14); req2[14] = comm.Irecv(&recvCount_YZ, 1, rank_YZ, recvtag + 14);
req1[15] = comm.Isend(&sendCount_YZ,1,rank_YZ,sendtag+15); req1[15] = comm.Isend(&sendCount_YZ, 1, rank_YZ, sendtag + 15);
req2[15] = comm.Irecv(&recvCount_yz,1,rank_yz,recvtag+15); req2[15] = comm.Irecv(&recvCount_yz, 1, rank_yz, recvtag + 15);
req1[16] = comm.Isend(&sendCount_Yz,1,rank_Yz,sendtag+16); req1[16] = comm.Isend(&sendCount_Yz, 1, rank_Yz, sendtag + 16);
req2[16] = comm.Irecv(&recvCount_yZ,1,rank_yZ,recvtag+16); req2[16] = comm.Irecv(&recvCount_yZ, 1, rank_yZ, recvtag + 16);
req1[17] = comm.Isend(&sendCount_yZ,1,rank_yZ,sendtag+17); req1[17] = comm.Isend(&sendCount_yZ, 1, rank_yZ, sendtag + 17);
req2[17] = comm.Irecv(&recvCount_Yz,1,rank_Yz,recvtag+17); req2[17] = comm.Irecv(&recvCount_Yz, 1, rank_Yz, recvtag + 17);
comm.waitAll( 18, req1 ); comm.waitAll(18, req1);
comm.waitAll( 18, req2 ); comm.waitAll(18, req2);
comm.barrier(); comm.barrier();
} }
//*************************************************************************************** //***************************************************************************************
inline void CommunicateRecvLists( const Utilities::MPI& comm, int sendtag, int recvtag, inline void CommunicateRecvLists(
int *sendList_x, int *sendList_y, int *sendList_z, int *sendList_X, int *sendList_Y, int *sendList_Z, const Utilities::MPI &comm, int sendtag, int recvtag, int *sendList_x,
int *sendList_xy, int *sendList_XY, int *sendList_xY, int *sendList_Xy, int *sendList_y, int *sendList_z, int *sendList_X, int *sendList_Y,
int *sendList_xz, int *sendList_XZ, int *sendList_xZ, int *sendList_Xz, int *sendList_Z, int *sendList_xy, int *sendList_XY, int *sendList_xY,
int *sendList_yz, int *sendList_YZ, int *sendList_yZ, int *sendList_Yz, int *sendList_Xy, int *sendList_xz, int *sendList_XZ, int *sendList_xZ,
int sendCount_x, int sendCount_y, int sendCount_z, int sendCount_X, int sendCount_Y, int sendCount_Z, int *sendList_Xz, int *sendList_yz, int *sendList_YZ, int *sendList_yZ,
int sendCount_xy, int sendCount_XY, int sendCount_xY, int sendCount_Xy, int *sendList_Yz, int sendCount_x, int sendCount_y, int sendCount_z,
int sendCount_xz, int sendCount_XZ, int sendCount_xZ, int sendCount_Xz, int sendCount_X, int sendCount_Y, int sendCount_Z, int sendCount_xy,
int sendCount_yz, int sendCount_YZ, int sendCount_yZ, int sendCount_Yz, int sendCount_XY, int sendCount_xY, int sendCount_Xy, int sendCount_xz,
int *recvList_x, int *recvList_y, int *recvList_z, int *recvList_X, int *recvList_Y, int *recvList_Z, int sendCount_XZ, int sendCount_xZ, int sendCount_Xz, int sendCount_yz,
int *recvList_xy, int *recvList_XY, int *recvList_xY, int *recvList_Xy, int sendCount_YZ, int sendCount_yZ, int sendCount_Yz, int *recvList_x,
int *recvList_xz, int *recvList_XZ, int *recvList_xZ, int *recvList_Xz, int *recvList_y, int *recvList_z, int *recvList_X, int *recvList_Y,
int *recvList_yz, int *recvList_YZ, int *recvList_yZ, int *recvList_Yz, int *recvList_Z, int *recvList_xy, int *recvList_XY, int *recvList_xY,
int recvCount_x, int recvCount_y, int recvCount_z, int recvCount_X, int recvCount_Y, int recvCount_Z, int *recvList_Xy, int *recvList_xz, int *recvList_XZ, int *recvList_xZ,
int recvCount_xy, int recvCount_XY, int recvCount_xY, int recvCount_Xy, int *recvList_Xz, int *recvList_yz, int *recvList_YZ, int *recvList_yZ,
int recvCount_xz, int recvCount_XZ, int recvCount_xZ, int recvCount_Xz, int *recvList_Yz, int recvCount_x, int recvCount_y, int recvCount_z,
int recvCount_yz, int recvCount_YZ, int recvCount_yZ, int recvCount_Yz, int recvCount_X, int recvCount_Y, int recvCount_Z, int recvCount_xy,
int rank_x, int rank_y, int rank_z, int rank_X, int rank_Y, int rank_Z, int rank_xy, int rank_XY, int rank_xY, int recvCount_XY, int recvCount_xY, int recvCount_Xy, int recvCount_xz,
int rank_Xy, int rank_xz, int rank_XZ, int rank_xZ, int rank_Xz, int rank_yz, int rank_YZ, int rank_yZ, int rank_Yz) int recvCount_XZ, int recvCount_xZ, int recvCount_Xz, int recvCount_yz,
{ int recvCount_YZ, int recvCount_yZ, int recvCount_Yz, int rank_x,
MPI_Request req1[18], req2[18]; int rank_y, int rank_z, int rank_X, int rank_Y, int rank_Z, int rank_xy,
req1[0] = comm.Isend(sendList_x,sendCount_x,rank_x,sendtag); int rank_XY, int rank_xY, int rank_Xy, int rank_xz, int rank_XZ,
req2[0] = comm.Irecv(recvList_X,recvCount_X,rank_X,recvtag); int rank_xZ, int rank_Xz, int rank_yz, int rank_YZ, int rank_yZ,
req1[1] = comm.Isend(sendList_X,sendCount_X,rank_X,sendtag); int rank_Yz) {
req2[1] = comm.Irecv(recvList_x,recvCount_x,rank_x,recvtag); MPI_Request req1[18], req2[18];
req1[2] = comm.Isend(sendList_y,sendCount_y,rank_y,sendtag); req1[0] = comm.Isend(sendList_x, sendCount_x, rank_x, sendtag);
req2[2] = comm.Irecv(recvList_Y,recvCount_Y,rank_Y,recvtag); req2[0] = comm.Irecv(recvList_X, recvCount_X, rank_X, recvtag);
req1[3] = comm.Isend(sendList_Y,sendCount_Y,rank_Y,sendtag); req1[1] = comm.Isend(sendList_X, sendCount_X, rank_X, sendtag);
req2[3] = comm.Irecv(recvList_y,recvCount_y,rank_y,recvtag); req2[1] = comm.Irecv(recvList_x, recvCount_x, rank_x, recvtag);
req1[4] = comm.Isend(sendList_z,sendCount_z,rank_z,sendtag); req1[2] = comm.Isend(sendList_y, sendCount_y, rank_y, sendtag);
req2[4] = comm.Irecv(recvList_Z,recvCount_Z,rank_Z,recvtag); req2[2] = comm.Irecv(recvList_Y, recvCount_Y, rank_Y, recvtag);
req1[5] = comm.Isend(sendList_Z,sendCount_Z,rank_Z,sendtag); req1[3] = comm.Isend(sendList_Y, sendCount_Y, rank_Y, sendtag);
req2[5] = comm.Irecv(recvList_z,recvCount_z,rank_z,recvtag); req2[3] = comm.Irecv(recvList_y, recvCount_y, rank_y, recvtag);
req1[4] = comm.Isend(sendList_z, sendCount_z, rank_z, sendtag);
req2[4] = comm.Irecv(recvList_Z, recvCount_Z, rank_Z, recvtag);
req1[5] = comm.Isend(sendList_Z, sendCount_Z, rank_Z, sendtag);
req2[5] = comm.Irecv(recvList_z, recvCount_z, rank_z, recvtag);
req1[6] = comm.Isend(sendList_xy,sendCount_xy,rank_xy,sendtag); req1[6] = comm.Isend(sendList_xy, sendCount_xy, rank_xy, sendtag);
req2[6] = comm.Irecv(recvList_XY,recvCount_XY,rank_XY,recvtag); req2[6] = comm.Irecv(recvList_XY, recvCount_XY, rank_XY, recvtag);
req1[7] = comm.Isend(sendList_XY,sendCount_XY,rank_XY,sendtag); req1[7] = comm.Isend(sendList_XY, sendCount_XY, rank_XY, sendtag);
req2[7] = comm.Irecv(recvList_xy,recvCount_xy,rank_xy,recvtag); req2[7] = comm.Irecv(recvList_xy, recvCount_xy, rank_xy, recvtag);
req1[8] = comm.Isend(sendList_Xy,sendCount_Xy,rank_Xy,sendtag); req1[8] = comm.Isend(sendList_Xy, sendCount_Xy, rank_Xy, sendtag);
req2[8] = comm.Irecv(recvList_xY,recvCount_xY,rank_xY,recvtag); req2[8] = comm.Irecv(recvList_xY, recvCount_xY, rank_xY, recvtag);
req1[9] = comm.Isend(sendList_xY,sendCount_xY,rank_xY,sendtag); req1[9] = comm.Isend(sendList_xY, sendCount_xY, rank_xY, sendtag);
req2[9] = comm.Irecv(recvList_Xy,recvCount_Xy,rank_Xy,recvtag); req2[9] = comm.Irecv(recvList_Xy, recvCount_Xy, rank_Xy, recvtag);
req1[10] = comm.Isend(sendList_xz,sendCount_xz,rank_xz,sendtag); req1[10] = comm.Isend(sendList_xz, sendCount_xz, rank_xz, sendtag);
req2[10] = comm.Irecv(recvList_XZ,recvCount_XZ,rank_XZ,recvtag); req2[10] = comm.Irecv(recvList_XZ, recvCount_XZ, rank_XZ, recvtag);
req1[11] = comm.Isend(sendList_XZ,sendCount_XZ,rank_XZ,sendtag); req1[11] = comm.Isend(sendList_XZ, sendCount_XZ, rank_XZ, sendtag);
req2[11] = comm.Irecv(recvList_xz,recvCount_xz,rank_xz,recvtag); req2[11] = comm.Irecv(recvList_xz, recvCount_xz, rank_xz, recvtag);
req1[12] = comm.Isend(sendList_Xz,sendCount_Xz,rank_Xz,sendtag); req1[12] = comm.Isend(sendList_Xz, sendCount_Xz, rank_Xz, sendtag);
req2[12] = comm.Irecv(recvList_xZ,recvCount_xZ,rank_xZ,recvtag); req2[12] = comm.Irecv(recvList_xZ, recvCount_xZ, rank_xZ, recvtag);
req1[13] = comm.Isend(sendList_xZ,sendCount_xZ,rank_xZ,sendtag); req1[13] = comm.Isend(sendList_xZ, sendCount_xZ, rank_xZ, sendtag);
req2[13] = comm.Irecv(recvList_Xz,recvCount_Xz,rank_Xz,recvtag); req2[13] = comm.Irecv(recvList_Xz, recvCount_Xz, rank_Xz, recvtag);
req1[14] = comm.Isend(sendList_yz,sendCount_yz,rank_yz,sendtag); req1[14] = comm.Isend(sendList_yz, sendCount_yz, rank_yz, sendtag);
req2[14] = comm.Irecv(recvList_YZ,recvCount_YZ,rank_YZ,recvtag); req2[14] = comm.Irecv(recvList_YZ, recvCount_YZ, rank_YZ, recvtag);
req1[15] = comm.Isend(sendList_YZ,sendCount_YZ,rank_YZ,sendtag); req1[15] = comm.Isend(sendList_YZ, sendCount_YZ, rank_YZ, sendtag);
req2[15] = comm.Irecv(recvList_yz,recvCount_yz,rank_yz,recvtag); req2[15] = comm.Irecv(recvList_yz, recvCount_yz, rank_yz, recvtag);
req1[16] = comm.Isend(sendList_Yz,sendCount_Yz,rank_Yz,sendtag); req1[16] = comm.Isend(sendList_Yz, sendCount_Yz, rank_Yz, sendtag);
req2[16] = comm.Irecv(recvList_yZ,recvCount_yZ,rank_yZ,recvtag); req2[16] = comm.Irecv(recvList_yZ, recvCount_yZ, rank_yZ, recvtag);
req1[17] = comm.Isend(sendList_yZ,sendCount_yZ,rank_yZ,sendtag); req1[17] = comm.Isend(sendList_yZ, sendCount_yZ, rank_yZ, sendtag);
req2[17] = comm.Irecv(recvList_Yz,recvCount_Yz,rank_Yz,recvtag); req2[17] = comm.Irecv(recvList_Yz, recvCount_Yz, rank_Yz, recvtag);
comm.waitAll( 18, req1 ); comm.waitAll(18, req1);
comm.waitAll( 18, req2 ); comm.waitAll(18, req2);
} }
//*************************************************************************************** //***************************************************************************************
inline void CommunicateMeshHalo(DoubleArray &Mesh, const Utilities::MPI& comm, inline void CommunicateMeshHalo(
double *sendbuf_x,double *sendbuf_y,double *sendbuf_z,double *sendbuf_X,double *sendbuf_Y,double *sendbuf_Z, DoubleArray &Mesh, const Utilities::MPI &comm, double *sendbuf_x,
double *sendbuf_xy,double *sendbuf_XY,double *sendbuf_xY,double *sendbuf_Xy, double *sendbuf_y, double *sendbuf_z, double *sendbuf_X, double *sendbuf_Y,
double *sendbuf_xz,double *sendbuf_XZ,double *sendbuf_xZ,double *sendbuf_Xz, double *sendbuf_Z, double *sendbuf_xy, double *sendbuf_XY,
double *sendbuf_yz,double *sendbuf_YZ,double *sendbuf_yZ,double *sendbuf_Yz, double *sendbuf_xY, double *sendbuf_Xy, double *sendbuf_xz,
double *recvbuf_x,double *recvbuf_y,double *recvbuf_z,double *recvbuf_X,double *recvbuf_Y,double *recvbuf_Z, double *sendbuf_XZ, double *sendbuf_xZ, double *sendbuf_Xz,
double *recvbuf_xy,double *recvbuf_XY,double *recvbuf_xY,double *recvbuf_Xy, double *sendbuf_yz, double *sendbuf_YZ, double *sendbuf_yZ,
double *recvbuf_xz,double *recvbuf_XZ,double *recvbuf_xZ,double *recvbuf_Xz, double *sendbuf_Yz, double *recvbuf_x, double *recvbuf_y, double *recvbuf_z,
double *recvbuf_yz,double *recvbuf_YZ,double *recvbuf_yZ,double *recvbuf_Yz, double *recvbuf_X, double *recvbuf_Y, double *recvbuf_Z, double *recvbuf_xy,
int *sendList_x,int *sendList_y,int *sendList_z,int *sendList_X,int *sendList_Y,int *sendList_Z, double *recvbuf_XY, double *recvbuf_xY, double *recvbuf_Xy,
int *sendList_xy,int *sendList_XY,int *sendList_xY,int *sendList_Xy, double *recvbuf_xz, double *recvbuf_XZ, double *recvbuf_xZ,
int *sendList_xz,int *sendList_XZ,int *sendList_xZ,int *sendList_Xz, double *recvbuf_Xz, double *recvbuf_yz, double *recvbuf_YZ,
int *sendList_yz,int *sendList_YZ,int *sendList_yZ,int *sendList_Yz, double *recvbuf_yZ, double *recvbuf_Yz, int *sendList_x, int *sendList_y,
int sendCount_x,int sendCount_y,int sendCount_z,int sendCount_X,int sendCount_Y,int sendCount_Z, int *sendList_z, int *sendList_X, int *sendList_Y, int *sendList_Z,
int sendCount_xy,int sendCount_XY,int sendCount_xY,int sendCount_Xy, int *sendList_xy, int *sendList_XY, int *sendList_xY, int *sendList_Xy,
int sendCount_xz,int sendCount_XZ,int sendCount_xZ,int sendCount_Xz, int *sendList_xz, int *sendList_XZ, int *sendList_xZ, int *sendList_Xz,
int sendCount_yz,int sendCount_YZ,int sendCount_yZ,int sendCount_Yz, int *sendList_yz, int *sendList_YZ, int *sendList_yZ, int *sendList_Yz,
int *recvList_x,int *recvList_y,int *recvList_z,int *recvList_X,int *recvList_Y,int *recvList_Z, int sendCount_x, int sendCount_y, int sendCount_z, int sendCount_X,
int *recvList_xy,int *recvList_XY,int *recvList_xY,int *recvList_Xy, int sendCount_Y, int sendCount_Z, int sendCount_xy, int sendCount_XY,
int *recvList_xz,int *recvList_XZ,int *recvList_xZ,int *recvList_Xz, int sendCount_xY, int sendCount_Xy, int sendCount_xz, int sendCount_XZ,
int *recvList_yz,int *recvList_YZ,int *recvList_yZ,int *recvList_Yz, int sendCount_xZ, int sendCount_Xz, int sendCount_yz, int sendCount_YZ,
int recvCount_x,int recvCount_y,int recvCount_z,int recvCount_X,int recvCount_Y,int recvCount_Z, int sendCount_yZ, int sendCount_Yz, int *recvList_x, int *recvList_y,
int recvCount_xy,int recvCount_XY,int recvCount_xY,int recvCount_Xy, int *recvList_z, int *recvList_X, int *recvList_Y, int *recvList_Z,
int recvCount_xz,int recvCount_XZ,int recvCount_xZ,int recvCount_Xz, int *recvList_xy, int *recvList_XY, int *recvList_xY, int *recvList_Xy,
int recvCount_yz,int recvCount_YZ,int recvCount_yZ,int recvCount_Yz, int *recvList_xz, int *recvList_XZ, int *recvList_xZ, int *recvList_Xz,
int rank_x,int rank_y,int rank_z,int rank_X,int rank_Y,int rank_Z,int rank_xy,int rank_XY,int rank_xY, int *recvList_yz, int *recvList_YZ, int *recvList_yZ, int *recvList_Yz,
int rank_Xy,int rank_xz,int rank_XZ,int rank_xZ,int rank_Xz,int rank_yz,int rank_YZ,int rank_yZ,int rank_Yz) int recvCount_x, int recvCount_y, int recvCount_z, int recvCount_X,
{ int recvCount_Y, int recvCount_Z, int recvCount_xy, int recvCount_XY,
int sendtag, recvtag; int recvCount_xY, int recvCount_Xy, int recvCount_xz, int recvCount_XZ,
sendtag = recvtag = 7; int recvCount_xZ, int recvCount_Xz, int recvCount_yz, int recvCount_YZ,
int recvCount_yZ, int recvCount_Yz, int rank_x, int rank_y, int rank_z,
int rank_X, int rank_Y, int rank_Z, int rank_xy, int rank_XY, int rank_xY,
int rank_Xy, int rank_xz, int rank_XZ, int rank_xZ, int rank_Xz,
int rank_yz, int rank_YZ, int rank_yZ, int rank_Yz) {
int sendtag, recvtag;
sendtag = recvtag = 7;
double *MeshData = Mesh.data(); double *MeshData = Mesh.data();
PackMeshData(sendList_x, sendCount_x ,sendbuf_x, MeshData); PackMeshData(sendList_x, sendCount_x, sendbuf_x, MeshData);
PackMeshData(sendList_X, sendCount_X ,sendbuf_X, MeshData); PackMeshData(sendList_X, sendCount_X, sendbuf_X, MeshData);
PackMeshData(sendList_y, sendCount_y ,sendbuf_y, MeshData); PackMeshData(sendList_y, sendCount_y, sendbuf_y, MeshData);
PackMeshData(sendList_Y, sendCount_Y ,sendbuf_Y, MeshData); PackMeshData(sendList_Y, sendCount_Y, sendbuf_Y, MeshData);
PackMeshData(sendList_z, sendCount_z ,sendbuf_z, MeshData); PackMeshData(sendList_z, sendCount_z, sendbuf_z, MeshData);
PackMeshData(sendList_Z, sendCount_Z ,sendbuf_Z, MeshData); PackMeshData(sendList_Z, sendCount_Z, sendbuf_Z, MeshData);
PackMeshData(sendList_xy, sendCount_xy ,sendbuf_xy, MeshData); PackMeshData(sendList_xy, sendCount_xy, sendbuf_xy, MeshData);
PackMeshData(sendList_Xy, sendCount_Xy ,sendbuf_Xy, MeshData); PackMeshData(sendList_Xy, sendCount_Xy, sendbuf_Xy, MeshData);
PackMeshData(sendList_xY, sendCount_xY ,sendbuf_xY, MeshData); PackMeshData(sendList_xY, sendCount_xY, sendbuf_xY, MeshData);
PackMeshData(sendList_XY, sendCount_XY ,sendbuf_XY, MeshData); PackMeshData(sendList_XY, sendCount_XY, sendbuf_XY, MeshData);
PackMeshData(sendList_xz, sendCount_xz ,sendbuf_xz, MeshData); PackMeshData(sendList_xz, sendCount_xz, sendbuf_xz, MeshData);
PackMeshData(sendList_Xz, sendCount_Xz ,sendbuf_Xz, MeshData); PackMeshData(sendList_Xz, sendCount_Xz, sendbuf_Xz, MeshData);
PackMeshData(sendList_xZ, sendCount_xZ ,sendbuf_xZ, MeshData); PackMeshData(sendList_xZ, sendCount_xZ, sendbuf_xZ, MeshData);
PackMeshData(sendList_XZ, sendCount_XZ ,sendbuf_XZ, MeshData); PackMeshData(sendList_XZ, sendCount_XZ, sendbuf_XZ, MeshData);
PackMeshData(sendList_yz, sendCount_yz ,sendbuf_yz, MeshData); PackMeshData(sendList_yz, sendCount_yz, sendbuf_yz, MeshData);
PackMeshData(sendList_Yz, sendCount_Yz ,sendbuf_Yz, MeshData); PackMeshData(sendList_Yz, sendCount_Yz, sendbuf_Yz, MeshData);
PackMeshData(sendList_yZ, sendCount_yZ ,sendbuf_yZ, MeshData); PackMeshData(sendList_yZ, sendCount_yZ, sendbuf_yZ, MeshData);
PackMeshData(sendList_YZ, sendCount_YZ ,sendbuf_YZ, MeshData); PackMeshData(sendList_YZ, sendCount_YZ, sendbuf_YZ, MeshData);
//...................................................................................... //......................................................................................
comm.sendrecv(sendbuf_x,sendCount_x,rank_x,sendtag,recvbuf_X,recvCount_X,rank_X,recvtag); comm.sendrecv(sendbuf_x, sendCount_x, rank_x, sendtag, recvbuf_X,
comm.sendrecv(sendbuf_X,sendCount_X,rank_X,sendtag,recvbuf_x,recvCount_x,rank_x,recvtag); recvCount_X, rank_X, recvtag);
comm.sendrecv(sendbuf_y,sendCount_y,rank_y,sendtag,recvbuf_Y,recvCount_Y,rank_Y,recvtag); comm.sendrecv(sendbuf_X, sendCount_X, rank_X, sendtag, recvbuf_x,
comm.sendrecv(sendbuf_Y,sendCount_Y,rank_Y,sendtag,recvbuf_y,recvCount_y,rank_y,recvtag); recvCount_x, rank_x, recvtag);
comm.sendrecv(sendbuf_z,sendCount_z,rank_z,sendtag,recvbuf_Z,recvCount_Z,rank_Z,recvtag); comm.sendrecv(sendbuf_y, sendCount_y, rank_y, sendtag, recvbuf_Y,
comm.sendrecv(sendbuf_Z,sendCount_Z,rank_Z,sendtag,recvbuf_z,recvCount_z,rank_z,recvtag); recvCount_Y, rank_Y, recvtag);
comm.sendrecv(sendbuf_xy,sendCount_xy,rank_xy,sendtag,recvbuf_XY,recvCount_XY,rank_XY,recvtag); comm.sendrecv(sendbuf_Y, sendCount_Y, rank_Y, sendtag, recvbuf_y,
comm.sendrecv(sendbuf_XY,sendCount_XY,rank_XY,sendtag,recvbuf_xy,recvCount_xy,rank_xy,recvtag); recvCount_y, rank_y, recvtag);
comm.sendrecv(sendbuf_Xy,sendCount_Xy,rank_Xy,sendtag,recvbuf_xY,recvCount_xY,rank_xY,recvtag); comm.sendrecv(sendbuf_z, sendCount_z, rank_z, sendtag, recvbuf_Z,
comm.sendrecv(sendbuf_xY,sendCount_xY,rank_xY,sendtag,recvbuf_Xy,recvCount_Xy,rank_Xy,recvtag); recvCount_Z, rank_Z, recvtag);
comm.sendrecv(sendbuf_xz,sendCount_xz,rank_xz,sendtag,recvbuf_XZ,recvCount_XZ,rank_XZ,recvtag); comm.sendrecv(sendbuf_Z, sendCount_Z, rank_Z, sendtag, recvbuf_z,
comm.sendrecv(sendbuf_XZ,sendCount_XZ,rank_XZ,sendtag,recvbuf_xz,recvCount_xz,rank_xz,recvtag); recvCount_z, rank_z, recvtag);
comm.sendrecv(sendbuf_Xz,sendCount_Xz,rank_Xz,sendtag,recvbuf_xZ,recvCount_xZ,rank_xZ,recvtag); comm.sendrecv(sendbuf_xy, sendCount_xy, rank_xy, sendtag, recvbuf_XY,
comm.sendrecv(sendbuf_xZ,sendCount_xZ,rank_xZ,sendtag,recvbuf_Xz,recvCount_Xz,rank_Xz,recvtag); recvCount_XY, rank_XY, recvtag);
comm.sendrecv(sendbuf_yz,sendCount_yz,rank_yz,sendtag,recvbuf_YZ,recvCount_YZ,rank_YZ,recvtag); comm.sendrecv(sendbuf_XY, sendCount_XY, rank_XY, sendtag, recvbuf_xy,
comm.sendrecv(sendbuf_YZ,sendCount_YZ,rank_YZ,sendtag,recvbuf_yz,recvCount_yz,rank_yz,recvtag); recvCount_xy, rank_xy, recvtag);
comm.sendrecv(sendbuf_Yz,sendCount_Yz,rank_Yz,sendtag,recvbuf_yZ,recvCount_yZ,rank_yZ,recvtag); comm.sendrecv(sendbuf_Xy, sendCount_Xy, rank_Xy, sendtag, recvbuf_xY,
comm.sendrecv(sendbuf_yZ,sendCount_yZ,rank_yZ,sendtag,recvbuf_Yz,recvCount_Yz,rank_Yz,recvtag); recvCount_xY, rank_xY, recvtag);
//........................................................................................ comm.sendrecv(sendbuf_xY, sendCount_xY, rank_xY, sendtag, recvbuf_Xy,
UnpackMeshData(recvList_x, recvCount_x ,recvbuf_x, MeshData); recvCount_Xy, rank_Xy, recvtag);
UnpackMeshData(recvList_X, recvCount_X ,recvbuf_X, MeshData); comm.sendrecv(sendbuf_xz, sendCount_xz, rank_xz, sendtag, recvbuf_XZ,
UnpackMeshData(recvList_y, recvCount_y ,recvbuf_y, MeshData); recvCount_XZ, rank_XZ, recvtag);
UnpackMeshData(recvList_Y, recvCount_Y ,recvbuf_Y, MeshData); comm.sendrecv(sendbuf_XZ, sendCount_XZ, rank_XZ, sendtag, recvbuf_xz,
UnpackMeshData(recvList_z, recvCount_z ,recvbuf_z, MeshData); recvCount_xz, rank_xz, recvtag);
UnpackMeshData(recvList_Z, recvCount_Z ,recvbuf_Z, MeshData); comm.sendrecv(sendbuf_Xz, sendCount_Xz, rank_Xz, sendtag, recvbuf_xZ,
UnpackMeshData(recvList_xy, recvCount_xy ,recvbuf_xy, MeshData); recvCount_xZ, rank_xZ, recvtag);
UnpackMeshData(recvList_Xy, recvCount_Xy ,recvbuf_Xy, MeshData); comm.sendrecv(sendbuf_xZ, sendCount_xZ, rank_xZ, sendtag, recvbuf_Xz,
UnpackMeshData(recvList_xY, recvCount_xY ,recvbuf_xY, MeshData); recvCount_Xz, rank_Xz, recvtag);
UnpackMeshData(recvList_XY, recvCount_XY ,recvbuf_XY, MeshData); comm.sendrecv(sendbuf_yz, sendCount_yz, rank_yz, sendtag, recvbuf_YZ,
UnpackMeshData(recvList_xz, recvCount_xz ,recvbuf_xz, MeshData); recvCount_YZ, rank_YZ, recvtag);
UnpackMeshData(recvList_Xz, recvCount_Xz ,recvbuf_Xz, MeshData); comm.sendrecv(sendbuf_YZ, sendCount_YZ, rank_YZ, sendtag, recvbuf_yz,
UnpackMeshData(recvList_xZ, recvCount_xZ ,recvbuf_xZ, MeshData); recvCount_yz, rank_yz, recvtag);
UnpackMeshData(recvList_XZ, recvCount_XZ ,recvbuf_XZ, MeshData); comm.sendrecv(sendbuf_Yz, sendCount_Yz, rank_Yz, sendtag, recvbuf_yZ,
UnpackMeshData(recvList_yz, recvCount_yz ,recvbuf_yz, MeshData); recvCount_yZ, rank_yZ, recvtag);
UnpackMeshData(recvList_Yz, recvCount_Yz ,recvbuf_Yz, MeshData); comm.sendrecv(sendbuf_yZ, sendCount_yZ, rank_yZ, sendtag, recvbuf_Yz,
UnpackMeshData(recvList_yZ, recvCount_yZ ,recvbuf_yZ, MeshData); recvCount_Yz, rank_Yz, recvtag);
UnpackMeshData(recvList_YZ, recvCount_YZ ,recvbuf_YZ, MeshData); //........................................................................................
UnpackMeshData(recvList_x, recvCount_x, recvbuf_x, MeshData);
UnpackMeshData(recvList_X, recvCount_X, recvbuf_X, MeshData);
UnpackMeshData(recvList_y, recvCount_y, recvbuf_y, MeshData);
UnpackMeshData(recvList_Y, recvCount_Y, recvbuf_Y, MeshData);
UnpackMeshData(recvList_z, recvCount_z, recvbuf_z, MeshData);
UnpackMeshData(recvList_Z, recvCount_Z, recvbuf_Z, MeshData);
UnpackMeshData(recvList_xy, recvCount_xy, recvbuf_xy, MeshData);
UnpackMeshData(recvList_Xy, recvCount_Xy, recvbuf_Xy, MeshData);
UnpackMeshData(recvList_xY, recvCount_xY, recvbuf_xY, MeshData);
UnpackMeshData(recvList_XY, recvCount_XY, recvbuf_XY, MeshData);
UnpackMeshData(recvList_xz, recvCount_xz, recvbuf_xz, MeshData);
UnpackMeshData(recvList_Xz, recvCount_Xz, recvbuf_Xz, MeshData);
UnpackMeshData(recvList_xZ, recvCount_xZ, recvbuf_xZ, MeshData);
UnpackMeshData(recvList_XZ, recvCount_XZ, recvbuf_XZ, MeshData);
UnpackMeshData(recvList_yz, recvCount_yz, recvbuf_yz, MeshData);
UnpackMeshData(recvList_Yz, recvCount_Yz, recvbuf_Yz, MeshData);
UnpackMeshData(recvList_yZ, recvCount_yZ, recvbuf_yZ, MeshData);
UnpackMeshData(recvList_YZ, recvCount_YZ, recvbuf_YZ, MeshData);
} }
#endif #endif
#include "common/Communication.hpp" #include "common/Communication.hpp"

View File

@ -37,101 +37,116 @@
#include "common/MPI.h" #include "common/MPI.h"
#include "common/Utilities.h" #include "common/Utilities.h"
/******************************************************** /********************************************************
* Redistribute data between two grids * * Redistribute data between two grids *
********************************************************/ ********************************************************/
template<class TYPE> template <class TYPE>
Array<TYPE> redistribute( const RankInfoStruct& src_rank, const Array<TYPE>& src_data, Array<TYPE>
const RankInfoStruct& dst_rank, std::array<int,3> dst_size, const Utilities::MPI& comm ) redistribute(const RankInfoStruct &src_rank, const Array<TYPE> &src_data,
{ const RankInfoStruct &dst_rank, std::array<int, 3> dst_size,
if ( comm.getSize() == 1 ) { const Utilities::MPI &comm) {
return src_data.subset( { 0, (size_t) dst_size[0]-1, 0, (size_t) dst_size[1]-1, 0, (size_t) dst_size[2]-1 } ); if (comm.getSize() == 1) {
return src_data.subset({0, (size_t)dst_size[0] - 1, 0,
(size_t)dst_size[1] - 1, 0,
(size_t)dst_size[2] - 1});
} }
// Get the src size // Get the src size
std::array<int,3> src_size; std::array<int, 3> src_size;
int size0[3] = { (int) src_data.size(0), (int) src_data.size(1), (int) src_data.size(2) }; int size0[3] = {(int)src_data.size(0), (int)src_data.size(1),
comm.maxReduce( size0, src_size.data(), 3 ); (int)src_data.size(2)};
if ( !src_data.empty() ) comm.maxReduce(size0, src_size.data(), 3);
ASSERT( src_size[0] == size0[0] && src_size[1] == size0[1] && src_size[2] == size0[2] ); if (!src_data.empty())
ASSERT(src_size[0] == size0[0] && src_size[1] == size0[1] &&
src_size[2] == size0[2]);
// Check that dst_size matches on all ranks // Check that dst_size matches on all ranks
comm.maxReduce( dst_size.data(), size0, 3 ); comm.maxReduce(dst_size.data(), size0, 3);
ASSERT( dst_size[0] == size0[0] && dst_size[1] == size0[1] && dst_size[2] == size0[2] ); ASSERT(dst_size[0] == size0[0] && dst_size[1] == size0[1] &&
dst_size[2] == size0[2]);
// Function to get overlap range // Function to get overlap range
auto calcOverlap = []( int i1[3], int i2[3], int j1[3], int j2[3] ) { auto calcOverlap = [](int i1[3], int i2[3], int j1[3], int j2[3]) {
std::vector<size_t> index; std::vector<size_t> index;
if ( i1[0] > j2[0] || i2[0] < j1[0] || i1[1] > j2[1] || i2[1] < j1[1] || i1[2] > j2[2] || i2[2] < j1[2] ) if (i1[0] > j2[0] || i2[0] < j1[0] || i1[1] > j2[1] || i2[1] < j1[1] ||
i1[2] > j2[2] || i2[2] < j1[2])
return index; return index;
index.resize( 6 ); index.resize(6);
index[0] = std::max( j1[0] - i1[0], 0 ); index[0] = std::max(j1[0] - i1[0], 0);
index[1] = std::min( j2[0] - i1[0], i2[0] - i1[0] ); index[1] = std::min(j2[0] - i1[0], i2[0] - i1[0]);
index[2] = std::max( j1[1] - i1[1], 0 ); index[2] = std::max(j1[1] - i1[1], 0);
index[3] = std::min( j2[1] - i1[1], i2[1] - i1[1] ); index[3] = std::min(j2[1] - i1[1], i2[1] - i1[1]);
index[4] = std::max( j1[2] - i1[2], 0 ); index[4] = std::max(j1[2] - i1[2], 0);
index[5] = std::min( j2[2] - i1[2], i2[2] - i1[2] ); index[5] = std::min(j2[2] - i1[2], i2[2] - i1[2]);
return index; return index;
}; };
// Pack and send my data to the appropriate ranks (including myself) // Pack and send my data to the appropriate ranks (including myself)
std::vector<int> send_rank; std::vector<int> send_rank;
std::vector<Array<TYPE>> send_data; std::vector<Array<TYPE>> send_data;
if ( !src_data.empty() ) { if (!src_data.empty()) {
int i1[3] = { src_size[0] * src_rank.ix, src_size[1] * src_rank.jy, src_size[2] * src_rank.kz }; int i1[3] = {src_size[0] * src_rank.ix, src_size[1] * src_rank.jy,
int i2[3] = { i1[0] + src_size[0] - 1, i1[1] + src_size[1] - 1, i1[2] + src_size[2] - 1 }; src_size[2] * src_rank.kz};
for ( int i=0; i<dst_rank.nx; i++ ) { int i2[3] = {i1[0] + src_size[0] - 1, i1[1] + src_size[1] - 1,
for ( int j=0; j<dst_rank.ny; j++ ) { i1[2] + src_size[2] - 1};
for ( int k=0; k<dst_rank.nz; k++ ) { for (int i = 0; i < dst_rank.nx; i++) {
int j1[3] = { i * dst_size[0], j * dst_size[1], k * dst_size[2] }; for (int j = 0; j < dst_rank.ny; j++) {
int j2[3] = { j1[0] + dst_size[0] - 1, j1[1] + dst_size[1] - 1, j1[2] + dst_size[2] - 1 }; for (int k = 0; k < dst_rank.nz; k++) {
auto index = calcOverlap( i1, i2, j1, j2 ); int j1[3] = {i * dst_size[0], j * dst_size[1],
if ( index.empty() ) k * dst_size[2]};
int j2[3] = {j1[0] + dst_size[0] - 1,
j1[1] + dst_size[1] - 1,
j1[2] + dst_size[2] - 1};
auto index = calcOverlap(i1, i2, j1, j2);
if (index.empty())
continue; continue;
send_rank.push_back( dst_rank.getRankForBlock(i,j,k) ); send_rank.push_back(dst_rank.getRankForBlock(i, j, k));
send_data.push_back( src_data.subset( index ) ); send_data.push_back(src_data.subset(index));
} }
} }
} }
} }
std::vector<MPI_Request> send_request( send_rank.size() ); std::vector<MPI_Request> send_request(send_rank.size());
for (size_t i=0; i<send_rank.size(); i++) for (size_t i = 0; i < send_rank.size(); i++)
send_request[i] = comm.Isend( send_data[i].data(), send_data[i].length(), send_rank[i], 5462 ); send_request[i] = comm.Isend(send_data[i].data(), send_data[i].length(),
send_rank[i], 5462);
// Unpack data from the appropriate ranks (including myself) // Unpack data from the appropriate ranks (including myself)
Array<TYPE> dst_data( dst_size[0], dst_size[1], dst_size[2] ); Array<TYPE> dst_data(dst_size[0], dst_size[1], dst_size[2]);
int i1[3] = { dst_size[0] * dst_rank.ix, dst_size[1] * dst_rank.jy, dst_size[2] * dst_rank.kz }; int i1[3] = {dst_size[0] * dst_rank.ix, dst_size[1] * dst_rank.jy,
int i2[3] = { i1[0] + dst_size[0] - 1, i1[1] + dst_size[1] - 1, i1[2] + dst_size[2] - 1 }; dst_size[2] * dst_rank.kz};
for ( int i=0; i<src_rank.nx; i++ ) { int i2[3] = {i1[0] + dst_size[0] - 1, i1[1] + dst_size[1] - 1,
for ( int j=0; j<src_rank.ny; j++ ) { i1[2] + dst_size[2] - 1};
for ( int k=0; k<src_rank.nz; k++ ) { for (int i = 0; i < src_rank.nx; i++) {
int j1[3] = { i * src_size[0], j * src_size[1], k * src_size[2] }; for (int j = 0; j < src_rank.ny; j++) {
int j2[3] = { j1[0] + src_size[0] - 1, j1[1] + src_size[1] - 1, j1[2] + src_size[2] - 1 }; for (int k = 0; k < src_rank.nz; k++) {
auto index = calcOverlap( i1, i2, j1, j2 ); int j1[3] = {i * src_size[0], j * src_size[1], k * src_size[2]};
if ( index.empty() ) int j2[3] = {j1[0] + src_size[0] - 1, j1[1] + src_size[1] - 1,
j1[2] + src_size[2] - 1};
auto index = calcOverlap(i1, i2, j1, j2);
if (index.empty())
continue; continue;
int rank = src_rank.getRankForBlock(i,j,k); int rank = src_rank.getRankForBlock(i, j, k);
Array<TYPE> data( index[1] - index[0] + 1, index[3] - index[2] + 1, index[5] - index[4] + 1 ); Array<TYPE> data(index[1] - index[0] + 1,
comm.recv( data.data(), data.length(), rank, 5462 ); index[3] - index[2] + 1,
dst_data.copySubset( index, data ); index[5] - index[4] + 1);
comm.recv(data.data(), data.length(), rank, 5462);
dst_data.copySubset(index, data);
} }
} }
} }
// Free data // Free data
comm.waitAll( send_request.size(), send_request.data() ); comm.waitAll(send_request.size(), send_request.data());
return dst_data; return dst_data;
} }
/******************************************************** /********************************************************
* Structure to fill halo cells * * Structure to fill halo cells *
********************************************************/ ********************************************************/
template<class TYPE> template <class TYPE>
fillHalo<TYPE>::fillHalo( const Utilities::MPI& comm_, const RankInfoStruct& info_, fillHalo<TYPE>::fillHalo(const Utilities::MPI &comm_,
std::array<int,3> n_, std::array<int,3> ng_, int tag0, int depth_, const RankInfoStruct &info_, std::array<int, 3> n_,
std::array<bool,3> fill, std::array<bool,3> periodic ): std::array<int, 3> ng_, int tag0, int depth_,
comm(comm_), info(info_), n(n_), ng(ng_), depth(depth_) std::array<bool, 3> fill, std::array<bool, 3> periodic)
{ : comm(comm_), info(info_), n(n_), ng(ng_), depth(depth_) {
// Set the fill pattern // Set the fill pattern
memset(fill_pattern,0,sizeof(fill_pattern)); memset(fill_pattern, 0, sizeof(fill_pattern));
if ( fill[0] ) { if (fill[0]) {
fill_pattern[0][1][1] = true; fill_pattern[0][1][1] = true;
fill_pattern[2][1][1] = true; fill_pattern[2][1][1] = true;
fill_pattern[1][0][1] = true; fill_pattern[1][0][1] = true;
@ -139,7 +154,7 @@ fillHalo<TYPE>::fillHalo( const Utilities::MPI& comm_, const RankInfoStruct& inf
fill_pattern[1][1][0] = true; fill_pattern[1][1][0] = true;
fill_pattern[1][1][2] = true; fill_pattern[1][1][2] = true;
} }
if ( fill[1] ) { if (fill[1]) {
fill_pattern[0][0][1] = true; fill_pattern[0][0][1] = true;
fill_pattern[0][2][1] = true; fill_pattern[0][2][1] = true;
fill_pattern[2][0][1] = true; fill_pattern[2][0][1] = true;
@ -153,7 +168,7 @@ fillHalo<TYPE>::fillHalo( const Utilities::MPI& comm_, const RankInfoStruct& inf
fill_pattern[1][2][0] = true; fill_pattern[1][2][0] = true;
fill_pattern[1][2][2] = true; fill_pattern[1][2][2] = true;
} }
if ( fill[2] ) { if (fill[2]) {
fill_pattern[0][0][0] = true; fill_pattern[0][0][0] = true;
fill_pattern[0][0][2] = true; fill_pattern[0][0][2] = true;
fill_pattern[0][2][0] = true; fill_pattern[0][2][0] = true;
@ -164,238 +179,233 @@ fillHalo<TYPE>::fillHalo( const Utilities::MPI& comm_, const RankInfoStruct& inf
fill_pattern[2][2][2] = true; fill_pattern[2][2][2] = true;
} }
// Remove communication for non-perioidic directions // Remove communication for non-perioidic directions
if ( !periodic[0] && info.ix==0 ) { if (!periodic[0] && info.ix == 0) {
for (int j=0; j<3; j++) { for (int j = 0; j < 3; j++) {
for (int k=0; k<3; k++) for (int k = 0; k < 3; k++)
fill_pattern[0][j][k] = false; fill_pattern[0][j][k] = false;
} }
} }
if ( !periodic[0] && info.ix==info.nx-1 ) { if (!periodic[0] && info.ix == info.nx - 1) {
for (int j=0; j<3; j++) { for (int j = 0; j < 3; j++) {
for (int k=0; k<3; k++) for (int k = 0; k < 3; k++)
fill_pattern[2][j][k] = false; fill_pattern[2][j][k] = false;
} }
} }
if ( !periodic[1] && info.jy==0 ) { if (!periodic[1] && info.jy == 0) {
for (int i=0; i<3; i++) { for (int i = 0; i < 3; i++) {
for (int k=0; k<3; k++) for (int k = 0; k < 3; k++)
fill_pattern[i][0][k] = false; fill_pattern[i][0][k] = false;
} }
} }
if ( !periodic[1] && info.jy==info.ny-1 ) { if (!periodic[1] && info.jy == info.ny - 1) {
for (int i=0; i<3; i++) { for (int i = 0; i < 3; i++) {
for (int k=0; k<3; k++) for (int k = 0; k < 3; k++)
fill_pattern[i][2][k] = false; fill_pattern[i][2][k] = false;
} }
} }
if ( !periodic[2] && info.kz==0 ) { if (!periodic[2] && info.kz == 0) {
for (int i=0; i<3; i++) { for (int i = 0; i < 3; i++) {
for (int j=0; j<3; j++) for (int j = 0; j < 3; j++)
fill_pattern[i][j][0] = false; fill_pattern[i][j][0] = false;
} }
} }
if ( !periodic[2] && info.kz==info.nz-1 ) { if (!periodic[2] && info.kz == info.nz - 1) {
for (int i=0; i<3; i++) { for (int i = 0; i < 3; i++) {
for (int j=0; j<3; j++) for (int j = 0; j < 3; j++)
fill_pattern[i][j][2] = false; fill_pattern[i][j][2] = false;
} }
} }
// Determine the number of elements for each send/recv // Determine the number of elements for each send/recv
for (int i=0; i<3; i++) { for (int i = 0; i < 3; i++) {
int ni = (i-1)==0 ? n[0]:ng[0]; int ni = (i - 1) == 0 ? n[0] : ng[0];
for (int j=0; j<3; j++) { for (int j = 0; j < 3; j++) {
int nj = (j-1)==0 ? n[1]:ng[1]; int nj = (j - 1) == 0 ? n[1] : ng[1];
for (int k=0; k<3; k++) { for (int k = 0; k < 3; k++) {
int nk = (k-1)==0 ? n[2]:ng[2]; int nk = (k - 1) == 0 ? n[2] : ng[2];
if ( fill_pattern[i][j][k] ) if (fill_pattern[i][j][k])
N_send_recv[i][j][k] = ni*nj*nk; N_send_recv[i][j][k] = ni * nj * nk;
else else
N_send_recv[i][j][k] = 0; N_send_recv[i][j][k] = 0;
} }
} }
} }
// Create send/recv buffers // Create send/recv buffers
size_t N_mem=0; size_t N_mem = 0;
for (int i=0; i<3; i++) { for (int i = 0; i < 3; i++) {
for (int j=0; j<3; j++) { for (int j = 0; j < 3; j++) {
for (int k=0; k<3; k++) for (int k = 0; k < 3; k++)
N_mem += N_send_recv[i][j][k]; N_mem += N_send_recv[i][j][k];
} }
} }
mem = new TYPE[2*depth*N_mem]; mem = new TYPE[2 * depth * N_mem];
size_t index = 0; size_t index = 0;
for (int i=0; i<3; i++) { for (int i = 0; i < 3; i++) {
for (int j=0; j<3; j++) { for (int j = 0; j < 3; j++) {
for (int k=0; k<3; k++) { for (int k = 0; k < 3; k++) {
send[i][j][k] = &mem[index]; send[i][j][k] = &mem[index];
index += depth*N_send_recv[i][j][k]; index += depth * N_send_recv[i][j][k];
recv[i][j][k] = &mem[index]; recv[i][j][k] = &mem[index];
index += depth*N_send_recv[i][j][k]; index += depth * N_send_recv[i][j][k];
} }
} }
} }
// Create the tags // Create the tags
for (int i=0; i<3; i++) { for (int i = 0; i < 3; i++) {
for (int j=0; j<3; j++) { for (int j = 0; j < 3; j++) {
for (int k=0; k<3; k++) { for (int k = 0; k < 3; k++) {
tag[i][j][k] = tag0 + i + j*3 + k*9; tag[i][j][k] = tag0 + i + j * 3 + k * 9;
} }
} }
} }
} }
template<class TYPE> template <class TYPE> fillHalo<TYPE>::~fillHalo() { delete[] mem; }
fillHalo<TYPE>::~fillHalo( ) template <class TYPE> void fillHalo<TYPE>::fill(Array<TYPE> &data) {
{
delete [] mem;
}
template<class TYPE>
void fillHalo<TYPE>::fill( Array<TYPE>& data )
{
//PROFILE_START("fillHalo::fill",1); //PROFILE_START("fillHalo::fill",1);
int depth2 = data.size(3); int depth2 = data.size(3);
ASSERT((int)data.size(0)==n[0]+2*ng[0]); ASSERT((int)data.size(0) == n[0] + 2 * ng[0]);
ASSERT((int)data.size(1)==n[1]+2*ng[1]); ASSERT((int)data.size(1) == n[1] + 2 * ng[1]);
ASSERT((int)data.size(2)==n[2]+2*ng[2]); ASSERT((int)data.size(2) == n[2] + 2 * ng[2]);
ASSERT(depth2<=depth); ASSERT(depth2 <= depth);
ASSERT(data.ndim()==3||data.ndim()==4); ASSERT(data.ndim() == 3 || data.ndim() == 4);
// Start the recieves // Start the recieves
for (int i=0; i<3; i++) { for (int i = 0; i < 3; i++) {
for (int j=0; j<3; j++) { for (int j = 0; j < 3; j++) {
for (int k=0; k<3; k++) { for (int k = 0; k < 3; k++) {
if ( !fill_pattern[i][j][k] ) if (!fill_pattern[i][j][k])
continue; continue;
recv_req[i][j][k] = comm.Irecv( recv[i][j][k], depth2*N_send_recv[i][j][k], recv_req[i][j][k] =
info.rank[i][j][k], tag[2-i][2-j][2-k] ); comm.Irecv(recv[i][j][k], depth2 * N_send_recv[i][j][k],
info.rank[i][j][k], tag[2 - i][2 - j][2 - k]);
} }
} }
} }
// Pack the src data and start the sends // Pack the src data and start the sends
for (int i=0; i<3; i++) { for (int i = 0; i < 3; i++) {
for (int j=0; j<3; j++) { for (int j = 0; j < 3; j++) {
for (int k=0; k<3; k++) { for (int k = 0; k < 3; k++) {
if ( !fill_pattern[i][j][k] ) if (!fill_pattern[i][j][k])
continue; continue;
pack( data, i-1, j-1, k-1, send[i][j][k] ); pack(data, i - 1, j - 1, k - 1, send[i][j][k]);
send_req[i][j][k] = comm.Isend( send[i][j][k], depth2*N_send_recv[i][j][k], send_req[i][j][k] =
info.rank[i][j][k], tag[i][j][k] ); comm.Isend(send[i][j][k], depth2 * N_send_recv[i][j][k],
info.rank[i][j][k], tag[i][j][k]);
} }
} }
} }
// Recv the dst data and unpack (we recive in reverse order to match the sends) // Recv the dst data and unpack (we recive in reverse order to match the sends)
for (int i=2; i>=0; i--) { for (int i = 2; i >= 0; i--) {
for (int j=2; j>=0; j--) { for (int j = 2; j >= 0; j--) {
for (int k=2; k>=0; k--) { for (int k = 2; k >= 0; k--) {
if ( !fill_pattern[i][j][k] ) if (!fill_pattern[i][j][k])
continue; continue;
comm.wait( recv_req[i][j][k] ); comm.wait(recv_req[i][j][k]);
unpack( data, i-1, j-1, k-1, recv[i][j][k] ); unpack(data, i - 1, j - 1, k - 1, recv[i][j][k]);
} }
} }
} }
// Wait until all sends have completed // Wait until all sends have completed
for (int i=0; i<3; i++) { for (int i = 0; i < 3; i++) {
for (int j=0; j<3; j++) { for (int j = 0; j < 3; j++) {
for (int k=0; k<3; k++) { for (int k = 0; k < 3; k++) {
if ( !fill_pattern[i][j][k] ) if (!fill_pattern[i][j][k])
continue; continue;
comm.wait( send_req[i][j][k] ); comm.wait(send_req[i][j][k]);
} }
} }
} }
//PROFILE_STOP("fillHalo::fill",1); //PROFILE_STOP("fillHalo::fill",1);
} }
template<class TYPE> template <class TYPE>
void fillHalo<TYPE>::pack( const Array<TYPE>& data, int i0, int j0, int k0, TYPE *buffer ) void fillHalo<TYPE>::pack(const Array<TYPE> &data, int i0, int j0, int k0,
{ TYPE *buffer) {
int depth2 = data.size(3); int depth2 = data.size(3);
int ni = i0==0 ? n[0]:ng[0]; int ni = i0 == 0 ? n[0] : ng[0];
int nj = j0==0 ? n[1]:ng[1]; int nj = j0 == 0 ? n[1] : ng[1];
int nk = k0==0 ? n[2]:ng[2]; int nk = k0 == 0 ? n[2] : ng[2];
int is = i0==0 ? ng[0]:((i0==-1)?ng[0]:n[0]); int is = i0 == 0 ? ng[0] : ((i0 == -1) ? ng[0] : n[0]);
int js = j0==0 ? ng[1]:((j0==-1)?ng[1]:n[1]); int js = j0 == 0 ? ng[1] : ((j0 == -1) ? ng[1] : n[1]);
int ks = k0==0 ? ng[2]:((k0==-1)?ng[2]:n[2]); int ks = k0 == 0 ? ng[2] : ((k0 == -1) ? ng[2] : n[2]);
for (int d=0; d<depth2; d++) { for (int d = 0; d < depth2; d++) {
for (int k=0; k<nk; k++) { for (int k = 0; k < nk; k++) {
for (int j=0; j<nj; j++) { for (int j = 0; j < nj; j++) {
for (int i=0; i<ni; i++) { for (int i = 0; i < ni; i++) {
buffer[i+j*ni+k*ni*nj+d*ni*nj*nk] = data(i+is,j+js,k+ks,d); buffer[i + j * ni + k * ni * nj + d * ni * nj * nk] =
data(i + is, j + js, k + ks, d);
} }
} }
} }
} }
} }
template<class TYPE> template <class TYPE>
void fillHalo<TYPE>::unpack( Array<TYPE>& data, int i0, int j0, int k0, const TYPE *buffer ) void fillHalo<TYPE>::unpack(Array<TYPE> &data, int i0, int j0, int k0,
{ const TYPE *buffer) {
int depth2 = data.size(3); int depth2 = data.size(3);
int ni = i0==0 ? n[0]:ng[0]; int ni = i0 == 0 ? n[0] : ng[0];
int nj = j0==0 ? n[1]:ng[1]; int nj = j0 == 0 ? n[1] : ng[1];
int nk = k0==0 ? n[2]:ng[2]; int nk = k0 == 0 ? n[2] : ng[2];
int is = i0==0 ? ng[0]:((i0==-1)?0:n[0]+ng[0]); int is = i0 == 0 ? ng[0] : ((i0 == -1) ? 0 : n[0] + ng[0]);
int js = j0==0 ? ng[1]:((j0==-1)?0:n[1]+ng[1]); int js = j0 == 0 ? ng[1] : ((j0 == -1) ? 0 : n[1] + ng[1]);
int ks = k0==0 ? ng[2]:((k0==-1)?0:n[2]+ng[2]); int ks = k0 == 0 ? ng[2] : ((k0 == -1) ? 0 : n[2] + ng[2]);
for (int d=0; d<depth2; d++) { for (int d = 0; d < depth2; d++) {
for (int k=0; k<nk; k++) { for (int k = 0; k < nk; k++) {
for (int j=0; j<nj; j++) { for (int j = 0; j < nj; j++) {
for (int i=0; i<ni; i++) { for (int i = 0; i < ni; i++) {
data(i+is,j+js,k+ks,d) = buffer[i+j*ni+k*ni*nj+d*ni*nj*nk]; data(i + is, j + js, k + ks, d) =
buffer[i + j * ni + k * ni * nj + d * ni * nj * nk];
} }
} }
} }
} }
} }
/******************************************************** /********************************************************
* Function to remove the ghost halo * * Function to remove the ghost halo *
********************************************************/ ********************************************************/
template<class TYPE> template <class TYPE>
template<class TYPE1, class TYPE2> template <class TYPE1, class TYPE2>
void fillHalo<TYPE>::copy( const Array<TYPE1>& src, Array<TYPE2>& dst ) void fillHalo<TYPE>::copy(const Array<TYPE1> &src, Array<TYPE2> &dst) {
{
//PROFILE_START("fillHalo::copy",1); //PROFILE_START("fillHalo::copy",1);
ASSERT( (int)src.size(0)==n[0] || (int)src.size(0)==n[0]+2*ng[0] ); ASSERT((int)src.size(0) == n[0] || (int)src.size(0) == n[0] + 2 * ng[0]);
ASSERT( (int)dst.size(0)==n[0] || (int)dst.size(0)==n[0]+2*ng[0] ); ASSERT((int)dst.size(0) == n[0] || (int)dst.size(0) == n[0] + 2 * ng[0]);
bool src_halo = (int)src.size(0)==n[0]+2*ng[0]; bool src_halo = (int)src.size(0) == n[0] + 2 * ng[0];
bool dst_halo = (int)dst.size(0)==n[0]+2*ng[0]; bool dst_halo = (int)dst.size(0) == n[0] + 2 * ng[0];
if ( src_halo ) { if (src_halo) {
ASSERT((int)src.size(0)==n[0]+2*ng[0]); ASSERT((int)src.size(0) == n[0] + 2 * ng[0]);
ASSERT((int)src.size(1)==n[1]+2*ng[1]); ASSERT((int)src.size(1) == n[1] + 2 * ng[1]);
ASSERT((int)src.size(2)==n[2]+2*ng[2]); ASSERT((int)src.size(2) == n[2] + 2 * ng[2]);
} else { } else {
ASSERT((int)src.size(0)==n[0]); ASSERT((int)src.size(0) == n[0]);
ASSERT((int)src.size(1)==n[1]); ASSERT((int)src.size(1) == n[1]);
ASSERT((int)src.size(2)==n[2]); ASSERT((int)src.size(2) == n[2]);
} }
if ( dst_halo ) { if (dst_halo) {
ASSERT((int)dst.size(0)==n[0]+2*ng[0]); ASSERT((int)dst.size(0) == n[0] + 2 * ng[0]);
ASSERT((int)dst.size(1)==n[1]+2*ng[1]); ASSERT((int)dst.size(1) == n[1] + 2 * ng[1]);
ASSERT((int)dst.size(2)==n[2]+2*ng[2]); ASSERT((int)dst.size(2) == n[2] + 2 * ng[2]);
} else { } else {
ASSERT((int)dst.size(0)==n[0]); ASSERT((int)dst.size(0) == n[0]);
ASSERT((int)dst.size(1)==n[1]); ASSERT((int)dst.size(1) == n[1]);
ASSERT((int)dst.size(2)==n[2]); ASSERT((int)dst.size(2) == n[2]);
} }
if ( src_halo == dst_halo ) { if (src_halo == dst_halo) {
// Src and dst halos match // Src and dst halos match
for (size_t i=0; i<src.length(); i++) for (size_t i = 0; i < src.length(); i++)
dst(i) = src(i); dst(i) = src(i);
} else if ( src_halo && !dst_halo ) { } else if (src_halo && !dst_halo) {
// Src has halos // Src has halos
for (int k=0; k<n[2]; k++) { for (int k = 0; k < n[2]; k++) {
for (int j=0; j<n[1]; j++) { for (int j = 0; j < n[1]; j++) {
for (int i=0; i<n[0]; i++) { for (int i = 0; i < n[0]; i++) {
dst(i,j,k) = src(i+ng[0],j+ng[1],k+ng[2]); dst(i, j, k) = src(i + ng[0], j + ng[1], k + ng[2]);
} }
} }
} }
} else if ( !src_halo && dst_halo ) { } else if (!src_halo && dst_halo) {
// Dst has halos // Dst has halos
for (int k=0; k<n[2]; k++) { for (int k = 0; k < n[2]; k++) {
for (int j=0; j<n[1]; j++) { for (int j = 0; j < n[1]; j++) {
for (int i=0; i<n[0]; i++) { for (int i = 0; i < n[0]; i++) {
dst(i+ng[0],j+ng[1],k+ng[2]) = src(i,j,k); dst(i + ng[0], j + ng[1], k + ng[2]) = src(i, j, k);
} }
} }
} }
@ -404,5 +414,4 @@ void fillHalo<TYPE>::copy( const Array<TYPE1>& src, Array<TYPE2>& dst )
//PROFILE_STOP("fillHalo::copy",1); //PROFILE_STOP("fillHalo::copy",1);
} }
#endif #endif

View File

@ -24,303 +24,268 @@
#include <string> #include <string>
#include <tuple> #include <tuple>
/******************************************************************** /********************************************************************
* Constructors/destructor * * Constructors/destructor *
********************************************************************/ ********************************************************************/
Database::Database() = default; Database::Database() = default;
Database::~Database() = default; Database::~Database() = default;
Database::Database( const Database& rhs ) : KeyData( rhs ) Database::Database(const Database &rhs) : KeyData(rhs) {
{
d_data.clear(); d_data.clear();
for ( const auto& tmp : rhs.d_data ) for (const auto &tmp : rhs.d_data)
putData( tmp.first, tmp.second->clone() ); putData(tmp.first, tmp.second->clone());
} }
Database& Database::operator=( const Database& rhs ) Database &Database::operator=(const Database &rhs) {
{ if (this == &rhs)
if ( this == &rhs )
return *this; return *this;
d_data.clear(); d_data.clear();
for ( const auto& tmp : rhs.d_data ) for (const auto &tmp : rhs.d_data)
putData( tmp.first, tmp.second->clone() ); putData(tmp.first, tmp.second->clone());
return *this; return *this;
} }
Database::Database( Database&& rhs ) { std::swap( d_data, rhs.d_data ); } Database::Database(Database &&rhs) { std::swap(d_data, rhs.d_data); }
Database& Database::operator=( Database&& rhs ) Database &Database::operator=(Database &&rhs) {
{ if (this != &rhs)
if ( this != &rhs ) std::swap(d_data, rhs.d_data);
std::swap( d_data, rhs.d_data );
return *this; return *this;
} }
/******************************************************************** /********************************************************************
* Clone the database * * Clone the database *
********************************************************************/ ********************************************************************/
std::shared_ptr<KeyData> Database::clone() const { return cloneDatabase(); } std::shared_ptr<KeyData> Database::clone() const { return cloneDatabase(); }
std::shared_ptr<Database> Database::cloneDatabase() const std::shared_ptr<Database> Database::cloneDatabase() const {
{
auto db = std::make_shared<Database>(); auto db = std::make_shared<Database>();
for ( const auto& tmp : d_data ) for (const auto &tmp : d_data)
db->putData( tmp.first, tmp.second->clone() ); db->putData(tmp.first, tmp.second->clone());
return db; return db;
} }
/******************************************************************** /********************************************************************
* Get the data object * * Get the data object *
********************************************************************/ ********************************************************************/
bool Database::keyExists( const std::string& key ) const bool Database::keyExists(const std::string &key) const {
{ return d_data.find(key) != d_data.end();
return d_data.find( key ) != d_data.end();
} }
std::shared_ptr<KeyData> Database::getData( const std::string& key ) std::shared_ptr<KeyData> Database::getData(const std::string &key) {
{ auto it = d_data.find(key);
auto it = d_data.find( key ); if (it == d_data.end()) {
if ( it == d_data.end() ) {
char msg[1000]; char msg[1000];
sprintf( msg, "Variable %s was not found in database", key.c_str() ); sprintf(msg, "Variable %s was not found in database", key.c_str());
ERROR( msg ); ERROR(msg);
} }
return it->second; return it->second;
} }
std::shared_ptr<const KeyData> Database::getData( const std::string& key ) const std::shared_ptr<const KeyData> Database::getData(const std::string &key) const {
{ return const_cast<Database *>(this)->getData(key);
return const_cast<Database*>( this )->getData( key );
} }
bool Database::isDatabase( const std::string& key ) const bool Database::isDatabase(const std::string &key) const {
{ auto ptr = getData(key);
auto ptr = getData( key ); auto ptr2 = std::dynamic_pointer_cast<const Database>(ptr);
auto ptr2 = std::dynamic_pointer_cast<const Database>( ptr );
return ptr2 != nullptr; return ptr2 != nullptr;
} }
std::shared_ptr<Database> Database::getDatabase( const std::string& key ) std::shared_ptr<Database> Database::getDatabase(const std::string &key) {
{ std::shared_ptr<KeyData> ptr = getData(key);
std::shared_ptr<KeyData> ptr = getData( key ); std::shared_ptr<Database> ptr2 = std::dynamic_pointer_cast<Database>(ptr);
std::shared_ptr<Database> ptr2 = std::dynamic_pointer_cast<Database>( ptr ); if (ptr2 == nullptr) {
if ( ptr2 == nullptr ) {
char msg[1000]; char msg[1000];
sprintf( msg, "Variable %s is not a database", key.c_str() ); sprintf(msg, "Variable %s is not a database", key.c_str());
ERROR( msg ); ERROR(msg);
} }
return ptr2; return ptr2;
} }
std::shared_ptr<const Database> Database::getDatabase( const std::string& key ) const std::shared_ptr<const Database>
{ Database::getDatabase(const std::string &key) const {
return const_cast<Database*>( this )->getDatabase( key ); return const_cast<Database *>(this)->getDatabase(key);
} }
std::vector<std::string> Database::getAllKeys() const std::vector<std::string> Database::getAllKeys() const {
{
std::vector<std::string> keys; std::vector<std::string> keys;
keys.reserve( d_data.size() ); keys.reserve(d_data.size());
for ( const auto& it : d_data ) for (const auto &it : d_data)
keys.push_back( it.first ); keys.push_back(it.first);
return keys; return keys;
} }
void Database::putDatabase( const std::string& key, std::shared_ptr<Database> db ) void Database::putDatabase(const std::string &key,
{ std::shared_ptr<Database> db) {
d_data[key] = std::move( db ); d_data[key] = std::move(db);
} }
void Database::putData( const std::string& key, std::shared_ptr<KeyData> data ) void Database::putData(const std::string &key, std::shared_ptr<KeyData> data) {
{ d_data[key] = std::move(data);
d_data[key] = std::move( data );
} }
/******************************************************************** /********************************************************************
* Is the data of the given type * * Is the data of the given type *
********************************************************************/ ********************************************************************/
template<> template <> bool Database::isType<double>(const std::string &key) const {
bool Database::isType<double>( const std::string& key ) const auto type = getData(key)->type();
{
auto type = getData( key )->type();
return type == "double"; return type == "double";
} }
template<> template <> bool Database::isType<float>(const std::string &key) const {
bool Database::isType<float>( const std::string& key ) const auto type = getData(key)->type();
{
auto type = getData( key )->type();
return type == "double"; return type == "double";
} }
template<> template <> bool Database::isType<int>(const std::string &key) const {
bool Database::isType<int>( const std::string& key ) const
{
bool pass = true; bool pass = true;
auto type = getData( key )->type(); auto type = getData(key)->type();
if ( type == "double" ) { if (type == "double") {
auto data = getVector<double>( key ); auto data = getVector<double>(key);
for ( auto tmp : data ) for (auto tmp : data)
pass = pass && static_cast<double>( static_cast<int>( tmp ) ) == tmp; pass = pass && static_cast<double>(static_cast<int>(tmp)) == tmp;
} else { } else {
pass = false; pass = false;
} }
return pass; return pass;
} }
template<> template <> bool Database::isType<std::string>(const std::string &key) const {
bool Database::isType<std::string>( const std::string& key ) const auto type = getData(key)->type();
{
auto type = getData( key )->type();
return type == "string"; return type == "string";
} }
template<> template <> bool Database::isType<bool>(const std::string &key) const {
bool Database::isType<bool>( const std::string& key ) const auto type = getData(key)->type();
{
auto type = getData( key )->type();
return type == "bool"; return type == "bool";
} }
/******************************************************************** /********************************************************************
* Get a vector * * Get a vector *
********************************************************************/ ********************************************************************/
template<> template <>
std::vector<std::string> Database::getVector<std::string>( std::vector<std::string>
const std::string& key, const Units& ) const Database::getVector<std::string>(const std::string &key, const Units &) const {
{ std::shared_ptr<const KeyData> ptr = getData(key);
std::shared_ptr<const KeyData> ptr = getData( key ); if (std::dynamic_pointer_cast<const EmptyKeyData>(ptr))
if ( std::dynamic_pointer_cast<const EmptyKeyData>( ptr ) )
return std::vector<std::string>(); return std::vector<std::string>();
const auto* ptr2 = dynamic_cast<const KeyDataString*>( ptr.get() ); const auto *ptr2 = dynamic_cast<const KeyDataString *>(ptr.get());
if ( ptr2 == nullptr ) { if (ptr2 == nullptr) {
ERROR( "Key '" + key + "' is not a string" ); ERROR("Key '" + key + "' is not a string");
} }
return ptr2->d_data; return ptr2->d_data;
} }
template<> template <>
std::vector<bool> Database::getVector<bool>( const std::string& key, const Units& ) const std::vector<bool> Database::getVector<bool>(const std::string &key,
{ const Units &) const {
std::shared_ptr<const KeyData> ptr = getData( key ); std::shared_ptr<const KeyData> ptr = getData(key);
if ( std::dynamic_pointer_cast<const EmptyKeyData>( ptr ) ) if (std::dynamic_pointer_cast<const EmptyKeyData>(ptr))
return std::vector<bool>(); return std::vector<bool>();
const auto* ptr2 = dynamic_cast<const KeyDataBool*>( ptr.get() ); const auto *ptr2 = dynamic_cast<const KeyDataBool *>(ptr.get());
if ( ptr2 == nullptr ) { if (ptr2 == nullptr) {
ERROR( "Key '" + key + "' is not a bool" ); ERROR("Key '" + key + "' is not a bool");
} }
return ptr2->d_data; return ptr2->d_data;
} }
template<class TYPE> template <class TYPE>
std::vector<TYPE> Database::getVector( const std::string& key, const Units& unit ) const std::vector<TYPE> Database::getVector(const std::string &key,
{ const Units &unit) const {
std::shared_ptr<const KeyData> ptr = getData( key ); std::shared_ptr<const KeyData> ptr = getData(key);
if ( std::dynamic_pointer_cast<const EmptyKeyData>( ptr ) ) if (std::dynamic_pointer_cast<const EmptyKeyData>(ptr))
return std::vector<TYPE>(); return std::vector<TYPE>();
std::vector<TYPE> data; std::vector<TYPE> data;
if ( std::dynamic_pointer_cast<const KeyDataDouble>( ptr ) ) { if (std::dynamic_pointer_cast<const KeyDataDouble>(ptr)) {
const auto* ptr2 = dynamic_cast<const KeyDataDouble*>( ptr.get() ); const auto *ptr2 = dynamic_cast<const KeyDataDouble *>(ptr.get());
const std::vector<double>& data2 = ptr2->d_data; const std::vector<double> &data2 = ptr2->d_data;
double factor = 1; double factor = 1;
if ( !unit.isNull() ) { if (!unit.isNull()) {
INSIST( !ptr2->d_unit.isNull(), "Field " + key + " must have units" ); INSIST(!ptr2->d_unit.isNull(), "Field " + key + " must have units");
factor = ptr2->d_unit.convert( unit ); factor = ptr2->d_unit.convert(unit);
INSIST( factor != 0, "Unit conversion failed" ); INSIST(factor != 0, "Unit conversion failed");
} }
data.resize( data2.size() ); data.resize(data2.size());
for ( size_t i = 0; i < data2.size(); i++ ) for (size_t i = 0; i < data2.size(); i++)
data[i] = static_cast<TYPE>( factor * data2[i] ); data[i] = static_cast<TYPE>(factor * data2[i]);
} else if ( std::dynamic_pointer_cast<const KeyDataString>( ptr ) ) { } else if (std::dynamic_pointer_cast<const KeyDataString>(ptr)) {
ERROR( "Converting std::string to another type" ); ERROR("Converting std::string to another type");
} else if ( std::dynamic_pointer_cast<const KeyDataBool>( ptr ) ) { } else if (std::dynamic_pointer_cast<const KeyDataBool>(ptr)) {
ERROR( "Converting std::bool to another type" ); ERROR("Converting std::bool to another type");
} else { } else {
ERROR( "Unable to convert data format" ); ERROR("Unable to convert data format");
} }
return data; return data;
} }
/******************************************************************** /********************************************************************
* Put a vector * * Put a vector *
********************************************************************/ ********************************************************************/
template<> template <>
void Database::putVector<std::string>( void Database::putVector<std::string>(const std::string &key,
const std::string& key, const std::vector<std::string>& data, const Units& ) const std::vector<std::string> &data,
{ const Units &) {
std::shared_ptr<KeyDataString> ptr( new KeyDataString() ); std::shared_ptr<KeyDataString> ptr(new KeyDataString());
ptr->d_data = data; ptr->d_data = data;
d_data[key] = ptr; d_data[key] = ptr;
} }
template<> template <>
void Database::putVector<bool>( void Database::putVector<bool>(const std::string &key,
const std::string& key, const std::vector<bool>& data, const Units& ) const std::vector<bool> &data, const Units &) {
{ std::shared_ptr<KeyDataBool> ptr(new KeyDataBool());
std::shared_ptr<KeyDataBool> ptr( new KeyDataBool() );
ptr->d_data = data; ptr->d_data = data;
d_data[key] = ptr; d_data[key] = ptr;
} }
template<class TYPE> template <class TYPE>
void Database::putVector( const std::string& key, const std::vector<TYPE>& data, const Units& unit ) void Database::putVector(const std::string &key, const std::vector<TYPE> &data,
{ const Units &unit) {
std::shared_ptr<KeyDataDouble> ptr( new KeyDataDouble() ); std::shared_ptr<KeyDataDouble> ptr(new KeyDataDouble());
ptr->d_unit = unit; ptr->d_unit = unit;
ptr->d_data.resize( data.size() ); ptr->d_data.resize(data.size());
for ( size_t i = 0; i < data.size(); i++ ) for (size_t i = 0; i < data.size(); i++)
ptr->d_data[i] = static_cast<double>( data[i] ); ptr->d_data[i] = static_cast<double>(data[i]);
d_data[key] = ptr; d_data[key] = ptr;
} }
/******************************************************************** /********************************************************************
* Print the database * * Print the database *
********************************************************************/ ********************************************************************/
void Database::print( std::ostream& os, const std::string& indent ) const void Database::print(std::ostream &os, const std::string &indent) const {
{ for (const auto &it : d_data) {
for ( const auto& it : d_data ) {
os << indent << it.first; os << indent << it.first;
if ( dynamic_cast<const Database*>( it.second.get() ) ) { if (dynamic_cast<const Database *>(it.second.get())) {
const auto* db = dynamic_cast<const Database*>( it.second.get() ); const auto *db = dynamic_cast<const Database *>(it.second.get());
os << " {\n"; os << " {\n";
db->print( os, indent + " " ); db->print(os, indent + " ");
os << indent << "}\n"; os << indent << "}\n";
} else { } else {
os << " = "; os << " = ";
it.second->print( os, "" ); it.second->print(os, "");
} }
} }
} }
std::string Database::print( const std::string& indent ) const std::string Database::print(const std::string &indent) const {
{
std::stringstream ss; std::stringstream ss;
print( ss, indent ); print(ss, indent);
return ss.str(); return ss.str();
} }
/******************************************************************** /********************************************************************
* Read input database file * * Read input database file *
********************************************************************/ ********************************************************************/
Database::Database( const std::string& filename ) Database::Database(const std::string &filename) {
{
// Read the input file into memory // Read the input file into memory
FILE* fid = fopen( filename.c_str(), "rb" ); FILE *fid = fopen(filename.c_str(), "rb");
if ( fid == nullptr ) if (fid == nullptr)
ERROR( "Error opening file " + filename ); ERROR("Error opening file " + filename);
fseek( fid, 0, SEEK_END ); fseek(fid, 0, SEEK_END);
size_t bytes = ftell( fid ); size_t bytes = ftell(fid);
rewind( fid ); rewind(fid);
auto* buffer = new char[bytes + 4]; auto *buffer = new char[bytes + 4];
size_t result = fread( buffer, 1, bytes, fid ); size_t result = fread(buffer, 1, bytes, fid);
fclose( fid ); fclose(fid);
if ( result != bytes ) if (result != bytes)
ERROR( "Error reading file " + filename ); ERROR("Error reading file " + filename);
buffer[bytes + 0] = '\n'; buffer[bytes + 0] = '\n';
buffer[bytes + 1] = '}'; buffer[bytes + 1] = '}';
buffer[bytes + 2] = '\n'; buffer[bytes + 2] = '\n';
buffer[bytes + 3] = 0; buffer[bytes + 3] = 0;
// Create the database entries // Create the database entries
loadDatabase( buffer, *this ); loadDatabase(buffer, *this);
// Free temporary memory // Free temporary memory
delete[] buffer; delete[] buffer;
} }
std::shared_ptr<Database> Database::createFromString( const std::string& data ) std::shared_ptr<Database> Database::createFromString(const std::string &data) {
{ std::shared_ptr<Database> db(new Database());
std::shared_ptr<Database> db( new Database() ); auto *buffer = new char[data.size() + 4];
auto* buffer = new char[data.size() + 4]; memcpy(buffer, data.data(), data.size());
memcpy( buffer, data.data(), data.size() );
buffer[data.size() + 0] = '\n'; buffer[data.size() + 0] = '\n';
buffer[data.size() + 1] = '}'; buffer[data.size() + 1] = '}';
buffer[data.size() + 2] = '\n'; buffer[data.size() + 2] = '\n';
buffer[data.size() + 3] = 0; buffer[data.size() + 3] = 0;
loadDatabase( buffer, *db ); loadDatabase(buffer, *db);
delete[] buffer; delete[] buffer;
return db; return db;
} }
@ -335,279 +300,285 @@ enum class token_type {
end_bracket, end_bracket,
end end
}; };
inline size_t length( token_type type ) inline size_t length(token_type type) {
{
size_t len = 0; size_t len = 0;
if ( type == token_type::newline || type == token_type::quote || type == token_type::equal || if (type == token_type::newline || type == token_type::quote ||
type == token_type::bracket || type == token_type::end_bracket || type == token_type::equal || type == token_type::bracket ||
type == token_type::end ) { type == token_type::end_bracket || type == token_type::end) {
len = 1; len = 1;
} else if ( type == token_type::line_comment || type == token_type::block_start || } else if (type == token_type::line_comment ||
type == token_type::block_stop ) { type == token_type::block_start ||
type == token_type::block_stop) {
len = 2; len = 2;
} }
return len; return len;
} }
inline std::tuple<size_t, token_type> find_next_token( const char* buffer ) inline std::tuple<size_t, token_type> find_next_token(const char *buffer) {
{
size_t i = 0; size_t i = 0;
while ( true ) { while (true) {
if ( buffer[i] == '\n' || buffer[i] == '\r' ) { if (buffer[i] == '\n' || buffer[i] == '\r') {
return std::pair<size_t, token_type>( i + 1, token_type::newline ); return std::pair<size_t, token_type>(i + 1, token_type::newline);
} else if ( buffer[i] == 0 ) { } else if (buffer[i] == 0) {
return std::pair<size_t, token_type>( i + 1, token_type::end ); return std::pair<size_t, token_type>(i + 1, token_type::end);
} else if ( buffer[i] == '"' ) { } else if (buffer[i] == '"') {
return std::pair<size_t, token_type>( i + 1, token_type::quote ); return std::pair<size_t, token_type>(i + 1, token_type::quote);
} else if ( buffer[i] == '=' ) { } else if (buffer[i] == '=') {
return std::pair<size_t, token_type>( i + 1, token_type::equal ); return std::pair<size_t, token_type>(i + 1, token_type::equal);
} else if ( buffer[i] == '{' ) { } else if (buffer[i] == '{') {
return std::pair<size_t, token_type>( i + 1, token_type::bracket ); return std::pair<size_t, token_type>(i + 1, token_type::bracket);
} else if ( buffer[i] == '}' ) { } else if (buffer[i] == '}') {
return std::pair<size_t, token_type>( i + 1, token_type::end_bracket ); return std::pair<size_t, token_type>(i + 1,
} else if ( buffer[i] == '/' ) { token_type::end_bracket);
if ( buffer[i + 1] == '/' ) { } else if (buffer[i] == '/') {
return std::pair<size_t, token_type>( i + 2, token_type::line_comment ); if (buffer[i + 1] == '/') {
} else if ( buffer[i + 1] == '*' ) { return std::pair<size_t, token_type>(i + 2,
return std::pair<size_t, token_type>( i + 2, token_type::block_start ); token_type::line_comment);
} else if (buffer[i + 1] == '*') {
return std::pair<size_t, token_type>(i + 2,
token_type::block_start);
} }
} else if ( buffer[i] == '*' ) { } else if (buffer[i] == '*') {
if ( buffer[i + 1] == '/' ) if (buffer[i + 1] == '/')
return std::pair<size_t, token_type>( i + 2, token_type::block_stop ); return std::pair<size_t, token_type>(i + 2,
token_type::block_stop);
} }
i++; i++;
} }
return std::pair<size_t, token_type>( 0, token_type::end ); return std::pair<size_t, token_type>(0, token_type::end);
} }
inline std::string deblank( const std::string& str ) inline std::string deblank(const std::string &str) {
{
size_t i1 = 0xFFFFFFF, i2 = 0; size_t i1 = 0xFFFFFFF, i2 = 0;
for ( size_t i = 0; i < str.size(); i++ ) { for (size_t i = 0; i < str.size(); i++) {
if ( str[i] != ' ' ) { if (str[i] != ' ') {
i1 = std::min( i1, i ); i1 = std::min(i1, i);
i2 = std::max( i2, i ); i2 = std::max(i2, i);
} }
} }
return i1 <= i2 ? str.substr( i1, i2 - i1 + 1 ) : std::string(); return i1 <= i2 ? str.substr(i1, i2 - i1 + 1) : std::string();
} }
size_t skip_comment( const char* buffer ) size_t skip_comment(const char *buffer) {
{ auto tmp = find_next_token(buffer);
auto tmp = find_next_token( buffer ); const token_type end_comment =
const token_type end_comment = ( std::get<1>( tmp ) == token_type::line_comment ) ? (std::get<1>(tmp) == token_type::line_comment) ? token_type::newline
token_type::newline : : token_type::block_stop;
token_type::block_stop;
size_t pos = 0; size_t pos = 0;
while ( std::get<1>( tmp ) != end_comment ) { while (std::get<1>(tmp) != end_comment) {
if ( std::get<1>( tmp ) == token_type::end ) if (std::get<1>(tmp) == token_type::end)
ERROR( "Encountered end of file before block comment end" ); ERROR("Encountered end of file before block comment end");
pos += std::get<0>( tmp ); pos += std::get<0>(tmp);
tmp = find_next_token( &buffer[pos] ); tmp = find_next_token(&buffer[pos]);
} }
pos += std::get<0>( tmp ); pos += std::get<0>(tmp);
return pos; return pos;
} }
inline std::string lower( const std::string& str ) inline std::string lower(const std::string &str) {
{ std::string tmp(str);
std::string tmp( str ); std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
std::transform( tmp.begin(), tmp.end(), tmp.begin(), ::tolower );
return tmp; return tmp;
} }
static std::tuple<size_t, std::shared_ptr<KeyData>> read_value( static std::tuple<size_t, std::shared_ptr<KeyData>>
const char* buffer, const std::string& key ) read_value(const char *buffer, const std::string &key) {
{
// Get the value as a std::string // Get the value as a std::string
size_t pos = 0; size_t pos = 0;
token_type type = token_type::end; token_type type = token_type::end;
std::tie( pos, type ) = find_next_token( &buffer[pos] ); std::tie(pos, type) = find_next_token(&buffer[pos]);
size_t len = pos - length( type ); size_t len = pos - length(type);
while ( type != token_type::newline ) { while (type != token_type::newline) {
if ( type == token_type::quote ) { if (type == token_type::quote) {
size_t i = 0; size_t i = 0;
std::tie( i, type ) = find_next_token( &buffer[pos] ); std::tie(i, type) = find_next_token(&buffer[pos]);
pos += i; pos += i;
while ( type != token_type::quote ) { while (type != token_type::quote) {
ASSERT( type != token_type::end ); ASSERT(type != token_type::end);
std::tie( i, type ) = find_next_token( &buffer[pos] ); std::tie(i, type) = find_next_token(&buffer[pos]);
pos += i; pos += i;
} }
} else if ( type == token_type::line_comment || type == token_type::block_start ) { } else if (type == token_type::line_comment ||
len = pos - length( type ); type == token_type::block_start) {
pos += skip_comment( &buffer[pos - length( type )] ) - length( type ); len = pos - length(type);
pos += skip_comment(&buffer[pos - length(type)]) - length(type);
break; break;
} }
size_t i = 0; size_t i = 0;
std::tie( i, type ) = find_next_token( &buffer[pos] ); std::tie(i, type) = find_next_token(&buffer[pos]);
pos += i; pos += i;
len = pos - length( type ); len = pos - length(type);
} }
const std::string value = deblank( std::string( buffer, len ) ); const std::string value = deblank(std::string(buffer, len));
// Split the value to an array of values // Split the value to an array of values
std::vector<std::string> values; std::vector<std::string> values;
size_t i0 = 0, i = 0, count = 0; size_t i0 = 0, i = 0, count = 0;
for ( ; i < value.size(); i++ ) { for (; i < value.size(); i++) {
if ( value[i] == '"' ) { if (value[i] == '"') {
count++; count++;
} else if ( value[i] == ',' && count % 2 == 0 ) { } else if (value[i] == ',' && count % 2 == 0) {
values.push_back( deblank( value.substr( i0, i - i0 ) ) ); values.push_back(deblank(value.substr(i0, i - i0)));
i0 = i + 1; i0 = i + 1;
} }
} }
values.push_back( deblank( value.substr( i0 ) ) ); values.push_back(deblank(value.substr(i0)));
// Convert the string value to the database value // Convert the string value to the database value
std::shared_ptr<KeyData> data; std::shared_ptr<KeyData> data;
if ( value.empty() ) { if (value.empty()) {
data.reset( new EmptyKeyData() ); data.reset(new EmptyKeyData());
} else if ( value.find( '"' ) != std::string::npos ) { } else if (value.find('"') != std::string::npos) {
auto* data2 = new KeyDataString(); auto *data2 = new KeyDataString();
data.reset( data2 ); data.reset(data2);
data2->d_data.resize( values.size() ); data2->d_data.resize(values.size());
for ( size_t i = 0; i < values.size(); i++ ) { for (size_t i = 0; i < values.size(); i++) {
ASSERT( values[i].size() >= 2 ); ASSERT(values[i].size() >= 2);
ASSERT( values[i][0] == '"' && values[i][values[i].size() - 1] == '"' ); ASSERT(values[i][0] == '"' &&
data2->d_data[i] = values[i].substr( 1, values[i].size() - 2 ); values[i][values[i].size() - 1] == '"');
data2->d_data[i] = values[i].substr(1, values[i].size() - 2);
} }
} else if ( lower( value ) == "true" || lower( value ) == "false" ) { } else if (lower(value) == "true" || lower(value) == "false") {
auto* data2 = new KeyDataBool(); auto *data2 = new KeyDataBool();
data.reset( data2 ); data.reset(data2);
data2->d_data.resize( values.size() ); data2->d_data.resize(values.size());
for ( size_t i = 0; i < values.size(); i++ ) { for (size_t i = 0; i < values.size(); i++) {
ASSERT( values[i].size() >= 2 ); ASSERT(values[i].size() >= 2);
if ( lower( values[i] ) != "true" && lower( values[i] ) != "false" ) if (lower(values[i]) != "true" && lower(values[i]) != "false")
ERROR( "Error converting " + key + " to logical array" ); ERROR("Error converting " + key + " to logical array");
data2->d_data[i] = lower( values[i] ) == "true"; data2->d_data[i] = lower(values[i]) == "true";
} }
} else { // if ( value.find('.')!=std::string::npos || value.find('e')!=std::string::npos ) { } else { // if ( value.find('.')!=std::string::npos || value.find('e')!=std::string::npos ) {
auto* data2 = new KeyDataDouble(); auto *data2 = new KeyDataDouble();
data.reset( data2 ); data.reset(data2);
data2->d_data.resize( values.size(), 0 ); data2->d_data.resize(values.size(), 0);
for ( size_t i = 0; i < values.size(); i++ ) { for (size_t i = 0; i < values.size(); i++) {
Units unit; Units unit;
std::tie( data2->d_data[i], unit ) = KeyDataDouble::read( values[i] ); std::tie(data2->d_data[i], unit) = KeyDataDouble::read(values[i]);
if ( !unit.isNull() ) if (!unit.isNull())
data2->d_unit = unit; data2->d_unit = unit;
} }
//} else { //} else {
// ERROR("Unable to determine data type: "+value); // ERROR("Unable to determine data type: "+value);
} }
return std::tuple<size_t, std::shared_ptr<KeyData>>( pos, data ); return std::tuple<size_t, std::shared_ptr<KeyData>>(pos, data);
} }
size_t Database::loadDatabase( const char* buffer, Database& db ) size_t Database::loadDatabase(const char *buffer, Database &db) {
{
size_t pos = 0; size_t pos = 0;
while ( true ) { while (true) {
size_t i; size_t i;
token_type type; token_type type;
std::tie( i, type ) = find_next_token( &buffer[pos] ); std::tie(i, type) = find_next_token(&buffer[pos]);
const std::string key = const std::string key = deblank(
deblank( std::string( &buffer[pos], std::max<int>( i - length( type ), 1 ) - 1 ) ); std::string(&buffer[pos], std::max<int>(i - length(type), 1) - 1));
if ( type == token_type::line_comment || type == token_type::block_start ) { if (type == token_type::line_comment ||
type == token_type::block_start) {
// Comment // Comment
INSIST( key.empty(), "Key should be empty: " + key ); INSIST(key.empty(), "Key should be empty: " + key);
pos += skip_comment( &buffer[pos] ); pos += skip_comment(&buffer[pos]);
} else if ( type == token_type::newline ) { } else if (type == token_type::newline) {
INSIST( key.empty(), "Key should be empty: " + key ); INSIST(key.empty(), "Key should be empty: " + key);
pos += i; pos += i;
} else if ( type == token_type::equal ) { } else if (type == token_type::equal) {
// Reading key/value pair // Reading key/value pair
ASSERT( !key.empty() ); ASSERT(!key.empty());
pos += i; pos += i;
std::shared_ptr<KeyData> data; std::shared_ptr<KeyData> data;
std::tie( i, data ) = read_value( &buffer[pos], key ); std::tie(i, data) = read_value(&buffer[pos], key);
ASSERT( data.get() != nullptr ); ASSERT(data.get() != nullptr);
db.d_data[key] = data; db.d_data[key] = data;
pos += i; pos += i;
} else if ( type == token_type::bracket ) { } else if (type == token_type::bracket) {
// Read database // Read database
ASSERT( !key.empty() ); ASSERT(!key.empty());
pos += i; pos += i;
std::shared_ptr<Database> database( new Database() ); std::shared_ptr<Database> database(new Database());
pos += loadDatabase( &buffer[pos], *database ); pos += loadDatabase(&buffer[pos], *database);
db.d_data[key] = database; db.d_data[key] = database;
} else if ( type == token_type::end_bracket ) { } else if (type == token_type::end_bracket) {
// Finished with the database // Finished with the database
pos += i; pos += i;
break; break;
} else { } else {
ERROR( "Error loading data" ); ERROR("Error loading data");
} }
} }
return pos; return pos;
} }
/******************************************************************** /********************************************************************
* Data type helper functions * * Data type helper functions *
********************************************************************/ ********************************************************************/
void KeyDataDouble::print( std::ostream& os, const std::string& indent ) const void KeyDataDouble::print(std::ostream &os, const std::string &indent) const {
{
os << indent; os << indent;
for ( size_t i = 0; i < d_data.size(); i++ ) { for (size_t i = 0; i < d_data.size(); i++) {
if ( i > 0 ) if (i > 0)
os << ", "; os << ", ";
if ( d_data[i] != d_data[i] ) { if (d_data[i] != d_data[i]) {
os << "nan"; os << "nan";
} else if ( d_data[i] == std::numeric_limits<double>::infinity() ) { } else if (d_data[i] == std::numeric_limits<double>::infinity()) {
os << "inf"; os << "inf";
} else if ( d_data[i] == -std::numeric_limits<double>::infinity() ) { } else if (d_data[i] == -std::numeric_limits<double>::infinity()) {
os << "-inf"; os << "-inf";
} else { } else {
os << std::setprecision( 12 ) << d_data[i]; os << std::setprecision(12) << d_data[i];
} }
} }
if ( !d_unit.isNull() ) if (!d_unit.isNull())
os << " " << d_unit.str(); os << " " << d_unit.str();
os << std::endl; os << std::endl;
} }
std::tuple<double, Units> KeyDataDouble::read( const std::string& str ) std::tuple<double, Units> KeyDataDouble::read(const std::string &str) {
{ std::string tmp = deblank(str);
std::string tmp = deblank( str ); size_t index = tmp.find(" ");
size_t index = tmp.find( " " ); if (index != std::string::npos) {
if ( index != std::string::npos ) { return std::make_tuple(readValue(tmp.substr(0, index)),
return std::make_tuple( Units(tmp.substr(index + 1)));
readValue( tmp.substr( 0, index ) ), Units( tmp.substr( index + 1 ) ) );
} else { } else {
return std::make_tuple( readValue( tmp ), Units() ); return std::make_tuple(readValue(tmp), Units());
} }
} }
double KeyDataDouble::readValue( const std::string& str ) double KeyDataDouble::readValue(const std::string &str) {
{ const std::string tmp = lower(str);
const std::string tmp = lower( str ); double data = 0;
double data = 0; if (tmp == "inf" || tmp == "infinity") {
if ( tmp == "inf" || tmp == "infinity" ) {
data = std::numeric_limits<double>::infinity(); data = std::numeric_limits<double>::infinity();
} else if ( tmp == "-inf" || tmp == "-infinity" ) { } else if (tmp == "-inf" || tmp == "-infinity") {
data = -std::numeric_limits<double>::infinity(); data = -std::numeric_limits<double>::infinity();
} else if ( tmp == "nan" ) { } else if (tmp == "nan") {
data = std::numeric_limits<double>::quiet_NaN(); data = std::numeric_limits<double>::quiet_NaN();
} else if ( tmp.find( '/' ) != std::string::npos ) { } else if (tmp.find('/') != std::string::npos) {
ERROR( "Error reading value" ); ERROR("Error reading value");
} else { } else {
char* pos = nullptr; char *pos = nullptr;
data = strtod( tmp.c_str(), &pos ); data = strtod(tmp.c_str(), &pos);
if ( static_cast<size_t>( pos - tmp.c_str() ) == tmp.size() + 1 ) if (static_cast<size_t>(pos - tmp.c_str()) == tmp.size() + 1)
ERROR( "Error reading value" ); ERROR("Error reading value");
} }
return data; return data;
} }
/******************************************************************** /********************************************************************
* Instantiations * * Instantiations *
********************************************************************/ ********************************************************************/
template std::vector<char> Database::getVector<char>( const std::string&, const Units& ) const; template std::vector<char> Database::getVector<char>(const std::string &,
template std::vector<int> Database::getVector<int>( const std::string&, const Units& ) const; const Units &) const;
template std::vector<size_t> Database::getVector<size_t>( const std::string&, const Units& ) const; template std::vector<int> Database::getVector<int>(const std::string &,
template std::vector<float> Database::getVector<float>( const std::string&, const Units& ) const; const Units &) const;
template std::vector<double> Database::getVector<double>( const std::string&, const Units& ) const; template std::vector<size_t> Database::getVector<size_t>(const std::string &,
template void Database::putVector<char>( const Units &) const;
const std::string&, const std::vector<char>&, const Units& ); template std::vector<float> Database::getVector<float>(const std::string &,
template void Database::putVector<int>( const std::string&, const std::vector<int>&, const Units& ); const Units &) const;
template void Database::putVector<size_t>( template std::vector<double> Database::getVector<double>(const std::string &,
const std::string&, const std::vector<size_t>&, const Units& ); const Units &) const;
template void Database::putVector<float>( template void Database::putVector<char>(const std::string &,
const std::string&, const std::vector<float>&, const Units& ); const std::vector<char> &,
template void Database::putVector<double>( const Units &);
const std::string&, const std::vector<double>&, const Units& ); template void Database::putVector<int>(const std::string &,
template bool Database::isType<int>( const std::string& ) const; const std::vector<int> &, const Units &);
template bool Database::isType<float>( const std::string& ) const; template void Database::putVector<size_t>(const std::string &,
template bool Database::isType<double>( const std::string& ) const; const std::vector<size_t> &,
template bool Database::isType<std::string>( const std::string& ) const; const Units &);
template void Database::putVector<float>(const std::string &,
const std::vector<float> &,
const Units &);
template void Database::putVector<double>(const std::string &,
const std::vector<double> &,
const Units &);
template bool Database::isType<int>(const std::string &) const;
template bool Database::isType<float>(const std::string &) const;
template bool Database::isType<double>(const std::string &) const;
template bool Database::isType<std::string>(const std::string &) const;

View File

@ -26,17 +26,13 @@
#include "common/Units.h" #include "common/Units.h"
inline bool exists(const std::string &filename) {
inline bool exists( const std::string& filename ) std::ifstream domain(filename);
{ return domain.good();
std::ifstream domain( filename );
return domain.good();
} }
//! Base class to hold data of a given type //! Base class to hold data of a given type
class KeyData class KeyData {
{
protected: protected:
//! Empty constructor //! Empty constructor
KeyData() {} KeyData() {}
@ -47,19 +43,18 @@ public:
//! Copy the data //! Copy the data
virtual std::shared_ptr<KeyData> clone() const = 0; virtual std::shared_ptr<KeyData> clone() const = 0;
//! Print the data to a stream //! Print the data to a stream
virtual void print( std::ostream& os, const std::string& indent = "" ) const = 0; virtual void print(std::ostream &os,
const std::string &indent = "") const = 0;
//! Return the native data type //! Return the native data type
virtual std::string type() const = 0; virtual std::string type() const = 0;
protected: protected:
KeyData( const KeyData& ) {} KeyData(const KeyData &) {}
KeyData& operator=( const KeyData& ); KeyData &operator=(const KeyData &);
}; };
//! Class to a database //! Class to a database
class Database : public KeyData class Database : public KeyData {
{
public: public:
//! Empty constructor //! Empty constructor
Database(); Database();
@ -68,25 +63,25 @@ public:
* Open an database file. * Open an database file.
* @param filename Name of input file to open * @param filename Name of input file to open
*/ */
explicit Database( const std::string& filename ); explicit Database(const std::string &filename);
/** /**
* Create database from string * Create database from string
* @param data String containing the database data * @param data String containing the database data
*/ */
static std::shared_ptr<Database> createFromString( const std::string& data ); static std::shared_ptr<Database> createFromString(const std::string &data);
//! Copy constructor //! Copy constructor
Database( const Database& ); Database(const Database &);
//! Assignment operator //! Assignment operator
Database& operator=( const Database& ); Database &operator=(const Database &);
//! Move constructor //! Move constructor
Database( Database&& rhs ); Database(Database &&rhs);
//! Move assignment operator //! Move assignment operator
Database& operator=( Database&& rhs ); Database &operator=(Database &&rhs);
//! Destructor //! Destructor
virtual ~Database(); virtual ~Database();
@ -97,25 +92,21 @@ public:
//! Copy the data //! Copy the data
std::shared_ptr<Database> cloneDatabase() const; std::shared_ptr<Database> cloneDatabase() const;
/** /**
* Return true if the specified key exists in the database and false * Return true if the specified key exists in the database and false
* otherwise. * otherwise.
* @param[in] key Key name to lookup. * @param[in] key Key name to lookup.
*/ */
bool keyExists( const std::string& key ) const; bool keyExists(const std::string &key) const;
/** /**
* Return all keys in the database. * Return all keys in the database.
*/ */
std::vector<std::string> getAllKeys() const; std::vector<std::string> getAllKeys() const;
//! Return the number of entries in the database //! Return the number of entries in the database
size_t size() const { return d_data.size(); } size_t size() const { return d_data.size(); }
/** /**
* Get the scalar entry from the database with the specified key * Get the scalar entry from the database with the specified key
* name. If the specified key does not exist in the database or * name. If the specified key does not exist in the database or
@ -125,14 +116,14 @@ public:
* @param[in] key Key name in database. * @param[in] key Key name in database.
* @param[in] unit Desired units * @param[in] unit Desired units
*/ */
template<class TYPE> template <class TYPE>
inline TYPE getScalar( const std::string& key, const Units& unit = Units() ) const; inline TYPE getScalar(const std::string &key,
const Units &unit = Units()) const;
/// @copydoc Database::getScalar(const std::string&,const Units&) const /// @copydoc Database::getScalar(const std::string&,const Units&) const
template<class TYPE> template <class TYPE>
inline TYPE getScalar( const std::string& key, const std::string& unit ) const; inline TYPE getScalar(const std::string &key,
const std::string &unit) const;
/** /**
* Get the scalar entry from the database with the specified key * Get the scalar entry from the database with the specified key
@ -143,16 +134,14 @@ public:
* @param[in] value Default value * @param[in] value Default value
* @param[in] unit Desired units * @param[in] unit Desired units
*/ */
template<class TYPE> template <class TYPE>
inline TYPE getWithDefault( inline TYPE getWithDefault(const std::string &key, const TYPE &value,
const std::string& key, const TYPE& value, const Units& unit = Units() ) const; const Units &unit = Units()) const;
/// @copydoc Database::getWithDefault(const std::string&,const TYPE&,const Units&) const /// @copydoc Database::getWithDefault(const std::string&,const TYPE&,const Units&) const
template<class TYPE> template <class TYPE>
inline TYPE getWithDefault( inline TYPE getWithDefault(const std::string &key, const TYPE &value,
const std::string& key, const TYPE& value, const std::string& unit ) const; const std::string &unit) const;
/** /**
* Put the scalar entry into the database with the specified key name. * Put the scalar entry into the database with the specified key name.
@ -160,9 +149,9 @@ public:
* @param value Value to store * @param value Value to store
* @param unit Desired units * @param unit Desired units
*/ */
template<class TYPE> template <class TYPE>
inline void putScalar( const std::string& key, const TYPE& value, const Units& unit = Units() ); inline void putScalar(const std::string &key, const TYPE &value,
const Units &unit = Units());
/** /**
* Put the scalar entry into the database with the specified key name. * Put the scalar entry into the database with the specified key name.
@ -170,9 +159,9 @@ public:
* @param value Value to store * @param value Value to store
* @param unit Desired units * @param unit Desired units
*/ */
template<class TYPE> template <class TYPE>
inline void putScalar( const std::string& key, const TYPE& value, const std::string& unit ); inline void putScalar(const std::string &key, const TYPE &value,
const std::string &unit);
/** /**
* Get the vector entries from the database with the specified key * Get the vector entries from the database with the specified key
@ -183,14 +172,14 @@ public:
* @param key Key name in database. * @param key Key name in database.
* @param unit Desired units * @param unit Desired units
*/ */
template<class TYPE> template <class TYPE>
std::vector<TYPE> getVector( const std::string& key, const Units& unit = Units() ) const; std::vector<TYPE> getVector(const std::string &key,
const Units &unit = Units()) const;
/// @copydoc Database::getVector(const std::string&,const Units&) const /// @copydoc Database::getVector(const std::string&,const Units&) const
template<class TYPE> template <class TYPE>
inline std::vector<TYPE> getVector( const std::string& key, const std::string& unit ) const; inline std::vector<TYPE> getVector(const std::string &key,
const std::string &unit) const;
/** /**
* Put the vector entries into the database with the specified key * Put the vector entries into the database with the specified key
@ -202,16 +191,14 @@ public:
* @param data Data to store * @param data Data to store
* @param unit Desired units * @param unit Desired units
*/ */
template<class TYPE> template <class TYPE>
void putVector( void putVector(const std::string &key, const std::vector<TYPE> &data,
const std::string& key, const std::vector<TYPE>& data, const Units& unit = Units() ); const Units &unit = Units());
/// @copydoc Database::putVector(const std::string&,const std::vector<TYPE>&,const Units&) /// @copydoc Database::putVector(const std::string&,const std::vector<TYPE>&,const Units&)
template<class TYPE> template <class TYPE>
inline void putVector( inline void putVector(const std::string &key, const std::vector<TYPE> &data,
const std::string& key, const std::vector<TYPE>& data, const std::string& unit ); const std::string &unit);
/** /**
* Get the data for a key in the database. If the specified key * Get the data for a key in the database. If the specified key
@ -220,7 +207,7 @@ public:
* *
* @param key Key name in database. * @param key Key name in database.
*/ */
std::shared_ptr<KeyData> getData( const std::string& key ); std::shared_ptr<KeyData> getData(const std::string &key);
/** /**
* Get the data for a key in the database. If the specified key * Get the data for a key in the database. If the specified key
@ -229,8 +216,7 @@ public:
* *
* @param key Key name in database. * @param key Key name in database.
*/ */
std::shared_ptr<const KeyData> getData( const std::string& key ) const; std::shared_ptr<const KeyData> getData(const std::string &key) const;
/** /**
* Put the data for a key in the database. * Put the data for a key in the database.
@ -238,17 +224,13 @@ public:
* @param key Key name in database. * @param key Key name in database.
* @param data Data to store * @param data Data to store
*/ */
void putData( const std::string& key, std::shared_ptr<KeyData> data ); void putData(const std::string &key, std::shared_ptr<KeyData> data);
// Check if the key is a database object // Check if the key is a database object
bool isDatabase( const std::string& key ) const; bool isDatabase(const std::string &key) const;
// Check if the entry can be stored as the given type // Check if the entry can be stored as the given type
template<class TYPE> template <class TYPE> bool isType(const std::string &key) const;
bool isType( const std::string& key ) const;
/** /**
* Get the database for a key in the database. If the specified key * Get the database for a key in the database. If the specified key
@ -257,7 +239,7 @@ public:
* *
* @param key Key name in database. * @param key Key name in database.
*/ */
std::shared_ptr<Database> getDatabase( const std::string& key ); std::shared_ptr<Database> getDatabase(const std::string &key);
/** /**
* Get the database for a key in the database. If the specified key * Get the database for a key in the database. If the specified key
@ -266,8 +248,7 @@ public:
* *
* @param key Key name in database. * @param key Key name in database.
*/ */
std::shared_ptr<const Database> getDatabase( const std::string& key ) const; std::shared_ptr<const Database> getDatabase(const std::string &key) const;
/** /**
* Get the database for a key in the database. If the specified key * Get the database for a key in the database. If the specified key
@ -277,36 +258,32 @@ public:
* @param key Key name in database. * @param key Key name in database.
* @param db Database to store * @param db Database to store
*/ */
void putDatabase( const std::string& key, std::shared_ptr<Database> db ); void putDatabase(const std::string &key, std::shared_ptr<Database> db);
/** /**
* Print the data to a stream * Print the data to a stream
* @param os Output stream * @param os Output stream
* @param indent Indenting to use before each line * @param indent Indenting to use before each line
*/ */
virtual void print( std::ostream& os, const std::string& indent = "" ) const override; virtual void print(std::ostream &os,
const std::string &indent = "") const override;
//! Print the type //! Print the type
virtual std::string type() const override { return "database"; } virtual std::string type() const override { return "database"; }
/** /**
* Print the data to a string * Print the data to a string
* @return Output string * @return Output string
*/ */
std::string print( const std::string& indent = "" ) const; std::string print(const std::string &indent = "") const;
protected: protected:
std::map<std::string, std::shared_ptr<KeyData>> d_data; std::map<std::string, std::shared_ptr<KeyData>> d_data;
// Function to load a database from a buffer // Function to load a database from a buffer
static size_t loadDatabase( const char* buffer, Database& db ); static size_t loadDatabase(const char *buffer, Database &db);
}; };
#include "common/Database.hpp" #include "common/Database.hpp"
#endif #endif

View File

@ -38,66 +38,58 @@
#include <tuple> #include <tuple>
/******************************************************************** /********************************************************************
* Basic classes for primative data types * * Basic classes for primative data types *
********************************************************************/ ********************************************************************/
class EmptyKeyData : public KeyData class EmptyKeyData : public KeyData {
{
public: public:
EmptyKeyData() {} EmptyKeyData() {}
virtual ~EmptyKeyData() {} virtual ~EmptyKeyData() {}
virtual std::shared_ptr<KeyData> clone() const override virtual std::shared_ptr<KeyData> clone() const override {
{
return std::make_shared<EmptyKeyData>(); return std::make_shared<EmptyKeyData>();
} }
virtual void print( std::ostream& os, const std::string& = "" ) const override virtual void print(std::ostream &os,
{ const std::string & = "") const override {
os << std::endl; os << std::endl;
} }
virtual std::string type() const override { return ""; } virtual std::string type() const override { return ""; }
}; };
class KeyDataDouble : public KeyData class KeyDataDouble : public KeyData {
{
public: public:
KeyDataDouble() {} KeyDataDouble() {}
explicit KeyDataDouble( const std::vector<double>& data, const Units& unit ) explicit KeyDataDouble(const std::vector<double> &data, const Units &unit)
: d_data( data ), d_unit( unit ) : d_data(data), d_unit(unit) {}
{
}
virtual ~KeyDataDouble() {} virtual ~KeyDataDouble() {}
virtual std::shared_ptr<KeyData> clone() const override virtual std::shared_ptr<KeyData> clone() const override {
{ return std::make_shared<KeyDataDouble>(d_data, d_unit);
return std::make_shared<KeyDataDouble>( d_data, d_unit );
} }
virtual void print( std::ostream& os, const std::string& indent = "" ) const override; virtual void print(std::ostream &os,
const std::string &indent = "") const override;
virtual std::string type() const override { return "double"; } virtual std::string type() const override { return "double"; }
static std::tuple<double, Units> read( const std::string& ); static std::tuple<double, Units> read(const std::string &);
static double readValue( const std::string& ); static double readValue(const std::string &);
public: public:
std::vector<double> d_data; std::vector<double> d_data;
Units d_unit; Units d_unit;
}; };
class KeyDataBool : public KeyData class KeyDataBool : public KeyData {
{
public: public:
KeyDataBool() {} KeyDataBool() {}
explicit KeyDataBool( const std::vector<bool>& data ) : d_data( data ) {} explicit KeyDataBool(const std::vector<bool> &data) : d_data(data) {}
virtual ~KeyDataBool() {} virtual ~KeyDataBool() {}
virtual std::shared_ptr<KeyData> clone() const override virtual std::shared_ptr<KeyData> clone() const override {
{ return std::make_shared<KeyDataBool>(d_data);
return std::make_shared<KeyDataBool>( d_data );
} }
virtual void print( std::ostream& os, const std::string& indent = "" ) const override virtual void print(std::ostream &os,
{ const std::string &indent = "") const override {
os << indent; os << indent;
for ( size_t i = 0; i < d_data.size(); i++ ) { for (size_t i = 0; i < d_data.size(); i++) {
if ( i > 0 ) { if (i > 0) {
os << ", "; os << ", ";
} }
if ( d_data[i] ) { if (d_data[i]) {
os << "true"; os << "true";
} else { } else {
os << "false"; os << "false";
@ -108,21 +100,20 @@ public:
virtual std::string type() const override { return "bool"; } virtual std::string type() const override { return "bool"; }
std::vector<bool> d_data; std::vector<bool> d_data;
}; };
class KeyDataString : public KeyData class KeyDataString : public KeyData {
{
public: public:
KeyDataString() {} KeyDataString() {}
explicit KeyDataString( const std::vector<std::string>& data ) : d_data( data ) {} explicit KeyDataString(const std::vector<std::string> &data)
: d_data(data) {}
virtual ~KeyDataString() {} virtual ~KeyDataString() {}
virtual std::shared_ptr<KeyData> clone() const override virtual std::shared_ptr<KeyData> clone() const override {
{ return std::make_shared<KeyDataString>(d_data);
return std::make_shared<KeyDataString>( d_data );
} }
virtual void print( std::ostream& os, const std::string& indent = "" ) const override virtual void print(std::ostream &os,
{ const std::string &indent = "") const override {
os << indent; os << indent;
for ( size_t i = 0; i < d_data.size(); i++ ) { for (size_t i = 0; i < d_data.size(); i++) {
if ( i > 0 ) { if (i > 0) {
os << ", "; os << ", ";
} }
os << '"' << d_data[i] << '"'; os << '"' << d_data[i] << '"';
@ -133,73 +124,66 @@ public:
std::vector<std::string> d_data; std::vector<std::string> d_data;
}; };
/******************************************************************** /********************************************************************
* Get a vector * * Get a vector *
********************************************************************/ ********************************************************************/
template<class TYPE> template <class TYPE>
inline std::vector<TYPE> Database::getVector( inline std::vector<TYPE> Database::getVector(const std::string &key,
const std::string& key, const std::string& unit ) const const std::string &unit) const {
{ return getVector<TYPE>(key, Units(unit));
return getVector<TYPE>( key, Units( unit ) );
} }
template<class TYPE> template <class TYPE>
inline void Database::putVector( inline void Database::putVector(const std::string &key,
const std::string& key, const std::vector<TYPE>& data, const std::string& unit ) const std::vector<TYPE> &data,
{ const std::string &unit) {
putVector<TYPE>( key, data, Units( unit ) ); putVector<TYPE>(key, data, Units(unit));
} }
/******************************************************************** /********************************************************************
* Get a scalar * * Get a scalar *
********************************************************************/ ********************************************************************/
template<class TYPE> template <class TYPE>
inline TYPE Database::getScalar( const std::string& key, const Units& unit ) const inline TYPE Database::getScalar(const std::string &key,
{ const Units &unit) const {
const std::vector<TYPE>& data = getVector<TYPE>( key, unit ); const std::vector<TYPE> &data = getVector<TYPE>(key, unit);
if ( data.size() != 1 ) { if (data.size() != 1) {
char msg[1000]; char msg[1000];
sprintf( msg, "Variable %s is not a scalar", key.c_str() ); sprintf(msg, "Variable %s is not a scalar", key.c_str());
ERROR( msg ); ERROR(msg);
} }
return data[0]; return data[0];
} }
template<class TYPE> template <class TYPE>
inline TYPE Database::getWithDefault( inline TYPE Database::getWithDefault(const std::string &key, const TYPE &value,
const std::string& key, const TYPE& value, const Units& unit ) const const Units &unit) const {
{ if (!keyExists(key))
if ( !keyExists( key ) )
return value; return value;
return getScalar<TYPE>( key, unit ); return getScalar<TYPE>(key, unit);
} }
template<class TYPE> template <class TYPE>
inline void Database::putScalar( const std::string& key, const TYPE& data, const Units& unit ) inline void Database::putScalar(const std::string &key, const TYPE &data,
{ const Units &unit) {
putVector<TYPE>( key, std::vector<TYPE>( 1, data ), unit ); putVector<TYPE>(key, std::vector<TYPE>(1, data), unit);
} }
template<class TYPE> template <class TYPE>
inline TYPE Database::getScalar( const std::string& key, const std::string& unit ) const inline TYPE Database::getScalar(const std::string &key,
{ const std::string &unit) const {
return getScalar<TYPE>( key, Units( unit ) ); return getScalar<TYPE>(key, Units(unit));
} }
template<class TYPE> template <class TYPE>
inline TYPE Database::getWithDefault( inline TYPE Database::getWithDefault(const std::string &key, const TYPE &value,
const std::string& key, const TYPE& value, const std::string& unit ) const const std::string &unit) const {
{ return getWithDefault<TYPE>(key, value, Units(unit));
return getWithDefault<TYPE>( key, value, Units( unit ) );
} }
template<class TYPE> template <class TYPE>
inline void Database::putScalar( const std::string& key, const TYPE& data, const std::string& unit ) inline void Database::putScalar(const std::string &key, const TYPE &data,
{ const std::string &unit) {
putScalar<TYPE>( key, data, Units( unit ) ); putScalar<TYPE>(key, data, Units(unit));
} }
template<class TYPE> template <class TYPE>
inline void putVector( inline void putVector(const std::string &key, const std::vector<TYPE> &data,
const std::string& key, const std::vector<TYPE>& data, const std::string& unit ) const std::string &unit) {
{ putVector<TYPE>(key, data, Units(unit));
putVector<TYPE>( key, data, Units( unit ) );
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,6 @@
* \brief Parallel Domain data structures and helper functions * \brief Parallel Domain data structures and helper functions
*/ */
/** /**
* \class Box * \class Box
* *
@ -63,20 +62,20 @@ class Patch;
* GPU-based data structures should be constructed separately but may utilize information that the Domain class provides. * GPU-based data structures should be constructed separately but may utilize information that the Domain class provides.
*/ */
class Domain{ class Domain {
public: public:
/** /**
* \brief Constructor * \brief Constructor
* @param db input database * @param db input database
* @param Communicator MPI communicator * @param Communicator MPI communicator
*/ */
Domain( std::shared_ptr<Database> db, const Utilities::MPI& Communicator); Domain(std::shared_ptr<Database> db, const Utilities::MPI &Communicator);
/** /**
* \brief Obsolete constructor * \brief Obsolete constructor
*/ */
Domain( int nx, int ny, int nz, int rnk, int npx, int npy, int npz, Domain(int nx, int ny, int nz, int rnk, int npx, int npy, int npz,
double lx, double ly, double lz, int BC); double lx, double ly, double lz, int BC);
/** /**
* \brief Empty constructor * \brief Empty constructor
@ -86,18 +85,18 @@ public:
/** /**
* \brief Copy constructor * \brief Copy constructor
*/ */
Domain( const Domain& ) = delete; Domain(const Domain &) = delete;
/** /**
* \brief Assignment operator * \brief Assignment operator
*/ */
Domain& operator=( const Domain& ) = delete; Domain &operator=(const Domain &) = delete;
/** /**
* \brief Destructor * \brief Destructor
*/ */
~Domain(); ~Domain();
/** /**
* \brief Get the database * \brief Get the database
*/ */
@ -106,37 +105,33 @@ public:
/** /**
* \brief Get the domain box * \brief Get the domain box
*/ */
inline const Box& getBox() const { return d_box; } inline const Box &getBox() const { return d_box; }
/** /**
* \brief Get local patch * \brief Get local patch
*/ */
inline const Patch& getLocalPatch() const { return *d_localPatch; } inline const Patch &getLocalPatch() const { return *d_localPatch; }
/** /**
* \brief Get all patches * \brief Get all patches
*/ */
inline const std::vector<Patch>& getAllPatch() const { return d_patches; } inline const std::vector<Patch> &getAllPatch() const { return d_patches; }
private: private:
/** /**
* \brief initialize from database * \brief initialize from database
*/ */
void initialize( std::shared_ptr<Database> db ); void initialize(std::shared_ptr<Database> db);
std::shared_ptr<Database> d_db; std::shared_ptr<Database> d_db;
Box d_box; Box d_box;
Patch *d_localPatch; Patch *d_localPatch;
std::vector<Patch> d_patches; std::vector<Patch> d_patches;
public: // Public variables (need to create accessors instead) public: // Public variables (need to create accessors instead)
std::shared_ptr<Database> database; std::shared_ptr<Database> database;
double Lx,Ly,Lz,Volume,voxel_length; double Lx, Ly, Lz, Volume, voxel_length;
int Nx,Ny,Nz,N; int Nx, Ny, Nz, N;
int inlet_layers_x, inlet_layers_y, inlet_layers_z; int inlet_layers_x, inlet_layers_y, inlet_layers_z;
int outlet_layers_x, outlet_layers_y, outlet_layers_z; int outlet_layers_x, outlet_layers_y, outlet_layers_z;
int inlet_layers_phase; //as usual: 1->n, 2->w int inlet_layers_phase; //as usual: 1->n, 2->w
@ -144,7 +139,7 @@ public: // Public variables (need to create accessors instead)
double porosity; double porosity;
RankInfoStruct rank_info; RankInfoStruct rank_info;
Utilities::MPI Comm; // MPI Communicator for this domain Utilities::MPI Comm; // MPI Communicator for this domain
int BoundaryCondition; int BoundaryCondition;
@ -153,7 +148,7 @@ public: // Public variables (need to create accessors instead)
//********************************** //**********************************
/** /**
* \brief Compute the porosity based on the current domain id file * \brief Compute the porosity based on the current domain id file
*/ */
inline double Porosity() const { return porosity; } inline double Porosity() const { return porosity; }
inline int iproc() const { return rank_info.ix; } inline int iproc() const { return rank_info.ix; }
inline int jproc() const { return rank_info.jy; } inline int jproc() const { return rank_info.jy; }
@ -186,70 +181,78 @@ public: // Public variables (need to create accessors instead)
// Get the actual D3Q19 communication counts (based on location of solid phase) // Get the actual D3Q19 communication counts (based on location of solid phase)
// Discrete velocity set symmetry implies the sendcount = recvcount // Discrete velocity set symmetry implies the sendcount = recvcount
//...................................................................................... //......................................................................................
inline int recvCount( const char* dir ) const { return getRecvList( dir ).size(); } inline int recvCount(const char *dir) const {
inline int sendCount( const char* dir ) const { return getSendList( dir ).size(); } return getRecvList(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(); } 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();
}
//...................................................................................... //......................................................................................
// Solid indicator function // Solid indicator function
std::vector<signed char> id; std::vector<signed char> id;
/** /**
* \brief Read domain IDs from file * \brief Read domain IDs from file
*/ */
void ReadIDs(); void ReadIDs();
/** /**
* \brief Compute the porosity * \brief Compute the porosity
*/ */
void ComputePorosity(); void ComputePorosity();
/** /**
* \brief Read image and perform domain decomposition * \brief Read image and perform domain decomposition
* @param filename - name of file to read IDs * @param filename - name of file to read IDs
*/ */
void Decomp( const std::string& filename ); void Decomp(const std::string &filename);
/** /**
* \brief Perform a halo exchange using MPI * \brief Perform a halo exchange using MPI
* @param Mesh - array data that holds scalar values * @param Mesh - array data that holds scalar values
*/ */
void CommunicateMeshHalo(DoubleArray &Mesh); void CommunicateMeshHalo(DoubleArray &Mesh);
/** /**
* \brief Initialize communication data structures within Domain object. * \brief Initialize communication data structures within Domain object.
* This routine needs to be called before the communication functionality will work * This routine needs to be called before the communication functionality will work
*/ */
void CommInit(); void CommInit();
/** /**
* \brief Count number of pore nodes (labels > 1) * \brief Count number of pore nodes (labels > 1)
*/ */
int PoreCount(); int PoreCount();
/** /**
* \brief Read array data from a file and distribute to local arrays for each MPI process * \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 Filename - name of the file to read the data
* @param Datatype - data type to use * @param Datatype - data type to use
* @param UserData - Array to store the values that are read * @param UserData - Array to store the values that are read
*/ */
void ReadFromFile(const std::string& Filename,const std::string& Datatype, double *UserData); void ReadFromFile(const std::string &Filename, const std::string &Datatype,
double *UserData);
/** /**
* \brief Aggregate labels from all MPI processes and write to a file * \brief Aggregate labels from all MPI processes and write to a file
* @param filename - name of the file to write * @param filename - name of the file to write
*/ */
void AggregateLabels( const std::string& filename ); void AggregateLabels(const std::string &filename);
/** /**
* \brief Aggregate user provided array from all MPI processes and write to a single file * \brief Aggregate user provided array from all MPI processes and write to a single file
* @param filename - name of the file to write * @param filename - name of the file to write
* @param UserData - array data to aggregate and write * @param UserData - array data to aggregate and write
*/ */
void AggregateLabels( const std::string& filename, DoubleArray &UserData ); void AggregateLabels(const std::string &filename, DoubleArray &UserData);
private: private:
/** /**
* \brief Pack halo data for 8-bit integer * \brief Pack halo data for 8-bit integer
* @param list - list of values in the halo * @param list - list of values in the halo
@ -258,7 +261,7 @@ private:
* @param ID - 8-bit values on mesh [Nx, Ny, Nz] * @param ID - 8-bit values on mesh [Nx, Ny, Nz]
*/ */
void PackID(int *list, int count, signed char *sendbuf, signed char *ID); void PackID(int *list, int count, signed char *sendbuf, signed char *ID);
/** /**
* \brief Unpack halo data for 8-bit integer * \brief Unpack halo data for 8-bit integer
* @param list - list of values in the halo * @param list - list of values in the halo
@ -267,29 +270,32 @@ private:
* @param ID - 8-bit values on mesh [Nx, Ny, Nz] * @param ID - 8-bit values on mesh [Nx, Ny, Nz]
*/ */
void UnpackID(int *list, int count, signed char *recvbuf, signed char *ID); void UnpackID(int *list, int count, signed char *recvbuf, signed char *ID);
//......................................................................................
MPI_Request req1[18], req2[18];
//......................................................................................
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;
//......................................................................................
const std::vector<int>& getRecvList( const char* dir ) const;
const std::vector<int>& getSendList( const char* dir ) const;
//......................................................................................
MPI_Request req1[18], req2[18];
//......................................................................................
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;
//......................................................................................
const std::vector<int> &getRecvList(const char *dir) const;
const std::vector<int> &getSendList(const char *dir) const;
}; };
template<class TYPE> class PatchData; template <class TYPE> class PatchData;
enum class DataLocation { CPU, DEVICE }; enum class DataLocation { CPU, DEVICE };
/** /**
* \class Patch * \class Patch
* *
@ -298,44 +304,40 @@ enum class DataLocation { CPU, DEVICE };
*/ */
class Patch { class Patch {
public: public:
//! Empty constructor //! Empty constructor
Patch() = delete; Patch() = delete;
//! Copy constructor //! Copy constructor
Patch( const Patch& ) = delete; Patch(const Patch &) = delete;
//! Assignment operator //! Assignment operator
Patch& operator=( const Patch& ) = delete; Patch &operator=(const Patch &) = delete;
//! Return the box for the patch //! Return the box for the patch
inline const Box& getBox() const { return d_box; } inline const Box &getBox() const { return d_box; }
//! Create patch data //! Create patch data
template<class TYPE> template <class TYPE>
std::shared_ptr<PatchData<TYPE>> createPatchData( DataLocation location ) const; std::shared_ptr<PatchData<TYPE>>
createPatchData(DataLocation location) const;
private: private:
Box d_box; Box d_box;
int d_owner; int d_owner;
Domain *d_domain; Domain *d_domain;
}; };
// Class to hold data on a patch // Class to hold data on a patch
template<class TYPE> template <class TYPE> class PatchData {
class PatchData {
public: public:
//! Get the raw data pointer
TYPE *data() { return d_data; }
//! Get the raw data pointer //! Get the raw data pointer
TYPE* data() { return d_data; } const TYPE *data() const { return d_data; }
//! Get the raw data pointer
const TYPE* data() const { return d_data; }
//! Get the patch //! Get the patch
const Patch& getPatch() const { return *d_patch; } const Patch &getPatch() const { return *d_patch; }
//! Start communication //! Start communication
void beginCommunication(); void beginCommunication();
@ -344,20 +346,20 @@ public:
void endCommunication(); void endCommunication();
//! Access ghost values //! Access ghost values
TYPE operator()( int, int, int ) const; TYPE operator()(int, int, int) const;
//! Copy data from another PatchData //! Copy data from another PatchData
void copy( const PatchData& rhs ); void copy(const PatchData &rhs);
private: private:
DataLocation d_location; DataLocation d_location;
const Patch *d_patch; const Patch *d_patch;
TYPE *d_data; TYPE *d_data;
TYPE *d_gcw; TYPE *d_gcw;
}; };
void WriteCheckpoint(const char *FILENAME, const double *cDen, const double *cfq, size_t Np); void WriteCheckpoint(const char *FILENAME, const double *cDen,
const double *cfq, size_t Np);
void ReadCheckpoint(char *FILENAME, double *cDen, double *cfq, size_t Np); void ReadCheckpoint(char *FILENAME, double *cDen, double *cfq, size_t Np);

View File

@ -1,6 +1,5 @@
#include "FunctionTable.hpp" #include "FunctionTable.hpp"
/******************************************************** /********************************************************
* Random number generation * * Random number generation *
********************************************************/ ********************************************************/
@ -93,55 +92,36 @@ template<> long double genRand<long double>()
/******************************************************** /********************************************************
* axpy * * axpy *
********************************************************/ ********************************************************/
template<> template <>
void call_axpy<float>( size_t N, const float alpha, const float *x, float *y ) void call_axpy<float>(size_t N, const float alpha, const float *x, float *y) {
{
ERROR("Not finished"); ERROR("Not finished");
} }
template<> template <>
void call_axpy<double>( size_t N, const double alpha, const double *x, double *y ) void call_axpy<double>(size_t N, const double alpha, const double *x,
{ double *y) {
ERROR("Not finished"); ERROR("Not finished");
} }
/******************************************************** /********************************************************
* Multiply two arrays * * Multiply two arrays *
********************************************************/ ********************************************************/
template<> template <>
void call_gemv<double>( void call_gemv<double>(size_t M, size_t N, double alpha, double beta,
size_t M, size_t N, double alpha, double beta, const double *A, const double *x, double *y ) const double *A, const double *x, double *y) {
{
ERROR("Not finished"); ERROR("Not finished");
} }
template<> template <>
void call_gemv<float>( void call_gemv<float>(size_t M, size_t N, float alpha, float beta,
size_t M, size_t N, float alpha, float beta, const float *A, const float *x, float *y ) const float *A, const float *x, float *y) {
{
ERROR("Not finished"); ERROR("Not finished");
} }
template<> template <>
void call_gemm<double>( size_t M, void call_gemm<double>(size_t M, size_t N, size_t K, double alpha, double beta,
size_t N, const double *A, const double *B, double *C) {
size_t K,
double alpha,
double beta,
const double *A,
const double *B,
double *C )
{
ERROR("Not finished"); ERROR("Not finished");
} }
template<> template <>
void call_gemm<float>( size_t M, void call_gemm<float>(size_t M, size_t N, size_t K, float alpha, float beta,
size_t N, const float *A, const float *B, float *C) {
size_t K,
float alpha,
float beta,
const float *A,
const float *B,
float *C )
{
ERROR("Not finished"); ERROR("Not finished");
} }

View File

@ -17,28 +17,23 @@
#ifndef included_FunctionTable #ifndef included_FunctionTable
#define included_FunctionTable #define included_FunctionTable
#include "common/ArraySize.h" #include "common/ArraySize.h"
#include <functional> #include <functional>
/*! /*!
* Class FunctionTable is a serial function table class that defines * Class FunctionTable is a serial function table class that defines
* a series of operations that can be performed on the Array class. * a series of operations that can be performed on the Array class.
* Users can impliment additional versions of the function table that match * Users can impliment additional versions of the function table that match
* the interface to change the behavior of the array class. * the interface to change the behavior of the array class.
*/ */
class FunctionTable final class FunctionTable final {
{
public: public:
/*! /*!
* Initialize the array with random values * Initialize the array with random values
* @param[in] x The array to operate on * @param[in] x The array to operate on
*/ */
template<class TYPE, class FUN> template <class TYPE, class FUN> static void rand(Array<TYPE, FUN> &x);
static void rand( Array<TYPE, FUN> &x );
/*! /*!
* Perform a reduce operator y = f(x) * Perform a reduce operator y = f(x)
@ -49,8 +44,9 @@ public:
* ...) * ...)
* @return The reduction * @return The reduction
*/ */
template<class TYPE, class FUN, typename LAMBDA> template <class TYPE, class FUN, typename LAMBDA>
static inline TYPE reduce( LAMBDA &op, const Array<TYPE, FUN> &A, const TYPE &initialValue ); static inline TYPE reduce(LAMBDA &op, const Array<TYPE, FUN> &A,
const TYPE &initialValue);
/*! /*!
* Perform a reduce operator z = f(x,y) * Perform a reduce operator z = f(x,y)
@ -62,11 +58,10 @@ public:
* ...) * ...)
* @return The reduction * @return The reduction
*/ */
template<class TYPE, class FUN, typename LAMBDA> template <class TYPE, class FUN, typename LAMBDA>
static inline TYPE reduce( LAMBDA &op, static inline TYPE reduce(LAMBDA &op, const Array<TYPE, FUN> &A,
const Array<TYPE, FUN> &A, const Array<TYPE, FUN> &B,
const Array<TYPE, FUN> &B, const TYPE &initialValue);
const TYPE &initialValue );
/*! /*!
* Perform a element-wise operation y = f(x) * Perform a element-wise operation y = f(x)
@ -75,8 +70,9 @@ public:
* @param[in,out] x The array to operate on * @param[in,out] x The array to operate on
* @param[out] y The output array * @param[out] y The output array
*/ */
template<class TYPE, class FUN, typename LAMBDA> template <class TYPE, class FUN, typename LAMBDA>
static inline void transform( LAMBDA &fun, const Array<TYPE, FUN> &x, Array<TYPE, FUN> &y ); static inline void transform(LAMBDA &fun, const Array<TYPE, FUN> &x,
Array<TYPE, FUN> &y);
/*! /*!
* Perform a element-wise operation z = f(x,y) * Perform a element-wise operation z = f(x,y)
@ -86,11 +82,10 @@ public:
* @param[in] y The second array * @param[in] y The second array
* @param[out] z The output array * @param[out] z The output array
*/ */
template<class TYPE, class FUN, typename LAMBDA> template <class TYPE, class FUN, typename LAMBDA>
static inline void transform( LAMBDA &fun, static inline void transform(LAMBDA &fun, const Array<TYPE, FUN> &x,
const Array<TYPE, FUN> &x, const Array<TYPE, FUN> &y,
const Array<TYPE, FUN> &y, Array<TYPE, FUN> &z);
Array<TYPE, FUN> &z );
/*! /*!
* Multiply two arrays * Multiply two arrays
@ -98,9 +93,9 @@ public:
* @param[in] b The second array * @param[in] b The second array
* @param[out] c The output array * @param[out] c The output array
*/ */
template<class TYPE, class FUN> template <class TYPE, class FUN>
static void static void multiply(const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b,
multiply( const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b, Array<TYPE, FUN> &c ); Array<TYPE, FUN> &c);
/*! /*!
* Perform dgemv/dgemm equavalent operation ( C = alpha*A*B + beta*C ) * Perform dgemv/dgemm equavalent operation ( C = alpha*A*B + beta*C )
@ -110,12 +105,10 @@ public:
* @param[in] beta The scalar value alpha * @param[in] beta The scalar value alpha
* @param[in,out] C The output array C * @param[in,out] C The output array C
*/ */
template<class TYPE, class FUN> template <class TYPE, class FUN>
static void gemm( const TYPE alpha, static void gemm(const TYPE alpha, const Array<TYPE, FUN> &A,
const Array<TYPE, FUN> &A, const Array<TYPE, FUN> &B, const TYPE beta,
const Array<TYPE, FUN> &B, Array<TYPE, FUN> &C);
const TYPE beta,
Array<TYPE, FUN> &C );
/*! /*!
* Perform axpy equavalent operation ( y = alpha*x + y ) * Perform axpy equavalent operation ( y = alpha*x + y )
@ -123,8 +116,9 @@ public:
* @param[in] x The input array x * @param[in] x The input array x
* @param[in,out] y The output array y * @param[in,out] y The output array y
*/ */
template<class TYPE, class FUN> template <class TYPE, class FUN>
static void axpy( const TYPE alpha, const Array<TYPE, FUN> &x, Array<TYPE, FUN> &y ); static void axpy(const TYPE alpha, const Array<TYPE, FUN> &x,
Array<TYPE, FUN> &y);
/*! /*!
* Check if two arrays are approximately equal * Check if two arrays are approximately equal
@ -132,24 +126,15 @@ public:
* @param[in] B The second array * @param[in] B The second array
* @param[in] tol The tolerance * @param[in] tol The tolerance
*/ */
template<class TYPE, class FUN> template <class TYPE, class FUN>
static bool equals( const Array<TYPE, FUN> &A, const Array<TYPE, FUN> &B, TYPE tol ); static bool equals(const Array<TYPE, FUN> &A, const Array<TYPE, FUN> &B,
TYPE tol);
template<class TYPE>
static inline void gemmWrapper( char TRANSA,
char TRANSB,
int M,
int N,
int K,
TYPE alpha,
const TYPE *A,
int LDA,
const TYPE *B,
int LDB,
TYPE beta,
TYPE *C,
int LDC );
template <class TYPE>
static inline void gemmWrapper(char TRANSA, char TRANSB, int M, int N,
int K, TYPE alpha, const TYPE *A, int LDA,
const TYPE *B, int LDB, TYPE beta, TYPE *C,
int LDC);
/* Specialized Functions */ /* Specialized Functions */
@ -158,62 +143,66 @@ public:
* @param[in] A The input array * @param[in] A The input array
* @param[out] B The output array * @param[out] B The output array
*/ */
template<class TYPE, class FUN, class ALLOC> template <class TYPE, class FUN, class ALLOC>
static void transformReLU( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B ); static void transformReLU(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B);
/*! /*!
* Perform a element-wise operation B = |A| * Perform a element-wise operation B = |A|
* @param[in] A The array to operate on * @param[in] A The array to operate on
* @param[out] B The output array * @param[out] B The output array
*/ */
template<class TYPE, class FUN, class ALLOC> template <class TYPE, class FUN, class ALLOC>
static void transformAbs( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B ); static void transformAbs(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B);
/*! /*!
* Perform a element-wise operation B = tanh(A) * Perform a element-wise operation B = tanh(A)
* @param[in] A The array to operate on * @param[in] A The array to operate on
* @param[out] B The output array * @param[out] B The output array
*/ */
template<class TYPE, class FUN, class ALLOC> template <class TYPE, class FUN, class ALLOC>
static void transformTanh( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B ); static void transformTanh(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B);
/*! /*!
* Perform a element-wise operation B = max(-1 , min(1 , A) ) * Perform a element-wise operation B = max(-1 , min(1 , A) )
* @param[in] A The array to operate on * @param[in] A The array to operate on
* @param[out] B The output array * @param[out] B The output array
*/ */
template<class TYPE, class FUN, class ALLOC> template <class TYPE, class FUN, class ALLOC>
static void transformHardTanh( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B ); static void transformHardTanh(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B);
/*! /*!
* Perform a element-wise operation B = 1 / (1 + exp(-A)) * Perform a element-wise operation B = 1 / (1 + exp(-A))
* @param[in] A The array to operate on * @param[in] A The array to operate on
* @param[out] B The output array * @param[out] B The output array
*/ */
template<class TYPE, class FUN, class ALLOC> template <class TYPE, class FUN, class ALLOC>
static void transformSigmoid( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B ); static void transformSigmoid(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B);
/*! /*!
* Perform a element-wise operation B = log(exp(A) + 1) * Perform a element-wise operation B = log(exp(A) + 1)
* @param[in] A The array to operate on * @param[in] A The array to operate on
* @param[out] B The output array * @param[out] B The output array
*/ */
template<class TYPE, class FUN, class ALLOC> template <class TYPE, class FUN, class ALLOC>
static void transformSoftPlus( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B ); static void transformSoftPlus(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B);
/*! /*!
* Sum the elements of the Array * Sum the elements of the Array
* @param[in] A The array to sum * @param[in] A The array to sum
*/ */
template<class TYPE, class FUN, class ALLOC> template <class TYPE, class FUN, class ALLOC>
static TYPE sum( const Array<TYPE, FUN, ALLOC> &A ); static TYPE sum(const Array<TYPE, FUN, ALLOC> &A);
private: private:
FunctionTable(); FunctionTable();
template<class T> template <class T> static inline void rand(size_t N, T *x);
static inline void rand( size_t N, T *x );
}; };
#endif #endif

View File

@ -41,7 +41,6 @@
#include <limits> #include <limits>
//#include <random> //#include <random>
/******************************************************** /********************************************************
* Random number initialization * * Random number initialization *
********************************************************/ ********************************************************/
@ -57,287 +56,252 @@ inline void FunctionTable::rand( Array<TYPE, FUN> &x )
/******************************************************** /********************************************************
* Reduction * * Reduction *
********************************************************/ ********************************************************/
template<class TYPE, class FUN, typename LAMBDA> template <class TYPE, class FUN, typename LAMBDA>
inline TYPE FunctionTable::reduce( LAMBDA &op, const Array<TYPE, FUN> &A, const TYPE &initialValue ) inline TYPE FunctionTable::reduce(LAMBDA &op, const Array<TYPE, FUN> &A,
{ const TYPE &initialValue) {
if ( A.length() == 0 ) if (A.length() == 0)
return TYPE(); return TYPE();
const TYPE *x = A.data(); const TYPE *x = A.data();
TYPE y = initialValue; TYPE y = initialValue;
for ( size_t i = 0; i < A.length(); i++ ) for (size_t i = 0; i < A.length(); i++)
y = op( x[i], y ); y = op(x[i], y);
return y; return y;
} }
template<class TYPE, class FUN, typename LAMBDA> template <class TYPE, class FUN, typename LAMBDA>
inline TYPE FunctionTable::reduce( LAMBDA &op, inline TYPE FunctionTable::reduce(LAMBDA &op, const Array<TYPE, FUN> &A,
const Array<TYPE, FUN> &A, const Array<TYPE, FUN> &B,
const Array<TYPE, FUN> &B, const TYPE &initialValue) {
const TYPE &initialValue ) ARRAY_ASSERT(A.length() == B.length());
{ if (A.length() == 0)
ARRAY_ASSERT( A.length() == B.length() );
if ( A.length() == 0 )
return TYPE(); return TYPE();
const TYPE *x = A.data(); const TYPE *x = A.data();
const TYPE *y = B.data(); const TYPE *y = B.data();
TYPE z = initialValue; TYPE z = initialValue;
for ( size_t i = 0; i < A.length(); i++ ) for (size_t i = 0; i < A.length(); i++)
z = op( x[i], y[i], z ); z = op(x[i], y[i], z);
return z; return z;
} }
/******************************************************** /********************************************************
* Unary transformation * * Unary transformation *
********************************************************/ ********************************************************/
template<class TYPE, class FUN, typename LAMBDA> template <class TYPE, class FUN, typename LAMBDA>
inline void FunctionTable::transform( LAMBDA &fun, const Array<TYPE, FUN> &x, Array<TYPE, FUN> &y ) inline void FunctionTable::transform(LAMBDA &fun, const Array<TYPE, FUN> &x,
{ Array<TYPE, FUN> &y) {
y.resize( x.size() ); y.resize(x.size());
const size_t N = x.length(); const size_t N = x.length();
for ( size_t i = 0; i < N; i++ ) for (size_t i = 0; i < N; i++)
y( i ) = fun( x( i ) ); y(i) = fun(x(i));
} }
template<class TYPE, class FUN, typename LAMBDA> template <class TYPE, class FUN, typename LAMBDA>
inline void FunctionTable::transform( LAMBDA &fun, inline void FunctionTable::transform(LAMBDA &fun, const Array<TYPE, FUN> &x,
const Array<TYPE, FUN> &x, const Array<TYPE, FUN> &y,
const Array<TYPE, FUN> &y, Array<TYPE, FUN> &z) {
Array<TYPE, FUN> &z ) if (x.size() != y.size())
{ throw std::logic_error("Sizes of x and y do not match");
if ( x.size() != y.size() ) z.resize(x.size());
throw std::logic_error( "Sizes of x and y do not match" );
z.resize( x.size() );
const size_t N = x.length(); const size_t N = x.length();
for ( size_t i = 0; i < N; i++ ) for (size_t i = 0; i < N; i++)
z( i ) = fun( x( i ), y( i ) ); z(i) = fun(x(i), y(i));
} }
/******************************************************** /********************************************************
* axpy * * axpy *
********************************************************/ ********************************************************/
template<class TYPE> template <class TYPE>
void call_axpy( size_t N, const TYPE alpha, const TYPE *x, TYPE *y ); void call_axpy(size_t N, const TYPE alpha, const TYPE *x, TYPE *y);
template<> template <>
void call_axpy<float>( size_t N, const float alpha, const float *x, float *y ); void call_axpy<float>(size_t N, const float alpha, const float *x, float *y);
template<> template <>
void call_axpy<double>( size_t N, const double alpha, const double *x, double *y ); void call_axpy<double>(size_t N, const double alpha, const double *x,
template<class TYPE> double *y);
void call_axpy( size_t N, const TYPE alpha, const TYPE *x, TYPE *y ) template <class TYPE>
{ void call_axpy(size_t N, const TYPE alpha, const TYPE *x, TYPE *y) {
for ( size_t i = 0; i < N; i++ ) for (size_t i = 0; i < N; i++)
y[i] += alpha * x[i]; y[i] += alpha * x[i];
} }
template<class TYPE, class FUN> template <class TYPE, class FUN>
void FunctionTable::axpy( const TYPE alpha, const Array<TYPE, FUN> &x, Array<TYPE, FUN> &y ) void FunctionTable::axpy(const TYPE alpha, const Array<TYPE, FUN> &x,
{ Array<TYPE, FUN> &y) {
if ( x.size() != y.size() ) if (x.size() != y.size())
throw std::logic_error( "Array sizes do not match" ); throw std::logic_error("Array sizes do not match");
call_axpy( x.length(), alpha, x.data(), y.data() ); call_axpy(x.length(), alpha, x.data(), y.data());
} }
/******************************************************** /********************************************************
* Multiply two arrays * * Multiply two arrays *
********************************************************/ ********************************************************/
template<class TYPE> template <class TYPE>
void call_gemv( size_t M, size_t N, TYPE alpha, TYPE beta, const TYPE *A, const TYPE *x, TYPE *y ); void call_gemv(size_t M, size_t N, TYPE alpha, TYPE beta, const TYPE *A,
template<> const TYPE *x, TYPE *y);
void call_gemv<double>( template <>
size_t M, size_t N, double alpha, double beta, const double *A, const double *x, double *y ); void call_gemv<double>(size_t M, size_t N, double alpha, double beta,
template<> const double *A, const double *x, double *y);
void call_gemv<float>( template <>
size_t M, size_t N, float alpha, float beta, const float *A, const float *x, float *y ); void call_gemv<float>(size_t M, size_t N, float alpha, float beta,
template<class TYPE> const float *A, const float *x, float *y);
void call_gemv( size_t M, size_t N, TYPE alpha, TYPE beta, const TYPE *A, const TYPE *x, TYPE *y ) template <class TYPE>
{ void call_gemv(size_t M, size_t N, TYPE alpha, TYPE beta, const TYPE *A,
for ( size_t i = 0; i < M; i++ ) const TYPE *x, TYPE *y) {
for (size_t i = 0; i < M; i++)
y[i] = beta * y[i]; y[i] = beta * y[i];
for ( size_t j = 0; j < N; j++ ) { for (size_t j = 0; j < N; j++) {
for ( size_t i = 0; i < M; i++ ) for (size_t i = 0; i < M; i++)
y[i] += alpha * A[i + j * M] * x[j]; y[i] += alpha * A[i + j * M] * x[j];
} }
} }
template<class TYPE> template <class TYPE>
void call_gemm( void call_gemm(size_t M, size_t N, size_t K, TYPE alpha, TYPE beta,
size_t M, size_t N, size_t K, TYPE alpha, TYPE beta, const TYPE *A, const TYPE *B, TYPE *C ); const TYPE *A, const TYPE *B, TYPE *C);
template<> template <>
void call_gemm<double>( size_t M, void call_gemm<double>(size_t M, size_t N, size_t K, double alpha, double beta,
size_t N, const double *A, const double *B, double *C);
size_t K, template <>
double alpha, void call_gemm<float>(size_t M, size_t N, size_t K, float alpha, float beta,
double beta, const float *A, const float *B, float *C);
const double *A, template <class TYPE>
const double *B, void call_gemm(size_t M, size_t N, size_t K, TYPE alpha, TYPE beta,
double *C ); const TYPE *A, const TYPE *B, TYPE *C) {
template<> for (size_t i = 0; i < K * M; i++)
void call_gemm<float>( size_t M,
size_t N,
size_t K,
float alpha,
float beta,
const float *A,
const float *B,
float *C );
template<class TYPE>
void call_gemm(
size_t M, size_t N, size_t K, TYPE alpha, TYPE beta, const TYPE *A, const TYPE *B, TYPE *C )
{
for ( size_t i = 0; i < K * M; i++ )
C[i] = beta * C[i]; C[i] = beta * C[i];
for ( size_t k = 0; k < K; k++ ) { for (size_t k = 0; k < K; k++) {
for ( size_t j = 0; j < N; j++ ) { for (size_t j = 0; j < N; j++) {
for ( size_t i = 0; i < M; i++ ) for (size_t i = 0; i < M; i++)
C[i + k * M] += alpha * A[i + j * M] * B[j + k * N]; C[i + k * M] += alpha * A[i + j * M] * B[j + k * N];
} }
} }
} }
template<class TYPE, class FUN> template <class TYPE, class FUN>
void FunctionTable::gemm( const TYPE alpha, void FunctionTable::gemm(const TYPE alpha, const Array<TYPE, FUN> &a,
const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b, const TYPE beta,
const Array<TYPE, FUN> &b, Array<TYPE, FUN> &c) {
const TYPE beta, if (a.size(1) != b.size(0))
Array<TYPE, FUN> &c ) throw std::logic_error("Inner dimensions must match");
{ if (a.ndim() == 2 && b.ndim() == 1) {
if ( a.size( 1 ) != b.size( 0 ) ) call_gemv<TYPE>(a.size(0), a.size(1), alpha, beta, a.data(), b.data(),
throw std::logic_error( "Inner dimensions must match" ); c.data());
if ( a.ndim() == 2 && b.ndim() == 1 ) { } else if (a.ndim() <= 2 && b.ndim() <= 2) {
call_gemv<TYPE>( a.size( 0 ), a.size( 1 ), alpha, beta, a.data(), b.data(), c.data() ); call_gemm<TYPE>(a.size(0), a.size(1), b.size(1), alpha, beta, a.data(),
} else if ( a.ndim() <= 2 && b.ndim() <= 2 ) { b.data(), c.data());
call_gemm<TYPE>(
a.size( 0 ), a.size( 1 ), b.size( 1 ), alpha, beta, a.data(), b.data(), c.data() );
} else { } else {
throw std::logic_error( "Not finished yet" ); throw std::logic_error("Not finished yet");
} }
} }
template<class TYPE, class FUN> template <class TYPE, class FUN>
void FunctionTable::multiply( const Array<TYPE, FUN> &a, void FunctionTable::multiply(const Array<TYPE, FUN> &a,
const Array<TYPE, FUN> &b, const Array<TYPE, FUN> &b, Array<TYPE, FUN> &c) {
Array<TYPE, FUN> &c ) if (a.size(1) != b.size(0))
{ throw std::logic_error("Inner dimensions must match");
if ( a.size( 1 ) != b.size( 0 ) ) if (a.ndim() == 2 && b.ndim() == 1) {
throw std::logic_error( "Inner dimensions must match" ); c.resize(a.size(0));
if ( a.ndim() == 2 && b.ndim() == 1 ) { call_gemv<TYPE>(a.size(0), a.size(1), 1, 0, a.data(), b.data(),
c.resize( a.size( 0 ) ); c.data());
call_gemv<TYPE>( a.size( 0 ), a.size( 1 ), 1, 0, a.data(), b.data(), c.data() ); } else if (a.ndim() <= 2 && b.ndim() <= 2) {
} else if ( a.ndim() <= 2 && b.ndim() <= 2 ) { c.resize(a.size(0), b.size(1));
c.resize( a.size( 0 ), b.size( 1 ) ); call_gemm<TYPE>(a.size(0), a.size(1), b.size(1), 1, 0, a.data(),
call_gemm<TYPE>( b.data(), c.data());
a.size( 0 ), a.size( 1 ), b.size( 1 ), 1, 0, a.data(), b.data(), c.data() );
} else { } else {
throw std::logic_error( "Not finished yet" ); throw std::logic_error("Not finished yet");
} }
} }
/******************************************************** /********************************************************
* Check if two arrays are equal * * Check if two arrays are equal *
********************************************************/ ********************************************************/
template<class TYPE, class FUN> template <class TYPE, class FUN>
inline typename std::enable_if<std::is_integral<TYPE>::value, bool>::type inline typename std::enable_if<std::is_integral<TYPE>::value, bool>::type
FunctionTableCompare( const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b, TYPE ) FunctionTableCompare(const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b,
{ TYPE) {
bool pass = true; bool pass = true;
if ( a.size() != b.size() ) if (a.size() != b.size())
throw std::logic_error( "Sizes of x and y do not match" ); throw std::logic_error("Sizes of x and y do not match");
for ( size_t i = 0; i < a.length(); i++ ) for (size_t i = 0; i < a.length(); i++)
pass = pass && a( i ) == b( i ); pass = pass && a(i) == b(i);
return pass; return pass;
} }
template<class TYPE, class FUN> template <class TYPE, class FUN>
inline typename std::enable_if<std::is_floating_point<TYPE>::value, bool>::type inline typename std::enable_if<std::is_floating_point<TYPE>::value, bool>::type
FunctionTableCompare( const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b, TYPE tol ) FunctionTableCompare(const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b,
{ TYPE tol) {
bool pass = true; bool pass = true;
if ( a.size() != b.size() ) if (a.size() != b.size())
throw std::logic_error( "Sizes of x and y do not match" ); throw std::logic_error("Sizes of x and y do not match");
for ( size_t i = 0; i < a.length(); i++ ) for (size_t i = 0; i < a.length(); i++)
pass = pass && ( std::abs( a( i ) - b( i ) ) < tol ); pass = pass && (std::abs(a(i) - b(i)) < tol);
return pass; return pass;
} }
template<class TYPE, class FUN> template <class TYPE, class FUN>
bool FunctionTable::equals( const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b, TYPE tol ) bool FunctionTable::equals(const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b,
{ TYPE tol) {
return FunctionTableCompare( a, b, tol ); return FunctionTableCompare(a, b, tol);
} }
/******************************************************** /********************************************************
* Specialized Functions * * Specialized Functions *
********************************************************/ ********************************************************/
template<class TYPE, class FUN, class ALLOC> template <class TYPE, class FUN, class ALLOC>
void FunctionTable::transformReLU( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B ) void FunctionTable::transformReLU(const Array<TYPE, FUN, ALLOC> &A,
{ Array<TYPE, FUN, ALLOC> &B) {
const auto &fun = []( const TYPE &a ) { return std::max( a, static_cast<TYPE>( 0 ) ); }; const auto &fun = [](const TYPE &a) {
transform( fun, A, B ); return std::max(a, static_cast<TYPE>(0));
}
template<class TYPE, class FUN, class ALLOC>
void FunctionTable::transformAbs( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B )
{
B.resize( A.size() );
const auto &fun = []( const TYPE &a ) { return std::abs( a ); };
transform( fun, A, B );
}
template<class TYPE, class FUN, class ALLOC>
void FunctionTable::transformTanh( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B )
{
B.resize( A.size() );
const auto &fun = []( const TYPE &a ) { return tanh( a ); };
transform( fun, A, B );
}
template<class TYPE, class FUN, class ALLOC>
void FunctionTable::transformHardTanh( const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B )
{
B.resize( A.size() );
const auto &fun = []( const TYPE &a ) {
return std::max( -static_cast<TYPE>( 1.0 ), std::min( static_cast<TYPE>( 1.0 ), a ) );
}; };
transform( fun, A, B ); transform(fun, A, B);
} }
template<class TYPE, class FUN, class ALLOC> template <class TYPE, class FUN, class ALLOC>
void FunctionTable::transformSigmoid( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B ) void FunctionTable::transformAbs(const Array<TYPE, FUN, ALLOC> &A,
{ Array<TYPE, FUN, ALLOC> &B) {
B.resize( A.size() ); B.resize(A.size());
const auto &fun = []( const TYPE &a ) { return 1.0 / ( 1.0 + exp( -a ) ); }; const auto &fun = [](const TYPE &a) { return std::abs(a); };
transform( fun, A, B ); transform(fun, A, B);
}
template <class TYPE, class FUN, class ALLOC>
void FunctionTable::transformTanh(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B) {
B.resize(A.size());
const auto &fun = [](const TYPE &a) { return tanh(a); };
transform(fun, A, B);
} }
template<class TYPE, class FUN, class ALLOC> template <class TYPE, class FUN, class ALLOC>
void FunctionTable::transformSoftPlus( const Array<TYPE, FUN, ALLOC> &A, void FunctionTable::transformHardTanh(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B ) Array<TYPE, FUN, ALLOC> &B) {
{ B.resize(A.size());
B.resize( A.size() ); const auto &fun = [](const TYPE &a) {
const auto &fun = []( const TYPE &a ) { return log1p( exp( a ) ); }; return std::max(-static_cast<TYPE>(1.0),
transform( fun, A, B ); std::min(static_cast<TYPE>(1.0), a));
};
transform(fun, A, B);
} }
template<class TYPE, class FUN, class ALLOC> template <class TYPE, class FUN, class ALLOC>
TYPE FunctionTable::sum( const Array<TYPE, FUN, ALLOC> &A ) void FunctionTable::transformSigmoid(const Array<TYPE, FUN, ALLOC> &A,
{ Array<TYPE, FUN, ALLOC> &B) {
const auto &fun = []( const TYPE &a, const TYPE &b ) { return a + b; }; B.resize(A.size());
return reduce( fun, A, (TYPE) 0 ); const auto &fun = [](const TYPE &a) { return 1.0 / (1.0 + exp(-a)); };
transform(fun, A, B);
} }
template<class TYPE> template <class TYPE, class FUN, class ALLOC>
inline void FunctionTable::gemmWrapper( char TRANSA, void FunctionTable::transformSoftPlus(const Array<TYPE, FUN, ALLOC> &A,
char TRANSB, Array<TYPE, FUN, ALLOC> &B) {
int M, B.resize(A.size());
int N, const auto &fun = [](const TYPE &a) { return log1p(exp(a)); };
int K, transform(fun, A, B);
TYPE alpha, }
const TYPE *A,
int LDA, template <class TYPE, class FUN, class ALLOC>
const TYPE *B, TYPE FunctionTable::sum(const Array<TYPE, FUN, ALLOC> &A) {
int LDB, const auto &fun = [](const TYPE &a, const TYPE &b) { return a + b; };
TYPE beta, return reduce(fun, A, (TYPE)0);
TYPE *C, }
int LDC )
{ template <class TYPE>
inline void FunctionTable::gemmWrapper(char TRANSA, char TRANSB, int M, int N,
int K, TYPE alpha, const TYPE *A,
int LDA, const TYPE *B, int LDB,
TYPE beta, TYPE *C, int LDC) {
ERROR("Not finished"); ERROR("Not finished");
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,6 @@ redistribution is prohibited.
#ifndef included_LBPM_MPI #ifndef included_LBPM_MPI
#define included_LBPM_MPI #define included_LBPM_MPI
#include <array> #include <array>
#include <atomic> #include <atomic>
#include <complex> #include <complex>
@ -31,7 +30,6 @@ redistribution is prohibited.
#include <string> #include <string>
#include <vector> #include <vector>
// Include mpi.h (or define MPI objects) // Include mpi.h (or define MPI objects)
// clang-format off // clang-format off
#ifdef USE_MPI #ifdef USE_MPI
@ -48,10 +46,8 @@ redistribution is prohibited.
#endif #endif
// clang-format on // clang-format on
namespace Utilities { namespace Utilities {
/** /**
* \class MPI * \class MPI
* *
@ -69,8 +65,7 @@ namespace Utilities {
* succeed provided that the size of the data type object is a fixed size on * succeed provided that the size of the data type object is a fixed size on
* all processors. sizeof(type) must be the same for all elements and processors. * all processors. sizeof(type) must be the same for all elements and processors.
*/ */
class MPI final class MPI final {
{
public: public:
enum class ThreadSupport : int { SINGLE, FUNNELED, SERIALIZED, MULTIPLE }; enum class ThreadSupport : int { SINGLE, FUNNELED, SERIALIZED, MULTIPLE };
@ -87,11 +82,9 @@ public: // Constructors
*/ */
MPI(); MPI();
//! Empty destructor //! Empty destructor
~MPI(); ~MPI();
/** /**
* \brief Constructor from existing MPI communicator * \brief Constructor from existing MPI communicator
* \details This constructor creates a new communicator from an existing MPI communicator. * \details This constructor creates a new communicator from an existing MPI communicator.
@ -104,8 +97,7 @@ public: // Constructors
* \param manage Do we want to manage the comm (free the MPI_Comm when this object leaves * \param manage Do we want to manage the comm (free the MPI_Comm when this object leaves
* scope) * scope)
*/ */
MPI( MPI_Comm comm, bool manage = false ); MPI(MPI_Comm comm, bool manage = false);
/** /**
* \brief Constructor from existing communicator * \brief Constructor from existing communicator
@ -113,30 +105,26 @@ public: // Constructors
* This does not create a new internal MPI_Comm, but uses the existing comm. * This does not create a new internal MPI_Comm, but uses the existing comm.
* \param comm Existing communicator * \param comm Existing communicator
*/ */
MPI( const MPI &comm ); MPI(const MPI &comm);
/*! /*!
* Move constructor * Move constructor
* @param rhs Communicator to copy * @param rhs Communicator to copy
*/ */
MPI( MPI &&rhs ); MPI(MPI &&rhs);
/** /**
* \brief Assignment operator * \brief Assignment operator
* \details This operator overloads the assignment to correctly copy an communicator * \details This operator overloads the assignment to correctly copy an communicator
* \param comm Existing MPI object * \param comm Existing MPI object
*/ */
MPI &operator=( const MPI &comm ); MPI &operator=(const MPI &comm);
/*! /*!
* Move assignment operator * Move assignment operator
* @param rhs Communicator to copy * @param rhs Communicator to copy
*/ */
MPI &operator=( MPI &&rhs ); MPI &operator=(MPI &&rhs);
/** /**
* \brief Reset the object * \brief Reset the object
@ -144,7 +132,6 @@ public: // Constructors
*/ */
void reset(); void reset();
public: // Member functions public: // Member functions
/** /**
* \brief Get the node name * \brief Get the node name
@ -153,18 +140,14 @@ public: // Member functions
*/ */
static std::string getNodeName(); static std::string getNodeName();
//! Function to return the number of processors available //! Function to return the number of processors available
static int getNumberOfProcessors(); static int getNumberOfProcessors();
//! Function to return the affinity of the current process //! Function to return the affinity of the current process
static std::vector<int> getProcessAffinity(); static std::vector<int> getProcessAffinity();
//! Function to set the affinity of the current process //! Function to set the affinity of the current process
static void setProcessAffinity( const std::vector<int> &procs ); static void setProcessAffinity(const std::vector<int> &procs);
/** /**
* \brief Load balance the processes within a node * \brief Load balance the processes within a node
@ -189,22 +172,21 @@ public: // Member functions
* processors). * processors).
* *
*/ */
static void balanceProcesses( const MPI &comm = MPI( MPI_COMM_WORLD ), const int method = 1, static void
const std::vector<int> &procs = std::vector<int>(), const int N_min = 1, balanceProcesses(const MPI &comm = MPI(MPI_COMM_WORLD),
const int N_max = -1 ); const int method = 1,
const std::vector<int> &procs = std::vector<int>(),
const int N_min = 1, const int N_max = -1);
//! Query the level of thread support //! Query the level of thread support
static ThreadSupport queryThreadSupport(); static ThreadSupport queryThreadSupport();
/** /**
* \brief Generate a random number * \brief Generate a random number
* \details This generates a random number that is consistent across the comm * \details This generates a random number that is consistent across the comm
*/ */
size_t rand() const; size_t rand() const;
/** /**
* \brief Split an existing communicator * \brief Split an existing communicator
* \details This creates a new communicator by splitting an existing communicator. * \details This creates a new communicator by splitting an existing communicator.
@ -222,8 +204,7 @@ public: // Member functions
* have the relative rank order as they did in their parent group. (See * have the relative rank order as they did in their parent group. (See
* MPI_Comm_split) * MPI_Comm_split)
*/ */
MPI split( int color, int key = -1 ) const; MPI split(int color, int key = -1) const;
/** /**
* \brief Split an existing communicator by node * \brief Split an existing communicator by node
@ -240,8 +221,7 @@ public: // Member functions
* have the relative rank order as they did in their parent group. (See * have the relative rank order as they did in their parent group. (See
* MPI_Comm_split) * MPI_Comm_split)
*/ */
MPI splitByNode( int key = -1 ) const; MPI splitByNode(int key = -1) const;
/** /**
* \brief Duplicate an existing communicator * \brief Duplicate an existing communicator
@ -253,7 +233,6 @@ public: // Member functions
*/ */
MPI dup() const; MPI dup() const;
/** /**
* \brief Create a communicator from the intersection of two communicators * \brief Create a communicator from the intersection of two communicators
* \details This creates a new communicator by intersecting two existing communicators. * \details This creates a new communicator by intersecting two existing communicators.
@ -265,15 +244,13 @@ public: // Member functions
* The communicators partially overlap. This will require communication on the first * The communicators partially overlap. This will require communication on the first
* communicator. * communicator.
*/ */
static MPI intersect( const MPI &comm1, const MPI &comm2 ); static MPI intersect(const MPI &comm1, const MPI &comm2);
/** /**
* Check if the current communicator is NULL * Check if the current communicator is NULL
*/ */
bool isNull() const { return d_isNull; } bool isNull() const { return d_isNull; }
/** /**
* \brief Return the global ranks for the comm * \brief Return the global ranks for the comm
* \details This returns a vector which contains the global ranks for each * \details This returns a vector which contains the global ranks for each
@ -283,7 +260,6 @@ public: // Member functions
*/ */
std::vector<int> globalRanks() const; std::vector<int> globalRanks() const;
/** /**
* Get the current MPI communicator. * Get the current MPI communicator.
* Note: The underlying MPI_Comm object may be free'd by the object when it is no * Note: The underlying MPI_Comm object may be free'd by the object when it is no
@ -294,15 +270,13 @@ public: // Member functions
*/ */
const MPI_Comm &getCommunicator() const { return communicator; } const MPI_Comm &getCommunicator() const { return communicator; }
/** /**
* \brief Overload operator == * \brief Overload operator ==
* \details Overload operator comm1 == comm2. Two MPI objects are == if they share the same * \details Overload operator comm1 == comm2. Two MPI objects are == if they share the same
* communicator. * communicator.
* Note: this is a local operation. * Note: this is a local operation.
*/ */
bool operator==( const MPI & ) const; bool operator==(const MPI &) const;
/** /**
* \brief Overload operator != * \brief Overload operator !=
@ -310,8 +284,7 @@ public: // Member functions
* do not share the same communicator. * do not share the same communicator.
* Note: this is a local operation. * Note: this is a local operation.
*/ */
bool operator!=( const MPI & ) const; bool operator!=(const MPI &) const;
/** /**
* \brief Overload operator < * \brief Overload operator <
@ -324,8 +297,7 @@ public: // Member functions
* Additionally, all processors on the first object MUST call this routine and will be * Additionally, all processors on the first object MUST call this routine and will be
* synchronized through this call (there is an internalallReduce). * synchronized through this call (there is an internalallReduce).
*/ */
bool operator<( const MPI & ) const; bool operator<(const MPI &) const;
/** /**
* \brief Overload operator <= * \brief Overload operator <=
@ -337,8 +309,7 @@ public: // Member functions
* call this routine and will be synchronized through this call (there is an internal * call this routine and will be synchronized through this call (there is an internal
* allReduce). * allReduce).
*/ */
bool operator<=( const MPI & ) const; bool operator<=(const MPI &) const;
/** /**
* \brief Overload operator > * \brief Overload operator >
@ -351,8 +322,7 @@ public: // Member functions
* Additionally, all processors on the first object MUST call this routine and will be * Additionally, all processors on the first object MUST call this routine and will be
* synchronized through this call (there is an internal allReduce). * synchronized through this call (there is an internal allReduce).
*/ */
bool operator>( const MPI & ) const; bool operator>(const MPI &) const;
/** /**
* \brief Overload operator >= * \brief Overload operator >=
@ -365,8 +335,7 @@ public: // Member functions
* Additionally, all processors on the first object MUST call this routine and will be * Additionally, all processors on the first object MUST call this routine and will be
* synchronized through this call (there is an internal allReduce). * synchronized through this call (there is an internal allReduce).
*/ */
bool operator>=( const MPI & ) const; bool operator>=(const MPI &) const;
/** /**
* \brief Compare to another communicator * \brief Compare to another communicator
@ -376,8 +345,7 @@ public: // Member functions
* 4 if different contexts but similar groups, and 0 otherwise. * 4 if different contexts but similar groups, and 0 otherwise.
* Note: this is a local operation. * Note: this is a local operation.
*/ */
int compare( const MPI & ) const; int compare(const MPI &) const;
/** /**
* Return the processor rank (identifier) from 0 through the number of * Return the processor rank (identifier) from 0 through the number of
@ -385,19 +353,16 @@ public: // Member functions
*/ */
int getRank() const { return comm_rank; } int getRank() const { return comm_rank; }
/** /**
* Return the number of processors. * Return the number of processors.
*/ */
int getSize() const { return comm_size; } int getSize() const { return comm_size; }
/** /**
* Return the maximum tag * Return the maximum tag
*/ */
int maxTag() const { return d_maxTag; } int maxTag() const { return d_maxTag; }
/** /**
* \brief Return a new tag * \brief Return a new tag
* \details This routine will return an unused tag for communication. * \details This routine will return an unused tag for communication.
@ -406,7 +371,6 @@ public: // Member functions
*/ */
int newTag(); int newTag();
/** /**
* Call MPI_Abort or exit depending on whether running with one or more * Call MPI_Abort or exit depending on whether running with one or more
* processes and value set by function above, if called. The default is * processes and value set by function above, if called. The default is
@ -416,15 +380,13 @@ public: // Member functions
*/ */
void abort() const; void abort() const;
/** /**
* Set boolean flag indicating whether exit or abort is called when running * Set boolean flag indicating whether exit or abort is called when running
* with one processor. Calling this function influences the behavior of * with one processor. Calling this function influences the behavior of
* calls to abort(). By default, the flag is true meaning that * calls to abort(). By default, the flag is true meaning that
* abort() will be called. Passing false means exit(-1) will be called. * abort() will be called. Passing false means exit(-1) will be called.
*/ */
void setCallAbortInSerialInsteadOfExit( bool flag = true ); void setCallAbortInSerialInsteadOfExit(bool flag = true);
/** /**
* \brief Boolean all reduce * \brief Boolean all reduce
@ -432,8 +394,7 @@ public: // Member functions
* It returns true iff all processor are true; * It returns true iff all processor are true;
* \param value The input value for the all reduce * \param value The input value for the all reduce
*/ */
bool allReduce( const bool value ) const; bool allReduce(const bool value) const;
/** /**
* \brief Boolean any reduce * \brief Boolean any reduce
@ -441,8 +402,7 @@ public: // Member functions
* It returns true if any processor is true; * It returns true if any processor is true;
* \param value The input value for the all reduce * \param value The input value for the all reduce
*/ */
bool anyReduce( const bool value ) const; bool anyReduce(const bool value) const;
/** /**
* \brief Sum Reduce * \brief Sum Reduce
@ -450,9 +410,7 @@ public: // Member functions
* It returns the sum across all processors; * It returns the sum across all processors;
* \param value The input value for the all reduce * \param value The input value for the all reduce
*/ */
template<class type> template <class type> type sumReduce(const type value) const;
type sumReduce( const type value ) const;
/** /**
* \brief Sum Reduce * \brief Sum Reduce
@ -462,9 +420,7 @@ public: // Member functions
* \param x The input/output array for the reduce * \param x The input/output array for the reduce
* \param n The number of values in the array (must match on all nodes) * \param n The number of values in the array (must match on all nodes)
*/ */
template<class type> template <class type> void sumReduce(type *x, const int n = 1) const;
void sumReduce( type *x, const int n = 1 ) const;
/** /**
* \brief Sum Reduce * \brief Sum Reduce
@ -475,9 +431,8 @@ public: // Member functions
* \param y The output array for the reduce * \param y The output array for the reduce
* \param n The number of values in the array (must match on all nodes) * \param n The number of values in the array (must match on all nodes)
*/ */
template<class type> template <class type>
void sumReduce( const type *x, type *y, const int n = 1 ) const; void sumReduce(const type *x, type *y, const int n = 1) const;
/** /**
* \brief Min Reduce * \brief Min Reduce
@ -485,9 +440,7 @@ public: // Member functions
* It returns the minimum value across all processors; * It returns the minimum value across all processors;
* \param value The input value for the all reduce * \param value The input value for the all reduce
*/ */
template<class type> template <class type> type minReduce(const type value) const;
type minReduce( const type value ) const;
/** /**
* \brief Sum Reduce * \brief Sum Reduce
@ -503,9 +456,8 @@ public: // Member functions
* \param rank_of_min Optional array indicating the rank of the processor containing the * \param rank_of_min Optional array indicating the rank of the processor containing the
* minimum value * minimum value
*/ */
template<class type> template <class type>
void minReduce( type *x, const int n = 1, int *rank_of_min = nullptr ) const; void minReduce(type *x, const int n = 1, int *rank_of_min = nullptr) const;
/** /**
* \brief Sum Reduce * \brief Sum Reduce
@ -522,9 +474,9 @@ public: // Member functions
* \param rank_of_min Optional array indicating the rank of the processor containing the * \param rank_of_min Optional array indicating the rank of the processor containing the
* minimum value * minimum value
*/ */
template<class type> template <class type>
void minReduce( const type *x, type *y, const int n = 1, int *rank_of_min = nullptr ) const; void minReduce(const type *x, type *y, const int n = 1,
int *rank_of_min = nullptr) const;
/** /**
* \brief Max Reduce * \brief Max Reduce
@ -532,9 +484,7 @@ public: // Member functions
* It returns the maximum value across all processors; * It returns the maximum value across all processors;
* \param value The input value for the all reduce * \param value The input value for the all reduce
*/ */
template<class type> template <class type> type maxReduce(const type value) const;
type maxReduce( const type value ) const;
/** /**
* \brief Sum Reduce * \brief Sum Reduce
@ -550,9 +500,8 @@ public: // Member functions
* \param rank_of_max Optional array indicating the rank of the processor containing the * \param rank_of_max Optional array indicating the rank of the processor containing the
* minimum value * minimum value
*/ */
template<class type> template <class type>
void maxReduce( type *x, const int n = 1, int *rank_of_max = nullptr ) const; void maxReduce(type *x, const int n = 1, int *rank_of_max = nullptr) const;
/** /**
* \brief Sum Reduce * \brief Sum Reduce
@ -569,9 +518,9 @@ public: // Member functions
* \param rank_of_max Optional array indicating the rank of the processor containing the * \param rank_of_max Optional array indicating the rank of the processor containing the
* minimum value * minimum value
*/ */
template<class type> template <class type>
void maxReduce( const type *x, type *y, const int n = 1, int *rank_of_max = nullptr ) const; void maxReduce(const type *x, type *y, const int n = 1,
int *rank_of_max = nullptr) const;
/** /**
* \brief Scan Sum Reduce * \brief Scan Sum Reduce
@ -581,9 +530,8 @@ public: // Member functions
* \param y The output array for the scan * \param y The output array for the scan
* \param n The number of values in the array (must match on all nodes) * \param n The number of values in the array (must match on all nodes)
*/ */
template<class type> template <class type>
void sumScan( const type *x, type *y, const int n = 1 ) const; void sumScan(const type *x, type *y, const int n = 1) const;
/** /**
* \brief Scan Min Reduce * \brief Scan Min Reduce
@ -593,9 +541,8 @@ public: // Member functions
* \param y The output array for the scan * \param y The output array for the scan
* \param n The number of values in the array (must match on all nodes) * \param n The number of values in the array (must match on all nodes)
*/ */
template<class type> template <class type>
void minScan( const type *x, type *y, const int n = 1 ) const; void minScan(const type *x, type *y, const int n = 1) const;
/** /**
* \brief Scan Max Reduce * \brief Scan Max Reduce
@ -605,9 +552,8 @@ public: // Member functions
* \param y The output array for the scan * \param y The output array for the scan
* \param n The number of values in the array (must match on all nodes) * \param n The number of values in the array (must match on all nodes)
*/ */
template<class type> template <class type>
void maxScan( const type *x, type *y, const int n = 1 ) const; void maxScan(const type *x, type *y, const int n = 1) const;
/** /**
* \brief Broadcast * \brief Broadcast
@ -615,9 +561,7 @@ public: // Member functions
* \param value The input value for the broadcast. * \param value The input value for the broadcast.
* \param root The processor performing the broadcast * \param root The processor performing the broadcast
*/ */
template<class type> template <class type> type bcast(const type &value, const int root) const;
type bcast( const type &value, const int root ) const;
/** /**
* \brief Broadcast * \brief Broadcast
@ -626,16 +570,14 @@ public: // Member functions
* \param n The number of values in the array (must match on all nodes) * \param n The number of values in the array (must match on all nodes)
* \param root The processor performing the broadcast * \param root The processor performing the broadcast
*/ */
template<class type> template <class type>
void bcast( type *value, const int n, const int root ) const; void bcast(type *value, const int n, const int root) const;
/** /**
* Perform a global barrier across all processors. * Perform a global barrier across all processors.
*/ */
void barrier() const; void barrier() const;
/*! /*!
* @brief This function sends an MPI message with an array to another processor. * @brief This function sends an MPI message with an array to another processor.
* *
@ -652,9 +594,9 @@ public: // Member functions
* to be sent with this message. Default tag is 0. * to be sent with this message. Default tag is 0.
* The matching recv must share this tag. * The matching recv must share this tag.
*/ */
template<class type> template <class type>
void send( const type *buf, const int length, const int recv, int tag = 0 ) const; void send(const type *buf, const int length, const int recv,
int tag = 0) const;
/*! /*!
* @brief This function sends an MPI message with an array of bytes * @brief This function sends an MPI message with an array of bytes
@ -669,8 +611,8 @@ public: // Member functions
* to be sent with this message. Default tag is 0. * to be sent with this message. Default tag is 0.
* The matching recv must share this tag. * The matching recv must share this tag.
*/ */
void sendBytes( const void *buf, const int N_bytes, const int recv, int tag = 0 ) const; void sendBytes(const void *buf, const int N_bytes, const int recv,
int tag = 0) const;
/*! /*!
* @brief This function sends an MPI message with an array * @brief This function sends an MPI message with an array
@ -684,10 +626,9 @@ public: // Member functions
* @param tag Integer argument specifying an integer tag * @param tag Integer argument specifying an integer tag
* to be sent with this message. * to be sent with this message.
*/ */
template<class type> template <class type>
MPI_Request Isend( MPI_Request Isend(const type *buf, const int length, const int recv_proc,
const type *buf, const int length, const int recv_proc, const int tag ) const; const int tag) const;
/*! /*!
* @brief This function sends an MPI message with an array of bytes * @brief This function sends an MPI message with an array of bytes
@ -701,9 +642,8 @@ public: // Member functions
* @param tag Integer argument specifying an integer tag * @param tag Integer argument specifying an integer tag
* to be sent with this message. * to be sent with this message.
*/ */
MPI_Request IsendBytes( MPI_Request IsendBytes(const void *buf, const int N_bytes,
const void *buf, const int N_bytes, const int recv_proc, const int tag ) const; const int recv_proc, const int tag) const;
/*! /*!
* @brief This function receives an MPI message with a data * @brief This function receives an MPI message with a data
@ -721,14 +661,12 @@ public: // Member functions
* @param tag Optional integer argument specifying a tag which must be matched * @param tag Optional integer argument specifying a tag which must be matched
* by the tag of the incoming message. Default tag is 0. * by the tag of the incoming message. Default tag is 0.
*/ */
template<class type> template <class type>
inline void recv( type *buf, int length, const int send, int tag ) const inline void recv(type *buf, int length, const int send, int tag) const {
{
int length2 = length; int length2 = length;
recv( buf, length2, send, false, tag ); recv(buf, length2, send, false, tag);
} }
/*! /*!
* @brief This function receives an MPI message with a data * @brief This function receives an MPI message with a data
* array from another processor. * array from another processor.
@ -748,9 +686,9 @@ public: // Member functions
* @param tag Optional integer argument specifying a tag which must be matched * @param tag Optional integer argument specifying a tag which must be matched
* by the tag of the incoming message. Default tag is 0. * by the tag of the incoming message. Default tag is 0.
*/ */
template<class type> template <class type>
void recv( type *buf, int &length, const int send, const bool get_length, int tag ) const; void recv(type *buf, int &length, const int send, const bool get_length,
int tag) const;
/*! /*!
* @brief This function receives an MPI message with an array of * @brief This function receives an MPI message with an array of
@ -765,8 +703,7 @@ public: // Member functions
* must be matched by the tag of the incoming message. Default * must be matched by the tag of the incoming message. Default
* tag is 0. * tag is 0.
*/ */
void recvBytes( void *buf, int &N_bytes, const int send, int tag = 0 ) const; void recvBytes(void *buf, int &N_bytes, const int send, int tag = 0) const;
/*! /*!
* @brief This function receives an MPI message with a data * @brief This function receives an MPI message with a data
@ -778,9 +715,9 @@ public: // Member functions
* @param tag Optional integer argument specifying a tag which must * @param tag Optional integer argument specifying a tag which must
* be matched by the tag of the incoming message. * be matched by the tag of the incoming message.
*/ */
template<class type> template <class type>
MPI_Request Irecv( type *buf, const int length, const int send_proc, const int tag ) const; MPI_Request Irecv(type *buf, const int length, const int send_proc,
const int tag) const;
/*! /*!
* @brief This function receives an MPI message with an array of * @brief This function receives an MPI message with an array of
@ -794,35 +731,30 @@ public: // Member functions
* @param tag Integer argument specifying a tag which must * @param tag Integer argument specifying a tag which must
* be matched by the tag of the incoming message. * be matched by the tag of the incoming message.
*/ */
MPI_Request IrecvBytes( MPI_Request IrecvBytes(void *buf, const int N_bytes, const int send_proc,
void *buf, const int N_bytes, const int send_proc, const int tag ) const; const int tag) const;
/*! /*!
* @brief This function sends and recieves data using a blocking call * @brief This function sends and recieves data using a blocking call
*/ */
template<class type> template <class type>
void sendrecv( const type *sendbuf, int sendcount, int dest, int sendtag, type *recvbuf, void sendrecv(const type *sendbuf, int sendcount, int dest, int sendtag,
int recvcount, int source, int recvtag ) const; type *recvbuf, int recvcount, int source, int recvtag) const;
/*! /*!
* Each processor sends every other processor a single value. * Each processor sends every other processor a single value.
* @param[in] x Input value for allGather * @param[in] x Input value for allGather
* @return Output array for allGather * @return Output array for allGather
*/ */
template<class type> template <class type> std::vector<type> allGather(const type &x) const;
std::vector<type> allGather( const type &x ) const;
/*! /*!
* Each processor sends every other processor an array * Each processor sends every other processor an array
* @param[in] x Input array for allGather * @param[in] x Input array for allGather
* @return Output array for allGather * @return Output array for allGather
*/ */
template<class type> template <class type>
std::vector<type> allGather( const std::vector<type> &x ) const; std::vector<type> allGather(const std::vector<type> &x) const;
/*! /*!
* Each processor sends every other processor a single value. * Each processor sends every other processor a single value.
@ -832,9 +764,7 @@ public: // Member functions
* @param x_out Output array for allGather (must be preallocated to the size of the * @param x_out Output array for allGather (must be preallocated to the size of the
* communicator) * communicator)
*/ */
template<class type> template <class type> void allGather(const type &x_in, type *x_out) const;
void allGather( const type &x_in, type *x_out ) const;
/*! /*!
* Each processor sends an array of data to all other processors. * Each processor sends an array of data to all other processors.
@ -861,27 +791,24 @@ public: // Member functions
* internally * internally
* and the sizes and displacements will be returned (if desired). * and the sizes and displacements will be returned (if desired).
*/ */
template<class type> template <class type>
int allGather( const type *send_data, const int send_cnt, type *recv_data, int allGather(const type *send_data, const int send_cnt, type *recv_data,
int *recv_cnt = nullptr, int *recv_disp = nullptr, bool known_recv = false ) const; int *recv_cnt = nullptr, int *recv_disp = nullptr,
bool known_recv = false) const;
/*! /*!
* This function combines sets from different processors to create a single master set * This function combines sets from different processors to create a single master set
* @param set Input/Output std::set for the gather. * @param set Input/Output std::set for the gather.
*/ */
template<class type> template <class type> void setGather(std::set<type> &set) const;
void setGather( std::set<type> &set ) const;
/*! /*!
* This function combines std::maps from different processors to create a single master std::map * This function combines std::maps from different processors to create a single master std::map
* If two or more ranks share the same key, the lowest rank will be used * If two or more ranks share the same key, the lowest rank will be used
* @param map Input/Output std::map for the gather. * @param map Input/Output std::map for the gather.
*/ */
template<class KEY, class DATA> template <class KEY, class DATA>
void mapGather( std::map<KEY, DATA> &map ) const; void mapGather(std::map<KEY, DATA> &map) const;
/*! /*!
* Each processor sends an array of n values to each processor. * Each processor sends an array of n values to each processor.
@ -894,9 +821,8 @@ public: // Member functions
* @param send_data Input array (nxN) * @param send_data Input array (nxN)
* @param recv_data Output array of received values (nxN) * @param recv_data Output array of received values (nxN)
*/ */
template<class type> template <class type>
void allToAll( const int n, const type *send_data, type *recv_data ) const; void allToAll(const int n, const type *send_data, type *recv_data) const;
/*! /*!
* Each processor sends an array of data to the different processors. * Each processor sends an array of data to the different processors.
@ -926,11 +852,11 @@ public: // Member functions
* internally * internally
* and the sizes and displacements will be returned (if desired). * and the sizes and displacements will be returned (if desired).
*/ */
template<class type> template <class type>
int allToAll( const type *send_data, const int send_cnt[], const int send_disp[], int allToAll(const type *send_data, const int send_cnt[],
type *recv_data, int *recv_cnt = nullptr, int *recv_disp = nullptr, const int send_disp[], type *recv_data,
bool known_recv = false ) const; int *recv_cnt = nullptr, int *recv_disp = nullptr,
bool known_recv = false) const;
/*! /*!
* \brief Send a list of proccesor ids to communicate * \brief Send a list of proccesor ids to communicate
@ -942,8 +868,7 @@ public: // Member functions
* \param ranks List of ranks that the current rank wants to communicate with * \param ranks List of ranks that the current rank wants to communicate with
* \return List of ranks that want to communicate with the current processor * \return List of ranks that want to communicate with the current processor
*/ */
std::vector<int> commRanks( const std::vector<int> &ranks ) const; std::vector<int> commRanks(const std::vector<int> &ranks) const;
/*! /*!
* \brief Wait for a communication to finish * \brief Wait for a communication to finish
@ -951,8 +876,7 @@ public: // Member functions
* Note: this does not require a communicator. * Note: this does not require a communicator.
* \param request Communication request to wait for (returned for Isend or Irecv) * \param request Communication request to wait for (returned for Isend or Irecv)
*/ */
static void wait( MPI_Request request ); static void wait(MPI_Request request);
/*! /*!
* \brief Wait for any communication to finish. * \brief Wait for any communication to finish.
@ -962,8 +886,7 @@ public: // Member functions
* \param count Number of communications to check * \param count Number of communications to check
* \param request Array of communication requests to wait for (returned for Isend or Irecv) * \param request Array of communication requests to wait for (returned for Isend or Irecv)
*/ */
static int waitAny( int count, MPI_Request *request ); static int waitAny(int count, MPI_Request *request);
/*! /*!
* \brief Wait for all communications to finish. * \brief Wait for all communications to finish.
@ -972,8 +895,7 @@ public: // Member functions
* \param count Number of communications to check * \param count Number of communications to check
* \param request Array of communication requests to wait for (returned for Isend or Irecv) * \param request Array of communication requests to wait for (returned for Isend or Irecv)
*/ */
static void waitAll( int count, MPI_Request *request ); static void waitAll(int count, MPI_Request *request);
/*! /*!
* \brief Wait for some communications to finish. * \brief Wait for some communications to finish.
@ -983,8 +905,7 @@ public: // Member functions
* \param count Number of communications to check * \param count Number of communications to check
* \param request Array of communication requests to wait for (returned for Isend or Irecv) * \param request Array of communication requests to wait for (returned for Isend or Irecv)
*/ */
static std::vector<int> waitSome( int count, MPI_Request *request ); static std::vector<int> waitSome(int count, MPI_Request *request);
/*! /*!
* \brief Nonblocking test for a message * \brief Nonblocking test for a message
@ -995,8 +916,7 @@ public: // Member functions
* \param source source rank (-1: any source) * \param source source rank (-1: any source)
* \param tag tag (-1: any tag) * \param tag tag (-1: any tag)
*/ */
int Iprobe( int source = -1, int tag = -1 ) const; int Iprobe(int source = -1, int tag = -1) const;
/*! /*!
* \brief Blocking test for a message * \brief Blocking test for a message
@ -1006,8 +926,7 @@ public: // Member functions
* \param source source rank (-1: any source) * \param source source rank (-1: any source)
* \param tag tag (-1: any tag) * \param tag tag (-1: any tag)
*/ */
int probe( int source = -1, int tag = -1 ) const; int probe(int source = -1, int tag = -1) const;
/*! /*!
* \brief Start a serial region * \brief Start a serial region
@ -1018,14 +937,12 @@ public: // Member functions
*/ */
void serializeStart(); void serializeStart();
/*! /*!
* \brief Stop a serial region * \brief Stop a serial region
* \details Stop a serial region. See serializeStart for more information. * \details Stop a serial region. See serializeStart for more information.
*/ */
void serializeStop(); void serializeStop();
/*! /*!
* \brief Elapsed time * \brief Elapsed time
* \details This function returns the elapsed time on the calling processor * \details This function returns the elapsed time on the calling processor
@ -1036,21 +953,18 @@ public: // Member functions
*/ */
static double time(); static double time();
/*! /*!
* \brief Timer resolution * \brief Timer resolution
* \details This function returns the timer resolution used by "time" * \details This function returns the timer resolution used by "time"
*/ */
static double tick(); static double tick();
/*! /*!
* \brief Change the level of the internal timers * \brief Change the level of the internal timers
* \details This function changes the level of the timers used to profile MPI * \details This function changes the level of the timers used to profile MPI
* \param level New level of the timers * \param level New level of the timers
*/ */
static void changeProfileLevel( int level ) { profile_level = level; } static void changeProfileLevel(int level) { profile_level = level; }
//! Return the total number of MPI_Comm objects that have been created //! Return the total number of MPI_Comm objects that have been created
static size_t MPI_Comm_created() { return N_MPI_Comm_created; } static size_t MPI_Comm_created() { return N_MPI_Comm_created; }
@ -1068,51 +982,51 @@ public: // Member functions
static bool MPI_Active(); static bool MPI_Active();
//! Start MPI //! Start MPI
static void start_MPI( int argc_in, char *argv_in[], int profile_level = 0 ); static void start_MPI(int argc_in, char *argv_in[], int profile_level = 0);
//! Stop MPI //! Stop MPI
static void stop_MPI(); static void stop_MPI();
/*! /*!
* \brief Load balance * \brief Load balance
* \details This function will return a new communicator in which the ranks match * \details This function will return a new communicator in which the ranks match
* the performance and the work load. * the performance and the work load.
*/ */
MPI loadBalance( double localPerformance, std::vector<double> work ); MPI loadBalance(double localPerformance, std::vector<double> work);
private: // Private helper functions for templated MPI operations; private: // Private helper functions for templated MPI operations;
template<class type> template <class type> void call_sumReduce(type *x, const int n = 1) const;
void call_sumReduce( type *x, const int n = 1 ) const; template <class type>
template<class type> void call_sumReduce(const type *x, type *y, const int n = 1) const;
void call_sumReduce( const type *x, type *y, const int n = 1 ) const; template <class type>
template<class type> void call_minReduce(type *x, const int n = 1,
void call_minReduce( type *x, const int n = 1, int *rank_of_min = nullptr ) const; int *rank_of_min = nullptr) const;
template<class type> template <class type>
void call_minReduce( void call_minReduce(const type *x, type *y, const int n = 1,
const type *x, type *y, const int n = 1, int *rank_of_min = nullptr ) const; int *rank_of_min = nullptr) const;
template<class type> template <class type>
void call_maxReduce( type *x, const int n = 1, int *rank_of_max = nullptr ) const; void call_maxReduce(type *x, const int n = 1,
template<class type> int *rank_of_max = nullptr) const;
void call_maxReduce( template <class type>
const type *x, type *y, const int n = 1, int *rank_of_max = nullptr ) const; void call_maxReduce(const type *x, type *y, const int n = 1,
template<class type> int *rank_of_max = nullptr) const;
void call_bcast( type *x, const int n, const int root ) const; template <class type>
template<class type> void call_bcast(type *x, const int n, const int root) const;
void call_allGather( const type &x_in, type *x_out ) const; template <class type>
template<class type> void call_allGather(const type &x_in, type *x_out) const;
void call_allGather( template <class type>
const type *x_in, int size_in, type *x_out, int *size_out, int *disp_out ) const; void call_allGather(const type *x_in, int size_in, type *x_out,
template<class type> int *size_out, int *disp_out) const;
void call_sumScan( const type *x, type *y, int n = 1 ) const; template <class type>
template<class type> void call_sumScan(const type *x, type *y, int n = 1) const;
void call_minScan( const type *x, type *y, int n = 1 ) const; template <class type>
template<class type> void call_minScan(const type *x, type *y, int n = 1) const;
void call_maxScan( const type *x, type *y, int n = 1 ) const; template <class type>
template<class type> void call_maxScan(const type *x, type *y, int n = 1) const;
void call_allToAll( const type *send_data, const int send_cnt[], const int send_disp[], template <class type>
type *recv_data, const int *recv_cnt, const int *recv_disp ) const; void call_allToAll(const type *send_data, const int send_cnt[],
const int send_disp[], type *recv_data,
const int *recv_cnt, const int *recv_disp) const;
private: // data members private: // data members
// The internal MPI communicator // The internal MPI communicator
@ -1157,14 +1071,11 @@ private: // data members
static volatile unsigned int N_MPI_Comm_destroyed; static volatile unsigned int N_MPI_Comm_destroyed;
}; };
} // namespace Utilities } // namespace Utilities
// Include the default instantiations // Include the default instantiations
// \cond HIDDEN_SYMBOLS // \cond HIDDEN_SYMBOLS
#include "common/MPI.I" #include "common/MPI.I"
// \endcond // \endcond
#endif #endif

View File

@ -5,112 +5,108 @@
#include <cstring> #include <cstring>
// Read a file into memory // Read a file into memory
std::vector<char> readFile( const std::string& filename ) std::vector<char> readFile(const std::string &filename) {
{ auto fid = fopen(filename.c_str(), "rb");
auto fid = fopen( filename.c_str(), "rb" ); INSIST(fid, "File does not exist: " + filename);
INSIST( fid, "File does not exist: " + filename ); fseek(fid, 0, SEEK_END);
fseek( fid, 0, SEEK_END );
size_t bytes = ftell(fid); size_t bytes = ftell(fid);
fseek( fid, 0, SEEK_SET ); fseek(fid, 0, SEEK_SET);
std::vector<char> data( bytes ); std::vector<char> data(bytes);
size_t bytes2 = fread( data.data(), 1, bytes, fid ); size_t bytes2 = fread(data.data(), 1, bytes, fid);
ASSERT( bytes == bytes2 ); ASSERT(bytes == bytes2);
fclose( fid ); fclose(fid);
return data; return data;
} }
// Decompress a gzip buffer // Decompress a gzip buffer
std::vector<char> gunzip( const std::vector<char>& in ) std::vector<char> gunzip(const std::vector<char> &in) {
{
z_stream stream; z_stream stream;
std::vector<char> out( 1000000 ); std::vector<char> out(1000000);
stream.next_in = (Bytef*) in.data(); stream.next_in = (Bytef *)in.data();
stream.avail_in = in.size(); stream.avail_in = in.size();
stream.total_in = 0; stream.total_in = 0;
stream.zalloc = Z_NULL; stream.zalloc = Z_NULL;
stream.zfree = Z_NULL; stream.zfree = Z_NULL;
stream.opaque = Z_NULL; stream.opaque = Z_NULL;
stream.next_out = (Bytef*) out.data(); stream.next_out = (Bytef *)out.data();
stream.avail_out = out.size(); stream.avail_out = out.size();
stream.total_out = 0; stream.total_out = 0;
ASSERT( inflateInit2(&stream, 16+MAX_WBITS) == Z_OK ); ASSERT(inflateInit2(&stream, 16 + MAX_WBITS) == Z_OK);
bool finished = inflate(&stream, Z_SYNC_FLUSH) == Z_STREAM_END; bool finished = inflate(&stream, Z_SYNC_FLUSH) == Z_STREAM_END;
while ( !finished && stream.msg == Z_NULL ) { while (!finished && stream.msg == Z_NULL) {
out.resize( 2 * out.size() ); out.resize(2 * out.size());
stream.next_out = (Bytef*) &out[stream.total_out]; stream.next_out = (Bytef *)&out[stream.total_out];
stream.avail_out = out.size() - stream.total_out; stream.avail_out = out.size() - stream.total_out;
finished = inflate(&stream, Z_SYNC_FLUSH) == Z_STREAM_END; finished = inflate(&stream, Z_SYNC_FLUSH) == Z_STREAM_END;
} }
ASSERT( stream.msg == Z_NULL ); ASSERT(stream.msg == Z_NULL);
out.resize( stream.total_out ); out.resize(stream.total_out);
inflateEnd(&stream); inflateEnd(&stream);
return out; return out;
} }
// Read the compressed micro CT data // Read the compressed micro CT data
Array<uint8_t> readMicroCT( const std::string& filename ) Array<uint8_t> readMicroCT(const std::string &filename) {
{ auto in = readFile(filename);
auto in = readFile( filename ); auto out = gunzip(in);
auto out = gunzip( in ); ASSERT(out.size() == 1024 * 1024 * 1024);
ASSERT( out.size() == 1024*1024*1024 ); Array<uint8_t> data(1024, 1024, 1024);
Array<uint8_t> data( 1024, 1024, 1024 ); memcpy(data.data(), out.data(), data.length());
memcpy( data.data(), out.data(), data.length() );
return data; return data;
} }
// Read the compressed micro CT data and distribute // Read the compressed micro CT data and distribute
Array<uint8_t> readMicroCT( const Database& domain, const Utilities::MPI& comm ) Array<uint8_t> readMicroCT(const Database &domain, const Utilities::MPI &comm) {
{
// Get the local problem info // Get the local problem info
auto n = domain.getVector<int>( "n" ); auto n = domain.getVector<int>("n");
int rank = comm.getRank(); int rank = comm.getRank();
auto nproc = domain.getVector<int>( "nproc" ); auto nproc = domain.getVector<int>("nproc");
RankInfoStruct rankInfo( rank, nproc[0], nproc[1], nproc[2] ); RankInfoStruct rankInfo(rank, nproc[0], nproc[1], nproc[2]);
// Determine the largest file number to get // Determine the largest file number to get
int Nfx = ( n[0] * rankInfo.nx + 1023 ) / 1024; int Nfx = (n[0] * rankInfo.nx + 1023) / 1024;
int Nfy = ( n[1] * rankInfo.ny + 1023 ) / 1024; int Nfy = (n[1] * rankInfo.ny + 1023) / 1024;
int Nfz = ( n[2] * rankInfo.nz + 1023 ) / 1024; int Nfz = (n[2] * rankInfo.nz + 1023) / 1024;
// Load one of the files if rank < largest file // Load one of the files if rank < largest file
Array<uint8_t> data; Array<uint8_t> data;
RankInfoStruct srcRankInfo( rank, Nfx, Nfy, Nfz ); RankInfoStruct srcRankInfo(rank, Nfx, Nfy, Nfz);
if ( srcRankInfo.ix >= 0 ) { if (srcRankInfo.ix >= 0) {
auto filename = domain.getScalar<std::string>( "Filename" ); auto filename = domain.getScalar<std::string>("Filename");
char tmp[100]; char tmp[100];
if ( filename.find( "0x_0y_0z.gbd.gz" ) != std::string::npos ) { if (filename.find("0x_0y_0z.gbd.gz") != std::string::npos) {
sprintf( tmp, "%ix_%iy_%iz.gbd.gz", srcRankInfo.ix, srcRankInfo.jy, srcRankInfo.kz ); sprintf(tmp, "%ix_%iy_%iz.gbd.gz", srcRankInfo.ix, srcRankInfo.jy,
filename = filename.replace( filename.find( "0x_0y_0z.gbd.gz" ), 15, std::string( tmp ) ); srcRankInfo.kz);
} else if ( filename.find( "x0_y0_z0.gbd.gz" ) != std::string::npos ) { filename = filename.replace(filename.find("0x_0y_0z.gbd.gz"), 15,
sprintf( tmp, "x%i_y%i_z%i.gbd.gz", srcRankInfo.ix, srcRankInfo.jy, srcRankInfo.kz ); std::string(tmp));
filename = filename.replace( filename.find( "x0_y0_z0.gbd.gz" ), 15, std::string( tmp ) ); } else if (filename.find("x0_y0_z0.gbd.gz") != std::string::npos) {
} else { sprintf(tmp, "x%i_y%i_z%i.gbd.gz", srcRankInfo.ix, srcRankInfo.jy,
ERROR( "Invalid name for first file" ); srcRankInfo.kz);
} filename = filename.replace(filename.find("x0_y0_z0.gbd.gz"), 15,
data = readMicroCT( filename ); std::string(tmp));
} else {
ERROR("Invalid name for first file");
}
data = readMicroCT(filename);
} }
// Redistribute the data // Redistribute the data
data = redistribute( srcRankInfo, data, rankInfo, { n[0], n[1], n[2] }, comm ); data = redistribute(srcRankInfo, data, rankInfo, {n[0], n[1], n[2]}, comm);
// Relabel the data // Relabel the data
auto ReadValues = domain.getVector<int>( "ReadValues" ); auto ReadValues = domain.getVector<int>("ReadValues");
auto WriteValues = domain.getVector<int>( "WriteValues" ); auto WriteValues = domain.getVector<int>("WriteValues");
ASSERT( ReadValues.size() == WriteValues.size() ); ASSERT(ReadValues.size() == WriteValues.size());
int readMaxValue = 0; int readMaxValue = 0;
for ( auto v : ReadValues ) for (auto v : ReadValues)
readMaxValue = std::max( data.max()+1, v ); readMaxValue = std::max(data.max() + 1, v);
std::vector<int> map( readMaxValue + 1, -1 ); std::vector<int> map(readMaxValue + 1, -1);
for ( size_t i=0; i<ReadValues.size(); i++ ) for (size_t i = 0; i < ReadValues.size(); i++)
map[ReadValues[i]] = WriteValues[i]; map[ReadValues[i]] = WriteValues[i];
for ( size_t i=0; i<data.length(); i++ ) { for (size_t i = 0; i < data.length(); i++) {
int t = data(i); int t = data(i);
ASSERT( t >= 0 && t <= readMaxValue ); ASSERT(t >= 0 && t <= readMaxValue);
data(i) = map[t]; data(i) = map[t];
} }

View File

@ -1,16 +1,13 @@
#ifndef READMICROCT_H #ifndef READMICROCT_H
#define READMICROCT_H #define READMICROCT_H
#include "common/Array.h" #include "common/Array.h"
#include "common/Communication.h" #include "common/Communication.h"
#include "common/Database.h" #include "common/Database.h"
#include "common/MPI.h" #include "common/MPI.h"
Array<uint8_t> readMicroCT(const std::string &filename);
Array<uint8_t> readMicroCT( const std::string& filename ); Array<uint8_t> readMicroCT(const Database &domain, const Utilities::MPI &comm);
Array<uint8_t> readMicroCT( const Database& domain, const Utilities::MPI& comm );
#endif #endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -47,245 +47,277 @@
#include "common/SpherePack.h" #include "common/SpherePack.h"
// Inline function to read line without a return argument // Inline function to read line without a return argument
static inline void fgetl( char * str, int num, FILE * stream ) static inline void fgetl(char *str, int num, FILE *stream) {
{ char *ptr = fgets(str, num, stream);
char* ptr = fgets( str, num, stream ); if (0) {
if ( 0 ) {char *temp = (char *)&ptr; temp++;} char *temp = (char *)&ptr;
temp++;
}
} }
void WriteLocalSolidID(char *FILENAME, char *ID, int N) void WriteLocalSolidID(char *FILENAME, char *ID, int N) {
{ char value;
char value; ofstream File(FILENAME, ios::binary);
ofstream File(FILENAME,ios::binary); for (int n = 0; n < N; n++) {
for (int n=0; n<N; n++){ value = ID[n];
value = ID[n]; File.write((char *)&value, sizeof(value));
File.write((char*) &value, sizeof(value)); }
} File.close();
File.close();
} }
void WriteLocalSolidDistance(char *FILENAME, double *Distance, int N) void WriteLocalSolidDistance(char *FILENAME, double *Distance, int N) {
{ double value;
double value; ofstream File(FILENAME, ios::binary);
ofstream File(FILENAME,ios::binary); for (int n = 0; n < N; n++) {
for (int n=0; n<N; n++){ value = Distance[n];
value = Distance[n]; File.write((char *)&value, sizeof(value));
File.write((char*) &value, sizeof(value)); }
} File.close();
File.close();
} }
void ReadSpherePacking(int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad) void ReadSpherePacking(int nspheres, double *List_cx, double *List_cy,
{ double *List_cz, double *List_rad) {
// Read in the full sphere pack // Read in the full sphere pack
//...... READ IN THE SPHERES................................... //...... READ IN THE SPHERES...................................
cout << "Reading the packing file..." << endl; cout << "Reading the packing file..." << endl;
FILE *fid = fopen("pack.out","rb"); FILE *fid = fopen("pack.out", "rb");
INSIST(fid!=NULL,"Error opening pack.out"); INSIST(fid != NULL, "Error opening pack.out");
//.........Trash the header lines.......... //.........Trash the header lines..........
char line[100]; char line[100];
fgetl(line, 100, fid); fgetl(line, 100, fid);
fgetl(line, 100, fid); fgetl(line, 100, fid);
fgetl(line, 100, fid); fgetl(line, 100, fid);
fgetl(line, 100, fid); fgetl(line, 100, fid);
fgetl(line, 100, fid); fgetl(line, 100, fid);
//........read the spheres.................. //........read the spheres..................
// We will read until a blank like or end-of-file is reached // We will read until a blank like or end-of-file is reached
int count = 0; int count = 0;
while ( !feof(fid) && fgets(line,100,fid)!=NULL ) { while (!feof(fid) && fgets(line, 100, fid) != NULL) {
char* line2 = line; char *line2 = line;
List_cx[count] = strtod(line2,&line2); List_cx[count] = strtod(line2, &line2);
List_cy[count] = strtod(line2,&line2); List_cy[count] = strtod(line2, &line2);
List_cz[count] = strtod(line2,&line2); List_cz[count] = strtod(line2, &line2);
List_rad[count] = strtod(line2,&line2); List_rad[count] = strtod(line2, &line2);
count++; count++;
} }
cout << "Number of spheres extracted is: " << count << endl; cout << "Number of spheres extracted is: " << count << endl;
INSIST( count==nspheres, "Specified number of spheres is probably incorrect!" ); INSIST(count == nspheres,
// ............................................................. "Specified number of spheres is probably incorrect!");
// .............................................................
} }
void AssignLocalSolidID(char *ID, int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad, void AssignLocalSolidID(char *ID, int nspheres, double *List_cx,
double Lx, double Ly, double Lz, int Nx, int Ny, int Nz, double *List_cy, double *List_cz, double *List_rad,
int iproc, int jproc, int kproc, int nprocx, int nprocy, int nprocz) double Lx, double Ly, double Lz, int Nx, int Ny, int Nz,
{ int iproc, int jproc, int kproc, int nprocx, int nprocy,
// Use sphere lists to determine which nodes are in porespace int nprocz) {
// Write out binary file for nodes // Use sphere lists to determine which nodes are in porespace
char value; // Write out binary file for nodes
int N = Nx*Ny*Nz; // Domain size, including the halo char value;
double hx,hy,hz; int N = Nx * Ny * Nz; // Domain size, including the halo
double x,y,z; double hx, hy, hz;
double cx,cy,cz,r; double x, y, z;
int imin,imax,jmin,jmax,kmin,kmax; double cx, cy, cz, r;
int p,i,j,k,n; int imin, imax, jmin, jmax, kmin, kmax;
//............................................ int p, i, j, k, n;
double min_x,min_y,min_z; //............................................
// double max_x,max_y,max_z; double min_x, min_y, min_z;
//............................................ // double max_x,max_y,max_z;
// Lattice spacing for the entire domain //............................................
// It should generally be true that hx=hy=hz // Lattice spacing for the entire domain
// Otherwise, you will end up with ellipsoids // It should generally be true that hx=hy=hz
hx = Lx/(Nx*nprocx-1); // Otherwise, you will end up with ellipsoids
hy = Ly/(Ny*nprocy-1); hx = Lx / (Nx * nprocx - 1);
hz = Lz/(Nz*nprocz-1); hy = Ly / (Ny * nprocy - 1);
//............................................ hz = Lz / (Nz * nprocz - 1);
// Get maximum and minimum for this domain //............................................
// Halo is included ! // Get maximum and minimum for this domain
min_x = double(iproc*Nx-1)*hx; // Halo is included !
min_y = double(jproc*Ny-1)*hy; min_x = double(iproc * Nx - 1) * hx;
min_z = double(kproc*Nz-1)*hz; min_y = double(jproc * Ny - 1) * hy;
// max_x = ((iproc+1)*Nx+1)*hx; min_z = double(kproc * Nz - 1) * hz;
// max_y = ((jproc+1)*Ny+1)*hy; // max_x = ((iproc+1)*Nx+1)*hx;
// max_z = ((kproc+1)*Nz+1)*hz; // max_y = ((jproc+1)*Ny+1)*hy;
//............................................ // max_z = ((kproc+1)*Nz+1)*hz;
//............................................
//............................................ //............................................
// Pre-initialize local ID // Pre-initialize local ID
for (n=0;n<N;n++){ for (n = 0; n < N; n++) {
ID[n]=1; ID[n] = 1;
} }
//............................................ //............................................
//............................................ //............................................
// .........Loop over the spheres............. // .........Loop over the spheres.............
for (p=0;p<nspheres;p++){ for (p = 0; p < nspheres; p++) {
// Get the sphere from the list, map to local min // Get the sphere from the list, map to local min
cx = List_cx[p] - min_x; cx = List_cx[p] - min_x;
cy = List_cy[p] - min_y; cy = List_cy[p] - min_y;
cz = List_cz[p] - min_z; cz = List_cz[p] - min_z;
r = List_rad[p]; r = List_rad[p];
// Check if // Check if
// Range for this sphere in global indexing // Range for this sphere in global indexing
imin = int ((cx-r)/hx)-1; imin = int((cx - r) / hx) - 1;
imax = int ((cx+r)/hx)+1; imax = int((cx + r) / hx) + 1;
jmin = int ((cy-r)/hy)-1; jmin = int((cy - r) / hy) - 1;
jmax = int ((cy+r)/hy)+1; jmax = int((cy + r) / hy) + 1;
kmin = int ((cz-r)/hz)-1; kmin = int((cz - r) / hz) - 1;
kmax = int ((cz+r)/hz)+1; kmax = int((cz + r) / hz) + 1;
// Obviously we have to do something at the edges // Obviously we have to do something at the edges
if (imin<0) imin = 0; if (imin < 0)
if (imin>Nx) imin = Nx; imin = 0;
if (imax<0) imax = 0; if (imin > Nx)
if (imax>Nx) imax = Nx; imin = Nx;
if (jmin<0) jmin = 0; if (imax < 0)
if (jmin>Ny) jmin = Ny; imax = 0;
if (jmax<0) jmax = 0; if (imax > Nx)
if (jmax>Ny) jmax = Ny; imax = Nx;
if (kmin<0) kmin = 0; if (jmin < 0)
if (kmin>Nz) kmin = Nz; jmin = 0;
if (kmax<0) kmax = 0; if (jmin > Ny)
if (kmax>Nz) kmax = Nz; jmin = Ny;
// Loop over the domain for this sphere (may be null) if (jmax < 0)
for (i=imin;i<imax;i++){ jmax = 0;
for (j=jmin;j<jmax;j++){ if (jmax > Ny)
for (k=kmin;k<kmax;k++){ jmax = Ny;
// Initialize ID value to 'fluid (=1)' if (kmin < 0)
x = i*hx; kmin = 0;
y = j*hy; if (kmin > Nz)
z = k*hz; kmin = Nz;
value = 1; if (kmax < 0)
// if inside sphere, set to zero kmax = 0;
if ( (cx-x)*(cx-x)+(cy-y)*(cy-y)+(cz-z)*(cz-z) < r*r){ if (kmax > Nz)
value=0; kmax = Nz;
} // Loop over the domain for this sphere (may be null)
// get the position in the list for (i = imin; i < imax; i++) {
n = k*Nx*Ny+j*Nx+i; for (j = jmin; j < jmax; j++) {
if ( ID[n] != 0 ){ for (k = kmin; k < kmax; k++) {
ID[n] = value; // Initialize ID value to 'fluid (=1)'
} x = i * hx;
} y = j * hy;
} z = k * hz;
} value = 1;
} // if inside sphere, set to zero
if ((cx - x) * (cx - x) + (cy - y) * (cy - y) +
(cz - z) * (cz - z) <
r * r) {
value = 0;
}
// get the position in the list
n = k * Nx * Ny + j * Nx + i;
if (ID[n] != 0) {
ID[n] = value;
}
}
}
}
}
} }
void SignedDistance(double *Distance, int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad, void SignedDistance(double *Distance, int nspheres, double *List_cx,
double Lx, double Ly, double Lz, int Nx, int Ny, int Nz, double *List_cy, double *List_cz, double *List_rad,
int iproc, int jproc, int kproc, int nprocx, int nprocy, int nprocz) double Lx, double Ly, double Lz, int Nx, int Ny, int Nz,
{ int iproc, int jproc, int kproc, int nprocx, int nprocy,
// Use sphere lists to determine which nodes are in porespace int nprocz) {
// Write out binary file for nodes // Use sphere lists to determine which nodes are in porespace
int N = Nx*Ny*Nz; // Domain size, including the halo // Write out binary file for nodes
double hx,hy,hz; int N = Nx * Ny * Nz; // Domain size, including the halo
double x,y,z; double hx, hy, hz;
double cx,cy,cz,r; double x, y, z;
int imin,imax,jmin,jmax,kmin,kmax; double cx, cy, cz, r;
int p,i,j,k,n; int imin, imax, jmin, jmax, kmin, kmax;
//............................................ int p, i, j, k, n;
double min_x,min_y,min_z; //............................................
double distance; double min_x, min_y, min_z;
//............................................ double distance;
// Lattice spacing for the entire domain //............................................
// It should generally be true that hx=hy=hz // Lattice spacing for the entire domain
// Otherwise, you will end up with ellipsoids // It should generally be true that hx=hy=hz
hx = Lx/((Nx-2)*nprocx-1); // Otherwise, you will end up with ellipsoids
hy = Ly/((Ny-2)*nprocy-1); hx = Lx / ((Nx - 2) * nprocx - 1);
hz = Lz/((Nz-2)*nprocz-1); hy = Ly / ((Ny - 2) * nprocy - 1);
//............................................ hz = Lz / ((Nz - 2) * nprocz - 1);
// Get maximum and minimum for this domain //............................................
// Halo is included ! // Get maximum and minimum for this domain
min_x = double(iproc*(Nx-2)-1)*hx; // Halo is included !
min_y = double(jproc*(Ny-2)-1)*hy; min_x = double(iproc * (Nx - 2) - 1) * hx;
min_z = double(kproc*(Nz-2)-1)*hz; min_y = double(jproc * (Ny - 2) - 1) * hy;
//............................................ min_z = double(kproc * (Nz - 2) - 1) * hz;
//............................................
//............................................ //............................................
// Pre-initialize Distance // Pre-initialize Distance
for (n=0;n<N;n++){ for (n = 0; n < N; n++) {
Distance[n]=100.0; Distance[n] = 100.0;
} }
//............................................ //............................................
//............................................ //............................................
// .........Loop over the spheres............. // .........Loop over the spheres.............
for (p=0;p<nspheres;p++){ for (p = 0; p < nspheres; p++) {
// Get the sphere from the list, map to local min // Get the sphere from the list, map to local min
cx = List_cx[p] - min_x; cx = List_cx[p] - min_x;
cy = List_cy[p] - min_y; cy = List_cy[p] - min_y;
cz = List_cz[p] - min_z; cz = List_cz[p] - min_z;
r = List_rad[p]; r = List_rad[p];
// Check if // Check if
// Range for this sphere in global indexing // Range for this sphere in global indexing
imin = int ((cx-2*r)/hx); imin = int((cx - 2 * r) / hx);
imax = int ((cx+2*r)/hx)+2; imax = int((cx + 2 * r) / hx) + 2;
jmin = int ((cy-2*r)/hy); jmin = int((cy - 2 * r) / hy);
jmax = int ((cy+2*r)/hy)+2; jmax = int((cy + 2 * r) / hy) + 2;
kmin = int ((cz-2*r)/hz); kmin = int((cz - 2 * r) / hz);
kmax = int ((cz+2*r)/hz)+2; kmax = int((cz + 2 * r) / hz) + 2;
// Obviously we have to do something at the edges // Obviously we have to do something at the edges
if (imin<0) imin = 0; if (imin < 0)
if (imin>Nx) imin = Nx; imin = 0;
if (imax<0) imax = 0; if (imin > Nx)
if (imax>Nx) imax = Nx; imin = Nx;
if (jmin<0) jmin = 0; if (imax < 0)
if (jmin>Ny) jmin = Ny; imax = 0;
if (jmax<0) jmax = 0; if (imax > Nx)
if (jmax>Ny) jmax = Ny; imax = Nx;
if (kmin<0) kmin = 0; if (jmin < 0)
if (kmin>Nz) kmin = Nz; jmin = 0;
if (kmax<0) kmax = 0; if (jmin > Ny)
if (kmax>Nz) kmax = Nz; jmin = Ny;
// Loop over the domain for this sphere (may be null) if (jmax < 0)
for (i=imin;i<imax;i++){ jmax = 0;
for (j=jmin;j<jmax;j++){ if (jmax > Ny)
for (k=kmin;k<kmax;k++){ jmax = Ny;
// x,y,z is distance in physical units if (kmin < 0)
x = i*hx; kmin = 0;
y = j*hy; if (kmin > Nz)
z = k*hz; kmin = Nz;
// if inside sphere, set to zero if (kmax < 0)
// get the position in the list kmax = 0;
n = k*Nx*Ny+j*Nx+i; if (kmax > Nz)
// Compute the distance kmax = Nz;
distance = sqrt((cx-x)*(cx-x)+(cy-y)*(cy-y)+(cz-z)*(cz-z)) - r; // Loop over the domain for this sphere (may be null)
// Assign the minimum distance for (i = imin; i < imax; i++) {
if (distance < Distance[n]) Distance[n] = distance; for (j = jmin; j < jmax; j++) {
for (k = kmin; k < kmax; k++) {
// x,y,z is distance in physical units
x = i * hx;
y = j * hy;
z = k * hz;
// if inside sphere, set to zero
// get the position in the list
n = k * Nx * Ny + j * Nx + i;
// Compute the distance
distance = sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y) +
(cz - z) * (cz - z)) -
r;
// Assign the minimum distance
if (distance < Distance[n])
Distance[n] = distance;
}
}
}
}
} // Map the distance to lattice units
} for (n = 0; n < N; n++)
} Distance[n] = Distance[n] / hx;
}
// Map the distance to lattice units
for (n=0; n<N; n++) Distance[n] = Distance[n]/hx;
} }

View File

@ -40,14 +40,19 @@ void WriteLocalSolidID(char *FILENAME, char *ID, int N);
void WriteLocalSolidDistance(char *FILENAME, double *Distance, int N); void WriteLocalSolidDistance(char *FILENAME, double *Distance, int N);
void ReadSpherePacking(int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad); void ReadSpherePacking(int nspheres, double *List_cx, double *List_cy,
double *List_cz, double *List_rad);
void AssignLocalSolidID(char *ID, int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad, void AssignLocalSolidID(char *ID, int nspheres, double *List_cx,
double Lx, double Ly, double Lz, int Nx, int Ny, int Nz, double *List_cy, double *List_cz, double *List_rad,
int iproc, int jproc, int kproc, int nprocx, int nprocy, int nprocz); double Lx, double Ly, double Lz, int Nx, int Ny, int Nz,
int iproc, int jproc, int kproc, int nprocx, int nprocy,
int nprocz);
void SignedDistance(double *Distance, int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad, void SignedDistance(double *Distance, int nspheres, double *List_cx,
double Lx, double Ly, double Lz, int Nx, int Ny, int Nz, double *List_cy, double *List_cz, double *List_rad,
int iproc, int jproc, int kproc, int nprocx, int nprocy, int nprocz); double Lx, double Ly, double Lz, int Nx, int Ny, int Nz,
int iproc, int jproc, int kproc, int nprocx, int nprocy,
int nprocz);
#endif #endif

View File

@ -22,373 +22,361 @@
#include <string> #include <string>
#include <vector> #include <vector>
#define pout std::cout #define pout std::cout
#define printp printf #define printp printf
/******************************************************************** /********************************************************************
* Constructor/Destructor * * Constructor/Destructor *
********************************************************************/ ********************************************************************/
UnitTest::UnitTest() UnitTest::UnitTest() {
{
#ifdef USE_MPI #ifdef USE_MPI
comm = MPI_COMM_WORLD; comm = MPI_COMM_WORLD;
#endif #endif
} }
UnitTest::~UnitTest() { reset(); } UnitTest::~UnitTest() { reset(); }
void UnitTest::reset() void UnitTest::reset() {
{
mutex.lock(); mutex.lock();
// Clear the data forcing a reallocation // Clear the data forcing a reallocation
std::vector<std::string>().swap( pass_messages ); std::vector<std::string>().swap(pass_messages);
std::vector<std::string>().swap( fail_messages ); std::vector<std::string>().swap(fail_messages);
std::vector<std::string>().swap( expected_fail_messages ); std::vector<std::string>().swap(expected_fail_messages);
mutex.unlock(); mutex.unlock();
} }
/******************************************************************** /********************************************************************
* Add a pass, fail, expected failure message in a thread-safe way * * Add a pass, fail, expected failure message in a thread-safe way *
********************************************************************/ ********************************************************************/
void UnitTest::passes( const std::string &in ) void UnitTest::passes(const std::string &in) {
{
mutex.lock(); mutex.lock();
pass_messages.push_back( in ); pass_messages.push_back(in);
mutex.unlock(); mutex.unlock();
} }
void UnitTest::failure( const std::string &in ) void UnitTest::failure(const std::string &in) {
{
mutex.lock(); mutex.lock();
fail_messages.push_back( in ); fail_messages.push_back(in);
mutex.unlock(); mutex.unlock();
} }
void UnitTest::expected_failure( const std::string &in ) void UnitTest::expected_failure(const std::string &in) {
{
mutex.lock(); mutex.lock();
expected_fail_messages.push_back( in ); expected_fail_messages.push_back(in);
mutex.unlock(); mutex.unlock();
} }
/******************************************************************** /********************************************************************
* Print a global report * * Print a global report *
* Note: only rank 0 will print, all messages will be aggregated * * Note: only rank 0 will print, all messages will be aggregated *
********************************************************************/ ********************************************************************/
inline std::vector<int> UnitTest::allGather( int value ) const inline std::vector<int> UnitTest::allGather(int value) const {
{
int size = getSize(); int size = getSize();
std::vector<int> data( size, value ); std::vector<int> data(size, value);
#ifdef USE_MPI #ifdef USE_MPI
if ( size > 1 ) if (size > 1)
MPI_Allgather( &value, 1, MPI_INT, data.data(), 1, MPI_INT, comm ); MPI_Allgather(&value, 1, MPI_INT, data.data(), 1, MPI_INT, comm);
#endif #endif
return data; return data;
} }
inline void UnitTest::barrier() const inline void UnitTest::barrier() const {
{
#ifdef USE_MPI #ifdef USE_MPI
if ( getSize() > 1 ) if (getSize() > 1)
MPI_Barrier( comm ); MPI_Barrier(comm);
#endif #endif
} }
static inline void print_messages( const std::vector<std::vector<std::string>> &messages ) static inline void
{ print_messages(const std::vector<std::vector<std::string>> &messages) {
if ( messages.size() > 1 ) { if (messages.size() > 1) {
for ( size_t i = 0; i < messages.size(); i++ ) { for (size_t i = 0; i < messages.size(); i++) {
if ( !messages[i].empty() ) { if (!messages[i].empty()) {
printp( " Proccessor %i:\n", static_cast<int>( i ) ); printp(" Proccessor %i:\n", static_cast<int>(i));
for ( const auto &j : messages[i] ) for (const auto &j : messages[i])
pout << " " << j << std::endl; pout << " " << j << std::endl;
} }
} }
} else { } else {
for ( const auto &j : messages[0] ) for (const auto &j : messages[0])
pout << " " << j << std::endl; pout << " " << j << std::endl;
} }
} }
void UnitTest::report( const int level0 ) const void UnitTest::report(const int level0) const {
{
mutex.lock(); mutex.lock();
int size = getSize(); int size = getSize();
int rank = getRank(); int rank = getRank();
// Broadcast the print level from rank 0 // Broadcast the print level from rank 0
int level = level0; int level = level0;
#ifdef USE_MPI #ifdef USE_MPI
if ( getSize() > 1 ) if (getSize() > 1)
MPI_Bcast( &level, 1, MPI_INT, 0, comm ); MPI_Bcast(&level, 1, MPI_INT, 0, comm);
#endif #endif
if ( level < 0 || level > 2 ) if (level < 0 || level > 2)
ERROR( "Invalid print level" ); ERROR("Invalid print level");
// Perform a global all gather to get the number of failures per processor // Perform a global all gather to get the number of failures per processor
auto N_pass = allGather( pass_messages.size() ); auto N_pass = allGather(pass_messages.size());
auto N_fail = allGather( fail_messages.size() ); auto N_fail = allGather(fail_messages.size());
auto N_expected_fail = allGather( expected_fail_messages.size() ); auto N_expected_fail = allGather(expected_fail_messages.size());
int N_pass_tot = 0; int N_pass_tot = 0;
int N_fail_tot = 0; int N_fail_tot = 0;
int N_expected_fail_tot = 0; int N_expected_fail_tot = 0;
for ( int i = 0; i < size; i++ ) { for (int i = 0; i < size; i++) {
N_pass_tot += N_pass[i]; N_pass_tot += N_pass[i];
N_fail_tot += N_fail[i]; N_fail_tot += N_fail[i];
N_expected_fail_tot += N_expected_fail[i]; N_expected_fail_tot += N_expected_fail[i];
} }
// Send all messages to rank 0 (if needed) // Send all messages to rank 0 (if needed)
std::vector<std::vector<std::string>> pass_messages_rank( size ); std::vector<std::vector<std::string>> pass_messages_rank(size);
std::vector<std::vector<std::string>> fail_messages_rank( size ); std::vector<std::vector<std::string>> fail_messages_rank(size);
std::vector<std::vector<std::string>> expected_fail_rank( size ); std::vector<std::vector<std::string>> expected_fail_rank(size);
// Get the pass messages // Get the pass messages
if ( ( level == 1 && N_pass_tot <= 20 ) || level == 2 ) if ((level == 1 && N_pass_tot <= 20) || level == 2)
pass_messages_rank = UnitTest::gatherMessages( pass_messages, 1 ); pass_messages_rank = UnitTest::gatherMessages(pass_messages, 1);
// Get the fail messages // Get the fail messages
if ( level == 1 || level == 2 ) if (level == 1 || level == 2)
fail_messages_rank = UnitTest::gatherMessages( fail_messages, 2 ); fail_messages_rank = UnitTest::gatherMessages(fail_messages, 2);
// Get the expected_fail messages // Get the expected_fail messages
if ( ( level == 1 && N_expected_fail_tot <= 50 ) || level == 2 ) if ((level == 1 && N_expected_fail_tot <= 50) || level == 2)
expected_fail_rank = UnitTest::gatherMessages( expected_fail_messages, 2 ); expected_fail_rank =
UnitTest::gatherMessages(expected_fail_messages, 2);
// Print the results of all messages (only rank 0 will print) // Print the results of all messages (only rank 0 will print)
if ( rank == 0 ) { if (rank == 0) {
pout << std::endl; pout << std::endl;
// Print the passed tests // Print the passed tests
pout << "Tests passed" << std::endl; pout << "Tests passed" << std::endl;
if ( level == 0 || ( level == 1 && N_pass_tot > 20 ) ) { if (level == 0 || (level == 1 && N_pass_tot > 20)) {
// We want to print a summary // We want to print a summary
if ( size > 8 ) { if (size > 8) {
// Print 1 summary for all processors // Print 1 summary for all processors
printp( " %i tests passed (use report level 2 for more detail)\n", N_pass_tot ); printp(" %i tests passed (use report level 2 for more "
"detail)\n",
N_pass_tot);
} else { } else {
// Print a summary for each processor // Print a summary for each processor
for ( int i = 0; i < size; i++ ) for (int i = 0; i < size; i++)
printp( " %i tests passed (proc %i) (use report level 2 for more detail)\n", printp(" %i tests passed (proc %i) (use report level 2 "
N_pass[i], i ); "for more detail)\n",
N_pass[i], i);
} }
} else { } else {
// We want to print all messages // We want to print all messages
for ( int i = 0; i < size; i++ ) for (int i = 0; i < size; i++)
ASSERT( (int) pass_messages_rank[i].size() == N_pass[i] ); ASSERT((int)pass_messages_rank[i].size() == N_pass[i]);
print_messages( pass_messages_rank ); print_messages(pass_messages_rank);
} }
pout << std::endl; pout << std::endl;
// Print the tests that failed // Print the tests that failed
pout << "Tests failed" << std::endl; pout << "Tests failed" << std::endl;
if ( level == 0 ) { if (level == 0) {
// We want to print a summary // We want to print a summary
if ( size > 8 ) { if (size > 8) {
// Print 1 summary for all processors // Print 1 summary for all processors
printp( " %i tests failed (use report level 2 for more detail)\n", N_fail_tot ); printp(" %i tests failed (use report level 2 for more "
"detail)\n",
N_fail_tot);
} else { } else {
// Print a summary for each processor // Print a summary for each processor
for ( int i = 0; i < size; i++ ) for (int i = 0; i < size; i++)
printp( " %i tests failed (proc %i) (use report level 2 for more detail)\n", printp(" %i tests failed (proc %i) (use report level 2 "
N_fail[i], i ); "for more detail)\n",
N_fail[i], i);
} }
} else { } else {
// We want to print all messages // We want to print all messages
for ( int i = 0; i < size; i++ ) for (int i = 0; i < size; i++)
ASSERT( (int) fail_messages_rank[i].size() == N_fail[i] ); ASSERT((int)fail_messages_rank[i].size() == N_fail[i]);
print_messages( fail_messages_rank ); print_messages(fail_messages_rank);
} }
pout << std::endl; pout << std::endl;
// Print the tests that expected failed // Print the tests that expected failed
pout << "Tests expected failed" << std::endl; pout << "Tests expected failed" << std::endl;
if ( level == 0 || ( level == 1 && N_expected_fail_tot > 50 ) ) { if (level == 0 || (level == 1 && N_expected_fail_tot > 50)) {
// We want to print a summary // We want to print a summary
if ( size > 8 ) { if (size > 8) {
// Print 1 summary for all processors // Print 1 summary for all processors
printp( " %i tests expected failed (use report level 2 for more detail)\n", printp(" %i tests expected failed (use report level 2 for "
N_expected_fail_tot ); "more detail)\n",
N_expected_fail_tot);
} else { } else {
// Print a summary for each processor // Print a summary for each processor
for ( int i = 0; i < size; i++ ) for (int i = 0; i < size; i++)
printp( " %i tests expected failed (proc %i) (use report level 2 for more " printp(" %i tests expected failed (proc %i) (use "
"detail)\n", "report level 2 for more "
N_expected_fail[i], i ); "detail)\n",
N_expected_fail[i], i);
} }
} else { } else {
// We want to print all messages // We want to print all messages
for ( int i = 0; i < size; i++ ) for (int i = 0; i < size; i++)
ASSERT( (int) expected_fail_rank[i].size() == N_expected_fail[i] ); ASSERT((int)expected_fail_rank[i].size() == N_expected_fail[i]);
print_messages( expected_fail_rank ); print_messages(expected_fail_rank);
} }
pout << std::endl; pout << std::endl;
} }
// Add a barrier to synchronize all processors (rank 0 is much slower) // Add a barrier to synchronize all processors (rank 0 is much slower)
barrier(); barrier();
Utilities::sleep_ms( 10 ); // Need a brief pause to allow any printing to finish Utilities::sleep_ms(
10); // Need a brief pause to allow any printing to finish
mutex.unlock(); mutex.unlock();
} }
/******************************************************************** /********************************************************************
* Gather the messages to rank 0 * * Gather the messages to rank 0 *
********************************************************************/ ********************************************************************/
std::vector<std::vector<std::string>> UnitTest::gatherMessages( std::vector<std::vector<std::string>>
const std::vector<std::string> &local_messages, int tag ) const UnitTest::gatherMessages(const std::vector<std::string> &local_messages,
{ int tag) const {
const int rank = getRank(); const int rank = getRank();
const int size = getSize(); const int size = getSize();
std::vector<std::vector<std::string>> messages( size ); std::vector<std::vector<std::string>> messages(size);
if ( rank == 0 ) { if (rank == 0) {
// Rank 0 should receive all messages // Rank 0 should receive all messages
for ( int i = 0; i < size; i++ ) { for (int i = 0; i < size; i++) {
if ( i == 0 ) if (i == 0)
messages[i] = local_messages; messages[i] = local_messages;
else else
messages[i] = unpack_message_stream( i, tag ); messages[i] = unpack_message_stream(i, tag);
} }
} else { } else {
// All other ranks send their message (use non-blocking communication) // All other ranks send their message (use non-blocking communication)
pack_message_stream( local_messages, 0, tag ); pack_message_stream(local_messages, 0, tag);
} }
return messages; return messages;
} }
/******************************************************************** /********************************************************************
* Pack and send the given messages * * Pack and send the given messages *
********************************************************************/ ********************************************************************/
void UnitTest::pack_message_stream( void UnitTest::pack_message_stream(const std::vector<std::string> &messages,
const std::vector<std::string> &messages, const int rank, const int tag ) const const int rank, const int tag) const {
{
#ifdef USE_MPI #ifdef USE_MPI
// Get the size of the messages // Get the size of the messages
auto N_messages = (int) messages.size(); auto N_messages = (int)messages.size();
auto *msg_size = new int[N_messages]; auto *msg_size = new int[N_messages];
int msg_size_tot = 0; int msg_size_tot = 0;
for ( int i = 0; i < N_messages; i++ ) { for (int i = 0; i < N_messages; i++) {
msg_size[i] = (int) messages[i].size(); msg_size[i] = (int)messages[i].size();
msg_size_tot += msg_size[i]; msg_size_tot += msg_size[i];
} }
// Allocate space for the message stream // Allocate space for the message stream
size_t size_data = ( N_messages + 1 ) * sizeof( int ) + msg_size_tot; size_t size_data = (N_messages + 1) * sizeof(int) + msg_size_tot;
auto *data = new char[size_data]; auto *data = new char[size_data];
// Pack the message stream // Pack the message stream
memcpy( data, &N_messages, sizeof( int ) ); memcpy(data, &N_messages, sizeof(int));
memcpy( &data[sizeof( int )], msg_size, N_messages * sizeof( int ) ); memcpy(&data[sizeof(int)], msg_size, N_messages * sizeof(int));
size_t k = ( N_messages + 1 ) * sizeof( int ); size_t k = (N_messages + 1) * sizeof(int);
for ( int i = 0; i < N_messages; i++ ) { for (int i = 0; i < N_messages; i++) {
messages[i].copy( &data[k], msg_size[i] ); messages[i].copy(&data[k], msg_size[i]);
k += msg_size[i]; k += msg_size[i];
} }
// Send the message stream (using a non-blocking send) // Send the message stream (using a non-blocking send)
MPI_Request request; MPI_Request request;
MPI_Isend( data, size_data, MPI_CHAR, rank, tag, comm, &request ); MPI_Isend(data, size_data, MPI_CHAR, rank, tag, comm, &request);
// Wait for the communication to send and free the temporary memory // Wait for the communication to send and free the temporary memory
MPI_Status status; MPI_Status status;
MPI_Wait( &request, &status ); MPI_Wait(&request, &status);
delete[] data; delete[] data;
delete[] msg_size; delete[] msg_size;
#else #else
NULL_USE( messages ); NULL_USE(messages);
NULL_USE( rank ); NULL_USE(rank);
NULL_USE( tag ); NULL_USE(tag);
#endif #endif
} }
/******************************************************************** /********************************************************************
* Receive and unpack a message stream * * Receive and unpack a message stream *
********************************************************************/ ********************************************************************/
std::vector<std::string> UnitTest::unpack_message_stream( const int rank, const int tag ) const std::vector<std::string> UnitTest::unpack_message_stream(const int rank,
{ const int tag) const {
#ifdef USE_MPI #ifdef USE_MPI
// Probe the message to get the message size // Probe the message to get the message size
MPI_Status status; MPI_Status status;
MPI_Probe( rank, tag, comm, &status ); MPI_Probe(rank, tag, comm, &status);
int size_data = -1; int size_data = -1;
MPI_Get_count( &status, MPI_BYTE, &size_data ); MPI_Get_count(&status, MPI_BYTE, &size_data);
ASSERT( size_data >= 0 ); ASSERT(size_data >= 0);
// Allocate memory to receive the data // Allocate memory to receive the data
auto *data = new char[size_data]; auto *data = new char[size_data];
// receive the data (using a non-blocking receive) // receive the data (using a non-blocking receive)
MPI_Request request; MPI_Request request;
MPI_Irecv( data, size_data, MPI_CHAR, rank, tag, comm, &request ); MPI_Irecv(data, size_data, MPI_CHAR, rank, tag, comm, &request);
// Wait for the communication to be received // Wait for the communication to be received
MPI_Wait( &request, &status ); MPI_Wait(&request, &status);
// Unpack the message stream // Unpack the message stream
int N_messages = 0; int N_messages = 0;
memcpy( &N_messages, data, sizeof( int ) ); memcpy(&N_messages, data, sizeof(int));
if ( N_messages == 0 ) { if (N_messages == 0) {
delete[] data; delete[] data;
return std::vector<std::string>(); return std::vector<std::string>();
} }
std::vector<int> msg_size( N_messages ); std::vector<int> msg_size(N_messages);
std::vector<std::string> messages( N_messages ); std::vector<std::string> messages(N_messages);
memcpy( msg_size.data(), &data[sizeof( int )], N_messages * sizeof( int ) ); memcpy(msg_size.data(), &data[sizeof(int)], N_messages * sizeof(int));
int k = ( N_messages + 1 ) * sizeof( int ); int k = (N_messages + 1) * sizeof(int);
for ( int i = 0; i < N_messages; i++ ) { for (int i = 0; i < N_messages; i++) {
messages[i] = std::string( &data[k], msg_size[i] ); messages[i] = std::string(&data[k], msg_size[i]);
k += msg_size[i]; k += msg_size[i];
} }
delete[] data; delete[] data;
return messages; return messages;
#else #else
NULL_USE( rank ); NULL_USE(rank);
NULL_USE( tag ); NULL_USE(tag);
return std::vector<std::string>(); return std::vector<std::string>();
#endif #endif
} }
/******************************************************************** /********************************************************************
* Other functions * * Other functions *
********************************************************************/ ********************************************************************/
int UnitTest::getRank() const int UnitTest::getRank() const {
{
int rank = 0; int rank = 0;
#ifdef USE_MPI #ifdef USE_MPI
int flag = 0; int flag = 0;
MPI_Initialized( &flag ); MPI_Initialized(&flag);
if ( flag ) if (flag)
MPI_Comm_rank( comm, &rank ); MPI_Comm_rank(comm, &rank);
#endif #endif
return rank; return rank;
} }
int UnitTest::getSize() const int UnitTest::getSize() const {
{
int size = 1; int size = 1;
#ifdef USE_MPI #ifdef USE_MPI
int flag = 0; int flag = 0;
MPI_Initialized( &flag ); MPI_Initialized(&flag);
if ( flag ) if (flag)
MPI_Comm_size( comm, &size ); MPI_Comm_size(comm, &size);
#endif #endif
return size; return size;
} }
size_t UnitTest::NumPassGlobal() const size_t UnitTest::NumPassGlobal() const {
{
size_t num = pass_messages.size(); size_t num = pass_messages.size();
#ifdef USE_MPI #ifdef USE_MPI
if ( getSize() > 1 ) { if (getSize() > 1) {
auto send = static_cast<int>( num ); auto send = static_cast<int>(num);
int sum = 0; int sum = 0;
MPI_Allreduce( &send, &sum, 1, MPI_INT, MPI_SUM, comm ); MPI_Allreduce(&send, &sum, 1, MPI_INT, MPI_SUM, comm);
num = static_cast<size_t>( sum ); num = static_cast<size_t>(sum);
} }
#endif #endif
return num; return num;
} }
size_t UnitTest::NumFailGlobal() const size_t UnitTest::NumFailGlobal() const {
{
size_t num = fail_messages.size(); size_t num = fail_messages.size();
#ifdef USE_MPI #ifdef USE_MPI
if ( getSize() > 1 ) { if (getSize() > 1) {
auto send = static_cast<int>( num ); auto send = static_cast<int>(num);
int sum = 0; int sum = 0;
MPI_Allreduce( &send, &sum, 1, MPI_INT, MPI_SUM, comm ); MPI_Allreduce(&send, &sum, 1, MPI_INT, MPI_SUM, comm);
num = static_cast<size_t>( sum ); num = static_cast<size_t>(sum);
} }
#endif #endif
return num; return num;
} }
size_t UnitTest::NumExpectedFailGlobal() const size_t UnitTest::NumExpectedFailGlobal() const {
{
size_t num = expected_fail_messages.size(); size_t num = expected_fail_messages.size();
#ifdef USE_MPI #ifdef USE_MPI
if ( getSize() > 1 ) { if (getSize() > 1) {
auto send = static_cast<int>( num ); auto send = static_cast<int>(num);
int sum = 0; int sum = 0;
MPI_Allreduce( &send, &sum, 1, MPI_INT, MPI_SUM, comm ); MPI_Allreduce(&send, &sum, 1, MPI_INT, MPI_SUM, comm);
num = static_cast<size_t>( sum ); num = static_cast<size_t>(sum);
} }
#endif #endif
return num; return num;

View File

@ -25,7 +25,6 @@
#include "mpi.h" #include "mpi.h"
#endif #endif
/*! /*!
* @brief Class UnitTest is simple utility for running unit tests. * @brief Class UnitTest is simple utility for running unit tests.
* It provides basic routines for tracing success or failure of tests, * It provides basic routines for tracing success or failure of tests,
@ -44,8 +43,7 @@
* \endcode * \endcode
*/ */
class UnitTest class UnitTest {
{
public: public:
//! Constructor //! Constructor
UnitTest(); UnitTest();
@ -54,13 +52,13 @@ public:
virtual ~UnitTest(); virtual ~UnitTest();
//! Indicate a passed test (thread-safe) //! Indicate a passed test (thread-safe)
virtual void passes( const std::string &in ); virtual void passes(const std::string &in);
//! Indicate a failed test (thread-safe) //! Indicate a failed test (thread-safe)
virtual void failure( const std::string &in ); virtual void failure(const std::string &in);
//! Indicate an expected failed test (thread-safe) //! Indicate an expected failed test (thread-safe)
virtual void expected_failure( const std::string &in ); virtual void expected_failure(const std::string &in);
//! Return the number of passed tests locally //! Return the number of passed tests locally
virtual size_t NumPassLocal() const { return pass_messages.size(); } virtual size_t NumPassLocal() const { return pass_messages.size(); }
@ -69,7 +67,9 @@ public:
virtual size_t NumFailLocal() const { return fail_messages.size(); } virtual size_t NumFailLocal() const { return fail_messages.size(); }
//! Return the number of expected failed tests locally //! Return the number of expected failed tests locally
virtual size_t NumExpectedFailLocal() const { return expected_fail_messages.size(); } virtual size_t NumExpectedFailLocal() const {
return expected_fail_messages.size();
}
//! Return the number of passed tests locally //! Return the number of passed tests locally
virtual size_t NumPassGlobal() const; virtual size_t NumPassGlobal() const;
@ -98,7 +98,7 @@ public:
* failed tests (if <=50) or the number passed otherwise. * failed tests (if <=50) or the number passed otherwise.
* 2: Report all passed, failed, and expected failed tests. * 2: Report all passed, failed, and expected failed tests.
*/ */
virtual void report( const int level = 1 ) const; virtual void report(const int level = 1) const;
//! Clear the messages //! Clear the messages
void reset(); void reset();
@ -114,23 +114,24 @@ protected:
private: private:
// Make the copy constructor private // Make the copy constructor private
UnitTest( const UnitTest & ) {} UnitTest(const UnitTest &) {}
// Function to pack the messages into a single data stream and send to the given processor // Function to pack the messages into a single data stream and send to the given processor
// Note: This function does not return until the message stream has been sent // Note: This function does not return until the message stream has been sent
void pack_message_stream( void pack_message_stream(const std::vector<std::string> &messages,
const std::vector<std::string> &messages, const int rank, const int tag ) const; const int rank, const int tag) const;
// Function to unpack the messages from a single data stream // Function to unpack the messages from a single data stream
// Note: This function does not return until the message stream has been received // Note: This function does not return until the message stream has been received
std::vector<std::string> unpack_message_stream( const int rank, const int tag ) const; std::vector<std::string> unpack_message_stream(const int rank,
const int tag) const;
// Helper functions // Helper functions
inline void barrier() const; inline void barrier() const;
inline std::vector<int> allGather( int value ) const; inline std::vector<int> allGather(int value) const;
inline std::vector<std::vector<std::string>> gatherMessages( inline std::vector<std::vector<std::string>>
const std::vector<std::string> &local_messages, int tag ) const; gatherMessages(const std::vector<std::string> &local_messages,
int tag) const;
}; };
#endif #endif

View File

@ -21,134 +21,126 @@
#include <cmath> #include <cmath>
#include <string> #include <string>
constexpr double Units::d_pow10[22]; constexpr double Units::d_pow10[22];
constexpr char Units::d_prefixSymbol[]; constexpr char Units::d_prefixSymbol[];
/******************************************************************** /********************************************************************
* Constructors * * Constructors *
********************************************************************/ ********************************************************************/
Units::Units() : d_prefix( UnitPrefix::unknown ), d_unit( UnitValue::unknown ) {} Units::Units() : d_prefix(UnitPrefix::unknown), d_unit(UnitValue::unknown) {}
Units::Units( UnitPrefix p, UnitValue u ) : d_prefix( p ), d_unit( u ) {} Units::Units(UnitPrefix p, UnitValue u) : d_prefix(p), d_unit(u) {}
Units::Units( const std::string& unit ) Units::Units(const std::string &unit)
: d_prefix( UnitPrefix::unknown ), d_unit( UnitValue::unknown ) : d_prefix(UnitPrefix::unknown), d_unit(UnitValue::unknown) {
{
// Parse the string to get it into a more friendly format // Parse the string to get it into a more friendly format
auto tmp = unit; auto tmp = unit;
tmp.erase( std::remove( tmp.begin(), tmp.end(), ' ' ), tmp.end() ); tmp.erase(std::remove(tmp.begin(), tmp.end(), ' '), tmp.end());
// Check if the character '-' is present indicating a seperation between the prefix and unit // Check if the character '-' is present indicating a seperation between the prefix and unit
size_t index = tmp.find( '-' ); size_t index = tmp.find('-');
if ( index != std::string::npos ) { if (index != std::string::npos) {
d_prefix = getUnitPrefix( tmp.substr( 0, index ) ); d_prefix = getUnitPrefix(tmp.substr(0, index));
d_unit = getUnitValue( tmp.substr( index + 1 ) ); d_unit = getUnitValue(tmp.substr(index + 1));
} else { } else {
if ( tmp.size() <= 1 ) { if (tmp.size() <= 1) {
d_prefix = UnitPrefix::none; d_prefix = UnitPrefix::none;
d_unit = getUnitValue( tmp ); d_unit = getUnitValue(tmp);
} else if ( tmp.substr( 0, 2 ) == "da" ) { } else if (tmp.substr(0, 2) == "da") {
d_prefix = UnitPrefix::deca; d_prefix = UnitPrefix::deca;
d_unit = getUnitValue( tmp.substr( 2 ) ); d_unit = getUnitValue(tmp.substr(2));
} else { } else {
d_prefix = getUnitPrefix( tmp.substr( 0, 1 ) ); d_prefix = getUnitPrefix(tmp.substr(0, 1));
d_unit = getUnitValue( tmp.substr( 1 ) ); d_unit = getUnitValue(tmp.substr(1));
if ( d_prefix == UnitPrefix::unknown || d_unit == UnitValue::unknown ) { if (d_prefix == UnitPrefix::unknown ||
d_unit == UnitValue::unknown) {
d_prefix = UnitPrefix::none; d_prefix = UnitPrefix::none;
d_unit = getUnitValue( tmp ); d_unit = getUnitValue(tmp);
} }
} }
} }
} }
/******************************************************************** /********************************************************************
* Get prefix * * Get prefix *
********************************************************************/ ********************************************************************/
Units::UnitPrefix Units::getUnitPrefix( const std::string& str ) noexcept Units::UnitPrefix Units::getUnitPrefix(const std::string &str) noexcept {
{
Units::UnitPrefix value = UnitPrefix::unknown; Units::UnitPrefix value = UnitPrefix::unknown;
if ( str.empty() ) { if (str.empty()) {
value = UnitPrefix::none; value = UnitPrefix::none;
} else if ( str == "yotta" || str == "Y" ) { } else if (str == "yotta" || str == "Y") {
value = UnitPrefix::yotta; value = UnitPrefix::yotta;
} else if ( str == "zetta" || str == "Z" ) { } else if (str == "zetta" || str == "Z") {
value = UnitPrefix::zetta; value = UnitPrefix::zetta;
} else if ( str == "exa" || str == "E" ) { } else if (str == "exa" || str == "E") {
value = UnitPrefix::exa; value = UnitPrefix::exa;
} else if ( str == "peta" || str == "P" ) { } else if (str == "peta" || str == "P") {
value = UnitPrefix::peta; value = UnitPrefix::peta;
} else if ( str == "tera" || str == "T" ) { } else if (str == "tera" || str == "T") {
value = UnitPrefix::tera; value = UnitPrefix::tera;
} else if ( str == "giga" || str == "G" ) { } else if (str == "giga" || str == "G") {
value = UnitPrefix::giga; value = UnitPrefix::giga;
} else if ( str == "mega" || str == "M" ) { } else if (str == "mega" || str == "M") {
value = UnitPrefix::mega; value = UnitPrefix::mega;
} else if ( str == "kilo" || str == "k" ) { } else if (str == "kilo" || str == "k") {
value = UnitPrefix::kilo; value = UnitPrefix::kilo;
} else if ( str == "hecto" || str == "h" ) { } else if (str == "hecto" || str == "h") {
value = UnitPrefix::hecto; value = UnitPrefix::hecto;
} else if ( str == "deca" || str == "da" ) { } else if (str == "deca" || str == "da") {
value = UnitPrefix::deca; value = UnitPrefix::deca;
} else if ( str == "deci" || str == "d" ) { } else if (str == "deci" || str == "d") {
value = UnitPrefix::deci; value = UnitPrefix::deci;
} else if ( str == "centi" || str == "c" ) { } else if (str == "centi" || str == "c") {
value = UnitPrefix::centi; value = UnitPrefix::centi;
} else if ( str == "milli" || str == "m" ) { } else if (str == "milli" || str == "m") {
value = UnitPrefix::milli; value = UnitPrefix::milli;
} else if ( str == "micro" || str == "u" ) { } else if (str == "micro" || str == "u") {
value = UnitPrefix::micro; value = UnitPrefix::micro;
} else if ( str == "nano" || str == "n" ) { } else if (str == "nano" || str == "n") {
value = UnitPrefix::nano; value = UnitPrefix::nano;
} else if ( str == "pico" || str == "p" ) { } else if (str == "pico" || str == "p") {
value = UnitPrefix::pico; value = UnitPrefix::pico;
} else if ( str == "femto" || str == "f" ) { } else if (str == "femto" || str == "f") {
value = UnitPrefix::femto; value = UnitPrefix::femto;
} else if ( str == "atto" || str == "a" ) { } else if (str == "atto" || str == "a") {
value = UnitPrefix::atto; value = UnitPrefix::atto;
} else if ( str == "zepto" || str == "z" ) { } else if (str == "zepto" || str == "z") {
value = UnitPrefix::zepto; value = UnitPrefix::zepto;
} else if ( str == "yocto" || str == "y" ) { } else if (str == "yocto" || str == "y") {
value = UnitPrefix::yocto; value = UnitPrefix::yocto;
} }
return value; return value;
} }
/******************************************************************** /********************************************************************
* Get unit value * * Get unit value *
********************************************************************/ ********************************************************************/
Units::UnitValue Units::getUnitValue( const std::string& str ) noexcept Units::UnitValue Units::getUnitValue(const std::string &str) noexcept {
{
Units::UnitValue value = UnitValue::unknown; Units::UnitValue value = UnitValue::unknown;
if ( str == "meter" || str == "m" ) { if (str == "meter" || str == "m") {
value = UnitValue::meter; value = UnitValue::meter;
} else if ( str == "gram" || str == "g" ) { } else if (str == "gram" || str == "g") {
value = UnitValue::gram; value = UnitValue::gram;
} else if ( str == "second" || str == "s" ) { } else if (str == "second" || str == "s") {
value = UnitValue::second; value = UnitValue::second;
} else if ( str == "ampere" || str == "A" ) { } else if (str == "ampere" || str == "A") {
value = UnitValue::ampere; value = UnitValue::ampere;
} else if ( str == "kelvin" || str == "K" ) { } else if (str == "kelvin" || str == "K") {
value = UnitValue::kelvin; value = UnitValue::kelvin;
} else if ( str == "joule" || str == "J" ) { } else if (str == "joule" || str == "J") {
value = UnitValue::joule; value = UnitValue::joule;
} else if ( str == "ergs" || str == "erg" ) { } else if (str == "ergs" || str == "erg") {
value = UnitValue::erg; value = UnitValue::erg;
} else if ( str == "degree" || str == "degrees" ) { } else if (str == "degree" || str == "degrees") {
value = UnitValue::degree; value = UnitValue::degree;
} else if ( str == "radian" || str == "radians" ) { } else if (str == "radian" || str == "radians") {
value = UnitValue::radian; value = UnitValue::radian;
} }
return value; return value;
} }
/******************************************************************** /********************************************************************
* Get unit type * * Get unit type *
********************************************************************/ ********************************************************************/
Units::UnitType Units::getUnitType( UnitValue u ) noexcept Units::UnitType Units::getUnitType(UnitValue u) noexcept {
{ switch (u) {
switch ( u ) {
case UnitValue::meter: case UnitValue::meter:
return UnitType::length; return UnitType::length;
case UnitValue::gram: case UnitValue::gram:
@ -170,72 +162,66 @@ Units::UnitType Units::getUnitType( UnitValue u ) noexcept
} }
} }
/******************************************************************** /********************************************************************
* Convert to another unit system * * Convert to another unit system *
********************************************************************/ ********************************************************************/
double Units::convert( const Units& rhs ) const noexcept double Units::convert(const Units &rhs) const noexcept {
{ if (this->operator==(rhs))
if ( this->operator==( rhs ) )
return 1; return 1;
// Convert the prefix // Convert the prefix
double cp = convert( d_prefix ) / convert( rhs.d_prefix ); double cp = convert(d_prefix) / convert(rhs.d_prefix);
if ( d_unit == rhs.d_unit ) if (d_unit == rhs.d_unit)
return cp; // Only need to convert prefix return cp; // Only need to convert prefix
// Convert the unit // Convert the unit
if ( getUnitType( d_unit ) != getUnitType( rhs.d_unit ) ) if (getUnitType(d_unit) != getUnitType(rhs.d_unit))
return 0; // Invalid conversion return 0; // Invalid conversion
double cu = 0; double cu = 0;
if ( d_unit == UnitValue::joule && rhs.d_unit == UnitValue::erg ) if (d_unit == UnitValue::joule && rhs.d_unit == UnitValue::erg)
cu = 1e7; cu = 1e7;
else if ( d_unit == UnitValue::erg && rhs.d_unit == UnitValue::joule ) else if (d_unit == UnitValue::erg && rhs.d_unit == UnitValue::joule)
cu = 1e-7; cu = 1e-7;
else if ( d_unit == UnitValue::degree && rhs.d_unit == UnitValue::radian ) else if (d_unit == UnitValue::degree && rhs.d_unit == UnitValue::radian)
cu = 0.017453292519943; cu = 0.017453292519943;
else if ( d_unit == UnitValue::radian && rhs.d_unit == UnitValue::degree ) else if (d_unit == UnitValue::radian && rhs.d_unit == UnitValue::degree)
cu = 57.295779513082323; cu = 57.295779513082323;
// Return the total conversion // Return the total conversion
return cp * cu; return cp * cu;
} }
/******************************************************************** /********************************************************************
* Write a string for the units * * Write a string for the units *
********************************************************************/ ********************************************************************/
std::string Units::str() const std::string Units::str() const {
{ ASSERT(!isNull());
ASSERT( !isNull() ); return std::string(str(d_prefix).data()) + str(d_unit);
return std::string( str( d_prefix ).data() ) + str( d_unit );
} }
std::array<char, 3> Units::str( UnitPrefix p ) noexcept std::array<char, 3> Units::str(UnitPrefix p) noexcept {
{
std::array<char, 3> str; std::array<char, 3> str;
str[0] = d_prefixSymbol[static_cast<int8_t>( p )]; str[0] = d_prefixSymbol[static_cast<int8_t>(p)];
str[1] = 0; str[1] = 0;
str[2] = 0; str[2] = 0;
if ( p == UnitPrefix::deca ) if (p == UnitPrefix::deca)
str[1] = 'a'; str[1] = 'a';
return str; return str;
} }
std::string Units::str( UnitValue u ) std::string Units::str(UnitValue u) {
{ if (u == UnitValue::meter) {
if ( u == UnitValue::meter ) {
return "m"; return "m";
} else if ( u == UnitValue::gram ) { } else if (u == UnitValue::gram) {
return "g"; return "g";
} else if ( u == UnitValue::second ) { } else if (u == UnitValue::second) {
return "s"; return "s";
} else if ( u == UnitValue::ampere ) { } else if (u == UnitValue::ampere) {
return "A"; return "A";
} else if ( u == UnitValue::kelvin ) { } else if (u == UnitValue::kelvin) {
return "K"; return "K";
} else if ( u == UnitValue::joule ) { } else if (u == UnitValue::joule) {
return "J"; return "J";
} else if ( u == UnitValue::erg ) { } else if (u == UnitValue::erg) {
return "erg"; return "erg";
} else if ( u == UnitValue::degree ) { } else if (u == UnitValue::degree) {
return "degree"; return "degree";
} else if ( u == UnitValue::radian ) { } else if (u == UnitValue::radian) {
return "radian"; return "radian";
} }
return "unknown"; return "unknown";

View File

@ -24,34 +24,32 @@
#include <string> #include <string>
#include <vector> #include <vector>
//! Unit system class //! Unit system class
class Units final class Units final {
{
public: public:
//! Enum to hold prefix //! Enum to hold prefix
enum class UnitPrefix : int8_t { enum class UnitPrefix : int8_t {
yocto = 0, yocto = 0,
zepto = 1, zepto = 1,
atto = 2, atto = 2,
femto = 3, femto = 3,
pico = 4, pico = 4,
nano = 5, nano = 5,
micro = 6, micro = 6,
milli = 7, milli = 7,
centi = 8, centi = 8,
deci = 9, deci = 9,
none = 10, none = 10,
deca = 11, deca = 11,
hecto = 12, hecto = 12,
kilo = 13, kilo = 13,
mega = 14, mega = 14,
giga = 15, giga = 15,
tera = 16, tera = 16,
peta = 17, peta = 17,
exa = 18, exa = 18,
zetta = 19, zetta = 19,
yotta = 20, yotta = 20,
unknown = 21 unknown = 21
}; };
@ -81,16 +79,15 @@ public:
unknown unknown
}; };
public: public:
//! Constructor //! Constructor
Units(); Units();
//! Constructor //! Constructor
explicit Units( const std::string& unit ); explicit Units(const std::string &unit);
//! Constructor //! Constructor
explicit Units( UnitPrefix, UnitValue ); explicit Units(UnitPrefix, UnitValue);
//! Get the prefix //! Get the prefix
inline UnitPrefix getPrefix() const noexcept { return d_prefix; } inline UnitPrefix getPrefix() const noexcept { return d_prefix; }
@ -99,57 +96,57 @@ public:
inline UnitValue getUnit() const noexcept { return d_unit; } inline UnitValue getUnit() const noexcept { return d_unit; }
//! Get the unit //! Get the unit
inline UnitType getUnitType() const noexcept { return getUnitType( d_unit ); } inline UnitType getUnitType() const noexcept { return getUnitType(d_unit); }
//! Get the unit //! Get the unit
static UnitType getUnitType( UnitValue ) noexcept; static UnitType getUnitType(UnitValue) noexcept;
//! Get the prefix from a string //! Get the prefix from a string
static UnitPrefix getUnitPrefix( const std::string& ) noexcept; static UnitPrefix getUnitPrefix(const std::string &) noexcept;
//! Get the unit value from a string //! Get the unit value from a string
static UnitValue getUnitValue( const std::string& ) noexcept; static UnitValue getUnitValue(const std::string &) noexcept;
//! Convert to the given unit system //! Convert to the given unit system
double convert( const Units& ) const noexcept; double convert(const Units &) const noexcept;
//! Convert a prefix to a scalar //! Convert a prefix to a scalar
static inline double convert( UnitPrefix x ) noexcept static inline double convert(UnitPrefix x) noexcept {
{ return d_pow10[static_cast<int8_t>(x)];
return d_pow10[static_cast<int8_t>( x )];
} }
//! Get a string representation of the units //! Get a string representation of the units
std::string str() const; std::string str() const;
//! Get a string representation for the prefix //! Get a string representation for the prefix
static std::array<char, 3> str( UnitPrefix ) noexcept; static std::array<char, 3> str(UnitPrefix) noexcept;
//! Get a string representation for the unit value //! Get a string representation for the unit value
static std::string str( UnitValue ); static std::string str(UnitValue);
//! Operator == //! Operator ==
inline bool operator==( const Units& rhs ) const noexcept inline bool operator==(const Units &rhs) const noexcept {
{
return d_prefix == rhs.d_prefix && d_unit == rhs.d_unit; return d_prefix == rhs.d_prefix && d_unit == rhs.d_unit;
} }
//! Operator != //! Operator !=
inline bool operator!=( const Units& rhs ) const noexcept inline bool operator!=(const Units &rhs) const noexcept {
{
return d_prefix != rhs.d_prefix || d_unit != rhs.d_unit; return d_prefix != rhs.d_prefix || d_unit != rhs.d_unit;
} }
//! Check if unit is null //! Check if unit is null
bool isNull() const { return d_prefix == UnitPrefix::unknown || d_unit == UnitValue::unknown; } bool isNull() const {
return d_prefix == UnitPrefix::unknown || d_unit == UnitValue::unknown;
}
protected: protected:
UnitPrefix d_prefix; UnitPrefix d_prefix;
UnitValue d_unit; UnitValue d_unit;
private: private:
constexpr static double d_pow10[22] = { 1e-24, 1e-21, 1e-18, 1e-15, 1e-12, 1e-9, 1e-6, 1e-3, constexpr static double d_pow10[22] = {
1e-2, 0.1, 1, 10, 100, 1000, 1e6, 1e9, 1e12, 1e15, 1e18, 1e21, 1e24, 0 }; 1e-24, 1e-21, 1e-18, 1e-15, 1e-12, 1e-9, 1e-6, 1e-3, 1e-2, 0.1, 1,
10, 100, 1000, 1e6, 1e9, 1e12, 1e15, 1e18, 1e21, 1e24, 0};
constexpr static char d_prefixSymbol[] = "yzafpnumcd\0dhkMGTPEZYu"; constexpr static char d_prefixSymbol[] = "yzafpnumcd\0dhkMGTPEZYu";
}; };

View File

@ -31,7 +31,6 @@
#include <math.h> #include <math.h>
#include <mutex> #include <mutex>
// OS specific includes / definitions // OS specific includes / definitions
// clang-format off // clang-format off
#if defined( WIN32 ) || defined( _WIN32 ) || defined( WIN64 ) || defined( _WIN64 ) #if defined( WIN32 ) || defined( _WIN32 ) || defined( WIN64 ) || defined( _WIN64 )
@ -45,162 +44,150 @@
#endif #endif
// clang-format on // clang-format on
// Mutex for Utility functions // Mutex for Utility functions
static std::mutex Utilities_mutex; static std::mutex Utilities_mutex;
/**************************************************************************** /****************************************************************************
* Function to perform the default startup/shutdown sequences * * Function to perform the default startup/shutdown sequences *
****************************************************************************/ ****************************************************************************/
void Utilities::startup( int argc, char **argv, bool multiple ) void Utilities::startup(int argc, char **argv, bool multiple) {
{ NULL_USE(argc);
NULL_USE( argc ); NULL_USE(argv);
NULL_USE( argv );
// Disable OpenMP // Disable OpenMP
Utilities::setenv( "OMP_NUM_THREADS", "1" ); Utilities::setenv("OMP_NUM_THREADS", "1");
Utilities::setenv( "MKL_NUM_THREADS", "1" ); Utilities::setenv("MKL_NUM_THREADS", "1");
// Start MPI // Start MPI
#ifdef USE_MPI #ifdef USE_MPI
if ( multiple ) { if (multiple) {
int provided; int provided;
MPI_Init_thread( &argc, &argv, MPI_THREAD_MULTIPLE, &provided ); MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
if ( provided < MPI_THREAD_MULTIPLE ) { if (provided < MPI_THREAD_MULTIPLE) {
int rank; int rank;
MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if ( rank == 0 ) if (rank == 0)
std::cerr << "Warning: Failed to start MPI with necessary thread support, thread support will be disabled" << std::endl; std::cerr << "Warning: Failed to start MPI with necessary "
"thread support, thread support will be disabled"
<< std::endl;
} }
StackTrace::globalCallStackInitialize( MPI_COMM_WORLD ); StackTrace::globalCallStackInitialize(MPI_COMM_WORLD);
} else { } else {
MPI_Init( &argc, &argv ); MPI_Init(&argc, &argv);
} }
#endif #endif
// Set the error handlers // Set the error handlers
Utilities::setAbortBehavior( true, 3 ); Utilities::setAbortBehavior(true, 3);
Utilities::setErrorHandlers(); Utilities::setErrorHandlers();
} }
void Utilities::shutdown() void Utilities::shutdown() {
{
// Clear the error handlers // Clear the error handlers
Utilities::clearErrorHandlers(); Utilities::clearErrorHandlers();
StackTrace::clearSignals(); StackTrace::clearSignals();
StackTrace::clearSymbols(); StackTrace::clearSymbols();
int rank = 0; int rank = 0;
#ifdef USE_MPI #ifdef USE_MPI
MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_rank(MPI_COMM_WORLD, &rank);
StackTrace::globalCallStackFinalize(); StackTrace::globalCallStackFinalize();
MPI_Barrier( MPI_COMM_WORLD ); MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize(); MPI_Finalize();
#endif #endif
#ifdef USE_TIMER #ifdef USE_TIMER
PROFILE_DISABLE(); PROFILE_DISABLE();
auto memory = MemoryApp::getMemoryStats(); auto memory = MemoryApp::getMemoryStats();
if ( rank == 0 && memory.N_new > memory.N_delete ) if (rank == 0 && memory.N_new > memory.N_delete)
MemoryApp::print( std::cout ); MemoryApp::print(std::cout);
#endif #endif
} }
/**************************************************************************** /****************************************************************************
* Function to set an environemental variable * * Function to set an environemental variable *
****************************************************************************/ ****************************************************************************/
void Utilities::setenv( const std::string &name, const std::string &value ) void Utilities::setenv(const std::string &name, const std::string &value) {
{
Utilities_mutex.lock(); Utilities_mutex.lock();
#if defined( USE_LINUX ) || defined( USE_MAC ) #if defined(USE_LINUX) || defined(USE_MAC)
bool pass = false; bool pass = false;
if ( !value.empty() ) if (!value.empty())
pass = ::setenv( name.data(), value.data(), 1 ) == 0; pass = ::setenv(name.data(), value.data(), 1) == 0;
else else
pass = ::unsetenv( name.data() ) == 0; pass = ::unsetenv(name.data()) == 0;
#elif defined( USE_WINDOWS ) #elif defined(USE_WINDOWS)
bool pass = SetEnvironmentVariable( name.data(), value.data() ) != 0; bool pass = SetEnvironmentVariable(name.data(), value.data()) != 0;
#else #else
#error Unknown OS #error Unknown OS
#endif #endif
Utilities_mutex.unlock(); Utilities_mutex.unlock();
if ( !pass ) { if (!pass) {
char msg[1024]; char msg[1024];
if ( !value.empty() ) if (!value.empty())
sprintf( sprintf(msg, "Error setting enviornmental variable: %s=%s\n",
msg, "Error setting enviornmental variable: %s=%s\n", name.data(), value.data() ); name.data(), value.data());
else else
sprintf( msg, "Error clearing enviornmental variable: %s\n", name.data() ); sprintf(msg, "Error clearing enviornmental variable: %s\n",
ERROR( msg ); name.data());
ERROR(msg);
} }
} }
std::string Utilities::getenv( const std::string &name ) std::string Utilities::getenv(const std::string &name) {
{
std::string var; std::string var;
Utilities_mutex.lock(); Utilities_mutex.lock();
auto tmp = std::getenv( name.data() ); auto tmp = std::getenv(name.data());
if ( tmp ) if (tmp)
var = std::string( tmp ); var = std::string(tmp);
Utilities_mutex.unlock(); Utilities_mutex.unlock();
return var; return var;
} }
/**************************************************************************** /****************************************************************************
* Factor a number into it's prime factors * * Factor a number into it's prime factors *
****************************************************************************/ ****************************************************************************/
std::vector<int> Utilities::factor(size_t number) std::vector<int> Utilities::factor(size_t number) {
{ if (number <= 3)
if ( number<=3 ) return std::vector<int>(1, (int)number);
return std::vector<int>(1,(int)number);
size_t i, n, n_max; size_t i, n, n_max;
bool factor_found; bool factor_found;
// Compute the maximum number of factors // Compute the maximum number of factors
int N_primes_max = 1; int N_primes_max = 1;
n = number; n = number;
while (n >>= 1) ++N_primes_max; while (n >>= 1)
// Initialize n, factors ++N_primes_max;
// Initialize n, factors
n = number; n = number;
std::vector<int> factors; std::vector<int> factors;
factors.reserve(N_primes_max); factors.reserve(N_primes_max);
while ( 1 ) { while (1) {
// Check if n is a trivial prime number // Check if n is a trivial prime number
if ( n==2 || n==3 || n==5 ) { if (n == 2 || n == 3 || n == 5) {
factors.push_back( (int) n ); factors.push_back((int)n);
break; break;
} }
// Check if n is divisible by 2 // Check if n is divisible by 2
if ( n%2 == 0 ) { if (n % 2 == 0) {
factors.push_back( 2 ); factors.push_back(2);
n/=2; n /= 2;
continue; continue;
} }
// Check each odd number until a factor is reached // Check each odd number until a factor is reached
n_max = (size_t) floor(sqrt((double) n)); n_max = (size_t)floor(sqrt((double)n));
factor_found = false; factor_found = false;
for (i=3; i<=n_max; i+=2) { for (i = 3; i <= n_max; i += 2) {
if ( n%i == 0 ) { if (n % i == 0) {
factors.push_back( i ); factors.push_back(i);
n/=i; n /= i;
factor_found = true; factor_found = true;
break; break;
} }
} }
if ( factor_found ) if (factor_found)
continue; continue;
// No factors were found, the number must be prime // No factors were found, the number must be prime
factors.push_back( (int) n ); factors.push_back((int)n);
break; break;
} }
// Sort the factors // Sort the factors
std::sort( factors.begin(), factors.end() ); std::sort(factors.begin(), factors.end());
return factors; return factors;
} }
/**************************************************************************** /****************************************************************************
* Dummy function to prevent compiler from optimizing away variable * * Dummy function to prevent compiler from optimizing away variable *
****************************************************************************/ ****************************************************************************/
void Utilities::nullUse( void* data ) void Utilities::nullUse(void *data) { NULL_USE(data); }
{
NULL_USE(data);
}

View File

@ -22,10 +22,8 @@
#include "StackTrace/Utilities.h" #include "StackTrace/Utilities.h"
namespace Utilities { namespace Utilities {
// Functions inherited from StackTrace::Utilities // Functions inherited from StackTrace::Utilities
using StackTrace::Utilities::abort; using StackTrace::Utilities::abort;
using StackTrace::Utilities::cause_segfault; using StackTrace::Utilities::cause_segfault;
@ -35,11 +33,10 @@ using StackTrace::Utilities::getMemoryUsage;
using StackTrace::Utilities::getSystemMemory; using StackTrace::Utilities::getSystemMemory;
using StackTrace::Utilities::setAbortBehavior; using StackTrace::Utilities::setAbortBehavior;
using StackTrace::Utilities::setErrorHandlers; using StackTrace::Utilities::setErrorHandlers;
using StackTrace::Utilities::tick;
using StackTrace::Utilities::time;
using StackTrace::Utilities::sleep_ms; using StackTrace::Utilities::sleep_ms;
using StackTrace::Utilities::sleep_s; using StackTrace::Utilities::sleep_s;
using StackTrace::Utilities::tick;
using StackTrace::Utilities::time;
/*! /*!
* \brief Start MPI, error handlers * \brief Start MPI, error handlers
@ -48,7 +45,7 @@ using StackTrace::Utilities::sleep_s;
* \param argv argv from main * \param argv argv from main
* \param multiple Intialize mpi with MPI_THREAD_MULTIPLE support? * \param multiple Intialize mpi with MPI_THREAD_MULTIPLE support?
*/ */
void startup( int argc, char **argv, bool multiple=true ); void startup(int argc, char **argv, bool multiple = true);
/*! /*!
* \brief Stop MPI, error handlers * \brief Stop MPI, error handlers
@ -56,51 +53,41 @@ void startup( int argc, char **argv, bool multiple=true );
*/ */
void shutdown(); void shutdown();
/*! /*!
* Get an environmental variable * Get an environmental variable
* @param name The name of the environmental variable * @param name The name of the environmental variable
* @return The value of the enviornmental variable * @return The value of the enviornmental variable
*/ */
std::string getenv( const std::string &name ); std::string getenv(const std::string &name);
/*! /*!
* Set an environmental variable * Set an environmental variable
* @param name The name of the environmental variable * @param name The name of the environmental variable
* @param value The value to set * @param value The value to set
*/ */
void setenv( const std::string &name, const std::string &value ); void setenv(const std::string &name, const std::string &value);
//! std::string version of sprintf //! std::string version of sprintf
inline std::string stringf( const char *format, ... ); inline std::string stringf(const char *format, ...);
//! Factor a number into it's prime factors //! Factor a number into it's prime factors
std::vector<int> factor(size_t number); std::vector<int> factor(size_t number);
//! Null use function //! Null use function
void nullUse( void* ); void nullUse(void *);
} // namespace Utilities } // namespace Utilities
#include "common/UtilityMacros.h" #include "common/UtilityMacros.h"
// stringf // stringf
inline std::string Utilities::stringf( const char *format, ... ) inline std::string Utilities::stringf(const char *format, ...) {
{
va_list ap; va_list ap;
va_start( ap, format ); va_start(ap, format);
char tmp[4096]; char tmp[4096];
vsprintf( tmp, format, ap ); vsprintf(tmp, format, ap);
va_end( ap ); va_end(ap);
return std::string( tmp ); return std::string(tmp);
} }
#endif #endif

View File

@ -1,108 +1,104 @@
#ifndef included_Utilities_hpp #ifndef included_Utilities_hpp
#define included_Utilities_hpp #define included_Utilities_hpp
#include "Utilities.h" #include "Utilities.h"
#include <vector> #include <vector>
namespace Utilities { namespace Utilities {
/************************************************************************ /************************************************************************
* templated quicksort routines * * templated quicksort routines *
************************************************************************/ ************************************************************************/
template<class T> template <class T> void quicksort(std::vector<T> &x) {
void quicksort( std::vector<T> &x ) if (x.size() <= 1u)
{
if ( x.size() <= 1u )
return; return;
T *arr = &x[0]; T *arr = &x[0];
bool test; bool test;
long int i, ir, j, jstack, k, l, istack[100]; long int i, ir, j, jstack, k, l, istack[100];
T a, tmp_a; T a, tmp_a;
jstack = 0; jstack = 0;
l = 0; l = 0;
ir = x.size() - 1; ir = x.size() - 1;
while ( 1 ) { while (1) {
if ( ir - l < 7 ) { // Insertion sort when subarray small enough. if (ir - l < 7) { // Insertion sort when subarray small enough.
for ( j = l + 1; j <= ir; j++ ) { for (j = l + 1; j <= ir; j++) {
a = arr[j]; a = arr[j];
test = true; test = true;
for ( i = j - 1; i >= 0; i-- ) { for (i = j - 1; i >= 0; i--) {
if ( arr[i] < a ) { if (arr[i] < a) {
arr[i + 1] = a; arr[i + 1] = a;
test = false; test = false;
break; break;
} }
arr[i + 1] = arr[i]; arr[i + 1] = arr[i];
} }
if ( test ) { if (test) {
i = l - 1; i = l - 1;
arr[i + 1] = a; arr[i + 1] = a;
} }
} }
if ( jstack == 0 ) if (jstack == 0)
return; return;
ir = istack[jstack]; // Pop stack and begin a new round of partitioning. ir = istack
l = istack[jstack - 1]; [jstack]; // Pop stack and begin a new round of partitioning.
l = istack[jstack - 1];
jstack -= 2; jstack -= 2;
} else { } else {
k = ( l + ir ) / 2; // Choose median of left, center and right elements as partitioning k = (l + ir) /
// element a. Also rearrange so that a(l) < a(l+1) < a(ir). 2; // Choose median of left, center and right elements as partitioning
tmp_a = arr[k]; // element a. Also rearrange so that a(l) < a(l+1) < a(ir).
arr[k] = arr[l + 1]; tmp_a = arr[k];
arr[k] = arr[l + 1];
arr[l + 1] = tmp_a; arr[l + 1] = tmp_a;
if ( arr[l] > arr[ir] ) { if (arr[l] > arr[ir]) {
tmp_a = arr[l]; tmp_a = arr[l];
arr[l] = arr[ir]; arr[l] = arr[ir];
arr[ir] = tmp_a; arr[ir] = tmp_a;
} }
if ( arr[l + 1] > arr[ir] ) { if (arr[l + 1] > arr[ir]) {
tmp_a = arr[l + 1]; tmp_a = arr[l + 1];
arr[l + 1] = arr[ir]; arr[l + 1] = arr[ir];
arr[ir] = tmp_a; arr[ir] = tmp_a;
} }
if ( arr[l] > arr[l + 1] ) { if (arr[l] > arr[l + 1]) {
tmp_a = arr[l]; tmp_a = arr[l];
arr[l] = arr[l + 1]; arr[l] = arr[l + 1];
arr[l + 1] = tmp_a; arr[l + 1] = tmp_a;
} }
// Scan up to find element > a // Scan up to find element > a
j = ir; j = ir;
a = arr[l + 1]; // Partitioning element. a = arr[l + 1]; // Partitioning element.
for ( i = l + 2; i <= ir; i++ ) { for (i = l + 2; i <= ir; i++) {
if ( arr[i] < a ) if (arr[i] < a)
continue; continue;
while ( arr[j] > a ) // Scan down to find element < a. while (arr[j] > a) // Scan down to find element < a.
j--; j--;
if ( j < i ) if (j < i)
break; // Pointers crossed. Exit with partitioning complete. break; // Pointers crossed. Exit with partitioning complete.
tmp_a = arr[i]; // Exchange elements of both arrays. tmp_a = arr[i]; // Exchange elements of both arrays.
arr[i] = arr[j]; arr[i] = arr[j];
arr[j] = tmp_a; arr[j] = tmp_a;
} }
arr[l + 1] = arr[j]; // Insert partitioning element in both arrays. arr[l + 1] = arr[j]; // Insert partitioning element in both arrays.
arr[j] = a; arr[j] = a;
jstack += 2; jstack += 2;
// Push pointers to larger subarray on stack, process smaller subarray immediately. // Push pointers to larger subarray on stack, process smaller subarray immediately.
if ( ir - i + 1 >= j - l ) { if (ir - i + 1 >= j - l) {
istack[jstack] = ir; istack[jstack] = ir;
istack[jstack - 1] = i; istack[jstack - 1] = i;
ir = j - 1; ir = j - 1;
} else { } else {
istack[jstack] = j - 1; istack[jstack] = j - 1;
istack[jstack - 1] = l; istack[jstack - 1] = l;
l = i; l = i;
} }
} }
} }
} }
template<class T1, class T2> template <class T1, class T2>
void quicksort( std::vector<T1> &x, std::vector<T2> &y ) void quicksort(std::vector<T1> &x, std::vector<T2> &y) {
{ if (x.size() <= 1u)
if ( x.size() <= 1u )
return; return;
T1 *arr = &x[0]; T1 *arr = &x[0];
T2 *brr = &y[0]; T2 *brr = &y[0];
@ -111,124 +107,123 @@ void quicksort( std::vector<T1> &x, std::vector<T2> &y )
T1 a, tmp_a; T1 a, tmp_a;
T2 b, tmp_b; T2 b, tmp_b;
jstack = 0; jstack = 0;
l = 0; l = 0;
ir = x.size() - 1; ir = x.size() - 1;
while ( 1 ) { while (1) {
if ( ir - l < 7 ) { // Insertion sort when subarray small enough. if (ir - l < 7) { // Insertion sort when subarray small enough.
for ( j = l + 1; j <= ir; j++ ) { for (j = l + 1; j <= ir; j++) {
a = arr[j]; a = arr[j];
b = brr[j]; b = brr[j];
test = true; test = true;
for ( i = j - 1; i >= 0; i-- ) { for (i = j - 1; i >= 0; i--) {
if ( arr[i] < a ) { if (arr[i] < a) {
arr[i + 1] = a; arr[i + 1] = a;
brr[i + 1] = b; brr[i + 1] = b;
test = false; test = false;
break; break;
} }
arr[i + 1] = arr[i]; arr[i + 1] = arr[i];
brr[i + 1] = brr[i]; brr[i + 1] = brr[i];
} }
if ( test ) { if (test) {
i = l - 1; i = l - 1;
arr[i + 1] = a; arr[i + 1] = a;
brr[i + 1] = b; brr[i + 1] = b;
} }
} }
if ( jstack == 0 ) if (jstack == 0)
return; return;
ir = istack[jstack]; // Pop stack and begin a new round of partitioning. ir = istack
l = istack[jstack - 1]; [jstack]; // Pop stack and begin a new round of partitioning.
l = istack[jstack - 1];
jstack -= 2; jstack -= 2;
} else { } else {
k = ( l + ir ) / 2; // Choose median of left, center and right elements as partitioning k = (l + ir) /
// element a. Also rearrange so that a(l) ? a(l+1) ? a(ir). 2; // Choose median of left, center and right elements as partitioning
tmp_a = arr[k]; // element a. Also rearrange so that a(l) ? a(l+1) ? a(ir).
arr[k] = arr[l + 1]; tmp_a = arr[k];
arr[k] = arr[l + 1];
arr[l + 1] = tmp_a; arr[l + 1] = tmp_a;
tmp_b = brr[k]; tmp_b = brr[k];
brr[k] = brr[l + 1]; brr[k] = brr[l + 1];
brr[l + 1] = tmp_b; brr[l + 1] = tmp_b;
if ( arr[l] > arr[ir] ) { if (arr[l] > arr[ir]) {
tmp_a = arr[l]; tmp_a = arr[l];
arr[l] = arr[ir]; arr[l] = arr[ir];
arr[ir] = tmp_a; arr[ir] = tmp_a;
tmp_b = brr[l]; tmp_b = brr[l];
brr[l] = brr[ir]; brr[l] = brr[ir];
brr[ir] = tmp_b; brr[ir] = tmp_b;
} }
if ( arr[l + 1] > arr[ir] ) { if (arr[l + 1] > arr[ir]) {
tmp_a = arr[l + 1]; tmp_a = arr[l + 1];
arr[l + 1] = arr[ir]; arr[l + 1] = arr[ir];
arr[ir] = tmp_a; arr[ir] = tmp_a;
tmp_b = brr[l + 1]; tmp_b = brr[l + 1];
brr[l + 1] = brr[ir]; brr[l + 1] = brr[ir];
brr[ir] = tmp_b; brr[ir] = tmp_b;
} }
if ( arr[l] > arr[l + 1] ) { if (arr[l] > arr[l + 1]) {
tmp_a = arr[l]; tmp_a = arr[l];
arr[l] = arr[l + 1]; arr[l] = arr[l + 1];
arr[l + 1] = tmp_a; arr[l + 1] = tmp_a;
tmp_b = brr[l]; tmp_b = brr[l];
brr[l] = brr[l + 1]; brr[l] = brr[l + 1];
brr[l + 1] = tmp_b; brr[l + 1] = tmp_b;
} }
// Scan up to find element > a // Scan up to find element > a
j = ir; j = ir;
a = arr[l + 1]; // Partitioning element. a = arr[l + 1]; // Partitioning element.
b = brr[l + 1]; b = brr[l + 1];
for ( i = l + 2; i <= ir; i++ ) { for (i = l + 2; i <= ir; i++) {
if ( arr[i] < a ) if (arr[i] < a)
continue; continue;
while ( arr[j] > a ) // Scan down to find element < a. while (arr[j] > a) // Scan down to find element < a.
j--; j--;
if ( j < i ) if (j < i)
break; // Pointers crossed. Exit with partitioning complete. break; // Pointers crossed. Exit with partitioning complete.
tmp_a = arr[i]; // Exchange elements of both arrays. tmp_a = arr[i]; // Exchange elements of both arrays.
arr[i] = arr[j]; arr[i] = arr[j];
arr[j] = tmp_a; arr[j] = tmp_a;
tmp_b = brr[i]; tmp_b = brr[i];
brr[i] = brr[j]; brr[i] = brr[j];
brr[j] = tmp_b; brr[j] = tmp_b;
} }
arr[l + 1] = arr[j]; // Insert partitioning element in both arrays. arr[l + 1] = arr[j]; // Insert partitioning element in both arrays.
arr[j] = a; arr[j] = a;
brr[l + 1] = brr[j]; brr[l + 1] = brr[j];
brr[j] = b; brr[j] = b;
jstack += 2; jstack += 2;
// Push pointers to larger subarray on stack, process smaller subarray immediately. // Push pointers to larger subarray on stack, process smaller subarray immediately.
if ( ir - i + 1 >= j - l ) { if (ir - i + 1 >= j - l) {
istack[jstack] = ir; istack[jstack] = ir;
istack[jstack - 1] = i; istack[jstack - 1] = i;
ir = j - 1; ir = j - 1;
} else { } else {
istack[jstack] = j - 1; istack[jstack] = j - 1;
istack[jstack - 1] = l; istack[jstack - 1] = l;
l = i; l = i;
} }
} }
} }
} }
template<class T> template <class T> void unique(std::vector<T> &x) {
void unique( std::vector<T> &x ) if (x.size() <= 1)
{
if ( x.size() <= 1 )
return; return;
// First perform a quicksort // First perform a quicksort
quicksort( x ); quicksort(x);
// Next remove duplicate entries // Next remove duplicate entries
size_t pos = 1; size_t pos = 1;
for ( size_t i = 1; i < x.size(); i++ ) { for (size_t i = 1; i < x.size(); i++) {
if ( x[i] != x[pos - 1] ) { if (x[i] != x[pos - 1]) {
x[pos] = x[i]; x[pos] = x[i];
pos++; pos++;
} }
} }
if ( pos < x.size() ) if (pos < x.size())
x.resize( pos ); x.resize(pos);
} }
} // namespace Utilities
}
#endif #endif

View File

@ -24,7 +24,6 @@
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
/*! \defgroup Macros Set of utility macro functions /*! \defgroup Macros Set of utility macro functions
* \details These functions are a list of C++ macros that are used * \details These functions are a list of C++ macros that are used
* for common operations, including checking for errors. * for common operations, including checking for errors.
@ -32,7 +31,6 @@
* @{ * @{
*/ */
/*! \def NULL_STATEMENT /*! \def NULL_STATEMENT
* \brief A null statement * \brief A null statement
* \details A statement that does nothing, for insure++ make it something * \details A statement that does nothing, for insure++ make it something
@ -40,33 +38,31 @@
*/ */
#ifndef NULL_STATEMENT #ifndef NULL_STATEMENT
#ifdef __INSURE__ #ifdef __INSURE__
#define NULL_STATEMENT \ #define NULL_STATEMENT \
do { \ do { \
if ( 0 ) \ if (0) \
int nullstatement = 0 \ int nullstatement = 0 \
} while ( 0 ) } while (0)
#else #else
#define NULL_STATEMENT #define NULL_STATEMENT
#endif #endif
#endif #endif
/*! \def NULL_USE(variable) /*! \def NULL_USE(variable)
* \brief A null use of a variable * \brief A null use of a variable
* \details A null use of a variable, use to avoid GNU compiler warnings about unused variables. * \details A null use of a variable, use to avoid GNU compiler warnings about unused variables.
* \param variable Variable to pretend to use * \param variable Variable to pretend to use
*/ */
#ifndef NULL_USE #ifndef NULL_USE
#define NULL_USE( variable ) \ #define NULL_USE(variable) \
do { \ do { \
if ( 0 ) { \ if (0) { \
auto temp = (char *) &variable; \ auto temp = (char *)&variable; \
temp++; \ temp++; \
} \ } \
} while ( 0 ) } while (0)
#endif #endif
/*! \def ERROR(MSG) /*! \def ERROR(MSG)
* \brief Throw error * \brief Throw error
* \details Throw an error exception from within any C++ source code. The * \details Throw an error exception from within any C++ source code. The
@ -74,25 +70,23 @@
* line number of the abort are also printed. * line number of the abort are also printed.
* \param MSG Error message to print * \param MSG Error message to print
*/ */
#define ERROR(MSG) \ #define ERROR(MSG) \
do { \ do { \
::Utilities::abort( MSG, __FILE__, __LINE__ ); \ ::Utilities::abort(MSG, __FILE__, __LINE__); \
} while ( 0 ) } while (0)
/*! \def WARNING(MSG) /*! \def WARNING(MSG)
* \brief Print a warning * \brief Print a warning
* \details Print a warning without exit. Print file and line number of the warning. * \details Print a warning without exit. Print file and line number of the warning.
* \param MSG Warning message to print * \param MSG Warning message to print
*/ */
#define WARNING(MSG) \ #define WARNING(MSG) \
do { \ do { \
std::stringstream tboxos; \ std::stringstream tboxos; \
tboxos << MSG << std::ends; \ tboxos << MSG << std::ends; \
printf("WARNING: %s\n Warning called in %s on line %i\n", \ printf("WARNING: %s\n Warning called in %s on line %i\n", \
tboxos.str().c_str(),__FILE__,__LINE__); \ tboxos.str().c_str(), __FILE__, __LINE__); \
}while(0) } while (0)
/*! \def ASSERT(EXP) /*! \def ASSERT(EXP)
* \brief Assert error * \brief Assert error
@ -102,15 +96,14 @@
* The file and line number of the abort are printed along with the stack trace (if availible). * The file and line number of the abort are printed along with the stack trace (if availible).
* \param EXP Expression to evaluate * \param EXP Expression to evaluate
*/ */
#define ASSERT(EXP) \ #define ASSERT(EXP) \
do { \ do { \
if ( !(EXP) ) { \ if (!(EXP)) { \
std::stringstream tboxos; \ std::stringstream tboxos; \
tboxos << "Failed assertion: " << #EXP << std::ends; \ tboxos << "Failed assertion: " << #EXP << std::ends; \
::Utilities::abort(tboxos.str(), __FILE__, __LINE__); \ ::Utilities::abort(tboxos.str(), __FILE__, __LINE__); \
} \ } \
}while(0) } while (0)
/*! \def INSIST(EXP,MSG) /*! \def INSIST(EXP,MSG)
* \brief Insist error * \brief Insist error
@ -121,15 +114,15 @@
* \param EXP Expression to evaluate * \param EXP Expression to evaluate
* \param MSG Debug message to print * \param MSG Debug message to print
*/ */
#define INSIST(EXP,MSG) do { \ #define INSIST(EXP, MSG) \
if ( !(EXP) ) { \ do { \
std::stringstream tboxos; \ if (!(EXP)) { \
tboxos << "Failed insist: " << #EXP << std::endl; \ std::stringstream tboxos; \
tboxos << "Message: " << MSG << std::ends; \ tboxos << "Failed insist: " << #EXP << std::endl; \
::Utilities::abort(tboxos.str(), __FILE__, __LINE__); \ tboxos << "Message: " << MSG << std::ends; \
} \ ::Utilities::abort(tboxos.str(), __FILE__, __LINE__); \
}while(0) } \
} while (0)
/** /**
* Macro for use when assertions are to be included * Macro for use when assertions are to be included
@ -143,12 +136,11 @@
* \param EXP Expression to evaluate * \param EXP Expression to evaluate
*/ */
#ifdef DEBUG_CHECK_ASSERTIONS #ifdef DEBUG_CHECK_ASSERTIONS
#define CHECK_ASSERT(EXP) ASSERT(EXP) #define CHECK_ASSERT(EXP) ASSERT(EXP)
#else #else
#define CHECK_ASSERT(EXP) #define CHECK_ASSERT(EXP)
#endif #endif
/*! \def DISABLE_WARNINGS /*! \def DISABLE_WARNINGS
* \brief Reenable warnings * \brief Reenable warnings
* \details This will re-enable warnings after a call to DIASABLE_WARNINGS * \details This will re-enable warnings after a call to DIASABLE_WARNINGS
@ -190,9 +182,6 @@
#endif #endif
// clang-format on // clang-format on
/*! @} */ /*! @} */
#endif #endif

View File

@ -3,338 +3,543 @@ This class implements support for halo widths larger than 1
*/ */
#include "common/WideHalo.h" #include "common/WideHalo.h"
ScaLBLWideHalo_Communicator::ScaLBLWideHalo_Communicator(std::shared_ptr <Domain> Dm, int width) ScaLBLWideHalo_Communicator::ScaLBLWideHalo_Communicator(
{ std::shared_ptr<Domain> Dm, int width) {
//...................................................................................... //......................................................................................
Lock=false; // unlock the communicator Lock = false; // unlock the communicator
//...................................................................................... //......................................................................................
// Create a separate copy of the communicator for the device // Create a separate copy of the communicator for the device
MPI_COMM_SCALBL = Dm->Comm.dup(); MPI_COMM_SCALBL = Dm->Comm.dup();
//...................................................................................... //......................................................................................
// Copy the domain size and communication information directly from Dm // Copy the domain size and communication information directly from Dm
Nx = Dm->Nx; Nx = Dm->Nx;
Ny = Dm->Ny; Ny = Dm->Ny;
Nz = Dm->Nz; Nz = Dm->Nz;
N = Nx*Ny*Nz; N = Nx * Ny * Nz;
Nxh = Nx + 2*(width - 1); Nxh = Nx + 2 * (width - 1);
Nyh = Ny + 2*(width - 1); Nyh = Ny + 2 * (width - 1);
Nzh = Nz + 2*(width - 1); Nzh = Nz + 2 * (width - 1);
Nh = Nxh*Nyh*Nzh; Nh = Nxh * Nyh * Nzh;
Map.resize(Nx,Ny,Nz);
rank=Dm->rank();
iproc = Dm->iproc();
jproc = Dm->jproc();
kproc = Dm->kproc();
nprocx = Dm->nprocx();
nprocy = Dm->nprocy();
nprocz = Dm->nprocz();
rank_info = RankInfoStruct(rank,nprocx,nprocy,nprocz);
rank = rank_info.rank[1][1][1];
rank_X = rank_info.rank[2][1][1];
rank_x = rank_info.rank[0][1][1];
rank_Y = rank_info.rank[1][2][1];
rank_y = rank_info.rank[1][0][1];
rank_Z = rank_info.rank[1][1][2];
rank_z = rank_info.rank[1][1][0];
rank_XY = rank_info.rank[2][2][1];
rank_xy = rank_info.rank[0][0][1];
rank_Xy = rank_info.rank[2][0][1];
rank_xY = rank_info.rank[0][2][1];
rank_XZ = rank_info.rank[2][1][2];
rank_xz = rank_info.rank[0][1][0];
rank_Xz = rank_info.rank[2][1][0];
rank_xZ = rank_info.rank[0][1][2];
rank_YZ = rank_info.rank[1][2][2];
rank_yz = rank_info.rank[1][0][0];
rank_Yz = rank_info.rank[1][2][0];
rank_yZ = rank_info.rank[1][0][2];
rank_XYz = rank_info.rank[2][2][0];
rank_xyz = rank_info.rank[0][0][0];
rank_Xyz = rank_info.rank[2][0][0];
rank_xYz = rank_info.rank[0][2][0];
rank_XYZ = rank_info.rank[2][2][2];
rank_xyZ = rank_info.rank[0][0][2];
rank_XyZ = rank_info.rank[2][0][2];
rank_xYZ = rank_info.rank[0][2][2];
MPI_COMM_SCALBL.barrier();
/* Fill in communications patterns for the lists */
/* Send lists */
sendCount_x =getHaloBlock(width,2*width,width,Nyh-width,width,Nzh-width,dvcSendList_x);
sendCount_X =getHaloBlock(Nxh-2*width,Nxh-width,width,Nyh-width,width,Nzh-width,dvcSendList_X);
sendCount_y =getHaloBlock(width,Nxh-width,width,2*width,width,Nzh-width,dvcSendList_y);
sendCount_Y =getHaloBlock(width,Nxh-width,Nyh-2*width,Nyh-width,width,Nzh-width,dvcSendList_Y);
sendCount_z =getHaloBlock(width,Nxh-width,width,Nyh-width,width,2*width,dvcSendList_z);
sendCount_Z =getHaloBlock(width,Nxh-width,width,Nyh-width,Nzh-2*width,Nzh-width,dvcSendList_Z);
// xy
sendCount_xy =getHaloBlock(width,2*width,width,2*width,width,Nzh-width,dvcSendList_xy);
sendCount_xY =getHaloBlock(width,2*width,Nyh-2*width,Nyh-width,width,Nzh-width,dvcSendList_xY);
sendCount_Xy =getHaloBlock(Nxh-2*width,Nxh-width,width,2*width,width,Nzh-width,dvcSendList_Xy);
sendCount_XY =getHaloBlock(Nxh-2*width,Nxh-width,Nyh-2*width,Nyh-width,width,Nzh-width,dvcSendList_XY);
// xz
sendCount_xz =getHaloBlock(width,2*width,width,Nyh-width,width,2*width,dvcSendList_xz);
sendCount_xZ =getHaloBlock(width,2*width,width,Nyh-width,Nzh-2*width,Nzh-width,dvcSendList_xZ);
sendCount_Xz =getHaloBlock(Nxh-2*width,Nxh-width,width,Nyh-width,width,2*width,dvcSendList_Xz);
sendCount_XZ =getHaloBlock(Nxh-2*width,Nxh-width,width,Nyh-width,Nzh-2*width,Nzh-width,dvcSendList_XZ);
// yz
sendCount_yz =getHaloBlock(width,Nxh-width,width,2*width,width,2*width,dvcSendList_yz);
sendCount_yZ =getHaloBlock(width,Nxh-width,width,2*width,Nzh-2*width,Nzh-width,dvcSendList_yZ);
sendCount_Yz =getHaloBlock(width,Nxh-width,Nyh-2*width,Nyh-width,width,2*width,dvcSendList_Yz);
sendCount_YZ =getHaloBlock(width,Nxh-width,Nyh-2*width,Nyh-width,Nzh-2*width,Nzh-width,dvcSendList_YZ);
// xyz
sendCount_xyz =getHaloBlock(width,2*width,width,2*width,width,2*width,dvcSendList_xyz);
sendCount_xyZ =getHaloBlock(width,2*width,width,2*width,Nzh-2*width,Nzh-width,dvcSendList_xyZ);
sendCount_xYz =getHaloBlock(width,2*width,Nyh-2*width,Nyh-width,width,2*width,dvcSendList_xYz);
sendCount_xYZ =getHaloBlock(width,2*width,Nyh-2*width,Nyh-width,Nzh-2*width,Nzh-width,dvcSendList_xYZ);
sendCount_Xyz =getHaloBlock(Nxh-2*width,Nxh-width,width,2*width,width,2*width,dvcSendList_Xyz);
sendCount_XyZ =getHaloBlock(Nxh-2*width,Nxh-width,width,2*width,Nzh-2*width,Nzh-width,dvcSendList_XyZ);
sendCount_XYz =getHaloBlock(Nxh-2*width,Nxh-width,Nyh-2*width,Nyh-width,width,2*width,dvcSendList_XYz);
sendCount_XYZ =getHaloBlock(Nxh-2*width,Nxh-width,Nyh-2*width,Nyh-width,Nzh-2*width,Nzh-width,dvcSendList_XYZ);
/* Recv lists */
recvCount_x =getHaloBlock(0,width,width,Nyh-width,width,Nzh-width,dvcRecvList_x);
recvCount_X =getHaloBlock(Nxh-width,Nxh,width,Nyh-width,width,Nzh-width,dvcRecvList_X);
recvCount_y =getHaloBlock(width,Nxh-width,0,width,width,Nzh-width,dvcRecvList_y);
recvCount_Y =getHaloBlock(width,Nxh-width,Nyh-width,Nyh,width,Nzh-width,dvcRecvList_Y);
recvCount_z =getHaloBlock(width,Nxh-width,width,Nyh-width,0,width,dvcRecvList_z);
recvCount_Z =getHaloBlock(width,Nxh-width,width,Nyh-width,Nzh-width,Nzh,dvcRecvList_Z);
//xy
recvCount_xy =getHaloBlock(0,width,0,width,width,Nzh-width,dvcRecvList_xy);
recvCount_xY =getHaloBlock(0,width,Nyh-width,Nyh,width,Nzh-width,dvcRecvList_xY);
recvCount_Xy =getHaloBlock(Nxh-width,Nxh,0,width,width,Nzh-width,dvcRecvList_Xy);
recvCount_XY =getHaloBlock(Nxh-width,Nxh,Nyh-width,Nyh,width,Nzh-width,dvcRecvList_XY);
//xz
recvCount_xz =getHaloBlock(0,width,width,Nyh-width,0,width,dvcRecvList_xz);
recvCount_xZ =getHaloBlock(0,width,width,Nyh-width,Nzh-width,Nzh,dvcRecvList_xZ);
recvCount_Xz =getHaloBlock(Nxh-width,Nxh,width,Nyh-width,0,width,dvcRecvList_Xz);
recvCount_XZ =getHaloBlock(Nxh-width,Nxh,width,Nyh-width,Nzh-width,Nzh,dvcRecvList_XZ);
//yz
recvCount_yz =getHaloBlock(width,Nxh-width,0,width,0,width,dvcRecvList_yz);
recvCount_yZ =getHaloBlock(width,Nxh-width,0,width,Nzh-width,Nzh,dvcRecvList_yZ);
recvCount_Yz =getHaloBlock(width,Nxh-width,Nyh-width,Nyh,0,width,dvcRecvList_Yz);
recvCount_YZ =getHaloBlock(width,Nxh-width,Nyh-width,Nyh,Nzh-width,Nzh,dvcRecvList_YZ);
//xyz
recvCount_xyz =getHaloBlock(0,width,0,width,0,width,dvcRecvList_xyz);
recvCount_xyZ =getHaloBlock(0,width,0,width,Nzh-width,Nzh,dvcRecvList_xyZ);
recvCount_xYz =getHaloBlock(0,width,Nyh-width,Nyh,0,width,dvcRecvList_xYz);
recvCount_xYZ =getHaloBlock(0,width,Nyh-width,Nyh,Nzh-width,Nzh,dvcRecvList_xYZ);
recvCount_Xyz =getHaloBlock(Nxh-width,Nxh,0,width,0,width,dvcRecvList_Xyz);
recvCount_XyZ =getHaloBlock(Nxh-width,Nxh,0,width,Nzh-width,Nzh,dvcRecvList_XyZ);
recvCount_XYz =getHaloBlock(Nxh-width,Nxh,Nyh-width,Nyh,0,width,dvcRecvList_XYz);
recvCount_XYZ =getHaloBlock(Nxh-width,Nxh,Nyh-width,Nyh,Nzh-width,Nzh,dvcRecvList_XYZ);
//...................................................................................... Map.resize(Nx, Ny, Nz);
ScaLBL_AllocateZeroCopy((void **) &sendbuf_x, sendCount_x*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_X, sendCount_X*sizeof(double)); // Allocate device memory rank = Dm->rank();
ScaLBL_AllocateZeroCopy((void **) &sendbuf_y, sendCount_y*sizeof(double)); // Allocate device memory iproc = Dm->iproc();
ScaLBL_AllocateZeroCopy((void **) &sendbuf_Y, sendCount_Y*sizeof(double)); // Allocate device memory jproc = Dm->jproc();
ScaLBL_AllocateZeroCopy((void **) &sendbuf_z, sendCount_z*sizeof(double)); // Allocate device memory kproc = Dm->kproc();
ScaLBL_AllocateZeroCopy((void **) &sendbuf_Z, sendCount_Z*sizeof(double)); // Allocate device memory nprocx = Dm->nprocx();
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xy, sendCount_xy*sizeof(double)); // Allocate device memory nprocy = Dm->nprocy();
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xY, sendCount_xY*sizeof(double)); // Allocate device memory nprocz = Dm->nprocz();
ScaLBL_AllocateZeroCopy((void **) &sendbuf_Xy, sendCount_Xy*sizeof(double)); // Allocate device memory rank_info = RankInfoStruct(rank, nprocx, nprocy, nprocz);
ScaLBL_AllocateZeroCopy((void **) &sendbuf_XY, sendCount_XY*sizeof(double)); // Allocate device memory rank = rank_info.rank[1][1][1];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xz, sendCount_xz*sizeof(double)); // Allocate device memory rank_X = rank_info.rank[2][1][1];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xZ, sendCount_xZ*sizeof(double)); // Allocate device memory rank_x = rank_info.rank[0][1][1];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_Xz, sendCount_Xz*sizeof(double)); // Allocate device memory rank_Y = rank_info.rank[1][2][1];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_XZ, sendCount_XZ*sizeof(double)); // Allocate device memory rank_y = rank_info.rank[1][0][1];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_yz, sendCount_yz*sizeof(double)); // Allocate device memory rank_Z = rank_info.rank[1][1][2];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_yZ, sendCount_yZ*sizeof(double)); // Allocate device memory rank_z = rank_info.rank[1][1][0];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_Yz, sendCount_Yz*sizeof(double)); // Allocate device memory rank_XY = rank_info.rank[2][2][1];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_YZ, sendCount_YZ*sizeof(double)); // Allocate device memory rank_xy = rank_info.rank[0][0][1];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xyz, sendCount_xyz*sizeof(double)); // Allocate device memory rank_Xy = rank_info.rank[2][0][1];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xYz, sendCount_xYz*sizeof(double)); // Allocate device memory rank_xY = rank_info.rank[0][2][1];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_Xyz, sendCount_Xyz*sizeof(double)); // Allocate device memory rank_XZ = rank_info.rank[2][1][2];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_XYz, sendCount_XYz*sizeof(double)); // Allocate device memory rank_xz = rank_info.rank[0][1][0];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xyZ, sendCount_xyZ*sizeof(double)); // Allocate device memory rank_Xz = rank_info.rank[2][1][0];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xYZ, sendCount_xYZ*sizeof(double)); // Allocate device memory rank_xZ = rank_info.rank[0][1][2];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_XyZ, sendCount_XyZ*sizeof(double)); // Allocate device memory rank_YZ = rank_info.rank[1][2][2];
ScaLBL_AllocateZeroCopy((void **) &sendbuf_XYZ, sendCount_XYZ*sizeof(double)); // Allocate device memory rank_yz = rank_info.rank[1][0][0];
//...................................................................................... rank_Yz = rank_info.rank[1][2][0];
ScaLBL_AllocateZeroCopy((void **) &recvbuf_x, recvCount_x*sizeof(double)); // Allocate device memory rank_yZ = rank_info.rank[1][0][2];
ScaLBL_AllocateZeroCopy((void **) &recvbuf_X, recvCount_X*sizeof(double)); // Allocate device memory rank_XYz = rank_info.rank[2][2][0];
ScaLBL_AllocateZeroCopy((void **) &recvbuf_y, recvCount_y*sizeof(double)); // Allocate device memory rank_xyz = rank_info.rank[0][0][0];
ScaLBL_AllocateZeroCopy((void **) &recvbuf_Y, recvCount_Y*sizeof(double)); // Allocate device memory rank_Xyz = rank_info.rank[2][0][0];
ScaLBL_AllocateZeroCopy((void **) &recvbuf_z, recvCount_z*sizeof(double)); // Allocate device memory rank_xYz = rank_info.rank[0][2][0];
ScaLBL_AllocateZeroCopy((void **) &recvbuf_Z, recvCount_Z*sizeof(double)); // Allocate device memory rank_XYZ = rank_info.rank[2][2][2];
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xy, recvCount_xy*sizeof(double)); // Allocate device memory rank_xyZ = rank_info.rank[0][0][2];
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xY, recvCount_xY*sizeof(double)); // Allocate device memory rank_XyZ = rank_info.rank[2][0][2];
ScaLBL_AllocateZeroCopy((void **) &recvbuf_Xy, recvCount_Xy*sizeof(double)); // Allocate device memory rank_xYZ = rank_info.rank[0][2][2];
ScaLBL_AllocateZeroCopy((void **) &recvbuf_XY, recvCount_XY*sizeof(double)); // Allocate device memory MPI_COMM_SCALBL.barrier();
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xz, recvCount_xz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xZ, recvCount_xZ*sizeof(double)); // Allocate device memory /* Fill in communications patterns for the lists */
ScaLBL_AllocateZeroCopy((void **) &recvbuf_Xz, recvCount_Xz*sizeof(double)); // Allocate device memory /* Send lists */
ScaLBL_AllocateZeroCopy((void **) &recvbuf_XZ, recvCount_XZ*sizeof(double)); // Allocate device memory sendCount_x = getHaloBlock(width, 2 * width, width, Nyh - width, width,
ScaLBL_AllocateZeroCopy((void **) &recvbuf_yz, recvCount_yz*sizeof(double)); // Allocate device memory Nzh - width, dvcSendList_x);
ScaLBL_AllocateZeroCopy((void **) &recvbuf_yZ, recvCount_yZ*sizeof(double)); // Allocate device memory sendCount_X = getHaloBlock(Nxh - 2 * width, Nxh - width, width, Nyh - width,
ScaLBL_AllocateZeroCopy((void **) &recvbuf_Yz, recvCount_Yz*sizeof(double)); // Allocate device memory width, Nzh - width, dvcSendList_X);
ScaLBL_AllocateZeroCopy((void **) &recvbuf_YZ, recvCount_YZ*sizeof(double)); // Allocate device memory sendCount_y = getHaloBlock(width, Nxh - width, width, 2 * width, width,
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xyz, recvCount_xyz*sizeof(double)); // Allocate device memory Nzh - width, dvcSendList_y);
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xYz, recvCount_xYz*sizeof(double)); // Allocate device memory sendCount_Y = getHaloBlock(width, Nxh - width, Nyh - 2 * width, Nyh - width,
ScaLBL_AllocateZeroCopy((void **) &recvbuf_Xyz, recvCount_Xyz*sizeof(double)); // Allocate device memory width, Nzh - width, dvcSendList_Y);
ScaLBL_AllocateZeroCopy((void **) &recvbuf_XYz, recvCount_XYz*sizeof(double)); // Allocate device memory sendCount_z = getHaloBlock(width, Nxh - width, width, Nyh - width, width,
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xyZ, recvCount_xyZ*sizeof(double)); // Allocate device memory 2 * width, dvcSendList_z);
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xYZ, recvCount_xYZ*sizeof(double)); // Allocate device memory sendCount_Z = getHaloBlock(width, Nxh - width, width, Nyh - width,
ScaLBL_AllocateZeroCopy((void **) &recvbuf_XyZ, recvCount_XyZ*sizeof(double)); // Allocate device memory Nzh - 2 * width, Nzh - width, dvcSendList_Z);
ScaLBL_AllocateZeroCopy((void **) &recvbuf_XYZ, recvCount_XYZ*sizeof(double)); // Allocate device memory // xy
sendCount_xy = getHaloBlock(width, 2 * width, width, 2 * width, width,
/* Set up a map to the halo width=1 data structure */ Nzh - width, dvcSendList_xy);
for (k=width; k<Nzh-width; k++){ sendCount_xY = getHaloBlock(width, 2 * width, Nyh - 2 * width, Nyh - width,
for (j=width; j<Nyh-width; j++){ width, Nzh - width, dvcSendList_xY);
for (i=width; i<Nxh-width; i++){ sendCount_Xy = getHaloBlock(Nxh - 2 * width, Nxh - width, width, 2 * width,
int idx = k*Nxh*Nyh + j*Nxh + i; width, Nzh - width, dvcSendList_Xy);
Map(i-width+1,j-width+1,k-width+1) = idx; sendCount_XY =
} getHaloBlock(Nxh - 2 * width, Nxh - width, Nyh - 2 * width, Nyh - width,
} width, Nzh - width, dvcSendList_XY);
} // xz
sendCount_xz = getHaloBlock(width, 2 * width, width, Nyh - width, width,
2 * width, dvcSendList_xz);
sendCount_xZ = getHaloBlock(width, 2 * width, width, Nyh - width,
Nzh - 2 * width, Nzh - width, dvcSendList_xZ);
sendCount_Xz = getHaloBlock(Nxh - 2 * width, Nxh - width, width,
Nyh - width, width, 2 * width, dvcSendList_Xz);
sendCount_XZ =
getHaloBlock(Nxh - 2 * width, Nxh - width, width, Nyh - width,
Nzh - 2 * width, Nzh - width, dvcSendList_XZ);
// yz
sendCount_yz = getHaloBlock(width, Nxh - width, width, 2 * width, width,
2 * width, dvcSendList_yz);
sendCount_yZ = getHaloBlock(width, Nxh - width, width, 2 * width,
Nzh - 2 * width, Nzh - width, dvcSendList_yZ);
sendCount_Yz = getHaloBlock(width, Nxh - width, Nyh - 2 * width,
Nyh - width, width, 2 * width, dvcSendList_Yz);
sendCount_YZ =
getHaloBlock(width, Nxh - width, Nyh - 2 * width, Nyh - width,
Nzh - 2 * width, Nzh - width, dvcSendList_YZ);
// xyz
sendCount_xyz = getHaloBlock(width, 2 * width, width, 2 * width, width,
2 * width, dvcSendList_xyz);
sendCount_xyZ = getHaloBlock(width, 2 * width, width, 2 * width,
Nzh - 2 * width, Nzh - width, dvcSendList_xyZ);
sendCount_xYz = getHaloBlock(width, 2 * width, Nyh - 2 * width, Nyh - width,
width, 2 * width, dvcSendList_xYz);
sendCount_xYZ = getHaloBlock(width, 2 * width, Nyh - 2 * width, Nyh - width,
Nzh - 2 * width, Nzh - width, dvcSendList_xYZ);
sendCount_Xyz = getHaloBlock(Nxh - 2 * width, Nxh - width, width, 2 * width,
width, 2 * width, dvcSendList_Xyz);
sendCount_XyZ = getHaloBlock(Nxh - 2 * width, Nxh - width, width, 2 * width,
Nzh - 2 * width, Nzh - width, dvcSendList_XyZ);
sendCount_XYz =
getHaloBlock(Nxh - 2 * width, Nxh - width, Nyh - 2 * width, Nyh - width,
width, 2 * width, dvcSendList_XYz);
sendCount_XYZ =
getHaloBlock(Nxh - 2 * width, Nxh - width, Nyh - 2 * width, Nyh - width,
Nzh - 2 * width, Nzh - width, dvcSendList_XYZ);
/* Recv lists */
recvCount_x = getHaloBlock(0, width, width, Nyh - width, width, Nzh - width,
dvcRecvList_x);
recvCount_X = getHaloBlock(Nxh - width, Nxh, width, Nyh - width, width,
Nzh - width, dvcRecvList_X);
recvCount_y = getHaloBlock(width, Nxh - width, 0, width, width, Nzh - width,
dvcRecvList_y);
recvCount_Y = getHaloBlock(width, Nxh - width, Nyh - width, Nyh, width,
Nzh - width, dvcRecvList_Y);
recvCount_z = getHaloBlock(width, Nxh - width, width, Nyh - width, 0, width,
dvcRecvList_z);
recvCount_Z = getHaloBlock(width, Nxh - width, width, Nyh - width,
Nzh - width, Nzh, dvcRecvList_Z);
//xy
recvCount_xy =
getHaloBlock(0, width, 0, width, width, Nzh - width, dvcRecvList_xy);
recvCount_xY = getHaloBlock(0, width, Nyh - width, Nyh, width, Nzh - width,
dvcRecvList_xY);
recvCount_Xy = getHaloBlock(Nxh - width, Nxh, 0, width, width, Nzh - width,
dvcRecvList_Xy);
recvCount_XY = getHaloBlock(Nxh - width, Nxh, Nyh - width, Nyh, width,
Nzh - width, dvcRecvList_XY);
//xz
recvCount_xz =
getHaloBlock(0, width, width, Nyh - width, 0, width, dvcRecvList_xz);
recvCount_xZ = getHaloBlock(0, width, width, Nyh - width, Nzh - width, Nzh,
dvcRecvList_xZ);
recvCount_Xz = getHaloBlock(Nxh - width, Nxh, width, Nyh - width, 0, width,
dvcRecvList_Xz);
recvCount_XZ = getHaloBlock(Nxh - width, Nxh, width, Nyh - width,
Nzh - width, Nzh, dvcRecvList_XZ);
//yz
recvCount_yz =
getHaloBlock(width, Nxh - width, 0, width, 0, width, dvcRecvList_yz);
recvCount_yZ = getHaloBlock(width, Nxh - width, 0, width, Nzh - width, Nzh,
dvcRecvList_yZ);
recvCount_Yz = getHaloBlock(width, Nxh - width, Nyh - width, Nyh, 0, width,
dvcRecvList_Yz);
recvCount_YZ = getHaloBlock(width, Nxh - width, Nyh - width, Nyh,
Nzh - width, Nzh, dvcRecvList_YZ);
//xyz
recvCount_xyz = getHaloBlock(0, width, 0, width, 0, width, dvcRecvList_xyz);
recvCount_xyZ =
getHaloBlock(0, width, 0, width, Nzh - width, Nzh, dvcRecvList_xyZ);
recvCount_xYz =
getHaloBlock(0, width, Nyh - width, Nyh, 0, width, dvcRecvList_xYz);
recvCount_xYZ = getHaloBlock(0, width, Nyh - width, Nyh, Nzh - width, Nzh,
dvcRecvList_xYZ);
recvCount_Xyz =
getHaloBlock(Nxh - width, Nxh, 0, width, 0, width, dvcRecvList_Xyz);
recvCount_XyZ = getHaloBlock(Nxh - width, Nxh, 0, width, Nzh - width, Nzh,
dvcRecvList_XyZ);
recvCount_XYz = getHaloBlock(Nxh - width, Nxh, Nyh - width, Nyh, 0, width,
dvcRecvList_XYz);
recvCount_XYZ = getHaloBlock(Nxh - width, Nxh, Nyh - width, Nyh,
Nzh - width, Nzh, dvcRecvList_XYZ);
//......................................................................................
ScaLBL_AllocateZeroCopy((void **)&sendbuf_x,
sendCount_x *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_X,
sendCount_X *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_y,
sendCount_y *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_Y,
sendCount_Y *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_z,
sendCount_z *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_Z,
sendCount_Z *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xy,
sendCount_xy *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xY,
sendCount_xY *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_Xy,
sendCount_Xy *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_XY,
sendCount_XY *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xz,
sendCount_xz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xZ,
sendCount_xZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_Xz,
sendCount_Xz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_XZ,
sendCount_XZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_yz,
sendCount_yz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_yZ,
sendCount_yZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_Yz,
sendCount_Yz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_YZ,
sendCount_YZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xyz,
sendCount_xyz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xYz,
sendCount_xYz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_Xyz,
sendCount_Xyz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_XYz,
sendCount_XYz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xyZ,
sendCount_xyZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xYZ,
sendCount_xYZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_XyZ,
sendCount_XyZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_XYZ,
sendCount_XYZ *
sizeof(double)); // Allocate device memory
//......................................................................................
ScaLBL_AllocateZeroCopy((void **)&recvbuf_x,
recvCount_x *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_X,
recvCount_X *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_y,
recvCount_y *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_Y,
recvCount_Y *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_z,
recvCount_z *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_Z,
recvCount_Z *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xy,
recvCount_xy *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xY,
recvCount_xY *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_Xy,
recvCount_Xy *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_XY,
recvCount_XY *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xz,
recvCount_xz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xZ,
recvCount_xZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_Xz,
recvCount_Xz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_XZ,
recvCount_XZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_yz,
recvCount_yz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_yZ,
recvCount_yZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_Yz,
recvCount_Yz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_YZ,
recvCount_YZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xyz,
recvCount_xyz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xYz,
recvCount_xYz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_Xyz,
recvCount_Xyz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_XYz,
recvCount_XYz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xyZ,
recvCount_xyZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xYZ,
recvCount_xYZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_XyZ,
recvCount_XyZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_XYZ,
recvCount_XYZ *
sizeof(double)); // Allocate device memory
/* Set up a map to the halo width=1 data structure */
for (k = width; k < Nzh - width; k++) {
for (j = width; j < Nyh - width; j++) {
for (i = width; i < Nxh - width; i++) {
int idx = k * Nxh * Nyh + j * Nxh + i;
Map(i - width + 1, j - width + 1, k - width + 1) = idx;
}
}
}
} }
void ScaLBLWideHalo_Communicator::Send(double *data){ void ScaLBLWideHalo_Communicator::Send(double *data) {
//................................................................................... //...................................................................................
if (Lock==true){ if (Lock == true) {
ERROR("ScaLBL Error (SendHalo): ScaLBLWideHalo_Communicator is locked -- did you forget to match Send/Recv calls?"); ERROR("ScaLBL Error (SendHalo): ScaLBLWideHalo_Communicator is locked "
} "-- did you forget to match Send/Recv calls?");
else{ } else {
Lock=true; Lock = true;
} }
ScaLBL_DeviceBarrier(); ScaLBL_DeviceBarrier();
//................................................................................... //...................................................................................
sendtag = recvtag = 1; sendtag = recvtag = 1;
//................................................................................... //...................................................................................
ScaLBL_Scalar_Pack(dvcSendList_x, sendCount_x,sendbuf_x, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_x, sendCount_x, sendbuf_x, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_y, sendCount_y,sendbuf_y, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_y, sendCount_y, sendbuf_y, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_z, sendCount_z,sendbuf_z, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_z, sendCount_z, sendbuf_z, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_X, sendCount_X,sendbuf_X, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_X, sendCount_X, sendbuf_X, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_Y, sendCount_Y,sendbuf_Y, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_Y, sendCount_Y, sendbuf_Y, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_Z, sendCount_Z,sendbuf_Z, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_Z, sendCount_Z, sendbuf_Z, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_xy, sendCount_xy,sendbuf_xy, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_xy, sendCount_xy, sendbuf_xy, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_xY, sendCount_xY,sendbuf_xY, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_xY, sendCount_xY, sendbuf_xY, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_Xy, sendCount_Xy,sendbuf_Xy, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_Xy, sendCount_Xy, sendbuf_Xy, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_XY, sendCount_XY,sendbuf_XY, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_XY, sendCount_XY, sendbuf_XY, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_xz, sendCount_xz,sendbuf_xz, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_xz, sendCount_xz, sendbuf_xz, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_xZ, sendCount_xZ,sendbuf_xZ, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_xZ, sendCount_xZ, sendbuf_xZ, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_Xz, sendCount_Xz,sendbuf_Xz, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_Xz, sendCount_Xz, sendbuf_Xz, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_XZ, sendCount_XZ,sendbuf_XZ, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_XZ, sendCount_XZ, sendbuf_XZ, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_yz, sendCount_yz,sendbuf_yz, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_yz, sendCount_yz, sendbuf_yz, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_yZ, sendCount_yZ,sendbuf_yZ, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_yZ, sendCount_yZ, sendbuf_yZ, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_Yz, sendCount_Yz,sendbuf_Yz, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_Yz, sendCount_Yz, sendbuf_Yz, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_YZ, sendCount_YZ,sendbuf_YZ, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_YZ, sendCount_YZ, sendbuf_YZ, data, Nh);
/* corners */ /* corners */
ScaLBL_Scalar_Pack(dvcSendList_xyz, sendCount_xyz,sendbuf_xyz, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_xyz, sendCount_xyz, sendbuf_xyz, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_xyZ, sendCount_xyZ,sendbuf_xyZ, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_xyZ, sendCount_xyZ, sendbuf_xyZ, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_xYz, sendCount_xYz,sendbuf_xYz, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_xYz, sendCount_xYz, sendbuf_xYz, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_xYZ, sendCount_xYZ,sendbuf_xYZ, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_xYZ, sendCount_xYZ, sendbuf_xYZ, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_Xyz, sendCount_Xyz,sendbuf_Xyz, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_Xyz, sendCount_Xyz, sendbuf_Xyz, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_XyZ, sendCount_XyZ,sendbuf_XyZ, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_XyZ, sendCount_XyZ, sendbuf_XyZ, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_XYz, sendCount_XYz,sendbuf_XYz, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_XYz, sendCount_XYz, sendbuf_XYz, data, Nh);
ScaLBL_Scalar_Pack(dvcSendList_XYZ, sendCount_XYZ,sendbuf_XYZ, data, Nh); ScaLBL_Scalar_Pack(dvcSendList_XYZ, sendCount_XYZ, sendbuf_XYZ, data, Nh);
//................................................................................... //...................................................................................
// Send / Recv all the phase indcator field values // Send / Recv all the phase indcator field values
//................................................................................... //...................................................................................
req1[0] = MPI_COMM_SCALBL.Isend(sendbuf_x,sendCount_x,rank_x,sendtag+0); req1[0] =
req2[0] = MPI_COMM_SCALBL.Irecv(recvbuf_X,recvCount_X,rank_X,recvtag+0); MPI_COMM_SCALBL.Isend(sendbuf_x, sendCount_x, rank_x, sendtag + 0);
req1[1] = MPI_COMM_SCALBL.Isend(sendbuf_X,sendCount_X,rank_X,sendtag+1); req2[0] =
req2[1] = MPI_COMM_SCALBL.Irecv(recvbuf_x,recvCount_x,rank_x,recvtag+1); MPI_COMM_SCALBL.Irecv(recvbuf_X, recvCount_X, rank_X, recvtag + 0);
req1[2] = MPI_COMM_SCALBL.Isend(sendbuf_y,sendCount_y,rank_y,sendtag+2); req1[1] =
req2[2] = MPI_COMM_SCALBL.Irecv(recvbuf_Y,recvCount_Y,rank_Y,recvtag+2); MPI_COMM_SCALBL.Isend(sendbuf_X, sendCount_X, rank_X, sendtag + 1);
req1[3] = MPI_COMM_SCALBL.Isend(sendbuf_Y,sendCount_Y,rank_Y,sendtag+3); req2[1] =
req2[3] = MPI_COMM_SCALBL.Irecv(recvbuf_y,recvCount_y,rank_y,recvtag+3); MPI_COMM_SCALBL.Irecv(recvbuf_x, recvCount_x, rank_x, recvtag + 1);
req1[4] = MPI_COMM_SCALBL.Isend(sendbuf_z,sendCount_z,rank_z,sendtag+4); req1[2] =
req2[4] = MPI_COMM_SCALBL.Irecv(recvbuf_Z,recvCount_Z,rank_Z,recvtag+4); MPI_COMM_SCALBL.Isend(sendbuf_y, sendCount_y, rank_y, sendtag + 2);
req1[5] = MPI_COMM_SCALBL.Isend(sendbuf_Z,sendCount_Z,rank_Z,sendtag+5); req2[2] =
req2[5] = MPI_COMM_SCALBL.Irecv(recvbuf_z,recvCount_z,rank_z,recvtag+5); MPI_COMM_SCALBL.Irecv(recvbuf_Y, recvCount_Y, rank_Y, recvtag + 2);
req1[6] = MPI_COMM_SCALBL.Isend(sendbuf_xy,sendCount_xy,rank_xy,sendtag+6); req1[3] =
req2[6] = MPI_COMM_SCALBL.Irecv(recvbuf_XY,recvCount_XY,rank_XY,recvtag+6); MPI_COMM_SCALBL.Isend(sendbuf_Y, sendCount_Y, rank_Y, sendtag + 3);
req1[7] = MPI_COMM_SCALBL.Isend(sendbuf_XY,sendCount_XY,rank_XY,sendtag+7); req2[3] =
req2[7] = MPI_COMM_SCALBL.Irecv(recvbuf_xy,recvCount_xy,rank_xy,recvtag+7); MPI_COMM_SCALBL.Irecv(recvbuf_y, recvCount_y, rank_y, recvtag + 3);
req1[8] = MPI_COMM_SCALBL.Isend(sendbuf_Xy,sendCount_Xy,rank_Xy,sendtag+8); req1[4] =
req2[8] = MPI_COMM_SCALBL.Irecv(recvbuf_xY,recvCount_xY,rank_xY,recvtag+8); MPI_COMM_SCALBL.Isend(sendbuf_z, sendCount_z, rank_z, sendtag + 4);
req1[9] = MPI_COMM_SCALBL.Isend(sendbuf_xY,sendCount_xY,rank_xY,sendtag+9); req2[4] =
req2[9] = MPI_COMM_SCALBL.Irecv(recvbuf_Xy,recvCount_Xy,rank_Xy,recvtag+9); MPI_COMM_SCALBL.Irecv(recvbuf_Z, recvCount_Z, rank_Z, recvtag + 4);
req1[10] = MPI_COMM_SCALBL.Isend(sendbuf_xz,sendCount_xz,rank_xz,sendtag+10); req1[5] =
req2[10] = MPI_COMM_SCALBL.Irecv(recvbuf_XZ,recvCount_XZ,rank_XZ,recvtag+10); MPI_COMM_SCALBL.Isend(sendbuf_Z, sendCount_Z, rank_Z, sendtag + 5);
req1[11] = MPI_COMM_SCALBL.Isend(sendbuf_XZ,sendCount_XZ,rank_XZ,sendtag+11); req2[5] =
req2[11] = MPI_COMM_SCALBL.Irecv(recvbuf_xz,recvCount_xz,rank_xz,recvtag+11); MPI_COMM_SCALBL.Irecv(recvbuf_z, recvCount_z, rank_z, recvtag + 5);
req1[12] = MPI_COMM_SCALBL.Isend(sendbuf_Xz,sendCount_Xz,rank_Xz,sendtag+12); req1[6] =
req2[12] = MPI_COMM_SCALBL.Irecv(recvbuf_xZ,recvCount_xZ,rank_xZ,recvtag+12); MPI_COMM_SCALBL.Isend(sendbuf_xy, sendCount_xy, rank_xy, sendtag + 6);
req1[13] = MPI_COMM_SCALBL.Isend(sendbuf_xZ,sendCount_xZ,rank_xZ,sendtag+13); req2[6] =
req2[13] = MPI_COMM_SCALBL.Irecv(recvbuf_Xz,recvCount_Xz,rank_Xz,recvtag+13); MPI_COMM_SCALBL.Irecv(recvbuf_XY, recvCount_XY, rank_XY, recvtag + 6);
req1[14] = MPI_COMM_SCALBL.Isend(sendbuf_yz,sendCount_yz,rank_yz,sendtag+14); req1[7] =
req2[14] = MPI_COMM_SCALBL.Irecv(recvbuf_YZ,recvCount_YZ,rank_YZ,recvtag+14); MPI_COMM_SCALBL.Isend(sendbuf_XY, sendCount_XY, rank_XY, sendtag + 7);
req1[15] = MPI_COMM_SCALBL.Isend(sendbuf_YZ,sendCount_YZ,rank_YZ,sendtag+15); req2[7] =
req2[15] = MPI_COMM_SCALBL.Irecv(recvbuf_yz,recvCount_yz,rank_yz,recvtag+15); MPI_COMM_SCALBL.Irecv(recvbuf_xy, recvCount_xy, rank_xy, recvtag + 7);
req1[16] = MPI_COMM_SCALBL.Isend(sendbuf_Yz,sendCount_Yz,rank_Yz,sendtag+16); req1[8] =
req2[16] = MPI_COMM_SCALBL.Irecv(recvbuf_yZ,recvCount_yZ,rank_yZ,recvtag+16); MPI_COMM_SCALBL.Isend(sendbuf_Xy, sendCount_Xy, rank_Xy, sendtag + 8);
req1[17] = MPI_COMM_SCALBL.Isend(sendbuf_yZ,sendCount_yZ,rank_yZ,sendtag+17); req2[8] =
req2[17] = MPI_COMM_SCALBL.Irecv(recvbuf_Yz,recvCount_Yz,rank_Yz,recvtag+17); MPI_COMM_SCALBL.Irecv(recvbuf_xY, recvCount_xY, rank_xY, recvtag + 8);
/* Corners */ req1[9] =
req1[18] = MPI_COMM_SCALBL.Isend(sendbuf_xyz,sendCount_xyz,rank_xyz,sendtag+18); MPI_COMM_SCALBL.Isend(sendbuf_xY, sendCount_xY, rank_xY, sendtag + 9);
req2[18] = MPI_COMM_SCALBL.Irecv(recvbuf_XYZ,recvCount_XYZ,rank_XYZ,recvtag+18); req2[9] =
req1[19] = MPI_COMM_SCALBL.Isend(sendbuf_XYz,sendCount_XYz,rank_XYz,sendtag+19); MPI_COMM_SCALBL.Irecv(recvbuf_Xy, recvCount_Xy, rank_Xy, recvtag + 9);
req2[19] = MPI_COMM_SCALBL.Irecv(recvbuf_xyZ,recvCount_xyZ,rank_xyZ,recvtag+19); req1[10] =
req1[20] = MPI_COMM_SCALBL.Isend(sendbuf_Xyz,sendCount_Xyz,rank_Xyz,sendtag+20); MPI_COMM_SCALBL.Isend(sendbuf_xz, sendCount_xz, rank_xz, sendtag + 10);
req2[20] = MPI_COMM_SCALBL.Irecv(recvbuf_xYZ,recvCount_xYZ,rank_xYZ,recvtag+20); req2[10] =
req1[21] = MPI_COMM_SCALBL.Isend(sendbuf_xYz,sendCount_xYz,rank_xYz,sendtag+21); MPI_COMM_SCALBL.Irecv(recvbuf_XZ, recvCount_XZ, rank_XZ, recvtag + 10);
req2[21] = MPI_COMM_SCALBL.Irecv(recvbuf_XyZ,recvCount_XyZ,rank_XyZ,recvtag+21); req1[11] =
req1[22] = MPI_COMM_SCALBL.Isend(sendbuf_xyZ,sendCount_xyZ,rank_xyZ,sendtag+22); MPI_COMM_SCALBL.Isend(sendbuf_XZ, sendCount_XZ, rank_XZ, sendtag + 11);
req2[22] = MPI_COMM_SCALBL.Irecv(recvbuf_XYz,recvCount_XYz,rank_XYz,recvtag+22); req2[11] =
req1[23] = MPI_COMM_SCALBL.Isend(sendbuf_XYZ,sendCount_XYZ,rank_XYZ,sendtag+23); MPI_COMM_SCALBL.Irecv(recvbuf_xz, recvCount_xz, rank_xz, recvtag + 11);
req2[23] = MPI_COMM_SCALBL.Irecv(recvbuf_xyz,recvCount_xyz,rank_xyz,recvtag+23); req1[12] =
req1[24] = MPI_COMM_SCALBL.Isend(sendbuf_XyZ,sendCount_XyZ,rank_XyZ,sendtag+24); MPI_COMM_SCALBL.Isend(sendbuf_Xz, sendCount_Xz, rank_Xz, sendtag + 12);
req2[24] = MPI_COMM_SCALBL.Irecv(recvbuf_xYz,recvCount_xYz,rank_xYz,recvtag+24); req2[12] =
req1[25] = MPI_COMM_SCALBL.Isend(sendbuf_xYZ,sendCount_xYZ,rank_xYZ,sendtag+25); MPI_COMM_SCALBL.Irecv(recvbuf_xZ, recvCount_xZ, rank_xZ, recvtag + 12);
req2[25] = MPI_COMM_SCALBL.Irecv(recvbuf_Xyz,recvCount_Xyz,rank_Xyz,recvtag+25); req1[13] =
//................................................................................... MPI_COMM_SCALBL.Isend(sendbuf_xZ, sendCount_xZ, rank_xZ, sendtag + 13);
req2[13] =
MPI_COMM_SCALBL.Irecv(recvbuf_Xz, recvCount_Xz, rank_Xz, recvtag + 13);
req1[14] =
MPI_COMM_SCALBL.Isend(sendbuf_yz, sendCount_yz, rank_yz, sendtag + 14);
req2[14] =
MPI_COMM_SCALBL.Irecv(recvbuf_YZ, recvCount_YZ, rank_YZ, recvtag + 14);
req1[15] =
MPI_COMM_SCALBL.Isend(sendbuf_YZ, sendCount_YZ, rank_YZ, sendtag + 15);
req2[15] =
MPI_COMM_SCALBL.Irecv(recvbuf_yz, recvCount_yz, rank_yz, recvtag + 15);
req1[16] =
MPI_COMM_SCALBL.Isend(sendbuf_Yz, sendCount_Yz, rank_Yz, sendtag + 16);
req2[16] =
MPI_COMM_SCALBL.Irecv(recvbuf_yZ, recvCount_yZ, rank_yZ, recvtag + 16);
req1[17] =
MPI_COMM_SCALBL.Isend(sendbuf_yZ, sendCount_yZ, rank_yZ, sendtag + 17);
req2[17] =
MPI_COMM_SCALBL.Irecv(recvbuf_Yz, recvCount_Yz, rank_Yz, recvtag + 17);
/* Corners */
req1[18] = MPI_COMM_SCALBL.Isend(sendbuf_xyz, sendCount_xyz, rank_xyz,
sendtag + 18);
req2[18] = MPI_COMM_SCALBL.Irecv(recvbuf_XYZ, recvCount_XYZ, rank_XYZ,
recvtag + 18);
req1[19] = MPI_COMM_SCALBL.Isend(sendbuf_XYz, sendCount_XYz, rank_XYz,
sendtag + 19);
req2[19] = MPI_COMM_SCALBL.Irecv(recvbuf_xyZ, recvCount_xyZ, rank_xyZ,
recvtag + 19);
req1[20] = MPI_COMM_SCALBL.Isend(sendbuf_Xyz, sendCount_Xyz, rank_Xyz,
sendtag + 20);
req2[20] = MPI_COMM_SCALBL.Irecv(recvbuf_xYZ, recvCount_xYZ, rank_xYZ,
recvtag + 20);
req1[21] = MPI_COMM_SCALBL.Isend(sendbuf_xYz, sendCount_xYz, rank_xYz,
sendtag + 21);
req2[21] = MPI_COMM_SCALBL.Irecv(recvbuf_XyZ, recvCount_XyZ, rank_XyZ,
recvtag + 21);
req1[22] = MPI_COMM_SCALBL.Isend(sendbuf_xyZ, sendCount_xyZ, rank_xyZ,
sendtag + 22);
req2[22] = MPI_COMM_SCALBL.Irecv(recvbuf_XYz, recvCount_XYz, rank_XYz,
recvtag + 22);
req1[23] = MPI_COMM_SCALBL.Isend(sendbuf_XYZ, sendCount_XYZ, rank_XYZ,
sendtag + 23);
req2[23] = MPI_COMM_SCALBL.Irecv(recvbuf_xyz, recvCount_xyz, rank_xyz,
recvtag + 23);
req1[24] = MPI_COMM_SCALBL.Isend(sendbuf_XyZ, sendCount_XyZ, rank_XyZ,
sendtag + 24);
req2[24] = MPI_COMM_SCALBL.Irecv(recvbuf_xYz, recvCount_xYz, rank_xYz,
recvtag + 24);
req1[25] = MPI_COMM_SCALBL.Isend(sendbuf_xYZ, sendCount_xYZ, rank_xYZ,
sendtag + 25);
req2[25] = MPI_COMM_SCALBL.Irecv(recvbuf_Xyz, recvCount_Xyz, rank_Xyz,
recvtag + 25);
//...................................................................................
} }
ScaLBLWideHalo_Communicator::~ScaLBLWideHalo_Communicator() {}
void ScaLBLWideHalo_Communicator::Recv(double *data) {
ScaLBLWideHalo_Communicator::~ScaLBLWideHalo_Communicator() //...................................................................................
{ Utilities::MPI::waitAll(26, req1);
Utilities::MPI::waitAll(26, req2);
ScaLBL_DeviceBarrier();
//...................................................................................
//printf("Ready to unpack %i to x\n",recvCount_x);
//printf(" print first 10 values...\n");
//for (int idx=0; idx<10; idx++) printf(" recvBuf[%i]=%f \n",idx,recvbuf_x[idx]);
ScaLBL_Scalar_Unpack(dvcRecvList_x, recvCount_x, recvbuf_x, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_y, recvCount_y, recvbuf_y, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_X, recvCount_X, recvbuf_X, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_Y, recvCount_Y, recvbuf_Y, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xy, recvCount_xy, recvbuf_xy, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xY, recvCount_xY, recvbuf_xY, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_Xy, recvCount_Xy, recvbuf_Xy, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_XY, recvCount_XY, recvbuf_XY, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_z, recvCount_z, recvbuf_z, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xz, recvCount_xz, recvbuf_xz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_Xz, recvCount_Xz, recvbuf_Xz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_yz, recvCount_yz, recvbuf_yz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_Yz, recvCount_Yz, recvbuf_Yz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_Z, recvCount_Z, recvbuf_Z, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xZ, recvCount_xZ, recvbuf_xZ, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_XZ, recvCount_XZ, recvbuf_XZ, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_yZ, recvCount_yZ, recvbuf_yZ, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_YZ, recvCount_YZ, recvbuf_YZ, data, Nh);
/* corners */
ScaLBL_Scalar_Unpack(dvcRecvList_xyz, recvCount_xyz, recvbuf_xyz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xYz, recvCount_xYz, recvbuf_xYz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xyZ, recvCount_xyZ, recvbuf_xyZ, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xYZ, recvCount_xYZ, recvbuf_xYZ, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_Xyz, recvCount_Xyz, recvbuf_Xyz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_XYz, recvCount_XYz, recvbuf_XYz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_XyZ, recvCount_XyZ, recvbuf_XyZ, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_XYZ, recvCount_XYZ, recvbuf_XYZ, data, Nh);
//...................................................................................
Lock = false; // unlock the communicator after communications complete
//...................................................................................
} }
void ScaLBLWideHalo_Communicator::Recv(double *data){
//...................................................................................
Utilities::MPI::waitAll(26,req1);
Utilities::MPI::waitAll(26,req2);
ScaLBL_DeviceBarrier();
//...................................................................................
//printf("Ready to unpack %i to x\n",recvCount_x);
//printf(" print first 10 values...\n");
//for (int idx=0; idx<10; idx++) printf(" recvBuf[%i]=%f \n",idx,recvbuf_x[idx]);
ScaLBL_Scalar_Unpack(dvcRecvList_x, recvCount_x,recvbuf_x, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_y, recvCount_y,recvbuf_y, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_X, recvCount_X,recvbuf_X, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_Y, recvCount_Y,recvbuf_Y, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xy, recvCount_xy,recvbuf_xy, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xY, recvCount_xY,recvbuf_xY, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_Xy, recvCount_Xy,recvbuf_Xy, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_XY, recvCount_XY,recvbuf_XY, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_z, recvCount_z,recvbuf_z, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xz, recvCount_xz,recvbuf_xz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_Xz, recvCount_Xz,recvbuf_Xz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_yz, recvCount_yz,recvbuf_yz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_Yz, recvCount_Yz,recvbuf_Yz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_Z, recvCount_Z,recvbuf_Z, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xZ, recvCount_xZ,recvbuf_xZ, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_XZ, recvCount_XZ,recvbuf_XZ, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_yZ, recvCount_yZ,recvbuf_yZ, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_YZ, recvCount_YZ,recvbuf_YZ, data, Nh);
/* corners */
ScaLBL_Scalar_Unpack(dvcRecvList_xyz, recvCount_xyz,recvbuf_xyz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xYz, recvCount_xYz,recvbuf_xYz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xyZ, recvCount_xyZ,recvbuf_xyZ, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_xYZ, recvCount_xYZ,recvbuf_xYZ, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_Xyz, recvCount_Xyz,recvbuf_Xyz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_XYz, recvCount_XYz,recvbuf_XYz, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_XyZ, recvCount_XyZ,recvbuf_XyZ, data, Nh);
ScaLBL_Scalar_Unpack(dvcRecvList_XYZ, recvCount_XYZ,recvbuf_XYZ, data, Nh);
//...................................................................................
Lock=false; // unlock the communicator after communications complete
//...................................................................................
}

View File

@ -6,110 +6,130 @@ This class implements support for halo widths larger than 1
#include "common/ScaLBL.h" #include "common/ScaLBL.h"
#include "common/MPI.h" #include "common/MPI.h"
class ScaLBLWideHalo_Communicator{ class ScaLBLWideHalo_Communicator {
public: public:
//...................................................................................... //......................................................................................
ScaLBLWideHalo_Communicator(std::shared_ptr <Domain> Dm, int width); ScaLBLWideHalo_Communicator(std::shared_ptr<Domain> Dm, int width);
~ScaLBLWideHalo_Communicator(); ~ScaLBLWideHalo_Communicator();
//...................................................................................... //......................................................................................
//MPI_Comm MPI_COMM_SCALBL; // MPI Communicator //MPI_Comm MPI_COMM_SCALBL; // MPI Communicator
Utilities::MPI MPI_COMM_SCALBL; Utilities::MPI MPI_COMM_SCALBL;
unsigned long int CommunicationCount,SendCount,RecvCount; unsigned long int CommunicationCount, SendCount, RecvCount;
int Nx,Ny,Nz,N; // original domain structure int Nx, Ny, Nz, N; // original domain structure
int Nxh,Nyh,Nzh,Nh; // with wide halo int Nxh, Nyh, Nzh, Nh; // with wide halo
DoubleArray Map; // map to regular halo DoubleArray Map; // map to regular halo
int first_interior,last_interior; int first_interior, last_interior;
//...................................................................................... //......................................................................................
// Set up for D3Q19 distributions -- all 27 neighbors are needed // Set up for D3Q19 distributions -- all 27 neighbors are needed
//...................................................................................... //......................................................................................
// Buffers to store data sent and recieved by this MPI process // Buffers to store data sent and recieved by this MPI process
double *sendbuf_x, *sendbuf_y, *sendbuf_z, *sendbuf_X, *sendbuf_Y, *sendbuf_Z; double *sendbuf_x, *sendbuf_y, *sendbuf_z, *sendbuf_X, *sendbuf_Y,
double *sendbuf_xy, *sendbuf_yz, *sendbuf_xz, *sendbuf_Xy, *sendbuf_Yz, *sendbuf_xZ; *sendbuf_Z;
double *sendbuf_xY, *sendbuf_yZ, *sendbuf_Xz, *sendbuf_XY, *sendbuf_YZ, *sendbuf_XZ; double *sendbuf_xy, *sendbuf_yz, *sendbuf_xz, *sendbuf_Xy, *sendbuf_Yz,
double *sendbuf_xyz, *sendbuf_Xyz, *sendbuf_xYz, *sendbuf_XYz; *sendbuf_xZ;
double *sendbuf_xyZ, *sendbuf_XyZ, *sendbuf_xYZ, *sendbuf_XYZ; double *sendbuf_xY, *sendbuf_yZ, *sendbuf_Xz, *sendbuf_XY, *sendbuf_YZ,
double *recvbuf_x, *recvbuf_y, *recvbuf_z, *recvbuf_X, *recvbuf_Y, *recvbuf_Z; *sendbuf_XZ;
double *recvbuf_xy, *recvbuf_yz, *recvbuf_xz, *recvbuf_Xy, *recvbuf_Yz, *recvbuf_xZ; double *sendbuf_xyz, *sendbuf_Xyz, *sendbuf_xYz, *sendbuf_XYz;
double *recvbuf_xY, *recvbuf_yZ, *recvbuf_Xz, *recvbuf_XY, *recvbuf_YZ, *recvbuf_XZ; double *sendbuf_xyZ, *sendbuf_XyZ, *sendbuf_xYZ, *sendbuf_XYZ;
double *recvbuf_xyz, *recvbuf_Xyz, *recvbuf_xYz, *recvbuf_XYz; double *recvbuf_x, *recvbuf_y, *recvbuf_z, *recvbuf_X, *recvbuf_Y,
double *recvbuf_xyZ, *recvbuf_XyZ, *recvbuf_xYZ, *recvbuf_XYZ; *recvbuf_Z;
//...................................................................................... double *recvbuf_xy, *recvbuf_yz, *recvbuf_xz, *recvbuf_Xy, *recvbuf_Yz,
int LastExterior(); *recvbuf_xZ;
int FirstInterior(); double *recvbuf_xY, *recvbuf_yZ, *recvbuf_Xz, *recvbuf_XY, *recvbuf_YZ,
int LastInterior(); *recvbuf_XZ;
double *recvbuf_xyz, *recvbuf_Xyz, *recvbuf_xYz, *recvbuf_XYz;
void Send(double *data); double *recvbuf_xyZ, *recvbuf_XyZ, *recvbuf_xYZ, *recvbuf_XYZ;
void Recv(double *data); //......................................................................................
int LastExterior();
int FirstInterior();
int LastInterior();
// Debugging and unit testing functions void Send(double *data);
void PrintDebug(); void Recv(double *data);
// Debugging and unit testing functions
void PrintDebug();
private: private:
bool Lock; // use Lock to make sure only one call at a time to protect data in transit bool
// only one set of Send requests can be active at any time (per instance) Lock; // use Lock to make sure only one call at a time to protect data in transit
int i,j,k,n; // only one set of Send requests can be active at any time (per instance)
int iproc,jproc,kproc; int i, j, k, n;
int nprocx,nprocy,nprocz; int iproc, jproc, kproc;
int sendtag,recvtag; int nprocx, nprocy, nprocz;
// Give the object it's own MPI communicator int sendtag, recvtag;
RankInfoStruct rank_info; // Give the object it's own MPI communicator
MPI_Request req1[26],req2[26]; RankInfoStruct rank_info;
//...................................................................................... MPI_Request req1[26], req2[26];
// MPI ranks for all 18 neighbors //......................................................................................
//...................................................................................... // MPI ranks for all 18 neighbors
// These variables are all private to prevent external things from modifying them!! //......................................................................................
//...................................................................................... // These variables are all private to prevent external things from modifying them!!
int rank; //......................................................................................
int rank_x,rank_y,rank_z,rank_X,rank_Y,rank_Z; int rank;
int rank_xy,rank_XY,rank_xY,rank_Xy; int rank_x, rank_y, rank_z, rank_X, rank_Y, rank_Z;
int rank_xz,rank_XZ,rank_xZ,rank_Xz; int rank_xy, rank_XY, rank_xY, rank_Xy;
int rank_yz,rank_YZ,rank_yZ,rank_Yz; int rank_xz, rank_XZ, rank_xZ, rank_Xz;
int rank_xyz,rank_Xyz,rank_xYz,rank_XYz; int rank_yz, rank_YZ, rank_yZ, rank_Yz;
int rank_xyZ,rank_XyZ,rank_xYZ,rank_XYZ; int rank_xyz, rank_Xyz, rank_xYz, rank_XYz;
//...................................................................................... int rank_xyZ, rank_XyZ, rank_xYZ, rank_XYZ;
//...................................................................................... //......................................................................................
int sendCount_x, sendCount_y, sendCount_z, sendCount_X, sendCount_Y, sendCount_Z; //......................................................................................
int sendCount_xy, sendCount_yz, sendCount_xz, sendCount_Xy, sendCount_Yz, sendCount_xZ; int sendCount_x, sendCount_y, sendCount_z, sendCount_X, sendCount_Y,
int sendCount_xY, sendCount_yZ, sendCount_Xz, sendCount_XY, sendCount_YZ, sendCount_XZ; sendCount_Z;
int sendCount_xyz,sendCount_Xyz,sendCount_xYz,sendCount_XYz; int sendCount_xy, sendCount_yz, sendCount_xz, sendCount_Xy, sendCount_Yz,
int sendCount_xyZ,sendCount_XyZ,sendCount_xYZ,sendCount_XYZ; sendCount_xZ;
//...................................................................................... int sendCount_xY, sendCount_yZ, sendCount_Xz, sendCount_XY, sendCount_YZ,
int recvCount_x, recvCount_y, recvCount_z, recvCount_X, recvCount_Y, recvCount_Z; sendCount_XZ;
int recvCount_xy, recvCount_yz, recvCount_xz, recvCount_Xy, recvCount_Yz, recvCount_xZ; int sendCount_xyz, sendCount_Xyz, sendCount_xYz, sendCount_XYz;
int recvCount_xY, recvCount_yZ, recvCount_Xz, recvCount_XY, recvCount_YZ, recvCount_XZ; int sendCount_xyZ, sendCount_XyZ, sendCount_xYZ, sendCount_XYZ;
int recvCount_xyz,recvCount_Xyz,recvCount_xYz,recvCount_XYz; //......................................................................................
int recvCount_xyZ,recvCount_XyZ,recvCount_xYZ,recvCount_XYZ; int recvCount_x, recvCount_y, recvCount_z, recvCount_X, recvCount_Y,
//...................................................................................... recvCount_Z;
// Send buffers that reside on the compute device int recvCount_xy, recvCount_yz, recvCount_xz, recvCount_Xy, recvCount_Yz,
int *dvcSendList_x, *dvcSendList_y, *dvcSendList_z, *dvcSendList_X, *dvcSendList_Y, *dvcSendList_Z; recvCount_xZ;
int *dvcSendList_xy, *dvcSendList_yz, *dvcSendList_xz, *dvcSendList_Xy, *dvcSendList_Yz, *dvcSendList_xZ; int recvCount_xY, recvCount_yZ, recvCount_Xz, recvCount_XY, recvCount_YZ,
int *dvcSendList_xY, *dvcSendList_yZ, *dvcSendList_Xz, *dvcSendList_XY, *dvcSendList_YZ, *dvcSendList_XZ; recvCount_XZ;
int *dvcSendList_xyz,*dvcSendList_Xyz,*dvcSendList_xYz,*dvcSendList_XYz; int recvCount_xyz, recvCount_Xyz, recvCount_xYz, recvCount_XYz;
int *dvcSendList_xyZ,*dvcSendList_XyZ,*dvcSendList_xYZ,*dvcSendList_XYZ; int recvCount_xyZ, recvCount_XyZ, recvCount_xYZ, recvCount_XYZ;
// Recieve buffers that reside on the compute device //......................................................................................
int *dvcRecvList_x, *dvcRecvList_y, *dvcRecvList_z, *dvcRecvList_X, *dvcRecvList_Y, *dvcRecvList_Z; // Send buffers that reside on the compute device
int *dvcRecvList_xy, *dvcRecvList_yz, *dvcRecvList_xz, *dvcRecvList_Xy, *dvcRecvList_Yz, *dvcRecvList_xZ; int *dvcSendList_x, *dvcSendList_y, *dvcSendList_z, *dvcSendList_X,
int *dvcRecvList_xY, *dvcRecvList_yZ, *dvcRecvList_Xz, *dvcRecvList_XY, *dvcRecvList_YZ, *dvcRecvList_XZ; *dvcSendList_Y, *dvcSendList_Z;
int *dvcRecvList_xyz,*dvcRecvList_Xyz,*dvcRecvList_xYz,*dvcRecvList_XYz; int *dvcSendList_xy, *dvcSendList_yz, *dvcSendList_xz, *dvcSendList_Xy,
int *dvcRecvList_xyZ,*dvcRecvList_XyZ,*dvcRecvList_xYZ,*dvcRecvList_XYZ; *dvcSendList_Yz, *dvcSendList_xZ;
//...................................................................................... int *dvcSendList_xY, *dvcSendList_yZ, *dvcSendList_Xz, *dvcSendList_XY,
*dvcSendList_YZ, *dvcSendList_XZ;
inline int getHaloBlock(int imin, int imax, int jmin, int jmax, int kmin, int kmax, int *& dvcList){ int *dvcSendList_xyz, *dvcSendList_Xyz, *dvcSendList_xYz, *dvcSendList_XYz;
int count = 0; int *dvcSendList_xyZ, *dvcSendList_XyZ, *dvcSendList_xYZ, *dvcSendList_XYZ;
int *List; // Recieve buffers that reside on the compute device
List = new int [(imax-imin)*(jmax-jmin)*(kmax-kmin)]; int *dvcRecvList_x, *dvcRecvList_y, *dvcRecvList_z, *dvcRecvList_X,
for (k=kmin; k<kmax; k++){ *dvcRecvList_Y, *dvcRecvList_Z;
for (j=jmin; j<jmax; j++){ int *dvcRecvList_xy, *dvcRecvList_yz, *dvcRecvList_xz, *dvcRecvList_Xy,
for (i=imin; i<imax; i++){ *dvcRecvList_Yz, *dvcRecvList_xZ;
List[count++] = k*Nxh*Nyh + j*Nxh + i; int *dvcRecvList_xY, *dvcRecvList_yZ, *dvcRecvList_Xz, *dvcRecvList_XY,
} *dvcRecvList_YZ, *dvcRecvList_XZ;
} int *dvcRecvList_xyz, *dvcRecvList_Xyz, *dvcRecvList_xYz, *dvcRecvList_XYz;
} int *dvcRecvList_xyZ, *dvcRecvList_XyZ, *dvcRecvList_xYZ, *dvcRecvList_XYZ;
size_t numbytes=count*sizeof(int); //......................................................................................
ScaLBL_AllocateZeroCopy((void **) &dvcList, numbytes); // Allocate device memory
ScaLBL_CopyToZeroCopy(dvcList,List,numbytes);
return count;
}
inline int getHaloBlock(int imin, int imax, int jmin, int jmax, int kmin,
int kmax, int *&dvcList) {
int count = 0;
int *List;
List = new int[(imax - imin) * (jmax - jmin) * (kmax - kmin)];
for (k = kmin; k < kmax; k++) {
for (j = jmin; j < jmax; j++) {
for (i = imin; i < imax; i++) {
List[count++] = k * Nxh * Nyh + j * Nxh + i;
}
}
}
size_t numbytes = count * sizeof(int);
ScaLBL_AllocateZeroCopy((void **)&dvcList,
numbytes); // Allocate device memory
ScaLBL_CopyToZeroCopy(dvcList, List, numbytes);
return count;
}
}; };
#endif #endif

View File

@ -14,278 +14,387 @@
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/>.
*/ */
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,
// conserved momemnts int Np, double rlx, double Fx,
double rho,ux,uy,uz,uu; double Fy, double Fz) {
// non-conserved moments // conserved momemnts
double f0,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18; double rho, ux, uy, uz, uu;
// non-conserved moments
double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
f16, f17, f18;
for (int n=start; n<finish; n++){ for (int n = start; n < finish; n++) {
// q=0 // q=0
f0 = dist[n]; f0 = dist[n];
f1 = dist[2*Np+n]; f1 = dist[2 * Np + n];
f2 = dist[1*Np+n]; f2 = dist[1 * Np + n];
f3 = dist[4*Np+n]; f3 = dist[4 * Np + n];
f4 = dist[3*Np+n]; f4 = dist[3 * Np + n];
f5 = dist[6*Np+n]; f5 = dist[6 * Np + n];
f6 = dist[5*Np+n]; f6 = dist[5 * Np + n];
f7 = dist[8*Np+n]; f7 = dist[8 * Np + n];
f8 = dist[7*Np+n]; f8 = dist[7 * Np + n];
f9 = dist[10*Np+n]; f9 = dist[10 * Np + n];
f10 = dist[9*Np+n]; f10 = dist[9 * Np + n];
f11 = dist[12*Np+n]; f11 = dist[12 * Np + n];
f12 = dist[11*Np+n]; f12 = dist[11 * Np + n];
f13 = dist[14*Np+n]; f13 = dist[14 * Np + n];
f14 = dist[13*Np+n]; f14 = dist[13 * Np + n];
f15 = dist[16*Np+n]; f15 = dist[16 * Np + n];
f16 = dist[15*Np+n]; f16 = dist[15 * Np + n];
f17 = dist[18*Np+n]; f17 = dist[18 * Np + n];
f18 = dist[17*Np+n]; f18 = dist[17 * Np + n];
rho = f0+f2+f1+f4+f3+f6+f5+f8+f7+f10+f9+f12+f11+f14+f13+f16+f15+f18+f17; rho = f0 + f2 + f1 + f4 + f3 + f6 + f5 + f8 + f7 + f10 + f9 + f12 +
ux = f1-f2+f7-f8+f9-f10+f11-f12+f13-f14; f11 + f14 + f13 + f16 + f15 + f18 + f17;
uy = f3-f4+f7-f8-f9+f10+f15-f16+f17-f18; ux = f1 - f2 + f7 - f8 + f9 - f10 + f11 - f12 + f13 - f14;
uz = f5-f6+f11-f12-f13+f14+f15-f16-f17+f18; uy = f3 - f4 + f7 - f8 - f9 + f10 + f15 - f16 + f17 - f18;
uu = 1.5*(ux*ux+uy*uy+uz*uz); uz = f5 - f6 + f11 - f12 - f13 + f14 + f15 - f16 - f17 + f18;
uu = 1.5 * (ux * ux + uy * uy + uz * uz);
// q=0 // q=0
dist[n] = f0*(1.0-rlx)+rlx*0.3333333333333333*(1.0-uu); dist[n] = f0 * (1.0 - rlx) + rlx * 0.3333333333333333 * (1.0 - uu);
// q = 1 // q = 1
dist[1*Np+n] = f1*(1.0-rlx) + rlx*0.05555555555555555*(rho + 3.0*ux + 4.5*ux*ux - uu) + 0.16666666*Fx; dist[1 * Np + n] =
f1 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho + 3.0 * ux + 4.5 * ux * ux - uu) +
0.16666666 * Fx;
// q=2 // q=2
dist[2*Np+n] = f2*(1.0-rlx) + rlx*0.05555555555555555*(rho - 3.0*ux + 4.5*ux*ux - uu)- 0.16666666*Fx; dist[2 * Np + n] =
f2 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho - 3.0 * ux + 4.5 * ux * ux - uu) -
0.16666666 * Fx;
// q = 3 // q = 3
dist[3*Np+n] = f3*(1.0-rlx) + dist[3 * Np + n] =
rlx*0.05555555555555555*(rho + 3.0*uy + 4.5*uy*uy - uu) + 0.16666666*Fy; f3 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho + 3.0 * uy + 4.5 * uy * uy - uu) +
0.16666666 * Fy;
// q = 4 // q = 4
dist[4*Np+n] = f4*(1.0-rlx) + dist[4 * Np + n] =
rlx*0.05555555555555555*(rho - 3.0*uy + 4.5*uy*uy - uu)- 0.16666666*Fy; f4 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho - 3.0 * uy + 4.5 * uy * uy - uu) -
0.16666666 * Fy;
// q = 5 // q = 5
dist[5*Np+n] = f5*(1.0-rlx) + dist[5 * Np + n] =
rlx*0.05555555555555555*(rho + 3.0*uz + 4.5*uz*uz - uu) + 0.16666666*Fz; f5 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho + 3.0 * uz + 4.5 * uz * uz - uu) +
0.16666666 * Fz;
// q = 6 // q = 6
dist[6*Np+n] = f6*(1.0-rlx) + dist[6 * Np + n] =
rlx*0.05555555555555555*(rho - 3.0*uz + 4.5*uz*uz - uu) - 0.16666666*Fz; f6 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho - 3.0 * uz + 4.5 * uz * uz - uu) -
0.16666666 * Fz;
// q = 7 // q = 7
dist[7*Np+n] = f7*(1.0-rlx) + dist[7 * Np + n] =
rlx*0.02777777777777778*(rho + 3.0*(ux+uy) + 4.5*(ux+uy)*(ux+uy) - uu) + 0.08333333333*(Fx+Fy); f7 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux + uy) + 4.5 * (ux + uy) * (ux + uy) - uu) +
0.08333333333 * (Fx + Fy);
// q = 8 // q = 8
dist[8*Np+n] = f8*(1.0-rlx) + dist[8 * Np + n] =
rlx*0.02777777777777778*(rho - 3.0*(ux+uy) + 4.5*(ux+uy)*(ux+uy) - uu) - 0.08333333333*(Fx+Fy); f8 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux + uy) + 4.5 * (ux + uy) * (ux + uy) - uu) -
0.08333333333 * (Fx + Fy);
// q = 9 // q = 9
dist[9*Np+n] = f9*(1.0-rlx) + dist[9 * Np + n] =
rlx*0.02777777777777778*(rho + 3.0*(ux-uy) + 4.5*(ux-uy)*(ux-uy) - uu) + 0.08333333333*(Fx-Fy); f9 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux - uy) + 4.5 * (ux - uy) * (ux - uy) - uu) +
0.08333333333 * (Fx - Fy);
// q = 10 // q = 10
dist[10*Np+n] = f10*(1.0-rlx) + dist[10 * Np + n] =
rlx*0.02777777777777778*(rho - 3.0*(ux-uy) + 4.5*(ux-uy)*(ux-uy) - uu) - 0.08333333333*(Fx-Fy); f10 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux - uy) + 4.5 * (ux - uy) * (ux - uy) - uu) -
0.08333333333 * (Fx - Fy);
// q = 11 // q = 11
dist[11*Np+n] = f11*(1.0-rlx) + dist[11 * Np + n] =
rlx*0.02777777777777778*(rho + 3.0*(ux+uz) + 4.5*(ux+uz)*(ux+uz) - uu) + 0.08333333333*(Fx+Fz); f11 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux + uz) + 4.5 * (ux + uz) * (ux + uz) - uu) +
0.08333333333 * (Fx + Fz);
// q = 12 // q = 12
dist[12*Np+n] = f12*(1.0-rlx) + dist[12 * Np + n] =
rlx*0.02777777777777778*(rho - 3.0*(ux+uz) + 4.5*(ux+uz)*(ux+uz) - uu) - 0.08333333333*(Fx+Fz); f12 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux + uz) + 4.5 * (ux + uz) * (ux + uz) - uu) -
0.08333333333 * (Fx + Fz);
// q = 13 // q = 13
dist[13*Np+n] = f13*(1.0-rlx) + dist[13 * Np + n] =
rlx*0.02777777777777778*(rho + 3.0*(ux-uz) + 4.5*(ux-uz)*(ux-uz) - uu) + 0.08333333333*(Fx-Fz); f13 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux - uz) + 4.5 * (ux - uz) * (ux - uz) - uu) +
0.08333333333 * (Fx - Fz);
// q= 14 // q= 14
dist[14*Np+n] = f14*(1.0-rlx) + dist[14 * Np + n] =
rlx*0.02777777777777778*(rho - 3.0*(ux-uz) + 4.5*(ux-uz)*(ux-uz) - uu)- 0.08333333333*(Fx-Fz); f14 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux - uz) + 4.5 * (ux - uz) * (ux - uz) - uu) -
0.08333333333 * (Fx - Fz);
// q = 15 // q = 15
dist[15*Np+n] = f15*(1.0-rlx) + dist[15 * Np + n] =
rlx*0.02777777777777778*(rho + 3.0*(uy+uz) + 4.5*(uy+uz)*(uy+uz) - uu) + 0.08333333333*(Fy+Fz); f15 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (uy + uz) + 4.5 * (uy + uz) * (uy + uz) - uu) +
0.08333333333 * (Fy + Fz);
// q = 16 // q = 16
dist[16*Np+n] = f16*(1.0-rlx) + dist[16 * Np + n] =
rlx*0.02777777777777778*(rho - 3.0*(uy+uz) + 4.5*(uy+uz)*(uy+uz) - uu) - 0.08333333333*(Fy+Fz); f16 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (uy + uz) + 4.5 * (uy + uz) * (uy + uz) - uu) -
0.08333333333 * (Fy + Fz);
// q = 17 // q = 17
dist[17*Np+n] = f17*(1.0-rlx) + dist[17 * Np + n] =
rlx*0.02777777777777778*(rho + 3.0*(uy-uz) + 4.5*(uy-uz)*(uy-uz) - uu) + 0.08333333333*(Fy-Fz); f17 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (uy - uz) + 4.5 * (uy - uz) * (uy - uz) - uu) +
0.08333333333 * (Fy - Fz);
// q = 18 // q = 18
dist[18*Np+n] = f18*(1.0-rlx) + dist[18 * Np + n] =
rlx*0.02777777777777778*(rho - 3.0*(uy-uz) + 4.5*(uy-uz)*(uy-uz) - uu) - 0.08333333333*(Fy-Fz); f18 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (uy - uz) + 4.5 * (uy - uz) * (uy - uz) - uu) -
0.08333333333 * (Fy - 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){ extern "C" void ScaLBL_D3Q19_AAodd_BGK(int *neighborList, double *dist,
// conserved momemnts int start, int finish, int Np,
double rho,ux,uy,uz,uu; double rlx, double Fx, double Fy,
// non-conserved moments double Fz) {
double f0,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18; // conserved momemnts
int nr1,nr2,nr3,nr4,nr5,nr6,nr7,nr8,nr9,nr10,nr11,nr12,nr13,nr14,nr15,nr16,nr17,nr18; double rho, ux, uy, uz, uu;
// non-conserved moments
double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
f16, f17, f18;
int nr1, nr2, nr3, nr4, nr5, nr6, nr7, nr8, nr9, nr10, nr11, nr12, nr13,
nr14, nr15, nr16, nr17, nr18;
for (int n=start; n<finish; n++){ for (int n = start; n < finish; n++) {
// q=0
f0 = dist[n];
// q=1
nr1 = neighborList[n]; // neighbor 2 ( > 10Np => odd part of dist)
f1 = dist[nr1]; // reading the f1 data into register fq
nr2 = neighborList[n+Np]; // neighbor 1 ( < 10Np => even part of dist) // q=0
f2 = dist[nr2]; // reading the f2 data into register fq f0 = dist[n];
// q=1
nr1 = neighborList[n]; // neighbor 2 ( > 10Np => odd part of dist)
f1 = dist[nr1]; // reading the f1 data into register fq
// q=3 nr2 = neighborList[n + Np]; // neighbor 1 ( < 10Np => even part of dist)
nr3 = neighborList[n+2*Np]; // neighbor 4 f2 = dist[nr2]; // reading the f2 data into register fq
f3 = dist[nr3];
// q = 4 // q=3
nr4 = neighborList[n+3*Np]; // neighbor 3 nr3 = neighborList[n + 2 * Np]; // neighbor 4
f4 = dist[nr4]; f3 = dist[nr3];
// q=5 // q = 4
nr5 = neighborList[n+4*Np]; nr4 = neighborList[n + 3 * Np]; // neighbor 3
f5 = dist[nr5]; f4 = dist[nr4];
// q = 6 // q=5
nr6 = neighborList[n+5*Np]; nr5 = neighborList[n + 4 * Np];
f6 = dist[nr6]; f5 = dist[nr5];
// q=7
nr7 = neighborList[n+6*Np];
f7 = dist[nr7];
// q = 8 // q = 6
nr8 = neighborList[n+7*Np]; nr6 = neighborList[n + 5 * Np];
f8 = dist[nr8]; f6 = dist[nr6];
// q=9 // q=7
nr9 = neighborList[n+8*Np]; nr7 = neighborList[n + 6 * Np];
f9 = dist[nr9]; f7 = dist[nr7];
// q = 10 // q = 8
nr10 = neighborList[n+9*Np]; nr8 = neighborList[n + 7 * Np];
f10 = dist[nr10]; f8 = dist[nr8];
// q=11 // q=9
nr11 = neighborList[n+10*Np]; nr9 = neighborList[n + 8 * Np];
f11 = dist[nr11]; f9 = dist[nr9];
// q=12 // q = 10
nr12 = neighborList[n+11*Np]; nr10 = neighborList[n + 9 * Np];
f12 = dist[nr12]; f10 = dist[nr10];
// q=13 // q=11
nr13 = neighborList[n+12*Np]; nr11 = neighborList[n + 10 * Np];
f13 = dist[nr13]; f11 = dist[nr11];
// q=14 // q=12
nr14 = neighborList[n+13*Np]; nr12 = neighborList[n + 11 * Np];
f14 = dist[nr14]; f12 = dist[nr12];
// q=15 // q=13
nr15 = neighborList[n+14*Np]; nr13 = neighborList[n + 12 * Np];
f15 = dist[nr15]; f13 = dist[nr13];
// q=16 // q=14
nr16 = neighborList[n+15*Np]; nr14 = neighborList[n + 13 * Np];
f16 = dist[nr16]; f14 = dist[nr14];
// q=17 // q=15
//fq = dist[18*Np+n]; nr15 = neighborList[n + 14 * Np];
nr17 = neighborList[n+16*Np]; f15 = dist[nr15];
f17 = dist[nr17];
// q=18 // q=16
nr18 = neighborList[n+17*Np]; nr16 = neighborList[n + 15 * Np];
f18 = dist[nr18]; f16 = dist[nr16];
rho = f0+f2+f1+f4+f3+f6+f5+f8+f7+f10+f9+f12+f11+f14+f13+f16+f15+f18+f17; // q=17
ux = f1-f2+f7-f8+f9-f10+f11-f12+f13-f14; //fq = dist[18*Np+n];
uy = f3-f4+f7-f8-f9+f10+f15-f16+f17-f18; nr17 = neighborList[n + 16 * Np];
uz = f5-f6+f11-f12-f13+f14+f15-f16-f17+f18; f17 = dist[nr17];
uu = 1.5*(ux*ux+uy*uy+uz*uz);
// q=0 // q=18
dist[n] = f0*(1.0-rlx)+rlx*0.3333333333333333*(1.0-uu); nr18 = neighborList[n + 17 * Np];
f18 = dist[nr18];
// q = 1 rho = f0 + f2 + f1 + f4 + f3 + f6 + f5 + f8 + f7 + f10 + f9 + f12 +
dist[nr2] = f1*(1.0-rlx) + rlx*0.05555555555555555*(rho + 3.0*ux + 4.5*ux*ux - uu) + 0.16666666*Fx; f11 + f14 + f13 + f16 + f15 + f18 + f17;
ux = f1 - f2 + f7 - f8 + f9 - f10 + f11 - f12 + f13 - f14;
uy = f3 - f4 + f7 - f8 - f9 + f10 + f15 - f16 + f17 - f18;
uz = f5 - f6 + f11 - f12 - f13 + f14 + f15 - f16 - f17 + f18;
uu = 1.5 * (ux * ux + uy * uy + uz * uz);
// q=2 // q=0
dist[nr1] = f2*(1.0-rlx) + rlx*0.05555555555555555*(rho - 3.0*ux + 4.5*ux*ux - uu)- 0.16666666*Fx; dist[n] = f0 * (1.0 - rlx) + rlx * 0.3333333333333333 * (1.0 - uu);
// q = 3 // q = 1
dist[nr4] = f3*(1.0-rlx) + dist[nr2] =
rlx*0.05555555555555555*(rho + 3.0*uy + 4.5*uy*uy - uu) + 0.16666666*Fy; f1 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho + 3.0 * ux + 4.5 * ux * ux - uu) +
0.16666666 * Fx;
// q = 4 // q=2
dist[nr3] = f4*(1.0-rlx) + dist[nr1] =
rlx*0.05555555555555555*(rho - 3.0*uy + 4.5*uy*uy - uu)- 0.16666666*Fy; f2 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho - 3.0 * ux + 4.5 * ux * ux - uu) -
0.16666666 * Fx;
// q = 5 // q = 3
dist[nr6] = f5*(1.0-rlx) + dist[nr4] =
rlx*0.05555555555555555*(rho + 3.0*uz + 4.5*uz*uz - uu) + 0.16666666*Fz; f3 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho + 3.0 * uy + 4.5 * uy * uy - uu) +
0.16666666 * Fy;
// q = 6 // q = 4
dist[nr5] = f6*(1.0-rlx) + dist[nr3] =
rlx*0.05555555555555555*(rho - 3.0*uz + 4.5*uz*uz - uu) - 0.16666666*Fz; f4 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho - 3.0 * uy + 4.5 * uy * uy - uu) -
0.16666666 * Fy;
// q = 7 // q = 5
dist[nr8] = f7*(1.0-rlx) + dist[nr6] =
rlx*0.02777777777777778*(rho + 3.0*(ux+uy) + 4.5*(ux+uy)*(ux+uy) - uu) + 0.08333333333*(Fx+Fy); f5 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho + 3.0 * uz + 4.5 * uz * uz - uu) +
0.16666666 * Fz;
// q = 8 // q = 6
dist[nr7] = f8*(1.0-rlx) + dist[nr5] =
rlx*0.02777777777777778*(rho - 3.0*(ux+uy) + 4.5*(ux+uy)*(ux+uy) - uu) - 0.08333333333*(Fx+Fy); f6 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho - 3.0 * uz + 4.5 * uz * uz - uu) -
0.16666666 * Fz;
// q = 9 // q = 7
dist[nr10] = f9*(1.0-rlx) + dist[nr8] =
rlx*0.02777777777777778*(rho + 3.0*(ux-uy) + 4.5*(ux-uy)*(ux-uy) - uu) + 0.08333333333*(Fx-Fy); f7 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux + uy) + 4.5 * (ux + uy) * (ux + uy) - uu) +
0.08333333333 * (Fx + Fy);
// q = 10 // q = 8
dist[nr9] = f10*(1.0-rlx) + dist[nr7] =
rlx*0.02777777777777778*(rho - 3.0*(ux-uy) + 4.5*(ux-uy)*(ux-uy) - uu) - 0.08333333333*(Fx-Fy); f8 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux + uy) + 4.5 * (ux + uy) * (ux + uy) - uu) -
0.08333333333 * (Fx + Fy);
// q = 11 // q = 9
dist[nr12] = f11*(1.0-rlx) + dist[nr10] =
rlx*0.02777777777777778*(rho + 3.0*(ux+uz) + 4.5*(ux+uz)*(ux+uz) - uu) + 0.08333333333*(Fx+Fz); f9 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux - uy) + 4.5 * (ux - uy) * (ux - uy) - uu) +
0.08333333333 * (Fx - Fy);
// q = 12 // q = 10
dist[nr11] = f12*(1.0-rlx) + dist[nr9] =
rlx*0.02777777777777778*(rho - 3.0*(ux+uz) + 4.5*(ux+uz)*(ux+uz) - uu) - 0.08333333333*(Fx+Fz); f10 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux - uy) + 4.5 * (ux - uy) * (ux - uy) - uu) -
0.08333333333 * (Fx - Fy);
// q = 13 // q = 11
dist[nr14] = f13*(1.0-rlx) + dist[nr12] =
rlx*0.02777777777777778*(rho + 3.0*(ux-uz) + 4.5*(ux-uz)*(ux-uz) - uu) + 0.08333333333*(Fx-Fz); f11 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux + uz) + 4.5 * (ux + uz) * (ux + uz) - uu) +
0.08333333333 * (Fx + Fz);
// q= 14 // q = 12
dist[nr13] = f14*(1.0-rlx) + dist[nr11] =
rlx*0.02777777777777778*(rho - 3.0*(ux-uz) + 4.5*(ux-uz)*(ux-uz) - uu)- 0.08333333333*(Fx-Fz); f12 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux + uz) + 4.5 * (ux + uz) * (ux + uz) - uu) -
0.08333333333 * (Fx + Fz);
// q = 15 // q = 13
dist[nr16] = f15*(1.0-rlx) + dist[nr14] =
rlx*0.02777777777777778*(rho + 3.0*(uy+uz) + 4.5*(uy+uz)*(uy+uz) - uu) + 0.08333333333*(Fy+Fz); f13 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux - uz) + 4.5 * (ux - uz) * (ux - uz) - uu) +
0.08333333333 * (Fx - Fz);
// q = 16 // q= 14
dist[nr15] = f16*(1.0-rlx) + dist[nr13] =
rlx*0.02777777777777778*(rho - 3.0*(uy+uz) + 4.5*(uy+uz)*(uy+uz) - uu) - 0.08333333333*(Fy+Fz); f14 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux - uz) + 4.5 * (ux - uz) * (ux - uz) - uu) -
0.08333333333 * (Fx - Fz);
// q = 17 // q = 15
dist[nr18] = f17*(1.0-rlx) + dist[nr16] =
rlx*0.02777777777777778*(rho + 3.0*(uy-uz) + 4.5*(uy-uz)*(uy-uz) - uu) + 0.08333333333*(Fy-Fz); f15 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (uy + uz) + 4.5 * (uy + uz) * (uy + uz) - uu) +
0.08333333333 * (Fy + Fz);
// q = 18 // q = 16
dist[nr17] = f18*(1.0-rlx) + dist[nr15] =
rlx*0.02777777777777778*(rho - 3.0*(uy-uz) + 4.5*(uy-uz)*(uy-uz) - uu) - 0.08333333333*(Fy-Fz); f16 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (uy + uz) + 4.5 * (uy + uz) * (uy + uz) - uu) -
0.08333333333 * (Fy + Fz);
} // q = 17
dist[nr18] =
f17 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (uy - uz) + 4.5 * (uy - uz) * (uy - uz) - uu) +
0.08333333333 * (Fy - Fz);
// q = 18
dist[nr17] =
f18 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (uy - uz) + 4.5 * (uy - uz) * (uy - uz) - uu) -
0.08333333333 * (Fy - Fz);
}
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -16,205 +16,211 @@
*/ */
// CPU Functions for D3Q7 Lattice Boltzmann Methods // CPU Functions for D3Q7 Lattice Boltzmann Methods
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) {
// Pack distribution q into the send buffer for the listed lattice sites //....................................................................................
// dist may be even or odd distributions stored by stream layout // Pack distribution q into the send buffer for the listed lattice sites
//.................................................................................... // dist may be even or odd distributions stored by stream layout
int idx,n; //....................................................................................
for (idx=0; idx<count; idx++){ int idx, n;
n = list[idx]; for (idx = 0; idx < count; idx++) {
sendbuf[idx] = Data[n]; n = list[idx];
} sendbuf[idx] = Data[n];
}
} }
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) {
// Pack distribution q into the send buffer for the listed lattice sites //....................................................................................
// dist may be even or odd distributions stored by stream layout // Pack distribution q into the send buffer for the listed lattice sites
//.................................................................................... // dist may be even or odd distributions stored by stream layout
int idx,n; //....................................................................................
for (idx=0; idx<count; idx++){ int idx, n;
n = list[idx]; for (idx = 0; idx < count; idx++) {
Data[n] = recvbuf[idx]; n = list[idx];
} Data[n] = recvbuf[idx];
}
} }
extern "C" void ScaLBL_D3Q7_Unpack(int q, int *list, int start, int count, extern "C" void ScaLBL_D3Q7_Unpack(int q, int *list, int start, int count,
double *recvbuf, double *dist, int N){ double *recvbuf, double *dist, int N) {
//.................................................................................... //....................................................................................
// Unack distribution from the recv buffer // Unack distribution from the recv buffer
// Distribution q matche Cqx, Cqy, Cqz // Distribution q matche Cqx, Cqy, Cqz
// swap rule means that the distributions in recvbuf are OPPOSITE of q // swap rule means that the distributions in recvbuf are OPPOSITE of q
// dist may be even or odd distributions stored by stream layout // dist may be even or odd distributions stored by stream layout
//.................................................................................... //....................................................................................
int n,idx; int n, idx;
for (idx=0; idx<count; idx++){ for (idx = 0; idx < count; idx++) {
// Get the value from the list -- note that n is the index is from the send (non-local) process // Get the value from the list -- note that n is the index is from the send (non-local) process
n = list[idx]; n = list[idx];
// unpack the distribution to the proper location // unpack the distribution to the proper location
if (!(n<0)) dist[q*N+n] = recvbuf[start+idx]; if (!(n < 0))
//dist[q*N+n] = recvbuf[start+idx]; dist[q * N + n] = recvbuf[start + idx];
//dist[q*N+n] = recvbuf[start+idx];
} }
} }
extern "C" void ScaLBL_PackDenD3Q7(int *list, int count, double *sendbuf,
extern "C" void ScaLBL_PackDenD3Q7(int *list, int count, double *sendbuf, int number, double *Data, int N){ int number, double *Data, int N) {
//.................................................................................... //....................................................................................
// Pack distribution into the send buffer for the listed lattice sites // Pack distribution into the send buffer for the listed lattice sites
//.................................................................................... //....................................................................................
int idx,n,component; int idx, n, component;
for (idx=0; idx<count; idx++){ for (idx = 0; idx < count; idx++) {
for (component=0; component<number; component++){ for (component = 0; component < number; component++) {
n = list[idx]; n = list[idx];
sendbuf[idx*number+component] = Data[number*n+component]; sendbuf[idx * number + component] = Data[number * n + component];
Data[number*n+component] = 0.0; // Set the data value to zero once it's in the buffer! Data[number * n + component] =
} 0.0; // Set the data value to zero once it's in the buffer!
} }
}
} }
extern "C" void ScaLBL_UnpackDenD3Q7(int *list, int count, double *recvbuf,
extern "C" void ScaLBL_UnpackDenD3Q7(int *list, int count, double *recvbuf, int number, double *Data, int N){ int number, double *Data, int N) {
//.................................................................................... //....................................................................................
// Unack distribution from the recv buffer // Unack distribution from the recv buffer
// Sum to the existing density value // Sum to the existing density value
//.................................................................................... //....................................................................................
int idx,n,component; int idx, n, component;
for (idx=0; idx<count; idx++){ for (idx = 0; idx < count; idx++) {
for (component=0; component<number; component++){ for (component = 0; component < number; component++) {
n = list[idx]; n = list[idx];
Data[number*n+component] += recvbuf[idx*number+component]; Data[number * n + component] += recvbuf[idx * number + component];
} }
} }
} }
extern "C" void ScaLBL_D3Q7_Reflection_BC_z(int *list, double *dist, int count, int Np){ extern "C" void ScaLBL_D3Q7_Reflection_BC_z(int *list, double *dist, int count,
int n; int Np) {
for (int idx=0; idx<count; idx++){ int n;
n = list[idx]; for (int idx = 0; idx < count; idx++) {
double f5 = 0.222222222222222222222222 - dist[6*Np+n]; n = list[idx];
dist[6*Np+n] = f5; double f5 = 0.222222222222222222222222 - dist[6 * Np + n];
} dist[6 * Np + n] = f5;
}
} }
extern "C" void ScaLBL_D3Q7_Reflection_BC_Z(int *list, double *dist, int count, int Np){ extern "C" void ScaLBL_D3Q7_Reflection_BC_Z(int *list, double *dist, int count,
int n; int Np) {
for (int idx=0; idx<count; idx++){ int n;
n = list[idx]; for (int idx = 0; idx < count; idx++) {
double f6 = 0.222222222222222222222222 - dist[5*Np+n]; n = list[idx];
dist[5*Np+n] = f6; double f6 = 0.222222222222222222222222 - dist[5 * Np + n];
} dist[5 * Np + n] = f6;
}
} }
extern "C" void ScaLBL_D3Q7_Init(char *ID, double *f_even, double *f_odd, double *Den, int Nx, int Ny, int Nz) extern "C" void ScaLBL_D3Q7_Init(char *ID, double *f_even, double *f_odd,
{ double *Den, int Nx, int Ny, int Nz) {
int n,N; int n, N;
N = Nx*Ny*Nz; N = Nx * Ny * Nz;
double value; double value;
for (n=0; n<N; n++){ for (n = 0; n < N; n++) {
if (ID[n] > 0){ if (ID[n] > 0) {
value = Den[n]; value = Den[n];
f_even[n] = 0.3333333333333333*value; f_even[n] = 0.3333333333333333 * value;
f_odd[n] = 0.1111111111111111*value; //double(100*n)+1.f; f_odd[n] = 0.1111111111111111 * value; //double(100*n)+1.f;
f_even[N+n] = 0.1111111111111111*value; //double(100*n)+2.f; f_even[N + n] = 0.1111111111111111 * value; //double(100*n)+2.f;
f_odd[N+n] = 0.1111111111111111*value; //double(100*n)+3.f; f_odd[N + n] = 0.1111111111111111 * value; //double(100*n)+3.f;
f_even[2*N+n] = 0.1111111111111111*value; //double(100*n)+4.f; f_even[2 * N + n] = 0.1111111111111111 * value; //double(100*n)+4.f;
f_odd[2*N+n] = 0.1111111111111111*value; //double(100*n)+5.f; f_odd[2 * N + n] = 0.1111111111111111 * value; //double(100*n)+5.f;
f_even[3*N+n] = 0.1111111111111111*value; //double(100*n)+6.f; f_even[3 * N + n] = 0.1111111111111111 * value; //double(100*n)+6.f;
} } else {
else{ for (int q = 0; q < 3; q++) {
for(int q=0; q<3; q++){ f_even[q * N + n] = -1.0;
f_even[q*N+n] = -1.0; f_odd[q * N + n] = -1.0;
f_odd[q*N+n] = -1.0; }
} f_even[3 * N + n] = -1.0;
f_even[3*N+n] = -1.0; }
} }
}
} }
//************************************************************************* //*************************************************************************
extern "C" void ScaLBL_D3Q7_Swap(char *ID, double *disteven, double *distodd, int Nx, int Ny, int Nz) extern "C" void ScaLBL_D3Q7_Swap(char *ID, double *disteven, double *distodd,
{ int Nx, int Ny, int Nz) {
int i,j,k,n,nn,N; int i, j, k, n, nn, N;
// distributions // distributions
double f1,f2,f3,f4,f5,f6; double f1, f2, f3, f4, f5, f6;
N = Nx*Ny*Nz; N = Nx * Ny * Nz;
for (n=0; n<N; n++){ for (n = 0; n < N; n++) {
//.......Back out the 3-D indices for node n.............. //.......Back out the 3-D indices for node n..............
k = n/(Nx*Ny); k = n / (Nx * Ny);
j = (n-Nx*Ny*k)/Nx; j = (n - Nx * Ny * k) / Nx;
i = n-Nx*Ny*k-Nz*j; i = n - Nx * Ny * k - Nz * j;
if (ID[n] > 0){ if (ID[n] > 0) {
//........................................................................ //........................................................................
// Retrieve even distributions from the local node (swap convention) // Retrieve even distributions from the local node (swap convention)
// f0 = disteven[n]; // Does not particupate in streaming // f0 = disteven[n]; // Does not particupate in streaming
f1 = distodd[n]; f1 = distodd[n];
f3 = distodd[N+n]; f3 = distodd[N + n];
f5 = distodd[2*N+n]; f5 = distodd[2 * N + n];
//........................................................................ //........................................................................
//........................................................................ //........................................................................
// Retrieve odd distributions from neighboring nodes (swap convention) // Retrieve odd distributions from neighboring nodes (swap convention)
//........................................................................ //........................................................................
nn = n+1; // neighbor index (pull convention) nn = n + 1; // neighbor index (pull convention)
if (!(i+1<Nx)) nn -= Nx; // periodic BC along the x-boundary if (!(i + 1 < Nx))
//if (i+1<Nx){ nn -= Nx; // periodic BC along the x-boundary
f2 = disteven[N+nn]; // pull neighbor for distribution 2 //if (i+1<Nx){
if (!(f2 < 0.0)){ f2 = disteven[N + nn]; // pull neighbor for distribution 2
distodd[n] = f2; if (!(f2 < 0.0)) {
disteven[N+nn] = f1; distodd[n] = f2;
} disteven[N + nn] = f1;
//} }
//........................................................................ //}
nn = n+Nx; // neighbor index (pull convention) //........................................................................
if (!(j+1<Ny)) nn -= Nx*Ny; // Perioidic BC along the y-boundary nn = n + Nx; // neighbor index (pull convention)
//if (j+1<Ny){ if (!(j + 1 < Ny))
f4 = disteven[2*N+nn]; // pull neighbor for distribution 4 nn -= Nx * Ny; // Perioidic BC along the y-boundary
if (!(f4 < 0.0)){ //if (j+1<Ny){
distodd[N+n] = f4; f4 = disteven[2 * N + nn]; // pull neighbor for distribution 4
disteven[2*N+nn] = f3; if (!(f4 < 0.0)) {
// } distodd[N + n] = f4;
} disteven[2 * N + nn] = f3;
//........................................................................ // }
nn = n+Nx*Ny; // neighbor index (pull convention) }
if (!(k+1<Nz)) nn -= Nx*Ny*Nz; // Perioidic BC along the z-boundary //........................................................................
//if (k+1<Nz){ nn = n + Nx * Ny; // neighbor index (pull convention)
f6 = disteven[3*N+nn]; // pull neighbor for distribution 6 if (!(k + 1 < Nz))
if (!(f6 < 0.0)){ nn -= Nx * Ny * Nz; // Perioidic BC along the z-boundary
distodd[2*N+n] = f6; //if (k+1<Nz){
disteven[3*N+nn] = f5; f6 = disteven[3 * N + nn]; // pull neighbor for distribution 6
// } if (!(f6 < 0.0)) {
} distodd[2 * N + n] = f6;
} disteven[3 * N + nn] = f5;
} // }
}
}
}
} }
//************************************************************************* //*************************************************************************
extern "C" void ScaLBL_D3Q7_Density(char *ID, double *disteven, double *distodd, double *Den, extern "C" void ScaLBL_D3Q7_Density(char *ID, double *disteven, double *distodd,
int Nx, int Ny, int Nz) double *Den, int Nx, int Ny, int Nz) {
{ char id;
char id; int n;
int n; double f0, f1, f2, f3, f4, f5, f6;
double f0,f1,f2,f3,f4,f5,f6; int N = Nx * Ny * Nz;
int N = Nx*Ny*Nz;
for (n = 0; n < N; n++) {
for (n=0; n<N; n++){ id = ID[n];
id = ID[n]; if (id > 0) {
if (id > 0 ){ // Read the distributions
// Read the distributions f0 = disteven[n];
f0 = disteven[n]; f2 = disteven[N + n];
f2 = disteven[N+n]; f4 = disteven[2 * N + n];
f4 = disteven[2*N+n]; f6 = disteven[3 * N + n];
f6 = disteven[3*N+n]; f1 = distodd[n];
f1 = distodd[n]; f3 = distodd[N + n];
f3 = distodd[N+n]; f5 = distodd[2 * N + n];
f5 = distodd[2*N+n]; // Compute the density
// Compute the density Den[n] = f0 + f1 + f2 + f3 + f4 + f5 + f6;
Den[n] = f0+f1+f2+f3+f4+f5+f6; }
} }
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -19,50 +19,47 @@
#include <string.h> #include <string.h>
#include <mm_malloc.h> #include <mm_malloc.h>
extern "C" int ScaLBL_SetDevice(int rank){ extern "C" int ScaLBL_SetDevice(int rank) { return 0; }
return 0;
extern "C" void ScaLBL_AllocateZeroCopy(void **address, size_t size) {
//cudaMalloc(address,size);
(*address) = _mm_malloc(size, 64);
memset(*address, 0, size);
if (*address == NULL) {
printf("Memory allocation failed! \n");
}
} }
extern "C" void ScaLBL_AllocateZeroCopy(void** address, size_t size){ extern "C" void ScaLBL_AllocateDeviceMemory(void **address, size_t size) {
//cudaMalloc(address,size); //cudaMalloc(address,size);
(*address) = _mm_malloc(size,64); (*address) = _mm_malloc(size, 64);
memset(*address,0,size); memset(*address, 0, size);
if (*address==NULL){ if (*address == NULL) {
printf("Memory allocation failed! \n"); printf("Memory allocation failed! \n");
} }
} }
extern "C" void ScaLBL_AllocateDeviceMemory(void** address, size_t size){ extern "C" void ScaLBL_FreeDeviceMemory(void *pointer) { _mm_free(pointer); }
//cudaMalloc(address,size);
(*address) = _mm_malloc(size,64); extern "C" void ScaLBL_CopyToDevice(void *dest, const void *source,
memset(*address,0,size); size_t size) {
// cudaMemcpy(dest,source,size,cudaMemcpyHostToDevice);
if (*address==NULL){ memcpy(dest, source, size);
printf("Memory allocation failed! \n");
}
} }
extern "C" void ScaLBL_FreeDeviceMemory(void* pointer){ extern "C" void ScaLBL_CopyToHost(void *dest, const void *source, size_t size) {
_mm_free(pointer); // cudaMemcpy(dest,source,size,cudaMemcpyDeviceToHost);
memcpy(dest, source, size);
} }
extern "C" void ScaLBL_CopyToDevice(void* dest, const void* source, size_t size){ extern "C" void ScaLBL_CopyToZeroCopy(void *dest, const void *source,
// cudaMemcpy(dest,source,size,cudaMemcpyHostToDevice); size_t size) {
memcpy(dest, source, size); // cudaMemcpy(dest,source,size,cudaMemcpyDeviceToHost);
memcpy(dest, source, size);
} }
extern "C" void ScaLBL_DeviceBarrier() {
extern "C" void ScaLBL_CopyToHost(void* dest, const void* source, size_t size){ // cudaDeviceSynchronize();
// cudaMemcpy(dest,source,size,cudaMemcpyDeviceToHost);
memcpy(dest, source, size);
}
extern "C" void ScaLBL_CopyToZeroCopy(void* dest, const void* source, size_t size){
// cudaMemcpy(dest,source,size,cudaMemcpyDeviceToHost);
memcpy(dest, source, size);
}
extern "C" void ScaLBL_DeviceBarrier(){
// cudaDeviceSynchronize();
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,284 +1,308 @@
#include <stdio.h> #include <stdio.h>
extern "C" void ScaLBL_D3Q7_AAodd_IonConcentration(int *neighborList, double *dist, double *Den, int start, int finish, int Np){ extern "C" void ScaLBL_D3Q7_AAodd_IonConcentration(int *neighborList,
int n,nread; double *dist, double *Den,
double fq,Ci; int start, int finish,
for (n=start; n<finish; n++){ int Np) {
int n, nread;
double fq, Ci;
for (n = start; n < finish; n++) {
// q=0 // q=0
fq = dist[n]; fq = dist[n];
Ci = fq; Ci = fq;
// q=1 // q=1
nread = neighborList[n]; nread = neighborList[n];
fq = dist[nread]; fq = dist[nread];
Ci += fq; Ci += fq;
// q=2 // q=2
nread = neighborList[n+Np]; nread = neighborList[n + Np];
fq = dist[nread]; fq = dist[nread];
Ci += fq; Ci += fq;
// q=3 // q=3
nread = neighborList[n+2*Np]; nread = neighborList[n + 2 * Np];
fq = dist[nread]; fq = dist[nread];
Ci += fq; Ci += fq;
// q=4 // q=4
nread = neighborList[n+3*Np]; nread = neighborList[n + 3 * Np];
fq = dist[nread]; fq = dist[nread];
Ci += fq; Ci += fq;
// q=5 // q=5
nread = neighborList[n+4*Np]; nread = neighborList[n + 4 * Np];
fq = dist[nread]; fq = dist[nread];
Ci += fq; Ci += fq;
// q=6 // q=6
nread = neighborList[n+5*Np]; nread = neighborList[n + 5 * Np];
fq = dist[nread]; fq = dist[nread];
Ci += fq; Ci += fq;
Den[n]=Ci; Den[n] = Ci;
} }
} }
extern "C" void ScaLBL_D3Q7_AAeven_IonConcentration(double *dist, double *Den, int start, int finish, int Np){ extern "C" void ScaLBL_D3Q7_AAeven_IonConcentration(double *dist, double *Den,
int start, int finish,
int Np) {
int n; int n;
double fq,Ci; double fq, Ci;
for (n=start; n<finish; n++){ for (n = start; n < finish; n++) {
// q=0 // q=0
fq = dist[n]; fq = dist[n];
Ci = fq; Ci = fq;
// q=1
fq = dist[2*Np+n];
Ci += fq;
// q=2 // q=1
fq = dist[1*Np+n]; fq = dist[2 * Np + n];
Ci += fq; Ci += fq;
// q=3 // q=2
fq = dist[4*Np+n]; fq = dist[1 * Np + n];
Ci += fq; Ci += fq;
// q=4 // q=3
fq = dist[3*Np+n]; fq = dist[4 * Np + n];
Ci += fq; Ci += fq;
// q=5 // q=4
fq = dist[6*Np+n]; fq = dist[3 * Np + n];
Ci += fq; Ci += fq;
// q=6 // q=5
fq = dist[5*Np+n]; fq = dist[6 * Np + n];
Ci += fq; Ci += fq;
Den[n]=Ci; // q=6
fq = dist[5 * Np + n];
Ci += fq;
Den[n] = Ci;
} }
} }
extern "C" void ScaLBL_D3Q7_AAodd_Ion(int *neighborList, double *dist, double *Den, double *FluxDiffusive, double *FluxAdvective, double *FluxElectrical, double *Velocity, double *ElectricField, extern "C" void ScaLBL_D3Q7_AAodd_Ion(int *neighborList, double *dist,
double Di, int zi, double rlx, double Vt, int start, int finish, int Np){ double *Den, double *FluxDiffusive,
int n; double *FluxAdvective,
double Ci; double *FluxElectrical, double *Velocity,
double ux,uy,uz; double *ElectricField, double Di, int zi,
double uEPx,uEPy,uEPz;//electrochemical induced velocity double rlx, double Vt, int start,
double Ex,Ey,Ez;//electrical field int finish, int Np) {
double flux_diffusive_x,flux_diffusive_y,flux_diffusive_z; int n;
double f0,f1,f2,f3,f4,f5,f6; double Ci;
int nr1,nr2,nr3,nr4,nr5,nr6; double ux, uy, uz;
double uEPx, uEPy, uEPz; //electrochemical induced velocity
double Ex, Ey, Ez; //electrical field
double flux_diffusive_x, flux_diffusive_y, flux_diffusive_z;
double f0, f1, f2, f3, f4, f5, f6;
int nr1, nr2, nr3, nr4, nr5, nr6;
for (n = start; n < finish; n++) {
for (n=start; n<finish; n++){
//Load data //Load data
Ci=Den[n]; Ci = Den[n];
Ex=ElectricField[n+0*Np]; Ex = ElectricField[n + 0 * Np];
Ey=ElectricField[n+1*Np]; Ey = ElectricField[n + 1 * Np];
Ez=ElectricField[n+2*Np]; Ez = ElectricField[n + 2 * Np];
ux=Velocity[n+0*Np]; ux = Velocity[n + 0 * Np];
uy=Velocity[n+1*Np]; uy = Velocity[n + 1 * Np];
uz=Velocity[n+2*Np]; uz = Velocity[n + 2 * Np];
uEPx=zi*Di/Vt*Ex; uEPx = zi * Di / Vt * Ex;
uEPy=zi*Di/Vt*Ey; uEPy = zi * Di / Vt * Ey;
uEPz=zi*Di/Vt*Ez; uEPz = zi * Di / Vt * Ez;
// q=0 // q=0
f0 = dist[n]; f0 = dist[n];
// q=1 // q=1
nr1 = neighborList[n]; // neighbor 2 ( > 10Np => odd part of dist) nr1 = neighborList[n]; // neighbor 2 ( > 10Np => odd part of dist)
f1 = dist[nr1]; // reading the f1 data into register fq f1 = dist[nr1]; // reading the f1 data into register fq
// q=2 // q=2
nr2 = neighborList[n+Np]; // neighbor 1 ( < 10Np => even part of dist) nr2 = neighborList[n + Np]; // neighbor 1 ( < 10Np => even part of dist)
f2 = dist[nr2]; // reading the f2 data into register fq f2 = dist[nr2]; // reading the f2 data into register fq
// q=3 // q=3
nr3 = neighborList[n+2*Np]; // neighbor 4 nr3 = neighborList[n + 2 * Np]; // neighbor 4
f3 = dist[nr3]; f3 = dist[nr3];
// q=4 // q=4
nr4 = neighborList[n+3*Np]; // neighbor 3 nr4 = neighborList[n + 3 * Np]; // neighbor 3
f4 = dist[nr4]; f4 = dist[nr4];
// q=5 // q=5
nr5 = neighborList[n+4*Np]; nr5 = neighborList[n + 4 * Np];
f5 = dist[nr5]; f5 = dist[nr5];
// q=6 // q=6
nr6 = neighborList[n+5*Np]; nr6 = neighborList[n + 5 * Np];
f6 = dist[nr6]; f6 = dist[nr6];
// compute diffusive flux // compute diffusive flux
flux_diffusive_x = (1.0-0.5*rlx)*((f1-f2)-ux*Ci); flux_diffusive_x = (1.0 - 0.5 * rlx) * ((f1 - f2) - ux * Ci);
flux_diffusive_y = (1.0-0.5*rlx)*((f3-f4)-uy*Ci); flux_diffusive_y = (1.0 - 0.5 * rlx) * ((f3 - f4) - uy * Ci);
flux_diffusive_z = (1.0-0.5*rlx)*((f5-f6)-uz*Ci); flux_diffusive_z = (1.0 - 0.5 * rlx) * ((f5 - f6) - uz * Ci);
FluxDiffusive[n+0*Np] = flux_diffusive_x; FluxDiffusive[n + 0 * Np] = flux_diffusive_x;
FluxDiffusive[n+1*Np] = flux_diffusive_y; FluxDiffusive[n + 1 * Np] = flux_diffusive_y;
FluxDiffusive[n+2*Np] = flux_diffusive_z; FluxDiffusive[n + 2 * Np] = flux_diffusive_z;
FluxAdvective[n+0*Np] = ux*Ci; FluxAdvective[n + 0 * Np] = ux * Ci;
FluxAdvective[n+1*Np] = uy*Ci; FluxAdvective[n + 1 * Np] = uy * Ci;
FluxAdvective[n+2*Np] = uz*Ci; FluxAdvective[n + 2 * Np] = uz * Ci;
FluxElectrical[n+0*Np] = uEPx*Ci; FluxElectrical[n + 0 * Np] = uEPx * Ci;
FluxElectrical[n+1*Np] = uEPy*Ci; FluxElectrical[n + 1 * Np] = uEPy * Ci;
FluxElectrical[n+2*Np] = uEPz*Ci; FluxElectrical[n + 2 * Np] = uEPz * Ci;
// q=0
dist[n] = f0*(1.0-rlx)+rlx*0.25*Ci;
// q = 1 // q=0
dist[nr2] = f1*(1.0-rlx) + rlx*0.125*Ci*(1.0+4.0*(ux+uEPx)); dist[n] = f0 * (1.0 - rlx) + rlx * 0.25 * Ci;
// q=2 // q = 1
dist[nr1] = f2*(1.0-rlx) + rlx*0.125*Ci*(1.0-4.0*(ux+uEPx)); dist[nr2] =
f1 * (1.0 - rlx) + rlx * 0.125 * Ci * (1.0 + 4.0 * (ux + uEPx));
// q = 3 // q=2
dist[nr4] = f3*(1.0-rlx) + rlx*0.125*Ci*(1.0+4.0*(uy+uEPy)); dist[nr1] =
f2 * (1.0 - rlx) + rlx * 0.125 * Ci * (1.0 - 4.0 * (ux + uEPx));
// q = 4 // q = 3
dist[nr3] = f4*(1.0-rlx) + rlx*0.125*Ci*(1.0-4.0*(uy+uEPy)); dist[nr4] =
f3 * (1.0 - rlx) + rlx * 0.125 * Ci * (1.0 + 4.0 * (uy + uEPy));
// q = 5 // q = 4
dist[nr6] = f5*(1.0-rlx) + rlx*0.125*Ci*(1.0+4.0*(uz+uEPz)); dist[nr3] =
f4 * (1.0 - rlx) + rlx * 0.125 * Ci * (1.0 - 4.0 * (uy + uEPy));
// q = 6 // q = 5
dist[nr5] = f6*(1.0-rlx) + rlx*0.125*Ci*(1.0-4.0*(uz+uEPz)); dist[nr6] =
f5 * (1.0 - rlx) + rlx * 0.125 * Ci * (1.0 + 4.0 * (uz + uEPz));
}
// q = 6
dist[nr5] =
f6 * (1.0 - rlx) + rlx * 0.125 * Ci * (1.0 - 4.0 * (uz + uEPz));
}
} }
extern "C" void ScaLBL_D3Q7_AAeven_Ion(double *dist, double *Den, double *FluxDiffusive, double *FluxAdvective, double *FluxElectrical, double *Velocity, double *ElectricField, extern "C" void ScaLBL_D3Q7_AAeven_Ion(
double Di, int zi, double rlx, double Vt, int start, int finish, int Np){ double *dist, double *Den, double *FluxDiffusive, double *FluxAdvective,
int n; double *FluxElectrical, double *Velocity, double *ElectricField, double Di,
double Ci; int zi, double rlx, double Vt, int start, int finish, int Np) {
double ux,uy,uz; int n;
double uEPx,uEPy,uEPz;//electrochemical induced velocity double Ci;
double Ex,Ey,Ez;//electrical field double ux, uy, uz;
double flux_diffusive_x,flux_diffusive_y,flux_diffusive_z; double uEPx, uEPy, uEPz; //electrochemical induced velocity
double f0,f1,f2,f3,f4,f5,f6; double Ex, Ey, Ez; //electrical field
double flux_diffusive_x, flux_diffusive_y, flux_diffusive_z;
double f0, f1, f2, f3, f4, f5, f6;
for (n = start; n < finish; n++) {
for (n=start; n<finish; n++){
//Load data //Load data
Ci=Den[n]; Ci = Den[n];
Ex=ElectricField[n+0*Np]; Ex = ElectricField[n + 0 * Np];
Ey=ElectricField[n+1*Np]; Ey = ElectricField[n + 1 * Np];
Ez=ElectricField[n+2*Np]; Ez = ElectricField[n + 2 * Np];
ux=Velocity[n+0*Np]; ux = Velocity[n + 0 * Np];
uy=Velocity[n+1*Np]; uy = Velocity[n + 1 * Np];
uz=Velocity[n+2*Np]; uz = Velocity[n + 2 * Np];
uEPx=zi*Di/Vt*Ex; uEPx = zi * Di / Vt * Ex;
uEPy=zi*Di/Vt*Ey; uEPy = zi * Di / Vt * Ey;
uEPz=zi*Di/Vt*Ez; uEPz = zi * Di / Vt * Ez;
f0 = dist[n];
f1 = dist[2 * Np + n];
f2 = dist[1 * Np + n];
f3 = dist[4 * Np + n];
f4 = dist[3 * Np + n];
f5 = dist[6 * Np + n];
f6 = dist[5 * Np + n];
f0 = dist[n];
f1 = dist[2*Np+n];
f2 = dist[1*Np+n];
f3 = dist[4*Np+n];
f4 = dist[3*Np+n];
f5 = dist[6*Np+n];
f6 = dist[5*Np+n];
// compute diffusive flux // compute diffusive flux
flux_diffusive_x = (1.0-0.5*rlx)*((f1-f2)-ux*Ci); flux_diffusive_x = (1.0 - 0.5 * rlx) * ((f1 - f2) - ux * Ci);
flux_diffusive_y = (1.0-0.5*rlx)*((f3-f4)-uy*Ci); flux_diffusive_y = (1.0 - 0.5 * rlx) * ((f3 - f4) - uy * Ci);
flux_diffusive_z = (1.0-0.5*rlx)*((f5-f6)-uz*Ci); flux_diffusive_z = (1.0 - 0.5 * rlx) * ((f5 - f6) - uz * Ci);
FluxDiffusive[n+0*Np] = flux_diffusive_x; FluxDiffusive[n + 0 * Np] = flux_diffusive_x;
FluxDiffusive[n+1*Np] = flux_diffusive_y; FluxDiffusive[n + 1 * Np] = flux_diffusive_y;
FluxDiffusive[n+2*Np] = flux_diffusive_z; FluxDiffusive[n + 2 * Np] = flux_diffusive_z;
FluxAdvective[n+0*Np] = ux*Ci; FluxAdvective[n + 0 * Np] = ux * Ci;
FluxAdvective[n+1*Np] = uy*Ci; FluxAdvective[n + 1 * Np] = uy * Ci;
FluxAdvective[n+2*Np] = uz*Ci; FluxAdvective[n + 2 * Np] = uz * Ci;
FluxElectrical[n+0*Np] = uEPx*Ci; FluxElectrical[n + 0 * Np] = uEPx * Ci;
FluxElectrical[n+1*Np] = uEPy*Ci; FluxElectrical[n + 1 * Np] = uEPy * Ci;
FluxElectrical[n+2*Np] = uEPz*Ci; FluxElectrical[n + 2 * Np] = uEPz * Ci;
// q=0 // q=0
dist[n] = f0*(1.0-rlx)+rlx*0.25*Ci; dist[n] = f0 * (1.0 - rlx) + rlx * 0.25 * Ci;
// q = 1 // q = 1
dist[1*Np+n] = f1*(1.0-rlx) + rlx*0.125*Ci*(1.0+4.0*(ux+uEPx)); dist[1 * Np + n] =
f1 * (1.0 - rlx) + rlx * 0.125 * Ci * (1.0 + 4.0 * (ux + uEPx));
// q=2 // q=2
dist[2*Np+n] = f2*(1.0-rlx) + rlx*0.125*Ci*(1.0-4.0*(ux+uEPx)); dist[2 * Np + n] =
f2 * (1.0 - rlx) + rlx * 0.125 * Ci * (1.0 - 4.0 * (ux + uEPx));
// q = 3 // q = 3
dist[3*Np+n] = f3*(1.0-rlx) + rlx*0.125*Ci*(1.0+4.0*(uy+uEPy)); dist[3 * Np + n] =
f3 * (1.0 - rlx) + rlx * 0.125 * Ci * (1.0 + 4.0 * (uy + uEPy));
// q = 4 // q = 4
dist[4*Np+n] = f4*(1.0-rlx) + rlx*0.125*Ci*(1.0-4.0*(uy+uEPy)); dist[4 * Np + n] =
f4 * (1.0 - rlx) + rlx * 0.125 * Ci * (1.0 - 4.0 * (uy + uEPy));
// q = 5 // q = 5
dist[5*Np+n] = f5*(1.0-rlx) + rlx*0.125*Ci*(1.0+4.0*(uz+uEPz)); dist[5 * Np + n] =
f5 * (1.0 - rlx) + rlx * 0.125 * Ci * (1.0 + 4.0 * (uz + uEPz));
// q = 6 // q = 6
dist[6*Np+n] = f6*(1.0-rlx) + rlx*0.125*Ci*(1.0-4.0*(uz+uEPz)); dist[6 * Np + n] =
f6 * (1.0 - rlx) + rlx * 0.125 * Ci * (1.0 - 4.0 * (uz + uEPz));
}
}
} }
extern "C" void ScaLBL_D3Q7_Ion_Init(double *dist, double *Den, double DenInit, int Np) extern "C" void ScaLBL_D3Q7_Ion_Init(double *dist, double *Den, double DenInit,
{ int Np) {
int n; int n;
for (n=0; n<Np; n++){ for (n = 0; n < Np; n++) {
dist[0*Np+n] = 0.25*DenInit; dist[0 * Np + n] = 0.25 * DenInit;
dist[1*Np+n] = 0.125*DenInit; dist[1 * Np + n] = 0.125 * DenInit;
dist[2*Np+n] = 0.125*DenInit; dist[2 * Np + n] = 0.125 * DenInit;
dist[3*Np+n] = 0.125*DenInit; dist[3 * Np + n] = 0.125 * DenInit;
dist[4*Np+n] = 0.125*DenInit; dist[4 * Np + n] = 0.125 * DenInit;
dist[5*Np+n] = 0.125*DenInit; dist[5 * Np + n] = 0.125 * DenInit;
dist[6*Np+n] = 0.125*DenInit; dist[6 * Np + n] = 0.125 * DenInit;
Den[n] = DenInit; Den[n] = DenInit;
}
}
extern "C" void ScaLBL_D3Q7_Ion_Init_FromFile(double *dist, double *Den, int Np)
{
int n;
double DenInit;
for (n=0; n<Np; n++){
DenInit = Den[n];
dist[0*Np+n] = 0.25*DenInit;
dist[1*Np+n] = 0.125*DenInit;
dist[2*Np+n] = 0.125*DenInit;
dist[3*Np+n] = 0.125*DenInit;
dist[4*Np+n] = 0.125*DenInit;
dist[5*Np+n] = 0.125*DenInit;
dist[6*Np+n] = 0.125*DenInit;
}
}
extern "C" void ScaLBL_D3Q7_Ion_ChargeDensity(double *Den, double *ChargeDensity, int IonValence, int ion_component, int start, int finish, int Np){
int n;
double Ci;//ion concentration of species i
double CD;//charge density
double CD_tmp;
double F = 96485.0;//Faraday's constant; unit[C/mol]; F=e*Na, where Na is the Avogadro constant
for (n=start; n<finish; n++){
Ci = Den[n+ion_component*Np];
CD = ChargeDensity[n];
CD_tmp = F*IonValence*Ci;
ChargeDensity[n] = CD*(ion_component>0) + CD_tmp;
} }
} }
extern "C" void ScaLBL_D3Q7_Ion_Init_FromFile(double *dist, double *Den,
int Np) {
int n;
double DenInit;
for (n = 0; n < Np; n++) {
DenInit = Den[n];
dist[0 * Np + n] = 0.25 * DenInit;
dist[1 * Np + n] = 0.125 * DenInit;
dist[2 * Np + n] = 0.125 * DenInit;
dist[3 * Np + n] = 0.125 * DenInit;
dist[4 * Np + n] = 0.125 * DenInit;
dist[5 * Np + n] = 0.125 * DenInit;
dist[6 * Np + n] = 0.125 * DenInit;
}
}
extern "C" void ScaLBL_D3Q7_Ion_ChargeDensity(double *Den,
double *ChargeDensity,
int IonValence, int ion_component,
int start, int finish, int Np) {
int n;
double Ci; //ion concentration of species i
double CD; //charge density
double CD_tmp;
double F =
96485.0; //Faraday's constant; unit[C/mol]; F=e*Na, where Na is the Avogadro constant
for (n = start; n < finish; n++) {
Ci = Den[n + ion_component * Np];
CD = ChargeDensity[n];
CD_tmp = F * IonValence * Ci;
ChargeDensity[n] = CD * (ion_component > 0) + CD_tmp;
}
}

View File

@ -14,279 +14,316 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>. along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/ */
extern "C" void INITIALIZE(char *ID, double *f_even, double *f_odd, int Nx, int Ny, int Nz) extern "C" void INITIALIZE(char *ID, double *f_even, double *f_odd, int Nx,
{ int Ny, int Nz) {
int n,N; int n, N;
N = Nx*Ny*Nz; N = Nx * Ny * Nz;
for (n=0; n<N; n++){ for (n = 0; n < N; n++) {
if (ID[n] > 0){ if (ID[n] > 0) {
f_even[n] = 0.3333333333333333; f_even[n] = 0.3333333333333333;
f_odd[n] = 0.055555555555555555; //double(100*n)+1.f; f_odd[n] = 0.055555555555555555; //double(100*n)+1.f;
f_even[N+n] = 0.055555555555555555; //double(100*n)+2.f; f_even[N + n] = 0.055555555555555555; //double(100*n)+2.f;
f_odd[N+n] = 0.055555555555555555; //double(100*n)+3.f; f_odd[N + n] = 0.055555555555555555; //double(100*n)+3.f;
f_even[2*N+n] = 0.055555555555555555; //double(100*n)+4.f; f_even[2 * N + n] = 0.055555555555555555; //double(100*n)+4.f;
f_odd[2*N+n] = 0.055555555555555555; //double(100*n)+5.f; f_odd[2 * N + n] = 0.055555555555555555; //double(100*n)+5.f;
f_even[3*N+n] = 0.055555555555555555; //double(100*n)+6.f; f_even[3 * N + n] = 0.055555555555555555; //double(100*n)+6.f;
f_odd[3*N+n] = 0.0277777777777778; //double(100*n)+7.f; f_odd[3 * N + n] = 0.0277777777777778; //double(100*n)+7.f;
f_even[4*N+n] = 0.0277777777777778; //double(100*n)+8.f; f_even[4 * N + n] = 0.0277777777777778; //double(100*n)+8.f;
f_odd[4*N+n] = 0.0277777777777778; //double(100*n)+9.f; f_odd[4 * N + n] = 0.0277777777777778; //double(100*n)+9.f;
f_even[5*N+n] = 0.0277777777777778; //double(100*n)+10.f; f_even[5 * N + n] = 0.0277777777777778; //double(100*n)+10.f;
f_odd[5*N+n] = 0.0277777777777778; //double(100*n)+11.f; f_odd[5 * N + n] = 0.0277777777777778; //double(100*n)+11.f;
f_even[6*N+n] = 0.0277777777777778; //double(100*n)+12.f; f_even[6 * N + n] = 0.0277777777777778; //double(100*n)+12.f;
f_odd[6*N+n] = 0.0277777777777778; //double(100*n)+13.f; f_odd[6 * N + n] = 0.0277777777777778; //double(100*n)+13.f;
f_even[7*N+n] = 0.0277777777777778; //double(100*n)+14.f; f_even[7 * N + n] = 0.0277777777777778; //double(100*n)+14.f;
f_odd[7*N+n] = 0.0277777777777778; //double(100*n)+15.f; f_odd[7 * N + n] = 0.0277777777777778; //double(100*n)+15.f;
f_even[8*N+n] = 0.0277777777777778; //double(100*n)+16.f; f_even[8 * N + n] = 0.0277777777777778; //double(100*n)+16.f;
f_odd[8*N+n] = 0.0277777777777778; //double(100*n)+17.f; f_odd[8 * N + n] = 0.0277777777777778; //double(100*n)+17.f;
f_even[9*N+n] = 0.0277777777777778; //double(100*n)+18.f; f_even[9 * N + n] = 0.0277777777777778; //double(100*n)+18.f;
} } else {
else{ for (int q = 0; q < 9; q++) {
for(int q=0; q<9; q++){ f_even[q * N + n] = -1.0;
f_even[q*N+n] = -1.0; f_odd[q * N + n] = -1.0;
f_odd[q*N+n] = -1.0; }
} f_even[9 * N + n] = -1.0;
f_even[9*N+n] = -1.0; }
} }
}
} }
extern "C" void Compute_VELOCITY(char *ID, double *disteven, double *distodd, double *vel, int Nx, int Ny, int Nz) extern "C" void Compute_VELOCITY(char *ID, double *disteven, double *distodd,
{ double *vel, int Nx, int Ny, int Nz) {
int n,N; int n, N;
// distributions // distributions
double f1,f2,f3,f4,f5,f6,f7,f8,f9; double f1, f2, f3, f4, f5, f6, f7, f8, f9;
double f10,f11,f12,f13,f14,f15,f16,f17,f18; double f10, f11, f12, f13, f14, f15, f16, f17, f18;
double vx,vy,vz; double vx, vy, vz;
N = Nx*Ny*Nz; N = Nx * Ny * Nz;
for (n=0; n<N; n++){ for (n = 0; n < N; n++) {
if (ID[n] > 0){
//........................................................................
// Registers to store the distributions
//........................................................................
f2 = disteven[N+n];
f4 = disteven[2*N+n];
f6 = disteven[3*N+n];
f8 = disteven[4*N+n];
f10 = disteven[5*N+n];
f12 = disteven[6*N+n];
f14 = disteven[7*N+n];
f16 = disteven[8*N+n];
f18 = disteven[9*N+n];
//........................................................................
f1 = distodd[n];
f3 = distodd[1*N+n];
f5 = distodd[2*N+n];
f7 = distodd[3*N+n];
f9 = distodd[4*N+n];
f11 = distodd[5*N+n];
f13 = distodd[6*N+n];
f15 = distodd[7*N+n];
f17 = distodd[8*N+n];
//.................Compute the velocity...................................
vx = f1-f2+f7-f8+f9-f10+f11-f12+f13-f14;
vy = f3-f4+f7-f8-f9+f10+f15-f16+f17-f18;
vz = f5-f6+f11-f12-f13+f14+f15-f16-f17+f18;
//..................Write the velocity.....................................
vel[n] = vx;
vel[N+n] = vy;
vel[2*N+n] = vz;
//........................................................................
}
}
}
if (ID[n] > 0) {
//........................................................................
// Registers to store the distributions
//........................................................................
f2 = disteven[N + n];
f4 = disteven[2 * N + n];
f6 = disteven[3 * N + n];
f8 = disteven[4 * N + n];
f10 = disteven[5 * N + n];
f12 = disteven[6 * N + n];
f14 = disteven[7 * N + n];
f16 = disteven[8 * N + n];
f18 = disteven[9 * N + n];
//........................................................................
f1 = distodd[n];
f3 = distodd[1 * N + n];
f5 = distodd[2 * N + n];
f7 = distodd[3 * N + n];
f9 = distodd[4 * N + n];
f11 = distodd[5 * N + n];
f13 = distodd[6 * N + n];
f15 = distodd[7 * N + n];
f17 = distodd[8 * N + n];
//.................Compute the velocity...................................
vx = f1 - f2 + f7 - f8 + f9 - f10 + f11 - f12 + f13 - f14;
vy = f3 - f4 + f7 - f8 - f9 + f10 + f15 - f16 + f17 - f18;
vz = f5 - f6 + f11 - f12 - f13 + f14 + f15 - f16 - f17 + f18;
//..................Write the velocity.....................................
vel[n] = vx;
vel[N + n] = vy;
vel[2 * N + n] = vz;
//........................................................................
}
}
}
//************************************************************************* //*************************************************************************
extern "C" void ScaLBL_D3Q19_MRT(char *ID, double *disteven, double *distodd, int Nx, int Ny, int Nz, extern "C" void ScaLBL_D3Q19_MRT(char *ID, double *disteven, double *distodd,
double rlx_setA, double rlx_setB, double Fx, double Fy, double Fz) int Nx, int Ny, int Nz, double rlx_setA,
{ double rlx_setB, double Fx, double Fy,
double Fz) {
int n,N; int n, N;
// distributions // distributions
double f0,f1,f2,f3,f4,f5,f6,f7,f8,f9; double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9;
double f10,f11,f12,f13,f14,f15,f16,f17,f18; double f10, f11, f12, f13, f14, f15, f16, f17, f18;
// conserved momemnts // conserved momemnts
double rho,jx,jy,jz; double rho, jx, jy, jz;
// non-conserved moments // non-conserved moments
double m1,m2,m4,m6,m8,m9,m10,m11,m12,m13,m14,m15,m16,m17,m18; double m1, m2, m4, m6, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18;
N = Nx*Ny*Nz; N = Nx * Ny * Nz;
char id; char id;
for (n=0; n<N; n++){ for (n = 0; n < N; n++) {
id = ID[n]; id = ID[n];
if (id > 0){
//........................................................................
// Registers to store the distributions - read based on swap convention
//........................................................................
f2 = distodd[n];
f4 = distodd[N+n];
f6 = distodd[2*N+n];
f8 = distodd[3*N+n];
f10 = distodd[4*N+n];
f12 = distodd[5*N+n];
f14 = distodd[6*N+n];
f16 = distodd[7*N+n];
f18 = distodd[8*N+n];
//........................................................................
f0 = disteven[n];
f1 = disteven[N+n];
f3 = disteven[2*N+n];
f5 = disteven[3*N+n];
f7 = disteven[4*N+n];
f9 = disteven[5*N+n];
f11 = disteven[6*N+n];
f13 = disteven[7*N+n];
f15 = disteven[8*N+n];
f17 = disteven[9*N+n];
//........................................................................
//....................compute the moments...............................................
rho = f0+f2+f1+f4+f3+f6+f5+f8+f7+f10+f9+f12+f11+f14+f13+f16+f15+f18+f17;
m1 = -30*f0-11*(f2+f1+f4+f3+f6+f5)+8*(f8+f7+f10+f9+f12+f11+f14+f13+f16+f15+f18 +f17);
m2 = 12*f0-4*(f2+f1 +f4+f3+f6 +f5)+f8+f7+f10+f9+f12+f11+f14+f13+f16+f15+f18+f17;
jx = f1-f2+f7-f8+f9-f10+f11-f12+f13-f14;
m4 = 4*(-f1+f2)+f7-f8+f9-f10+f11-f12+f13-f14;
jy = f3-f4+f7-f8-f9+f10+f15-f16+f17-f18;
m6 = -4*(f3-f4)+f7-f8-f9+f10+f15-f16+f17-f18;
jz = f5-f6+f11-f12-f13+f14+f15-f16-f17+f18;
m8 = -4*(f5-f6)+f11-f12-f13+f14+f15-f16-f17+f18;
m9 = 2*(f1+f2)-f3-f4-f5-f6+f7+f8+f9+f10+f11+f12+f13+f14-2*(f15+f16+f17+f18);
m10 = -4*(f1+f2)+2*(f4+f3+f6+f5)+f8+f7+f10+f9+f12+f11+f14+f13-2*(f16+f15+f18+f17);
m11 = f4+f3-f6-f5+f8+f7+f10+f9-f12-f11-f14-f13;
m12 = -2*(f4+f3-f6-f5)+f8+f7+f10+f9-f12-f11-f14-f13;
m13 = f8+f7-f10-f9;
m14 = f16+f15-f18-f17;
m15 = f12+f11-f14-f13;
m16 = f7-f8+f9-f10-f11+f12-f13+f14;
m17 = -f7+f8+f9-f10+f15-f16+f17-f18;
m18 = f11-f12-f13+f14-f15+f16+f17-f18;
//..............incorporate external force................................................
//jx += 0.5*Fx;
//jy += 0.5*Fy;
//jz += 0.5*Fz;
//..............carry out relaxation process...............................................
m1 = m1 + rlx_setA*((19*(jx*jx+jy*jy+jz*jz)/rho - 11*rho) - m1);
m2 = m2 + rlx_setA*((3*rho - 5.5*(jx*jx+jy*jy+jz*jz)/rho) - m2);
m4 = m4 + rlx_setB*((-0.6666666666666666*jx) - m4);
m6 = m6 + rlx_setB*((-0.6666666666666666*jy) - m6);
m8 = m8 + rlx_setB*((-0.6666666666666666*jz) - m8);
m9 = m9 + rlx_setA*(((2*jx*jx-jy*jy-jz*jz)/rho) - m9);
m10 = m10 + rlx_setA*(-0.5*((2*jx*jx-jy*jy-jz*jz)/rho) - m10);
m11 = m11 + rlx_setA*(((jy*jy-jz*jz)/rho) - m11);
m12 = m12 + rlx_setA*(-0.5*((jy*jy-jz*jz)/rho) - m12);
m13 = m13 + rlx_setA*((jx*jy/rho) - m13);
m14 = m14 + rlx_setA*((jy*jz/rho) - m14);
m15 = m15 + rlx_setA*((jx*jz/rho) - m15);
m16 = m16 + rlx_setB*( - m16);
m17 = m17 + rlx_setB*( - m17);
m18 = m18 + rlx_setB*( - m18);
//.................inverse transformation......................................................
f0 = 0.05263157894736842*rho-0.012531328320802*m1+0.04761904761904762*m2;
f1 = 0.05263157894736842*rho-0.004594820384294068*m1-0.01587301587301587*m2
+0.1*(jx-m4)+0.05555555555555555*(m9-m10);
f2 = 0.05263157894736842*rho-0.004594820384294068*m1-0.01587301587301587*m2
+0.1*(m4-jx)+0.05555555555555555*(m9-m10);
f3 = 0.05263157894736842*rho-0.004594820384294068*m1-0.01587301587301587*m2
+0.1*(jy-m6)+0.02777777777777778*(m10-m9)+0.08333333333333333*(m11-m12);
f4 = 0.05263157894736842*rho-0.004594820384294068*m1-0.01587301587301587*m2
+0.1*(m6-jy)+0.02777777777777778*(m10-m9)+0.08333333333333333*(m11-m12);
f5 = 0.05263157894736842*rho-0.004594820384294068*m1-0.01587301587301587*m2
+0.1*(jz-m8)+0.02777777777777778*(m10-m9)+0.08333333333333333*(m12-m11);
f6 = 0.05263157894736842*rho-0.004594820384294068*m1-0.01587301587301587*m2
+0.1*(m8-jz)+0.02777777777777778*(m10-m9)+0.08333333333333333*(m12-m11);
f7 = 0.05263157894736842*rho+0.003341687552213868*m1+0.003968253968253968*m2+0.1*(jx+jy)+0.025*(m4+m6)
+0.02777777777777778*m9+0.01388888888888889*m10+0.08333333333333333*m11
+0.04166666666666666*m12+0.25*m13+0.125*(m16-m17);
f8 = 0.05263157894736842*rho+0.003341687552213868*m1+0.003968253968253968*m2-0.1*(jx+jy)-0.025*(m4+m6)
+0.02777777777777778*m9+0.01388888888888889*m10+0.08333333333333333*m11
+0.04166666666666666*m12+0.25*m13+0.125*(m17-m16);
f9 = 0.05263157894736842*rho+0.003341687552213868*m1+0.003968253968253968*m2+0.1*(jx-jy)+0.025*(m4-m6)
+0.02777777777777778*m9+0.01388888888888889*m10+0.08333333333333333*m11
+0.04166666666666666*m12-0.25*m13+0.125*(m16+m17);
f10 = 0.05263157894736842*rho+0.003341687552213868*m1+0.003968253968253968*m2+0.1*(jy-jx)+0.025*(m6-m4)
+0.02777777777777778*m9+0.01388888888888889*m10+0.08333333333333333*m11
+0.04166666666666666*m12-0.25*m13-0.125*(m16+m17);
f11 = 0.05263157894736842*rho+0.003341687552213868*m1
+0.003968253968253968*m2+0.1*(jx+jz)+0.025*(m4+m8)
+0.02777777777777778*m9+0.01388888888888889*m10-0.08333333333333333*m11
-0.04166666666666666*m12+0.25*m15+0.125*(m18-m16);
f12 = 0.05263157894736842*rho+0.003341687552213868*m1
+0.003968253968253968*m2-0.1*(jx+jz)-0.025*(m4+m8)
+0.02777777777777778*m9+0.01388888888888889*m10-0.08333333333333333*m11
-0.04166666666666666*m12+0.25*m15+0.125*(m16-m18);
f13 = 0.05263157894736842*rho+0.003341687552213868*m1
+0.003968253968253968*m2+0.1*(jx-jz)+0.025*(m4-m8)
+0.02777777777777778*m9+0.01388888888888889*m10-0.08333333333333333*m11
-0.04166666666666666*m12-0.25*m15-0.125*(m16+m18);
f14 = 0.05263157894736842*rho+0.003341687552213868*m1
+0.003968253968253968*m2+0.1*(jz-jx)+0.025*(m8-m4)
+0.02777777777777778*m9+0.01388888888888889*m10-0.08333333333333333*m11
-0.04166666666666666*m12-0.25*m15+0.125*(m16+m18);
f15 = 0.05263157894736842*rho+0.003341687552213868*m1
+0.003968253968253968*m2+0.1*(jy+jz)+0.025*(m6+m8)
-0.05555555555555555*m9-0.02777777777777778*m10+0.25*m14+0.125*(m17-m18);
f16 = 0.05263157894736842*rho+0.003341687552213868*m1
+0.003968253968253968*m2-0.1*(jy+jz)-0.025*(m6+m8)
-0.05555555555555555*m9-0.02777777777777778*m10+0.25*m14+0.125*(m18-m17);
f17 = 0.05263157894736842*rho+0.003341687552213868*m1
+0.003968253968253968*m2+0.1*(jy-jz)+0.025*(m6-m8)
-0.05555555555555555*m9-0.02777777777777778*m10-0.25*m14+0.125*(m17+m18);
f18 = 0.05263157894736842*rho+0.003341687552213868*m1
+0.003968253968253968*m2+0.1*(jz-jy)+0.025*(m8-m6)
-0.05555555555555555*m9-0.02777777777777778*m10-0.25*m14-0.125*(m17+m18);
//.......................................................................................................
// incorporate external force
f1 += 0.16666666*Fx;
f2 -= 0.16666666*Fx;
f3 += 0.16666666*Fy;
f4 -= 0.16666666*Fy;
f5 += 0.16666666*Fz;
f6 -= 0.16666666*Fz;
f7 += 0.08333333333*(Fx+Fy);
f8 -= 0.08333333333*(Fx+Fy);
f9 += 0.08333333333*(Fx-Fy);
f10 -= 0.08333333333*(Fx-Fy);
f11 += 0.08333333333*(Fx+Fz);
f12 -= 0.08333333333*(Fx+Fz);
f13 += 0.08333333333*(Fx-Fz);
f14 -= 0.08333333333*(Fx-Fz);
f15 += 0.08333333333*(Fy+Fz);
f16 -= 0.08333333333*(Fy+Fz);
f17 += 0.08333333333*(Fy-Fz);
f18 -= 0.08333333333*(Fy-Fz);
//.......................................................................................................
// Write data based on un-swapped convention
disteven[n] = f0;
disteven[N+n] = f2;
disteven[2*N+n] = f4;
disteven[3*N+n] = f6;
disteven[4*N+n] = f8;
disteven[5*N+n] = f10;
disteven[6*N+n] = f12;
disteven[7*N+n] = f14;
disteven[8*N+n] = f16;
disteven[9*N+n] = f18;
distodd[n] = f1;
distodd[N+n] = f3;
distodd[2*N+n] = f5;
distodd[3*N+n] = f7;
distodd[4*N+n] = f9;
distodd[5*N+n] = f11;
distodd[6*N+n] = f13;
distodd[7*N+n] = f15;
distodd[8*N+n] = f17;
//.......................................................................................................
}
}
}
if (id > 0) {
//........................................................................
// Registers to store the distributions - read based on swap convention
//........................................................................
f2 = distodd[n];
f4 = distodd[N + n];
f6 = distodd[2 * N + n];
f8 = distodd[3 * N + n];
f10 = distodd[4 * N + n];
f12 = distodd[5 * N + n];
f14 = distodd[6 * N + n];
f16 = distodd[7 * N + n];
f18 = distodd[8 * N + n];
//........................................................................
f0 = disteven[n];
f1 = disteven[N + n];
f3 = disteven[2 * N + n];
f5 = disteven[3 * N + n];
f7 = disteven[4 * N + n];
f9 = disteven[5 * N + n];
f11 = disteven[6 * N + n];
f13 = disteven[7 * N + n];
f15 = disteven[8 * N + n];
f17 = disteven[9 * N + n];
//........................................................................
//....................compute the moments...............................................
rho = f0 + f2 + f1 + f4 + f3 + f6 + f5 + f8 + f7 + f10 + f9 + f12 +
f11 + f14 + f13 + f16 + f15 + f18 + f17;
m1 = -30 * f0 - 11 * (f2 + f1 + f4 + f3 + f6 + f5) +
8 * (f8 + f7 + f10 + f9 + f12 + f11 + f14 + f13 + f16 + f15 +
f18 + f17);
m2 = 12 * f0 - 4 * (f2 + f1 + f4 + f3 + f6 + f5) + f8 + f7 + f10 +
f9 + f12 + f11 + f14 + f13 + f16 + f15 + f18 + f17;
jx = f1 - f2 + f7 - f8 + f9 - f10 + f11 - f12 + f13 - f14;
m4 = 4 * (-f1 + f2) + f7 - f8 + f9 - f10 + f11 - f12 + f13 - f14;
jy = f3 - f4 + f7 - f8 - f9 + f10 + f15 - f16 + f17 - f18;
m6 = -4 * (f3 - f4) + f7 - f8 - f9 + f10 + f15 - f16 + f17 - f18;
jz = f5 - f6 + f11 - f12 - f13 + f14 + f15 - f16 - f17 + f18;
m8 = -4 * (f5 - f6) + f11 - f12 - f13 + f14 + f15 - f16 - f17 + f18;
m9 = 2 * (f1 + f2) - f3 - f4 - f5 - f6 + f7 + f8 + f9 + f10 + f11 +
f12 + f13 + f14 - 2 * (f15 + f16 + f17 + f18);
m10 = -4 * (f1 + f2) + 2 * (f4 + f3 + f6 + f5) + f8 + f7 + f10 +
f9 + f12 + f11 + f14 + f13 - 2 * (f16 + f15 + f18 + f17);
m11 =
f4 + f3 - f6 - f5 + f8 + f7 + f10 + f9 - f12 - f11 - f14 - f13;
m12 = -2 * (f4 + f3 - f6 - f5) + f8 + f7 + f10 + f9 - f12 - f11 -
f14 - f13;
m13 = f8 + f7 - f10 - f9;
m14 = f16 + f15 - f18 - f17;
m15 = f12 + f11 - f14 - f13;
m16 = f7 - f8 + f9 - f10 - f11 + f12 - f13 + f14;
m17 = -f7 + f8 + f9 - f10 + f15 - f16 + f17 - f18;
m18 = f11 - f12 - f13 + f14 - f15 + f16 + f17 - f18;
//..............incorporate external force................................................
//jx += 0.5*Fx;
//jy += 0.5*Fy;
//jz += 0.5*Fz;
//..............carry out relaxation process...............................................
m1 = m1 + rlx_setA * ((19 * (jx * jx + jy * jy + jz * jz) / rho -
11 * rho) -
m1);
m2 = m2 + rlx_setA * ((3 * rho -
5.5 * (jx * jx + jy * jy + jz * jz) / rho) -
m2);
m4 = m4 + rlx_setB * ((-0.6666666666666666 * jx) - m4);
m6 = m6 + rlx_setB * ((-0.6666666666666666 * jy) - m6);
m8 = m8 + rlx_setB * ((-0.6666666666666666 * jz) - m8);
m9 = m9 +
rlx_setA * (((2 * jx * jx - jy * jy - jz * jz) / rho) - m9);
m10 = m10 +
rlx_setA *
(-0.5 * ((2 * jx * jx - jy * jy - jz * jz) / rho) - m10);
m11 = m11 + rlx_setA * (((jy * jy - jz * jz) / rho) - m11);
m12 = m12 + rlx_setA * (-0.5 * ((jy * jy - jz * jz) / rho) - m12);
m13 = m13 + rlx_setA * ((jx * jy / rho) - m13);
m14 = m14 + rlx_setA * ((jy * jz / rho) - m14);
m15 = m15 + rlx_setA * ((jx * jz / rho) - m15);
m16 = m16 + rlx_setB * (-m16);
m17 = m17 + rlx_setB * (-m17);
m18 = m18 + rlx_setB * (-m18);
//.................inverse transformation......................................................
f0 = 0.05263157894736842 * rho - 0.012531328320802 * m1 +
0.04761904761904762 * m2;
f1 = 0.05263157894736842 * rho - 0.004594820384294068 * m1 -
0.01587301587301587 * m2 + 0.1 * (jx - m4) +
0.05555555555555555 * (m9 - m10);
f2 = 0.05263157894736842 * rho - 0.004594820384294068 * m1 -
0.01587301587301587 * m2 + 0.1 * (m4 - jx) +
0.05555555555555555 * (m9 - m10);
f3 = 0.05263157894736842 * rho - 0.004594820384294068 * m1 -
0.01587301587301587 * m2 + 0.1 * (jy - m6) +
0.02777777777777778 * (m10 - m9) +
0.08333333333333333 * (m11 - m12);
f4 = 0.05263157894736842 * rho - 0.004594820384294068 * m1 -
0.01587301587301587 * m2 + 0.1 * (m6 - jy) +
0.02777777777777778 * (m10 - m9) +
0.08333333333333333 * (m11 - m12);
f5 = 0.05263157894736842 * rho - 0.004594820384294068 * m1 -
0.01587301587301587 * m2 + 0.1 * (jz - m8) +
0.02777777777777778 * (m10 - m9) +
0.08333333333333333 * (m12 - m11);
f6 = 0.05263157894736842 * rho - 0.004594820384294068 * m1 -
0.01587301587301587 * m2 + 0.1 * (m8 - jz) +
0.02777777777777778 * (m10 - m9) +
0.08333333333333333 * (m12 - m11);
f7 = 0.05263157894736842 * rho + 0.003341687552213868 * m1 +
0.003968253968253968 * m2 + 0.1 * (jx + jy) +
0.025 * (m4 + m6) + 0.02777777777777778 * m9 +
0.01388888888888889 * m10 + 0.08333333333333333 * m11 +
0.04166666666666666 * m12 + 0.25 * m13 + 0.125 * (m16 - m17);
f8 = 0.05263157894736842 * rho + 0.003341687552213868 * m1 +
0.003968253968253968 * m2 - 0.1 * (jx + jy) -
0.025 * (m4 + m6) + 0.02777777777777778 * m9 +
0.01388888888888889 * m10 + 0.08333333333333333 * m11 +
0.04166666666666666 * m12 + 0.25 * m13 + 0.125 * (m17 - m16);
f9 = 0.05263157894736842 * rho + 0.003341687552213868 * m1 +
0.003968253968253968 * m2 + 0.1 * (jx - jy) +
0.025 * (m4 - m6) + 0.02777777777777778 * m9 +
0.01388888888888889 * m10 + 0.08333333333333333 * m11 +
0.04166666666666666 * m12 - 0.25 * m13 + 0.125 * (m16 + m17);
f10 = 0.05263157894736842 * rho + 0.003341687552213868 * m1 +
0.003968253968253968 * m2 + 0.1 * (jy - jx) +
0.025 * (m6 - m4) + 0.02777777777777778 * m9 +
0.01388888888888889 * m10 + 0.08333333333333333 * m11 +
0.04166666666666666 * m12 - 0.25 * m13 - 0.125 * (m16 + m17);
f11 = 0.05263157894736842 * rho + 0.003341687552213868 * m1 +
0.003968253968253968 * m2 + 0.1 * (jx + jz) +
0.025 * (m4 + m8) + 0.02777777777777778 * m9 +
0.01388888888888889 * m10 - 0.08333333333333333 * m11 -
0.04166666666666666 * m12 + 0.25 * m15 + 0.125 * (m18 - m16);
f12 = 0.05263157894736842 * rho + 0.003341687552213868 * m1 +
0.003968253968253968 * m2 - 0.1 * (jx + jz) -
0.025 * (m4 + m8) + 0.02777777777777778 * m9 +
0.01388888888888889 * m10 - 0.08333333333333333 * m11 -
0.04166666666666666 * m12 + 0.25 * m15 + 0.125 * (m16 - m18);
f13 = 0.05263157894736842 * rho + 0.003341687552213868 * m1 +
0.003968253968253968 * m2 + 0.1 * (jx - jz) +
0.025 * (m4 - m8) + 0.02777777777777778 * m9 +
0.01388888888888889 * m10 - 0.08333333333333333 * m11 -
0.04166666666666666 * m12 - 0.25 * m15 - 0.125 * (m16 + m18);
f14 = 0.05263157894736842 * rho + 0.003341687552213868 * m1 +
0.003968253968253968 * m2 + 0.1 * (jz - jx) +
0.025 * (m8 - m4) + 0.02777777777777778 * m9 +
0.01388888888888889 * m10 - 0.08333333333333333 * m11 -
0.04166666666666666 * m12 - 0.25 * m15 + 0.125 * (m16 + m18);
f15 = 0.05263157894736842 * rho + 0.003341687552213868 * m1 +
0.003968253968253968 * m2 + 0.1 * (jy + jz) +
0.025 * (m6 + m8) - 0.05555555555555555 * m9 -
0.02777777777777778 * m10 + 0.25 * m14 + 0.125 * (m17 - m18);
f16 = 0.05263157894736842 * rho + 0.003341687552213868 * m1 +
0.003968253968253968 * m2 - 0.1 * (jy + jz) -
0.025 * (m6 + m8) - 0.05555555555555555 * m9 -
0.02777777777777778 * m10 + 0.25 * m14 + 0.125 * (m18 - m17);
f17 = 0.05263157894736842 * rho + 0.003341687552213868 * m1 +
0.003968253968253968 * m2 + 0.1 * (jy - jz) +
0.025 * (m6 - m8) - 0.05555555555555555 * m9 -
0.02777777777777778 * m10 - 0.25 * m14 + 0.125 * (m17 + m18);
f18 = 0.05263157894736842 * rho + 0.003341687552213868 * m1 +
0.003968253968253968 * m2 + 0.1 * (jz - jy) +
0.025 * (m8 - m6) - 0.05555555555555555 * m9 -
0.02777777777777778 * m10 - 0.25 * m14 - 0.125 * (m17 + m18);
//.......................................................................................................
// incorporate external force
f1 += 0.16666666 * Fx;
f2 -= 0.16666666 * Fx;
f3 += 0.16666666 * Fy;
f4 -= 0.16666666 * Fy;
f5 += 0.16666666 * Fz;
f6 -= 0.16666666 * Fz;
f7 += 0.08333333333 * (Fx + Fy);
f8 -= 0.08333333333 * (Fx + Fy);
f9 += 0.08333333333 * (Fx - Fy);
f10 -= 0.08333333333 * (Fx - Fy);
f11 += 0.08333333333 * (Fx + Fz);
f12 -= 0.08333333333 * (Fx + Fz);
f13 += 0.08333333333 * (Fx - Fz);
f14 -= 0.08333333333 * (Fx - Fz);
f15 += 0.08333333333 * (Fy + Fz);
f16 -= 0.08333333333 * (Fy + Fz);
f17 += 0.08333333333 * (Fy - Fz);
f18 -= 0.08333333333 * (Fy - Fz);
//.......................................................................................................
// Write data based on un-swapped convention
disteven[n] = f0;
disteven[N + n] = f2;
disteven[2 * N + n] = f4;
disteven[3 * N + n] = f6;
disteven[4 * N + n] = f8;
disteven[5 * N + n] = f10;
disteven[6 * N + n] = f12;
disteven[7 * N + n] = f14;
disteven[8 * N + n] = f16;
disteven[9 * N + n] = f18;
distodd[n] = f1;
distodd[N + n] = f3;
distodd[2 * N + n] = f5;
distodd[3 * N + n] = f7;
distodd[4 * N + n] = f9;
distodd[5 * N + n] = f11;
distodd[6 * N + n] = f13;
distodd[7 * N + n] = f15;
distodd[8 * N + n] = f17;
//.......................................................................................................
}
}
}

View File

@ -1,48 +1,51 @@
/* Implement Mixed Gradient (Lee et al. JCP 2016)*/ /* Implement Mixed Gradient (Lee et al. JCP 2016)*/
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,
static int D3Q19[18][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}, int finish, int Np, int Nx, int Ny,
{1,1,0},{-1,-1,0},{1,-1,0},{-1,1,0}, int Nz) {
{1,0,1},{-1,0,-1},{1,0,-1},{-1,0,1}, static int D3Q19[18][3] = {{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0},
{0,1,1},{0,-1,-1},{0,1,-1},{0,-1,1}}; {0, 0, 1}, {0, 0, -1}, {1, 1, 0}, {-1, -1, 0},
{1, -1, 0}, {-1, 1, 0}, {1, 0, 1}, {-1, 0, -1},
int i,j,k,n; {1, 0, -1}, {-1, 0, 1}, {0, 1, 1}, {0, -1, -1},
int np,np2,nm; // neighbors {0, 1, -1}, {0, -1, 1}};
double v,vp,vp2,vm; // values at neighbors
double grad; int i, j, k, n;
for (int idx=start; idx<finish; idx++){ int np, np2, nm; // neighbors
n = Map[idx]; // layout in regular array double v, vp, vp2, vm; // values at neighbors
//.......Back out the 3-D indices for node n.............. double grad;
k = n/(Nx*Ny); for (int idx = start; idx < finish; idx++) {
j = (n-Nx*Ny*k)/Nx; n = Map[idx]; // layout in regular array
i = n-Nx*Ny*k-Nx*j; //.......Back out the 3-D indices for node n..............
v = Phi[n]; k = n / (Nx * Ny);
grad = 0.0; j = (n - Nx * Ny * k) / Nx;
for (int q=0; q<6; q++){ i = n - Nx * Ny * k - Nx * j;
int iqx = D3Q19[q][0]; v = Phi[n];
int iqy = D3Q19[q][1]; grad = 0.0;
int iqz = D3Q19[q][2]; for (int q = 0; q < 6; q++) {
np = (k+iqz)*Nx*Ny + (j+iqy)*Nx + i + iqx; int iqx = D3Q19[q][0];
np2 = (k+2*iqz)*Nx*Ny + (j+2*iqy)*Nx + i + 2*iqx; int iqy = D3Q19[q][1];
nm = (k-iqz)*Nx*Ny + (j-iqy)*Nx + i - iqx; int iqz = D3Q19[q][2];
vp = Phi[np]; np = (k + iqz) * Nx * Ny + (j + iqy) * Nx + i + iqx;
vp2 = Phi[np2]; np2 = (k + 2 * iqz) * Nx * Ny + (j + 2 * iqy) * Nx + i + 2 * iqx;
vm = Phi[nm]; nm = (k - iqz) * Nx * Ny + (j - iqy) * Nx + i - iqx;
grad += 0.25*(5.0*vp-vp2-3.0*v-vm); vp = Phi[np];
} vp2 = Phi[np2];
for (int q=6; q<18; q++){ vm = Phi[nm];
int iqx = D3Q19[q][0]; grad += 0.25 * (5.0 * vp - vp2 - 3.0 * v - vm);
int iqy = D3Q19[q][1]; }
int iqz = D3Q19[q][2]; for (int q = 6; q < 18; q++) {
np = (k+iqz)*Nx*Ny + (j+iqy)*Nx + i + iqx; int iqx = D3Q19[q][0];
np2 = (k+2*iqz)*Nx*Ny + (j+2*iqy)*Nx + i + 2*iqx; int iqy = D3Q19[q][1];
nm = (k-iqz)*Nx*Ny + (j-iqy)*Nx + i - iqx; int iqz = D3Q19[q][2];
vp = Phi[np]; np = (k + iqz) * Nx * Ny + (j + iqy) * Nx + i + iqx;
vp2 = Phi[np2]; np2 = (k + 2 * iqz) * Nx * Ny + (j + 2 * iqy) * Nx + i + 2 * iqx;
vm = Phi[nm]; nm = (k - iqz) * Nx * Ny + (j - iqy) * Nx + i - iqx;
grad += 0.125*(5.0*vp-vp2-3.0*v-vm); vp = Phi[np];
} vp2 = Phi[np2];
Gradient[n] = grad; vm = Phi[nm];
} grad += 0.125 * (5.0 * vp - vp2 - 3.0 * v - vm);
}
Gradient[n] = grad;
}
} }

View File

@ -1,320 +1,342 @@
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
int n; ScaLBL_D3Q7_AAodd_Poisson_ElectricPotential(int *neighborList, int *Map,
double psi;//electric potential double *dist, double *Psi,
double fq; int start, int finish, int Np) {
int nread; int n;
double psi; //electric potential
double fq;
int nread;
int idx; int idx;
for (n=start; n<finish; n++){ for (n = start; n < finish; n++) {
// q=0 // q=0
fq = dist[n]; fq = dist[n];
psi = fq; psi = fq;
// q=1 // q=1
nread = neighborList[n]; nread = neighborList[n];
fq = dist[nread]; fq = dist[nread];
psi += fq; psi += fq;
// q=2
nread = neighborList[n+Np];
fq = dist[nread];
psi += fq;
// q=3 // q=2
nread = neighborList[n+2*Np]; nread = neighborList[n + Np];
fq = dist[nread]; fq = dist[nread];
psi += fq; psi += fq;
// q = 4 // q=3
nread = neighborList[n+3*Np]; nread = neighborList[n + 2 * Np];
fq = dist[nread]; fq = dist[nread];
psi += fq; psi += fq;
// q=5 // q = 4
nread = neighborList[n+4*Np]; nread = neighborList[n + 3 * Np];
fq = dist[nread]; fq = dist[nread];
psi += fq; psi += fq;
// q = 6 // q=5
nread = neighborList[n+5*Np]; nread = neighborList[n + 4 * Np];
fq = dist[nread]; fq = dist[nread];
psi += fq; psi += fq;
idx=Map[n]; // q = 6
nread = neighborList[n + 5 * Np];
fq = dist[nread];
psi += fq;
idx = Map[n];
Psi[idx] = psi; Psi[idx] = psi;
} }
} }
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 n; int *Map, double *dist, double *Psi, int start, int finish, int Np) {
double psi;//electric potential int n;
double fq; double psi; //electric potential
double fq;
int idx; int idx;
for (n=start; n<finish; n++){ for (n = start; n < finish; n++) {
// q=0 // q=0
fq = dist[n]; fq = dist[n];
psi = fq; psi = fq;
// q=1
fq = dist[2*Np+n];
psi += fq;
// q=2 // q=1
fq = dist[1*Np+n]; fq = dist[2 * Np + n];
psi += fq; psi += fq;
// q=3 // q=2
fq = dist[4*Np+n]; fq = dist[1 * Np + n];
psi += fq; psi += fq;
// q=4 // q=3
fq = dist[3*Np+n]; fq = dist[4 * Np + n];
psi += fq; psi += fq;
// q=5 // q=4
fq = dist[6*Np+n]; fq = dist[3 * Np + n];
psi += fq; psi += fq;
// q=6 // q=5
fq = dist[5*Np+n]; fq = dist[6 * Np + n];
psi += fq; psi += fq;
idx=Map[n]; // q=6
fq = dist[5 * Np + n];
psi += fq;
idx = Map[n];
Psi[idx] = psi; Psi[idx] = psi;
} }
} }
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){ extern "C" void ScaLBL_D3Q7_AAodd_Poisson(int *neighborList, int *Map,
int n; double *dist, double *Den_charge,
double psi;//electric potential double *Psi, double *ElectricField,
double Ex,Ey,Ez;//electric field double tau, double epsilon_LB,
double rho_e;//local charge density int start, int finish, int Np) {
double f0,f1,f2,f3,f4,f5,f6; int n;
int nr1,nr2,nr3,nr4,nr5,nr6; double psi; //electric potential
double rlx=1.0/tau; double Ex, Ey, Ez; //electric field
double rho_e; //local charge density
double f0, f1, f2, f3, f4, f5, f6;
int nr1, nr2, nr3, nr4, nr5, nr6;
double rlx = 1.0 / tau;
int idx; int idx;
for (n=start; n<finish; n++){ for (n = start; n < finish; n++) {
//Load data //Load data
rho_e = Den_charge[n]; rho_e = Den_charge[n];
rho_e = rho_e/epsilon_LB; rho_e = rho_e / epsilon_LB;
idx=Map[n]; idx = Map[n];
psi = Psi[idx]; psi = Psi[idx];
// q=0
f0 = dist[n];
// q=1
nr1 = neighborList[n]; // neighbor 2 ( > 10Np => odd part of dist)
f1 = dist[nr1]; // reading the f1 data into register fq
nr2 = neighborList[n+Np]; // neighbor 1 ( < 10Np => even part of dist) // q=0
f2 = dist[nr2]; // reading the f2 data into register fq f0 = dist[n];
// q=1
nr1 = neighborList[n]; // neighbor 2 ( > 10Np => odd part of dist)
f1 = dist[nr1]; // reading the f1 data into register fq
// q=3 nr2 = neighborList[n + Np]; // neighbor 1 ( < 10Np => even part of dist)
nr3 = neighborList[n+2*Np]; // neighbor 4 f2 = dist[nr2]; // reading the f2 data into register fq
f3 = dist[nr3];
// q = 4 // q=3
nr4 = neighborList[n+3*Np]; // neighbor 3 nr3 = neighborList[n + 2 * Np]; // neighbor 4
f4 = dist[nr4]; f3 = dist[nr3];
// q=5 // q = 4
nr5 = neighborList[n+4*Np]; nr4 = neighborList[n + 3 * Np]; // neighbor 3
f5 = dist[nr5]; f4 = dist[nr4];
// q = 6 // q=5
nr6 = neighborList[n+5*Np]; nr5 = neighborList[n + 4 * Np];
f6 = dist[nr6]; f5 = dist[nr5];
Ex = (f1-f2)*rlx*4.0;//NOTE the unit of electric field here is V/lu
Ey = (f3-f4)*rlx*4.0;//factor 4.0 is D3Q7 lattice squared speed of sound
Ez = (f5-f6)*rlx*4.0;
ElectricField[n+0*Np] = Ex;
ElectricField[n+1*Np] = Ey;
ElectricField[n+2*Np] = Ez;
// q = 0 // q = 6
dist[n] = f0*(1.0-rlx) + 0.25*(rlx*psi+rho_e); nr6 = neighborList[n + 5 * Np];
f6 = dist[nr6];
// q = 1 Ex = (f1 - f2) * rlx *
dist[nr2] = f1*(1.0-rlx) + 0.125*(rlx*psi+rho_e); 4.0; //NOTE the unit of electric field here is V/lu
Ey = (f3 - f4) * rlx *
4.0; //factor 4.0 is D3Q7 lattice squared speed of sound
Ez = (f5 - f6) * rlx * 4.0;
ElectricField[n + 0 * Np] = Ex;
ElectricField[n + 1 * Np] = Ey;
ElectricField[n + 2 * Np] = Ez;
// q = 2 // q = 0
dist[nr1] = f2*(1.0-rlx) + 0.125*(rlx*psi+rho_e); dist[n] = f0 * (1.0 - rlx) + 0.25 * (rlx * psi + rho_e);
// q = 3 // q = 1
dist[nr4] = f3*(1.0-rlx) + 0.125*(rlx*psi+rho_e); dist[nr2] = f1 * (1.0 - rlx) + 0.125 * (rlx * psi + rho_e);
// q = 4 // q = 2
dist[nr3] = f4*(1.0-rlx) + 0.125*(rlx*psi+rho_e); dist[nr1] = f2 * (1.0 - rlx) + 0.125 * (rlx * psi + rho_e);
// q = 5 // q = 3
dist[nr6] = f5*(1.0-rlx) + 0.125*(rlx*psi+rho_e); dist[nr4] = f3 * (1.0 - rlx) + 0.125 * (rlx * psi + rho_e);
// q = 6 // q = 4
dist[nr5] = f6*(1.0-rlx) + 0.125*(rlx*psi+rho_e); dist[nr3] = f4 * (1.0 - rlx) + 0.125 * (rlx * psi + rho_e);
//........................................................................
} // q = 5
dist[nr6] = f5 * (1.0 - rlx) + 0.125 * (rlx * psi + rho_e);
// q = 6
dist[nr5] = f6 * (1.0 - rlx) + 0.125 * (rlx * psi + rho_e);
//........................................................................
}
} }
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){ extern "C" void ScaLBL_D3Q7_AAeven_Poisson(int *Map, double *dist,
int n; double *Den_charge, double *Psi,
double psi;//electric potential double *ElectricField, double tau,
double Ex,Ey,Ez;//electric field double epsilon_LB, int start,
double rho_e;//local charge density int finish, int Np) {
double f0,f1,f2,f3,f4,f5,f6; int n;
double rlx=1.0/tau; double psi; //electric potential
double Ex, Ey, Ez; //electric field
double rho_e; //local charge density
double f0, f1, f2, f3, f4, f5, f6;
double rlx = 1.0 / tau;
int idx; int idx;
for (n=start; n<finish; n++){ for (n = start; n < finish; n++) {
//Load data //Load data
rho_e = Den_charge[n]; rho_e = Den_charge[n];
rho_e = rho_e/epsilon_LB; rho_e = rho_e / epsilon_LB;
idx=Map[n]; idx = Map[n];
psi = Psi[idx]; psi = Psi[idx];
f0 = dist[n]; f0 = dist[n];
f1 = dist[2*Np+n]; f1 = dist[2 * Np + n];
f2 = dist[1*Np+n]; f2 = dist[1 * Np + n];
f3 = dist[4*Np+n]; f3 = dist[4 * Np + n];
f4 = dist[3*Np+n]; f4 = dist[3 * Np + n];
f5 = dist[6*Np+n]; f5 = dist[6 * Np + n];
f6 = dist[5*Np+n]; f6 = dist[5 * Np + n];
Ex = (f1 - f2) * rlx *
4.0; //NOTE the unit of electric field here is V/lu
Ey = (f3 - f4) * rlx *
4.0; //factor 4.0 is D3Q7 lattice squared speed of sound
Ez = (f5 - f6) * rlx * 4.0;
ElectricField[n + 0 * Np] = Ex;
ElectricField[n + 1 * Np] = Ey;
ElectricField[n + 2 * Np] = Ez;
Ex = (f1-f2)*rlx*4.0;//NOTE the unit of electric field here is V/lu // q = 0
Ey = (f3-f4)*rlx*4.0;//factor 4.0 is D3Q7 lattice squared speed of sound dist[n] = f0 * (1.0 - rlx) + 0.25 * (rlx * psi + rho_e);
Ez = (f5-f6)*rlx*4.0;
ElectricField[n+0*Np] = Ex;
ElectricField[n+1*Np] = Ey;
ElectricField[n+2*Np] = Ez;
// q = 0 // q = 1
dist[n] = f0*(1.0-rlx) + 0.25*(rlx*psi+rho_e); dist[1 * Np + n] = f1 * (1.0 - rlx) + 0.125 * (rlx * psi + rho_e);
// q = 1 // q = 2
dist[1*Np+n] = f1*(1.0-rlx) + 0.125*(rlx*psi+rho_e); dist[2 * Np + n] = f2 * (1.0 - rlx) + 0.125 * (rlx * psi + rho_e);
// q = 2 // q = 3
dist[2*Np+n] = f2*(1.0-rlx) + 0.125*(rlx*psi+rho_e); dist[3 * Np + n] = f3 * (1.0 - rlx) + 0.125 * (rlx * psi + rho_e);
// q = 3 // q = 4
dist[3*Np+n] = f3*(1.0-rlx) + 0.125*(rlx*psi+rho_e); dist[4 * Np + n] = f4 * (1.0 - rlx) + 0.125 * (rlx * psi + rho_e);
// q = 4 // q = 5
dist[4*Np+n] = f4*(1.0-rlx) + 0.125*(rlx*psi+rho_e); dist[5 * Np + n] = f5 * (1.0 - rlx) + 0.125 * (rlx * psi + rho_e);
// q = 5 // q = 6
dist[5*Np+n] = f5*(1.0-rlx) + 0.125*(rlx*psi+rho_e); dist[6 * Np + n] = f6 * (1.0 - rlx) + 0.125 * (rlx * psi + rho_e);
//........................................................................
// q = 6 }
dist[6*Np+n] = f6*(1.0-rlx) + 0.125*(rlx*psi+rho_e);
//........................................................................
}
} }
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) {
int n; int n;
int ijk; int ijk;
for (n=start; n<finish; n++){ for (n = start; n < finish; n++) {
ijk = Map[n]; ijk = Map[n];
dist[0*Np+n] = 0.25*Psi[ijk]; dist[0 * Np + n] = 0.25 * Psi[ijk];
dist[1*Np+n] = 0.125*Psi[ijk]; dist[1 * Np + n] = 0.125 * Psi[ijk];
dist[2*Np+n] = 0.125*Psi[ijk]; dist[2 * Np + n] = 0.125 * Psi[ijk];
dist[3*Np+n] = 0.125*Psi[ijk]; dist[3 * Np + n] = 0.125 * Psi[ijk];
dist[4*Np+n] = 0.125*Psi[ijk]; dist[4 * Np + n] = 0.125 * Psi[ijk];
dist[5*Np+n] = 0.125*Psi[ijk]; dist[5 * Np + n] = 0.125 * Psi[ijk];
dist[6*Np+n] = 0.125*Psi[ijk]; dist[6 * Np + n] = 0.125 * Psi[ijk];
} }
} }
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){ 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) {
int n,nn,ijk; int n, nn, ijk;
double psi;//electric potential double psi; //electric potential
double rho_e;//local charge density double rho_e; //local charge density
// neighbors of electric potential psi // neighbors of electric potential psi
double m1,m2,m4,m6,m8,m9,m10,m11,m12,m13,m14,m15,m16,m17,m18; double m1, m2, m4, m6, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18;
double m3,m5,m7; double m3, m5, m7;
double psi_Laplacian; double psi_Laplacian;
double residual_error; double residual_error;
for (n=start; n<finish; n++){ for (n = start; n < finish; n++) {
//Load data //Load data
rho_e = Den_charge[n]; rho_e = Den_charge[n];
ijk=Map[n]; ijk = Map[n];
psi = Psi[ijk]; psi = Psi[ijk];
// COMPUTE THE COLOR GRADIENT // COMPUTE THE COLOR GRADIENT
//........................................................................ //........................................................................
//.................Read Phase Indicator Values............................ //.................Read Phase Indicator Values............................
//........................................................................ //........................................................................
nn = ijk-1; // neighbor index (get convention) nn = ijk - 1; // neighbor index (get convention)
m1 = Psi[nn]; // get neighbor for phi - 1 m1 = Psi[nn]; // get neighbor for phi - 1
//........................................................................ //........................................................................
nn = ijk+1; // neighbor index (get convention) nn = ijk + 1; // neighbor index (get convention)
m2 = Psi[nn]; // get neighbor for phi - 2 m2 = Psi[nn]; // get neighbor for phi - 2
//........................................................................ //........................................................................
nn = ijk-strideY; // neighbor index (get convention) nn = ijk - strideY; // neighbor index (get convention)
m3 = Psi[nn]; // get neighbor for phi - 3 m3 = Psi[nn]; // get neighbor for phi - 3
//........................................................................ //........................................................................
nn = ijk+strideY; // neighbor index (get convention) nn = ijk + strideY; // neighbor index (get convention)
m4 = Psi[nn]; // get neighbor for phi - 4 m4 = Psi[nn]; // get neighbor for phi - 4
//........................................................................ //........................................................................
nn = ijk-strideZ; // neighbor index (get convention) nn = ijk - strideZ; // neighbor index (get convention)
m5 = Psi[nn]; // get neighbor for phi - 5 m5 = Psi[nn]; // get neighbor for phi - 5
//........................................................................ //........................................................................
nn = ijk+strideZ; // neighbor index (get convention) nn = ijk + strideZ; // neighbor index (get convention)
m6 = Psi[nn]; // get neighbor for phi - 6 m6 = Psi[nn]; // get neighbor for phi - 6
//........................................................................ //........................................................................
nn = ijk-strideY-1; // neighbor index (get convention) nn = ijk - strideY - 1; // neighbor index (get convention)
m7 = Psi[nn]; // get neighbor for phi - 7 m7 = Psi[nn]; // get neighbor for phi - 7
//........................................................................ //........................................................................
nn = ijk+strideY+1; // neighbor index (get convention) nn = ijk + strideY + 1; // neighbor index (get convention)
m8 = Psi[nn]; // get neighbor for phi - 8 m8 = Psi[nn]; // get neighbor for phi - 8
//........................................................................ //........................................................................
nn = ijk+strideY-1; // neighbor index (get convention) nn = ijk + strideY - 1; // neighbor index (get convention)
m9 = Psi[nn]; // get neighbor for phi - 9 m9 = Psi[nn]; // get neighbor for phi - 9
//........................................................................ //........................................................................
nn = ijk-strideY+1; // neighbor index (get convention) nn = ijk - strideY + 1; // neighbor index (get convention)
m10 = Psi[nn]; // get neighbor for phi - 10 m10 = Psi[nn]; // get neighbor for phi - 10
//........................................................................ //........................................................................
nn = ijk-strideZ-1; // neighbor index (get convention) nn = ijk - strideZ - 1; // neighbor index (get convention)
m11 = Psi[nn]; // get neighbor for phi - 11 m11 = Psi[nn]; // get neighbor for phi - 11
//........................................................................ //........................................................................
nn = ijk+strideZ+1; // neighbor index (get convention) nn = ijk + strideZ + 1; // neighbor index (get convention)
m12 = Psi[nn]; // get neighbor for phi - 12 m12 = Psi[nn]; // get neighbor for phi - 12
//........................................................................ //........................................................................
nn = ijk+strideZ-1; // neighbor index (get convention) nn = ijk + strideZ - 1; // neighbor index (get convention)
m13 = Psi[nn]; // get neighbor for phi - 13 m13 = Psi[nn]; // get neighbor for phi - 13
//........................................................................ //........................................................................
nn = ijk-strideZ+1; // neighbor index (get convention) nn = ijk - strideZ + 1; // neighbor index (get convention)
m14 = Psi[nn]; // get neighbor for phi - 14 m14 = Psi[nn]; // get neighbor for phi - 14
//........................................................................ //........................................................................
nn = ijk-strideZ-strideY; // neighbor index (get convention) nn = ijk - strideZ - strideY; // neighbor index (get convention)
m15 = Psi[nn]; // get neighbor for phi - 15 m15 = Psi[nn]; // get neighbor for phi - 15
//........................................................................ //........................................................................
nn = ijk+strideZ+strideY; // neighbor index (get convention) nn = ijk + strideZ + strideY; // neighbor index (get convention)
m16 = Psi[nn]; // get neighbor for phi - 16 m16 = Psi[nn]; // get neighbor for phi - 16
//........................................................................ //........................................................................
nn = ijk+strideZ-strideY; // neighbor index (get convention) nn = ijk + strideZ - strideY; // neighbor index (get convention)
m17 = Psi[nn]; // get neighbor for phi - 17 m17 = Psi[nn]; // get neighbor for phi - 17
//........................................................................ //........................................................................
nn = ijk-strideZ+strideY; // neighbor index (get convention) nn = ijk - strideZ + strideY; // neighbor index (get convention)
m18 = Psi[nn]; // get neighbor for phi - 18 m18 = Psi[nn]; // get neighbor for phi - 18
psi_Laplacian = 2.0*3.0/18.0*(m1+m2+m3+m4+m5+m6-6*psi+0.5*(m7+m8+m9+m10+m11+m12+m13+m14+m15+m16+m17+m18-12*psi));//Laplacian of electric potential psi_Laplacian =
residual_error = psi_Laplacian+rho_e/epsilon_LB; 2.0 * 3.0 / 18.0 *
ResidualError[n] = residual_error; (m1 + m2 + m3 + m4 + m5 + m6 - 6 * psi +
} 0.5 * (m7 + m8 + m9 + m10 + m11 + m12 + m13 + m14 + m15 + m16 +
m17 + m18 - 12 * psi)); //Laplacian of electric potential
residual_error = psi_Laplacian + rho_e / epsilon_LB;
ResidualError[n] = residual_error;
}
} }
//extern "C" void ScaLBL_D3Q7_Poisson_ElectricField(int *neighborList, int *Map, signed char *ID, double *Psi, double *ElectricField, int SolidBC, //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){ // int strideY, int strideZ,int start, int finish, int Np){
@ -413,7 +435,7 @@ extern "C" void ScaLBL_D3Q7_PoissonResidualError(int *neighborList, int *Map, do
// nx = 1.f/6.f*(m1-m2);//but looks like it needs to multiply another factor of 3 // nx = 1.f/6.f*(m1-m2);//but looks like it needs to multiply another factor of 3
// ny = 1.f/6.f*(m3-m4); // ny = 1.f/6.f*(m3-m4);
// nz = 1.f/6.f*(m5-m6); // nz = 1.f/6.f*(m5-m6);
// //
// ElectricField[n] = nx; // ElectricField[n] = nx;
// ElectricField[Np+n] = ny; // ElectricField[Np+n] = ny;
// ElectricField[2*Np+n] = nz; // ElectricField[2*Np+n] = nz;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,3 @@
*/ */
// cpu implementation for thermal lattice boltzmann methods // cpu implementation for thermal lattice boltzmann methods
// copyright James McClure, 2014 // copyright James McClure, 2014

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,6 @@ Implementation of color lattice boltzmann model
#include "ProfilerApp.h" #include "ProfilerApp.h"
#include "threadpool/thread_pool.h" #include "threadpool/thread_pool.h"
#ifndef ScaLBL_ColorModel_INC #ifndef ScaLBL_ColorModel_INC
#define ScaLBL_ColorModel_INC #define ScaLBL_ColorModel_INC
@ -46,7 +45,7 @@ Implementation of color lattice boltzmann model
* Mass transport equations are described by D3Q7 scheme * Mass transport equations are described by D3Q7 scheme
*/ */
class ScaLBL_ColorModel{ class ScaLBL_ColorModel {
public: public:
/** /**
* \brief Constructor * \brief Constructor
@ -54,81 +53,81 @@ public:
* @param NP number of processors * @param NP number of processors
* @param COMM MPI communicator * @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();
/** /**
* \brief Read simulation parameters * \brief Read simulation parameters
* @param filename input database file that includes "Color" section * @param filename input database file that includes "Color" section
*/ */
void ReadParams(string filename); void ReadParams(string filename);
/** /**
* \brief Read simulation parameters * \brief Read simulation parameters
* @param db0 input database that includes "Color" section * @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 * \brief Create domain data structures
*/ */
void SetDomain(); void SetDomain();
/** /**
* \brief Read image data * \brief Read image data
*/ */
void ReadInput(); void ReadInput();
/** /**
* \brief Create color model data structures * \brief Create color model data structures
*/ */
void Create(); void Create();
/** /**
* \brief Initialize the simulation * \brief Initialize the simulation
*/ */
void Initialize(); void Initialize();
/** /**
* \brief Run the simulation * \brief Run the simulation
*/ */
void Run(); void Run();
/** /**
* \brief Run the simulation * \brief Run the simulation
* @param returntime - timestep at which the routine will return * @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 * \brief Debugging function to dump simulation state to disk
*/ */
void WriteDebug(); void WriteDebug();
/** /**
* \brief Copy the phase field for use by external methods * \brief Copy the phase field for use by external methods
* @param f - DoubleArray to hold the phase field * @param f - DoubleArray to hold the phase field
*/ */
void getPhaseField(DoubleArray &f); void getPhaseField(DoubleArray &f);
bool Restart,pBC;
bool REVERSE_FLOW_DIRECTION;
int timestep,timestepMax;
int BoundaryCondition;
double tauA,tauB,rhoA,rhoB,alpha,beta;
double Fx,Fy,Fz,flux;
double din,dout,inletA,inletB,outletA,outletB;
int Nx,Ny,Nz,N,Np;
int rank,nprocx,nprocy,nprocz,nprocs;
double Lx,Ly,Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis bool Restart, pBC;
std::shared_ptr<Domain> Mask; // this domain is for lbm bool REVERSE_FLOW_DIRECTION;
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm; int timestep, timestepMax;
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm_Regular; int BoundaryCondition;
double tauA, tauB, rhoA, rhoB, alpha, beta;
double Fx, Fy, Fz, flux;
double din, dout, inletA, inletB, outletA, outletB;
int Nx, Ny, Nz, N, Np;
int rank, nprocx, nprocy, nprocz, nprocs;
double Lx, Ly, Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis
std::shared_ptr<Domain> Mask; // this domain is for lbm
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm;
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm_Regular;
std::shared_ptr<SubPhase> Averages; std::shared_ptr<SubPhase> Averages;
// input database // input database
std::shared_ptr<Database> db; std::shared_ptr<Database> db;
std::shared_ptr<Database> domain_db; std::shared_ptr<Database> domain_db;
@ -137,33 +136,32 @@ public:
std::shared_ptr<Database> vis_db; std::shared_ptr<Database> vis_db;
IntArray Map; IntArray Map;
signed char *id; signed char *id;
int *NeighborList; int *NeighborList;
int *dvcMap; int *dvcMap;
double *fq, *Aq, *Bq; double *fq, *Aq, *Bq;
double *Den, *Phi; double *Den, *Phi;
double *ColorGrad; double *ColorGrad;
double *Velocity; double *Velocity;
double *Pressure; double *Pressure;
/** /**
* \brief Assign wetting affinity values * \brief Assign wetting affinity values
*/ */
void AssignComponentLabels(double *phase); void AssignComponentLabels(double *phase);
private:
Utilities::MPI comm;
int dist_mem_size; private:
int neighborSize; Utilities::MPI comm;
// filenames
int dist_mem_size;
int neighborSize;
// filenames
char LocalRankString[8]; char LocalRankString[8];
char LocalRankFilename[40]; char LocalRankFilename[40];
char LocalRestartFile[40]; char LocalRestartFile[40];
//int rank,nprocs; //int rank,nprocs;
void LoadParams(std::shared_ptr<Database> db0); void LoadParams(std::shared_ptr<Database> db0);
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -16,38 +16,38 @@ Implementation of color lattice boltzmann model
#include "ProfilerApp.h" #include "ProfilerApp.h"
#include "threadpool/thread_pool.h" #include "threadpool/thread_pool.h"
class ScaLBL_DFHModel{ class ScaLBL_DFHModel {
public: public:
ScaLBL_DFHModel(int RANK, int NP, const Utilities::MPI& COMM); ScaLBL_DFHModel(int RANK, int NP, const Utilities::MPI &COMM);
~ScaLBL_DFHModel(); ~ScaLBL_DFHModel();
// functions in they should be run
void ReadParams(string filename);
void ReadParams(std::shared_ptr<Database> db0);
void SetDomain();
void ReadInput();
void Create();
void Initialize();
void AssignSolidPotential();
void Run();
void WriteDebug();
bool Restart,pBC;
int timestep,timestepMax;
int BoundaryCondition;
double tauA,tauB,rhoA,rhoB,alpha,beta;
double Fx,Fy,Fz,flux;
double din,dout,inletA,inletB,outletA,outletB;
int Nx,Ny,Nz,N,Np;
int rank,nprocx,nprocy,nprocz,nprocs;
double Lx,Ly,Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis // functions in they should be run
std::shared_ptr<Domain> Mask; // this domain is for lbm void ReadParams(string filename);
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm; void ReadParams(std::shared_ptr<Database> db0);
void SetDomain();
void ReadInput();
void Create();
void Initialize();
void AssignSolidPotential();
void Run();
void WriteDebug();
bool Restart, pBC;
int timestep, timestepMax;
int BoundaryCondition;
double tauA, tauB, rhoA, rhoB, alpha, beta;
double Fx, Fy, Fz, flux;
double din, dout, inletA, inletB, outletA, outletB;
int Nx, Ny, Nz, N, Np;
int rank, nprocx, nprocy, nprocz, nprocs;
double Lx, Ly, Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis
std::shared_ptr<Domain> Mask; // this domain is for lbm
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm;
std::shared_ptr<TwoPhase> Averages; std::shared_ptr<TwoPhase> Averages;
// input database // input database
std::shared_ptr<Database> db; std::shared_ptr<Database> db;
std::shared_ptr<Database> domain_db; std::shared_ptr<Database> domain_db;
@ -64,20 +64,18 @@ public:
double *Velocity; double *Velocity;
double *Gradient; double *Gradient;
double *Pressure; double *Pressure;
private: private:
Utilities::MPI comm; Utilities::MPI comm;
int dist_mem_size; int dist_mem_size;
int neighborSize; int neighborSize;
// filenames // filenames
char LocalRankString[8]; char LocalRankString[8];
char LocalRankFilename[40]; char LocalRankFilename[40];
char LocalRestartFile[40]; char LocalRestartFile[40];
//int rank,nprocs; //int rank,nprocs;
void LoadParams(std::shared_ptr<Database> db0); void LoadParams(std::shared_ptr<Database> db0);
void AssignComponentLabels(double *phase); void AssignComponentLabels(double *phase);
}; };

File diff suppressed because it is too large Load Diff

View File

@ -19,50 +19,50 @@ Implementation of Lee et al JCP 2016 lattice boltzmann model
#ifndef ScaLBL_FreeLeeModel_INC #ifndef ScaLBL_FreeLeeModel_INC
#define ScaLBL_FreeLeeModel_INC #define ScaLBL_FreeLeeModel_INC
class ScaLBL_FreeLeeModel{ class ScaLBL_FreeLeeModel {
public: public:
ScaLBL_FreeLeeModel(int RANK, int NP, const Utilities::MPI& COMM); ScaLBL_FreeLeeModel(int RANK, int NP, const Utilities::MPI &COMM);
~ScaLBL_FreeLeeModel(); ~ScaLBL_FreeLeeModel();
// functions in they should be run
void ReadParams(string filename);
void ReadParams(std::shared_ptr<Database> db0);
void SetDomain();
void ReadInput();
void Create_TwoFluid();
void Initialize_TwoFluid();
double Run_TwoFluid(int returntime);
void WriteDebug_TwoFluid(); // functions in they should be run
void Create_SingleFluid(); void ReadParams(string filename);
void Initialize_SingleFluid(); void ReadParams(std::shared_ptr<Database> db0);
void Run_SingleFluid(); void SetDomain();
void ReadInput();
void WriteDebug_SingleFluid(); void Create_TwoFluid();
void Initialize_TwoFluid();
double Run_TwoFluid(int returntime);
void WriteDebug_TwoFluid();
void Create_SingleFluid();
void Initialize_SingleFluid();
void Run_SingleFluid();
void WriteDebug_SingleFluid();
// test utilities // test utilities
void Create_DummyPhase_MGTest(); void Create_DummyPhase_MGTest();
void MGTest(); void MGTest();
bool Restart,pBC;
int timestep,timestepMax;
int BoundaryCondition;
double tauA,tauB,rhoA,rhoB;
double tau, rho0;//only for single-fluid Lee model
double tauM;//relaxation time for phase field (or mass)
double W,gamma,kappa,beta;
double Fx,Fy,Fz,flux;
double din,dout,inletA,inletB,outletA,outletB;
int Nx,Ny,Nz,N,Np;
int Nxh,Nyh,Nzh,Nh; // extra halo width
int rank,nprocx,nprocy,nprocz,nprocs;
double Lx,Ly,Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis bool Restart, pBC;
std::shared_ptr<Domain> Mask; // this domain is for lbm int timestep, timestepMax;
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm; int BoundaryCondition;
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm_Regular; double tauA, tauB, rhoA, rhoB;
std::shared_ptr<ScaLBLWideHalo_Communicator> ScaLBL_Comm_WideHalo; double tau, rho0; //only for single-fluid Lee model
double tauM; //relaxation time for phase field (or mass)
double W, gamma, kappa, beta;
double Fx, Fy, Fz, flux;
double din, dout, inletA, inletB, outletA, outletB;
int Nx, Ny, Nz, N, Np;
int Nxh, Nyh, Nzh, Nh; // extra halo width
int rank, nprocx, nprocy, nprocz, nprocs;
double Lx, Ly, Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis
std::shared_ptr<Domain> Mask; // this domain is for lbm
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm;
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm_Regular;
std::shared_ptr<ScaLBLWideHalo_Communicator> ScaLBL_Comm_WideHalo;
// input database // input database
std::shared_ptr<Database> db; std::shared_ptr<Database> db;
@ -72,35 +72,34 @@ public:
std::shared_ptr<Database> vis_db; std::shared_ptr<Database> vis_db;
IntArray Map; IntArray Map;
signed char *id; signed char *id;
int *NeighborList; int *NeighborList;
int *dvcMap; int *dvcMap;
double *gqbar, *hq; double *gqbar, *hq;
double *mu_phi, *Den, *Phi; double *mu_phi, *Den, *Phi;
double *ColorGrad; double *ColorGrad;
double *Velocity; double *Velocity;
double *Pressure; double *Pressure;
void getPhase(DoubleArray &PhaseValues); void getPhase(DoubleArray &PhaseValues);
void getPotential(DoubleArray &PressureValues, DoubleArray &MuValues); void getPotential(DoubleArray &PressureValues, DoubleArray &MuValues);
void getVelocity(DoubleArray &Vx, DoubleArray &Vy, DoubleArray &Vz); void getVelocity(DoubleArray &Vx, DoubleArray &Vy, DoubleArray &Vz);
void getData_RegularLayout(const double *data, DoubleArray &regdata); void getData_RegularLayout(const double *data, DoubleArray &regdata);
DoubleArray SignDist; DoubleArray SignDist;
private: private:
Utilities::MPI comm; Utilities::MPI comm;
int dist_mem_size; int dist_mem_size;
int neighborSize; int neighborSize;
// filenames // filenames
char LocalRankString[8]; char LocalRankString[8];
char LocalRankFilename[40]; char LocalRankFilename[40];
char LocalRestartFile[40]; char LocalRestartFile[40];
//int rank,nprocs; //int rank,nprocs;
void LoadParams(std::shared_ptr<Database> db0); void LoadParams(std::shared_ptr<Database> db0);
void AssignComponentLabels_ChemPotential_ColorGrad(); void AssignComponentLabels_ChemPotential_ColorGrad();
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -25,8 +25,7 @@ Implementation of two-fluid greyscale color lattice boltzmann model
* Mass transport equations are described by D3Q7 scheme * Mass transport equations are described by D3Q7 scheme
*/ */
class ScaLBL_GreyscaleColorModel {
class ScaLBL_GreyscaleColorModel{
public: public:
/** /**
* \brief Constructor * \brief Constructor
@ -34,75 +33,76 @@ public:
* @param NP number of processors * @param NP number of processors
* @param COMM MPI communicator * @param COMM MPI communicator
*/ */
ScaLBL_GreyscaleColorModel(int RANK, int NP, const Utilities::MPI& COMM); ScaLBL_GreyscaleColorModel(int RANK, int NP, const Utilities::MPI &COMM);
~ScaLBL_GreyscaleColorModel(); ~ScaLBL_GreyscaleColorModel();
// functions in they should be run // functions in they should be run
/** /**
* \brief Read simulation parameters * \brief Read simulation parameters
* @param filename input database file that includes "Color" section * @param filename input database file that includes "Color" section
*/ */
void ReadParams(string filename); void ReadParams(string filename);
/** /**
* \brief Read simulation parameters * \brief Read simulation parameters
* @param db0 input database that includes "Color" section * @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 * \brief Create domain data structures
*/ */
void SetDomain(); void SetDomain();
/** /**
* \brief Read image data * \brief Read image data
*/ */
void ReadInput(); void ReadInput();
/** /**
* \brief Create color model data structures * \brief Create color model data structures
*/ */
void Create(); void Create();
/** /**
* \brief Initialize the simulation * \brief Initialize the simulation
*/ */
void Initialize(); void Initialize();
/** /**
* \brief Run the simulation * \brief Run the simulation
*/ */
void Run(); void Run();
/** /**
* \brief Debugging function to dump simulation state to disk * \brief Debugging function to dump simulation state to disk
*/ */
void WriteDebug(); void WriteDebug();
void WriteVisFiles(); void WriteVisFiles();
bool Restart,pBC;
bool REVERSE_FLOW_DIRECTION;
int timestep,timestepMax;
int BoundaryCondition;
double tauA,tauB,rhoA,rhoB,alpha,beta;
double tauA_eff,tauB_eff;
double Fx,Fy,Fz,flux;
double din,dout,inletA,inletB,outletA,outletB;
double GreyPorosity;
bool RecoloringOff;//recoloring can be turn off for grey nodes if this is true
//double W;//wetting strength paramter for capillary pressure penalty for grey nodes
int Nx,Ny,Nz,N,Np;
int rank,nprocx,nprocy,nprocz,nprocs;
double Lx,Ly,Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis bool Restart, pBC;
std::shared_ptr<Domain> Mask; // this domain is for lbm bool REVERSE_FLOW_DIRECTION;
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm; int timestep, timestepMax;
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm_Regular; int BoundaryCondition;
double tauA, tauB, rhoA, rhoB, alpha, beta;
double tauA_eff, tauB_eff;
double Fx, Fy, Fz, flux;
double din, dout, inletA, inletB, outletA, outletB;
double GreyPorosity;
bool
RecoloringOff; //recoloring can be turn off for grey nodes if this is true
//double W;//wetting strength paramter for capillary pressure penalty for grey nodes
int Nx, Ny, Nz, N, Np;
int rank, nprocx, nprocy, nprocz, nprocs;
double Lx, Ly, Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis
std::shared_ptr<Domain> Mask; // this domain is for lbm
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm;
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm_Regular;
std::shared_ptr<GreyPhaseAnalysis> Averages; std::shared_ptr<GreyPhaseAnalysis> Averages;
// input database // input database
std::shared_ptr<Database> db; std::shared_ptr<Database> db;
std::shared_ptr<Database> domain_db; std::shared_ptr<Database> domain_db;
@ -111,11 +111,11 @@ public:
std::shared_ptr<Database> vis_db; std::shared_ptr<Database> vis_db;
IntArray Map; IntArray Map;
signed char *id; signed char *id;
int *NeighborList; int *NeighborList;
int *dvcMap; int *dvcMap;
double *fq, *Aq, *Bq; double *fq, *Aq, *Bq;
double *Den, *Phi; double *Den, *Phi;
//double *GreySolidPhi; //Model 2 & 3 //double *GreySolidPhi; //Model 2 & 3
//double *GreySolidGrad;//Model 1 & 4 //double *GreySolidGrad;//Model 1 & 4
double *GreySolidW; double *GreySolidW;
@ -123,31 +123,31 @@ public:
double *GreySw; double *GreySw;
double *GreyKn; double *GreyKn;
double *GreyKw; double *GreyKw;
double *MobilityRatio; double *MobilityRatio;
double *Velocity; double *Velocity;
double *Pressure; double *Pressure;
double *Porosity_dvc; double *Porosity_dvc;
double *Permeability_dvc; double *Permeability_dvc;
//double *Psi; //double *Psi;
private: private:
Utilities::MPI comm; Utilities::MPI comm;
int dist_mem_size; int dist_mem_size;
int neighborSize; int neighborSize;
// filenames // filenames
char LocalRankString[8]; char LocalRankString[8];
char LocalRankFilename[40]; char LocalRankFilename[40];
char LocalRestartFile[40]; char LocalRestartFile[40];
//int rank,nprocs; //int rank,nprocs;
void LoadParams(std::shared_ptr<Database> db0); void LoadParams(std::shared_ptr<Database> db0);
/** /**
* \brief Assign wetting affinity values * \brief Assign wetting affinity values
*/ */
void AssignComponentLabels(); void AssignComponentLabels();
/** /**
* \brief Assign wetting affinity values in greyscale regions * \brief Assign wetting affinity values in greyscale regions
*/ */
@ -161,4 +161,3 @@ private:
*/ */
double SeedPhaseField(const double seed_water_in_oil); double SeedPhaseField(const double seed_water_in_oil);
}; };

File diff suppressed because it is too large Load Diff

View File

@ -31,43 +31,43 @@
#include "ProfilerApp.h" #include "ProfilerApp.h"
#include "threadpool/thread_pool.h" #include "threadpool/thread_pool.h"
class ScaLBL_GreyscaleModel{ class ScaLBL_GreyscaleModel {
public: public:
ScaLBL_GreyscaleModel(int RANK, int NP, const Utilities::MPI& COMM); ScaLBL_GreyscaleModel(int RANK, int NP, const Utilities::MPI &COMM);
~ScaLBL_GreyscaleModel(); ~ScaLBL_GreyscaleModel();
// functions in they should be run // functions in they should be run
void ReadParams(string filename); void ReadParams(string filename);
void ReadParams(std::shared_ptr<Database> db0); void ReadParams(std::shared_ptr<Database> db0);
void SetDomain(); void SetDomain();
void ReadInput(); void ReadInput();
void Create(); void Create();
void Initialize(); void Initialize();
void Run(); void Run();
void WriteDebug(); void WriteDebug();
void VelocityField(); void VelocityField();
bool Restart,pBC; bool Restart, pBC;
int timestep,timestepMax; int timestep, timestepMax;
int BoundaryCondition; int BoundaryCondition;
int CollisionType; int CollisionType;
double tau; double tau;
double tau_eff; double tau_eff;
double Den;//constant density double Den; //constant density
double tolerance; double tolerance;
double Fx,Fy,Fz,flux; double Fx, Fy, Fz, flux;
double din,dout; double din, dout;
double dp;//solid particle diameter, unit in voxel double dp; //solid particle diameter, unit in voxel
double GreyPorosity; double GreyPorosity;
int Nx,Ny,Nz,N,Np; int Nx, Ny, Nz, N, Np;
int rank,nprocx,nprocy,nprocz,nprocs; int rank, nprocx, nprocy, nprocz, nprocs;
double Lx,Ly,Lz; double Lx, Ly, Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis
std::shared_ptr<Domain> Mask; // this domain is for lbm
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm;
std::shared_ptr<Domain> Dm; // this domain is for analysis
std::shared_ptr<Domain> Mask; // this domain is for lbm
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm;
// input database // input database
std::shared_ptr<Database> db; std::shared_ptr<Database> db;
std::shared_ptr<Database> domain_db; std::shared_ptr<Database> domain_db;
@ -75,13 +75,13 @@ public:
std::shared_ptr<Database> analysis_db; std::shared_ptr<Database> analysis_db;
std::shared_ptr<Database> vis_db; std::shared_ptr<Database> vis_db;
signed char *id; signed char *id;
int *NeighborList; int *NeighborList;
double *fq; double *fq;
double *Permeability;//grey voxel permeability double *Permeability; //grey voxel permeability
double *Porosity; double *Porosity;
double *Velocity; double *Velocity;
double *Pressure_dvc; double *Pressure_dvc;
IntArray Map; IntArray Map;
DoubleArray SignDist; DoubleArray SignDist;
DoubleArray Velocity_x; DoubleArray Velocity_x;
@ -89,18 +89,19 @@ public:
DoubleArray Velocity_z; DoubleArray Velocity_z;
DoubleArray PorosityMap; DoubleArray PorosityMap;
DoubleArray Pressure; DoubleArray Pressure;
private: private:
Utilities::MPI comm; Utilities::MPI comm;
int dist_mem_size; int dist_mem_size;
int neighborSize; int neighborSize;
// filenames // filenames
char LocalRankString[8]; char LocalRankString[8];
char LocalRankFilename[40]; char LocalRankFilename[40];
char LocalRestartFile[40]; char LocalRestartFile[40];
void AssignComponentLabels(double *Porosity, double *Permeablity);
void AssignComponentLabels(double *Porosity,double *Permeability,const vector<std::string> &File_poro,const vector<std::string> &File_perm);
};
void AssignComponentLabels(double *Porosity, double *Permeablity);
void AssignComponentLabels(double *Porosity, double *Permeability,
const vector<std::string> &File_poro,
const vector<std::string> &File_perm);
};

File diff suppressed because it is too large Load Diff

View File

@ -20,25 +20,28 @@
#include "analysis/Minkowski.h" #include "analysis/Minkowski.h"
#include "ProfilerApp.h" #include "ProfilerApp.h"
class ScaLBL_IonModel{ class ScaLBL_IonModel {
public: public:
ScaLBL_IonModel(int RANK, int NP, const Utilities::MPI& COMM); ScaLBL_IonModel(int RANK, int NP, const Utilities::MPI &COMM);
~ScaLBL_IonModel(); ~ScaLBL_IonModel();
// functions in they should be run // functions in they should be run
void ReadParams(string filename,vector<int> &num_iter); void ReadParams(string filename, vector<int> &num_iter);
void ReadParams(string filename); void ReadParams(string filename);
void ReadParams(std::shared_ptr<Database> db0); void ReadParams(std::shared_ptr<Database> db0);
void SetDomain(); void SetDomain();
void ReadInput(); void ReadInput();
void Create(); void Create();
void Initialize(); void Initialize();
void Run(double *Velocity, double *ElectricField); void Run(double *Velocity, double *ElectricField);
void getIonConcentration(DoubleArray &IonConcentration, const size_t ic); void getIonConcentration(DoubleArray &IonConcentration, const size_t ic);
void getIonConcentration_debug(int timestep); void getIonConcentration_debug(int timestep);
void getIonFluxDiffusive(DoubleArray &IonFlux_x,DoubleArray &IonFlux_y,DoubleArray &IonFlux_z,const size_t ic); void getIonFluxDiffusive(DoubleArray &IonFlux_x, DoubleArray &IonFlux_y,
void getIonFluxAdvective(DoubleArray &IonFlux_x,DoubleArray &IonFlux_y,DoubleArray &IonFlux_z,const size_t ic); DoubleArray &IonFlux_z, const size_t ic);
void getIonFluxElectrical(DoubleArray &IonFlux_x,DoubleArray &IonFlux_y,DoubleArray &IonFlux_z,const size_t ic); void getIonFluxAdvective(DoubleArray &IonFlux_x, DoubleArray &IonFlux_y,
DoubleArray &IonFlux_z, const size_t ic);
void getIonFluxElectrical(DoubleArray &IonFlux_x, DoubleArray &IonFlux_y,
DoubleArray &IonFlux_z, const size_t ic);
void getIonFluxDiffusive_debug(int timestep); void getIonFluxDiffusive_debug(int timestep);
void getIonFluxAdvective_debug(int timestep); void getIonFluxAdvective_debug(int timestep);
void getIonFluxElectrical_debug(int timestep); void getIonFluxElectrical_debug(int timestep);
@ -46,35 +49,37 @@ public:
void DummyElectricField(); void DummyElectricField();
double CalIonDenConvergence(vector<double> &ci_avg_previous); double CalIonDenConvergence(vector<double> &ci_avg_previous);
//bool Restart,pBC; //bool Restart,pBC;
int timestep; int timestep;
vector<int> timestepMax; vector<int> timestepMax;
int BoundaryConditionSolid; int BoundaryConditionSolid;
double h;//domain resolution, unit [um/lu] double h; //domain resolution, unit [um/lu]
double kb,electron_charge,T,Vt; double kb, electron_charge, T, Vt;
double k2_inv; double k2_inv;
double tolerance; double tolerance;
double fluidVelx_dummy,fluidVely_dummy,fluidVelz_dummy; double fluidVelx_dummy, fluidVely_dummy, fluidVelz_dummy;
double Ex_dummy,Ey_dummy,Ez_dummy; double Ex_dummy, Ey_dummy, Ez_dummy;
size_t number_ion_species;
vector<int> BoundaryConditionInlet;
vector<int> BoundaryConditionOutlet;
vector<double> IonDiffusivity;//User input unit [m^2/sec]
vector<int> IonValence;
vector<double> IonConcentration;//unit [mol/m^3]
vector<double> Cin;//inlet boundary value, can be either concentration [mol/m^3] or flux [mol/m^2/sec]
vector<double> Cout;//outlet boundary value, can be either concentration [mol/m^3] or flux [mol/m^2/sec]
vector<double> tau;
vector<double> time_conv;
int Nx,Ny,Nz,N,Np;
int rank,nprocx,nprocy,nprocz,nprocs;
double Lx,Ly,Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis size_t number_ion_species;
std::shared_ptr<Domain> Mask; // this domain is for lbm vector<int> BoundaryConditionInlet;
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm; vector<int> BoundaryConditionOutlet;
vector<double> IonDiffusivity; //User input unit [m^2/sec]
vector<int> IonValence;
vector<double> IonConcentration; //unit [mol/m^3]
vector<double>
Cin; //inlet boundary value, can be either concentration [mol/m^3] or flux [mol/m^2/sec]
vector<double>
Cout; //outlet boundary value, can be either concentration [mol/m^3] or flux [mol/m^2/sec]
vector<double> tau;
vector<double> time_conv;
int Nx, Ny, Nz, N, Np;
int rank, nprocx, nprocy, nprocz, nprocs;
double Lx, Ly, Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis
std::shared_ptr<Domain> Mask; // this domain is for lbm
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm;
// input database // input database
std::shared_ptr<Database> db; std::shared_ptr<Database> db;
std::shared_ptr<Database> domain_db; std::shared_ptr<Database> domain_db;
@ -84,8 +89,8 @@ public:
DoubleArray Distance; DoubleArray Distance;
int *NeighborList; int *NeighborList;
double *fq; double *fq;
double *Ci; double *Ci;
double *ChargeDensity; double *ChargeDensity;
double *IonSolid; double *IonSolid;
double *FluidVelocityDummy; double *FluidVelocityDummy;
double *ElectricFieldDummy; double *ElectricFieldDummy;
@ -94,18 +99,20 @@ public:
double *FluxElectrical; double *FluxElectrical;
private: private:
Utilities::MPI comm; Utilities::MPI comm;
// filenames // filenames
char LocalRankString[8]; char LocalRankString[8];
char LocalRankFilename[40]; char LocalRankFilename[40];
char LocalRestartFile[40]; char LocalRestartFile[40];
char OutputFilename[200]; char OutputFilename[200];
//int rank,nprocs; //int rank,nprocs;
void LoadParams(std::shared_ptr<Database> db0); void LoadParams(std::shared_ptr<Database> db0);
void AssignSolidBoundary(double *ion_solid); void AssignSolidBoundary(double *ion_solid);
void AssignIonConcentration_FromFile(double *Ci,const vector<std::string> &File_ion,int ic); void AssignIonConcentration_FromFile(double *Ci,
const vector<std::string> &File_ion,
int ic);
void IonConcentration_LB_to_Phys(DoubleArray &Den_reg); void IonConcentration_LB_to_Phys(DoubleArray &Den_reg);
void IonFlux_LB_to_Phys(DoubleArray &Den_reg, const size_t ic); void IonFlux_LB_to_Phys(DoubleArray &Den_reg, const size_t ic);
}; };

View File

@ -20,375 +20,408 @@
#include "models/MRTModel.h" #include "models/MRTModel.h"
#include "analysis/distance.h" #include "analysis/distance.h"
#include "common/ReadMicroCT.h" #include "common/ReadMicroCT.h"
ScaLBL_MRTModel::ScaLBL_MRTModel(int RANK, int NP, const Utilities::MPI& COMM): ScaLBL_MRTModel::ScaLBL_MRTModel(int RANK, int NP, const Utilities::MPI &COMM)
rank(RANK), nprocs(NP), Restart(0),timestep(0),timestepMax(0),tau(0), : rank(RANK), nprocs(NP), Restart(0), timestep(0), timestepMax(0), tau(0),
Fx(0),Fy(0),Fz(0),flux(0),din(0),dout(0),mu(0), Fx(0), Fy(0), Fz(0), flux(0), din(0), dout(0), mu(0), Nx(0), Ny(0), Nz(0),
Nx(0),Ny(0),Nz(0),N(0),Np(0),nprocx(0),nprocy(0),nprocz(0),BoundaryCondition(0),Lx(0),Ly(0),Lz(0),comm(COMM) N(0), Np(0), nprocx(0), nprocy(0), nprocz(0), BoundaryCondition(0), Lx(0),
{ Ly(0), Lz(0), comm(COMM) {}
ScaLBL_MRTModel::~ScaLBL_MRTModel() {}
} void ScaLBL_MRTModel::ReadParams(string filename) {
ScaLBL_MRTModel::~ScaLBL_MRTModel(){ // read the input database
db = std::make_shared<Database>(filename);
domain_db = db->getDatabase("Domain");
mrt_db = db->getDatabase("MRT");
vis_db = db->getDatabase("Visualization");
} tau = 1.0;
timestepMax = 100000;
tolerance = 1.0e-8;
Fx = Fy = 0.0;
Fz = 1.0e-5;
dout = 1.0;
din = 1.0;
void ScaLBL_MRTModel::ReadParams(string filename){ // Color Model parameters
// read the input database if (mrt_db->keyExists("timestepMax")) {
db = std::make_shared<Database>( filename ); timestepMax = mrt_db->getScalar<int>("timestepMax");
domain_db = db->getDatabase( "Domain" );
mrt_db = db->getDatabase( "MRT" );
vis_db = db->getDatabase( "Visualization" );
tau = 1.0;
timestepMax = 100000;
tolerance = 1.0e-8;
Fx = Fy = 0.0;
Fz = 1.0e-5;
dout = 1.0;
din = 1.0;
// Color Model parameters
if (mrt_db->keyExists( "timestepMax" )){
timestepMax = mrt_db->getScalar<int>( "timestepMax" );
}
if (mrt_db->keyExists( "tolerance" )){
tolerance = mrt_db->getScalar<double>( "tolerance" );
}
if (mrt_db->keyExists( "tau" )){
tau = mrt_db->getScalar<double>( "tau" );
}
if (mrt_db->keyExists( "F" )){
Fx = mrt_db->getVector<double>( "F" )[0];
Fy = mrt_db->getVector<double>( "F" )[1];
Fz = mrt_db->getVector<double>( "F" )[2];
}
if (mrt_db->keyExists( "Restart" )){
Restart = mrt_db->getScalar<bool>( "Restart" );
}
if (mrt_db->keyExists( "din" )){
din = mrt_db->getScalar<double>( "din" );
}
if (mrt_db->keyExists( "dout" )){
dout = mrt_db->getScalar<double>( "dout" );
}
if (mrt_db->keyExists( "flux" )){
flux = mrt_db->getScalar<double>( "flux" );
}
// Read domain parameters
if (mrt_db->keyExists( "BoundaryCondition" )){
BoundaryCondition = mrt_db->getScalar<int>( "BC" );
}
else if (domain_db->keyExists( "BC" )){
BoundaryCondition = domain_db->getScalar<int>( "BC" );
}
mu=(tau-0.5)/3.0;
}
void ScaLBL_MRTModel::SetDomain(){
Dm = std::shared_ptr<Domain>(new Domain(domain_db,comm)); // full domain for analysis
Mask = std::shared_ptr<Domain>(new Domain(domain_db,comm)); // mask domain removes immobile phases
// domain parameters
Nx = Dm->Nx;
Ny = Dm->Ny;
Nz = Dm->Nz;
Lx = Dm->Lx;
Ly = Dm->Ly;
Lz = Dm->Lz;
N = Nx*Ny*Nz;
Distance.resize(Nx,Ny,Nz);
Velocity_x.resize(Nx,Ny,Nz);
Velocity_y.resize(Nx,Ny,Nz);
Velocity_z.resize(Nx,Ny,Nz);
for (int i=0; i<Nx*Ny*Nz; i++) Dm->id[i] = 1; // initialize this way
//Averages = std::shared_ptr<TwoPhase> ( new TwoPhase(Dm) ); // TwoPhase analysis object
comm.barrier();
Dm->CommInit();
comm.barrier();
rank = Dm->rank();
nprocx = Dm->nprocx();
nprocy = Dm->nprocy();
nprocz = Dm->nprocz();
}
void ScaLBL_MRTModel::ReadInput(){
sprintf(LocalRankString,"%05d",Dm->rank());
sprintf(LocalRankFilename,"%s%s","ID.",LocalRankString);
sprintf(LocalRestartFile,"%s%s","Restart.",LocalRankString);
if (domain_db->keyExists( "Filename" )){
auto Filename = domain_db->getScalar<std::string>( "Filename" );
Mask->Decomp(Filename);
} }
else if (domain_db->keyExists( "GridFile" )){ if (mrt_db->keyExists("tolerance")) {
// Read the local domain data tolerance = mrt_db->getScalar<double>("tolerance");
auto input_id = readMicroCT( *domain_db, comm );
// Fill the halo (assuming GCW of 1)
array<int,3> size0 = { (int) input_id.size(0), (int) input_id.size(1), (int) input_id.size(2) };
ArraySize size1 = { (size_t) Mask->Nx, (size_t) Mask->Ny, (size_t) Mask->Nz };
ASSERT( (int) size1[0] == size0[0]+2 && (int) size1[1] == size0[1]+2 && (int) size1[2] == size0[2]+2 );
fillHalo<signed char> fill( comm, Mask->rank_info, size0, { 1, 1, 1 }, 0, 1 );
Array<signed char> id_view;
id_view.viewRaw( size1, Mask->id.data() );
fill.copy( input_id, id_view );
fill.fill( id_view );
} }
else{ if (mrt_db->keyExists("tau")) {
Mask->ReadIDs(); tau = mrt_db->getScalar<double>("tau");
}
if (mrt_db->keyExists("F")) {
Fx = mrt_db->getVector<double>("F")[0];
Fy = mrt_db->getVector<double>("F")[1];
Fz = mrt_db->getVector<double>("F")[2];
}
if (mrt_db->keyExists("Restart")) {
Restart = mrt_db->getScalar<bool>("Restart");
}
if (mrt_db->keyExists("din")) {
din = mrt_db->getScalar<double>("din");
}
if (mrt_db->keyExists("dout")) {
dout = mrt_db->getScalar<double>("dout");
}
if (mrt_db->keyExists("flux")) {
flux = mrt_db->getScalar<double>("flux");
}
// Read domain parameters
if (mrt_db->keyExists("BoundaryCondition")) {
BoundaryCondition = mrt_db->getScalar<int>("BC");
} else if (domain_db->keyExists("BC")) {
BoundaryCondition = domain_db->getScalar<int>("BC");
}
mu = (tau - 0.5) / 3.0;
}
void ScaLBL_MRTModel::SetDomain() {
Dm = std::shared_ptr<Domain>(
new Domain(domain_db, comm)); // full domain for analysis
Mask = std::shared_ptr<Domain>(
new Domain(domain_db, comm)); // mask domain removes immobile phases
// domain parameters
Nx = Dm->Nx;
Ny = Dm->Ny;
Nz = Dm->Nz;
Lx = Dm->Lx;
Ly = Dm->Ly;
Lz = Dm->Lz;
N = Nx * Ny * Nz;
Distance.resize(Nx, Ny, Nz);
Velocity_x.resize(Nx, Ny, Nz);
Velocity_y.resize(Nx, Ny, Nz);
Velocity_z.resize(Nx, Ny, Nz);
for (int i = 0; i < Nx * Ny * Nz; i++)
Dm->id[i] = 1; // initialize this way
//Averages = std::shared_ptr<TwoPhase> ( new TwoPhase(Dm) ); // TwoPhase analysis object
comm.barrier();
Dm->CommInit();
comm.barrier();
rank = Dm->rank();
nprocx = Dm->nprocx();
nprocy = Dm->nprocy();
nprocz = Dm->nprocz();
}
void ScaLBL_MRTModel::ReadInput() {
sprintf(LocalRankString, "%05d", Dm->rank());
sprintf(LocalRankFilename, "%s%s", "ID.", LocalRankString);
sprintf(LocalRestartFile, "%s%s", "Restart.", LocalRankString);
if (domain_db->keyExists("Filename")) {
auto Filename = domain_db->getScalar<std::string>("Filename");
Mask->Decomp(Filename);
} else if (domain_db->keyExists("GridFile")) {
// Read the local domain data
auto input_id = readMicroCT(*domain_db, comm);
// Fill the halo (assuming GCW of 1)
array<int, 3> size0 = {(int)input_id.size(0), (int)input_id.size(1),
(int)input_id.size(2)};
ArraySize size1 = {(size_t)Mask->Nx, (size_t)Mask->Ny,
(size_t)Mask->Nz};
ASSERT((int)size1[0] == size0[0] + 2 && (int)size1[1] == size0[1] + 2 &&
(int)size1[2] == size0[2] + 2);
fillHalo<signed char> fill(comm, Mask->rank_info, size0, {1, 1, 1}, 0,
1);
Array<signed char> id_view;
id_view.viewRaw(size1, Mask->id.data());
fill.copy(input_id, id_view);
fill.fill(id_view);
} else {
Mask->ReadIDs();
} }
// Generate the signed distance map // Generate the signed distance map
// Initialize the domain and communication // Initialize the domain and communication
Array<char> id_solid(Nx,Ny,Nz); Array<char> id_solid(Nx, Ny, Nz);
// Solve for the position of the solid phase // Solve for the position of the solid phase
for (int k=0;k<Nz;k++){ for (int k = 0; k < Nz; k++) {
for (int j=0;j<Ny;j++){ for (int j = 0; j < Ny; j++) {
for (int i=0;i<Nx;i++){ for (int i = 0; i < Nx; i++) {
int n = k*Nx*Ny+j*Nx+i; int n = k * Nx * Ny + j * Nx + i;
// Initialize the solid phase // Initialize the solid phase
if (Mask->id[n] > 0) id_solid(i,j,k) = 1; if (Mask->id[n] > 0)
else id_solid(i,j,k) = 0; id_solid(i, j, k) = 1;
} else
} id_solid(i, j, k) = 0;
} }
// Initialize the signed distance function }
for (int k=0;k<Nz;k++){ }
for (int j=0;j<Ny;j++){ // Initialize the signed distance function
for (int i=0;i<Nx;i++){ for (int k = 0; k < Nz; k++) {
// Initialize distance to +/- 1 for (int j = 0; j < Ny; j++) {
Distance(i,j,k) = 2.0*double(id_solid(i,j,k))-1.0; for (int i = 0; i < Nx; i++) {
} // Initialize distance to +/- 1
} Distance(i, j, k) = 2.0 * double(id_solid(i, j, k)) - 1.0;
} }
// MeanFilter(Averages->SDs); }
if (rank==0) printf("Initialized solid phase -- Converting to Signed Distance function \n"); }
CalcDist(Distance,id_solid,*Dm); // MeanFilter(Averages->SDs);
if (rank == 0) cout << "Domain set." << endl; if (rank == 0)
printf("Initialized solid phase -- Converting to Signed Distance "
"function \n");
CalcDist(Distance, id_solid, *Dm);
if (rank == 0)
cout << "Domain set." << endl;
} }
void ScaLBL_MRTModel::Create(){ void ScaLBL_MRTModel::Create() {
/* /*
* This function creates the variables needed to run a LBM * This function creates the variables needed to run a LBM
*/ */
int rank=Mask->rank(); int rank = Mask->rank();
//......................................................... //.........................................................
// Initialize communication structures in averaging domain // Initialize communication structures in averaging domain
for (int i=0; i<Nx*Ny*Nz; i++) Dm->id[i] = Mask->id[i]; for (int i = 0; i < Nx * Ny * Nz; i++)
Mask->CommInit(); Dm->id[i] = Mask->id[i];
Np=Mask->PoreCount(); Mask->CommInit();
//........................................................................... Np = Mask->PoreCount();
if (rank==0) printf ("Create ScaLBL_Communicator \n"); //...........................................................................
// Create a communicator for the device (will use optimized layout) if (rank == 0)
// ScaLBL_Communicator ScaLBL_Comm(Mask); // original printf("Create ScaLBL_Communicator \n");
ScaLBL_Comm = std::shared_ptr<ScaLBL_Communicator>(new ScaLBL_Communicator(Mask)); // Create a communicator for the device (will use optimized layout)
// ScaLBL_Communicator ScaLBL_Comm(Mask); // original
ScaLBL_Comm =
std::shared_ptr<ScaLBL_Communicator>(new ScaLBL_Communicator(Mask));
int Npad=(Np/16 + 2)*16; int Npad = (Np / 16 + 2) * 16;
if (rank==0) printf ("Set up memory efficient layout \n"); if (rank == 0)
Map.resize(Nx,Ny,Nz); Map.fill(-2); printf("Set up memory efficient layout \n");
auto neighborList= new int[18*Npad]; Map.resize(Nx, Ny, Nz);
Np = ScaLBL_Comm->MemoryOptimizedLayoutAA(Map,neighborList,Mask->id.data(),Np,1); Map.fill(-2);
comm.barrier(); auto neighborList = new int[18 * Npad];
Np = ScaLBL_Comm->MemoryOptimizedLayoutAA(Map, neighborList,
Mask->id.data(), Np, 1);
comm.barrier();
//........................................................................... //...........................................................................
// MAIN VARIABLES ALLOCATED HERE // MAIN VARIABLES ALLOCATED HERE
//........................................................................... //...........................................................................
// LBM variables // LBM variables
if (rank==0) printf ("Allocating distributions \n"); if (rank == 0)
//......................device distributions................................. printf("Allocating distributions \n");
int dist_mem_size = Np*sizeof(double); //......................device distributions.................................
int neighborSize=18*(Np*sizeof(int)); int dist_mem_size = Np * sizeof(double);
//........................................................................... int neighborSize = 18 * (Np * sizeof(int));
ScaLBL_AllocateDeviceMemory((void **) &NeighborList, neighborSize); //...........................................................................
ScaLBL_AllocateDeviceMemory((void **) &fq, 19*dist_mem_size); ScaLBL_AllocateDeviceMemory((void **)&NeighborList, neighborSize);
ScaLBL_AllocateDeviceMemory((void **) &Pressure, sizeof(double)*Np); ScaLBL_AllocateDeviceMemory((void **)&fq, 19 * dist_mem_size);
ScaLBL_AllocateDeviceMemory((void **) &Velocity, 3*sizeof(double)*Np); ScaLBL_AllocateDeviceMemory((void **)&Pressure, sizeof(double) * Np);
//........................................................................... ScaLBL_AllocateDeviceMemory((void **)&Velocity, 3 * sizeof(double) * Np);
// Update GPU data structures //...........................................................................
if (rank==0) printf ("Setting up device map and neighbor list \n"); // Update GPU data structures
// copy the neighbor list if (rank == 0)
ScaLBL_CopyToDevice(NeighborList, neighborList, neighborSize); printf("Setting up device map and neighbor list \n");
comm.barrier(); // copy the neighbor list
double MLUPS = ScaLBL_Comm->GetPerformance(NeighborList,fq,Np); ScaLBL_CopyToDevice(NeighborList, neighborList, neighborSize);
printf(" MLPUS=%f from rank %i\n",MLUPS,rank); comm.barrier();
} double MLUPS = ScaLBL_Comm->GetPerformance(NeighborList, fq, Np);
printf(" MLPUS=%f from rank %i\n", MLUPS, rank);
}
void ScaLBL_MRTModel::Initialize(){ void ScaLBL_MRTModel::Initialize() {
/* /*
* This function initializes model * This function initializes model
*/ */
if (rank==0) printf ("Initializing distributions \n"); if (rank == 0)
printf("Initializing distributions \n");
ScaLBL_D3Q19_Init(fq, Np); ScaLBL_D3Q19_Init(fq, Np);
} }
void ScaLBL_MRTModel::Run(){ void ScaLBL_MRTModel::Run() {
double rlx_setA=1.0/tau; double rlx_setA = 1.0 / tau;
double rlx_setB = 8.f*(2.f-rlx_setA)/(8.f-rlx_setA); double rlx_setB = 8.f * (2.f - rlx_setA) / (8.f - rlx_setA);
Minkowski Morphology(Mask);
if (rank==0){ Minkowski Morphology(Mask);
bool WriteHeader=false;
FILE *log_file = fopen("Permeability.csv","r");
if (log_file != NULL)
fclose(log_file);
else
WriteHeader=true;
if (WriteHeader){ if (rank == 0) {
log_file = fopen("Permeability.csv","a+"); bool WriteHeader = false;
fprintf(log_file,"time Fx Fy Fz mu Vs As Js Xs vx vy vz k\n"); FILE *log_file = fopen("Permeability.csv", "r");
fclose(log_file); if (log_file != NULL)
} fclose(log_file);
} else
WriteHeader = true;
//.......create and start timer............ if (WriteHeader) {
ScaLBL_DeviceBarrier(); comm.barrier(); log_file = fopen("Permeability.csv", "a+");
if (rank==0) printf("Beginning AA timesteps, timestepMax = %i \n", timestepMax); fprintf(log_file, "time Fx Fy Fz mu Vs As Js Xs vx vy vz k\n");
if (rank==0) printf("********************************************************\n"); fclose(log_file);
timestep=0; }
double error = 1.0; }
double flow_rate_previous = 0.0;
//.......create and start timer............
ScaLBL_DeviceBarrier();
comm.barrier();
if (rank == 0)
printf("Beginning AA timesteps, timestepMax = %i \n", timestepMax);
if (rank == 0)
printf("********************************************************\n");
timestep = 0;
double error = 1.0;
double flow_rate_previous = 0.0;
auto t1 = std::chrono::system_clock::now(); auto t1 = std::chrono::system_clock::now();
while (timestep < timestepMax && error > tolerance) { while (timestep < timestepMax && error > tolerance) {
//************************************************************************/ //************************************************************************/
timestep++; timestep++;
ScaLBL_Comm->SendD3Q19AA(fq); //READ FROM NORMAL ScaLBL_Comm->SendD3Q19AA(fq); //READ FROM NORMAL
ScaLBL_D3Q19_AAodd_MRT(NeighborList, fq, ScaLBL_Comm->FirstInterior(), ScaLBL_Comm->LastInterior(), Np, rlx_setA, rlx_setB, Fx, Fy, Fz); ScaLBL_D3Q19_AAodd_MRT(NeighborList, fq, ScaLBL_Comm->FirstInterior(),
ScaLBL_Comm->RecvD3Q19AA(fq); //WRITE INTO OPPOSITE ScaLBL_Comm->LastInterior(), Np, rlx_setA,
// Set boundary conditions rlx_setB, Fx, Fy, Fz);
if (BoundaryCondition == 3){ ScaLBL_Comm->RecvD3Q19AA(fq); //WRITE INTO OPPOSITE
ScaLBL_Comm->D3Q19_Pressure_BC_z(NeighborList, fq, din, timestep); // Set boundary conditions
ScaLBL_Comm->D3Q19_Pressure_BC_Z(NeighborList, fq, dout, timestep); if (BoundaryCondition == 3) {
} ScaLBL_Comm->D3Q19_Pressure_BC_z(NeighborList, fq, din, timestep);
else if (BoundaryCondition == 4){ ScaLBL_Comm->D3Q19_Pressure_BC_Z(NeighborList, fq, dout, timestep);
din = ScaLBL_Comm->D3Q19_Flux_BC_z(NeighborList, fq, flux, timestep); } else if (BoundaryCondition == 4) {
ScaLBL_Comm->D3Q19_Pressure_BC_Z(NeighborList, fq, dout, timestep); din =
} ScaLBL_Comm->D3Q19_Flux_BC_z(NeighborList, fq, flux, timestep);
else if (BoundaryCondition == 5){ ScaLBL_Comm->D3Q19_Pressure_BC_Z(NeighborList, fq, dout, timestep);
ScaLBL_Comm->D3Q19_Reflection_BC_z(fq); } else if (BoundaryCondition == 5) {
ScaLBL_Comm->D3Q19_Reflection_BC_Z(fq); ScaLBL_Comm->D3Q19_Reflection_BC_z(fq);
} ScaLBL_Comm->D3Q19_Reflection_BC_Z(fq);
ScaLBL_D3Q19_AAodd_MRT(NeighborList, fq, 0, ScaLBL_Comm->LastExterior(), Np, rlx_setA, rlx_setB, Fx, Fy, Fz); }
ScaLBL_DeviceBarrier(); comm.barrier(); ScaLBL_D3Q19_AAodd_MRT(NeighborList, fq, 0, ScaLBL_Comm->LastExterior(),
timestep++; Np, rlx_setA, rlx_setB, Fx, Fy, Fz);
ScaLBL_Comm->SendD3Q19AA(fq); //READ FORM NORMAL ScaLBL_DeviceBarrier();
ScaLBL_D3Q19_AAeven_MRT(fq, ScaLBL_Comm->FirstInterior(), ScaLBL_Comm->LastInterior(), Np, rlx_setA, rlx_setB, Fx, Fy, Fz); comm.barrier();
ScaLBL_Comm->RecvD3Q19AA(fq); //WRITE INTO OPPOSITE timestep++;
// Set boundary conditions ScaLBL_Comm->SendD3Q19AA(fq); //READ FORM NORMAL
if (BoundaryCondition == 3){ ScaLBL_D3Q19_AAeven_MRT(fq, ScaLBL_Comm->FirstInterior(),
ScaLBL_Comm->D3Q19_Pressure_BC_z(NeighborList, fq, din, timestep); ScaLBL_Comm->LastInterior(), Np, rlx_setA,
ScaLBL_Comm->D3Q19_Pressure_BC_Z(NeighborList, fq, dout, timestep); rlx_setB, Fx, Fy, Fz);
} ScaLBL_Comm->RecvD3Q19AA(fq); //WRITE INTO OPPOSITE
else if (BoundaryCondition == 4){ // Set boundary conditions
din = ScaLBL_Comm->D3Q19_Flux_BC_z(NeighborList, fq, flux, timestep); if (BoundaryCondition == 3) {
ScaLBL_Comm->D3Q19_Pressure_BC_Z(NeighborList, fq, dout, timestep); ScaLBL_Comm->D3Q19_Pressure_BC_z(NeighborList, fq, din, timestep);
} ScaLBL_Comm->D3Q19_Pressure_BC_Z(NeighborList, fq, dout, timestep);
else if (BoundaryCondition == 5){ } else if (BoundaryCondition == 4) {
ScaLBL_Comm->D3Q19_Reflection_BC_z(fq); din =
ScaLBL_Comm->D3Q19_Reflection_BC_Z(fq); ScaLBL_Comm->D3Q19_Flux_BC_z(NeighborList, fq, flux, timestep);
} ScaLBL_Comm->D3Q19_Pressure_BC_Z(NeighborList, fq, dout, timestep);
ScaLBL_D3Q19_AAeven_MRT(fq, 0, ScaLBL_Comm->LastExterior(), Np, rlx_setA, rlx_setB, Fx, Fy, Fz); } else if (BoundaryCondition == 5) {
ScaLBL_DeviceBarrier(); comm.barrier(); ScaLBL_Comm->D3Q19_Reflection_BC_z(fq);
//************************************************************************/ ScaLBL_Comm->D3Q19_Reflection_BC_Z(fq);
}
if (timestep%1000==0){ ScaLBL_D3Q19_AAeven_MRT(fq, 0, ScaLBL_Comm->LastExterior(), Np,
ScaLBL_D3Q19_Momentum(fq,Velocity, Np); rlx_setA, rlx_setB, Fx, Fy, Fz);
ScaLBL_DeviceBarrier(); comm.barrier(); ScaLBL_DeviceBarrier();
ScaLBL_Comm->RegularLayout(Map,&Velocity[0],Velocity_x); comm.barrier();
ScaLBL_Comm->RegularLayout(Map,&Velocity[Np],Velocity_y); //************************************************************************/
ScaLBL_Comm->RegularLayout(Map,&Velocity[2*Np],Velocity_z);
double count_loc=0;
double count;
double vax,vay,vaz;
double vax_loc,vay_loc,vaz_loc;
vax_loc = vay_loc = vaz_loc = 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 (Distance(i,j,k) > 0){
vax_loc += Velocity_x(i,j,k);
vay_loc += Velocity_y(i,j,k);
vaz_loc += Velocity_z(i,j,k);
count_loc+=1.0;
}
}
}
}
vax=Dm->Comm.sumReduce( vax_loc);
vay=Dm->Comm.sumReduce( vay_loc);
vaz=Dm->Comm.sumReduce( vaz_loc);
count=Dm->Comm.sumReduce( count_loc);
vax /= count;
vay /= count;
vaz /= count;
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 flow_rate = (vax*dir_x + vay*dir_y + vaz*dir_z);
error = fabs(flow_rate - flow_rate_previous) / fabs(flow_rate);
flow_rate_previous = flow_rate;
//if (rank==0) printf("Computing Minkowski functionals \n");
Morphology.ComputeScalar(Distance,0.f);
//Morphology.PrintAll();
double mu = (tau-0.5)/3.f;
double Vs = Morphology.V();
double As = Morphology.A();
double Hs = Morphology.H();
double Xs = Morphology.X();
Vs=Dm->Comm.sumReduce( Vs);
As=Dm->Comm.sumReduce( As);
Hs=Dm->Comm.sumReduce( Hs);
Xs=Dm->Comm.sumReduce( Xs);
double h = Dm->voxel_length; if (timestep % 1000 == 0) {
double absperm = h*h*mu*Mask->Porosity()*flow_rate / force_mag; ScaLBL_D3Q19_Momentum(fq, Velocity, Np);
if (rank==0) { ScaLBL_DeviceBarrier();
printf(" %f\n",absperm); comm.barrier();
FILE * log_file = fopen("Permeability.csv","a"); ScaLBL_Comm->RegularLayout(Map, &Velocity[0], Velocity_x);
fprintf(log_file,"%i %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g\n",timestep, Fx, Fy, Fz, mu, ScaLBL_Comm->RegularLayout(Map, &Velocity[Np], Velocity_y);
h*h*h*Vs,h*h*As,h*Hs,Xs,vax,vay,vaz, absperm); ScaLBL_Comm->RegularLayout(Map, &Velocity[2 * Np], Velocity_z);
fclose(log_file);
} double count_loc = 0;
} double count;
} double vax, vay, vaz;
//************************************************************************/ double vax_loc, vay_loc, vaz_loc;
if (rank==0) printf("-------------------------------------------------------------------\n"); vax_loc = vay_loc = vaz_loc = 0.f;
// Compute the walltime per timestep 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 (Distance(i, j, k) > 0) {
vax_loc += Velocity_x(i, j, k);
vay_loc += Velocity_y(i, j, k);
vaz_loc += Velocity_z(i, j, k);
count_loc += 1.0;
}
}
}
}
vax = Dm->Comm.sumReduce(vax_loc);
vay = Dm->Comm.sumReduce(vay_loc);
vaz = Dm->Comm.sumReduce(vaz_loc);
count = Dm->Comm.sumReduce(count_loc);
vax /= count;
vay /= count;
vaz /= count;
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 flow_rate = (vax * dir_x + vay * dir_y + vaz * dir_z);
error = fabs(flow_rate - flow_rate_previous) / fabs(flow_rate);
flow_rate_previous = flow_rate;
//if (rank==0) printf("Computing Minkowski functionals \n");
Morphology.ComputeScalar(Distance, 0.f);
//Morphology.PrintAll();
double mu = (tau - 0.5) / 3.f;
double Vs = Morphology.V();
double As = Morphology.A();
double Hs = Morphology.H();
double Xs = Morphology.X();
Vs = Dm->Comm.sumReduce(Vs);
As = Dm->Comm.sumReduce(As);
Hs = Dm->Comm.sumReduce(Hs);
Xs = Dm->Comm.sumReduce(Xs);
double h = Dm->voxel_length;
double absperm =
h * h * mu * Mask->Porosity() * flow_rate / force_mag;
if (rank == 0) {
printf(" %f\n", absperm);
FILE *log_file = fopen("Permeability.csv", "a");
fprintf(log_file,
"%i %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g "
"%.8g %.8g\n",
timestep, Fx, Fy, Fz, mu, h * h * h * Vs, h * h * As,
h * Hs, Xs, vax, vay, vaz, absperm);
fclose(log_file);
}
}
}
//************************************************************************/
if (rank == 0)
printf("---------------------------------------------------------------"
"----\n");
// Compute the walltime per timestep
auto t2 = std::chrono::system_clock::now(); auto t2 = std::chrono::system_clock::now();
double cputime = std::chrono::duration<double>( t2 - t1 ).count() / timestep; double cputime = std::chrono::duration<double>(t2 - t1).count() / timestep;
// Performance obtained from each node // Performance obtained from each node
double MLUPS = double(Np)/cputime/1000000; double MLUPS = double(Np) / cputime / 1000000;
if (rank==0) printf("********************************************************\n");
if (rank==0) printf("CPU time = %f \n", cputime);
if (rank==0) printf("Lattice update rate (per core)= %f MLUPS \n", MLUPS);
MLUPS *= nprocs;
if (rank==0) printf("Lattice update rate (total)= %f MLUPS \n", MLUPS);
if (rank==0) printf("********************************************************\n");
if (rank == 0)
printf("********************************************************\n");
if (rank == 0)
printf("CPU time = %f \n", cputime);
if (rank == 0)
printf("Lattice update rate (per core)= %f MLUPS \n", MLUPS);
MLUPS *= nprocs;
if (rank == 0)
printf("Lattice update rate (total)= %f MLUPS \n", MLUPS);
if (rank == 0)
printf("********************************************************\n");
} }
void ScaLBL_MRTModel::VelocityField(){ void ScaLBL_MRTModel::VelocityField() {
auto format = vis_db->getWithDefault<string>( "format", "silo" ); auto format = vis_db->getWithDefault<string>("format", "silo");
/* memcpy(Morphology.SDn.data(), Distance.data(), Nx*Ny*Nz*sizeof(double)); /* memcpy(Morphology.SDn.data(), Distance.data(), Nx*Ny*Nz*sizeof(double));
Morphology.Initialize(); Morphology.Initialize();
@ -428,59 +461,63 @@ void ScaLBL_MRTModel::VelocityField(){
if (rank==0) printf("%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g\n",Fx, Fy, Fz, mu, if (rank==0) printf("%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g\n",Fx, Fy, Fz, mu,
Morphology.V(),Morphology.A(),Morphology.J(),Morphology.X(),vax,vay,vaz); Morphology.V(),Morphology.A(),Morphology.J(),Morphology.X(),vax,vay,vaz);
*/ */
vis_db = db->getDatabase( "Visualization" ); vis_db = db->getDatabase("Visualization");
if (vis_db->getWithDefault<bool>( "write_silo", false )){ if (vis_db->getWithDefault<bool>("write_silo", false)) {
std::vector<IO::MeshDataStruct> visData;
fillHalo<double> fillData(Dm->Comm,Dm->rank_info,{Dm->Nx-2,Dm->Ny-2,Dm->Nz-2},{1,1,1},0,1);
auto VxVar = std::make_shared<IO::Variable>(); std::vector<IO::MeshDataStruct> visData;
auto VyVar = std::make_shared<IO::Variable>(); fillHalo<double> fillData(Dm->Comm, Dm->rank_info,
auto VzVar = std::make_shared<IO::Variable>(); {Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2},
auto SignDistVar = std::make_shared<IO::Variable>(); {1, 1, 1}, 0, 1);
IO::initialize("",format,"false"); auto VxVar = std::make_shared<IO::Variable>();
// Create the MeshDataStruct auto VyVar = std::make_shared<IO::Variable>();
visData.resize(1); auto VzVar = std::make_shared<IO::Variable>();
visData[0].meshName = "domain"; auto SignDistVar = std::make_shared<IO::Variable>();
visData[0].mesh = std::make_shared<IO::DomainMesh>( Dm->rank_info,Dm->Nx-2,Dm->Ny-2,Dm->Nz-2,Dm->Lx,Dm->Ly,Dm->Lz );
SignDistVar->name = "SignDist"; IO::initialize("", format, "false");
SignDistVar->type = IO::VariableType::VolumeVariable; // Create the MeshDataStruct
SignDistVar->dim = 1; visData.resize(1);
SignDistVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); visData[0].meshName = "domain";
visData[0].vars.push_back(SignDistVar); visData[0].mesh = std::make_shared<IO::DomainMesh>(
Dm->rank_info, Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2, Dm->Lx, Dm->Ly,
VxVar->name = "Velocity_x"; Dm->Lz);
VxVar->type = IO::VariableType::VolumeVariable; SignDistVar->name = "SignDist";
VxVar->dim = 1; SignDistVar->type = IO::VariableType::VolumeVariable;
VxVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); SignDistVar->dim = 1;
visData[0].vars.push_back(VxVar); SignDistVar->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
VyVar->name = "Velocity_y"; visData[0].vars.push_back(SignDistVar);
VyVar->type = IO::VariableType::VolumeVariable;
VyVar->dim = 1; VxVar->name = "Velocity_x";
VyVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); VxVar->type = IO::VariableType::VolumeVariable;
visData[0].vars.push_back(VyVar); VxVar->dim = 1;
VzVar->name = "Velocity_z"; VxVar->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
VzVar->type = IO::VariableType::VolumeVariable; visData[0].vars.push_back(VxVar);
VzVar->dim = 1; VyVar->name = "Velocity_y";
VzVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2); VyVar->type = IO::VariableType::VolumeVariable;
visData[0].vars.push_back(VzVar); VyVar->dim = 1;
VyVar->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
Array<double>& SignData = visData[0].vars[0]->data; visData[0].vars.push_back(VyVar);
Array<double>& VelxData = visData[0].vars[1]->data; VzVar->name = "Velocity_z";
Array<double>& VelyData = visData[0].vars[2]->data; VzVar->type = IO::VariableType::VolumeVariable;
Array<double>& VelzData = visData[0].vars[3]->data; VzVar->dim = 1;
VzVar->data.resize(Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2);
ASSERT(visData[0].vars[0]->name=="SignDist"); visData[0].vars.push_back(VzVar);
ASSERT(visData[0].vars[1]->name=="Velocity_x");
ASSERT(visData[0].vars[2]->name=="Velocity_y"); Array<double> &SignData = visData[0].vars[0]->data;
ASSERT(visData[0].vars[3]->name=="Velocity_z"); Array<double> &VelxData = visData[0].vars[1]->data;
Array<double> &VelyData = visData[0].vars[2]->data;
fillData.copy(Distance,SignData); Array<double> &VelzData = visData[0].vars[3]->data;
fillData.copy(Velocity_x,VelxData);
fillData.copy(Velocity_y,VelyData); ASSERT(visData[0].vars[0]->name == "SignDist");
fillData.copy(Velocity_z,VelzData); ASSERT(visData[0].vars[1]->name == "Velocity_x");
ASSERT(visData[0].vars[2]->name == "Velocity_y");
IO::writeData( timestep, visData, Dm->Comm ); ASSERT(visData[0].vars[3]->name == "Velocity_z");
fillData.copy(Distance, SignData);
fillData.copy(Velocity_x, VelxData);
fillData.copy(Velocity_y, VelyData);
fillData.copy(Velocity_z, VelzData);
IO::writeData(timestep, visData, Dm->Comm);
} }
} }

View File

@ -31,36 +31,36 @@
#include "analysis/Minkowski.h" #include "analysis/Minkowski.h"
#include "ProfilerApp.h" #include "ProfilerApp.h"
class ScaLBL_MRTModel{ class ScaLBL_MRTModel {
public: public:
ScaLBL_MRTModel(int RANK, int NP, const Utilities::MPI& COMM); ScaLBL_MRTModel(int RANK, int NP, const Utilities::MPI &COMM);
~ScaLBL_MRTModel(); ~ScaLBL_MRTModel();
// functions in they should be run
void ReadParams(string filename);
void ReadParams(std::shared_ptr<Database> db0);
void SetDomain();
void ReadInput();
void Create();
void Initialize();
void Run();
void VelocityField();
bool Restart,pBC;
int timestep,timestepMax;
int BoundaryCondition;
double tau,mu;
double Fx,Fy,Fz,flux;
double din,dout;
double tolerance;
int Nx,Ny,Nz,N,Np;
int rank,nprocx,nprocy,nprocz,nprocs;
double Lx,Ly,Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis // functions in they should be run
std::shared_ptr<Domain> Mask; // this domain is for lbm void ReadParams(string filename);
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm; void ReadParams(std::shared_ptr<Database> db0);
void SetDomain();
void ReadInput();
void Create();
void Initialize();
void Run();
void VelocityField();
bool Restart, pBC;
int timestep, timestepMax;
int BoundaryCondition;
double tau, mu;
double Fx, Fy, Fz, flux;
double din, dout;
double tolerance;
int Nx, Ny, Nz, N, Np;
int rank, nprocx, nprocy, nprocz, nprocs;
double Lx, Ly, Lz;
std::shared_ptr<Domain> Dm; // this domain is for analysis
std::shared_ptr<Domain> Mask; // this domain is for lbm
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm;
// input database // input database
std::shared_ptr<Database> db; std::shared_ptr<Database> db;
std::shared_ptr<Database> domain_db; std::shared_ptr<Database> domain_db;
@ -73,20 +73,21 @@ public:
double *fq; double *fq;
double *Velocity; double *Velocity;
double *Pressure; double *Pressure;
//Minkowski Morphology; //Minkowski Morphology;
DoubleArray Velocity_x; DoubleArray Velocity_x;
DoubleArray Velocity_y; DoubleArray Velocity_y;
DoubleArray Velocity_z; DoubleArray Velocity_z;
private: private:
Utilities::MPI comm; Utilities::MPI comm;
// filenames // filenames
char LocalRankString[8]; char LocalRankString[8];
char LocalRankFilename[40]; char LocalRankFilename[40];
char LocalRestartFile[40]; char LocalRestartFile[40];
//int rank,nprocs; //int rank,nprocs;
void LoadParams(std::shared_ptr<Database> db0); void LoadParams(std::shared_ptr<Database> db0);
}; };

View File

@ -1,51 +1,48 @@
#include "models/MultiPhysController.h" #include "models/MultiPhysController.h"
ScaLBL_Multiphys_Controller::ScaLBL_Multiphys_Controller(int RANK, int NP, const Utilities::MPI& COMM): ScaLBL_Multiphys_Controller::ScaLBL_Multiphys_Controller(
rank(RANK),nprocs(NP),Restart(0),timestepMax(0),num_iter_Stokes(0),num_iter_Ion(0), int RANK, int NP, const Utilities::MPI &COMM)
analysis_interval(0),visualization_interval(0),tolerance(0),time_conv_max(0),comm(COMM) : rank(RANK), nprocs(NP), Restart(0), timestepMax(0), num_iter_Stokes(0),
{ num_iter_Ion(0), analysis_interval(0), visualization_interval(0),
tolerance(0), time_conv_max(0), comm(COMM) {}
ScaLBL_Multiphys_Controller::~ScaLBL_Multiphys_Controller() {}
} void ScaLBL_Multiphys_Controller::ReadParams(string filename) {
ScaLBL_Multiphys_Controller::~ScaLBL_Multiphys_Controller(){
} // read the input database
db = std::make_shared<Database>(filename);
void ScaLBL_Multiphys_Controller::ReadParams(string filename){ study_db = db->getDatabase("MultiphysController");
// read the input database
db = std::make_shared<Database>( filename );
study_db = db->getDatabase( "MultiphysController" );
// Default parameters // Default parameters
timestepMax = 10000; timestepMax = 10000;
Restart = false; Restart = false;
num_iter_Stokes=1; num_iter_Stokes = 1;
num_iter_Ion.push_back(1); num_iter_Ion.push_back(1);
analysis_interval = 500; analysis_interval = 500;
visualization_interval = 10000; visualization_interval = 10000;
tolerance = 1.0e-6; tolerance = 1.0e-6;
time_conv_max = 0.0; time_conv_max = 0.0;
// load input parameters // load input parameters
if (study_db->keyExists( "timestepMax" )){ if (study_db->keyExists("timestepMax")) {
timestepMax = study_db->getScalar<int>( "timestepMax" ); timestepMax = study_db->getScalar<int>("timestepMax");
} }
if (study_db->keyExists( "analysis_interval" )){ if (study_db->keyExists("analysis_interval")) {
analysis_interval = study_db->getScalar<int>( "analysis_interval" ); analysis_interval = study_db->getScalar<int>("analysis_interval");
} }
if (study_db->keyExists( "visualization_interval" )){ if (study_db->keyExists("visualization_interval")) {
visualization_interval = study_db->getScalar<int>( "visualization_interval" ); visualization_interval =
} study_db->getScalar<int>("visualization_interval");
if (study_db->keyExists( "tolerance" )){ }
tolerance = study_db->getScalar<double>( "tolerance" ); if (study_db->keyExists("tolerance")) {
} tolerance = study_db->getScalar<double>("tolerance");
//if (study_db->keyExists( "time_conv" )){ }
// time_conv = study_db->getScalar<double>( "time_conv" ); //if (study_db->keyExists( "time_conv" )){
//} // time_conv = study_db->getScalar<double>( "time_conv" );
//if (study_db->keyExists( "Schmidt_Number" )){ //}
// SchmidtNum = study_db->getScalar<double>( "Schmidt_Number" ); //if (study_db->keyExists( "Schmidt_Number" )){
//} // SchmidtNum = study_db->getScalar<double>( "Schmidt_Number" );
//}
// recalculate relevant parameters // recalculate relevant parameters
//if (SchmidtNum>1){ //if (SchmidtNum>1){
@ -61,87 +58,104 @@ void ScaLBL_Multiphys_Controller::ReadParams(string filename){
// num_iter_Ion = 1; // num_iter_Ion = 1;
//} //}
//else{ //else{
// ERROR("Error: SchmidtNum (Schmidt number) must be a positive number! \n"); // ERROR("Error: SchmidtNum (Schmidt number) must be a positive number! \n");
//} //}
// load input parameters // load input parameters
// in case user wants to have an absolute control over the iternal iteration // in case user wants to have an absolute control over the iternal iteration
if (study_db->keyExists( "num_iter_Ion_List" )){ if (study_db->keyExists("num_iter_Ion_List")) {
num_iter_Ion.clear(); num_iter_Ion.clear();
num_iter_Ion = study_db->getVector<int>( "num_iter_Ion_List" ); num_iter_Ion = study_db->getVector<int>("num_iter_Ion_List");
} }
if (study_db->keyExists( "num_iter_Stokes" )){ if (study_db->keyExists("num_iter_Stokes")) {
num_iter_Stokes = study_db->getScalar<int>( "num_iter_Stokes" ); num_iter_Stokes = study_db->getScalar<int>("num_iter_Stokes");
} }
} }
int ScaLBL_Multiphys_Controller::getStokesNumIter_PNP_coupling(double StokesTimeConv,const vector<double> &IonTimeConv){ int ScaLBL_Multiphys_Controller::getStokesNumIter_PNP_coupling(
double StokesTimeConv, const vector<double> &IonTimeConv) {
//Return number of internal iterations for the Stokes solver //Return number of internal iterations for the Stokes solver
int num_iter_stokes; int num_iter_stokes;
vector<double> TimeConv; vector<double> TimeConv;
TimeConv.assign(IonTimeConv.begin(),IonTimeConv.end()); TimeConv.assign(IonTimeConv.begin(), IonTimeConv.end());
TimeConv.insert(TimeConv.begin(),StokesTimeConv); TimeConv.insert(TimeConv.begin(), StokesTimeConv);
vector<double>::iterator it_max = max_element(TimeConv.begin(),TimeConv.end()); vector<double>::iterator it_max =
int idx_max = distance(TimeConv.begin(),it_max); max_element(TimeConv.begin(), TimeConv.end());
if (idx_max==0){ int idx_max = distance(TimeConv.begin(), it_max);
if (idx_max == 0) {
num_iter_stokes = 2; num_iter_stokes = 2;
} } else {
else{ double temp =
double temp = 2*TimeConv[idx_max]/StokesTimeConv;//the factor 2 is the number of iterations for the element has max time_conv 2 * TimeConv[idx_max] /
num_iter_stokes = int(round(temp/2)*2); StokesTimeConv; //the factor 2 is the number of iterations for the element has max time_conv
num_iter_stokes = int(round(temp / 2) * 2);
} }
return num_iter_stokes; return num_iter_stokes;
} }
vector<int> ScaLBL_Multiphys_Controller::getIonNumIter_PNP_coupling(double StokesTimeConv,const vector<double> &IonTimeConv){ vector<int> ScaLBL_Multiphys_Controller::getIonNumIter_PNP_coupling(
double StokesTimeConv, const vector<double> &IonTimeConv) {
//Return number of internal iterations for the Ion transport solver //Return number of internal iterations for the Ion transport solver
vector<int> num_iter_ion; vector<int> num_iter_ion;
vector<double> TimeConv; vector<double> TimeConv;
TimeConv.assign(IonTimeConv.begin(),IonTimeConv.end()); TimeConv.assign(IonTimeConv.begin(), IonTimeConv.end());
TimeConv.insert(TimeConv.begin(),StokesTimeConv); TimeConv.insert(TimeConv.begin(), StokesTimeConv);
vector<double>::iterator it_max = max_element(TimeConv.begin(),TimeConv.end()); vector<double>::iterator it_max =
unsigned int idx_max = distance(TimeConv.begin(),it_max); max_element(TimeConv.begin(), TimeConv.end());
if (idx_max==0){ unsigned int idx_max = distance(TimeConv.begin(), it_max);
for (unsigned int idx=1;idx<TimeConv.size();idx++){ if (idx_max == 0) {
double temp = 2*StokesTimeConv/TimeConv[idx];//the factor 2 is the number of iterations for the element has max time_conv for (unsigned int idx = 1; idx < TimeConv.size(); idx++) {
num_iter_ion.push_back(int(round(temp/2)*2)); double temp =
2 * StokesTimeConv /
TimeConv
[idx]; //the factor 2 is the number of iterations for the element has max time_conv
num_iter_ion.push_back(int(round(temp / 2) * 2));
} }
} } else if (idx_max == 1) {
else if (idx_max==1){
num_iter_ion.push_back(2); num_iter_ion.push_back(2);
for (unsigned int idx=2;idx<TimeConv.size();idx++){ for (unsigned int idx = 2; idx < TimeConv.size(); idx++) {
double temp = 2*TimeConv[idx_max]/TimeConv[idx];//the factor 2 is the number of iterations for the element has max time_conv double temp =
num_iter_ion.push_back(int(round(temp/2)*2)); 2 * TimeConv[idx_max] /
TimeConv
[idx]; //the factor 2 is the number of iterations for the element has max time_conv
num_iter_ion.push_back(int(round(temp / 2) * 2));
} }
} } else if (idx_max == TimeConv.size() - 1) {
else if (idx_max==TimeConv.size()-1){ for (unsigned int idx = 1; idx < TimeConv.size() - 1; idx++) {
for (unsigned int idx=1;idx<TimeConv.size()-1;idx++){ double temp =
double temp = 2*TimeConv[idx_max]/TimeConv[idx];//the factor 2 is the number of iterations for the element has max time_conv 2 * TimeConv[idx_max] /
num_iter_ion.push_back(int(round(temp/2)*2)); TimeConv
[idx]; //the factor 2 is the number of iterations for the element has max time_conv
num_iter_ion.push_back(int(round(temp / 2) * 2));
} }
num_iter_ion.push_back(2); num_iter_ion.push_back(2);
} } else {
else { for (unsigned int idx = 1; idx < idx_max; idx++) {
for (unsigned int idx=1;idx<idx_max;idx++){ double temp =
double temp = 2*TimeConv[idx_max]/TimeConv[idx];//the factor 2 is the number of iterations for the element has max time_conv 2 * TimeConv[idx_max] /
num_iter_ion.push_back(int(round(temp/2)*2)); TimeConv
[idx]; //the factor 2 is the number of iterations for the element has max time_conv
num_iter_ion.push_back(int(round(temp / 2) * 2));
} }
num_iter_ion.push_back(2); num_iter_ion.push_back(2);
for (unsigned int idx=idx_max+1;idx<TimeConv.size();idx++){ for (unsigned int idx = idx_max + 1; idx < TimeConv.size(); idx++) {
double temp = 2*TimeConv[idx_max]/TimeConv[idx];//the factor 2 is the number of iterations for the element has max time_conv double temp =
num_iter_ion.push_back(int(round(temp/2)*2)); 2 * TimeConv[idx_max] /
TimeConv
[idx]; //the factor 2 is the number of iterations for the element has max time_conv
num_iter_ion.push_back(int(round(temp / 2) * 2));
} }
} }
return num_iter_ion; return num_iter_ion;
} }
void ScaLBL_Multiphys_Controller::getTimeConvMax_PNP_coupling(double StokesTimeConv,const vector<double> &IonTimeConv){ void ScaLBL_Multiphys_Controller::getTimeConvMax_PNP_coupling(
double StokesTimeConv, const vector<double> &IonTimeConv) {
//Return maximum of the time converting factor from Stokes and ion solvers //Return maximum of the time converting factor from Stokes and ion solvers
vector<double> TimeConv; vector<double> TimeConv;
TimeConv.assign(IonTimeConv.begin(),IonTimeConv.end()); TimeConv.assign(IonTimeConv.begin(), IonTimeConv.end());
TimeConv.insert(TimeConv.begin(),StokesTimeConv); TimeConv.insert(TimeConv.begin(), StokesTimeConv);
time_conv_max = *max_element(TimeConv.begin(),TimeConv.end()); time_conv_max = *max_element(TimeConv.begin(), TimeConv.end());
} }

View File

@ -17,19 +17,22 @@
#include "analysis/Minkowski.h" #include "analysis/Minkowski.h"
#include "ProfilerApp.h" #include "ProfilerApp.h"
class ScaLBL_Multiphys_Controller{ class ScaLBL_Multiphys_Controller {
public: public:
ScaLBL_Multiphys_Controller(int RANK, int NP, const Utilities::MPI& COMM); ScaLBL_Multiphys_Controller(int RANK, int NP, const Utilities::MPI &COMM);
~ScaLBL_Multiphys_Controller(); ~ScaLBL_Multiphys_Controller();
void ReadParams(string filename); void ReadParams(string filename);
void ReadParams(std::shared_ptr<Database> db0); void ReadParams(std::shared_ptr<Database> db0);
int getStokesNumIter_PNP_coupling(double StokesTimeConv,const vector<double> &IonTimeConv); int getStokesNumIter_PNP_coupling(double StokesTimeConv,
vector<int> getIonNumIter_PNP_coupling(double StokesTimeConv,const vector<double> &IonTimeConv); const vector<double> &IonTimeConv);
vector<int> getIonNumIter_PNP_coupling(double StokesTimeConv,
const vector<double> &IonTimeConv);
//void getIonNumIter_PNP_coupling(double StokesTimeConv,vector<double> &IonTimeConv,vector<int> &IonTimeMax); //void getIonNumIter_PNP_coupling(double StokesTimeConv,vector<double> &IonTimeConv,vector<int> &IonTimeMax);
void getTimeConvMax_PNP_coupling(double StokesTimeConv,const vector<double> &IonTimeConv); void getTimeConvMax_PNP_coupling(double StokesTimeConv,
const vector<double> &IonTimeConv);
bool Restart;
bool Restart;
int timestepMax; int timestepMax;
int num_iter_Stokes; int num_iter_Stokes;
vector<int> num_iter_Ion; vector<int> num_iter_Ion;
@ -39,20 +42,20 @@ public:
double time_conv_max; double time_conv_max;
//double SchmidtNum;//Schmidt number = kinematic_viscosity/mass_diffusivity //double SchmidtNum;//Schmidt number = kinematic_viscosity/mass_diffusivity
int rank,nprocs; int rank, nprocs;
// input database // input database
std::shared_ptr<Database> db; std::shared_ptr<Database> db;
std::shared_ptr<Database> study_db; std::shared_ptr<Database> study_db;
private: private:
Utilities::MPI comm; Utilities::MPI comm;
// filenames // filenames
char LocalRankString[8]; char LocalRankString[8];
char LocalRankFilename[40]; char LocalRankFilename[40];
char LocalRestartFile[40]; char LocalRestartFile[40];
//int rank,nprocs; //int rank,nprocs;
void LoadParams(std::shared_ptr<Database> db0); void LoadParams(std::shared_ptr<Database> db0);
}; };

Some files were not shown because too many files have changed in this diff Show More