wofost¶
A single model receives input from a WOFOST-style parameter file and sends output to a file. This example demonstrates how to interact with generic data structures containing maps in the compiled languages.
C Version¶
Model Code:
1#include <stdio.h>
2// Include methods for input/output channels
3#include "YggInterface.h"
4
5int main(int argc, char *argv[]) {
6 // Initialize input/output channels
7 yggInput_t in_channel = yggGenericInput("input");
8 yggOutput_t out_channel = yggGenericOutput("output");
9
10 // Declare resulting variables and create buffer for received message
11 int flag = 1;
12 generic_t obj = init_generic();
13 double* amaxtb_x = NULL;
14 double* amaxtb_y = NULL;
15 char** keys = NULL;
16 size_t nkeys, i;
17 double co2;
18 generic_t amaxtb;
19 size_t n_amaxtb;
20
21 // Loop until there is no longer input or the queues are closed
22 while (flag >= 0) {
23
24 // Receive input from input channel
25 // If there is an error, the flag will be negative
26 // Otherwise, it is the size of the received message
27 flag = yggRecv(in_channel, &obj);
28 if (flag < 0) {
29 printf("C Model: No more input.\n");
30 break;
31 }
32
33 // Print received message
34 printf("C Model:\n");
35 display_generic(obj);
36
37 // Print keys
38 nkeys = generic_map_get_keys(obj, &keys);
39 printf("C Model: keys = ");
40 for (i = 0; i < nkeys; i++) {
41 printf("%s ", keys[i]);
42 }
43 printf("\n");
44
45 // Get double precision floating point element
46 co2 = generic_map_get_double(obj, "CO2");
47 printf("C Model: CO2 = %lf\n", co2);
48
49 // Get array element
50 amaxtb = generic_map_get_array(obj, "AMAXTB");
51 n_amaxtb = generic_array_get_1darray_double(amaxtb, 0, &amaxtb_x);
52 generic_array_get_1darray_double(amaxtb, 1, &amaxtb_y);
53 printf("C Model: AMAXTB = \n");
54 for (i = 0; i < n_amaxtb; i++) {
55 printf("\t%lf\t%lf\n", amaxtb_x[i], amaxtb_y[i]);
56 }
57
58 // Send output to output channel
59 // If there is an error, the flag will be negative
60 flag = yggSend(out_channel, obj);
61 if (flag < 0) {
62 printf("C Model: Error sending output.\n");
63 break;
64 }
65
66 // Free dynamically allocated variables for this loop
67 free_generic(&amaxtb);
68
69 }
70
71 // Free dynamically allocated obj structure
72 free_generic(&obj);
73
74 return 0;
75}
76
Model YAML:
1models:
2 - name: c_model
3 language: c
4 args: ./src/wofost.c
5
6connections:
7 - input: ./Input/input.txt # Connection between file and model input
8 output: c_model:input
9 filetype: cabo
10 - input: c_model:output # Connection between model output and file
11 output: ./output.txt
12 filetype: cabo
C++ Version¶
Model Code:
1#include <iostream>
2// Include methods for input/output channels
3#include "YggInterface.hpp"
4
5int main(int argc, char *argv[]) {
6 // Initialize input/output channels
7 YggJSONObjectInput in_channel("input");
8 YggJSONObjectOutput out_channel("output");
9
10 // Declare resulting variables and create buffer for received message
11 int flag = 1;
12 rapidjson::Document obj;
13 rapidjson::CrtAllocator allocator;
14 double* amaxtb_x = NULL;
15 double* amaxtb_y = NULL;
16 char** keys = NULL;
17 size_t nkeys, i;
18 double co2;
19 rapidjson::SizeType n_amaxtb;
20
21 // Loop until there is no longer input or the queues are closed
22 while (flag >= 0) {
23
24 // Receive input from input channel
25 // If there is an error, the flag will be negative
26 // Otherwise, it is the size of the received message
27 flag = in_channel.recv(1, &obj);
28 if (flag < 0) {
29 std::cout << "C++ Model: No more input." << std::endl;
30 break;
31 }
32
33 // Print received message
34 std::cout << "C++ Model:" << std::endl <<
35 document2string(obj) << std::endl;
36
37 // Get double precision floating point element
38 co2 = obj["CO2"].GetDouble();
39 std::cout << "C++ Model: CO2 = " << co2 << std::endl;
40
41 // Get array element
42 const rapidjson::Value& amaxtb = obj["AMAXTB"];
43 amaxtb[0].Get1DArray(amaxtb_x, n_amaxtb, obj.GetAllocator());
44 amaxtb[1].Get1DArray(amaxtb_y, n_amaxtb, obj.GetAllocator());
45 std::cout << "C++ Model: AMAXTB = " << std::endl;
46 for (i = 0; i < n_amaxtb; i++) {
47 std::cout << "\t" << amaxtb_x[i] << "\t" << amaxtb_y[i] << std::endl;
48 }
49
50 // Send output to output channel
51 // If there is an error, the flag will be negative
52 flag = out_channel.send(1, &obj);
53 if (flag < 0) {
54 std::cout << "C++ Model: Error sending output." << std::endl;
55 break;
56 }
57
58 }
59
60 return 0;
61}
Model YAML:
1models:
2 - name: cpp_model
3 language: cpp
4 args: ./src/wofost.cpp
5
6connections:
7 - input: ./Input/input.txt # Connection between file and model input
8 output: cpp_model:input
9 filetype: cabo
10 - input: cpp_model:output # Connection between model output and file
11 output: ./output.txt
12 filetype: cabo
Fortran Version¶
Model Code:
1program main
2 ! Include methods for input/output channels
3 use fygg
4
5 ! Declare resulting variables and create buffer for received message
6 logical :: flag = .true.
7 type(yggcomm) :: in_channel, out_channel
8 type(ygggeneric) :: obj
9 character(len=20), dimension(:), pointer :: keys
10 type(ygggeneric), pointer :: amaxtb
11 real(kind=8), dimension(:), pointer :: amaxtb_x, amaxtb_y
12 real(kind=8), pointer :: co2
13 integer :: i
14 obj = init_generic()
15
16 ! Initialize input/output channels
17 in_channel = ygg_generic_input("input")
18 out_channel = ygg_generic_output("output")
19
20 ! Loop until there is no longer input or the queues are closed
21 do while (flag)
22
23 ! Receive input from input channel
24 ! If there is an error, the flag will be false
25 ! Otherwise, it is the number of variables filled
26 flag = ygg_recv_var(in_channel, yggarg(obj))
27 if (.not.flag) then
28 write (*, '("Fortran Model: No more input.")')
29 exit
30 end if
31
32 ! Print received message
33 write (*, '("Fortran Model:")')
34 call display_generic(obj)
35
36 ! Print keys
37 call generic_map_get_keys(obj, keys)
38 write (*, '("Fortran Model: keys = ")')
39 do i = 1, size(keys)
40 write (*, '(A," ")', advance="no") trim(keys(i))
41 end do
42 write (*, '("")')
43
44 ! Get double precision floating point element
45 call generic_map_get(obj, "CO2", co2)
46 write (*, '("Fortran Model: CO2 = ",F10.5)') co2
47
48 ! Get array element
49 call generic_map_get(obj, "AMAXTB", amaxtb)
50 call generic_array_get(amaxtb, 1, amaxtb_x)
51 call generic_array_get(amaxtb, 2, amaxtb_y)
52 write (*, '("Fortran Model: AMAXTB = ")')
53 do i = 1, size(amaxtb_x)
54 write (*, '(A,F10.5,A,F10.5)') char(11), amaxtb_x(i), &
55 char(11), amaxtb_y(i)
56 end do
57
58 ! Send output to output channel
59 ! If there is an error, the flag will be false
60 flag = ygg_send_var(out_channel, yggarg(obj))
61 if (.not.flag) then
62 write (*, '("Fortran Model: Error sending output.")')
63 exit
64 end if
65
66 end do
67
68end program main
Model YAML:
1models:
2 - name: fortran_model
3 language: fortran
4 args: ./src/wofost.f90
5
6connections:
7 - input: ./Input/input.txt # Connection between file and model input
8 output: fortran_model:input
9 filetype: cabo
10 - input: fortran_model:output # Connection between model output and file
11 output: ./output.txt
12 filetype: cabo
Julia Version¶
Model Code:
1# Import library for input/output
2using Yggdrasil
3using Printf
4
5# Initialize input/output channels
6in_channel = Yggdrasil.YggInterface("YggInput", "input")
7out_channel = Yggdrasil.YggInterface("YggOutput", "output")
8
9# Loop until there is no longer input or the queues are closed
10while(true)
11
12 # Receive input from input channel
13 # If there is an error, the flag will be False
14 flag, obj = in_channel.recv()
15 if (!flag)
16 println("Julia Model: No more input.")
17 break
18 end
19
20 # Print received message
21 @printf("Julia Model: %s\n", obj)
22
23 # Print keys
24 @printf("Julia Model: keys = %s\n", keys(obj))
25
26 # Get floating point element
27 co2 = obj["CO2"]
28 @printf("Julia Model: CO2 = %f\n", co2)
29
30 # Get array element
31 amaxtb = obj["AMAXTB"]
32 println("Julia Model: AMAXTB = ")
33 for i = 1:length(amaxtb[1])
34 @printf("\t%s\t%s\n", amaxtb[1][i], amaxtb[2][i])
35 end
36
37 # Send output to output channel
38 # If there is an error, the flag will be False
39 flag = out_channel.send(obj)
40 if (!flag)
41 error("Julia Model: Error sending output.")
42 end
43
44end
Model YAML:
1models:
2 - name: julia_model
3 language: julia
4 args: ./src/wofost.jl
5
6connections:
7 - input: ./Input/input.txt # Connection between file and model input
8 output: julia_model:input
9 filetype: cabo
10 - input: julia_model:output # Connection between model output and file
11 output: ./output.txt
12 filetype: cabo
Matlab Version¶
Model Code:
1% Initialize input/output channels
2in_channel = YggInterface('YggInput', 'input');
3out_channel = YggInterface('YggOutput', 'output');
4
5flag = true;
6
7% Loop until there is no longer input or the queues are closed
8while flag
9
10 % Receive input from input channel
11 % If there is an error, the flag will be False.
12 [flag, obj] = in_channel.recv();
13 if (~flag)
14 disp('Matlab Model: No more input.');
15 break;
16 end;
17
18 % Print received message
19 fprintf('Matlab Model:');
20 disp(obj);
21
22 % Print keys
23 fprintf('Matlab Model: keys = ');
24 disp(keys(obj));
25
26 % Get floating point element
27 co2 = obj('CO2');
28 fprintf('Matlab Model: CO2 = %f\n', co2);
29
30 % Get array element
31 amaxtb = obj('AMAXTB');
32 fprintf('Matlab Model: AMAXTB = \n');
33 for i = 1:length(amaxtb{1})
34 fprintf('\t%f\t%f\n', amaxtb{1}(i), amaxtb{2}(i));
35 end;
36
37 % Send output to output channel
38 % If there is an error, the flag will be False
39 flag = out_channel.send(obj);
40 if (~flag)
41 error('Matlab Model: Error sending output.');
42 break;
43 end;
44
45end;
Model YAML:
1models:
2 - name: matlab_model
3 language: matlab
4 args: ./src/wofost.m
5
6connections:
7 - input: ./Input/input.txt # Connection between file and model input
8 output: matlab_model:input
9 filetype: cabo
10 - input: matlab_model:output # Connection between model output and file
11 output: ./output.txt
12 filetype: cabo
Python Version¶
Model Code:
1# Import classes for input/output channels
2from yggdrasil.interface.YggInterface import YggInput, YggOutput
3# Import method for printing Unicode on Windows
4from yggdrasil.tools import print_encoded
5
6# Initialize input/output channels
7in_channel = YggInput('input')
8out_channel = YggOutput('output')
9
10# Loop until there is no longer input or the queues are closed
11while True:
12
13 # Receive input from input channel
14 # If there is an error, the flag will be False
15 flag, obj = in_channel.recv()
16 if not flag:
17 print("Python Model: No more input.")
18 break
19
20 # Print received message
21 print_encoded('Python Model: %s' % str(obj))
22
23 # Print keys
24 print('Python Model: keys = %s' % str(obj.keys()))
25
26 # Get floating point element
27 co2 = obj['CO2']
28 print('Python Model: CO2 = %f' % co2)
29
30 # Get array element
31 amaxtb = obj['AMAXTB']
32 print('Python Model: AMAXTB = ')
33 for x, y in zip(*amaxtb):
34 print('\t%f\t%f' % (x, y))
35
36 # Send output to output channel
37 # If there is an error, the flag will be False
38 flag = out_channel.send(obj)
39 if not flag:
40 raise RuntimeError("Python Model: Error sending output.")
Model YAML:
1models:
2 - name: python_model
3 language: python
4 args: ./src/wofost.py
5
6connections:
7 - input: ./Input/input.txt # Connection between file and model input
8 output: python_model:input
9 filetype: cabo
10 - input: python_model:output # Connection between model output and file
11 output: ./output.txt
12 filetype: cabo
R Version¶
Model Code:
1# Import library for input/output
2library(yggdrasil)
3
4# Initialize input/output channels
5in_channel <- YggInterface('YggInput', 'input')
6out_channel <- YggInterface('YggOutput', 'output')
7
8# Loop until there is no longer input or the queues are closed
9while(TRUE) {
10
11 # Receive input from input channel
12 # If there is an error, the flag will be False
13 c(flag, obj) %<-% in_channel$recv()
14 if (!flag) {
15 print('R Model: No more input.')
16 break
17 }
18
19 # Print received message
20 print('R Model:')
21 print(obj)
22
23 # Print keys
24 print('R Model: keys = ')
25 print(names(obj))
26
27 # Get floating point element
28 co2 = obj[["CO2"]]
29 print(sprintf('R Model: CO2 = %f', co2))
30
31 # Get array element
32 amaxtb = obj[["AMAXTB"]]
33 print('R Model: AMAXTB = ')
34 for (i in 1:length(amaxtb[[1]])) {
35 print(sprintf('\t%f\t%f', amaxtb[[1]][[i]], amaxtb[[2]][[i]]))
36 }
37
38 # Send output to output channel
39 # If there is an error, the flag will be False
40 flag = out_channel$send(obj)
41 if (!flag) {
42 stop('R Model: Error sending output.')
43 }
44
45}
Model YAML:
1models:
2 - name: r_model
3 language: r
4 args: ./src/wofost.R
5
6connections:
7 - input: ./Input/input.txt # Connection between file and model input
8 output: r_model:input
9 filetype: cabo
10 - input: r_model:output # Connection between model output and file
11 output: ./output.txt
12 filetype: cabo