Changes between Version 11 and Version 12 of Tutorials

Show
Ignore:
Timestamp:
06/10/13 16:05:37 (12 years ago)
Author:
jorisborgdorff
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Tutorials

    v11 v12  
    2727== Full MUSCLE tutorial == 
    2828 
    29 For more information, please contact [mailto:j.borgdorff@uva.nl j.borgdorff@uva.nl]. 
    30  
    31 = Part 1: installing and testing = 
     29For more information, please contact <j.borgdorff@uva.nl>. 
     30 
     31== Part 1: installing and testing == 
    3232 
    3333If you have a Windows machine, first log in to a Linux or Mac OS X machine. 
    3434 
    35 <ol style="list-style-type: decimal;"> 
    36 <li><p>Follow the [http://apps.man.poznan.pl/trac/muscle/wiki/Installation MUSCLE installation page].</p></li> 
    37 <li><p>To add MUSCLE to the path and set a few environment variables, run the following (don't forget the dot at the start!):</p> 
    38 <pre>. [MUSCLE_DIR]/etc/muscle.profile</pre></li> 
    39 <li><p>Now you can run <code>muscle2</code>. We will show its functionality with an example model that is packaged with MUSCLE. First go to the unzipped MUSCLE folder, and try to read <code>src/cxa/SimpleSubmodelExample.cxa.rb</code> and see what it does. To show the submodels that the example contains, run:</p> 
    40 <pre>cd .. 
    41 muscle2 --cxa src/cxa/SimpleSubmodelExample.cxa.rb </pre> 
    42 <p>This example has a writer submodel <code>w</code> and a reader submodel <code>r</code>. The writer sends data to the reader, and the reader prints that data to screen.</p> 
    43 <p>You can run the simple example by specifying that the current MUSCLE command will run the Simulation Manager with the <code>--main</code> flag or its shorthand <code>-m</code>, and specifying all submodels that should run in this command:</p> 
    44 <pre>muscle2 -mc src/cxa/SimpleSubmodelExample.cxa.rb w r</pre> 
    45 <p>Usually, if you want to run all the submodels instances with the current MUSCLE command, specify the <code>--allinstances</code> or its shorthand <code>-a</code>:</p> 
    46 <pre>muscle2 -amc src/cxa/SimpleSubmodelExample.cxa.rb</pre> 
    47 <p>So what do we observe? MUSCLE detects that it should start the Simulation Manager and a Simulation. It first starts the manager, which shows its TCP/IP address. Then the Simulation starts and it executes the submodel instances <code>w</code> and <code>r</code>. These start their respective conduits, and start 'computing'.</p> 
    48 <p>On local machines, these commands are sufficient to run any MUSCLE model. You can try the other examples in the <code>src/cxa</code> directory, just run</p> 
    49 <pre>muscle2 -amc src/cxa/[...].cxa.rb</pre></li> 
    50 <li><p>Scientific applications that are started remotely generally do not have a direct feedback to a user interface, but we will run one that does. This is why we logged in with the -X flag of SSH in step 2.</p> 
    51 <pre>muscle2 -amc src/cxa/LaplaceExample.cxa.rb</pre> 
    52 <p>It will open two windows that compute temperature dissipation, that are coupled on the boundary. Red is a +1 temparature, blue a -1 temperature, and green a zero temperature. The initial condition, far right and far left correspond to zero temperature, the top to a sine function and the bottom to a cosine. Temperature is dissipated during each time step by taking the average of the four neighboring cells. The adjacent boundary is transmitted each iteration.</p></li> 
    53 <li><p>Take a look at all the options by running</p> 
    54 <pre>muscle2</pre></li></ol> 
    55  
    56 = Part 2: distributed execution = 
     351. Follow the [wiki:Installation MUSCLE installation] 
     36 
     372. To add MUSCLE to the path and set a few environment variables, run the 
     38        following (don't forget the dot at the start!): 
     39        {{{ 
     40                . [MUSCLE_DIR]/etc/muscle.profile 
     41        }}} 
     42 
     433. Now you can run `muscle2`. We will show its functionality with an example 
     44        model that is packaged with MUSCLE. First go to the unzipped MUSCLE folder, 
     45        and try to read `src/cxa/SimpleSubmodelExample.cxa.rb` and see what it does. 
     46        To show the submodels that the example contains, run: 
     47        {{{ 
     48                cd .. 
     49                muscle2 --cxa src/cxa/SimpleSubmodelExample.cxa.rb  
     50        }}} 
     51 
     52        This example has a writer submodel `w` and a reader submodel `r`. The 
     53        writer sends data to the reader, and the reader prints that data to screen. 
     54 
     55        You can run the simple example by specifying that the current MUSCLE command 
     56        will run the Simulation Manager with the `--main` flag or its shorthand `-m`, 
     57        and specifying all submodels that should run in this command: 
     58        {{{ 
     59                muscle2 -mc src/cxa/SimpleSubmodelExample.cxa.rb w r 
     60        }}} 
     61         
     62        Usually, if you want to run all the submodels instances with the current MUSCLE 
     63        command, specify the `--allinstances` or its shorthand `-a`: 
     64         
     65        {{{ 
     66                muscle2 -amc src/cxa/SimpleSubmodelExample.cxa.rb 
     67        }}} 
     68 
     69        So what do we observe? MUSCLE detects that it should start the Simulation 
     70        Manager and a Simulation. It first starts the manager, which shows its 
     71        TCP/IP address. Then the Simulation starts and it executes the submodel 
     72        instances `w` and `r`. These start their respective conduits, and start 
     73        'computing'. 
     74         
     75        On local machines, these commands are sufficient to run any MUSCLE model. 
     76        You can try the other examples in the `src/cxa` directory, just run 
     77         
     78        {{{ 
     79                muscle2 -amc src/cxa/[...].cxa.rb 
     80        }}} 
     81 
     824. Scientific applications that are started remotely generally do not 
     83    have a direct feedback to a user interface, but we will run one that does. 
     84    This is why we logged in with the -X flag of SSH in step 2. 
     85         
     86        {{{ 
     87        muscle2 -amc src/cxa/LaplaceExample.cxa.rb 
     88        }}} 
     89         
     90        It will open two windows that compute temperature dissipation, that are 
     91    coupled on the boundary. Red is a +1 temparature, blue a -1 temperature, 
     92    and green a zero temperature. The initial condition, far right and far left 
     93    correspond to zero temperature, the top to a sine function and the bottom to a cosine. 
     94        Temperature is dissipated during each time step by taking the average of 
     95        the four neighboring cells. The adjacent boundary is transmitted each 
     96        iteration. 
     97 
     985. Take a look at all the options by running 
     99        {{{ 
     100                muscle2 
     101        }}} 
     102 
     103== Part 2: distributed execution == 
    57104 
    58105In this part we will do an inter-process and an inter-machine run of MUSCLE. 
    59106 
    60 <ol style="list-style-type: decimal;"> 
    61 <li><p>Open a second terminal, and log in to another machine, or try it on the same machine. When logged in do</p> 
    62 <pre>. [MUSCLE_DIR]/etc/muscle.profile</pre> 
    63 <p>Then go to the unzipped MUSCLE directory. Now we can run muscle on the same site. In the first terminal window, start the main MUSCLE with the writing submodel w. This is done by typing:</p> 
    64 <pre>muscle2 -mc src/cxa/SimpleSubmodelExample.cxa.rb w</pre> 
    65 <p>So what do you observe?</p> 
    66 <p>One of the most important messages is <code>Started the connection handler, listening on [IPADDRESS:PORT]</code>. Copy the IP address and port number. In the second terminal, start the reading submodel r, and at the end put the <code>-M</code> or <code>--manager</code> flag with the IP address and port:</p> 
    67 <pre>muscle2 -c src/cxa/SimpleSubmodelExample.cxa.rb r -M [IPADDRESS:PORT]</pre> 
    68 <p>What happens in both terminals?</p></li> 
    69 <li><p>To isolate the output from the Simulation Manager, we can run it separately.</p> 
    70 <p>In the first terminal window, start the Simulation Manager:</p> 
    71 <pre>muscle2 -mc src/cxa/SimpleSubmodelExample.cxa.rb</pre> 
    72 <p>In the second terminal, start the submodels. Again, replace the port number with the one that is printed by the Simulation Manager.</p> 
    73 <pre>muscle2 -ac src/cxa/SimpleSubmodelExample.cxa.rb -M [IPADDRESS:PORT]</pre> 
    74 <p>What happens in both terminals?</p></li> 
    75 <li><p>To do distributed computing, also install MUSCLE on another node</p> 
    76 <pre>ssh user@node2 
    77 [INSTALL MUSCLE...] 
    78 . MUSCLE_DIR/etc/muscle.profile</pre> 
    79 <p>And go to the source directory of MUSCLE. We will perform the same experiment, but now on different hosts. So on the first node, for instance run only <code>w</code></p> 
    80 <pre>muscle2 -mc src/cxa/SimpleSubmodelExample.cxa.rb w</pre> 
    81 <p>On the other node, we now also need to specify which host and port the other MUSCLE instance is running on</p> 
    82 <pre>muscle -c src/cxa/SimpleSubmodelExample.cxa.rb -M [IPADDRESS:PORT] r</pre> 
    83 <p>What is the output in node one? And on the other?</p></li></ol> 
    84  
    85 '''Related:''' inter-cluster executions can be done with the <code>--intercluster</code> tag, with which the MUSCLE transport overlay (MTO) is used. We will not be doing this directly here. In the [http://apps.man.poznan.pl/trac/muscle/wiki/MTO MTO documentation] this is explained more thoroughly. 
    86  
    87 = Part 3: The power of coupling = 
     1071. Open a second terminal, and log in to another machine, or try it on the same machine. 
     108        When logged in do 
     109        {{{ 
     110                . [MUSCLE_DIR]/etc/muscle.profile 
     111        }}} 
     112 
     113        Then go to the unzipped MUSCLE directory. Now we can run muscle on the same site. In the first terminal window, start the main MUSCLE with the writing submodel w. This is done by typing: 
     114        {{{ 
     115                muscle2 -mc src/cxa/SimpleSubmodelExample.cxa.rb w 
     116        }}} 
     117 
     118        So what do you observe? 
     119 
     120        One of the most important messages is `Started the connection handler, listening on [IPADDRESS:PORT]`. 
     121        Copy the IP address and port number. 
     122        In the second terminal, start the reading submodel r, and at the end put the `-M` or `--manager` flag 
     123        with the IP address and port: 
     124        {{{ 
     125                muscle2 -c src/cxa/SimpleSubmodelExample.cxa.rb r -M [IPADDRESS:PORT] 
     126        }}} 
     127 
     128        What happens in both terminals? 
     129 
     1302. To isolate the output from the Simulation Manager, we can run it separately. 
     131 
     132        In the first terminal window, start the Simulation Manager: 
     133        {{{ 
     134                muscle2 -mc src/cxa/SimpleSubmodelExample.cxa.rb 
     135        }}} 
     136 
     137        In the second terminal, start the submodels. Again, replace the port number 
     138        with the one that is printed by the Simulation Manager. 
     139        {{{ 
     140                muscle2 -ac src/cxa/SimpleSubmodelExample.cxa.rb -M [IPADDRESS:PORT] 
     141        }}} 
     142 
     143        What happens in both terminals? 
     144 
     1453. To do distributed computing, also install MUSCLE on another node 
     146        {{{ 
     147                ssh user@node2 
     148                [INSTALL MUSCLE...] 
     149                . MUSCLE_DIR/etc/muscle.profile 
     150        }}} 
     151 
     152        And go to the source directory of MUSCLE. We will perform the same experiment, 
     153        but now on different hosts. So on the first node, for instance run only `w` 
     154        {{{ 
     155                muscle2 -mc src/cxa/SimpleSubmodelExample.cxa.rb w 
     156        }}} 
     157 
     158        On the other node, we now also need to specify which host and port the other 
     159        MUSCLE instance is running on 
     160        {{{ 
     161                muscle -c src/cxa/SimpleSubmodelExample.cxa.rb -M [IPADDRESS:PORT] r 
     162        }}} 
     163 
     164        What is the output in node one? And on the other? 
     165 
     166**Related:** inter-cluster executions can be done with the `--intercluster` tag, 
     167with which the MUSCLE transport overlay (MTO) is used. We will not be doing this 
     168directly here. In the [wiki:MTO MTO documentation] 
     169this is explained more thoroughly. 
     170 
     171== Part 3: The power of coupling == 
    88172 
    89173First, download an extension of the LaplaceExample that was shown in item 1.4. 
    90  
    91 <pre>wget http://apps.man.poznan.pl/trac/muscle/raw-attachment/wiki/Tutorials/laplace.zip 
    92 unzip laplace.zip 
    93 cd laplace 
    94 ant</pre> 
    95 The source of the submodels can be found in <code>src/laplace</code>. This example code shows how the same code can be reused in different scenarios: 
    96  
    97 * Coupling as in example 1.4 - run <code>muscle2 -amc laplace.cxa.rb</code> 
    98 * Doing some simple transformation with filters after sending the data - <code>muscle2 -amc laplaceFilter.cxa.rb</code> 
    99 * Setting one boundary explicitly using terminals - <code>muscle2 -amc laplaceTerminal.cxa.rb</code> 
    100 * Using a periodic boundary condition - <code>muscle2 -amc laplacePeriodic.cxa.rb</code> 
    101 * Doing domain decomposition using mappers - <code>muscle2 -amc laplaceMapper.cxa.rb</code> 
     174{{{ 
     175    wget http://apps.man.poznan.pl/trac/muscle/raw-attachment/wiki/Tutorials/laplace.zip 
     176    unzip laplace.zip 
     177    cd laplace 
     178    ant 
     179}}} 
     180 
     181The source of the submodels can be found in `src/laplace`. This example code 
     182shows how the same code can be reused in different scenarios: 
     183 
     184* Coupling as in example 1.4 - run `muscle2 -amc laplace.cxa.rb` 
     185* Doing some simple transformation with filters after sending the data - `muscle2 -amc laplaceFilter.cxa.rb` 
     186* Setting one boundary explicitly using terminals - `muscle2 -amc laplaceTerminal.cxa.rb` 
     187* Using a periodic boundary condition - `muscle2 -amc laplacePeriodic.cxa.rb` 
     188* Doing domain decomposition using mappers - `muscle2 -amc laplaceMapper.cxa.rb` 
    102189 
    103190Their coupling is shown in the following diagrams: 
    104191 
    105 [[Image:http://apps.man.poznan.pl/trac/muscle/raw-attachment/wiki/Tutorials/scenarios.png|frame|none|alt=|caption Scenarios]] 
    106  
    107 # Try the different scenarios and see what the differences are between the configuration files. 
    108 # Modify the configuration files to get different geometries or transformations. For example (pick one): 
    109 #* add a submodel instance so that you get a coupling between West - Middle - East; 
    110 #* change the filters and see how it affects the computations (see [http://apps.man.poznan.pl/trac/muscle/wiki/Configuration#Filters Filter documentation]); or 
    111 #* modify the file <code>src/laplace/filter/InvertFilter</code> to do something additional (see [http://apps.man.poznan.pl/trac/muscle/wiki/Java%20API#Filters Java filter documentation]) 
    112 #* modify the file <code>src/laplace/terminal/DoubleArraySource.java</code> to do something additional, such as computing a function instead of sending a fixed number (see [http://apps.man.poznan.pl/trac/muscle/wiki/Java%20API#Terminals Java terminal documentation]) 
    113  
    114 = Part 4: a diagram of your tightly coupled model = 
    115  
    116 To apply this programming paradigm to your own multiscale model, you can apply the methodology as presented on day 1. 
    117  
    118 # Identify the processes in your problem, and their scales. Draw them on the same diagram, taking time as a x-axis, and space as the y-axis. Each process should have a granularity (step size), which is the lower bound for the rectangle, and a problem size (total size), which is the upper bound for the rectangle. 
    119 # Draw arrows between interacting processes. Now your scale separation map is more or less complete. 
    120 # When you think about implementation of that scale separation map, could you use any of the coupling types shown in part 3? Would it be tightly or loosely coupled? 
    121 # Work out coupling diagram of your own application. 
    122  
    123 = Part 5: modifying the simple example (optional) = 
    124  
    125 To start on using MUSCLE for your own applications, you can start by modifying the examples. Depending on the programming language of your application, you can start with ([http://apps.man.poznan.pl/trac/muscle/wiki/Java%20API Java documentation]) the files in <code>src/java/examples/simplesubmodel</code> or with ([http://apps.man.poznan.pl/trac/muscle/wiki/C%2B%2B%20API C++/C documentation]) <code>src/cpp/examples/simplecpp</code> or ([http://apps.man.poznan.pl/trac/muscle/wiki/Fortran%20API Fortran documentation]) <code>src/cpp/examples/simplefortran</code>. The last two only contain the Sender (the submodel w) of the simple example. 
    126  
    127 <ol style="list-style-type: decimal;"> 
    128 <li><p>Modify src/java/examples/simplesubmodel/ConsoleWriter.java so that it sends a message back to Sender.java; modify Sender.java to receive this message. In this example, call both the sending and the receiving port &quot;messages&quot;, for example. Test your implementation by running</p> 
    129 <pre>cd build 
    130 ./build.sh $MUSCLE_HOME 
    131 cd .. 
    132 muscle2 -amc src/cxa/SimpleSubmodelExample.cxa.rb</pre> 
    133 <p>'''Spoiler:'''</p> 
    134 <ul> 
    135 <li>In ConsoleWriter.java 
    136 <ul> 
    137 <li>create the method <code>protected void intermediateObservation()</code><br /></li> 
    138 <li><p>send some data over it in <code>execute()</code> by adding</p> 
    139 <pre>double[] msg = {1.0, 0.0, 1.0}; 
    140 out(&quot;messages&quot;).send(msg);</pre></li></ul> 
    141 </li> 
    142 <li>In Sender.java 
    143 <ul> 
    144 <li>Create the method <code>protected void solvingStep()</code></li> 
    145 <li><p>Receive the data</p> 
    146 <pre>double[] msg = (double[])in(&quot;messages&quot;).receive();</pre></li> 
    147 <li><p>Print the data with</p> 
    148 <pre>for (double d : msg) { 
    149      log(&quot;Message from ConsoleWriter: &quot; + d); 
    150 }</pre></li></ul> 
    151 </li> 
    152 <li>In the configuration file <code>src/cxa/SimpleSubmodelExample.cxa.rb</code> 
    153 <ul> 
    154 <li><p>Append the lines</p> 
    155 <pre>cs.attach('r' =&gt; 'w') { 
    156     tie('messages', 'messages') 
    157 }</pre></li> 
    158 <li><p>Since the names of the ports are equal (<code>messages</code>), you can also use the abbreviated form:</p> 
    159 <pre>cs.attach('r' =&gt; 'w') { 
    160     tie('messages') 
    161 }           </pre></li></ul> 
    162 </li> 
    163 <li>Build it and execute</li></ul> 
    164 </li> 
    165 <li><p>Modify <code>src/cpp/examples/simplecpp/Sender.cpp</code> to receive a message from ConsoleWriter</p> 
    166 <pre>cd build 
    167 ./build.sh $HOME/muscle 
    168 muscle2 -amc ../src/cxa/NativeExample2.cxa.rb</pre> 
    169 <p>'''Spoiler:'''</p> 
    170 <ul> 
    171 <li>In Sender.cpp 
    172 <ul> 
    173 <li><p>Receive some data after sending by coding in the <code>main()</code> function</p> 
    174 <pre>size_t sz; 
    175 double* msg = (double *) 
    176     muscle::env::receive(&quot;messages&quot;, (void *)0, sz, MUSCLE_DOUBLE);</pre></li> 
    177 <li><p>Print the data with</p> 
    178 <pre>for (size_t j = 0; j &lt; sz; j++) { 
    179     logger::info(&quot;Message from ConsoleWriter: %f&quot;, msg[j]); 
    180 }</pre></li> 
    181 <li><p>Free the data with</p> 
    182 <pre>muscle::env::free_data(msg, MUSCLE_DOUBLE);</pre></li></ul> 
    183 </li> 
    184 <li>In the configuration file <code>src/cxa/NativeExample2.cxa.rb</code> 
    185 <ul> 
    186 <li><p>Change the line</p> 
    187 <pre>cxa.add_kernel('r', 'examples.simplejava.ConsoleWriter')</pre> 
    188 <p>to</p> 
    189 <pre>cxa.add_kernel('r', 'examples.simplesubmodel.ConsoleWriter')</pre></li> 
    190 <li><p>Append the lines</p> 
    191 <pre>cs.attach('r' =&gt; 'w') { 
    192     tie('messages') 
    193 }</pre></li></ul> 
    194 </li></ul> 
    195 </li></ol> 
    196  
    197 If you would prefer to use the free-form API of MUSCLE, take a look at the SimpleExample, this doesn't implement the different formal operators of MML, but just an <code>execute()</code> method. 
     192[[Image(http://apps.man.poznan.pl/trac/muscle/raw-attachment/wiki/Tutorials/scenarios.png)]] 
     193 
     1941. Try the different scenarios and see what the differences are between the configuration files. 
     1952. Modify the configuration files to get different geometries or transformations. For example (pick one): 
     196         * add a submodel instance so that you get a coupling between West - Middle - East; 
     197         * change the filters and see how it affects the computations (see [wiki:Configuration#Filters Filter documentation]); or 
     198         * modify the file `src/laplace/filter/InvertFilter` to do something additional (see [wiki:"Java API#Filters" Java filter documentation]) 
     199         * modify the file `src/laplace/terminal/DoubleArraySource.java` to do something additional, such as computing a function instead of sending a fixed number (see [wiki:"Java API#Terminals" Java terminal documentation]) 
     200 
     201== Part 4: a diagram of your tightly coupled model == 
     202 
     203To apply this programming paradigm to your own multiscale model, you can apply 
     204the methodology as presented on day 1. 
     205 
     2061. Identify the processes in your problem, and their scales. Draw them on the same diagram, taking time as a x-axis, and space as the y-axis. Each process should have a granularity (step size), which is the lower bound for the rectangle, and a problem size (total size), which is the upper bound for the rectangle. 
     2072. Draw arrows between interacting processes. Now your scale separation map is more or less complete. 
     2083. When you think about implementation of that scale separation map, could you use any of the coupling types shown in part 3? Would it be tightly or loosely coupled?  
     2094. Work out coupling diagram of your own application. 
     210 
     211== Part 5: modifying the simple example (optional) == 
     212 
     213To start on using MUSCLE for your own applications, you can start by modifying 
     214the examples. Depending on the programming language of your application, you can 
     215start with ([wiki:"Java API" Java documentation]) the files in `src/java/examples/simplesubmodel` or with 
     216([wiki:"C++ API" C++/C documentation]) `src/cpp/examples/simplecpp` or ([wiki:"Fortran API" Fortran documentation]) `src/cpp/examples/simplefortran`. 
     217The last two only contain the Sender (the submodel w) of the simple example. 
     218 
     2191. Modify src/java/examples/simplesubmodel/ConsoleWriter.java so that it sends a 
     220        message back to Sender.java; modify Sender.java to receive this message. In 
     221        this example, call both the sending and the receiving port "messages", for 
     222        example. Test your implementation by running 
     223     
     224        {{{ 
     225        cd build 
     226                ./build.sh $MUSCLE_HOME 
     227                cd .. 
     228                muscle2 -amc src/cxa/SimpleSubmodelExample.cxa.rb 
     229        }}} 
     230 
     231        **Spoiler:** 
     232 
     233        * In ConsoleWriter.java 
     234                * create the method `protected void intermediateObservation()`           
     235                * send some data over it in `execute()` by adding 
     236                        {{{ 
     237                double[] msg = {1.0, 0.0, 1.0}; 
     238                            out("messages").send(msg); 
     239                        }}} 
     240        * In Sender.java 
     241                * Create the method `protected void solvingStep()` 
     242                * Receive the data 
     243                        {{{ 
     244                                double[] msg = (double[])in("messages").receive(); 
     245                        }}} 
     246                * Print the data with  
     247                        {{{ 
     248                                for (double d : msg) { 
     249                                         log("Message from ConsoleWriter: " + d); 
     250                                } 
     251                        }}} 
     252        * In the configuration file `src/cxa/SimpleSubmodelExample.cxa.rb` 
     253                * Append the lines 
     254                        {{{ 
     255                                cs.attach('r' => 'w') { 
     256                                        tie('messages', 'messages') 
     257                                } 
     258                        }}} 
     259                * Since the names of the ports are equal (`messages`), you can also use the abbreviated form: 
     260                        {{{ 
     261                                cs.attach('r' => 'w') { 
     262                                        tie('messages') 
     263                                } 
     264                        }}} 
     265        * Build it and execute 
     266 
     2672. Modify `src/cpp/examples/simplecpp/Sender.cpp` to receive a message from ConsoleWriter 
     268        {{{ 
     269                cd build 
     270                ./build.sh $HOME/muscle 
     271                muscle2 -amc ../src/cxa/NativeExample2.cxa.rb 
     272        }}} 
     273 
     274        **Spoiler:** 
     275         
     276        * In Sender.cpp 
     277                * Receive some data after sending by coding in the `main()` function 
     278                        {{{ 
     279                                size_t sz; 
     280                                double* msg = (double *) 
     281                                        muscle::env::receive("messages", (void *)0, sz, MUSCLE_DOUBLE); 
     282                        }}} 
     283                * Print the data with  
     284                        {{{ 
     285                                for (size_t j = 0; j < sz; j++) { 
     286                                        logger::info("Message from ConsoleWriter: %f", msg[j]); 
     287                                } 
     288                        }}} 
     289                * Free the data with 
     290                        {{{ 
     291                                muscle::env::free_data(msg, MUSCLE_DOUBLE); 
     292                        }}} 
     293        * In the configuration file `src/cxa/NativeExample2.cxa.rb` 
     294                * Change the line 
     295                        {{{ 
     296                                cxa.add_kernel('r', 'examples.simplejava.ConsoleWriter') 
     297                        }}} 
     298                        to 
     299                        {{{ 
     300                                cxa.add_kernel('r', 'examples.simplesubmodel.ConsoleWriter') 
     301                        }}} 
     302                 
     303                * Append the lines 
     304                        {{{ 
     305                                cs.attach('r' => 'w') { 
     306                                        tie('messages') 
     307                                } 
     308                        }}} 
     309 
     310If you would prefer to use the free-form API of MUSCLE, take a look at the 
     311SimpleExample, this doesn't implement the different formal operators of MML, but just an `execute()` method. 
    198312 
    199313For MAPPER partners, visit the [[MAPPER tutorial]].