ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
main.cpp File Reference
#include <iostream>
#include <AMReX.H>
#include <AMReX_BLProfiler.H>
#include <AMReX_ParallelDescriptor.H>
#include "ERF.H"
#include "ERF_InputsName.H"
Include dependency graph for main.cpp:

Functions

void add_par ()
 
int main (int argc, char *argv[])
 

Variables

std::string inputs_name
 

Function Documentation

◆ add_par()

void add_par ( )

Function to set the refine_grid_layout flags to (1,1,0) by default since the ERF default is different from the amrex default (1,1,1) Also set max_grid_size to very large since the only reason for chopping grids is if Nprocs > Ngrids

25  {
26  ParmParse pp("amr");
27  ParmParse pp_erf("erf");
28 
29  // Set the refine_grid_layout flags to (1,1,0) by default
30  pp.add("refine_grid_layout_x",1);
31  pp.add("refine_grid_layout_y",1);
32  pp.add("refine_grid_layout_z",0);
33 
34  // n_proper is the minimum number of coarse cells between coarse-fine boundaries
35  // between levels (ell and ell+1) and levels (ell-1 and ell). We want this to be
36  // greater than or equal to the stencil width (a function of spatial order) divided by
37  // ref_ratio (which can be 2,3 or 4). This ensures that fillpatch at level (ell)
38  // does not need to reach beyond level (ell-1). Here to be conservative we set this to 2
39  // (rather than the amrex default of 1).
40  pp.add("n_proper",2);
41 
42  int max_grid_size = 2048;
43  pp.queryAdd("max_grid_size",max_grid_size);
44 
45  // This will set the default value of blocking_factor to be 1, but will allow
46  // the user to override it in the inputs file or on command line
47  int blocking_factor = 1;
48  pp.queryAdd("blocking_factor",blocking_factor);
49 
50  int n_error_buf = 0;
51  pp.queryAdd("n_error_buf",n_error_buf);
52 
53  amrex::Vector<int> legacy_n_cell;
54  amrex::Vector<int> erf_n_cell;
55  const bool has_legacy_n_cell = pp.queryarr("n_cell", legacy_n_cell);
56  const bool has_erf_n_cell = pp_erf.queryarr("n_cell", erf_n_cell);
57  if (has_erf_n_cell && has_legacy_n_cell) {
58  amrex::Abort("erf.n_cell and amr.n_cell are both specified. Please use only one!");
59  }
60  if (has_erf_n_cell) {
61  pp.addarr("n_cell", erf_n_cell);
62  }
63 
64  ParmParse pp_geometry("geometry");
65  amrex::Vector<amrex::Real> legacy_prob_lo;
66  amrex::Vector<amrex::Real> legacy_prob_hi;
67  amrex::Vector<amrex::Real> legacy_prob_extent;
68  amrex::Vector<int> legacy_is_periodic;
69  amrex::Vector<amrex::Real> erf_prob_lo;
70  amrex::Vector<amrex::Real> erf_prob_hi;
71  amrex::Vector<amrex::Real> erf_prob_extent;
72  amrex::Vector<int> erf_is_periodic;
73 
74  const bool has_legacy_prob_lo = pp_geometry.queryarr("prob_lo", legacy_prob_lo);
75  const bool has_legacy_prob_hi = pp_geometry.queryarr("prob_hi", legacy_prob_hi);
76  const bool has_legacy_prob_extent = pp_geometry.queryarr("prob_extent", legacy_prob_extent);
77  const bool has_legacy_is_periodic = pp_geometry.queryarr("is_periodic", legacy_is_periodic);
78 
79  const bool has_erf_prob_lo = pp_erf.queryarr("prob_lo", erf_prob_lo);
80  const bool has_erf_prob_hi = pp_erf.queryarr("prob_hi", erf_prob_hi);
81  const bool has_erf_prob_extent = pp_erf.queryarr("prob_extent", erf_prob_extent);
82  const bool has_erf_is_periodic = pp_erf.queryarr("is_periodic", erf_is_periodic);
83 
84  if (has_erf_prob_lo && has_legacy_prob_lo) {
85  amrex::Abort("erf.prob_lo and geometry.prob_lo are both specified. Please use only one!");
86  }
87  if ((has_erf_prob_hi || has_erf_prob_extent) && !has_erf_prob_lo) {
88  amrex::Abort("ERF prefixed geometry requires erf.prob_lo together with erf.prob_hi or erf.prob_extent.");
89  }
90  if (has_erf_is_periodic && has_legacy_is_periodic) {
91  amrex::Abort("erf.is_periodic and geometry.is_periodic are both specified. Please use only one!");
92  }
93  if (has_erf_prob_hi && has_legacy_prob_hi) {
94  amrex::Abort("erf.prob_hi and geometry.prob_hi are both specified. Please use only one!");
95  }
96  if (has_erf_prob_extent && has_legacy_prob_extent) {
97  amrex::Abort("erf.prob_extent and geometry.prob_extent are both specified. Please use only one!");
98  }
99  if (has_erf_prob_hi || has_erf_prob_extent) {
100  if (has_legacy_prob_hi || has_legacy_prob_extent) {
101  amrex::Abort("ERF prefixed geometry and legacy geometry.prob_hi/prob_extent are both specified. Please use only one form.");
102  }
103  }
104  if (has_erf_prob_hi && has_erf_prob_extent) {
105  amrex::Vector<amrex::Real> derived_prob_hi(erf_prob_extent.size(), 0.0);
106  for (int i = 0; i < static_cast<int>(erf_prob_extent.size()); ++i) {
107  derived_prob_hi[i] = (i < static_cast<int>(erf_prob_lo.size()) ? erf_prob_lo[i] : 0.0) + erf_prob_extent[i];
108  }
109  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
110  derived_prob_hi.size() == erf_prob_hi.size(),
111  "erf.prob_hi and erf.prob_extent have inconsistent lengths.");
112  for (int i = 0; i < static_cast<int>(erf_prob_hi.size()); ++i) {
113  if (derived_prob_hi[i] != erf_prob_hi[i]) {
114  amrex::Abort("erf.prob_hi and erf.prob_extent are both specified but inconsistent.");
115  }
116  }
117  }
118 
119  if (has_erf_prob_lo) {
120  pp_geometry.addarr("prob_lo", erf_prob_lo);
121  }
122  if (has_erf_prob_hi) {
123  pp_geometry.addarr("prob_hi", erf_prob_hi);
124  } else if (has_erf_prob_extent) {
125  amrex::Vector<amrex::Real> derived_prob_hi(erf_prob_extent.size(), 0.0);
126  for (int i = 0; i < static_cast<int>(erf_prob_extent.size()); ++i) {
127  derived_prob_hi[i] = (i < static_cast<int>(erf_prob_lo.size()) ? erf_prob_lo[i] : 0.0) + erf_prob_extent[i];
128  }
129  pp_geometry.addarr("prob_hi", derived_prob_hi);
130  }
131  if (has_erf_is_periodic) {
132  pp_geometry.addarr("is_periodic", erf_is_periodic);
133  }
134 }
ParmParse pp("prob")

Referenced by main().

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

◆ main()

int main ( int  argc,
char *  argv[] 
)

Main driver – creates the ERF object, calls ERF.InitData() and ERF.Evolve()

140 {
141 
142 auto finalize_mpi_and_return = [](int code) {
143 #ifdef AMREX_USE_MPI
144 #ifdef ERF_USE_WW3_COUPLING
145  amrex::MPMD::Finalize();
146 #else
147  MPI_Finalize();
148 #endif
149 #endif
150 return code;
151 };
152 
153 #if defined(AMREX_MPI_THREAD_MULTIPLE)
154  int requested = MPI_THREAD_MULTIPLE;
155  int provided = -1;
156  MPI_Init_thread(&argc, &argv, requested, &provided);
157 #elif defined(AMREX_USE_MPI)
158  MPI_Init(&argc, &argv);
159 #endif
160 
161  if (argc < 2) {
162  // Print usage and exit with error code if no input file was provided.
163  ERF::print_usage(MPI_COMM_WORLD, std::cout);
165  MPI_COMM_WORLD, "No input file provided. Exiting!!");
166  return 1;
167  }
168 
169  // Look for "-h" or "--help" flag and print usage
170  for (auto i = 1; i < argc; i++) {
171  const std::string param(argv[i]);
172  if ((param == "--help") || (param == "-h") || (param == "--usage")) {
173  ERF::print_banner(MPI_COMM_WORLD, std::cout);
174  ERF::print_usage(MPI_COMM_WORLD, std::cout);
175  return 0;
176  }
177  }
178 
179  if (argc >= 2) {
180  for (auto i = 1; i < argc; i++) {
181  if (std::string(argv[i]) == "--describe") {
182  ERF::writeBuildInfo(std::cout);
183  return finalize_mpi_and_return(0);
184  }
185  }
186  }
187 
188  if (!strchr(argv[1], '=') && !amrex::FileSystem::Exists(std::string(argv[1])))
189  {
190  // Print usage and exit with error code if we cannot find the input file
191  ERF::print_usage(MPI_COMM_WORLD, std::cout);
193  MPI_COMM_WORLD, "Input file does not exist = " +
194  std::string(argv[1]) + ". Exiting!!");
195  return finalize_mpi_and_return(1);
196  }
197 
198  // print_banner(MPI_COMM_WORLD, std::cout);
199  // Check to see if the command line contains --describe
200  if (argc >= 2) {
201  for (auto i = 1; i < argc; i++) {
202  if (std::string(argv[i]) == "--describe") {
203  ERF::writeBuildInfo(std::cout);
204  return 0;
205  }
206  }
207  }
208 #ifdef ERF_USE_WW3_COUPLING
209  MPI_Comm comm = amrex::MPMD::Initialize(argc, argv);
210  amrex::Initialize(argc,argv,true,comm,add_par);
211 #else
212  amrex::Initialize(argc,argv,true,MPI_COMM_WORLD,add_par);
213 #endif
214  CheckForDuplicateInputs(argv[1]);
215 
216 #ifdef ERF_USE_KOKKOS
217  // Initialize kokkos
218  if (!Kokkos::is_initialized()) {
219  Kokkos::initialize(Kokkos::InitializationSettings()
220  .set_device_id(amrex::Gpu::Device::deviceId()));
221  }
222 #endif
223 
224  // Save the inputs file name for later.
225  if (!strchr(argv[1], '=')) {
226  inputs_name = argv[1];
227  }
228 
229  // timer for profiling
230  BL_PROFILE_VAR("main()", pmain);
231 
232  // wallclock time
233  const double strt_total = amrex::second();
234 
235  {
236  // constructor - reads in parameters from inputs file
237  // - sizes multilevel arrays and data structures
238  ERF erf;
239 
240  // initialize AMR data
241  erf.InitData();
242 
243  // advance solution to final time
244  erf.Evolve();
245 
246  // wallclock time
247  double end_total = amrex::second() - strt_total;
248 
249  // print wallclock time
250  ParallelDescriptor::ReduceRealMax(end_total ,ParallelDescriptor::IOProcessorNumber());
251  if (erf.Verbose()) {
252  amrex::Print() << "\nTotal Time: " << end_total << '\n';
253  }
254  }
255 
256  // destroy timer for profiling
257  BL_PROFILE_VAR_STOP(pmain);
258 #ifdef ERF_USE_WW3_COUPLING
259  MPI_Barrier(MPI_COMM_WORLD);
260 #endif
261 
262 #ifdef ERF_USE_KOKKOS
263  Kokkos::finalize();
264 #endif
265 
266  amrex::Finalize();
267 #ifdef AMREX_USE_MPI
268 #ifdef ERF_USE_WW3_COUPLING
269  amrex::MPMD::Finalize();
270 #else
271  MPI_Finalize();
272 #endif
273 #endif
274 }
void CheckForDuplicateInputs(const std::string &inputs_file)
Definition: ERF_InputsName.H:26
void Evolve()
Definition: ERF.cpp:136
static void print_banner(MPI_Comm, std::ostream &)
Definition: ERF_ConsoleIO.cpp:60
void InitData()
Definition: ERF.cpp:512
static void print_error(MPI_Comm, const std::string &msg)
Definition: ERF_ConsoleIO.cpp:43
static void writeBuildInfo(std::ostream &os)
Definition: ERF_WriteJobInfo.cpp:175
static void print_usage(MPI_Comm, std::ostream &)
Definition: ERF_ConsoleIO.cpp:26
void add_par()
Definition: main.cpp:25
std::string inputs_name
Definition: main.cpp:15
Definition: ERF_InterpolationUtils.H:16
Here is the call graph for this function:

Variable Documentation

◆ inputs_name

std::string inputs_name

Referenced by main(), and ERF::writeJobInfo().