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

Generated by: LCOV version 2.0-1