C++ Problem in Openfoam
-
Hallo,
evtl. kennt sich einer ein bißchen mit der Software "Openfoam" aus. Ich denke mal die meisten nicht, aber im Prinzip ist das auch kein Problem. Es geht im wesentlichen darum für mich eine Gitterbewegung zu simulieren. Beim Setzen der zyklischen Randbedingungen gibt es allerdings ein Problem:
Man kann Zellschichten löschen, nehmen wir als Beispiel, dass unser Netz am Anfang 1500 Zellen hat. Dieser Wert wird "irgendwo" gespeichert und die Schleifen werden mit dieser Variablen durchlaufen. In dem Moment wo eine Zellschicht gelöscht wird, ändert sich die Zellenanzahl aber auf z.B. 1400. Im Hintergrund durchläuft er aber die Schleife noch mit dem alten Wert 1500 und die Berechnung stürzt mit einem "Segmentation faults" ab. Ich denke, wenn ich den folgenden Quelltext hineinsetze wird es klarer:
// 3. Baffles(coincident faces) converted into cyclics (e.g. jump) // 3. Übereinstimmende faces in cyclics konvertieren (z.B. springen) if (!matchedAll) { label baffleI = 0; forAll(*this, faceI) { const face& f = pp.localFaces()[faceI]; //hole faces const labelList& pFaces = pp.pointFaces()[f[0]]; label matchedFaceI = -1; forAll(pFaces, i) { label otherFaceI = pFaces[i]; Info << " pFaces[i] = " << pFaces[i] << " i=" << i << " and faceI= " << faceI << " and otherFaceI= " << otherFaceI << endl; if (otherFaceI > faceI) { const face& otherF = pp.localFaces()[otherFaceI]; Info << "otherFaceI = " << otherFaceI; // Note: might pick up two similar oriented faces // (but that is illegal anyway) if (f == otherF) { matchedFaceI = otherFaceI; Info << "matchedFaceI = " << matchedFaceI; break; } } }Die Abfrage von i wird in einer anderen Routine gemacht mit dem Wert "size_". Leider sind meine C++ nicht so gut, dass ich genau weiß wie ich diesen Wert auslese und evtl. ändern kann. Wenn ich bspw. eingebe
const groesse = size_
Kommt die Fehlermeldung, dass size_ privat deklariert ist (logisch). Hier mal der Fehler wie er ausgegeben wird.
**index 1400 out of range 0 ... 1399
From function UList<T>::checkIndex(const label)**
Quelltext wo die Fehlerabfrage passiert:
Constructors:
template<class T> inline Foam::UList<T>::UList() : v_(0), size_(0) {} template<class T> inline Foam::UList<T>::UList(T* __restrict__ v, label size) : v_(v), size_(size) {}Member functions:
// Check index i is within valid range (0 ... size-1). template<class T> inline void Foam::UList<T>::checkIndex(const label i) const { if (!size_) { FatalErrorIn("UList<T>::checkIndex(const label)") << "attempt to access element from zero sized list" << abort(FatalError); } else if (i<0 || i>=size_) { FatalErrorIn("UList<T>::checkIndex(const label)") << "index " << i << " out of range 0 ... " << size_-1 << abort(FatalError); } }Also das Problem nochmal zusammengefaßt:
Ich denke das ist soweit logisch.
Der Wert size_ beinhaltet schon die aktuelle Anzahl an Zellen (0...1399) aber die Schleife wird mit der Variablen pFaces durchlaufen, welche anscheinende noch den alten Wert beinhaltet (0..1499), damit ist klar, dass die Schleife abschmiert. Ich dachte ich setze einfach eine Bedingung
**
forAll(pFaces = size_, i)** aber da meckert der Compiler halt, dass es privat ist.
Hat jemand eine pfiffige Idee, wie ich die Abfrage austricksen könnte?
-
Wie sieht dieses forAll-Makro aus?
-
Hallo camper,
#define forAll(list, i) \ 00331 for (Foam::label i=0; i<(list).size(); i++)Hilft das was ?
-
Auch hier zu finden:
http://foam.sourceforge.net/doc/Doxygen/html/UList_8H-source.html
-
Die Fehleranalyse erscheint unzutreffend.
Soweit erkennbar, wird pFaces innerhalb der Schleife nicht verändert, und selbst wenn das anders wäre, würde sich die Abbruchbedung entsprechend ändern, da in jedem Durchlauf pFaces.size() erneut aufgerufen wird.
Sollte es also hier dennoch zu einem Zugriff auf ein nicht mehr existentes Element kommen, müssen wir schlussfolgern, dass die Liste bereits vorher defekt ist.
-
Das kann sein. Fakt scheint ja zu sein, dass er bei
const labelList& pFaces = pp.pointFaces()[f[0]]sich schon die unaktuelle Liste holt. Wenn ich mir die Listengröße anzeigen lasse, zeigt er mir tatsächlich den Wert 1500 kurz vor dem Segmentation fault an, obwohl es ja nur 1400 sein sollen.
Genau wie du es sagst ist bereits vorher die Liste "fehlerhaft". Was meinst du wäre ein guter Ansatzpunkt zum Beheben des Problems ?
-
Als Erstes würde ich die Stelle anschauen, bei der die Liste verändert wird.
Sieht so aus, als könnte man die Anzahl der Elemente nur per swap verändern.
-
So wird ja leider nicht verändert. Oder wie meinst du das ?
Was ich nicht so ganz verstehe ist, warum er in der UListI.H in der Variable size_ den richtigen Wert hat. Man müsste doch diesen nur für das Array einlesen oder ? Dadurch, dass der Wert aber geschützt ist kann ich von außen nicht darauf zugreifen.
Wie meinst du das mit der Swap Funktion? Kenne das nur für Werte tauschen, aber nie wirklich mit gearbeitet und bin ja auch kein Programmierer.

-
Enno schrieb:
In dem Moment wo eine Zellschicht gelöscht wird, ändert sich die Zellenanzahl aber auf z.B. 1400.
Löschen=ändern. Oder was soll das sonst bedeuten?
-
Hi camper, erstmal danke dass du dich so geduldig mit meinem Problem rumplagst.

Ja das ist schon richtig. Die Zellen, Punkte und Faces werden ab einem bestimmten Zeitpunkt gelöscht. Diese sind dann auch nicht mehr existent. Im Prinzip werden diese dann neu durchnummeriert von 0 bis size_ und die Liste, die diese Informationen enthält sollte normalerweise aktualisiert werden. Und mit diesem Wert soll er dann die Schleife von oben durchlaufen.
Eigentlich klingt das Problem doch total simpel von der Lösung her oder ?
-
Enno schrieb:
Im Prinzip werden diese dann neu durchnummeriert von 0 bis size_ und die Liste, die diese Informationen enthält sollte normalerweise aktualisiert werden.
Und das bedeutet, dass die Liste an irgendeiner Stelle im Programm verändert werden muss. Und genau um diese Stelle geht es.
-
Ich habe im debugger mal mit "bt" den Weg zum Fehler anzeigen lassen.
#0 0xb7fa4430 in __kernel_vsyscall () #1 0xb60a76d0 in raise () from /lib/tls/i686/cmov/libc.so.6 #2 0xb60a9098 in abort () from /lib/tls/i686/cmov/libc.so.6 #3 0xb653c4e8 in Foam::error::abort (this=0xb68c3640) at lnInclude/error.C:243 #4 0x08087e9c in Foam::operator<< <Foam::error> (os=@0x98bd5d8, m= {fPtr_ = 0xb653c1ea <Foam::error::abort()>, err_ = @0xb68c3640}) at /home/cfd/OpenFOAM/OpenFOAM-1.5-dev/src/OpenFOAM/lnInclude/errorManip.H:86 #5 0xb7e19fbf in Foam::UList<Foam::face>::checkIndex (this=0xa6a0308, i=1238) at /home/cfd/OpenFOAM/OpenFOAM-1.5-dev/src/OpenFOAM/lnInclude/UListI.H:111 #6 0xb7e19fea in Foam::UList<Foam::face>::operator[] (this=0xa6a0308, i=1238) at /home/cfd/OpenFOAM/OpenFOAM-1.5-dev/src/OpenFOAM/lnInclude/UListI.H:136 #7 0xb6635a64 in Foam::cyclicPolyPatch::order (this=0x99c1930, pp=@0xbf8bad0c, faceMap=@0xbf8badbc, rotation=@0xbf8badb4) at meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.C:1248 #8 0xb5c00ca0 in Foam::polyTopoChanger::reorderCoupledPatches (boundary=@0x990117c, patchStarts=@0xbf8bb470, patchSizes=@0xbf8bb478, faces=@0xbf8bb4a0, points=@0xbf8bb33c, faceMap=@0xbf8bb468, rotation=@0xbf8bb460) at polyTopoChange/polyTopoChanger/polyTopoChangerChangeMesh.C:155 #9 0xb5c048e0 in Foam::polyTopoChanger::changeMesh (mesh=@0x9900f88, ref=@0xa283ba8) at polyTopoChange/polyTopoChanger/polyTopoChangerChangeMesh.C:1052 #10 0xb5c0b192 in Foam::polyTopoChanger::changeMesh (this=0x9901844) at polyTopoChange/polyTopoChanger/polyTopoChangerChangeMesh.C:2406 #11 0xb7e6e24b in Foam::layerAR::update (this=0x9900f88) at engineTopoChangerMesh/layerAR/layerAR.C:255Ich fang mal bei #9 an:
bool anyChange = reorderCoupledPatches ( boundary, patchStarts, patchSizes, newFaces, // new faces newPointsMotion, // points after inflation localFaceMap, // for every face the new position rotation // amount face needs to be rotated );#8
bool changed = boundary[patchI].order ( primitivePatch ( SubList<face> ( faces, patchSizes[patchI], patchStarts[patchI] ), points ), patchFaceMap, patchFaceRotation );#7 Das aus dem Startpost mit der forAll-Schleife
#6 Diese UList-Abfrage
...
In diesen Algorithmen werden die Zellen, Faces usw. neu sortiert. Ich kann aber nicht erkennen in welche Liste bzw. wo er es hinschreibt

Die scheinen ja alle irgendwie in labellist zu stehen ( const labelList& pFaces = pp.pointFaces()[f[0]]
-
Hallo Enno,
konntest Du das Problem lösen?
Ich hänge wahrscheinlich an der gleichen Stelle....Viele Grüße,
Georg