Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
322dbdc
usable fix to velocity BC for channel_regular
Jul 2, 2025
5910371
formatting change
Jul 2, 2025
b92df4a
formatting with llvm 20.1.7
Jul 3, 2025
4168c20
blocked unused variables
Jul 3, 2025
6c10113
removed commented code
Jul 3, 2025
79ecc99
fixed periodicity and n_cell
Jul 23, 2025
0b307e1
zero gradient outlet
Jul 23, 2025
34603d0
Merge branch 'main' into main
marchdf Jul 24, 2025
67d370e
build fix
marchdf Jul 24, 2025
ed73c99
default to something wrong so we know it's wrong
marchdf Jul 24, 2025
dc90053
white space
marchdf Jul 24, 2025
1527ff3
consolidate mach
marchdf Jul 24, 2025
2454387
remove um
marchdf Jul 24, 2025
453e7dc
consolidate input file
marchdf Jul 24, 2025
c20d35b
remove a couple other input options
marchdf Jul 24, 2025
4cad3ac
Merge branch 'NREL:main' into main
nileshsawant Aug 18, 2025
012f57f
Merge branch 'NREL:main' into main
nileshsawant Aug 21, 2025
38c935c
Merge branch 'NREL:main' into main
nileshsawant Aug 26, 2025
7eb0ddc
cylinder shedding case
Aug 26, 2025
59be659
corrected underline length
Aug 26, 2025
9d16e58
Merge branch 'NREL:main' into main
nileshsawant Sep 11, 2025
9e9d02f
Possible fix to AMR reflections. compute_q_corrections is needed befo…
Sep 11, 2025
e7fe638
turek amr input file
Sep 11, 2025
223a473
draft isothermal BC
Sep 15, 2025
e7b223e
removed unused variable nn
Sep 15, 2025
db27a1a
fix for implicit capture nvcc error
Sep 15, 2025
a8b324d
case style fix
Sep 16, 2025
b7c8613
seperated amr turek into its own folder
Sep 24, 2025
adbd2b6
added tureks to tests
Sep 24, 2025
965ccac
tureks 2D tests only
Sep 24, 2025
b7541a9
test turek only in 3D
Sep 25, 2025
cdacebc
crashing even after bound checks
Oct 10, 2025
6cd8ce5
Merge branch 'main' into backup-before-reset
Oct 11, 2025
ebb4f95
tentative hot plate at bottom
Oct 11, 2025
cf88f0b
inputs for geothermal cracks
Oct 11, 2025
dfb2e57
file converters
Oct 11, 2025
9037ceb
binary file reading capability
Oct 15, 2025
c8b2fd0
draft cracks
Oct 16, 2025
3992f32
csv reading capability added
Oct 16, 2025
3fec0b4
unit conversion explained
Oct 16, 2025
6a1bc41
added csv geom input file
Oct 16, 2025
0a03010
fixed default initialization to fluid in the code. Added fluid only l…
Oct 16, 2025
e0cd3b3
removed amr turek from tests
Oct 20, 2025
75c22e6
not checking q>=0 code quality test
Oct 20, 2025
b84e166
more codeQL fix
Oct 20, 2025
ee5740f
corrected X,Y,Z coordinates but ignoring dummmy points
Oct 22, 2025
d36cb76
corrected 1st and last slice
Oct 30, 2025
d11a2bd
formatting
Oct 30, 2025
6fa4ee8
remove bound checks
Oct 30, 2025
6fee785
Merge branch 'backup-before-reset' into main
Nov 3, 2025
fc512b2
addressed some warnings
Nov 3, 2025
952d233
isothermal wall BC, .bin and .csv voxel reading, cracks test case
Nov 3, 2025
8be1e97
fixed file loading error on GPU
Nov 6, 2025
1d49ef1
changed long long to long
Nov 11, 2025
9d06a51
changed long long to long
Nov 11, 2025
a984ad4
python scripts do not auromatically install dependencies anymore
Nov 11, 2025
72536b5
use uvx to install modules or suggest uv install commands
Nov 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Source/Constants.H
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ static constexpr int D_Q_CORR_X_IDX = 4;
static constexpr int D_Q_CORR_Y_IDX = 5;
static constexpr int D_Q_CORR_Z_IDX = 6;

static constexpr int N_IS_FLUID = 2;
static constexpr int N_IS_FLUID = 3;

static constexpr amrex::Real ROOT3 =
static_cast<amrex::Real>(1.732050807568877293527446341);
Expand Down
5 changes: 5 additions & 0 deletions Source/EB.H
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ namespace lbm {
void initialize_eb(const amrex::Geometry& geom, const int max_level);
void initialize_from_stl(
const amrex::Geometry& geom, amrex::iMultiFab& is_fluid);
std::vector<uint16_t>
read_crack_file(const std::string& filename, int nx, int ny, int nz);

void generate_voxel_cracks(
const amrex::Geometry& geom, amrex::iMultiFab& is_fluid);

} // namespace lbm
#endif
210 changes: 207 additions & 3 deletions Source/EB.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "EB.H"
#include "Geometry.H"
#include <cstring> // for std::memcpy
#include <sstream> // for CSV parsing

namespace lbm {
void initialize_eb(const amrex::Geometry& geom, const int max_level)
Expand Down Expand Up @@ -27,12 +29,15 @@ void initialize_eb(const amrex::Geometry& geom, const int max_level)
amrex::Vector<std::string> amrex_defaults(
{"all_regular", "box", "cylinder", "plane", "sphere", "torus", "parser",
"stl"});
if (!(std::find(amrex_defaults.begin(), amrex_defaults.end(), geom_type) !=
amrex_defaults.end())) {
if (std::find(amrex_defaults.begin(), amrex_defaults.end(), geom_type) ==
amrex_defaults.end()) {
std::unique_ptr<lbm::Geometry> geometry(
lbm::Geometry::create(geom_type));
geometry->build(geom, max_coarsening_level);
} else {
// For all AMReX default types (including voxel_cracks), use standard
// build voxel_cracks will override the m_is_fluid in
// initialize_from_stl
amrex::EB2::Build(geom, max_level, max_level);
}
}
Expand Down Expand Up @@ -84,11 +89,210 @@ void initialize_from_stl(
static_cast<int>(marker_arrs[nbx](i, j, k, 0));
});
amrex::Gpu::synchronize();
} else if ((!name.empty()) && (geom_type != "all_regular")) {
}

// Check for voxel crack generation flag
int use_voxel_cracks = 0;
pp.query("use_voxel_cracks", use_voxel_cracks);
if (use_voxel_cracks != 0) {
amrex::Print() << "Using voxel crack generation" << std::endl;
generate_voxel_cracks(geom, is_fluid);
return;
}

if ((!name.empty()) && (geom_type != "all_regular")) {
amrex::Abort(
"LBM::initialize_from_stl() geom_type should be all_regular to "
"avoid issues");
}
}

std::vector<uint16_t>
read_crack_file(const std::string& filename, int nx, int ny, int nz)
{
BL_PROFILE("LBM::read_crack_file()");

// Auto-detect file format
bool is_csv =
(filename.size() >= 4 &&
filename.substr(filename.size() - 4) == ".csv");

// Use AMReX's cross-platform file reading utilities
amrex::Vector<char> file_char_ptr;

// Use AMReX's parallel-safe file reading
try {
amrex::ParallelDescriptor::ReadAndBcastFile(filename, file_char_ptr);
} catch (const std::exception& e) {
amrex::Abort(
"Error reading crack file: " + filename + " - " +
std::string(e.what()));
}

std::vector<uint16_t> crack_data(
static_cast<size_t>(nx) * static_cast<size_t>(ny) *
static_cast<size_t>(nz));

if (is_csv) {
// Parse CSV format
if (amrex::ParallelDescriptor::IOProcessor()) {
std::fill(
crack_data.begin(), crack_data.end(), 1); // Initialize as solid

std::string file_content(
file_char_ptr.data(), file_char_ptr.size());
std::istringstream iss(file_content);
std::string line;

// Skip header line
if (!std::getline(iss, line)) {
amrex::Abort("CSV file is empty or corrupted: " + filename);
}

size_t line_count = 0;
while (std::getline(iss, line)) {
// Skip empty lines
if (line.empty()) {
continue;
}

std::istringstream line_stream(line);
std::string token;

// Parse tokens: X, Y, Z (discard), then tag
int tag;
try {
// discard X
if (!std::getline(line_stream, token, ',')) {
continue;
}
// discard Y
if (!std::getline(line_stream, token, ',')) {
continue;
}
// discard Z
if (!std::getline(line_stream, token, ',')) {
continue;
}
// read tag
if (std::getline(line_stream, token, ',')) {
tag = std::stoi(token);
} else {
continue;
}
} catch (const std::exception& e) {
// Skip malformed lines
continue;
}

// CSV and binary are written in identical sequence by
// mainCrackGenerator.C Both loop: k(Z) -> j(Y) -> i(X), so just
// read sequentially The X,Y,Z coordinates are metadata - what
// matters is the order

if (line_count < static_cast<size_t>(nx) *
static_cast<size_t>(ny) *
static_cast<size_t>(nz)) {
crack_data[line_count] = static_cast<uint16_t>(tag);
}
line_count++;
}

amrex::Print() << "Successfully read CSV crack file: " << filename
<< " (" << line_count << " data points)"
<< std::endl;
}
// Broadcast the parsed data to all processors
amrex::ParallelDescriptor::Bcast(
crack_data.data(), crack_data.size() * sizeof(uint16_t), 0);

} else {
// Parse binary format
size_t expected_size = static_cast<size_t>(nx) *
static_cast<size_t>(ny) *
static_cast<size_t>(nz) * sizeof(uint16_t);

// ReadAndBcastFile may add extra bytes, so ensure we only use what we
// need
if (static_cast<size_t>(file_char_ptr.size()) < expected_size) {
amrex::Abort(
"Binary file too small after reading. Expected: " +
std::to_string(expected_size) + " bytes, got: " +
std::to_string(file_char_ptr.size()) + " bytes");
}

// Convert char data to uint16_t array
std::memcpy(crack_data.data(), file_char_ptr.data(), expected_size);

if (amrex::ParallelDescriptor::IOProcessor()) {
amrex::Print() << "Successfully read binary crack file: "
<< filename << " (" << expected_size << " bytes)"
<< std::endl;
}
}

return crack_data;
}

void generate_voxel_cracks(
const amrex::Geometry& geom, amrex::iMultiFab& is_fluid)
{
BL_PROFILE("LBM::generate_voxel_cracks()");

amrex::ParmParse pp("voxel_cracks");

// Get grid dimensions from domain
const amrex::Box& domain = geom.Domain();
const int nx = domain.length(0);
const int ny = domain.length(1);
const int nz = domain.length(2);

amrex::Print() << "Loading voxel cracks for domain: " << nx << " x " << ny
<< " x " << nz << std::endl;

// Get binary crack file path
std::string crack_file;
if (pp.query("crack_file", crack_file) == 0) {
// Default filename pattern matching mainCrackGenerator.C output
crack_file = "microstructure_nX" + std::to_string(nx) + "_nY" +
std::to_string(ny) + "_nZ" + std::to_string(nz) + ".bin";
}

// Read crack pattern from file (auto-detect format)
std::vector<uint16_t> crack_data = read_crack_file(crack_file, nx, ny, nz);

// Initialize all cells as SOLID first
is_fluid.setVal(1);

// Copy crack data to GPU-accessible memory for CUDA builds
amrex::Gpu::DeviceVector<uint16_t> d_crack_data(crack_data.size());
amrex::Gpu::copyAsync(
amrex::Gpu::hostToDevice, crack_data.begin(), crack_data.end(),
d_crack_data.begin());
amrex::Gpu::synchronize();

// Get raw pointer for device access
auto const* crack_ptr = d_crack_data.data();

// Copy crack data to MultiFab using GPU-compatible approach
// Your file stores in k,j,i (z,y,x) order
for (amrex::MFIter mfi(is_fluid); mfi.isValid(); ++mfi) {
const amrex::Box& box = mfi.validbox();
amrex::Array4<int> const& is_fluid_arr = is_fluid.array(mfi);

amrex::ParallelFor(
box, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
// Convert AMReX (i,j,k) to file index (z,y,x order)
int file_index = k * (nx * ny) + j * nx + i;
// Your binary file: 0 = fluid (tubes), 1 = solid
// AMReX m_is_fluid: 0 = solid, 1 = fluid
// So we need to invert the values
is_fluid_arr(i, j, k, 0) = (crack_ptr[file_index] == 0) ? 1 : 0;
});
}
amrex::Gpu::synchronize();

amrex::Print() << "Voxel crack generation complete" << std::endl;
}

} // namespace lbm
6 changes: 6 additions & 0 deletions Source/LBM.H
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,12 @@ private:
// Initial temperature.
amrex::Real m_initialTemperature = 1.0 / 3.0;

// Body is isothermal.
bool m_bodyIsIsothermal = false;

// Body temperature.
amrex::Real m_bodyTemperature = 1.0 / 3.0;

// Adiabatic exponent.
amrex::Real m_adiabaticExponent = 5.0 / 3.0;

Expand Down
Loading