newbie in cpp

T

toylas

Dear All,

I am a newbie to cpp. I am writing my computational physics course
codes in cpp. I have written a code which simulates a magnet using a
model of spins. I use a subroutine called metropolis in the program.

First let me describe the program before describing my problem. The
structure of the program is as follows:

***************************************************************************************************************
#include<iostream>
#include<math.h>
#include<vector>
#include<fstream>
#include<stdlib.h>

using namespace std;
const int size=10;
double metropolis(int sweeps, int spin[size][size], double H, double
beta, char *outfile);
int main ()
{
int i, j;
int sweeps;
int spin[size][size];

I DO SOMETHING and then call metropolis

metropolis(sweeps,spin,H,beta,outfile);

SOMETHING...
}

and the subroutine goes as...

double metropolis(int sweeps, int spin[size][size], double H, double
beta, char *outfile)
{
int imet,i,j,ipos,jpos,ineg,jneg;
more declarations....

SOMETNIGS DONE on spin[size][size].... with loops like for
(i=1;i<size;i++) ...

}
***********************************************************************************************************

My problem is that I have a 2D lattice represented as a matrix whose
size I define as the variable size at the top. I want to read this
variable from STDIN so that I just need to compile the code just once
to run for different lattice sizes. I have no idea about the syntax. I
tried to use the usual cout, cin but it gave me loads of errors.
Program works nicely but if I want a different lattice size, I need to
compile it everytime. Could you please tell me a way of reading the
variable size from STDIN??

with thanks in advance,

Tulasi
 
I

Ian Collins

toylas said:
Dear All,

My problem is that I have a 2D lattice represented as a matrix whose
size I define as the variable size at the top. I want to read this
variable from STDIN so that I just need to compile the code just once
to run for different lattice sizes. I have no idea about the syntax. I
tried to use the usual cout, cin but it gave me loads of errors.
Program works nicely but if I want a different lattice size, I need to
compile it everytime. Could you please tell me a way of reading the
variable size from STDIN??
int size;

std::cout << "input size " << std::endl;
std::cin >> size;
 
J

Jonathan Mcdougall

toylas said:
My problem is that I have a 2D lattice represented as a matrix whose
size I define as the variable size at the top. I want to read this
variable from STDIN so that I just need to compile the code just once
to run for different lattice sizes. I have no idea about the syntax. I
tried to use the usual cout, cin but it gave me loads of errors.

What were these errors? It may help us to help you.
Program works nicely but if I want a different lattice size, I need to
compile it everytime. Could you please tell me a way of reading the
variable size from STDIN??

Reading is easy:

std::size_t size = 0;
std::cin >> size;

But using that size is less easy with arrays. In C++, the size of an
array must be a compile-time constant, which is definitely not the case
now. You have two solutions: use dynamically allocated arrays:

int** matrix;
matrix = new int*[size];

for (std::size_t i=0; i<size; ++i)
matrix = new int[size];

// .. and then

for (std::size_t i=0; i<size; ++i)
delete[] matrix;

delete[] matrix;

which is a pain, you'll agree. The other solution is using standard
containers:

# include <vector>
# include <cstddef>

int main()
{
typedef std::vector<int> row;
typedef std::vector<row> matrix;
matrix m;

std::size_t size = 10; // you may ask the user for a size here

for (std::size_t i=0; i<size; ++i)
{
row r;
for (std::size_t j=0; j<size; ++j)
{
r.push_back(j);
}

m.push_back(r);
}
}

This should get you started.


Jonathan
 
R

rageratwork

toylas wrote:
[snip]
#include<iostream>
[snip]

using namespace std;
const int size=10;
[snip]

I tried to use the usual cout, cin but it gave me loads of errors.

[snip]

As others have stated, cout and cin should work. You did not post the
code that was failing so I can't determine why they would not work for
you. If your size variable was declared const as it is in this code you
posted, you will get "loads of errors" if you try to read a value into
it with cin.

Dave.
 
T

toylas

Dear All,

Thank you very much for the response. I think I was not able to convey
my problem properly. My problem is not declaring the matrix. My problem
is keeping the size of the matrix variable so that I just compile it
once and when I run the program, it asks me the size of the matrix. I
do not have any idea how to keep the size variable. If it was just
being used in the main program I could simply read it using cin, it
worked fine. But it is being passed into a subroutine so I am declaring
it outside the main
program. The cï½ï½„e wï½ï½’ks fine if I declï½ï½’e size ï½ï½“ cï½ï½Žï½“t but when
I try to read size from STDIN as suggested by Ian (i.e I instead of
const int size=20; I use what he said), I get errors. This time I have
attached my code as well as the error messages.

Also as I'm a newbie, any suggestions to improve the code (both from
aesthetic as well as efficiency point of view) will be greatly
appreciated.

Thanks,
Tulasi


$$$$$$$$$$$$$$$$$$$$ CODE $$$$$$$$$$$$$$$$$$$$$$$$$$
#include<iostream>
#include<math.h>
#include<vector>
#include<fstream>
#include<stdlib.h>

using namespace std;
const int size=10;
double metropolis(int sweeps, int spin[size][size], double H, double
beta, char *outfile);
int main ()
{
int i, j;
int sweeps;
int spin[size][size];
char outfile[20];
double temp, beta, H, av_M, cv;

cout <<"output filename ";
cin.getline(outfile, 20);

cout <<"Temperature, Initial magnetic field? ";
cin >> temp >> H;
beta=1.0/temp;

cout <<"How many sweeps? ";
cin >> sweeps;

// Just a dirty trick to overwrite the file if it exists as I have to
append it all the time
// in metropolis.

ofstream avfile(outfile);
avfile.close();

//assign spins
for (i=0;i<size;i++) {
for (j=0;j<size;j++) {
spin[j] = -1;
}
}


for (i=0;i<101;i++) {
metropolis(sweeps,spin,H,beta,outfile);
H=H+0.1;
}

for (i=99;i>=0;i--) {
H=H-0.1;
metropolis(sweeps,spin,H,beta,outfile);
}

H=0.0;
for (i=0;i<12;i++) {
temp=temp+0.1;
beta=1/temp;
metropolis(sweeps,spin,H,beta,outfile);
}

for (i=0;i<10;i++) {
temp=temp+0.01;
beta=1/temp;
metropolis(sweeps,spin,H,beta,outfile);
}

for (i=0;i<21;i++) {
temp=temp+0.1;
beta=1/temp;
metropolis(sweeps,spin,H,beta,outfile);
}

for (j=0;j<10;j++) {
H=-5.0;
for (i=0;i<101;i++) {
metropolis(sweeps,spin,H,beta,outfile);
H=H+0.1;
}
temp=temp+0.5;
beta=1/temp;
}



return 0;
}
/* Metropolis Monte Carlo update of 2-d Ising ferromagnet */



double metropolis(int sweeps, int spin[size][size], double H, double
beta, char *outfile)
{
int imet,i,j,ipos,jpos,ineg,jneg;
int old_spin,new_spin,spin_sum;
double old_energy,new_energy;
double
energy_diff,energy_micro,total_energy,av_energy,total_sq_energy,av_sq_energy;
double M_micro,total_M;
double av_M,cv,av_spin_energy;
double ranum; /* random number generator */

ofstream avfile(outfile,ios_base::app);
// I use append mode as I calculate a few things inside metropolis and
I want the result ï¼ï¼for each call of metropolis. Is there a way to
open the file in main and then write these
//there??

total_energy=0.0;
total_sq_energy=0.0;
total_M=0.0;

/* Loop over sweeps */
for (imet=0;imet<sweeps;imet++) {

/* Part comparable to F90 starts here */
/* Loop over sites */
for (i=0;i<size;i++) {
for (j=0;j<size;j++) {

ranum=float(rand())/float(RAND_MAX);

/* periodic boundary conditions */
ipos = (i+1) % size;
jpos = (j+1) % size;
ineg = (i+size-1) % size;
jneg = (j+size-1) % size;

old_spin = spin[j];
new_spin = - old_spin;

/* Sum of neighboring spins */
spin_sum = spin[jpos] + spin[ipos][j] +
spin[jneg] + spin[ineg][j];

old_energy = - old_spin * spin_sum - H * old_spin;
new_energy = - new_spin * spin_sum - H * new_spin;
energy_diff = beta * (new_energy - old_energy); /* beta = J/kT */
// cout << energy_diff <<" "<< exp(-energy_diff) <<" "<< ranum
<<"\n";

/* Do the update */
if ( (energy_diff <= 0.0) || (exp(-energy_diff) > ranum ) ) {
/* Accept the change */
spin[j] = new_spin;
}

}} /* end of loop over sites */

/* Part comparable to F90 ends here */
/* Calculation of total energy */
energy_micro=0.0;
M_micro=0.0;
for (i=0;i<size;i++) {
for (j=0;j<size;j++) {
// cout << spin[j] <<"\n";
/* periodic boundary conditions */
ipos = (i+1) % size;
jpos = (j+1) % size;
ineg = (i+size-1) % size;
jneg = (j+size-1) % size;
/* Sum of neighboring spins */
spin_sum = spin[jpos] + spin[ipos][j] +
spin[jneg] + spin[ineg][j];
M_micro=M_micro+spin[j];
// M_micro+=spin[j];
energy_micro=energy_micro+(-spin_sum*spin[j]-2*H*spin[j]);
}}

av_spin_energy=energy_micro/2.0;
// av_spin_energy=energy_micro/2;
if (imet >= 10000){
total_energy=total_energy+(av_spin_energy);
total_sq_energy=total_sq_energy+(av_spin_energy*av_spin_energy);
total_M=total_M+M_micro;
}

} /* end of loop over sweeps */

av_energy=total_energy/(sweeps-10000);
av_sq_energy=total_sq_energy/(sweeps-10000);
av_M=total_M/(sweeps-10000);
cv=beta*beta*(av_sq_energy-av_energy*av_energy);

avfile.precision(8);
avfile << H <<"\t \t"<< av_M <<"\t \t"<< av_energy <<"\t \t"<<
1/beta <<"\t \t"<< cv

<<"\n";

}


$$$$$$$$$$$$$$ errï½ï½’s $$$$$$$$$$$$$$

proj.cpp(11): error #77: this declaration has no storage class or type
specifier
std::cout << "input size " << std::endl;
^

proj.cpp(11): error: declaration is incompatible with "std::eek:stream
std::cout" (declared at line 64 of "/usr/include/c++/3.4.4/iostream")
std::cout << "input size " << std::endl;
^

proj.cpp(11): error: expected a ";"
std::cout << "input size " << std::endl;
^

proj.cpp(12): error #77: this declaration has no storage class or type
specifier
std::cin >> size;
^

proj.cpp(12): error: declaration is incompatible with "std::istream
std::cin" (declared at line 63 of "/usr/include/c++/3.4.4/iostream")
std::cin >> size;
^

proj.cpp(12): error: expected a ";"
std::cin >> size;
^

proj.cpp(13): error: expression must have a constant value
double metropolis(int sweeps, int spin[size][size], double H, double
beta, char *outfile);
^

proj.cpp(13): error: expression must have a constant value
double metropolis(int sweeps, int spin[size][size], double H, double
beta, char *outfile);
^

proj.cpp(22): error: expression must have integral or enum type
cout <<"output filename ";
^

proj.cpp(23): error: expression must have class type
cin.getline(outfile, 20);
^

proj.cpp(25): error: expression must have integral or enum type
cout <<"Temperature, Initial magnetic field? ";
^

proj.cpp(26): error: expression must have integral or enum type
cin >> temp >> H;
^

proj.cpp(26): warning #592: variable "temp" is used before its value is
set
cin >> temp >> H;
^

proj.cpp(29): error: expression must have integral or enum type
cout <<"How many sweeps? ";
^

proj.cpp(30): warning #592: variable "sweeps" is used before its value
is set
cin >> sweeps;
^

proj.cpp(91): error: expression must have a constant value
double metropolis(int sweeps, int spin[size][size], double H, double
beta, char *outfile)
^

proj.cpp(91): error: expression must have a constant value
double metropolis(int sweeps, int spin[size][size], double H, double
beta, char *outfile)
^

proj.cpp(182): warning #1011: missing return statement at end of
non-void function "metropolis"
}
^

compilation aborted for proj.cpp (code 2)
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
 
T

toylas

I'm sorry I posted the uchanged code. The code begins like this....

#include<iostream>
#include<math.h>
#include<vector>
#include<fstream>
#include<stdlib.h>

using namespace std;
//const int size=10;

int size;
std::cout << "input size " << std::endl;
std::cin >> size;

double metropolis(int sweeps, int spin[size][size], double H, double
beta, char *outfile);
int main ()
{
.....


Sorry for the confusion :(

Best,
Tulasi
 
V

Victor Bazarov

toylas said:
I'm sorry I posted the uchanged code. The code begins like this....

#include<iostream>
#include<math.h>
#include<vector>
#include<fstream>
#include<stdlib.h>

using namespace std;
//const int size=10;

int size;
std::cout << "input size " << std::endl;
std::cin >> size;

You cannot have executable statements outside any function body.

Read about dynamic memory management (may be too advanced for you)
or use a standard container.

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,113
Latest member
Vinay KumarNevatia
Top