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 622123 : FileOutput::validParams() 25 : { 26 : // Create InputParameters object for this stand-alone object 27 622123 : InputParameters params = PetscOutput::validParams(); 28 622123 : params.addClassDescription("Base class for all file-based output"); 29 622123 : 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 622123 : params.addParam<std::string>("file_base_suffix", "Suffix to add to the file base"); 36 1866369 : params.addParam<bool>( 37 1244246 : "append_date", false, "When true the date and time are appended to the output filename."); 38 622123 : 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 1866369 : params.addParam<unsigned int>( 43 1244246 : "padding", 4, "The number of digits for the extension suffix (e.g., out.e-s002)"); 44 1866369 : params.addParam<std::vector<std::string>>("output_if_base_contains", 45 1244246 : 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 622123 : params.addParamNamesToGroup( 51 : "file_base append_date append_date_format padding output_if_base_contains", 52 : "File name customization"); 53 : 54 622123 : return params; 55 0 : } 56 : 57 166599 : FileOutput::FileOutput(const InputParameters & parameters) 58 : : PetscOutput(parameters), 59 166591 : _file_num(declareRecoverableData<unsigned int>("file_num", 0)), 60 166591 : _padding(getParam<unsigned int>("padding")), 61 333190 : _output_if_base_contains(getParam<std::vector<std::string>>("output_if_base_contains")) 62 : { 63 : // If restarting reset the file number 64 166591 : if (_app.isRestarting()) 65 1377 : _file_num = 0; 66 : 67 166591 : if (isParamValid("file_base")) 68 : { 69 : // Check that we are the only process or not a subapp 70 45876 : if (!_app.isUltimateMaster()) 71 72 : 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 45872 : setFileBaseInternal(getParam<std::string>("file_base")); 76 : } 77 166587 : } 78 : 79 : bool 80 3583321 : FileOutput::shouldOutput() 81 : { 82 3583321 : if (!checkFilename()) 83 0 : return false; 84 3583321 : return Output::shouldOutput(); 85 : } 86 : 87 : bool 88 12438106 : FileOutput::checkFilename() 89 : { 90 : // Return true if 'output_if_base_contains' is not utilized 91 12438106 : if (_output_if_base_contains.empty()) 92 12436882 : return true; 93 : 94 : // Assumed output is false 95 1224 : bool output = false; 96 : 97 : // Loop through each string in the list 98 2754 : 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 2142 : if (_file_base.find(search_string) != std::string::npos) 102 : { 103 612 : output = true; 104 612 : break; 105 : } 106 : } 107 : 108 : // Return the value 109 1224 : return output; 110 : } 111 : 112 : std::string 113 280 : FileOutput::filename() 114 : { 115 280 : return _file_base; 116 : } 117 : 118 : void 119 163808 : FileOutput::setFileBase(const std::string & file_base) 120 : { 121 163808 : if (!isParamValid("file_base")) 122 118380 : setFileBaseInternal(file_base); 123 163808 : } 124 : 125 : void 126 164252 : FileOutput::setFileBaseInternal(const std::string & file_base) 127 : { 128 164252 : _file_base = file_base; 129 : 130 164252 : if (isParamValid("file_base_suffix")) 131 13 : _file_base += "_" + getParam<std::string>("file_base_suffix"); 132 : 133 : // Append the date/time 134 164252 : if (getParam<bool>("append_date")) 135 : { 136 33 : std::string format; 137 33 : if (isParamValid("append_date_format")) 138 11 : format = getParam<std::string>("append_date_format"); 139 : else 140 22 : format = "%Y-%m-%dT%T%z"; 141 : 142 : // Get the current time 143 : std::time_t now; 144 33 : ::time(&now); // need :: to avoid confusion with time() method of Output class 145 : 146 : // Format the time 147 : char buffer[80]; 148 33 : strftime(buffer, 80, format.c_str(), localtime(&now)); 149 33 : _file_base += "_"; 150 33 : _file_base += buffer; 151 33 : } 152 : 153 : // Check the file directory of file_base and create if needed 154 164252 : std::filesystem::path directory_base = _file_base; 155 164252 : directory_base.remove_filename(); 156 164252 : if (directory_base.empty()) 157 163924 : directory_base = "."; 158 : // ensure relative path 159 164252 : directory_base = std::filesystem::relative(std::filesystem::absolute(directory_base)); 160 : 161 164252 : std::filesystem::path possible_dir_to_make; 162 328603 : for (auto it = directory_base.begin(); it != directory_base.end(); ++it) 163 : { 164 164351 : possible_dir_to_make = possible_dir_to_make / *it; 165 164351 : const auto dir_string = possible_dir_to_make.generic_string(); 166 164351 : if (_app.processor_id() == 0 && access(dir_string.c_str(), F_OK) == -1) 167 : // Directory does not exist. Create 168 42 : if (Utility::mkdir(dir_string.c_str()) == -1) 169 0 : mooseError("Could not create directory: " + dir_string + " for file base: " + _file_base); 170 164351 : } 171 164252 : } 172 : 173 : void 174 194 : FileOutput::setFileNumber(unsigned int num) 175 : { 176 194 : _file_num = num; 177 194 : } 178 : 179 : unsigned int 180 1195 : FileOutput::getFileNumber() 181 : { 182 1195 : return _file_num; 183 : }