38 #include <boost/algorithm/string/classification.hpp> 39 #include <boost/algorithm/string/split.hpp> 40 #include <boost/algorithm/string/predicate.hpp> 49 string DriverSteadyState::className
51 "SteadyState", DriverSteadyState::create);
52 string DriverSteadyState::driverLookupId
53 = LibUtilities::SessionReader::RegisterEnumValue(
54 "Driver",
"SteadyState",0);
59 DriverSteadyState::DriverSteadyState(
115 if (
m_comm->GetRank() == 0)
127 if (
m_session->GetSolverInfo(
"EqType") ==
"EulerCFE" ||
128 m_session->GetSolverInfo(
"EqType") ==
"NavierStokesCFE")
133 if(
m_session->DefinesSolverInfo(
"HOMOGENEOUS"))
135 if (
m_session->GetSolverInfo(
"HOMOGENEOUS") ==
"1D")
147 cout <<
"Besed on the dominant EV given in the xml file," 148 <<
"a 1D model is used to evaluate the optumum parameters" 149 <<
"of the SFD method:" << endl;
162 ofstream
m_file(
"ConvergenceHistory.txt", ios::out | ios::trunc);
223 if (
m_comm->GetRank() == 0)
225 cout <<
"\n\t The SFD method is converging: we compute " 226 <<
"stability analysis using the 'partially " 227 <<
"converged' steady state as base flow:\n" << endl;
233 A->GetAdvObject()->SetBaseFlow(q0,
m_equ[0]->UpdateFields());
236 if (
m_comm->GetRank() == 0)
259 if (
m_comm->GetRank() == 0)
261 cout <<
"\n\t We compute stability analysis using" 262 <<
" the current flow field as base flow:\n" 269 A->GetAdvObject()->SetBaseFlow(q0,
m_equ[0]->UpdateFields());
272 if (
m_comm->GetRank() == 0)
308 for(
int j = 0; j <
m_equ[
m_nequ - 1]->GetNvariables(); ++j)
312 if (
m_comm->GetRank() == 0)
314 out <<
"L 2 error (variable " <<
m_equ[
m_nequ - 1]->GetVariable(j)
315 <<
") : " << vL2Error << endl;
316 out <<
"L inf error (variable " <<
m_equ[
m_nequ - 1]->GetVariable(j)
317 <<
") : " << vLinfError << endl;
334 M11 = coeff*(1.0 + X*Delta*exp(-(X + 1.0/Delta)));
335 M12 = coeff*(X*Delta*(1.0 - exp(-(X + 1.0/Delta))));
336 M21 = coeff*(1.0 - exp(-(X + 1.0/Delta)));
337 M22 = coeff*(X*Delta + exp(-(X + 1.0/Delta)));
351 Vmath::Svtvp(q1[i].num_elements(),
M11, q0[i], 1, q1[i], 1, q1[i], 1 );
352 Vmath::Svtvp(q1[i].num_elements(),
M12, qBar0[i], 1, q1[i], 1, q1[i], 1 );
370 cout <<
"\n\tgrowthEV = " << growthEV << endl;
371 cout <<
"\tfrequencyEV = " << frequencyEV << endl;
373 complex<NekDouble> ApproxEV = polar(exp(growthEV), frequencyEV);
392 const complex<NekDouble> &alpha,
396 cout <<
"\n\tWe enter the Gradient Descent Method [...]" << endl;
397 bool OptParmFound =
false;
398 bool Descending =
true;
416 while (OptParmFound ==
false)
424 s = abs(0.000001/dirx);
425 X_output = X_input + s*dirx;
426 Delta_output = Delta_input + s*diry;
429 while (Descending ==
true)
433 Delta_input = Delta_output;
443 X_output = X_input + s*dirx;
444 Delta_output = Delta_input + s*diry;
447 if(stepCounter > 9999999)
453 Delta_init = Delta_init + Delta_init*0.1;
454 Delta_input = Delta_init;
462 cout <<
"\tThe Gradient Descent Method has converged!" << endl;
464 cout <<
"\n\tThe updated parameters are: X_tilde = " << X_output
465 <<
" and Delta_tilde = " << Delta_output << endl;
480 const complex<NekDouble> &alpha,
483 NekDouble A11 = ( 1.0 + X_input * Delta_input *
484 exp(-(X_input + 1.0/Delta_input)) )/(1.0 + X_input*Delta_input);
485 NekDouble A12 = ( X_input*Delta_input - X_input * Delta_input *
486 exp(-(X_input + 1.0/Delta_input)) )/(1.0 + X_input*Delta_input);
488 exp(-(X_input + 1.0/Delta_input)) )/(1 + X_input*Delta_input);
489 NekDouble A22 = ( X_input*Delta_input + 1.0 *
490 exp(-(X_input + 1.0/Delta_input)) )/(1.0 + X_input*Delta_input);
492 complex<NekDouble> B11 = alpha;
497 complex<NekDouble> a = A11*B11 + A12*B21;
499 complex<NekDouble> c = A21*B11 + A22*B21;
502 complex<NekDouble> delt = sqrt((a-d)*(a-d) + 4.0*b*c);
503 complex<NekDouble> lambda_1 = 0.5*(a+d + delt);
504 complex<NekDouble> lambda_2 = 0.5*(a+d - delt);
509 MaxEV = max(NORM_1, NORM_2);
514 int &KrylovSubspaceDim,
521 int NumLinesInFile = 0;
522 std::string EVfileName =
m_session->GetSessionName() +
".evl";
523 std::ifstream EVfile(EVfileName.c_str());
524 ASSERTL0(EVfile.good(),
"Cannot open .evl file.");
530 while(getline(EVfile, line))
538 if(NumLinesInFile < KrylovSubspaceDim*2.0
539 + KrylovSubspaceDim*(KrylovSubspaceDim+1.0)/2.0)
541 for(
int i = 1; i <= KrylovSubspaceDim; ++i)
543 if(NumLinesInFile == i*2.0 + i*(i+1.0)/2.0)
545 KrylovSubspaceDim = i;
552 EVfile.seekg(0, ios::beg);
556 for(
int i = 0; i < (NumLinesInFile - KrylovSubspaceDim); ++i)
558 std::getline(EVfile, line);
559 cout <<
"Discard line: " << line << endl;
562 std::vector<std::string> tokens;
563 std::getline(EVfile, line);
564 boost::algorithm::split(tokens, line,
565 boost::is_any_of(
"\t "),boost::token_compress_on);
568 "Unexpected formatting of .evl file while reading line:\n" 570 growthEV = boost::lexical_cast<
NekDouble>(tokens[4]);
571 frequencyEV = boost::lexical_cast<
NekDouble>(tokens[5]);
575 cout <<
"An error occurred when opening the .evl file" << endl;
593 MaxNormDiff_q_qBar=0.0;
594 MaxNormDiff_q1_q0=0.0;
598 NormDiff_q_qBar[i] =
m_equ[
m_nequ - 1]->LinfError(i, qBar1[i]);
599 NormDiff_q1_q0[i] =
m_equ[
m_nequ - 1]->LinfError(i, q0[i]);
601 if (MaxNormDiff_q_qBar < NormDiff_q_qBar[i])
603 MaxNormDiff_q_qBar = NormDiff_q_qBar[i];
605 if (MaxNormDiff_q1_q0 < NormDiff_q1_q0[i])
607 MaxNormDiff_q1_q0 = NormDiff_q1_q0[i];
616 if (
m_comm->GetRank() == 0)
619 <<
";\tTime: " << left <<
m_equ[
m_nequ - 1]->GetFinalTime()
620 <<
";\tCPU time = " << left <<
cpuTime <<
" s" 621 <<
";\tTot time = " << left <<
totalTime <<
" s" 622 <<
";\tX = " << left <<
m_X 623 <<
";\tDelta = " << left <<
m_Delta 624 <<
";\t|q-qBar|inf = " << left << MaxNormDiff_q_qBar << endl;
625 std::ofstream
m_file(
"ConvergenceHistory.txt", std::ios_base::app);
629 << MaxNormDiff_q_qBar <<
"\t" 630 << MaxNormDiff_q1_q0 << endl;
641 cout <<
"\n=====================================" 642 "==================================" 644 cout <<
"Parameters for the SFD method:" << endl;
645 cout <<
"\tControl Coefficient: X = " <<
m_X << endl;
646 cout <<
"\tFilter Width: Delta = " <<
m_Delta << endl;
647 cout <<
"The simulation is stopped when |q-qBar|inf < " <<
TOL << endl;
650 cout <<
"\nWe use the adaptive SFD method:" << endl;
651 cout <<
" The parameters are updated every " <<
AdaptiveTime 652 <<
" time units;" << endl;
653 cout <<
" until |q-qBar|inf becomes smaller than " <<
AdaptiveTOL 656 cout <<
"=====================================" 657 "==================================\n" << endl;
#define ASSERTL0(condition, msg)
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
void ConvergenceHistory(const Array< OneD, const Array< OneD, NekDouble > > &qBar1, const Array< OneD, const Array< OneD, NekDouble > > &q0, NekDouble &MaxNormDiff_q_qBar, NekDouble &MaxNormDiff_q1_q0)
void Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
svtvp (scalar times vector plus vector): z = alpha*x + y
virtual SOLVER_UTILS_EXPORT void v_InitObject(std::ostream &out=std::cout)
Second-stage initialisation.
virtual void v_InitObject(std::ostream &out=std::cout)
Virtual function for initialisation implementation.
void ComputeSFD(const int i, const Array< OneD, const Array< OneD, NekDouble > > &q0, const Array< OneD, const Array< OneD, NekDouble > > &qBar0, Array< OneD, Array< OneD, NekDouble > > &q1, Array< OneD, Array< OneD, NekDouble > > &qBar1)
int m_NonConvergingStepsCounter
void ReadEVfile(int &KrylovSubspaceDim, NekDouble &growthEV, NekDouble &frequencyEV)
std::shared_ptr< AdvectionSystem > AdvectionSystemSharedPtr
Shared pointer to an AdvectionSystem class.
LibUtilities::Timer timer
enum EvolutionOperatorType m_EvolutionOperator
Evolution Operator.
void GradientDescentMethod(const std::complex< NekDouble > &alpha, NekDouble &X_output, NekDouble &Delta_output)
void ComputeOptimization()
void EvalEV_ScalarSFD(const NekDouble &X_input, const NekDouble &Delta_input, const std::complex< NekDouble > &alpha, NekDouble &MaxEV)
virtual SOLVER_UTILS_EXPORT ~DriverSteadyState()
Destructor.
void SetSFDOperator(const NekDouble X_input, const NekDouble Delta_input)
Array< OneD, EquationSystemSharedPtr > m_equ
Equation system to solve.
NekDouble M11
Definition of the SFD operator.
DriverFactory & GetDriverFactory()
LibUtilities::CommSharedPtr m_comm
Communication object.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
NekDouble m_Delta
Definition of the SFD parameters:
virtual void v_Execute(std::ostream &out=std::cout)
Virtual function for solve implementation.
virtual SOLVER_UTILS_EXPORT void v_Execute(std::ostream &out=std::cout)
Virtual function for solve implementation.
A base class for PDEs which include an advection component.
std::shared_ptr< SessionReader > SessionReaderSharedPtr
LibUtilities::SessionReaderSharedPtr m_session
Session reader object.
int m_nequ
number of equations
bool FlowPartiallyConverged
For adaptive SFD method.