Salome HOME
bos #29864 Irrelevant assert in test.
[modules/yacs.git] / doc / calciumyacs.rst
1
2 .. _calciumyacs:
3
4
5 From the old CALCIUM product to CALCIUM in SALOME
6 -------------------------------------------------------
7
8 This section describes why the CALCIUM product has been upgraded to CALCIUM in SALOME.  
9 After a brief presentation of the advantages and disadvantages of the existing CALCIUM product, the second section 
10 presents the implementation of CALCIUM in SALOME using the DSC ports.  
11 The final section describes the joint use of CALCIUM ports and the YACS supervisor.
12
13 The existing CALCIUM product
14 ''''''''''''''''''''''''''''''
15 The CALCIUM product enables fast and easy coupling of Fortran / C / C++ codes in a simple and only slightly 
16 intrusive manner.  Persons responsible for codes used in coupling make a distinction between general interest 
17 data by the definition of input and output connection points.  The person responsible for global coupling defines 
18 the number of simultaneous executions of the different codes and transmission links between connection points of 
19 these execution instances.  This description is called the coupling scheme and is stored in a coupling file.
20
21 Connection points are typed by simple types (integer, floating point, double, booleans, chain) and operate based 
22 on the time or iterative mode.  The data produced are stamped by a date or an iteration number.  Data are 
23 produced and read in codes by a call to write or read primitives.  Production is independent of requests on 
24 read connection points (asynchronism).
25
26 When data are requested for a date later than the data already produced, read instances wait on blocking read primitives 
27 or receive a code indicating that there are no data in non-blocking mode.  When data are requested at a date surrounded 
28 by previously produced data stamps, the reader can obtain interpolated data (L0 and L1) in time mode.  Coupling is 
29 interlocked if the reader(s) is (are) waiting for data that will never be produced.  CALCIUM detects this situation 
30 and proposes either that the execution of coupling should be stopped or that the requested data should be extrapolated 
31 to unlock the situation.  This management depends on mode in which CALCIUM is being used (production mode or debug mode).
32
33 CALCIUM has had two operating modes since its version 3.  The first called debug mode was the only mode available in 
34 earlier versions, and has a coupler process through which all data pass.  In the second so-called production mode, 
35 instances of codes communicate with each other directly.  In debug mode, the transfer flow is limited by the capacity 
36 of the coupler network link to manage simultaneous accesses.  In this mode, the coupler must store a copy of each 
37 received data so as to be able to deliver them at the required time and be capable of detecting an interlocked situation.  
38 Production mode enables a data transfer with performances that are not limited by the capacity of input and output 
39 links of the coupler because there is no longer a coupler.  However, this mode has the limitations that there is no 
40 detection of interlocking (but a timeout is managed), step back requests are controlled locally, there is no step 
41 by step execution mode and no dynamic management of coupling.
42
43 CALCIUM ports in SALOME
44 '''''''''''''''''''''''''''''
45 Several couplings were set up during the 2004 Summer school as a result of experimental use of the existing CALCIUM 
46 tool (in production mode) in SALOME.  It showed the relevance of getting datastream type ports to cohabit with 
47 SALOME dataflow / control flow ports.  However, it required a specific modification located in the CALCIUM start 
48 procedure and it highlighted the following limitations:
49
50 - the need to use a different container for each service using CALCIUM (even for services in the same 
51   component (CALCIUM is not multithread safe)).
52 - successive re-executions of coupling are difficult (need to not call MPI_FIN and problems related to the state of 
53   the MPI virtual machine)
54 - the SALOME SUPERVISOR has no control over execution of CALCIUM coupling
55 - no possible extension of transmitted CALCIUM types
56 - cohabitation of the MPI environment and the CORBA environment is sometimes difficult.
57
58 The SALOME KERNEL module is provided with new communication ports called DSC (Dynamic Software Component) ports 
59 that components use to dynamically add / delete new interfaces accessible to everyone.  
60 :ref:`progdsc` describes how these new ports are used / designed / and their usefulness.  
61 There are two classes of DSC ports, firstly ports that provide an interface (provides ports), and secondly ports 
62 that use the interfaces (uses ports).
63
64 An implementation of CALCIUM ports based on this technology has been available since SALOME KERNEL version V4.  
65 Therefore, CALCIUM couplings are possible simply by calling CALCIUM primitives in component services.  
66 This implementation reuses CALCIUM functions in its production mode.  Use of this technology only requires 
67 the SALOME KERNEL module.  However, unless the YACS supervisor is used, the user must write a python script or 
68 a component service to load and initialize the coupling components, connect the different ports and configure 
69 them, and start the services in the appropriate order.
70
71
72 CALCIUM / SALOME ports and the YACS supervisor
73 '''''''''''''''''''''''''''''''''''''''''''''''''
74 The YACS supervisor available in SALOME (since version V4.1) manages all types of DSC ports, and particularly CALCIUM  ports.  
75 It relieves the user from the need to implement a script or a service to connect and configure the ports.  It checks 
76 the validity of the calculation scheme and starts services in accordance with the described dependencies.  
77 A calculation scheme can be created mixing datastream type ports (calcium mode), dataflow ports (arrival of data that 
78 can trigger starting a service) and control flow ports (one service is started by the end of execution of another 
79 service), thus creating elaborated calculation schemes.
80
81 The calculation scheme thus created can be saved in the XML format.  This file represents the equivalent of the 
82 CALCIUM coupling file for the link declaration and parameter setting part, ports being declared in the XML file 
83 that catalogs component resources.
84
85 Creating a SALOME component using CALCIUM
86 ---------------------------------------------------
87 The use of CALCIUM in SALOME assumes that SALOME components are available offering services based on CALCIUM ports.  
88 There are several choices for creating such components:
89
90 - Create a SALOME module containing components for which the services have CALCIUM ports
91 - Create several SALOME modules containing at least one component for which the service(s) have CALCIUM ports.
92
93 Creating a SALOME module consists of structuring header, source, library and resource files in the form of a standard 
94 directory structure.  It can be done from a model module (HELLO, PYHELLO), or from a module generator (for example :ref:`yacsgen`)
95
96 Customisation of the SALOME component for the use of CALCIUM ports consists of:
97
98 - including a file declaring DSC ports in the IDL file of the component,
99 - including a file and declaring an inheritance to make our component supervisable,
100 - creating CALCIUM ports used in the definition of a standard method called init_service,
101 - declaration of CALCIUM ports of the component(s) in the module catalog file.
102
103 By using YACSGEN, the init_service method and the XML catalog of services provided by components are generated automatically.
104
105
106 The IDL declaration of components using CALCIUM ports
107 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
108 Since ports are dynamically declared in the init_service method, CALCIUM ports do not need to be previously declared 
109 in the IDL file.  However, the DSC_Engine.idl file must be included in the components IDL file(s) to benefit from DSC ports.
110
111 Example of the CALCIUM_TESTS.idl file for the CALCIUM_TEST module defining the three ECODE, SCODE, ESPION components, each 
112 of which offers a unique service to start up the corresponding wrapped code:
113
114 ::
115
116     #include "DSC_Engines.idl"
117     
118     /*! \file CALCIUM_TESTS.idl
119       This file contains the first installation test of CALCIUM product.
120       Each engine contains one service.
121     */
122     module CALCIUM_TESTS {
123     
124       interface ECODE : Engines::Superv_Component {
125         void EcodeGo();
126       };
127     
128       interface SCODE : Engines::Superv_Component {
129         void ScodeGo();
130       };
131     
132       interface ESPION : Engines::Superv_Component {
133         void EspionGo();
134       };
135     
136     };
137
138 Declaration of a C++ component using CALCIUM ports
139 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
140 Only one header is necessary in the case of a wrapper component (that does nothing except to call an 
141 implementation of another compilation unit):
142
143 .. code-block:: cpp
144
145   #include “Superv_Component_i.hxx”
146
147 This header file is necessary to make our component supervisable and to use DSC ports.  The component will 
148 virtually inherit the Superv_Component_i class.
149
150 Example ECODE.hxx declaration file for the ECODE component:
151
152 .. code-block:: cpp
153
154     #ifndef _ECODE_HXX_
155     #define _ECODE_HXX_
156     
157     #include "Superv_Component_i.hxx"
158     //Header CORBA generated from the CALCIUM_TESTS module
159     #include "CALCIUM_TESTS.hh"
160     
161     //Interface for the wrapped code, in this case C code ecode
162     extern "C" { int ecode(void *); }
163     
164     class ECODE_impl :
165       //Implements the CORBA interface for the ECODE component
166       public virtual POA_CALCIUM_TESTS::ECODE,
167       //Makes the component supervisable
168       public virtual Superv_Component_i {
169     
170     public :
171       //Classical SALOME component constructor
172       ECODE_impl(CORBA::ORB_ptr orb,
173              PortableServer::POA_ptr poa,
174              PortableServer::ObjectId * contId, 
175              const char *instanceName, 
176              const char *interfaceName);
177       
178       virtual ~ECODE_impl();
179     
180       //Initialisation of the service EcodeGo()
181       CORBA::Boolean init_service(const char * service_name);
182       void EcodeGo();
183     };
184     
185     extern "C"
186     {
187       PortableServer::ObjectId * ECODEEngine_factory(CORBA::ORB_ptr orb,
188                              PortableServer::POA_ptr poa,
189                              PortableServer::ObjectId * contId,
190                              const char *instanceName,
191                              const char *interfaceName);
192     }
193     
194     #endif
195
196
197 Declaration of component resources (part 1)
198 '''''''''''''''''''''''''''''''''''''''''''''''''''''''
199 Components publish signatures of their services in an XML resource file called the module catalog (or components catalog).  
200 This file can be generated by YACSGEN.
201
202 Extract from the CALCIUM_TESTSCatalog.xml catalog concerning the ECODE component:
203
204 Our ECODE component provides a unique EcodeGo() service that has no input parameters and no output parameters.
205
206 The Creating CALCIUM ports section describes how this resource file will be extended by the declaration of datastream ports.
207
208 .. code-block:: xml
209
210     ....
211       <component>
212             <component-name>ECODE</component-name>
213           ....
214             <component-interface-list>
215                 <component-interface-name>ECODE</component-interface-name>
216                 <component-interface-comment></component-interface-comment>
217                 <component-service-list>
218                     <component-service>
219                         <!-- service-identification -->
220                         <service-name>EcodeGo</service-name>
221                          ...
222                         <!-- service-connexion -->
223                         <inParameter-list>
224                         </inParameter-list>
225                         <outParameter-list>
226                         </outParameter-list>
227                         <DataStream-list>
228                          </DataStream-list>
229                     </component-service>
230                 </component-service-list>
231             </component-interface-list>
232       </component>
233
234 Definition of a component using CALCIUM ports
235 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''
236 The component creates the ports that it needs.  The step to create a CALCIUM port consists of calling the add_port method 
237 provided by the virtual inheritance from the Superv_Component_i class.  It must be done before the service(s) that use 
238 the port is (are) started.  This is why this declaration is located in the 
239 standard init_service(char * name_of_service_to_be_initialised) method.  There are two methods of creating a 
240 CALCIUM port, firstly the create_calcium_port method and secondly the add_port method.
241
242 Creating CALCIUM ports using the add_port method
243 ++++++++++++++++++++++++++++++++++++++++++++++++++++
244 This method is used to create any type of DSC port.  It can be used to create CALCIUM ports in particular.
245
246 .. code-block:: cpp
247
248      add_port< typing_of_my_fabricated_port >( "the type of port to be fabricated",
249                                               "provides"|”uses”,
250                                               "the port name")
251
252
253 *"the type of port to be fabricated"*:
254   This string notifies the DSC port factory in the KERNEL module about the name of the type of port 
255   to be created.  The following types are possible for CALCIUM:
256   “CALCIUM_integer”, “CALCIUM_real”, “CALCIUM_double”, “CALCIUM_logical”, “CALCIUM_complex”,
257   “CALCIUM_string”
258 *“provides”|”uses”*:
259   This string indicates if it is a CALCIUM output (uses) port or an input provides port.  Note that in the DSC semantic, 
260   the provides port provides a write interface used by the uses port.
261 *“the port name”*:
262   The port name corresponds to the name of the variable used in CALCIUM primitives.
263 *typing_of_my_fabricated_port*:
264   This type types the pointer returned by add_port.  The objective for CALCIUM is to indicate the typing corresponding to 
265   the type name already given in the factory plus the uses or provides information:
266
267   - calcium_integer_port_provides or calcium_integer_port_uses
268   - calcium_real_port_provides or calcium_real_port_uses
269   - calcium_double_port_provides or calcium_double_port_uses
270   - calcium_string_port_provides or calcium_string_port_uses
271   - calcium_complex_port_provides or calcium_complex_port_uses
272   - calcium_logical_port_provides or calcium_logical_port_uses
273
274
275 Extract from the init_service method in the ECODE.cxx file for the ECODE component:
276
277 .. code-block:: cpp
278
279     CORBA::Boolean ECODE_impl::init_service(const char * service_name) {
280     
281       CORBA::Boolean rtn = false;
282       string s_name(service_name);
283       
284       if (s_name == "EcodeGo") {
285     
286         try {
287       
288         add_port<calcium_integer_port_provides>("CALCIUM_integer","provides","ETP_EN")->
289           setDependencyType(CalciumTypes::TIME_DEPENDENCY);
290      
291          add_port<calcium_real_port_provides>("CALCIUM_real","provides","ETP_RE") ->
292           setDependencyType(CalciumTypes::TIME_DEPENDENCY);
293         
294         add_port<calcium_double_port_provides>("CALCIUM_double","provides","ETP_DB")->
295           setDependencyType(CalciumTypes::TIME_DEPENDENCY);
296     
297         add_port<calcium_complex_port_provides>("CALCIUM_complex","provides","ETP_CX")->
298           setDependencyType(CalciumTypes::TIME_DEPENDENCY);
299     
300         add_port<calcium_string_port_provides>("CALCIUM_string","provides","ETP_CH")->
301           setDependencyType(CalciumTypes::TIME_DEPENDENCY);
302     
303         add_port<calcium_logical_port_provides>("CALCIUM_logical","provides","ETP_LQ")->
304           setDependencyType(CalciumTypes::TIME_DEPENDENCY);
305      ....
306         rtn = true;
307         } catch ( const DSC_Exception & ex ) {
308           std::cerr << ex.what() << std::endl;;
309         }
310       } //FIN (s_name == "Ecode")
311     
312       return rtn;
313     }
314
315 Creating CALCIUM ports using the create_calcium_port method
316 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
317 This method is specially written for the creation of CALCIUM ports, and simplifies the creation of ports.  
318 It is used by YACSGEN.  The “IN”|”OUT” parameter indicates whether it is a CALCIUM input or output port.  
319 The “T”|”I” parameter indicates the port mode, time or iterative.
320
321 Extract from the init_service method in the ECODE.cxx file for the ECODE component:
322
323
324 .. code-block:: cpp
325
326     ECODE_i::init_service(const char * service_name) {
327        CORBA::Boolean rtn = false;
328        string s_name(service_name);
329        if (s_name == "EcodeGo")   {
330             try   {
331                 //initialisation CALCIUM ports IN
332                create_calcium_port(this,"ETP_EN","CALCIUM_integer","IN","T");
333                create_calcium_port(this,"ETP_RE","CALCIUM_real","IN","T");
334                create_calcium_port(this,"ETP_DB","CALCIUM_double","IN","T");
335                create_calcium_port(this,"ETP_CX","CALCIUM_complex","IN","T");
336                create_calcium_port(this,"ETP_CH","CALCIUM_string","IN","T");
337                create_calcium_port(this,"ETP_LQ","CALCIUM_logical","IN","T");
338     ...      }
339            catch(const PortAlreadyDefined& ex)   {
340                std::cerr << "ECODE: " << ex.what() << std::endl;
341                //Ports already created : we use them
342             }
343            catch ( ... )   {
344                std::cerr << "ECODE: unknown exception" << std::endl;
345             }
346            rtn = true;
347          }
348        return rtn;
349      }
350
351
352 Declaration of component resources (part 2)
353 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''
354 The XML component resource file must be completed to declare that CALCIUM ports exist in the different components.  
355 YACSGEN takes account of CALCIUM ports in the generation of the module catalog.
356
357 Extract from the CALCIUM_TESTSCatalog.xml catalog for the ECODE component:
358
359 .. code-block:: xml
360
361     .....           
362                         <DataStream-list>
363                            <inParameter>
364                               <inParameter-name>ETP_EN</inParameter-name>
365                               <inParameter-type>CALCIUM_integer</inParameter-type>
366                               <inParameter-dependency>T</inParameter-dependency>
367                            </inParameter>
368                            <inParameter>
369                               <inParameter-name>ETP_RE</inParameter-name>
370                               <inParameter-type>CALCIUM_real</inParameter-type>
371                               <inParameter-dependency>T</inParameter-dependency>
372                            </inParameter>
373                            <inParameter>
374                               <inParameter-name>ETP_DB</inParameter-name>
375                               <inParameter-type>CALCIUM_double</inParameter-type>
376                               <inParameter-dependency>T</inParameter-dependency>
377                            </inParameter>
378     .....           
379                         </DataStream-list>
380
381
382 Configuring a CALCIUM port
383 ''''''''''''''''''''''''''''''''''
384 The step to configure ports uses all possible link parameter settings in the CALCIUM coupling file outside SALOME.  
385 This step can be done when the port is created in the component (init_service method) by a coupling parameter 
386 setting component / script, or by the YACS supervisor.  This step indicates the following characteristics 
387 for each port in the provides class:
388
389 - time / iteration dependency of received data:
390      TIME_DEPENDENCY or ITERATION_DEPENDENCY
391 - The data storage level (size of the history stack):
392      UNLIMITED_STORAGE_LEVEL (by default) or a strictly positive integer
393 - The time scheme selected to define the date used in read primitives (CPLxx) in time mode:
394  
395    * TI_SCHEM (default value):  Values of the input variable used are taken at the time corresponding to the beginning of 
396      the current time step in the calculation (see parameter **ti** of CPLxx)
397    * TF_SCHEM:  Values of the input variable are taken at the time corresponding to the end of the current time step 
398      in the calculation (see parameter **tf** of CPLxx)
399    * ALPHA_SCHEM:  Values of the input variable are taken at an instant equal to TF * *ALPHA* + TI * (1 - *ALPHA*).  
400      *ALPHA* can be equal to values strictly between 0 and 1.  The value 0 is replaced by the TI_SCHEM option and 
401      the value 1 is replaced by the TF_SCHEM option).
402
403 - The interpolation type to be used for a port in time mode:
404      L0_SCHEM, L1_SCHEM
405 - The extrapolation type to be used in the case of blockage / timeout:
406      E0_SCHEM, E1_SCHEM (not yet functional)
407 - The value of the DELTAT parameter that indicates if two dates are identical.
408
409 All of the keywords used when the ports are configured are defined in the CalciumTypes C++ namespace in the CalciumTypes.hxx file.
410
411 Configuration when the PORT is created
412 +++++++++++++++++++++++++++++++++++++++++++++++++
413 When a port is created, the add_port method returns a pointer to the port useful to its configuration.  One example 
414 configuration in the init_service method consists of indicating if the port is in time dependency or iteration dependency mode:
415
416 .. code-block:: cpp
417
418       add_port<calcium_integer_port_provides>("CALCIUM_integer","provides","ETP_EN")->
419           setDependencyType(CalciumTypes::TIME_DEPENDENCY);
420
421
422 The following methods are available to configure CALCIUM ports:
423
424 * Set / Query the dependency type:
425
426 The dependency type informs the port if the data are stamped by a date or (exclusive) an iteration number.  The default 
427 dependency type is undefined (CalciumTypes::UNDEFINED_DEPENDENCY).  CalciumTYpes::TIME_DEPENDENCY or 
428 CalciumTypes::ITERATION_DEPENDENCY can be defined.
429
430 .. code-block:: cpp
431
432      void setDependencyType (DependencyType dependencyType);
433      DependencyType getDependencyType () const;
434     
435
436 * Set / Query the storage level of the data produced:
437
438 The storage level in the history of data produced must be greater than or equal to 1.  By default it is 
439 unlimited (CalciumTypes::UNLIMITED_STORAGE_LEVEL).  It may have to be reduced, to limit memory consumption for the 
440 case of a coupling with many iterations.
441
442 .. code-block:: cpp
443
444      void   setStorageLevel   (size_t storageLevel);
445      size_t getStorageLevel   () const;
446
447   
448 * Set / Query the time scheme used to define the read date:
449
450 The time scheme chosen to define the date used in read primitives in time mode is set to CalciumTypes::TI_SCHEM by default.  It is also possible to enter CalciumTypes::TF_SCHEM or CalciumTypes::ALPHA_SCHEM.
451
452 .. code-block:: cpp
453
454       void                  setDateCalSchem   (DateCalSchem   dateCalSchem);
455       DateCalSchem getDateCalSchem () const;
456
457   
458 If the time scheme used is ALPHA_SCHEM, the next method is used to indicate the value of ALPHA to be used.  Alpha is equal to zero by default (equivalent to TI_SCHEM) and it can be set to between 0 and 1 inclusive.
459
460
461 .. code-block:: cpp
462
463     void     setAlpha(double alpha);
464     double getAlpha() const ;
465
466
467 * Set / Query the tolerated deviation within which two dates will be considered to be identical:
468
469 Two dates D1 and D2 are identical if abs(T1-T2) <CalciumTypes::EPSILON.  Epsilon is equal to 1E-6 by default.  
470 Parameters can be set for it on each port (0 <= deltaT <= 1).
471
472 .. code-block:: cpp
473
474       void     setDeltaT(double deltaT );
475       double getDeltaT() const ;
476
477
478 * Set / Query the type of time interpolation to be used:
479
480 When a read request is formulated for a date T that has not been produced but is surrounded by dates T1(min) and T2(max) for which data have already been produced, CALCIUM produces a CalciumTypes::L1_SCHEM linear interpolation by default.  The user can request a CalciumTypes::L0_SCHEM step “interpolation”.
481
482 .. code-block:: cpp
483
484       void setInterpolationSchem (InterpolationSchem interpolationSchem);
485       InterpolationSchem getInterpolationSchem () const ;
486
487 * Set / Query the type of the extrapolation to be used:
488
489 This parameter is used to indicate whether an extrapolation is required to exit from a blocking case (a port waiting for data that will never be produced).  The default value is Calcium-Types::UNDEFINED_EXTRA_SCHEM.  Possible values are EO_SCHEM (step extrapolation) or E1-SCHEM (linear extrapolation).
490
491 .. code-block:: cpp
492
493      void setExtrapolationSchem (ExtrapolationSchem extrapolationSchem);
494      ExtrapolationSchem getExtrapolationSchem () const ;
495
496
497 Configuration using properties of DSC ports
498 +++++++++++++++++++++++++++++++++++++++++++++++++
499 This section explains advanced use of the properties of DSC ports to perform the CALCIUM ports configuration step, it can 
500 be ignored if CALCIUM ports are used in a simple manner.
501
502 All DSC ports can be configured by a list of properties.  Therefore, the configuration step can be made using a CORBA call on the ports concerned.
503
504 The [set|get]_property methods of DSC ports manipulate a list of pairs with a key equal to the name of the property in 
505 the first position and the associated value in the second position.
506
507 Extract from the SALOME_Component.idl file of the SALOME KERNEL:
508
509 ::
510
511      struct KeyValuePair  {
512         string key;
513         any value;
514       };
515      typedef sequence<KeyValuePair> FieldsDict;
516      void setProperties(in FieldsDict dico);
517      FieldsDict getProperties();
518
519
520
521 CALCIUM declares the following types in the SALOME KERNEL Calcium_Ports.idl file:
522
523 ::
524
525     const long UNLIMITED_STORAGE_LEVEL = -70;   
526     enum DependencyType { UNDEFINED_DEPENDENCY, TIME_DEPENDENCY, ITERATION_DEPENDENCY};
527     enum DateCalSchem           { TI_SCHEM, TF_SCHEM , ALPHA_SCHEM};
528     enum InterpolationSchem   { L0_SCHEM, L1_SCHEM };
529     enum ExtrapolationSchem  { UNDEFINED_EXTRA_SCHEM, E0_SCHEM, E1_SCHEM};
530
531
532 Therefore, the recognised properties are the following pairs:
533
534 - (“StorageLevel”, int > 0 )
535 - (“Alpha”, 0 <= double <= 1 )
536 - (“DeltaT”, 0 <= double <= 1 )
537 - (“DependencyType”, enum CORBA DependencyType)
538 - (“DateCalSchem”, enum CORBA DateCalSchem)
539 - (“InterpolationSchem”,enum CORBA InterpolationSchem)
540 - (“ExtrapolationSchem”,enum CORBA ExtrapolationSchem)
541
542 Example dynamic configuration by a python script (extract from file CAS_1.py):
543
544 .. code-block:: python
545
546     ...
547     port1=ecode.get_provides_port("ETS_DB",0);
548     myAny1_1=4
549     port1.set_property("StorageLevel",any.to_any(myAny1_1))
550     
551
552 The get_provides_port and set_property methods are provided by the default implementation of supervisable SALOME components.
553
554 The configuration in the YACS XML file
555 ++++++++++++++++++++++++++++++++++++++++++++
556 The YACS supervisor module is capable of importing / exporting calculation schemes in the XML format.  In particular, this 
557 includes the declaration of links between the ports of the different component instances.  The YACS GUI generates all sorts of 
558 calculation schemes and starts their execution.
559
560 At the present time, properties cannot be added to CALCIUM ports with YACS GUI.  Therefore, they have to be added into 
561 the XML file manually.  In YACS, calcium ports are configured by declaring properties on the links.
562
563 Extract from the CAS_1.xml calculation scheme, first test case of CALCIUM functions:
564
565 Example configuration of the ETS_DB port at a history level of 4.
566
567 .. code-block:: xml
568
569      <stream>
570           <fromnode>SCODE</fromnode> <fromport>STS_DB</fromport>
571           <tonode>ECODE</tonode> <toport>ETS_DB</toport>
572           <property name="StorageLevel" value="4"/>
573        </stream>
574     
575
576 (Keys, value) pairs used to describe properties are as listed in the previous section. 
577  
578 Calls to CALCIUM methods
579 '''''''''''''''''''''''''''''''
580 The CALCIUM C / C++ / Fortran API in SALOME is globally identical to the API for the CALCIUM product outside SALOME.  
581 It is now also available in Python.
582
583 See :ref:`calciumapi` for C and Fortran API documentation and :mod:`calcium` for Python API documentation.
584
585 The classical C / C++ API is extended by a zero copy version that transfers data without an intermediate copy.
586
587 C++ developers can use an API more specific to C++ that proposes parameter types more adapted to the language.
588
589 It is also possible to use CALCIUM DSC ports more directly with their associated CORBA types.
590
591
592
593 Classical CALCIUM calls in C / C++ / F / Python
594 +++++++++++++++++++++++++++++++++++++++++++++++++
595 The classical CALCIUM API remains essentially the same, regardless of whether the objective is to include an existing 
596 CALCIUM C / C ++ / Fortran code in the SALOME platform or to develop a new CALCIUM component.
597
598 The code containing CALCIUM calls is written directly in the SALOME service of the C++ component, or is accessible through a procedure call.
599
600 In the first case, the code must be written in C / C++ / Python because there is no SALOME component written directly in Fortran.
601
602 In the second case, the calling service must transmit the access pointer to its component.  Unlike the CALCIUM outside 
603 SALOME API, the first argument of all procedures is the pointer of the component that holds the associated ports.  
604 This enables the CALCIUM library to identify the component that holds the requested ports [1]_.
605
606 Extract from the implementation of the EcodeGo() (ECODE.cxx) service calling the ecode wrapped code (void* component)(Ecode.c):
607
608 (This code can be generated by YACSGEN)
609
610
611 .. code-block:: cpp
612
613     void ECODE_impl::EcodeGo() {
614       Superv_Component_i * component = dynamic_cast<Superv_Component_i*>(this);
615       try {
616         ecode(component);            
617       } 
618       catch ( const CalciumException & ex)
619     ....
620     }
621
622
623 A code already written to use CALCIUM only needs to be adapted to transmit the pointer of its component as a first 
624 parameter of calls to CALCIUM procedures.  Apart from this observation, the code remains exactly the same as the 
625 initial calcium code.
626
627 Extract from the implementation of the calcium source code applied by the service (Ecode.c):
628
629 .. code-block:: c
630
631     ...
632     #include <calcium.h>
633     ...
634     int    ecode(void * component)
635     {
636     ...
637     /*    Connection to the coupler   */
638         info = cp_cd(component,nom_instance);
639     
640         info= cp_len(component,CP_TEMPS,&ti_re,&tf_re,&i,"ETP_EN",1,&n,EDATA_EN);
641     ...
642         info = cp_fin(component,CP_CONT);
643     }
644
645
646
647 The C ecode procedure connects to the CALCIUM coupler through the cp_cd procedure and then formulates a blocking read 
648 request to the ETP_EN port / connection point according to a time scheme between ti_re and tf_re.  Only one data is 
649 requested, it will be stored in the EDATA_EN buffer.  The procedure finishes when the coupler is disconnected, using 
650 the CP_CONT flag to indicate that any clients of ports associated with ecode will receive the most recent known value 
651 if there are any new read requests.  If the CP_ARRET flag was used, any subsequent read request on the ports associated 
652 with ecode() would exit in error.
653
654 The scheme is the same in fortran, the following is an extract from the Ecode.f file:
655
656 .. code-block:: fortran
657
658         SUBROUTINE ECODE(compo)
659         INCLUDE 'calcium.hf'
660         INTEGER compo
661         ----
662         CALL CPCD(compo,nom_instance, info)
663         ----
664         CALL CPLEN(compo,CP_TEMPS,ti_re,tf_re,i,'ETP_EN',1,n,EDATA_EN,info)
665         ----
666         CALL CPFIN(compo,CP_CONT, info)
667         ----
668
669
670 CALCIUM C/C++ calls in zero copy mode
671 +++++++++++++++++++++++++++++++++++++++
672 CALCIUM DSC ports of the provides type (CALCIUM entry connection points) keep the received data to be able to create the 
673 requested history (unlimited by default).  When the user formulates a read for data that are already available, the port 
674 copies these data into the buffer provided by the user.  An extended CALCIUM API allows the user to supply a null pointer 
675 to replace the pre-allocated reception pointer, so as to obtain a pointer to the internal buffer of the CALCIUM provides 
676 class port directly.  This prevents a potentially large copy, but it obliges the user to be vigilant on the following points:
677
678 1. The buffer obtained must be used in read only.  Unless it is used in a particular manner, any modification to the buffer 
679    would be reflected in new read requests for the same stamp or during an interpolation calculation using this stamp.
680 2. The buffer is dependent on the history level set for the port.  If the history level set for the port is such that the 
681    stamp and the associated buffer will be deleted, the user will have a pointer to an invalid buffer and its use would probably corrupt memory.
682 3. Zero copy is not used on integers and booleans because these types do not exist in CORBA.
683 4. The user must call the CALCIUM procedure once only to release the pointer obtained.  This releases any buffers created for 
684    cases in which a zero copy is impossible.  This also helps to count distributed references to prevent early release (not yet implemented).
685
686 The zero copy API consists of calling ecp_lxx read procedures instead of their corresponding procedure cp_lxx and transferring 
687 the address of a pointer for which the value is initialized to zero.
688
689 The write procedures API is not modified because these procedures still operate in zero copy.  If the sender and receiver 
690 components are placed in the same container, a copy is triggered on reception  of data to prevent any interaction between 
691 the sender's buffer and the receiver's buffer.
692
693 Extract from the zero copy implementation of the CALCIUM source code called by the (Ecode.c) service:
694
695
696 .. code-block:: c
697
698         float *sav_EDATA_RE = _EDATA_RE; //keep a ptr to previously received data
699         _EDATA_RE = NULL;
700         ti_re = 1.1;
701         tf_re = 1.2;
702         info = ecp_lre(component,CP_TEMPS,&ti_re,&tf_re,&i,"ETP_RE",0,&n,&_EDATA_RE);
703         fprintf(file_2,"%f\n", _EDATA_RE[0]);
704         ti_re = 0.0;
705         tf_re = 1.0;
706     
707         ecp_lre_free(sav_EDATA_RE);
708         ecp_lre_free(_EDATA_RE);
709
710
711 CALCIUM calls with API specific to C++
712 +++++++++++++++++++++++++++++++++++++++++
713 C++ developers can use a specific API that proposes parameters with types better adapted to the language.
714
715 Time stamps are always of the double type and iterations are always of the long type, regardless of whether it is in write or 
716 read and regardless of the type of transmitted data.  Variable names are STL strings.  The name of read and write methods is 
717 the same regardless of the type of data manipulated.  The type of data is found automatically, except for complex types, 
718 logical types and character strings.
719
720 .. code-block:: cpp
721
722       template <typename T1, typename T2> static void
723       ecp_ecriture ( Superv_Component_i & component,  int const  & dependencyType,
724              double const & t,  long const  & i,
725              const   string & nomVar,  size_t bufferLength,  T1 const  & data ) 
726
727
728
729       template <typename T1, typename T2 > static void
730       ecp_lecture ( Superv_Component_i & component,   int    const  & dependencyType,
731                    double & ti,  double const  & tf,  long & i,
732                    const string  & nomVar,  size_t bufferLength,
733                    size_t  & nRead,  T1 * &data )
734
735
736 These methods are defined in the CalciumCxxInterface.hxx header file.  Therefore the user will include 
737 the ``#include ”CalciumCxxInterface.hxx”`` directive in the code.
738
739 Note:  the CalciumInterface.hxx file has to be included only once because it declares and defines C++ template methods.  
740 This does not create any problem with compilation, but there is a multiple definition problem during link editing.
741
742 But there is no need to specify T1 and T2 for integer, float or double CALCIUM types, because there is a write method 
743 and a read method with a single template parameter that calls their corresponding methods with the constraint T1==T2==<Type of Data Used>.
744
745 For complex types, the <float,cplx> instantiation has to be used and the number of complexes has to be multiplied by two to 
746 transfer the bufferLength parameter.  In this case, the only difference from use of the float type is the typing of the ports 
747 used, namely calcium_complex_port_provides instead of calcium_real_port_provides.
748
749 Instantiation for the logical type is done with <int, bool>.
750
751 Instantiation for character strings is <char*, str>.  The character strings can be read without giving the maximum string 
752 length parameter located in the classical C / C++ / Fortran API.
753
754 Differences from the CALCIUM product outside SALOME
755 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
756 All that are implemented are read / write procedures and connection/disconnection procedures. Step back, query, dynamic 
757 configuration and debugging procedures are not implemented.
758
759 However, it is possible to dynamically create and connect components that read/write on ports of other component services.  
760 Any SALOME service using CALCIUM ports has the privileges of a spy (in production mode).
761
762 Several output ports can be connected to the same input port and one output port can be connected to several input ports.  
763 The first case was not possible in CALCIUM outside SALOME.
764
765 Reads/writes are implemented in blocking mode;  non-blocking mode is not yet implemented.
766
767 All ports created by the different services of a single component are visible / usable by all these services.  
768 However, it is not recommended that they should be used in this way.
769
770 The extrapolation has not yet been implemented.
771
772 File ports have not yet been implemented, however there are some DSC file ports in SALOME.
773
774 Ports not connected do not cause any error in execution of coupling unless they are used.
775
776 CALCIUM error codes returned by primitives are the same as for CALCIUM outside SALOME.  By using the specific C++ API, 
777 CalciumException class exceptions (CalciumException.hxx) that contain the CALCIUM error code and an explanation message 
778 can be caught.  The error code contained in the exception is obtained by calling the CalciumTypes::InfoType getInfo() method.  
779 The CalciumException class also inherits from the C++ SALOME_Exception exception.
780
781 A compilation option has to be used to allow C++ exceptions to pass through the C and Fortran codes called from 
782 the SALOME component service.  This option for GNU compilers is -fexceptions.
783
784 Data type exchange will be extended to complex types such as MED fields or meshes.
785
786
787 Starting CALCIUM coupling
788 --------------------------------
789 CALCIUM coupling can be started in three different ways.  The first is to use the SALOME KERNEL only and to manage 
790 component instances by a python script.  The second is to create a component that would control coupling.  The third 
791 is to use the YACS supervisor component with or without its GUI.
792
793 Setting up the environment
794 '''''''''''''''''''''''''''''''''''
795 Regardless of what method is chosen, the KERNEL module has to be notified about the existence of new modules to be used.  
796 Only one module needs to be declared if all components are within the same module.
797
798 This step is no specific to CALCIUM components, it is necessary for all SALOME components.
799
800 Declaration of <my module>_ROOT_DIR
801 ++++++++++++++++++++++++++++++++++++
802 The KERNEL module is based on a <my module>_ROOT_DIR variable in either a envSalome.sh shell script containing all environment 
803 variables useful to SALOME or in the user console, to locate the installation directory of the <my module> module.
804
805 Example declaration of the CALCIUM_TESTS module in bash:
806
807 .. code-block:: sh
808
809     INSTALLROOT="/local/salome/SALOME5/V5NoDebug"
810     export CALCIUM_TESTS=${INSTALLROOT}/DEV/INSTALL/CALCIUM_TESTS
811     
812
813 The appli_gen.py tool will prepare the appropriate environment in the env.d directory for a SALOME application (see :ref:`appli`).
814
815 Loading the <my module> module when running SALOME 
816 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
817 There are two solutions for loading the <my module> module when SALOME is run.
818
819 Declaration in the SalomeApp.xml file. 
820 #########################################
821 All that is necessary is to declare the name of its module in the modules parameter in the SalomeApp.xml file.
822
823 The following is an example for the CALCIUM_TESTS module:
824
825 .. code-block:: xml
826
827      <section name="launch">
828      ....
829      <parameter name="modules"    value="GEOM,SMESH,VISU,YACS,MED,CALCIUM_TESTS"/>
830      ....
831      </section>
832
833
834
835 Using the --module option.  
836 ################################
837 This option limits loading of modules to the list indicated in the command line (it assumes that the user’s environment 
838 indicates the location of the modules).
839
840 .. code-block:: sh
841
842     ./runAppli  --module=YACS,CALCIUM_TESTS
843
844
845 Running a simple coupling through a python script
846 ''''''''''''''''''''''''''''''''''''''''''''''''''''''
847 Components can be created and their ports can be connected using a Python SALOME session.
848 The script CAS_1.py loads instances of the ECODE, SCODE and ESPION components, connects their ports, makes the necessary 
849 configurations and starts executions.
850
851 The following is an extract from the CAS_1.py file that can be found in <path to CALCIUM_TESTS module>/CALCIUM_TESTS/lib/python2.4/site-packages/salome:
852
853 .. code-block:: python
854
855     
856     import LifeCycleCORBA
857     import Engines
858     import Ports
859     import CALCIUM_TESTS
860     import orbmodule
861     import user
862     
863     import sys
864     import threading
865     from omniORB import any
866     
867     #Load component instances through the LifeCycle 
868     lcc = LifeCycleCORBA.LifeCycleCORBA()
869     ecode = lcc.FindOrLoad_Component('FactoryServer3', 'ECODE')
870     ecode.init_service("EcodeGo")
871     scode = lcc.FindOrLoad_Component('FactoryServer4', 'SCODE')
872     scode.init_service("ScodeGo")
873     
874     #Display the content of the naming server
875     #Obtain a reference to the connection manager
876
877     clt=orbmodule.client()
878     clt.showNS()
879     connection_manager = clt.Resolve("ConnectionManager")
880     
881     #Create CALCIUM links through the connection manager
882     connection_manager.connect(scode, "STP_EN",ecode, "ETP_EN")
883     connection_manager.connect(scode, "STP_RE", ecode, "ETP_RE")
884     connection_manager.connect(scode, "STP_DB", ecode, "ETP_DB")
885     connection_manager.connect(scode, "SIP_EN", ecode, "EIP_EN")
886     connection_manager.connect(scode, "SIP_DB", ecode, "EIP_DB")
887     connection_manager.connect(scode, "SIS_EN", ecode, "EIS_EN")
888     connection_manager.connect(scode, "SIS_DB", ecode, "EIS_DB")
889     connection_manager.connect(scode, "STS_EN", ecode, "ETS_EN")
890     connection_manager.connect(scode, "STS_DB", ecode, "ETS_DB")
891     port1=ecode.get_provides_port("ETS_DB",0);
892     myAny1_1=4
893     port1.set_property("StorageLevel",any.to_any(myAny1_1))
894     connection_manager.connect(scode, "STS_DB", ecode, "ETP_DB2")
895     connection_manager.connect(scode, "STP_CX", ecode, "ETP_CX")
896     connection_manager.connect(scode, "STP_CH", ecode, "ETP_CH")
897     connection_manager.connect(scode, "STP_LQ", ecode, "ETP_LQ")
898     #Create and connect the spy (espion) 
899     #The ESPION can be created after the instances of ECODE and SCODE have been run,
900     #however data produced before the connection will be lost
901     espion = lcc.FindOrLoad_Component('FactoryServer5', 'ESPION')
902     espion.init_service("EspionGo")
903     
904     connection_manager.connect(scode,  "STP_DB2", ecode, "ETP_DB2")
905     connection_manager.connect(espion, "STP_DB2", ecode, "ETP_DB2")
906     connection_manager.connect(scode,  "SIP_DB2", espion, "SIP_DB2")
907     connection_manager.connect(espion, "SIP_DB" , ecode , "EIP_DB" )
908     connection_manager.connect(scode,  "SIP_DB" , espion, "EIP_DB")
909     
910     #If the spy is run last, CAS_1 works but test 15 does not work
911     handler3=threading.Thread(target=espion.EspionGo)
912     handler3.start()
913     handler=threading.Thread(target=ecode.EcodeGo)
914     handler.start()
915     handler2=threading.Thread(target=scode.ScodeGo)
916     handler2.start()
917     
918     handler.join()
919     handler2.join()
920     handler3.join()
921
922
923
924 The script can be run using the following command:
925
926 .. code-block:: sh
927
928   ./runAppli -t --module=YACS,CALCIUM_TESTS -u CAS_1.py
929
930 Running coupling through the YACS GUI
931 '''''''''''''''''''''''''''''''''''''''''''
932 If the module catalog contains the description of components and their services, it is easy to create a coupling scheme by 
933 inserting the services of components that are to be linked.
934
935 To insert a service, simply do a right click / CASE_1 / create a node / create a node from catalog / in the edit tree of the graph.
936
937 Linking two ports consists of selecting the output port (in the edit tree) and then doing a right click on the /add data link/ command, and then selecting the input port.
938
939 There is no consistency check on the branch of incompatible CALCIUM port types in current version of the YACS GUI.  However, an error will occur at the time of execution.
940
941 Once the scheme has been created, it can be exported in the YACS coupling scheme XML format (see toolbar).
942
943 The following is a graphic example of the coupling scheme for the first CALCIUM test case:
944
945 .. image:: images/calcium1.png
946   :align: center
947
948 Once the scheme has been created, all that is necessary is to create an execution by doing a right click on /YACS/CAS_1/New Execution/.  
949 The study tree becomes the execution tree in which the state of the different services appears.  Once it has been 
950 run (by pressing the appropriate button in the tool bar), the services are in the ‘done’ state if everything took place correctly.  
951 The log of a container associated with execution of a service can be displayed by doing a right click on the service concerned 
952 and selecting /Node container Log/.  If an error occurs, reports are displayed by selecting /Error Details/ or /Error Report/.
953
954 As many executions as are necessary can be created.  Modifying the edit scheme does not modify existing execution schemes. 
955 One execution has to be recreated to start the modified scheme.  Do a right click and select /New Edition/ in order to find 
956 the edit scheme corresponding to an execution scheme again.
957
958 Any container configuration is possible:
959
960 1. several CALCIUM services (for one component or different components) coupled within a single container
961 2. several CALCIUM services (for one component or different components) coupled within different containers
962 3. an intermediate configuration between the previous two cases.
963
964 Current limitations:
965
966 1. It is impossible to have several services of a single component simultaneously using distinct CALCIUM ports with the same name.
967 2. It is not possible to restart the same execution because the init_service method will attempt to create existing 
968    ports (an execution has to be created or init_service has to be modified so as to memorise the creation of ports).
969
970
971 Running coupling through YACS without GUI
972 ''''''''''''''''''''''''''''''''''''''''''
973 To do this, you have to create a schema file in XML format (see :ref:`schemaxml`) and to execute it in console
974 mode (see :ref:`execxml`).
975
976
977 Setting up a timeout to interrupt execution in case of interlocking
978 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
979 Sometimes (mainly during development phases), a calculation can ends up in a deadlock. A component waits for a data that 
980 another component must send but this component is also waiting and all these components are waiting in a loop, so the calculation
981 never ends : it's a deadlock.
982
983 There is no way in CALCIUM to detect this deadlock, but it is possible to set a timeout to go out of the deadlock. 
984 A timeout is a time in seconds. When a component waits longer than timeout, an error occurs and the calculation is interrupted.
985 The timeout can be specified by setting the environment variable DSC_TIMEOUT (export DSC_TIMEOUT=600, in bash to set a 10 minutes timeout).
986 It must be set before launching a SALOME session and is therefore globally used for all the calculations in the session. 
987  
988 It is also possible to specify a timeout in the XML coupling file by way of a service node property (DSC_TIMEOUT) as in
989 the following example:
990
991 .. code-block:: xml
992
993       <service name="canal" >
994         <component>FLUIDE</component>
995         <method>prun</method>
996         <load container="A"/>
997         <property name="DSC_TIMEOUT" value="20"/>
998         <instream name="tpi" type="CALCIUM_real"/>
999         <instream name="iconv" type="CALCIUM_integer"/>
1000         <outstream name="tfi" type="CALCIUM_real"/>
1001       </service>
1002
1003 As a consequence, the timeout will be active for all the services in the container of the service (container A in the example).
1004
1005 It is not yet possible to specify a timeout limited to one port or one link.
1006
1007 Creating a SALOME application
1008 --------------------------------------------
1009 Example command invoked to create a SALOME application after adapting the config_appli.xml file:
1010
1011 .. code-block:: sh
1012
1013     python $KERNEL_ROOT_DIR/bin/salome/appli_gen.py --prefix=/local/salome5_my_appli \
1014                                                     --config=config_appli_mod.xml                   
1015
1016
1017
1018 Coupling scheme: example of YACS XML file
1019 -----------------------------------------------
1020 The complete CAS_1.xml file for the coupling scheme of the CALCIUM CAS_1 test case (it can be generated by the YACS GUI):
1021
1022 .. code-block:: xml
1023
1024     <?xml version='1.0'?>
1025     <proc>
1026        <type name="Bool" kind="bool"/>
1027        <type name="Double" kind="double"/>
1028        <type name="Int" kind="int"/>
1029        <type name="String" kind="string"/>
1030        <objref name="CALCIUM_complex"
1031                id="IDL:Ports/Calcium_Ports/Calcium_Complex_Port:1.0"/>
1032        <objref name="CALCIUM_double"
1033                id="IDL:Ports/Calcium_Ports/Calcium_Double_Port:1.0"/>
1034        <objref name="CALCIUM_integer"
1035                id="IDL:Ports/Calcium_Ports/Calcium_Integer_Port:1.0"/>
1036        <objref name="CALCIUM_logical"
1037                id="IDL:Ports/Calcium_Ports/Calcium_Logical_Port:1.0"/>
1038        <objref name="CALCIUM_real" 
1039                id="IDL:Ports/Calcium_Ports/Calcium_Real_Port:1.0"/>
1040        <objref name="CALCIUM_string"
1041                id="IDL:Ports/Calcium_Ports/Calcium_String_Port:1.0"/>
1042        <objref name="file" id="file"/>
1043        <container name="DefaultContainer">
1044           <property name="container_name" value=""/>
1045           <property name="cpu_clock" value="0"/>
1046           <property name="hostname" value=""/>
1047           <property name="isMPI" value="false"/>
1048           <property name="mem_mb" value="0"/>
1049           <property name="nb_component_nodes" value="0"/>
1050           <property name="nb_node" value="0"/>
1051           <property name="nb_proc_per_node" value="0"/>
1052           <property name="parallelLib" value=""/>
1053           <property name="workingdir" value=""/>
1054        </container>
1055        <service name="SCODE">
1056           <component>SCODE</component>
1057           <load container="DefaultContainer"/>
1058           <method>ScodeGo</method>
1059           <outstream name="STP_EN" type="CALCIUM_integer"/>
1060           <outstream name="STP_RE" type="CALCIUM_real"/>
1061           <outstream name="STP_DB" type="CALCIUM_double"/>
1062           <outstream name="STP_CX" type="CALCIUM_complex"/>
1063           <outstream name="STP_CH" type="CALCIUM_string"/>
1064           <outstream name="STP_LQ" type="CALCIUM_logical"/>
1065           <outstream name="SIP_EN" type="CALCIUM_integer"/>
1066           <outstream name="SIP_DB" type="CALCIUM_double"/>
1067           <outstream name="STP_DB2" type="CALCIUM_double"/>
1068           <outstream name="SIS_EN" type="CALCIUM_integer"/>
1069           <outstream name="SIS_DB" type="CALCIUM_double"/>
1070           <outstream name="STS_EN" type="CALCIUM_integer"/>
1071           <outstream name="STS_DB" type="CALCIUM_double"/>
1072           <outstream name="SIP_DB2" type="CALCIUM_double"/>
1073        </service>
1074        <service name="ECODE">
1075           <component>ECODE</component>
1076           <load container="DefaultContainer"/>
1077           <method>EcodeGo</method>
1078           <instream name="ETP_EN" type="CALCIUM_integer"/>
1079           <instream name="ETP_RE" type="CALCIUM_real"/>
1080           <instream name="ETP_DB" type="CALCIUM_double"/>
1081           <instream name="ETP_CX" type="CALCIUM_complex"/>
1082           <instream name="ETP_CH" type="CALCIUM_string"/>
1083           <instream name="ETP_LQ" type="CALCIUM_logical"/>
1084           <instream name="EIP_EN" type="CALCIUM_integer"/>
1085           <instream name="EIP_DB" type="CALCIUM_double"/>
1086           <instream name="ETP_DB2" type="CALCIUM_double"/>
1087           <instream name="EIS_EN" type="CALCIUM_integer"/>
1088           <instream name="EIS_DB" type="CALCIUM_double"/>
1089           <instream name="ETS_EN" type="CALCIUM_integer"/>
1090           <instream name="ETS_DB" type="CALCIUM_double"/>
1091        </service>
1092        <service name="Espion">
1093           <component>ESPION</component>
1094           <load container="DefaultContainer"/>
1095           <method>EspionGo</method>
1096           <instream name="SIP_DB2" type="CALCIUM_double"/>
1097           <instream name="EIP_DB" type="CALCIUM_double"/>
1098           <outstream name="STP_DB2" type="CALCIUM_double"/>
1099           <outstream name="SIP_DB" type="CALCIUM_double"/>
1100        </service>
1101        <stream>
1102           <fromnode>SCODE</fromnode> <fromport>STP_EN</fromport>
1103           <tonode>ECODE</tonode> <toport>ETP_EN</toport>
1104        </stream>
1105        <stream>
1106           <fromnode>SCODE</fromnode> <fromport>STP_RE</fromport>
1107           <tonode>ECODE</tonode> <toport>ETP_RE</toport>
1108        </stream>
1109        <stream>
1110           <fromnode>SCODE</fromnode> <fromport>STP_DB</fromport>
1111           <tonode>ECODE</tonode> <toport>ETP_DB</toport>
1112        </stream>
1113        <stream>
1114           <fromnode>SCODE</fromnode> <fromport>STP_CX</fromport>
1115           <tonode>ECODE</tonode> <toport>ETP_CX</toport>
1116        </stream>
1117        <stream>
1118           <fromnode>SCODE</fromnode> <fromport>STP_CH</fromport>
1119           <tonode>ECODE</tonode> <toport>ETP_CH</toport>
1120        </stream>
1121        <stream>
1122           <fromnode>SCODE</fromnode> <fromport>STP_LQ</fromport>
1123           <tonode>ECODE</tonode> <toport>ETP_LQ</toport>
1124        </stream>
1125        <stream>
1126           <fromnode>SCODE</fromnode> <fromport>SIP_EN</fromport>
1127           <tonode>ECODE</tonode> <toport>EIP_EN</toport>
1128        </stream>
1129        <stream>
1130           <fromnode>SCODE</fromnode> <fromport>SIP_DB</fromport>
1131           <tonode>ECODE</tonode> <toport>EIP_DB</toport>
1132        </stream>
1133        <stream>
1134           <fromnode>SCODE</fromnode> <fromport>SIP_DB</fromport>
1135           <tonode>Espion</tonode> <toport>EIP_DB</toport>
1136        </stream>
1137        <stream>
1138           <fromnode>SCODE</fromnode> <fromport>STP_DB2</fromport>
1139           <tonode>ECODE</tonode> <toport>ETP_DB2</toport>
1140        </stream>
1141        <stream>
1142           <fromnode>SCODE</fromnode> <fromport>SIS_EN</fromport>
1143           <tonode>ECODE</tonode> <toport>EIS_EN</toport>
1144        </stream>
1145        <stream>
1146           <fromnode>SCODE</fromnode> <fromport>SIS_DB</fromport>
1147           <tonode>ECODE</tonode> <toport>EIS_DB</toport>
1148        </stream>
1149        <stream>
1150           <fromnode>SCODE</fromnode> <fromport>STS_EN</fromport>
1151           <tonode>ECODE</tonode> <toport>ETS_EN</toport>
1152        </stream>
1153        <stream>
1154           <fromnode>SCODE</fromnode> <fromport>STS_DB</fromport>
1155           <tonode>ECODE</tonode> <toport>ETS_DB</toport>
1156           <property name="level" value="4"/>
1157        </stream>
1158        <stream>
1159           <fromnode>SCODE</fromnode> <fromport>STS_DB</fromport>
1160           <tonode>Espion</tonode> <toport>SIP_DB2</toport>
1161        </stream>
1162        <stream>
1163           <fromnode>SCODE</fromnode> <fromport>STS_DB</fromport>
1164           <tonode>Espion</tonode> <toport>EIP_DB</toport>
1165        </stream>
1166        <stream>
1167           <fromnode>SCODE</fromnode> <fromport>SIP_DB2</fromport>
1168           <tonode>Espion</tonode> <toport>SIP_DB2</toport>
1169        </stream>
1170        <stream>
1171           <fromnode>Espion</fromnode> <fromport>STP_DB2</fromport>
1172           <tonode>ECODE</tonode> <toport>ETP_DB2</toport>
1173        </stream>
1174        <stream>
1175           <fromnode>Espion</fromnode> <fromport>SIP_DB</fromport>
1176           <tonode>ECODE</tonode> <toport>EIP_DB</toport>
1177        </stream>
1178     </proc>
1179     
1180
1181
1182 Generating a CALCIUM module with YACSGEN: example
1183 -----------------------------------------------------
1184 Complete YACSGEN script to create a generated CALCIUM_TESTS module:
1185
1186 .. code-block:: python
1187
1188     from module_generator import Generator,Module,Service
1189     from module_generator import PYComponent,CPPComponent,F77Component
1190     context={"update":1,
1191              "prerequisites":"/local/salome5/SALOME5/V5NoDebug/prerequis-V5NoDebug.sh",
1192              "kernel":"/local/salome5/SALOME5/V5NoDebug/DEV/INSTALL/KERNEL/"
1193              }
1194            
1195     c1=CPPComponent("ECODE",
1196                     services=[
1197         Service("EcodeGo",
1198                 instream=[
1199         ("ETP_EN","CALCIUM_integer","T"),
1200         ("ETP_RE","CALCIUM_real","T"),
1201         ("ETP_DB","CALCIUM_double","T"),
1202         ("ETP_CX","CALCIUM_complex","T"),
1203         ("ETP_CH","CALCIUM_string","T"),
1204         ("ETP_LQ","CALCIUM_logical","T"),
1205         ("EIP_EN","CALCIUM_integer","I"),
1206         ("EIP_DB","CALCIUM_double","I"),
1207         ("ETP_DB2","CALCIUM_double","T"),
1208         ("EIS_EN","CALCIUM_integer","I"),
1209         ("EIS_DB","CALCIUM_double","I"),
1210         ("ETS_EN","CALCIUM_integer","T"),
1211         ("ETS_DB","CALCIUM_double","T") ],
1212                 outstream=[],
1213                 defs="""extern "C" {
1214     int ecode(void *);
1215     }""",
1216                 body="""
1217                 ecode(component);
1218                 """
1219                 ,),
1220         ],
1221                     libs="",
1222                     rlibs=""
1223                     )
1224     
1225     c2=CPPComponent("SCODE",
1226                     services=[
1227         Service("ScodeGo",
1228                 instream=[],
1229                 outstream=[
1230         ("STP_EN","CALCIUM_integer","T"),
1231         ("STP_RE","CALCIUM_real","T"),
1232         ("STP_DB","CALCIUM_double","T"),
1233         ("STP_CX","CALCIUM_complex","T"),
1234         ("STP_CH","CALCIUM_string","T"),
1235         ("STP_LQ","CALCIUM_logical","T"),
1236         ("SIP_EN","CALCIUM_integer","I"),
1237         ("SIP_DB","CALCIUM_double","I"),
1238         ("STP_DB2","CALCIUM_double","T"),
1239         ("SIS_EN","CALCIUM_integer","I"),
1240         ("SIS_DB","CALCIUM_double","I"),
1241         ("STS_EN","CALCIUM_integer","T"),
1242         ("STS_DB","CALCIUM_double","T"),
1243         ("SIP_DB2","CALCIUM_double","I") ],
1244                 defs="""extern "C" {
1245     int scode(void *);
1246     }""",
1247                 body="""
1248                 scode(component);
1249                 """
1250                 ,),
1251         ],
1252                     libs="",
1253                     rlibs=""
1254                     )
1255     
1256     c3=CPPComponent("ESPION",
1257                     services=[
1258         Service("EspionGo",
1259                 instream=[
1260         ("SIP_DB2","CALCIUM_double","I"),
1261         ("EIP_DB","CALCIUM_double","I")],
1262                 outstream=[           
1263         ("STP_DB2","CALCIUM_double","T"),
1264         ("SIP_DB","CALCIUM_double","I") ],
1265                 defs="""extern "C" {
1266     int espion(void *);
1267     }""",
1268                 body="""
1269                 espion(component);
1270                 """
1271                 ,),
1272         ],
1273                     libs="",
1274                     rlibs=""
1275                     )
1276     
1277     
1278     m=Module("CALCIUM_TESTS",components=[c1,c2,c3],prefix="INSTALL")
1279     
1280     g=Generator(m,context)
1281     g.generate()
1282     ##g.bootstrap()
1283     ##g.configure()
1284     ##g.make()
1285     ##g.install()
1286     ##g.make_appli("appli",restrict=["KERNEL","GUI","YACS"])
1287     
1288 .. [1] The CALCIUM library is shared between several components in a single container, therefore it needs a pointer to the component to identify the requested ports.
1289