ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_InteriorGhostCells.cpp File Reference
#include <ERF_Utils.H>
Include dependency graph for ERF_InteriorGhostCells.cpp:

Functions

void realbdy_interior_bxs_xy (const Box &bx, const Box &domain, const int &width, Box &bx_xlo, Box &bx_xhi, Box &bx_ylo, Box &bx_yhi, const int &set_width, const IntVect &ng_vect, const bool get_int_ng)
 
void realbdy_bc_bxs_xy (const Box &bx, const Box &domain, const int &set_width, Box &bx_xlo, Box &bx_xhi, Box &bx_ylo, Box &bx_yhi, const IntVect &ng_vect)
 
void realbdy_compute_interior_ghost_rhs (const Real &bdy_time_interval, const Real &time, const Real &delta_t, const Real &stop_time_elapsed, int width, int set_width, const Geometry &geom, Vector< MultiFab > &S_rhs, Vector< MultiFab > &S_old_data, Vector< MultiFab > &S_cur_data, Vector< Vector< FArrayBox >> &bdy_data_xlo, Vector< Vector< FArrayBox >> &bdy_data_xhi, Vector< Vector< FArrayBox >> &bdy_data_ylo, Vector< Vector< FArrayBox >> &bdy_data_yhi)
 
void fine_compute_interior_ghost_rhs (const Real &time, const Real &delta_t, const int &width, const int &set_width, const Geometry &geom, ERFFillPatcher *FPr_c, ERFFillPatcher *FPr_u, ERFFillPatcher *FPr_v, ERFFillPatcher *FPr_w, Vector< BCRec > &domain_bcs_type, Vector< MultiFab > &S_rhs_f, Vector< MultiFab > &S_data_f)
 

Variables

PhysBCFunctNoOp void_bc
 

Function Documentation

◆ fine_compute_interior_ghost_rhs()

void fine_compute_interior_ghost_rhs ( const Real time,
const Real delta_t,
const int &  width,
const int &  set_width,
const Geometry &  geom,
ERFFillPatcher FPr_c,
ERFFillPatcher FPr_u,
ERFFillPatcher FPr_v,
ERFFillPatcher FPr_w,
Vector< BCRec > &  domain_bcs_type,
Vector< MultiFab > &  S_rhs_f,
Vector< MultiFab > &  S_data_f 
)

Compute the RHS in the fine relaxation zone

Parameters
[in]timecurrent time
[in]delta_ttimestep
[in]widthnumber of cells in (relaxation+specified) zone
[in]set_widthnumber of cells in (specified) zone
[in]FPr_ccons fine patch container
[in]FPr_uuvel fine patch container
[in]FPr_vvvel fine patch container
[in]FPr_wwvel fine patch container
[in]boxes_at_levelboxes at current level
[in]domain_bcs_typeboundary condition types
[out]S_rhsRHS to be computed here
[in]S_datacurrent value of the solution
623 {
624  BL_PROFILE_REGION("fine_compute_interior_ghost_RHS()");
625 
626  // Relaxation constants
627  Real F1 = 1./(10.*delta_t);
628  Real F2 = 1./(50.*delta_t);
629 
630  // Vector of MFs to hold data (dm differs w/ fine patch)
631  Vector<MultiFab> fmf_p_v;
632 
633  // Loop over the variables
634  for (int ivar_idx = 0; ivar_idx < IntVars::NumTypes; ++ivar_idx)
635  {
636  // Fine mfs
637  MultiFab& fmf = S_data_f[ivar_idx];
638  MultiFab& rhs = S_rhs_f [ivar_idx];
639 
640  // NOTE: These temporary MFs and copy operations are horrible
641  // for memory usage and efficiency. However, we need to
642  // have access to ghost cells in the cons array to convert
643  // from primitive u/v/w to momentum. Furthermore, the BA
644  // for the fine patches in ERFFillPatcher don't match the
645  // BA for the data/RHS. For this reason, the data is copied
646  // to a vector of MFs (with ghost cells) so the BAs match
647  // the BA of data/RHS and we have access to rho to convert
648  // prim to conserved.
649 
650  // Temp MF on box (distribution map differs w/ fine patch)
651  int num_var = fmf.nComp();
652  fmf_p_v.emplace_back(fmf.boxArray(), fmf.DistributionMap(), num_var, fmf.nGrowVect());
653  MultiFab& fmf_p = fmf_p_v[ivar_idx];
654  MultiFab::Copy(fmf_p,fmf, 0, 0, num_var, fmf.nGrowVect());
655 
656  // Integer mask MF
657  int set_mask_val;
658  int relax_mask_val;
659  iMultiFab* mask;
660 
661  // Fill fine patch on interior halo region
662  //==========================================================
663  if (ivar_idx == IntVars::cons)
664  {
665  FPr_c->FillRelax(fmf_p, time, void_bc, domain_bcs_type);
666  mask = FPr_c->GetMask();
667  set_mask_val = FPr_c->GetSetMaskVal();
668  relax_mask_val = FPr_c->GetRelaxMaskVal();
669  }
670  else if (ivar_idx == IntVars::xmom)
671  {
672  FPr_u->FillRelax(fmf_p, time, void_bc, domain_bcs_type);
673  mask = FPr_u->GetMask();
674  set_mask_val = FPr_u->GetSetMaskVal();
675  relax_mask_val = FPr_u->GetRelaxMaskVal();
676 
677 #ifdef _OPENMP
678 #pragma omp parallel if (Gpu::notInLaunchRegion())
679 #endif
680  for ( MFIter mfi(fmf_p,TilingIfNotGPU()); mfi.isValid(); ++mfi)
681  {
682  Box tbx = mfi.tilebox();
683 
684  const Array4<Real>& prim_arr = fmf_p.array(mfi);
685  const Array4<const Real>& rho_arr = fmf_p_v[0].const_array(mfi);
686  const Array4<const int>& mask_arr = mask->const_array(mfi);
687 
688  ParallelFor(tbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
689  {
690  if (mask_arr(i,j,k) == relax_mask_val) {
691  Real rho_interp = 0.5 * ( rho_arr(i-1,j,k) + rho_arr(i,j,k) );
692  prim_arr(i,j,k) *= rho_interp;
693  }
694  });
695  } // mfi
696  }
697  else if (ivar_idx == IntVars::ymom)
698  {
699  FPr_v->FillRelax(fmf_p, time, void_bc, domain_bcs_type);
700  mask = FPr_v->GetMask();
701  set_mask_val = FPr_v->GetSetMaskVal();
702  relax_mask_val = FPr_v->GetRelaxMaskVal();
703 
704 #ifdef _OPENMP
705 #pragma omp parallel if (Gpu::notInLaunchRegion())
706 #endif
707  for ( MFIter mfi(fmf_p,TilingIfNotGPU()); mfi.isValid(); ++mfi)
708  {
709  Box tbx = mfi.tilebox();
710 
711  const Array4<Real>& prim_arr = fmf_p.array(mfi);
712  const Array4<const Real>& rho_arr = fmf_p_v[0].const_array(mfi);
713  const Array4<const int>& mask_arr = mask->const_array(mfi);
714 
715  ParallelFor(tbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
716  {
717  if (mask_arr(i,j,k) == relax_mask_val) {
718  Real rho_interp = 0.5 * ( rho_arr(i,j-1,k) + rho_arr(i,j,k) );
719  prim_arr(i,j,k) *= rho_interp;
720  }
721  });
722  } // mfi
723  }
724  else if (ivar_idx == IntVars::zmom)
725  {
726  FPr_w->FillRelax(fmf_p, time, void_bc, domain_bcs_type);
727  mask = FPr_w->GetMask();
728  set_mask_val = FPr_w->GetSetMaskVal();
729  relax_mask_val = FPr_w->GetRelaxMaskVal();
730 
731 #ifdef _OPENMP
732 #pragma omp parallel if (Gpu::notInLaunchRegion())
733 #endif
734  for ( MFIter mfi(fmf_p,TilingIfNotGPU()); mfi.isValid(); ++mfi)
735  {
736  Box tbx = mfi.tilebox();
737 
738  const Array4<Real>& prim_arr = fmf_p.array(mfi);
739  const Array4<const Real>& rho_arr = fmf_p_v[0].const_array(mfi);
740  const Array4<const int>& mask_arr = mask->const_array(mfi);
741 
742  ParallelFor(tbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
743  {
744  if (mask_arr(i,j,k) == relax_mask_val) {
745  Real rho_interp = 0.5 * ( rho_arr(i,j,k-1) + rho_arr(i,j,k) );
746  prim_arr(i,j,k) *= rho_interp;
747  }
748  });
749  } // mfi
750  } else {
751  Abort("Dont recognize this variable type in fine_compute_interior_ghost_RHS");
752  }
753 
754 
755  // Zero RHS in set region
756  //==========================================================
757 #ifdef _OPENMP
758 #pragma omp parallel if (Gpu::notInLaunchRegion())
759 #endif
760  for ( MFIter mfi(rhs,TilingIfNotGPU()); mfi.isValid(); ++mfi)
761  {
762  Box tbx = mfi.tilebox();
763  const Array4<Real>& rhs_arr = rhs.array(mfi);
764  const Array4<const int>& mask_arr = mask->const_array(mfi);
765 
766  ParallelFor(tbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
767  {
768  if (mask_arr(i,j,k) == set_mask_val) {
769  rhs_arr(i,j,k) = 0.0;
770  }
771  });
772  } // mfi
773 
774  // For Laplacian stencil
775  rhs.FillBoundary(geom.periodicity());
776 
777 
778  // Compute RHS in relaxation region
779  //==========================================================
780 #ifdef _OPENMP
781 #pragma omp parallel if (Gpu::notInLaunchRegion())
782 #endif
783  for ( MFIter mfi(fmf_p,TilingIfNotGPU()); mfi.isValid(); ++mfi)
784  {
785  Box tbx = mfi.tilebox();
786  const Array4<Real>& rhs_arr = rhs.array(mfi);
787  const Array4<const Real>& fine_arr = fmf_p.const_array(mfi);
788  const Array4<const Real>& data_arr = fmf.const_array(mfi);
789  const Array4<const int>& mask_arr = mask->const_array(mfi);
790 
791  Box vbx = mfi.validbox();
792  const auto& vbx_lo = lbound(vbx);
793  const auto& vbx_hi = ubound(vbx);
794 
795  int icomp = 0;
796 
797  int Spec_z = set_width;
798  int Relax_z = width - Spec_z;
799  Real num = Real(Spec_z + Relax_z);
800  Real denom = Real(Relax_z - 1);
801  ParallelFor(tbx, num_var, [=] AMREX_GPU_DEVICE (int i, int j, int k, int n) noexcept
802  {
803  if (mask_arr(i,j,k) == relax_mask_val) {
804 
805  // Indices
806  Real n_ind(-1); // Set to -1 to quiet compiler warning
807  int ii(width-1); int jj(width-1);
808  bool near_x_lo_wall(false); bool near_x_hi_wall(false);
809  bool near_y_lo_wall(false); bool near_y_hi_wall(false);
810  bool mask_x_found(false); bool mask_y_found(false);
811 
812  // Near x-wall
813  if ((i-vbx_lo.x) < width) {
814  near_x_lo_wall = true;
815  ii = i-vbx_lo.x;
816  if (mask_arr(vbx_lo.x,j,k) == 2) mask_x_found = true;
817  } else if ((vbx_hi.x-i) < width) {
818  near_x_hi_wall = true;
819  ii = vbx_hi.x-i;
820  if (mask_arr(vbx_hi.x,j,k) == 2) mask_x_found = true;
821  }
822 
823  // Near y-wall
824  if ((j-vbx_lo.y) < width) {
825  near_y_lo_wall = true;
826  jj = j-vbx_lo.y;
827  if (mask_arr(i,vbx_lo.y,k) == 2) mask_y_found = true;
828  } else if ((vbx_hi.y-j) < width) {
829  near_y_hi_wall = true;
830  jj = vbx_hi.y-j;
831  if (mask_arr(i,vbx_hi.y,k) == 2) mask_y_found = true;
832  }
833 
834  // Found a nearby masked cell (valid n_ind)
835  if (mask_x_found && mask_y_found) {
836  n_ind = std::min(ii,jj) + 1.0;
837  } else if (mask_x_found) {
838  n_ind = ii + 1.0;
839  } else if (mask_y_found) {
840  n_ind = jj + 1.0;
841  // Pesky corner cell
842  } else {
843  if (near_x_lo_wall || near_x_hi_wall) {
844  Real dj_min{width-1.0};
845  int j_lb = std::max(vbx_lo.y,j-width);
846  int j_ub = std::min(vbx_hi.y,j+width);
847  int li = (near_x_lo_wall) ? vbx_lo.x : vbx_hi.x;
848  for (int lj(j_lb); lj<=j_ub; ++lj) {
849  if (mask_arr(li,lj,k) == 2) {
850  mask_y_found = true;
851  dj_min = std::min(dj_min,(Real) std::abs(lj-j));
852  }
853  }
854  if (mask_y_found) {
855  Real mag = sqrt( Real(dj_min*dj_min + ii*ii) );
856  n_ind = std::min(mag,width-1.0) + 1.0;
857  } else {
858  Abort("Mask not found near x wall!");
859  }
860  } else if (near_y_lo_wall || near_y_hi_wall) {
861  Real di_min{width-1.0};
862  int i_lb = std::max(vbx_lo.x,i-width);
863  int i_ub = std::min(vbx_hi.x,i+width);
864  int lj = (near_y_lo_wall) ? vbx_lo.y : vbx_hi.y;
865  for (int li(i_lb); li<=i_ub; ++li) {
866  if (mask_arr(li,lj,k) == 2) {
867  mask_x_found = true;
868  di_min = std::min(di_min,(Real) std::abs(li-i));
869  }
870  }
871  if (mask_x_found) {
872  Real mag = sqrt( Real(di_min*di_min + jj*jj) );
873  n_ind = std::min(mag,width-1.0) + 1.0;
874  } else {
875  Abort("Mask not found near y wall!");
876  }
877  } else {
878  Abort("Relaxation cell must be near a wall!");
879  }
880  }
881 
882  Real Factor = (num - n_ind)/denom;
883  Real d = data_arr(i ,j ,k ,n+icomp) + delta_t*rhs_arr(i , j , k ,n+icomp);
884  Real d_ip1 = data_arr(i+1,j ,k ,n+icomp) + delta_t*rhs_arr(i+1, j , k ,n+icomp);
885  Real d_im1 = data_arr(i-1,j ,k ,n+icomp) + delta_t*rhs_arr(i-1, j , k ,n+icomp);
886  Real d_jp1 = data_arr(i ,j+1,k ,n+icomp) + delta_t*rhs_arr(i , j+1, k ,n+icomp);
887  Real d_jm1 = data_arr(i ,j-1,k ,n+icomp) + delta_t*rhs_arr(i , j-1, k ,n+icomp);
888  Real delta = fine_arr(i ,j ,k,n) - d;
889  Real delta_xp = fine_arr(i+1,j ,k,n) - d_ip1;
890  Real delta_xm = fine_arr(i-1,j ,k,n) - d_im1;
891  Real delta_yp = fine_arr(i ,j+1,k,n) - d_jp1;
892  Real delta_ym = fine_arr(i ,j-1,k,n) - d_jm1;
893  Real Laplacian = delta_xp + delta_xm + delta_yp + delta_ym - 4.0*delta;
894  rhs_arr(i,j,k,n) += (F1*delta - F2*Laplacian) * Factor;
895  }
896  });
897  } // mfi
898  } // ivar_idx
899 }
@ num
Definition: ERF_DataStruct.H:23
PhysBCFunctNoOp void_bc
Definition: ERF_InteriorGhostCells.cpp:5
amrex::Real Real
Definition: ERF_ShocInterface.H:19
amrex::iMultiFab * GetMask()
Definition: ERF_FillPatcher.H:43
void FillRelax(amrex::MultiFab &mf, amrex::Real time, BC &cbc, amrex::Vector< amrex::BCRec > const &bcs)
Definition: ERF_FillPatcher.H:105
int GetSetMaskVal()
Definition: ERF_FillPatcher.H:39
int GetRelaxMaskVal()
Definition: ERF_FillPatcher.H:41
@ NumTypes
Definition: ERF_IndexDefines.H:162
@ ymom
Definition: ERF_IndexDefines.H:160
@ cons
Definition: ERF_IndexDefines.H:158
@ zmom
Definition: ERF_IndexDefines.H:161
@ xmom
Definition: ERF_IndexDefines.H:159
Here is the call graph for this function:

◆ realbdy_bc_bxs_xy()

void realbdy_bc_bxs_xy ( const Box &  bx,
const Box &  domain,
const int &  set_width,
Box &  bx_xlo,
Box &  bx_xhi,
Box &  bx_ylo,
Box &  bx_yhi,
const IntVect &  ng_vect 
)

Get the boxes for looping over interior/exterior ghost cells for use by fillpatch, erf_slow_rhs_pre, and erf_slow_rhs_post.

Parameters
[in]bxbox to intersect with 4 halo regions
[in]domainbox of the whole domain
[in]widthnumber of cells in (relaxation+specified) zone
[in]set_widthnumber of cells in (specified) zone
[out]bx_xlohalo box at x_lo boundary
[out]bx_xhihalo box at x_hi boundary
[out]bx_ylohalo box at y_lo boundary
[out]bx_yhihalo box at y_hi boundary
[in]ng_vectnumber of ghost cells in each direction
[in]get_int_ngflag to get ghost cells inside the domain
117 {
118  AMREX_ALWAYS_ASSERT(bx.ixType() == domain.ixType());
119 
120  // Domain bounds without ghost cells
121  const auto& dom_lo = lbound(domain);
122  const auto& dom_hi = ubound(domain);
123 
124  // Four boxes matching the domain
125  Box gdom_xlo(domain); Box gdom_xhi(domain);
126  Box gdom_ylo(domain); Box gdom_yhi(domain);
127 
128  // Get offsets from box index type
129  IntVect iv_type = bx.ixType().toIntVect();
130  int offx = (iv_type[0]==1) ? 0 : -1;
131  int offy = (iv_type[1]==1) ? 0 : -1;
132 
133  // Stagger the boxes based upon index type
134  gdom_xlo += IntVect(offx,0,0); gdom_xhi += IntVect(-offx,0,0);
135  gdom_ylo += IntVect(0,offy,0); gdom_yhi += IntVect(0,-offy,0);
136 
137  // Trim the boxes to only include internal ghost cells
138  gdom_xlo.setBig(0,dom_lo.x+set_width+offx-1); gdom_xhi.setSmall(0,dom_hi.x-set_width-offx+1);
139  gdom_ylo.setBig(1,dom_lo.y+set_width+offy-1); gdom_yhi.setSmall(1,dom_hi.y-set_width-offy+1);
140 
141  // Remove overlapping corners from y-face boxes
142  gdom_ylo.setSmall(0,gdom_xlo.bigEnd(0)+1); gdom_ylo.setBig(0,gdom_xhi.smallEnd(0)-1);
143  gdom_yhi.setSmall(0,gdom_xlo.bigEnd(0)+1); gdom_yhi.setBig(0,gdom_xhi.smallEnd(0)-1);
144 
145  // Grow boxes to get external ghost cells only
146  gdom_xlo.growLo(0,ng_vect[0]+offx); gdom_xhi.growHi(0,ng_vect[0]+offx);
147  gdom_xlo.grow (1,ng_vect[1] ); gdom_xhi.grow (1,ng_vect[1] );
148  gdom_ylo.growLo(1,ng_vect[1]+offy); gdom_yhi.growHi(1,ng_vect[1]+offy);
149 
150  // Populate everything
151  bx_xlo = (bx & gdom_xlo);
152  bx_xhi = (bx & gdom_xhi);
153  bx_ylo = (bx & gdom_ylo);
154  bx_yhi = (bx & gdom_yhi);
155 }
const auto & dom_hi
Definition: ERF_SetupVertDiff.H:2
const auto & dom_lo
Definition: ERF_SetupVertDiff.H:1

Referenced by realbdy_interior_bxs_xy().

Here is the caller graph for this function:

◆ realbdy_compute_interior_ghost_rhs()

void realbdy_compute_interior_ghost_rhs ( const Real bdy_time_interval,
const Real time,
const Real delta_t,
const Real stop_time_elapsed,
int  width,
int  set_width,
const Geometry &  geom,
Vector< MultiFab > &  S_rhs,
Vector< MultiFab > &  S_old_data,
Vector< MultiFab > &  S_cur_data,
Vector< Vector< FArrayBox >> &  bdy_data_xlo,
Vector< Vector< FArrayBox >> &  bdy_data_xhi,
Vector< Vector< FArrayBox >> &  bdy_data_ylo,
Vector< Vector< FArrayBox >> &  bdy_data_yhi 
)

Compute the RHS in the relaxation zone

Parameters
[in]bdy_time_intervaltime interval between boundary condition time stamps
[in]timecurrent time
[in]delta_ttimestep
[in]widthnumber of cells in (relaxation+specified) zone
[in]set_widthnumber of cells in (specified) zone
[in]geomcontainer for geometric information
[out]S_rhsRHS to be computed here
[in]S_datacurrent value of the solution
[in]bdy_data_xloboundary data on interior of low x-face
[in]bdy_data_xhiboundary data on interior of high x-face
[in]bdy_data_yloboundary data on interior of low y-face
[in]bdy_data_yhiboundary data on interior of high y-face
188 {
189  BL_PROFILE_REGION("realbdy_compute_interior_ghost_RHS()");
190 
191  // NOTE: We pass the full width into this routine.
192  // For relaxation, the last cell is a halo
193  // cell for the Laplacian. We remove that
194  // cell here if it is present.
195 
196  // The width to do RHS augmentation
197  if (width > set_width+1) width -= 1;
198 
199  // Relaxation constants
200  Real F1 = 1./(10.*delta_t);
201  Real F2 = 1./(50.*delta_t);
202 
203  // Time interpolation
204  Real dT = bdy_time_interval;
205 
206  //
207  // Note this is because we define "time" to be time since start_bdy_time
208  //
209  Real time_since_start = time;
210 
211  int n_time = static_cast<int>( time_since_start / dT);
212  Real alpha = (time_since_start - n_time * dT) / dT;
213  AMREX_ALWAYS_ASSERT( alpha >= 0. && alpha <= 1.0);
214  Real oma = 1.0 - alpha;
215 
216  int n_time_p1 = n_time + 1;
217  if ((time == stop_time_elapsed) && (alpha==0)) {
218  // stop time coincides with final bdy snapshot -- don't try to read in
219  // another snapshot
220  n_time_p1 = n_time;
221  }
222 
223  /*
224  // UNIT TEST DEBUG
225  oma = 1.0; alpha = 0.0;
226  */
227 
228  // Temporary FABs for storage (owned/filled on all ranks)
229  FArrayBox U_xlo, U_xhi, U_ylo, U_yhi;
230  FArrayBox V_xlo, V_xhi, V_ylo, V_yhi;
231  FArrayBox T_xlo, T_xhi, T_ylo, T_yhi;
232 
233  // Variable index map (WRFBdyVars -> Vars)
234  Vector<int> var_map = {Vars::xvel, Vars::yvel, Vars::cons, Vars::cons};
235  Vector<int> ivar_map = {IntVars::xmom, IntVars::ymom, IntVars::cons, IntVars::cons};
236 
237  // Variable icomp map
238  Vector<int> comp_map = {0, 0, RhoTheta_comp};
239 
240  // Indices
241  int ivarU = RealBdyVars::U;
242  int ivarV = RealBdyVars::V;
243  int ivarT = RealBdyVars::T;
244  int BdyEnd = RealBdyVars::NumTypes-1;
245 
246 
247  // NOTE: These sizing of the temporary BDY FABS is
248  // GLOBAL and occurs over the entire BDY region.
249 
250  // Size the FABs
251  //==========================================================
252  for (int ivar(ivarU); ivar < BdyEnd; ivar++) {
253  int ivar_idx = var_map[ivar];
254  Box domain = geom.Domain();
255  auto ixtype = S_cur_data[ivar_idx].boxArray().ixType();
256  domain.convert(ixtype);
257 
258  // Grown domain to get the 4 halo boxes w/ ghost cells
259  // NOTE: 2 ghost cells needed here for Laplacian
260  // halo cell.
261  IntVect ng_vect{2,2,0};
262  Box gdom(domain); gdom.grow(ng_vect);
263  Box bx_xlo, bx_xhi, bx_ylo, bx_yhi;
264  realbdy_interior_bxs_xy(gdom, domain, width,
265  bx_xlo, bx_xhi,
266  bx_ylo, bx_yhi,
267  0, ng_vect, true);
268 
269  // Size the FABs
270  if (ivar == ivarU) {
271  U_xlo.resize(bx_xlo,1,The_Async_Arena()); U_xhi.resize(bx_xhi,1,The_Async_Arena());
272  U_ylo.resize(bx_ylo,1,The_Async_Arena()); U_yhi.resize(bx_yhi,1,The_Async_Arena());
273  } else if (ivar == ivarV) {
274  V_xlo.resize(bx_xlo,1,The_Async_Arena()); V_xhi.resize(bx_xhi,1,The_Async_Arena());
275  V_ylo.resize(bx_ylo,1,The_Async_Arena()); V_yhi.resize(bx_yhi,1,The_Async_Arena());
276  } else if (ivar == ivarT){
277  T_xlo.resize(bx_xlo,1,The_Async_Arena()); T_xhi.resize(bx_xhi,1,The_Async_Arena());
278  T_ylo.resize(bx_ylo,1,The_Async_Arena()); T_yhi.resize(bx_yhi,1,The_Async_Arena());
279  } else {
280  continue;
281  }
282  } // ivar
283 
284 
285  // NOTE: These operations use the BDY FABS and RHO. The
286  // use of RHO to go from PRIM -> CONS requires that
287  // these operations be LOCAL. So we have allocated
288  // enough space to do global operations (1 rank) but
289  // will fill a subset of that data that the rank owns.
290 
291  // Populate FABs from bdy interpolation (primitive vars)
292  //==========================================================
293  for (int ivar(ivarU); ivar < BdyEnd; ivar++) {
294  int ivar_idx = var_map[ivar];
295  Box domain = geom.Domain();
296  auto ixtype = S_cur_data[ivar_idx].boxArray().ixType();
297  domain.convert(ixtype);
298  const auto& dom_lo = lbound(domain);
299  const auto& dom_hi = ubound(domain);
300 
301 #ifdef _OPENMP
302 #pragma omp parallel if (Gpu::notInLaunchRegion())
303 #endif
304  for (MFIter mfi(S_cur_data[ivar_idx],TilingIfNotGPU()); mfi.isValid(); ++mfi) {
305  // We need lateral ghost cells for the Laplacian
306  // NOTE: We don't write into the ghost cells
307  IntVect ng_vect{2,2,0};
308  Box gtbx = grow(mfi.tilebox(ixtype.toIntVect()),ng_vect);
309  Box tbx_xlo, tbx_xhi, tbx_ylo, tbx_yhi;
310  realbdy_interior_bxs_xy(gtbx, domain, width,
311  tbx_xlo, tbx_xhi,
312  tbx_ylo, tbx_yhi,
313  0, ng_vect, true);
314 
315  Array4<Real> arr_xlo; Array4<Real> arr_xhi;
316  Array4<Real> arr_ylo; Array4<Real> arr_yhi;
317  if (ivar == ivarU) {
318  arr_xlo = U_xlo.array(); arr_xhi = U_xhi.array();
319  arr_ylo = U_ylo.array(); arr_yhi = U_yhi.array();
320  } else if (ivar == ivarV) {
321  arr_xlo = V_xlo.array(); arr_xhi = V_xhi.array();
322  arr_ylo = V_ylo.array(); arr_yhi = V_yhi.array();
323  } else if (ivar == ivarT){
324  arr_xlo = T_xlo.array(); arr_xhi = T_xhi.array();
325  arr_ylo = T_ylo.array(); arr_yhi = T_yhi.array();
326  } else {
327  continue;
328  }
329 
330  // Boundary data at fixed time intervals
331  const auto& bdatxlo_n = bdy_data_xlo[n_time ][ivar].const_array();
332  const auto& bdatxlo_np1 = bdy_data_xlo[n_time_p1][ivar].const_array();
333  const auto& bdatxhi_n = bdy_data_xhi[n_time ][ivar].const_array();
334  const auto& bdatxhi_np1 = bdy_data_xhi[n_time_p1][ivar].const_array();
335  const auto& bdatylo_n = bdy_data_ylo[n_time ][ivar].const_array();
336  const auto& bdatylo_np1 = bdy_data_ylo[n_time_p1][ivar].const_array();
337  const auto& bdatyhi_n = bdy_data_yhi[n_time ][ivar].const_array();
338  const auto& bdatyhi_np1 = bdy_data_yhi[n_time_p1][ivar].const_array();
339 
340  // Current density to convert to conserved vars
341  Array4<Real> r_arr = S_cur_data[IntVars::cons].array(mfi);
342 
343  // NOTE: width is now one less than the total bndy width
344  // if we have a relaxation zone; so we can access
345  // dom_lo/hi +- width. If we do not have a relax
346  // zone, this offset is set_width - 1.
347  int offset = set_width - 1;
348  if (width > set_width) offset = width;
349 
350  // Populate with interpolation (protect from ghost cells)
351  ParallelFor(tbx_xlo, tbx_xhi,
352  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
353  {
354  int ii = std::max(i , dom_lo.x);
355  ii = std::min(ii, dom_lo.x+offset);
356  int jj = std::max(j , dom_lo.y);
357  jj = std::min(jj, dom_hi.y);
358 
359  Real rho_interp;
360  if (ivar==ivarU) {
361  rho_interp = 0.5 * ( r_arr(i-1,j ,k) + r_arr(i,j,k) );
362  } else if (ivar==ivarV) {
363  rho_interp = 0.5 * ( r_arr(i ,j-1,k) + r_arr(i,j,k) );
364  } else {
365  rho_interp = r_arr(i,j,k);
366  }
367  arr_xlo(i,j,k) = rho_interp * ( oma * bdatxlo_n (ii,jj,k,0)
368  + alpha * bdatxlo_np1(ii,jj,k,0) );
369  },
370  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
371  {
372  int ii = std::max(i , dom_hi.x-offset);
373  ii = std::min(ii, dom_hi.x);
374  int jj = std::max(j , dom_lo.y);
375  jj = std::min(jj, dom_hi.y);
376 
377  Real rho_interp;
378  if (ivar==ivarU) {
379  rho_interp = 0.5 * ( r_arr(i-1,j ,k) + r_arr(i,j,k) );
380  } else if (ivar==ivarV) {
381  rho_interp = 0.5 * ( r_arr(i ,j-1,k) + r_arr(i,j,k) );
382  } else {
383  rho_interp = r_arr(i,j,k);
384  }
385  arr_xhi(i,j,k) = rho_interp * ( oma * bdatxhi_n (ii,jj,k,0)
386  + alpha * bdatxhi_np1(ii,jj,k,0) );
387  });
388 
389  ParallelFor(tbx_ylo, tbx_yhi,
390  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
391  {
392  int ii = std::max(i , dom_lo.x);
393  ii = std::min(ii, dom_hi.x);
394  int jj = std::max(j , dom_lo.y);
395  jj = std::min(jj, dom_lo.y+offset);
396 
397  Real rho_interp;
398  if (ivar==ivarU) {
399  rho_interp = 0.5 * ( r_arr(i-1,j ,k) + r_arr(i,j,k) );
400  } else if (ivar==ivarV) {
401  rho_interp = 0.5 * ( r_arr(i ,j-1,k) + r_arr(i,j,k) );
402  } else {
403  rho_interp = r_arr(i,j,k);
404  }
405  arr_ylo(i,j,k) = rho_interp * ( oma * bdatylo_n (ii,jj,k,0)
406  + alpha * bdatylo_np1(ii,jj,k,0) );
407  },
408  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
409  {
410  int ii = std::max(i , dom_lo.x);
411  ii = std::min(ii, dom_hi.x);
412  int jj = std::max(j , dom_hi.y-offset);
413  jj = std::min(jj, dom_hi.y);
414 
415  Real rho_interp;
416  if (ivar==ivarU) {
417  rho_interp = 0.5 * ( r_arr(i-1,j ,k) + r_arr(i,j,k) );
418  } else if (ivar==ivarV) {
419  rho_interp = 0.5 * ( r_arr(i ,j-1,k) + r_arr(i,j,k) );
420  } else {
421  rho_interp = r_arr(i,j,k);
422  }
423  arr_yhi(i,j,k) = rho_interp * ( oma * bdatyhi_n (ii,jj,k,0)
424  + alpha * bdatyhi_np1(ii,jj,k,0) );
425  });
426  } // mfi
427  } // ivar
428 
429 
430  // NOTE: These operations use current RHS, so they are
431  // LOCAL and occur over the data owned by a given rank.
432 
433  // Compute RHS in specified region
434  //==========================================================
435  if (set_width > 0) {
436  for (int ivar(ivarU); ivar < BdyEnd; ivar++) {
437  int ivar_idx = ivar_map[ivar];
438  int icomp = comp_map[ivar];
439 
440  Box domain = geom.Domain();
441  auto ix_type = S_old_data[ivar_idx].boxArray().ixType();
442  auto iv_type = ix_type.toIntVect();
443  domain.convert(ix_type);
444  const auto& dom_hi = ubound(domain);
445  const auto& dom_lo = lbound(domain);
446 
447  int set_width_x = (iv_type[0]) ? set_width : set_width-1;
448  int set_width_y = (iv_type[1]) ? set_width : set_width-1;
449 
450 #ifdef _OPENMP
451 #pragma omp parallel if (Gpu::notInLaunchRegion())
452 #endif
453  for (MFIter mfi(S_old_data[ivar_idx],TilingIfNotGPU()); mfi.isValid(); ++mfi) {
454  Box tbx = mfi.tilebox();
455  Box tbx_xlo, tbx_xhi, tbx_ylo, tbx_yhi;
456  realbdy_interior_bxs_xy(tbx, domain, width,
457  tbx_xlo, tbx_xhi,
458  tbx_ylo, tbx_yhi);
459 
460  Array4<Real> rhs_arr; Array4<Real> data_arr;
461  Array4<Real> arr_xlo; Array4<Real> arr_xhi;
462  Array4<Real> arr_ylo; Array4<Real> arr_yhi;
463  if (ivar == ivarU) {
464  arr_xlo = U_xlo.array(); arr_xhi = U_xhi.array();
465  arr_ylo = U_ylo.array(); arr_yhi = U_yhi.array();
466  rhs_arr = S_rhs[IntVars::xmom].array(mfi);
467  data_arr = S_old_data[IntVars::xmom].array(mfi);
468  } else if (ivar == ivarV) {
469  arr_xlo = V_xlo.array(); arr_xhi = V_xhi.array();
470  arr_ylo = V_ylo.array(); arr_yhi = V_yhi.array();
471  rhs_arr = S_rhs[IntVars::ymom].array(mfi);
472  data_arr = S_old_data[IntVars::ymom].array(mfi);
473  } else if (ivar == ivarT){
474  arr_xlo = T_xlo.array(); arr_xhi = T_xhi.array();
475  arr_ylo = T_ylo.array(); arr_yhi = T_yhi.array();
476  rhs_arr = S_rhs[IntVars::cons].array(mfi);
477  data_arr = S_old_data[IntVars::cons].array(mfi);
478  } else {
479  continue;
480  }
481 
482  realbdy_set_rhs_in_spec_region(delta_t, icomp, 1,
483  width, set_width_x, set_width_y,
484  dom_lo, dom_hi,
485  tbx_xlo, tbx_xhi, tbx_ylo, tbx_yhi,
486  arr_xlo, arr_xhi, arr_ylo, arr_yhi,
487  data_arr, rhs_arr);
488 
489  } // mfi
490  } // ivar
491  } // set_width
492 
493  // NOTE: These operations use current density, so they are
494  // LOCAL and occur over the data owned by a given rank
495 
496  // Compute RHS in relaxation region
497  //==========================================================
498  if (width > set_width) {
499  auto dx = geom.CellSizeArray();
500  auto ProbLo = geom.ProbLoArray();
501  auto ProbHi = geom.ProbHiArray();
502  for (int ivar(ivarU); ivar < BdyEnd; ivar++) {
503  int ivar_idx = ivar_map[ivar];
504  int icomp = comp_map[ivar];
505 
506  Box domain = geom.Domain();
507  domain.convert(S_cur_data[ivar_idx].boxArray().ixType());
508  IntVect ng_vect = S_cur_data[ivar_idx].nGrowVect();
509 
510 #ifdef _OPENMP
511 #pragma omp parallel if (Gpu::notInLaunchRegion())
512 #endif
513  for (MFIter mfi(S_cur_data[ivar_idx],TilingIfNotGPU()); mfi.isValid(); ++mfi) {
514  Box tbx = mfi.tilebox();
515  Box tbx_xlo, tbx_xhi, tbx_ylo, tbx_yhi;
516  realbdy_interior_bxs_xy(tbx, domain, width,
517  tbx_xlo, tbx_xhi,
518  tbx_ylo, tbx_yhi,
519  set_width, ng_vect);
520 
521  Array4<Real> rhs_arr; Array4<Real> data_arr;
522  Array4<Real> arr_xlo; Array4<Real> arr_xhi;
523  Array4<Real> arr_ylo; Array4<Real> arr_yhi;
524  if (ivar == ivarU) {
525  arr_xlo = U_xlo.array(); arr_xhi = U_xhi.array();
526  arr_ylo = U_ylo.array(); arr_yhi = U_yhi.array();
527  rhs_arr = S_rhs[IntVars::xmom].array(mfi);
528  data_arr = S_cur_data[IntVars::xmom].array(mfi);
529  } else if (ivar == ivarV) {
530  arr_xlo = V_xlo.array(); arr_xhi = V_xhi.array();
531  arr_ylo = V_ylo.array(); arr_yhi = V_yhi.array();
532  rhs_arr = S_rhs[IntVars::ymom].array(mfi);
533  data_arr = S_cur_data[IntVars::ymom].array(mfi);
534  } else if (ivar == ivarT){
535  arr_xlo = T_xlo.array(); arr_xhi = T_xhi.array();
536  arr_ylo = T_ylo.array(); arr_yhi = T_yhi.array();
537  rhs_arr = S_rhs[IntVars::cons].array(mfi);
538  data_arr = S_cur_data[IntVars::cons].array(mfi);
539  } else {
540  continue;
541  }
542 
544  width, dx, ProbLo, ProbHi, F1, F2,
545  tbx_xlo, tbx_xhi, tbx_ylo, tbx_yhi,
546  arr_xlo, arr_xhi, arr_ylo, arr_yhi,
547  data_arr, rhs_arr);
548 
549  /*
550  // UNIT TEST DEBUG
551  realbdy_interior_bxs_xy(tbx, domain, width+1,
552  tbx_xlo, tbx_xhi,
553  tbx_ylo, tbx_yhi);
554  ParallelFor(tbx_xlo, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
555  {
556  if (arr_xlo(i,j,k) != data_arr(i,j,k,icomp)) {
557  Print() << "ERROR XLO: " << ivar << ' ' << icomp << ' ' << IntVect(i,j,k) << "\n";
558  Print() << "DATA: " << data_arr(i,j,k,icomp) << ' ' << arr_xlo(i,j,k) << "\n";
559  exit(0);
560  }
561  });
562  ParallelFor(tbx_xhi, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
563  {
564  if (arr_xhi(i,j,k) != data_arr(i,j,k,icomp)) {
565  Print() << "ERROR XHI: " << ivar << ' ' << icomp << ' ' << IntVect(i,j,k) << "\n";
566  Print() << "DATA: " << data_arr(i,j,k,icomp) << ' ' << arr_xhi(i,j,k) << "\n";
567  exit(0);
568  }
569  });
570  ParallelFor(tbx_ylo, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
571  {
572  if (arr_ylo(i,j,k) != data_arr(i,j,k,icomp)) {
573  Print() << "ERROR YLO: " << ivar << ' ' << icomp << ' ' << IntVect(i,j,k) << "\n";
574  Print() << "DATA: " << data_arr(i,j,k,icomp) << ' ' << arr_ylo(i,j,k) << "\n";
575  exit(0);
576  }
577  });
578  ParallelFor(tbx_yhi, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
579  {
580  if (arr_yhi(i,j,k) != data_arr(i,j,k,icomp)) {
581  Print() << "ERROR YHI: " << ivar << ' ' << icomp << ' ' << IntVect(i,j,k) << "\n";
582  Print() << "DATA: " << data_arr(i,j,k,icomp) << ' ' << arr_yhi(i,j,k) << "\n";
583  exit(0);
584  }
585  });
586  */
587  } // mfi
588  } // ivar
589  } // width
590  //ParallelDescriptor::Barrier();
591  //exit(0);
592 }
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
void realbdy_interior_bxs_xy(const Box &bx, const Box &domain, const int &width, Box &bx_xlo, Box &bx_xhi, Box &bx_ylo, Box &bx_yhi, const int &set_width, const IntVect &ng_vect, const bool get_int_ng)
Definition: ERF_InteriorGhostCells.cpp:23
AMREX_FORCE_INLINE IntVect offset(const int face_dir, const int normal)
Definition: ERF_ReadBndryPlanes.cpp:28
AMREX_GPU_HOST AMREX_FORCE_INLINE void realbdy_set_rhs_in_spec_region(const amrex::Real &dt, const int &icomp, const int &num_var, const int &width, const int &set_width_x, const int &set_width_y, const amrex::Dim3 &dom_lo, const amrex::Dim3 &dom_hi, const amrex::Box &bx_xlo, const amrex::Box &bx_xhi, const amrex::Box &bx_ylo, const amrex::Box &bx_yhi, const amrex::Array4< const amrex::Real > &arr_xlo, const amrex::Array4< const amrex::Real > &arr_xhi, const amrex::Array4< const amrex::Real > &arr_ylo, const amrex::Array4< const amrex::Real > &arr_yhi, const amrex::Array4< const amrex::Real > &data_arr, const amrex::Array4< amrex::Real > &rhs_arr)
Definition: ERF_Utils.H:182
AMREX_GPU_HOST AMREX_FORCE_INLINE void realbdy_compute_laplacian_relaxation(const int &icomp, const int &num_var, const int &width, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dx, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &ProbLo, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &ProbHi, const amrex::Real &F1, const amrex::Real &F2, const amrex::Box &bx_xlo, const amrex::Box &bx_xhi, const amrex::Box &bx_ylo, const amrex::Box &bx_yhi, const amrex::Array4< const amrex::Real > &arr_xlo, const amrex::Array4< const amrex::Real > &arr_xhi, const amrex::Array4< const amrex::Real > &arr_ylo, const amrex::Array4< const amrex::Real > &arr_yhi, const amrex::Array4< const amrex::Real > &data_arr, const amrex::Array4< amrex::Real > &rhs_arr)
Definition: ERF_Utils.H:276
@ U
Definition: ERF_IndexDefines.H:108
@ NumTypes
Definition: ERF_IndexDefines.H:112
@ T
Definition: ERF_IndexDefines.H:110
@ V
Definition: ERF_IndexDefines.H:109
@ xvel
Definition: ERF_IndexDefines.H:141
@ cons
Definition: ERF_IndexDefines.H:140
@ yvel
Definition: ERF_IndexDefines.H:142
Here is the call graph for this function:

◆ realbdy_interior_bxs_xy()

void realbdy_interior_bxs_xy ( const Box &  bx,
const Box &  domain,
const int &  width,
Box &  bx_xlo,
Box &  bx_xhi,
Box &  bx_ylo,
Box &  bx_yhi,
const int &  set_width,
const IntVect &  ng_vect,
const bool  get_int_ng 
)

Get the boxes for looping over interior/exterior ghost cells for use by fillpatch, erf_slow_rhs_pre, and erf_slow_rhs_post.

Parameters
[in]bxbox to intersect with 4 halo regions
[in]domainbox of the whole domain
[in]widthnumber of cells in (relaxation+specified) zone
[in]set_widthnumber of cells in (specified) zone
[out]bx_xlohalo box at x_lo boundary
[out]bx_xhihalo box at x_hi boundary
[out]bx_ylohalo box at y_lo boundary
[out]bx_yhihalo box at y_hi boundary
[in]ng_vectnumber of ghost cells in each direction
[in]get_int_ngflag to get ghost cells inside the domain
33 {
34  AMREX_ALWAYS_ASSERT(bx.ixType() == domain.ixType());
35 
36  //==================================================================
37  // NOTE: X-face boxes take ownership of the overlapping region.
38  // With exterior ghost cells (ng_vect != 0), the x-face
39  // boxes will have exterior ghost cells in both x & y.
40  //==================================================================
41 
42  // Domain bounds without ghost cells
43  const auto& dom_lo = lbound(domain);
44  const auto& dom_hi = ubound(domain);
45 
46  // Four boxes matching the domain
47  Box gdom_xlo(domain); Box gdom_xhi(domain);
48  Box gdom_ylo(domain); Box gdom_yhi(domain);
49 
50  // Trim the boxes to only include internal ghost cells
51  gdom_xlo.setBig(0,dom_lo.x+width-1); gdom_xhi.setSmall(0,dom_hi.x-width+1);
52  gdom_ylo.setBig(1,dom_lo.y+width-1); gdom_yhi.setSmall(1,dom_hi.y-width+1);
53 
54  // Remove overlapping corners from y-face boxes
55  gdom_ylo.setSmall(0,gdom_xlo.bigEnd(0)+1); gdom_ylo.setBig(0,gdom_xhi.smallEnd(0)-1);
56  gdom_yhi.setSmall(0,gdom_xlo.bigEnd(0)+1); gdom_yhi.setBig(0,gdom_xhi.smallEnd(0)-1);
57 
58  if (set_width>0) {
59  // Cut out the set region (uses offsets)
60  IntVect iv_type = bx.ixType().toIntVect();
61  Box sdom_xlo,sdom_xhi,sdom_ylo,sdom_yhi;
62  realbdy_bc_bxs_xy (grow(domain,ng_vect), domain, set_width,
63  sdom_xlo, sdom_xhi,
64  sdom_ylo, sdom_yhi,
65  ng_vect);
66  gdom_xlo.setSmall(0,sdom_xlo.bigEnd(0)+1); gdom_xhi.setBig(0,sdom_xhi.smallEnd(0)-1);
67  gdom_ylo.setSmall(1,sdom_ylo.bigEnd(1)+1); gdom_yhi.setBig(1,sdom_yhi.smallEnd(1)-1);
68  if (iv_type[1]==1) {
69  gdom_xlo.setSmall(1,sdom_ylo.bigEnd(1)+1); gdom_xhi.setSmall(1,sdom_ylo.bigEnd(1)+1);
70  gdom_xlo.setBig(1,sdom_yhi.smallEnd(1)-1); gdom_xhi.setBig(1,sdom_yhi.smallEnd(1)-1);
71  }
72  } else {
73  // Grow boxes to get external ghost cells only
74  gdom_xlo.growLo(0,ng_vect[0]); gdom_xhi.growHi(0,ng_vect[0]);
75  gdom_xlo.grow (1,ng_vect[1]); gdom_xhi.grow (1,ng_vect[1]);
76  gdom_ylo.growLo(1,ng_vect[1]); gdom_yhi.growHi(1,ng_vect[1]);
77  }
78 
79  // Grow boxes to get internal ghost cells
80  if (get_int_ng) {
81  gdom_xlo.growHi(0,ng_vect[0]); gdom_xhi.growLo(0,ng_vect[0]);
82  gdom_ylo.grow (0,ng_vect[0]); gdom_yhi.grow (0,ng_vect[0]);
83  gdom_ylo.growHi(1,ng_vect[1]); gdom_yhi.growLo(1,ng_vect[1]);
84  }
85 
86  // Populate everything
87  bx_xlo = (bx & gdom_xlo);
88  bx_xhi = (bx & gdom_xhi);
89  bx_ylo = (bx & gdom_ylo);
90  bx_yhi = (bx & gdom_yhi);
91 }
void realbdy_bc_bxs_xy(const Box &bx, const Box &domain, const int &set_width, Box &bx_xlo, Box &bx_xhi, Box &bx_ylo, Box &bx_yhi, const IntVect &ng_vect)
Definition: ERF_InteriorGhostCells.cpp:109

Referenced by realbdy_compute_interior_ghost_rhs().

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

Variable Documentation

◆ void_bc

PhysBCFunctNoOp void_bc