REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_DataStruct.H
Go to the documentation of this file.
1#ifndef _REMORA_DATA_STRUCT_H_
2#define _REMORA_DATA_STRUCT_H_
3
4#include <string>
5#include <iostream>
6#include <array>
7
8#include <AMReX_ParmParse.H>
9#include <AMReX_Print.H>
10#include <AMReX_Gpu.H>
11
12#include <REMORA_Constants.H>
13#include "REMORA_IndexDefines.H"
14
15/** \brief Type of coupling between levels in AMR */
16enum struct CouplingType {
18};
19
20/** \brief Coordinates */
21enum class Coord {
22 x, y, z
23};
24
25/** \brief Horizontal advection schemes */
29
30/** \brief Type of initial condition type. Analytic reads from prob.cpp. Netcdf is from file */
31enum class IC_Type {
33};
34
35/** \brief Coriolis factor */
36enum class Cor_Type {
38};
39
40/** \brief plotfile format */
41enum class PlotfileType {
43};
44
45/** \brief vertical mixing type */
46enum class VertMixingType {
48};
49
50/** \brief horizontal viscosity/diffusion type */
54
55/** \brief How to scale scaled_to_grid coefficients on AMR levels */
58};
59
60/** \brief stability function for GLS */
64
65/** \brief equation of state */
66enum class EOSType {
68};
69
70/** \brief bottom stress formulation */
74
75/** \brief initialization for pm and pn */
76enum class GridScaleType {
78};
79
80/** \brief surface momentum flux */
81enum class SMFluxType {
83};
84
85/** \brief surface wind */
86enum class WindType {
88};
89
90/** \brief masks */
91enum class MaskType {
93};
94
95/** \brief harmonic mixing; which surfaces to calculate along */
98};
99
101 public:
102 static BulkForcingType parse_bulk_forcing_type(const std::string& type_string,
103 const std::string& param_name,
104 bool allow_computed)
105 {
106 const std::string type = amrex::toLower(type_string);
107 if (type == "constant" || type == "const") {
109 } else if (type == "custom") {
110 amrex::Warning((param_name + " uses 'custom'; use 'analytic' instead.").c_str());
112 } else if (type == "analytic" || type == "analytical") {
114 } else if (type == "netcdf" || type == "file" || type == "nc") {
116 } else if (type == "computed") {
117 if (!allow_computed) {
118 amrex::Abort((param_name + " does not accept 'computed'; only remora.lwrad_type and remora.eminusp_type do.").c_str());
119 }
121 }
122 amrex::Abort(("Don't know this " + param_name).c_str());
124 }
125
126 /** \brief read in and initialize parameters */
127 void init_params(int ncons)
128 {
129 amrex::ParmParse pp(pp_prefix);
130
131 pp.queryAdd("flat_bathymetry", flat_bathymetry);
132
133 // Which horizontal advection scheme for tracers
134 static std::string tracer_hadv_string = "upstream3";
135 pp.queryAdd("tracer_horizontal_advection_scheme",tracer_hadv_string);
136 if (tracer_hadv_string == "centered4")
138 else if (tracer_hadv_string == "upstream3")
140 else
141 amrex::Error("Advection scheme unknown.");
142
143 // Which horizontal advection scheme
144 static std::string uv_hadv_string = "upstream3";
145 pp.queryAdd("uv_horizontal_advection_scheme",uv_hadv_string);
146 if (uv_hadv_string == "upstream3")
148 else if (uv_hadv_string == "centered2")
150 else
151 amrex::Error("UV advection scheme unknown.");
152
153 pp.queryAdd("rdrag", rdrag);
154 pp.queryAdd("rdrag2", rdrag2);
155 pp.queryAdd("Zos", Zos);
156 pp.queryAdd("Zob", Zob);
157 pp.queryAdd("Cdb_max", Cdb_max);
158 pp.queryAdd("Cdb_min", Cdb_min);
159
160 // Include salinity?
161 pp.queryAdd("use_salt", use_salt);
162
163 // Include Coriolis forcing?
164 pp.queryAdd("use_coriolis", use_coriolis);
165
166 // Include prestep / lagged predictor / corrections
167 pp.queryAdd("use_prestep", use_prestep);
168
169 //This affect forcing and some of the mixing terms for velocity
170 pp.queryAdd("use_uv3dmix", use_uv3dmix);
171
172 //This accounts for the main 2d loop but may not include coupling and copying properly
173 pp.queryAdd("use_barotropic", use_barotropic);
174
175 pp.queryAdd("use_curvilinear_grid", use_curvilinear_grid);
176
177 // Whether to do rivers. By default, rivers are temp and salt sources. Rivers
178 // have to be momentum sources.
179 pp.queryAdd("do_rivers", do_rivers);
180
181 pp.queryAdd("do_rivers_temp", do_rivers_temp);
182 pp.queryAdd("do_rivers_salt", do_rivers_salt);
183 pp.queryAdd("do_rivers_scalar", do_rivers_scalar);
184
185 do_rivers_cons.assign(ncons, 0);
186 // If we aren't doing rivers, set all of these flags to false
189 for (int icomp = Tracer_comp; icomp < ncons; ++icomp) {
190 do_rivers_cons[icomp] = do_rivers ? do_rivers_scalar : false;
191 }
192
193 pp.queryAdd("init_l1ad_T", init_l1ad_T);
194
195 pp.queryAdd("init_ana_T", init_ana_T);
196
197 pp.queryAdd("init_l0int_T", init_l0int_T);
198
199 static std::string eos_type_string = "linear";
200 pp.queryAdd("eos_type",eos_type_string);
201 if (eos_type_string == "linear" || eos_type_string == "Linear" ||
202 eos_type_string == "lin" || eos_type_string == "Lin") {
204 pp.queryAdd("Tcoef",Tcoef);
205 pp.queryAdd("Scoef",Scoef);
206 } else if (eos_type_string == "nonlinear" || eos_type_string == "Nonlinear" ||
207 eos_type_string == "non-linear" || eos_type_string == "Non-linear" ||
208 eos_type_string == "nonlin" || eos_type_string == "Nonlin") {
210 } else {
211 amrex::Abort("Dont know this eos_type");
212 }
213 pp.queryAdd("R0",R0);
214 pp.queryAdd("S0",S0);
215 pp.queryAdd("T0",T0);
216 pp.queryAdd("rho0", rho0);
217
218 pp.queryAdd("bulk_fluxes",bulk_fluxes);
219 pp.queryAdd("atm2ocn_flux_mode", atm2ocn_flux_mode);
220 {
221 amrex::ParmParse pp_driver("driver");
222 std::string driver_atm2ocn_mode = "state";
223 pp_driver.query("atm2ocn_mode", driver_atm2ocn_mode);
224 if (amrex::toLower(driver_atm2ocn_mode) == "flux") {
225 atm2ocn_flux_mode = true;
226 }
227 }
229 do_salt_flux = true;
230 do_temp_flux = true;
231 }
232 // Outputs forcing variables if true
233 pp.queryAdd("output_forcing", output_forcing);
234 pp.queryAdd("air_pressure",Pair);
235 pp.queryAdd("air_temperature",Tair);
236 pp.queryAdd("air_humidity",Hair);
237 pp.queryAdd("surface_radiation_flux",srflux);
238 pp.queryAdd("uwind", Uwind);
239 pp.queryAdd("vwind", Vwind);
240 pp.queryAdd("longwave_radiation_flux", longwave_rad);
241 pp.query("lwrad", longwave_rad);
242 pp.queryAdd("longwave_down", longwave_down);
243 pp.queryAdd("longwave_is_net", longwave_is_net);
244 pp.queryAdd("longwave_netcdf_varname", longwave_netcdf_varname);
245 pp.queryAdd("cloud",cloud);
246 pp.queryAdd("rain",rain);
247 pp.queryAdd("EminusP", EminusP);
248 pp.query("eminusp_value", EminusP);
249 pp.queryAdd("blk_ZQ",blk_ZQ);
250 pp.queryAdd("blk_ZT",blk_ZT);
251 pp.queryAdd("blk_ZW",blk_ZW);
252 pp.queryAdd("eminusp",eminusp);
253 pp.queryAdd("eminusp_correct_ssh",eminusp_correct_ssh);
254 pp.queryAdd("qair_is_percent",qair_is_percent);
255
256 struct BulkTypeInput {
257 const char* name;
258 int idx;
259 const char* default_type;
260 bool allow_computed;
261 };
262
263 const BulkTypeInput bulk_type_inputs[] = {
264 {"uwind_type", BulkFlux::Uwind, "analytic", false},
265 {"vwind_type", BulkFlux::Vwind, "analytic", false},
266 {"tair_type", BulkFlux::Tair, "constant", false},
267 {"qair_type", BulkFlux::Qair, "constant", false},
268 {"pair_type", BulkFlux::Pair, "constant", false},
269 {"swrad_type", BulkFlux::SWrad, "constant", false},
270 {"lwrad_type", BulkFlux::LWrad, "computed", true},
271 {"rain_type", BulkFlux::Rain, "constant", false},
272 {"cloud_type", BulkFlux::Cloud, "constant", false},
273 {"eminusp_type", BulkFlux::EminusP, "computed", true},
274 };
275
276 bool uwind_type_specified = false;
277 bool vwind_type_specified = false;
278 for (const BulkTypeInput& input : bulk_type_inputs) {
279 std::string type_string = input.default_type;
280 const bool type_specified = pp.queryAdd(input.name, type_string);
281 if (type_specified) {
282 bulk_flux_type[input.idx] = parse_bulk_forcing_type(type_string,
283 "remora." + std::string(input.name),
284 input.allow_computed);
285 if (input.idx == BulkFlux::Uwind) {
286 uwind_type_specified = true;
287 } else if (input.idx == BulkFlux::Vwind) {
288 vwind_type_specified = true;
289 }
290 }
291 }
292
293 struct BulkTypeAlias {
294 const char* name;
295 int idx;
296 bool allow_computed;
297 };
298
299 const BulkTypeAlias bulk_type_aliases[] = {
300 {"srflx_type", BulkFlux::SWrad, false},
301 {"longwave_type", BulkFlux::LWrad, true},
302 {"longwave_down_type", BulkFlux::LWrad, true},
303 };
304
305 for (const BulkTypeAlias& input : bulk_type_aliases) {
306 std::string type_string;
307 if (pp.query(input.name, type_string)) {
308 bulk_flux_type[input.idx] = parse_bulk_forcing_type(type_string,
309 "remora." + std::string(input.name),
310 input.allow_computed);
311 }
312 }
313
314 const BulkTypeAlias legacy_netcdf_flags[] = {
315 {"Tair_from_netcdf", BulkFlux::Tair, false},
316 {"qair_from_netcdf", BulkFlux::Qair, false},
317 {"Pair_from_netcdf", BulkFlux::Pair, false},
318 {"srflx_from_netcdf", BulkFlux::SWrad, false},
319 {"longwave_down_from_netcdf", BulkFlux::LWrad, false},
320 {"rain_from_netcdf", BulkFlux::Rain, false},
321 {"cloud_from_netcdf", BulkFlux::Cloud, false},
322 {"EminusP_from_netcdf", BulkFlux::EminusP, false},
323 };
324
325 for (const BulkTypeAlias& input : legacy_netcdf_flags) {
326 bool from_netcdf = false;
327 if (pp.query(input.name, from_netcdf) && from_netcdf) {
329 }
330 }
331
332 bool legacy_longwave_netcdf_is_net = false;
333 if (pp.query("longwave_netcdf_is_net", legacy_longwave_netcdf_is_net) && legacy_longwave_netcdf_is_net) {
334 longwave_is_net = true;
337 }
338 }
339
342 }
343
345 amrex::Warning("remora.longwave_netcdf_varname is set but remora.lwrad_type is not netcdf; the value will be ignored.");
346 }
347
349 amrex::Abort("If evaporation minus precipitation (E-P) sea surface height correction is on, bulk fluxes must be on as well (remora.bulk_fluxes=true)");
350 }
351 if (eminusp and !bulk_fluxes) {
352 amrex::Abort("Evaporation minus precipitation (E-P) requires bulk flux parametrizations (remora.bulk_fluxes=true)");
353 }
354
355 const bool use_external_lwrad =
357
358 if (longwave_is_net && !use_external_lwrad) {
359 amrex::Abort("remora.longwave_is_net=true requires remora.lwrad_type to be constant, analytic, or netcdf");
360 }
361
362 if (longwave_down && !use_external_lwrad) {
363 amrex::Abort("remora.longwave_down=true requires remora.lwrad_type to be constant, analytic, or netcdf");
364 }
365
366 {
367 static bool printed_ep_source = false;
368 if (!printed_ep_source) {
369 printed_ep_source = true;
371 amrex::Print() << "[REMORA] Active E-P source: NetCDF EminusP (remora.eminusp_type=netcdf).\n";
373 amrex::Print() << "[REMORA] Active E-P source: analytic EminusP (remora.eminusp_type=analytic).\n";
375 amrex::Print() << "[REMORA] Active E-P source: constant EminusP (remora.eminusp_type=constant).\n";
376 } else {
377 amrex::Print() << "[REMORA] Active E-P source: bulk evap-rain diagnostic.\n";
378 }
379 }
380 }
381
382 //Grid stretching
383 pp.queryAdd("theta_s",theta_s);
384 pp.queryAdd("theta_b",theta_b);
385 pp.queryAdd("tcline",tcline);
386
387 //coriolis factor
388 pp.queryAdd("coriolis_f0",coriolis_f0);
389 pp.queryAdd("coriolis_beta",coriolis_beta);
390
391 pp.queryAdd("Akv_bak",Akv_bak);
392 pp.queryAdd("Akt_bak",Akt_bak);
393
394
395 static std::string grid_scale_type_string = "constant";
396 pp.queryAdd("grid_scale_type",grid_scale_type_string);
397
398 if (amrex::toLower(grid_scale_type_string) == "constant") {
400 } else if (amrex::toLower(grid_scale_type_string) == "custom") {
401 amrex::Warning("Initialization of grid scale from prob.cpp is now called 'analytic'. 'custom' will be deprecated");
403 } else if (amrex::toLower(grid_scale_type_string) == "analytic") {
405 } else {
406 amrex::Error("Don't know this grid_scale_type");
407 }
408
409 static std::string ic_type_string = "analytic";
410 bool found_ic_bc = pp.queryAdd("ic_bc_type", ic_type_string);
411 pp.queryAdd("ic_type", ic_type_string);
412
413 if (found_ic_bc) {
414 amrex::Warning("remora.ic_bc_type is now called remora.ic_type, and will eventually be deprecated");
415 }
416
417 if ( amrex::toLower(ic_type_string) == "custom") {
418 amrex::Warning("Problem initialization from prob.cpp is now called 'analytic'. 'custom' will be deprecated");
420 } else if ( amrex::toLower(ic_type_string) == "analytic") {
422 } else if ( amrex::toLower(ic_type_string) == "netcdf") {
424 } else if ( amrex::toLower(ic_type_string) == "real") {
425 amrex::Warning("Problem initialization from NetCDF (remora.ic_type) is now called 'netcdf'. 'real' will be deprecated");
427 } else {
428 amrex::Error("Don't know this ic_type");
429 }
430
431 // Which type of refinement
432 static std::string coupling_type_string = "TwoWay";
433 pp.queryAdd("coupling_type",coupling_type_string);
434 if (amrex::toLower(coupling_type_string) == "twoway" ||
435 amrex::toLower(coupling_type_string) == "two_way") {
437 } else if (amrex::toLower(coupling_type_string) == "oneway" ||
438 amrex::toLower(coupling_type_string) == "one_way") {
440 } else {
441 amrex::Abort("Dont know this coupling_type");
442 }
443
444 // Which type of coriolis forcing
445 if (use_coriolis) {
446 static std::string coriolis_type_string = "beta_plane";
447 pp.queryAdd("coriolis_type",coriolis_type_string);
448 if ( amrex::toLower(coriolis_type_string) == "custom") {
449 amrex::Warning("Coriolis initialization from prob.cpp is now called 'analytic'. 'custom' will be deprecated");
451 } else if ( amrex::toLower(coriolis_type_string) == "analytic") {
453 } else if ((amrex::toLower(coriolis_type_string) == "beta_plane") ||
454 (amrex::toLower(coriolis_type_string) == "betaplane")) {
456 } else if ( (amrex::toLower(coriolis_type_string) == "netcdf")) {
458 } else if ( (amrex::toLower(coriolis_type_string) == "real")) {
459 amrex::Warning("Coriolis initialization from NetCDF is now called 'netcdf'. 'real' will be deprecated");
461 } else {
462 amrex::Abort("Don't know this coriolis_type");
463 }
464 }
465
466 static std::string smflux_type_string = "analytic";
467 int smflux_specified = pp.queryAdd("smflux_type",smflux_type_string);
468 if ( amrex::toLower(smflux_type_string) == "custom") {
469 amrex::Warning("Surface momentum flux initialization from prob.cpp is now called 'analytic'. 'custom' will be deprecated");
471 } else if ( amrex::toLower(smflux_type_string) == "analytic") {
473 } else if ( amrex::toLower(smflux_type_string) == "netcdf") {
475 } else {
476 amrex::Abort("Don't know this smflux_type");
477 }
478
479 static std::string wind_type_string = "analytic";
480 int wind_specified = pp.queryAdd("wind_type",wind_type_string);
481 if ( amrex::toLower(wind_type_string) == "custom") {
482 amrex::Warning("Surface wind initialization from prob.cpp is now called 'analytic'. 'custom' will be deprecated");
484 } else if ( amrex::toLower(wind_type_string) == "analytic") {
486 } else if ( amrex::toLower(wind_type_string) == "netcdf") {
488 } else {
489 amrex::Abort("Don't know this smflux_type");
490 }
491
492 if (wind_specified) {
493 const auto specified_wind_bulk_type = (wind_type == WindType::netcdf) ?
495 if (!uwind_type_specified) {
496 bulk_flux_type[BulkFlux::Uwind] = specified_wind_bulk_type;
497 }
498 if (!vwind_type_specified) {
499 bulk_flux_type[BulkFlux::Vwind] = specified_wind_bulk_type;
500 }
501 }
502
503 if (wind_specified && smflux_specified) {
504 amrex::Abort("Cannot specify both wind and surface momentum flux");
505 }
506
507 static std::string mask_type_string = "none";
508 // If initial condition type is netcdf, default to netcdf masks
509 if (ic_type == IC_Type::netcdf) {
510 mask_type_string = "netcdf";
511 }
512 pp.queryAdd("mask_type", mask_type_string);
513 if (amrex::toLower(mask_type_string) == "none") {
515 } else if (amrex::toLower(mask_type_string) == "analytic") {
517 } else if (amrex::toLower(mask_type_string) == "netcdf") {
519 } else {
520 amrex::Abort("Don't know this mask_type");
521 }
522
523 static std::string bottom_stress_type_string = "linear";
524 pp.queryAdd("bottom_stress_type", bottom_stress_type_string);
525 if (amrex::toLower(bottom_stress_type_string) == "linear") {
527 } else if (amrex::toLower(bottom_stress_type_string) == "quadratic") {
529 } else if (amrex::toLower(bottom_stress_type_string) == "logarithmic") {
531 } else {
532 amrex::Abort("Don't know this bottom_stress_type");
533 }
534
535 amrex::Real tnu2_salt = zero;
536 amrex::Real tnu2_temp = zero;
537 amrex::Real tnu2_scalar = zero;
538 static std::string horiz_mixing_type_string = "analytic";
539 pp.queryAdd("horizontal_mixing_type", horiz_mixing_type_string);
540 if (amrex::toLower(horiz_mixing_type_string) == "analytical" ||
541 amrex::toLower(horiz_mixing_type_string) == "analytic") {
543 } else if (amrex::toLower(horiz_mixing_type_string) == "constant") {
545 } else if (amrex::toLower(horiz_mixing_type_string) == "scaled_to_grid") {
547 } else {
548 amrex::Abort("Don't know this horizontal mixing type");
549 }
550 pp.queryAdd("visc2",visc2);
551 pp.queryAdd("tnu2_salt",tnu2_salt);
552 pp.queryAdd("tnu2_temp",tnu2_temp);
553 pp.queryAdd("tnu2_scalar",tnu2_scalar);
554
555 // For scaled_to_grid runs with AMR refinement: optionally scale the coefficients
556 // by the horizontal refinement ratio (linear in grid size).
557 static std::string scaled_to_grid_amr_scaling_string = "none";
558 pp.queryAdd("scaled_to_grid_amr_scaling", scaled_to_grid_amr_scaling_string);
559 if (amrex::toLower(scaled_to_grid_amr_scaling_string) == "none") {
561 } else if (amrex::toLower(scaled_to_grid_amr_scaling_string) == "linear") {
563 } else {
564 amrex::Abort("Don't know this scaled_to_grid_amr_scaling option");
565 }
566
567 tnu2.assign(ncons, tnu2_scalar);
568 if (ncons > Temp_comp) {
569 tnu2[Temp_comp] = tnu2_temp;
570 }
571 if (ncons > Salt_comp) {
572 tnu2[Salt_comp] = tnu2_salt;
573 }
574
575 static std::string harmonic_mixing_type_string = "s";
576 pp.queryAdd("harmonic_mixing_type", harmonic_mixing_type_string);
577 if (amrex::toLower(harmonic_mixing_type_string) == "s") {
579 } else if (amrex::toLower(harmonic_mixing_type_string) == "geopotential" ||
580 amrex::toLower(harmonic_mixing_type_string) == "geo") {
582 } else {
583 amrex::Abort("Don't know this harmonic_mixing_type");
584 }
585
586 pp.queryAdd("Akk_bak", Akk_bak);
587 pp.queryAdd("Akp_bak", Akp_bak);
588 static std::string vert_mixing_type_string = "analytic";
589 static std::string gls_stability_type_string = "Canuto_A";
590 pp.queryAdd("vertical_mixing_type", vert_mixing_type_string);
591 pp.queryAdd("gls_stability_type", gls_stability_type_string);
592 if (amrex::toLower(vert_mixing_type_string) == "analytical" ||
593 amrex::toLower(vert_mixing_type_string) == "analytic") {
595 } else if (amrex::toLower(vert_mixing_type_string) == "gls") {
597 if (amrex::toLower(gls_stability_type_string) == "canuto_a") {
599 }
600 else if (amrex::toLower(gls_stability_type_string) == "canuto_b") {
602 }
603 else if (amrex::toLower(gls_stability_type_string) == "galperin") {
605 }
606 else {
607 amrex::Abort("Don't know this GLS stability type");
608 }
609 } else {
610 amrex::Abort("Don't know this vertical mixing type");
611 }
612 // Read in GLS params
614 pp.queryAdd("gls_P", gls_p);
615 pp.queryAdd("gls_M", gls_m);
616 pp.queryAdd("gls_N", gls_n);
617 pp.queryAdd("gls_Kmin", gls_Kmin);
618 pp.queryAdd("gls_Pmin", gls_Pmin);
619
620 pp.queryAdd("gls_cmu0", gls_cmu0);
621 pp.queryAdd("gls_c1", gls_c1);
622 pp.queryAdd("gls_c2", gls_c2);
623 pp.queryAdd("gls_c3m", gls_c3m);
624 pp.queryAdd("gls_c3p", gls_c3p);
625 pp.queryAdd("gls_sigk", gls_sigk);
626 pp.queryAdd("gls_sigp", gls_sigp);
628 gls_Gh0 = amrex::Real(0.0329); // 0.0329 GOTM, 0.0673 Burchard
629 gls_Ghcri = amrex::Real(0.03);
630 gls_L1 = amrex::Real(0.107);
631 gls_L2 = amrex::Real(0.0032);
632 gls_L3 = amrex::Real(0.0864);
633 gls_L4 = amrex::Real(0.12);
634 gls_L5 = amrex::Real(11.9);
635 gls_L6 = amrex::Real(0.4);
636 gls_L7 = zero;
637 gls_L8 = amrex::Real(0.48);
639 gls_Gh0 = amrex::Real(0.0444); // 0.044 GOTM, 0.0673 Burchard
640 gls_Ghcri = amrex::Real(0.0414);
641 gls_L1 = amrex::Real(0.127);
642 gls_L2 = amrex::Real(0.00336);
643 gls_L3 = amrex::Real(0.0906);
644 gls_L4 = amrex::Real(0.101);
645 gls_L5 = amrex::Real(11.2);
646 gls_L6 = amrex::Real(0.4);
647 gls_L7 = zero;
648 gls_L8 = amrex::Real(0.318);
649 } else {
650 gls_Gh0 = amrex::Real(0.028);
651 gls_Ghcri = amrex::Real(0.02);
652 }
653 }
654
655 // Read and compute inverse nudging coeffs from inputs given in days,
656 // and store in a vector corresponding to BdyVars enum
657 amrex::Real tnudg = zero;
658 amrex::Real znudg = zero;
659 amrex::Real m2nudg = zero;
660 amrex::Real m3nudg = zero;
661 pp.queryAdd("tnudg",tnudg);
662 pp.queryAdd("znudg",znudg);
663 pp.queryAdd("m2nudg",m2nudg);
664 pp.queryAdd("m3nudg",m3nudg);
665 pp.queryAdd("obcfac",obcfac);
666
668 nudg_coeff[BdyVars::u ] = (m3nudg > zero) ? one / (m3nudg * amrex::Real(86400.0)) : zero;//BdyVars::u
669 nudg_coeff[BdyVars::v ] = (m3nudg > zero) ? one / (m3nudg * amrex::Real(86400.0)) : zero;//BdyVars::v
670 nudg_coeff[BdyVars::t ] = ( tnudg > zero) ? one / ( tnudg * amrex::Real(86400.0)) : zero;//BdyVars::t
671 nudg_coeff[BdyVars::s ] = ( tnudg > zero) ? one / ( tnudg * amrex::Real(86400.0)) : zero;//BdyVars::s
672 nudg_coeff[BdyVars::ubar ] = (m2nudg > zero) ? one / (m2nudg * amrex::Real(86400.0)) : zero;//BdyVars::ubar
673 nudg_coeff[BdyVars::vbar ] = (m2nudg > zero) ? one / (m2nudg * amrex::Real(86400.0)) : zero;//BdyVars::vbar
674 nudg_coeff[BdyVars::zeta ] = ( znudg > zero) ? one / ( znudg * amrex::Real(86400.0)) : zero;//BdyVars::zeta
675
676 pp.queryAdd("do_m3_clim_nudg", do_m3_clim_nudg);
677 pp.queryAdd("do_m2_clim_nudg", do_m2_clim_nudg);
678 pp.queryAdd("do_temp_clim_nudg", do_temp_clim_nudg);
679 pp.queryAdd("do_salt_clim_nudg", do_salt_clim_nudg);
680
682 do_any_clim_nudg = true;
683 }
684#ifndef REMORA_USE_NETCDF
685 if (do_any_clim_nudg) {
686 amrex::Abort("Climatology nudging requires building with NetCDF");
687 }
688#endif
689 }
690
691 void display()
692 {
693 amrex::Print() << "SOLVER CHOICE: " << std::endl;
694 amrex::Print() << "use_salt : " << use_salt << std::endl;
695 amrex::Print() << "use_coriolis : " << use_coriolis << std::endl;
696 amrex::Print() << "use_prestep : " << use_prestep << std::endl;
697 amrex::Print() << "use_uv3dmix : " << use_uv3dmix << std::endl;
698 amrex::Print() << "use_barotropic : " << use_barotropic << std::endl;
699 amrex::Print() << "flat_bathymetry : " << flat_bathymetry << std::endl;
700 amrex::Print() << "spatial_order : " << spatial_order << std::endl;
701
702 if (ic_type == IC_Type::analytic) {
703 amrex::Print() << "Using analytic initial onditions" << std::endl;
704 }
705 else if (ic_type == IC_Type::netcdf) {
706 amrex::Print() << "Using NetCDF initial conditions" << std::endl;
707 }
708
710 amrex::Print() << "Horizontal advection scheme for tracers: " << "Centered 4" << std::endl;
711 }
713 amrex::Print() << "Horizontal advection scheme for tracers: " << "Upstream 3" << std::endl;
714 }
715 else {
716 amrex::Error("Invalid horizontal advection scheme for tracers.");
717 }
718
720 amrex::Print() << "Horizontal advection scheme for momenta: " << "Centered 2" << std::endl;
721 }
723 amrex::Print() << "Horizontal advection scheme for momenta: " << "Upstream 3" << std::endl;
724 }
725 else {
726 amrex::Error("Invalid horizontal advection scheme for momenta.");
727 }
728
730 amrex::Print() << "Using two-way coupling " << std::endl;
731 } else if (coupling_type == CouplingType::one_way) {
732 amrex::Print() << "Using one-way coupling " << std::endl;
733 }
734
735 if (use_coriolis) {
737 amrex::Print() << "Using analytic coriolis forcing " << std::endl;
738 } else if (coriolis_type == Cor_Type::beta_plane) {
739 amrex::Print() << "Using beta plane coriolis forcing " << std::endl;
740 } else if (coriolis_type == Cor_Type::netcdf) {
741 amrex::Print() << "Using coriolis forcing loaded from file " << std::endl;
742 }
743 }
744 }
745
746 // Default prefix
747 std::string pp_prefix {"remora"};
748
749 bool flat_bathymetry = false;
750
751 bool use_salt = true;
752
753 // Specify what additional physics/forcing modules we use
754 bool use_coriolis = false;
755
756 // Specify whether terms are used for debugging purposes
757 bool use_prestep = true;
758 bool use_uv3dmix = true;
759 bool use_baroclinic = true;
760 bool use_barotropic = true;
761
763
764 bool bulk_fluxes = false;
765 bool atm2ocn_flux_mode = false;
766
767 bool output_forcing = false;
768 bool do_temp_flux = false;
769 bool do_salt_flux = false;
770 bool longwave_down = false;
771
772 std::array<BulkForcingType, BulkFlux::NumTypes> bulk_flux_type {{
781 BulkForcingType::computed, // LWrad defaults to the internal longwave formula
782 BulkForcingType::computed // EminusP defaults to bulk evap-rain diagnostic
783 }};
784 bool longwave_is_net = false;
785 bool qair_is_percent = false;
786 std::string longwave_netcdf_varname = "lwrad";
787
788
789 bool do_rivers = false;
790 bool do_rivers_temp = true;
791 bool do_rivers_salt = true;
792 bool do_rivers_scalar = false;
793 amrex::Vector<int> do_rivers_cons;
794
795 bool init_l1ad_T = false;
796
797 bool init_ana_T = false;
798
799 bool init_l0int_T = true;
800
803
804 // Coupling options are "OneWay" or "TwoWay"
806
807 // IC and BC Type: "analytic" or "netcdf"
809
810 // Coriolis forcing type
812
813 // Surface momentum flux type
815
816 // Surface wind speed type
818
819 // EOS type
821
822 // Bottom stress type
824
825 // Land/sea mask type
827
828 // Mixing type and parameters
834
835 // Type for grid scale (pm and pn)
837
838 // Stretching and depth parameters which may need to be read from inputs
839 amrex::Real theta_s = amrex::Real(3.0);
840 amrex::Real theta_b = zero;
841 amrex::Real tcline = amrex::Real(150.0);
842
843 // Linear drag coefficient [m/s]
844 amrex::Real rdrag = amrex::Real(3e-4);
845 // Quadratic drag coefficient [dimensionless]
846 amrex::Real rdrag2 = amrex::Real(3e-3);
847
848 // Momentum stress scales [m]
849 amrex::Real Zob = amrex::Real(2e-2);
850 amrex::Real Zos = amrex::Real(2e-2);
851
852 amrex::Real Cdb_max = amrex::Real(0.5);
853 amrex::Real Cdb_min = amrex::Real(1e-6);
854
855 // Linear equation of state parameters
856 amrex::Real R0 = amrex::Real(1028); // background density value (Kg/m3) used in Linear Equation of State
857 amrex::Real S0 = amrex::Real(35.0); // background salinity (nondimensional) constant
858 amrex::Real T0 = amrex::Real(5.0); // background potential temperature (Celsius) constant
859 amrex::Real Tcoef = amrex::Real(1.7e-4); // linear equation of state parameter (1/Celsius)
860 amrex::Real Scoef = zero; // linear equation of state parameter (nondimensional)
861 amrex::Real rho0 = amrex::Real(1025.0); // Mean density (Kg/m3) used when Boussinesq approx is inferred
862
863 // Coriolis forcing
864 amrex::Real coriolis_f0 = zero; // f-plane constant (1/s)
865 amrex::Real coriolis_beta = zero; // beta-plane constant (1/s/m)
866
867 // Air pressure
868 amrex::Real Pair = amrex::Real(1013.48);
869 // Air temperature
870 amrex::Real Tair = amrex::Real(23.567);
871 // Relative humidity (air)
872 amrex::Real Hair = amrex::Real(0.776);
873 // Cloud cover fraction (0=clear sky, 1=overcast)
874 amrex::Real cloud = zero;
875 // Precipitation rate (kg/m2/s)
876 amrex::Real rain = zero;
877 // Height (m) of atmospheric measurements for Bulk fluxes parametrization
878 amrex::Real blk_ZQ = amrex::Real(10.0); // air humidity
879 amrex::Real blk_ZT = amrex::Real(10.0); // air temperature
880 amrex::Real blk_ZW = amrex::Real(10.0); // winds
881
882 bool eminusp = false;
884
885 // Surface radiation flux
886 amrex::Real srflux = zero;
887 // Surface wind speed
888 amrex::Real Uwind = zero;
889 amrex::Real Vwind = zero;
890 // External longwave radiation flux
891 amrex::Real longwave_rad = zero;
892 // Prescribed evaporation minus precipitation
893 amrex::Real EminusP = zero;
894
895 // Spatial discretization
897
898 // Horizontal mixing parameters
899 amrex::Real visc2 = zero;
900 amrex::Vector<amrex::Real> tnu2;
901
902 // GLS params
903 amrex::Real gls_p = amrex::Real(3.0);
904 amrex::Real gls_m = amrex::Real(1.5);
905 amrex::Real gls_n = amrex::Real(-1.0);
906 amrex::Real gls_Kmin = amrex::Real(7.6e-6);
907 amrex::Real gls_Pmin = amrex::Real(1.0e-12);
908
909 amrex::Real gls_cmu0 = amrex::Real(0.5477);
910 amrex::Real gls_c1 = amrex::Real(1.44);
911 amrex::Real gls_c2 = amrex::Real(1.92);
912 amrex::Real gls_c3m = amrex::Real(-0.4);
913 amrex::Real gls_c3p = one;
914 amrex::Real gls_sigk = one;
915 amrex::Real gls_sigp = amrex::Real(1.3);
916
917 // Turbulence closure
918 amrex::Real Akk_bak = amrex::Real(5.0e-6);
919 amrex::Real Akp_bak = amrex::Real(5.0e-6);
920 amrex::Real Akv_bak = amrex::Real(5.0e-6);
921 amrex::Real Akt_bak = amrex::Real(1.0e-6); // Note: this is a vector with one component per tracer in ROMS
922
923 // Params for stability functions.
924 amrex::Real gls_Gh0;
925 amrex::Real gls_Ghcri;
926 amrex::Real gls_Ghmin = amrex::Real(-0.28);
927 amrex::Real gls_E2 = amrex::Real(1.33);
928 // Params only for Canuto stability
929 amrex::Real gls_L1;
930 amrex::Real gls_L2;
931 amrex::Real gls_L3;
932 amrex::Real gls_L4;
933 amrex::Real gls_L5;
934 amrex::Real gls_L6;
935 amrex::Real gls_L7;
936 amrex::Real gls_L8;
937
938 // Params for some GLS and also Mellor-Yamada
939 amrex::Real my_A1 = amrex::Real(0.92);
940 amrex::Real my_A2 = amrex::Real(0.74);
941 amrex::Real my_B1 = amrex::Real(16.6);
942 amrex::Real my_B2 = amrex::Real(10.1);
943 amrex::Real my_C1 = amrex::Real(0.08);
944 amrex::Real my_C2 = amrex::Real(0.7);
945 amrex::Real my_C3 = amrex::Real(0.2);
946 amrex::Real my_E1 = amrex::Real(1.8);
947 amrex::Real my_E2 = amrex::Real(1.33);
948 amrex::Real my_Gh0 = amrex::Real(0.0233);
949 amrex::Real my_Sq = amrex::Real(0.2);
950 amrex::Real my_dtfac = amrex::Real(0.05);
951 amrex::Real my_lmax = amrex::Real(0.53);
952 amrex::Real my_qmin = amrex::Real(1.0E-8);
953
954 // Nudging time scales in 1/s
955 amrex::Vector<amrex::Real> nudg_coeff;
956
957 // Factor between passive (outflow) and active (inflow) open boundary
958 // conditions.
959 amrex::Real obcfac = zero;
960
961 // Whether to do climatoogy nudging
962 bool do_m2_clim_nudg = false;
963 bool do_m3_clim_nudg = false;
964 bool do_temp_clim_nudg = false;
965 bool do_salt_clim_nudg = false;
966 bool do_any_clim_nudg = false;
967
969};
970
971#endif
constexpr amrex::Real one
constexpr amrex::Real zero
BottomStressType
bottom stress formulation
GridScaleType
initialization for pm and pn
HarmonicMixingType
harmonic mixing; which surfaces to calculate along
SMFluxType
surface momentum flux
AdvectionScheme
Horizontal advection schemes.
PlotfileType
plotfile format
HorizMixingType
horizontal viscosity/diffusion type
Coord
Coordinates.
MaskType
masks
ScaledToGridAMRScaling
How to scale scaled_to_grid coefficients on AMR levels.
Cor_Type
Coriolis factor.
WindType
surface wind
GLS_StabilityType
stability function for GLS
CouplingType
Type of coupling between levels in AMR.
VertMixingType
vertical mixing type
IC_Type
Type of initial condition type. Analytic reads from prob.cpp. Netcdf is from file.
EOSType
equation of state
#define Temp_comp
BulkForcingType
Source type for bulk-flux atmospheric forcing variables.
#define Tracer_comp
#define Salt_comp
@ Vwind
10-m meridional wind [m/s]
@ Pair
atmospheric pressure [mb]
@ Uwind
10-m zonal wind [m/s]
@ LWrad
longwave radiation [W/m^2]
@ Tair
air temperature [degC]
@ Qair
specific humidity or relative humidity [kg/kg or fraction]
@ Cloud
cloud fraction [0-1]
@ SWrad
downward shortwave radiation [W/m^2]
@ Rain
precipitation rate [kg/m^2/s]
@ EminusP
evaporation minus precipitation [m/s]
GLS_StabilityType gls_stability_type
HorizMixingType horiz_mixing_type
amrex::Real Cdb_min
amrex::Real Akv_bak
amrex::Real blk_ZT
amrex::Real cloud
amrex::Real coriolis_beta
amrex::Real gls_sigp
amrex::Vector< amrex::Real > nudg_coeff
amrex::Real my_E2
amrex::Real rdrag2
amrex::Real gls_m
amrex::Real my_lmax
amrex::Real my_Gh0
amrex::Real my_B2
amrex::Real my_A1
amrex::Vector< amrex::Real > tnu2
amrex::Real gls_sigk
amrex::Real gls_L3
amrex::Real coriolis_f0
std::string longwave_netcdf_varname
AdvectionScheme uv_Hadv_scheme
amrex::Vector< int > do_rivers_cons
amrex::Real Tcoef
amrex::Real gls_cmu0
amrex::Real Vwind
ScaledToGridAMRScaling scaled_to_grid_amr_scaling
std::string pp_prefix
amrex::Real gls_L6
amrex::Real gls_L2
AdvectionScheme tracer_Hadv_scheme
amrex::Real Akk_bak
amrex::Real Uwind
amrex::Real gls_L1
amrex::Real blk_ZW
amrex::Real my_E1
amrex::Real my_C3
amrex::Real gls_n
amrex::Real theta_b
amrex::Real theta_s
amrex::Real Akt_bak
static BulkForcingType parse_bulk_forcing_type(const std::string &type_string, const std::string &param_name, bool allow_computed)
amrex::Real visc2
amrex::Real EminusP
void init_params(int ncons)
read in and initialize parameters
amrex::Real tcline
amrex::Real gls_c3m
BottomStressType bottom_stress_type
amrex::Real my_A2
amrex::Real gls_Gh0
amrex::Real gls_Ghmin
amrex::Real my_C1
amrex::Real gls_c1
amrex::Real gls_L5
amrex::Real gls_L8
amrex::Real my_dtfac
amrex::Real longwave_rad
amrex::Real srflux
SMFluxType smflux_type
amrex::Real my_C2
amrex::Real gls_Kmin
amrex::Real rdrag
VertMixingType vert_mixing_type
amrex::Real gls_c3p
std::array< BulkForcingType, BulkFlux::NumTypes > bulk_flux_type
amrex::Real gls_p
amrex::Real gls_L4
amrex::Real my_B1
amrex::Real blk_ZQ
amrex::Real gls_L7
amrex::Real Cdb_max
GridScaleType grid_scale_type
amrex::Real my_qmin
amrex::Real gls_Ghcri
amrex::Real obcfac
amrex::Real gls_Pmin
amrex::Real gls_c2
amrex::Real Scoef
HarmonicMixingType harmonic_mixing_type
amrex::Real Akp_bak
amrex::Real my_Sq
CouplingType coupling_type
amrex::Real gls_E2