|
[Sponsors] |
November 14, 2023, 10:46 |
ODE solver in OpenFOAM
|
#1 |
Senior Member
|
Hi deal Foamers,
I have a couple of questions about the ODE solver in OpenFOAM. Question 1: In the file test-ODE.C I don't see the purpose of the following two lines: Code:
// Print the evolution of the solution and the time-step scalarField dyStart(ode.nEqns()); ode.derivatives(xStart, yStart, dyStart); is never used again later. The ODE is solved by calling the function Code:
odeSolver->solve(x, xEnd, y, dxEst); Question 2: In the ODESolver.C, the following two solve functions call each other recursively, so there seems to be a dead loop. Can anyone explain how they work? Code:
void Foam::ODESolver::solve ( scalar& x, scalarField& y, scalar& dxTry ) const { stepState step(dxTry); solve(x, y, step); dxTry = step.dxTry; } void Foam::ODESolver::solve ( scalar& x, scalarField& y, stepState& step ) const { scalar x0 = x; solve(x, y, step.dxTry); step.dxDid = x - x0; } Feel free to answer or discuss any of these questions. Thank you! Michael |
|
November 15, 2023, 07:09 |
|
#2 |
Senior Member
|
Many thanks for raising these issues!
Q1: not sure. Possibly it helps to write down the problem more formally, as \dot{y} = f(y(x), x) supplied with initial guess y(0) = y0 and try to reason on an algorithm from here. You raise the issue of derivatives. I assume that derivatives are used by implicit algorithms only. RK45 is an explicit algorithm. Not sure whether this helps. Q2: not sure either. It is possible that the size of the step is adapted inbetween calls of the solve function? I am happy to discuss further. |
|
November 15, 2023, 09:30 |
|
#3 | ||
Senior Member
|
[QUOTE=dlahaye;860062]Many thanks for raising these issues!
Thank you for the discussion. Quote:
Code:
Foam::scalar Foam::Euler::solve ( const scalar x0, const scalarField& y0, const scalarField& dydx0, const scalar dx, scalarField& y ) const { // Calculate error estimate from the change in state: forAll(err_, i) { err_[i] = dx*dydx0[i]; } // Update the state forAll(y, i) { y[i] = y0[i] + err_[i]; } return normalizeError(y0, y, err_); } By contrast, if we call Code:
void Foam::Euler::solve ( scalar& x, scalarField& y, scalar& dxTry ) const { adaptiveSolver::solve(odes_, x, y, dxTry); } Quote:
Code:
void Foam::ODESolver::solve ( scalar& x, scalarField& y, scalar& dxTry ) const { stepState step(dxTry); solve(x, y, step); dxTry = step.dxTry; } Code:
void Foam::ODESolver::solve ( scalar& x, scalarField& y, stepState& step ) const { scalar x0 = x; solve(x, y, step.dxTry); step.dxDid = x - x0; } Your response helped me to think more deeply. Hope more ideas can come in and clarify these issues. |
|||
November 16, 2023, 07:46 |
|
#4 |
Senior Member
|
Dear Michael,
I am confused about your most recent reply. I miss the head, body and tail of the points you raise. Is it valuable for you to re-iterative on the points you raise? Possibly it allows me to provide input. Thanks, Domenico. |
|
November 16, 2023, 09:41 |
|
#5 |
Senior Member
|
Sorry for the confusion. I came out of these thoughts when I was trying to comment on your comments, but I did not address your comments actually. Let me rephrase my thoughts.
(Q1) First of all, I don't think the derivatives are needed in the code of ODE-Test.C, because odeSolver->solve(x, xEnd, y, dxEst) takes care of the derivatives inside the function. However, if you call another version of solve function, such as odeSolver->solve(x0, y0, dydx0, dx, y), then we need to call ode.derivatives(x0, y0, dxdy0) explicitly. This responds to your comment: "Possibly it helps to write down the problem more formally, as \dot{y} = f(y(x), x) supplied with initial guess y(0) = y0 and try to reason on an algorithm from here." By the way, both the implicit and explicit ODE solver use the derivatives for the integration. Again, as a test code, the appearance of the unnecessary ode.derivatives is confusing. (Q2) "It is possible that the size of the step is adapted in-between calls of the solve function" Yes, the size of the step can be adapted by these in-between calls, but it does not explain how to exit the dead-loop call. My explanation is that these two functions are virtual functions in the base class (ODESolver), so if one of the two solve functions is (must be) overridden in the derived class, this call-loop will be broken. The design seems subtle and I cannot fully understand. Hope this makes more sense to you. Please feel free to share your inputs and post more discussion. |
|
Tags |
ode sovler, openfoam v2112 |
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Frequently Asked Questions about Installing OpenFOAM | wyldckat | OpenFOAM Installation | 3 | November 14, 2023 12:58 |
How to check the results of OpenFOAM Solver? | priyankap | OpenFOAM Running, Solving & CFD | 3 | April 8, 2019 04:18 |
How to contribute to the community of OpenFOAM users and to the OpenFOAM technology | wyldckat | OpenFOAM | 17 | November 10, 2017 16:54 |
Suggestion for a new sub-forum at OpenFOAM's Forum | wyldckat | Site Help, Feedback & Discussions | 20 | October 28, 2014 10:04 |
New OpenFOAM Forum Structure | jola | OpenFOAM | 2 | October 19, 2011 07:55 |