Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit 6beb4f4

Browse files
qichenghuaOpenModelica-Hudson
authored andcommitted
Experimental rounding error fixing for fluid models in MSL
1 parent faa82e6 commit 6beb4f4

File tree

2 files changed

+63
-44
lines changed
  • SimulationRuntime/cpp

2 files changed

+63
-44
lines changed

SimulationRuntime/cpp/Include/Solver/Nox/Nox.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ class Nox : public IAlgLoopSolver
5353
*_y0,
5454
*_y_old,
5555
*_y_new,
56-
*_yScale;
56+
*_yScale,
57+
_locTol,
58+
_currentIterateNorm,
59+
*_currentIterate;
5760

5861
Teuchos::RCP<NoxLapackInterface> _noxLapackInterface;
5962

SimulationRuntime/cpp/Solver/Nox/Nox.cpp

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Nox::Nox(INonLinearAlgLoop* algLoop, INonLinSolverSettings* settings)
3030
, _firstCall (true)
3131
, _generateoutput (false)
3232
, _useDomainScaling (false)
33+
, _currentIterate (NULL)
3334
{
3435
_dimSys=_algLoop->getDimReal();
3536
}
@@ -42,6 +43,7 @@ Nox::~Nox()
4243
if(_y_new) delete [] _y_new;
4344
if(_yScale) delete [] _yScale;
4445
//if(_noxLapackInterface) delete _noxLapackInterface;
46+
if(_currentIterate) delete [] _currentIterate;
4547

4648
}
4749

@@ -64,6 +66,7 @@ void Nox::initialize()
6466
_y_old = new double[_dimSys];
6567
_y_new = new double[_dimSys];
6668
_yScale = new double[_dimSys];
69+
_currentIterate = new double[_dimSys];
6770

6871
_algLoop->getReal(_y);
6972
_algLoop->getReal(_y0);
@@ -92,10 +95,14 @@ void Nox::solve()
9295
double * rhs = new double[_dimSys];
9396
double sum;
9497

98+
_locTol=5.0e-7;
99+
_currentIterateNorm=1.0e2;
100+
95101
_output = Teuchos::rcp(new std::stringstream);
96102
if (_firstCall) initialize();
97103

98104
// Set up the status tests
105+
// can be moved to initialize.
99106
_statusTestNormF = Teuchos::rcp(new NOX::StatusTest::NormF(1.0e-13));
100107
_statusTestMaxIters = Teuchos::rcp(new NOX::StatusTest::MaxIters(100));
101108
_statusTestStagnation = Teuchos::rcp(new NOX::StatusTest::Stagnation(15,0.99));
@@ -272,8 +279,6 @@ void Nox::solve()
272279
}
273280
}
274281

275-
int numberofdifferentnormtests=5;//this variable is used twice.
276-
277282
_algLoop->setReal(_y);
278283
try{
279284
_algLoop->evaluate();
@@ -300,53 +305,55 @@ void Nox::solve()
300305
if (_generateoutput) std::cout << "simtime=" << _algLoop->getSimTime() << std::endl;
301306
_iterationStatus=DONE;
302307
}else{
303-
//skip iter=1,2,4,6,7,9,11,12,13
304-
305-
if (iter==11){
306-
iter = 14;
307-
}
308-
if (iter==9){
309-
iter = 10;
310-
}
311-
if (iter==6){
312-
iter = 8;
313-
}
314-
if (iter==4){
315-
iter = 5;
316-
}
317-
if (iter==0){
318-
iter = 3;
319-
}
320-
if ((iter == 1) || (iter == 2) || (iter == 4) || (iter == 6) || (iter == 7) || (iter == 9)){
321-
std::cout << "You failed heavily at iter = " << iter << " and simtime " << _algLoop->getSimTime() << std::endl;
308+
if(true){
309+
try{
310+
_algLoop->setReal(_y);
311+
_algLoop->evaluate();
312+
_algLoop->getRHS(rhs);
313+
314+
double*ypluseps=new double [_dimSys];
315+
double*rhs2=new double [_dimSys];
316+
memcpy(ypluseps,_y,_dimSys*sizeof(double));
317+
for(int i=0;i<_dimSys;i++){
318+
ypluseps[i]*=(1.0+std::numeric_limits<double>::epsilon()*8.0);//increase _ypluseps in the smallest amount possible.
319+
}
320+
_algLoop->setReal(ypluseps);
321+
_algLoop->evaluate();
322+
_algLoop->getRHS(rhs2);
323+
double threshold=0.0;
324+
for(int i=0;i<_dimSys;i++){
325+
threshold+=(rhs2[i]-rhs[i])*(rhs2[i]-rhs[i]);
326+
}
327+
threshold=std::sqrt(threshold);
328+
329+
delete [] ypluseps;
330+
delete [] rhs2;
331+
332+
if(_statusTestNormF->getNormF()<2*threshold){
333+
std::cout << "threshold (this should typically be a very small value (we vary the real value by ). In case of occurence of rounding errors, the threshold should be big though.) = " << threshold << ", simtime = " << _algLoop->getSimTime() << ", algloop " << _algLoop->getEquationIndex() << std::endl;
334+
_algLoop->setReal(_y);
335+
_algLoop->evaluate();
336+
_algLoop->getRHS(rhs);
337+
_iterationStatus=DONE;
338+
break;
339+
}
340+
}
341+
catch(const std::exception &ex)
342+
{
343+
if (_generateoutput) std::cout << "algloop evaluation after solve failed with error message:" << std::endl << ex.what() << std::endl << "Trying to continue without. This should hopefully lead to statusTest::Failed." << std::endl;
344+
}
322345
}
323346

324-
switch(iter%(numberofdifferentnormtests)){
325-
case 0:
326-
*_statusTestNormF=NOX::StatusTest::NormF(1.0e-13);
327-
break;
328-
case 1:
329-
*_statusTestNormF=NOX::StatusTest::NormF(1.0e-11);
330-
break;
331-
case 2:
332-
*_statusTestNormF=NOX::StatusTest::NormF(1.0e-9);
333-
break;
334-
case 3:
335-
*_statusTestNormF=NOX::StatusTest::NormF(1.0e-7);
336-
break;
337-
default:
338-
*_statusTestNormF=NOX::StatusTest::NormF(1.0e-5);
339-
break;
340-
}
341-
_statusTestsCombo = Teuchos::rcp(new NOX::StatusTest::Combo(NOX::StatusTest::Combo::OR, _statusTestNormF, _statusTestMaxIters));
342-
_statusTestsCombo->addStatusTest(_statusTestStagnation);
343-
_statusTestsCombo->addStatusTest(_statusTestDivergence);
347+
// if(_statusTestNormF->getNormF()<std::min(_locTol,_currentIterateNorm)){
348+
// memcpy(_currentIterate,_y,_dimSys*sizeof(double));
349+
// _currentIterateNorm=_statusTestNormF->getNormF();
350+
// }
344351

345-
switch (iter/numberofdifferentnormtests){
352+
switch (iter){
346353
case 0:
347354
break;
348355
//default Nox Line Search failed -> Try damped Newton instead
349-
case 1:
356+
case 1://should delete this. It typically does not help (verify this))
350357
_solverParametersPtr->sublist("Line Search").sublist("Full Step").set("Full Step", 0.5);
351358

352359
//default Nox Line Search failed -> Try Backtracking instead
@@ -415,6 +422,14 @@ void Nox::solve()
415422

416423
//Tensor failed or other failure
417424
default:
425+
if(_currentIterateNorm<_locTol){
426+
memcpy(_y,_currentIterate,_dimSys*sizeof(double));
427+
_iterationStatus=DONE;
428+
break;
429+
}
430+
if(_currentIterateNorm<_locTol){
431+
std::cout << "you should not see this." << std::endl;
432+
}
418433
int numberofhomotopytries = 0;
419434
while((_iterationStatus!=DONE)){
420435
//todo: This is implemented in the worst way possible. Please fix this.
@@ -430,6 +445,7 @@ void Nox::solve()
430445
}
431446
numberofhomotopytries++;
432447
}
448+
433449
break;
434450
}
435451
//comment in for debugging

0 commit comments

Comments
 (0)