Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : // C POSIX includes 11 : #include <sys/stat.h> 12 : 13 : // MOOSE includes 14 : #include "FileOutput.h" 15 : #include "MooseApp.h" 16 : #include "FEProblem.h" 17 : 18 : #include <unistd.h> 19 : #include <ctime> 20 : 21 : #include "libmesh/utility.h" 22 : 23 : InputParameters 24 595979 : FileOutput::validParams() 25 : { 26 : // Create InputParameters object for this stand-alone object 27 595979 : InputParameters params = PetscOutput::validParams(); 28 595979 : params.addClassDescription("Base class for all file-based output"); 29 595979 : params.addParam<std::string>( 30 : "file_base", 31 : "The desired solution output name without an extension. If not provided, MOOSE sets it " 32 : "with Outputs/file_base when available. Otherwise, MOOSE uses input file name and this " 33 : "object name for a master input or uses master file_base, the subapp name and this object " 34 : "name for a subapp input to set it."); 35 595979 : params.addParam<std::string>("file_base_suffix", "Suffix to add to the file base"); 36 1787937 : params.addParam<bool>( 37 1191958 : "append_date", false, "When true the date and time are appended to the output filename."); 38 595979 : params.addParam<std::string>("append_date_format", 39 : "The format of the date/time to append, if not given UTC format " 40 : "is used (see http://www.cplusplus.com/reference/ctime/strftime)."); 41 : // Add the padding option and list it as 'Advanced' 42 1787937 : params.addParam<unsigned int>( 43 1191958 : "padding", 4, "The number of digits for the extension suffix (e.g., out.e-s002)"); 44 1787937 : params.addParam<std::vector<std::string>>("output_if_base_contains", 45 1191958 : std::vector<std::string>(), 46 : "If this is supplied then output will only be done in " 47 : "the case that the output base contains one of these " 48 : "strings. This is helpful in outputting only a subset " 49 : "of outputs when using MultiApps."); 50 595979 : params.addParamNamesToGroup( 51 : "file_base append_date append_date_format padding output_if_base_contains", 52 : "File name customization"); 53 : 54 595979 : return params; 55 0 : } 56 : 57 154259 : FileOutput::FileOutput(const InputParameters & parameters) 58 : : PetscOutput(parameters), 59 154251 : _file_num(declareRecoverableData<unsigned int>("file_num", 0)), 60 154251 : _padding(getParam<unsigned int>("padding")), 61 308510 : _output_if_base_contains(getParam<std::vector<std::string>>("output_if_base_contains")) 62 : { 63 : // If restarting reset the file number 64 154251 : if (_app.isRestarting()) 65 1267 : _file_num = 0; 66 : 67 154251 : if (isParamValid("file_base")) 68 : { 69 : // Check that we are the only process or not a subapp 70 42236 : if (!_app.isUltimateMaster()) 71 64 : if (_app.multiAppNumber() > 0) 72 4 : mooseError("The parameter 'file_base' may not be specified for a child app when the " 73 : "MultiApp has multiple instances of the child app, since all instances would " 74 : "use the same file base and thus write to the same file."); 75 42232 : setFileBaseInternal(getParam<std::string>("file_base")); 76 : } 77 154247 : } 78 : 79 : bool 80 3262320 : FileOutput::shouldOutput() 81 : { 82 3262320 : if (!checkFilename()) 83 0 : return false; 84 3262320 : return Output::shouldOutput(); 85 : } 86 : 87 : bool 88 11321241 : FileOutput::checkFilename() 89 : { 90 : // Return true if 'output_if_base_contains' is not utilized 91 11321241 : if (_output_if_base_contains.empty()) 92 11320281 : return true; 93 : 94 : // Assumed output is false 95 960 : bool output = false; 96 : 97 : // Loop through each string in the list 98 2160 : for (const auto & search_string : _output_if_base_contains) 99 : { 100 : // Search for the string in the file base, if found set the output to true and break the loop 101 1680 : if (_file_base.find(search_string) != std::string::npos) 102 : { 103 480 : output = true; 104 480 : break; 105 : } 106 : } 107 : 108 : // Return the value 109 960 : return output; 110 : } 111 : 112 : std::string 113 173 : FileOutput::filename() 114 : { 115 173 : return _file_base; 116 : } 117 : 118 : void 119 151476 : FileOutput::setFileBase(const std::string & file_base) 120 : { 121 151476 : if (!isParamValid("file_base")) 122 109704 : setFileBaseInternal(file_base); 123 151476 : } 124 : 125 : void 126 151936 : FileOutput::setFileBaseInternal(const std::string & file_base) 127 : { 128 151936 : _file_base = file_base; 129 : 130 151936 : if (isParamValid("file_base_suffix")) 131 12 : _file_base += "_" + getParam<std::string>("file_base_suffix"); 132 : 133 : // Append the date/time 134 151936 : if (getParam<bool>("append_date")) 135 : { 136 30 : std::string format; 137 30 : if (isParamValid("append_date_format")) 138 10 : format = getParam<std::string>("append_date_format"); 139 : else 140 20 : format = "%Y-%m-%dT%T%z"; 141 : 142 : // Get the current time 143 : std::time_t now; 144 30 : ::time(&now); // need :: to avoid confusion with time() method of Output class 145 : 146 : // Format the time 147 : char buffer[80]; 148 30 : strftime(buffer, 80, format.c_str(), localtime(&now)); 149 30 : _file_base += "_"; 150 30 : _file_base += buffer; 151 30 : } 152 : 153 : // Check the file directory of file_base and create if needed 154 151936 : std::filesystem::path directory_base = _file_base; 155 151936 : directory_base.remove_filename(); 156 151936 : if (directory_base.empty()) 157 151730 : directory_base = "."; 158 : // ensure relative path 159 151936 : directory_base = std::filesystem::relative(std::filesystem::absolute(directory_base)); 160 : 161 151936 : std::filesystem::path possible_dir_to_make; 162 303950 : for (auto it = directory_base.begin(); it != directory_base.end(); ++it) 163 : { 164 152014 : possible_dir_to_make = possible_dir_to_make / *it; 165 152014 : const auto dir_string = possible_dir_to_make.generic_string(); 166 152014 : if (_app.processor_id() == 0 && access(dir_string.c_str(), F_OK) == -1) 167 : // Directory does not exist. Create 168 32 : if (Utility::mkdir(dir_string.c_str()) == -1) 169 0 : mooseError("Could not create directory: " + dir_string + " for file base: " + _file_base); 170 152014 : } 171 151936 : } 172 : 173 : void 174 180 : FileOutput::setFileNumber(unsigned int num) 175 : { 176 180 : _file_num = num; 177 180 : } 178 : 179 : unsigned int 180 808 : FileOutput::getFileNumber() 181 : { 182 808 : return _file_num; 183 : }