Von gefundener Zele, weitere Zeilen suchen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
recnice
User
Beiträge: 45
Registriert: Sonntag 20. März 2011, 12:10

Hallo,

ich hab folgendes Problem:
Ich habe eine Datei, bei der ein Teil so aussieht:
  • Boundary Condition 5 ! Block oben
    Target Boundaries = 6
    Velocity 1 = Equals Mesh Velocity 1
    Velocity 2 = Equals Mesh Velocity 2

    Mesh Update 2 = Variable Coordinate 1
    Real
    include pandas_disp_x_bc_t_1_iter_1.dat

    End
Ich möchte nun ein Programm schreiben, dass unter bestimmten Bedingungen diesen Abschnitt in den folgenden ändert:
  • Boundary Condition 5 ! Block oben
    Target Boundaries = 6
    Velocity 1 = 0.0
    Velocity 2 = 0.0

    Mesh Update 2 = 0.0
    End
Mein Programm such bis der den Eintrag "include Pandas" und löscht ihn:

Code: Alles auswählen

#!/user/bin/py
# -*- coding: utf-8 -*-
feld_iter      	 = 1
time_step 	 = 1
elmer_init_file = "fsi.sif"
target = 'include pandas'

if feld_iter==1 and time_step==1:
  with open(elmer_init_file,'r') as init_sif_file:
    with open("mesh_update_t_"+str(time_step)+"iter_"+str(feld_iter)+"_.sif",'w') as new_sif_file:
      
      for line in init_sif_file:
	#print line,	
	if target in line:	  
	  new_include = line.replace(line,'')
	  new_sif_file.write(new_include)
	  
	else:
	  new_sif_file.write(line)
Also der Part "include Pandas" wird gesucht, gefunden un ersetzt.
Aber wie bekomme ich es hin, dass er nun von der gefunden Zeile aus, z.B. die 4 vor und die 4 Zeilen nach danach nach u.a. "Velocity 1" sucht und ersetzt?
Oder sollte ich es komplett anders angehen?

Gruß
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Du solltest es auf jeden Fall anders angehen, da Du im Moment zu sehr auf Dateiebene operierst!

Du brauchst eine Parser-Funktionalität, die aus Daten die wesentlichen Dinge extrahiert und in sinnvollen Datenstrukturen hinterlegt. Dann eine Komponente, die diese Daten entsprechend ändert.

Das Lesen und Schreiben auf Dateiebene kann man dann immer noch in separaten Funktionen implementieren.

Aber generell fehlen uns noch zu viele Infos: Was ist das für ein Format? Evtl. gibt es da fertige Parser? Wie verhällt es sich mit den Ziffern / Zahlen: Steht da immer eine "1" oder "6"? Wie viele Einträge von "Velocity x = " können denn da kommen? Immer nur exakt zwei? Soll da immer nur exakt der Wert "0.0" eingetragen werden? Wie fix oder variabel ist denn der Anfang des Blocks, also `Boundary Condition 5 ! Block oben`? Brauche ich überhaupt die Daten im Block oder kann ich das komplett statisch generieren?

Fragen, die immanent wichtig sind, um zu einem guten Ergebnis zu kommen!

Ach ja, verwende doch für solche Daten Code-Tags. Damit heben die sich besser vom normalen Text ab :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
recnice
User
Beiträge: 45
Registriert: Sonntag 20. März 2011, 12:10

Hi Hyperion,

Also die "Target Boundaries" kommen beliebig oft vor. Diese sind Teile eines Inputfiles für einen Solver
Diese folgende Einträge gelten dann nur für die erste Rechnung:

Code: Alles auswählen

Boundary Condition 5       ! Block oben
  Target Boundary = 6
  Velocity 1    =  0.0
  Velocity 2    =  0.0

  Mesh Update 2 =  0.0
  Mesh Update 1 =  0.0
 End
Danach soll für eben jenen "Target Boundaries" die Einträge der Velocity und Mesh-Update zu folgende umgeändert werden. Im weiteren verlauf
der Rechnung ändert sich dann nur noch der nachfolgende Eintrag von iter in den Zeilen "pandas_disp_x_bc_t_1_iter_2.dat" und "pandas_disp_x_bc_t_1_iter_2.dat" :

Code: Alles auswählen

Boundary Condition 5       ! Block oben
  Target Boundaries = 6
  Velocity 1    =  Equals Mesh Velocity 1
  Velocity 2    =  Equals Mesh Velocity 2
  
  Mesh Update 2 =  Variable Coordinate 1
  Real
       include pandas_disp_x_bc_t_1_iter_2.dat
           
  End

  Mesh Update 1 =   Variable Coordinate 1	
  Real
      include pandas_disp_x_bc_t_1_iter_2.dat
  End
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hm... waren meine Fragen zu kompliziert oder unverständlich? Ich sehe nicht eine davon wirklich beantwortet!

Ich weiß jetzt, dass es sich um das Eingabeformat für einen "Solver" handelt - welchen denn? Wie heißt das Programm? Oder ist dieses Format sogar ein Standardformat? (Das ist immer das erste, was zu klären ist, da man dann ggf. auf eine fertige Parser-Lib zurückgreifen kann!)

Was mir noch einfällt: Diese Dateien existieren also und Du willst an diesen spezielle Inhalte ändern? Oder aber existiert quasi nur das Grundgerüst und Du willst dieses mit Werten an speziellen Stellen konkretisieren?
Das muss geklärt werden, denn abhängig davon entscheidet sich, ob man einen Parser braucht, oder aber einfach mit einer Templating-Engine arbeiten kann.

Wenn Du mir das beantwortet hast, dann musst Du noch mal genauer auf das Format eingehen!

Woran erkenne ich einen zusammengehörigen Block? Wie wird dieser eindeutig und universell eingeleitet? Mit dem Keyword "Boundary", oder "Boundary Condition" oder sogar "Boundary Condition 5", oder...

Wie wird der Block abgeschlossen? Ist dafür "end" da? Kann das verschachtelt auftreten?

Wie sehen die "inneren" Einträge aus? Welche können da auftreten? Wie sieht deren Syntax aus?

Stehen diese in fester Reihenfolge? Kommen sie immer in gleicher Anzahl vor?

Und dann als letztes: Wie sollen Ersetzungen vorgenommen werden? Sind die Ersetzungen abhängig von den Inhalten der Ursprungsdatei? Sind die Änderungen immer fix?

Sorry, aber ohne eine klare, präzise und exakte Darstellung des Problems kommen wir nicht sinnvoll weiter. Und dazu sollen diese Fragen dienen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
recnice
User
Beiträge: 45
Registriert: Sonntag 20. März 2011, 12:10

Hi,
also dies ist das Eingabeformat für den Solver "Elmer" und ist kein Standardformat.

Die Grundidee ist, bei einem vorhandenen File an bestimmten Stellen nur das File zu verändern und daraus ein neues File zu generieren
was für die nächste Rechnung als Input für den Solver gilt!

Jetzt zu den Blocks:

Code: Alles auswählen

Boundary Condition 5                    //hier beginnt ein  Block; von diesen kann es viele geben   (Boundary Conditon 1, Boundary Conditon 2,....)
  Target Boundary = 6                   // hier entscheidet es sich ob der Block bearbeitet werden soll oder nicht
  Velocity 1    = 0.0
  Velocity 2    = 0.0
  
  Mesh Update 2 = 0.0
  Mesh Update 1 = 0.0
End                                            // Ende des Blocks
Die inneren Einträge sind konstant, mehr kann nicht dazukommen, weniger darf es nicht sein!

Die Änderung der Velocity 1,2 Einträge bleiben nachfolgend gleich, jeoch nicht die für Mesh Update Zeilen

aus "Mesh Update1 = 0.0"
wird

Code: Alles auswählen

Boundary Condition 5       ! Block oben                           
  Target Boundaries = 6
  Velocity 1    =  Equals Mesh Velocity 1                             // Vorher Velocity 1 = 0.0; im weiteren Verlauf konstant
  Velocity 2    =  Equals Mesh Velocity 2                             // Vorher Velocity 2 = 0.0,  im weiteren Verlauf konstant
  
  Mesh Update 2 =  Variable Coordinate 1                           // Vorher Mesh Update 2 = 0.0;  im weiteren Verlauf konstant
  Real                                                                              // neu;  im weiteren Verlauf konstant
       include pandas_disp_x_bc_t_1_iter_j.dat                    // neu    Eintrag nach t (hier:1) bleibt fix, Eintrag nach iter (hier: j) ändert sich absofort
  End                                                                              //   im weiteren Verlauf konstant

  Mesh Update 1 =   Variable Coordinate 1	                           //ab hier:  wie oben
  Real
      include pandas_disp_x_bc_t_1_iter_1.dat
  End
End
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

recnice hat geschrieben: also dies ist das Eingabeformat für den Solver "Elmer" und ist kein Standardformat.
Ok, also eine schnelle Recherche ergab bei mir nichts - allerdings gab es einige Foreneinträge im Projektforum, bei denen Leute mit Python einiges gemacht haben - ich weiß aber nicht was ;-)
recnice hat geschrieben: Die Grundidee ist, bei einem vorhandenen File an bestimmten Stellen nur das File zu verändern und daraus ein neues File zu generieren
was für die nächste Rechnung als Input für den Solver gilt!
Hier muss ich doch mal nachfragen: Ist das Ursprungsfile immer das selbe? Und wenn ja, ändern sich immer an den selben Stellen Werte? Das wäre doch wichtig zu wissen!

Und sollen diese Änderungen nur einmal vorgenommen werden? Oder ist das ein sich wiederholender Prozess und die neu einzutragenden Werte können sich auch noch mal ändern?

Ich muss darüber noch eine klarere Vorstellung bekommen, damit man den richtigen Ansatz zur Lösung wählt!

Evtl. kannst Du mal auf paste.pocoo.org eine komplette Beispieldatei posten?

Code: Alles auswählen

  Target Boundary = 6                   // hier entscheidet es sich ob der Block 
Ist also die "6" der Indikator?
recnice hat geschrieben: Die inneren Einträge sind konstant, mehr kann nicht dazukommen, weniger darf es nicht sein!
Also gibt es nur "Velocity 1" und "Velocity 2" und niemals "Velocity 3"? Gilt selbigs auch für "Mesh Update 2/1"?

Code: Alles auswählen

       include pandas_disp_x_bc_t_1_iter_j.dat                    // neu    Eintrag nach t (hier:1) bleibt fix, Eintrag nach iter (hier: j) ändert sich absofort
Also ist "j" eine Laufvariable? Diesen Ausdruck musst Du noch mal genauer erklären... evtl. mit einem Beispiel? (Und wie sieht der in einem weiteren Block aus, der geändert wird? Geht es dann mit "2" weiter oider wie?

Also stell hier noch mal klar, was an dem Ausdruck variabel ist und was nicht. Darüber hinaus, nach welchen Regeln sich die variablen Teile ändern.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
recnice
User
Beiträge: 45
Registriert: Sonntag 20. März 2011, 12:10

Ist das Ursprungsfile immer das selbe? Und wenn ja, ändern sich immer an den selben Stellen Werte
Genau, das Ursprungsfile bleibt unverändert und ist immer das Selbe.

Also nochmals zum genauen vorgehen:
Für eine initial Rechnung wird für die "Target Boundary 5" die folgenden Konditionen und somit folgenden Einträge gebraucht:

Code: Alles auswählen

Boundary Condition 5                    
  Target Boundary = 6                 
  Velocity 1    = 0.0
  Velocity 2    = 0.0
  
  Mesh Update 2 = 0.0
  Mesh Update 1 = 0.0
End      
Ist also die "6" der Indikator?
6 ist der Indikator, dass was passieren muss!
Im nächsten Schritt, ändern sich die Boundary Conditions:
Die Einträge "Equals Mesh Velocity 1" und "Equals Mesh Velocity 2" bleiben in den folgenden Rechnungen gleich, eine Velocity 3 oder Mesh Update 3 kommt nicht hinzu!
Die Werte für Mesh Update 2 und Mesh Update 1 sind nun in den Dateien pandas_disp_x_bc_t_1_iter_1.dat und pandas_disp_y_bc_t_1_iter_1.dat hinterlegt

Code: Alles auswählen

Boundary Condition 5       ! Block oben                           
  Target Boundaries = 6
  Velocity 1    =  Equals Mesh Velocity 1                            
  Velocity 2    =  Equals Mesh Velocity 2                            
  
  Mesh Update 2 =  Variable Coordinate 1                           
  Real                                                                             
       include pandas_disp_x_bc_t_1_iter_1.dat                  
  End                                                                            
  Mesh Update 1 =   Variable Coordinate 1                             
      include pandas_disp_x_bc_t_1_iter_1.dat
  End
End

Je Zeitschritt, hier Zeitschritt t=1 wird die Rechnung wiederholt bis ein bestimmtes Kriterium erfüllt ist, d.h. der Eintrag für die nächste Rechnung t=1, iter=2 muss wie folgt aussehen:

Code: Alles auswählen

Boundary Condition 5       ! Block oben                           
  Target Boundaries = 6
  Velocity 1    =  Equals Mesh Velocity 1                            
  Velocity 2    =  Equals Mesh Velocity 2                            
  
  Mesh Update 2 =  Variable Coordinate 1                           
  Real                                                                             
       include pandas_disp_x_bc_t_1_iter_2.dat        // Änderung:  iter_2            
  End                                                                            
  Mesh Update 1 =   Variable Coordinate 1                             
      include pandas_disp_x_bc_t_1_iter_2.dat        // Änderung:  iter_2  
  End
End

Also nur der iter-Eintrag in dem include File ändert sich, sonst nichts!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Moment! Wieso benutzt Du dann nicht zwei Dateien? Wenn Du die erste so für eine initiale Rechnung brauchst, ok. Aber alles was danach kommt, unterscheidet sich doch nur in *genau einer* Zahl untereinander - zumindest ist das das einzige, was ich nun bisher aus Deinen Infos heraus ziehen konnte.

Dieses Vorgehen würde es doch viel einfacher machen: Link

Das ist natürlich jetzt nur exemplarisch - in der Realität müsstest Du eben vermutlich die Templates noch aus den jeweiligen Datei laden.

Das sieht mir jedenfalls wesentlich leichter aus, als erst aus der initialen Datei die eigentliche Templatedatei zu erstellen...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
recnice
User
Beiträge: 45
Registriert: Sonntag 20. März 2011, 12:10

Die Idee mit den zwei Dateien hatte ich auch schon, fand dass mit einer Datei zu arbeiten und diese zu variieren schöner
wäre.
Hätte nicht geglaubt, dass das mit einer Datei so aufwendig werden würde...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

recnice hat geschrieben:Die Idee mit den zwei Dateien hatte ich auch schon, fand dass mit einer Datei zu arbeiten und diese zu variieren schöner
wäre.
Wieso das? Wenn die Dateien sich dermaßen unterscheiden... man könnte in einer mächtigeren Templateengine a la Jinja2 tatsächlich auch mit einer Templatedatei arbeiten: Link

Die Frage ist doch nur: Die initiale Datei hast Du doch eh vorliegen! Insofern müsstest Du doch eh nur die "echte" Templatedatei einmal anlegen...

recnice hat geschrieben: Hätte nicht geglaubt, dass das mit einer Datei so aufwendig werden würde...
Was ist an meinem Vorschlag so aufwendig? Der Code ist doch recht spärlich...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
recnice
User
Beiträge: 45
Registriert: Sonntag 20. März 2011, 12:10

Ja habe mit Templates bisher noch nichts gemacht, werd mich mal reinknien!
Zum prinzipiellen Verständnis:
Ein Template entspricht einer Datei mit Platzhalter, die eben mit bestimmten Werten befüllt werden ❔
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

recnice hat geschrieben: Ein Template entspricht einer Datei mit Platzhalter, die eben mit bestimmten Werten befüllt werden ❔
Ganz genau so.

Wobei mir jetzt nicht klar ist, was Dir hier noch "fehlt". Es ist doch nur diese eine Stelle, an der man den Index einsetzt...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten