Skip to content

Commit

Permalink
Option to use a powder layer on layer 0 (#190)
Browse files Browse the repository at this point in the history
* Option to use a powder layer on layer 0
* Ensure baseplate microstructure always starts at domain bottom, size consistent betweeen from file and from spacing init routines
  • Loading branch information
MattRolchigo authored May 4, 2023
1 parent b3fcd0e commit b869c0a
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 46 deletions.
72 changes: 53 additions & 19 deletions src/CAinitialize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void InputReadFromFile_Old(int id, std::string InputFile, std::string &Simulatio
int &NSpotsX, int &NSpotsY, int &SpotOffset, int &SpotRadius, bool &PrintTimeSeries,
int &TimeSeriesInc, bool &PrintIdleTimeSeriesFrames, bool &PrintDefaultRVE, double &RNGSeed,
bool &BaseplateThroughPowder, double &PowderActiveFraction, int &RVESize,
bool &LayerwiseTempRead, bool &PrintBinary) {
bool &LayerwiseTempRead, bool &PrintBinary, bool &PowderFirstLayer) {

// Required inputs that should be present in the input file, regardless of problem type
std::vector<std::string> RequiredInputs_General = {
Expand Down Expand Up @@ -262,6 +262,7 @@ void InputReadFromFile_Old(int id, std::string InputFile, std::string &Simulatio
throw std::runtime_error("Error: if the option to extend the baseplate through through all powder "
"layers is turned on, a powder density cannot be given");
}
PowderFirstLayer = false; // only set with JSON input file format
if (id == 0) {
std::cout << "CA Simulation using temperature data from file(s)" << std::endl;
std::cout << "The time step is " << deltat << " seconds" << std::endl;
Expand Down Expand Up @@ -325,6 +326,7 @@ void InputReadFromFile_Old(int id, std::string InputFile, std::string &Simulatio
throw std::runtime_error("Error: if the option to extend the baseplate through the powder layers it "
"toggled, a powder density cannot be given");
}
PowderFirstLayer = false; // only set with JSON input file format
if (id == 0) {
std::cout << "CA Simulation using a radial, fixed thermal gradient of " << G
<< " K/m as a series of hemispherical spots, and a cooling rate of " << R << " K/s" << std::endl;
Expand Down Expand Up @@ -487,7 +489,7 @@ void InputReadFromFile(int id, std::string InputFile, std::string &SimulationTyp
int &NSpotsY, int &SpotOffset, int &SpotRadius, bool &PrintTimeSeries, int &TimeSeriesInc,
bool &PrintIdleTimeSeriesFrames, bool &PrintDefaultRVE, double &RNGSeed,
bool &BaseplateThroughPowder, double &PowderActiveFraction, int &RVESize,
bool &LayerwiseTempRead, bool &PrintBinary) {
bool &LayerwiseTempRead, bool &PrintBinary, bool &PowderFirstLayer) {

std::ifstream InputData(InputFile);
nlohmann::json inputdata = nlohmann::json::parse(InputData);
Expand Down Expand Up @@ -640,12 +642,19 @@ void InputReadFromFile(int id, std::string InputFile, std::string &SimulationTyp
if ((PowderActiveFraction < 0.0) || (PowderActiveFraction > 1.0))
throw std::runtime_error("Error: Density of powder surface sites active must be larger than 0 and less "
"than 1/(CA cell volume)");
if (BaseplateThroughPowder)
throw std::runtime_error("Error: if the option to extend the baseplate through the powder layers it "
"toggled, a powder density cannot be given");
}
else
PowderActiveFraction = 1.0; // defaults to a unique grain at each site in the powder layers
// Should a powder layer be initialized at the top of the baseplate for the first layer? (Defaults to false,
// where the baseplate spans all of layer 0, and only starting with layer 1 is a powder layer present)
if (inputdata["Substrate"].contains("PowderFirstLayer"))
PowderFirstLayer = inputdata["Substrate"]["PowderFirstLayer"];
else
PowderFirstLayer = false;
if ((BaseplateThroughPowder) && ((PowderFirstLayer) || (inputdata["Substrate"].contains("PowderDensity"))))
throw std::runtime_error(
"Error: if the option to extend the baseplate through the powder layers is toggled, options regarding "
"the powder layer (PowderFirstLayer/PowderDensity cannot be given");
}

// Printing inputs:
Expand Down Expand Up @@ -1997,9 +2006,32 @@ void SubstrateInit_ConstrainedGrowth(int id, double FractSurfaceSitesActive, int
std::cout << "Number of substrate active cells across all ranks: " << SubstrateActCells << std::endl;
}

// Determine the height of the baseplate, in CA cells
// The baseplate always starts at the simulation bottom (Z coordinate corresponding to ZMin), regardless of whether the
// first layer melts the cells at the bottom or not If BaseplateThroughPowder is true, the baseplate microstructure
// extends through the entire simulation domain in Z If BaseplateThroughPowder is false and PowderFirstLayer is true,
// the baseplate extends to the Z coordinate that is LayerHeight cells short of the top of the first layer (the final
// LayerHeight cells of the first layer will be initialized using the powder options specified)) If
// BaseplateThroughPowder is false and PowderFirstLayer is false, the baseplate extends to the top of the first layer
int getBaseplateSizeZ(int nz, double *ZMaxLayer, double ZMin, double deltax, int LayerHeight,
bool BaseplateThroughPowder, bool PowderFirstLayer) {
int BaseplateSizeZ;
if (BaseplateThroughPowder)
BaseplateSizeZ = nz;
else {
if (PowderFirstLayer)
BaseplateSizeZ = round((ZMaxLayer[0] - ZMin) / deltax) + 1 - LayerHeight;

else
BaseplateSizeZ = round((ZMaxLayer[0] - ZMin) / deltax) + 1;
}
return BaseplateSizeZ;
}

// Initializes Grain ID values where the substrate comes from a file
void SubstrateInit_FromFile(std::string SubstrateFileName, int nz, int nx, int MyYSlices, int MyYOffset, int id,
ViewI &GrainID_Device, int nzActive, bool BaseplateThroughPowder) {
ViewI &GrainID_Device, double ZMin, double *ZMaxLayer, bool BaseplateThroughPowder,
bool PowderFirstLayer, int LayerHeight, double deltax) {

// Assign GrainID values to cells that are part of the substrate - read values from file and initialize using
// temporary host view
Expand All @@ -2009,11 +2041,12 @@ void SubstrateInit_FromFile(std::string SubstrateFileName, int nz, int nx, int M
int Substrate_LowY = MyYOffset;
int Substrate_HighY = MyYOffset + MyYSlices;
int nxS, nyS, nzS;
int BaseplateSizeZ; // in CA cells
if (BaseplateThroughPowder)
BaseplateSizeZ = nz; // baseplate microstructure used as entire domain's initial condition
else
BaseplateSizeZ = nzActive; // baseplate microstructure is layer 0's initial condition
int BaseplateSizeZ = getBaseplateSizeZ(nz, ZMaxLayer, ZMin, deltax, LayerHeight, BaseplateThroughPowder,
PowderFirstLayer); // in CA cells
if ((id == 0) && (BaseplateSizeZ < 1))
std::cout << "Warning: No substrate data from the file be used, as the powder layer extends further in the Z "
"direction than the first layer's temperature data"
<< std::endl;
std::string s;
getline(Substrate, s);
std::size_t found = s.find("=");
Expand Down Expand Up @@ -2061,17 +2094,18 @@ void SubstrateInit_FromFile(std::string SubstrateFileName, int nz, int nx, int M
}

// Initializes Grain ID values where the baseplate is generated using an input grain spacing and a Voronoi Tessellation
void BaseplateInit_FromGrainSpacing(float SubstrateGrainSpacing, int nx, int ny, double *ZMinLayer, double *ZMaxLayer,
void BaseplateInit_FromGrainSpacing(float SubstrateGrainSpacing, int nx, int ny, double ZMin, double *ZMaxLayer,
int MyYSlices, int MyYOffset, int id, double deltax, ViewI GrainID, double RNGSeed,
int &NextLayer_FirstEpitaxialGrainID, int nz, double BaseplateThroughPowder) {
int &NextLayer_FirstEpitaxialGrainID, int nz, double BaseplateThroughPowder,
bool PowderFirstLayer, int LayerHeight) {

// Number of cells to assign GrainID
int BaseplateSizeZ; // in CA cells
if (BaseplateThroughPowder)
BaseplateSizeZ = nz; // baseplate microstructure used as entire domain's initial condition
else
BaseplateSizeZ = round((ZMaxLayer[0] - ZMinLayer[0]) / deltax) +
1; // baseplate microstructure is layer 0's initial condition
int BaseplateSizeZ = getBaseplateSizeZ(nz, ZMaxLayer, ZMin, deltax, LayerHeight, BaseplateThroughPowder,
PowderFirstLayer); // in CA cells
if ((id == 0) && (BaseplateSizeZ < 1))
std::cout << "Warning: no baseplate microstructure will be used, as the powder layer extends further in the Z "
"direction than the first layer's temperature data"
<< std::endl;
std::mt19937_64 gen(RNGSeed);

// Based on the baseplate volume (convert to cubic microns to match units) and the substrate grain spacing,
Expand Down
14 changes: 9 additions & 5 deletions src/CAinitialize.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void InputReadFromFile_Old(int id, std::string InputFile, std::string &Simulatio
int &NSpotsX, int &NSpotsY, int &SpotOffset, int &SpotRadius, bool &PrintTimeSeries,
int &TimeSeriesInc, bool &PrintIdleTimeSeriesFrames, bool &PrintDefaultRVE, double &RNGSeed,
bool &BaseplateThroughPowder, double &PowderDensity, int &RVESize, bool &LayerwiseTempRead,
bool &PrintBinary);
bool &PrintBinary, bool &PowderFirstLayer);
void InputReadFromFile(int id, std::string InputFile, std::string &SimulationType, double &deltax, double &NMax,
double &dTN, double &dTsigma, std::string &OutputFile, std::string &GrainOrientationFile,
int &TempFilesInSeries, std::vector<std::string> &temp_paths, double &HT_deltax,
Expand All @@ -40,7 +40,7 @@ void InputReadFromFile(int id, std::string InputFile, std::string &SimulationTyp
int &NSpotsY, int &SpotOffset, int &SpotRadius, bool &PrintTimeSeries, int &TimeSeriesInc,
bool &PrintIdleTimeSeriesFrames, bool &PrintDefaultRVE, double &RNGSeed,
bool &BaseplateThroughPowder, double &PowderActiveFraction, int &RVESize,
bool &LayerwiseTempRead, bool &PrintBinary);
bool &LayerwiseTempRead, bool &PrintBinary, bool &PowderFirstLayer);
void checkPowderOverflow(int nx, int ny, int LayerHeight, int NumberOfLayers, bool BaseplateThroughPowder,
double PowderDensity);
void NeighborListInit(NList &NeighborX, NList &NeighborY, NList &NeighborZ);
Expand Down Expand Up @@ -111,11 +111,15 @@ void SubstrateInit_ConstrainedGrowth(int id, double FractSurfaceSitesActive, int
ViewF DiagonalLength, ViewF DOCenter, ViewF CritDiagonalLength, double RNGSeed,
int np, Buffer2D BufferNorthSend, Buffer2D BufferSouthSend, ViewI SendSizeNorth,
ViewI SendSizeSouth, bool AtNorthBoundary, bool AtSouthBoundary, int BufSize);
int getBaseplateSizeZ(int nz, double *ZMaxLayer, double ZMin, double deltax, int LayerHeight,
bool BaseplateThroughPowder, bool PowderFirstLayer);
void SubstrateInit_FromFile(std::string SubstrateFileName, int nz, int nx, int MyYSlices, int MyYOffset, int pid,
ViewI &GrainID, int nzActive, bool BaseplateThroughPowder);
void BaseplateInit_FromGrainSpacing(float SubstrateGrainSpacing, int nx, int ny, double *ZMinLayer, double *ZMaxLayer,
ViewI &GrainID, double ZMin, double *ZMaxLayer, bool BaseplateThroughPowder,
bool PowderFirstLayer, int LayerHeight, double deltax);
void BaseplateInit_FromGrainSpacing(float SubstrateGrainSpacing, int nx, int ny, double ZMin, double *ZMaxLayer,
int MyYSlices, int MyYOffset, int id, double deltax, ViewI GrainID, double RNGSeed,
int &NextLayer_FirstEpitaxialGrainID, int nz, double BaseplateThroughPowder);
int &NextLayer_FirstEpitaxialGrainID, int nz, double BaseplateThroughPowder,
bool PowderFirstLayer, int LayerHeight);
void PowderInit(int layernumber, int nx, int ny, int LayerHeight, double *ZMaxLayer, double ZMin, double deltax,
int MyYSlices, int MyYOffset, int id, ViewI GrainID, double RNGSeed,
int &NextLayer_FirstEpitaxialGrainID, double PowderActiveFraction);
Expand Down
22 changes: 14 additions & 8 deletions src/runCA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void RunProgram_Reduced(int id, int np, std::string InputFile) {
int PrintDebug, TimeSeriesInc;
bool PrintMisorientation, PrintFinalUndercoolingVals, PrintFullOutput, RemeltingYN, UseSubstrateFile,
PrintTimeSeries, PrintIdleTimeSeriesFrames, PrintDefaultRVE, BaseplateThroughPowder, LayerwiseTempRead,
PrintBinary;
PrintBinary, PowderFirstLayer;
float SubstrateGrainSpacing;
double HT_deltax, deltax, deltat, FractSurfaceSitesActive, G, R, NMax, dTN, dTsigma, RNGSeed, PowderActiveFraction;
std::string SubstrateFileName, MaterialFileName, SimulationType, OutputFile, GrainOrientationFile, PathToOutput;
Expand All @@ -43,7 +43,8 @@ void RunProgram_Reduced(int id, int np, std::string InputFile) {
nz, FractSurfaceSitesActive, PathToOutput, PrintDebug, PrintMisorientation,
PrintFinalUndercoolingVals, PrintFullOutput, NSpotsX, NSpotsY, SpotOffset, SpotRadius,
PrintTimeSeries, TimeSeriesInc, PrintIdleTimeSeriesFrames, PrintDefaultRVE, RNGSeed,
BaseplateThroughPowder, PowderActiveFraction, RVESize, LayerwiseTempRead, PrintBinary);
BaseplateThroughPowder, PowderActiveFraction, RVESize, LayerwiseTempRead, PrintBinary,
PowderFirstLayer);
#endif
}
else
Expand All @@ -54,7 +55,7 @@ void RunProgram_Reduced(int id, int np, std::string InputFile) {
PrintMisorientation, PrintFinalUndercoolingVals, PrintFullOutput, NSpotsX, NSpotsY,
SpotOffset, SpotRadius, PrintTimeSeries, TimeSeriesInc, PrintIdleTimeSeriesFrames,
PrintDefaultRVE, RNGSeed, BaseplateThroughPowder, PowderActiveFraction, RVESize,
LayerwiseTempRead, PrintBinary);
LayerwiseTempRead, PrintBinary, PowderFirstLayer);
InterfacialResponseFunction irf(id, MaterialFileName, deltat, deltax, JsonInputFormat);

// Variables characterizing local processor grids relative to global domain
Expand Down Expand Up @@ -235,13 +236,18 @@ void RunProgram_Reduced(int id, int np, std::string InputFile) {
}
}
else {
// Generate the baseplate microstructure, or read it from a file
if (UseSubstrateFile)
SubstrateInit_FromFile(SubstrateFileName, nz, nx, MyYSlices, MyYOffset, id, GrainID, nzActive,
BaseplateThroughPowder);
SubstrateInit_FromFile(SubstrateFileName, nz, nx, MyYSlices, MyYOffset, id, GrainID, ZMin, ZMaxLayer,
BaseplateThroughPowder, PowderFirstLayer, LayerHeight, deltax);
else
BaseplateInit_FromGrainSpacing(SubstrateGrainSpacing, nx, ny, ZMinLayer, ZMaxLayer, MyYSlices, MyYOffset,
id, deltax, GrainID, RNGSeed, NextLayer_FirstEpitaxialGrainID, nz,
BaseplateThroughPowder);
BaseplateInit_FromGrainSpacing(SubstrateGrainSpacing, nx, ny, ZMin, ZMaxLayer, MyYSlices, MyYOffset, id,
deltax, GrainID, RNGSeed, NextLayer_FirstEpitaxialGrainID, nz,
BaseplateThroughPowder, PowderFirstLayer, LayerHeight);
// Optionally generate powder grain structure for top of layer 0
if (PowderFirstLayer)
PowderInit(0, nx, ny, LayerHeight, ZMaxLayer, ZMin, deltax, MyYSlices, MyYOffset, id, GrainID, RNGSeed,
NextLayer_FirstEpitaxialGrainID, PowderActiveFraction);
// Separate routine for active cell data structure init for problems other than constrained solidification
if (RemeltingYN)
CellTypeInit_Remelt(nx, MyYSlices, LocalActiveDomainSize, CellType, CritTimeStep, id, ZBound_Low);
Expand Down
Loading

0 comments on commit b869c0a

Please sign in to comment.