In the following, you see my c++ code that it solves 1-d Schrödinger equation with Numerov's method. But I have two problems:
When I increase the size of the box, the wave function for the ground state will be zero, the problem is in Normalization and I do not know why.
It is too slow, I need to increase box sufficiently large, any idea about how to speed up would be great.
This is my code:
#include <iostream>
#include <math.h>
#include <fstream>
#include <string>
#include <iomanip>
#include <sstream>
using namespace std;
#define pi 3.1415926535897932384626433
class ID_TISE{
public:
ID_TISE(int N_graid, int x_min, int x_max, double dx, double e_tr, double de, double e_up, double m, double h_bar, double c);
~ID_TISE();
//functions
double Potential(char, int);
double PotentialIon(char, int);
void Setk2(double *k2, double E, int N, char lr);
void Numerov(double *psi, double *k2, int N);
double diff_slope(double e_tr,int N_L, int N_R);;
string string_precision(int, int);
double x(char lr, int index);
void Numerov_Solver(double*, double*);
void id_tise();
int N_graid ;
double x_min;
double x_max;
double dx;
//set trial energy
double e_tr;
double de;
double e_up;
int N_E = 10000;
//constant
double m ;
double h_bar;
double c; // second point of the wavefunctions
//array
double *psi_l = NULL;
double *psi_r = NULL;
double *k2_l = NULL;
double *k2_r = NULL;
};
ID_TISE::ID_TISE(int N_graid, int x_min, int x_max, double dx, double e_tr, double de, double e_up, double m, double h_bar, double c){
this->N_graid = N_graid;
this->x_min = x_min;
this->x_max = x_max;
this->dx = dx;
this->e_tr =e_tr;
this->de = de;
this->e_up = e_up;
this->m = m;
this->h_bar=h_bar;
this->c=c;
psi_l = new double[N_graid];
psi_r = new double[N_graid];
k2_l = new double[N_graid];
k2_r = new double[N_graid];
}
ID_TISE::~ID_TISE(){
delete[] psi_l;
delete[] psi_r;
delete[] k2_l;
delete[] k2_r;
}
void ID_TISE::id_tise(){
ofstream fout;
int im = int(N_graid/2);
int N_R = N_graid - im + 2;
int N_L = im + 2;
//initialization left solution
psi_l[0] = 0.0;
psi_l[1] = c;
//initialization right solution
psi_r[0] = 0.0;
psi_r[1] = c;
int ii = 0, inode = 0, inodeUp = 1;
while(e_tr < e_up){
double ds1 = diff_slope(e_tr,N_L,N_R);
e_tr += de;
double ds2 = diff_slope(e_tr,N_L,N_R);
if(ds1*ds2 < 0.0){
if(e_tr < -9.0e-7 || e_tr > 9.0e-7){ // to prevent reaching to E = 0
cout <<"E_"<<ii++ <<" = "<< e_tr << endl;
Normalizer(psi_r,im);
Normalizer(psi_l,im);
fout.open("psi_"+string_precision(ii,0)+ ".dat");
if(e_tr < 0){
if(inode%2 != 0.){
for(int i = 0; i < im; i++)
fout << x('l',i) << "\t" << -psi_l[i] << endl;
}
else{
for(int i = 0; i < im; i++)
fout << x('l',i) << "\t" << psi_l[i] << endl;
}
for(int i = im-1; i > -1; i--)
fout << x('r',i) << "\t" << psi_r[i] << endl;
inode++;
}
else{
if(inodeUp%2 == 0.){
for(int i = 0; i < im; i++)
fout << x('l',i) << "\t" << -psi_l[i] << endl;
}
else{
for(int i = 0; i < im; i++)
fout << x('l',i) << "\t" << psi_l[i] << endl;
}
for(int i = im-1; i > -1; i--)
fout << x('r',i) << "\t" << psi_r[i] << endl;
inodeUp++;
}
fout.close();
}
}
else continue;
}
}
void ID_TISE::Normalizer(double *psi,int N){
double sum = 0.;
for(int i=0 ; i<N ; i++)
sum += psi[i]*psi[i]*dx;
sum=sqrt(sum);
for(int i=0 ; i<N ; i++){
psi[i]=psi[i]/sum;
}
}
void ID_TISE::Numerov(double *psi, double *k2 , int N){
double h12 = (dx*dx)/12.;
for(int i = 1; i < N; i++){
psi[i+1] = (2.*(1.-5.*h12*k2[i])*psi[i] - (1. + h12*k2[i-1])*psi[i-1])/(1. + h12*k2[i+1]);
}
}
void ID_TISE::Setk2(double *k2, double E, int N, char lr){
for(int i = 0; i < N; i++){
if(E > 0)
k2[i] = (2.*m/(h_bar*h_bar))*(E - PotentialIon(lr,i));
else
k2[i] = (2.*m/(h_bar*h_bar))*(E - Potential(lr,i));
}
}
double ID_TISE::Potential(char lr, int index){
return -1./sqrt(x(lr, index)*x(lr, index)+2.);
}
double ID_TISE::PotentialIon(char lr, int index){
return 0.;
}
double ID_TISE::x(char lr, int index){
if(lr == 'l')
return x_min + (index)*dx; // dx = h
else
return x_max - (index)*dx; // the right solution
}
double ID_TISE::diff_slope(double e_tr, int N_L, int N_R){
double dslope;
//initialization left solution
psi_l[0] = 0.0;
psi_l[1] = c;
//initialization right solution
psi_r[0] = 0.0;
psi_r[1] = c;
Setk2(k2_l, e_tr, N_L, 'l');
Setk2(k2_r, e_tr, N_R, 'r');
Numerov(psi_l, k2_l, N_L);
Numerov(psi_r, k2_r, N_R);
double y_m = (psi_l[N_L-1]+psi_r[N_R-1])/2.;
dslope = (2.*y_m - psi_l[N_L - 3] - psi_r[N_R - 3])/(dx*psi_r[N_R - 2]);
return dslope;
}
string ID_TISE::string_precision(int value, int n_digits){
if(n_digits < 6) n_digits = 6;
ostringstream out;
out << fixed<<setprecision(n_digits) << value;
return out.str();
}
int main(){
int N_graid = 500000;
double x_min = -500;
double x_max = -x_min;
double dx = (x_max - x_min)/(N_graid-1);
//set trial energy
double e_tr = -0.6;
double de = 0.000001;
double e_up = 1.0;
//constant
double m = 1.;
double h_bar = 1.;
double c = 0.00000001; // second point of the wavefunctions
ID_TISE &id_tise = *(new ID_TISE(N_graid,x_min,x_max,dx,e_tr,de,e_up,m,h_bar,c));
id_tise.id_tise();
}
Related
I am trying this code about Kohonen Network:
// Fausett.cpp
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
double euclidean(double *vec1,double *vec2,int n)
{
double dist = 0.0;
for(int i=0;i<n;i++) dist += (vec1[i]-vec2[i])*(vec1[i]-vec2[i]);
return dist;
}
double distance(int i,int jstar)
{
return double(i!=jstar);
// returns 1.0 if i!=jstar, returns 0.0 if i==jstar
}
double h(double d) { return 1.0-d; }
void train(double **W,int n,int cols,double *vec,double rate)
{
int i,j;
int win = 0;
double windist = euclidean(W[0],vec,n),edist;
for(i=0;i<cols;i++){
if((edist=euclidean(W[i],vec,n)) < windist)
{ win = i; windist = edist;}
for(i=0;i<cols;i++)
for(j=0;j<n;j++)
W[i][j] += (rate*h(distance(i,win)))*(vec[j]-W[i][j]);
}
int main(void)
{
int i, j;
int T = 10000; // number of iterations
double eta = 0.6; // learning rate
const int m = 4;
int cols;
// training vectors
double x0[m] = { 1.0,1.0,0.0,0.0 };
double x1[m] = { 0.0,0.0,0.0,1.0 };
double x2[m] = { 1.0,0.0,0.0,0.0 };
double x3[m] = { 0.0,0.0,1.0,1.0 };
cout << "Enter number of columns for weight matrix: ";
cin >> cols;
double** W = NULL; W = new double*[cols];
for(i=0;i<cols;i++) W[i] = new double[m];
srand(time(NULL));
for(i=0;i<cols;i++)
for(j=0;j<m;j++) W[i][j] = rand()/double(RAND_MAX);
for(i=0;i<T;i++)
{
train(W,m,cols,x0,eta); train(W,m,cols,x1,eta);
train(W,m,cols,x2,eta); train(W,m,cols,x3,eta);
eta /= 1.05; // learning rate decreased
}
for(i=0;i<cols;i++)
{
cout << "W[" << i << "]= [";
for(j=0;j<m;j++) cout << W[i][j] << " ";
cout << "]" << endl;
}
for(i=0;i<cols;i++) delete[] W[i];
delete[] W;
return 0;
}
its from book Willi - Hans Steeb, I copy paste that, but it gives me error when compiled. error: 'int' is not a class, struct, or union type typedef typename _Iterator::iterator_category iterator_category, this is one of the error messages and I have no idea at all why this happen. Can someone please explain it? I am a newbie in C++.
I am trying to solve the generalized eigenvalue problem for the hydrogen atom by using LAPACKE_dsygvd. For the parameters of the generator functions, I use an interval that starts at 0.01 and takes N steps of 0.01. What I change is the value of N. Everythings fine for N = 14 and below, where I get the answers from the analytical solution. However, when I choose N = 15 and above, I get an error and info is returned with a value > N. After reading the documentation from LAPACK, it says the following:
N: if INFO = N + i, for 1 <= i <= N, then the leading
minor of order i of B is not positive definite.
The factorization of B could not be completed and
no eigenvalues or eigenvectors were computed.
But I have checked my matrix B and it is positive definite. I don't know what is wrong.
Below I show my scripts
#include <cmath>
#include <cstdio>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "library.h"
#include "mkl.h"
using namespace std;
double Superposition(const double ai, const double aj, const int m);
double Hamiltonian(const double ai, const double aj, const int m);
void print_matrix(double *A, int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("%.7f ", A[i*n + j]);
}
cout << "\n";
}
}
void print_vector(double *vec, int n) {
for (int i = 0; i < n; i++) {
cout << vec[i] << " ";
}
cout << "\n";
}
double* interval(double min, double step) {
double *result;
result = (double *)mkl_malloc( N*sizeof( double ), 64 );
for (int i = 0; i < N; i++) {
result[i] = min + i*step;
}
return result;
}
int main() {
cout << Ry << "\n";
double *S, *H, *I, *eigenvalues;
double alpha, beta;
int i, j, info;
char* uplo = "U"; char* jobz = "V";
I = interval(0.01, 0.01);
alpha = 1.0; beta = 0.0;
S = (double *)mkl_malloc( N*N*sizeof( double ), 64 );
H = (double *)mkl_malloc( N*N*sizeof( double ), 64 );
eigenvalues = (double *)mkl_malloc( N*sizeof( double ), 64 );
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
int index = i*N + j;
if (j < i) {
S[index] = 0.0;
H[index] = 0.0;
}
else {
S[index] = Superposition(I[i], I[j], m);
H[index] = Hamiltonian(I[i], I[j], m);
}
}
}
print_matrix(S, N); cout << "\n";
print_matrix(H, N); cout << "\n" << "\n";
info = LAPACKE_dsygv(LAPACK_ROW_MAJOR, 1, *jobz, *uplo, N,
H, N, S, N, eigenvalues);
//print_matrix(H, N); cout << "\n";
//for (i = 0; i < N; i++) {
// eigenvalues[i] /= Ry;
//}
cout << info << "\n" << "\n";
print_matrix(H, N); cout << "\n";
print_vector(eigenvalues, N);
mkl_free(S);
mkl_free(H);
mkl_free(I);
mkl_free(eigenvalues);
}
*Edit: I used dsygvd as included in MKL, and the same error doesn't occur. However, I get very different results for both functions using the same inputs.
Just wanted to know what is wrong with this. Double in is suppose to be set to 50 if it is NULL. Then after it is set to 50 it gets subtracted with the user input of double bbet with the analyze(). But after it loops it self it still thinks double in is NULL. Can any one point me in the right direction to get in to remember the value it subtracted its self with.
#include <iostream>
#include <string>
using namespace std;
class Bet
{
public:
void set_stack(double n);
void set_bet(double n);
void analyze();
double get_stack();
double get_bet();
private:
double pCount;
double bet;
};
void Bet::analyze()
{
double p = pCount;
double b = bet;
double z = p - b;
pCount = z ;
}
void Bet::set_bet(double n)
{
double z = n;
bet = z;
}
double Bet::get_bet()
{
return bet;
}
void Bet::set_stack(double n)
{
double z = n;
pCount = z;
}
double Bet::get_stack()
{
double p = pCount;
double b = bet;
double z = p - b;
return z;
}
double bbet;
double in ;
double* inV;
int main()
{
bool con = true;
while(con){
double start = 50;
if(*inV == NULL){
in = start;}
Bet rr;
rr.set_stack(in);
cout << "Enter min 1 Bet: ";
cin >> bbet;
rr.set_bet(bbet);
double newStack = rr.get_stack();
cout << "Stack: " << newStack << endl;
cout << "Bet: " << bbet << endl;
inV = ∈
}
system("pause");
return 0;
}
You want if (inV == NULL) rather than if (*inV == NULL).
I have some problems with my program, it currently gives the wrong results for finding a meeting point.
I choose to use geometric median algorithm for searching for a meeting point, as described here .
Also I have implemented a brute-force algorithm, just to compare the results.
Source code were EDIT to possible solution, correct me, it's not working sometimes for > 100000 points:
#include <vector>
#include <random>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
long double ComputeMean(vector<long long> InputData) {
long double rtn = 0;
for (unsigned int i = 0; i < InputData.size(); i++) {
rtn += InputData[i];
}
if(rtn == 0) return rtn;
return rtn/InputData.size();
}
long double CallRecursiveAverage(long double m0, vector<long long> X) {
long double m1 =0 ;
long double numerator = 0, denominator = 0;
for (unsigned int i = 0; i < X.size(); i++) {
long double temp =abs((X[i] - m0));
if(X[i]!=0 && temp!=0) {
numerator += X[i] / temp;
}
if(temp!=0) {
denominator += 1 / temp;
}
}
if( denominator != 0 ) {
m1 = numerator / denominator;
}
return m1;
}
long double ComputeReWeightedAverage(vector<long long> InputVector) {
long double m0 = ComputeMean(InputVector);
long double m1 = CallRecursiveAverage(m0, InputVector);
while (abs(m1 - m0) > 1e-6) {
m0 = m1;
m1 = CallRecursiveAverage(m0, InputVector);
}
return m1;
}
int randomizer(){
int n =(rand() % 1000000 + 1)*(-1 + ((rand() & 1) << 1));
return(n);
}
struct points
{
long double ch;
long long remp;
bool operator<(const points& a) const
{
return ch < a.ch;
}
};
int main () {
long double houses=10;
// rand() % 100 + 1;
// cin >> houses;
vector <long long> x;
vector <long long> y;
vector <long long> xr;
vector <long long> yr;
vector <long long> sums;
vector <long long> remp;
long long x0, y0;
long double path = 1e9;
long double sumy = 0;
long double sumx = 0;
long double avgx = 1;
long double avgy = 1;
srand((unsigned)time(NULL));
int rnd;
for(int i = 0; i < houses; i++) {
// cin>>x0>>y0;
x0 = randomizer();
x.push_back(x0);
sumx += x0;
y0 = randomizer();
y.push_back(y0);
sumy += y0;
}
if(sumx!=0) {
avgx=ComputeReWeightedAverage(x);
} else {
avgx=0;
}
if(sumy!=0) {
avgy=ComputeReWeightedAverage(y);
} else {
avgy=0;
}
long double check=1e9;
long double pathr=0;
int rx, ry;
long double wpath=1e9;
///brute force////
for(int j = 0; j < houses; j++) {
pathr = 0;
for(int i = 0; i < houses; i++) {
pathr += max(abs(x[i] - x[j]), abs(y[i] - y[j]));
}
if(pathr<wpath)
{
wpath = pathr;
ry=j;
}
}
cout << "\nx ="<<x[ry]<<"\n";
cout << "y ="<<y[ry]<<"\n";
cout << "bruteForce path ="<<wpath<<"\n\n";
////end brute force///
cout << "avgx ="<<avgx<<"\n";
cout << "avgy ="<<avgy<<"\n";
vector<points> ch;
for(int j = 0; j < houses; j++) {
remp.push_back(j);
points tb;
tb.ch=max(abs(x[j] - (avgx)), abs(y[j] - (avgy)));
tb.remp=j;
ch.push_back(tb) ;
}
sort(ch.begin(),ch.end());
path =1e9;
for(unsigned int z = 0; z < 10; z++) {
pathr = 0;
for(int i = 0; i < houses; i++) {
pathr += max(abs(x[i] - x[ch[z].remp]), abs(y[i] - y[ch[z].remp]));
}
if(pathr<path)
{
path = pathr;
}
}
cout << "x ="<<x[remp[0]]<<"\n";
cout << "y ="<<y[remp[0]]<<"\n";
cout << "Weizsfield path ="<<path<<"\n\n";
if (wpath!=path){ cout <<"ERRROR"<<"\n";
cout << "dots\n";
for(int i = 0; i < houses; i++) {
cout << x[i]<<" "<<y[i]<<"\n";
}
cout << "dots\n\n";
}
return 0;
}
Where did I make a mistake in my program? Any help will be appreciated.
EDIT
Is changing search radius of nearest points to geometric median and checking path for all of them the best approach? If answer is yes, how do I find the optimal start radius?
The Weiszfeld algorithm is one that approximates the geometric median and will therefore very often deviate from the real one computed by brute force.
Increasing the search radius will probably help.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
C++ Loop Not Looping Appropriately
Warning..I am new to C++ programming...I have an array of 20 x 20 that outputs how hot a plate is. I need to reiterate through a loop until no cell in the array changes more than 0.1 degree(I refresh the values through every iteration. How would you monitor the largest change for any cell in an array in order to determine when to stop iterating? Right now I have tried, but the below doesn't output correctly.
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
using namespace std;
const int array_size = 20; // set array size and neighbors to calculate rest of cells
const int cell_neighbors = 4;
void initialize(double hot_plate[][array_size]); //functions here
bool writeFile(const double hot_plate[][array_size],
const string file_name);
double sum_cell(const double hot_plate[][array_size],
const int cell_X, const int cell_Y);
double value_cell(const double hot_plate[][array_size],
const int cell_X, const int cell_Y);
int main()
{
double hot_plate[array_size][array_size];//set variables
initialize(hot_plate); //run function
string file_name = "hot_plate.csv"; //file name for Excel
//repeat until stable
int repeat_until_stable = 1000;
while ( repeat_until_stable > 0)
{
for (int a = 1; a < array_size - 1; a++)
{
for (int b = 1; b < array_size - 1; b++)
{
{
hot_plate[a][b] = sum_cell(hot_plate, b, a);
}
}
}
repeat_until_stable--;
}
if (writeFile(hot_plate, file_name)) //check functionality of the program
{
cout << "Excel File created\n";
}
else
{
cout << "The Excel file did not write\n";
}
system("pause");
return 0;
}
//function definition
double sum_cell(const double hot_plate[][array_size],
const int cell_X, const int cell_Y)
{
double cell_num = hot_plate[cell_X - 1][cell_Y]; // Top
cell_num += hot_plate[cell_X][cell_Y - 1]; // Left
cell_num += hot_plate[cell_X][cell_Y + 1]; // Right
cell_num += hot_plate[cell_X + 1][cell_Y]; // Bottom
cell_num /= cell_neighbors; // find average of the 4 values closest to cell
return cell_num;
}
// setup the array so all values are defined
void initialize(double hot_plate[][array_size])
{
for (int a = 0; a < array_size; a++)
{
for (int b = 0; b < array_size; b++)
{
if (a == 0 || a == array_size - 1)
{
if (b == 0 || b == array_size - 1)
{
hot_plate[a][b] = 0.0;
}
else
{
hot_plate[a][b] = 100.0;
}
}
else
{
hot_plate[a][b] = 0.0;
}
}
}
}
double value_cell(const double hot_plate[][array_size],
const int cell_X, const int cell_Y)
{
double cell_value = hot_plate[cell_X][cell_Y]; // cell value
return cell_value;
}
// Write the data to the Excel CSV file
bool writeFile(const double hot_plate[][array_size],
const string file_name)
{
// open the excel file
ofstream fout(file_name);
if (fout.fail())
return false;
for (int a = 0; a < array_size; a++)
{
for (int b = 0; b < array_size; b++)
{
fout << hot_plate[a][b];
if ( b < array_size - 1)
{
fout << ", ";
}
else if (a != array_size - 1)
{
fout << endl;
}
}
}
// close the input stream from the file.
fout.close();
return true;
}
Put a variable that holds the maximum change that is made and check it after the for loops
double maxChange=.11;
.
.
.
while(maxChange>.1)
{
maxChange=-1;
for(.....)
for(.....)
{
change=fabs(oldValue-plate[a][b]);
if(change>maxChange)
maxChange=change;
}
}