diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b018b0..fabf0fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,15 @@ history, so they summarise each release rather than list every change. The ### Fixed +- `setParameter[key="""..."""]` stores the value without the triple quotes, so + an inline multiline `fuelsTable` in a `.ff` script is read correctly. The + value may also contain `=`. +- `Balbi2020.Cpa` now sets the air heat capacity; the model used a fixed + 1150 J/kg/K whatever the parameter said. The default is now 1150, so results + do not change. +- `FDCellsOutputs=0` turns off the atmospheric cell debug output. The code + read `FDCellOutputs`, so the output was always on when `watchedProc` + selected the process. - The Farsite model now matches the FARSITE reference (mbedward/farsite) at the flanks and back of the fire, not only at the head. On slopes it is an approximation. This changes Farsite results. ([#270]) diff --git a/docs/source/user_guide/models.rst b/docs/source/user_guide/models.rst index b78f176..a4ee963 100644 --- a/docs/source/user_guide/models.rst +++ b/docs/source/user_guide/models.rst @@ -82,8 +82,8 @@ Balbi2020 It registers ``slope``, ``normalWind``, ``moisture``, ``temperature`` and the standard 20 ``fuel.*`` columns in :ref:`The Standard Rothermel / Balbi Fuel Table ` - (from ``fuel.Rhod`` to ``fuel.Blai``). The air heat capacity is fixed at - ``1150`` J/kg/K in the spread computation. + (from ``fuel.Rhod`` to ``fuel.Blai``). Optional parameter: + ``Balbi2020.Cpa``, the air heat capacity (default ``1150`` J/kg/K). BalbiNov2011, BalbiNov2011Curv and BalbiNov2011TMdMl ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/Command.cpp b/src/Command.cpp index f6783ed..e440869 100644 --- a/src/Command.cpp +++ b/src/Command.cpp @@ -18,6 +18,25 @@ using namespace std; +namespace +{ + // If `in`, once trimmed of surrounding whitespace, is wrapped in triple + // quotes, puts the text between them in `out` and returns true. + bool stripTripleQuotes(const std::string &in, std::string &out) + { + const std::string ws = " \t\r\n"; + const std::size_t first = in.find_first_not_of(ws); + if (first == std::string::npos) + return false; + const std::string trimmed = in.substr(first, in.find_last_not_of(ws) - first + 1); + if (trimmed.size() < 6 || trimmed.compare(0, 3, "\"\"\"") != 0 + || trimmed.compare(trimmed.size() - 3, 3, "\"\"\"") != 0) + return false; + out = trimmed.substr(3, trimmed.size() - 6); + return true; + } +} + namespace libforefire { @@ -308,16 +327,7 @@ namespace libforefire trimmed.erase(0, trimmed.find_first_not_of(" \t\r\n")); trimmed.erase(trimmed.find_last_not_of(" \t\r\n") + 1); - /* Triple‑quoted inline string? e.g. \"\"\"{ ... }\"\"\" */ - bool tripleQuoted = trimmed.size() >= 6 && - trimmed.substr(0, 3) == "\"\"\"" && - trimmed.substr(trimmed.size() - 3) == "\"\"\""; - - if (tripleQuoted) - { - geojsonText = trimmed.substr(3, trimmed.size() - 6); // strip outer quotes - } - else + if (!stripTripleQuotes(trimmed, geojsonText)) { /* Try to open it as a file path. */ std::ifstream jf(trimmed.c_str()); @@ -2034,34 +2044,25 @@ namespace libforefire } int Command::setParameter(const string &arg, size_t &/*numTabs*/) { - // Getting all the arguments, using the 'tokenize' function - // Returns strings of the form 'arg=...' - vector tmpArgs; - string delimiter = "="; - tokenize(arg, tmpArgs, delimiter); - if (tmpArgs.size() > 2) + // key=value, split on the first '=' so the value may contain '='. + // A leading '!' protects the key; a value wrapped in triple quotes + // (a multiline literal) is stored without them. + const size_t eq = arg.find('='); + if (eq == string::npos || eq == 0) { cout << "problem in the number of arguments when setting " << arg << endl; return error; } + const string key = arg.substr(0, eq); + string value = arg.substr(eq + 1); + const bool protect = !value.empty() && value[0] == '!'; + if (protect) + value = value.substr(1); + stripTripleQuotes(value, value); - // Check if the parameter value begins with '!' - if (!tmpArgs[1].empty() && tmpArgs[1][0] == '!') - { - // Remove the leading '!' to get the actual value. - std::string value = tmpArgs[1].substr(1); - // Set the parameter with a protection flag (true). - currentSession.params->setParameter(tmpArgs[0], value, true); - std::cout << "Parameter " << tmpArgs[0] - << " set to fixed protected value " << value << std::endl; - } - else - { - // Set the parameter normally (without protection). - currentSession.params->setParameter(tmpArgs[0], tmpArgs[1], false); - } - - currentSession.params->setParameter(tmpArgs[0], tmpArgs[1]); + currentSession.params->setParameter(key, value, protect); + if (protect) + cout << "Parameter " << key << " set to fixed protected value " << value << endl; return normal; } @@ -2435,6 +2436,10 @@ namespace libforefire while (std::getline(*inputStream, line)) { + // Scripts saved with CRLF line endings. + if (!line.empty() && line.back() == '\r') + line.pop_back(); + // A `quit[]` earlier in the script stops the file here rather than // ending the process, so the caller still gets to return normally. if (quitAsked) diff --git a/src/FireDomain.cpp b/src/FireDomain.cpp index eb8d0e5..bbb8c17 100644 --- a/src/FireDomain.cpp +++ b/src/FireDomain.cpp @@ -2526,7 +2526,7 @@ if ( params->getInt("FireDomainOutputs") != 0 ) outputs = true; if ( params->getInt("FireFrontOutputs") != 0 ) FireFront::outputs = true; if ( params->getInt("FireNodeOutputs") != 0 ) FireNode::outputs = true; - if ( params->getInt("FDCellOutputs") != 0 ) FDCell::outputs = true; + if ( params->getInt("FDCellsOutputs") != 0 ) FDCell::outputs = true; } // std::cout<<"ID"<getParameter("SOUTH")<<" WEST:"<getParameter("WEST")<<" NORTH:"<getParameter("NORTH")<<" EAST:"<getParameter("EAST")<isValued("Balbi2020.cooling") ) cooling = params->getDouble("Balbi2020.cooling"); - Cpa = 1004.; + Cpa = 1150.; if ( params->isValued("Balbi2020.Cpa") ) Cpa = params->getDouble("Balbi2020.Cpa"); } @@ -176,7 +176,6 @@ double Balbi2020::getSpeed(double* valueOf){ double lg = 9.81; double B = 5.6e-8; // nomenclature - double Cpa = 1150 ;// nomenclature double Tvap = 373; // nomenclature double K1 = 130 ;// nomenclature new parameter double st = 17 ;// nomenclature new parameter