|
ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
|
#include <ERF_IBFaceSet.H>

Classes | |
| struct | SunState |
| Sun and irradiances of the last compute_shortwave() call, for reports. More... | |
| struct | TwoStreamSun |
| The two-stream sun of the next compute_shortwave() (sun_mode = two_stream). More... | |
Public Member Functions | |
| IBFaceSet (const IBSEBParams ¶ms, int lev) | |
| void | build (const amrex::MultiFab &blanking, const amrex::Geometry &geom) |
| void | add_outside_occluders (const IBFaceSet &coarser, const amrex::IntVect &ratio, const amrex::BoxArray &grids_crse) |
| void | set_two_stream_sun (amrex::Real declination, amrex::Real hour_angle, amrex::Real latitude_deg, amrex::Real toa_irradiance) |
| void | map_buildings_to_level0 (const IBFaceSet &coarser, const amrex::IntVect &ratio) |
| int | building_level0 (int b) const |
| void | release_labels () |
| int | n_faces () const |
| int | n_buildings () const |
| int | n_layers () const |
| int | state_ncomp () const |
| int | n_slots () const |
| const amrex::BoxArray & | state_boxarray () const |
| bool | has_state () const |
| amrex::MultiFab | make_state () const |
| void | compute_view_fractions () |
| void | compute_longwave (const amrex::MultiFab &cons, const TwoStreamCanopyView &canopy=TwoStreamCanopyView{}) |
| void | assign_materials () |
| void | compute_ground (amrex::Real dt) |
| void | solve_balance (amrex::Real dt) |
| void | compute_sensible (const amrex::MultiFab &cons, const amrex::MultiFab &xvel, const amrex::MultiFab &yvel, const amrex::MultiFab &zvel, amrex::Real c_p, const amrex::MultiFab *olen_ground=nullptr, const amrex::MultiFab *pblh_ground=nullptr, amrex::Real z_i_bulk=0.0) |
| void | add_heat_flux_to_source (amrex::MultiFab &source, const amrex::MultiFab &cons, const amrex::Geometry &geom, amrex::Real c_p, amrex::Real rdOcp) const |
| void | compute_shortwave (amrex::Real time, const TwoStreamCanopyView &canopy=TwoStreamCanopyView{}) |
| int | top_sample_interface () const |
| bool | has_faces () const |
| void | check_canopy_layout (const amrex::MultiFab &cons, const TwoStreamCanopyView &canopy) const |
| void | compute_shortwave_two_stream (const TwoStreamCanopyView &canopy) |
| void | compute_longwave_two_stream (const amrex::MultiFab &cons, const TwoStreamCanopyView &canopy) |
| void | scatter_field (const amrex::Gpu::DeviceVector< amrex::Real > &v, amrex::MultiFab &out) const |
| void | dump_faces (const std::string &prefix) const |
| void | scatter_diagnostics (amrex::MultiFab &nfaces, amrex::MultiFab &tskin) const |
| void | save_state (amrex::MultiFab &state) const |
| void | load_state (const amrex::MultiFab &state) |
| void | report (amrex::Real time, int step, bool write_csv) const |
| const SunState & | sun () const |
| void | print_debug_summary () const |
| void | add_cost (double seconds) |
| void | set_init_cost (double seconds) |
| const std::vector< int > & | fab_start () const |
Public Attributes | |
| amrex::Gpu::DeviceVector< int > | d_i |
| amrex::Gpu::DeviceVector< int > | d_j |
| amrex::Gpu::DeviceVector< int > | d_k |
| Fluid cell of the face. More... | |
| amrex::Gpu::DeviceVector< int > | d_dir |
| Face direction: 0 x, 1 y, 2 z. More... | |
| amrex::Gpu::DeviceVector< int > | d_side |
| Solid neighbour at -1 (low) or +1 (high) side. More... | |
| amrex::Gpu::DeviceVector< int > | d_slot |
| Slot of the face within its cell's checkpoint record. More... | |
| amrex::Gpu::DeviceVector< int > | d_bid |
| Building id (1-based) More... | |
| amrex::Gpu::DeviceVector< int > | d_mat |
| Material id (0 = uniform inputs) More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_albedo |
| amrex::Gpu::DeviceVector< amrex::Real > | d_emis |
| Optical properties of the face. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_kth |
| amrex::Gpu::DeviceVector< amrex::Real > | d_rhocp |
| amrex::Gpu::DeviceVector< amrex::Real > | d_thick |
| Slab conductivity [W/m/K], heat capacity [J/m3/K], thickness [m]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_area |
| Face area [m2]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_xf |
| amrex::Gpu::DeviceVector< amrex::Real > | d_yf |
| amrex::Gpu::DeviceVector< amrex::Real > | d_zf |
| Face centre [m]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_T_skin |
| Skin temperature [K]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_T_slab |
| Slab layers [K], face-major: [face * n_layers + layer]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_f_sky |
| amrex::Gpu::DeviceVector< amrex::Real > | d_f_ground |
| amrex::Gpu::DeviceVector< amrex::Real > | d_f_bldg |
| View fractions, sum to 1. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_SW_abs |
| amrex::Gpu::DeviceVector< amrex::Real > | d_LW_net |
| amrex::Gpu::DeviceVector< amrex::Real > | d_H |
| amrex::Gpu::DeviceVector< amrex::Real > | d_LE |
| amrex::Gpu::DeviceVector< amrex::Real > | d_G |
| amrex::Gpu::DeviceVector< amrex::Real > | d_Q_ext |
| External incident flux [W/m2], e.g. fire radiation. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_shadow |
| 1 when the ray to the sun hits a building, else 0 More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_SW_direct_in |
| Direct beam incident on the face. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_SW_diffuse_in |
| Sky and ground-reflected diffuse incident. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_LW_down_in |
| Incoming longwave on the face (sky, ground and walls) More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_T_air |
| Air temperature of the fluid cell. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_theta_air |
| Potential temperature of the fluid cell [K]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_rho |
| Density of the fluid cell [kg/m3]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_U_tan |
| Tangential wind speed at the fluid cell [m/s]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_ustar |
| Friction velocity of the wall function [m/s]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_H_coeff |
| H = H_coeff (theta_skin - theta_air) [W/m2/K]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_hbld |
| Height of the face's building column [m]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_w_star |
| Convective velocity scale of the step [m/s]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_olen |
| Obukhov length used [m] (1e30 when neutral) More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_z_i |
| Depth in w* [m]: mixed layer above a roof, building height for a wall. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_LW_ext |
| Incoming longwave from sky and ground only [W/m2]. More... | |
| amrex::Gpu::DeviceVector< amrex::Real > | d_resid |
| |balance| after the solve [W/m2] More... | |
| amrex::Gpu::DeviceVector< int > | d_niter |
| Newton iterations of the last solve. More... | |
| amrex::Gpu::DeviceVector< int > | d_col_top |
| int | m_col_i0 = 0 |
| int | m_col_j0 = 0 |
| int | m_col_nx = 0 |
| int | m_col_ny = 0 |
| amrex::BoxArray | m_state_ba |
| amrex::BoxArray | m_xfer_ba |
| amrex::DistributionMapping | m_xfer_dm |
| std::vector< int > | m_xfer_src |
| amrex::Long | m_domain_cells = 0 |
| Cells of the level, for the debug summary of the field. More... | |
Private Attributes | |
| IBSEBParams | m_params |
| Copy of the inputs. More... | |
| int | m_lev = 0 |
| AMR level, for reports. More... | |
| int | m_nface = 0 |
| Faces owned by this rank. More... | |
| int | m_nslots = 0 |
| Slots per cell of the checkpoint field (largest face count on a cell) More... | |
| int | m_top_sample = -1 |
| Highest interface a face samples, over all ranks (-1: no faces) More... | |
| int | m_nbld = 0 |
| Buildings of the level (global) More... | |
| std::vector< int > | m_fab_start |
| See fab_start() More... | |
| std::vector< amrex::Long > | m_bld_nface |
| Faces per building. More... | |
| std::vector< amrex::Real > | m_bld_area |
| Face area per building [m2]. More... | |
| amrex::Long | m_nface_dir [3] = {0, 0, 0} |
| Faces per direction. More... | |
| amrex::Real | m_area_total = 0.0 |
| Total face area [m2]. More... | |
| std::vector< amrex::Long > | m_bld_ncol |
| std::vector< int > | m_bld_ilo |
| std::vector< int > | m_bld_ihi |
| std::vector< int > | m_bld_jlo |
| std::vector< int > | m_bld_jhi |
| std::vector< int > | m_to_lev0 |
| std::vector< int > | m_lab |
| int | m_lab_i0 = 0 |
| int | m_lab_j0 = 0 |
| int | m_lab_nx = 0 |
| int | m_lab_ny = 0 |
| int | m_nx = 0 |
| int | m_ny = 0 |
| Columns of the domain. More... | |
| amrex::IntVect | m_dom_lo {AMREX_D_DECL(0, 0, 0)} |
| Low corner of the level's domain. More... | |
| amrex::Real | m_x_lo = 0.0 |
| amrex::Real | m_y_lo = 0.0 |
| Domain origin [m]. More... | |
| amrex::Real | m_dx [3] = {0.0, 0.0, 0.0} |
| Cell sizes [m]. More... | |
| bool | m_per_x = false |
| bool | m_per_y = false |
| Periodicity in x and y. More... | |
| amrex::Real | m_col_top_max = 0.0 |
| Tallest column [m]. More... | |
| amrex::Real | m_z_ground = 0.0 |
| Ground height [m] (flat, the domain bottom) More... | |
| amrex::Real | m_max_path = 0.0 |
| Ray path cap [m]. More... | |
| SunState | m_sun |
| TwoStreamSun | m_ts_sun |
| double | m_cost_s = 0.0 |
| Wall-clock seconds spent in the per-step update on this rank. More... | |
| amrex::Long | m_cost_n = 0 |
| Number of per-step updates timed. More... | |
| double | m_init_cost_s = 0.0 |
| Wall-clock seconds of build() and compute_view_fractions() More... | |
|
inline |
Construct an empty face set for one level; build() fills it.
| params | Inputs of the balance (copied; the set never reads ParmParse). |
| lev | AMR level the set belongs to, for reports only. |
|
inline |
Add the wall-clock time of one per-step update of this rank, for the cost line of report().
| void IBFaceSet::add_heat_flux_to_source | ( | amrex::MultiFab & | source, |
| const amrex::MultiFab & | cons, | ||
| const amrex::Geometry & | geom, | ||
| amrex::Real | c_p, | ||
| amrex::Real | rdOcp | ||
| ) | const |
Add the face heat flux to the temperature equation: every face deposits H A / (c_p V Pi) into the rho-theta source of its fluid cell (Pi the Exner function, so the flux heats the cell by H A / (c_p V) in temperature). Called after the sources are rebuilt at every slow stage; adds, never overwrites, and uses atomic adds because a corner cell receives several faces.
Face flux into the temperature equation. The rho-theta tendency of the fluid cell is H A / (c_p V Pi); with several faces on one cell the adds are atomic.

| void IBFaceSet::add_outside_occluders | ( | const IBFaceSet & | coarser, |
| const amrex::IntVect & | ratio, | ||
| const amrex::BoxArray & | grids_crse | ||
| ) |
Add the buildings this refined level does not hold to the column map of its ray cast, from the map of the level below.
build() takes the map from the level's own cells, so on a refined level that covers part of the domain the rays of the shortwave and the view fractions would pass through every building outside it. Every column of the coarser map whose top cell this level's grids do not cover (ERF::ibseb_check_refined_levels() has made sure a building is wholly inside or wholly outside) is copied onto the ratio x ratio columns of this level beneath it, at the same height, and the map grows to the bounding box of both. Only the ray cast reads the result: the building ids, the face heights of the wall function and the reports keep the level's own buildings. Call after build() and before compute_view_fractions(); the coarser set must have had its own call already, so buildings outside several levels pass down the hierarchy.
| coarser | Face set of the level below. |
| ratio | Refinement ratio from the level below to this one. |
| grids_crse | This level's grids coarsened by ratio. |
Copy the coarser level's columns that this level does not cover into the column map of the ray cast (see the header). The coarser map is copied to the host, as both maps are replicated on every rank, and the merged map is uploaded again: one pass over the two built bounding boxes at initialisation.

| void IBFaceSet::assign_materials | ( | ) |
Assign every face its material properties: from the material library by building id, or the uniform inputs. Called once after build(); fills d_mat, d_albedo, d_emis, d_k, d_rhocp, d_thick and initialises the slab layers to the skin temperature.
Materials per face from the library by building id, or the uniform inputs. Host work on the static geometry, once.

| void IBFaceSet::build | ( | const amrex::MultiFab & | blanking, |
| const amrex::Geometry & | geom | ||
| ) |
Detect this rank's faces from the cell-centred blanking and allocate every per-face array.
Runs on the host once at initialisation: the blanking is copied fab by fab (a pinned copy on GPU builds), the valid cells are scanned, and the arrays are uploaded to the device at the end. Must be called after the blanking has been built and its ghost cells filled, since the solid neighbour of a fluid cell on a box edge lives in a ghost cell. Stops when a solid cell outside the level's grids neighbours a cell of the level, fluid or solid: a building across the edge of a refined level.
| blanking | Cell-centred blanking of the level (needs at least one ghost cell, filled). |
| geom | Geometry of the level: cell sizes for the face areas, domain and periodicity for the neighbour tests. |
Detect the faces owned by this rank and allocate the per-face arrays.
The scan visits every valid cell of every local fab in MFIter order. A fluid cell (blanking < 0.5) contributes one face for each of its six neighbours that is solid (blanking >= 0.5); the neighbour may sit in a ghost cell, which is why the blanking must have its ghost cells filled. Neighbours outside the domain in a non-periodic direction are skipped, so a building against a non-periodic boundary has no face there. Solid cells contribute no face, only the column mask used for the building ids. A solid neighbour outside the level's grids, of a fluid or a solid cell, means a building crosses the edge of a refined level; the scan counts them and stops the run once all ranks have reported.
Faces are appended in scan order, which makes them contiguous per fab; m_fab_start records where each fab's faces begin. The per-direction, per-building and total counts are reduced over all ranks here, once, so report() does not have to reduce static numbers every time.

|
inline |
Level 0's number for building b of this level (1-based; 0 for one only this level resolves).
| void IBFaceSet::check_canopy_layout | ( | const amrex::MultiFab & | cons, |
| const TwoStreamCanopyView & | canopy | ||
| ) | const |
Stop unless the fields of canopy (this level's two-stream view) lie on the columns of cons, with the same distribution: the two-stream kernels read the column of a face from the fabs with the local index of the face's own fab.
The fields of a two-stream view must lie on this level's columns, with the level's distribution, so that the fabs of local index n hold the columns of the faces fab_start()[n] .. fab_start()[n+1]-1 own: the interface fluxes on the level's own grids (with the top-of-atmosphere ghost, which a face whose cell is the top of the domain reads); the beam on its boxes in x and y with the interfaces from the surface up to at least top_sample_interface() in z; the cosine of the zenith on them flattened to index 0 in z.

| void IBFaceSet::compute_ground | ( | amrex::Real | dt | ) |
Ground heat flux of the current step: advance every face's slab by dt with the skin temperature at the top and the interior temperature at the bottom (implicit, ERF_IBSEBSlab.H) and store the conduction into the slab, G, positive into the wall.
Slab conduction on every face: one kernel over the faces, each solving its own tridiagonal system with the skin at the top and the interior at the bottom.

| void IBFaceSet::compute_longwave | ( | const amrex::MultiFab & | cons, |
| const TwoStreamCanopyView & | canopy = TwoStreamCanopyView{} |
||
| ) |
Longwave of the current step. Incoming on a face: f_sky LW_sky + f_ground LW_ground + f_bldg sigma T_skin^4, the sky term fixed or gray (sky_emissivity sigma T_air^4 with the air temperature of the face's fluid cell) with the ground term eps_g sigma T_g^4, or with lw_mode = two_stream the longwave down and up at the face's height in the face's column (canopy); the building term is the isothermal-surroundings approximation. Net: eps (LW_in - sigma T_skin^4), positive into the face.
| cons | Conserved state of the level, for the air temperature. |
| canopy | With lw_mode = two_stream, this step's two-stream view of the level (ERF_TwoStreamCanopyForcing.H), or an empty one before the first sweep, when the incoming and net longwave are zero. |
Longwave of the current step. One kernel per fab over that fab's faces, reading the air temperature of the fluid cell from the conserved state (potential temperature and density through the equation of state). With lw_mode = two_stream the sky and ground terms come from the canopy forcing of the face's column, read from the 2D fab of the same local index (the level's grids flattened, on the same distribution).

| void IBFaceSet::compute_longwave_two_stream | ( | const amrex::MultiFab & | cons, |
| const TwoStreamCanopyView & | canopy | ||
| ) |
Longwave of the current step with lw_mode = two_stream: the sky term is the longwave down of the face's column at the face's height (a roof's interface, a wall's mean of its cell's two; two_stream_canopy_sample()), the ground term its longwave up at the same height (the ground seen through the air in between), so the ground's temperature, emissivity and reflection of the sky are the column's (two_stream_face_sky()). Before the level's first sweep (an empty canopy, the initial report) the air temperature is read and the incoming and net longwave are zero.

| void IBFaceSet::compute_sensible | ( | const amrex::MultiFab & | cons, |
| const amrex::MultiFab & | xvel, | ||
| const amrex::MultiFab & | yvel, | ||
| const amrex::MultiFab & | zvel, | ||
| amrex::Real | c_p, | ||
| const amrex::MultiFab * | olen_ground = nullptr, |
||
| const amrex::MultiFab * | pblh_ground = nullptr, |
||
| amrex::Real | z_i_bulk = 0.0 |
||
| ) |
Sensible heat of the current step through a wall function on every face: the tangential wind of the fluid cell at half a cell from the wall gives u* with the roughness z0_wall, the skin-to-air potential-temperature difference gives theta* with z0h_wall, and H = rho c_p u* theta*, positive out of the face. Neutral, or with the surface layer's stability functions on roofs when asked. The latent flux is not modelled and stays zero.
Beyond neutral: with convective_velocity = deardorff the wind is sqrt(U_tan^2 + (beta w*)^2) with w* from the previous step's H (zero when H is into the face) and a depth that is the mixed layer above a roof or the building height for a wall; with stability_correction the roofs iterate the similarity functions on the face's own Obukhov length, seeded from the ground surface layer's 2D field at the face's column when given.
Fills d_H, d_ustar, d_U_tan, d_rho, d_theta_air, d_H_coeff (the coefficient of the skin-to-air potential-temperature difference that the balance keeps frozen), d_w_star, d_olen and d_z_i; T_air was read by compute_longwave(), which must run first in a step.
| cons | Conserved state of the level (density, rho theta). |
| xvel,yvel,zvel | Face-centred velocities of the level. |
| c_p | Specific heat of air [J/kg/K]. |
| olen_ground | Ground surface layer's Obukhov length (2D field on the level's box array collapsed to k = 0), or null. |
| pblh_ground | Its boundary-layer height field, or null. |
| z_i_bulk | Mixed-layer depth of the level from the bulk Richardson diagnostic or the fixed input [m]. |
Wall function on every face. One kernel per fab over that fab's faces: the cell-centred velocity of the fluid cell from its face values, its tangential part with respect to the wall, the neutral log law for u* and theta*, and on request two additions: a convective velocity scale in the wind (Beljaars' gustiness form with Deardorff's w* from the previous step's flux) and, on roofs, the surface layer's similarity functions iterated on the face's own Obukhov length. The skin temperature is converted to a potential temperature with the fluid cell's Exner function before the difference is taken.
The Obukhov length of a face is L = u*^2 theta / (kappa g theta*) (negative over a hot face). Walls stay on the log law even with the stability correction: the similarity functions assume a horizontal surface, and the convective scale is what carries free convection on a wall. The ground's 2D Obukhov field only seeds the roof iteration.
| void IBFaceSet::compute_shortwave | ( | amrex::Real | time, |
| const TwoStreamCanopyView & | canopy = TwoStreamCanopyView{} |
||
| ) |
Shortwave of the current step: the sun's position (sun_mode), the irradiances of the prescribed provider or, with radiation = two_stream, those of the face's own column at its height (canopy), then per face the direct beam on the face (zero when the ray toward the sun hits a building), the diffuse light through the view fractions, and the absorbed sum.
Fills d_shadow, d_SW_direct_in, d_SW_diffuse_in and d_SW_abs; stores the sun vector and irradiances for the reports (with two_stream the means over all the level's faces of the direct-normal and diffuse irradiance each takes, written to every row of the level).
| time | Simulation time [s]; with sun_mode = solar it is added to time_zero_utc_s (with sun_mode = two_stream the sun comes from set_two_stream_sun()). |
| canopy | With radiation = two_stream, this step's two-stream view of the level (see compute_longwave()), or an empty one before the first sweep, when every face gets no shortwave. |
Shortwave of the current step. The sun and the irradiances are scalars computed on the host from the provider inputs; the per-face work is one kernel: incidence cosine, ray cast against the column tops, direct and diffuse incident, absorbed.
With sun_mode = fixed the direct-normal irradiance and the horizontal diffuse are the inputs as given. With sun_mode = solar the sun follows the site and time and the clear-sky formulas give both irradiances; with sun_mode = two_stream the position and the top-of-atmosphere irradiance are the two-stream radiation's (set_two_stream_sun()) and the same clear-sky formulas give the irradiances. The sun below the horizon gives zero everywhere.
Diffuse on a face: f_sky * diffuse_h + f_ground * albedo_ground * (direct_h + diffuse_h), the second term being the ground-reflected part, with the direct on a horizontal surface direct_h = dni * cos z. The view fractions are the placeholders of build() until compute_view_fractions() has run.

| void IBFaceSet::compute_shortwave_two_stream | ( | const TwoStreamCanopyView & | canopy | ) |
Shortwave of the current step with radiation = two_stream, after compute_shortwave() has placed the sun (m_sun): per face, the direct-normal irradiance of its column at its height (two_stream_face_sky(): a roof's interface, a wall's mean of its cell's two), the beam over the column's own cosine of the zenith, on the face (shadowed by the same ray cast), the diffuse light of the sky there through f_sky, and the ground's reflection, the column's shortwave up at the face's height, through f_ground. One kernel per fab, reading the view's fields of the same local index.
The faces' sun (sun_mode) and the sweep's are required to be one sun (ERF::ibseb_check_sun_matches_two_stream()); the kernel checks it, column by column: a cosine of the zenith more than 1e-4 (1e-3 in single precision) from the faces' stops the run, since a direct beam divided by the wrong cosine and laid along the wrong direction would still look plausible.
Before the level's first sweep (an empty canopy, the initial report) every face gets no shortwave. The reported direct-normal and diffuse irradiances are the means over the level's faces of their columns'.
Referenced by compute_shortwave().


| void IBFaceSet::compute_view_fractions | ( | ) |
View fractions: sample a cosine-weighted hemisphere around every face's outward normal with view_n_az x view_n_el rays through the column walk and count where they end: sky, ground or a building. The three fractions sum to one and are view factors. Called once at initialisation; the geometry is static.
Hemisphere sampling for the view fractions. One kernel over the faces, each looping over its rays; the count of rays ending on the sky, the ground and a building over the total gives the three fractions. Roofs point up and never see the ground; a wall on flat open ground sees half sky and half ground, which the regression test checks.

| void IBFaceSet::dump_faces | ( | const std::string & | prefix | ) | const |
Write every face of this rank to <prefix>.rank<N>.csv with its geometry, view fractions, shadow flag, shortwave terms and skin temperature, for the regression tests and for users who want the raw list.
Per-rank face dump. Every rank writes its own file so no gather is needed; readers concatenate <prefix>.rank*.csv.
Referenced by report().


|
inline |
First face of each local fab in MFIter order; size number of fabs + 1. Faces fab_start()[n] to fab_start()[n+1]-1 belong to the fab with local index n, which is what the scatter kernels rely on.
|
inline |
Whether the level has faces on any rank.
|
inline |
Whether the level has a checkpoint field to write (any faces at all).
| void IBFaceSet::load_state | ( | const amrex::MultiFab & | state | ) |
Read the face state (skin, flux, slab) back from a field written by save_state(), after build() has recreated the list from the blanking: the reverse ParallelCopy onto the transfer field, then each face reads its slot. Only the slots that correspond to a face of this list are read.
Read the skin temperature, the sensible flux and the slab temperatures back from the state field, the inverse of save_state(), into a list that build() has just recreated with the same slot numbering.

| MultiFab IBFaceSet::make_state | ( | ) | const |
A field on state_boxarray() with state_ncomp() components, for the checkpoint.
Write the skin temperature, the sensible flux and the slab temperatures into the state field. The record of a face starts at component slot * (2 + n_layers), the slot being the face's number within its own cell (see state_ncomp()); no two faces of a cell share a slot, so the writes are plain stores.

| void IBFaceSet::map_buildings_to_level0 | ( | const IBFaceSet & | coarser, |
| const amrex::IntVect & | ratio | ||
| ) |
Number this refined level's buildings as level 0 numbers them.
Each level labels its buildings from its own cells, so the ids of a refined level differ from level 0's wherever the levels see different buildings: a building outside the refined level, or two that level 0 merges into one. Inputs that go by building (erf.ibseb.material_by_building) and the report's building_level0 column use level 0's numbering, so every building of this level is looked up in the labels of the level below, and through that level's own map in level 0's: each of its columns votes with the id under it and the majority wins. A building only this level resolves maps to 0 (the default material), with a warning. Call after build() of both levels; the level below keeps its labels until release_labels().
| coarser | Face set of the level below, already mapped. |
| ratio | Refinement ratio from the level below to this one. |
Map this level's buildings to level 0's numbering through the labels of the level below (see the header). Every column of a building votes with the level-0 id of the coarse column under it (through the level below's own map), unlabelled coarse columns abstaining, and the most frequent id wins (the lowest on a tie). No single column is trusted: the coarse blanking is a volume average, so a column the coarse level leaves unlabelled (a spire alone in its coarse cell) cannot unmap a building the level below resolves through its other columns. A building none of whose columns lies under a labelled coarse column is one only this level resolves; it maps to 0, and a warning names it when the level below has buildings at all.

|
inline |
Number of buildings of the level, the same on every rank.
|
inline |
|
inline |
Conduction layers per face, from erf.ibseb.n_slab_layers.
Referenced by dump_faces(), load_state(), print_debug_summary(), save_state(), and state_ncomp().

|
inline |
Slots per cell of the checkpoint field: the largest face count on a cell of the level.
| void IBFaceSet::print_debug_summary | ( | ) | const |
Print the [IBSEB DEBUG] description of the set: the inputs, every rank's face count and per-fab ranges, the buildings with their footprint columns and bounding boxes, and the device memory of the arrays. Called once from build() when erf.ibseb.debug is set.
Debug description of the set, in the style of the fire module's [FIRE DEBUG] lines: what was read, what every rank holds, what the buildings look like, and what the arrays cost. Per-rank lines use AllPrint() so every rank reports; the rest is printed by the I/O rank.

|
inline |
Free the column labels once the level above has been mapped (map_buildings_to_level0()).
| void IBFaceSet::report | ( | amrex::Real | time, |
| int | step, | ||
| bool | write_csv | ||
| ) | const |
Print the [IBSEB] summary line and, when asked, append one row per building to erf.ibseb.csv_file.
The summary carries the global face counts per direction, the number of buildings, the total face area and the range of the skin temperature; the CSV rows carry per building the face count, the area, the area-weighted mean fluxes and skin temperature with its range, the largest balance residual, and the sun the step used, from its start (zenith, azimuth, direct-normal and diffuse irradiance), on a row stamped with the time at the end of the step. All numbers are reduced over the ranks; the file is written by the I/O rank only, with a header only when the file does not exist yet, so a restarted run appends. Every level appends to the same file, its rows marked by the level column. With erf.ibseb.dump_faces_file the rows come with a face dump, dump_faces() to <prefix>[.levN][.stepNNNNNN].rank<N>.csv: a refined level N adds .levN so it does not overwrite the level below, and erf.ibseb.dump_faces_tag_step the step.
| time | Simulation time [s] written to the rows. |
| step | Step number written to the rows. |
| write_csv | Whether to append rows, or only print the summary. |
Summary line and per-building CSV rows. The dynamic quantities (skin temperature range and area-weighted mean per building) are gathered on the host from the device arrays and reduced; the static counts and areas were reduced in build().

| void IBFaceSet::save_state | ( | amrex::MultiFab & | state | ) | const |
Write the face state (skin temperature, sensible flux and slab temperatures) into a field from make_state(), for the checkpoint.
The faces of this rank are written into a transfer field on this rank's grids cut by the state boxes, which a ParallelCopy moves onto the state's own distribution. Each face writes its own slot (see state_ncomp()), so no two faces touch the same component of the same cell and no atomics are needed; cells without a face in a slot keep zero there.

| void IBFaceSet::scatter_diagnostics | ( | amrex::MultiFab & | nfaces, |
| amrex::MultiFab & | tskin | ||
| ) | const |
Scatter the faces into two cell-centred diagnostics for the plotfile.
| [out] | nfaces | Number of wall faces touching each fluid cell (0 away from buildings; up to 3 at an outside corner, 6 in a one-cell slot). |
| [out] | tskin | Mean skin temperature of those faces, 0 where there are none. |
Both fields must be on the level's box array with no ghost cells. Faces of one fab are accumulated with atomic adds because a corner cell receives several faces.
Scatter the face count and the mean skin temperature into cell-centred fields. One kernel per fab over that fab's faces (contiguous, see fab_start()), with atomic adds since a corner cell collects several faces, then a kernel over the box divides the temperature sum by the count.

| void IBFaceSet::scatter_field | ( | const amrex::Gpu::DeviceVector< amrex::Real > & | v, |
| amrex::MultiFab & | out | ||
| ) | const |
Scatter one per-face array into a cell-centred field as the mean over the faces touching each cell (zero where there are none).
Scatter one per-face array as a per-cell mean, the same accumulation as scatter_diagnostics() with the face count as the divisor.

|
inline |
Record the wall-clock time of the initialisation (build and view fractions).
|
inline |
Give the sun of the next compute_shortwave() with erf.ibseb.sun_mode = two_stream: the two-stream radiation's declination and hour angle at that time, its site latitude and its top-of-atmosphere irradiance (the date's distance factor included). ERF::ibseb_set_two_stream_sun() calls it before every call; the call uses it up, so a shortwave without a fresh sun stops rather than reusing an old one.
| void IBFaceSet::solve_balance | ( | amrex::Real | dt | ) |
Prognostic balance of the current step. Per face: the slab's linear response to the skin temperature for this step, the Newton solve of ERF_IBSEBBalance.H with the shortwave, the external flux, the sky and ground longwave, the frozen wall-function coefficient and the latent flux, the slab advanced with the solution, and the fluxes (LW_in, LW_net, H, G) rewritten at the solution. Fills d_resid (|balance| at the end, non-zero only at a bound or the iteration cap) and d_niter. Needs compute_shortwave(), compute_longwave() and compute_sensible() of the same step first.
| dt | Atmospheric time step [s], the slab's step. |
Prognostic balance on every face: one kernel over the faces, each with its own slab response, Newton solve and slab advance. Everything the solve needs was stored by the three flux routines of the step, so no fab data is touched here. The fluxes are rewritten at the solution so that the dump, the reports and the heat deposited into the air all describe the same closed balance; d_resid holds what is left of it.

|
inline |
Boxes of the checkpoint field: 4 x 4 column blocks clipped to the k-range that actually owns faces, so the field follows the shell of face-owning cells rather than the built volume. A block over the interior of a wide footprint keeps only the layer above the roof, while a block on a wall still spans its height. Built identically on every rank by build() from a reduced block k-range map; the same buildings give the same boxes on restart, whatever the rank count. Empty when the level has no faces.
|
inline |
Number of components of the checkpoint state field.
The field carries n_slots() slots of 2 + n_layers() values per cell: component slot * (2 + n_layers()) is the skin temperature of that slot, the next its sensible flux (read as the previous step's by the convective velocity scale), and the following n_layers() components are its slab layers.
A cell carries one slot per face it owns, numbered in the (dir, side) order in which build() finds them, so the width is the largest face count on any one cell of the level rather than the six a cell could hold in principle. Around ordinary buildings that maximum is two or three (an outside edge or corner); six needs a one-cell slot. build() rebuilds the numbering from the same blanking on restart, so the slots line up whatever the rank count.
Referenced by load_state(), make_state(), and save_state().


|
inline |
The highest interface of the level's vertical grid that any of its faces samples with radiation = two_stream (a roof the bottom of its fluid cell, a ceiling and a wall the top of its cell too), counted from the domain bottom, over all ranks; -1 when the level has no faces. The two-stream beam the faces read holds the interfaces up to there.
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_albedo |
Referenced by compute_shortwave(), compute_shortwave_two_stream(), and dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_area |
Face area [m2].
Referenced by add_heat_flux_to_source(), dump_faces(), and report().
| amrex::Gpu::DeviceVector<int> IBFaceSet::d_bid |
Building id (1-based)
Referenced by dump_faces(), and report().
| amrex::Gpu::DeviceVector<int> IBFaceSet::d_col_top |
Referenced by add_outside_occluders(), compute_shortwave(), and compute_shortwave_two_stream().
| amrex::Gpu::DeviceVector<int> IBFaceSet::d_dir |
Face direction: 0 x, 1 y, 2 z.
Referenced by compute_shortwave(), compute_shortwave_two_stream(), and dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_emis |
Optical properties of the face.
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_f_bldg |
View fractions, sum to 1.
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_f_ground |
Referenced by compute_shortwave(), compute_shortwave_two_stream(), and dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_f_sky |
Referenced by compute_shortwave(), compute_shortwave_two_stream(), and dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_G |
Referenced by dump_faces(), and report().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_H |
Referenced by add_heat_flux_to_source(), dump_faces(), load_state(), report(), and save_state().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_H_coeff |
H = H_coeff (theta_skin - theta_air) [W/m2/K].
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_hbld |
Height of the face's building column [m].
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<int> IBFaceSet::d_i |
| amrex::Gpu::DeviceVector<int> IBFaceSet::d_j |
| amrex::Gpu::DeviceVector<int> IBFaceSet::d_k |
Fluid cell of the face.
Referenced by add_heat_flux_to_source(), compute_shortwave_two_stream(), dump_faces(), load_state(), save_state(), scatter_diagnostics(), and scatter_field().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_kth |
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_LE |
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_LW_down_in |
Incoming longwave on the face (sky, ground and walls)
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_LW_ext |
Incoming longwave from sky and ground only [W/m2].
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_LW_net |
Referenced by dump_faces(), and report().
| amrex::Gpu::DeviceVector<int> IBFaceSet::d_mat |
Material id (0 = uniform inputs)
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<int> IBFaceSet::d_niter |
Newton iterations of the last solve.
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_olen |
Obukhov length used [m] (1e30 when neutral)
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_Q_ext |
External incident flux [W/m2], e.g. fire radiation.
Referenced by dump_faces(), and report().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_resid |
|balance| after the solve [W/m2]
Referenced by dump_faces(), and report().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_rho |
Density of the fluid cell [kg/m3].
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_rhocp |
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_shadow |
1 when the ray to the sun hits a building, else 0
Referenced by compute_shortwave(), compute_shortwave_two_stream(), dump_faces(), and report().
| amrex::Gpu::DeviceVector<int> IBFaceSet::d_side |
Solid neighbour at -1 (low) or +1 (high) side.
Referenced by compute_shortwave(), compute_shortwave_two_stream(), and dump_faces().
| amrex::Gpu::DeviceVector<int> IBFaceSet::d_slot |
Slot of the face within its cell's checkpoint record.
Referenced by load_state(), and save_state().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_SW_abs |
Referenced by compute_shortwave(), compute_shortwave_two_stream(), dump_faces(), and report().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_SW_diffuse_in |
Sky and ground-reflected diffuse incident.
Referenced by compute_shortwave(), compute_shortwave_two_stream(), and dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_SW_direct_in |
Direct beam incident on the face.
Referenced by compute_shortwave(), compute_shortwave_two_stream(), and dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_T_air |
Air temperature of the fluid cell.
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_T_skin |
Skin temperature [K].
Referenced by dump_faces(), load_state(), report(), save_state(), and scatter_diagnostics().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_T_slab |
Slab layers [K], face-major: [face * n_layers + layer].
Referenced by dump_faces(), load_state(), and save_state().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_theta_air |
Potential temperature of the fluid cell [K].
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_thick |
Slab conductivity [W/m/K], heat capacity [J/m3/K], thickness [m].
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_U_tan |
Tangential wind speed at the fluid cell [m/s].
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_ustar |
Friction velocity of the wall function [m/s].
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_w_star |
Convective velocity scale of the step [m/s].
Referenced by dump_faces(), and report().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_xf |
Referenced by compute_shortwave(), compute_shortwave_two_stream(), and dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_yf |
Referenced by compute_shortwave(), compute_shortwave_two_stream(), and dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_z_i |
Depth in w* [m]: mixed layer above a roof, building height for a wall.
Referenced by dump_faces().
| amrex::Gpu::DeviceVector<amrex::Real> IBFaceSet::d_zf |
Face centre [m].
Referenced by compute_shortwave(), compute_shortwave_two_stream(), and dump_faces().
|
private |
Total face area [m2].
Referenced by print_debug_summary(), and report().
|
private |
Face area per building [m2].
Referenced by print_debug_summary(), and report().
|
private |
Referenced by print_debug_summary().
|
private |
Referenced by print_debug_summary().
|
private |
Referenced by print_debug_summary().
|
private |
Referenced by print_debug_summary().
|
private |
Referenced by print_debug_summary().
|
private |
Faces per building.
Referenced by print_debug_summary(), and report().
| int IBFaceSet::m_col_i0 = 0 |
Referenced by add_outside_occluders(), compute_shortwave(), and compute_shortwave_two_stream().
| int IBFaceSet::m_col_j0 = 0 |
Referenced by add_outside_occluders(), compute_shortwave(), and compute_shortwave_two_stream().
| int IBFaceSet::m_col_nx = 0 |
Referenced by add_outside_occluders(), compute_shortwave(), and compute_shortwave_two_stream().
| int IBFaceSet::m_col_ny = 0 |
Referenced by add_outside_occluders(), compute_shortwave(), and compute_shortwave_two_stream().
|
private |
Tallest column [m].
Referenced by compute_shortwave(), and compute_shortwave_two_stream().
|
private |
Number of per-step updates timed.
Referenced by add_cost(), and report().
|
private |
Wall-clock seconds spent in the per-step update on this rank.
Referenced by add_cost(), and report().
|
private |
Low corner of the level's domain.
Referenced by add_outside_occluders(), and compute_shortwave_two_stream().
| amrex::Long IBFaceSet::m_domain_cells = 0 |
Cells of the level, for the debug summary of the field.
Referenced by save_state().
|
private |
Cell sizes [m].
Referenced by add_outside_occluders(), compute_shortwave(), and compute_shortwave_two_stream().
|
private |
|
private |
Wall-clock seconds of build() and compute_view_fractions()
Referenced by report(), and set_init_cost().
|
private |
Referenced by map_buildings_to_level0(), and release_labels().
|
private |
Referenced by map_buildings_to_level0().
|
private |
Referenced by map_buildings_to_level0().
|
private |
Referenced by map_buildings_to_level0().
|
private |
Referenced by map_buildings_to_level0().
|
private |
AMR level, for reports.
Referenced by compute_shortwave(), compute_shortwave_two_stream(), load_state(), print_debug_summary(), report(), and save_state().
|
private |
Ray path cap [m].
Referenced by compute_shortwave(), and compute_shortwave_two_stream().
|
private |
Buildings of the level (global)
Referenced by map_buildings_to_level0(), n_buildings(), print_debug_summary(), and report().
|
private |
Faces owned by this rank.
Referenced by compute_shortwave(), compute_shortwave_two_stream(), dump_faces(), load_state(), n_faces(), print_debug_summary(), and report().
|
private |
Faces per direction.
Referenced by compute_shortwave_two_stream(), print_debug_summary(), and report().
|
private |
Slots per cell of the checkpoint field (largest face count on a cell)
Referenced by n_slots(), save_state(), and state_ncomp().
|
private |
Referenced by compute_shortwave(), and compute_shortwave_two_stream().
|
private |
Columns of the domain.
Referenced by compute_shortwave(), and compute_shortwave_two_stream().
|
private |
Copy of the inputs.
Referenced by compute_shortwave(), compute_shortwave_two_stream(), load_state(), n_layers(), print_debug_summary(), report(), and save_state().
|
private |
Referenced by compute_shortwave(), and compute_shortwave_two_stream().
|
private |
Periodicity in x and y.
Referenced by compute_shortwave(), and compute_shortwave_two_stream().
| amrex::BoxArray IBFaceSet::m_state_ba |
Referenced by has_state(), load_state(), make_state(), save_state(), and state_boxarray().
|
private |
Referenced by compute_shortwave(), compute_shortwave_two_stream(), report(), and sun().
|
private |
Referenced by building_level0(), map_buildings_to_level0(), and report().
|
private |
Highest interface a face samples, over all ranks (-1: no faces)
Referenced by has_faces(), and top_sample_interface().
|
private |
Referenced by compute_shortwave(), and set_two_stream_sun().
|
private |
Referenced by compute_shortwave(), and compute_shortwave_two_stream().
| amrex::BoxArray IBFaceSet::m_xfer_ba |
Referenced by load_state(), and save_state().
| amrex::DistributionMapping IBFaceSet::m_xfer_dm |
Referenced by load_state(), and save_state().
| std::vector<int> IBFaceSet::m_xfer_src |
Referenced by load_state(), and save_state().
|
private |
Domain origin [m].
Referenced by compute_shortwave(), and compute_shortwave_two_stream().
|
private |
Ground height [m] (flat, the domain bottom)
Referenced by compute_shortwave(), and compute_shortwave_two_stream().