diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index a3cc267c2ca82f444097dd946b22d68aa51d4dee..14dbfe7914824c2db7753eef1e45b69a9024b417 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -198,7 +198,7 @@ set(INTERFACE ${ACTORS_DIR}/global/cppwrap_datatypes.f90 ${ACTORS_DIR}/global/cppwrap_metadata.f90) set(FILE_ACCESS_INTERFACE - ${FILE_ACCESS_DIR}/cppwrap_fileAccess.f90 + ${FILE_ACCESS_DIR}/file_access_actor.f90 ${FILE_ACCESS_DIR}/output_structure.f90 ${FILE_ACCESS_DIR}/read_force.f90 ${FILE_ACCESS_DIR}/fileAccess_writeOutput.f90) @@ -227,7 +227,9 @@ set(SUMMA_ACTOR ${ACTORS_DIR}/summa_actor/summa_client.cpp ${ACTORS_DIR}/summa_actor/summa_server.cpp) set(FILE_ACCESS_ACTOR + ${ACTORS_DIR}/file_access_actor/file_access_utils.cpp ${ACTORS_DIR}/file_access_actor/file_access_actor.cpp + ${ACTORS_DIR}/file_access_actor/file_access_init.cpp ${ACTORS_DIR}/file_access_actor/forcing_file_info.cpp ${ACTORS_DIR}/file_access_actor/output_container.cpp) set(JOB_ACTOR diff --git a/build/includes/file_access_actor/file_access_actor.hpp b/build/includes/file_access_actor/file_access_actor.hpp index 32dc0cfed22f0744946ed75ffaba0bf8a4776185..43fd12416d59a15b2e8271a987a7e26908d5da8c 100644 --- a/build/includes/file_access_actor/file_access_actor.hpp +++ b/build/includes/file_access_actor/file_access_actor.hpp @@ -12,6 +12,7 @@ #include "forcing_file_info.hpp" #include "json.hpp" +using namespace caf; /********************************************* * File Access Actor Fortran Functions @@ -41,7 +42,7 @@ extern "C" { * File Access Actor state variables *********************************************/ -namespace caf { + struct file_access_state { // Variables set on Spawn caf::actor parent; @@ -79,6 +80,8 @@ behavior file_access_actor(stateful_actor<file_access_state>* self, NumGRUInfo num_gru_info, File_Access_Actor_Settings file_access_actor_settings, actor parent); + +behavior file_access_init(stateful_actor<file_access_state>* self); /********************************************* * Functions for the file access actor *********************************************/ @@ -87,5 +90,4 @@ behavior file_access_actor(stateful_actor<file_access_state>* self, void writeOutput(stateful_actor<file_access_state>* self, Output_Partition* partition); - -} // end namespace \ No newline at end of file + \ No newline at end of file diff --git a/build/includes/global/message_atoms.hpp b/build/includes/global/message_atoms.hpp index f0854ffc23c6db24b2b54ae092abbb6850344ff6..3c61047f73a5399a37d06132af44dc32ca49b86a 100644 --- a/build/includes/global/message_atoms.hpp +++ b/build/includes/global/message_atoms.hpp @@ -196,6 +196,7 @@ CAF_BEGIN_TYPE_ID_BLOCK(summa, first_custom_type_id) CAF_ADD_ATOM(summa, reinit_hru) CAF_ADD_ATOM(summa, def_output) CAF_ADD_ATOM(summa, load_balance) + CAF_ADD_ATOM(summa, file_access_actor_ready) // Sender: job_actor // Reciever: summa_actor diff --git a/build/source/file_access_actor/file_access_actor.cpp b/build/source/file_access_actor/file_access_actor.cpp index e715bcaab4cf1abc74a82c54ae5e5be2c31cbfe3..8cff4dbac91ded1918452cbeec801aa1f0f0f3ba 100644 --- a/build/source/file_access_actor/file_access_actor.cpp +++ b/build/source/file_access_actor/file_access_actor.cpp @@ -2,10 +2,9 @@ using json = nlohmann::json; -namespace caf { -behavior file_access_actor(stateful_actor<file_access_state>* self, - NumGRUInfo num_gru_info, +behavior file_access_actor( + stateful_actor<file_access_state>* self, NumGRUInfo num_gru_info, File_Access_Actor_Settings file_access_actor_settings, actor parent) { aout(self) << "\n----------File_Access_Actor Started----------\n"; @@ -17,7 +16,6 @@ behavior file_access_actor(stateful_actor<file_access_state>* self, self->state.file_access_actor_settings = file_access_actor_settings; auto& fa_settings = self->state.file_access_actor_settings; self->state.parent = parent; - self->state.num_gru_info = num_gru_info; if (self->state.num_gru_info.use_global_for_data_structures) { @@ -27,62 +25,63 @@ behavior file_access_actor(stateful_actor<file_access_state>* self, self->state.start_gru = self->state.num_gru_info.start_gru_local; self->state.num_gru = self->state.num_gru_info.num_gru_local; } - - self->state.num_output_steps = fa_settings.num_timesteps_in_output_buffer; - int num_hru = self->state.num_gru; - int err = 0; - fileAccessActor_init_fortran(self->state.handle_forcing_file_info, - &self->state.numFiles, &self->state.num_steps, - &fa_settings.num_timesteps_in_output_buffer, self->state.handle_ncid, - &self->state.start_gru, &self->state.num_gru, &num_hru, &err); - if (err != 0) { - aout(self) << "ERROR: File Access Actor - File_Access_init_Fortran\n"; - if (err == 100) - self->send(self->state.parent, file_access_error::mDecisions_error, - self); - else - self->send(self->state.parent, file_access_error::unhandleable_error, - self); - return {}; - } - // Notify job actor that initial files have been loaded - self->send(self->state.parent, init_file_access_actor_v, - self->state.num_steps); + return { + [=](init_file_access_actor, int file_gru) { + auto& fa_settings = self->state.file_access_actor_settings; + int num_hru = self->state.num_gru; + int err = 0; - // Initalize the forcingFile array - self->state.filesLoaded = 0; - for (int i = 1; i <= self->state.numFiles; i++) { - self->state.forcing_file_list.push_back(Forcing_File_Info(i)); - } - - // Ensure output buffer size is less than the number of simulation timesteps - if (self->state.num_steps < fa_settings.num_timesteps_in_output_buffer) { - self->state.num_output_steps = self->state.num_steps; - fa_settings.num_timesteps_in_output_buffer = self->state.num_steps; - } + aout(self) << "File Access Actor: Intializing\n"; + fileAccessActor_init_fortran(self->state.handle_forcing_file_info, + &self->state.numFiles, + &self->state.num_steps, + &fa_settings.num_timesteps_in_output_buffer, + self->state.handle_ncid, + &self->state.start_gru, + &self->state.num_gru, + &num_hru, + &err); + if (err != 0) { + // TODO: Fix Error Handling + return -1; + // aout(self) << "ERROR: File Access Actor - File_Access_init_Fortran\n"; + // if (err == 100) + // self->send(self->state.parent, file_access_error::mDecisions_error, + // self); + // else + // self->send(self->state.parent, file_access_error::unhandleable_error, + // self); + // return -1; + } - // Set up the output container - if (!self->state.num_gru_info.use_global_for_data_structures) { - self->state.output_container = new Output_Container( - fa_settings.num_partitions_in_output_buffer, self->state.num_gru, - fa_settings.num_timesteps_in_output_buffer, self->state.num_steps); - } + // Initalize the forcingFile array + self->state.filesLoaded = 0; + for (int i = 1; i <= self->state.numFiles; i++) { + self->state.forcing_file_list.push_back(Forcing_File_Info(i)); + } + + // Ensure output buffer size is less than the number of simulation timesteps + if (self->state.num_steps < fa_settings.num_timesteps_in_output_buffer) { + self->state.num_output_steps = self->state.num_steps; + fa_settings.num_timesteps_in_output_buffer = self->state.num_steps; + } - self->state.file_access_timing.updateEndPoint("init_duration"); + // Set up the output container + if (!self->state.num_gru_info.use_global_for_data_structures) { + self->state.output_container = new Output_Container( + fa_settings.num_partitions_in_output_buffer, self->state.num_gru, + fa_settings.num_timesteps_in_output_buffer, self->state.num_steps); + } - return { - [=](def_output, int file_gru) { aout(self) << "Creating Output File\n"; std::string actor_address = ""; - int num_hru = self->state.num_gru; if (self->state.num_gru_info.use_global_for_data_structures) { actor_address = "_" + to_string(self->address()); } - int err = 0; defOutputFortran(self->state.handle_ncid, &self->state.start_gru, &self->state.num_gru, &num_hru, &file_gru, &self->state.num_gru_info.use_global_for_data_structures, @@ -91,8 +90,14 @@ behavior file_access_actor(stateful_actor<file_access_state>* self, aout(self) << "ERROR: Defining Output\n"; self->quit(); } + + self->state.file_access_timing.updateEndPoint("init_duration"); + return self->state.num_steps; }, + + + // Message from the HRU actor to get the forcing file that is loaded [=](access_forcing, int currentFile, caf::actor refToRespondTo) { if (currentFile <= self->state.numFiles) { @@ -256,5 +261,3 @@ void writeOutput(stateful_actor<file_access_state>* self, partition->resetReadyToWriteList(); } - -} // end namespace \ No newline at end of file diff --git a/build/source/file_access_actor/cppwrap_fileAccess.f90 b/build/source/file_access_actor/file_access_actor.f90 similarity index 99% rename from build/source/file_access_actor/cppwrap_fileAccess.f90 rename to build/source/file_access_actor/file_access_actor.f90 index 50b4b689398e7f7ed670ad967135a370adbbc9fe..b36a524f7ee30ec7ac706be9e7a6a39990f533e9 100644 --- a/build/source/file_access_actor/cppwrap_fileAccess.f90 +++ b/build/source/file_access_actor/file_access_actor.f90 @@ -1,4 +1,4 @@ -module cppwrap_fileAccess +module file_access_actor !======= Inclusions =========== @@ -748,4 +748,4 @@ SUBROUTINE SOIL_VEG_GEN_PARM(FILENAME_VEGTABLE, FILENAME_SOILTABLE, FILENAME_GEN END SUBROUTINE SOIL_VEG_GEN_PARM -end module cppwrap_fileAccess +end module file_access_actor diff --git a/build/source/file_access_actor/file_access_init.cpp b/build/source/file_access_actor/file_access_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a07853ef6b30aee0758ba6c971939e543dee1acb --- /dev/null +++ b/build/source/file_access_actor/file_access_init.cpp @@ -0,0 +1,8 @@ +#include "file_access_actor.hpp" + + +behavior file_access_init(stateful_actor<file_access_state>* self) { + aout(self) << "File Access Actor: Intializing\n"; + + return {}; +} \ No newline at end of file diff --git a/build/source/file_access_actor/file_access_utils.cpp b/build/source/file_access_actor/file_access_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f5b5059bbdc618618ccebb5d85e5f1761a66f814 --- /dev/null +++ b/build/source/file_access_actor/file_access_utils.cpp @@ -0,0 +1,18 @@ +#include <string> +#include <vector> + +/** + * Same file_info from data_types.f90 + * This is a C++ Representation of the file_info data type +*/ +class fileInfo { + private: + std::string filenmData; // name of data file + int nVars; // number of variables in file + int nTimeSteps; // number of time steps in file + std::vector<int> var_ix; // index of each forcing data variable in the data structure + std::vector<int> data_id; // netcdf variable id for each forcing data variable + std::vector<int> varName; // netcdf variable name for each forcing data variable + double firstJulDay; // first julian day in forcing file + double convTime2Days; // conversion factor to convert time units to days +}; \ No newline at end of file diff --git a/build/source/hru_actor/hru_actor.cpp b/build/source/hru_actor/hru_actor.cpp index 37bd152084cf409db21d6c12c656e664f73f6ae8..d4839ec8baf045d568760530d324ae74817196e4 100644 --- a/build/source/hru_actor/hru_actor.cpp +++ b/build/source/hru_actor/hru_actor.cpp @@ -1,6 +1,6 @@ #include "hru_actor.hpp" -bool hru_extra_logging = false; +bool hru_extra_logging = true; namespace caf { diff --git a/build/source/job_actor/async_mode.cpp b/build/source/job_actor/async_mode.cpp index e16ddb1b52df4786e7998ba32e57a032546b6f3c..18c39f1e96f45c23b576caebc1b8d560a86ae9c5 100644 --- a/build/source/job_actor/async_mode.cpp +++ b/build/source/job_actor/async_mode.cpp @@ -6,7 +6,7 @@ behavior async_mode(stateful_actor<job_state>* self) { return { /*** From file access actor after it spawns ***/ - [=](init_file_access_actor, int num_timesteps) { + [=](file_access_actor_ready, int num_timesteps) { aout(self) << "Async Mode: init_file_access_actor\n"; self->state.num_steps = num_timesteps; spawnHRUActors(self); diff --git a/build/source/job_actor/data_assimilation_mode.cpp b/build/source/job_actor/data_assimilation_mode.cpp index 3e12870d1bc34d56f97daecd742cae91b9c4b581..f36af0d23c894d11f9fc982740a2b87fb61bfafe 100644 --- a/build/source/job_actor/data_assimilation_mode.cpp +++ b/build/source/job_actor/data_assimilation_mode.cpp @@ -5,7 +5,7 @@ behavior data_assimilation_mode(stateful_actor<job_state>* self) { aout(self) << "Data Assimilation Mode: Started\n"; return { - [=](init_file_access_actor, int num_timesteps) { + [=](file_access_actor_ready, int num_timesteps) { aout(self) << "Data Assimilation Mode: init_file_access_actor\n"; self->state.num_steps = num_timesteps; self->state.job_actor_settings.batch_size > 0 ? diff --git a/build/source/job_actor/job_actor.cpp b/build/source/job_actor/job_actor.cpp index 19f70cf8d21e172712cda807f71075cb03d1df5e..82e67e978954dbd28be6db56f27dc312046de9ca 100644 --- a/build/source/job_actor/job_actor.cpp +++ b/build/source/job_actor/job_actor.cpp @@ -60,22 +60,43 @@ behavior job_actor(stateful_actor<job_state>* self, self->state.start_gru, self->state.num_gru, self->state.num_gru, file_gru, false); + // Spawn File Access Actor and await confirmation it is ready self->state.file_access_actor = self->spawn(file_access_actor, self->state.num_gru_info, self->state.file_access_actor_settings, self); - self->send(self->state.file_access_actor, def_output_v, file_gru); + // self->send(self->state.file_access_actor, def_output_v, file_gru); + self->request(self->state.file_access_actor, caf::infinite, + init_file_access_actor_v, file_gru).await( + [=](int num_timesteps){ + + if (num_timesteps < 0) { + aout(self) << "ERROR: Job_Actor: File Access Actor Not Ready\n"; + self->quit(); + return; + } - self->state.job_timing.updateEndPoint("init_duration"); - aout(self) << "Job Actor Initialized \n"; + aout(self) << "Job_Actor: File Access Actor Ready\n"; + self->state.job_timing.updateEndPoint("init_duration"); + aout(self) << "Job Actor Initialized \n"; - if (job_actor_settings.data_assimilation_mode) { - self->become(data_assimilation_mode(self)); - return {}; - } else { - self->become(async_mode(self)); - return {}; - } + job_actor_settings.data_assimilation_mode ? + self->become(data_assimilation_mode(self)) : + self->become(async_mode(self)); + + // Start the specific mode + self->send(self, file_access_actor_ready_v, num_timesteps); + }); + + /** + * TODO: This is where the error handling code can go + * We can add a timeout to the receive and if we do not receive it in + * Time then we have to handle that error here + */ + + + return {}; + return { diff --git a/utils/C_Data_Struct/Makefile b/utils/C_Data_Struct/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..70528767e2360913dc0f0857fc73ea3f90736236 --- /dev/null +++ b/utils/C_Data_Struct/Makefile @@ -0,0 +1,27 @@ +# Makefile + +# Compiler +CXX = g++ + +# Compiler flags +CXXFLAGS = -Wall -std=c++11 + +# Target executable name +TARGET = data_types + +# Source files +SRCS = data_types.cpp + +# Object files +OBJS = $(SRCS:.cpp=.o) + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) + +.cpp.o: + $(CXX) $(CXXFLAGS) -c $< -o $@ + +clean: + $(RM) $(OBJS) $(TARGET) \ No newline at end of file diff --git a/utils/C_Data_Struct/data_types.cpp b/utils/C_Data_Struct/data_types.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10a6fb2e1a68a7305c095508713df88541bdb357 --- /dev/null +++ b/utils/C_Data_Struct/data_types.cpp @@ -0,0 +1,19 @@ +#include <string> +#include <vector> + +/** + * Same file_info from data_types.f90 + * This is a C++ Representation of the file_info data type +*/ +class fileInfo { + + private: + std::string filenmData; // name of data file + int nVars; // number of variables in file + int nTimeSteps; // number of time steps in file + std::vector<int> var_ix; // index of each forcing data variable in the data structure + std::vector<int> data_id; // netcdf variable id for each forcing data variable + std::vector<int> varName; // netcdf variable name for each forcing data variable + double firstJulDay; // first julian day in forcing file + double convTime2Days; // conversion factor to convert time units to days +}; \ No newline at end of file diff --git a/utils/C_Data_Struct/data_types.o b/utils/C_Data_Struct/data_types.o new file mode 100644 index 0000000000000000000000000000000000000000..4ac463be19539d757bab7ae3f4d1604b72411b05 Binary files /dev/null and b/utils/C_Data_Struct/data_types.o differ