Verfasst am: 30.03.2015, 21:43
Titel: Datei mit mehr als 65536 Zeilen
Hallo,
ich habe eine Schleife, die mindestens 100.000 mal durchläuft. In jedem Durchgang speicher ich mit fprintf eine Zeile in einer .dat-Datei. Allerdings speichert er immer nur um die 60.000 Zeilen in der Datei.
Mein benutzter Code gleicht dem folgenden:
while ds <= s && (zk >= 0 && zk <= zmax)% läuft so jedes mal 20 mal durch
k = k + 1;
ifexp(...) < rand(1)
%%%%%% In die if-Abfrage geht er irgendwann nicht mehr rein, obwohl die Bedingung erfüllt ist. Müsste etwa 5 - 10 mal pro while-Schleifendurchlauf erfüllt sein
l = l + 1;
if i ~= ls fprintf(fid,'...\r\n',var);
else fprintf(fid,'...\r\n',var);
end
Bis zu einer bestimmten Anzahl Durchläufe führt er das Skript aus. Irgendwann jedoch geht er nicht mehr in die im Code markierte if-Abfrage. Meine im Code eingefügten Zählvariablen verraten aber, das er das Skript bis zum Ende ausführt. Auch die besagte if-Abfrage bleibt die ganze Zeit erfüllt. Eine 'out of memory' Meldung spuckt er auch nicht aus.
Die Zählvariablen besitzen den Inhalt:
i = 100000
k = 1947354
l = 60679
l muss in der Größenordnung 500000 - 1000000 liegen. Egal was ich für laenge eingebe, wenn es scheinbar über einem bestimmten Wert liegt, kommt das Problem.
Hat vielleicht jemand eine Idee?
Grüße
Markus
MarkusP
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 30.03.2015, 21:49
Titel: Entschuldigung für den Titel
Entschuldigt bitte den Titel. Ich dachte zuerst, dass das Problem darin besteht, dass er nur 65536 Zeilen in die Datei schreibt. Aber das Problem besteht auch ohne speichern.
versuchs doch mal mit dem Debugger?
Alternativ bitte eine reproduzierbare Version des Codes bereitstellen.
Grüße,
Harald
MarkusP
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 30.03.2015, 22:57
Titel: Code
Okay Sorry. Ich wollte nicht den ganzen Code hier reinstellen, da er aufgrund meines nicht so guten Programmierstils nicht so leicht zu lesen ist.
Ich bin mir bei den Zahlen sicher. Ich lese Teilchen ein, die durch ein Volumen laufen und evtl. stoßen. Egal ob ich 10000 oder 20000 Teilchen loslaufen lasse, ich erhalte immer die selbe Anzahl Stöße. Ich müsste da ja mindestens einen Faktor 2 zwischen haben.
Code:
clearall;
clc;
% Datei zum Speichern der Messwerte
fids = fopen('datei.dat','w');
% Einlesen der Datei mit den Messwerten % Spalte 1: Energien im Festkörper an der Grenze Oberfläche - "Vakuum" % Spalte 2: normierte x-Richtung % Spalte 3: normierte y-Richtung % Spalte 4: normierte z-Richtung
datei = 'C:\Modell_100000_Ionen.txt';
fid = fopen(datei,'r');
daten = textscan(fid,'%*s %*f %*f %f %*f %*f %*f %f %f %f','HeaderLines',35);
% Einlesen der Datei mit dem energieabhäng. Stoßquerschnitt der Kupferlinie % Spalte 1: Energie % Spalte 2: zugehöriger Stoßquerschnitt
datei_sq = 'C:\Modell\Cu_3p8eV.dat';
fid_sq = fopen(datei_sq,'r');
sq = textscan(fid_sq,'%f %f','Headerlines',10);
% Festlegen der Versuchsparameter
r = 13; % Radius der Hohlkathode in mm
z = 200; % Länge der Hohlkathode in mm
E_Bind = 3.52; %in eV- Oberflächenbindungsenergie des Kupfers im Festkörper
m_Cu = 63.546 * Constants.u; % in kg
dt = 5e-5; % in s - zeitliche Auflösung (Abstand zwischen zwei Punkten)
ne = 1.3e+17; % m^-3
Te = 1.0; % Elektronentemperatur in eV
Int_Start = sq{1}(1);
Int_Ende = 20; % Obere Integrationsgrenze zur Bestimmung von nu_Stoss
n_Int = 2000; % Anzahl Integrationsschritte zur Bestimmung von nu_Stoss
dE = (Int_Ende - Int_Start) / n_Int;
% Bestimmen der Stoßfrequenz mithilfe folgender Formel % nu_Stoß = n_e * int(v_e(E)*f(E)*sigma(E))dE % %%%%%%%%%%%%%%%%
nu = 0;
E = Int_Start;
while E < Int_Ende
nu = nu + sigma(E,'C:\Modell\Cu_3p8eV.dat',10) * E * Constants.e^2 * exp(-E * Constants.e / (Constants.k * Te * 11604.5)) * dE;
E = E + dE;
end
nu = nu * sqrt(2 / Constants.me) * 2 / sqrt(pi) * (1 / (Constants.k * Te * 11604.5))^(3/2) * ne;
% Stoßwahrscheinlichkeit
stosscheck = exp(-nu * dt);
% Umrechnen der Energien auf die 3 Raumrichtungen. % Dazu das Cosinus-Quadrat der Raumrichtungen bestimmen und mit der Energie % des austretenden Teilchens multiplizieren. % Von der x-Richtung die Oberflächenbindungsenergie von E_Bind = 3.52 eV abziehen.
x0 = -r * cos(phi);
y0 = r * sin(phi);
z0 = z * rand(1);
% Abstand vom Startpunkt bis zur Wand (dort Absorption und Ende der % Trajektorie)
d_FB = 2 * r * cos(atan((cosy)/abs(cosx)));
% Zurückgelegte Strecke in der X-Y-Ebene innerhalb eines Zeitintervalls % dt
s_dt = sqrt((dt * v_x)^2 + (dt * v_y)^2);
% Anzahl Zeitintervalle dt bis das Atom die Oberfläche erreicht hat.
n_dt = floor(d_FB / s_dt);
t = dt;
n_durchgaenge = 1;
% Alternative Stopbedingung: z_k < 0 || z_k > z
z_k = z0;
while n_durchgaenge <= n_dt && (z_k >= 0 && z_k <= z)
z_k = z_k + dt * v_z_e;
% Nur wenn exp(-nu_stoss * dt) kleiner als eine Zufallszahl % zwischen 0 und 1 ist, gibt es einen Stoß und das Cu-Atom strahlt % ein Photon ab.
da die daten nicht beiliegen ist das so auch nicht lauffähig.
ich würde also empfehlen den ratschlag von harald wahrzunehmen und den debugger zu benutzen. dazu musst du aber das clear all entfernen. das macht das debuggen unmöglich und man sollte das darum nicht benutzen.
außerdem würde ich empfehlen nicht andauernd auf die festplatte zu schreiben sondern erstmal die daten zu sammeln und dann alles zusammen zu schreiben.
_________________
Hallo,
das habe ich bereits getan. Er wertet alles normal aus. Bis zu einer bestimmten Größe der Datei. Ab da geht er nciht mehr in die if-Abfrage ob das Teilchen stößt oder nicht. Das ignoriert er.
Wenn ich meine datei mit 250.000 Werten zum Beispiel einlese, speichert er mir 59822 Zeilen in die Datei. Lasse ich die Schleife jedoch nur bis 100.000 laufen, speichert er mir 60064 Zeilen. Die Differenz folgt aus der Zufälligkeit der Stöße.
Kann ich dem Debugger bestimmte Werte für dei variablen vorgeben? Also z.B. für i = 200000?
MarkusP
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 30.03.2015, 23:33
Titel:
Wenn ich die Zählvariable der if-Schleife jedesmal ausgebe, ist auffällig, dass sie bis ~14000 langsam hochzählt, aber ab 14000 sehr viel schneller. Das Skript braucht für die ersten 14000 Schleifendurchläufe also wesentlich länger als für die letzten 236000.
Er scheint nicht auf die Elemente des Vektors ab dem Index 14750 zugreifen zu können. Bis zu dem Index funktioniert das Skript. Anschließend sind die Variablen, in denen ich die Werte einlese leer.
Versuche morgen mal die Dateien zeilenweise einzulesen.
Ab einer bestimmten Zeile habe ich dann statt 10 nur noch 9 Spalten in der Datei. Mein textscan funktioniert dann nicht mehr richtig.
Ich habe jetzt bereits versucht die datei zeilenweise mit fgetl einzulesen, die Zeile in einen String umzuwandeln und diesen aufzusplitten und die Anzahl der Elemente zu zählen. Allerdings kommt er da mit der unterschiedlichen Anzahl Leerzeichen nicht zurecht.
Code:
laenge = 1;
zeile = fgetl(fid);
i = 1;
while i <= 100%ischar(zeile) if i > 35% Header
A = regexp(cellstr(zeile),' ','split');
A{1}
laenge = laenge + 1;
end
zeile = fgetl(fid);
i = i + 1;
end
Auch ein Tabulator als Trennzeichen ändert nichts.
Gibt es da einen anderen Weg?
MarkusP
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 31.03.2015, 08:40
Titel:
Okay. Gerade gesehen, dass '\s+' zum Ziel führt.
Einstellungen und Berechtigungen
Du kannst Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen. Du kannst Dateien in diesem Forum posten Du kannst Dateien in diesem Forum herunterladen
MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.