Changes between Initial Version and Version 1 of Java API

Show
Ignore:
Timestamp:
09/04/12 11:06:21 (13 years ago)
Author:
jorisborgdorff
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Java API

    v1 v1  
     1== About the API == 
     2 
     3The Multiscale Modeling Language (MML) defines several computational elements. The names of these elements are: 
     4* conduit; 
     5* submodel; 
     6* mapper; 
     7* filter; and 
     8* terminal. 
     9 
     10These elements are all supported in the MUSCLE API. 
     11 
     12There are two ways to exploit the MUSCLE API: either by using these constructs, or by writing free-form code, where all orchestration and deadlock detection is your own responsibility. The former gives code that is easy to read and to debug, while the latter makes it possible to optimally exploit any parallelism in the model. This page section is split in two parts, one for each approach. With care, it is also possible to combine these approaches in a model, choosing the more appropriate form per submodel. 
     13 
     14In both cases, conduits are defined the same, and parameters are passed in the same way. 
     15 
     16=== Conduits === 
     17 
     18The conduit is the mechanism in the MUSCLE runtime environment to send data. In the API, the ConduitEntrance and ConduitExit are accessible. The ConduitEntrance is used to send data, while the ConduitExit receives data. These entrances and exits, as we call them, can be accessed in two ways. Either they are created in the addPortals() method, or they are called on the fly in the code using the out() and in() methods. 
     19 
     20The addPortals method is called before the submodel starts, so the exits and entrances are stored as fields of your class. The conduit exit and entrance uses Java Generics to define what kind of data will be received or sent, both in the field declaration and in the addExit or addEntrance method. This allows for compile-time and run-time checking of data that is sent over the conduit. 
     21{{{ 
     22ConduitExit<double[]> exitA; 
     23ConduitEntrance<double[]> entranceA; 
     24 
     25@Override 
     26protected void addPortals() { 
     27    exitA = addExit("exitName", double[].class); 
     28    entranceA = addEntrance("entranceName", double[].class); 
     29} 
     30}}} 
     31To send or receive, use the fields that were initialized in addPortals(). 
     32{{{ 
     33double[] dataA = exitA.receive(); 
     34entranceA.send(dataA); 
     35}}} 
     36 
     37If addPortals() is not overridden it is possible to use the out() and in() methods to send or receive data. It is then not necessary to store the ConduitExit and ConduitEntrance as a field. 
     38{{{ 
     39double[] dataA = (double[]) in("exitName").receive(); 
     40out("entranceName").send(dataA); 
     41}}} 
     42In this case received data needs to be cast to double[] to use it, and in the send statement, the Java compiler will give a warning that an unchecked conversion is being done. If the cast is not correct, a ClassCastException will be thrown by Java. If the exit or entrance name is not configured, an IllegalArgumentException will be thrown by MUSCLE. 
     43 
     44The advantage of the first method is that it is type-safe, so there is no need to cast the data. Also if the code and the configuration file do not match this is detected immediately. The advantage of the second method is that it is less verbose and leads to smaller classes. 
     45 
     46=== Parameters === 
     47 
     48Parameters that are defined in the configuration file are accessed through a range of get*Property() methods. The most basic form is 
     49{{{ 
     50String parameter = getProperty("propName"); 
     51}}} 
     52In this form the property is read as a string. It first tries to find the instance property by searching for "instanceName:propName" and then for a global property named "propName". All get*Property() methods will throw an IllegalArgumentException if the property does not exist, this can be prevented by first calling hasProperty(). 
     53If a instance property is specifically required, this can be checked by first calling 
     54{{{ 
     55String parameter = null; 
     56if (hasInstanceProperty("propName")) { 
     57    parameter = getProperty("propName"); 
     58} 
     59}}} 
     60If on the other hand only a global property is wanted, write 
     61{{{ 
     62String parameter = getGlobalProperty("propName"); 
     63}}} 
     64 
     65To get other types of parameters than strings, use getPathProperty for a File, getIntProperty for an int, getDoubleProperty for a double and getBoolProperty for a boolean. 
     66 
     67== MUSCLE MML API == 
     68 
     69== MUSCLE free-form API == 
     70 
     71In the free-form API all kernels extend muscle.core.kernel.Instance. At least the execute() method of Instance should be overridden. In this method any sequence of send and receive is possible, and the conceptual coupling between different submodels can be as small or large as wanted. 
     72 
     73One notable difference with the MUSCLE MML API is that it can quit a submodel more directly. If there should still be some synchronization with other submodels, the willStop() method checks when the conduits have sent messages that are larger than the total timescale of the current submodel, or larger than the "max_timesteps" property. An example submodel Sender with name "w" (see src/java/examples/simplejava for the full code), which sends data each iteration would look as follows when using willStop(): 
     74 
     75{{{ 
     76import muscle.core.ConduitEntrance; 
     77import muscle.core.kernel.Instance; 
     78 
     79/** 
     80a simple java example kernel which sends data 
     81*/ 
     82public class Sender extends Instance { 
     83        private ConduitEntrance<double[]> entrance; 
     84 
     85        @Override 
     86        protected void addPortals() { 
     87                entrance = addEntrance("data", double[].class); 
     88        } 
     89 
     90        @Override 
     91        protected void execute() { 
     92                double[] dataA = new double[5]; 
     93                 
     94                while (!this.willStop()) { 
     95                        // process data 
     96                        for(int i = 0; i < dataA.length; i++) { 
     97                                dataA[i] = i; 
     98                        } 
     99                                                 
     100                        // send the data 
     101                        entrance.send(dataA); 
     102                } 
     103        } 
     104 
     105} 
     106}}} 
     107By changing the "max_timesteps" and the "w:dt" property, this submodel will send different number of messages. For example, if max_timesteps is 4, and w:dt is 1 it will send 4 messages.