ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
BuildingsIF Class Reference

Buildings implicit function backed by STL triangle mesh. More...

#include <ERF_EBIFBuildings.H>

Collaboration diagram for BuildingsIF:

Public Member Functions

 BuildingsIF (std::string const &stl_file, amrex::Real scale, amrex::Array< amrex::Real, 3 > const &center, int reverse_normal, amrex::Geometry const &geom)
 Construct a buildings implicit function from an STL file. More...
 
AMREX_GPU_HOST_DEVICE amrex::Real operator() (AMREX_D_DECL(amrex::Real x, amrex::Real y, amrex::Real z)) const noexcept
 Evaluate signed distance at a point. More...
 
AMREX_GPU_HOST_DEVICE amrex::Real operator() (const amrex::RealArray &p) const noexcept
 Evaluate signed distance at a point array. More...
 

Protected Attributes

amrex::Geometry m_geom
 Domain geometry (for coordinate transformations) More...
 
amrex::STLtools m_stl_tools
 STL tools object (for loading and processing STL files) More...
 
std::shared_ptr< amrex::MultiFab > m_levelset_mf
 Pre-sampled signed distance field (distributed MultiFab for parallel computation) More...
 
amrex::Box m_data_box
 Bounding box of sampled data. More...
 
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > m_problo
 Cached geometry data for GPU-compatible access. More...
 
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > m_dx
 
amrex::Array4< const amrex::Real > m_local_array
 Local array view for GPU-compatible operator() access. More...
 

Detailed Description

Buildings implicit function backed by STL triangle mesh.

This class provides an implicit function interface for building geometry loaded from STL files. It uses AMReX's STL infrastructure with BVH (Bounding Volume Hierarchy) acceleration for efficient signed distance queries.

The operator evaluates signed distance at any 3D point, following the AMReX EB convention: positive = inside solid (building), zero = boundary, negative = fluid.

Note: This class pre-samples the STL geometry onto a reference grid and interpolates at query points. For very large or complex geometries, consider using AMReX's IndexSpaceSTL directly instead.

Constructor & Destructor Documentation

◆ BuildingsIF()

BuildingsIF::BuildingsIF ( std::string const &  stl_file,
amrex::Real  scale,
amrex::Array< amrex::Real, 3 > const &  center,
int  reverse_normal,
amrex::Geometry const &  geom 
)
inline

Construct a buildings implicit function from an STL file.

Parameters
stl_filePath to the STL mesh file (binary or ASCII format).
scaleUniform scaling factor applied to STL coordinates (typically 1.0).
centerTranslation vector to recenter the mesh [m].
reverse_normalNon-zero to flip triangle normals if needed.
geomDomain geometry for grid setup and BVH optimization.

The constructor:

  1. Loads the STL file using AMReX::STLtools
  2. Builds a BVH acceleration structure for fast distance queries
  3. Pre-samples signed distances onto a reference grid
  4. Stores interpolation data for operator() calls
64  : m_geom(geom)
65  {
66  using namespace amrex;
67 
68  // Load STL file with BVH optimization
69  // This broadcasts triangle data to all ranks internally
70  m_stl_tools.setBVHOptimization(true);
71  m_stl_tools.read_stl_file(stl_file, scale, center, reverse_normal);
72 
73  // Pre-sample signed distance field onto a reference grid
74  // This grid covers the entire domain with sufficient resolution
75  // to capture building features (match computational grid)
76  Box const& domain = geom.Domain();
77  IntVect ngrow_vec(2); // Ghost cells for interpolation
78 
79  Box sampled_box = domain;
80  sampled_box.grow(ngrow_vec);
81 
82  // Create distributed BoxArray and DistributionMapping for parallel computation
83  // Chunk the domain into reasonable-sized boxes for load balancing
84  BoxArray ba(sampled_box);
85  ba.maxSize(32);
86  DistributionMapping dm(ba);
87 
88  // Create distributed MultiFab to hold signed distance values
89  // Each rank will compute its portion in parallel
90  MultiFab mf_distributed(ba, dm, 1, ngrow_vec);
91 
92  // Compute signed distances in parallel across all ranks
93  // fillSignedDistance uses ParallelFor internally, distributing work
94  // across the MultiFab's boxes according to the DistributionMapping
95  m_stl_tools.fillSignedDistance(mf_distributed, ngrow_vec, geom);
96 
97  // Now create a replicated MultiFab where each rank has a copy of the full domain
98  // This is needed because operator() must access data locally (no MPI in GPU kernels)
99 
100  // Create BoxArray with one box per rank, all covering the same spatial region
101  int nprocs = ParallelDescriptor::NProcs();
102  Vector<Box> boxes(nprocs, sampled_box); // All boxes cover the full domain
103  BoxList bl;
104  for (const auto& bx : boxes) {
105  bl.push_back(bx);
106  }
107  BoxArray ba_replicated(std::move(bl));
108 
109  // Create DistributionMapping so each rank owns exactly one box
110  Vector<int> pmap(nprocs);
111  std::iota(pmap.begin(), pmap.end(), 0); // pmap = [0, 1, 2, ..., nprocs-1]
112  DistributionMapping dm_replicated(std::move(pmap));
113 
114  // Each rank will own one box covering the full domain
115  m_levelset_mf = std::make_shared<MultiFab>(ba_replicated, dm_replicated, 1, 0);
116 
117  // ParallelCopy from distributed to replicated
118  // Source: mf_distributed (each rank has different spatial portions)
119  // Dest: m_levelset_mf (each rank will receive the full domain)
120  IntVect dst_nghost(0);
121  m_levelset_mf->ParallelCopy(mf_distributed, 0, 0, 1, ngrow_vec, dst_nghost);
122 
123  // Store bounds for interpolation
124  m_data_box = sampled_box;
125 
126  // Cache geometry data for GPU-compatible access
127  const Real* problo_ptr = geom.ProbLo();
128  const Real* dx_ptr = geom.CellSize();
129  for (int d = 0; d < AMREX_SPACEDIM; ++d) {
130  m_problo[d] = problo_ptr[d];
131  m_dx[d] = dx_ptr[d];
132  }
133 
134  // Set up local array view for operator() access
135  // Each rank iterates its own local box (which contains the full domain)
136  for (MFIter mfi(*m_levelset_mf); mfi.isValid(); ++mfi) {
137  m_local_array = (*m_levelset_mf)[mfi].const_array();
138  break; // Only one box per rank
139  }
140  }
amrex::Real Real
Definition: ERF_ShocInterface.H:19
amrex::Box m_data_box
Bounding box of sampled data.
Definition: ERF_EBIFBuildings.H:238
amrex::Array4< const amrex::Real > m_local_array
Local array view for GPU-compatible operator() access.
Definition: ERF_EBIFBuildings.H:245
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > m_problo
Cached geometry data for GPU-compatible access.
Definition: ERF_EBIFBuildings.H:241
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > m_dx
Definition: ERF_EBIFBuildings.H:242
amrex::STLtools m_stl_tools
STL tools object (for loading and processing STL files)
Definition: ERF_EBIFBuildings.H:232
amrex::Geometry m_geom
Domain geometry (for coordinate transformations)
Definition: ERF_EBIFBuildings.H:229
std::shared_ptr< amrex::MultiFab > m_levelset_mf
Pre-sampled signed distance field (distributed MultiFab for parallel computation)
Definition: ERF_EBIFBuildings.H:235
Definition: ERF_ConsoleIO.cpp:17

Member Function Documentation

◆ operator()() [1/2]

AMREX_GPU_HOST_DEVICE amrex::Real BuildingsIF::operator() ( AMREX_D_DECL(amrex::Real x, amrex::Real y, amrex::Real z)  ) const
inlinenoexcept

Evaluate signed distance at a point.

Parameters
xPhysical x-coordinate [m]
yPhysical y-coordinate [m]
zPhysical z-coordinate [m]
Returns
Signed distance value: >0 inside building, <0 in fluid, =0 at boundary.

This operator performs trilinear interpolation of the pre-sampled signed distance field. For points outside the sampled domain, it returns a negative value (fluid region).

Note: The signed distance field is computed in parallel across ranks during construction, then replicated for fast operator() access.

161  {
162  using namespace amrex;
163 
164  // fillSignedDistance samples at prob_lo + (index + 0.5) * dx.
165  // Convert physical coordinates to continuous cell-centered indices.
166  Real i_real = (x - m_problo[0]) / m_dx[0] - 0.5;
167  Real j_real = (y - m_problo[1]) / m_dx[1] - 0.5;
168  Real k_real = (z - m_problo[2]) / m_dx[2] - 0.5;
169 
170  // Get integer cell indices
171  int i = static_cast<int>(std::floor(i_real));
172  int j = static_cast<int>(std::floor(j_real));
173  int k = static_cast<int>(std::floor(k_real));
174 
175  // Check if point is within data bounds
176  if (!m_data_box.contains(IntVect(AMREX_D_DECL(i, j, k))) ||
177  !m_data_box.contains(IntVect(AMREX_D_DECL(i + 1, j + 1, k + 1)))) {
178  // Outside sampled region - assume fluid (negative distance)
179  return -1.0;
180  }
181 
182  // Trilinear interpolation weights
183  Real wx = i_real - static_cast<Real>(i);
184  Real wy = j_real - static_cast<Real>(j);
185  Real wz = k_real - static_cast<Real>(k);
186 
187  // Access replicated levelset data
188  auto const& arr = m_local_array;
189 
190  // Trilinear interpolation
191  Real phi_000 = arr(i, j, k);
192  Real phi_100 = arr(i + 1, j, k);
193  Real phi_010 = arr(i, j + 1, k);
194  Real phi_110 = arr(i + 1, j + 1, k);
195  Real phi_001 = arr(i, j, k + 1);
196  Real phi_101 = arr(i + 1, j, k + 1);
197  Real phi_011 = arr(i, j + 1, k + 1);
198  Real phi_111 = arr(i + 1, j + 1, k + 1);
199 
200  Real phi_00 = phi_000 * (1.0 - wx) + phi_100 * wx;
201  Real phi_01 = phi_001 * (1.0 - wx) + phi_101 * wx;
202  Real phi_10 = phi_010 * (1.0 - wx) + phi_110 * wx;
203  Real phi_11 = phi_011 * (1.0 - wx) + phi_111 * wx;
204 
205  Real phi_0 = phi_00 * (1.0 - wy) + phi_10 * wy;
206  Real phi_1 = phi_01 * (1.0 - wy) + phi_11 * wy;
207 
208  Real phi = phi_0 * (1.0 - wz) + phi_1 * wz;
209 
210  // fillSignedDistance has the opposite sign to STLtools::fillFab,
211  // including with reversed normals. Match EB: positive solid, negative fluid.
212  return -phi;
213  }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real phi(amrex::Real d, amrex::Real z0, amrex::Real psi) noexcept
Definition: ERF_ImmersedWallCell.H:142

Referenced by operator()().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator()() [2/2]

AMREX_GPU_HOST_DEVICE amrex::Real BuildingsIF::operator() ( const amrex::RealArray &  p) const
inlinenoexcept

Evaluate signed distance at a point array.

Parameters
pPhysical coordinate array [x, y, z] in meters.
Returns
Signed distance value.
223  {
224  return this->operator()(AMREX_D_DECL(p[0], p[1], p[2]));
225  }
AMREX_GPU_HOST_DEVICE amrex::Real operator()(AMREX_D_DECL(amrex::Real x, amrex::Real y, amrex::Real z)) const noexcept
Evaluate signed distance at a point.
Definition: ERF_EBIFBuildings.H:158
@ p
Definition: ERF_WSM6.H:301
Here is the call graph for this function:

Member Data Documentation

◆ m_data_box

amrex::Box BuildingsIF::m_data_box
protected

Bounding box of sampled data.

Referenced by BuildingsIF(), and operator()().

◆ m_dx

amrex::GpuArray<amrex::Real, AMREX_SPACEDIM> BuildingsIF::m_dx
protected

Referenced by BuildingsIF(), and operator()().

◆ m_geom

amrex::Geometry BuildingsIF::m_geom
protected

Domain geometry (for coordinate transformations)

◆ m_levelset_mf

std::shared_ptr<amrex::MultiFab> BuildingsIF::m_levelset_mf
protected

Pre-sampled signed distance field (distributed MultiFab for parallel computation)

Referenced by BuildingsIF().

◆ m_local_array

amrex::Array4<const amrex::Real> BuildingsIF::m_local_array
mutableprotected

Local array view for GPU-compatible operator() access.

Referenced by BuildingsIF(), and operator()().

◆ m_problo

amrex::GpuArray<amrex::Real, AMREX_SPACEDIM> BuildingsIF::m_problo
protected

Cached geometry data for GPU-compatible access.

Referenced by BuildingsIF(), and operator()().

◆ m_stl_tools

amrex::STLtools BuildingsIF::m_stl_tools
protected

STL tools object (for loading and processing STL files)

Referenced by BuildingsIF().


The documentation for this class was generated from the following file: