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::Realm_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:235
amrex::Array4< const amrex::Real > m_local_array
Local array view for GPU-compatible operator() access.
Definition: ERF_EBIFBuildings.H:242
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > m_problo
Cached geometry data for GPU-compatible access.
Definition: ERF_EBIFBuildings.H:238
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > m_dx
Definition: ERF_EBIFBuildings.H:239
amrex::STLtools m_stl_tools
STL tools object (for loading and processing STL files)
Definition: ERF_EBIFBuildings.H:229
amrex::Geometry m_geom
Domain geometry (for coordinate transformations)
Definition: ERF_EBIFBuildings.H:226
std::shared_ptr< amrex::MultiFab > m_levelset_mf
Pre-sampled signed distance field (distributed MultiFab for parallel computation)
Definition: ERF_EBIFBuildings.H:232
Definition: ERF_ConsoleIO.cpp:15

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  // Convert physical coordinates to cell indices (floating point)
165  Real i_real = (x - m_problo[0]) / m_dx[0];
166  Real j_real = (y - m_problo[1]) / m_dx[1];
167  Real k_real = (z - m_problo[2]) / m_dx[2];
168 
169  // Get integer cell indices
170  int i = static_cast<int>(std::floor(i_real));
171  int j = static_cast<int>(std::floor(j_real));
172  int k = static_cast<int>(std::floor(k_real));
173 
174  // Check if point is within data bounds
175  if (!m_data_box.contains(IntVect(AMREX_D_DECL(i, j, k))) ||
176  !m_data_box.contains(IntVect(AMREX_D_DECL(i + 1, j + 1, k + 1)))) {
177  // Outside sampled region - assume fluid (negative distance)
178  return -1.0;
179  }
180 
181  // Trilinear interpolation weights
182  Real wx = i_real - static_cast<Real>(i);
183  Real wy = j_real - static_cast<Real>(j);
184  Real wz = k_real - static_cast<Real>(k);
185 
186  // Access replicated levelset data
187  auto const& arr = m_local_array;
188 
189  // Trilinear interpolation
190  Real phi_000 = arr(i, j, k);
191  Real phi_100 = arr(i + 1, j, k);
192  Real phi_010 = arr(i, j + 1, k);
193  Real phi_110 = arr(i + 1, j + 1, k);
194  Real phi_001 = arr(i, j, k + 1);
195  Real phi_101 = arr(i + 1, j, k + 1);
196  Real phi_011 = arr(i, j + 1, k + 1);
197  Real phi_111 = arr(i + 1, j + 1, k + 1);
198 
199  Real phi_00 = phi_000 * (1.0 - wx) + phi_100 * wx;
200  Real phi_01 = phi_001 * (1.0 - wx) + phi_101 * wx;
201  Real phi_10 = phi_010 * (1.0 - wx) + phi_110 * wx;
202  Real phi_11 = phi_011 * (1.0 - wx) + phi_111 * wx;
203 
204  Real phi_0 = phi_00 * (1.0 - wy) + phi_10 * wy;
205  Real phi_1 = phi_01 * (1.0 - wy) + phi_11 * wy;
206 
207  Real phi = phi_0 * (1.0 - wz) + phi_1 * wz;
208 
209  return phi;
210  }

Referenced by operator()().

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.
220  {
221  return this->operator()(AMREX_D_DECL(p[0], p[1], p[2]));
222  }
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:280
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: