2024-03-11 14:55:19 +00:00
|
|
|
#include <iostream>
|
|
|
|
#include <vector>
|
|
|
|
#include <math.h>
|
2024-03-12 20:34:40 +00:00
|
|
|
#include <iomanip>
|
2024-03-11 14:55:19 +00:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
2024-03-13 10:06:11 +00:00
|
|
|
int l = 1925; // Edge length
|
|
|
|
int dx = 5; // Spatial step
|
|
|
|
int kmax = l / dx; // Number of spatial steps
|
2024-03-11 14:55:19 +00:00
|
|
|
|
2024-03-13 10:06:11 +00:00
|
|
|
/**
|
|
|
|
* Coefficients alpha and gamma are different for different
|
|
|
|
* edges. It depends on the edge's lenght, cross-sectional area etc.
|
|
|
|
*/
|
|
|
|
double alpha = 0.744;
|
2024-03-11 14:55:19 +00:00
|
|
|
double beta = 0.004;
|
2024-03-13 10:06:11 +00:00
|
|
|
double gamma = 5829;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* dt - the number of approximation in Euler method
|
|
|
|
* h - discretization step in Euler method
|
|
|
|
*
|
|
|
|
* Those two values work well with all existing steps and give us
|
|
|
|
* result that satisfies the initial condition pretty close.
|
|
|
|
*
|
|
|
|
* Changing of any of them might result in NaN error.
|
|
|
|
*/
|
|
|
|
int dt = 100000;
|
2024-03-12 20:34:40 +00:00
|
|
|
double h = 0.007;
|
|
|
|
|
2024-03-13 10:06:11 +00:00
|
|
|
// Stores the approximated values for each step
|
2024-03-12 20:34:40 +00:00
|
|
|
double Q[kmax][dt];
|
|
|
|
double P[kmax][dt];
|
2024-03-11 14:55:19 +00:00
|
|
|
|
2024-03-13 10:06:11 +00:00
|
|
|
// Prepare initial condition
|
2024-03-12 20:34:40 +00:00
|
|
|
for (int i = 0; i < dt; i++)
|
2024-03-11 14:55:19 +00:00
|
|
|
{
|
|
|
|
// Loop over spatial steps
|
|
|
|
for (int k = 0; k < kmax; k++)
|
|
|
|
{
|
|
|
|
// Boundary condition for the last spatial step
|
|
|
|
if (k == kmax - 1)
|
|
|
|
{
|
|
|
|
Q[k][i] = 0;
|
2024-03-12 20:34:40 +00:00
|
|
|
P[k][i] = -202.0; // P = -202 when Q = 10
|
2024-03-11 14:55:19 +00:00
|
|
|
} else
|
|
|
|
{
|
|
|
|
Q[k][i] = 0;
|
|
|
|
P[k][i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-13 10:06:11 +00:00
|
|
|
/**
|
|
|
|
* In fact, we have two 'steps'. The first step represents the approximation
|
|
|
|
* criteria in Euler's method (dt) and the second one represents the actual
|
|
|
|
* spatial step along the edge (dx).
|
|
|
|
*/
|
2024-03-12 20:34:40 +00:00
|
|
|
for (int i = 2; i < dt; i++)
|
2024-03-11 14:55:19 +00:00
|
|
|
{
|
|
|
|
// Loop over spatial steps
|
|
|
|
for (int k = 1; k < kmax; k++)
|
|
|
|
{
|
2024-03-12 20:34:40 +00:00
|
|
|
Q[k][i + 1] = Q[k][i] + h * (alpha * (P[k - 1][i] - P[k][i]) - beta * Q[k][i] * abs(Q[k][i]));
|
|
|
|
|
|
|
|
// DO NOT calculate pressure for the last element such as it is given by default
|
|
|
|
if (k != kmax - 1)
|
2024-03-11 14:55:19 +00:00
|
|
|
P[k][i + 1] = P[k][i - 2] + h * (gamma * (Q[k][i] - Q[k + 1][i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-13 10:06:11 +00:00
|
|
|
// Print out the first 10 values of Q for each spatial step
|
2024-03-11 14:55:19 +00:00
|
|
|
std::cout << "FIRST 10 VALUES\n";
|
|
|
|
for(int i = 0; i < kmax; i++)
|
|
|
|
{
|
|
|
|
std::cout.width(5);
|
|
|
|
std::cout.flags(std::ios::left);
|
|
|
|
std::cout << i << ": ";
|
|
|
|
|
|
|
|
for(int k = 0; k < 10; k++)
|
|
|
|
std::cout << std::setw(10) << Q[i][k];
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
|
2024-03-13 10:06:11 +00:00
|
|
|
// Print out the last 10 values of Q for each spatial step
|
2024-03-12 20:34:40 +00:00
|
|
|
std::cout << "LAST 10 VALUES:\n";
|
|
|
|
for(int i = 1; i < kmax; i++)
|
2024-03-11 14:55:19 +00:00
|
|
|
{
|
|
|
|
std::cout.width(5);
|
|
|
|
std::cout.flags(std::ios::left);
|
|
|
|
std::cout << i << ": ";
|
2024-03-12 20:34:40 +00:00
|
|
|
|
2024-03-11 14:55:19 +00:00
|
|
|
for(int k = 0; k < 10; k++)
|
2024-03-12 20:34:40 +00:00
|
|
|
std::cout << std::setw(10) << Q[i][dt - 10 + k];
|
2024-03-11 14:55:19 +00:00
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|