-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error in Adams-Bashforth integrator implementation #18
Comments
@milancurcic thank you for the check. Yes this is a bug/problem. I cannot access to a computer before two days, but in the meanwhile if you find a solution, feel free to push it to the upstream. |
@milancurcic As I said, today and maybe tomorrow I gave not a computer under my hands, but I think a simple solution is to modify the overloaded operators like this local_product%state = lhs%state * rhs%state to operate only on the current time level local_product%state = lhs%state
local_product%state(:, lhs%steps) = lhs%state(:, lhs%steps) * rhs%state(:, lhs%steps) The reason is: operators should operate only on the current time level while the other time steps stored should be used only by the time derivative that, in turn, is used be the multi-step integrator. Does this sound reasonable? |
@szaghi Do you mean the sum instead of the product? local_sum%steps = lhs%steps
local_sum%state(:, lhs%steps) = lhs%state(:, lhs%steps) + rhs%state(:, lhs%steps) I think this may be a step in the right direction. However, it would not work exactly as it is, because the tendency fields can have non-zero state elements at indices different from local_sum%state(:, lhs%steps) = lhs%state(:, lhs%steps) + rhs%state(:, 1) and if adding tendency from time level local_sum%state(:, lhs%steps) = lhs%state(:, lhs%steps) + rhs%state(:, 2) In some way, this function needs to be aware from which time level is the tendency being added to the field. One thing that I can think of right now is that the multi-step tendency field (i.e. result of the local_sum%state(:, lhs%steps) = lhs%state(:, lhs%steps) + sum(rhs%state,dim=2) because the sum along the second dimension of What do you think? |
Nope, what I was thinking is something different. Let us consider a generic operator (sum, multiply, etc...). The overloaded operator should be aware of only 1 time step, the current one, namely result%state(:, lhs%steps) = lhs%state(:, lhs%steps).op.rhs%state(:, lhs%steps) Then, let us consider the problem of tendencies summation. It is done via the time derivative function that must return a field = field + field%t(n=1) * (dt * self%b(1)) should be computed with:
I just thinking to an imaginary separation of the current time level from the previous one... maybe I can prove the concept implementing an actual separation storing the previous time level into a different array as a member of the Thank you Milan for you great help! |
I found a workstation and few minutes to test my idea... it seems to work. Briefly, I think that the problem (as you pointed out) was on the summation of tendencies due to the concurrent The oscillation test now produces the expected results. 1st order2nd order3rd order |
@szaghi Wonderful, thanks! It looks like AB2 and AB3 produce the expected solution. |
The
integrate
method of theadams_bashforth_integrator
class is implemented as:For simplicity, let's consider the 2nd order Adams-Bashforth (AB2).
field%state
then has the second dimension of size 2, which corresponds to the number of stored time levels. The solution to the ODE du/dt = F(u,t) using AB2 is:In the code, this is calculated with the loop:
which is equivalent to:
The problem that arises here is that
field%t(n=1) * (dt * self%b(1))
is added tofield
using the overloaded operator+
which performs element-wise sum for each respective array element. So, tendencies from each time level (n-2, n-1) are always added to the same time level, instead of time level n. The implementation is correct only for number of steps = 1, where the scheme degenerates to forward Euler, and there is only time level n in both the state and the tendency.Please discuss what would be the best way to solve this. Somehow we need to add the tendency from previous time levels to the field at the present time level, something like:
but this is not allowed because
integrand
is an abstract derived type, and we cannot access its state at this level in the code. Perhaps a solution would be to implement another method, perhapsfield%update()
, that would act to add tendencies from different time levels to state at the desired time level?The text was updated successfully, but these errors were encountered: