timesync1¶
Two models, A & B, run simulations over time and exchange data via a timestep synchronization communication pattern. Both models compute the same variables (x and y) via the same source code and output data at each time step to a file, but they have different time steps.
C Version¶
Model Code:
1#define _USE_MATH_DEFINES // Required to use M_PI with MSVC
2#include <math.h>
3#include <stdio.h>
4#include "YggInterface.h"
5
6
7int timestep_calc(double t, const char* t_units, generic_t state) {
8 double x_period = 10.0; // Days
9 double y_period = 5.0; // Days
10 double x, y;
11 int ret = 0;
12 if (strcmp(t_units, "day") == 0) {
13 // No conversion necessary
14 } else if (strcmp(t_units, "hr") == 0) {
15 x_period = x_period * 24.0;
16 y_period = y_period * 24.0;
17 } else {
18 printf("timestep_calc: Unsupported unit '%s'\n", t_units);
19 ret = -1;
20 }
21 if (ret >= 0) {
22 x = sin(2.0 * M_PI * t / x_period);
23 y = cos(2.0 * M_PI * t / y_period);
24 ret = generic_map_set_double(state, "x", x, "");
25 ret = generic_map_set_double(state, "y", y, "");
26 }
27 return ret;
28}
29
30
31int main(int argc, char *argv[]) {
32
33 double t_step = atof(argv[1]);
34 char* t_units = argv[2];
35 int exit_code = 0;
36 printf("Hello from C timesync: timestep %f %s\n", t_step, t_units);
37 double t_start = 0.0;
38 double t_end = 5.0;
39 if (strcmp(t_units, "hr") == 0) {
40 t_end = 24.0 * t_end;
41 }
42 int ret;
43 generic_t state = init_generic_map();
44 ret = timestep_calc(t_start, t_units, state);
45 if (ret < 0) {
46 printf("timesync(C): Error in initial timestep calculation.");
47 return -1;
48 }
49
50 // Set up connections matching yaml
51 // Timestep synchronization connection will be 'timesync'
52 comm_t* timesync = yggTimesync("timesync", t_units);
53 dtype_t* out_dtype = create_dtype_json_object(0, NULL, NULL, true);
54 comm_t* out = yggOutputType("output", out_dtype);
55
56 // Initialize state and synchronize with other models
57 double t = t_start;
58 ret = rpcCall(timesync, t, state, &state);
59 if (ret < 0) {
60 printf("timesync(C): Initial sync failed.\n");
61 return -1;
62 }
63 printf("timesync(C): t = %5.1f %-3s, x = %+ 5.2f, y = %+ 5.2f\n",
64 t, t_units, generic_map_get_double(state, "x"),
65 generic_map_get_double(state, "y"));
66
67 // Send initial state to output
68 generic_t msg = copy_generic(state);
69 ret = generic_map_set_double(msg, "time", t, t_units);
70 if (ret < 0) {
71 printf("timesync(C): Failed to set time in initial output map.\n");
72 return -1;
73 }
74 ret = yggSend(out, msg);
75 if (ret < 0) {
76 printf("timesync(C): Failed to send initial output for t=%f.\n", t);
77 return -1;
78 }
79 destroy_generic(&msg);
80
81 // Iterate until end
82 while (t < t_end) {
83
84 // Perform calculations to update the state
85 t = t + t_step;
86 ret = timestep_calc(t, t_units, state);
87 if (ret < 0) {
88 printf("timesync(C): Error in timestep calculation for t = %f.\n", t);
89 return -1;
90 }
91
92 // Synchronize the state
93 ret = rpcCall(timesync, t, state, &state);
94 if (ret < 0) {
95 printf("timesync(C): sync for t=%f failed.\n", t);
96 return -1;
97 }
98 printf("timesync(C): t = %5.1f %-3s, x = %+ 5.2f, y = %+ 5.2f\n",
99 t, t_units, generic_map_get_double(state, "x"),
100 generic_map_get_double(state, "y"));
101
102 // Send output
103 msg = copy_generic(state);
104 ret = generic_map_set_double(msg, "time", t, t_units);
105 if (ret < 0) {
106 printf("timesync(C): Failed to set time in output map.\n");
107 return -1;
108 }
109 ret = yggSend(out, msg);
110 if (ret < 0) {
111 printf("timesync(C): Failed to send output for t=%f.\n", t);
112 return -1;
113 }
114 destroy_generic(&msg);
115 }
116
117 printf("Goodbye from C timesync\n");
118 destroy_generic(&state);
119 return 0;
120
121}
Model YAML:
1---
2
3models:
4 - name: modelA
5 language: c
6 args:
7 - ./src/timesync.c
8 - 7 # Pass the timestep in hours
9 - hr
10 timesync: True
11 outputs:
12 name: output
13 default_file:
14 name: modelA_output.txt
15 in_temp: True
16 filetype: table
17 - name: modelB
18 language: c
19 args:
20 - ./src/timesync.c
21 - 1 # Pass the timestep in days
22 - day
23 timesync: True
24 outputs:
25 name: output
26 default_file:
27 name: modelB_output.txt
28 in_temp: True
29 filetype: table
C++ Version¶
Model Code:
1#define _USE_MATH_DEFINES // Required to use M_PI with MSVC
2#include <math.h>
3#include <stdio.h>
4#include "YggInterface.hpp"
5
6
7void timestep_calc(rapidjson::units::Quantity<double>& t,
8 rapidjson::Document& state) {
9 rapidjson::units::Quantity<double> x_period(10.0, "days");
10 rapidjson::units::Quantity<double> y_period(5.0, "days");
11 double x = sin(2.0 * M_PI * (t / x_period).value());
12 double y = cos(2.0 * M_PI * (t / y_period).value());
13#define SET_(key, val) \
14 if (!state.HasMember(key)) \
15 state.AddMember(key, rapidjson::Value(val).Move(), \
16 state.GetAllocator()); \
17 else \
18 state[key].SetDouble(val)
19 SET_("x", x);
20 SET_("y", y);
21}
22
23
24int main(int argc, char *argv[]) {
25
26 char* t_units = argv[2];
27 rapidjson::units::Quantity<double> t_step(atof(argv[1]), t_units);
28 std::cout << "Hello from C++ timesync: timestep " << t_step << std::endl;
29 rapidjson::units::Quantity<double> t_start(0.0, t_units);
30 rapidjson::units::Quantity<double> t_end(5.0, "days");
31 rapidjson::Document state(rapidjson::kObjectType);
32 timestep_calc(t_start, state);
33 int ret = 0;
34
35 // Set up connections matching yaml
36 // Timestep synchronization connection will default to 'timesync'
37 YggTimesync timesync("timesync", t_units);
38 dtype_t* out_dtype = create_dtype_json_object(0, NULL, NULL, true);
39 YggOutput out("output", out_dtype);
40
41 // Initialize state and synchronize with other models
42 rapidjson::units::Quantity<double> t = t_start;
43 ret = timesync.call(3, t.value(), &state, &state);
44 if (ret < 0) {
45 std::cerr << "timesync(C++): Initial sync failed." << std::endl;
46 return -1;
47 }
48 std::cout << "timesync(C++): t = " << t <<
49 ", x = " << state["x"].GetDouble() <<
50 ", y = " << state["x"].GetDouble() << std::endl;
51
52 // Send initial state to output
53 rapidjson::Document msg;
54 msg.CopyFrom(state, msg.GetAllocator());
55 msg.AddMember("time",
56 rapidjson::Value(t, msg.GetAllocator()).Move(),
57 msg.GetAllocator());
58 ret = out.send(1, &msg);
59 if (ret < 0) {
60 std::cerr << "timesync(C++): Failed to send initial output for t=" << t << std::endl;
61 return -1;
62 }
63
64 // Iterate until end
65 while (t < t_end) {
66
67 // Perform calculations to update the state
68 t = t + t_step;
69 timestep_calc(t, state);
70
71 // Synchronize the state
72 ret = timesync.call(3, t.value(), &state, &state);
73 if (ret < 0) {
74 std::cerr << "timesync(C++): sync for t=" << t << " failed" << std::endl;
75 return -1;
76 }
77 std::cout << "timesync(C++): t = " << t <<
78 ", x = " << state["x"].GetDouble() <<
79 ", y = " << state["x"].GetDouble() << std::endl;
80
81 // Send output
82 msg.CopyFrom(state, msg.GetAllocator());
83 msg.AddMember("time",
84 rapidjson::Value(t, msg.GetAllocator()).Move(),
85 msg.GetAllocator());
86 ret = out.send(1, &msg);
87 if (ret < 0) {
88 std::cerr << "timesync(C++): Failed to send output for t=" << t << std::endl;
89 return -1;
90 }
91 }
92
93 std::cout << "Goodbye from C++ timesync" << std::endl;
94 return 0;
95
96}
Model YAML:
1---
2
3models:
4 - name: modelA
5 language: c++
6 args:
7 - ./src/timesync.cpp
8 - 7 # Pass the timestep in hours
9 - hr
10 timesync: True
11 outputs:
12 name: output
13 default_file:
14 name: modelA_output.txt
15 in_temp: True
16 filetype: table
17 - name: modelB
18 language: c++
19 args:
20 - ./src/timesync.cpp
21 - 1 # Pass the timestep in days
22 - day
23 timesync: True
24 outputs:
25 name: output
26 default_file:
27 name: modelB_output.txt
28 in_temp: True
29 filetype: table
Fortran Version¶
Model Code:
1program main
2 use fygg
3
4 ! Declare resulting variables and create buffer for received message
5 logical :: timestep_calc
6 logical :: ret = .true.
7 type(yggcomm) :: timesync, out
8 character(len=32) :: arg
9 character(len=0), dimension(0) :: dtype_keys
10 type(yggdtype), dimension(0) :: dtype_vals
11 type(yggdtype) :: out_dtype
12 real(kind=8) :: t_step, t_start, t_end, t
13 character(len=32) :: t_units
14 type(ygggeneric) :: state, msg
15 real(kind=8), pointer :: x, y
16
17 call get_command_argument(1, arg)
18 read(arg, *) t_step
19 call get_command_argument(2, arg)
20 read(arg, *) t_units
21 write (*, '("Hello from Fortran timesync: timestep ",F10.5," ",A)') &
22 t_step, trim(t_units)
23 t_start = 0.0
24 t_end = 5.0
25 if (t_units.eq."hr") then
26 t_end = 24.0 * t_end
27 end if
28 state = init_generic_map()
29 ret = timestep_calc(t_start, t_units, state)
30 if (.not.ret) then
31 write (*, '("timesync(Fortran): Error in initial timestep &
32 &calculation.")')
33 end if
34
35 ! Set up connections matching yaml
36 ! Timestep synchronization connection will be 'timesync'
37 timesync = ygg_timesync("timesync", t_units)
38 out_dtype = create_dtype_json_object(0, dtype_keys, dtype_vals, .true.)
39 out = ygg_output_type("output", out_dtype)
40
41 ! Initialize state and synchronize with other models
42 t = t_start
43 ret = ygg_rpc_call(timesync, [yggarg(t), yggarg(state)], &
44 yggarg(state))
45 if (.not.ret) then
46 write (*, '("timesync(Fortran): Initial sync failed.")')
47 stop 1
48 end if
49 call generic_map_get(state, "x", x)
50 call generic_map_get(state, "y", y)
51 write (*, '("timesync(Fortran): t = ",F5.1," ",A3,", x = ",&
52 &SP,F5.2,", y = ",F5.2)') t, adjustl(t_units), x, y
53
54 ! Send initial state to output
55 msg = copy_generic(state)
56 call generic_map_set(msg, "time", t, t_units)
57 ret = ygg_send_var(out, yggarg(msg))
58 if (.not.ret) then
59 write (*, '("timesync(Fortran): Failed to send initial output &
60 &for t=",F10.5,".")') t
61 stop 1
62 end if
63 call free_generic(msg)
64
65 ! Iterate until end
66 do while (t.lt.t_end)
67
68 ! Perform calculations to update the state
69 t = t + t_step
70 ret = timestep_calc(t, t_units, state)
71 if (.not.ret) then
72 write (*, '("timesync(Fortran): Error in timestep &
73 &calculation for t = ",F10.5,".")') t
74 stop 1
75 end if
76
77 ! Synchronize the state
78 ret = ygg_rpc_call(timesync, [yggarg(t), yggarg(state)], &
79 yggarg(state))
80 if (.not.ret) then
81 write (*, '("timesync(Fortran): sync failed for t=",F10.5,&
82 &".")') t
83 stop 1
84 end if
85 call generic_map_get(state, "x", x)
86 call generic_map_get(state, "y", y)
87 write (*, '("timesync(Fortran): t = ",F5.1," ",A3,", x = ",&
88 &SP,F5.2,", y = ",F5.2)') t, adjustl(t_units), x, y
89
90 ! Send output
91 msg = copy_generic(state)
92 call generic_map_set(msg, "time", t, t_units)
93 ret = ygg_send_var(out, yggarg(msg))
94 if (.not.ret) then
95 write (*, '("timesync(Fortran): Failed to send output for &
96 &t=",F10.5,".")') t
97 stop 1
98 end if
99 call free_generic(msg)
100
101 end do
102
103 write (*, '("Goodbye from Fortran timesync")')
104 call free_generic(state)
105
106end program main
107
108
109function timestep_calc(t, t_units, state) result (ret)
110 use fygg
111 implicit none
112 real(kind=8) :: t
113 character(len=*) :: t_units
114 type(ygggeneric) :: state
115 logical :: ret
116 real(kind=8) :: x_period = 10.0 ! Days
117 real(kind=8) :: y_period = 10.0 ! Days
118 real(kind=8) :: x, y
119 ret = .true.
120 if (t_units.eq."day") then
121 ! No conversion necessary
122 else if (t_units.eq."hr") then
123 x_period = x_period * 24.0
124 y_period = y_period * 24.0
125 else
126 write (*, '("timestep_calc: Unsupported unit ''",A,"''")') t_units
127 ret = .false.
128 end if
129 if (ret) then
130 x = sin(2.0 * PI_8 * t / x_period)
131 y = cos(2.0 * PI_8 * t / y_period)
132 call generic_map_set(state, "x", x)
133 call generic_map_set(state, "y", y)
134 end if
135end function timestep_calc
Model YAML:
1---
2
3models:
4 - name: modelA
5 language: fortran
6 args:
7 - ./src/timesync.f90
8 - 7 # Pass the timestep in hours
9 - hr
10 timesync: True
11 outputs:
12 name: output
13 default_file:
14 name: modelA_output.txt
15 in_temp: True
16 filetype: table
17 - name: modelB
18 language: fortran
19 args:
20 - ./src/timesync.f90
21 - 1 # Pass the timestep in days
22 - day
23 timesync: True
24 outputs:
25 name: output
26 default_file:
27 name: modelB_output.txt
28 in_temp: True
29 filetype: table
Julia Version¶
Model Code:
1using Yggdrasil
2using Unitful
3using Printf
4
5function timestep_calc(t::Unitful.Quantity)
6 state = Dict("x"=>sin(2.0 * t / Unitful.Quantity(10.0, u"d")),
7 "y"=>cos(2.0 * t / Unitful.Quantity(5.0, u"d")))
8 return state
9end
10
11function main(t_step::Float64, t_units::String)
12
13 @printf("Hello from Julia timesync: timestep = %f %s\n", t_step, t_units)
14 t_step = Unitful.Quantity(t_step, Unitful.uparse(t_units))
15 t_start = Unitful.Quantity(0.0, Unitful.uparse(t_units))
16 t_end = Unitful.Quantity(1.0, u"d")
17 state = timestep_calc(t_start)
18
19 # Set up connections matching yaml
20 # Timestep synchronization connection will default to 'timesync'
21 timesync = Yggdrasil.YggInterface("YggTimesync", "timesync")
22 out = Yggdrasil.YggInterface("YggOutput", "output")
23
24 # Initialize state and synchronize with other models
25 t = t_start
26 ret, state = timesync.call(t, state)
27 if (!ret)
28 error("timesync(Julia): Initial sync failed.")
29 end
30 @printf("timesync(Julia): t = %s, x = %s, y = %s\n", t, state["x"], state["y"])
31
32 # Send initial state to output
33 msg = state
34 msg["time"] = t
35 flag = out.send(msg)
36 if (!flag)
37 error(@sprintf("timesync(Julia): Failed to send initial output for t=%s\n", t))
38 end
39
40 # Iterate until end
41 while (t < t_end)
42
43 # Perform calculations to update the state
44 t = t + t_step
45 state = timestep_calc(t)
46
47 # Synchronize the state
48 ret, state = timesync.call(t, state)
49 if (!ret)
50 error(@sprintf("timesync(Julia): sync for t=%s failed.", t))
51 end
52 @printf("timesync(Julia): t = %s, x = %s, y = %s\n", t, state["x"], state["y"])
53
54 # Send output
55 msg = state
56 msg["time"] = t
57 flag = out.send(msg)
58 if (!flag)
59 error(@sprintf("timesync(Julia): Failed to send output for t=%s.", t))
60 end
61
62 end
63
64 println("Goodbye from Julia timesync")
65
66end
67
68main(parse(Float64, ARGS[1]), ARGS[2])
Model YAML:
1---
2
3models:
4 - name: modelA
5 language: julia
6 args:
7 - ./src/timesync.jl
8 - 7 # Pass the timestep in hours
9 - hr
10 timesync: True
11 outputs:
12 name: output
13 default_file:
14 name: modelA_output.txt
15 in_temp: True
16 filetype: table
17 - name: modelB
18 language: julia
19 args:
20 - ./src/timesync.jl
21 - 1 # Pass the timestep in days
22 - d
23 timesync: True
24 outputs:
25 name: output
26 default_file:
27 name: modelB_output.txt
28 in_temp: True
29 filetype: table
Matlab Version¶
Model Code:
1function timesync(t_step, t_units)
2
3 t_step = str2num(t_step);
4 fprintf('Hello from Matlab timesync: timestep = %f %s\n', t_step, t_units);
5 t_step = t_step * str2symunit(t_units);
6 t_start = 0.0000000000000001 * str2symunit(t_units);
7 t_end = 5.0 * str2symunit('day');
8 state = containers.Map('UniformValues', false, 'ValueType', 'any');
9 state('x') = sin(2.0 * pi * t_start / (10.0 * str2symunit('day')));
10 state('y') = cos(2.0 * pi * t_start / (5.0 * str2symunit('day')));
11
12 % Set up connections matching yaml
13 % Timestep synchonization connection will default to 'timesync'
14 timesync = YggInterface('YggTimesync', 'timesync');
15 out = YggInterface('YggOutput', 'output');
16
17 % Initialize state and synchronize with other models
18 t = t_start;
19 [ret, state] = timesync.call(t, state);
20 if (~ret);
21 error('timesync(Matlab): Initial sync failed.');
22 end;
23 [t_data, t_unit] = separateUnits(t);
24 fprintf('timesync(Matlab): t = %5.1f %-1s, x = %+ 5.2f, y = %+ 5.2f\n', ...
25 t_data, symunit2str(t_unit), state('x'), state('y'));
26
27 % Send initial state to output
28 msg_keys = keys(state);
29 msg_keys{length(msg_keys) + 1} = 'time';
30 msg_vals = values(state);
31 msg_vals{length(msg_vals) + 1} = t;
32 msg = containers.Map(msg_keys, msg_vals, 'UniformValues', false);
33 flag = out.send(msg);
34
35 % Iterate until end
36 while (simplify(t/t_end) < 1)
37
38 % Perform calculations to update the state
39 t = t + t_step;
40 state = containers.Map('UniformValues', false, 'ValueType', 'any');
41 state('x') = sin(2.0 * pi * t / (10.0 * str2symunit('day')));
42 state('y') = cos(2.0 * pi * t / (5.0 * str2symunit('day')));
43
44 % Synchronize the state
45 [ret, state] = timesync.call(t, state);
46 if (~ret);
47 error(sprintf('timesync(Matlab): sync for t=%f failed.\n', t));
48 end;
49 [t_data, t_unit] = separateUnits(t);
50 fprintf('timesync(Matlab): t = %5.1f %-1s, x = %+ 5.2f, y = %+ 5.2f\n', ...
51 t_data, symunit2str(t_unit), state('x'), state('y'));
52
53 % Send output
54 msg_keys = keys(state);
55 msg_keys{length(msg_keys) + 1} = 'time';
56 msg_vals = values(state);
57 msg_vals{length(msg_vals) + 1} = t;
58 msg = containers.Map(msg_keys, msg_vals, 'UniformValues', false);
59 flag = out.send(msg);
60 if (~flag);
61 error(sprintf('timesync(Matlab): Failed to send output for t=%s.\n', t));
62 end;
63 end;
64
65 disp('Goodbye from Matlab timesync');
66
67end
Model YAML:
1---
2
3models:
4 - name: modelA
5 language: matlab
6 args:
7 - ./src/timesync.m
8 - 7 # Pass the timestep in hours
9 - hr
10 timesync: True
11 use_symunit: True
12 outputs:
13 name: output
14 default_file:
15 name: modelA_output.txt
16 in_temp: True
17 filetype: table
18 - name: modelB
19 language: matlab
20 args:
21 - ./src/timesync.m
22 - 1 # Pass the timestep in days
23 - day
24 timesync: True
25 use_symunit: True
26 outputs:
27 name: output
28 default_file:
29 name: modelB_output.txt
30 in_temp: True
31 filetype: table
Python Version¶
Model Code:
1import sys
2import numpy as np
3from yggdrasil import units
4from yggdrasil.interface.YggInterface import (
5 YggTimesync, YggOutput)
6
7
8def timestep_calc(t):
9 r"""Updates the state based on the time where x is a sine wave
10 with period of 10 days and y is a cosine wave with a period of 5 days.
11
12 Args:
13 t (float): Current time.
14
15 Returns:
16 dict: Map of state parameters.
17
18 """
19 state = {
20 'x': np.sin(2.0 * np.pi * t / units.add_units(10, 'day')),
21 'y': np.cos(2.0 * np.pi * t / units.add_units(5, 'day'))}
22 return state
23
24
25def main(t_step, t_units):
26 r"""Function to execute integration.
27
28 Args:
29 t_step (float): The time step that should be used.
30 t_units (str): Units of the time step.
31
32 """
33 print('Hello from Python timesync: timestep = %s %s' % (t_step, t_units))
34 t_step = units.add_units(t_step, t_units)
35 t_start = units.add_units(0.0, t_units)
36 t_end = units.add_units(5.0, 'day')
37 state = timestep_calc(t_start)
38
39 # Set up connections matching yaml
40 # Timestep synchonization connection will default to 'timesync'
41 timesync = YggTimesync('timesync')
42 out = YggOutput('output')
43
44 # Initialize state and synchronize with other models
45 t = t_start
46 ret, state = timesync.call(t, state)
47 if not ret:
48 raise RuntimeError("timesync(Python): Initial sync failed.")
49 print('timesync(Python): t = % 8s, x = %+ 5.2f, y = %+ 5.2f' % (
50 t, state['x'], state['y']))
51
52 # Send initial state to output
53 flag = out.send(dict(state, time=t))
54 if not flag:
55 raise RuntimeError("timesync(Python): Failed to send "
56 "initial output for t=%s." % t)
57
58 # Iterate until end
59 while t < t_end:
60
61 # Perform calculations to update the state
62 t = t + t_step
63 state = timestep_calc(t)
64
65 # Synchronize the state
66 ret, state = timesync.call(t, state)
67 if not ret:
68 raise RuntimeError("timesync(Python): sync for t=%f failed." % t)
69 print('timesync(Python): t = % 8s, x = %+ 5.2f, y = %+ 5.2f' % (
70 t, state['x'], state['y']))
71
72 # Send output
73 flag = out.send(dict(state, time=t))
74 if not flag:
75 raise RuntimeError("timesync(Python): Failed to send output for t=%s." % t)
76
77 print('Goodbye from Python timesync')
78
79
80if __name__ == '__main__':
81 # Take time step from the first argument
82 main(float(sys.argv[1]), sys.argv[2])
Model YAML:
1---
2
3models:
4 - name: modelA
5 language: python
6 args:
7 - ./src/timesync.py
8 - 7 # Pass the timestep in hours
9 - hr
10 timesync: True
11 outputs:
12 name: output
13 default_file:
14 name: modelA_output.txt
15 in_temp: True
16 filetype: table
17 - name: modelB
18 language: python
19 args:
20 - ./src/timesync.py
21 - 1 # Pass the timestep in days
22 - day
23 timesync: True
24 outputs:
25 name: output
26 default_file:
27 name: modelB_output.txt
28 in_temp: True
29 filetype: table
R Version¶
Model Code:
1library(yggdrasil)
2
3
4timestep_calc <- function(t) {
5 state = list(x=sinpi(2.0 * t / units::set_units(10.0, 'day', mode="standard")),
6 y=cospi(2.0 * t / units::set_units(5.0, 'day', mode="standard")))
7 return(state)
8}
9
10main <- function(t_step, t_units) {
11
12 fprintf('Hello from R timesync: timestep = %f %s', t_step, t_units)
13 t_step <- units::set_units(t_step, t_units, mode="standard")
14 t_start <- units::set_units(0.0, t_units, mode="standard")
15 t_end <- units::set_units(5.0, 'day', mode="standard")
16 state <- timestep_calc(t_start)
17
18 # Set up connections matching yaml
19 # Timestep synchronization connection will default to 'timesync'
20 timesync <- YggInterface('YggTimesync', 'timesync')
21 out <- YggInterface('YggOutput', 'output')
22
23 # Initialize state and synchronize with other models
24 t <- t_start
25 c(ret, state) %<-% timesync$call(t, state)
26 if (!ret) {
27 stop('timesync(R): Initial sync failed.')
28 }
29 fprintf('timesync(R): t = %5.1f %-1s, x = %+ 5.2f, y = %+ 5.2f\n',
30 units::drop_units(t), units::deparse_unit(t),
31 state[['x']], state[['y']])
32
33 # Send initial state to output
34 msg = state
35 msg[['time']] = t
36 flag <- out$send(msg)
37 if (!flag) {
38 stop(sprintf('timesync(R): Failed to send initial output for t=%s', t))
39 }
40
41 # Iterate until end
42 while (t < t_end) {
43
44 # Perform calculations to update the state
45 t <- t + t_step
46 state <- timestep_calc(t)
47
48 # Synchronize the state
49 c(ret, state) %<-% timesync$call(t, state)
50 if (!ret) {
51 stop(sprintf('timesync(R): sync for t=%f failed.', t))
52 }
53 fprintf('timesync(R): t = %5.1f %-1s, x = %+ 5.2f, y = %+ 5.2f\n',
54 units::drop_units(t), units::deparse_unit(t),
55 state[['x']], state[['y']])
56
57 # Send output
58 msg = state
59 msg[['time']] = t
60 flag <- out$send(msg)
61 if (!flag) {
62 stop(sprintf('timesync(R): Failed to send output for t=%s.', t))
63 }
64 }
65
66 print('Goodbye from R timesync')
67
68}
69
70
71args = commandArgs(trailingOnly=TRUE)
72main(as.double(args[[1]]), args[[2]])
Model YAML:
1---
2
3models:
4 - name: modelA
5 language: R
6 args:
7 - ./src/timesync.R
8 - 7 # Pass the timestep in hours
9 - hr
10 timesync: True
11 outputs:
12 name: output
13 default_file:
14 name: modelA_output.txt
15 in_temp: True
16 filetype: table
17 - name: modelB
18 language: R
19 args:
20 - ./src/timesync.R
21 - 1 # Pass the timestep in days
22 - day
23 timesync: True
24 outputs:
25 name: output
26 default_file:
27 name: modelB_output.txt
28 in_temp: True
29 filetype: table