Solving Poisson's Equation using basic do-while loops - c++

My program runs. However, it seems that the do-while loop won't loop. This is because the output always declare "...was obtained after 1 iterations". I mean it should take more than 1 iterations. I would like to ask for help for I am facing a brick wall right now. Thanks!
#include <iostream>
#include <iomanip>
#include <cmath>
#include <fstream>
#include <string>
using namespace std;
int main()
{
int i,j,n,iter1=0,iter2=0;
double L,t,q,E,v,h,D,error,e;
cout << "\nUse length, L (m): ";
cin >> L;
cout << "\nUse thickness, t (m): ";
cin >> t;
cout << "\nUse uniform load, q (N/m^2): ";
cin >> q;
cout << "\nUse Young's modulus, E (N/m^2): ";
cin >> E;
cout << "\nUse Poisson's ratio, v: ";
cin >> v;
D=(E*pow(t,3))/(12*(1-pow(v,2)));
cout << "\nUse uniform interval, n: ";
cin >> n;
double u[n+1][n+1],r[n+1][n+1],w[n+1][n+1];
h = L/n;
cout << "\nUse tolerance, e: ";
cin >> e;
//PERFORM THE ITERATIONS!
cout << "* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" ;
cout.precision(5);
cout.setf(ios::fixed);
for (i=0;i<=n;i++)
for (j=0;j<=n;j++)
{
u[i][j]=0;
r[i][j]=0;
w[i][j]=0;
}
//Set the boundary conditions
for (i=0;i<=n;i++)
{
u[i][0]=0;
u[i][n]=0;
u[0][i]=0;
u[0][i]=0;
}
//Solving for the u-matrix
do
{
error=0;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
{
r[i][j]=0.25*(u[i-1][j]+u[i+1][j]+u[i][j-1]+u[i][j+1]-4*u[i][j]-pow(h,2)*(q/D));
u[i][j]+=r[i][j];
}
iter1++;
if (abs(r[i][j])>error)
error = abs(r[i][j]);
}
while (error>e);
//Solving for the w-matrix
do
{
error=0;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
{
r[i][j]=0.25*(w[i-1][j]+w[i+1][j]+w[i][j-1]+w[i][j+1]-4*w[i][j]-pow(h,2)*(u[i][j]));
w[i][j]+=r[i][j];
}
iter2++;
if (abs(r[i][j])>error)
error = abs(r[i][j]);
}
while (error>e);
//RESULTS!
cout << "\nThe matrix of deflection w was obtained after " << iter2 << " iterations" << endl;
cout << "\n(The matrix of variable u was obtained after " << iter1 << " iterations" << endl;
cout << "\n";
cout << "\nFor the matrix of deflection w, open the generated Excel file.\n";
return 0;
}

A better solution is to use a container, which will transparently manage assignment, copy, destruction, etc. without memory leaks.
There are plenty of implementations, here is a basic one
template<typename T>
class Matrix {
private:
unsigned int m_rows, m_cols;
std::vector<T> m_data;
public:
Matrix(unsigned int r, unsigned int c) // constructor
: m_rows{r}
, m_cols{c}
, m_data(r * c) // size of the vector
{}
T * operator[](int r) // address of first element of row r
{
return & m_data[ r * m_cols ];
}
};
Example of how to use it
Matrix<int> m(3,4); // declare a matrix
for (int r = 0; r < 3; r++)
for (int c=0; c<4; c++)
m[r][c] = 10*r + c; // usual notation
for (int r = 0; r < 3; r++) {
for (int c=0; c<4; c++) {
std::cout << m[r][c] << "\t";
}
std::cout << std::endl;
}

You can't declare arrays like that double u[n+1][n+1],r[n+1][n+1],w[n+1][n+1]; because variable n isn't known the time when array is declared. I guess it can't be declared that way even if the n is known during run time. It's possible only if the n is known during compilation.
The arrays should be declared as double **u; and when variable n is known use malloc or new.
int n;
double **u;
double **r;
double **w;
cout << "\nUse uniform interval, n: ";
cin >> n;
// C style of allocation, requires additional library, I think it's cstdlib
u = (double**)malloc(sizeof(double*)*(n+1));
for(int i = 0; i <= n; ++i) {
u[i] = (double*)malloc(sizeof(double)*(n+1));
}
// C++ style of allocation
r = new double*[n+1];
for(int i = 0; i <= n; ++i) {
r[i] = new double[n+1];
}
// C++11 or newer - compile with --c++11 flag
w = new double[n+1][n+1];
// Don't forget to clear memory
// C style
free(u);
// C++ style
delete r;
delete w;

Related

I need some assistance with creating a function

I am new, not that good with functions, and I am trying to solve this question:
Suppose A, B, C are arrays of integers of size [M], [N], and [M][N], respectively. The user will enter the values for the array A and B. Write a user defined function in C++ to calculate the third array C by adding the elements of A and B. If the elements have the same index number, they will be multiplied. C is calculated as the following: -
Use A, B and C as arguments in the function.
Below is my attempt at the problem.
#include<iostream>
using namespace std;
void Mix(int(&A)[], int(&B)[], int(&C)[][100], int N, int M);
//dont understand why you used Q
int main()
{
//variable declaration
int A[100], B[100], C[100][100], n, m, l = 0;
//input of size of elements for first ararys
cout << "Enter number of elements you want to insert in first array: ";
cin >> n;
cout << "-----------------" << endl;
cout << "-----------------" << endl;
cout << "Enter your elements in ascending order" << endl;
//input the elements of the array
for (int i = 0; i < n; i++)
{
cout << "Enter element " << i + 1 << ":";
cin >> A[i];
}
cout << endl << endl;
//input of size of elements for first ararys
cout << "Enter number of elements you want to insert in second array: ";
cin >> m;
cout << "-----------------" << endl;
cout << "-----------------" << endl;
cout << "Enter your elements in descending order" << endl;
//input the elements of the array
for (int i = 0; i < m; i++)
{
cout << "Enter element " << i + 1 << ":";
cin >> B[i];
}
Mix(A, B, C, n, m);
cout << "\nThe Merged Array in Ascending Order" << endl;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++)
{
cout << C[i][j] << " ";
}
cout << "\n"; //endline never use endl its 10 times slower
}
system("pause");
return 0;
}
void Mix(int(&A)[], int(&B)[], int(&C)[][100], int N, int M)
{
// rows is the index for the B array, cols is index for A array
int rows = 0;
int cols = 0;
while (rows < M) {
while (cols < N) {
if (rows == cols) { // remember ==
C[rows][cols] = B[rows] * A[cols];
}
else {
C[rows][cols] = B[rows] + A[cols];
}
cols++; // increment here
}
rows++; // increment here
}
return;
}
Here is an example of the output:
enter image description here
In order to make the C array two-dimensional, it needs to be expressed as C[100][100], instead of C[200]. That is the first step. Next, in your Mix() function, you need to cycle through each element of both A and B (ex. two for loops). Your rows change as B changes, and your columns change as A changes. Include a check for identical indices that will determine whether to add or multiply the two values together.
void Mix(int A[], int B[], int C[][], int N, int M) {
// rows is the index for the B array, cols is index for A array
for (int rows = 0; rows < M; rows++) {
for (int cols = 0; cols < N; cols++) {
if (rows == cols) { // remember ==
C[rows][cols] = B[rows] * A[cols];
} else {
C[rows][cols] = B[rows] + A[cols];
}
}
}
}
Make sure your arrays are properly defined and print out the C array by row and column to match the specifications.
UPDATE: If you want to use while loops, I would default to deconstructing the for loops and apply the same logic:
void Mix(int A[], int B[], int C[][], int N, int M) {
// rows is the index for the B array, cols is index for A array
int rows = 0;
int cols = 0;
while (rows < M) {
while (cols < N) {
if (rows == cols) { // remember ==
C[rows][cols] = B[rows] * A[cols];
} else {
C[rows][cols] = B[rows] + A[cols];
}
cols++; // increment here
}
rows++; // increment here
}
}
I would definitely recommend the for loop approach, as it is more compact, yet does the exact same operations.
There are a lot of things wrong with your code. First off an 2D array must be declared with 2 squared brackets so C[200][200]. In the Mix function the logical operator is == not = in if (A[I] = B[J])
Anyway here's the function that you need:
#include<iostream>
using namespace std;
void Mix(int A[], int B[], int C[], int N, int M) {
//dont understand why you used Q
int i, j;
for(i=0; i<N; i++) {
for(j=0; j<M; j++) {
if(i==j){
C[i][j] = A[i] * B[j];
}
else {
C[i][j] = A[i] + B[j];
}
}
}
return C[i][j];
}
int main()
{
//variable declaration
int A[100], B[100], C[200], j, i, n, m, l = 0;
string Comma;
//input of size of elements for first ararys
cout << "Enter number of elements you want to insert in first array: ";
cin >> n;
cout << "-----------------" << endl;
cout << "-----------------" << endl;
cout << "Enter your elements in ascending order" << endl;
//input the elements of the array
for (i = 0; i < n; i++)
{
cout << "Enter element " << i + 1 << ":";
cin >> A[i];
}
cout << endl << endl;
//input of size of elements for first ararys
cout << "Enter number of elements you want to insert in second array: ";
cin >> m;
cout << "-----------------" << endl;
cout << "-----------------" << endl;
cout << "Enter your elements in descending order" << endl;
//input the elements of the array
for (j = 0; j < m; j++)
{
cout << "Enter element " << j + 1 << ":";
cin >> B[j];
}
C = Mix(A, B, C, n, m);
cout << "\nThe Merged Array in Ascending Order" << endl;
for(i=0; i<n; i++) {
for(j=0; j<m; j++) {
cout<<C[i][j]<<" ";
}
cout<<"\n" //endline never use endl its 10 times slower
}
system("pause");
return 0;
}
Because M and N are defined at run time, you'll really want to use vectors to represent them. Additionally consider returning a 2D container so as to leverage return value optimization.
I'm going to write an example using a vector of vectors for simplicity (see What are the Issues with a vector-of-vectors? for more on why that's really just good for a toy example):
vector<vector<int>> Mix(const vector<int>& A, const vector<int>& B) {
vector<vector<int>> result(size(B), vector<int>(size(A)));
for(size_t i = 0U; i < size(B); ++i) {
for(size_t j = 0U; j < size(A); ++j) {
result[i][j] = A[j] * B[i];
}
}
return result;
}
Live Example
EDIT:
If you must use arrays you'll miss out on return value optimization. I'd only choose this as a good option in the situations:
That you weren't returning anything, in which case your function would probably look something like:
void Mix(const int* A, const int* B, const size_t size_A, const size_t size_B)
{
for(size_t i = 0U; i < size_B; ++i) {
for(size_t j = 0U; j < size_A; ++j) {
cout << '[' << i << "][" << j << "]: " << A[j] * B[i] << '\t';
}
cout << endl;
}
}
That you weren't calling a function and you'd already been given int A[M] and int B[N] as inputs and int C[N][M] as an output, in which case the code you'd inline would probably look something like this:
for(size_t i = 0U; i < size(B); ++i) {
for(size_t j = 0U; j < size(A); ++j) {
C[i][j] = A[j] * B[i];
}
}

Method declaration issue

The program should read n resistances and a voltage from the keyboard and then calculate the equivalent resistance and the current.
My problem is that it calculates based only on the last entered resistance.
Is it possible to declare a method inside a function? or should I give up this completely unpractical approach
#include "stdafx.h"
#include<iostream>
#include<conio.h>
using namespace std;
class rez {
float r;
public:
void set(int n);
float val() { return r; }
};
void rez :: set(int n) { //n is the number of resistances
int i;
for (i = 1; i <= n; i++) {
cout << "R" << i << "=";
cin >> r;
}
}
float serie(rez r1,int n)
{
float s=0;
int i;
for (i = 1; i <= n; i++)
{
s = s+ r1.val();
}
return s;
}
float para(rez r1, int n)
{
float s = 0;
int i;
for (i = 1; i <= n; i++)
{
s = s + (1/r1.val());
}
return 1/s;
}
int main()
{
char c, k = 'y'; // 'c' selects series or para
rez r1;
int n;
cout << "number of resis:";
cin >> n;
cout << endl;
while (k != 'q')
{
r1.set(n);
float i, u;
cout << "\n Vdc= ";
cin >> u;
cout << endl;
cout << "series or para(s/p)?"<<endl;
cin >> c;
switch (c)
{
case('s'):cout <<"\n equiv resistance = "<< serie(r1,n)<<endl;
i = u / serie(r1, n);
cout << "curr i = " << i << " amp";
break;
case('p'):cout << "\n equiv res = " << para(r1, n)<<endl;
i = u / para(r1, n);
cout << "cur i = " << i << " amp";
break;
}
cout <<endl<< "\n another set?(y/q)?"<<endl;
cin >> k;
}
return 0;
}
It is because when you read in the resistances you are setting the value of the total resistance each time not adding to the total resistance.
void rez :: set(int n) { //n is the number of resistances
int i;
for (i = 1; i <= n; i++) {
cout << "R" << i << "=";
cin >> r; // <- this sets the value of r, it does not add to it
}
}
To fix this you should create a temporary variable to store the input resistance and then add it to the total resistance
void rez :: set(int n)
{
int i;
for (i = 1; i <= n; i++)
{
float input;
cout << "R" << i << "=";
cin >> input;
r += input;
}
}

Using a Variable as an Array Parameter in C++

I am trying to write code that will compare a 10 sequence piece of DNA to that of a relative's 10 sequence DNA. The user inputs their name, how many relatives they want to compare, and their DNA. The computer outputs the percentage of a match. ATTAGACGCA compared to ATAAGACGCA would match 90%. The number of relatives is a constant after the user states how many relatives. I have tried using const, but it doesn't seem to want to use the number.
/**********************************************************************
* Get DNA Sequence
***********************************************************************/
void getMyDNA(char myDNA[])
{
cout << "Enter your DNA sequence: ";
cin >> myDNA;
}
/**********************************************************************
* Get Potential Relatives
***********************************************************************/
int getRelatives()
{
int relatives = 0;
cout << "Enter the number of potential relatives: ";
cin >> relatives;
return relatives;
}
/**********************************************************************
* Get Potential Relatives Names
***********************************************************************/
void getRelativeName(string relativeNames[], int relatives)
{
string name;
for (int i = 0; i < relatives; i++)
{
cout << "Please enter the name of relative #" << i + 1 << ": ";
cin >> name;
relativeNames[i] = name;
}
}
/**********************************************************************
* Get Potential Relatives DNA Sequence
***********************************************************************/
void getRelativeDNA(char relativeDNA[][10], string relativeNames[], int relatives)
{
for (int i = 0; i < relatives; i++)
{
cout << "Please enter the DNA sequence for " << relativeNames[i] << ": ";
cin >> relativeDNA[i];
}
}
/**********************************************************************
* Display Potential Relatives Match
***********************************************************************/
void displayMatch(string relativeNames, char relativeDNA[][10], int relatives, char myDNA[])
{
const int family = relatives;
int count[family] = 0;
for (int r = 0; r < 3; r++) //relative number r
{
for (int d = 0; d < 10; d++) //dna piece number d
{
if (relativeDNA[r][d] == myDNA[d])
count[r]++;
}
}
}
/**********************************************************************
* Main
***********************************************************************/
int main()
{
char myDNA[10];
string relativeNames[50];
char relativeDNA[50][10];
// My DNA
getMyDNA(myDNA);
//# of relatives
int relatives = getRelatives();
cout << endl;
//thier names
getRelativeName(relativeNames,relatives);
cout << endl;
//their dna
getRelativeDNA(relativeDNA,relativeNames,relatives);
cout << endl;
//display
displayMatch(relativeNames,relativeDNA,relatives,myDNA);
return 0;
}
Instead of
int count[relatives] = 0;
which is invalid as standard C++ when relatives can vary at run-time, use
std::vector<int> count( relatives );
Include the <vector> header.
If count is a new array create a new array dynamically as follows...
int *count = new int[relatives];
I noticed you're using the following later...
count++;
Are you trying to increment an integer or move a pointer? This code might help make it clearer...
#include <assert.h>
#include <iostream>
#include <typeinfo>
int main(void) {
const int x = 500;
int* a = new int[x];
size_t i = 0;
for(i = 0; i < x;i++) {
a[i] = i;
}
for(i = 0; i < x;i++) {
//Print numbers without moving pointer
std::cout << a[i] << std::endl;
}
for(i = 0; i < x;i++) {
//Print numbers moving pointer
std::cout << a[0] << std::endl;
a++;
}
a = a - x;
delete[] a;
return 0;
}
Even if the parameter is passed as const it won't work. You can try with an array created dynamically
int *count = new int[relatives];

Creating a Table of Powers with C++

I'm working on a project to print out a table of exponential numbers using nested for-loops. Users specify the number of rows to print and the number of powers. For example, if the users specifies 2 rows and 3 powers, the program should print 1,1,1 and 2,4,9 (2^1,2,3 etc). I should note this is for class and we aren't allowed to use cmath, otherwise I would use pow(). I can't seem to figure out the correct function in a nested for loop that can change both values of the base and the exponent. Here's what I have so far. Thanks for your help!
#include <iostream>
#include <iomanip>
using namespace std;
int main ()
{
int r, p, a;
cout << "The program prints a table of exponential powers.\nEnter the number of rows to print: ";
cin >> r;
cout << "Enter the number of powers to print: " ;
cin >> p;
cout << endl;
for (int i = 1 ; i <= r; i++)
{
cout << setw(2) << i;
for (int q = 1; q <= i; q++)
{
a = (q * q); //This only works for static numbers...
cout << setw(8) << a;
}
cout << endl;
}
}
for (int i = 1 ; i <= r; i++)
{
cout << setw(2) << i;
int a = 1;
for (int q = 1; q <= r; q++)
{
a = (a * i);
cout << setw(8) << a;
}
cout << endl;
}
Several things to note. First, you can compute the powers by maintaining the variable a and multiplying it by i for each power. Also, I think you want the upper bound on your second loop to be r and not i.
You need couple to change the way accumulate the values of raising a number to a power.
Also, you are using the wrong variable to end the loop in the inner for-loop.
#include <iostream>
#include <iomanip>
using namespace std;
int main ()
{
int r, p, a;
cout << "The program prints a table of exponential powers.\nEnter the number of rows to print: ";
cin >> r;
cout << "Enter the number of powers to print: " ;
cin >> p;
cout << endl;
for (int i = 1 ; i <= r; i++)
{
cout << setw(2) << i;
a = 1; // Start with 1
for (int q = 1; q <= p; q++) // That needs to <= p, not <= i
{
a *= i; // Multiply it by i get the value of i^q
cout << setw(8) << a;
}
cout << endl;
}
}

2D ArrayLoops C++

Having trouble getting my code to run properly, first time I have ever used C++ and just trying to learn it for my knowledge, I am trying to get a 2d array with all zeros except in the final column. Inputs are stock = 100, strike = 100, time to maturity = 1, interest rate = 0.06, time steps = 3, upfactor = 1.1, downfactor = 0.9091. The end Array should look like {[0,0,0,133.10], [0,0,0,110], [0,0,0,90.91], [0,0,0,75.13]}, bot for some reason I keep getting values in the first column as well and I am stumped. Any advice?
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <math.h>
#include <cmath>
using namespace std;
int main(int nNumberofArgs, char*pszArgs[])
{
double st;
cout << " Enter Value of stock: ";
cin >> st;
double K;
cout << " Enter Value of strike price: ";
cin >> K;
double t;
cout << " Enter time of maturity: ";
cin >> t;
double r;
cout << " Enter Value of the interest rate: ";
cin >> r;
int N;
cout << " Enter Value of time steps: ";
cin >> N;
double u;
cout << " Enter value of up factor: ";
cin >> u;
double d;
cout << " Enter Value of down factor: ";
cin >> d;
double dt;
dt = t/N;
double p;
p = (exp(r*dt)-d)/(u-d);
// Initialise asset price at maturity time step N
double price[N][N];
for( int i = 0; i < N+1; i++)
{
for (int j = 0; j<N+1; j++)
{
price[i][j] = 0;
}
}
price[N][N] = st*pow(d,N);
cout << "price[N][N] is equal to: " << price[N][N] << endl;
double newN;
newN = N-1;
//cout << price[2][0] << endl;
for(int ii = newN; ii >=0; ii--)
{
price[ii][N] = (price[ii+1][N]) * (u/d);
}
//cout << price[2][0] << endl;
for( int i = 0; i <= N; i++)
{
for (int j = 0; j <=N; j++)
{
cout << price[i][j] << " ";
}
cout << endl;
}
system("PAUSE");
return 0;
}
The problem area is
for(int ii = newN; ii >=0; ii--)
{
price[ii][N] = (price[ii+1][N]) * (u/d);
}
and not sure exactly how to fix it. Any thoughts??
In C/C++ indexes are from 0
double price[N][N];
or
double price[10][10];
means that you have an array from 0..9 and 0..9
so
price[N][N] = st*pow(d,N);
is writing to a location outside the arrays as the maximum index is price[N-1][N-1]
and for that reason, loops in C/C++
for( int i = 0; i <= N; i++)
should be written as
for( int i = 0; i < N; i++)
since N is not included as a valid index value for the array.
Couple of issues with your program.
You have created a double dimensional array on stack with variable sized length (N).
If your array size is dynamic don't create it on stack, use new to allocate it on heap.
Also, as I see it you are accessing out-of-array entries. (Index greater than max array index)