std::min function help

I have a simple question really

I am trying to find the minimum between two values and use it as a new value in a function. For example, in my code I am starting with time step "dt_max" and I want to find the min between it and another time step called "dt_D" and then assign this new value in "dt_max" to be used later in code. So something like:
 
dt_max = min([dt_max, dt_D]); (this is an example in MATALB)

For my C code I have tried to use an if statement (that doesn't work really) and I tried std::min that works but not necessarily gives correct output:
1
2
3
4
  double dt_max = 2.;
double dt_D = CFL/(D*pow(k,2)); //CFL and D are just constants given in code 
std::min(dt_max,dt_D);
//Use function to calculate new time step 

My question is how does C know that the min value from std::min is assigned back to dt_max to be used later in code? Is this expression valid in C?
1
2
3
4
  double dt_max = 2.;
double dt_D = CFL/(D*pow(k,2)); //CFL and D are just constants given in code 
double dt_max = std::min(dt_max,dt_D); // ??????
//Use function to calculate new time step 

Thanks
First, if you're able to use std::min, then your code is C++ (not C).

But more importantly,
and I tried std::min that works but not necessarily gives correct output
What do you mean by "doesn't give the correct output"? Please shown a minimum, compileable example along with your expected vs. actual output.

Your second code excerpt is not valid, because you are re-declaring dt_max.
Most programming languages do not use "variables" in the same way they are used in mathematics (as generic symbols).

In a program, each instruction is executed sequentially. For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Example program
#include <iostream>
#include <algorithm>

int main()
{
    double a = 42;   
    std::cout << "(1) Value of a: " << a << '\n';
    
    double b = 11;   
    std::cout << "(2) Value of a: " << a << '\n';
    
    a = std::min(a, b);       
    std::cout << "(3) Value of a: " << a << '\n';
    
    b = 10; // (does not retroactively affect previous assignments)
    std::cout << "(4) Value of a: " << a << '\n'; 
}

(1) Value of a: 42
(2) Value of a: 42
(3) Value of a: 11
(4) Value of a: 11


Let us know if that doesn't sufficiently alleviate your issue.
Last edited on
Yes, it's C++!

Well, the reason I say it is kinda working, because the code gives correct time step value for three iterations before blowing up. This is a small test for stability of my time step. The code was originally written in MATLAB and I am rewriting it in C++. So, in your small example you basically use "a" again in std::min without using double so it doesn't cause a re-declaration error?
I am trying to figure out why my code is blowing up in C++ but not the original MATLAB code with the same initializations/functions.

I can share the original code, which is pretty lengthy unfortunately, and I was not sure how to write a small example for it. The code, in line 216 is where I have some failed attempts in stabilizing my dt_max:
https://www.zipshare.com/download/eyJhcmNoaXZlSWQiOiI3NmIxODc3Mi05MTU1LTRmYzYtODY3OS03MzA0ZTk3MmI4NjQiLCJlbWFpbCI6ImFzdHJvbHVqeUBnbWFpbC5jb20ifQ==
Just write
if ( dt_max > dt _D ) dt_max = dt_D; // diffusion-limited timestep

If D is diffusivity in your code, what is k? Normally such timestep limiting is based on the spatial size, dx.
Last edited on
use std::min<double>(a,b)

example
dt_max = std::min<double>(dt_max,dt_D)
@JamieAl. Don't forget that std::min returns the min value that then needs to be assigned/used. It doesn't change either of the passed arguments.

Also, std::min() and std::max() can take more than one argument using {}. eg

 
const auto newmin {std::min({2, 3, 4, 1, 5})};


 
dt_max = min([dt_max, dt_D]); (this is an example in MATALB)


As a strict convert to C++, just replace the [] with {}:

 
dt_max = min({dt_max, dt_D});


For the original incorrect c++ code:

1
2
3
double dt_max = 2.;
double dt_D = CFL/(D*pow(k,2)); //CFL and D are just constants given in code 
std::min(dt_max,dt_D);


becomes:

1
2
const auto dt_D {CFL / (D * k * k)};
const auto dt_max {std::min(2.0, dt_D)};


auto means that the compiler will automatically assign the correct type to the variable based on the type from which it is being initialised.

const means that once initialised, the value can't change.

If the power is small, then consider using explicit multiplication which can have a better performance than using std::pow().

This assumes that either (or both) of D or CFL are already of type double. Note that integer division in C/C++ gives an int result. So 6 / 4 gives 1 and not 1.5 as might be expected - as 6 and 4 are of type integer! 6.0 / 4.0 gives 1.5 as both 6.0 and 4.0 are of type double. For division to give a result of type double, one of the values must be of type double.
Last edited on
lastchance, can you explain what a diffusion-limited timestep is? Never heard of such a thing. I looked it up and I am only finding scholarly articles that my eyes glaze over on.
Ganado wrote:
can you explain what a diffusion-limited timestep is?


https://en.wikipedia.org/wiki/Finite_difference_method#Explicit_method

If he has an explicit numerical method for a diffusion-like equation then, for numerical stability, his timestep dt must satisfy
D.(dt)/(dx)2 < C
where, for Forward Differencing, that constant C would be 1/2, but it might take other values for other schemes like Runge-Kutta. D is diffusivity, dt is timestep, dx is space step. I'm guessing that his k is a wavenumber and that he's Fourier-transforming or something, because k would have to be 1/dx.

He is, unfortunately, using a constant called CFL (Courant-Friedrichs-Lewy: look it up), which I (but not everybody) would usually associate with advection, not diffusion: CFL = u.dt/dx, where u is velocity. That imposes a different, usually more stringent, timestep limit for stability.

If he used an implicit numerical scheme (e.g. Backward Differencing, or, for a diffusion equation, Crank-Nicolson) rather than an explicit one then he is less likely to run into timestep problems.

But only the OP knows.
Last edited on
@lastchance
If D is diffusivity in your code, what is k? Normally such timestep limiting is based on the spatial size, dx.

So, kmax here is the wave number and is defined as:
 
double kmax= makeSpatialMesh2D(dx,dy,XX,YY);


where makeSpatialMesh2D is a function that gives the physical grid in x and y with 2D arrays XX and YY. D is the numerical diffusion and the effect of it is to damp the higher wavenumber modes.

I am using here a Pseudo-Spectral method for spatial discretization of my PDE and it uses Fourier series for the basis function and therefore has periodic BCs.

The CFL constant here is dependent on the time integration scheme which is Runge-Kutta Method and it is an explicit 4-stage RK.
Last edited on
Topic archived. No new replies allowed.