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:
Setting up Projects in NetBeans
The projects are to be integrated according to the following order:
Step 1 - Integrating the JAMS Project
The JAMS/J2000 sources have to be loaded into the Netbeans. First, the JAMS project is set up. In order to do so, open NetBeans and select New Project under the menu item File.
The following window appears:
Since you want to integrate an existing source code, select Java Project with Existing Source. Click on Next. In the second step, you have to enter a name and a project folder. A project folder is entered as a default but it can be modified. Click on Next.
By clicking on the button Add Folder you should load the following sources into the project:
- JAMSapi
- JAMScommon
- JAMSExplorer
- JAMSMain
- JAMSRemote
- JAMSstarter
- JAMSui
Click on Finish.
In the next step, the required libraries for the project have to be loaded. You can find them in the downloaded source folder under JAMS-2_x-src\ext. (x stands for the version which is currently downloaded but changes over time) Right-click on the JAMS project in the generated JAMS project. Select item Properties.
Select the item Libraries in the right part of the window Project Properties - JAMS under Categories. By using the button Add JAR/Folder the required libraries can be loaded. Load all libraries which are available in the downloaded source folder JAMS-2_x-src\ext.
The JAMS project has been set up.
If you want to compile the project, right-click on the JAMS project and select the item Build and Clean. The JAMS.jar is being generated. In the bottom left window of your NetBeans developer environment you can check whether the process has been successful and where the JAMS.jar has been saved.
Step 2 - Integrating the J2000 Project
Integrate the project J2000 as new project with existing sources as described in step 1. The sources are in directory ...\JAMS-x-src\J2K\src which has been downloaded.
Load the generated JAMS.jar which has been generated in step 1 as a library.
Bild:Bibliotheken_laden_J2000.png
Compile the new project by right-clicking on the project J2000 and selecting the menu item Build and Clean. In the bottom right window of your NetBeans developer environment you should read BUILD SUCCESSFUL.
Step 3 - Integrating the JAMSComponents Project
Integrate the project JAMSComponents as new project with existing sources as described in step 1. The sources are in directory ...\JAMS-x-src\JAMSComponents\src which has been downloaded.
Load the JAMS.jar which has been generated in step 1 as library as well as all libraries (*.jar - files) from folder ...\JAMS-x-src\ext. Bild:Bibliotheken_laden_JAMSComponents.png
Compile the new project by right-clicking on the project J2000 and selecting the menu item Build and Clean. In the bottom right window of your NetBeans developer environment you should read BUILD SUCCESSFUL.
Launching Process Components from the NetBeans
Every process component which has a main procedure can be launched directly from the NetBeans. Jede Prozesskomponente welche über eine Main-Procedure vefügt, kann aus dem NetBeans direkt gestartet werden. As an example, we will launch the JAMSLauncher directly which is described in detail in the tutorial for basic users.
Main Classes
Right-click on the project JAMS. Choose the menu item Properties. Click on run in the left part of the window. Enter as Main Class the class which should be launched during project run. By single-clicking on the button Browse... all Main Classes which are available in the project are shown; these are all components which have a main procedure. Choose jamsui.launcher.JAMSui as an example. Click on Set Main Class. The following window should appear:
Click on OK. Launch the project JAMS by (left-)clicking on the project, the choosing the item run. The JAMSLauncher starts. In this way, various classes with a main procedure can be started.
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.