FV3-JEDI
Utilities.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2018 UCAR
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  */
7 
8 #include <mpi.h>
9 #include <unistd.h>
10 
11 #include <fstream>
12 #include <iostream>
13 #include <string>
14 #include <vector>
15 
16 #include "eckit/config/Configuration.h"
17 #include "eckit/exception/Exceptions.h"
18 
19 #include "oops/mpi/mpi.h"
20 #include "oops/util/abor1_cpp.h"
21 #include "oops/util/Logger.h"
22 
24 
25 namespace eckit {
26  class Configuration;
27 }
28 
29 namespace fv3jedi {
30 
31 // -----------------------------------------------------------------------------
32 void stageFMSFiles(const eckit::Configuration & conf, const eckit::mpi::Comm & comm) {
33  // Get processor ID
34  int world_rank = oops::mpi::world().rank();
35 
36  if (world_rank == 0) {
37  // User provided input files for this geom/state/model etc
38  delete_file("input.nml");
39  if (conf.has("nml_file_mpp")) {
40  oops::Log::debug() << "Staging input.nml" << std::endl;
41  std::string nml_file = conf.getString("nml_file_mpp");
42  if (symlink(nml_file.c_str(), "./input.nml"))
43  ABORT("Unable to symlink input.nml");
44  } else {
45  ABORT("nml_file_mpp not in configuration");
46  }
47  }
48  // Nobody moves until files are in place
49  oops::mpi::world().barrier();
50 }
51 // -----------------------------------------------------------------------------
52 
53 void stageFv3Files(const eckit::Configuration &conf, const eckit::mpi::Comm & comm) {
54  // Get processor ID
55  int world_rank = oops::mpi::world().rank();
56 
57  // Only one processor needs to move the files
58  // When we use several backgrounds, this lines will have to change
59  if (world_rank == 0) {
60  // User provided input files for this geom/state/model etc
61  delete_file("input.nml");
62  if (conf.has("nml_file")) {
63  oops::Log::debug() << "Staging input.nml" << std::endl;
64  std::string nml_file = conf.getString("nml_file");
65 
66  // Create empty file
67  std::ifstream startNml(nml_file);
68  std::ofstream finalNml("./input.nml");
69 
70  std::string startStr("layout = $LAYOUTX,$LAYOUTY");
71  std::string finalStr("layout = 1,1");
72 
73  std::string line;
74  std::size_t len = startStr.length();
75  while (getline(startNml, line))
76  {
77  while (true)
78  {
79  size_t pos = line.find(startStr);
80  if (pos != std::string::npos)
81  line.replace(pos, len, finalStr);
82  else
83  break;
84  }
85 
86  finalNml << line << '\n';
87  }
88 
89  finalNml.close();
90 
91  // if (symlink(nml_file.c_str(), "./input.nml"))
92  // ABORT("Unable to symlink input.nml");
93  }
94 
95  // User may also be requesting the field_table to be staged
96  delete_file("field_table");
97  if (conf.has("trc_file")) {
98  oops::Log::debug() << "Staging field_table" << std::endl;
99  std::string trc_file = conf.getString("trc_file");
100  if (symlink(trc_file.c_str(), "./field_table"))
101  ABORT("Unable to symlink field_table");
102  }
103 
104  // User may also be requesting the tlm/adm nml file
105  delete_file("inputpert.nml");
106  if (conf.has("nml_file_pert")) {
107  oops::Log::debug() << "Staging inputpert.nml" << std::endl;
108  std::string nml_file_pert = conf.getString("nml_file_pert");
109  if (symlink(nml_file_pert.c_str(), "./inputpert.nml"))
110  ABORT("Unable to symlink inputpert.nml");
111  }
112 
113  // User may also want the INPUT directory linked (regional grid for example)
114  delete_file("INPUT");
115  if (conf.has("fv3_input_dir")) {
116  oops::Log::debug() << "Staging INPUT directory" << std::endl;
117  std::string fv3_input_dir = conf.getString("fv3_input_dir");
118  oops::Log::debug() << "INPUT/ --> " << fv3_input_dir << std::endl;
119  if (symlink(fv3_input_dir.c_str(), "./INPUT"))
120  ABORT("Unable to symlink INPUT");
121  }
122  }
123 
124  // Nobody moves until files are in place
125  oops::mpi::world().barrier();
126 }
127 
128 // -----------------------------------------------------------------------------
129 
130 void removeFv3Files(const eckit::mpi::Comm & comm) {
131  // Get processor ID
132  int world_rank = oops::mpi::world().rank();
133 
134  // No file deletion until everyone catches up
135  oops::mpi::world().barrier();
136 
137  // Only one processor needs to move the files
138  if (world_rank == 0) {
139  delete_file("input.nml");
140  delete_file("field_table");
141  delete_file("inputpert.nml");
142  }
143  // Nobody moves until files are deleted
144  oops::mpi::world().barrier();
145 }
146 
147 // -----------------------------------------------------------------------------
148 
149 void delete_file(const char *fileName)
150 {
151  std::ifstream infile(fileName);
152  if (infile.good()) {
153  oops::Log::debug() << "Removing: " << fileName << std::endl;
154  std::remove(fileName);
155  }
156 }
157 
158 // -------------------------------------------------------------------------------------------------
159 
160 void generateGeomFv3Conf(const eckit::Configuration & conf, const eckit::mpi::Comm & comm) {
161  // Trace
162  // -----
163  oops::Log::trace() << "generateGeomFv3Conf starting" << std::endl;
164 
165  // Barrier
166  // -------
167  oops::mpi::world().barrier();
168 
169  // Only root
170  // ---------
171  if (oops::mpi::world().rank() == 0) {
172  // Delete the file if it exists
173  // ----------------------------
174  delete_file("input.nml");
175 
176  // Parse config
177  // ------------
178  std::vector<std::string> layout = conf.getStringVector("layout", {"1", "1"});
179  std::vector<std::string> io_layout = conf.getStringVector("io_layout", {"1", "1"});
180  std::string npx = conf.getString("npx");
181  std::string npy = conf.getString("npy", npx);
182  std::string npz = conf.getString("npz");
183  std::string ntiles = conf.getString("ntiles", "6");
184 
185  // Vector of config
186  // ----------------
187  std::vector<std::string> inputnml;
188 
189  inputnml.push_back("&fv_core_nml\n");
190  inputnml.push_back("\tlayout = "+layout[0]+","+layout[1]+"\n");
191  inputnml.push_back("\tio_layout = "+io_layout[0]+","+io_layout[1]+"\n");
192  inputnml.push_back("\tnpx = "+npx+"\n");
193  inputnml.push_back("\tnpy = "+npy+"\n");
194  inputnml.push_back("\tnpz = "+npz+"\n");
195  inputnml.push_back("\tntiles = "+ntiles+"\n");
196 
197  // Parse config for optional fields
198  // --------------------------------
199  if (conf.has("regional")) {
200  bool regional = conf.getBool("regional");
201  if (regional) {
202  inputnml.push_back("\tregional = .T.\n");
203  }
204  }
205 
206  if (conf.has("nested")) {
207  bool nested = conf.getBool("nested");
208  if (nested) {
209  inputnml.push_back("\tnested = .T.\n");
210  }
211  }
212 
213  if (conf.has("do_schmidt")) {
214  bool do_schmidt = conf.getBool("do_schmidt");
215  if (do_schmidt) {
216  inputnml.push_back("\tdo_schmidt = .T.\n");
217  }
218  }
219 
220  if (conf.has("target_lat")) {
221  std::string target_lat = conf.getString("target_lat");
222  inputnml.push_back("\ttarget_lat = "+target_lat+"\n");
223  }
224 
225  if (conf.has("target_lon")) {
226  std::string target_lon = conf.getString("target_lon");
227  inputnml.push_back("\ttarget_lon = "+target_lon+"\n");
228  }
229 
230  if (conf.has("stretch_fac")) {
231  std::string stretch_fac = conf.getString("stretch_fac");
232  inputnml.push_back("\tstretch_fac = "+stretch_fac+"\n");
233  }
234 
235  if (conf.has("hydrostatic")) {
236  bool hydrostatic = conf.getBool("hydrostatic");
237  if (!hydrostatic) {
238  inputnml.push_back("\thydrostatic = .false.\n");
239  }
240  }
241 
242  if (conf.has("nwat")) {
243  std::string nwat = conf.getString("nwat");
244  inputnml.push_back("\tnwat = "+nwat+"\n");
245  }
246 
247  // End of section marker
248  // ---------------------
249  inputnml.push_back("/");
250 
251  // Write the config to the input.nml file
252  // --------------------------------------
253  std::string file = "input.nml";
254  std::ofstream out(file);
255  for (int km = 0; km < static_cast<int>(inputnml.size()); ++km) {
256  out << inputnml[km];
257  }
258  out.close();
259  }
260 
261  // Barrier
262  // -------
263  oops::mpi::world().barrier();
264 
265  // Trace
266  // -----
267  oops::Log::trace() << "generateGeomFv3Conf done" << std::endl;
268 }
269 
270 // -----------------------------------------------------------------------------
271 
272 } // namespace fv3jedi
Utilities.h
eckit
Definition: FieldsMetadata.h:25
fv3jedi::stageFMSFiles
void stageFMSFiles(const eckit::Configuration &conf, const eckit::mpi::Comm &comm)
Definition: Utilities.cc:32
fv3jedi::stageFv3Files
void stageFv3Files(const eckit::Configuration &conf, const eckit::mpi::Comm &comm)
Definition: Utilities.cc:53
fv3jedi
Configuration files should be formatted as e.g.
Definition: ErrorCovariance.cc:20
fv3jedi::generateGeomFv3Conf
void generateGeomFv3Conf(const eckit::Configuration &conf, const eckit::mpi::Comm &comm)
Definition: Utilities.cc:160
fv3jedi::removeFv3Files
void removeFv3Files(const eckit::mpi::Comm &comm)
Definition: Utilities.cc:130
fv3jedi::delete_file
void delete_file(const char *fileName)
Definition: Utilities.cc:149