Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Witch of Agnesi test case for JAMES paper #1942

Merged
merged 4 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Exec/DryRegTests/WitchOfAgnesi_JAMES/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
set(erf_exe_name erf_witch_of_agnesi)

add_executable(${erf_exe_name} "")
target_sources(${erf_exe_name}
PRIVATE
ERF_prob.cpp
)

target_include_directories(${erf_exe_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

include(${CMAKE_SOURCE_DIR}/CMake/BuildERFExe.cmake)
build_erf_exe(${erf_exe_name})

#find_package(AMReX)
#target_link_libraries( ${_target} AMReX::amrex)
63 changes: 63 additions & 0 deletions Exec/DryRegTests/WitchOfAgnesi_JAMES/ERF_prob.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#ifndef ERF_PROB_H_
#define ERF_PROB_H_

#include <string>

#include "AMReX_REAL.H"

#include "ERF_prob_common.H"

struct ProbParm : ProbParmDefaults {
// perturbations to initial conditions
amrex::Real rho_0 = 0.0;
amrex::Real T_0 = 0.0;
amrex::Real U_0 = 0.0;
amrex::Real V_0 = 0.0;
amrex::Real W_0 = 0.0; // needed for rayleigh damping

// hill parameters
amrex::Real hmax = 0.0; // full hill height, can be negative to simulate valleys
amrex::Real L = 0.0; // hill length at half-height
}; // namespace ProbParm

class Problem : public ProblemBase
{
public:
Problem();

#include "Prob/ERF_init_density_hse_dry.H"
#include "Prob/ERF_init_rayleigh_damping.H"

void init_custom_pert (
const amrex::Box& bx,
const amrex::Box& xbx,
const amrex::Box& ybx,
const amrex::Box& zbx,
amrex::Array4<amrex::Real const> const& state,
amrex::Array4<amrex::Real > const& state_pert,
amrex::Array4<amrex::Real > const& x_vel_pert,
amrex::Array4<amrex::Real > const& y_vel_pert,
amrex::Array4<amrex::Real > const& z_vel_pert,
amrex::Array4<amrex::Real > const& r_hse,
amrex::Array4<amrex::Real > const& p_hse,
amrex::Array4<amrex::Real const> const& z_nd,
amrex::Array4<amrex::Real const> const& z_cc,
amrex::GeometryData const& geomdata,
amrex::Array4<amrex::Real const> const& mf_m,
amrex::Array4<amrex::Real const> const& mf_u,
amrex::Array4<amrex::Real const> const& mf_v,
const SolverChoice& sc) override;

void init_custom_terrain (
const amrex::Geometry& geom,
amrex::MultiFab& z_phys_nd,
const amrex::Real& time) override;

protected:
std::string name() override { return "Witch of Agnesi Hill"; }

private:
ProbParm parms;
};

#endif
163 changes: 163 additions & 0 deletions Exec/DryRegTests/WitchOfAgnesi_JAMES/ERF_prob.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#include "ERF_prob.H"
#include "ERF_TerrainMetrics.H"

using namespace amrex;

std::unique_ptr<ProblemBase>
amrex_probinit (
const amrex_real* /*problo*/,
const amrex_real* /*probhi*/)
{
return std::make_unique<Problem>();
}

Problem::Problem ()
{
// Parse params
ParmParse pp("prob");
pp.query("rho_0", parms.rho_0);
pp.query("T_0", parms.T_0);
pp.query("U_0", parms.U_0);
pp.query("V_0", parms.V_0);
pp.query("W_0", parms.W_0);

pp.query("hmax", parms.hmax);
pp.query("L", parms.L);

init_base_parms(parms.rho_0, parms.T_0);
}

void
Problem::init_custom_pert (
const Box& bx,
const Box& xbx,
const Box& ybx,
const Box& zbx,
Array4<Real const> const& /*state*/,
Array4<Real > const& state_pert,
Array4<Real > const& x_vel_pert,
Array4<Real > const& y_vel_pert,
Array4<Real > const& z_vel_pert,
Array4<Real > const& /*r_hse*/,
Array4<Real > const& /*p_hse*/,
Array4<Real const> const& z_nd,
Array4<Real const> const& /*z_cc*/,
GeometryData const& geomdata,
Array4<Real const> const& /*mf_m*/,
Array4<Real const> const& /*mf_u*/,
Array4<Real const> const& /*mf_v*/,
const SolverChoice& sc)
{
const bool use_moisture = (sc.moisture_type != MoistureType::None);

ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
{
// Set scalar = 0 everywhere
state_pert(i, j, k, RhoScalar_comp) = 0.0;

if (use_moisture) {
state_pert(i, j, k, RhoQ1_comp) = 0.0;
state_pert(i, j, k, RhoQ2_comp) = 0.0;
}
});

// Set the x-velocity
ParallelFor(xbx, [=, parms_d=parms] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
{
x_vel_pert(i, j, k) = parms_d.U_0;
});

// Set the y-velocity
ParallelFor(ybx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
{
y_vel_pert(i, j, k) = 0.0;
});

const auto dx = geomdata.CellSize();
amrex::GpuArray<Real, AMREX_SPACEDIM> dxInv;
dxInv[0] = 1. / dx[0];
dxInv[1] = 1. / dx[1];
dxInv[2] = 1. / dx[2];

// Set the z-velocity from impenetrable condition
ParallelFor(zbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
{
z_vel_pert(i, j, k) = WFromOmega(i, j, k, 0.0, x_vel_pert, y_vel_pert, z_nd, dxInv);
});

amrex::Gpu::streamSynchronize();
}

void
Problem::init_custom_terrain (
const Geometry& geom,
MultiFab& z_phys_nd,
const Real& time)
{

// Check if a valid text file exists for the terrain
std::string fname;
ParmParse pp("erf");
auto valid_fname = pp.query("terrain_file_name",fname);
if (valid_fname) {
this->read_custom_terrain(fname,geom,z_phys_nd,time);
} else {
// Domain cell size and real bounds
auto dx = geom.CellSizeArray();
auto ProbLoArr = geom.ProbLoArray();
auto ProbHiArr = geom.ProbHiArray();

// Domain valid box (z_nd is nodal)
const amrex::Box& domain = geom.Domain();
int domlo_x = domain.smallEnd(0); int domhi_x = domain.bigEnd(0) + 1;
// int domlo_y = domain.smallEnd(1); int domhi_y = domain.bigEnd(1) + 1;
int domlo_z = domain.smallEnd(2);

// User function parameters
Real a = 0.5;
Real num = 8 * a * a * a;
Real xcen = 0.5 * (ProbLoArr[0] + ProbHiArr[0]);
// Real ycen = 0.5 * (ProbLoArr[1] + ProbHiArr[1]);

// if hm is nonzero, then use alternate hill definition
Real hm = parms.hmax;
Real L = parms.L;

// Number of ghost cells
int ngrow = z_phys_nd.nGrow();

// Populate bottom plane
int k0 = domlo_z;

for ( amrex::MFIter mfi(z_phys_nd,amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi )
{
amrex::Box zbx = mfi.nodaltilebox(2);
if (zbx.smallEnd(2) > k0) continue;

// Grown box with no z range
amrex::Box xybx = mfi.growntilebox(ngrow);
xybx.setRange(2,0);

amrex::Array4<Real> const& z_arr = z_phys_nd.array(mfi);

ParallelFor(xybx, [=] AMREX_GPU_DEVICE (int i, int j, int)
{
// Clip indices for ghost-cells
int ii = amrex::min(amrex::max(i,domlo_x),domhi_x);
// int jj = amrex::min(amrex::max(j,domlo_y),domhi_y);

// Location of nodes
Real x = (ProbLoArr[0] + ii * dx[0] - xcen);
// Real y = (jj * dx[1] - ycen);

// WoA Hill in x-direction
if (hm==0) {
z_arr(i,j,k0) = num / (x*x + 4 * a * a);
} else {
Real x_L = x / L;
z_arr(i,j,k0) = hm / (1 + x_L*x_L);
}
});
}
}
}
33 changes: 33 additions & 0 deletions Exec/DryRegTests/WitchOfAgnesi_JAMES/GNUmakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# AMReX
COMP = gnu
PRECISION = DOUBLE

# Profiling
PROFILE = FALSE
TINY_PROFILE = FALSE
COMM_PROFILE = FALSE
TRACE_PROFILE = FALSE
MEM_PROFILE = FALSE
USE_GPROF = FALSE

# Performance
USE_MPI = TRUE
USE_OMP = FALSE

USE_CUDA = FALSE
USE_HIP = FALSE
USE_SYCL = FALSE

# Debugging
DEBUG = FALSE

TEST = TRUE
USE_ASSERTION = TRUE

# GNU Make
Bpack := ./Make.package
Blocs := .

ERF_HOME := ../../..
ERF_PROBLEM_DIR = $(ERF_HOME)/Exec/DryRegTests/WitchOfAgnesi_JAMES
include $(ERF_HOME)/Exec/Make.ERF
2 changes: 2 additions & 0 deletions Exec/DryRegTests/WitchOfAgnesi_JAMES/Make.package
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CEXE_headers += ERF_prob.H
CEXE_sources += ERF_prob.cpp
6 changes: 6 additions & 0 deletions Exec/DryRegTests/WitchOfAgnesi_JAMES/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
This problem setup is for flow over an idealized hill with a "Witch of Agnesi" profile.
The domain is periodic in the y-direction, with inflow at low x and outflow at high x.
The terrain-fitted coordinates follow the contour of the hill.

This problem is primarily designed to test the implementation of the terrain-fitted coordinates.

Loading
Loading