Skip to content

Commit ab5ab6c

Browse files
committed
some optimization
1 parent 9fd4ee0 commit ab5ab6c

4 files changed

Lines changed: 95 additions & 26 deletions

File tree

Common/include/option_structure.inl

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,6 @@ public:
9696
typeName(type_name) {
9797
}
9898

99-
~COptionScalar() = default;
100-
10199
string SetValue(vector<string> option_value) override {
102100
COptionBase::SetValue(option_value);
103101

@@ -155,14 +153,6 @@ public:
155153
}
156154
};
157155

158-
class COptionString final : public COptionScalar<string> {
159-
public:
160-
template<class... Ts>
161-
COptionString(Ts&&... args) :
162-
COptionScalar<string>("string", args...) {
163-
}
164-
};
165-
166156
class COptionBool final : public COptionScalar<bool> {
167157
public:
168158
template<class... Ts>
@@ -191,6 +181,38 @@ public:
191181
}
192182
};
193183

184+
class COptionString final : public COptionBase {
185+
protected:
186+
string& field; // Reference to the fieldname
187+
const string def; // Default value
188+
const string name; // identifier for the option
189+
190+
public:
191+
COptionString() = delete;
192+
193+
COptionString(const string& option_field_name,
194+
string& option_field,
195+
string default_value) :
196+
field(option_field),
197+
def(default_value),
198+
name(option_field_name) {
199+
}
200+
201+
string SetValue(vector<string> option_value) override {
202+
COptionBase::SetValue(option_value);
203+
204+
string out = optionCheckMultipleValues(option_value, "string", name);
205+
if (!out.empty()) return out;
206+
207+
field = option_value.front();
208+
return "";
209+
}
210+
211+
void SetDefault() override {
212+
field = def;
213+
}
214+
};
215+
194216
template <class Tenum, class TField>
195217
class COptionEnumList final : public COptionBase {
196218

Common/src/CConfig.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7315,6 +7315,13 @@ bool CConfig::TokenizeString(string & str, string & option_name,
73157315
// now fill the option value vector
73167316
option_value.clear();
73177317
last_pos = value_part.find_first_not_of(delimiters, 0);
7318+
7319+
// detect a raw string
7320+
if (value_part[last_pos] == '\'' && value_part.back() == '\'') {
7321+
option_value.push_back(value_part.substr(last_pos+1, value_part.size()-last_pos-2));
7322+
return true;
7323+
}
7324+
73187325
pos = value_part.find_first_of(delimiters, last_pos);
73197326
while (string::npos != pos || string::npos != last_pos) {
73207327
// add token to the vector<string>

SU2_CFD/include/output/COutput.hpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@
3939
#include "tools/CWindowingTools.hpp"
4040
#include "../../../Common/include/option_structure.hpp"
4141

42+
/*--- AD workaround for a cmath function not defined in CoDi. ---*/
43+
namespace mel::internal {
44+
inline su2double hypot(const su2double& a, const su2double& b) {
45+
return sqrt(a*a + b*b);
46+
}
47+
}
48+
#include "mel.hpp"
49+
4250
class CGeometry;
4351
class CSolver;
4452
class CFileWriter;
@@ -159,6 +167,20 @@ class COutput {
159167
//! Structure to store the value initial residuals for relative residual computation
160168
std::map<string, su2double> initialResiduals;
161169

170+
/** \brief Struct to hold a parsed user-defined expression. */
171+
struct CustomHistoryOutput {
172+
mel::ExpressionTree<passivedouble> expression;
173+
/*--- Pointers to values in the history output maps, to avoid key lookup every time. ---*/
174+
std::vector<const su2double*> symbolValues;
175+
bool ready = false;
176+
177+
su2double eval() const {
178+
return mel::Eval<su2double>(expression, [&](int i) {return *symbolValues[i];});
179+
}
180+
};
181+
182+
CustomHistoryOutput customObjFunc; /*!< \brief User-defined expression for a custom objective. */
183+
162184
/*----------------------------- Volume output ----------------------------*/
163185

164186
CParallelDataSorter* volumeDataSorter; //!< Volume data sorter
@@ -379,13 +401,6 @@ class COutput {
379401
return historyOutputPerSurface_Map.at(field)[iMarker].value;
380402
}
381403

382-
/*!
383-
* \brief Evaluate a custom expression of the history values.
384-
* \param[in] expression - Some user-defined math with the history field names as variables.
385-
* \return Result of the expression
386-
*/
387-
su2double ComputeCustomHistoryValue(const string& expression) const;
388-
389404
/*!
390405
* \brief Get a vector with all output fields in a particular group
391406
* \param groupname - Name of the history group
@@ -587,6 +602,13 @@ class COutput {
587602
}
588603
}
589604

605+
/*!
606+
* \brief Setup a custom history output object for a given expression.
607+
* \param[in] expression - Some user-defined math with the history field names as variables.
608+
* \param[out] output - Custom output ready to evaluate.
609+
*/
610+
void SetupCustomHistoryOutput(const string& expression, CustomHistoryOutput& output) const;
611+
590612
/*!
591613
* \brief Add a new field to the volume output.
592614
* \param[in] name - Name for referencing it (in the config file and in the code).

SU2_CFD/src/output/COutput.cpp

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@
2828
#include "../../../Common/include/geometry/CGeometry.hpp"
2929
#include "../../include/solvers/CSolver.hpp"
3030

31-
#include "mel.hpp"
32-
3331
#include "../../include/output/COutput.hpp"
3432
#include "../../include/output/filewriter/CFVMDataSorter.hpp"
3533
#include "../../include/output/filewriter/CFEMDataSorter.hpp"
@@ -264,30 +262,50 @@ void COutput::OutputScreenAndHistory(CConfig *config) {
264262
}
265263
}
266264

267-
su2double COutput::ComputeCustomHistoryValue(const string& expression) const {
265+
void COutput::SetupCustomHistoryOutput(const std::string& expression, CustomHistoryOutput& output) const {
268266

269267
std::vector<std::string> symbols;
270-
const auto tree = mel::Parse<passivedouble>(expression, symbols);
268+
output.expression = mel::Parse<passivedouble>(expression, symbols);
271269

272-
auto valueOfSymbol = [&](const std::string& symbol) {
270+
auto ptrToSymbolValue = [&](const std::string& symbol) {
273271
/*--- Decide if it should be per surface. ---*/
274272
const auto pos = symbol.find('[');
273+
const su2double* ptr = nullptr;
275274
if (pos == std::string::npos) {
276-
return GetHistoryFieldValue(symbol);
275+
const auto it = historyOutput_Map.find(symbol);
276+
if (it != historyOutput_Map.end()) {
277+
ptr = &(it->second.value);
278+
}
277279
} else {
278280
const auto name = std::string(symbol, 0, pos);
279281
const auto idx = std::stoi(std::string(symbol.begin()+pos+1, symbol.end()-1));
280-
return GetHistoryFieldValuePerSurface(name, idx);
282+
const auto it = historyOutputPerSurface_Map.find(name);
283+
if (it != historyOutputPerSurface_Map.end()) {
284+
ptr = &(it->second[idx].value);
285+
}
281286
}
287+
return ptr;
282288
};
283289

284-
return mel::Eval<su2double>(tree, symbols, valueOfSymbol);
290+
output.symbolValues.reserve(symbols.size());
291+
for (const auto& symbol : symbols) {
292+
const auto* ptr = ptrToSymbolValue(symbol);
293+
if (ptr == nullptr) {
294+
SU2_MPI::Error(std::string("Invalid history output (") + symbol + std::string(") used in expression:\n") +
295+
expression, CURRENT_FUNCTION);
296+
}
297+
output.symbolValues.push_back(ptr);
298+
}
299+
output.ready = true;
285300
}
286301

287302
void COutput::SetCustomAndComboObjectives(int idxSol, const CConfig *config, CSolver **solver) {
288303

289304
if (config->GetKind_ObjFunc() == CUSTOM_OBJFUNC && !config->GetCustomObjFunc().empty()) {
290-
solver[idxSol]->SetTotal_Custom_ObjFunc(ComputeCustomHistoryValue(config->GetCustomObjFunc()));
305+
if (!customObjFunc.ready) {
306+
SetupCustomHistoryOutput(config->GetCustomObjFunc(), customObjFunc);
307+
}
308+
solver[idxSol]->SetTotal_Custom_ObjFunc(customObjFunc.eval());
291309
}
292310
solver[idxSol]->Evaluate_ObjFunc(config, solver);
293311
SetHistoryOutputValue("COMBO", solver[idxSol]->GetTotal_ComboObj());

0 commit comments

Comments
 (0)