Chapter 16

The broad purpose of the FieldConvert utility is to read in data from a file, perform some operation on this data, and write the data resulting from this operation to an output file. To illustrate how it does this, let us consider a case in which the user wishes to calculate the wall shear stress on the boundary labelled "0", given a session file session.xml and field file field.fld, and write it to field file field_wss.fld at 10 equispaced points using the output-points option 1

1FieldConvert -n 10 -m wss:bnd=0 session.xml field.fld field_wss.fld

The first task is to determine how to proceed based on the user input on the command line. In this case, each command line input apart from -n 10 corresponds to a module. The program stores these inputs as a boost::program_options::variables_map object, in which each input is the key and its corresponding argument (if it has one) is the value. The key is a std::string, and the value is optional, and can be any type.

The names of process modules are specified using the flag--module or -m, and these are stored in the map using the key "module" and the value being whatever follows the flag, in this case the "wss:bnd=0". The file names, corresponding to input and output modules, are so-called hidden options, meaning they don’t require a flag. These are stored in the map using the key "input-file", with the value being a std::vector consisting of the filenames, in this case "session.xml", "field.fld", and "field_wss.fld". The output-points option is stored in the map using the key output-points and the value being 10.

Assuming the user did not specify the command line options help, modules-list, or modules-opt, the program proceeds with its main functionality and a FieldSharedPtr is constructed. The values in the map corresponding with the module and input-file keys are stored as a std::vector of std::strings called the module commands, with the values corresponding to input modules at the start, process modules in the middle, and output modules at the end. Note that the program assumes that all these files apart from the last are input files, unless specified by the prefix out on the command line:, e.g. out:file.fld.

The module commands are iterated over, and for each entry, the the module string is identified and stored with the module type in a ModuleKey. For input modules, the module string is identified using InputModule::GuessFormat(), or failing that, by taking the name of the file extension, as is done for output modules. For process modules, the module string is simply the name of the entry (up to the colon separator if there is one). The ModuleKey is used to create a ModuleSharedPtr using the factory by calling Module::GetModuleFactory().CreateInstance, passing the ModuleKey and the FieldSharedPtr as arguments. This ModuleSharedPtr is appended to a std::vector of ModuleSharedPtrs. For input modules, InputModule::AddFile is called with the module string and the input file name passed as arguments. The configuration options are then parsed and registered using Module::RegisterConfig(), with arguments being the option name and its value (if it is boolean, the argument is just the option name). For input and output modules, the option infile or outfile is passed, along with the input or output file name. To complete the loop, the Module::SetDefaults function is called. The process of constructing a module, registering the configuration options (as well as calling AddFile for InputModules), and setting the default configuration options for those that were not set is summarised as setting up the module. The processes involved in the set up of input, process, and output modules are shown in figure 16. In this case, instances of the InputXml, InputFld, ProcessWSS, and OutputFld classes are constructed. The configuration option name for InputXml and InputFld is the string infile and the values are the filenames session.xml and field.fld respectively. The option for ProcessWSS is bnd with value 0, and the option name for OutputFld is the string outfile with the value being the filename field_wss.fld. Then, a ModuleSharedPtr is created for the ProcessEquispacedOutput module if it is needed. 2 The CheckModules function (defined FieldConvert.cpp is called with the std::vector of ModuleSharedPtrs as argument in order to check the modules that have been set up are compatible. Finally, the RunModule function (defined in FieldConvert.cpp) is called with each ModuleSharedPtr as argument in order of priority, which essentially calls the Process function as for each module, operating on the various member variables of Field, with the map used to store the command line arguments passed to each. When using the nparts command line argument, the calling of RunModule is done in a loop over the number of partitions. On each iteration, Field::ClearField is called, and a new Comm object is generated called partComm using the current partition number, with the original saved as defComm. Field’s m_comm is switched to partComm when running InputXml or any output module, and kept as defComm otherwise.

A diagram of the process is shown in figure 16. It shows the order in which the modules are set up and run, and what member variables of Field each updates. The key for the diagrams in this section is shown in figure 16.


Figure 16.1 Setting up modules


Figure 16.2 A diagram showing how FieldConvert performs a task


Figure 16.3 Key for the diagrams in this section