LCOV - code coverage report
Current view: top level - src/Util - Util.cpp (source / functions) Coverage Total Hit
Test: coverage_merged.info Lines: 64.5 % 228 147
Test Date: 2026-07-17 16:35:08 Functions: 64.7 % 17 11

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

Generated by: LCOV version 2.0-1