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