1 / 18

Struktur-Funktions-Modelle von Pflanzen - Sommersemester 2010 - Winfried Kurth

Struktur-Funktions-Modelle von Pflanzen - Sommersemester 2010 - Winfried Kurth Universität Göttingen, Lehrstuhl Computergrafik und Ökologische Informatik 12. Vorlesung: 8. 7. 2010. letztes Mal: Analyse des Fichtenmodells Fortsetzung: Vorstufen des Pappelmodells

zared
Download Presentation

Struktur-Funktions-Modelle von Pflanzen - Sommersemester 2010 - Winfried Kurth

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Struktur-Funktions-Modelle von Pflanzen - Sommersemester 2010 - Winfried Kurth Universität Göttingen, Lehrstuhl Computergrafik und Ökologische Informatik 12. Vorlesung: 8. 7. 2010

  2. letztes Mal: • Analyse des Fichtenmodells • Fortsetzung: Vorstufen des Pappelmodells • Beschreibung des Pappelmodells • Aufgabenstellung der Hausarbeit • Bewertungskriterien

  3. als nächstes: • noch ein neuer Regeltyp: Instanzierungsregeln • dtd-Daten zu den ausgemessenen Pappeln • Beantwortung von Fragen zum Pappelmodell • und zur Hausarbeit

  4. Ein weiterer Regeltyp in XL: • Instanzierungsregeln • Zweck: Ersetzung einzelner Module durch kompliziertere Strukturen, nur für die Darstellung • (wie bei Interpretationsregeln) • aber: es wird weniger abgespeichert (Einsparen von • Speicherplatz) • anders als bei Interpretationsregeln dürfen keine Turtle- • Befehle mit Wirkung auf andere Knoten verwendet werden • weitere Möglichkeit: „Replikator-Knoten“ zum Kopieren und Neuplatzieren von ganzen Strukturen

  5. Instanzierungsregeln: Syntax kein neuer Regelpfeil Angabe der Instanzierungsregel direkt in der Moduldeklaration module A ==> B C D; ersetzt (instanziert) überall A durch B C D Beispiel sm09_b43.rgg

  6. const int multiply = EDGE_0; /* selbstdefinierter Kantentyp */ module Tree ==> F(20, 1) [ M(-8) RU(45) F(6, 0.8) Sphere(1) ] [ M(-5) RU(-45) F(4, 0.6) Sphere(1) ] Sphere(2); module Replicator ==> [ getFirst(multiply) ] Translate(10, 0, 0) [ getFirst(multiply) ]; public void run1() [ Axiom ==> F(2, 6) P(10) Tree; ] public void run2() [ Axiom ==> F(2, 6) P(10) Replicator -multiply-> Tree; ] Tree wird mit der roten Struktur instanziert es wird eingefügt, was an der „multiply“-Kante hängt

  7. Hausaufgabe vom letzten Mal: • - Fertigstellung der dtd-Datei auf Grundlage Ihrer Messdaten • - erste Plausibilitätsprüfung • erste Sichtung des Pappelmodells; Fragen dazu? • Anhang:XL-Code des Pappelmodells (ohne Photosyntheseteil)

  8. /* Datei streckung.rgg, gehoert zu pappel.gsz */ /* Aenderungen gegenueber frueherer Version: Wichtig: Die Basiszeiteinheit dieser Simulation liegt bei einer Stunde, d.h. pro Ausfuehrung des run()-Regelblocks vergeht eine Stunde Simulationszeit. Definiert wird dies durch die Konstante NUMBER_OF_TIME_UNITS_DURING_A_DAY = 24. Alle weiteren Angaben sind relativ zu dieser Angabe. Die Photosyntheseberechnung wurde auf SI-Einheiten umgestellt. Kommentare wurden ergaenzt. Die Statusvariable fuer das Oeffnen des Datenfiles wurde geaendert. */ import java.io.*; // Import der zweiten rgg-Datei: import static photosynthese.*; /**************************************************************************/ /************************* Modul-Definitionen des Baumes ******************/ /**************************************************************************/ // Der ganze Baum: module Tree(int age, float pspool) extends Sphere(0.01); // ein einfaches Internodium mit einer festen, sehr kleinen Startgroesse: module Internode(int alter, int lnfb) extends F(0.01, 0.0005) { // Variable zur Speicherung der freien Assimilate: float pspool = 0; float mass = 0; { setShader(GREEN); } public double getVolume() { return Math.PI*(this.diameter)*(this.diameter) / 4 * this.length; } public double getMass() { return this.getVolume()*INTERNODIUM_DENSITY; } }

  9. // ein Meristem als Keimzelle des Wachstums: module Meristem(int alter, int lnfb) extends Sphere(0.0005) {{ setShader(RED); }}; // lnfb = leaf number from base // der Blattstiel: module Petiole(int alter, int lnfb) extends F(0.001, 0.0001) { // Variable zur Speicherung der freien Assimilate: float pspool = 0.0; float mass = 0.0; { setShader(GREEN); } public double getVolume() { return Math.PI*(this.diameter)*(this.diameter) / 4 * this.length; } public double getMass() { return this.getVolume()*PETIOLE_DENSITY; } } // das Blatt: die Groesse wird hier ueber Scale gesetzt. // Basis der Scale-Berechnung ist 1 Meter Laenge und 0.77 Meter Breite // (definiert durch LEAF_LENGTH_WIDTH_RATIO). // Das Verhaeltnis ist zur Zeit unveraenderlich! module Blade(int alter, int lnfb) extends Parallelogram(1.0, 1.0/LEAF_LENGTH_WIDTH_RATIO) { //Variable zur Speicherung der freien Assimilate float pspool = 0; float leafarea = 0; float mass = 0; public double getMass() { return this.leafarea*LEAF_WEIGHT_PER_SQUAREMETER; } };

  10. // Module zum Veraendern der Winkel (zwischen Internodium und Blattstiel // und zwischen Blattsiel und Blattspreite): // Die Eigenschaften des Moduls werden durch eine Aktualisierungsregel // veraendert, so dass sich die Position der Blaetter waehrend der Simulation // veraendert. module Winkel(super.angle, int max_angle) extends RL(angle); /*************** Die Sonne: **************************************/ // Die Sonne, sie umkreist den Baum einmal pro Tag ... module Sonne(float ppfd) extends Sphere(3.3) {{ setShader(RGBAShader.YELLOW);}}; // Hilfssymbol zur Bewegung der Sonne: module Sonnenwinkel(super.angle) extends RU(angle); /**************************************************************/ /************** Konstanten und globale Variablen: *************/ /**************************************************************/ const float NUMBER_OF_TIME_UNITS_DURING_A_DAY = 24; // dient der Umrechnung von Tageswerten (Photosynthese) auf die // Bezugsgroesse Basiszeiteinheiten. const Shader leafmat = shader("Leaf1"); // Textur fuer die Blaetter const PrintWriter tmpfile; // Ausgabespeicher: -> Ausgabe in Datei private Boolean tmpFileOpen = false; // Kontrollvariable, ob Datenfile offen ist. const Vector3d zz = new Vector3d(0, 0, 1); // Richtung nach oben const int PLASTOCHRON = 48; // Anzahl der Zeiteinheiten zwischen dem Erscheinen zweier Blaetter

  11. // Maximale Wachstumszeiten fuer die drei Metamer-Bestandteile: // koennen fuer Stopbedingungen fuer das Wachstum genutzt werden. const int MAX_GROWTHTIME_INTERNODE = 600; // in Basiszeiteinheiten const int MAX_GROWTHTIME_PETIOLE = 30; // in Basiszeiteinheiten const int MAX_GROWTHTIME_LEAF = 96; // in Basiszeiteinheiten // Wachstumsraten fuer die drei Metamer-Bestandteile // Wachstum pro Zeiteinheit const float GROWTH_RATE_INTERNODE_LENGTH = 0.001; // in Metern const float GROWTH_RATE_INTERNODE_DIAMETER = 0.000004; // in Metern const float GROWTH_RATE_PETIOLE_LENGTH = 0.00117; // in Metern const float GROWTH_RATE_PETIOLE_DIAMETER = 0.000031; // in Metern const float GROWTH_RATE_LEAF_SCALE = 0.0016; // betrifft beide Achsen: Skalierungsfaktor der Basisgroesse des // Blattes von 1 Meter * 0.77 Meter // Definition von 3 Wachstumszonen am Baum: // Die oberste Wachstumszone wird definiert durch den maximalen // Leaf Position Index (LPI): -1 bis TOPSECTION_MAXLPI. // Die unterste Wachstumszone durch die angegebene maximale // Leaf Number From Base (LNFB): 1 bis BASESECTION_MAXLEAFNUMBER. // Die mittlere Wachstumszone umfasst alle anderen Blaetter. // Die Wachstumszone wird errechnet durch die Servicefunktion // getGrowthSection() const int TOPSECTION = 0; const int TOPSECTION_MAXLPI = 8; const int MIDDLESECTION= 1; const int BASESECTION = 2; const int BASESECTION_MAXLEAFNUMBER = 5; // maximale Dimensionen fuer die 3 Metamerbestandteile: // die Werte werden als Arry getrennt fuer die drei Wachstumszonen // angegeben const float[] MAX_GWROWTH_INTERNODE = {0.01, 0.03, 0.02}; // in Metern const float[] MAX_GWROWTH_PETIOLE = {0.01, 0.07, 0.02}; // in Metern const float[] MAX_GWROWTH_LEAF_SCALE = {0.07, 0.09, 0.03}; // in Metern

  12. const float LEAF_LENGTH_WIDTH_RATIO = 1.3; // konstantes Laengen / Breitenverhaeltnis der Blaetter const float LEAFFORMFACTOR = 0.6; // Flaechenanteil der realen Blattflaeche an Laenge * Breite const float INTERNODIUM_DENSITY = 106.0; // in kg/m^3 const float PETIOLE_DENSITY = 106.0; // in kg/m^3 const float LEAF_WEIGHT_PER_SQUAREMETER =100.0; // in kg/m^2 /***************** Winkel: ****************/ const int LEAF_MAX_ANGLE = 55; const int PETIOLE_MAX_ANGLE = 90; // Maximaler Divergenzwinkel zwischen zwei Internodien: const int MAX_ORIENTATION_ANGLE = 5; // Azimuthwinkel fuer den Ansatzpunkt der Blaetter am Stamm: const int MAX_AZIMUTH = 160; const int MIN_AZIMUTH = 120; // Seitliche Drehung der Blattspreite um die Blattstielachse (nicht gemessen) const int MAX_ANGLE_LAMINA = 5; //angle of lamina /******************** globale Variablen: ***************************/ public float totalPSPool = 0.0; public int maxleaf = 0; // aktuelle Zahl aller Blaetter des Baumes public int time = 0; // Zaehlvariable fuer aktuelle Zeit

  13. /***************************************************************//***************************************************************/ /**************** Regelbloecke: ********************************/ /***************************************************************/ protected void init() { time = 0; maxleaf = 0; [ Axiom ==> Tree(0, 0.03) Meristem(0, 0) { totalPSPool = 0.03; }, ^ Sonnenwinkel(0) RU(90.0) M(50.0) Sonne(0); ] } // Zentrale Methode zur Steuerung des Simulationslaufes: // Ruft die Regelbloecke fuer die Photosntheseberechnung, den Transport // der freien Assimilate und das Wachstum der Metamere und der Bewegung // der Sonne auf. Basis der zeitlichen Abfolge ist die Variable time. public void run() { if (!tmpFileOpen) newDataFile(); println("Stunde:" + time + " Gesamt-Produktion: " + totalPSPool); tmpfile.println("Stunde" + time + "Gesamt-Produktion: " + totalPSPool); for (apply(1)) moveSun(360 / NUMBER_OF_TIME_UNITS_DURING_A_DAY); for (apply(1)) photosynthese(NUMBER_OF_TIME_UNITS_DURING_A_DAY); for (apply(4)) transport(); for (apply(1)) grow(); tmpfile.flush(); // Schreiben des Speichers tmpfiles in die Datei. time ++; } // Regel zur Kalkulation der Photosynthese in den Blaettern: // Die Photosyntheseberechnung erfolgt immer fuer einen Tagesgang. // Daher ist es noetig, den Anteil fuer die Zeitschritte zu berechnen. // Hierzu wird durch number_of_time_units geteilt.

  14. private void photosynthese(float number_of_time_units) { tmpfile.println(" Photosynthese"); [ s:Blade ::> { int lpi = getLPI(maxleaf, s[lnfb]); s[leafarea] = s[scale] * s[scale] / LEAF_LENGTH_WIDTH_RATIO * LEAFFORMFACTOR; println("blattflaeche" + s[leafarea]); float production = calculatePS(s[leafarea], convertMC(lpi)) / number_of_time_units; s[pspool] += production; totalPSPool += production; // tmpfile.println(" Blatt: " + s[lnfb] + " LPI " + lpi + // " Pool: " + s[pspool] + " Blattflaeche: " + s[leafarea]); } ] } // Regelblock fuer das Wachstum der Pflanze: // es existieren Unter-Regelbloecke fuer das Meristem, Internodium, Petiole, Blade und Winkel. private void grow() { // Regelblock fuer das Meristem: [ // erste Regel: Das Meristem altert m1:Meristem ::> m1[alter] :+= 1; // fuer ein neues Meristem: Bildung des Internodiums: m2:Meristem, ((m2[alter] == PLASTOCHRON) || (m2[lnfb] == 0)) ==> Internode(0, m2[lnfb]+1) [ Winkel(0, PETIOLE_MAX_ANGLE) Petiole(0, m2[lnfb]+1) RH(random(MAX_ANGLE_LAMINA, -MAX_ANGLE_LAMINA)) Winkel(1,LEAF_MAX_ANGLE) [ Blade(0, m2[lnfb]+1).(setShader(leafmat), setScale(0.001)) { maxleaf++; } ] ] RH(random(MAX_AZIMUTH, MIN_AZIMUTH)) RU(random(MAX_ORIENTATION_ANGLE, -MAX_ORIENTATION_ANGLE)) Meristem(0, m2[lnfb]+1); ] // Regelblock fuer das Veraendern der Winkel von Blattstiel und Blatt: [ x:Winkel, (x[angle] <= x[max_angle]) ::> x[angle] :+= 1; ]

  15. // Regelblock fuer die Streckung des Internodiums [ i:Internode ::> { if (i[alter] < MAX_GROWTHTIME_INTERNODE && i[length] <= MAX_GWROWTH_INTERNODE[getGrowthSection(maxleaf, i[lnfb])]) { i[length] += GROWTH_RATE_INTERNODE_LENGTH; } // Laengenwachstum in den ersten 30 Tagen i[diameter] += GROWTH_RATE_INTERNODE_DIAMETER; // Dickenwachstum immer i[alter]++; // Hochsetzen des Alters i[mass] = i.getMass(); } ] // Regelblock fuer die Streckung des Blattstiels in den ersten 60 Tagen: [ p:Petiole, (p[alter] < MAX_GROWTHTIME_PETIOLE && p[length] < MAX_GWROWTH_PETIOLE[getGrowthSection(maxleaf, p[lnfb])]) ::> { p[length] += GROWTH_RATE_PETIOLE_LENGTH; // Laengenwachstum p[diameter] += GROWTH_RATE_PETIOLE_DIAMETER; // Dickenwachstum p[alter]++; // Hochsetzen des Alters p[mass] = p.getMass(); } ] // Regelblock fuer das Blattwachstum: [ s:Blade, (s[alter] < MAX_GROWTHTIME_LEAF && s[scale] < MAX_GWROWTH_LEAF_SCALE[getGrowthSection(maxleaf, s[lnfb])]) ::> { s.setScale(s[scale] + GROWTH_RATE_LEAF_SCALE); s[alter]++; s[mass] = s.getMass(); } ] }

  16. // Regelblock fuer den Transport von Assimilaten innerhalb der Pflanze: es existieren mehrere Transportwege // Blade (Quelle) -> zum tragenden Internodium // Internodium -> zum benachbarten Internodium // Tree (Keimling) -> zum ersten Infernodium private void transport() { tmpfile.println(" Transport " ); // Transport Blade -> zum tragenden Internodiium [ b:Blade -ancestor-> i:Internode ::> { if (getLPI(maxleaf, b[lnfb]) >= 4) { float r = 0.01 * (b[pspool] - i[pspool]); b[pspool] :-= r; i[pspool] :+= r; tmpfile.println(" Blatt: " + b[lnfb] + " zu Internode " + i[lnfb] + " Menge: " + r); } } ] // Transport Internodium -> zum benachbarten Internodium [ i_oben:Internode -ancestor-> i_unten:Internode ::> { float r = 0.01 * (i_unten[pspool] - i_oben[pspool]); tmpfile.println(" Transport von Internodium: " + i_unten[lnfb] + "zu : " + i_oben[lnfb] + " Menge: " + r); i_unten[pspool] :-= r; i_oben[pspool] :+= r; } ] // Transport Tree -> zum ersten Internodium [ t:Tree -successor-> i:Internode, (t[pspool] > 0.0001) ::> { float r = 0.001 * t[pspool]; tmpfile.println(" Transport von Treepool zu Internodium: " + i[lnfb] + " Menge: " + r); t[pspool] :-= r; i[pspool] :+= r; } ] /* Hier moegl. Ergaenzung Transp. zum Meristem: Sinnvoll bei Kopplung d. Metamerbildung an vorh. Assimil. */ }

  17. private void moveSun(float sonnenbewegung) [ // Bewegung der Sonne: Hat nur Bedeutung für die Animation. // Es existiert kein Bezug zur numerischen Simulation. x:Sonnenwinkel ::> x[angle] :+= sonnenbewegung; ] /********************** Methoden mit Zugriff auf die Struktur ***********/ // Beschattungsfunktion: prueft, ob es fuer einen Knoten "s" // innerhalb eines Sichtkegels mit der Oeffnungsweite 40 Grad (kann man veraendern) // ein Objekt f der Modul-Klasse Petiole (Blattstiel) gibt, wobei "s" (als // "Beobachter" sozusagen) nicht beruecksichtigt wird. Rueckgabewert ist false // oder true private static boolean isShaded(Node s) { return !empty( (* f:Petiole, (f != s && f in cone(s, zz, 40)) *) ); } /********************** Methoden zur Berechnung ************************/ private int getLPI(int maxLeaf, int lnfb) { return maxLeaf - lnfb - 1; } private int getGrowthSection(int maxleaf, int lnfb) { int section = 0; if (lnfb <= BASESECTION_MAXLEAFNUMBER) section = BASESECTION; else if(getLPI(maxleaf, lnfb) <= TOPSECTION_MAXLPI) section = TOPSECTION; else section = MIDDLESECTION; return section; }

  18. /********************* Methoden fuer Serviveausgaben ********************/ private void newDataFile() { tmpfile = new PrintWriter(new FileWriter("c:\\tmp\\dataoutput3.txt")); tmpFileOpen = true; } //-------- Spezielle Methode (public) zum Schliessen der Datei public void closeDataFile() { tmpfile.close(); // Schliessen der Datei tmpFileOpen = false; }

More Related