Skip to content

Commit

Permalink
Shared Voronoi functionality between baseplate and powder init (#372)
Browse files Browse the repository at this point in the history
* Shared Voronoi functionality between baseplate and powder init

* Updated deprecation notices and log file print
  • Loading branch information
MattRolchigo authored Aug 28, 2024
1 parent c4756dd commit 50929fd
Show file tree
Hide file tree
Showing 16 changed files with 216 additions and 207 deletions.
2 changes: 1 addition & 1 deletion examples/Inp_Finch.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"TrimUnmeltedRegion": true
},
"Substrate": {
"MeanSize": 50
"MeanBaseplateGrainSize": 50
},
"Printing": {
"PathToOutput": "./",
Expand Down
2 changes: 1 addition & 1 deletion examples/Inp_FinchTranslate.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"StDev": 0.5
},
"Substrate": {
"MeanSize": 50
"MeanBaseplateGrainSize": 50
},
"TemperatureData": {
"TranslationCount": 2,
Expand Down
4 changes: 2 additions & 2 deletions examples/Inp_SingleLine.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
"TemperatureFiles": ["examples/Temperatures/Line.txt"]
},
"Substrate": {
"MeanSize": 25,
"PowderDensity": 64000,
"MeanBaseplateGrainSize": 25,
"MeanPowderGrainSize": 2.5,
"BaseplateTopZ": -0.000020
},
"Printing": {
Expand Down
4 changes: 2 additions & 2 deletions examples/Inp_SingleLineTranslate.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
"AlternatingDirection": true
},
"Substrate": {
"MeanSize": 25,
"PowderDensity": 64000,
"MeanBaseplateGrainSize": 25,
"MeanPowderGrainSize": 2.5,
"BaseplateTopZ": -0.000020
},
"Printing": {
Expand Down
2 changes: 1 addition & 1 deletion examples/Inp_SmallFinch.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"StDev": 0.5
},
"Substrate": {
"MeanSize": 75
"MeanBaseplateGrainSize": 75
},
"Printing": {
"PathToOutput": "./",
Expand Down
4 changes: 2 additions & 2 deletions examples/Inp_SmallSpotMelt.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"R": 300000
},
"Substrate": {
"MeanSize": 25,
"PowderDensity": 1000000
"MeanBaseplateGrainSize": 25,
"MeanPowderGrainSize": 1000000
},
"Printing": {
"PathToOutput": "./",
Expand Down
4 changes: 2 additions & 2 deletions examples/Inp_SpotMelt.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"R": 300000
},
"Substrate": {
"MeanSize": 25,
"PowderDensity": 1000000
"MeanBaseplateGrainSize": 25,
"MeanPowderGrainSize": 1
},
"Printing": {
"PathToOutput": "./",
Expand Down
4 changes: 2 additions & 2 deletions examples/Inp_TwoLineTwoLayer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
"TemperatureFiles": ["examples/Temperatures/TwoLine.txt"]
},
"Substrate": {
"MeanSize": 25,
"PowderDensity": 64000
"MeanBaseplateGrainSize": 25,
"MeanPowderGrainSize": 2.5
},
"Printing": {
"PathToOutput": "./",
Expand Down
4 changes: 2 additions & 2 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ The .json files in the examples subdirectory are provided on the command line to
|GrainLocationsY | Directional | List of grain locations in Y on the bottom surface of the domain (see note (b-iii))
|GrainIDs | Directional | GrainID values for each grain in (X,Y) (see note (b3))
|FillBottomSurface | Directional | Optionally assign all cells on the bottom surface the grain ID of the closest grain (defaults to false)
|MeanSize | Spot, FromFile, FromFinch | Mean spacing between grain centers in the baseplate/substrate (in microns) (see note (a))
|MeanBaseplateGrainSize | Spot, FromFile, FromFinch | Mean spacing between grain centers in the baseplate/substrate (in microns) (see note (a))
|SubstrateFilename | Spot, FromFile, FromFinch | Path to and filename for substrate data in vtk format (see note (a))
|PowderDensity | Spot, FromFile, FromFinch | Density of sites in the powder layer to be assigned as the home of a unique grain, normalized by 1 x 10^12 m^-3 (default value is 1/(CA cell size ^3) (see note (a))
|MeanPowderGrainSize | Spot, FromFile, FromFinch | Mean spacing between grain centers in the powder layer (in microns). Defaults to one grain per cell
|ExtendSubstrateThroughPowder| FromFile, FromFinch | true/false value: Whether to use the baseplate microstructure as the boundary condition for the entire height of the simulation (defaults to false) (see note (a))
| BaseplateTopZ | FromFile, FromFinch | The Z coordinate that marks the top of the baseplate/boundary of the baseplate with the powder. If not given, Z = 0 microns will be assumed to be the baseplate top if ExtendSubstrateThroughPowder = false (If ExtendSubstrateThroughPowder = true, the entire domain will be initialized with the baseplate grain structure)
|GrainOrientation | SingleGrain | Which orientation from the orientation's file is assigned to the grain (starts at 0). Default is 0
Expand Down
253 changes: 112 additions & 141 deletions src/CAcelldata.hpp

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions src/CAinputdata.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,8 @@ struct SubstrateInputs {
bool use_substrate_file = false;
bool baseplate_through_powder = false;
std::string substrate_filename = "";
double substrate_grain_spacing = 0.0;
// defaults to all sites in powder layer initialized with a new grain
double powder_active_fraction = 1.0;
double baseplate_grain_spacing = 0.0;
double powder_grain_spacing = 1.0;
// Top of baseplate assumed at Z = 0 if not otherwise given
double baseplate_top_z = 0.0;
// Initial size of octahedra during initialization of an active cell
Expand Down
111 changes: 76 additions & 35 deletions src/CAinputs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,19 +311,43 @@ struct Inputs {
else {
// Substrate data - should data come from an initial size or a file?
if ((input_data["Substrate"].contains("SubstrateFilename")) &&
(input_data["Substrate"].contains("MeanSize")))
((input_data["Substrate"].contains("MeanSize")) ||
(input_data["Substrate"].contains("MeanBaseplateGrainSize"))))
throw std::runtime_error(
"Error: only one of substrate grain size and substrate structure filename should "
"Error: only one of baseplate grain size and substrate structure filename should "
"be provided in the input file");
else if (input_data["Substrate"].contains("SubstrateFilename")) {
substrate.substrate_filename = input_data["Substrate"]["SubstrateFilename"];
if (substrate.substrate_filename.substr(substrate.substrate_filename.length() - 4) != ".vtk")
throw std::runtime_error("Error: Substrate filename must be a vtk file");
substrate.use_substrate_file = true;
}
else if (input_data["Substrate"].contains("MeanSize")) {
substrate.substrate_grain_spacing = input_data["Substrate"]["MeanSize"];
substrate.use_substrate_file = false;
else if (input_data["Substrate"].contains("MeanSize") ||
(input_data["Substrate"].contains("MeanBaseplateGrainSize"))) {
// Case where only the deprecated input MeanSize was given
if (!input_data["Substrate"].contains("MeanBaseplateGrainSize")) {
substrate.baseplate_grain_spacing = input_data["Substrate"]["MeanSize"];
substrate.use_substrate_file = false;
if (id == 0)
std::cout
<< "Warning: deprecated input MeanSize has been replaced with MeanBaseplateGrainSize, "
"compatibility with MeanSize input will be removed in a future release"
<< std::endl;
}
else {
// Case were the new input MeanBaseplateGrainSize was given
substrate.baseplate_grain_spacing = input_data["Substrate"]["MeanBaseplateGrainSize"];
substrate.use_substrate_file = false;
// Warning for case where both the deprecated and new input were given
if ((input_data["Substrate"].contains("MeanSize")) && (id == 0))
std::cout << "Warning: redundant inputs MeanSize and MeanBaseplateGrainSize were given - "
"deprecated input MeanSize will be ignored"
<< std::endl;
}
// Check that baseplate_grain_spacing is valid
if ((id == 0) && (substrate.baseplate_grain_spacing < domain.deltax))
throw std::runtime_error(
"Error: Input MeanBaseplateGrainSize must be no smaller than the CA cell size");
}
if (simulation_type == "Spot") {
// No powder for this problem type, baseplate top at Z = 0
Expand All @@ -337,14 +361,45 @@ struct Inputs {
// defaults to a unique grain at each site in the powder layers if not given
if (input_data["Substrate"].contains("PowderDensity")) {
// powder density is given as a density per unit volume, normalized by 10^12 m^-3 --> convert this
// into a density of sites active on the CA grid (0 to 1)
substrate.powder_active_fraction = input_data["Substrate"]["PowderDensity"];
substrate.powder_active_fraction =
substrate.powder_active_fraction * pow(10, 12) * pow(domain.deltax, 3);
if ((substrate.powder_active_fraction < 0.0) || (substrate.powder_active_fraction > 1.0))
// into a powder grain spacing
if (id == 0)
std::cout << "Warning: PowderDensity input has been deprecated and will be removed in a future "
"release, please specify MeanPowderGrainSpacing in microns"
<< std::endl;
// Warning for a case where the old input PowderDensity and new input MeanPowderGrainSize are both
// given
if (input_data["Substrate"].contains("MeanPowderGrainSize")) {
if (id == 0)
std::cout << "Warning: Redundant inputs PowderDensity and MeanPowderGrainSize were given - "
"deprecated input PowderDensity will be ignored"
<< std::endl;
}
else {
double powder_density_input = input_data["Substrate"]["PowderDensity"];
double powder_active_fraction = powder_density_input * pow(10, 12) * pow(domain.deltax, 3);
if ((powder_active_fraction < 0.0) || (powder_active_fraction > 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)");
// convert powder density into a powder grain spacing, in microns
substrate.powder_grain_spacing =
pow((1.0 / (powder_density_input * pow(10, 12))), 1.0 / 3.0) * pow(10, 6);
if (id == 0)
std::cout << "Calculated powder layer grain spacing using PowderDensity is "
<< substrate.powder_grain_spacing << " microns" << std::endl;
}
}
if (input_data["Substrate"].contains("MeanPowderGrainSize")) {
substrate.powder_grain_spacing = input_data["Substrate"]["MeanPowderGrainSize"];
if ((id == 0) && (substrate.powder_grain_spacing < domain.deltax))
throw std::runtime_error(
"Error: Density of powder surface sites active must be larger than 0 and less "
"than 1/(CA cell volume)");
"Error: Input MeanPowderGrainSize must be no smaller than the CA cell size");
}
else if ((!input_data["Substrate"].contains("PowderDensity")) &&
(!input_data["Substrate"].contains("MeanPowderGrainSize"))) {
// Case where neither PowderDensity nor MeanPowderGrainSize inputs are given - defaults to powder
// active fraction of 1, mean powder grain size equal to the cell size
substrate.powder_grain_spacing = domain.deltax;
}
if ((input_data["Substrate"].contains("PowderFirstLayer")) && (id == 0))
std::cout
Expand All @@ -355,10 +410,11 @@ struct Inputs {
// file)
if (input_data["Substrate"].contains("BaseplateTopZ"))
substrate.baseplate_top_z = input_data["Substrate"]["BaseplateTopZ"];
if ((substrate.baseplate_through_powder) && (input_data["Substrate"].contains("PowderDensity")))
if ((substrate.baseplate_through_powder) && ((input_data["Substrate"].contains("PowderDensity")) ||
(input_data["Substrate"].contains("MeanPowderGrainSize"))))
throw std::runtime_error(
"Error: if the option to extend the baseplate through the powder layers is "
"toggled, a powder layer density cannot be given");
"toggled, a powder layer density or powder grain size cannot be given");
}
// Optional input for initial size of octhedra when a cell begins solidification (in units of CA cells)
if (input_data["Substrate"].contains("InitOctahedronSize")) {
Expand Down Expand Up @@ -633,25 +689,6 @@ struct Inputs {
std::cout << "Successfully parsed data printing options from input file" << std::endl;
}

// Ensure that input powder layer init options are compatible with this domain size, if needed for this problem type
// TODO: Expand check that inputs are valid for the problem type
void checkPowderOverflow(const int nx, const int ny, const int layer_height, const int number_of_layers) {
// Check to make sure powder grain density is compatible with the number of powder sites
// If this problem type includes a powder layer of some grain density, ensure that integer overflow won't occur
// when assigning powder layer GrainIDs
if (!(substrate.baseplate_through_powder)) {
long int num_cells_powder_layers = static_cast<long int>(nx) * static_cast<long int>(ny) *
static_cast<long int>(layer_height) *
static_cast<long int>(number_of_layers - 1);
long int num_assigned_cells_powder_layers = std::lround(
Kokkos::round(static_cast<double>(num_cells_powder_layers) * substrate.powder_active_fraction));
if (num_assigned_cells_powder_layers > INT_MAX)
throw std::runtime_error(
"Error: A smaller value for powder density is required to avoid potential integer "
"overflow when assigning powder layer GrainID");
}
}

// Print a log file for this ExaCA run in json file format, containing information about the run parameters used
// from the input file as well as the decomposition scheme
void printExaCALog(const int id, const int np, const int cycle, const Grid grid, Timers timers,
Expand Down Expand Up @@ -723,8 +760,12 @@ struct Inputs {
if (substrate.use_substrate_file)
exaca_log << " \"SubstrateFilename\": "
<< "\"" << substrate.substrate_filename << "\"" << std::endl;
else
exaca_log << " \"MeanSize\": " << substrate.substrate_grain_spacing << std::endl;
else {
exaca_log << " \"MeanSize\": " << substrate.baseplate_grain_spacing << "," << std::endl;
exaca_log << " \"MeanBaseplateGrainSize\": " << substrate.baseplate_grain_spacing << ","
<< std::endl;
exaca_log << " \"MeanPowderGrainSize\": " << substrate.powder_grain_spacing << std::endl;
}
}
exaca_log << " }," << std::endl;
exaca_log << " \"InterfacialResponse\": {" << std::endl;
Expand Down
6 changes: 3 additions & 3 deletions src/CAnucleation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@ struct Nucleation {
std::shuffle(nuclei_grain_id_whole_domain_v.begin(), nuclei_grain_id_whole_domain_v.end(), generator);
std::shuffle(nuclei_undercooling_whole_domain_v.begin(), nuclei_undercooling_whole_domain_v.end(), generator);
if ((id == 0) && (nuclei_this_layer > 0))
std::cout << "Range of Grain IDs from which layer " << layernumber
<< " nucleation events were selected: " << nuclei_whole_domain + 1 << " through "
<< nuclei_whole_domain + nuclei_this_layer << std::endl;
std::cout << "Range of Grain IDs from which layer " << layernumber << " nucleation events were selected: -"
<< nuclei_whole_domain + 1 << " through -" << nuclei_whole_domain + nuclei_this_layer
<< std::endl;
// Update number of nuclei counter for whole domain based on the number of nuclei in this layer
nuclei_whole_domain += nuclei_this_layer;

Expand Down
4 changes: 0 additions & 4 deletions src/runCA.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ void runExaCA(int id, int np, Inputs inputs, Timers timers, Grid grid, Temperatu
// Material response function
InterfacialResponseFunction irf(inputs.domain.deltat, grid.deltax, inputs.irf);

// Ensure that input powder layer init options are compatible with this domain size, if needed for this problem type
if (simulation_type == "FromFile")
inputs.checkPowderOverflow(grid.nx, grid.ny, grid.layer_height, grid.number_of_layers);

// Read temperature data if necessary
if (simulation_type == "FromFile")
temperature.readTemperatureData(id, grid, 0);
Expand Down
8 changes: 4 additions & 4 deletions unit_test/tstCellData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,9 @@ void testCellDataInit(bool powder_first_layer) {
// baseplate. This grain spacing ensures that there will be 1 grain per number of MPI ranks present (larger when
// powder layer is present as the baseplate will only have a third as many cells)
if (powder_first_layer)
inputs.substrate.substrate_grain_spacing = 2.62;
inputs.substrate.baseplate_grain_spacing = 2.62;
else
inputs.substrate.substrate_grain_spacing = 3.0;
inputs.substrate.baseplate_grain_spacing = 3.0;
inputs.rng_seed = 0.0;

// Create dummy temperature data
Expand All @@ -295,10 +295,10 @@ void testCellDataInit(bool powder_first_layer) {
CellData<memory_space> celldata(grid, inputs.substrate);
// Check that substrate inputs were copied from inputs struct correctly
EXPECT_DOUBLE_EQ(inputs.substrate.baseplate_top_z, celldata._inputs.baseplate_top_z);
EXPECT_DOUBLE_EQ(inputs.substrate.substrate_grain_spacing, celldata._inputs.substrate_grain_spacing);
EXPECT_DOUBLE_EQ(inputs.substrate.baseplate_grain_spacing, celldata._inputs.baseplate_grain_spacing);
EXPECT_FALSE(celldata._inputs.use_substrate_file);
EXPECT_FALSE(celldata._inputs.baseplate_through_powder);
EXPECT_DOUBLE_EQ(celldata._inputs.powder_active_fraction, 1.0);
EXPECT_DOUBLE_EQ(celldata._inputs.powder_grain_spacing, grid.deltax * pow(10, 6));
// Initialize baseplate grain structure
celldata.initSubstrate(id, grid, inputs.rng_seed, number_of_solidification_events);

Expand Down
Loading

0 comments on commit 50929fd

Please sign in to comment.