Tutorial Model Developers
Contents |
Development of JAMS Components
Installation of a Development Environment
You can download the development environment NetBeans at http://netbeans.org for free. The latest version is NetBeans IDE 6.9.1. Select Java SE, JavaFX, Java or All as NetBeans IDE Download package. In addition, the Java Development Kit (JDK) is required which can be downloaded at http://www.oracle.com/technetwork/java/javase/downloads/index.html.
Your NetBeans developer environment looks like this after starting it:
Loading JAMS/J2000 sources from the Internet
The Java sources from JAMS/J2000 and various standard components, including all required libraries, can be downloaded at http://www.geoinf.uni-jena.de/5580.0.html using the link JAMS-2 16-src.tgz.
The following source folders are included:
Projekte in NetBeans anlegen
Die Projekte sollten in der im Folgenden beschriebenen Reihenfolge eingebunden werden.
1. Schritt - Einbinden des Projektes JAMS
Nun müssen die JAMS/J2000 Quellen ins Netbeans geladen werden. Im ersten Schritt wird das JAMS-Projekt angelegt. Öffnen Sie dazu NetBeans und wählen Sie unter dem Menüpunkt File den Punkt New Project.
Das folgende Fenster wird angezeigt:
Da Sie bestehenden Quellcode einbinden wollen, wählen Sie Java Project with Existing Source. Klicken Sie Next. Im zweiten Schritt muss ein Name sowie ein Projektordner angegeben werden. Nennen sie das Projekt JAMS. Ein Projektordner ist standardmäßig angegeben, kann aber von Ihnen verändert werden. Klicken Sie auf Next.
Laden Sie über den Button Add Folder die folgenden Source-Quellen in das Projekt.
- JAMSapi
- JAMScommon
- JAMSExplorer
- JAMSMain
- JAMSRemote
- JAMSstarter
- JAMSui
Klicken sie auf Finish.
Im nächsten Schritt müssen im Projekt die erforderlichen Bibliotheken geladen werden. Diese sind im heruntergeladenen Quellordner unter JAMS-2_x-src\ext zu finden. (x steht für die aktuell heruntergeladene Version, die sich jedoch im Laufe der Zeit verändert) Klicken Sie dazu im erzeugten JAMS-Projekt mit der rechten Maustaste auf das Projekt JAMS. Wählen Sie den Punkt Properties.
Wählen Sie im rechten Bereich des Fensters Project Properties - JAMS unter Categories den Punkt Libraries. Mithilfe des Buttons Add JAR/Folder können die benötigten Bibliotheken geladen werden. Laden Sie alle Bibliotheken, die im heruntergeladenen Quellordner JAMS-2_x-src\ext vorhanden sind.
Das JAMS Projekt wurde angelegt.
Möchten Sie das Projekt kompilieren, so klicken sie mit der rechten Maustaste aus das JAMS Projekt und wählen den Punkt Build and Clean. Das JAMS.jar wir erzeugt. Im unteren linken Fenster Ihrer NetBeans Entwicklerumgebung sehen Sie, ob der Prozess erfolgreich war und wohin die JAMS.jar gespeichert worden ist.
2. Schritt - Einbinden des Projektes J2000
Binden Sie wie im ersten Schritt beschrieben nun das Projekt J2000 als neues Projekt mit existierenden Quellen ein. Die Quellen befinden sich im Verzeichnis ...\JAMS-x-src\J2K\src, welches Sie heruntergeladen haben.
Laden Sie als Bibliothek die im ersten Schritt erzeugte JAMS.jar.
Bild:Bibliotheken_laden_J2000.png
Kompilieren Sie das neue Projekt indem Sie mit der rechten Maustaste auf das Projekt J2000 klicken und den Menüpunkt Build and Clean auswählen. Im unteren rechten Fenster Ihrer NetBeans-Entwicklerumgebung sollte nun BUILD SUCCESSFUL erscheinen.
3. Schritt - Einbinden des Projektes JAMSComponents
Binden Sie wie im ersten Schritt beschrieben nun das Projekt JAMSComponents als neues Projekt mit existierenden Quellen ein. Die Quellen befinden sich im Verzeichnis ...\JAMS-x-src\JAMSComponents\src, welches Sie heruntergeladen haben.
Laden Sie als Bibliothek die im ersten Schritt erzeugte JAMS.jar, sowie alle Bibliotheken (*.jar - Files) aus dem Ordner ...\JAMS-x-src\ext. Bild:Bibliotheken_laden_JAMSComponents.png
Kompilieren Sie das neue Projekt indem Sie mit der rechten Maustaste auf das Projekt J2000 klicken und den Menüpunkt Build and Clean auswählen. Im unteren rechten Fenster Ihrer NetBeans-Entwicklerumgebung sollte nun BUILD SUCCESSFUL erscheinen.
Starten von Prozesskomponenten aus dem NetBeans
Jede Prozesskomponente welche über eine Main-Procedure vefügt, kann aus dem NetBeans direkt gestartet werden. Beispielhaft werden wir in den nächsten Schritten den JAMSLaucher, welcher im Tutorium für Anfänger genauer beschrieben ist, direkt starten.
Main Klassen
Klicken Sie mit der rechten Maustaste auf das Projekt JAMS. Wählen Sie den Menüpunkt Properties. Klicken Sie im linken Teil des Fensters auf run. Tragen Sie als Main Class die Klasse ein, die bei der Projektausführung gestartet werden soll. Mit einem Klick auf den Button Browse... werden alle im Projekt verfügbaren Main Classes angezeigt, das sind alle Komponenten, die über eine Main-Procedure verfügen. Wählen Sie beispielhaft jamsui.launcher.JAMSui. Klicken Sie auf Set Main Class. Das folgende Fenster sollte angezeigt werden:
Klicken Sie auf OK. Starten Sie jetzt das Projekt JAMS, indem Sie mit der linken Maustaste auf das Projekt klicken und dann den Punkt run auswählen. Der JAMSLauncher wird gestartet. Auf diese Art und Weise, können beliebige Klassen, welche über Main-Proceduren verfügen, gestartet werden.
Entwicklung neuer Prozesskomponenten in JAVA
Aufbau einer Komponente
Eine JAMSProzesskomponente ist immer folgendermaßen aufgebaut:
1. Paketname. Dieser wird von NetBeans automatisch erzeugt.
package org.unijena.j2k.interception;
2. Importieren von Bibliotheken/Klassen die für die Prozesskomponente benötigt werden.
import jams.data.*; import jams.model.*; ...
3. Start der Prozesskomponente. Jede Prozesskomponente beginnt mit eine Komponentenbeschreibung. Damit können Metainformationen zur Komponente im Quellcode verankert werden. Es sollten Informationen zum Titel der Komponente, zum Autor, zur Version und zum Erstellungdatum hinterlegt werden. Weiterhin ist eine kurze Beschreibung der Komponente erforderlich.
@JAMSComponentDescription( title="...", author="...", description="...", version="...", date="..." )
public class NewClass {
4. Variablenblock öffentlicher und privater Variablen. Auf die öffentlichen Variablen kann auch aus anderen Klassen innerhalb eines Modells zugegriffen werden. Zu jeder öffentlichen Variable werden Bemerkungen in Form von Annotations im Quellcode verankert.
Für den Zugriffstype (AccessType) muss zwischen JAMSVarDescription.AccessType.READ (Variablen die nur gelesen werden), JAMSVarDescription.AccessType.WRITE (Variablen die nur geschrieben werden) und JAMSVarDescription.AccessType.READWRITE (Variablen die gelesen als auch geschrieben werden) gewählt werden.
Weiterhin ist eine kurze Beschreibung und wenn möglich eine Einheit sowie obere und untere Schranke der Variable erforderlich.
@JAMSVarDescription( access =... , description = "...", unit = "...", lowerBound= ..., upperBound =... ) public JAMSDouble var1; @JAMSVarDescription( access =... , description = "...", unit = "...", lowerBound= ..., upperBound =... ) public JAMSInteger var2; @JAMSVarDescription( access =... , description = "...", unit = "...", lowerBound= ..., upperBound =... ) public JAMSString var3; ... private JAMSDoublr var4; ...
Jede JAMS- oder J2000-Klasse verfügt über die Prozeduren init(), run() und cleanup().
5. Die init-Prozedur wird zur Modellinitialisierung durchlaufen.
public void init() throws JAMSEntity.NoSuchAttributeException{ ... }
6. Die run-Prozedur wird während der Modellausführeung durchlaufen.
public void run() throws JAMSEntity.NoSuchAttributeException{ ... }
7. Die cleanup-Prozedur wird am Ende eines Modelllaufs durchlaufen.
public void cleanup() throws JAMSEntity.NoSuchAttributeException{ ... }
8. Private Prozeduren und Funktionen. Diese stehen nur innerhalb der Prozesskomponente zur Verfügung.
private double funktion1(double var){ ... return ...; }
9. Ende der Prozesskomponente.
}
Beispiel einer vollständigen Prozesskomponente
1. Paketname.
package org.unijena.j2k.potET;
2. Importierte Bibliotheken
import java.io.*; import jams.data.*; import jams.model.*;
3. Start der Prozesskomponente. Jede Prozesskomponente beginnt mit eine Komponentenbeschreibung. Damit können Metainformationen zur Komponente im Quellcode verankert werden. Es sollten Informationen zum Titel der Komponente, zum Autor, zur Version und zum Erstellungdatum hinterlegt werden. Weiterhin ist eine kurze Beschreibung der Komponente erforderlich.
@JAMSComponentDescription( title=""CalcDailyETP_PenmanMonteith"", author="Peter Krause", description="Calculates potential ETP according Penman-Monteith", version="1.0_0", date="2011-04-11" )
public class Penman extends JAMSComponent {
4. Variablenblock öffentlicher und privater Variablen. Auf die öffentlichen Variablen kann auch aus anderen Klassen innerhalb eines Modells zugegriffen werden. Zu jeder öffentlichen Variable werden Bemerkungen in Form von Annotations im Quellcode verankert.
Für den Zugriffstype (AccessType) muss zwischen JAMSVarDescription.AccessType.READ (Variablen die nur gelesen werden), JAMSVarDescription.AccessType.WRITE (Variablen die nur geschrieben werden) und JAMSVarDescription.AccessType.READWRITE (Variablen die gelesen als auch geschrieben werden) gewählt werden.
Weiterhin ist eine kurze Beschreibung und wenn möglich eine Einheit sowie obere und untere Schranke der Variable erforderlich.
@JAMSVarDescription(access = JAMSVarDescription.AccessType.READ, description = "Current time") public JAMSCalendar time; @JAMSVarDescription(access = JAMSVarDescription.AccessType.READ, description = "temporal resolution [d | h | m]") public JAMSString tempRes; @JAMSVarDescription(access = JAMSVarDescription.AccessType.READ, description = "state variable wind") public JAMSDouble wind; @JAMSVarDescription(access = JAMSVarDescription.AccessType.READ, description = "state variable mean temperature") public JAMSDouble tmean; @JAMSVarDescription(access = JAMSVarDescription.AccessType.READ, description = "state variable relative humidity") public JAMSDouble rhum; @JAMSVarDescription(access = JAMSVarDescription.AccessType.READ, description = "state variable net radiation") public JAMSDouble netRad; @JAMSVarDescription(access = JAMSVarDescription.AccessType.READ, description = "attribute elevation") public JAMSDouble elevation; @JAMSVarDescription(access = JAMSVarDescription.AccessType.READ, description = "attribute area") public JAMSDouble area; @JAMSVarDescription(access = JAMSVarDescription.AccessType.WRITE, description = "potential ET [mm/ timeUnit]") public JAMSDouble potET; @JAMSVarDescription(access = JAMSVarDescription.AccessType.WRITE, description = "actual ET [mm/ timeUnit]") public JAMSDouble actET; @JAMSVarDescription(access = JAMSVarDescription.AccessType.READ, description = "et calibration parameter") public JAMSDouble et_cal; @JAMSVarDescription(access = JAMSVarDescription.AccessType.READ, defaultValue = "0") public JAMSInteger dataCaching; private File cacheFile; transient private ObjectOutputStream writer; transient private ObjectInputStream reader; public final double CP = 1.031E-3; //konstanter Parameter public final double RSS = 150; //konstanter Parameter
5. Die init-Prozedur wird zur Modellinitialisierung durchlaufen.
public void init() throws JAMSEntity.NoSuchAttributeException, IOException { cacheFile = new File(getModel().getWorkspace().getTempDirectory(), this.getInstanceName() + ".cache"); if (!cacheFile.exists() && (dataCaching.getValue() == 1)) { getModel().getRuntime().sendHalt(this.getInstanceName() + ": dataCaching is true but no cache file available!"); } if (dataCaching.getValue() == 1) { reader = new ObjectInputStream(new BufferedInputStream(new FileInputStream(cacheFile)));//new FileInputStream(cacheFile)); } else if (dataCaching.getValue() == 0) { writer = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(cacheFile))); } }
6. Die run-Prozedur wird während der Modellausführeung durchlaufen.
public void run() throws JAMSEntity.NoSuchAttributeException, IOException { if (dataCaching.getValue() == 1) { this.potET.setValue(reader.readDouble()); this.actET.setValue(0.0); } else { double netRad = this.netRad.getValue(); double temperature = this.tmean.getValue(); double rhum = this.rhum.getValue(); double wind = this.wind.getValue(); double elevation = this.elevation.getValue(); double area = this.area.getValue(); double abs_temp = org.unijena.j2k.physicalCalculations.ClimatologicalVariables.calc_absTemp(temperature, "degC"); double delta_s = org.unijena.j2k.physicalCalculations.ClimatologicalVariables.calc_slopeOfSaturationPressureCurve(temperature); double pz = org.unijena.j2k.physicalCalculations.ClimatologicalVariables.calc_atmosphericPressure(elevation, abs_temp); double est = org.unijena.j2k.physicalCalculations.ClimatologicalVariables.calc_saturationVapourPressure(temperature); double ea = org.unijena.j2k.physicalCalculations.ClimatologicalVariables.calc_vapourPressure(rhum, est); double latH = org.unijena.j2k.physicalCalculations.ClimatologicalVariables.calc_latentHeatOfVaporization(temperature); double psy = org.unijena.j2k.physicalCalculations.ClimatologicalVariables.calc_psyConst(pz, latH); double G = this.calc_groundHeatFlux(netRad); double vT = org.unijena.j2k.physicalCalculations.ClimatologicalVariables.calc_VirtualTemperature(abs_temp, pz, ea); double pa = org.unijena.j2k.physicalCalculations.ClimatologicalVariables.calc_AirDensityAtConstantPressure(vT, pz); double tempFactor = 0; double pET = 0; double aET = 0; if (this.tempRes.getValue().equals("d")) { tempFactor = 86400; } else if (this.tempRes.getValue().equals("h")) { tempFactor = 3600; } else if (this.tempRes.getValue().equals("m")) { tempFactor = 86400; } double Letp = 0; Letp = this.calcPM(delta_s, netRad, G, pa, CP, est, ea, psy, tempFactor, wind); pET = Letp / latH; aET = 0; //converting mm to litres pET = pET * area; //aggregation to monthly values if (this.time != null) { if (this.tempRes.getValue().equals("m")) { int daysInMonth = this.time.getActualMaximum(time.DATE); pET = pET * daysInMonth; } } //avoiding negative potETPs if (pET < 0) { pET = 0; } this.potET.setValue(pET*et_cal.getValue()); this.actET.setValue(aET); if (dataCaching.getValue() == 0) { writer.writeDouble(pET*et_cal.getValue()); } } }
7. Die cleanup-Prozedur wird am Ende eines Modelllaufs durchlaufen.
public void cleanup() throws IOException { if (dataCaching.getValue() == 0) { writer.flush(); writer.close(); } else if (dataCaching.getValue() == 1) { reader.close(); } }
8. Private Prozeduren und Funktionen. Diese stehen nur innerhalb der Prozesskomponente zur Verfügung.
private double calcPM(double ds, double netRad, double G, double pa, double CP, double est, double ea, double psy, double tempFactor, double wind){ double fu = (0.27 + 0.2333 * wind); double Letp = (ds * (netRad - G) + (pa * CP * (est - ea) * fu)) / (ds + psy); return Letp; } private double calc_groundHeatFlux(double netRad) { double g = 0.1 * netRad; return g; }
9. Ende der Prozesskomponente.
}
Integration neuer Prozesskomponenten in JAMS oder J2000 Bibliotheken
Um Ihre entwickelte Prozesskomponente den bestehenden JAMS oder J2000 Komponenten hinzuzufügen, erstellen sie ein neues *.jar des Projektes, indem die Komponente liegt. Klicken Sie dazu mit der rechten Maustaste auf das Projekt und wählen Sie den Punkte Build and Clean. Binden Sie dieses *.jar nun als Bibliothek ein, so enthält diese Ihre neue Komponente.