Help me tune numerically function misbehavior

I am experiencing some numerical misbehavior, probably because I’ve made some error writing the scripts (I am a newbie).

I wrote a code that makes a prefab “growing” following some mathematical rules. These rules are Ordinary Differential Equations solved by Runge-Kutta numerical method (https://www.codeguru.com/csharp/.net/net_general/arithmetic/article.php/c4597/Numerical-Computing-in-C.htm)

The growth script has a variable calculated as ODE solution each timestep:

``````public void UpdateGrowth()
{

if (timeManager.IsDayElapsed && timeManager.Seconds <= setup.SimulationTime)
{
if (internodeID <= setup.StaticGeneticInfo.MaxInternodeNumber)
setup.Manager.InternodesCurrentLenght[internodeID - 1] = transform.localScale.y;

float nextValue = nextStepValue.NextStepValue;
float dayCount = timeManager.Days;
annualLengthGrowth = Runge.runge(0.0f, 1.0f, nextValue, .1f, new Runge.Function(Equation.equation));

annualGrowth = new Vector3(annualWidthGrowth, annualLengthGrowth, annualWidthGrowth);

nextStepValue.NextStepValue = annualLengthGrowth;

currentLenght = (annualGrowth.y);
``````

The classRunge is the one for Runge-Kutta numerical method:

``````public class Runge
{
//declare a delegate that takes a float and returns
public delegate float Function(float dayCount, float annualGrowth);
public static float runge(float a, float b, float value, float step, Function f)
{
float dayCount,  w, k1, k2, k3, k4;
dayCount = a;
w = value;
for (int i = 0; i < (b - a) / step; i++)
{
k1 = step * f(dayCount, w);
k2 = step * f(dayCount + step / 2f, w + k1 / 2f);
k3 = step * f(dayCount + step / 2f, w + k2 / 2f);
k4 = step * f(dayCount + step, w + k3);
w = w + (k1 + 2f * k2 + 2f * k3 + k4) / 6f;
dayCount = a + i * step;
}
return w;
}
}
``````

The equation to solve is in equation script:

``````    public void Update()
{
dayCount = time.Days;
}

public static float equation(float dayCount, float annualGrowth)
{
float y_prime;

float maxLenght = (1 - (setup.Manager.TotalLenght() / maxTreeHeight));
temp = (float)-Math.Pow(((180 - dayCount) / 180), 2) * a + a;
alfaT = temp / a;
y_prime = alfaT * annualGrowth * (1 - (annualGrowth / maxLenght));

return y_prime;
}
``````

While the daycount is given by timemanager script:

``````private void Start()
{
isdayElapsed = false;
}

private void Update()
{
rate += Time.deltaTime;

if (rate > 1)
{
rate = 0;
seconds++;
days++;
isdayElapsed = true;
}

if (days > 365)
{
days = 0;
}
}
``````

The issue I am experiencing is that in the equation script, the dayCount variable is passed from 0 to 1, then from 1 is “resetting” calculating back from 0. This made annualLenghtGrowth in growth script miscalculated. Of course it should continue with 2, 3 ,4 and so on until 365.
It looks like is resetting each update while the dayCount is working fine.
Thank you

``````annualLengthGrowth = Runge.runge(0.0f, 1.0f, nextValue, .1f, new Runge.Function(Equation.equation));
``````

Looks to me like your code is just always passing 0 and 1 into the function. Maybe you meant to pass the day count?

the dayCount is passed via the Runge.Function. 0 and 1 is the range of Runge-Kutta method calculation

`public static float runge(float a, float b, float value, float step, Function f)`

Fourth order Runge Kutte method for y’=f(t,y) solves first order ODE in the interval (a,b) with a given initial condition (value) and fixed step (step) as seen in the link I provided in my first post

I don’t understand your function/math at all. But what I do see is this. You are getting the day count from `timeManager`:

``````float dayCount = timeManager.Days;
annualLengthGrowth = Runge.runge(0.0f, 1.0f, nextValue, .1f, new Runge.Function(Equation.equation));
``````

But as far as I can tell, the day count value is completely ignored. You recalculate it inside Runge.runge from `a ` So what is the point of the dayCount variable or timeManager?

Part of the confusion here is probably from obscure variable names. You have variables like `a` `w` `b` what are the meanings of these variables? Hard to tell.

You should sprinkle your code with Debug.Log statements to make sure variables are what you expect at certain points. Or better yet, use Visual Studio’s debugger and step through the execution to see what’s going wrong.

That’s what I did and how I recognized the strange behavior.
In equation script, even if `time.Days` returns the correct value, `dayCount` is wrong

`a`; `w`; `b` variables are just used in Runge-Kutta numerical method to solve the ODE (equation).
To explain better, take a look at these screenshot:

`a` and `b` is the given range (first bullet point in the screen t = 0…10);
`w` is yn+1
`nextValue` is the first initial condition (y0 in the screen above)
`step` is the given step value (dt = 0.1 in the screen above)

That’s the thing though. You have multiple variables in your program called `dayCount`

in your screenshot of the debugger, there is a static variable called `dayCount` and there is a function parameter for the `equation` function called `dayCount`. These are two completely different variables that have no relation to one another. When you have two variables with the same name in a scope, the variable that was declared in the smaller scope wins out. This means when you access `dayCount` in the `equation` function you can see the function parameter `dayCount`, but not the static variable `dayCount`.

Ok, so (sorry for the stupid question) how could I “trace back” to see where the dayCount I pass as parameter to the function is?

Not sure what you mean by that, but the easiest way to resolve your confusion will be to simply rename the static variable dayCount so you don’t have any name conflicts. Then go back through your code and make sure you’re using the correct variables everywhere you see dayCount.

In debugger go one frame up the call stack. But it’s in your Runge.runge function when you call the f() function look at what you are passing in. From there you see it comes from the “a” variable.