Probleme beim Zuweisen von Werten an Arrayelemente
-
Hallo!
Ich bin vor kurzem von FORTRAN zu C++ umgestiegen und versuche nun eine Metropolis Monte Carlo Simulation für das Ising Modell zu schreiben.
Dabei hat man ein Gitter von Spins, von denen jeder die Werte +1 und -1 annehmen kann. Mit Hilfe von Übergangsvorschriften und Zufallszahlen simuliert man dann, welche Werte die Spins des Gitters am "liebsten" annehmen.Mein Spinsystem wird im Array
int spin[V]abgespeichert. Das Problem ist nun, dass ich in Zeile 43 in main.cpp bei jedem Simulationsschritt einem Element des Arrays einen neuen Wert zuordnen will. Nur scheint das Array das irgendwie zu ignorieren. Es bleibt lange Zeit unverändert und dann auf einmal ändern sich alle Werte.
Nun debugge ich schon tagelang und es scheint mir alles richtig zu sein. Aber wo liegt dann der Programmierfehler? Vielleicht ist das ja für einen C++ Profi offensichtlich?!
Wenn ich ein kleines Testprogramm schreibe, in dem ein Array an eine Funktion übergeben wird und diese Funktion einzelne Elemente ändert, so funktioniert alles. Warum funktioniert das bei dem großen Porgramm nicht, obwohl ich es da genauso mache.
Falls es wichtig ist, ich benutze Ubuntu 11.10, gcc 4.4 und QtCreator
Bitte helft mir.
Danke schonmal!
Hier die Simulation:
main.h#ifndef MAIN_H #define MAIN_H #include <iostream> #include <stdlib.h> #include <math.h> #include <fstream> #include <iomanip> #include <time.h> using namespace std; // SIMULATION AND SYSTEM PARAMETERS const int dim = 2; const int Lx = 10, Ly = 10, Lz = 1; const int V = Lx*Ly*Lz; const double betai = 0.05, betaf = 2.05; // beta -> beta*J const int Nbeta = 5; const double H = 0.0; // H -> H/J const int Nsweeps = 10, eqsweeps = 0; // GLOBAL VARIABLES int NNtab[V][2*dim]; double Rmntab[2*dim+1]; double Esum, Msum, Mabssum, sqEsum, sqMsum; // FUNCTIONS void Ising_MC(int spin[]); void initialization(); void close(); int energy(int spin[], int site); void NNchart(); void Rmnchart(double beta); void eval(int spin[]); void output(int spin[], double beta); // CLASS DECLARATIONS ofstream file_out, system_out; clock_t start, end; #endif // MAIN_Hmain.cpp
//******************************************************// // METROPOLIS MC SIMULATION OF THE ISING MODEL // //******************************************************// #include <main.h> //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // PERFORMS THE MC SIMULATION ACROSS A SPECIFIC PARAMETER INTERVAL int main(){ int spin[V]; double beta; fill(spin,spin+V,1); initialization(); beta = betai; for (int kbeta = 0; kbeta <= Nbeta; kbeta++){ Rmnchart(beta); Ising_MC(spin); output(spin,beta); cout << beta << "\n"; if(Nbeta != 0) beta += fabs(betaf-betai)/Nbeta; } close(); return 0; } //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // MC SIMULATION ROUTINE FOR CERTAIN PARAMETERS void Ising_MC(int spin[]){ int site; int dE; double urn,prob; for(int isw = 1; isw <= Nsweeps; isw++){ for(int iup = 0; iup < V; iup++){ site = rand() % V; dE = energy(spin,site); urn = (double)rand()/RAND_MAX; prob = Rmntab[dim-dE/2]; if (urn <= prob) spin[site] = -spin[site]; // spin system output zu testzwecken -------------------------------- spin[site] = 4; cout << "\n" <<"\n"; for(int k = 0; k < Lz; k++){ for(int l = 0; l < Ly; l++){ for(int m = 0; m < Lx; m++){ cout << setw(2) << spin[k*l*m]; } cout << "\n"; } cout << "\n" << "\n"; } //spin system test end----------------------------------------------- } if (isw > eqsweeps) eval(spin); } return; } //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // PROGRAM INITIALIZATION void initialization(){ start = clock(); srand(time(NULL)); NNchart(); file_out.open("IsingMC_out.dat"); system_out.open("IsingSystem_out.dat"); cout << "\n"; cout << "METROPOLIS MONTE CARLO SIMULATION OF THE ISING MODEL" << "\n"; cout << "::::::::::::::::::::::::::::::::::::::::::::::::::::" << "\n"; cout << "Parameters" << "\n"; cout << setw(10) << "Lx = " << Lx << setw(10) << "Ly = " << Ly << setw(10) << "Lz = " << Lz << setw(10) << "V = " << V << "\n"; cout << setw(10) << "H = " << H << setw(15) << "Nsweeps = " << Nsweeps << setw(20) << "eqsweeps = " << eqsweeps << "\n" << "\n"; file_out << "METROPOLIS MONTE CARLO SIMULATION OF THE ISING MODEL" << "\n"; file_out << "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::" << "::::::::::::::::::::::" << "\n"; file_out << "Parameters" << "\n"; file_out << setw(15) << "Lx = " << Lx << setw(15) << "Ly = " << Ly << setw(15) << "Lz = " << Lz << setw(15) << "V = " << V << "\n"; file_out << setw(15) << "H = " << H << setw(30) << "Nsweeps = " << Nsweeps << setw(15) << "eqsweeps = " << eqsweeps << "\n"; file_out << "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::" << "::::::::::::::::::::::" << "\n"; file_out << left << setw(15) << "T" << setw(15) << "beta" << setw(15) << "E" << setw(15) << "M" << setw(15) << "|M|" << setw(15) << "C" << setw(15) << "X" << "\n"; file_out << "----------------------------------------------------------------------------" << "----------------------" << "\n"; return; } //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // PROGRAM CLOSING PROCEDURE void close(){ file_out.close(); system_out.close(); end = clock(); cout << "::::::::::::::::::::::::::::::::::::::::::::::::::::" << "\n"; cout << "\n" << "CPU time in sec: " << (double) end/CLOCKS_PER_SEC << "\n"; return; } //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // CALCULATION OF THE ENERGY DIFFERENCE int energy(int spin[], int site){ int dE; dE = 0; for (int i = 0; i < 2*dim; i++) { dE += spin[NNtab[site][i]]; } return dE; } //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // NEAREST NEIGHBOR ARRAY GENERATOR void NNchart(){ for (int l = 0; l < V; l++){ NNtab[l][0] = l-1; if(l % Lx == 0) NNtab[l][0] += Lx; NNtab[l][1] = l+1; if((l+1) % Lx == 0) NNtab[l][1] -= Lx; if (dim > 1) { NNtab[l][2] = l-Lx; if(l % (Lx*Ly) < Lx) NNtab[l][2] += Lx*Ly; NNtab[l][3] = l+Lx; if(l % (Lx*Ly) >= Lx*(Ly-1)) NNtab[l][3] -= Lx*Ly; if (dim > 2) { NNtab[l][4] = l-Lx*Ly; if(l % (Lx*Ly*Lz) < Lx*Ly) NNtab[l][4] += Lx*Ly*Lz; NNtab[l][5] = l+Lx*Ly; if(l % (Lx*Ly*Lz) >= Lx*Ly*(Lz-1)) NNtab[l][5] -= Lx*Ly*Lz; } } } return; } //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // ARRAY OF ALL POSSIBLE EXP VALUES void Rmnchart(double beta){ for (int i = 0; i <= 2*dim; i++){ Rmntab[i] = min(1.0, exp(-2*beta*(2*dim - 2*i + H))); } return; } //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // EVALUATION OF OBSERVABLES void eval(int spin[]){ double E, M; E = M = 0.0; for (int i = 0; i < V; i++){ for (int jNN =0; jNN < 2*dim; jNN++){ E += -1/2*spin[i]*spin[NNtab[i][jNN]]; } E += -H*spin[i]; M += spin[i]; } Esum += E; Msum += M; Mabssum += fabs(M); sqEsum += E*E; sqMsum += M*M; return; } //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // OUTPUT OF AVERAGES AND SPIN SYSTEM void output(int spin[], double beta){ int N = Nsweeps - eqsweeps; double C, X; C = beta*beta*(sqEsum/N - Esum*Esum/(N*N)); X = beta*(sqMsum/N - Mabssum*Mabssum/(N*N)); system_out << "\n" << "T = " << 1/beta << "\n" <<"\n"; for(int k = 0; k < Lz; k++){ for(int l = 0; l < Ly; l++){ for(int m = 0; m < Lx; m++){ system_out << setw(3) << spin[k*l*m]; } system_out << "\n"; } system_out << "\n" << "\n"; } file_out << left << setw(15) << 1/beta << setw(15) << beta << setw(15) << Esum/(N*V) << setw(15) << Msum/(N*V) << setw(15) << Mabssum/(N*V) << setw(15) << C/V << setw(15) << X/V <<"\n"; Esum = Msum = Mabssum = sqEsum = sqMsum = 0.0; return; }und hier noch das Testprogramm, wo die Zuweisung zu Arrayelementen funktioniert:
#include<iostream> using namespace std; void assignelement(int array[]){ array[1] = 2; array[2] = 3; } int main(){ int array[3] = {1,1,1}; assignelement(array); cout << array[0] << array[1] << array[2]<<endl; return 0; }
-
Das ist furchtbar viel Code und furchtbar unübersichtlich. Konkret kann ich an Zeile 43 nix sehen und der Rest ist mir erst einmal zu lang. Aber es fällt auf dem ersten Blick auf: Du machst Fortran in C++. Und zwar im negativen Sinne:
Google: writing fortran in any languageDaraus resultieren zwei Probleme:
1. Es ist furchtbar unübersichtlich. Variablen kannst du in C++ deklarieren, wo du sie brauchst, nicht am Anfang der Funktion. C++ unterstützt Objektorientierung von Haus aus. C++ kann Variablennamen die länger als 1 Zeichen sind. C++ kommt mit jeder Menge fertiger Algorithmen, die vieles abkürzen. C++ kommt mit jeder Menge fertiger Datenstrukturen die für alle praktischen Zwecke das richtige bieten. Insbesondere ein brauchbarer Ersatz für Arrays. In C++ brauchst du so gut wie nie globale Variablen.
Ein Programm, dass in gutem C++ geschrieben ist, ist schon fast erschreckend robust gegen Programmierfehler, da viele Logikfehler und fast alle technischen Fehler gar nicht erst compilierbar sind.
2. Manche Sprachfeatures funktionieren in C++ schlichtweg anders als in FORTRAN, insbesondere Arrays, die von C her kommen und im Vergleich mit anderen Datentypen ganz ungewohnte Eigenschaften haben. Kann gut sein, dass du da einen Fehler gemacht hast. Aber wie in 1 schon gesagt, hättest du wahrscheinlich gar keine Arrays gebraucht, sondern, je nachdem wie dein Programm genau funktioniert, std::array oder std::vector. Diese zählen wiederum zu den in 1 genannten Datenstrukturen, bei denen Fehler so gut wie ausgeschlossen oder, falls man doch mal einen macht, sehr viel leichter debugbar sind.
-
Wie siehst du das, dass das Array die falschen Werte enthält? Anhand deiner Testausgabe? Der Zugriff spin[k*l*m] ist ja wahrscheinlich nicht das, was du an der Stelle willst.
-
Wie siehst du das, dass das Array die falschen Werte enthält? Anhand deiner Testausgabe?
Ja, die Ausgabe sieht so aus:
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1müsste aber eher so aussehen:
1-1 1 1 1
1 1 1 1-1
1-1 1 1 1
-1-1 1-1 1
1 1 1-1 1Du machst Fortran in C++. Und zwar im negativen Sinne:
Google: writing fortran in any languageKennt denn jemand ein gutes Tutorial explizit um auf objektorientierte Programmierung umzusteigen?
-
APE<<&l schrieb:
Wie siehst du das, dass das Array die falschen Werte enthält? Anhand deiner Testausgabe?Ja, die Ausgabe sieht so aus:
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1müsste aber eher so aussehen:
1-1 1 1 1
1 1 1 1-1
1-1 1 1 1
-1-1 1-1 1
1 1 1-1 1Bashar schrieb:
Der Zugriff spin[k*l*m] ist ja wahrscheinlich nicht das, was du an der Stelle willst.
Das wird's sein. Da sollen bestimmt noch die Breiten des Arrays beim Berechnen des Index einfließen.
-
Ah jetzt hab ichs kapiert. Ich war zu dumm mein Array richtig auszugeben.
Danke für den Tipp!