@@ -14,7 +14,7 @@ ABLAnelastic::ABLAnelastic(CFDSim& sim) : m_sim(sim)
14
14
{
15
15
amrex::ParmParse pp (" incflo" );
16
16
pp.queryarr (" gravity" , m_gravity);
17
- pp.query (" density" , m_rho0_const );
17
+ pp.query (" density" , m_reference_density_constant );
18
18
pp.query (" godunov_type" , godunov_type);
19
19
pp.query (" icns_conserv" , conserv);
20
20
}
@@ -35,8 +35,8 @@ ABLAnelastic::ABLAnelastic(CFDSim& sim) : m_sim(sim)
35
35
" reference_density" , 1 , density.num_grow ()[0 ], 1 );
36
36
ref_density.set_default_fillpatch_bc (m_sim.time ());
37
37
m_sim.repo ().declare_nd_field (" reference_pressure" , 1 , 0 , 1 );
38
- auto & ref_theta = m_sim. repo (). declare_field (
39
- " reference_temperature" , 1 , density. num_grow ()[ 0 ] , 1 );
38
+ auto & ref_theta =
39
+ m_sim. repo (). declare_field ( " reference_temperature" , 1 , 1 , 1 );
40
40
ref_theta.set_default_fillpatch_bc (m_sim.time ());
41
41
}
42
42
}
@@ -62,45 +62,108 @@ void ABLAnelastic::initialize_data()
62
62
63
63
m_density.resize (m_axis, m_sim.mesh ().Geom ());
64
64
m_pressure.resize (m_axis, m_sim.mesh ().Geom ());
65
+ m_theta.resize (m_axis, m_sim.mesh ().Geom ());
65
66
66
67
AMREX_ALWAYS_ASSERT (m_sim.repo ().num_active_levels () == m_density.size ());
67
68
AMREX_ALWAYS_ASSERT (m_sim.repo ().num_active_levels () == m_pressure.size ());
69
+ AMREX_ALWAYS_ASSERT (m_sim.repo ().num_active_levels () == m_theta.size ());
70
+
71
+ initialize_isentropic_hse ();
72
+
73
+ auto & density0_field = m_sim.repo ().get_field (" reference_density" );
74
+ auto & p0 = m_sim.repo ().get_field (" reference_pressure" );
75
+ auto & temp0 = m_sim.repo ().get_field (" reference_temperature" );
76
+ m_density.copy_to_field (density0_field);
77
+ m_pressure.copy_to_field (p0);
78
+ m_theta.copy_to_field (temp0);
79
+ density0_field.fillpatch (m_sim.time ().current_time ());
80
+ temp0.fillpatch (m_sim.time ().current_time ());
81
+ }
82
+
83
+ void ABLAnelastic::initialize_isentropic_hse ()
84
+ {
85
+ const int max_iterations = 10 ;
86
+ const auto ref_theta = m_sim.transport_model ().reference_temperature ();
87
+ const auto eos = amr_wind::eos::GammaLaw (m_bottom_reference_pressure);
68
88
69
89
for (int lev = 0 ; lev < m_density.size (); lev++) {
70
90
auto & dens = m_density.host_data (lev);
71
91
auto & pres = m_pressure.host_data (lev);
72
- const auto & dx = m_sim.mesh ().Geom (lev).CellSizeArray ();
73
- dens.assign (dens.size (), m_rho0_const);
74
- pres[0 ] = m_bottom_reference_pressure;
75
- for (int k = 0 ; k < pres.size () - 1 ; k++) {
76
- pres[k + 1 ] = pres[k] - dens[k] * m_gravity[m_axis] * dx[m_axis];
92
+ auto & theta = m_theta.host_data (lev);
93
+ theta.assign (theta.size (), ref_theta);
94
+
95
+ const auto & dx = m_sim.mesh ().Geom (lev).CellSizeArray ()[m_axis];
96
+ const amrex::Real half_dx = 0.5 * dx;
97
+
98
+ // Initial guess
99
+ dens[0 ] = m_reference_density_constant;
100
+ pres[0 ] =
101
+ m_bottom_reference_pressure + half_dx * dens[0 ] * m_gravity[m_axis];
102
+
103
+ // We do a Newton iteration to satisfy the EOS & HSE (with constant
104
+ // theta) at the surface
105
+ bool converged_hse = false ;
106
+ amrex::Real p_hse = 0.0 ;
107
+ amrex::Real p_eos = 0.0 ;
108
+
109
+ for (int iter = 0 ; (iter < max_iterations) && (!converged_hse);
110
+ iter++) {
111
+ p_hse = m_bottom_reference_pressure +
112
+ half_dx * dens[0 ] * m_gravity[m_axis];
113
+ p_eos = eos.p_rth (dens[0 ], ref_theta);
114
+
115
+ const amrex::Real p_diff = p_hse - p_eos;
116
+ const amrex::Real dpdr = eos.dp_constanttheta (dens[0 ], ref_theta);
117
+ const amrex::Real ddens =
118
+ p_diff / (dpdr - half_dx * m_gravity[m_axis]);
119
+
120
+ dens[0 ] = dens[0 ] + ddens;
121
+ pres[0 ] = eos.p_rth (dens[0 ], ref_theta);
122
+
123
+ if (std::abs (ddens) < constants::LOOSE_TOL) {
124
+ converged_hse = true ;
125
+ break ;
126
+ }
127
+ }
128
+ if (!converged_hse) {
129
+ amrex::Abort (" Initializing with hydrostatic equilibrium failed" );
77
130
}
78
- }
79
- m_density.copy_host_to_device ();
80
- m_pressure.copy_host_to_device ();
81
131
82
- auto & rho0 = m_sim. repo (). get_field ( " reference_density " );
83
- auto & p0 = m_sim. repo (). get_field ( " reference_pressure " );
84
- m_density. copy_to_field (rho0);
85
- m_pressure. copy_to_field (p0) ;
132
+ // To get values at k > 0 we do a Newton iteration to satisfy the EOS
133
+ // (with constant theta)
134
+ for ( int k = 1 ; k < dens. size (); k++) {
135
+ converged_hse = false ;
86
136
87
- rho0.fillpatch (m_sim.time ().current_time ());
137
+ dens[k] = dens[k - 1 ];
138
+ for (int iter = 0 ; (iter < max_iterations) && (!converged_hse);
139
+ iter++) {
140
+ const amrex::Real dens_avg = 0.5 * (dens[k - 1 ] + dens[k]);
141
+ p_hse = pres[k - 1 ] + dx * dens_avg * m_gravity[m_axis];
142
+ p_eos = eos.p_rth (dens[k], ref_theta);
88
143
89
- auto & temp0 = m_sim.repo ().get_field (" reference_temperature" );
90
- const amrex::Real air_molar_mass = 0.02896492 ; // kg/mol
91
- const amrex::Real Rair = constants::UNIVERSAL_GAS_CONSTANT / air_molar_mass;
92
- for (int lev = 0 ; lev < m_sim.repo ().num_active_levels (); ++lev) {
93
- const auto & rho0_arrs = rho0 (lev).const_arrays ();
94
- const auto & p0_arrs = p0 (lev).const_arrays ();
95
- const auto & temp0_arrs = temp0 (lev).arrays ();
96
- amrex::ParallelFor (
97
- temp0 (lev), amrex::IntVect (0 ),
98
- [=] AMREX_GPU_DEVICE (int nbx, int i, int j, int k) noexcept {
99
- temp0_arrs[nbx](i, j, k) =
100
- p0_arrs[nbx](i, j, k) / (Rair * rho0_arrs[nbx](i, j, k));
101
- });
144
+ const amrex::Real p_diff = p_hse - p_eos;
145
+ const amrex::Real dpdr =
146
+ eos.dp_constanttheta (dens[k], ref_theta);
147
+ const amrex::Real ddens =
148
+ p_diff / (dpdr - dx * m_gravity[m_axis]);
149
+
150
+ dens[k] = dens[k] + ddens;
151
+ pres[k] = eos.p_rth (dens[k], ref_theta);
152
+
153
+ if (std::abs (ddens) < constants::LOOSE_TOL * dens[k - 1 ]) {
154
+ converged_hse = true ;
155
+ break ;
156
+ }
157
+ }
158
+ if (!converged_hse) {
159
+ amrex::Abort (
160
+ " Initializing with hydrostatic equilibrium failed" );
161
+ }
162
+ }
102
163
}
103
- amrex::Gpu::synchronize ();
104
- temp0.fillpatch (m_sim.time ().current_time ());
164
+ m_density.copy_host_to_device ();
165
+ m_pressure.copy_host_to_device ();
166
+ m_theta.copy_host_to_device ();
105
167
}
168
+
106
169
} // namespace amr_wind
0 commit comments