I have a variable of type const int, but the parameters that it’s dependent upon are of type double. When I try to cast this down from a ‘double’ to a ‘const int’, it doesn’t work properly. For example, when N should be 991, it is entered as 990. I’ve tried several methods and only one has worked, but I’m not sure if this method is going to work all the time. Here are some methods that I have tried:
First method:
const int N = (Ls-1)/dx + 1;
Second Method:
const int N = static_cast<const int>((Ls-1)/dx) + 1;
Third Method:
double Z = (Ls-1)/dx + 1;
const int N = Z;
Fourth Method (only working method):
double Z = (Ls-1)/dx;
const int N = Z + 1;
Please note that dx is a value such that the remainder of (Ls-1)/dx will always be zero (i.e. it’s always an integer value). Can anyway explain why the other methods aren’t working so that I may understand type casting better?
EDIT: As requested, I’m uploading the entire code to show how everything is working:
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <fstream>
#include <cmath>
#include <algorithm>
#define pi 3.14159265
using namespace std;
//Define Fluid Properties
double rho_L = 998; //Liquid Density
double rho_LG = 828.9; //Liquid-Gas Density Ratio
double mu_L = 0.000798; //Liquid Viscosity
double mu_LG = 40.24; //Liquid-Gas Viscosity Ratio
double sigma = 0.0712; //Surface Tension
double nu_G = (mu_L/mu_LG)/(rho_L/rho_LG);
//Define Injector Properties
double Uinj = 56.7; //Injection Velocity
double Dinj = 0.0998; //Injector Diameter
double theta = 15.0*pi/180.0; //Spray Cone Angle
double L = 500.0*Dinj; //Atomization Length
double Ls = L/Dinj; //Normalized Atomization Length
//Define Solver Parameters
double K = 5294; //Viscous Dissipation Coefficient
double Eps = pow(10,-5); //Residual Error
double dx = 0.0001; //Step Size
double Ui = 10; //Initial Guess
//const int Z = static_cast<const int>((Ls-1)/dx + 1) + 1;
const int N = (Ls-1)/dx + 1;//Z;
double deriv (double U, double X, double delta, double m)
{
double dudx;
dudx = -(1.0/delta)*(1.0/U)*(U - sqrt(1.0 - U)/sqrt(m*X*X))*(U - sqrt(1.0 - U)/sqrt(m*X*X));
return (dudx);
}
int main()
{
//Declare Variables
int max_step;
double ERR;
int step;
double DEN;
double SMD;
double m;
double Ug;
double Re;
double Cd;
double delta;
double K1;
double K2;
double K3;
double K4;
//Allocate Memory From Heap
double *U = new double [N];
double *X = new double [N];
//Initialize Vectors and Variables
DEN = 0.5*rho_L - (4.0/3.0)*K*(mu_L)/(Uinj*Dinj*Dinj)*L;
m = 4.0/rho_LG*tan(theta)*tan(theta);
for (int i = 0; i < N; i++)
{
X[i] = 1.0 + dx*i;
}
U[0] = 1.0;
max_step = 1;
ERR = 1;
step = 0;
while(abs(ERR) > Eps && step < max_step)
{
//Calculate Ug
Ug = sqrt(1.0 - (Ui/Uinj))/sqrt(m*Ls*Ls)*Uinj;
//Calculate SMD
SMD = 6.0*sigma/(DEN*(Uinj*Uinj - Ui*Ui));
//Calculate Re # and Drag Coefficient
Re = abs(Ui-Ug)*SMD/nu_G;
if(Re <= 0.01)
{
Cd = (0.1875) + (24.0/Re);
}
else if(Re > 0.01 && Re <= 260.0)
{
Cd = (24.0/Re)*(1.0 + 0.1315*pow(Re,(0.32 - 0.05*log10(Re))));
}
else
{
Cd = (24.0/Re)*(1.0 + 0.1935*pow(Re,0.6305));
}
//Determine New U
delta = (4.0/3.0)*(1.0/Cd)*(rho_LG)*(SMD/Dinj);
//RK4
for (int i = 0; i < N-1; i++)
{
K1 = deriv(U[i],X[i],delta,m);
K2 = deriv(U[i]+0.5*dx*K1,X[i]+0.5*dx,delta,m);
K3 = deriv(U[i]+0.5*dx*K2,X[i]+0.5*dx,delta,m);
K4 = deriv(U[i]+dx*K3,X[i+1],delta,m);
U[i+1] = U[i] + dx/6.0*(K1 + 2.0*K2 + 2.0*K3 + K4);
//if(i >= 0 && i <= 3)
//cout << i << " " << K1 << " " << K2 << " " << K3 << " " << K4 << " " << U[i] << endl;
}
ERR = abs(U[N-1]*Uinj - Ui)/Ui;
Ui = U[N-1]*Uinj;
step = step + 1;
}
SMD = 6.0*sigma/(DEN*(Uinj*Uinj - Ui*Ui));
cout << "U = " << Ui << endl;
cout << "SMD = " << SMD << endl;
cout << "DEN = " << DEN << endl;
cout << "Ug = " << Ug << endl;
cout << "m = " << m << endl;
cout << "delta = " << delta << endl;
cout << "Re = " << Re << endl;
cout << "Cd = " << Cd << endl;
cout << "U* = " << U[N-1] << endl;
cout << "Error = " << ERR << endl;
cout << "step = " << step << endl;
//Output Data Into Text File
ofstream outputdata("result-500-15.txt");
for (int i = 0; i < N; i++)
{
outputdata << X[i] << " " << U[i] << '\n';
}
outputdata.close();
delete [] U;
delete [] X;
return 0;
}
Your guess is correct: 0.1 doesn’t have a finite expression in binary. This is a rather complex issue and has many corner cases that will not be solved in general by adding 0.01 as mentioned in your comment. (It highly depends on the values you expect etc.)
Your question suggests that the quotient is always supposed to be an integer. In that case, the right approach to maintain correct results is to not use any
doubles to begin with (forLs,dx,Z). Either use a fractional type (nothing built-in in C++, use your own or a library), an arbitrary-precision decimal type (again, use a library likegmp– sensible if you know all your numbers have a terminating decimal expression), or, easiest: If bothLsanddxare guaranteed to have at mostndigits after the decimal point, multiply both by10^nand use integral types.Okay, your code is very different from what I expected. In this case, in my opinion, the right thing is to fix the number of steps
Nand calculatedxfrom that rather than the other way round:If you want to start with a value for dx and choose N such that the calculated value for dx, ask the user when the program starts: