i want to implement crank-nicolson method in c++ according to that :
−ru(i−1,j+1) + 2(1 + r)u(i,j+1) − ru(i+1,j+1) = 2(1 − r)u(i,j) + r
(u(i−1,j)+ u(i+1,j) )
I use gauss-jordan method to solve the system but i can't figure how to implement the above formula.
const double pi=3.14159265;
double f (double x){
return sin(pi*x);
}
using namespace std;
//gauss-jordan
double* gauss(int n ,double **a){
double factor;
double *b,*x;
x=new double[n];
b=new double[n];
for (int k=1;k<=n;k++) {
for (int i=1;i<=n;i++) {
if (i!=k) {
factor=a[i][k]/a[k][k];
for (int j=1; j<=n; j++ ) {
a[i][j]=a[k][j]*factor-a[i][j];
}
b[i]=b[k]*factor -b[i];
}
}
}
for (int i=1;i<=n;i++) {
x[i]=b[i]/a[i][i];
}
return x;
}
int main()
{
int i,j,n,m,xd,td;
double h,k,r;
double **t,**p;
//----- initialize double pointer------------------
double **u;
u=new double *[m];
for (int o=1;o<=m;o++){
u[o]=new double [n];
}
//----- end of initialization-----------------------
cout <<"\nEnter the value of x dimension : \n";
cin >> xd;
cout <<"\nEnter the step size h for x dimension : \n";
cin >>h;
cout <<"\nEnter the value of time dimension : \n";
cin >>td;
cout<<"\nEnter the step k of time dimension : \n";
cin >>k;
n=xd/h -1.0;
m=td/k -1.0;
cout <<"\n\nThe internal elements of x dimension are :"<<n;
cout <<"\nThe internal elements of t dimension are :"<<m;
r=k/(h*h);
cout <<"\nThe r value is : "<<r;
//initial conditions
for (j=0;j<=m;j++){
u[0][m]=0;
u[10][m]=0;
}
//get the function
for (i=1;i<n;i++){
u[i][0]=f(i*h);
}
//apply crank-nicolson
for (i=1;i<n;i++){
for (j=1;j<n;j++){
-r*u[i-1][j+1] +2.0*(1.0+r)*u[i][j+1] -r*u[i+1][j+1]=2.0*(1.0-r)*u[i][j] +r*(u[i-1][j]+u[i+1][j]);
} // here i can't figure the steps i must follow in order for this to work
//-----delete double pointer-------------
for(int o=1;o<m;o++){
delete [] u[o];
delete [] u;
}
//---------------------------------------
return 0;
}
I am assuming that the variable j represents the time steps. In order to implement Crank-Nicolson, you have to pose the problem as a system of linear equations and solve it. The matrix corresponding to the system will be of tridiagonal form, so it is better to use Thomas' algorithm rather than Gauss-Jordan.
The linear system will be of the form A x = b, with x being the vector (..., u(i-1, j+1), u(i, j+1), u(i+1, j+1), ...) and b being the vector (..., r u(i−1,j), 2(1 − r)u(i,j), r u(i+1,j), ...). The i-th row of the matrix A will be of the form
(0, ..., 0, −r, 2(1 + r), −r, 0, ..., 0). You will have to be careful with the first and last rows, where you'll have to substitute the boundary conditions for your problem.
A good reference for finite difference methods and Crank-Nicolson in particular is the book by John Strikwerda.
Hope this helps.
C++ is not an equation solving system. = does not have the meaning of equals as it does have in math, but mean assignment.
As such having anything complex like you have on the left side makes no sense, what you probably want to do is to solve the equation so there is a single variable that is being assigned to, possibly with an equation solving program.
Related
So essentially, I'm trying to code a small block that should create or generate coefficients for polynomial n-degree that can be represented through vector which is a=[a0, a1..an] given the basic formula is
Well, the issue is when doing a function to get value of polynomial P from point "x" it returns value from entirely using Horner's Rule which it's not the same result as intended although not sure which one I should put on. The math basic explanation tells me at least something out of:
E.g: n=2; (A[i] stack terms by 4, 2, 1) and calculates P(value of x) = 4 * x ^ 0 – 2 * x ^ 1 + 1 * x ^ 2 = 4 – 2x + x2 = x2 – 2x + 4 = 4
With other words , can't find the culprit when for "x" value is meant to go through "i" variable numbered wrong by exponent and the result gets output for P(0)=7 while it shouldn't be and concrete as in P(0) = 0 ^ 2 – 2 * 0 + 4 = 4
Here's a little snippet went through so far, I would appreciate if someone could point me in the right direction.
double horner(const double&x, const int& n, const double& nn) {
if (n < 0)
return nn;
else {
double m; cin>>m;
return horner(x, n-1, nn*x+m);
}
}
int main() {
int n;double x;
cout << "n=";cin >> n;
cout << "x=";cin >> x;
cout << "P(0)=" << horner(x, n, 0);
return 0;
}
Edit: My brain farted for a moment somewhere while was coding and continuously revising the case, I forgot to mention what exactly are the parts of each variables for the program to avoid confusion yes, so:
n, polynomial grade;
p, polynomial coefficient;
x, the point in which evaluates;
And here given the grade equation to polynomial
which any negative and positive input terms adding by exponent to these coefficients are the steps that holds the result exception, hence the reason Horner's rule that it reduces the number of multiplication operations.
Edit: After few hours, managed to fix with polynomial evaluating issue, the only question remains how I'd suppose to generate coefficients using method std::vector ?
float honer(float p[], int n, float x)
{
int i;
float val;
val = p[n];
for (i = n - 1; i >= 0; i--)
val = val * x + p[i];
return val;
}
int main()
{
float p[20]; // Coefficient of the initial polynomial
int n; // Polynomial degree -n
float x; // Value that evaluates P -> X
cout << "(n) = ";
cin >> n;
for (int i = n; i >= 0; i--)
{
cout << "A[" << i << "]=";
cin >> p[i];
}
cout << "x:= ";
cin >> x;
cout << "P(" << x << ")=" << honer(p, n, x);
//Result (input):
//n: 2,
//P[i]: 4, -2, 1 -> x: 0, 1
// Result (output):
//P() = 4
}
Expect some certain output scenarios given below input if assigned:
I'm trying to translate this series into a code that give me the sum of it. Here is the series:
X + (-1/3)X^3 + (1/5)X^5 + (-1/7)X^7 + …. +((-1)^(n-1)/2n-1)X^(2n-1)
That's the code (by the way I can't use cmath library..):
#include <iostream>
using namespace std;
int main()
{
cout << "enter 2 numbers: \n";
int x, n;
cin >> x;
do
{
cin >> n;
if (n <= 0) cout << "ERROR \n";
} while (n <= 0);
int i{ 1 }; // index for the first organ and so on.
double denom{ 2.0 * i - 1 }; // the denominator and the power in the equation.
bool posCardinal{ 1 }; // check if the cardinal is positive.
int cardinal{ 1 };
if (posCardinal) cardinal = 1;
else cardinal = -1;
double factor{ cardinal / denom }; // the factor.
int xValue{ x }; // the value of X each time.
double an{ factor * xValue }; // general organ.
double sum{ 0 }; // the total sum.
for (i = 1; i <= n; ++i)
{
factor = cardinal / denom;
for (int j{ 1 }; j < denom && i != 1; ++j)
{
xValue *= x;
}
an = factor * xValue;
sum += an;
xValue = x;
!posCardinal;
}
cout << sum;
}
Why doesn't the code show me the sum?
Thank you all very much!!
As you are working with fractions in the series, you should think about using float or double (depending on what precision do you need) for your x, xValue, sum, an and factor (as its value is 1/some_int, so if factor is int, then the value will almost always be 0).
Your second problem are both for nested loops, which do not have any incrementer, so they work endlessly, similarly to while (true){...} loop - almost always i is smaller than denom (only if i=1 the value of denom is 1). You should think about rebuilding these functions to work on some other variable, let's say j. Then you could count n-th power of x this way:
for (int j = 0; j < denom; j++)
xValue *= xValue;
There are still few things you should fix, e.g your denom does not change its value when the program is running, it has fixed value after you first declare it after i.
I want to find the sum up to the 'n'th term for the following series:
(1/2)+((1*3)/(2*4))+((1*3*5)/(2*4*6))....
So, I wrote the following program in c++ :
#include <bits/stdc++.h>
#include <conio.h>
using namespace std;
int main()
{
int p=1, k=1, n=0;
float h=0;
cout<<"Enter the term: ";
cin>>n;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=i; j++)
{
p*=((2*j)-1);
k*=(2*j);
}
h+=(p/k);
p=1;
k=1;
}
cout<<"The sum is : "<<h;
return 0;
getch();
}
However, the output of the program always gives me '0'. I can't figure out the problem with the program.
N.B. I'm new to programming.
The problem here is that you haven't declared p and k as float or doubleor explicitly cast them as such before the calculation and assignment to h.
What's happening is for every iteration of the loop p < k (by nature of the problem) since p and k are both declared as int, p / k = 0. So you're just summing 0 for every iteration.
Either declare p and k as float or double or do this:
h += ((float) p) / ((float) k)
Also, for this specific problem I assume you're looking for precision, so be wary and look into that as well Should I use double or float?
implicit conversion and type casting are a trap where all newbies fall.
in the instruction:
h += p/k;
the compiler performs an integer division first, then a promotion of the result to floating point type.
and since:
p < k ; for all i,j < n
then:
res = (p / k) < 1 => truncates to 0; // by integer division
thus:
sum(1->n) of p/k = sum (1->n) 0 = 0;
finally:
h = conversion to float of (0) = 0.0f;
that's why you have the result of 0.0f at the end.
the solution:
1- first of all you need to use the natural type for floating point of c++ which is "double" (under the hood c++ promotes float to double, so use it directly).
2- declare all your variable as double, except the number of terms n:
3- the number of terms is never negative, you need to express that in your code by declaring it as an unsigned int.
4- if you do step 3, make sure to catch overflow errors, that is if the user enters a negative number your risk to have a very big number in "n", expel : n =-1 converts to 0xffffffff positive number.
5- engineer your code sometimes is better.
6- include only the headers that you need, and avoid a importing any namespace in your global namespace.
here is how i think you should write your program.
#include <iostream>
double sum_serie(unsigned int n)
{
double prod = 1.0, sum = 0.0;
for (double c=1; c<=n ; c++)
{
prod *= ( ( 2*c ) - 1 ) / ( 2*c ); // remark the parenthesis
sum += prod;
}
return sum;
}
int main()
{
unsigned int n = 0;
int temp = 0;
std::cout << " enter the number of terms n: ";
std::cin >> temp;
if (temp > 0)
n = temp; // this is how you catch overflow
else
{
std::cout << " n < 0, no result calculated " << std::endl;
return 0;
}
std::cout << " the result is sum = " << sum_serie(n) << std::endl;
return 0;
}
I know that the question was about the implicit conversion and casting in C++, but even the way of writing a code can show you what bugs you have in it, so try to learn a proper way of expressing your ideas into code, debugging comes natural afterward.
Good Luck
The following code uses Euler's Method to approximate a value of y(x). My code currently accepts the endpoints a and b as user input and values for values for alpha which is the initial condition and the step size value which is h. Given my code I can now approximate a value of y, say y(8) given the initial condition y(0)=6.
However I have a small mistake in my code and I am not quite sure how to fix it and am looking for help. Right now my code does not check to ensure that the right endpoint b is an integer multiple of the stepsize h. Due to this the final approximation may not be for f(b) but for f(c) where c is the closest integer multiple of h to b. I am looking for some help on how to fix this, Thanks!
#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
double dydx (double x, double y)
{
double f = y*(2-y)/(x+3);
return f;
}
int main()
{
double a,b,alpha,h,z;
cout<<"\nEnter the value of endpoint a: \n";
cin>>a;
cout<<"\nEnter the value of endpoint b: \n";
cin>>b;
cout<<"\nEnter the y value of the initial condition: \n";
cin>>alpha;
cout<<"\nEnter the stepsize, h: \n";
cin>>h;
cout<<"\n";
while((b-a)>0.0000001)
{
z=alpha+(h*dydx(a,alpha));
cout<<"z("<<a<<")="<<z<<endl;
alpha=z;
a=a+h;
}
cout<<"\nThe approximate solution of y("<<b<<") is "<<z<<"."<<endl;
return 0;
}
You can calculate step size h from number of steps n:
#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
double dydx (double x, double y)
{
double f = y*(2-y)/(x+3);
return f;
}
int main()
{
double a,b,alpha,h,z;
cout<<"\nEnter the value of endpoint a: \n";
cin>>a;
cout<<"\nEnter the value of endpoint b: \n";
cin>>b;
cout<<"\nEnter the y value of the initial condition: \n";
cin>>alpha;
/*
* Obtains step size from number on steps
* h = 0.1 for [a; b] = [0; 8] can be given by n = 80
*/
int n = 0;
cout<<"\nEnter the number of steps, n: \n";
cin>>n;
h = (b - a) / n;
//------
cout<<"\n";
//-- Replaced 0.0000001 by h / 2.0 --
while((b-a)> h / 2.0)
{
z=alpha+(h*dydx(a,alpha));
alpha=z;
a=a+h;
/*
* z - function value in next point,
* so to output correct point a need to be incremented before this.
*/
cout<<"z("<<a<<")="<<z<<endl;
}
cout<<"\nThe approximate solution of y("<<b<<") is "<<z<<"."<<endl;
return 0;
}
Insert this instead of h input.
I have a function, fx named and has two input variable as an array and a double, so I wrote my program like this and I am faced with below error. The problem is in definition of input array but I don't know how to solve it.
And another problem is when I want to call this fx function with inputs, how can I give a complete array as the first input variable — fx(matris[n],x)?
error : variable-size type declared outside of any function
Code:
#include<iostream>
using namespace std;
int n=1;
double y=1;
double x;
double fx(double matris[], double x){
double f = 0;
for(int i=0;i<n;i++)//e.g f(X)= 3x^2 + 2x -4 = 0 [3 2 -4]
{
y = 1;
for(int k = 0;k<n-i-1;k++){//temp: y = x*x*x or x*x or x ... (calcules powers)
y = y*x;
}
f = f+y*matris[i];// 3 * y((x*x)) + 2 * y((x)) + -4* y(1)
}
return f;
}
double dif(double matris[], double x){
double temp[n];
temp[0] = 0;
for (int i=0;i<n;i++){
temp [i+1] = matris[i] * (n-i-1);
}
return fx(temp[n], x);
}
int main(){
//newton-raphson method to solve a equilibrium
cout << "please enter the degree of your equilibrium: ";
cin >> n;
double matris[n];
cout << "please enter your equlibruim array: ";
for(int i =0; i<n; i++)
cin >> matris[i];
//x = x0 - f(x)/f'(x);
x = 1;
fx(matris,x);
return 0;
}
Since arrays passed to a function don't actually have a size (variable or otherwise), the compiler objects to you passing a variable n as the size of matris.
Just remove the n from your double matris[n] expression, leaving the square brackets empty.
[Note that the code doing cin > n; double matris[n]; is not standards compliant C++ - C++14 will introduce such a concept, but for existing C++ standards, it is not allowed - only GNU C++ and some "GNU C++ compatible" compilers support this construct].