CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (https://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   Adaptive time step control for generic problems (https://www.cfd-online.com/Forums/openfoam-programming-development/130001-adaptive-time-step-control-generic-problems.html)

chriss85 February 18, 2014 03:28

Adaptive time step control for generic problems
 
Hello,

I'm working on a solver that employs other equations than flow, like radiation and electromagnetic equations.
The solver is very dependent on the time step size, it quickly diverges and crashes if it gets too high. I'm wondering if I can implement a time step control that considers every field, and not just the flow. I found this post for residual based time step control:
http://www.cfd-online.com/Forums/ope...tml#post240272

Is this a feasible approach for transient problems where no steady solution is expected, due to unsteady boundary conditions?

What kind of control loop would I use? A PID loop, separately for each residual, and use the minimum time step then?

Or are there other methods I could try for stabilizing the solver? Maybe use different schemes? Unfortunately robust schemes like upwind make no sense for equations unrelated to the flow...are there others that could be used here?

chriss85 February 18, 2014 09:14

I have it half-way working for absolute tolerances...

I added a residualDict:
Code:

IOdictionary residualDict
(
    IOobject
    (
        "residualDict",
        runTime.system(),
        mesh,
        IOobject::MUST_READ,
        IOobject::NO_WRITE
    )
);

dictionary relDict(residualDict.subDict("relative"));
dictionary absDict(residualDict.subDict("absolute"));

And then calculate a measure for an error indicator:
Code:

forAll(absDict.toc(), i)
        {
            if(mesh.solverPerformanceDict().lookupEntry(absDict.toc()[i]) != NULL)
            {
                List<solverPerformance> perf = mesh.solverPerformanceDict().lookup(absDict.toc()[i]);
                scalar delta = perf.first().initialResidual() - absDict.lookupOrDefault<scalar>(absDict.toc()[i], 1e-3);
                Info << absDict.toc()[i] << ": "  << perf.first().initialResidual() << " - " << absDict.lookupOrDefault<scalar>(absDict.toc()[i], 1e-3) << " = " << delta << endl;
                absError = i == 0 ? delta : max(absError, delta);
            }
        }

        Info << "absError: " << absError << endl << "deltaT: " << runTime.deltaT() << " --> ";
        if(absError < 0)
            runTime.setDeltaT(runTime.deltaT() * residualDict.lookupOrDefault<scalar>("increase", 1.1));
        else
            runTime.setDeltaT(runTime.deltaT() / residualDict.lookupOrDefault<scalar>("decrease", 2));

In general this is working, however, I have some issues with vectorFields. The residual stored in solverPerformance is only of scalar type, looking in fvMatrixSolve.C reveals that it's the maximum component of the vector. I would like to use individual residuals for every component though, which are also printed in the console.

Is there any other place where OF exposes the residual data, or do I need to modify the OF core files for this?

Relative tolerances aren't implemented yet, but will be in the future. I'll post the example code as reference then.
Having relative tolerances requires storing the initial residuals from a previous time step, by doing this I also get the benefit of being able to use a PID loop instead of this simple control loop here.

jherb February 18, 2014 10:05

This bug report and the links within it might help:
http://www.openfoam.org/mantisbt/view.php?id=270


All times are GMT -4. The time now is 02:45.