Xyst test code coverage report
Current view: top level - Control - InciterConfig.cpp (source / functions) Hit Total Coverage
Commit: 5689ba12dc66a776d3d75f1ee48cc7d78eaa18dc Lines: 463 483 95.9 %
Date: 2024-11-22 19:02:53 Functions: 33 33 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 325 1019 31.9 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/Control/InciterConfig.cpp
       4                 :            :   \copyright 2012-2015 J. Bakosi,
       5                 :            :              2016-2018 Los Alamos National Security, LLC.,
       6                 :            :              2019-2021 Triad National Security, LLC.,
       7                 :            :              2022-2024 J. Bakosi
       8                 :            :              All rights reserved. See the LICENSE file for details.
       9                 :            :   \brief     Lua parser for Inciter's control file
      10                 :            :   \see       https://github.com/edubart/minilua
      11                 :            :   \see       https://www.codingwiththomas.com/blog/a-lua-c-api-cheat-sheet
      12                 :            : */
      13                 :            : // *****************************************************************************
      14                 :            : 
      15                 :            : #include "Compiler.hpp"
      16                 :            : 
      17                 :            : #if defined(__clang__)
      18                 :            :   #pragma clang diagnostic push
      19                 :            :   #pragma clang diagnostic ignored "-Wold-style-cast"
      20                 :            : #endif
      21                 :            : 
      22                 :            : #include "minilua.h"
      23                 :            : 
      24                 :            : #if defined(__clang__)
      25                 :            :   #pragma clang diagnostic pop
      26                 :            : #endif
      27                 :            : 
      28                 :            : #include "InciterConfig.hpp"
      29                 :            : 
      30                 :            : #include "NoWarning/charm++.hpp"
      31                 :            : 
      32                 :            : #include "XystConfig.hpp"
      33                 :            : #include "Exception.hpp"
      34                 :            : #include "Print.hpp"
      35                 :            : #include "TaggedTuple.hpp"
      36                 :            : #include "PrintTaggedTupleDeep.hpp"
      37                 :            : #include "Writer.hpp"
      38                 :            : 
      39                 :            : namespace inciter {
      40                 :            : namespace ctr {
      41                 :            : 
      42                 :            : static constexpr auto largeint = std::numeric_limits< int64_t >::max();
      43                 :            : static constexpr auto largeuint = std::numeric_limits< uint64_t >::max();
      44                 :            : static constexpr auto largereal = std::numeric_limits< double >::max();
      45                 :            : 
      46                 :            : void
      47                 :        256 : Config::cmdline( int argc, char** argv )
      48                 :            : // *****************************************************************************
      49                 :            : //! Contructor: parse inciter command line
      50                 :            : //! \param[in] argc Number of arguments to executable
      51                 :            : //! \param[in] argv Arguments to executable
      52                 :            : // *****************************************************************************
      53                 :            : {
      54         [ -  + ]:        256 :   if (!argc) return;
      55                 :            : 
      56                 :            :   // Defaults
      57         [ +  - ]:        768 :   if (!tk::git_commit().empty()) get< tag::commit >() = tk::git_commit();
      58                 :            :   get< tag::output >() = "out";
      59                 :            :   get< tag::diag >() = "diag";
      60                 :            :   get< tag::checkpoint >() = "restart";
      61                 :        256 :   get< tag::lbfreq >() = 1;
      62                 :        256 :   get< tag::rsfreq >() = 1000;
      63                 :            : 
      64         [ -  + ]:        256 :   if (argc == 1) {
      65                 :          0 :     help( argv );
      66                 :          0 :     CkExit( EXIT_FAILURE );
      67                 :            :   }
      68                 :            :   tk::Print print;
      69                 :            : 
      70                 :            :   // Process command line arguments
      71                 :            :   int c;
      72         [ +  + ]:       1218 :   while ((c = getopt( argc, argv, "bc:d:fh?i:l:no:qr:s:u:v" )) != -1) {
      73 [ +  + ][ +  - ]:        965 :     switch (c) {
         [ +  + ][ +  - ]
         [ -  - ][ +  + ]
                    [ + ]
      74                 :          2 :       case '?':
      75                 :            :       case 'h':
      76                 :            :       default:
      77                 :          2 :         help( argv );
      78                 :          2 :         CkExit();
      79                 :            :         break;
      80                 :        108 :       case 'b':
      81                 :        108 :         get< tag::benchmark >() = true;
      82                 :        108 :         break;
      83                 :        253 :       case 'c':
      84                 :        253 :         get< tag::control >() = optarg;
      85                 :            :         break;
      86                 :          0 :       case 'd':
      87                 :          0 :         get< tag::diag >() = optarg;
      88                 :            :         break;
      89                 :         11 :       case 'f':
      90                 :         11 :         get< tag::feedback >() = true;
      91                 :         11 :         break;
      92                 :        253 :       case 'i':
      93                 :        253 :         get< tag::input >() = optarg;
      94                 :            :         break;
      95                 :            :       case 'l':
      96         [ -  + ]:         24 :         get< tag::lbfreq >() = std::stoul( optarg );
      97                 :         12 :         break;
      98                 :          0 :       case 'n':
      99                 :          0 :         get< tag::nonblocking >() = true;
     100                 :          0 :         break;
     101                 :          0 :       case 'o':
     102                 :          0 :         get< tag::output >() = optarg;
     103                 :            :         break;
     104                 :            :       case 'r':
     105         [ -  - ]:          0 :         get< tag::rsfreq >() = std::stoul( optarg );
     106                 :          0 :         break;
     107                 :        184 :       case 'q':
     108                 :        184 :         get< tag::quiescence >() = true;
     109                 :        184 :         break;
     110                 :            :       case 'u':
     111         [ -  + ]:        282 :         get< tag::virt >() = std::stod( optarg );
     112                 :        141 :         break;
     113                 :          1 :       case 'v':
     114                 :            :         print << '\n';
     115 [ +  - ][ +  - ]:          2 :         print.version( tk::inciter_executable(), tk::git_commit() );
         [ +  - ][ -  - ]
     116                 :          1 :         CkExit();
     117                 :            :         break;
     118                 :            :     }
     119                 :            :   }
     120                 :            : 
     121         [ -  + ]:        253 :   if (optind != argc) {
     122                 :            :     print << "\nA non-option was supplied";
     123                 :          0 :     help( argv );
     124                 :          0 :     CkExit( EXIT_FAILURE );
     125                 :            :   }
     126 [ -  + ][ -  - ]:        253 :   ErrChk( not get< tag::input >().empty(),
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     127                 :            :           "Mandatory input mesh file not specified. Use -i <filename>." );
     128 [ -  + ][ -  - ]:        253 :   ErrChk( not get< tag::control >().empty(),
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     129                 :            :           "Mandatory control file not specified. Use -c <filename>." );
     130                 :            : }
     131                 :            : 
     132                 :            : void
     133                 :          2 : Config::help( char** argv )
     134                 :            : // *****************************************************************************
     135                 :            : // Echo help on command line arguments
     136                 :            : //! \param[in] argv Arguments to executable
     137                 :            : // *****************************************************************************
     138                 :            : {
     139                 :          2 :   tk::Print() <<
     140                 :            :     "\nUsage: " << argv[0] << " -i <in.exo> -c <config.q> [OPTION]...\n"
     141                 :            :     "\n"
     142                 :            :     "  -h, -?        Print out this help\n"
     143                 :            :     "  -b            Benchmark mode, "
     144                 :            :                      "default: " << get< tag::benchmark >() << "\n" <<
     145                 :            :     "  -c <config.q> Specify control file\n"
     146                 :            :     "  -d <diag>     Specify diagnostics file, "
     147                 :            :                      "default: " << get< tag::diag >() << "\n" <<
     148                 :            :     "  -f            Extra feedback, "
     149                 :            :                      "default: " << get< tag::feedback >() << "\n" <<
     150                 :            :     "  -i <in.exo>   Specify input mesh file\n"
     151                 :            :     "  -l <int>      Load balancing frequency, "
     152                 :            :                      "default: " << get< tag::lbfreq >() << "\n" <<
     153                 :            :     "  -n            Non-blocking migration, "
     154                 :            :                      "default: " << get< tag::nonblocking >() << "\n" <<
     155                 :            :     "  -o <outfile>  Base-filename for field output, "
     156                 :            :                      "default: " << get< tag::output >() << "\n" <<
     157                 :            :     "  -r <int>      Checkpoint frequency, "
     158                 :            :                      "default: " << get< tag::rsfreq >() << "\n" <<
     159                 :            :     "  -q            Enable quiescence detection, "
     160                 :            :                      "default: " << get< tag::quiescence >() << "\n" <<
     161                 :            :     "  -u <real>     Virtualization, "
     162                 :            :                      "default: " << get< tag::virt >() << "\n" <<
     163                 :            :     "  -v            Print revision information\n"
     164                 :          4 :     "\n";
     165                 :          2 : }
     166                 :            : 
     167                 :            : [[maybe_unused]] static void
     168                 :            : dumpstack( lua_State *L )
     169                 :            : // *****************************************************************************
     170                 :            : // Dump lua stack for debugging
     171                 :            : //! \param[in] L Lua state
     172                 :            : // *****************************************************************************
     173                 :            : {
     174                 :            :   int top=lua_gettop(L);
     175                 :            :   for (int i=1; i <= top; i++) {
     176                 :            :     printf("%d\t%s\t", i, luaL_typename(L,i));
     177                 :            :     switch (lua_type(L, i)) {
     178                 :            :       case LUA_TNUMBER:
     179                 :            :         printf("%g\n",lua_tonumber(L,i));
     180                 :            :         break;
     181                 :            :       case LUA_TSTRING:
     182                 :            :         printf("%s\n",lua_tostring(L,i));
     183                 :            :         break;
     184                 :            :       case LUA_TBOOLEAN:
     185                 :            :         printf("%s\n", (lua_toboolean(L, i) ? "true" : "false"));
     186                 :            :         break;
     187                 :            :       case LUA_TNIL:
     188                 :            :         printf("%s\n", "nil");
     189                 :            :         break;
     190                 :            :       default:
     191                 :            :         printf("%p\n",lua_topointer(L,i));
     192                 :            :         break;
     193                 :            :     }
     194                 :            :   }
     195                 :            : }
     196                 :            : 
     197                 :            : static int64_t
     198                 :        759 : sigint( lua_State* L,
     199                 :            :         const char* name,
     200                 :            :         int64_t def = largeint,
     201                 :            :         bool global = false )
     202                 :            : // *****************************************************************************
     203                 :            : // Parse integer from global scope
     204                 :            : //! \param[in] L Lua state
     205                 :            : //! \param[in] name Label to parse
     206                 :            : //! \param[in] def Default if does not exist
     207                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     208                 :            : // *****************************************************************************
     209                 :            : {
     210                 :            :   int64_t a = def;
     211                 :            : 
     212         [ -  + ]:        759 :   if (global) {
     213                 :          0 :     lua_getglobal( L, name );
     214                 :            :   } else {
     215         [ +  + ]:        759 :     if (lua_istable( L, -1 )) {
     216                 :        157 :       lua_getfield( L, -1, name );
     217                 :            :     } else {
     218                 :            :       return a;
     219                 :            :     }
     220                 :            :   }
     221                 :            : 
     222         [ +  + ]:        157 :   if (!lua_isnil( L, -1 )) {
     223 [ -  + ][ -  - ]:         73 :     ErrChk( lua_isinteger( L, -1 ), std::string(name) + " must be an integer" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     224                 :         73 :     a = lua_tointeger( L, -1 );
     225                 :            :   }
     226                 :            : 
     227                 :        157 :   lua_pop( L, 1 );
     228                 :            : 
     229                 :        157 :   return a;
     230                 :            : }
     231                 :            : 
     232                 :            : static uint64_t
     233                 :       4048 : unsigint( lua_State* L,
     234                 :            :           const char* name,
     235                 :            :           uint64_t def = largeuint,
     236                 :            :           bool global = false )
     237                 :            : // *****************************************************************************
     238                 :            : // Parse unsigned integer from global scope
     239                 :            : //! \param[in] L Lua state
     240                 :            : //! \param[in] name Label to parse
     241                 :            : //! \param[in] def Default if does not exist
     242                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     243                 :            : // *****************************************************************************
     244                 :            : {
     245                 :            :   uint64_t a = def;
     246                 :            : 
     247         [ +  + ]:       4048 :   if (global) {
     248                 :       1012 :     lua_getglobal( L, name );
     249                 :            :   } else {
     250         [ +  + ]:       3036 :     if (lua_istable( L, -1 )) {
     251                 :        450 :       lua_getfield( L, -1, name );
     252                 :            :     } else {
     253                 :            :       return a;
     254                 :            :     }
     255                 :            :   }
     256                 :            : 
     257         [ +  + ]:       1462 :   if (!lua_isnil( L, -1 )) {
     258 [ -  + ][ -  - ]:        875 :     ErrChk( lua_isinteger( L, -1 ), std::string(name) + " must be an integer" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     259                 :        875 :     a = static_cast< uint64_t >( lua_tointeger( L, -1 ) );
     260                 :            :   }
     261                 :            : 
     262                 :       1462 :   lua_pop( L, 1 );
     263                 :            : 
     264                 :       1462 :   return a;
     265                 :            : }
     266                 :            : 
     267                 :            : static bool
     268                 :       1771 : boolean( lua_State* L, const char* name, bool def = false, bool global = false )
     269                 :            : // *****************************************************************************
     270                 :            : // Parse boolean from global scope or table
     271                 :            : //! \param[in] L Lua state
     272                 :            : //! \param[in] name Label to parse
     273                 :            : //! \param[in] def Default if does not exist
     274                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     275                 :            : // *****************************************************************************
     276                 :            : {
     277                 :            :   bool a = def;
     278                 :            : 
     279         [ +  + ]:       1771 :   if (global) {
     280                 :       1265 :     lua_getglobal( L, name );
     281                 :            :   } else {
     282         [ +  + ]:        506 :     if (lua_istable( L, -1 )) {
     283                 :         24 :       lua_getfield( L, -1, name );
     284                 :            :     } else {
     285                 :            :       return a;
     286                 :            :     }
     287                 :            :   }
     288                 :            : 
     289         [ +  + ]:       1289 :   if (!lua_isnil( L, -1 )) {
     290 [ -  + ][ -  - ]:         89 :     ErrChk( lua_isboolean( L, -1 ), std::string(name) + " must be a boolean" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     291                 :         89 :     a = lua_toboolean( L, -1 );
     292                 :            :   }
     293                 :            : 
     294                 :       1289 :   lua_pop( L, 1 );
     295                 :            : 
     296                 :       1289 :   return a;
     297                 :            : }
     298                 :            : 
     299                 :            : static double
     300                 :       9666 : real( lua_State* L,
     301                 :            :       const char* name,
     302                 :            :       double def = largereal,
     303                 :            :       bool global = false )
     304                 :            : // *****************************************************************************
     305                 :            : // Parse real from global scope or table
     306                 :            : //! \param[in] L Lua state
     307                 :            : //! \param[in] name Label to parse
     308                 :            : //! \param[in] def Default if does not exist
     309                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     310                 :            : // *****************************************************************************
     311                 :            : {
     312                 :            :   double a = def;
     313                 :            : 
     314         [ +  + ]:       9666 :   if (global) {
     315                 :       3289 :     lua_getglobal( L, name );
     316                 :            :   } else {
     317         [ +  + ]:       6377 :     if (lua_istable( L, -1 )) lua_getfield( L, -1, name ); else return a;
     318                 :            :   }
     319                 :            : 
     320         [ +  + ]:       5902 :   if (!lua_isnil( L, -1 )) {
     321 [ -  + ][ -  - ]:       1018 :     ErrChk( lua_isnumber( L, -1 ), std::string(name) + " must be a number" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     322                 :       1018 :     a = lua_tonumber( L, -1 );
     323                 :            :   }
     324                 :            : 
     325                 :       5902 :   lua_pop( L, 1 );
     326                 :            : 
     327                 :       5902 :   return a;
     328                 :            : }
     329                 :            : 
     330                 :            : static std::string
     331                 :       2530 : string( lua_State* L,
     332                 :            :         const char* name,
     333                 :            :         const char* def = "default",
     334                 :            :         bool global = false )
     335                 :            : // *****************************************************************************
     336                 :            : // Parse string from global scope or table
     337                 :            : //! \param[in] L Lua state
     338                 :            : //! \param[in] name Label to parse
     339                 :            : //! \param[in] def Default if does not exist
     340                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     341                 :            : // *****************************************************************************
     342                 :            : {
     343                 :       2530 :   std::string a = def;
     344                 :            : 
     345         [ +  + ]:       2530 :   if (global) {
     346         [ +  - ]:        759 :     lua_getglobal( L, name );
     347                 :            :   } else {
     348 [ +  - ][ +  + ]:       1771 :     if (lua_istable( L, -1 )) lua_getfield( L, -1, name ); else return a;
                 [ +  - ]
     349                 :            :   }
     350                 :            : 
     351 [ +  - ][ +  + ]:       1072 :   if (!lua_isnil( L, -1 )) {
     352 [ +  - ][ -  + ]:        663 :     ErrChk( lua_isstring( L, -1 ), std::string(name) + " must be a string" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     353         [ +  - ]:        663 :     a = lua_tostring( L, -1 );
     354                 :            :   }
     355                 :            : 
     356         [ +  - ]:       1072 :   lua_pop( L, 1 );
     357                 :            : 
     358                 :            :   return a;
     359                 :            : }
     360                 :            : 
     361                 :            : static std::vector< double >
     362                 :       1020 : vector( lua_State* L,
     363                 :            :         const char* name,
     364                 :            :         double def = largereal,
     365                 :            :         bool global = false )
     366                 :            : // *****************************************************************************
     367                 :            : // Parse vector table from global scope or table
     368                 :            : //! \param[in] L Lua state
     369                 :            : //! \param[in] name Label to parse
     370                 :            : //! \param[in] def Default if does not exist
     371                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     372                 :            : //! \return Vector components parsed
     373                 :            : // *****************************************************************************
     374                 :            : {
     375                 :       1020 :   std::vector< double > v( 3, def );
     376                 :            : 
     377         [ +  + ]:       1020 :   if (global) {
     378         [ +  - ]:        253 :     lua_getglobal( L, name );
     379                 :            :   } else {
     380 [ +  - ][ +  + ]:        767 :     if (lua_istable( L, -1 )) lua_getfield( L, -1, name ); else return v;
                 [ +  - ]
     381                 :            :   }
     382                 :            : 
     383 [ +  - ][ +  + ]:        523 :   if (!lua_isnil( L, -1 )) {
     384 [ +  - ][ -  + ]:        188 :     ErrChk( lua_istable( L, -1 ), "vector must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     385         [ +  - ]:        188 :     int64_t n = luaL_len( L, -1 );
     386         [ +  + ]:        752 :     for (int64_t i=1; i<=n; ++i) {
     387         [ +  - ]:        564 :       lua_geti( L, -1, i );
     388 [ +  - ][ -  + ]:        564 :       ErrChk( lua_isnumber( L, -1 ), "vector components must be numbers" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     389 [ +  - ][ +  - ]:        564 :       v[ static_cast<std::size_t>(i-1) ] = lua_tonumber( L, -1 );
     390         [ +  - ]:        564 :       lua_pop( L, 1 );
     391                 :            :     }
     392                 :            :   }
     393                 :            : 
     394         [ +  - ]:        523 :   lua_pop( L, 1 );
     395                 :            : 
     396                 :            :   return v;
     397                 :            : }
     398                 :            : 
     399                 :            : static std::vector< std::string >
     400         [ +  + ]:        506 : stringlist( lua_State* L, const char* name, bool global = false )
     401                 :            : // *****************************************************************************
     402                 :            : // Parse string list table from global scope or table
     403                 :            : //! \param[in] L Lua state
     404                 :            : //! \param[in] name Label to parse
     405                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     406                 :            : //! \return List of strings parsed
     407                 :            : // *****************************************************************************
     408                 :            : {
     409                 :            :   std::vector< std::string > v;
     410                 :            : 
     411         [ +  + ]:        506 :   if (global) {
     412         [ +  - ]:        253 :     lua_getglobal( L, name );
     413                 :            :   } else {
     414 [ +  - ][ +  + ]:        253 :     if (lua_istable( L, -1 )) lua_getfield( L, -1, name ); else return v;
                 [ +  - ]
     415                 :            :   }
     416                 :            : 
     417 [ +  - ][ +  + ]:        265 :   if (!lua_isnil( L, -1 )) {
     418 [ +  - ][ -  + ]:         14 :     ErrChk( lua_istable( L, -1 ), "stringlist must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     419         [ +  - ]:         14 :     int64_t n = luaL_len( L, -1 );
     420         [ +  + ]:         60 :     for (int64_t i=1; i<=n; ++i) {
     421         [ +  - ]:         46 :       lua_geti( L, -1, i );
     422 [ +  - ][ -  + ]:         46 :       ErrChk( lua_isstring( L, -1 ), "stringlist components must be strings" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     423 [ +  - ][ +  - ]:         46 :       v.push_back( lua_tostring( L, -1 ) );
     424         [ +  - ]:         46 :       lua_pop( L, 1 );
     425                 :            :     }
     426                 :            :   }
     427                 :            : 
     428         [ +  - ]:        265 :   lua_pop( L, 1 );
     429                 :            : 
     430                 :            :   return v;
     431                 :          0 : }
     432                 :            : 
     433                 :            : static std::vector< uint64_t >
     434         [ +  + ]:        759 : unsigints( lua_State* L, const char* name, bool global = false )
     435                 :            : // *****************************************************************************
     436                 :            : // Parse table of unsigned integers from global scope or table
     437                 :            : //! \param[in] L Lua state
     438                 :            : //! \param[in] name Label to parse
     439                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     440                 :            : //! \return List of unsigned integers parsed
     441                 :            : // *****************************************************************************
     442                 :            : {
     443                 :            :   std::vector< uint64_t > v;
     444                 :            : 
     445         [ +  + ]:        759 :   if (global) {
     446         [ +  - ]:        253 :     lua_getglobal( L, name );
     447                 :            :   } else {
     448 [ +  - ][ +  + ]:        506 :     if (lua_istable( L, -1 )) lua_getfield( L, -1, name ); else return v;
                 [ +  - ]
     449                 :            :   }
     450                 :            : 
     451 [ +  - ][ +  + ]:        266 :   if (!lua_isnil( L, -1 )) {
     452 [ +  - ][ -  + ]:         23 :     ErrChk( lua_istable( L, -1 ), "unsigints must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     453         [ +  - ]:         23 :     int64_t n = luaL_len( L, -1 );
     454         [ +  + ]:         86 :     for (int64_t i=1; i<=n; ++i) {
     455         [ +  - ]:         63 :       lua_geti( L, -1, i );
     456 [ +  - ][ -  + ]:         63 :       ErrChk( lua_isinteger( L, -1 ), "unsigints components must be numbers" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     457 [ +  - ][ +  - ]:         63 :       v.push_back( static_cast< uint64_t >( lua_tointeger( L, -1 ) ) );
                 [ -  - ]
     458         [ +  - ]:         63 :       lua_pop( L, 1 );
     459                 :            :     }
     460                 :            :   }
     461                 :            : 
     462         [ +  - ]:        266 :   lua_pop( L, 1 );
     463                 :            : 
     464                 :            :   return v;
     465                 :            : }
     466                 :            : 
     467                 :            : static std::vector< int >
     468         [ -  + ]:        950 : sideset( lua_State* L, bool global = false )
     469                 :            : // *****************************************************************************
     470                 :            : // Parse sideset table from global scope or table
     471                 :            : //! \param[in] L Lua state
     472                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     473                 :            : //! \return Vector of side set ids parsed
     474                 :            : // *****************************************************************************
     475                 :            : {
     476                 :            :   std::vector< int > v;
     477                 :            : 
     478         [ -  + ]:        950 :   if (global) {
     479         [ -  - ]:          0 :     lua_getglobal( L, "sideset" );
     480                 :            :   } else {
     481 [ +  - ][ +  + ]:        950 :     if (lua_istable( L, -1 )) lua_getfield( L, -1, "sideset" ); else return v;
                 [ +  - ]
     482                 :            :   }
     483                 :            : 
     484 [ +  - ][ +  + ]:        348 :   if (!lua_isnil( L, -1 )) {
     485 [ +  - ][ -  + ]:        213 :     ErrChk( lua_istable( L, -1 ), "sideset must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     486         [ +  - ]:        213 :     int64_t n = luaL_len( L, -1 );
     487         [ +  + ]:        618 :     for (int64_t i=1; i<=n; ++i) {
     488         [ +  - ]:        405 :       lua_geti( L, -1, i );
     489 [ +  - ][ -  + ]:        405 :       ErrChk( lua_isinteger( L, -1 ), "sideset id must be a number" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     490         [ +  - ]:        405 :       int a = static_cast< int >( lua_tointeger( L, -1 ) );
     491 [ -  + ][ -  - ]:        405 :       ErrChk( a >= 0, "sideset id must be non-negative" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     492         [ +  - ]:        405 :       v.push_back( a );
     493         [ +  - ]:        405 :       lua_pop( L, 1 );
     494                 :            :     }
     495                 :            :   }
     496                 :            : 
     497         [ +  - ]:        348 :   lua_pop( L, 1 );
     498                 :            : 
     499                 :            :   return v;
     500                 :            : }
     501                 :            : 
     502                 :            : static std::vector< std::vector< double > >
     503         [ -  + ]:        759 : range( lua_State* L, bool global = false )
     504                 :            : // *****************************************************************************
     505                 :            : // Parse range(s) table from global scope or table
     506                 :            : //! \param[in] L Lua state
     507                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     508                 :            : //! \return Vector of vectors of range(s)
     509                 :            : // *****************************************************************************
     510                 :            : {
     511                 :            :   std::vector< std::vector< double > > v;
     512                 :            : 
     513         [ -  + ]:        759 :   if (global) {
     514         [ -  - ]:          0 :     lua_getglobal( L, "range" );
     515                 :            :   } else {
     516 [ +  - ][ +  + ]:        759 :     if (lua_istable( L, -1 )) lua_getfield( L, -1, "range" ); else return v;
                 [ +  - ]
     517                 :            :   }
     518                 :            : 
     519 [ +  - ][ +  + ]:        165 :   if (!lua_isnil( L, -1 )) {
     520 [ +  - ][ -  + ]:          6 :     ErrChk( lua_istable( L, -1 ), "range must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     521         [ +  - ]:          6 :     int64_t n = luaL_len( L, -1 );
     522         [ +  - ]:          6 :     v.emplace_back();
     523         [ +  + ]:         23 :     for (int64_t i=1; i<=n; ++i) {
     524         [ +  - ]:         17 :       lua_geti( L, -1, i );
     525 [ +  - ][ +  + ]:         17 :       if (lua_isnumber( L, -1 )) {
     526 [ +  - ][ +  - ]:         15 :         v.back().push_back( lua_tonumber( L, -1 ) );
     527                 :            :       } else {
     528 [ +  - ][ -  + ]:          2 :         ErrChk( lua_istable( L, -1 ), "non-number range must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     529 [ +  + ][ +  - ]:          2 :         if (i>1) v.emplace_back();
     530         [ +  - ]:          2 :         int64_t m = luaL_len( L, -1 );
     531         [ +  + ]:          8 :         for (int64_t j=1; j<=m; ++j) {
     532         [ +  - ]:          6 :           lua_geti( L, -1, j );
     533 [ +  - ][ -  + ]:          6 :           ErrChk( lua_isnumber( L, -1 ), "vector components must be numbers" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     534 [ +  - ][ +  - ]:          6 :           v.back().push_back( lua_tonumber( L, -1 ) );
     535         [ +  - ]:          6 :           lua_pop( L, 1 );
     536                 :            :         }
     537                 :            :       }
     538         [ +  - ]:         17 :       lua_pop( L, 1 );
     539                 :            :     }
     540                 :            :   }
     541                 :            : 
     542         [ +  - ]:        165 :   lua_pop( L, 1 );
     543                 :            : 
     544                 :            :   return v;
     545                 :          0 : }
     546                 :            : 
     547                 :            : static void
     548                 :        253 : fieldout( lua_State* L, Config& cfg )
     549                 :            : // *****************************************************************************
     550                 :            : // Parse fieldout table
     551                 :            : //! \param[in,out] L Lua state
     552                 :            : //! \param[in,out] cfg Config state
     553                 :            : // *****************************************************************************
     554                 :            : {
     555                 :        253 :   lua_getglobal( L, "fieldout" );
     556                 :            : 
     557                 :        253 :   cfg.get< tag::fieldout_iter >() = unsigint( L, "iter" );
     558                 :        253 :   cfg.get< tag::fieldout_time >() = real( L, "time" );
     559                 :        253 :   cfg.get< tag::fieldout_range >() = range( L );
     560                 :        253 :   cfg.get< tag::fieldout >() = sideset( L );
     561                 :            : 
     562                 :        253 :   lua_pop( L, 1 );
     563                 :        253 : }
     564                 :            : 
     565                 :            : static void
     566                 :        253 : histout( lua_State* L, Config& cfg )
     567                 :            : // *****************************************************************************
     568                 :            : // Parse histout table
     569                 :            : //! \param[in,out] L Lua state
     570                 :            : //! \param[in,out] cfg Config state
     571                 :            : // *****************************************************************************
     572                 :            : {
     573                 :        253 :   lua_getglobal( L, "histout" );
     574                 :            : 
     575                 :        253 :   cfg.get< tag::histout_iter >() = unsigint( L, "iter" );
     576                 :        253 :   cfg.get< tag::histout_time >() = real( L, "time" );
     577                 :        253 :   cfg.get< tag::histout_range >() = range( L );
     578                 :        253 :   cfg.get< tag::histout_precision >() = sigint( L, "precision", 8 );
     579                 :        253 :   cfg.get< tag::histout_format >() = string( L, "format" );
     580                 :            : 
     581         [ +  + ]:        253 :   if (lua_istable( L, -1 )) {
     582                 :         15 :     lua_getfield( L, -1, "points" );
     583         [ +  - ]:         15 :     if (!lua_isnil( L, -1 )) {
     584 [ -  + ][ -  - ]:         15 :       ErrChk( lua_istable( L, -1 ), "histout points must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     585                 :            :       auto& r = cfg.get< tag::histout >();
     586                 :         15 :       int64_t n = luaL_len( L, -1 );
     587         [ +  + ]:         90 :       for (int64_t i=1; i<=n; ++i) {
     588                 :         75 :         lua_geti( L, -1, i );
     589 [ -  + ][ -  - ]:         75 :         ErrChk( lua_istable( L, -1 ), "histout point must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     590                 :         75 :         r.emplace_back();
     591                 :            :         auto& p = r.back();
     592                 :         75 :         int64_t m = luaL_len( L, -1 );
     593         [ +  + ]:        300 :         for (int64_t j=1; j<=m; ++j) {
     594                 :        225 :           lua_geti( L, -1, j );
     595 [ -  + ][ -  - ]:        225 :           ErrChk( lua_isnumber( L, -1 ), "point coordinate must be a number" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     596                 :        225 :           p.push_back( lua_tonumber( L, -1 ) );
     597                 :        225 :           lua_pop( L, 1 );
     598                 :            :         }
     599                 :         75 :         lua_pop( L, 1 );
     600                 :            :       }
     601                 :            :     }
     602                 :         15 :     lua_pop( L, 1 );
     603                 :            :   }
     604                 :            : 
     605                 :        253 :   lua_pop( L, 1 );
     606                 :        253 : }
     607                 :            : 
     608                 :            : static void
     609                 :        253 : integout( lua_State* L, Config& cfg )
     610                 :            : // *****************************************************************************
     611                 :            : // Parse integout table
     612                 :            : //! \param[in,out] L Lua state
     613                 :            : //! \param[in,out] cfg Config state
     614                 :            : // *****************************************************************************
     615                 :            : {
     616                 :        253 :   lua_getglobal( L, "integout" );
     617                 :            : 
     618                 :        253 :   cfg.get< tag::integout_iter >() = unsigint( L, "iter" );
     619                 :        253 :   cfg.get< tag::integout_time >() = real( L, "time" );
     620                 :        253 :   cfg.get< tag::integout_range >() = range( L );
     621                 :        253 :   cfg.get< tag::integout_precision >() = sigint( L, "precision", 8 );
     622                 :        253 :   cfg.get< tag::integout_format >() = string( L, "format" );
     623                 :        253 :   cfg.get< tag::integout >() = sideset( L );
     624                 :            : 
     625                 :        253 :   lua_pop( L, 1 );
     626                 :        253 : }
     627                 :            : 
     628                 :            : static void
     629                 :        253 : diag( lua_State* L, Config& cfg )
     630                 :            : // *****************************************************************************
     631                 :            : // Parse diag table
     632                 :            : //! \param[in,out] L Lua state
     633                 :            : //! \param[in,out] cfg Config state
     634                 :            : // *****************************************************************************
     635                 :            : {
     636                 :        253 :   lua_getglobal( L, "diag" );
     637                 :            : 
     638                 :        253 :   cfg.get< tag::diag_iter >() = unsigint( L, "iter", 1 );
     639                 :        253 :   cfg.get< tag::diag_precision >() = sigint( L, "precision", 8 );
     640                 :        253 :   cfg.get< tag::diag_format >() = string( L, "format" );
     641                 :            : 
     642                 :        253 :   lua_pop( L, 1 );
     643                 :        253 : }
     644                 :            : 
     645                 :            : static void
     646                 :        506 : bc_dir( lua_State* L,
     647                 :            :         std::vector< std::vector< int > >& mask,
     648                 :            :         bool global = false )
     649                 :            : // *****************************************************************************
     650                 :            : // Parse bc_dir table
     651                 :            : //! \param[in,out] L Lua state
     652                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     653                 :            : //! \param[in,out] mask Config state to store Dirichlet BC setids and mask
     654                 :            : // *****************************************************************************
     655                 :            : {
     656         [ +  + ]:        506 :   if (global) {
     657                 :        253 :     lua_getglobal( L, "bc_dir" );
     658                 :            :   } else {
     659         [ +  + ]:        253 :     if (lua_istable( L, -1 )) lua_getfield( L, -1, "bc_dir" ); else return;
     660                 :            :   }
     661                 :            : 
     662         [ +  + ]:        290 :   if (!lua_isnil( L, -1 )) {
     663 [ -  + ][ -  - ]:        138 :     ErrChk( lua_istable( L, -1 ), "bc_dir must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     664                 :        138 :     int64_t n = luaL_len( L, -1 );
     665         [ +  + ]:        648 :     for (int64_t i=1; i<=n; ++i) {
     666                 :        510 :       lua_geti( L, -1, i );
     667 [ -  + ][ -  - ]:        510 :       ErrChk( lua_istable( L, -1 ), "bc_dir table entry must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     668                 :        510 :       mask.emplace_back();
     669                 :            :       auto& b = mask.back();
     670                 :        510 :       int64_t m = luaL_len( L, -1 );
     671         [ +  + ]:       3298 :       for (int64_t j=1; j<=m; ++j) {
     672                 :       2788 :         lua_geti( L, -1, j );
     673 [ -  + ][ -  - ]:       2788 :         ErrChk( lua_isinteger( L, -1 ), "bc_dir entry must be an integer" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     674                 :       2788 :         b.push_back( static_cast< int >( lua_tointeger( L, -1 ) ) );
     675                 :       2788 :         lua_pop( L, 1 );
     676                 :            :       }
     677                 :        510 :       lua_pop( L, 1 );
     678                 :            :     }
     679                 :            :   }
     680                 :            : 
     681                 :        290 :   lua_pop( L, 1 );
     682                 :            : }
     683                 :            : 
     684                 :            : static void
     685                 :        506 : bc_dirval( lua_State* L,
     686                 :            :            std::vector< std::vector< double > >& val,
     687                 :            :            bool global = false )
     688                 :            : // *****************************************************************************
     689                 :            : // Parse bc_dirval table
     690                 :            : //! \param[in,out] L Lua state
     691                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     692                 :            : //! \param[in,out] val Config state to store Dirichlet BC setids and values
     693                 :            : // *****************************************************************************
     694                 :            : {
     695         [ +  + ]:        506 :   if (global) {
     696                 :        253 :     lua_getglobal( L, "bc_dirval" );
     697                 :            :   } else {
     698         [ +  + ]:        253 :     if (lua_istable( L, -1 )) lua_getfield( L, -1, "bc_dirval" ); else return;
     699                 :            :   }
     700                 :            : 
     701         [ +  + ]:        290 :   if (!lua_isnil( L, -1 )) {
     702 [ -  + ][ -  - ]:         27 :     ErrChk( lua_istable( L, -1 ), "bc_dirval must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     703                 :         27 :     int64_t n = luaL_len( L, -1 );
     704         [ +  + ]:         70 :     for (int64_t i=1; i<=n; ++i) {
     705                 :         43 :       lua_geti( L, -1, i );
     706 [ -  + ][ -  - ]:         43 :       ErrChk( lua_istable( L, -1 ), "bc_dirval table entry must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     707                 :         43 :       val.emplace_back();
     708                 :            :       auto& b = val.back();
     709                 :         43 :       int64_t m = luaL_len( L, -1 );
     710         [ +  + ]:        157 :       for (int64_t j=1; j<=m; ++j) {
     711                 :        114 :         lua_geti( L, -1, j );
     712 [ -  + ][ -  - ]:        114 :         ErrChk( lua_isnumber( L, -1 ), "bc_dirval entry must be an real" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     713                 :        114 :         b.push_back( static_cast< double >( lua_tonumber( L, -1 ) ) );
     714                 :        114 :         lua_pop( L, 1 );
     715                 :            :       }
     716                 :         43 :       lua_pop( L, 1 );
     717                 :            :     }
     718                 :            :   }
     719                 :            : 
     720                 :        290 :   lua_pop( L, 1 );
     721                 :            : }
     722                 :            : 
     723                 :            : static void
     724                 :        506 : bc_sym( lua_State* L, std::vector< int >& s, bool global = false )
     725                 :            : // *****************************************************************************
     726                 :            : // Parse bc_sym table
     727                 :            : //! \param[in,out] L Lua state
     728                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     729                 :            : //! \param[in,out] s Config state
     730                 :            : // *****************************************************************************
     731                 :            : {
     732         [ +  + ]:        506 :   if (global) {
     733                 :        253 :     lua_getglobal( L, "bc_sym" );
     734                 :            :   } else {
     735         [ +  + ]:        253 :     if (lua_istable( L, -1 )) lua_getfield( L, -1, "bc_sym" ); else return;
     736                 :            :   }
     737                 :            : 
     738         [ +  + ]:        290 :   if (!lua_isnil( L, -1 )) {
     739                 :        304 :     s = sideset( L );
     740                 :            :   }
     741                 :            : 
     742                 :        290 :   lua_pop( L, 1 );
     743                 :            : }
     744                 :            : 
     745                 :            : static void
     746                 :        253 : bc_noslip( lua_State* L, std::vector< int >& s, bool global = false )
     747                 :            : // *****************************************************************************
     748                 :            : // Parse bc_noslip table
     749                 :            : //! \param[in,out] L Lua state
     750                 :            : //! \param[in] global True to parse from global scope, false from table on stack
     751                 :            : //! \param[in,out] s Config state
     752                 :            : // *****************************************************************************
     753                 :            : {
     754         [ +  - ]:        253 :   if (global) {
     755                 :        253 :     lua_getglobal( L, "bc_noslip" );
     756                 :            :   } else {
     757         [ -  - ]:          0 :     if (lua_istable( L, -1 )) lua_getfield( L, -1, "bc_noslip" ); else return;
     758                 :            :   }
     759                 :            : 
     760         [ +  + ]:        253 :   if (!lua_isnil( L, -1 )) {
     761                 :         54 :     s = sideset( L );
     762                 :            :   }
     763                 :            : 
     764                 :        253 :   lua_pop( L, 1 );
     765                 :            : }
     766                 :            : 
     767                 :            : static void
     768                 :        253 : bc_far( lua_State* L, Config& cfg )
     769                 :            : // *****************************************************************************
     770                 :            : // Parse bc_far table
     771                 :            : //! \param[in,out] L Lua state
     772                 :            : //! \param[in,out] cfg Config state
     773                 :            : // *****************************************************************************
     774                 :            : {
     775                 :        253 :   lua_getglobal( L, "bc_far" );
     776                 :            : 
     777                 :        253 :   cfg.get< tag::bc_far >() = sideset( L );
     778                 :        253 :   cfg.get< tag::bc_far_velocity >() = vector( L, "velocity" );
     779                 :        253 :   cfg.get< tag::bc_far_density >() = real( L, "density" );
     780                 :        253 :   cfg.get< tag::bc_far_pressure >() = real( L, "pressure" );
     781                 :            : 
     782                 :        253 :   lua_pop( L, 1 );
     783                 :        253 : }
     784                 :            : 
     785                 :            : static void
     786                 :        253 : bc_pre( lua_State* L, Config& cfg )
     787                 :            : // *****************************************************************************
     788                 :            : // Parse bc_pre table
     789                 :            : //! \param[in,out] L Lua state
     790                 :            : //! \param[in,out] cfg Config state
     791                 :            : // *****************************************************************************
     792                 :            : {
     793                 :        253 :   lua_getglobal( L, "bc_pre" );
     794                 :            : 
     795         [ +  + ]:        253 :   if (lua_istable( L, -1 )) {
     796                 :         12 :     auto bc_pre_set = [&]( const char* name ) {
     797                 :         24 :       lua_getfield( L, -1, name );
     798         [ +  - ]:         12 :       if (!lua_isnil( L, -1 )) {
     799 [ -  + ][ -  - ]:         12 :         ErrChk( lua_istable( L, -1 ), "bc_pre must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     800                 :         24 :         cfg.get< tag::bc_pre >().push_back( sideset( L ) );
     801                 :         12 :         cfg.get< tag::bc_pre_density >().push_back( real(L,"density") );
     802                 :         12 :         cfg.get< tag::bc_pre_pressure >().push_back( real(L,"pressure") );
     803                 :            :       }
     804                 :         12 :       lua_pop( L, 1 );
     805                 :         12 :     };
     806                 :            : 
     807                 :          6 :     bc_pre_set( "inlet" );
     808                 :          6 :     bc_pre_set( "outlet" );
     809                 :            :   }
     810                 :            : 
     811                 :        253 :   lua_pop( L, 1 );
     812                 :        253 : }
     813                 :            : 
     814                 :            : static void
     815                 :        253 : ic( lua_State* L, Config& cfg )
     816                 :            : // *****************************************************************************
     817                 :            : // Parse ic table
     818                 :            : //! \param[in,out] L Lua state
     819                 :            : //! \param[in,out] cfg Config state
     820                 :            : // *****************************************************************************
     821                 :            : {
     822                 :        253 :   lua_getglobal( L, "ic" );
     823                 :            : 
     824                 :        253 :   cfg.get< tag::ic_velocity >() = vector( L, "velocity" );
     825                 :        253 :   cfg.get< tag::ic_density >() = real( L, "density" );
     826                 :        253 :   cfg.get< tag::ic_pressure >() = real( L, "pressure" );
     827                 :        253 :   cfg.get< tag::ic_energy >() = real( L, "energy" );
     828                 :        253 :   cfg.get< tag::ic_temperature >() = real( L, "temperature" );
     829                 :            : 
     830                 :         18 :   auto box_extent = [&]( const char* axis, auto& v ) {
     831                 :         18 :     lua_getfield( L, -1, axis );
     832         [ +  - ]:         18 :     if (!lua_isnil( L, -1 )) {
     833 [ -  + ][ -  - ]:         18 :       ErrChk( lua_istable( L, -1 ), "ic box extents must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     834                 :         18 :       int64_t n = luaL_len( L, -1 );
     835         [ +  + ]:         54 :       for (int64_t i=1; i<=n; ++i) {
     836                 :         36 :         lua_geti( L, -1, i );
     837 [ -  + ][ -  - ]:         36 :         ErrChk( lua_isnumber( L, -1 ), "ic extent must be a number" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     838                 :         36 :         v.push_back( lua_tonumber( L, -1 ) );
     839                 :         36 :         lua_pop( L, 1 );
     840                 :            :       }
     841                 :            :     }
     842                 :         18 :     lua_pop( L, 1 );
     843                 :         18 :   };
     844                 :            : 
     845         [ +  + ]:        253 :   if (lua_istable( L, -1 )) {
     846                 :        154 :     lua_getfield( L, -1, "boxes" );
     847         [ +  + ]:        154 :     if (!lua_isnil( L, -1 )) {
     848 [ -  + ][ -  - ]:          3 :       ErrChk( lua_istable( L, -1 ), "ic boxes must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     849                 :            :       auto& boxes = cfg.get< tag::ic >();
     850                 :          3 :       int64_t n = luaL_len( L, -1 );
     851         [ +  + ]:          9 :       for (int64_t i=1; i<=n; ++i) {
     852                 :          6 :         lua_geti( L, -1, i );
     853 [ -  + ][ -  - ]:          6 :         ErrChk( lua_istable( L, -1 ), "ic box must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     854                 :          6 :         boxes.emplace_back();
     855                 :            :         auto& box = boxes.back();
     856                 :          6 :         box_extent( "x", box.get< tag::x >() );
     857                 :          6 :         box_extent( "y", box.get< tag::y >() );
     858                 :          6 :         box_extent( "z", box.get< tag::z >() );
     859                 :          6 :         box.get< tag::ic_velocity >() = vector( L, "velocity" );
     860                 :          6 :         box.get< tag::ic_density >() = real( L, "density" );
     861                 :          6 :         box.get< tag::ic_pressure >() = real( L, "pressure" );
     862                 :          6 :         box.get< tag::ic_energy >() = real( L, "energy" );
     863                 :          6 :         box.get< tag::ic_temperature >() = real( L, "temperature" );
     864                 :          6 :         lua_pop( L, 1 );
     865                 :            :       }
     866                 :            :     }
     867                 :        154 :     lua_pop( L, 1 );
     868                 :            :   }
     869                 :            : 
     870                 :        253 :   lua_pop( L, 1 );
     871                 :        253 : }
     872                 :            : 
     873                 :            : static void
     874                 :        253 : mat( lua_State* L, Config& cfg )
     875                 :            : // *****************************************************************************
     876                 :            : // Parse mat table
     877                 :            : //! \param[in,out] L Lua state
     878                 :            : //! \param[in,out] cfg Config state
     879                 :            : // *****************************************************************************
     880                 :            : {
     881                 :        253 :   lua_getglobal( L, "mat" );
     882                 :            : 
     883                 :        253 :   cfg.get< tag::mat_spec_heat_ratio >() = real( L, "spec_heat_ratio", 1.4 );
     884                 :        253 :   cfg.get< tag::mat_spec_heat_const_vol >() = real( L, "spec_heat_const_vol" );
     885                 :        253 :   cfg.get< tag::mat_spec_gas_const >() = real(L, "spec_gas_const", 287.052874);
     886                 :        253 :   cfg.get< tag::mat_heat_conductivity >() = real( L, "heat_conductivity" );
     887                 :        253 :   cfg.get< tag::mat_dyn_viscosity >() = real( L, "dyn_viscosity", 0.0 );
     888                 :            : 
     889                 :        253 :   lua_pop( L, 1 );
     890                 :        253 : }
     891                 :            : 
     892                 :            : static void
     893                 :        253 : problem( lua_State* L, Config& cfg )
     894                 :            : // *****************************************************************************
     895                 :            : // Parse problem table
     896                 :            : //! \param[in,out] L Lua state
     897                 :            : //! \param[in,out] cfg Config state
     898                 :            : // *****************************************************************************
     899                 :            : {
     900                 :        253 :   lua_getglobal( L, "problem" );
     901                 :            : 
     902                 :        253 :   cfg.get< tag::problem >() = string( L, "name", "userdef" );
     903                 :        253 :   cfg.get< tag::problem_alpha >() = real( L, "alpha" );
     904                 :        253 :   cfg.get< tag::problem_kappa >() = real( L, "kappa" );
     905                 :        253 :   cfg.get< tag::problem_r0 >() = real( L, "r0" );
     906                 :        253 :   cfg.get< tag::problem_p0 >() = real( L, "p0" );
     907                 :        253 :   cfg.get< tag::problem_ce >() = real( L, "ce" );
     908                 :        253 :   cfg.get< tag::problem_beta >() = vector( L, "beta" );
     909                 :            : 
     910         [ +  + ]:        253 :   if (lua_istable( L, -1 )) {
     911                 :        101 :     lua_getfield( L, -1, "src" );
     912         [ +  + ]:        101 :     if (!lua_isnil( L, -1 )) {
     913 [ -  + ][ -  - ]:          2 :       ErrChk( lua_istable( L, -1 ), "problem source must be a table" );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     914                 :            :       auto& s = cfg.get< tag::problem_src >();
     915                 :          2 :       s.get< tag::location >() = vector( L, "location" );
     916                 :          2 :       s.get< tag::radius >() = real( L, "radius" );
     917                 :          2 :       s.get< tag::release_time >() = real( L, "release_time" );
     918                 :            :     }
     919                 :        101 :     lua_pop( L, 1 );
     920                 :            :   }
     921                 :            : 
     922                 :            :   const auto& solver = cfg.get< tag::solver >();
     923                 :            :   const auto& problem = cfg.get< tag::problem >();
     924                 :            : 
     925                 :            :   auto& n = cfg.get< tag::problem_ncomp >();
     926                 :        253 :   n = 5;
     927 [ +  + ][ +  + ]:        484 :   if (problem == "slot_cyl" || problem == "point_src") ++n;
     928                 :            : 
     929         [ +  + ]:        253 :        if (solver == "chocg") n -= 2;
     930         [ +  + ]:        210 :   else if (solver == "lohcg") n -= 1;
     931                 :            : 
     932                 :        253 :   lua_pop( L, 1 );
     933                 :        253 : }
     934                 :            : 
     935                 :            : static void
     936                 :        253 : href( lua_State* L, Config& cfg )
     937                 :            : // *****************************************************************************
     938                 :            : // Parse href table
     939                 :            : //! \param[in,out] L Lua state
     940                 :            : //! \param[in,out] cfg Config state
     941                 :            : // *****************************************************************************
     942                 :            : {
     943                 :        253 :   lua_getglobal( L, "href" );
     944                 :            : 
     945                 :        253 :   cfg.get< tag::href_t0 >() = boolean( L, "t0" );
     946                 :        253 :   cfg.get< tag::href_dt >() = boolean( L, "dt" );
     947                 :        253 :   cfg.get< tag::href_dtfreq >() = unsigint( L, "dtfreq", 5 );
     948                 :        253 :   cfg.get< tag::href_init >() = stringlist( L, "init" );
     949                 :        253 :   cfg.get< tag::href_refvar >() = unsigints( L, "refvar" );
     950                 :        253 :   cfg.get< tag::href_error >() = string( L, "error", "jump" );
     951                 :        253 :   cfg.get< tag::href_maxlevels >() = unsigint( L, "maxlevels", 2 );
     952                 :            : 
     953                 :        253 :   lua_pop( L, 1 );
     954                 :        253 : }
     955                 :            : 
     956                 :            : static void
     957                 :        253 : deactivate( lua_State* L, Config& cfg )
     958                 :            : // *****************************************************************************
     959                 :            : // Parse deactivate table
     960                 :            : //! \param[in,out] L Lua state
     961                 :            : //! \param[in,out] cfg Config state
     962                 :            : // *****************************************************************************
     963                 :            : {
     964                 :        253 :   lua_getglobal( L, "deactivate" );
     965                 :            : 
     966                 :        253 :   cfg.get< tag::deafreq >() = unsigint( L, "freq", 0 );
     967                 :        253 :   cfg.get< tag::deatol >() = real( L, "tol", 1.0e-3 );
     968                 :        253 :   cfg.get< tag::deadif >() = real( L, "dif", 0.0 );
     969                 :        253 :   cfg.get< tag::deasys >() = unsigints( L, "sys" );
     970                 :        253 :   cfg.get< tag::deatime >() = real( L, "time", 0.0 );
     971                 :            : 
     972                 :        253 :   cfg.get< tag::deactivate >() = cfg.get< tag::deafreq >();  // on if freq > 0
     973                 :            : 
     974                 :        253 :   lua_pop( L, 1 );
     975                 :        253 : }
     976                 :            : 
     977                 :            : static void
     978                 :        253 : pressure( lua_State* L, Config& cfg )
     979                 :            : // *****************************************************************************
     980                 :            : // Parse pressure table
     981                 :            : //! \param[in,out] L Lua state
     982                 :            : //! \param[in,out] cfg Config state
     983                 :            : // *****************************************************************************
     984                 :            : {
     985                 :        253 :   lua_getglobal( L, "pressure" );
     986                 :            : 
     987                 :        253 :   cfg.get< tag::pre_iter >() = unsigint( L, "iter", 10 );
     988                 :        253 :   cfg.get< tag::pre_tol >() = real( L, "tol", 1.0e-3 );
     989                 :        253 :   cfg.get< tag::pre_verbose >() = unsigint( L, "verbose", 0 );
     990                 :        253 :   cfg.get< tag::pre_hydrostat >() = unsigint( L, "hydrostat" );
     991                 :        506 :   cfg.get< tag::pre_pc >() = string( L, "pc", "none" );
     992                 :        253 :   bc_dir( L, cfg.get< tag::pre_bc_dir >() );
     993                 :        253 :   bc_dirval( L, cfg.get< tag::pre_bc_dirval >() );
     994                 :        253 :   bc_sym( L, cfg.get< tag::pre_bc_sym >() );
     995                 :            : 
     996                 :        253 :   lua_pop( L, 1 );
     997                 :        253 : }
     998                 :            : 
     999                 :            : static void
    1000                 :        253 : momentum( lua_State* L, Config& cfg )
    1001                 :            : // *****************************************************************************
    1002                 :            : // Parse momentum table
    1003                 :            : //! \param[in,out] L Lua state
    1004                 :            : //! \param[in,out] cfg Config state
    1005                 :            : // *****************************************************************************
    1006                 :            : {
    1007                 :        253 :   lua_getglobal( L, "momentum" );
    1008                 :            : 
    1009                 :        253 :   cfg.get< tag::mom_iter >() = unsigint( L, "iter", 10 );
    1010                 :        253 :   cfg.get< tag::mom_tol >() = real( L, "tol", 1.0e-3 );
    1011                 :        253 :   cfg.get< tag::mom_verbose >() = unsigint( L, "verbose", 0 );
    1012                 :        253 :   cfg.get< tag::mom_pc >() = string( L, "pc", "none" );
    1013                 :            : 
    1014                 :        253 :   lua_pop( L, 1 );
    1015                 :        253 : }
    1016                 :            : 
    1017                 :            : static void
    1018                 :        253 : lb( lua_State* L, Config& cfg )
    1019                 :            : // *****************************************************************************
    1020                 :            : // Parse lb (load balancing configuration) table
    1021                 :            : //! \param[in,out] L Lua state
    1022                 :            : //! \param[in,out] cfg Config state
    1023                 :            : // *****************************************************************************
    1024                 :            : {
    1025                 :        253 :   lua_getglobal( L, "lb" );
    1026                 :            : 
    1027                 :        253 :   cfg.get< tag::lbtime >() = real( L, "time", 0.0 );
    1028                 :            : 
    1029                 :        253 :   lua_pop( L, 1 );
    1030                 :        253 : }
    1031                 :            : 
    1032                 :            : void
    1033                 :        253 : Config::control()
    1034                 :            : // *****************************************************************************
    1035                 :            : // Parse control file
    1036                 :            : // *****************************************************************************
    1037                 :            : {
    1038                 :            :   const auto& controlfile = get< tag::control >();
    1039                 :            : 
    1040                 :            :   tk::Print print;
    1041         [ +  - ]:        253 :   print.section( "Control file: " + controlfile );
    1042                 :            : 
    1043                 :        253 :   lua_State* L = luaL_newstate();
    1044                 :        253 :   luaL_openlibs( L );
    1045                 :            : 
    1046                 :            :   std::string err;
    1047                 :            : 
    1048 [ +  - ][ +  - ]:        253 :   if (luaL_dofile( L, controlfile.c_str() ) == LUA_OK) {
         [ +  - ][ -  + ]
    1049                 :            : 
    1050         [ +  - ]:        253 :     get< tag::nstep >() = unsigint( L, "nstep", largeuint, true );
    1051         [ +  - ]:        253 :     get< tag::term >() = real( L, "term", largereal, true );
    1052         [ +  - ]:        253 :     get< tag::ttyi >() = unsigint( L, "ttyi", 1, true );
    1053         [ +  - ]:        253 :     get< tag::cfl >() = real( L, "cfl", 0.0, true );
    1054         [ +  - ]:        253 :     get< tag::rk >() = unsigint( L, "rk", 1, true );
    1055         [ +  - ]:        253 :     get< tag::theta >() = real( L, "theta", 0.0, true );
    1056         [ +  - ]:        253 :     get< tag::dt >() = real( L, "dt", 0.0, true );
    1057         [ +  - ]:        253 :     get< tag::turkel >() = real( L, "turkel", 0.5, true );
    1058         [ +  - ]:        253 :     get< tag::soundspeed >() = real( L, "soundspeed", 1.0, true );
    1059         [ +  - ]:        253 :     get< tag::velinf >() = vector( L, "velinf", 1.0, true );
    1060         [ +  - ]:        253 :     get< tag::t0 >() = real( L, "t0", 0.0, true );
    1061         [ +  - ]:        253 :     get< tag::reorder >() = boolean( L, "reorder", false, true );
    1062         [ +  - ]:        253 :     get< tag::flux >() = string( L, "flux", "rusanov", true );
    1063         [ +  - ]:        253 :     get< tag::steady >() = boolean( L, "steady", false, true );
    1064         [ +  - ]:        253 :     get< tag::residual >() = real( L, "residual", 0.0, true );
    1065         [ +  - ]:        253 :     get< tag::rescomp >() = unsigint( L, "rescomp", 1, true );
    1066         [ +  - ]:        253 :     get< tag::part >() = string( L, "part", "rcb", true );
    1067         [ +  - ]:        253 :     get< tag::zoltan_params >() = stringlist( L, "zoltan_params", true );
    1068         [ +  - ]:        253 :     get< tag::solver >() = string( L, "solver", "riecg", true );
    1069         [ +  - ]:        253 :     get< tag::stab2 >() = boolean( L, "stab2", false, true );
    1070         [ +  - ]:        253 :     get< tag::stab2coef >() = real( L, "stab2coef", 0.2, true );
    1071         [ +  - ]:        253 :     get< tag::fct >() = boolean( L, "fct", true, true );
    1072         [ +  - ]:        253 :     get< tag::fctdif >() = real( L, "fctdif", 1.0, true );
    1073         [ +  - ]:        253 :     get< tag::fctclip >() = boolean( L, "fctclip", false, true );
    1074         [ +  - ]:        253 :     get< tag::fctsys >() = unsigints( L, "fctsys", true );
    1075         [ +  - ]:        253 :     get< tag::fctfreeze >() = real( L, "fctfreeze", -largereal, true );
    1076         [ +  - ]:        253 :     get< tag::freezeflow >() = real( L, "freezeflow", 1.0, true );
    1077         [ +  - ]:        253 :     get< tag::freezetime >() = real( L, "freezetime", 0.0, true );
    1078                 :            : 
    1079         [ +  - ]:        253 :     ic( L, *this );
    1080         [ +  - ]:        253 :     bc_dir( L, get< tag::bc_dir >(), true );
    1081         [ +  - ]:        253 :     bc_dirval( L, get< tag::bc_dirval >(), true );
    1082         [ +  - ]:        253 :     bc_sym( L, get< tag::bc_sym >(), true );
    1083         [ +  - ]:        253 :     bc_noslip( L, get< tag::bc_noslip >(), true );
    1084         [ +  - ]:        253 :     bc_far( L, *this );
    1085         [ +  - ]:        253 :     bc_pre( L, *this );
    1086         [ +  - ]:        253 :     problem( L, *this );
    1087         [ +  - ]:        253 :     mat( L, *this );
    1088         [ +  - ]:        253 :     fieldout( L, *this );
    1089         [ +  - ]:        253 :     histout( L, *this );
    1090         [ +  - ]:        253 :     integout( L, *this );
    1091         [ +  - ]:        253 :     diag( L, *this );
    1092         [ +  - ]:        253 :     href( L, *this );
    1093         [ +  - ]:        253 :     deactivate( L, *this );
    1094         [ +  - ]:        253 :     pressure( L, *this );
    1095         [ +  - ]:        253 :     momentum( L, *this );
    1096         [ +  - ]:        253 :     lb( L, *this );
    1097                 :            : 
    1098         [ +  - ]:        253 :     print << "Solver: " << get< tag::solver >() << '\n';
    1099                 :            : 
    1100                 :            :   } else {
    1101         [ -  - ]:          0 :     err = lua_tostring( L, -1 );
    1102                 :            :   }
    1103                 :            : 
    1104         [ +  - ]:        253 :   lua_close( L );
    1105                 :            : 
    1106 [ -  + ][ -  - ]:        253 :   ErrChk( err.empty(), "Lua error during control file parsing: " + err );
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
    1107                 :            : 
    1108                 :            :   // Output command line object to file
    1109 [ +  - ][ -  - ]:        253 :   auto logfilename = tk::inciter_executable() + "_control.log";
    1110         [ +  - ]:        253 :   tk::Writer log( logfilename );
    1111         [ +  - ]:        253 :   tk::print( log.stream(), *this );
    1112         [ +  - ]:        253 :   print << "Control data saved in " << logfilename << '\n';
    1113                 :        506 : }
    1114                 :            : 
    1115                 :            : } // ctr::
    1116                 :            : } // inciter::

Generated by: LCOV version 1.16