LCOV - code coverage report
Current view: top level - src/Util - Util.cpp (source / functions) Coverage Total Hit
Test: coverage_merged.info Lines: 59.7 % 201 120
Test Date: 2025-08-05 17:56:56 Functions: 62.5 % 16 10

            Line data    Source code
       1              : #include "Util.H"
       2              : #include "Color.H"
       3              : 
       4              : #include <chrono>
       5              : #include <cstdlib>
       6              : #include <filesystem>
       7              : #include <stdexcept>
       8              : 
       9              : #include "AMReX_ParallelDescriptor.H"
      10              : #include "AMReX_Utility.H"
      11              : 
      12              : #include "IO/ParmParse.H"
      13              : #include "IO/WriteMetaData.H"
      14              : #include "IO/FileNameParse.H"
      15              : #include "Color.H"
      16              : #include "Numeric/Stencil.H"
      17              : 
      18              : namespace Util
      19              : {
      20              : 
      21              : std::string filename = "";
      22              : std::string globalprefix = "";
      23              : std::pair<std::string,std::string> file_overwrite;
      24              : bool initialized = false;
      25              : bool finalized = false;
      26              : 
      27          115 : std::string GetFileName()
      28              : {
      29          115 :     if (filename == "")
      30              :     {
      31           39 :         IO::ParmParse pp;
      32           39 :         IO::ParmParse pp_amr("amr");
      33              : 
      34          117 :         if (pp_amr.contains("plot_file") && pp.contains("plot_file"))
      35            0 :             Util::Abort("plot_file specified in too many locations");
      36           78 :         else if (pp_amr.contains("plot_file"))
      37              :         {
      38            0 :             if (amrex::ParallelDescriptor::IOProcessor())
      39              :                 amrex::Warning("amr.plot_file will be depricated; use plot_file instead");
      40            0 :             pp_amr.query("plot_file", filename);
      41              : 
      42              :         }
      43           78 :         else if (pp.contains("plot_file"))
      44              :         {
      45           39 :             pp_query("plot_file", filename); // Name of directory containing all output data
      46              :         }
      47           39 :         IO::FileNameParse(filename);
      48              :         // else
      49              :         // if (amrex::ParallelDescriptor::IOProcessor())
      50              :         // Util::Abort("No plot file specified! (Specify plot_file = \"plot_file_name\" in input file");
      51           39 :     }
      52          115 :     return filename;
      53              : }
      54            2 : void CopyFileToOutputDir(std::string a_path, bool fullpath, std::string prefix)
      55              : {
      56              :     try
      57              :     {
      58            2 :         if (filename == "")
      59            0 :             Util::Exception(INFO,"Cannot back up files yet because the output directory has not been specified");
      60              : 
      61            2 :         std::string basefilename = std::filesystem::path(a_path).filename();
      62            2 :         std::string absolutepath = std::filesystem::absolute(std::filesystem::path(a_path)).string();
      63            2 :         std::string abspathfilename = absolutepath;
      64            2 :         std::replace(abspathfilename.begin(),abspathfilename.end(),'/','_');
      65            2 :         if (prefix != "")
      66              :         {
      67            2 :             abspathfilename = prefix + "__" + abspathfilename;
      68            2 :             basefilename    = prefix + "__" + abspathfilename;
      69              :         }
      70              : 
      71            2 :         if (amrex::ParallelDescriptor::IOProcessor())
      72              :         {
      73            2 :             std::string destinationpath;
      74            2 :             if (fullpath) destinationpath = filename+"/"+abspathfilename;
      75            0 :             else          destinationpath = filename+"/"+basefilename;
      76              : 
      77              :             // Copy the file where the file name is the absolute path, with / replaced with _
      78            2 :             if (std::filesystem::exists(destinationpath))
      79            0 :                 Util::Exception(INFO,"Trying to copy ",destinationpath," but it already exists.");
      80            2 :             std::filesystem::copy_file(a_path,destinationpath);
      81            2 :         }
      82            2 :     }
      83            0 :     catch (std::filesystem::filesystem_error const& ex)
      84              :     {
      85            0 :         Util::Exception(INFO,
      86              :                         "file system error: \n",
      87            0 :                         "     what():  " , ex.what()  , '\n',
      88            0 :                         "     path1(): " , ex.path1() , '\n',
      89            0 :                         "     path2(): " , ex.path2() , '\n',
      90            0 :                         "     code().value():    " , ex.code().value() , '\n',
      91            0 :                         "     code().message():  " , ex.code().message() , '\n',
      92            0 :                         "     code().category(): " , ex.code().category().name());
      93            0 :     }
      94            2 : }
      95              : 
      96            0 : std::pair<std::string,std::string> GetOverwrittenFile()
      97              : {
      98            0 :     return file_overwrite;
      99              : }
     100              : 
     101            0 : void SignalHandler(int s)
     102              : {
     103            0 :     if (amrex::ParallelDescriptor::IOProcessor())
     104              :     {
     105            0 :         std::string filename = GetFileName();
     106            0 :         IO::Status status = IO::Status::Running;
     107            0 :         if (s == SIGSEGV) status = IO::Status::Segfault;
     108            0 :         else if (s == SIGINT) status = IO::Status::Interrupt;
     109            0 :         if (s == SIGABRT) status = IO::Status::Abort;
     110            0 :         if (filename != "")
     111            0 :             IO::WriteMetaData(filename,status);
     112            0 :     }
     113              : 
     114              : #ifdef MEME
     115              :     IO::ParmParse pp;
     116              :     if (!pp.contains("nomeme"))
     117              :     {
     118              :         time_t timer; time(&timer);
     119              :         std::stringstream cmd;
     120              :         cmd << "xdg-open " << BUILD_DIR << "/src/Util/Meme/cat0" << (1+((int)timer)%6) << ".gif &";
     121              :         std::system(cmd.str().c_str());
     122              :         std::cout << Color::Bold << Color::FG::Red << "PROGRAM FAILED!" << Color::Reset << " (Compile without -DMEME, or set nomeme = 1 in the input file to disable this!)";
     123              :     }
     124              : #endif 
     125              : 
     126            0 :     amrex::BLBackTrace::handler(s);
     127            0 : }
     128              : 
     129              : 
     130            0 : void Initialize ()
     131              : {
     132            0 :     int argc = 0;
     133            0 :     char **argv = nullptr;
     134            0 :     Initialize(argc,argv);
     135            0 :     initialized = true;
     136            0 : }
     137           39 : void Initialize (int argc, char* argv[])
     138              : {
     139           39 :     srand (time(NULL));
     140              : 
     141           39 :     amrex::Initialize(argc, argv);
     142              : 
     143           39 :     IO::ParmParse pp_amrex("amrex");
     144           39 :     pp_amrex.add("throw_exception",1);
     145              :     //amrex.throw_exception=1
     146              : 
     147           39 :     signal(SIGSEGV, Util::SignalHandler);
     148           39 :     signal(SIGINT,  Util::SignalHandler);
     149           39 :     signal(SIGABRT, Util::SignalHandler);
     150              : 
     151           39 :     std::string filename = GetFileName();
     152              : 
     153           39 :     if (amrex::ParallelDescriptor::IOProcessor() && filename != "")
     154              :     {
     155           39 :         file_overwrite = Util::CreateCleanDirectory(filename, false);
     156           39 :         IO::WriteMetaData(filename);
     157              :     }
     158              : 
     159           39 :     IO::ParmParse pp;
     160           39 :     std::string length, time;
     161              :     // Set the system length unit
     162           78 :     pp.query_default("system.length",length,"m");
     163              :     // Set the system time unit
     164           39 :     pp.query_default("system.time",time,"s");
     165              :     try
     166              :     {
     167           39 :         Unit::setLengthUnit(length);
     168           39 :         Unit::setTimeUnit(time);
     169              :     }
     170            0 :     catch (std::runtime_error &e)
     171              :     {
     172            0 :         Util::Exception(INFO, "Error in setting system units: ", e.what());
     173            0 :     }
     174              : 
     175              :     //
     176              :     // This is some logic to unit-ize the geometry.prob_lo, geometry.prob_hi input variables/
     177              :     // We also do some checking to make sure the geometry is valid.
     178              :     //
     179              :     // Note that here, unlike most places, we actually **replace and overwrite** the 
     180              :     // geom.prob_* variables, since they are read deep inside amrex infrastructure.
     181              :     //
     182              :     {
     183           78 :         IO::ParmParse pp("geometry");
     184              :         
     185           78 :         if (pp.contains("prob_lo"))
     186              :         {
     187           37 :             std::vector<Set::Scalar> prob_lo, prob_hi;
     188              :             // Location of the lower+left+bottom corner
     189           74 :             pp.queryarr("prob_lo", prob_lo, Unit::Length());
     190              :             // Location of the upper_right_top corner
     191           74 :             pp.queryarr("prob_hi", prob_hi, Unit::Length());
     192           37 :             pp.remove("prob_lo");
     193           37 :             pp.remove("prob_hi");
     194              : 
     195          259 :             Util::Assert(   INFO,TEST(prob_lo[0] < prob_hi[0]),
     196           37 :                             "Invalid domain specified: ", prob_lo[0], " < x < ", prob_hi[0], " is incorrect.");
     197          259 :             Util::Assert(   INFO,TEST(prob_lo[1] < prob_hi[1]),
     198           37 :                             "Invalid domain specified: ", prob_lo[0], " < y < ", prob_hi[0], " is incorrect.");
     199              : #if AMREX_SPACEDIM>2
     200           21 :             Util::Assert(   INFO,TEST(prob_lo[2] < prob_hi[2]),
     201            3 :                             "Invalid domain specified: ", prob_lo[0], " < z < ", prob_hi[0], " is incorrect.");
     202              : #endif
     203              : 
     204          148 :             Util::DebugMessage(INFO,"Domain lower left corner: ", Set::Vector(prob_lo.data()).transpose());
     205          148 :             Util::DebugMessage(INFO,"Domain upper right corenr: ", Set::Vector(prob_hi.data()).transpose());
     206              : 
     207           37 :             pp.addarr("prob_lo",prob_lo);
     208           37 :             pp.addarr("prob_hi",prob_hi);
     209           37 :         }
     210           39 :     }
     211           39 : }
     212              : 
     213           39 : void Finalize()
     214              : {
     215           39 :     std::string filename = GetFileName();
     216           39 :     if (filename != "")
     217           39 :         IO::WriteMetaData(filename,IO::Status::Complete);
     218           39 :     amrex::Finalize();
     219           39 :     finalized = true;
     220           39 : }
     221              : 
     222              : 
     223              : 
     224              : void
     225            0 : Abort (const char * msg) { Terminate(msg, SIGABRT, true); }
     226              : 
     227              : void
     228            0 : Terminate(const char * /* msg */, int signal, bool /*backtrace*/)
     229              : {
     230            0 :     SignalHandler(signal);
     231            0 : }
     232              : 
     233              : std::pair<std::string,std::string>
     234           39 : CreateCleanDirectory (const std::string &path, bool callbarrier)
     235              : {
     236           39 :     std::pair<std::string,std::string> ret("","");
     237              : 
     238           39 :     if(amrex::ParallelDescriptor::IOProcessor()) {
     239           39 :         if(amrex::FileExists(path)) {
     240            0 :             std::time_t t = std::time(0);
     241            0 :             std::tm * now = std::localtime(&t);
     242            0 :             int year = now->tm_year+1900;
     243            0 :             int month = now->tm_mon+1;
     244            0 :             int day = now->tm_mday;
     245            0 :             int hour = now->tm_hour;
     246            0 :             int minute = now->tm_min;
     247            0 :             int second = now->tm_sec;
     248              : 
     249            0 :             std::stringstream ss;
     250              :             ss << year
     251            0 :                 << std::setfill('0') << std::setw(2) << month
     252            0 :                 << std::setfill('0') << std::setw(2) << day
     253            0 :                 << std::setfill('0') << std::setw(2) << hour
     254            0 :                 << std::setfill('0') << std::setw(2) << minute
     255            0 :                 << std::setfill('0') << std::setw(2) << second;
     256              : 
     257            0 :             std::string newoldname(path + ".old." + ss.str());
     258            0 :             if (amrex::system::verbose) {
     259            0 :                 amrex::Print() << "Util::CreateCleanDirectory():  " << path
     260            0 :                             << " exists.  Renaming to:  " << newoldname << std::endl;
     261              :             }
     262            0 :             std::rename(path.c_str(), newoldname.c_str());
     263            0 :             ret.first = path;
     264            0 :             ret.second = newoldname;
     265            0 :         }
     266           39 :         if( ! amrex::UtilCreateDirectory(path, 0755)) {
     267            0 :             amrex::CreateDirectoryFailed(path);
     268              :         }
     269              :     }
     270           39 :     if(callbarrier) {
     271              :         // Force other processors to wait until directory is built.
     272            0 :         amrex::ParallelDescriptor::Barrier("amrex::UtilCreateCleanDirectory");
     273              :     }
     274           39 :     return ret;
     275            0 : }
     276              : 
     277              : 
     278              : namespace Test
     279              : {
     280           32 : int Message(std::string testname)
     281              : {
     282           32 :     if (amrex::ParallelDescriptor::IOProcessor())
     283           32 :         std::cout << std::left
     284           32 :             << Color::FG::White << Color::Bold << testname << Color::Reset << std::endl;
     285           32 :     return 0;
     286              : }
     287            0 : int Message(std::string testname, int failed)
     288              : {
     289            0 :     if (amrex::ParallelDescriptor::IOProcessor())
     290              :     {
     291              :         winsize w;
     292            0 :         ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
     293            0 :         std::stringstream ss;
     294            0 :         if (!failed)
     295            0 :             ss << "[" << Color::FG::Green << Color::Bold << "PASS" << Color::Reset << "]";
     296              :         else
     297            0 :             ss << "[" << Color::FG::Red << Color::Bold << "FAIL" << Color::Reset << "]";
     298              : 
     299            0 :         int terminalwidth = 80; //std::min(w.ws_col,(short unsigned int) 100);
     300              : 
     301            0 :         std::cout << std::left
     302              :             << testname 
     303            0 :             << std::setw(terminalwidth - testname.size() + ss.str().size() - 6)  << std::right << std::setfill('.') << ss.str() << std::endl;
     304            0 :     }
     305            0 :     return failed;
     306              : }
     307          134 : int SubMessage(std::string testname, int failed)
     308              : {
     309          134 :     if (amrex::ParallelDescriptor::IOProcessor())
     310              :     {
     311              :         winsize w;
     312          134 :         ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
     313          134 :         std::stringstream ss;
     314          134 :         if (!failed)
     315          134 :             ss << "[" << Color::FG::LightGreen << Color::Bold << "PASS" << Color::Reset << "]";
     316              :         else
     317            0 :             ss << "[" << Color::FG::Red << Color::Bold << "FAIL" << Color::Reset << "]";
     318              : 
     319          134 :         int terminalwidth = 80; 
     320              : 
     321          134 :         std::cout << std::left
     322              :             << "  ├ "
     323              :             << testname 
     324          134 :             << std::setw(terminalwidth - testname.size() + ss.str().size() - 12)  << std::right << std::setfill('.') << ss.str() << std::endl;
     325          134 :     }
     326          134 :     return failed;
     327              : }
     328           32 : int SubFinalMessage(int failed)
     329              : {
     330           32 :     if (amrex::ParallelDescriptor::IOProcessor())
     331              :     {
     332              :         winsize w;
     333           32 :         ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
     334           32 :         std::stringstream ss;
     335           32 :         std::cout << std::left << "  └ ";
     336              : 
     337           32 :         if (!failed)
     338           32 :             std::cout << Color::FG::Green << Color::Bold << failed << " tests failed" << Color::Reset << std::endl;
     339              :         else
     340            0 :             std::cout << Color::FG::Red << Color::Bold << failed << " tests failed" << Color::Reset << std::endl;
     341           32 :     }
     342           32 :     return failed;
     343              : }
     344              : 
     345              : }
     346              : 
     347           62 : void AverageCellcenterToNode(amrex::MultiFab& node_mf, const int &dcomp, const amrex::MultiFab &cell_mf, const int &scomp, const int &ncomp/*, const int ngrow=0*/)
     348              : {
     349          434 :     Util::Assert(INFO,TEST(dcomp + ncomp <= node_mf.nComp()));
     350          434 :     Util::Assert(INFO,TEST(scomp + ncomp <= cell_mf.nComp()));
     351              :     //Util::Assert(INFO,TEST(cell_mf.boxArray() == node_mf.boxArray()));
     352          434 :     Util::Assert(INFO,TEST(cell_mf.DistributionMap() == cell_mf.DistributionMap()));
     353          434 :     Util::Assert(INFO,TEST(cell_mf.nGrow() > 0));
     354          269 :     for (amrex::MFIter mfi(node_mf,amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
     355              :     {
     356          207 :             amrex::Box bx = mfi.nodaltilebox();
     357          207 :             amrex::Array4<Set::Scalar>       const& node = node_mf.array(mfi);
     358          207 :             amrex::Array4<const Set::Scalar> const& cell = cell_mf.array(mfi);
     359          414 :             for (int n = 0; n < ncomp; n++)
     360          207 :                 amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(int i, int j, int k) {
     361       212934 :                                             node(i,j,k,dcomp+n) = Numeric::Interpolate::CellToNodeAverage(cell,i,j,k,scomp+n);
     362       106467 :                                         });
     363           62 :     }
     364           62 : }
     365              : 
     366              : 
     367              : }
        

Generated by: LCOV version 2.0-1