diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt
index a3cc267c2ca82f444097dd946b22d68aa51d4dee..00d0e9add17356c6dda8c921b5a397031fd814ec 100644
--- a/build/CMakeLists.txt
+++ b/build/CMakeLists.txt
@@ -77,7 +77,8 @@ set(NETCDF_DIR ${F_MASTER}/build/source/netcdf)
 set(NOAHMP_DIR ${F_MASTER}/build/source/noah-mp)
 
 # Define Actors specific directories
-set(ACTORS_DIR ${PARENT_DIR}/build/source)
+set(ACTORS_DIR      ${PARENT_DIR}/build/source)
+set(SYS_INIT_DIR    ${ACTORS_DIR}/system_initialization)
 set(FILE_ACCESS_DIR ${ACTORS_DIR}/file_access_actor)
 set(JOB_ACTOR_DIR   ${ACTORS_DIR}/job_actor)
 set(HRU_ACTOR_DIR   ${ACTORS_DIR}/hru_actor)
@@ -140,7 +141,7 @@ set(PRELIM
     ${ENGINE_DIR}/childStruc.f90
     ${ENGINE_DIR}/conv_funcs.f90
     ${ENGINE_DIR}/convE2Temp.f90
-    ${FILE_ACCESS_DIR}/ffile_info.f90
+    ${ENGINE_DIR}/ffile_info.f90
     ${ENGINE_DIR}/read_pinit.f90
     ${ENGINE_DIR}/read_attrb.f90
     ${ENGINE_DIR}/paramCheck.f90
@@ -188,6 +189,9 @@ set(SOLVER
     ${ENGINE_DIR}/vegSWavRad.f90)
 
 set(DRIVER
+    ${DRIVER_DIR}/summa_type.f90
+    ${DRIVER_DIR}/summa_setup.f90
+    ${DRIVER_DIR}/summa_restart.f90
     ${DRIVER_DIR}/summa_alarms.f90
     ${DRIVER_DIR}/summa_globalData.f90)
 
@@ -196,14 +200,18 @@ set(DRIVER
 set(INTERFACE
     ${ACTORS_DIR}/global/cppwrap_auxiliary.f90
     ${ACTORS_DIR}/global/cppwrap_datatypes.f90
-    ${ACTORS_DIR}/global/cppwrap_metadata.f90)
+    ${ACTORS_DIR}/global/cppwrap_metadata.f90
+    ${ACTORS_DIR}/global/c_interface_module.f90)
+set(SYS_INIT_INTERFACE
+    ${SYS_INIT_DIR}/batch_distributer_actor.f90)
 set(FILE_ACCESS_INTERFACE
-    ${FILE_ACCESS_DIR}/cppwrap_fileAccess.f90
+    ${FILE_ACCESS_DIR}/summa_init_struc.f90
+    ${FILE_ACCESS_DIR}/forcing_file_info.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)
 set(JOB_INTERFACE
-    ${JOB_ACTOR_DIR}/job_actor.f90)
+    ${JOB_ACTOR_DIR}/gru_struc.f90)
 set(HRU_INTERFACE
     ${HRU_ACTOR_DIR}/hru_init.f90
     ${HRU_ACTOR_DIR}/hru_read.f90
@@ -214,33 +222,38 @@ set(HRU_INTERFACE
 set(ACTORS_GLOBAL
     ${ACTORS_DIR}/global/auxiliary.cpp
     ${ACTORS_DIR}/global/global.cpp
+    ${ACTORS_DIR}/global/fileManager.cpp
     ${ACTORS_DIR}/global/message_atoms.cpp
     ${ACTORS_DIR}/global/settings_functions.cpp
     ${ACTORS_DIR}/global/timing_info.cpp)
-set(SUMMA_ACTOR
-    ${ACTORS_DIR}/summa_actor/batch.cpp
-    ${ACTORS_DIR}/summa_actor/batch_container.cpp
-    ${ACTORS_DIR}/summa_actor/client.cpp
-    ${ACTORS_DIR}/summa_actor/client_container.cpp
-    ${ACTORS_DIR}/summa_actor/summa_actor.cpp
-    ${ACTORS_DIR}/summa_actor/summa_backup_server.cpp
-    ${ACTORS_DIR}/summa_actor/summa_client.cpp
-    ${ACTORS_DIR}/summa_actor/summa_server.cpp)
+set(SYS_INIT
+    ${SYS_INIT_DIR}/batch.cpp
+    ${SYS_INIT_DIR}/batch_container.cpp
+    ${SYS_INIT_DIR}/client.cpp
+    ${SYS_INIT_DIR}/client_container.cpp
+    ${SYS_INIT_DIR}/summa_global_data.cpp
+    ${SYS_INIT_DIR}/summa_actor.cpp
+    ${SYS_INIT_DIR}/summa_backup_server.cpp
+    ${SYS_INIT_DIR}/summa_client.cpp
+    ${SYS_INIT_DIR}/summa_server.cpp)
 set(FILE_ACCESS_ACTOR
-    ${ACTORS_DIR}/file_access_actor/file_access_actor.cpp
-    ${ACTORS_DIR}/file_access_actor/forcing_file_info.cpp
-    ${ACTORS_DIR}/file_access_actor/output_container.cpp)
+    ${FILE_ACCESS_DIR}/summa_init_struc.cpp
+    ${FILE_ACCESS_DIR}/file_access_actor.cpp
+    ${FILE_ACCESS_DIR}/forcing_file_info.cpp
+    ${FILE_ACCESS_DIR}/output_container.cpp)
 set(JOB_ACTOR
-    ${ACTORS_DIR}/job_actor/GRU.cpp
-    ${ACTORS_DIR}/job_actor/job_actor.cpp
-    ${ACTORS_DIR}/job_actor/async_mode.cpp
-    ${ACTORS_DIR}/job_actor/data_assimilation_mode.cpp
-    ${ACTORS_DIR}/job_actor/job_utils.cpp
-    ${ACTORS_DIR}/job_actor/distributed_job_actor.cpp
-    ${ACTORS_DIR}/job_actor/node_actor.cpp)
+    ${JOB_ACTOR_DIR}/GRU.cpp
+    ${JOB_ACTOR_DIR}/gru_struc.cpp
+    ${JOB_ACTOR_DIR}/job_actor.cpp
+    ${JOB_ACTOR_DIR}/async_mode.cpp
+    ${JOB_ACTOR_DIR}/data_assimilation_mode.cpp
+    ${JOB_ACTOR_DIR}/job_utils.cpp
+    ${JOB_ACTOR_DIR}/distributed_job_actor.cpp
+    ${JOB_ACTOR_DIR}/node_actor.cpp)
 set(HRU_ACTOR
-    ${ACTORS_DIR}/hru_actor/hru_actor.cpp
-    ${ACTORS_DIR}/hru_actor/hru_batch_actor.cpp)
+    ${HRU_ACTOR_DIR}/hru_utils.cpp
+    ${HRU_ACTOR_DIR}/hru_actor.cpp
+    ${HRU_ACTOR_DIR}/hru_batch_actor.cpp)
     
 
 #=========================================================================================
@@ -262,6 +275,7 @@ set(SUMMA_ALL
 
 set(SUMMA_ALL 
     ${SUMMA_ALL}
+    ${SYS_INIT_INTERFACE}
     ${FILE_ACCESS_INTERFACE}
     ${JOB_INTERFACE}
     ${HRU_INTERFACE})
@@ -305,7 +319,7 @@ add_executable(${EXEC_NAME}
                ${FILE_ACCESS_ACTOR}
                ${JOB_ACTOR}
                ${HRU_ACTOR}
-               ${SUMMA_ACTOR}
+               ${SYS_INIT}
                ${SUMMA_CLIENT}
                ${SUMMA_SERVER})
 set_property(TARGET ${EXEC_NAME} PROPERTY LINKER_LANGUAGE Fortran)
diff --git a/build/build_scripts/build_v4_local.sh b/build/build_scripts/build_v4_local.sh
index a3f990e6249a53118febf3233507cd82839f2c1b..8024e64ceacd90560134838302deb43b1198fa4d 100755
--- a/build/build_scripts/build_v4_local.sh
+++ b/build/build_scripts/build_v4_local.sh
@@ -11,5 +11,5 @@ export LIBRARY_LINKS='-llapack;-lgfortran;-lnetcdff;-lnetcdf' # list of library
 export SUNDIALS_PATH="/usr/local/sundials"
 export ACTOR_FRAMEWORK_PATH="/usr/local"
 
-cmake -B ./cmake_build -S ../summa/build/cmake/. -DCMAKE_BUILD_TYPE=Sundials_Actors
-cmake --build ./cmake_build --target all
+cmake -B ./cmake_build -S ../summa/build/cmake/. -DCMAKE_BUILD_TYPE=Sundials_Actors_Debug
+cmake --build ./cmake_build --target all -j
diff --git a/build/includes/file_access_actor/file_access_actor.hpp b/build/includes/file_access_actor/file_access_actor.hpp
index 068d1e5f9a4d34c12c18fce47e343d042eb33cdc..95b259728e8486751d9349dcbcaba4b064a484cc 100644
--- a/build/includes/file_access_actor/file_access_actor.hpp
+++ b/build/includes/file_access_actor/file_access_actor.hpp
@@ -1,8 +1,6 @@
 #pragma once
 
 #include "caf/actor.hpp"
-#include "forcing_file_info.hpp"
-#include "timing_info.hpp"
 #include "output_container.hpp"
 #include "settings_functions.hpp"
 #include "fortran_data_types.hpp"
@@ -11,56 +9,43 @@
 #include "message_atoms.hpp"
 #include "forcing_file_info.hpp"
 #include "json.hpp"
-
+// #include "summa_init_struc.hpp"
 
 /*********************************************
  * File Access Actor Fortran Functions
  *********************************************/
 extern "C" {
-  void defOutputFortran(void* handle_ncid, int* start_gru, int* num_gru, 
-      int* num_hru, int* file_gru, bool* use_extention, 
-      char const* output_extention, int* err); 
+  void fileAccessActor_init_fortran(int* num_timesteps, 
+                                    int* num_timesteps_output_buffer, 
+                                    int* numGRU, int* err, void* message);
 
-  void fileAccessActor_init_fortran(void* handle_forcing_file_info, 
-      int* num_forcing_files, int* num_timesteps, 
-      int* num_timesteps_output_buffer, void* handle_output_ncid, int* startGRU,
-      int* numGRU, int* numHRU, int* err);
+  void defOutputFortran(void* handle_ncid, int* start_gru, int* num_gru, 
+                        int* num_hru, int* file_gru, bool* use_extention, 
+                        char const* output_extention, int* err); 
 
   void writeOutput_fortran(void* handle_ncid, int* num_steps, int* start_gru, 
-      int* max_gru, bool* writeParamFlag, int* err);
+                          int* max_gru, bool* writeParamFlag, int* err);
 
-  void writeRestart_fortran(void* handle_ncid, int* start_gru, int* max_gru, int* timestep, 
-      int* year, int* month, int* day, int* hour, int* err); 
-
-  void read_forcingFile(void* forcFileInfo, int* currentFile, int* stepsInFile,
-      int* startGRU, int* numGRU, int* err);
-
-  void FileAccessActor_DeallocateStructures(void* handle_forcFileInfo, 
-      void* handle_ncid);
+  void writeRestart_fortran(void* handle_ncid, int* start_gru, int* max_gru, 
+                            int* timestep, int* year, int* month, int* day, 
+                            int* hour, int* err); 
 
+  void FileAccessActor_DeallocateStructures(void* handle_ncid);
 }
 
 /*********************************************
  * File Access Actor state variables
  *********************************************/
-
-namespace caf {
 struct file_access_state {
-  // Variables set on Spawn
+  TimingInfo file_access_timing;
   caf::actor parent; 
   int start_gru;
   int num_gru;
 
   NumGRUInfo num_gru_info;
 
-
-  void *handle_forcing_file_info = new_handle_file_info(); // Handle for the forcing file information
-  void *handle_ncid = new_handle_var_i();                  // output file ids
-  int num_vectors_in_output_manager;
+  void *handle_ncid = new_handle_var_i();  // output file ids
   int num_steps;
-  int stepsInCurrentFile;
-  int numFiles;
-  int filesLoaded;
   int num_output_steps;
   int err = 0; // this is to make compiler happy
 
@@ -68,12 +53,8 @@ struct file_access_state {
 
   File_Access_Actor_Settings file_access_actor_settings;
 
-  std::vector<Forcing_File_Info> forcing_file_list; // list of steps in file
-
-    // Timing Variables
-  TimingInfo file_access_timing;
-
-
+  // std::unique_ptr<SummaInitStruc> summa_init_struc;
+  std::unique_ptr<forcingFileContainer> forcing_files;
 
   bool write_params_flag = true;
 
@@ -85,20 +66,21 @@ struct file_access_state {
 };
 
 // called to spawn a file_access_actor
-behavior file_access_actor(stateful_actor<file_access_state>* self, 
-    NumGRUInfo num_gru_info,
-    File_Access_Actor_Settings file_access_actor_settings, actor parent);
+caf::behavior file_access_actor(caf::stateful_actor<file_access_state>* self, 
+                                NumGRUInfo num_gru_info,
+                                File_Access_Actor_Settings file_access_actor_settings, 
+                                caf::actor parent);
+
 
 /*********************************************
  * Functions for the file access actor
  *********************************************/
-
 /* Setup and call the fortran routine that writes the output */
-void writeOutput(stateful_actor<file_access_state>* self, 
-    Output_Partition* partition);
+void writeOutput(caf::stateful_actor<file_access_state>* self, 
+                 Output_Partition* partition);
 
-void writeRestart(stateful_actor<file_access_state>* self, Output_Partition* partition, 
-    int start_gru, int num_gru, int timestep, int year, int month, int day, int hour);
+void writeRestart(caf::stateful_actor<file_access_state>* self, 
+                  Output_Partition* partition, int start_gru, int num_gru, 
+                  int timestep, int year, int month, int day, int hour);
 
  
-} // end namespace
\ No newline at end of file
diff --git a/build/includes/file_access_actor/forcing_file_info.hpp b/build/includes/file_access_actor/forcing_file_info.hpp
index 3a3ef8c2f2c8565e8f895b9caea2648dfbfe8115..bab7d4f5d597eb90b982e84950990f92c841e457 100644
--- a/build/includes/file_access_actor/forcing_file_info.hpp
+++ b/build/includes/file_access_actor/forcing_file_info.hpp
@@ -1,31 +1,78 @@
 #pragma once
 
+#include <string>
 #include <vector>
+#include <iostream>
+#include "timing_info.hpp"
 
+extern "C" {
+  // Create the fortran ffile_info and return the number of forcing_files
+  void getNumFrocingFiles_fortran(int& num_forcing_files);
+  // Creation and population of Fortran structures
+  void getFileInfoSizes_fortran(int& iFile, int& var_ix_size, int& data_id_size, 
+      int& varName_size);
+  void getFileInfoCopy_fortran(int& iFile, void* file_name, int& nVars, 
+      int& nTimeSteps, int& var_name_size, int& var_ix_size, int& data_id_size, 
+      void* var_name_arr, void* var_ix_arr, void* data_id_arr, 
+      double& firstJulDay, double& convTime2Days);
 
-class Forcing_File_Info {
-    private:
-        int file_ID;
-        int num_steps;
-        bool is_loaded;
-    
-    public:
-        Forcing_File_Info(int file_ID);
+  // File Loading
+  void read_forcingFile(int& iFile, int& start_gru, int& num_gru, 
+      int& err, void* message);
 
-        int getNumSteps();
+  // Deallocate Fortran Structures associate with forcing files
+  void freeForcingFiles_fortran();
+}
 
-        bool isFileLoaded();
+/**
+ * Same file_info from data_types.f90 
+ * This is a C++ Representation of the file_info data type
+*/
+class fileInfo {
+  public:
+    /** Fortran Replication Part **/
+    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<std::string> 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
+    /** Fortran Replication Part **/
 
-        void updateIsLoaded();
-
-        void updateNumSteps(int num_steps);
+    /** C++ Part **/
+    bool is_loaded = false;
 
+    fileInfo(); 
 };
 
-struct Forcing_Info {
-    int num_vars;
-    int num_timesteps;
-    std::vector<int> index_forc_var;
-    std::vector<int> ncid_var;
+class forcingFileContainer {
+  public:
+    std::vector<fileInfo> forcing_files_;
+    forcingFileContainer();
+    ~forcingFileContainer();
+
+    int initForcingFiles();
+
+    int loadForcingFile(int file_ID, int start_gru, int num_gru);
+    bool isFileLoaded(int file_ID);
+    inline bool allFilesLoaded() { 
+      return files_loaded_ == forcing_files_.size(); 
+    }
+    inline int getNumSteps(int iFile) {
+      return forcing_files_[iFile-1].nTimeSteps;
+    }
 
-};
\ No newline at end of file
+    inline double getInitDuration() {
+      return file_access_timing_.getDuration("init_duration").value_or(-1.0);
+    }
+
+    inline double getReadDuration() {
+      return file_access_timing_.getDuration("read_duration").value_or(-1.0);
+    }
+
+  private:
+    int files_loaded_ = 0;
+    TimingInfo file_access_timing_ = TimingInfo();
+};
diff --git a/build/includes/file_access_actor/summa_init_struc.hpp b/build/includes/file_access_actor/summa_init_struc.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..2303cb0e54c23aa706cf060418e4158b3df3c9c7
--- /dev/null
+++ b/build/includes/file_access_actor/summa_init_struc.hpp
@@ -0,0 +1,24 @@
+#define SUMMA_INIT_STRUC
+#ifdef SUMMA_INIT_STRUC
+#include "settings_functions.hpp"
+extern "C" {
+  void initialize_init_struc(int& num_gru, int& err, void* message);
+  void paramSetup_fortran(int& err, void* message);
+  void readRestart_fortran(int& err, void* message);
+  void getInitTolerance_fortran(double& rtol, double& atol);
+  void deallocate_init_struc();
+}
+
+class SummaInitStruc {
+  public:
+    SummaInitStruc();
+    ~SummaInitStruc();
+
+    int allocate(int num_gru); // allocate space in Fortran
+    int summa_paramSetup();    // call summa_paramSetup
+    int summa_readRestart();   // call summa_readRestart
+    void getInitTolerance(HRU_Actor_Settings& hru_settings); 
+};
+
+
+#endif
diff --git a/build/includes/global/fileManager.hpp b/build/includes/global/fileManager.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..4b26ab03073d7d5a39eca50d4a5ecffe34c103ea
--- /dev/null
+++ b/build/includes/global/fileManager.hpp
@@ -0,0 +1,44 @@
+#include <string>
+
+extern "C" {
+  void setTimesDirsAndFiles_fortran(char const* file_manager_path,  
+        int* err, void* err_msg);
+}
+
+class fileManager {
+
+  public:
+    std::string file_manager_path_; // path to the file manager file
+    // defines the time of the run
+    std::string control_vrs_;       // control version
+    std::string sim_start_tm_;      // simulation start time
+    std::string sim_end_tm_;        // simulation end time
+    std::string nc_time_zone_;      // time zone info
+    // defines the path for data files (and default values)
+    std::string settings_path_;     // settings dir path
+    std::string state_path_;        // state file / init. cond. dir path (if omitted, defaults to SETTINGS_PATH for input, OUTPATH for output)
+    std::string forcing_path_;      // input_dir_path
+    std::string output_path_;       // output_dir_path
+    // define name of control files (and default values)
+    std::string m_decisions_;       // definition of model decisions
+    std::string output_control_;    // metadata for model variables
+    std::string local_attributes_;  // local attributes
+    std::string localparam_info_;   // default values and constraints for local model parameters
+    std::string basinparam_info_;   // default values and constraints for basin model parameters
+    std::string vegparm_;           // noah vegetation parameter table
+    std::string soilparm_;          // noah soil parameter table
+    std::string genparm_;           // noah general parameter table
+    std::string mptable_;           // noah mp parameter table
+    std::string forcing_filelist_;  // list of focing files for each HRU
+    std::string model_initcond_;    // model initial conditions
+    std::string parameter_trial_;   // trial values for model parameters
+    std::string output_prefix_;     // prefix for the output file
+  
+    // Constructor - read file_manager_path & populate class variables
+    fileManager(const std::string& file_manager_path);
+    ~fileManager() {};
+
+    // Set the variables that are used by the summaFileManager (summaFileManager.f90)
+    std::string setTimesDirsAndFiles();
+    std::string toString();
+};
\ No newline at end of file
diff --git a/build/includes/global/message_atoms.hpp b/build/includes/global/message_atoms.hpp
index d08ce36f8b4692342454f2fd33fc3e7d518537d4..60c85c0721c939b5073669b9097242ca2ca052a0 100644
--- a/build/includes/global/message_atoms.hpp
+++ b/build/includes/global/message_atoms.hpp
@@ -1,162 +1,21 @@
 #pragma once
+#include "caf/all.hpp"
 
 #include "batch.hpp"
 #include "batch_container.hpp"
+
 #include "client.hpp"
 #include "client_container.hpp"
-#include <vector>
+
+#include "hru_utils.hpp"
+#include "num_gru_info.hpp"
 #include "settings_functions.hpp"
 #include "global.hpp"
-#include "caf/all.hpp"
+
+#include <vector>
 #include <unordered_map>
 
 // HRU Data structure used for serialization
-struct hru {
-  int indx_hru;
-  int indx_gru;
-  int ref_gru;
-
-  // Misc Variables
-  int timestep;
-  int forcing_step;
-  int num_steps;
-  int iFile;
-  int dt_init_factor;
-  int output_structure_step_index;
-  double dt_init;
-  double upArea;
-
-  // Sundials variables
-  double rtol;
-  double atol;
-
-  // HRU data structures
-  // Statistic Structure
-  std::vector<std::vector<double>> forc_stat;
-  std::vector<std::vector<double>> prog_stat;
-  std::vector<std::vector<double>> diag_stat;
-  std::vector<std::vector<double>> flux_stat;
-  std::vector<std::vector<double>> indx_stat;
-  std::vector<std::vector<double>> bvar_stat;
-  // Primary Data Strutures (scalars)
-  std::vector<int> time_struct;
-  std::vector<double> forc_struct;
-  std::vector<double> attr_struct;
-  std::vector<int> type_struct;
-  std::vector<long int> id_struct;
-  // Primary Data Structures (arrays)
-  std::vector<std::vector<int>> indx_struct;
-  std::vector<std::vector<double>> mpar_struct;
-  std::vector<std::vector<double>> prog_struct;
-  std::vector<std::vector<double>> diag_struct;
-  std::vector<std::vector<double>> flux_struct;
-  // Basin-average structures
-  std::vector<double> bpar_struct;
-  std::vector<std::vector<double>> bvar_struct;
-  std::vector<double> dpar_struct;
-  // Local HRU data structures
-  std::vector<int> start_time;
-  std::vector<int> end_time;
-  std::vector<int> ref_time;
-  std::vector<int> old_time;
-  // statistic flags
-  std::vector<int> stat_counter;
-  std::vector<int> output_timestep;
-  std::vector<int> reset_stats;
-  std::vector<int> finalize_stats;
-
-  // scalar data
-  double frac_jul_day;
-  double tm_zone_offset_frac_day;
-  int year_length;
-  int compute_veg_flux;
-};
-
-template <class Inspector>
-bool inspect(Inspector& inspector, hru& hru_data) {
-  return inspector.object(hru_data).fields(
-      inspector.field("indx_hru", hru_data.indx_hru),
-      inspector.field("indx_gru", hru_data.indx_gru),
-      inspector.field("ref_gru", hru_data.ref_gru),
-      inspector.field("timestep", hru_data.timestep),
-      inspector.field("forcing_step", hru_data.forcing_step),
-      inspector.field("num_steps", hru_data.num_steps),
-      inspector.field("iFile", hru_data.iFile),
-      inspector.field("dt_init_factor", hru_data.dt_init_factor),
-      inspector.field("output_structure_step_index", 
-          hru_data.output_structure_step_index),
-      inspector.field("dt_init", hru_data.dt_init),
-      inspector.field("upArea", hru_data.upArea),
-      inspector.field("rtol", hru_data.rtol),
-      inspector.field("atol", hru_data.atol),
-      inspector.field("forc_stat", hru_data.forc_stat),
-      inspector.field("prog_stat", hru_data.prog_stat),
-      inspector.field("diag_stat", hru_data.diag_stat),
-      inspector.field("flux_stat", hru_data.flux_stat),
-      inspector.field("indx_stat", hru_data.indx_stat),
-      inspector.field("bvar_stat", hru_data.bvar_stat),
-      inspector.field("time_struct", hru_data.time_struct),
-      inspector.field("forc_struct", hru_data.forc_struct),
-      inspector.field("attr_struct", hru_data.attr_struct),
-      inspector.field("type_struct", hru_data.type_struct),
-      inspector.field("id_struct", hru_data.id_struct),
-      inspector.field("indx_struct", hru_data.indx_struct),
-      inspector.field("mpar_struct", hru_data.mpar_struct),
-      inspector.field("prog_struct", hru_data.prog_struct),
-      inspector.field("diag_struct", hru_data.diag_struct),
-      inspector.field("flux_struct", hru_data.flux_struct),
-      inspector.field("bpar_struct", hru_data.bpar_struct),
-      inspector.field("bvar_struct", hru_data.bvar_struct),
-      inspector.field("dpar_struct", hru_data.dpar_struct),
-      inspector.field("start_time", hru_data.start_time),
-      inspector.field("end_time", hru_data.end_time),
-      inspector.field("ref_time", hru_data.ref_time),
-      inspector.field("old_time", hru_data.old_time),
-      inspector.field("stat_counter", hru_data.stat_counter),
-      inspector.field("output_timestep", hru_data.output_timestep),
-      inspector.field("reset_stats", hru_data.reset_stats),
-      inspector.field("finalize_stats", hru_data.finalize_stats),
-      inspector.field("frac_jul_day", hru_data.frac_jul_day),
-      inspector.field("tm_zone_offset_frac_day", 
-          hru_data.tm_zone_offset_frac_day),
-      inspector.field("year_length", hru_data.year_length),
-      inspector.field("compute_veg_flux", hru_data.compute_veg_flux));
-}
-
-struct NumGRUInfo {
-  int start_gru_local;
-  int start_gru_global; 
-  int num_gru_local;
-  int num_gru_global;
-  int file_gru; 
-  bool use_global_for_data_structures;
-
-  // Constructor
-  NumGRUInfo(int start_gru_local = 0, int start_gru_global= 0, 
-      int num_gru_local = 0, int num_gru_global = 0, int file_gru = 0, 
-      bool use_global_for_data_structures = false) 
-    : start_gru_local(start_gru_local), start_gru_global(start_gru_global), 
-    num_gru_local(num_gru_local), num_gru_global(num_gru_global), 
-    file_gru(file_gru), 
-    use_global_for_data_structures(use_global_for_data_structures) {}
-};
-template <class Insepctor>
-bool inspect(Insepctor& inspector, NumGRUInfo& num_gru) {
-  return inspector.object(num_gru).fields(
-      inspector.field("start_gru_local", num_gru.start_gru_local),
-      inspector.field("start_gru_global", num_gru.start_gru_global),
-      inspector.field("num_gru_local", num_gru.num_gru_local),
-      inspector.field("num_gru_global", num_gru.num_gru_global),
-      inspector.field("file_gru", num_gru.file_gru),
-      inspector.field("use_global_for_data_structures", 
-          num_gru.use_global_for_data_structures));
-}
-
-
-enum class hru_error : uint8_t {
-    run_physics_unhandleable = 1,
-    run_physics_infeasible_state = 2,
-};
 
 enum class file_access_error : uint8_t {
     writing_error = 1,
@@ -164,15 +23,6 @@ enum class file_access_error : uint8_t {
     mDecisions_error = 100,
 };
 
-// HRU Errors
-std::string to_string(hru_error err);
-bool from_string(caf::string_view in, hru_error& out);
-bool from_integer(uint8_t in, hru_error& out);
-template<class Inspector>
-bool inspect(Inspector& f, hru_error& x) {
-    return caf::default_enum_inspect(f, x);
-}
-
 // File Access Actor
 std::string to_string(file_access_error err);
 bool from_string(caf::string_view in, file_access_error& out);
@@ -196,6 +46,8 @@ 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)
+    CAF_ADD_ATOM(summa, global_data_ready)
 
     // Sender: job_actor 
     // Reciever: summa_actor
@@ -392,14 +244,12 @@ CAF_BEGIN_TYPE_ID_BLOCK(summa, first_custom_type_id)
 
     CAF_ADD_TYPE_ID(summa, (std::optional<caf::strong_actor_ptr>))
 
-    // error types
-    CAF_ADD_TYPE_ID(summa, (hru_error))
+
 
     CAF_ADD_TYPE_ID(summa, (file_access_error))
 
 
 CAF_END_TYPE_ID_BLOCK(summa)
 
-CAF_ERROR_CODE_ENUM(hru_error)
 CAF_ERROR_CODE_ENUM(file_access_error)
 
diff --git a/build/includes/global/num_gru_info.hpp b/build/includes/global/num_gru_info.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..2ae115673224e38fcb9bdc30dd152c05b4bb270b
--- /dev/null
+++ b/build/includes/global/num_gru_info.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+
+struct NumGRUInfo {
+  int start_gru_local;
+  int start_gru_global; 
+  int num_gru_local;
+  int num_gru_global;
+  int file_gru; 
+  bool use_global_for_data_structures;
+
+  // Constructor
+  NumGRUInfo(int start_gru_local = 0, int start_gru_global= 0, 
+             int num_gru_local = 0, int num_gru_global = 0, int file_gru = 0, 
+             bool use_global_for_data_structures = false) 
+      : start_gru_local(start_gru_local), start_gru_global(start_gru_global), 
+        num_gru_local(num_gru_local), num_gru_global(num_gru_global), 
+        file_gru(file_gru), 
+        use_global_for_data_structures(use_global_for_data_structures) {}
+};
+template <class Insepctor>
+bool inspect(Insepctor& inspector, NumGRUInfo& num_gru) {
+  return inspector.object(num_gru).fields(
+      inspector.field("start_gru_local", num_gru.start_gru_local),
+      inspector.field("start_gru_global", num_gru.start_gru_global),
+      inspector.field("num_gru_local", num_gru.num_gru_local),
+      inspector.field("num_gru_global", num_gru.num_gru_global),
+      inspector.field("file_gru", num_gru.file_gru),
+      inspector.field("use_global_for_data_structures", 
+          num_gru.use_global_for_data_structures));
+}
diff --git a/build/includes/global/settings_functions.hpp b/build/includes/global/settings_functions.hpp
index e6992e0bc4b89762f7c9bf3052c3b3263df1dedd..4ec61cb3151cdcf3fa2421b3bfb47156b73fdcb4 100644
--- a/build/includes/global/settings_functions.hpp
+++ b/build/includes/global/settings_functions.hpp
@@ -117,20 +117,6 @@ struct HRU_Actor_Settings {
     int dt_init_factor; // factor to multiply the initial timestep by
     double rel_tol;
     double abs_tol;
-    double relTolTempCas;
-    double absTolTempCas;
-    double relTolTempVeg;
-    double absTolTempVeg;
-    double relTolWatVeg;
-    double absTolWatVeg;
-    double relTolTempSoilSnow;
-    double absTolTempSoilSnow;
-    double relTolWatSnow;
-    double absTolWatSnow;
-    double relTolMatric;
-    double absTolMatric;
-    double relTolAquifr;
-    double absTolAquifr;
 };
 
 template<class Inspector>
diff --git a/build/includes/hru_actor/hru_actor.hpp b/build/includes/hru_actor/hru_actor.hpp
index 7240d5d38b2d22970d4078c643a6e1055570c0ac..408c603194a5114a2c1e612b10e6fb29b5024191 100644
--- a/build/includes/hru_actor/hru_actor.hpp
+++ b/build/includes/hru_actor/hru_actor.hpp
@@ -25,25 +25,28 @@ extern "C" {
   // Initialize HRU data_structures
   void initHRU(int* indxGRU, int* num_steps, void* hru_data, int* err);
   
-  void setupHRUParam( int* indxGRU, int* indxHRU, void* hru_data, 
-      double* upArea, int* err);
+  void setupHRUParam(int* indxGRU, int* indxHRU, void* hru_data, 
+                     double* upArea, int* err);
   
   // Setup summa_readRestart File if this option has been chosen 
   void summa_readRestart(int* indxGRU, int* indxHRU, void* hru_data, 
-      double* dtInit, int* err);
+                         double* dtInit, int* err);
   
   // Run the model for one timestep
   void RunPhysics(int* id, int* stepIndex, void* hru_data, double* dt, 
-      int* dt_int_factor, double* walltime_timestep, int* err);
+                  int* dt_int_factor, double* walltime_timestep, int* err);
   
-  void hru_writeOutput(int* index_hru, int* index_gru, int* timestep, int* output_step, void* hru_data, int* y, int* m, int* d, int* h, int* err);
+  void hru_writeOutput(int* index_hru, int* index_gru, int* timestep, 
+                       int* output_step, void* hru_data, int* y, int* m, 
+                       int* d, int* h, int* err);
     
-  int  hru_writeRestart(int* index_hru, int* index_gru, int* timestep, int* output_step, void* hru_data, int* err);
+  int  hru_writeRestart(int* index_hru, int* index_gru, int* timestep, 
+                        int* output_step, void* hru_data, int* err);
 
   void setTimeZoneOffset(int* iFile, void* hru_data, int* err);
 
   void HRU_readForcing(int* index_gru, int* iStep, int* iRead, int* iFile, 
-      void* hru_data,  int* err);
+                       void* hru_data,  int* err);
   
   // hru_writeOutput.f90
   void setFinalizeStatsFalse(int* indx_gru);
@@ -52,27 +55,26 @@ extern "C" {
   void set_sundials_tolerances(void* hru_data, double* relTol, double* absTol);
 
   void setIDATolerances(void* hru_data, double* relTolTempCas, 
-      double* absTolTempCas, double* relTolTempVeg, double* absTolTempVeg, 
-      double* relTolWatVeg, double* absTolWatVeg, double* relTolTempSoilSnow,
-      double* absTolTempSoilSnow, double* relTolWatSnow, 
-      double* absTolWatSnow, double* relTolMatric,
-      double* absTolMatric, double* relTolAquifr, double* absTolAquifr);
+                        double* absTolTempCas, double* relTolTempVeg, 
+                        double* absTolTempVeg, double* relTolWatVeg, 
+                        double* absTolWatVeg, double* relTolTempSoilSnow,
+                        double* absTolTempSoilSnow, double* relTolWatSnow, 
+                        double* absTolWatSnow, double* relTolMatric,
+                        double* absTolMatric, double* relTolAquifr, 
+                        double* absTolAquifr);
 }
 
 /*********************************************
  * HRU Actor state variables
  *********************************************/
-namespace caf {
 struct hru_state {
-	// Actor References
+  // Actor References
 	caf::actor file_access_actor;
 	caf::actor parent;
 
-  // Info about which HRU we are and our indexes
-  // into global structures in Fortran
+  int ref_gru;			  // gru_index from attributes/forcing files
+  int indxGRU; 		  // index for gru part of derived types in FORTRAN
   int indxHRU; 	    // index for hru part of derived types in FORTRAN
-  int indxGRU; 		// index for gru part of derived types in FORTRAN
-  int refGRU;			// The actual ID of the GRU we are
 
     // Variables for forcing structures
 	int stepsInCurrentFFile;        // number of time steps in current forcing file
@@ -93,7 +95,6 @@ struct hru_state {
   int     output_structure_step_index = 1; // index of current time step in output structure
   double  dt_init;            // used to initialize the length of the sub-step for each HRU
   double	upArea;             // area upslope of each HRU
-  int     err = 0;	
 
   // Sundials variables
   double rtol = -9999; // -9999 uses default
@@ -117,22 +118,22 @@ struct hru_state {
   }
 };
 
-behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
-    HRU_Actor_Settings hru_actor_settings, caf::actor file_access_actor, 
-    caf::actor parent);
+caf::behavior hru_actor(caf::stateful_actor<hru_state>* self, int ref_gru, 
+                        int indx_gru, HRU_Actor_Settings hru_actor_settings, 
+                        caf::actor file_access_actor, caf::actor parent);
 
 /*********************************************
  * Functions for the HRU Actor
  *********************************************/
 
 /** Function to initalize the HRU for running */
-void Initialize_HRU(stateful_actor<hru_state>* self);
+void Initialize_HRU(caf::stateful_actor<hru_state>* self);
 
 /** Function runs all of the hru time_steps */
-int Run_HRU(stateful_actor<hru_state>* self);
+int Run_HRU(caf::stateful_actor<hru_state>* self);
 
-//** Function checks if the HRU is at a restart checkpoint **/
-bool isCheckpoint(stateful_actor<hru_state>* self);
+/** Function checks if the HRU is at a restart checkpoint */
+bool isCheckpoint(caf::stateful_actor<hru_state>* self);
 
-
-}
\ No newline at end of file
+void serializeHru(caf::stateful_actor<hru_state>* self, hru& serialized_state);
+void deserializeHru(caf::stateful_actor<hru_state>* self, hru& new_state);
diff --git a/build/includes/hru_actor/hru_utils.hpp b/build/includes/hru_actor/hru_utils.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..0275d60d5e9d405fdbe55eac2325588468896c5f
--- /dev/null
+++ b/build/includes/hru_actor/hru_utils.hpp
@@ -0,0 +1,115 @@
+#pragma once
+#include <vector>
+
+// Serialization HRU Stucture
+struct hru {
+  int indx_hru;
+  int indx_gru;
+  int ref_gru;
+
+  // Misc Variables
+  int timestep;
+  int forcing_step;
+  int num_steps;
+  int iFile;
+  int dt_init_factor;
+  int output_structure_step_index;
+  double dt_init;
+  double upArea;
+
+  // Sundials variables
+  double rtol;
+  double atol;
+
+  // HRU data structures
+  // Statistic Structure
+  std::vector<std::vector<double>> forc_stat;
+  std::vector<std::vector<double>> prog_stat;
+  std::vector<std::vector<double>> diag_stat;
+  std::vector<std::vector<double>> flux_stat;
+  std::vector<std::vector<double>> indx_stat;
+  std::vector<std::vector<double>> bvar_stat;
+  // Primary Data Strutures (scalars)
+  std::vector<int> time_struct;
+  std::vector<double> forc_struct;
+  std::vector<double> attr_struct;
+  std::vector<int> type_struct;
+  std::vector<long int> id_struct;
+  // Primary Data Structures (arrays)
+  std::vector<std::vector<int>> indx_struct;
+  std::vector<std::vector<double>> mpar_struct;
+  std::vector<std::vector<double>> prog_struct;
+  std::vector<std::vector<double>> diag_struct;
+  std::vector<std::vector<double>> flux_struct;
+  // Basin-average structures
+  std::vector<double> bpar_struct;
+  std::vector<std::vector<double>> bvar_struct;
+  std::vector<double> dpar_struct;
+  // Local HRU data structures
+  std::vector<int> start_time;
+  std::vector<int> end_time;
+  std::vector<int> ref_time;
+  std::vector<int> old_time;
+  // statistic flags
+  std::vector<int> stat_counter;
+  std::vector<int> output_timestep;
+  std::vector<int> reset_stats;
+  std::vector<int> finalize_stats;
+
+  // scalar data
+  double frac_jul_day;
+  double tm_zone_offset_frac_day;
+  int year_length;
+  int compute_veg_flux;
+};
+
+template <class Inspector>
+bool inspect(Inspector& inspector, hru& hru_data) {
+  return inspector.object(hru_data).fields(
+         inspector.field("indx_hru", hru_data.indx_hru),
+         inspector.field("indx_gru", hru_data.indx_gru),
+         inspector.field("ref_gru", hru_data.ref_gru),
+         inspector.field("timestep", hru_data.timestep),
+         inspector.field("forcing_step", hru_data.forcing_step),
+         inspector.field("num_steps", hru_data.num_steps),
+         inspector.field("iFile", hru_data.iFile),
+         inspector.field("dt_init_factor", hru_data.dt_init_factor),
+         inspector.field("output_structure_step_index", 
+                         hru_data.output_structure_step_index),
+         inspector.field("dt_init", hru_data.dt_init),
+         inspector.field("upArea", hru_data.upArea),
+         inspector.field("rtol", hru_data.rtol),
+         inspector.field("atol", hru_data.atol),
+         inspector.field("forc_stat", hru_data.forc_stat),
+         inspector.field("prog_stat", hru_data.prog_stat),
+         inspector.field("diag_stat", hru_data.diag_stat),
+         inspector.field("flux_stat", hru_data.flux_stat),
+         inspector.field("indx_stat", hru_data.indx_stat),
+         inspector.field("bvar_stat", hru_data.bvar_stat),
+         inspector.field("time_struct", hru_data.time_struct),
+         inspector.field("forc_struct", hru_data.forc_struct),
+         inspector.field("attr_struct", hru_data.attr_struct),
+         inspector.field("type_struct", hru_data.type_struct),
+         inspector.field("id_struct", hru_data.id_struct),
+         inspector.field("indx_struct", hru_data.indx_struct),
+         inspector.field("mpar_struct", hru_data.mpar_struct),
+         inspector.field("prog_struct", hru_data.prog_struct),
+         inspector.field("diag_struct", hru_data.diag_struct),
+         inspector.field("flux_struct", hru_data.flux_struct),
+         inspector.field("bpar_struct", hru_data.bpar_struct),
+         inspector.field("bvar_struct", hru_data.bvar_struct),
+         inspector.field("dpar_struct", hru_data.dpar_struct),
+         inspector.field("start_time", hru_data.start_time),
+         inspector.field("end_time", hru_data.end_time),
+         inspector.field("ref_time", hru_data.ref_time),
+         inspector.field("old_time", hru_data.old_time),
+         inspector.field("stat_counter", hru_data.stat_counter),
+         inspector.field("output_timestep", hru_data.output_timestep),
+         inspector.field("reset_stats", hru_data.reset_stats),
+         inspector.field("finalize_stats", hru_data.finalize_stats),
+         inspector.field("frac_jul_day", hru_data.frac_jul_day),
+         inspector.field("tm_zone_offset_frac_day", 
+                         hru_data.tm_zone_offset_frac_day),
+         inspector.field("year_length", hru_data.year_length),
+         inspector.field("compute_veg_flux", hru_data.compute_veg_flux));
+}
\ No newline at end of file
diff --git a/build/includes/job_actor/GRU.hpp b/build/includes/job_actor/GRU.hpp
index 3c33f51d0afd520b43a230c2fd370f3f7a846959..69dc87275da50f368443772996922c4d086c8485 100644
--- a/build/includes/job_actor/GRU.hpp
+++ b/build/includes/job_actor/GRU.hpp
@@ -1,92 +1,57 @@
 #pragma once
-
 #include "caf/all.hpp"
-#include <iostream>
-#include <fstream>
-
-/*
- * Determine the state of the GRU
-*/
-enum class gru_state {
-    running,
-    failed,
-    succeeded
-};
 
-int is_success(const gru_state& state);
+/** Determine the state of the GRU */
+enum class gru_state { running, failed, succeeded };
 
-/**
- * Class that holds information about the running GRUs. This class is held by the job actor
- * The GRU/HRU actors that carry out the simulation are held by the GRU class 
-*/
+/** Gru Information (meant to mimic gru_struc)*/
 class GRU {
   private:
-    int global_gru_index; // The index of the GRU in the netcdf file
-    int local_gru_index; // The index of the GRU within this job
-    caf::actor gru_actor; // The actor for the GRU
+    int index_netcdf_;       // The index of the GRU in the netcdf file
+    int index_job_;          // The index of the GRU within this job
+    caf::actor actor_ref_;   // The actor for the GRU
 
     // Modifyable Parameters
-    int dt_init_factor; // The initial dt for the GRU
-    double rel_tol; // The relative tolerance for the GRU
-    double abs_tol; // The absolute tolerance for the GRU
+    int dt_init_factor_;     // The initial dt for the GRU
+    double rel_tol_;         // The relative tolerance for the GRU
+    double abs_tol_;         // The absolute tolerance for the GRU
 
     // Status Information
-    int attempts_left; // The number of attempts left for the GRU to succeed
-    gru_state state; // The state of the GRU
+    int attempts_left_;      // The number of attempts left for the GRU to succeed
+    gru_state state_;        // The state of the GRU
 
     // Timing Information
-    double run_time = 0.0; // The total time to run the GRU
-    double init_duration = 0.0; // The time to initialize the GRU
-    double forcing_duration = 0.0; // The time to read the forcing data
-    double run_physics_duration = 0.0; // The time to run the physics
-    double write_output_duration = 0.0; // The time to write the output
+    double run_time_ = 0.0;  // The total time to run the GRU
 
     
   public:
     // Constructor
-    GRU(int global_gru_index, int local_gru_index, caf::actor gru_actor, int dt_init_factor, 
-        double rel_tol, double abs_tol, int max_attempts);
+    GRU(int index_netcdf, int index_job, caf::actor actor_ref, 
+        int dt_init_factor, double rel_tol, double abs_tol, int max_attempts);
 
     // Deconstructor
     ~GRU();
 
     // Getters
-    int getGlobalGRUIndex();
-    int getLocalGRUIndex();
-    caf::actor getGRUActor();
-
-    double getRunTime();
-    double getInitDuration();
-    double getForcingDuration();
-    double getRunPhysicsDuration();
-    double getWriteOutputDuration();
-
-    double getRelTol();
-    double getAbsTol();
-
-    double getAttemptsLeft();
-    gru_state getStatus();
-
-    bool isFailed();
-
-
+    inline int getIndexNetcdf() const { return index_netcdf_; }
+    inline int getIndexJob() const { return index_job_; }
+    inline caf::actor getActorRef() const { return actor_ref_; }
+    inline double getRunTime() const { return run_time_; }
+    inline double getRelTol() const { return rel_tol_; }
+    inline double getAbsTol() const { return abs_tol_; }
+    inline int getAttemptsLeft() const { return attempts_left_; }
+    inline gru_state getStatus() const { return state_; }
 
     // Setters
-    void setRunTime(double run_time);
-    void setInitDuration(double init_duration);
-    void setForcingDuration(double forcing_duration);
-    void setRunPhysicsDuration(double run_physics_duration);
-    void setWriteOutputDuration(double write_output_duration);
-
-    void setRelTol(double rel_tol);
-    void setAbsTol(double abs_tol);
-
-    void setSuccess();
-    void setFailed();
-    void setRunning();
-
-    void decrementAttemptsLeft();
-
-    void setGRUActor(caf::actor gru_actor);
-
+    inline void setRunTime(double run_time) { run_time_ = run_time; }
+    inline void setRelTol(double rel_tol) { rel_tol_ = rel_tol; }
+    inline void setAbsTol(double abs_tol) { abs_tol_ = abs_tol; }
+    inline void setSuccess() { state_ = gru_state::succeeded; }
+    inline void setFailed() { state_ = gru_state::failed; }
+    inline void setRunning() { state_ = gru_state::running; }
+
+    // Methods
+    inline bool isFailed() const { return state_ == gru_state::failed; }
+    inline void decrementAttemptsLeft() { attempts_left_--; }
+    inline void setActorRef(caf::actor gru_actor) { actor_ref_ = gru_actor; }
 };
diff --git a/build/includes/job_actor/gru_struc.hpp b/build/includes/job_actor/gru_struc.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..1d9daf49f14f0eed97aa41deecb27e0c0ad7a7a4
--- /dev/null
+++ b/build/includes/job_actor/gru_struc.hpp
@@ -0,0 +1,68 @@
+#pragma once
+#include <string>
+#include "GRU.hpp"
+
+extern "C" {
+  void read_dimension_fortran(int& start_gru, int& num_gru, int& num_hru, 
+                              int& file_gru, int& file_hru, int& err, 
+                              void* message);
+
+  void read_icond_nlayers_fortran(int& num_gru, int& err, void* message);
+
+  void deallocate_gru_struc_fortran();
+}
+
+class GruStruc {
+  
+  public:
+    GruStruc(int start_gru, int num_gru, int num_retry_attempts);
+    ~GruStruc(){deallocate_gru_struc_fortran();};
+    int ReadDimension();
+    int ReadIcondNlayers();
+    inline int getStartGru() const { return start_gru_; }
+    inline int getNumGrus() const { return num_gru_; }
+    inline int get_file_gru() const { return file_gru_; }
+    inline int get_gru_info_size() const { return gru_info_.size(); }
+    inline int getNumGrusDone() const { return num_gru_done_; }
+    inline int getNumGRUFailed() const { return num_gru_failed_; }
+
+    inline void addGRU(std::unique_ptr<GRU> gru) {
+      gru_info_[gru->getIndexJob() - 1] = std::move(gru);
+    }
+
+    inline void incrementNumGRUDone() { num_gru_done_++; }
+    inline void incrementNumGRUFailed() { num_gru_failed_++; num_gru_done_++;}
+    inline void decrementRetryAttempts() { num_retry_attempts_left_--; }
+    inline void decrementNumGRUFailed() { num_gru_failed_--; num_gru_done_--;}
+    inline GRU* getGRU(int index) { return gru_info_[index-1].get(); }
+
+    inline bool isDone() { return num_gru_done_ >= num_gru_; }
+    inline bool hasFailures() { return num_gru_failed_ > 0; }
+    inline bool shouldRetry() { return num_retry_attempts_left_ > 0; }
+
+    int getFailedIndex() {
+      for (int i = 0; i < gru_info_.size(); i++) {
+        if (gru_info_[i]->getStatus() == gru_state::failed) {
+          return gru_info_[i]->getIndexJob();
+        }
+      }
+      return -1;
+    }
+
+  private:
+    // Inital Information about the GRUs
+    int start_gru_;
+    int num_gru_;
+    int num_hru_;
+    int file_gru_;
+    int file_hru_;
+    
+    // GRU specific Information
+    std::vector<std::unique_ptr<GRU>> gru_info_;
+
+    // Runtime status of the GRUs
+    int num_gru_done_ = 0;
+    int num_gru_failed_ = 0;
+    int num_retry_attempts_left_ = 0;
+
+};
\ No newline at end of file
diff --git a/build/includes/job_actor/job_actor.hpp b/build/includes/job_actor/job_actor.hpp
index 6c42a0007d91709be06f79371feca7459f43c45b..f69871c4cbbe4fa1ea7aafa77325cad7112d3608 100644
--- a/build/includes/job_actor/job_actor.hpp
+++ b/build/includes/job_actor/job_actor.hpp
@@ -1,7 +1,9 @@
 #pragma once
 #include "caf/all.hpp"
 #include "caf/io/all.hpp"
+#include "num_gru_info.hpp"
 #include "GRU.hpp"
+#include "gru_struc.hpp"
 #include "timing_info.hpp"
 #include "settings_functions.hpp"
 #include "global.hpp"
@@ -15,35 +17,29 @@
 #include <cmath>
 #include <vector>
 #include <tuple>
+#include "summa_init_struc.hpp"
 
-/*********************************************
- * Job Actor Fortran Functions
- *********************************************/
-extern "C" {
-  void job_init_fortran(char const* file_manager, int* start_gru_index, 
-      int* num_gru, int* num_hru, int* file_gru, int* err);
-
-  void deallocateJobActor(int* err);
-}
 
 
 /*********************************************
- * Job Actor state variables
+ * Job Actor Data Structures
  *********************************************/
-namespace caf {
-using chrono_time = std::chrono::time_point<std::chrono::system_clock>;
-
 // Holds information about the GRUs
 struct GRU_Container {
   std::vector<GRU*> gru_list;
-  chrono_time gru_start_time; // Vector of start times for each GRU
+  std::chrono::time_point<std::chrono::system_clock> gru_start_time; // Vector of start times for each GRU
   int num_gru_done = 0; 
   int num_gru_failed = 0; // number of grus that are waiting to be restarted
   int num_gru_in_run_domain = 0; // number of grus we are currently solving for
   int run_attempts_left = 1; // current run attempt for all grus
 };
 
+
+/*********************************************
+ * Job Actor state variables
+ *********************************************/
 struct job_state {
+  TimingInfo job_timing;
   // Actor References
   caf::actor file_access_actor; // actor reference for the file_access_actor
   caf::actor parent;            // actor reference to the top-level SummaActor
@@ -53,19 +49,21 @@ struct job_state {
   int num_gru;                  // Number of GRUs for this job
   int num_hru;
   int max_run_attempts = 1;     // Max number of attempts to solve a GRU
-
+  
+  // TODO: gru_struc can contain the num_gru_info and be the gru_container
+  std::unique_ptr<GruStruc> gru_struc; 
   NumGRUInfo num_gru_info;
-
-
   GRU_Container gru_container;
   
+
+  std::unique_ptr<SummaInitStruc> summa_init_struc;
+
   // Variables for GRU monitoring
   int dt_init_start_factor = 1; // Initial Factor for dt_init (coupled_em)
   int num_gru_done = 0;         // The number of GRUs that have completed
   int num_gru_failed = 0;       // Number of GRUs that have failed
 
   // Timing Variables
-  TimingInfo job_timing;
   
   std::string hostname;
 
@@ -105,8 +103,8 @@ struct distributed_job_state {
   std::vector<std::vector<double>> gru_times_per_node;
   std::vector<double> node_walltimes;
 
-  chrono_time load_balance_start_time;
-  chrono_time load_balance_end_time;
+  std::chrono::time_point<std::chrono::system_clock> load_balance_start_time;
+  std::chrono::time_point<std::chrono::system_clock> load_balance_end_time;
   double load_balance_time = 0.0;
 
   
@@ -145,19 +143,20 @@ struct distributed_job_state {
 };
 
 /** The Job Actor Behaviors */
-behavior job_actor(stateful_actor<job_state>* self, 
-    int start_gru, int num_gru, 
-    File_Access_Actor_Settings file_access_actor_settings, 
-    Job_Actor_Settings job_actor_settings, 
-    HRU_Actor_Settings hru_actor_settings, actor parent);
+caf::behavior job_actor(caf::stateful_actor<job_state>* self, int start_gru, 
+                        int num_gru, 
+                        File_Access_Actor_Settings file_access_actor_settings, 
+                        Job_Actor_Settings job_actor_settings, 
+                        HRU_Actor_Settings hru_actor_settings, 
+                        caf::actor parent);
 
-behavior data_assimilation_mode(stateful_actor<job_state>* self);
-behavior async_mode(stateful_actor<job_state>* self); 
+caf::behavior data_assimilation_mode(caf::stateful_actor<job_state>* self);
+caf::behavior async_mode(caf::stateful_actor<job_state>* self); 
 
 /** The Job Actor For Internode Communication */
-behavior distributed_job_actor(stateful_actor<distributed_job_state>* self,
-    int start_gru, int num_gru,
-    Distributed_Settings distributed_settings,
+caf::behavior distributed_job_actor(
+    caf::stateful_actor<distributed_job_state>* self, int start_gru, 
+    int num_gru, Distributed_Settings distributed_settings,
     File_Access_Actor_Settings file_access_actor_settings,
     Job_Actor_Settings job_actor_settings, 
     HRU_Actor_Settings hru_actor_settings);
@@ -167,17 +166,14 @@ behavior distributed_job_actor(stateful_actor<distributed_job_state>* self,
  * Functions for the Job Actor (job_utils.cpp)
  *********************************************/
 // Spawn HRU Actors Individually
-void spawnHRUActors(stateful_actor<job_state>* self);
+void spawnHRUActors(caf::stateful_actor<job_state>* self);
 // Spawn HRU Batch Actors
-void spawnHRUBatches(stateful_actor<job_state>* self);
-
-void handleFinishedGRU(stateful_actor<job_state>* self, int local_gru_index);
+void spawnHRUBatches(caf::stateful_actor<job_state>* self);
 
-void finalizeJob(stateful_actor<job_state>* self);
+void handleFinishedGRU(caf::stateful_actor<job_state>* self,
+                       int local_gru_index);
 
-/** Get the information for the GRUs that will be written to the netcdf file */
-std::vector<serializable_netcdf_gru_actor_info> getGruNetcdfInfo(
-    int max_run_attempts, std::vector<GRU*> &gru_list);
+void finalizeJob(caf::stateful_actor<job_state>* self);
 
-void handleGRUError(stateful_actor<job_state>* self, caf::actor src);
-} // end namespace
\ No newline at end of file
+void handleGRUError(caf::stateful_actor<job_state>* self, int err_code, 
+                    int index);
\ No newline at end of file
diff --git a/build/includes/job_actor/node_actor.hpp b/build/includes/job_actor/node_actor.hpp
index 7e5b27947db73bc78035e63c2cb5dadc91b7ee08..7b6a4b175eb16e699c45cf182583afd64f235a7e 100644
--- a/build/includes/job_actor/node_actor.hpp
+++ b/build/includes/job_actor/node_actor.hpp
@@ -33,6 +33,8 @@ struct node_state {
   caf::actor file_access_actor; // actor reference for the file_access_actor
   GRU_Container gru_container;
 
+  std::unique_ptr<GruStruc> gru_struc;
+
   Distributed_Settings distributed_settings;
   File_Access_Actor_Settings file_access_actor_settings;
   Job_Actor_Settings job_actor_settings;
diff --git a/build/includes/summa_actor/summa_actor.hpp b/build/includes/summa_actor/summa_actor.hpp
index 8a736afdb93dd527f6781dec1f41c40781c0f366..5794e4a48f72af0542d60c5b3ffb146af77d5dd3 100644
--- a/build/includes/summa_actor/summa_actor.hpp
+++ b/build/includes/summa_actor/summa_actor.hpp
@@ -5,37 +5,32 @@
 #include "timing_info.hpp"
 #include "settings_functions.hpp"
 #include "batch_container.hpp"
+#include "fileManager.hpp"
+#include "gru_struc.hpp"
 #include <chrono>
 #include <string>
 #include <vector>
-
-namespace caf {
+#include "message_atoms.hpp"
+#include "summa_global_data.hpp"
 
 
-struct job_timing_info {
-  std::vector<double> job_duration;
-  std::vector<double> job_read_duration;
-  std::vector<double> job_write_duration;
-};
-
+namespace caf {
 struct summa_actor_state {
-  // Timing Information For Summa-Actor
   TimingInfo summa_actor_timing;
-  struct job_timing_info timing_info_for_jobs;
 
-  // Program Parameters
-  int startGRU;           // starting GRU for the simulation
-  int numGRU;             // number of GRUs to compute
-  int fileGRU;            // number of GRUs in the file
-  std::string configPath; // path to the fileManager.txt file
-  int numFailed = 0;      // Number of jobs that have failed
-  caf::actor currentJob;  // Reference to the current job actor
+  int start_gru;           // starting GRU for the simulation
+  int num_gru;             // number of GRUs to compute
+  int file_gru;            // number of GRUs in the file
+  int num_gru_failed = 0;  // Number of GRUs that have failed
+  caf::actor current_job;  // Reference to the current job actor
   caf::actor parent;
 
-  // Batches
   Batch_Container batch_container;
   int current_batch_id;
 
+  std::unique_ptr<fileManager> file_manager;
+  std::unique_ptr<summaGlobalData> global_fortran_state;
+
 
   // settings for all child actors (save in case we need to recover)
   Summa_Actor_Settings summa_actor_settings;
@@ -44,7 +39,11 @@ struct summa_actor_state {
   HRU_Actor_Settings hru_actor_settings;
 };
 
-
+/**
+ * This actor is for local computation and computes a num_gru from the 
+ * start_gru index. This actor can split the computation into multiple
+ * jobs if needed.
+*/
 behavior summa_actor(stateful_actor<summa_actor_state>* self, 
                      int startGRU, int numGRU, 
                      Summa_Actor_Settings summa_actor_settings, 
@@ -55,11 +54,9 @@ behavior summa_actor(stateful_actor<summa_actor_state>* self,
 void spawnJob(stateful_actor<summa_actor_state>* self);
 } // namespace caf
 
+// Gets the number of GRUs from the attribute file
+int getNumGRUInFile(const std::string &settingsPath, 
+                    const std::string &attributeFile);
 
-// Helper Function to extract a string from the line of a file that 
-// is enclosed in quotes
-std::string extractEnclosed(const std::string& line);
 
-// Gets the number of GRUs from the attribute file
-int getNumGRUInFile(const std::string &file_manager);
 
diff --git a/build/includes/summa_actor/summa_global_data.hpp b/build/includes/summa_actor/summa_global_data.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a99ddeb2e8f0cdcd1a2d13af463da6a6885125f0
--- /dev/null
+++ b/build/includes/summa_actor/summa_global_data.hpp
@@ -0,0 +1,17 @@
+extern "C" {
+  void defineGlobalData_fortran(int* err, void* err_msg);
+
+  void deallocateGlobalData_fortran(int* err, void* err_msg);
+}
+
+// This is a class that wraps around the data created in 
+// defineGlobalData()
+class summaGlobalData {
+  public:
+    summaGlobalData();
+    ~summaGlobalData();
+
+    int defineGlobalData();
+  private:
+    bool global_data_ready;
+};  
diff --git a/build/source/file_access_actor/cppwrap_fileAccess.f90 b/build/source/file_access_actor/cppwrap_fileAccess.f90
deleted file mode 100644
index f99ca0e861c02e9a0eb845fb656513d78b6de9e0..0000000000000000000000000000000000000000
--- a/build/source/file_access_actor/cppwrap_fileAccess.f90
+++ /dev/null
@@ -1,751 +0,0 @@
-module cppwrap_fileAccess
-
-
-  !======= Inclusions ===========
-  USE, intrinsic :: iso_c_binding
-  USE nrtype
-  USE data_types
-  USE actor_data_types
-  USE globalData
-  USE globalData,only:integerMissing      ! missing integer value
-  USE globalData,only:realMissing         ! missing double precision value
-
-
-
-  implicit none
-  public::fileAccessActor_init_fortran
-  public::defOutputFortran
-  public::FileAccessActor_DeallocateStructures
-  public::SOIL_VEG_GEN_PARM
-
-  character(len=64), parameter     :: summaVersion = ''
-  character(len=64), parameter     :: buildTime = ''
-  character(len=64), parameter     :: gitBranch = ''
-  character(len=64), parameter     :: gitHash = ''
-  
-  contains
-
-! Call the fortran routines that read data in and are associtated with the forcing structure
-subroutine fileAccessActor_init_fortran(& ! Variables for forcing
-                                        handle_forcFileInfo,&
-                                        num_forcing_files,&
-                                        num_timesteps,&
-                                        num_timesteps_output_buffer,&
-                                        ! Variables for output
-                                        handle_output_ncid,&
-                                        start_gru,&  
-                                        num_gru,&
-                                        num_hru,&
-                                        err) bind(C, name="fileAccessActor_init_fortran")
-  USE ffile_info_actors_module,only:ffile_info
-  USE mDecisions_module,only:mDecisions                       ! module to read model decisions
-  USE read_pinit_module,only:read_pinit                       ! module to read initial model parameter values
-  USE module_sf_noahmplsm,only:read_mp_veg_parameters         ! module to read NOAH vegetation tables
-  USE output_structure_module,only:initOutputStructure        ! module to initialize output structure
-  USE output_structure_module,only:initOutputTimeStep         ! module to initialize output timestep structure (tracks GRUs timestep for output)
-  USE read_attrb_module,only:read_attrb                       ! module to read local attributes
-  USE read_param_module,only:read_param                       ! module to read model parameter sets
-  USE pOverwrite_module,only:pOverwrite                       ! module to overwrite default parameter values with info from the Noah tables
-  USE var_derive_module,only:fracFuture                       ! module to calculate the fraction of runoff in future time steps (time delay histogram)
-  USE paramCheck_module,only:paramCheck                       ! module to check consistency of model parameters
-  USE read_icond_module,only:read_icond                       ! module to read initial conditions
-  USE check_icond_module,only:check_icond                     ! module to check initial conditions
-  USE globalData,only:localParFallback                        ! local column default parameters
-  USE globalData,only:basinParFallback                        ! basin-average default parameters
-  USE globalData,only:mpar_meta,bpar_meta                     ! parameter metadata structures
-  USE summaFileManager,only:LOCALPARAM_INFO,BASINPARAM_INFO   ! files defining the default values and constraints for model parameters
-  USE summaFileManager,only:SETTINGS_PATH                     ! define path to settings files (e.g., parameters, soil and veg. tables)
-  USE summaFileManager,only:LOCAL_ATTRIBUTES                  ! name of model initial attributes file
-  USE summaFileManager,only:GENPARM,VEGPARM,SOILPARM,MPTABLE  ! files defining the noah tables
-  USE summaFileManager,only:MODEL_INITCOND                    ! name of model initial conditions file
-  USE summaFileManager,only:STATE_PATH                        ! optional path to state/init. condition files (defaults to SETTINGS_PATH)
-  USE summaFileManager,only:OUTPUT_PATH,OUTPUT_PREFIX ! define output file
-  USE globalData,only:model_decisions                         ! model decision structure
-  USE var_lookup,only:iLookDECISIONS                          ! look-up values for model decisions
-  USE var_lookup,only:iLookTYPE                               ! look-up values for model types
-  USE var_lookup,only:iLookID                                 ! look-up values for model IDs
-  USE var_lookup,only:iLookPARAM
-  USE var_lookup,only:iLookATTR                               ! look-up values for model attributes
-  USE var_lookup,only:iLookBVAR                               ! look-up values for basin-average variables
-  USE output_structure_module,only:summa_struct            ! output structure
-
-  USE globalData,only:iRunModeFull,iRunModeGRU,iRunModeHRU
-  USE globalData,only:iRunMode                                ! define the current running mode
-  USE globalData,only:checkHRU                                ! index of the HRU for a single HRU run
-  
-
-  USE mDecisions_module,only:&
-                        monthlyTable,&        ! LAI/SAI taken directly from a monthly table for different vegetation classes
-                        specified,&           ! LAI/SAI computed from green vegetation fraction and winterSAI and summerLAI parameters
-                        sameRulesAllLayers, & ! SNTHERM option: same combination/sub-dividion rules applied to all layers
-                        rulesDependLayerIndex ! CLM option: combination/sub-dividion rules depend on layer index
-
-  USE NOAHMP_VEG_PARAMETERS,only:SAIM,LAIM    ! 2-d tables for stem area index and leaf area index (vegType,month)
-  USE NOAHMP_VEG_PARAMETERS,only:HVT,HVB      ! height at the top and bottom of vegetation (vegType)
-  USE globalData,only:numtim                  ! number of time steps in the simulation
-  USE globalData,only:fileout                 ! name of the output file
-  USE globalData,only:ncid                    ! id of the output file
-
-  ! Moudles that pertian to Version 4 (Sundials addition)
-#ifdef V4_ACTIVE
-  USE mDecisions_module,only:enthalpyFD,enthalpyFDlu  ! look-up values for the choice of heat capacity computation
-  USE enthalpyTemp_module,only:T2H_lookup_snow        ! module to calculate a look-up table for the snow temperature-enthalpy conversion
-  USE enthalpyTemp_module,only:T2L_lookup_soil        ! module to calculate a look-up table for the soil temperature-enthalpy conversion
-#endif
-
-  implicit none
-
-  type(c_ptr), intent(in), value         :: handle_forcFileInfo
-  integer(c_int),intent(out)             :: num_forcing_files
-  integer(c_int),intent(out)             :: num_timesteps
-  integer(c_int),intent(in)              :: num_timesteps_output_buffer
-  type(c_ptr),intent(in), value          :: handle_output_ncid
-  integer(c_int),intent(out)             :: start_gru
-  integer(c_int),intent(out)             :: num_gru
-  integer(c_int),intent(out)             :: num_hru
-  integer(c_int),intent(out)             :: err
-
-  ! local Variables
-  type(file_info_array),pointer          :: forcFileInfo
-  type(var_i),pointer                    :: output_ncid        ! id of output file
-  integer(i4b)                           :: iGRU               ! counter for GRUs
-  integer(i4b)                           :: iHRU               ! counter for HRUs
-  integer(i4b)                           :: jHRU,kHRU          ! HRU indices
-  integer(i4b)                           :: ivar               ! counter for variables
-  character(len=256)                     :: attrFile           ! attributes file name
-  character(LEN=256)                     :: restartFile        ! restart file name
-  logical                                :: needLookup         ! logical to decide if computing enthalpy lookup tables
-  
-  integer(i4b)                           :: indxGRU=1
-  character(len=256)                     :: message            ! error message for downwind routine
-
-
-  err=0; message="fileAccessActor_init_fortran/"
-
-  call c_f_pointer(handle_forcFileInfo, forcFileInfo)
-  call c_f_pointer(handle_output_ncid, output_ncid)
-
-  ! *****************************************************************************
-  ! *** read description of model forcing datafile used in each HRU
-  ! *****************************************************************************
-  call ffile_info(indxGRU, forcFileInfo, num_forcing_files, err, message)
-  if(err/=0)then; print*, trim(message); return; endif
-
-  ! *****************************************************************************
-  ! *** read model decisions
-  ! *****************************************************************************
-  ! NOTE: Must be after ffile_info because mDecisions uses the data_step
-  call mDecisions(err,message)
-  if(err/=0)then; print*,trim(message); return; endif
-  
-  ! TODO: This can be moved to a simple getter the file_access_actor calls
-  num_timesteps = numtim ! Returns to the file_access_actor
-
-#ifdef V4_ACTIVE
-  ! decide if computing enthalpy lookup tables, if need enthalpy and not using hypergeometric function
-  needLookup = .false.
-  if(model_decisions(iLookDECISIONS%nrgConserv)%iDecision == enthalpyFDlu) needLookup = .true.
-#endif
-
-  ! get the maximum number of snow layers
-  select case(model_decisions(iLookDECISIONS%snowLayers)%iDecision)
-    case(sameRulesAllLayers);    maxSnowLayers = 100
-    case(rulesDependLayerIndex); maxSnowLayers = 5
-    case default; err=20; message=trim(message)//'unable to identify option to combine/sub-divide snow layers'; return
-  end select ! (option to combine/sub-divide snow layers)
-
-  maxLayers = gru_struc(1)%hruInfo(1)%nSoil + maxSnowLayers
-
-  ! *****************************************************************************
-  ! *** read default model parameters
-  ! *****************************************************************************
-  ! read default values and constraints for model parameters (local column)
-  call read_pinit(LOCALPARAM_INFO,.TRUE., mpar_meta,localParFallback,err,message)
-  if(err/=0)then; print*,trim(message); return; endif
-
-  ! read default values and constraints for model parameters (basin-average)
-  call read_pinit(BASINPARAM_INFO,.FALSE.,bpar_meta,basinParFallback,err,message)
-  if(err/=0)then; print*,trim(message); return; endif
-  
-  
-  ! *****************************************************************************
-  ! *** read Noah vegetation and soil tables
-  ! *****************************************************************************
-
-  greenVegFrac_monthly = (/0.01_dp, 0.02_dp, 0.03_dp, 0.07_dp, 0.50_dp, 0.90_dp,& 
-      0.95_dp, 0.96_dp, 0.65_dp, 0.24_dp, 0.11_dp, 0.02_dp/)
-
-
-  ! read Noah soil and vegetation tables
-  call soil_veg_gen_parm(trim(SETTINGS_PATH)//trim(VEGPARM),      & ! filename for vegetation table
-      trim(SETTINGS_PATH)//trim(SOILPARM), & ! filename for soils table
-      trim(SETTINGS_PATH)//trim(GENPARM),  & ! filename for general table
-      trim(model_decisions(iLookDECISIONS%vegeParTbl)%cDecision), & ! classification system used for vegetation
-      trim(model_decisions(iLookDECISIONS%soilCatTbl)%cDecision))   ! classification system used for soils
-  if(err/=0)then; print*,trim(message); return; endif
-
-  ! read Noah-MP vegetation tables
-  call read_mp_veg_parameters(trim(SETTINGS_PATH)//trim(MPTABLE),                       & ! filename for Noah-MP table
-                              trim(model_decisions(iLookDECISIONS%vegeParTbl)%cDecision)) ! classification system used for vegetation
-  if(err/=0)then; print*,trim(message); return; endif
-
-    ! define urban vegetation category
-  select case(trim(model_decisions(iLookDECISIONS%vegeParTbl)%cDecision))
-    case('USGS');                     urbanVegCategory =    1
-    case('MODIFIED_IGBP_MODIS_NOAH'); urbanVegCategory =   13
-    case('plumberCABLE');             urbanVegCategory = -999
-    case('plumberCHTESSEL');          urbanVegCategory = -999
-    case('plumberSUMMA');             urbanVegCategory = -999
-    case default; message=trim(message)//'unable to identify vegetation category';print*,message;return
-  end select
-
-  ! *****************************************************************************
-  ! *** Initialize output structure
-  ! *****************************************************************************
-  call initOutputStructure(forcFileInfo, num_timesteps_output_buffer, num_gru, err)
-  if(err/=0)then; print*,trim(message); return; endif
-
-  ! *****************************************************************************
-  ! *** Initialize output time step
-  ! *****************************************************************************
-  call initOutputTimeStep(num_gru, err)
-  if(err/=0)then; print*,trim(message); return; endif
-
-
-  ! *****************************************************************************
-  ! *** Read Attributes
-  ! *****************************************************************************
-
-  attrFile = trim(SETTINGS_PATH)//trim(LOCAL_ATTRIBUTES)
-  call read_attrb(trim(attrFile),num_gru,summa_struct(1)%attrStruct,&
-      summa_struct(1)%typeStruct,summa_struct(1)%idStruct,err,message)
-  if(err/=0)then; print*,trim(message); return; endif
-
-
-  ! set default model parameters
-  do iGRU=1, num_gru
-    do iHRU=1, gru_struc(iGRU)%hruCount
-      ! set parmameters to their default value
-      summa_struct(1)%dparStruct%gru(iGRU)%hru(iHRU)%var(:) = localParFallback(:)%default_val         ! x%hru(:)%var(:)
-
-      ! overwrite default model parameters with information from the Noah-MP tables
-      call pOverwrite(summa_struct(1)%typeStruct%gru(iGRU)%hru(iHRU)%var(iLookTYPE%vegTypeIndex),  &  ! vegetation category
-                      summa_struct(1)%typeStruct%gru(iGRU)%hru(iHRU)%var(iLookTYPE%soilTypeIndex), &  ! soil category
-                      summa_struct(1)%dparStruct%gru(iGRU)%hru(iHRU)%var,                          &  ! default model parameters
-                      err,message)                                                   ! error control
-      if(err/=0)then; print*, trim(message); return; endif
-
-
-   ! copy over to the parameter structure
-   ! NOTE: constant for the dat(:) dimension (normally depth)
-      do ivar=1,size(localParFallback)
-        summa_struct(1)%mparStruct%gru(iGRU)%hru(iHRU)%var(ivar)%dat(:) = summa_struct(1)%dparStruct%gru(iGRU)%hru(iHRU)%var(ivar)
-      end do  ! looping through variables
-    
-    end do  ! looping through HRUs
-    
-    ! set default for basin-average parameters
-    summa_struct(1)%bparStruct%gru(iGRU)%var(:) = basinParFallback(:)%default_val
-    
-  end do  ! looping through GRUs
-
-
-  ! *****************************************************************************
-  ! *** Read Parameters
-  ! *****************************************************************************
-  checkHRU = integerMissing
-  call read_param(iRunMode,checkHRU,start_gru,num_hru,num_gru,summa_struct(1)%idStruct,&
-      summa_struct(1)%mparStruct,summa_struct(1)%bparStruct,err,message)
-  if(err/=0)then; print*,trim(message); return; endif
-
-  ! *****************************************************************************
-  ! *** compute derived model variables that are pretty much constant for the basin as a whole
-  ! *****************************************************************************
-  ! ! loop through GRUs
-  do iGRU=1,num_gru
-    ! calculate the fraction of runoff in future time steps
-    call fracFuture(summa_struct(1)%bparStruct%gru(iGRU)%var,     &  ! vector of basin-average model parameters
-                    summa_struct(1)%bvarStruct_init%gru(iGRU),    &  ! data structure of basin-average variables
-                    err,message)                   ! error control
-    if(err/=0)then; print*, trim(message); return; endif
-
-    ! loop through local HRUs
-    do iHRU=1,gru_struc(iGRU)%hruCount
-
-    
-      kHRU=0
-      ! check the network topology (only expect there to be one downslope HRU)
-      do jHRU=1,gru_struc(iGRU)%hruCount
-      if(summa_struct(1)%typeStruct%gru(iGRU)%hru(iHRU)%var(iLookTYPE%downHRUindex) == summa_struct(1)%idStruct%gru(iGRU)%hru(jHRU)%var(iLookID%hruId))then
-        if(kHRU==0)then  ! check there is a unique match
-        kHRU=jHRU
-        else
-        message=trim(message)//'only expect there to be one downslope HRU'; print*, message; return
-        end if  ! (check there is a unique match)
-      end if  ! (if identified a downslope HRU)
-      end do
-
-
-      ! check that the parameters are consistent
-      call paramCheck(summa_struct(1)%mparStruct%gru(iGRU)%hru(iHRU),err,message)
-      if(err/=0)then; print*, message; return; endif
-
-#ifdef V4_ACTIVE      
-      ! calculate a look-up table for the temperature-enthalpy conversion of snow for future snow layer merging
-      ! NOTE2: H is the mixture enthalpy of snow liquid and ice
-      call T2H_lookup_snow(summa_struct(1)%mparStruct%gru(iGRU)%hru(iHRU),err,message)
-      if(err/=0)then; print*, message; return; endif
-
-      ! calculate a lookup table for the temperature-enthalpy conversion of soil
-      ! NOTE: L is the integral of soil Clapeyron equation liquid water matric potential from temperature
-      !       multiply by Cp_liq*iden_water to get temperature component of enthalpy
-      if(needLookup)then
-        call T2L_lookup_soil(gru_struc(iGRU)%hruInfo(iHRU)%nSoil,   &   ! intent(in):    number of soil layers
-                        summa_struct(1)%mparStruct%gru(iGRU)%hru(iHRU),        &   ! intent(in):    parameter data structure
-                        summa_struct(1)%lookupStruct%gru(iGRU)%hru(iHRU),      &   ! intent(inout): lookup table data structure
-                        err,message)                              ! intent(out):   error control
-        if(err/=0)then; print*, message; return; endif
-      endif
-else
-      ! calculate a look-up table for the temperature-enthalpy conversion
-      call E2T_lookup(summa_struct(1)%mparStruct%gru(iGRU)%hru(iHRU),err,message)
-      if(err/=0)then; message=trim(message); print*, message; return; endif
-
-#endif
-      ! overwrite the vegetation height
-      HVT(summa_struct(1)%typeStruct%gru(iGRU)%hru(iHRU)%var(iLookTYPE%vegTypeIndex)) = summa_struct(1)%mparStruct%gru(iGRU)%hru(iHRU)%var(iLookPARAM%heightCanopyTop)%dat(1)
-      HVB(summa_struct(1)%typeStruct%gru(iGRU)%hru(iHRU)%var(iLookTYPE%vegTypeIndex)) = summa_struct(1)%mparStruct%gru(iGRU)%hru(iHRU)%var(iLookPARAM%heightCanopyBottom)%dat(1)
-         
-      ! overwrite the tables for LAI and SAI
-      if(model_decisions(iLookDECISIONS%LAI_method)%iDecision == specified)then
-        SAIM(summa_struct(1)%typeStruct%gru(iGRU)%hru(iHRU)%var(iLookTYPE%vegTypeIndex),:) = summa_struct(1)%mparStruct%gru(iGRU)%hru(iHRU)%var(iLookPARAM%winterSAI)%dat(1)
-        LAIM(summa_struct(1)%typeStruct%gru(iGRU)%hru(iHRU)%var(iLookTYPE%vegTypeIndex),:) = summa_struct(1)%mparStruct%gru(iGRU)%hru(iHRU)%var(iLookPARAM%summerLAI)%dat(1)*greenVegFrac_monthly
-      endif
-
-    end do ! HRU
-    
-    ! compute total area of the upstream HRUS that flow into each HRU
-    do iHRU=1,gru_struc(iGRU)%hruCount
-      summa_struct(1)%upArea%gru(iGRU)%hru(iHRU) = 0._rkind
-      do jHRU=1,gru_struc(iGRU)%hruCount
-       ! check if jHRU flows into iHRU; assume no exchange between GRUs
-       if(summa_struct(1)%typeStruct%gru(iGRU)%hru(jHRU)%var(iLookTYPE%downHRUindex)==summa_struct(1)%typeStruct%gru(iGRU)%hru(iHRU)%var(iLookID%hruId))then
-        summa_struct(1)%upArea%gru(iGRU)%hru(iHRU) = summa_struct(1)%upArea%gru(iGRU)%hru(iHRU) + summa_struct(1)%attrStruct%gru(iGRU)%hru(jHRU)%var(iLookATTR%HRUarea)
-       endif   ! (if jHRU is an upstream HRU)
-      end do  ! jHRU
-    end do  ! iHRU
-  
-    ! identify the total basin area for a GRU (m2)  
-    summa_struct(1)%bvarStruct_init%gru(iGRU)%var(iLookBVAR%basin__totalArea)%dat(1) = 0._rkind
-    do iHRU=1,gru_struc(iGRU)%hruCount
-      summa_struct(1)%bvarStruct_init%gru(iGRU)%var(iLookBVAR%basin__totalArea)%dat(1) = &
-      summa_struct(1)%bvarStruct_init%gru(iGRU)%var(iLookBVAR%basin__totalArea)%dat(1) + summa_struct(1)%attrStruct%gru(iGRU)%hru(iHRU)%var(iLookATTR%HRUarea)
-    end do
-  
-  end do ! GRU
-
-
-
-
-
-
-  ! *****************************************************************************
-  ! Restart File
-  ! *****************************************************************************
-  ! define restart file path/name
-  if(STATE_PATH == '') then
-    restartFile = trim(SETTINGS_PATH)//trim(MODEL_INITCOND)
-  else
-    restartFile = trim(STATE_PATH)//trim(MODEL_INITCOND)
-  endif
-
- ! read initial conditions
-  call read_icond(restartFile,                        & ! intent(in):    name of initial conditions file
-                  num_gru,                            & ! intent(in):    number of response units
-                  summa_struct(1)%mparStruct,      & ! intent(in):    model parameters
-                  summa_struct(1)%progStruct_init, & ! intent(inout): model prognostic variables
-                  summa_struct(1)%bvarStruct_init, & ! intent(inout): model basin (GRU) variables
-                  summa_struct(1)%indxStruct_init, & ! intent(inout): model indices
-                  err,message)                          ! intent(out):   error control
-  if(err/=0)then; print*, message; return; endif
-
-  call check_icond(num_gru,                            &
-                   summa_struct(1)%progStruct_init, &  ! intent(inout): model prognostic variables
-                   summa_struct(1)%mparStruct,      & ! intent(in):    model parameters
-                   summa_struct(1)%indxStruct_init, & ! intent(inout): model indices
-                   err,message)                          ! intent(out):   error control
-  if(err/=0)then; print*, message; return; endif  
-end subroutine fileAccessActor_init_fortran
-
-subroutine defOutputFortran(handle_output_ncid, start_gru, num_gru, num_hru, &
-    file_gru, use_extention, file_extention_c, err) bind(C, name="defOutputFortran")
-  USE globalData,only:nGRUrun,nHRUrun
-  USE globalData,only:fileout,output_fileSuffix
-  USE globalData,only:ncid
-  USE globalData,only:integerMissing
-  USE globalData,only:iRunMode,iRunModeFull,iRunModeGRU,iRunModeHRU ! define the running modes
-  USE summaFileManager,only:OUTPUT_PATH,OUTPUT_PREFIX ! define output file
-  USE var_lookup,only:maxvarFreq ! maximum number of output files
-  USE def_output_module,only:def_output ! module to define model output
-  USE cppwrap_auxiliary,only:c_f_string           ! Convert C String to Fortran String
-  
-  implicit none
-
-  ! Dummy Variables
-  type(c_ptr),intent(in), value          :: handle_output_ncid
-  integer(c_int),intent(in)              :: start_gru
-  integer(c_int),intent(in)              :: num_gru
-  integer(c_int),intent(in)              :: num_hru
-  integer(c_int),intent(in)              :: file_gru
-  logical(c_bool),intent(in)             :: use_extention
-  character(kind=c_char,len=1),intent(in):: file_extention_c
-  integer(c_int),intent(out)             :: err
-  ! Local Variables
-  type(var_i),pointer                    :: output_ncid
-  character(len=128)                     :: fmtGruOutput ! a format string used to write start and end GRU in output file names
-  character(len=256)                     :: file_extention
-  character(len=256)                     :: message ! error message
-
-
-  call c_f_pointer(handle_output_ncid, output_ncid)
-  call c_f_string(file_extention_c,file_extention, 256)
-  file_extention = trim(file_extention)
-
-  output_fileSuffix = ''
-  if (output_fileSuffix(1:1) /= '_') output_fileSuffix='_'//trim(output_fileSuffix)
-  if (output_fileSuffix(len_trim(output_fileSuffix):len_trim(output_fileSuffix)) == '_') output_fileSuffix(len_trim(output_fileSuffix):len_trim(output_fileSuffix)) = ' '
-  select case (iRunMode)
-    case(iRunModeGRU)
-      ! left zero padding for startGRU and endGRU
-      write(fmtGruOutput,"(i0)") ceiling(log10(real(file_gru)+0.1))                      ! maximum width of startGRU and endGRU
-      fmtGruOutput = "i"//trim(fmtGruOutput)//"."//trim(fmtGruOutput)                   ! construct the format string for startGRU and endGRU
-      fmtGruOutput = "('_G',"//trim(fmtGruOutput)//",'-',"//trim(fmtGruOutput)//")"
-      write(output_fileSuffix((len_trim(output_fileSuffix)+1):len(output_fileSuffix)),fmtGruOutput) start_gru,start_gru+num_gru-1
-      if (use_extention) then
-        output_fileSuffix = trim(output_fileSuffix)//trim(file_extention)
-      endif
-    case(iRunModeHRU)
-      write(output_fileSuffix((len_trim(output_fileSuffix)+1):len(output_fileSuffix)),"('_H',i0)") checkHRU
-  end select
-
-
-
-  nGRUrun = num_gru
-  nHRUrun = num_hru
-  fileout = trim(OUTPUT_PATH)//trim(OUTPUT_PREFIX)//trim(output_fileSuffix)
-  ncid(:) = integerMissing
-  call def_output(summaVersion,buildTime,gitBranch,gitHash,num_gru,num_hru,&
-      gru_struc(1)%hruInfo(1)%nSoil,fileout,err,message)
-  if(err/=0)then; print*,trim(message); return; endif
-  ! allocate space for the output file ID array
-  if (.not.allocated(output_ncid%var))then
-    allocate(output_ncid%var(maxVarFreq))
-    output_ncid%var(:) = integerMissing
-  endif
-  ! copy ncid
-  output_ncid%var(:) = ncid(:)
-
-
-end subroutine defOutputFortran
-
-
-subroutine FileAccessActor_DeallocateStructures(handle_forcFileInfo, handle_ncid) bind(C,name="FileAccessActor_DeallocateStructures")
-  USE netcdf_util_module,only:nc_file_close 
-  USE globalData,only:structInfo                              ! information on the data structures
-  USE access_forcing_module,only:forcingDataStruct
-  USE access_forcing_module,only:vectime
-  USE output_structure_module,only:outputTimeStep
-  USE var_lookup,only:maxvarFreq                ! maximum number of output files
-  implicit none
-  type(c_ptr),intent(in), value        :: handle_forcFileInfo
-  type(c_ptr),intent(in), value        :: handle_ncid
-  type(var_i),pointer                  :: ncid
-
-  type(file_info_array), pointer       :: forcFileInfo
-  integer(i4b)                         :: iFreq
-  character(LEN=256)                   :: cmessage
-  character(LEN=256)                   :: message
-  integer(i4b)                         :: err
-
-  call c_f_pointer(handle_ncid, ncid)
-  call c_f_pointer(handle_forcFileInfo, forcFileInfo)
-
-
-  ! close the open output FIle
-  do iFreq=1,maxvarFreq
-    if (ncid%var(iFreq)/=integerMissing) then
-      call nc_file_close(ncid%var(iFreq),err,cmessage)
-      if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
-    endif   
-  end do
-  
-  deallocate(forcFileInfo)
-  deallocate(ncid)
-  deallocate(outputTimeStep)
-end subroutine FileAccessActor_DeallocateStructures
-
-! **************************************************************************************************
-! private subroutine SOIL_VEG_GEN_PARM: Read soil, vegetation and other model parameters (from NOAH)
-! **************************************************************************************************
-SUBROUTINE SOIL_VEG_GEN_PARM(FILENAME_VEGTABLE, FILENAME_SOILTABLE, FILENAME_GENERAL, MMINLU, MMINSL)
-  !-----------------------------------------------------------------
-  use module_sf_noahlsm, only : shdtbl, nrotbl, rstbl, rgltbl, &
-  &                        hstbl, snuptbl, maxalb, laimintbl, &
-  &                        bb, drysmc, f11, maxsmc, laimaxtbl, &
-  &                        emissmintbl, emissmaxtbl, albedomintbl, &
-  &                        albedomaxtbl, wltsmc, qtz, refsmc, &
-  &                        z0mintbl, z0maxtbl, &
-  &                        satpsi, satdk, satdw, &
-  &                        theta_res, theta_sat, vGn_alpha, vGn_n, k_soil, &  ! MPC add van Genutchen parameters
-  &                        fxexp_data, lvcoef_data, &
-  &                        lutype, maxalb, &
-  &                        slope_data, frzk_data, bare, cmcmax_data, &
-  &                        cfactr_data, csoil_data, czil_data, &
-  &                        refkdt_data, natural, refdk_data, &
-  &                        rsmax_data, salp_data, sbeta_data, &
-  &                        zbot_data, smhigh_data, smlow_data, &
-  &                        lucats, topt_data, slcats, slpcats, sltype
-
-  IMPLICIT NONE
-
-  CHARACTER(LEN=*), INTENT(IN) :: FILENAME_VEGTABLE, FILENAME_SOILTABLE, FILENAME_GENERAL
-  CHARACTER(LEN=*), INTENT(IN) :: MMINLU, MMINSL
-  integer :: LUMATCH, IINDEX, LC, NUM_SLOPE
-  integer :: ierr
-  INTEGER , PARAMETER :: OPEN_OK = 0
-
-  character*128 :: mess , message
-
-  !-----SPECIFY VEGETATION RELATED CHARACTERISTICS :
-  !             ALBBCK: SFC albedo (in percentage)
-  !                 Z0: Roughness length (m)
-  !             SHDFAC: Green vegetation fraction (in percentage)
-  !  Note: The ALBEDO, Z0, and SHDFAC values read from the following table
-  !          ALBEDO, amd Z0 are specified in LAND-USE TABLE; and SHDFAC is
-  !          the monthly green vegetation data
-  !             CMXTBL: MAX CNPY Capacity (m)
-  !             NROTBL: Rooting depth (layer)
-  !              RSMIN: Mimimum stomatal resistance (s m-1)
-  !              RSMAX: Max. stomatal resistance (s m-1)
-  !                RGL: Parameters used in radiation stress function
-  !                 HS: Parameter used in vapor pressure deficit functio
-  !               TOPT: Optimum transpiration air temperature. (K)
-  !             CMCMAX: Maximum canopy water capacity
-  !             CFACTR: Parameter used in the canopy inteception calculati
-  !               SNUP: Threshold snow depth (in water equivalent m) that
-  !                     implies 100% snow cover
-  !                LAI: Leaf area index (dimensionless)
-  !             MAXALB: Upper bound on maximum albedo over deep snow
-  !
-  !-----READ IN VEGETAION PROPERTIES FROM VEGPARM.TBL
-  !
-
-  OPEN(19, FILE=trim(FILENAME_VEGTABLE),FORM='FORMATTED',STATUS='OLD',IOSTAT=ierr)
-  IF(ierr .NE. OPEN_OK ) THEN
-  WRITE(message,FMT='(A)') &
-  'module_sf_noahlsm.F: soil_veg_gen_parm: failure opening VEGPARM.TBL'
-  CALL wrf_error_fatal ( message )
-  END IF
-
-  LUMATCH=0
-
-  FIND_LUTYPE : DO WHILE (LUMATCH == 0)
-  READ (19,*,END=2002)
-  READ (19,*,END=2002)LUTYPE
-  READ (19,*)LUCATS,IINDEX
-
-  IF(LUTYPE.EQ.MMINLU)THEN
-  WRITE( mess , * ) 'LANDUSE TYPE = ' // TRIM ( LUTYPE ) // ' FOUND', LUCATS,' CATEGORIES'
-  ! CALL wrf_message( mess )
-  LUMATCH=1
-  ELSE
-  ! call wrf_message ( "Skipping over LUTYPE = " // TRIM ( LUTYPE ) )
-  DO LC = 1, LUCATS+12
-  read(19,*)
-  ENDDO
-  ENDIF
-  ENDDO FIND_LUTYPE
-  ! prevent possible array overwrite, Bill Bovermann, IBM, May 6, 2008
-  IF ( SIZE(SHDTBL)       < LUCATS .OR. &
-  SIZE(NROTBL)       < LUCATS .OR. &
-  SIZE(RSTBL)        < LUCATS .OR. &
-  SIZE(RGLTBL)       < LUCATS .OR. &
-  SIZE(HSTBL)        < LUCATS .OR. &
-  SIZE(SNUPTBL)      < LUCATS .OR. &
-  SIZE(MAXALB)       < LUCATS .OR. &
-  SIZE(LAIMINTBL)    < LUCATS .OR. &
-  SIZE(LAIMAXTBL)    < LUCATS .OR. &
-  SIZE(Z0MINTBL)     < LUCATS .OR. &
-  SIZE(Z0MAXTBL)     < LUCATS .OR. &
-  SIZE(ALBEDOMINTBL) < LUCATS .OR. &
-  SIZE(ALBEDOMAXTBL) < LUCATS .OR. &
-  SIZE(EMISSMINTBL ) < LUCATS .OR. &
-  SIZE(EMISSMAXTBL ) < LUCATS ) THEN
-  CALL wrf_error_fatal('Table sizes too small for value of LUCATS in module_sf_noahdrv.F')
-  ENDIF
-
-  IF(LUTYPE.EQ.MMINLU)THEN
-  DO LC=1,LUCATS
-  READ (19,*)IINDEX,SHDTBL(LC),                        &
-  NROTBL(LC),RSTBL(LC),RGLTBL(LC),HSTBL(LC), &
-  SNUPTBL(LC),MAXALB(LC), LAIMINTBL(LC),     &
-  LAIMAXTBL(LC),EMISSMINTBL(LC),             &
-  EMISSMAXTBL(LC), ALBEDOMINTBL(LC),         &
-  ALBEDOMAXTBL(LC), Z0MINTBL(LC), Z0MAXTBL(LC)
-  ENDDO
-
-  READ (19,*)
-  READ (19,*)TOPT_DATA
-  READ (19,*)
-  READ (19,*)CMCMAX_DATA
-  READ (19,*)
-  READ (19,*)CFACTR_DATA
-  READ (19,*)
-  READ (19,*)RSMAX_DATA
-  READ (19,*)
-  READ (19,*)BARE
-  READ (19,*)
-  READ (19,*)NATURAL
-  ENDIF
-
-  2002 CONTINUE
-
-  CLOSE (19)
-  IF (LUMATCH == 0) then
-  CALL wrf_error_fatal ("Land Use Dataset '"//MMINLU//"' not found in VEGPARM.TBL.")
-  ENDIF
-
-  !
-  !-----READ IN SOIL PROPERTIES FROM SOILPARM.TBL
-  !
-  OPEN(19, FILE=trim(FILENAME_SOILTABLE),FORM='FORMATTED',STATUS='OLD',IOSTAT=ierr)
-  IF(ierr .NE. OPEN_OK ) THEN
-  WRITE(message,FMT='(A)') &
-  'module_sf_noahlsm.F: soil_veg_gen_parm: failure opening SOILPARM.TBL'
-  CALL wrf_error_fatal ( message )
-  END IF
-
-  WRITE(mess,*) 'INPUT SOIL TEXTURE CLASSIFICATION = ', TRIM ( MMINSL )
-  ! CALL wrf_message( mess )
-
-  LUMATCH=0
-
-  ! MPC add a new soil table
-  FIND_soilTYPE : DO WHILE (LUMATCH == 0)
-  READ (19,*)
-  READ (19,*,END=2003)SLTYPE
-  READ (19,*)SLCATS,IINDEX
-  IF(SLTYPE.EQ.MMINSL)THEN
-  WRITE( mess , * ) 'SOIL TEXTURE CLASSIFICATION = ', TRIM ( SLTYPE ) , ' FOUND', &
-  SLCATS,' CATEGORIES'
-  ! CALL wrf_message ( mess )
-  LUMATCH=1
-  ELSE
-  ! call wrf_message ( "Skipping over SLTYPE = " // TRIM ( SLTYPE ) )
-  DO LC = 1, SLCATS
-  read(19,*)
-  ENDDO
-  ENDIF
-  ENDDO FIND_soilTYPE
-  ! prevent possible array overwrite, Bill Bovermann, IBM, May 6, 2008
-  IF ( SIZE(BB    ) < SLCATS .OR. &
-  SIZE(DRYSMC) < SLCATS .OR. &
-  SIZE(F11   ) < SLCATS .OR. &
-  SIZE(MAXSMC) < SLCATS .OR. &
-  SIZE(REFSMC) < SLCATS .OR. &
-  SIZE(SATPSI) < SLCATS .OR. &
-  SIZE(SATDK ) < SLCATS .OR. &
-  SIZE(SATDW ) < SLCATS .OR. &
-  SIZE(WLTSMC) < SLCATS .OR. &
-  SIZE(QTZ   ) < SLCATS  ) THEN
-  CALL wrf_error_fatal('Table sizes too small for value of SLCATS in module_sf_noahdrv.F')
-  ENDIF
-
-  ! MPC add new soil table
-  select case(trim(SLTYPE))
-  case('STAS','STAS-RUC')  ! original soil tables
-  DO LC=1,SLCATS
-  READ (19,*) IINDEX,BB(LC),DRYSMC(LC),F11(LC),MAXSMC(LC),&
-  REFSMC(LC),SATPSI(LC),SATDK(LC), SATDW(LC),   &
-  WLTSMC(LC), QTZ(LC)
-  ENDDO
-  case('ROSETTA')          ! new soil table
-  DO LC=1,SLCATS
-  READ (19,*) IINDEX,&
-  ! new soil parameters (from Rosetta)
-  theta_res(LC), theta_sat(LC),        &
-  vGn_alpha(LC), vGn_n(LC), k_soil(LC), &
-  ! original soil parameters
-  BB(LC),DRYSMC(LC),F11(LC),MAXSMC(LC),&
-  REFSMC(LC),SATPSI(LC),SATDK(LC), SATDW(LC),   &
-  WLTSMC(LC), QTZ(LC)
-  ENDDO
-  case default
-  CALL wrf_message( 'SOIL TEXTURE IN INPUT FILE DOES NOT ' )
-  CALL wrf_message( 'MATCH SOILPARM TABLE'                 )
-  CALL wrf_error_fatal ( 'INCONSISTENT OR MISSING SOILPARM FILE' )
-  end select
-
-  2003 CONTINUE
-
-  CLOSE (19)
-
-  IF(LUMATCH.EQ.0)THEN
-  CALL wrf_message( 'SOIL TEXTURE IN INPUT FILE DOES NOT ' )
-  CALL wrf_message( 'MATCH SOILPARM TABLE'                 )
-  CALL wrf_error_fatal ( 'INCONSISTENT OR MISSING SOILPARM FILE' )
-  ENDIF
-
-  !
-  !-----READ IN GENERAL PARAMETERS FROM GENPARM.TBL
-  !
-  OPEN(19, FILE=trim(FILENAME_GENERAL),FORM='FORMATTED',STATUS='OLD',IOSTAT=ierr)
-  IF(ierr .NE. OPEN_OK ) THEN
-  WRITE(message,FMT='(A)') &
-  'module_sf_noahlsm.F: soil_veg_gen_parm: failure opening GENPARM.TBL'
-  CALL wrf_error_fatal ( message )
-  END IF
-
-  READ (19,*)
-  READ (19,*)
-  READ (19,*) NUM_SLOPE
-
-  SLPCATS=NUM_SLOPE
-  ! prevent possible array overwrite, Bill Bovermann, IBM, May 6, 2008
-  IF ( SIZE(slope_data) < NUM_SLOPE ) THEN
-  CALL wrf_error_fatal('NUM_SLOPE too large for slope_data array in module_sf_noahdrv')
-  ENDIF
-
-  DO LC=1,SLPCATS
-  READ (19,*)SLOPE_DATA(LC)
-  ENDDO
-
-  READ (19,*)
-  READ (19,*)SBETA_DATA
-  READ (19,*)
-  READ (19,*)FXEXP_DATA
-  READ (19,*)
-  READ (19,*)CSOIL_DATA
-  READ (19,*)
-  READ (19,*)SALP_DATA
-  READ (19,*)
-  READ (19,*)REFDK_DATA
-  READ (19,*)
-  READ (19,*)REFKDT_DATA
-  READ (19,*)
-  READ (19,*)FRZK_DATA
-  READ (19,*)
-  READ (19,*)ZBOT_DATA
-  READ (19,*)
-  READ (19,*)CZIL_DATA
-  READ (19,*)
-  READ (19,*)SMLOW_DATA
-  READ (19,*)
-  READ (19,*)SMHIGH_DATA
-  READ (19,*)
-  READ (19,*)LVCOEF_DATA
-  CLOSE (19)
-
-END SUBROUTINE SOIL_VEG_GEN_PARM
-
-end module cppwrap_fileAccess
diff --git a/build/source/file_access_actor/ffile_info.f90 b/build/source/file_access_actor/ffile_info.f90
deleted file mode 100755
index 02f1dfdfc36607f66309ac5c0cfaf0b6c52d57e4..0000000000000000000000000000000000000000
--- a/build/source/file_access_actor/ffile_info.f90
+++ /dev/null
@@ -1,401 +0,0 @@
-! SUMMA - Structure for Unifying Multiple Modeling Alternatives
-! Copyright (C) 2014-2020 NCAR/RAL; University of Saskatchewan; University of Washington
-!
-! This file is part of SUMMA
-!
-! For more information see: http://www.ral.ucar.edu/projects/summa
-!
-! This program is free software: you can redistribute it and/or modify
-! it under the terms of the GNU General Public License as published by
-! the Free Software Foundation, either version 3 of the License, or
-! (at your option) any later version.
-!
-! This program is distributed in the hope that it will be useful,
-! but WITHOUT ANY WARRANTY; without even the implied warranty of
-! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-! GNU General Public License for more details.
-!
-! You should have received a copy of the GNU General Public License
-! along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-module ffile_info_actors_module
-USE nrtype
-USE netcdf
-USE data_types
-USE actor_data_types,only:file_info_array
-USE globalData,only:integerMissing
-implicit none
-private
-public::ffile_info
-private::getAndSetVars
-private::popFileNames
-private::popForcStructVars
-private::getAndCheckDataStep
-contains
-
-
-
- ! ************************************************************************************************
- ! public subroutine ffile_info: read information on model forcing files
- ! ************************************************************************************************
-subroutine ffile_info(indxGRU,forcFileInfo,num_forcing_files,err,message)
-  ! used to read metadata on the forcing data file
-  USE ascii_util_module,only:file_open
-  USE ascii_util_module,only:linewidth
-  USE netcdf_util_module,only:nc_file_open           ! open netCDF file
-  USE netcdf_util_module,only:netcdf_err             ! netcdf error handling function
-  USE summaFileManager,only:SETTINGS_PATH            ! path for metadata files
-  USE summaFileManager,only:FORCING_PATH             ! path for forcing files
-  USE summaFileManager,only:FORCING_FILELIST         ! list of model forcing files
-  USE globalData,only:forc_meta                      ! forcing metadata
-  USE get_ixname_module,only:get_ixtime,get_ixforce  ! identify index of named variable
-  USE ascii_util_module,only:get_vlines              ! get a vector of non-comment lines
-  USE ascii_util_module,only:split_line              ! split a line into words
-  USE time_utils_module,only:extractTime
-  USE globalData,only:time_meta
-  USE allocspace_module,only:allocLocal
-  USE time_utils_module,only:extractTime     ! extract time info from units string
-  USE summaFileManager,only: SIM_START_TM, SIM_END_TM! time info from control file module
-  USE var_lookup,only:iLookTIME              ! named variables that identify indices in the time structures
-
-
-  implicit none
-  ! define input & output
-  integer(i4b),intent(in)                  :: indxGRU          
-  type(file_info_array),pointer,intent(in) :: forcFileInfo
-  integer(i4b),intent(out)                 :: num_forcing_files
-  integer(i4b),intent(out)                 :: err              ! error code
-  character(*),intent(inout)               :: message          ! error message
-  ! define local variables
-
-  ! netcdf file i/o related
-  integer(i4b)                             :: ncid             ! netcdf file id
-  integer(i4b)                             :: mode             ! netCDF file open mode
-  integer(i4b)                             :: dimId            ! netcdf dimension id
-  character(LEN=nf90_max_name)             :: varName          ! character array of netcdf variable name
-  integer(i4b)                             :: iNC              ! index of a variable in netcdf file
-  integer(i4b)                             :: nvar             ! number of variables in netcdf local attribute file
-  ! the rest
-  character(LEN=linewidth),allocatable     :: dataLines(:)     ! vector of lines of information (non-comment lines)
-  character(len=256)                       :: cmessage         ! error message for downwind routine
-  character(LEN=256)                       :: infile           ! input filename
-  integer(i4b)                             :: unt              ! file unit (free unit output from file_open)
-  integer(i4b)                             :: ivar             ! index of model variable
-  integer(i4b)                             :: iFile            ! counter for forcing files
-  integer(i4b)                             :: nFile            ! number of forcing files in forcing file list
-  integer(i4b)                             :: totalFiles       ! total number of forcing files defiend in the forcing file list
-  integer(i4b)                             :: startIndx        ! total number of forcing files defiend in the forcing file list
-  integer(i4b)                             :: file_nHRU        ! number of HRUs in current forcing file
-  integer(i4b)                             :: nForcing         ! number of forcing variables
-  real(dp)                                 :: dataStep_iFile   ! data step for a given forcing data file
-  logical(lgt)                             :: xist             ! .TRUE. if the file exists
-  ! Time Variables
-  type(var_i)                              :: startTime
-  type(var_i)                              :: forcingStart
-  type(var_i)                              :: finishTime
-  real(rkind)                              :: dsec,dsec_tz
-  integer(i4b)                             :: ffinfo_index
-  
-  ! Start procedure here
-  err=0; message="ffile_info/"
-  ! ------------------------------------------------------------------------------------------------------------------
-  ! (1) read from the list of forcing files
-  ! ------------------------------------------------------------------------------------------------------------------
-  
-  ! build filename for forcing-file list file
-  infile = trim(SETTINGS_PATH)//trim(FORCING_FILELIST)
-
-  ! open file
-  call file_open(trim(infile),unt,err,cmessage)
-  if(err/=0)then;message=trim(message)//trim(cmessage);print*,message;return;end if;
-
-  ! get a list of character strings from non-comment lines
-  call get_vlines(unt,dataLines,err,cmessage)
-  if(err/=0)then; err=20;message=trim(message)//trim(cmessage);print*,message;return;end if;
-
-  nFile = size(dataLines)
-    
-  ! allocate space for forcing information
-  if(allocated(forcFileInfo%ffile_list)) deallocate(forcFileInfo%ffile_list)
-  allocate(forcFileInfo%ffile_list(nFile), stat=err)
-  if(err/=0)then; err=20; message=trim(message)//'problem allocating space for forcFileInfo'; return; end if
-
-  ! poputate the forcingInfo structure with filenames
-  call popFileNames(forcFileInfo,dataLines,nFile,inFile,err,message)
-  if(err/=0)then; err=20; message=trim(message);print*,message;return;endif
-
-  ! close ascii file
-  close(unit=unt,iostat=err); if(err/=0)then;message=trim(message)//'problem closing forcing file list'; return; end if
-
-  ! ------------------------------------------------------------------------------------------------------------------
-  ! (2) pull descriptive information from netcdf forcing file and check number of HRUs in each forcing file matches nHRU
-  ! ------------------------------------------------------------------------------------------------------------------
-
-  ! get the number of forcing variables
-  nForcing = size(forc_meta)
-
-  ! loop through files, and read descriptive information from each file
-  do iFile=1,nFile
-
-    ! ensure allocatable structure components are deallocated
-    if(allocated(forcFileInfo%ffile_list(iFile)%data_id)) deallocate(forcFileInfo%ffile_list(iFile)%data_id)
-    if(allocated(forcFileInfo%ffile_list(iFile)%varName)) deallocate(forcFileInfo%ffile_list(iFile)%varName)
-
-    ! allocate space for structure components
-    allocate(forcFileInfo%ffile_list(iFile)%data_id(nForcing), forcFileInfo%ffile_list(iFile)%varName(nForcing), stat=err)
-    if(err/=0)then; err=41; message=trim(message)//"problemAllocateStructureElement"; return;endif;
-
-    ! initialize variable ids to missing
-    forcFileInfo%ffile_list(iFile)%data_id(:) = integerMissing
-
-    ! build filename for actual forcing file
-    infile = trim(FORCING_PATH)//trim(forcFileInfo%ffile_list(iFile)%filenmData)
-    ! check if file exists
-    inquire(file=trim(infile),exist=xist)
-    if(.not.xist)then;message=trim(message)//"FileNotFound[file='"//trim(infile)//"']";print*,message;err=10;return;endif;
-
-    ! open file
-    mode=nf90_NoWrite
-    call nc_file_open(trim(infile), mode, ncid, err, cmessage)
-    if(err/=0)then;message=trim(message)//trim(cmessage);print*,message;return;endif;
-
-    ! check how many variables are in the netCDF file
-    ! populate forcFileInfo with variable information
-    call getAndSetVars(ncid,forcFileInfo,iFile,nVar,err,cmessage)
-
-    ! inquire nhru dimension size
-    err = nf90_inq_dimid(ncid,'hru',dimId);                 if(err/=0)then; message=trim(message)//'cannot find dimension hru'; return; endif
-    err = nf90_inquire_dimension(ncid,dimId,len=file_nHRU); if(err/=0)then; message=trim(message)//'cannot read dimension hru'; return; endif
-
-    ! inquire time dimension size
-    err = nf90_inq_dimid(ncid,'time',dimId);                                     if(err/=0)then; message=trim(message)//'cannot find dimension time'; return; end if
-    err = nf90_inquire_dimension(ncid,dimId,len=forcFileInfo%ffile_list(iFile)%nTimeSteps); if(err/=0)then; message=trim(message)//'cannot read dimension time'; return; end if
-
-    ! loop through all variables in netcdf file, check to see if everything needed to run the model exists and data_step is correct
-    do iNC=1,nVar
-
-      ! inquire about current variable name, type, number of dimensions
-      err = nf90_inquire_variable(ncid,iNC,name=varName)
-      if(err/=0)then; message=trim(message)//'problem inquiring variable: '//trim(varName); return; end if
-
-      ! process variable
-      select case(trim(varName))
-
-        ! if variable is in the forcing vector
-        case('time','pptrate','SWRadAtm','LWRadAtm','airtemp','windspd','airpres','spechum')
-          
-          call popForcStructVars(ncid,forcFileInfo,iFile,iNC,varName,err,message)
-          if(err/=0)then;print*,message;return;endif
-
-        case('data_step' )
-
-          call getAndCheckDataStep(ncid,dataStep_iFile,iFile,err,message)
-          if(err/=0)then;print*,message;return;endif
-          
-        ! HRU id -- required
-        case('hruId')
-          
-          call setHRUID(ncid,indxGRU,varName,inFile,err,message)
-          if(err/=0)then;print*,message;return;endif
-       
-        ! OK to have additional variables in the forcing file that are not used
-        case default; cycle
-      end select  ! select variable name
-    end do ! (end of netcdf file variable loop)
-
-    ! check to see if any forcing variables are missed
-    if(any(forcFileInfo%ffile_list(iFile)%data_id(:)==integerMissing))then
-      do iVar=1,size(forcFileInfo%ffile_list(iFile)%data_id)
-        if(forcFileInfo%ffile_list(iFile)%data_id(iVar)==integerMissing)then; err=40; message=trim(message)//"variable missing [var='"//trim(forcFileInfo%ffile_list(iFile)%varname(iVar))//"']"; return; end if
-      end do
-    end if
-
-    ! close file
-    err = nf90_close(ncid)
-    if(err/=nf90_noerr)then
-      message=trim(message)//'trouble closing file '//trim(infile)
-      print*, message
-      return
-    endif
-
-  end do ! (loop through files)
-
-  ! Get the number of forcing files we have
-  num_forcing_files = size(forcFileInfo%ffile_list(:))
-end subroutine ffile_info
-
-
-  ! check how many variables are in the netCDF file
-  ! populate forcFileInfo with variable information
-subroutine getAndSetVars(ncid,forcFileInfo,iFile,nVar,err,message)
-  USE netCDF
-  USE netcdf_util_module,only:netcdf_err
-  USE globalData,only:integerMissing
-
-  implicit none
-  integer(i4b),intent(in)                             :: ncid
-  type(file_info_array),pointer,intent(in)            :: forcFileInfo
-  integer(i4b),intent(in)                             :: iFile
-  integer(i4b),intent(out)                            :: nVar
-  integer(i4b),intent(out)                            :: err
-  character(*),intent(inout)                          :: message
-  
-  ! how many variables are there?
-  err = nf90_inquire(ncid, nvariables=nVar)
-  call netcdf_err(err,message); if (err/=0) return
-
-  ! set nVar attribute
-  forcFileInfo%ffile_list(iFile)%nVars = nVar
-  if(allocated(forcFileInfo%ffile_list(iFile)%var_ix))then;print*,"Already Allocated";endif;
-  ! allocate space
-  allocate(forcFileInfo%ffile_list(iFile)%var_ix(nVar), stat=err)
-  if(err/=0)then;message=trim(message)//'problem allocating space for structure element';print*,message;err=20;return;endif;
-
-  ! initialize data structure
-  forcFileInfo%ffile_list(iFile)%var_ix(:) = integerMissing
-
-
-end subroutine getAndSetVars
-
-! Private subroutine that filles the array of forcing files with the names
-! of the forcing files
-subroutine popFileNames(forcFileInfo,dataLines,nFile,inFile,err,message)
-  USE ascii_util_module,only:linewidth
-  implicit none
-
-  type(file_info_array),pointer                       :: forcFileInfo
-  character(*),intent(out)                            :: dataLines(:) ! forcingFileList
-  integer(i4b),intent(in)                             :: nFile        ! number of forcing files
-  character(*),intent(inout)                          :: inFile       ! file that populated dataLines
-  integer(i4b),intent(out)                            :: err
-  character(*),intent(inout)                          :: message
-  ! local variables
-  character(LEN=256)                                  :: filenameData     ! name of forcing datafile
-  integer(i4b)                                        :: iFile
-
-  do iFile=1,nFile
-    ! split the line into "words" (expect one word: the file describing forcing data for that index)
-    read(dataLines(iFile),*,iostat=err) filenameData
-    if(err/=0)then; message=trim(message)//'problem reading a line of data from file ['//trim(infile)//']'; return; end if
-    ! set forcing file name attribute
-    forcFileInfo%ffile_list(iFile)%filenmData = trim(filenameData)
-  end do  ! (looping through files)
-
-
-end subroutine popFileNames
-
-! populate the variable indexes and names in ffile_list
-subroutine popForcStructVars(ncid,forcFileInfo,iFile,iNC,varName,err,message)
-  USE get_ixname_module,only:get_ixforce  ! identify index of named variable
-  USE netCDF
-  implicit none
-  integer(i4b),intent(in)                              :: ncid
-  type(file_info_array),pointer                        :: forcFileInfo
-  integer(i4b),intent(in)                              :: iFile
-  integer(i4b),intent(in)                              :: iNC ! index of a variable in netcdf file
-  character(*),intent(in)                              :: varName
-  integer(i4b),intent(out)                             :: err
-  character(*),intent(inout)                           :: message
-  ! local variables
-  integer(i4b)                                         :: iVar
-  
-  
-  ! get variable index
-  ivar = get_ixforce(trim(varname))
-  if(ivar < 0)then
-    err=40
-    message=trim(message)//"variableNotFound[var="//trim(varname)//"]"
-    return
-  end if
-  if(ivar>size(forcFileInfo%ffile_list(iFile)%data_id))then
-    err=35
-    message=trim(message)//"indexOutOfRange[var="//trim(varname)//"]"
-    return
-  end if
-
-  ! put netcdf file variable index in the forcing file metadata structure
-  err = nf90_inq_varid(ncid, trim(varName), forcFileInfo%ffile_list(iFile)%data_id(ivar))
-  if(err/=0)then; message=trim(message)//"problem inquiring forcing variable[var="//trim(varName)//"]"; return; end if
-
-  ! put variable index of the forcing structure in the metadata structure
-  if(trim(varName)/='time')then
-    forcFileInfo%ffile_list(iFile)%var_ix(iNC)   = ivar
-    forcFileInfo%ffile_list(iFile)%varName(ivar) = trim(varName)
-
-  ! get first time from file, place into forcFileInfo
-  else
-    err = nf90_get_var(ncid,forcFileInfo%ffile_list(iFile)%data_id(ivar),forcFileInfo%ffile_list(iFile)%firstJulDay,start=(/1/))
-    if(err/=0)then; message=trim(message)//'problem reading first Julian day'; return; end if
-  end if  ! if the variable name is time
-
-end subroutine popForcStructVars
-
-! set the datastep from the first file
-! check every file has the same data_step
-subroutine getAndCheckDataStep(ncid,dataStep_iFile,iFile,err,message)
-  USE globalData,only:data_step
-  USE netCDF
-  implicit none
-  integer(i4b),intent(in)                           :: ncid
-  real(dp),intent(out)                              :: dataStep_iFile   ! data step for a given forcing data file
-  integer(i4b),intent(in)                           :: iFile            ! index of current forcing file
-  integer(i4b),intent(out)                          :: err
-  character(*),intent(inout)                        :: message
-  ! local variables
-  integer(i4b)                                      :: varid            ! netcdf variable id
-                                      
-  ! read data_step from netcdf file
-  err = nf90_inq_varid(ncid, "data_step", varId); if(err/=0)then; message=trim(message)//'cannot find data_step'; return; end if
-  err = nf90_get_var(ncid,varid,dataStep_iFile);  if(err/=0)then; message=trim(message)//'cannot read data_step'; return; end if
-
-  ! check data_step is the same for all forcing files
-  if(iFile == 1)then
-    data_step = dataStep_iFile
-  else
-    if(abs(dataStep_iFile - data_step) > epsilon(dataStep_iFile))then
-    write(message,'(a,i0,a)') trim(message)//'data step for forcing file ',iFile,'differs from the datastep of the first forcing file'
-    err=20; return
-    end if
-  end if
-
-end subroutine getAndCheckDataStep
-
-! get the HRU_ID from the forcing file
-! populate the gru_struc with the HRU ID
-! Check if the hru is expected
-subroutine setHRUID(ncid,indxGRU,varName,inFile,err,message)
-  USE globalData,only:gru_struc                      ! gru-hru mapping structure
-  USE netCDF
-  implicit none
-  integer(i4b),intent(in)                           :: ncid
-  integer(i4b),intent(in)                           :: indxGRU
-  character(*),intent(in)                           :: varName
-  character(*),intent(in)                           :: inFile       ! file that populated dataLines
-  integer(i4b),intent(out)                          :: err
-  character(*),intent(inout)                        :: message
-  ! local variables 
-  integer(i4b)                                      :: localHRU_ix      ! index of HRU
-  integer(i4b)                                      :: varid            ! netcdf variable id
-  integer(8)                                        :: ncHruId(1)       ! hruID from the forcing files
-
-
-  ! check to see if hruId exists as a variable, this is a required variable
-  err = nf90_inq_varid(ncid,trim(varname),varId)
-  if(err/=0)then; message=trim(message)//'hruID variable not present'; return; endif
-
-  ! check that the hruId is what we expect
-  ! NOTE: we enforce that the HRU order in the forcing files is the same as in the zLocalAttributes files (too slow otherwise)
-  do localHRU_ix=1,gru_struc(indxGRU)%hruCount
-    ! check the HRU is what we expect
-    err = nf90_get_var(ncid,varId,ncHruId,start=(/gru_struc(indxGRU)%hruInfo(localHRU_ix)%hru_nc/),count=(/1/))
-    if(gru_struc(indxGRU)%hruInfo(localHRU_ix)%hru_id /= ncHruId(1))then
-      write(message,'(a,i0,a,i0,a,i0,a,a)') trim(message)//'hruId for global HRU: ',gru_struc(indxGRU)%hruInfo(localHRU_ix)%hru_nc,' - ',  &
-          ncHruId(1), ' differs from the expected: ',gru_struc(indxGRU)%hruInfo(localHRU_ix)%hru_id, ' in file ', trim(infile)
-      write(message,'(a)') trim(message)//' order of hruId in forcing file needs to match order in zLocalAttributes.nc'
-      err=40; return
-    endif
-  end do
-
-end subroutine
-
-end module ffile_info_actors_module
diff --git a/build/source/file_access_actor/fileAccess_writeOutput.f90 b/build/source/file_access_actor/fileAccess_writeOutput.f90
index d9745cf2dd0df5758dd91766779b41d41326e1f8..bff869754962029a0eaaf7212453c0e42ad2e51b 100644
--- a/build/source/file_access_actor/fileAccess_writeOutput.f90
+++ b/build/source/file_access_actor/fileAccess_writeOutput.f90
@@ -436,10 +436,13 @@ subroutine writeData(ncid,outputTimestep,outputTimestepUpdate,maxLayers,nSteps,
 
         ! stats output: only scalar variable type
         if(meta(iVar)%varType==iLookVarType%scalarv) then
-          call writeScalar(ncid, outputTimeStep, outputTimeStepUpdate, nSteps, minGRU, maxGRU, numGRU, iFreq, iVar, meta, stat, map, err, message)
+          call writeScalar(ncid, outputTimeStep, outputTimeStepUpdate, nSteps, &
+                           minGRU, maxGRU, numGRU, iFreq, iVar, meta, stat,    &
+                           map, err, message)
         else ! non-scalar variables: regular data structures
-          call writeVector(ncid, outputTimeStep, maxLayers, nSteps, minGRU, maxGRU, numGRU, iFreq, iVar, meta, dat, &
-            indx, err, message)
+          call writeVector(ncid, outputTimeStep, maxLayers, nSteps, minGRU, &
+                           maxGRU, numGRU, iFreq, iVar, meta, dat, indx,    &
+                           err, message)
         end if ! not scalarv
 
       ! process error code
diff --git a/build/source/file_access_actor/file_access_actor.cpp b/build/source/file_access_actor/file_access_actor.cpp
index 0b2ededc077e37daedb6a79a44ab59cecf87305e..eca8711f8860f8f3ee2f5d217111b5346026771a 100644
--- a/build/source/file_access_actor/file_access_actor.cpp
+++ b/build/source/file_access_actor/file_access_actor.cpp
@@ -1,23 +1,25 @@
 #include "file_access_actor.hpp"
 
 using json = nlohmann::json;
-
-namespace caf {
+using namespace caf;
 
 behavior file_access_actor(stateful_actor<file_access_state>* self, 
-    NumGRUInfo num_gru_info,
-    File_Access_Actor_Settings file_access_actor_settings, actor parent) {
+                           NumGRUInfo num_gru_info,
+                           File_Access_Actor_Settings file_access_actor_settings, 
+                           actor parent) {
   aout(self) << "\n----------File_Access_Actor Started----------\n";
+
+  self->set_exit_handler([=](const caf::exit_msg& em) {
+    aout(self) << "File Access Actor: Received Exit Message\n";
+  });
     
   // Set Up timing Info we wish to track
   self->state.file_access_timing = TimingInfo();
-  self->state.file_access_timing.addTimePoint("read_duration");
   self->state.file_access_timing.addTimePoint("write_duration");
   // Save the parameters passed from job_actor
   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,141 +29,98 @@ 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);
-
-  // 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;
-  }
-
-  // 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);
-  }
-
-  // initialize vecs for keeping track of each hru's timestep and checkpoint
-  for (int i = 1; i < self->state.num_gru +1; ++i) {
-      self->state.hru_timesteps.push_back(0);
-      self->state.hru_checkpoints.push_back(0);
-  } 
+  return {
+    [=](init_file_access_actor, int file_gru) {
+      aout(self) << "File Access Actor: Intializing\n";
+      auto& fa_settings = self->state.file_access_actor_settings;
+      int num_hru = self->state.num_gru;
+      
+      // Get the information about the forcing files
+      self->state.forcing_files = std::make_unique<forcingFileContainer>();
+      if (self->state.forcing_files->initForcingFiles() != 0) return -1;
 
+      int err = 0;
+      std::unique_ptr<char[]> message(new char[256]);
+      fileAccessActor_init_fortran(&self->state.num_steps,
+                                   &fa_settings.num_timesteps_in_output_buffer, 
+                                   &self->state.num_gru, &err, &message);
+      if (err != 0) {
+        aout(self) << "\n\nERROR: fileAccessActor_init_fortran() - " 
+                   << message.get() << "\n\n";
+        return -1;
+      }
+   
+      // 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,
-          actor_address.c_str(), &err);
-      if (err != 0) {
-        aout(self) << "ERROR: Defining Output\n";
-        self->quit();
-      }
+                       &self->state.num_gru, &num_hru, &file_gru, 
+                       &self->state.num_gru_info.use_global_for_data_structures,
+                       actor_address.c_str(), &err);
+      if (err != 0) return -1;
+
+      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) {
-        // Note: C++ starts at 0 and Fortran starts at 1
-        if(!self->state.forcing_file_list[currentFile - 1].isFileLoaded()) {
-          self->state.file_access_timing.updateStartPoint("read_duration");
-          int err = 0;
-          read_forcingFile(self->state.handle_forcing_file_info, &currentFile,
-              &self->state.stepsInCurrentFile, &self->state.start_gru, 
-              &self->state.num_gru, &err);
-          if (err != 0) {
-            aout(self) << "ERROR: Reading Forcing" << std::endl;
-          }
-          self->state.filesLoaded += 1;
-          self->state.forcing_file_list[currentFile - 1]
-              .updateNumSteps(self->state.stepsInCurrentFile);
-
-          self->state.file_access_timing.updateEndPoint("read_duration");
-          // Check if all files have been loaded
-          if(self->state.filesLoaded <= self->state.numFiles) {
-            self->send(self, access_forcing_internal_v, currentFile + 1);
-          }
-        }
-        
+    [=](access_forcing, int iFile, caf::actor refToRespondTo) {
+      if (self->state.forcing_files->allFilesLoaded()) {
         self->send(refToRespondTo, new_forcing_file_v, 
-            self->state.forcing_file_list[currentFile - 1].getNumSteps(),
-            currentFile);
-        } else {
-          aout(self) << currentFile << " exceeds the number of forcing files\n"; 
-        }
-    },
-        
-    [=](access_forcing_internal, int currentFile) {
-      if (self->state.filesLoaded <= self->state.numFiles &&
-          currentFile <= self->state.numFiles) {
-        
-        if (self->state.forcing_file_list[currentFile - 1].isFileLoaded()) {
-          aout(self) << "Unexpected File Loaded!!\n";
-        }
+          self->state.forcing_files->getNumSteps(iFile), iFile);
+        return;
+      }
+      auto err = self->state.forcing_files->
+          loadForcingFile(iFile, self->state.start_gru, self->state.num_gru);
+      if (err != 0) {
+        aout(self) << "ERROR: Reading Forcing\n";
+        self->quit();
+        return;
+      }
       
-        self->state.file_access_timing.updateStartPoint("read_duration");
-        int err = 0;
-        read_forcingFile(self->state.handle_forcing_file_info, &currentFile,
-            &self->state.stepsInCurrentFile, &self->state.start_gru, 
-            &self->state.num_gru, &err);
-        if (err != 0) {
-          aout(self) << "ERROR: Reading Forcing" << std::endl;
-        }
-        
-        self->state.filesLoaded += 1;
-        self->state.forcing_file_list[currentFile - 1]
-            .updateNumSteps(self->state.stepsInCurrentFile);
-          
-        self->state.file_access_timing.updateEndPoint("read_duration");
-        self->send(self, access_forcing_internal_v, currentFile + 1);
-      } else {
-        aout(self) << "All Forcing Files Loaded \n";
+      // Load files behind the scenes
+      self->send(self, access_forcing_internal_v, iFile + 1);
+      self->send(refToRespondTo, new_forcing_file_v, 
+                 self->state.forcing_files->getNumSteps(iFile), iFile);
+    },
+
+    // Internal message to load the forcing files in the background    
+    [=](access_forcing_internal, int iFile) {
+      if (self->state.forcing_files->allFilesLoaded()) {
+        return;
       }
+      auto err = self->state.forcing_files->loadForcingFile(iFile, 
+          self->state.start_gru, self->state.num_gru);
+      if (err != 0) {
+        aout(self) << "ERROR: Reading Forcing Internal\n";
+        self->quit();
+        return;
+      }
+      self->send(self, access_forcing_internal_v, iFile + 1);
     },
         
     // Number of steps an HRU can compute before needing to write
-    [=] (get_num_output_steps) { return self->state.num_output_steps; },
+    [=] (get_num_output_steps) { 
+      return self->state.num_output_steps; 
+    },
 
     [=](write_output, int index_gru, int index_hru, caf::actor hru_actor) {
       self->state.file_access_timing.updateStartPoint("write_duration");
@@ -178,35 +137,40 @@ behavior file_access_actor(stateful_actor<file_access_state>* self,
       self->state.file_access_timing.updateEndPoint("write_duration");
     },
 
-    [=] (write_restart, int gru, int gru_timestep, int gru_checkpoint, int output_stucture_index, int year, int month, int day, int hour){
-    // update hru progress vecs 
-    int gru_index = abs(self->state.start_gru - gru); 
-    self->state.hru_timesteps[gru_index] = gru_timestep;
-    self->state.hru_checkpoints[gru_index] = gru_checkpoint;
-
-    // find slowest time step of all hrus in job, stored in self->state.hru_timesteps
-    int slowest_timestep = *std::min_element(self->state.hru_timesteps.begin(), self->state.hru_timesteps.end());  
-    int slowest_checkpoint = *std::min_element(self->state.hru_checkpoints.begin(), self->state.hru_checkpoints.end());  
-
-    // if the slowest hru is past the ith checkpoint (current threshold)            
-    if ( slowest_checkpoint >= (self->state.completed_checkpoints)){// temp for dubuging
-        Output_Partition *output_partition = self->state.output_container->getOutputPartition(gru-1);
-        writeRestart(self, output_partition, self->state.start_gru, self->state.hru_timesteps.size(), output_stucture_index,
+    [=] (write_restart, int gru, int gru_timestep, int gru_checkpoint, 
+         int output_stucture_index, int year, int month, int day, int hour){
+      // update hru progress vecs 
+      int gru_index = abs(self->state.start_gru - gru); 
+      self->state.hru_timesteps[gru_index] = gru_timestep;
+      self->state.hru_checkpoints[gru_index] = gru_checkpoint;
+
+      // find slowest time step of all hrus in job, stored in self->state.hru_timesteps
+      int slowest_timestep = *std::min_element(
+          self->state.hru_timesteps.begin(), 
+          self->state.hru_timesteps.end());  
+      int slowest_checkpoint = *std::min_element(
+          self->state.hru_checkpoints.begin(), 
+          self->state.hru_checkpoints.end());  
+
+      // if the slowest hru is past the ith checkpoint (current threshold)            
+      if ( slowest_checkpoint >= (self->state.completed_checkpoints)){// temp for dubuging
+        Output_Partition *output_partition = 
+            self->state.output_container->getOutputPartition(gru-1);
+        writeRestart(self, output_partition, self->state.start_gru, 
+                     self->state.hru_timesteps.size(), output_stucture_index,
                      year, month, day, hour);
         // update checkpint counter
         self->state.completed_checkpoints++;
-    }
-},
-
+      }
+    },
 
     // Write message from the job actor TODO: This could be async
     [=](write_output, int steps_to_write, int start_gru, int max_gru) {
       self->state.file_access_timing.updateStartPoint("write_duration");
       int err = 0;
-      writeOutput_fortran(self->state.handle_ncid, &steps_to_write,
-          &start_gru, &max_gru, &self->state.write_params_flag, &err);
-      if (self->state.write_params_flag) 
-        self->state.write_params_flag = false;
+      writeOutput_fortran(self->state.handle_ncid, &steps_to_write, &start_gru, 
+                          &max_gru, &self->state.write_params_flag, &err);
+      if (self->state.write_params_flag) self->state.write_params_flag = false;
       self->state.file_access_timing.updateEndPoint("write_duration");
       return err;
     },
@@ -217,7 +181,7 @@ behavior file_access_actor(stateful_actor<file_access_state>* self,
 
     [=](run_failure, int local_gru_index) {
       self->state.file_access_timing.updateStartPoint("write_duration");
-
+      aout(self) << "File Access Actor: GRU Failed: " << local_gru_index << "\n";
       Output_Partition *output_partition = 
           self->state.output_container->getOutputPartition(local_gru_index);
         
@@ -234,16 +198,17 @@ behavior file_access_actor(stateful_actor<file_access_state>* self,
       aout(self) << "File Access Actor: Deallocating Structures\n";
       // TODO: output container can be wrapped in a smart pointer
       if (!self->state.num_gru_info.use_global_for_data_structures) {
-        self->state.output_container->~Output_Container();
+        delete self->state.output_container;
       }
-      FileAccessActor_DeallocateStructures(self->state.handle_forcing_file_info, 
-          self->state.handle_ncid);
+
+      FileAccessActor_DeallocateStructures(self->state.handle_ncid);
+
+
 
       aout(self) << "\n________________" 
                  << "FILE_ACCESS_ACTOR TIMING INFO RESULTS________________\n"
                  << "Total Read Duration = "
-                 << self->state.file_access_timing.getDuration("read_duration")
-                     .value_or(-1.0) << " Seconds\n"
+                 << self->state.forcing_files->getReadDuration() << " Seconds\n"
                  << "Total Write Duration = "
                  << self->state.file_access_timing.getDuration("write_duration")
                      .value_or(-1.0) << " Seconds\n"
@@ -251,24 +216,24 @@ behavior file_access_actor(stateful_actor<file_access_state>* self,
            
         
       self->quit();
-      return std::make_tuple(self->state.file_access_timing
-          .getDuration("read_duration").value_or(-1.0), 
-          self->state.file_access_timing
-          .getDuration("write_duration").value_or(-1.0));
+      return std::make_tuple(self->state.forcing_files->getReadDuration(),
+                             self->state.file_access_timing
+                             .getDuration("write_duration").value_or(-1.0));
     },
   };
 }
 
 
 void writeOutput(stateful_actor<file_access_state>* self, 
-    Output_Partition* partition) {              
+                 Output_Partition* partition) {              
   int num_timesteps_to_write = partition->getNumStoredTimesteps();
   int start_gru = partition->getStartGRUIndex();
   int max_gru = partition->getMaxGRUIndex();
   bool write_param_flag = partition->isWriteParams();
   int err = 0;
+  // aout(self) << "Writing Output\n";
   writeOutput_fortran(self->state.handle_ncid, &num_timesteps_to_write,
-      &start_gru, &max_gru, &write_param_flag, &err);
+                      &start_gru, &max_gru, &write_param_flag, &err);
   
   partition->updateTimeSteps();
 
@@ -278,20 +243,19 @@ void writeOutput(stateful_actor<file_access_state>* self,
   
   for (int i = 0; i < hrus_to_update.size(); i++) {
     self->send(hrus_to_update[i], num_steps_before_write_v, 
-        num_steps_before_next_write);
+               num_steps_before_next_write);
     self->send(hrus_to_update[i], run_hru_v);
   }
 
   partition->resetReadyToWriteList();
 }
 
-void writeRestart(stateful_actor<file_access_state>* self , Output_Partition* partition, 
-  int start_gru, int num_gru, int timestep,
-  int year, int month, int day, int hour){  
+void writeRestart(stateful_actor<file_access_state>* self , 
+                  Output_Partition* partition, int start_gru, int num_gru, 
+                  int timestep, int year, int month, int day, int hour){  
   
   writeRestart_fortran(self->state.handle_ncid, &start_gru, &num_gru, &timestep, 
-    &year, &month, &day, &hour, &self->state.err);
-  }
+                       &year, &month, &day, &hour, &self->state.err);
+}
 
 
-} // end namespace
\ No newline at end of file
diff --git a/build/source/file_access_actor/file_access_actor.f90 b/build/source/file_access_actor/file_access_actor.f90
new file mode 100644
index 0000000000000000000000000000000000000000..10bd87dfef8affba86239b2529bbdb34fd18436c
--- /dev/null
+++ b/build/source/file_access_actor/file_access_actor.f90
@@ -0,0 +1,177 @@
+module file_access_actor
+
+
+  !======= Inclusions ===========
+  USE, intrinsic :: iso_c_binding
+  USE nrtype
+  USE data_types
+  USE actor_data_types
+  USE globalData
+  USE globalData,only:integerMissing      ! missing integer value
+  USE globalData,only:realMissing         ! missing double precision value
+
+
+
+  implicit none
+  public::fileAccessActor_init_fortran
+  public::defOutputFortran
+  public::FileAccessActor_DeallocateStructures
+
+  character(len=64), parameter     :: summaVersion = ''
+  character(len=64), parameter     :: buildTime = ''
+  character(len=64), parameter     :: gitBranch = ''
+  character(len=64), parameter     :: gitHash = ''
+  
+  contains
+
+! Call the fortran routines that read data in and are associtated with the forcing structure
+subroutine fileAccessActor_init_fortran(num_timesteps,& 
+    num_timesteps_output_buffer, num_gru, err, message_r) &
+    bind(C, name="fileAccessActor_init_fortran")
+  USE output_structure_module,only:initOutputStructure        ! module to initialize output structure
+  USE output_structure_module,only:initOutputTimeStep         ! module to initialize output timestep structure (tracks GRUs timestep for output)
+  USE C_interface_module,only:f_c_string_ptr  ! convert fortran string to c string
+  implicit none
+  ! Dummy Variables
+  integer(c_int),intent(out)             :: num_timesteps
+  integer(c_int),intent(in)              :: num_timesteps_output_buffer
+  integer(c_int),intent(out)             :: num_gru
+  integer(c_int),intent(out)             :: err
+  type(c_ptr),intent(out)                :: message_r
+  ! local Variables
+  character(len=256)                     :: message            ! error message for downwind routine
+
+
+  err=0; message="fileAccessActor_init_fortran/"
+  call f_c_string_ptr(trim(message), message_r)
+
+  ! TODO: This can be moved to a simple getter the file_access_actor calls
+  num_timesteps = numtim ! Returns to the file_access_actor
+
+  ! *****************************************************************************
+  ! *** Initialize output structure
+  ! *****************************************************************************
+  call initOutputStructure(num_timesteps_output_buffer, num_gru, err)
+  if(err/=0)then; call f_c_string_ptr(trim(message), message_r); return; endif
+
+  ! *****************************************************************************
+  ! *** Initialize output time step
+  ! *****************************************************************************
+  call initOutputTimeStep(num_gru, err)
+  if(err/=0)then; call f_c_string_ptr(trim(message), message_r); return; endif
+
+end subroutine fileAccessActor_init_fortran
+
+subroutine defOutputFortran(handle_output_ncid, start_gru, num_gru, num_hru, &
+    file_gru, use_extention, file_extention_c, err) bind(C, name="defOutputFortran")
+  USE globalData,only:nGRUrun,nHRUrun
+  USE globalData,only:fileout,output_fileSuffix
+  USE globalData,only:ncid
+  USE globalData,only:integerMissing
+  USE globalData,only:iRunMode,iRunModeFull,iRunModeGRU,iRunModeHRU ! define the running modes
+  USE summaFileManager,only:OUTPUT_PATH,OUTPUT_PREFIX ! define output file
+  USE var_lookup,only:maxvarFreq ! maximum number of output files
+  USE def_output_module,only:def_output ! module to define model output
+  USE cppwrap_auxiliary,only:c_f_string           ! Convert C String to Fortran String
+  
+  implicit none
+
+  ! Dummy Variables
+  type(c_ptr),intent(in), value          :: handle_output_ncid
+  integer(c_int),intent(in)              :: start_gru
+  integer(c_int),intent(in)              :: num_gru
+  integer(c_int),intent(in)              :: num_hru
+  integer(c_int),intent(in)              :: file_gru
+  logical(c_bool),intent(in)             :: use_extention
+  character(kind=c_char,len=1),intent(in):: file_extention_c
+  integer(c_int),intent(out)             :: err
+  ! Local Variables
+  type(var_i),pointer                    :: output_ncid
+  character(len=128)                     :: fmtGruOutput ! a format string used to write start and end GRU in output file names
+  character(len=256)                     :: file_extention
+  character(len=256)                     :: message ! error message
+
+
+  call c_f_pointer(handle_output_ncid, output_ncid)
+  call c_f_string(file_extention_c,file_extention, 256)
+  file_extention = trim(file_extention)
+
+  output_fileSuffix = ''
+  if (output_fileSuffix(1:1) /= '_') output_fileSuffix='_'//trim(output_fileSuffix)
+  if (output_fileSuffix(len_trim(output_fileSuffix):len_trim(output_fileSuffix)) == '_') output_fileSuffix(len_trim(output_fileSuffix):len_trim(output_fileSuffix)) = ' '
+  select case (iRunMode)
+    case(iRunModeGRU)
+      ! left zero padding for startGRU and endGRU
+      write(fmtGruOutput,"(i0)") ceiling(log10(real(file_gru)+0.1))                      ! maximum width of startGRU and endGRU
+      fmtGruOutput = "i"//trim(fmtGruOutput)//"."//trim(fmtGruOutput)                   ! construct the format string for startGRU and endGRU
+      fmtGruOutput = "('_G',"//trim(fmtGruOutput)//",'-',"//trim(fmtGruOutput)//")"
+      write(output_fileSuffix((len_trim(output_fileSuffix)+1):len(output_fileSuffix)),fmtGruOutput) start_gru,start_gru+num_gru-1
+      if (use_extention) then
+        output_fileSuffix = trim(output_fileSuffix)//trim(file_extention)
+      endif
+    case(iRunModeHRU)
+      write(output_fileSuffix((len_trim(output_fileSuffix)+1):len(output_fileSuffix)),"('_H',i0)") checkHRU
+  end select
+
+
+
+  nGRUrun = num_gru
+  nHRUrun = num_hru
+  fileout = trim(OUTPUT_PATH)//trim(OUTPUT_PREFIX)//trim(output_fileSuffix)
+  ncid(:) = integerMissing
+  call def_output(summaVersion,                  &
+                  buildTime,                     &
+                  gitBranch,                     &
+                  gitHash,                       &
+                  num_gru,                       &
+                  num_hru,                       &
+                  gru_struc(1)%hruInfo(1)%nSoil, &
+                  fileout,                       &
+                  err,message)
+  if(err/=0)then; print*,trim(message); return; endif
+  ! allocate space for the output file ID array
+  if (.not.allocated(output_ncid%var))then
+    allocate(output_ncid%var(maxVarFreq))
+    output_ncid%var(:) = integerMissing
+  endif
+  ! copy ncid
+  output_ncid%var(:) = ncid(:)
+
+
+end subroutine defOutputFortran
+
+
+
+
+subroutine FileAccessActor_DeallocateStructures(handle_ncid) bind(C,name="FileAccessActor_DeallocateStructures")
+  USE netcdf_util_module,only:nc_file_close 
+  USE globalData,only:structInfo                              ! information on the data structures
+  USE output_structure_module,only:outputTimeStep
+  USE output_structure_module,only:summa_struct
+  USE var_lookup,only:maxvarFreq                ! maximum number of output files
+   USE globalData,only:index_map 
+  implicit none
+  type(c_ptr),intent(in), value        :: handle_ncid
+
+  type(var_i),pointer                  :: ncid
+  integer(i4b)                         :: iFreq
+  character(LEN=256)                   :: cmessage
+  character(LEN=256)                   :: message
+  integer(i4b)                         :: err
+
+  call c_f_pointer(handle_ncid, ncid)
+  ! close the open output FIle
+  do iFreq=1,maxvarFreq
+    if (ncid%var(iFreq)/=integerMissing) then
+      call nc_file_close(ncid%var(iFreq),err,cmessage)
+      if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
+    endif   
+  end do
+
+  deallocate(ncid)
+  deallocate(outputTimeStep)
+  deallocate(summa_struct)
+  deallocate(index_map)
+end subroutine FileAccessActor_DeallocateStructures
+
+end module file_access_actor
diff --git a/build/source/file_access_actor/forcing_file_info.cpp b/build/source/file_access_actor/forcing_file_info.cpp
index 13f1ec0934d301e6aa4fe6e9e5b391b88e6c29b6..868b6b79e7e181c46bd585ce4b39f5e749712dac 100644
--- a/build/source/file_access_actor/forcing_file_info.cpp
+++ b/build/source/file_access_actor/forcing_file_info.cpp
@@ -1,27 +1,104 @@
 #include "forcing_file_info.hpp"
+#include <memory>
 
-Forcing_File_Info::Forcing_File_Info(int file_ID) {
-    this->file_ID = file_ID;
-    this->num_steps = 0;
-    this->is_loaded = false;
+fileInfo::fileInfo() {
+  filenmData = "";
+  nVars = 0;
+  nTimeSteps = 0;
+  var_ix = std::vector<int>();
+  data_id = std::vector<int>();
+  varName = std::vector<std::string>();
+  firstJulDay = 0.0;
+  convTime2Days = 0.0;
 }
 
-int Forcing_File_Info::getNumSteps() {
-    return this->num_steps;
-}
 
-bool Forcing_File_Info::isFileLoaded() {
-    return this->is_loaded;
+forcingFileContainer::forcingFileContainer() {
+  forcing_files_ = std::vector<fileInfo>();
+  file_access_timing_.addTimePoint("init_duration");
+  file_access_timing_.addTimePoint("read_duration");
 }
 
-void Forcing_File_Info::updateIsLoaded() {
-    this->is_loaded = true;
+forcingFileContainer::~forcingFileContainer() {
+  freeForcingFiles_fortran();
 }
 
+int forcingFileContainer::initForcingFiles() {
+  file_access_timing_.updateStartPoint("init_duration");
+  int num_files = 0; 
+  int err = 0;
+  std::unique_ptr<char[]> message(new char[256]);
+  
+  // initalize the fortran side
+  getNumFrocingFiles_fortran(num_files);
+  if (err != 0) {
+    std::cout << "Error initializing forcing files: " << message.get() << "\n";
+    file_access_timing_.updateEndPoint("init_duration");
+    return -1;
+  }
+
+  forcing_files_.resize(num_files);
+
+  for (int i = 1; i < num_files+1; i++) {
+    int var_ix_size = 0;
+    int data_id_size = 0;
+    int varName_size = 0;
+    getFileInfoSizes_fortran(i, var_ix_size, data_id_size, varName_size);
+    forcing_files_[i-1].var_ix.resize(var_ix_size);
+    forcing_files_[i-1].data_id.resize(data_id_size);
+    forcing_files_[i-1].varName.resize(varName_size);
+
+    // Allocate space for the file name and variable names
+    std::unique_ptr<char[]> file_name(new char[256]);
+    std::vector<std::unique_ptr<char[]>> var_name_arr;
+    for (int j = 0; j < varName_size; j++) {
+      var_name_arr.push_back(std::unique_ptr<char[]>(new char[256]));
+    }
+
+    getFileInfoCopy_fortran(i, &file_name, forcing_files_[i-1].nVars,
+                            forcing_files_[i-1].nTimeSteps, varName_size, 
+                            var_ix_size, data_id_size, var_name_arr.data(), 
+                            forcing_files_[i-1].var_ix.data(), 
+                            forcing_files_[i-1].data_id.data(), 
+                            forcing_files_[i-1].firstJulDay,
+                            forcing_files_[i-1].convTime2Days);
 
-void Forcing_File_Info::updateNumSteps(int num_steps) {
-    this->num_steps = num_steps;
-    this->is_loaded = true;
+    forcing_files_[i-1].filenmData = std::string(file_name.get());
+    forcing_files_[i-1].nVars = varName_size;
+    for (int j = 0; j < varName_size; j++) {
+      forcing_files_[i-1].varName[j] = std::string(var_name_arr[j].get());
+    }
+  }
+
+  file_access_timing_.updateEndPoint("init_duration");
+  return 0;
 }
 
 
+int forcingFileContainer::loadForcingFile(int file_ID, int start_gru, 
+    int num_gru) {
+  int err = 0;
+  if (forcing_files_[file_ID-1].is_loaded) {
+    return 0;
+  }
+
+  if (file_ID < 1 || file_ID > forcing_files_.size()) {
+    std::cout << "Error: Invalid file ID: " << file_ID << std::endl;
+    return -1;
+  }
+  file_access_timing_.updateStartPoint("read_duration");
+  std::unique_ptr<char[]> message(new char[256]);
+  read_forcingFile(file_ID, start_gru, num_gru, err, &message);
+  file_access_timing_.updateEndPoint("read_duration");
+  if (err != 0) {
+    std::cout << "Error reading forcing file: " << message.get() << std::endl;
+    return -2;
+  }
+  forcing_files_[file_ID-1].is_loaded = true;
+  files_loaded_++;
+  return 0;
+}
+
+bool forcingFileContainer::isFileLoaded(int file_ID) {
+  return forcing_files_[file_ID-1].is_loaded;
+}
diff --git a/build/source/file_access_actor/read_force.f90 b/build/source/file_access_actor/forcing_file_info.f90
similarity index 54%
rename from build/source/file_access_actor/read_force.f90
rename to build/source/file_access_actor/forcing_file_info.f90
index 15f4f5c0d21117154daa8b42b6d085917af64965..9cc76e9721d3c8bfff220e522e6eae7310c0d248 100644
--- a/build/source/file_access_actor/read_force.f90
+++ b/build/source/file_access_actor/forcing_file_info.f90
@@ -1,47 +1,115 @@
+module forcing_file_info
+  USE, intrinsic :: iso_c_binding
+  USE nrtype
+  USE globalData,only:integerMissing   ! integer missing value
+  USE actor_data_types,only:var_forc   ! global data structure for forcing data
+  USE data_types,only:dlength          ! global data structure for forcing data
+  implicit none
+  public::getNumFrocingFiles_fortran
+  public::getFileInfoSizes_fortran
+  public::getFileInfoCopy_fortran
+  public::read_forcingFile
+  public::openForcingFile
+  public::freeForcingFiles_fortran
 
-! This module contains all the functions that are used to
-! access the forcing file and setup the forcing data
-! for the HRUs to read from
-module access_forcing_module
+  ! Module Data Structures (global to hrus that import this module)
+  type(var_forc),allocatable,save,public  :: forcingDataStruct(:) ! forcingDataStruct(:)%var(:)%dataFromFile(:,:)
+  type(dlength),allocatable,save,public   :: vecTime(:)
+  contains
+! Initalize the fortran data structure and return the number of forcing files
+subroutine getNumFrocingFiles_fortran(num_forcing_files) &
+      bind(C, name="getNumFrocingFiles_fortran")
+  USE globalData,only:forcFileInfo            ! Structure allocated by ffil info
+  implicit none
+  ! dummy variables
+  integer(c_int), intent(out) :: num_forcing_files
+  num_forcing_files = size(forcFileInfo)
+end subroutine getNumFrocingFiles_fortran
 
-USE, intrinsic :: iso_c_binding
-USE nrtype
+! Get the sizes fo the vector components that make up a forcingFile
+subroutine getFileInfoSizes_fortran(iFile, var_ix_size, data_id_size, &
+    varName_size) bind(C, name="getFileInfoSizes_fortran")
+  USE globalData,only:forcFileInfo
+  implicit none
+  integer(c_int),intent(in)  :: iFile
+  integer(c_int),intent(out) :: var_ix_size
+  integer(c_int),intent(out) :: data_id_size
+  integer(c_int),intent(out) :: varName_size
+  var_ix_size = size(forcFileInfo(iFile)%var_ix)
+  data_id_size = size(forcFileInfo(iFile)%data_id)
+  varName_size = size(forcFileInfo(iFile)%varName)
+end subroutine getFileInfoSizes_fortran
 
-USE data_types,only:file_info
-USE data_types,only:dlength         ! global data structure for forcing data
-USE data_types,only:ilength         ! global data structure for forcing data
-USE actor_data_types,only:file_info_array
-USE actor_data_types,only:var_forc        ! global data structure for forcing data
+! Get the file info for a specific file
+subroutine getFileInfoCopy_fortran(iFile, filenmData, nVars, nTimeSteps, &
+    varName_size, var_ix_size, data_id_size, var_name_arr, var_ix_arr, &
+    data_id_arr, firstJulDay, convTime2Days) bind(C, name="getFileInfoCopy_fortran")
+  USE globalData,only:forcFileInfo
+  USE C_interface_module,only:f_c_string_ptr
+  implicit none
+  ! dummy variables
+  integer(c_int),intent(in)   :: iFile
+  type(c_ptr),intent(out)     :: filenmData
+  integer(c_int),intent(out)  :: nVars
+  integer(c_int),intent(out)  :: nTimeSteps
+  integer(c_int),intent(in)   :: varName_size
+  integer(c_int),intent(in)   :: var_ix_size
+  integer(c_int),intent(in)   :: data_id_size  
+  type(c_ptr),intent(out)     :: var_name_arr(varName_size)
+  integer(c_int),intent(out)  :: var_ix_arr(var_ix_size)
+  integer(c_int),intent(out)  :: data_id_arr(data_id_size)
+  real(c_double),intent(out)  :: firstJulDay
+  real(c_double),intent(out)  :: convTime2Days
+  ! local variables
+  integer(i4b)                :: i
+  integer(i4b)                :: index
+  character(len=256)          :: emptyString = ""
+  
+  call f_c_string_ptr(trim(forcFileInfo(iFile)%filenmData), filenmData)
 
-USE globalData,only:gru_struc
-USE globalData,only:time_meta,forc_meta       ! metadata structures
-USE globalData,only:integerMissing            ! integer missing value
-USE var_lookup,only:iLookTIME,iLookFORCE      ! named variables to define structure elements
-USE summaFileManager,only:FORCING_PATH        ! path of the forcing data file
-USE netcdf_util_module,only:nc_file_close  ! close netcdf file
+  nVars = forcFileInfo(iFile)%nVars
+  nTimeSteps = forcFileInfo(iFile)%nTimeSteps
 
+  ! First just populate with an empty string
+  do i=1, varName_size
+    call f_c_string_ptr(trim(emptyString), var_name_arr(i))
+  end do
+  ! Then look for the actual values by index
+  do i=1, size(forcFileInfo(iFile)%var_ix)
+    index = forcFileInfo(iFile)%var_ix(i)
+    if (index /= integerMissing) then
+      call f_c_string_ptr(trim(forcFileInfo(iFile)%varName(index)), var_name_arr(index))
+    end if
+  end do 
 
+  var_ix_arr(:) = forcFileInfo(iFile)%var_ix(:)
+  data_id_arr(:) = forcFileInfo(iFile)%data_id(:)
 
-implicit none
-private
-public::read_forcingFile
+  firstJulDay = forcFileInfo(iFile)%firstJulDay
+  convTime2Days = forcFileInfo(iFile)%convTime2Days
 
-type(var_forc),allocatable,save,public         :: forcingDataStruct(:)              ! forcingDataStruct(:)%var(:)%dataFromFile(:,:)
-type(dlength),allocatable,save,public          :: vecTime(:)
+end subroutine getFileInfoCopy_fortran
+
+! Read an entire forcing file into the global structures defined in this module
+subroutine read_forcingFile(iFile, startGRU, numGRU, err, message_r) &
+    bind(C,name="read_forcingFile")
+  USE netcdf                                             
+  USE netcdf_util_module,only:nc_file_open        
+  USE netcdf_util_module,only:nc_file_close  ! close netcdf file
+  USE C_interface_module,only:f_c_string_ptr
+  USE globalData,only:forcFileInfo              
+  USE globalData,only:gru_struc
+  USE globalData,only:forc_meta 
+  USE var_lookup,only:iLookTIME,iLookFORCE      ! named variables to define structure elements
+  USE summaFileManager,only:FORCING_PATH        ! path of the forcing data file
 
-contains
-subroutine read_forcingFile(handle_forcFileInfo, iFile, stepsInFile, startGRU, numGRU, err) bind(C,name="read_forcingFile")
-  USE netcdf                                              ! netcdf capability
-  USE netcdf_util_module,only:nc_file_open                ! open netcdf file
   implicit none
-  type(c_ptr), intent(in), value          :: handle_forcFileInfo
   integer(c_int),intent(in)               :: iFile
-  integer(c_int),intent(inout)            :: stepsInFile
   integer(c_int),intent(in)               :: startGRU
   integer(c_int),intent(in)               :: numGRU
-  integer(c_int),intent(inout)            :: err
+  integer(c_int),intent(out)              :: err
+  type(c_ptr), intent(out)                :: message_r
   ! local varibles            
-  type(file_info_array), pointer          :: forcFileInfo
   integer(i4b)                            :: iHRU_Global
   integer(i4b)                            :: varId
   integer(i4b)                            :: ncid
@@ -58,15 +126,13 @@ subroutine read_forcingFile(handle_forcFileInfo, iFile, stepsInFile, startGRU, n
   logical(lgt),dimension(size(forc_meta)) :: checkForce       ! flags to check forcing data variables exist
   character(len=256)                      :: message          ! error message 
   
-  call c_f_pointer(handle_forcFileInfo, forcFileInfo)
 
   ! Start Procedure here
-  err=0; message="read_force.f90 - read_forcingFile/"
-
-  nFiles=size(forcFileInfo%ffile_list(:))
-
-  nTimeSteps = sum(forcFileInfo%ffile_list(:)%nTimeSteps)
+  err=0; message="read_forcingFile/"
+  call f_c_string_ptr(trim(message),message_r)
 
+  ! TODO: I wonder if I can wrap this in a shared pointer???
+  nFiles=size(forcFileInfo(:))
   ! Allocate forcing data input Struct
   if (.not.allocated(forcingDataStruct))then
     allocate(forcingDataStruct(nFiles))
@@ -75,31 +141,28 @@ subroutine read_forcingFile(handle_forcFileInfo, iFile, stepsInFile, startGRU, n
   endif
  
   ! Files are assumed to be in the correct order
-  infile=trim(FORCING_PATH)//trim(forcFileInfo%ffile_list(iFile)%filenmData)
-  ! open netCDF file
-  call openForcingFile(forcFileInfo%ffile_list,iFile,trim(infile),ncid,err,cmessage)
-  if(err/=0)then; message=trim(message)//trim(cmessage);return; end if
-
-  err = nf90_inq_varid(ncid,'time',varId);                              if(err/=nf90_noerr)then; message=trim(message)//'cannot find time variable/'//trim(nf90_strerror(err)); return; endif
-  err = nf90_inquire_attribute(ncid,varId,'units',len = attLen);        if(err/=nf90_noerr)then; message=trim(message)//'cannot find time units/'//trim(nf90_strerror(err));    return; endif
-  err = nf90_get_att(ncid,varid,'units',forcingDataStruct(iFile)%refTimeString);if(err/=nf90_noerr)then; message=trim(message)//'cannot read time units/'//trim(nf90_strerror(err));    return; endif
-
+  infile=trim(FORCING_PATH)//trim(forcFileInfo(iFile)%filenmData)
+  call openForcingFile(forcFileInfo(iFile),iFile,trim(infile),ncid,err,cmessage)
+  if(err/=0)then;message=trim(message)//trim(cmessage);call f_c_string_ptr(trim(message),message_r);return; end if
 
-  nTimeSteps = forcFileInfo%ffile_list(iFile)%nTimeSteps
+  err = nf90_inq_varid(ncid,'time',varId);                              if(err/=nf90_noerr)then; message=trim(message)//'cannot find time variable/'//trim(nf90_strerror(err));call f_c_string_ptr(trim(message),message_r);return; endif
+  err = nf90_inquire_attribute(ncid,varId,'units',len = attLen);        if(err/=nf90_noerr)then; message=trim(message)//'cannot find time units/'//trim(nf90_strerror(err));call f_c_string_ptr(trim(message),message_r);return; endif
+  err = nf90_get_att(ncid,varid,'units',forcingDataStruct(iFile)%refTimeString);if(err/=nf90_noerr)then; message=trim(message)//'cannot read time units/'//trim(nf90_strerror(err));call f_c_string_ptr(trim(message),message_r);return; endif
+  
+  nTimeSteps = forcFileInfo(iFile)%nTimeSteps
   forcingDataStruct(iFile)%nTimeSteps = nTimeSteps
-  stepsInFile = nTimeSteps
   if(.not.allocated(vecTime(iFile)%dat))then
     allocate(vecTime(iFile)%dat(nTimeSteps))
   end if
 
   ! Get Time Information
   err = nf90_inq_varid(ncid,'time',varId);
-  if(err/=nf90_noerr)then; message=trim(message)//'trouble finding time variable/'//trim(nf90_strerror(err)); return; endif
+  if(err/=nf90_noerr)then; message=trim(message)//'trouble finding time variable/'//trim(nf90_strerror(err)); call f_c_string_ptr(trim(message),message_r); return; endif
   err = nf90_get_var(ncid,varId,vecTime(iFile)%dat(:),start=(/1/),count=(/nTimeSteps/))    
-  if(err/=nf90_noerr)then; message=trim(message)//'trouble reading time variable/'//trim(nf90_strerror(err)); return; endif
+  if(err/=nf90_noerr)then; message=trim(message)//'trouble reading time variable/'//trim(nf90_strerror(err)); call f_c_string_ptr(trim(message),message_r); return; endif
 
   ! Need to loop through vars and add forcing data
-  nVars = forcFileInfo%ffile_list(iFile)%nVars
+  nVars = forcFileInfo(iFile)%nVars
   forcingDataStruct(iFile)%nVars = nVars
   if (.not.allocated(forcingDataStruct(iFile)%var))then
     allocate(forcingDataStruct(iFile)%var(nVars))
@@ -114,13 +177,12 @@ subroutine read_forcingFile(handle_forcFileInfo, iFile, stepsInFile, startGRU, n
   checkForce(iLookFORCE%time) = .true.  ! time is handled separately
   do iNC=1,nVars
     ! populate var_ix so HRUs can access the values
-    forcingDataStruct(iFile)%var_ix(iNC) = forcFileInfo%ffile_list(iFile)%var_ix(iNC)
+    forcingDataStruct(iFile)%var_ix(iNC) = forcFileInfo(iFile)%var_ix(iNC)
 
     ! check variable is desired
-    if(forcFileInfo%ffile_list(iFile)%var_ix(iNC)==integerMissing) cycle
-          
+    if(forcFileInfo(iFile)%var_ix(iNC)==integerMissing) cycle
           
-    iVar = forcFileInfo%ffile_list(iFile)%var_ix(iNC)
+    iVar = forcFileInfo(iFile)%var_ix(iNC)
     checkForce(iVar) = .true.
     if (.not.allocated(forcingDataStruct(iFile)%var(iVar)%dataFromFile))then
       allocate(forcingDataStruct(iFile)%var(iVar)%dataFromFile(numGRU,nTimeSteps))
@@ -129,40 +191,38 @@ subroutine read_forcingFile(handle_forcFileInfo, iFile, stepsInFile, startGRU, n
     ! Get Forcing Data
     ! get variable name for error reporting
     err=nf90_inquire_variable(ncid,iNC,name=varName)
-    if(err/=nf90_noerr)then; message=trim(message)//'problem reading forcing variable name from netCDF: '//trim(nf90_strerror(err)); return; endif
+    if(err/=nf90_noerr)then; message=trim(message)//'problem reading forcing variable name from netCDF: '//trim(nf90_strerror(err)); call f_c_string_ptr(trim(message),message_r); return; endif
 
     ! define global HRU
     iHRU_global = gru_struc(1)%hruInfo(1)%hru_nc
     numHRU = sum(gru_struc(:)%hruCount)
     
 
-    err=nf90_get_var(ncid,forcFileInfo%ffile_list(iFile)%data_id(ivar),forcingDataStruct(iFile)%var(iVar)%dataFromFile, start=(/startGRU,1/),count=(/numHRU, nTimeSteps/))
-    if(err/=nf90_noerr)then; message=trim(message)//'problem reading forcing data: '//trim(varName)//'/'//trim(nf90_strerror(err)); return; endif
+    err=nf90_get_var(ncid,forcFileInfo(iFile)%data_id(ivar),forcingDataStruct(iFile)%var(iVar)%dataFromFile, start=(/startGRU,1/),count=(/numHRU, nTimeSteps/))
+    if(err/=nf90_noerr)then; message=trim(message)//'problem reading forcing data: '//trim(varName)//'/'//trim(nf90_strerror(err)); call f_c_string_ptr(trim(message),message_r); return; endif
   end do
 
   call nc_file_close(ncid,err,message)
-  if(err/=0)then;message=trim(message)//trim(cmessage);return;end if
-
-       
+  if(err/=0)then;message=trim(message)//trim(cmessage);call f_c_string_ptr(trim(message),message_r);return;end if  
 end subroutine read_forcingFile
 
 ! *************************************************************************
 ! * open the NetCDF forcing file and get the time information
 ! *************************************************************************
-subroutine openForcingFile(forcFileInfo,iFile,infile,ncId,err,message)
+subroutine openForcingFile(forc_file,iFile,infile,ncId,err,message)
   USE netcdf                                              ! netcdf capability
   USE netcdf_util_module,only:nc_file_open                ! open netcdf file
+  USE data_types,only:file_info
   USE time_utils_module,only:fracDay                      ! compute fractional day
   USE time_utils_module,only:extractTime                  ! extract time info from units string
   USE time_utils_module,only:compJulDay                   ! convert calendar date to julian day
-  !USE globalData,only:tmZoneOffsetFracDay                ! time zone offset in fractional days
   USE globalData,only:ncTime                              ! time zone information from NetCDF file (timeOffset = longitude/15. - ncTimeOffset)
   USE globalData,only:utcTime                             ! all times in UTC (timeOffset = longitude/15. hours)
   USE globalData,only:localTime                           ! all times local (timeOffset = 0)
   USE globalData,only:refJulDay_data
   USE summafilemanager,only:NC_TIME_ZONE
   ! dummy variables
-  type(file_info),intent(inout)     :: forcFileInfo(:)
+  type(file_info),intent(inout)     :: forc_file
   integer(i4b),intent(in)           :: iFile              ! index of current forcing file in forcing file list
   character(*) ,intent(in)          :: infile             ! input file
   integer(i4b) ,intent(out)         :: ncId               ! NetCDF ID
@@ -193,9 +253,9 @@ subroutine openForcingFile(forcFileInfo,iFile,infile,ncId,err,message)
   
   ! define the reference time for the model simulation
   call extractTime(refTimeString,                        & ! input  = units string for time data
-                  iyyy,im,id,ih,imin,dsec,               & ! output = year, month, day, hour, minute, second
-                  ih_tz, imin_tz, dsec_tz,               & ! output = time zone information (hour, minute, second)
-                  err,cmessage)                            ! output = error code and error message
+                   iyyy,im,id,ih,imin,dsec,              & ! output = year, month, day, hour, minute, second
+                   ih_tz, imin_tz, dsec_tz,              & ! output = time zone information (hour, minute, second)
+                   err,cmessage)                            ! output = error code and error message
   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
    
   select case(trim(NC_TIME_ZONE))
@@ -214,20 +274,28 @@ subroutine openForcingFile(forcFileInfo,iFile,infile,ncId,err,message)
   ! get the time multiplier needed to convert time to units of days
   select case( trim( refTimeString(1:index(refTimeString,' ')) ) )
     case('seconds') 
-      forcFileInfo(iFile)%convTime2Days=86400._dp
+      forc_file%convTime2Days=86400._dp
       forcingDataStruct(iFile)%convTime2Days=86400._dp
     case('minutes') 
-      forcFileInfo(iFile)%convTime2Days=1440._dp
+      forc_file%convTime2Days=1440._dp
       forcingDataStruct(iFile)%convTime2Days=1440._dp
     case('hours')
-      forcFileInfo(iFile)%convTime2Days=24._dp
+      forc_file%convTime2Days=24._dp
       forcingDataStruct(iFile)%convTime2Days=24._dp
     case('days')
-      forcFileInfo(iFile)%convTime2Days=1._dp
+      forc_file%convTime2Days=1._dp
       forcingDataStruct(iFile)%convTime2Days=1._dp
     case default;    message=trim(message)//'unable to identify time units'; err=20; return
   end select
    
-  end subroutine openForcingFile
+end subroutine openForcingFile
+
+subroutine freeForcingFiles_fortran() bind(C, name="freeForcingFiles_fortran")
+  USE globalData,only:forcFileInfo
+  implicit none
+  if (allocated(forcFileInfo)) deallocate(forcFileInfo)
+  if (allocated(forcingDataStruct)) deallocate(forcingDataStruct)
+  if (allocated(vecTime)) deallocate(vecTime)
+end subroutine freeForcingFiles_fortran
 
-end module access_forcing_module
\ No newline at end of file
+end module forcing_file_info
diff --git a/build/source/file_access_actor/output_container.cpp b/build/source/file_access_actor/output_container.cpp
index 65a900410c1c866c604407cc405893fb63b07e60..1799d666795a2e50ae5c66b61f4683e1e1ad819a 100644
--- a/build/source/file_access_actor/output_container.cpp
+++ b/build/source/file_access_actor/output_container.cpp
@@ -152,6 +152,10 @@ int Output_Container::findPartition(int local_gru_index) {
         if (it != this->failed_gru_index_list.end()) {
             return std::distance(this->failed_gru_index_list.begin(), it);
         } else {
+            std::cout << "GRU index: " << local_gru_index << std::endl;
+            for (int i = 0; i < this->failed_gru_index_list.size(); i++) {
+                std::cout << this->failed_gru_index_list[i] << std::endl;
+            }
             throw std::runtime_error("GRU index not found in failed GRU index list");
         }
     }
diff --git a/build/source/file_access_actor/output_structure.f90 b/build/source/file_access_actor/output_structure.f90
index c7da30bd56e529048b4ff4cfa509de4f4b3e977d..d3321f63dcf2be51a99a6d549b137410d3f7b8bd 100644
--- a/build/source/file_access_actor/output_structure.f90
+++ b/build/source/file_access_actor/output_structure.f90
@@ -129,7 +129,7 @@ subroutine initOutputTimeStep(num_gru, err)
 
 end subroutine initOutputTimeStep
 
-subroutine initOutputStructure(forcFileInfo, maxSteps, num_gru, err)
+subroutine initOutputStructure(maxSteps, num_gru, err)
   USE globalData,only:time_meta,forc_meta,attr_meta,type_meta ! metadata structures
   USE globalData,only:prog_meta,diag_meta,flux_meta,id_meta   ! metadata structures
   USE globalData,only:mpar_meta,indx_meta                     ! metadata structures
@@ -146,14 +146,14 @@ subroutine initOutputStructure(forcFileInfo, maxSteps, num_gru, err)
   USE globalData,only:gru_struc
   USE globalData,only:structInfo                              ! information on the data structures
   USE multiconst,only:secprday                                ! number of seconds in a day
-  USE actor_data_types,only:file_info_array
   USE var_lookup,only:maxvarFreq                              ! maximum number of output files
 
   USE allocspace_module,only:allocGlobal                      ! module to allocate space for global data structures
   USE globalData,only:maxSnowLayers
+
+  USE globalData,only:forcFileInfo
   
   implicit none
-  type(file_info_array),intent(in)      :: forcFileInfo
   integer(i4b), intent(in)              :: maxSteps
   integer(i4b), intent(in)              :: num_gru
   integer(i4b), intent(out)             :: err 
@@ -268,7 +268,7 @@ subroutine initOutputStructure(forcFileInfo, maxSteps, num_gru, err)
     do iHRU=1,gru_struc(iGRU)%hruCount
 
       ! Get the maximum number of steps needed to initalize the output structure
-      nVars = maxval(forcFileInfo%ffile_list(:)%nVars)
+      nVars = maxval(forcFileInfo(:)%nVars)
       nSnow = gru_struc(iGRU)%hruInfo(iHRU)%nSnow
       nSoil = gru_struc(iGRU)%hruInfo(iHRU)%nSoil
 
diff --git a/build/source/file_access_actor/summa_init_struc.cpp b/build/source/file_access_actor/summa_init_struc.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad99941c316e72ae8a4efba81295d98c24156d81
--- /dev/null
+++ b/build/source/file_access_actor/summa_init_struc.cpp
@@ -0,0 +1,38 @@
+#include "summa_init_struc.hpp"
+#include <memory>
+#include <iostream>
+
+SummaInitStruc::SummaInitStruc() {}
+
+SummaInitStruc::~SummaInitStruc() {
+  deallocate_init_struc();
+}
+
+int SummaInitStruc::allocate(int num_gru) {
+  int err = 0;
+  std::unique_ptr<char[]> message(new char[256]);
+  initialize_init_struc(num_gru, err, &message);
+  if (err != 0) std::cout << message.get() << std::endl;
+  return err;
+}
+
+int SummaInitStruc::summa_paramSetup() {
+  int err = 0;
+  std::unique_ptr<char[]> message(new char[256]);
+  paramSetup_fortran(err, &message);
+  if (err != 0) std::cout << message.get() << std::endl;
+  return err;
+}
+
+int SummaInitStruc::summa_readRestart() {
+  int err = 0;
+  std::unique_ptr<char[]> message(new char[256]);
+  readRestart_fortran(err, &message);
+  if (err != 0) std::cout << message.get() << std::endl;
+  return err;
+}
+
+void SummaInitStruc::getInitTolerance(HRU_Actor_Settings& hru_settings) {
+  getInitTolerance_fortran(hru_settings.rel_tol, hru_settings.abs_tol);
+}
+
diff --git a/build/source/file_access_actor/summa_init_struc.f90 b/build/source/file_access_actor/summa_init_struc.f90
new file mode 100644
index 0000000000000000000000000000000000000000..450cb0c8ac27eeacface183c884912e5823bad4c
--- /dev/null
+++ b/build/source/file_access_actor/summa_init_struc.f90
@@ -0,0 +1,241 @@
+module summa_init_struc
+  USE iso_c_binding
+  USE nrtype
+  USE summa_type, only:summa1_type_dec                        ! master summa data type
+  implicit none
+  public :: initialize_init_struc
+  public :: paramSetup_fortran
+  public :: deallocate_init_struc
+  public :: getInitTolerance_fortran 
+  ! Used to get all the inital conditions for the model -- allows calling summa_setup.f90
+  type(summa1_type_dec),allocatable,save,public :: init_struc 
+
+  contains
+subroutine initialize_init_struc(num_gru, err, message_r) bind(C, name="initialize_init_struc")
+  USE globalData,only:structInfo            ! information on the data structures
+  USE globalData,only:gru_struc                               ! gru-hru mapping structures
+  USE globalData,only:time_meta, &                       
+                      forc_meta, &
+                      attr_meta, &
+                      type_meta, &
+                      prog_meta, &
+                      diag_meta, &
+                      flux_meta, &
+                      id_meta,   &
+                      mpar_meta, &
+                      indx_meta, &
+                      bpar_meta, &
+                      bvar_meta
+#ifdef V4_ACTIVE
+  USE globalData,only:lookup_meta
+#endif
+  ! statistics metadata structures
+  USE globalData,only:statForc_meta, &        ! child metadata for stats
+                      statProg_meta, &        ! child metadata for stats
+                      statDiag_meta, &        ! child metadata for stats
+                      statFlux_meta, &        ! child metadata for stats
+                      statIndx_meta, &        ! child metadata for stats
+                      statBvar_meta           ! child metadata for stats
+  USE allocspace_module,only:allocGlobal      ! module to allocate space for global data structures
+  USE allocspace_module,only:allocLocal
+  USE globalData,only:startTime,finshTime,refTime,oldTime
+  USE C_interface_module,only:f_c_string_ptr  ! convert fortran string to c string
+  implicit none
+  ! dummy variables
+  integer(c_int),       intent(in)        :: num_gru
+  integer(c_int),       intent(out)       :: err
+  type(c_ptr),          intent(out)       :: message_r
+  ! local variables
+  integer(i4b)                            :: iStruct,iGRU      ! looping variables
+  character(len=256)                      :: message           ! error message
+  character(len=256)                      :: cmessage          ! error message
+
+  ! Start of subroutine
+  message = ""
+  call f_c_string_ptr(trim(message), message_r)
+  allocate(init_struc)
+  summaVars: associate(&
+#ifdef V4_ACTIVE  
+    lookupStruct         =>init_struc%lookupStruct         , & ! x%gru(:)%hru(:)%z(:)%var(:)%lookup(:) -- lookup tables
+#endif
+    ! statistics structures
+    forcStat             => init_struc%forcStat            , & ! x%gru(:)%hru(:)%var(:)%dat -- model forcing data
+    progStat             => init_struc%progStat            , & ! x%gru(:)%hru(:)%var(:)%dat -- model prognostic (state) variables
+    diagStat             => init_struc%diagStat            , & ! x%gru(:)%hru(:)%var(:)%dat -- model diagnostic variables
+    fluxStat             => init_struc%fluxStat            , & ! x%gru(:)%hru(:)%var(:)%dat -- model fluxes
+    indxStat             => init_struc%indxStat            , & ! x%gru(:)%hru(:)%var(:)%dat -- model indices
+    bvarStat             => init_struc%bvarStat            , & ! x%gru(:)%var(:)%dat        -- basin-average variables
+
+    ! primary data structures (scalars)
+    timeStruct           => init_struc%timeStruct          , & ! x%var(:)                   -- model time data
+    forcStruct           => init_struc%forcStruct          , & ! x%gru(:)%hru(:)%var(:)     -- model forcing data
+    attrStruct           => init_struc%attrStruct          , & ! x%gru(:)%hru(:)%var(:)     -- local attributes for each HRU
+    typeStruct           => init_struc%typeStruct          , & ! x%gru(:)%hru(:)%var(:)     -- local classification of soil veg etc. for each HRU
+    idStruct             => init_struc%idStruct            , & ! x%gru(:)%hru(:)%var(:)     --
+
+    ! primary data structures (variable length vectors)
+    indxStruct           => init_struc%indxStruct          , & ! x%gru(:)%hru(:)%var(:)%dat -- model indices
+    mparStruct           => init_struc%mparStruct          , & ! x%gru(:)%hru(:)%var(:)%dat -- model parameters
+    progStruct           => init_struc%progStruct          , & ! x%gru(:)%hru(:)%var(:)%dat -- model prognostic (state) variables
+    diagStruct           => init_struc%diagStruct          , & ! x%gru(:)%hru(:)%var(:)%dat -- model diagnostic variables
+    fluxStruct           => init_struc%fluxStruct          , & ! x%gru(:)%hru(:)%var(:)%dat -- model fluxes
+
+    ! basin-average structures
+    bparStruct           => init_struc%bparStruct          , & ! x%gru(:)%var(:)            -- basin-average parameters
+    bvarStruct           => init_struc%bvarStruct          , & ! x%gru(:)%var(:)%dat        -- basin-average variables
+
+    ! ancillary data structures
+    dparStruct           => init_struc%dparStruct          , &  ! x%gru(:)%hru(:)%var(:)     -- default model parameters
+
+     ! run time variables
+    computeVegFlux       => init_struc%computeVegFlux      , & ! flag to indicate if we are computing fluxes over vegetation (.false. means veg is buried with snow)
+    dt_init              => init_struc%dt_init             , & ! used to initialize the length of the sub-step for each HRU
+    upArea               => init_struc%upArea              , & ! area upslope of each HRU
+    
+    ! miscellaneous variables
+    nGRU                 => init_struc%nGRU              , & ! number of grouped response units
+    nHRU                 => init_struc%nHRU              , & ! number of global hydrologic response units
+    hruCount             => init_struc%hruCount              & ! number of local hydrologic response units
+  )
+
+  ! allocate other data structures
+  do iStruct=1,size(structInfo)
+    ! allocate space
+    select case(trim(structInfo(iStruct)%structName))
+      case('time'); call allocGlobal(time_meta,  timeStruct,  err, cmessage)   ! model forcing data
+      case('forc'); call allocGlobal(forc_meta,  forcStruct,  err, cmessage)   ! model forcing data
+      case('attr'); call allocGlobal(attr_meta,  attrStruct,  err, cmessage)   ! local attributes for each HRU
+      case('type'); call allocGlobal(type_meta,  typeStruct,  err, cmessage)   ! local classification of soil veg etc. for each HRU
+      case('id'  ); call allocGlobal(id_meta,    idStruct,    err, message)    ! local values of hru and gru IDs
+      case('mpar'); call allocGlobal(mpar_meta,  mparStruct,  err, cmessage)   ! model parameters
+      case('indx'); call allocGlobal(indx_meta,  indxStruct,  err, cmessage)   ! model variables
+      case('prog'); call allocGlobal(prog_meta,  progStruct,  err, cmessage)   ! model prognostic (state) variables
+      case('diag'); call allocGlobal(diag_meta,  diagStruct,  err, cmessage)   ! model diagnostic variables
+      case('flux'); call allocGlobal(flux_meta,  fluxStruct,  err, cmessage)   ! model fluxes
+      case('bpar'); call allocGlobal(bpar_meta,  bparStruct,  err, cmessage)   ! basin-average parameters
+      case('bvar'); call allocGlobal(bvar_meta,  bvarStruct,  err, cmessage)   ! basin-average variables
+#ifdef V4_ACTIVE
+      case('lookup'); call allocGlobal(lookup_meta, lookupStruct, err, cmessage) ! lookup tables
+#endif      
+      case('deriv'); cycle
+      case default; err=20; message='unable to find structure name: '//trim(structInfo(iStruct)%structName)
+    end select
+    ! check errors
+    if(err/=0)then
+      message=trim(message)//trim(cmessage)//'[structure =  '//trim(structInfo(iStruct)%structName)//']'
+      call f_c_string_ptr(trim(message), message_r)
+      return
+    endif
+  end do  ! looping through data structures
+  
+  ! allocate space for default model parameters
+  ! NOTE: This is done here, rather than in the loop above, because dpar is not one of the "standard" data structures
+  call allocGlobal(mpar_meta,dparStruct,err,cmessage)   ! default model parameters
+  if(err/=0)then
+    message=trim(message)//trim(cmessage)//' [problem allocating dparStruct]'
+    call f_c_string_ptr(trim(message), message_r)
+    return
+  endif
+
+  ! allocate space for the time step and computeVegFlux flags (recycled for each GRU for subsequent model calls)
+  allocate(dt_init%gru(num_gru),upArea%gru(num_gru),computeVegFlux%gru(num_gru),stat=err)
+  if(err/=0)then
+    message=trim(message)//'problem allocating space for dt_init, upArea, or computeVegFlux [GRU]'
+    call f_c_string_ptr(trim(message), message_r)
+    return
+  endif
+
+   ! allocate space for the HRUs
+  do iGRU=1,num_gru
+    hruCount = gru_struc(iGRU)%hruCount  ! gru_struc populated in "read_dimension"
+    allocate(dt_init%gru(iGRU)%hru(hruCount),upArea%gru(iGRU)%hru(hruCount),&
+             computeVegFlux%gru(iGRU)%hru(hruCount),stat=err)
+    if(err/=0)then
+      message='problem allocating space for dt_init, upArea, or computeVegFlux [HRU]'
+      call f_c_string_ptr(trim(message), message_r)
+      return
+    endif
+  end do
+
+  nGRU = num_gru
+  nHRU = sum(gru_struc%hruCount)
+  
+  end associate summaVars
+
+  ! Allocate the time structures
+  call allocLocal(time_meta, startTime, err=err, message=message)
+  call allocLocal(time_meta, finshTime, err=err, message=message)
+  call allocLocal(time_meta, refTime,   err=err, message=message)
+  call allocLocal(time_meta, oldTime,   err=err, message=message)
+  if(err/=0)then; call f_c_string_ptr(trim(message), message_r); return; endif
+
+end subroutine initialize_init_struc
+
+subroutine paramSetup_fortran(err, message_r) bind(C, name="paramSetup_fortran")
+  USE C_interface_module,only:f_c_string_ptr  ! convert fortran string to c string
+  USE summa_setup,only:summa_paramSetup
+  implicit none
+  ! dummy variables
+  integer(c_int),       intent(out)       :: err
+  type(c_ptr),          intent(out)       :: message_r
+  ! local variables
+  character(len=256)                      :: message           ! error message
+
+  message = ''
+  call f_c_string_ptr(trim(message), message_r)
+
+  call summa_paramSetup(init_struc, err, message)
+  call f_c_string_ptr(trim(message), message_r)
+
+end subroutine paramSetup_fortran
+
+subroutine readRestart_fortran(err, message_r) bind(C, name="readRestart_fortran")
+  USE C_interface_module,only:f_c_string_ptr  ! convert fortran string to c string
+  USE summa_restart,only:summa_readRestart
+  implicit none
+  ! dummy variables
+  integer(c_int),       intent(out)       :: err
+  type(c_ptr),          intent(out)       :: message_r
+  ! local variables
+  character(len=256)                      :: message           ! error message
+
+  message = ''
+  call f_c_string_ptr(trim(message), message_r)
+  call summa_readRestart(init_struc, err, message)
+  call f_c_string_ptr(trim(message), message_r)
+
+end subroutine readRestart_fortran
+
+subroutine getInitTolerance_fortran(rtol, atol) &
+    bind(C, name="getInitTolerance_fortran")
+   USE globalData,only:model_decisions                         ! model decision structure
+  USE var_lookup,only:iLookDECISIONS
+  USE var_lookup,only:iLookPARAM
+  implicit none
+  ! dummy variables
+  real(c_double),       intent(out)       :: rtol 
+  real(c_double),       intent(out)       :: atol
+
+  rtol = -9999
+  atol = -9999
+#ifdef V4_ACTIVE
+  if (model_decisions(iLookDECISIONS%num_method)%iDecision == 83) then
+    rtol = init_struc%mparStruct%gru(1)%hru(1)%var(iLookPARAM%relTolWatSnow)%dat(1)
+    atol = init_struc%mparStruct%gru(1)%hru(1)%var(iLookPARAM%absTolWatSnow)%dat(1)
+  end if
+#endif
+
+end subroutine getInitTolerance_fortran
+
+subroutine deallocate_init_struc() bind(C, name="deallocate_init_struc")
+  USE globalData,only:startTime,finshTime,refTime,oldTime
+  implicit none
+  deallocate(init_struc)
+  deallocate(startTime%var);
+  deallocate(finshTime%var);
+  deallocate(refTime%var);
+  deallocate(oldTime%var);
+  
+end subroutine deallocate_init_struc
+
+end module summa_init_struc
\ No newline at end of file
diff --git a/build/source/global/actor_data_types.f90 b/build/source/global/actor_data_types.f90
index 1367876cfc6feb4fe3d52c5e52e1203a9981cd54..ffe1132a9fac9feb9b5065aa0c542ef5868b3f6b 100644
--- a/build/source/global/actor_data_types.f90
+++ b/build/source/global/actor_data_types.f90
@@ -5,13 +5,7 @@ module actor_data_types
   implicit none
   private
 
-  ! ***********************************************************************************************************
-  ! Wrapping of file_info (prevents a segmentation fault)
-  ! ***********************************************************************************************************
-  type,public :: file_info_array
-    type(file_info), allocatable         :: ffile_list(:)
-  end type file_info_array
-
+  
   type,public :: forcingFileData
     real(rkind), dimension (:,:), allocatable   :: dataFromFile
   end type forcingFileData
@@ -27,6 +21,7 @@ module actor_data_types
     integer(i4b)                         :: nTimeSteps    ! Number of Timesteps in the file
   end type var_forc
 
+
   ! ** double precision type of for time series
   type, public :: time_dlength
     type(dlength),allocatable          :: tim(:)    ! tim(:)%dat
diff --git a/build/source/global/c_interface_module.f90 b/build/source/global/c_interface_module.f90
new file mode 100644
index 0000000000000000000000000000000000000000..5e5e36f3392d549979809771d8b95f6069b675e5
--- /dev/null
+++ b/build/source/global/c_interface_module.f90
@@ -0,0 +1,448 @@
+! FILE: c_interface_module.f (https://fortranwiki.org/fortran/show/c_interface_module)
+! PURPOSE: Supplement ISO-C-Binding to provide type aliases and interfaces
+!          to common ISO-C string functions to aid working with strings.
+! AUTHOR: Joseph M. Krahn
+! STATUS: Still in development. Reasonably complete, but somewhat limited testing.
+!
+! The idea is to provide type aliases for all ISO-C types, so that the
+! Fortran interface code more explicitly defines the actual C interface.
+! This should be updated to support F2008 variable-length allocatable
+! strings.
+!
+! Entity names all have the "C_" prefix, as with ISO-C-Binding, with a
+! few exceptions.
+! 
+module C_interface_module
+  use, intrinsic :: ISO_C_Binding, &
+  ! C type aliases for pointer derived types:
+      C_ptr => C_ptr , &
+      C_char_ptr => C_ptr, &
+      C_const_char_ptr => C_ptr, &
+      C_void_ptr => C_ptr, &
+      C_const_void_ptr => C_ptr
+
+  implicit none
+
+!----------------------------------------------------------------------------
+! C type aliases for intrinsic type KIND parameters:
+
+! NOTE: a C enum may not always be a standard C int
+  integer, parameter :: C_enum = C_int
+
+! Defining off_t is difficult, because it may depend on "LARGEFILE" selection.
+!  integer, parameter :: C_off_t = ??
+
+! C string terminator alais using the 3-letter ASCII name.
+! The C_ prefix is not used because it is just an ASCII character.
+  character(len=1,kind=C_char), parameter :: NUL = C_NULL_char
+
+! NOTE: In C, "char" is distinct from "signed char", unlike integers.
+! The plain "char" type is specific for text/string values, whereas
+! "signed char" should indicate 1-byte integer data.
+!
+! Most ISO-C systems have wide chars "wchar_t", but Fortran compilers
+! have limited support for different character kinds. UTF encoding
+! adds more complexity. This should be updated as Fortran compilers
+! include support for more character types.
+! 
+
+! Fortran does not (yet) support unsigned types.
+  integer, parameter :: &
+      C_unsigned = C_int, &
+      C_unsigned_short = C_short, &
+      C_unsigned_long = C_long, &
+      C_unsigned_long_long = C_long_long, &
+      C_unsigned_char = C_signed_char, &
+      C_ssize_t = C_size_t, &
+      C_uint8_t = C_int8_t, &
+      C_uint16_t = C_int16_t, &
+      C_uint32_t = C_int32_t, &
+      C_uint64_t = C_int64_t, &
+      C_uint_least8_t = C_int_least8_t, &
+      C_uint_least16_t = C_int_least16_t, &
+      C_uint_least32_t = C_int_least32_t, &
+      C_uint_least64_t = C_int_least64_t, &
+      C_uint_fast8_t = C_int_fast8_t, &
+      C_uint_fast16_t = C_int_fast16_t, &
+      C_uint_fast32_t = C_int_fast32_t, &
+      C_uint_fast64_t = C_int_fast64_t, &
+      C_uintmax_t = C_intmax_t
+! Note: ptrdiff_t cannot be reliably defined from other types.
+! When practical, it is larger than a pointer because it benefits
+! from the full unsigned range in both positive and negative directions.
+
+! Integer versions including 'int', where the 'int' is optional:
+  integer, parameter :: &
+      C_short_int = C_short, &
+      C_long_int = C_long, &
+      C_long_long_int = C_long_long, &
+      C_unsigned_int = C_unsigned, &
+      C_unsigned_short_int = C_short, &
+      C_unsigned_long_int = C_long, &
+      C_unsigned_long_long_int = C_long_long
+
+  interface C_F_string
+    module procedure C_F_string_ptr
+    module procedure C_F_string_chars
+  end interface C_F_string
+
+  interface F_C_string
+    module procedure F_C_string_ptr
+    module procedure F_C_string_chars
+  end interface F_C_string
+
+!=======================================================================
+! Some useful ISO C library string functions from <string.h>
+! These are based on GCC header sections marked as NAMESPACE_STD
+  interface
+
+! Copy N bytes of SRC to DEST, no aliasing or overlapping allowed.
+!extern void *memcpy (void *dest, const void *src, size_t n);
+    function C_memcpy(dest, src, n) result(result) bind(C,name="memcpy")
+      import C_void_ptr, C_size_t
+      type(C_void_ptr) :: result
+      type(C_void_ptr), value, intent(in) :: dest ! target=intent(out)
+      type(C_void_ptr), value, intent(in) :: src  ! target=intent(in)
+      integer(C_size_t), value, intent(in) :: n
+    end function C_memcpy
+
+! Copy N bytes of SRC to DEST, guaranteeing correct behavior for overlapping strings.
+!extern void *memmove (void *dest, const void *src, size_t n)
+    function C_memmove(dest, src, n) result(result) bind(C,name="memmove")
+      import C_void_ptr, C_size_t
+      type(C_void_ptr) :: result
+      type(C_void_ptr), value, intent(in) :: dest ! target=intent(out)
+      type(C_void_ptr), value, intent(in) :: src
+      integer(C_size_t), value, intent(in) :: n
+    end function C_memmove
+
+! Set N bytes of S to C.
+!extern void *memset (void *s, int c, size_t n)
+    function C_memset(s, c, n) result(result) bind(C,name="memset")
+      import C_void_ptr, C_int, C_size_t
+      type(C_void_ptr) :: result
+      type(C_void_ptr), value, intent(in) :: s ! target=intent(out)
+      integer(C_int), value, intent(in) :: c
+      integer(C_size_t), value, intent(in) :: n
+    end function C_memset
+
+! Compare N bytes of S1 and S2.
+!extern int memcmp (const void *s1, const void *s2, size_t n)
+    pure &
+    function C_memcmp(s1, s2, n) result(result) bind(C,name="memcmp")
+      import C_int, C_void_ptr, C_size_t
+      integer(C_int) :: result
+      type(C_void_ptr), value, intent(in) :: s1
+      type(C_void_ptr), value, intent(in) :: s2
+      integer(C_size_t), value, intent(in) :: n
+    end function C_memcmp
+
+! Search N bytes of S for C.
+!extern void *memchr (const void *s, int c, size_t n)
+    pure &
+    function C_memchr(s, c, n) result(result) bind(C,name="memchr")
+      import C_void_ptr, C_int, C_size_t
+      type(C_void_ptr) :: result
+      type(C_void_ptr), value, intent(in) :: s
+      integer(C_int), value, intent(in) :: c
+      integer(C_size_t), value, intent(in) :: n
+    end function C_memchr
+
+! Copy SRC to DEST.
+!extern char *strcpy (char *dest, const char *src)
+    function C_strcpy(dest, src) result(result) bind(C,name="strcpy")
+      import C_char_ptr, C_size_t
+      type(C_char_ptr) :: result
+      type(C_char_ptr), value, intent(in) :: dest ! target=intent(out)
+      type(C_char_ptr), value, intent(in) :: src
+    end function C_strcpy
+
+! Copy no more than N characters of SRC to DEST.
+!extern char *strncpy (char *dest, const char *src, size_t n)
+    function C_strncpy(dest, src, n) result(result) bind(C,name="strncpy")
+      import C_char_ptr, C_size_t
+      type(C_char_ptr) :: result
+      type(C_char_ptr), value, intent(in) :: dest ! target=intent(out)
+      type(C_char_ptr), value, intent(in) :: src
+      integer(C_size_t), value, intent(in) :: n
+    end function C_strncpy
+
+! Append SRC onto DEST.
+!extern char *strcat (char *dest, const char *src)
+    function C_strcat(dest, src) result(result) bind(C,name="strcat")
+      import C_char_ptr, C_size_t
+      type(C_char_ptr) :: result
+      type(C_char_ptr), value, intent(in) :: dest ! target=intent(out)
+      type(C_char_ptr), value, intent(in) :: src
+    end function C_strcat
+
+! Append no more than N characters from SRC onto DEST.
+!extern char *strncat (char *dest, const char *src, size_t n)
+    function C_strncat(dest, src, n) result(result) bind(C,name="strncat")
+      import C_char_ptr, C_size_t
+      type(C_char_ptr) :: result
+      type(C_char_ptr), value, intent(in) :: dest ! target=intent(out)
+      type(C_char_ptr), value, intent(in) :: src
+      integer(C_size_t), value, intent(in) :: n
+    end function C_strncat
+
+! Compare S1 and S2.
+!extern int strcmp (const char *s1, const char *s2)
+    pure &
+    function C_strcmp(s1, s2) result(result) bind(C,name="strcmp")
+      import C_int, C_char_ptr, C_size_t
+      integer(C_int) :: result
+      type(C_char_ptr), value, intent(in) :: s1
+      type(C_char_ptr), value, intent(in) :: s2
+    end function C_strcmp
+
+! Compare N characters of S1 and S2.
+!extern int strncmp (const char *s1, const char *s2, size_t n)
+    pure &
+    function C_strncmp(s1, s2, n) result(result) bind(C,name="strncmp")
+      import C_int, C_char_ptr, C_size_t
+      integer(C_int) :: result
+      type(C_char_ptr), value, intent(in) :: s1
+      type(C_char_ptr), value, intent(in) :: s2
+      integer(C_size_t), value, intent(in) :: n
+    end function C_strncmp
+
+! Return the length of S.
+!extern size_t strlen (const char *s)
+    pure &
+    function C_strlen(s) result(result) bind(C,name="strlen")
+      import C_char_ptr, C_size_t
+      integer(C_size_t) :: result
+      type(C_char_ptr), value, intent(in) :: s  !character(len=*), intent(in)
+    end function C_strlen
+
+  end interface
+
+! End of <string.h>
+!=========================================================================
+! Standard ISO-C malloc routines:
+  interface
+
+    ! void *calloc(size_t nmemb, size_t size);
+    type(C_void_ptr) &
+    function C_calloc(nmemb, size) bind(C,name="calloc")
+      import C_void_ptr, C_size_t
+      integer(C_size_t), value, intent(in) :: nmemb, size
+    end function C_calloc
+
+    ! void *malloc(size_t size);
+    type(C_void_ptr) &
+    function C_malloc(size) bind(C,name="malloc")
+      import C_void_ptr, C_size_t
+      integer(C_size_t), value, intent(in) :: size
+    end function C_malloc
+
+    ! void free(void *ptr);
+    subroutine C_free(ptr) bind(C,name="free")
+      import C_void_ptr
+      type(C_void_ptr), value, intent(in) :: ptr
+    end subroutine C_free
+
+    ! void *realloc(void *ptr, size_t size);
+    type(C_void_ptr) &
+    function C_realloc(ptr,size) bind(C,name="realloc")
+      import C_void_ptr, C_size_t
+      type(C_void_ptr), value, intent(in) :: ptr
+      integer(C_size_t), value, intent(in) :: size
+    end function C_realloc
+
+  end interface
+
+  interface assignment(=)
+    module procedure F_string_assign_C_string
+  end interface assignment(=)
+
+!==========================================================================
+
+contains
+
+  ! HACK: For some reason, C_associated was not defined as pure. 
+  pure logical &
+  function C_associated_pure(ptr) result(associated)
+    type(C_ptr), intent(in) :: ptr
+    integer(C_intptr_t) :: iptr
+    iptr = transfer(ptr,iptr)
+    associated = (iptr /= 0)
+  end function C_associated_pure
+
+! Set a fixed-length Fortran string to the value of a C string.
+  subroutine F_string_assign_C_string(F_string, C_string)
+    character(len=*), intent(out) :: F_string
+    type(C_ptr), intent(in) :: C_string
+    character(len=1,kind=C_char), pointer :: p_chars(:)
+    integer :: i
+    if (.not. C_associated(C_string) ) then
+      F_string = ' '
+    else
+      call C_F_pointer(C_string,p_chars,[huge(0)])
+      i=1
+      do while(p_chars(i)/=NUL .and. i<=len(F_string))
+        F_string(i:i) = p_chars(i)
+        i=i+1
+      end do
+      if (i<len(F_string)) F_string(i:) = ' '
+    end if
+  end subroutine F_string_assign_C_string
+
+! Copy a C string, passed by pointer, to a Fortran string.
+! If the C pointer is NULL, the Fortran string is blanked.
+! C_string must be NUL terminated, or at least as long as F_string.
+! If C_string is longer, it is truncated. Otherwise, F_string is
+! blank-padded at the end.
+  subroutine C_F_string_ptr(C_string, F_string)
+    type(C_ptr), intent(in) :: C_string
+    character(len=*), intent(out) :: F_string
+    character(len=1,kind=C_char), dimension(:), pointer :: p_chars
+    integer :: i
+    if (.not. C_associated(C_string)) then
+      F_string = ' '
+    else
+      call C_F_pointer(C_string,p_chars,[huge(0)])
+      i=1
+      do while(p_chars(i)/=NUL .and. i<=len(F_string))
+        F_string(i:i) = p_chars(i)
+        i=i+1
+      end do
+      if (i<len(F_string)) F_string(i:) = ' '
+    end if
+  end subroutine C_F_string_ptr
+
+! Copy a C string, passed as a char-array reference, to a Fortran string.
+  subroutine C_F_string_chars(C_string, F_string)
+    character(len=1,kind=C_char), intent(in) :: C_string(*)
+    character(len=*), intent(out) :: F_string
+    integer :: i
+    i=1
+    do while(C_string(i)/=NUL .and. i<=len(F_string))
+      F_string(i:i) = C_string(i)
+      i=i+1
+    end do
+    if (i<len(F_string)) F_string(i:) = ' '
+  end subroutine C_F_string_chars
+
+! Copy a Fortran string to an allocated C string pointer.
+! If the C pointer is NULL, no action is taken. (Maybe auto allocate via libc call?)
+! If the length is not passed, the C string must be at least: len(F_string)+1
+! If the length is passed and F_string is too long, it is truncated.
+  subroutine F_C_string_ptr(F_string, C_string, C_string_len)
+    character(len=*), intent(in) :: F_string
+    type(C_ptr), intent(in) :: C_string ! target = intent(out)
+    integer, intent(in), optional :: C_string_len  ! Max string length,
+                                                   ! INCLUDING THE TERMINAL NUL
+    character(len=1,kind=C_char), dimension(:), pointer :: p_chars
+    integer :: i, strlen
+    strlen = len(F_string)
+    if (present(C_string_len)) then
+      if (C_string_len <= 0) return
+      strlen = min(strlen,C_string_len-1)
+    end if
+    if (.not. C_associated(C_string)) then
+      return
+    end if
+    call C_F_pointer(C_string,p_chars,[strlen+1])
+    forall (i=1:strlen)
+      p_chars(i) = F_string(i:i)
+    end forall
+    p_chars(strlen+1) = NUL
+  end subroutine F_C_string_ptr
+
+  pure &
+  function C_strlen_safe(s) result(length)
+    integer(C_size_t) :: length
+    type(C_char_ptr), value, intent(in) :: s
+    if (.not. C_associated_pure(s)) then
+      length = 0
+    else
+      length = C_strlen(s)
+    end if
+  end function C_strlen_safe
+
+  function C_string_value(C_string) result(F_string)
+    type(C_ptr), intent(in) :: C_string
+    character(len=C_strlen_safe(C_string)) :: F_string
+    character(len=1,kind=C_char), dimension(:), pointer :: p_chars
+    integer :: i, length
+    length = len(F_string)
+    if (length/=0) then
+      call C_F_pointer(C_string,p_chars,[length])
+      forall (i=1:length)
+        F_string(i:i) = p_chars(i)
+      end forall
+    end if
+  end function C_string_value
+
+! Copy a Fortran string to a C string passed by char-array reference.
+! If the length is not passed, the C string must be at least: len(F_string)+1
+! If the length is passed and F_string is too long, it is truncated.
+  subroutine F_C_string_chars(F_string, C_string, C_string_len)
+    character(len=*), intent(in) :: F_string
+    character(len=1,kind=C_char), dimension(*), intent(out) :: C_string
+    integer, intent(in), optional :: C_string_len  ! Max string length,
+                                                   ! INCLUDING THE TERMINAL NUL
+    integer :: i, strlen
+    strlen = len(F_string)
+    if (present(C_string_len)) then
+      if (C_string_len <= 0) return
+      strlen = min(strlen,C_string_len-1)
+    end if
+    forall (i=1:strlen)
+      C_string(i) = F_string(i:i)
+    end forall
+    C_string(strlen+1) = NUL
+  end subroutine F_C_string_chars
+
+! NOTE: Strings allocated here must be freed by the
+! C library, such as via C_free() or C_string_free(),
+  type(C_ptr) &
+  function F_C_string_dup(F_string,length) result(C_string)
+    character(len=*), intent(in) :: F_string
+    integer, intent(in), optional :: length
+    character(len=1,kind=C_char), pointer :: C_string_ptr(:)
+    integer :: i
+    integer(C_size_t) :: strlen
+    if (present(length)) then
+      strlen = length
+    else
+      strlen = len(F_string)
+    end if
+    if (strlen <= 0) then
+      C_string = C_NULL_ptr
+    else
+      C_string = C_malloc(strlen+1)
+      if (C_associated(C_string)) then
+        call C_F_pointer(C_string,C_string_ptr,[strlen+1])
+        forall (i=1:strlen)
+          C_string_ptr(i) = F_string(i:i)
+        end forall
+        C_string_ptr(strlen+1) = NUL
+      end if
+    end if
+  end function F_C_string_dup
+
+! NOTE: Strings allocated here must be freed by the
+! C library, such as via C_free() or C_string_free(),
+  type(C_ptr) &
+  function C_string_alloc(length) result(C_string)
+    integer(C_size_t), intent(in) :: length
+    character(len=1,kind=C_char), pointer :: C_charptr
+    C_string = C_malloc(length+1)
+    if (C_associated(C_string)) then
+      call C_F_pointer(C_string,C_charptr)
+      C_charptr = NUL
+    end if
+  end function C_string_alloc
+
+  subroutine C_string_free(string)
+    type(C_ptr), intent(inout) :: string
+    if (C_associated(string)) then
+      call C_free(string)
+      string = C_NULL_ptr
+    end if
+  end subroutine C_string_free
+
+end module C_interface_module
\ No newline at end of file
diff --git a/build/source/global/cppwrap_datatypes.f90 b/build/source/global/cppwrap_datatypes.f90
index 7c77c80252ef98a42b64be74f7b680572ae727e2..0cc81f77579cb7e2c1d946951186824fd9475db8 100644
--- a/build/source/global/cppwrap_datatypes.f90
+++ b/build/source/global/cppwrap_datatypes.f90
@@ -1227,29 +1227,8 @@ subroutine delete_handle_dlength_array(handle) bind(C, name='delete_handle_dleng
 
 end subroutine
 ! ************************ var_dlength_array ************************
-! ***************************** file_info ***************************
-function new_handle_file_info() result(handle) bind(C, name='new_handle_file_info')
-  type(c_ptr) :: handle
-  type(file_info_array), pointer :: p
-
-  allocate(p)
-  handle = c_loc(p)
-
-end function new_handle_file_info
-
-!---------------------------------
-subroutine delete_handle_file_info(handle) bind(C, name='delete_handle_file_info')
-
-  type(c_ptr), intent(in), value :: handle
-  type(file_info_array), pointer :: p
-
-  call c_f_pointer(handle, p)
-  deallocate(p)
-
-end subroutine delete_handle_file_info
-! ***************************** file_info ***************************
-    
 
+  
 ! ****************************** z_lookup ****************************
 #ifdef V4_ACTIVE
 function new_handle_z_lookup() result(handle) bind(C, name="new_handle_z_lookup")
diff --git a/build/source/global/fileManager.cpp b/build/source/global/fileManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..06ba4e59d4420fa2d391080a62e73a96f7720cc1
--- /dev/null
+++ b/build/source/global/fileManager.cpp
@@ -0,0 +1,110 @@
+#include "fileManager.hpp"
+#include <iostream>
+#include <fstream>
+#include <memory>
+
+// Helper function to extract a string enclosed in single quotes
+std::string extractEnclosed(const std::string& line) {
+  std::size_t first_quote = line.find_first_of("'");
+  std::size_t last_quote = line.find_last_of("'");
+  if (first_quote != std::string::npos && last_quote != std::string::npos 
+      && first_quote < last_quote) {
+    return line.substr(first_quote + 1, last_quote - first_quote - 1);
+  }
+  return "";
+}
+
+fileManager::fileManager(const std::string& file_manager_path) {
+  std::cout << "Rading File Manager\n";
+  file_manager_path_ = file_manager_path;
+
+  std::ifstream file(file_manager_path);
+  if (!file.is_open()) {
+    std::cerr << "Unable to open file: " << file_manager_path << std::endl;
+    return;
+  }
+
+  std::string line;
+  while (std::getline(file, line)) {
+    if (line.compare(0, 14, "controlVersion") == 0) {
+      control_vrs_ = extractEnclosed(line);
+    } else if (line.compare(0, 12,"simStartTime") == 0) {
+      sim_start_tm_ = extractEnclosed(line);
+    } else if (line.compare(0, 10, "simEndTime") == 0) {
+      sim_end_tm_ = extractEnclosed(line);
+    } else if (line.compare(0, 10, "tmZoneInfo") == 0) {
+      nc_time_zone_ = extractEnclosed(line);
+    } else if (line.compare(0, 12, "settingsPath") == 0) {
+      settings_path_ = extractEnclosed(line);
+    } else if (line.compare(0, 11, "forcingPath") == 0) {
+      forcing_path_ = extractEnclosed(line);
+    } else if (line.compare(0, 10, "outputPath") == 0) {
+      output_path_ = extractEnclosed(line);
+    } else if (line.compare(0, 9, "statePath") == 0) {
+      state_path_ = extractEnclosed(line);
+    } else if (line.compare(0, 13, "decisionsFile") == 0) {
+      m_decisions_ = extractEnclosed(line);
+    } else if (line.compare(0, 17, "outputControlFile") == 0) {
+      output_control_ = extractEnclosed(line);
+    } else if (line.compare(0, 18, "globalHruParamFile") == 0) {
+      localparam_info_ = extractEnclosed(line);
+    } else if (line.compare(0, 18, "globalGruParamFile") == 0) {
+      basinparam_info_ = extractEnclosed(line);
+    } else if (line.compare(0, 13, "attributeFile") == 0) {
+      local_attributes_ = extractEnclosed(line);
+    } else if (line.compare(0, 14, "trialParamFile") == 0) {
+      parameter_trial_ = extractEnclosed(line);
+    } else if (line.compare(0, 12, "vegTableFile") == 0) {
+      vegparm_ = extractEnclosed(line);
+    } else if (line.compare(0, 13, "soilTableFile") == 0) {
+      soilparm_ = extractEnclosed(line);
+    } else if (line.compare(0, 16, "generalTableFile") == 0) {
+      genparm_ = extractEnclosed(line);
+    } else if (line.compare(0, 15, "noahmpTableFile") == 0) {
+      mptable_ = extractEnclosed(line);
+    } else if (line.compare(0, 15, "forcingListFile") == 0) {
+      forcing_filelist_ = extractEnclosed(line);
+    } else if (line.compare(0, 17, "initConditionFile") == 0) {
+      model_initcond_ = extractEnclosed(line);
+    } else if (line.compare(0, 13, "outFilePrefix") == 0) {
+      output_prefix_ = extractEnclosed(line);
+    } else {
+      std::cerr << "Unrecognized line in file: " << line << std::endl;
+    }
+  }
+  file.close();
+}
+
+
+std::string fileManager::setTimesDirsAndFiles() {
+  int err = 0;
+  std::unique_ptr<char[]> err_msg(new char[1024]);
+  // Calls summa_SetTimesDirsAndFiles() 
+  setTimesDirsAndFiles_fortran(file_manager_path_.c_str(), &err, &err_msg);
+  return std::string(err_msg.get());
+}
+
+std::string fileManager::toString() {
+  std::string str = "Control Version: " + control_vrs_ + "\n";
+              str += "Simulation Start Time: " + sim_start_tm_ + "\n";
+              str += "Simulation End Time: " + sim_end_tm_ + "\n";
+              str += "Time Zone Info: " + nc_time_zone_ + "\n";
+              str += "Settings Path: " + settings_path_ + "\n";
+              str += "Forcing Path: " + forcing_path_ + "\n";
+              str += "Output Path: " + output_path_ + "\n";
+              str += "State Path: " + state_path_ + "\n";
+              str += "Decisions File: " + m_decisions_ + "\n";
+              str += "Output Control File: " + output_control_ + "\n";
+              str += "Global HRU Param File: " + localparam_info_ + "\n";
+              str += "Global GRU Param File: " + basinparam_info_ + "\n";
+              str += "Attribute File: " + local_attributes_ + "\n";
+              str += "Trial Param File: " + parameter_trial_ + "\n";
+              str += "Veg Table File: " + vegparm_ + "\n";
+              str += "Soil Table File: " + soilparm_ + "\n";
+              str += "General Table File: " + genparm_ + "\n";
+              str += "NoahMP Table File: " + mptable_ + "\n";
+              str += "Forcing List File: " + forcing_filelist_ + "\n";
+              str += "Init Condition File: " + model_initcond_ + "\n";
+              str += "Output File Prefix: " + output_prefix_ + "\n";
+  return str;
+}
\ No newline at end of file
diff --git a/build/source/global/message_atoms.cpp b/build/source/global/message_atoms.cpp
index 25037a479af6b2b24744eac87975ba03d25c5a02..dd86857c1b31d3d2d2ff587b2549256760472a6c 100644
--- a/build/source/global/message_atoms.cpp
+++ b/build/source/global/message_atoms.cpp
@@ -1,42 +1,6 @@
 #include "caf/all.hpp"
 #include "message_atoms.hpp"
 
-// HRU Errors
-std::string to_string(hru_error err) {
-    switch(err) {
-        case hru_error::run_physics_unhandleable:
-            return "run_physics_unhandleable";
-        case hru_error::run_physics_infeasible_state:
-            return "run_physics_infeasible_state";
-        default:
-            return "unknown";
-    }
-}
-
-bool from_string(caf::string_view in, hru_error& out) {
-    if (in == "run_physics_unhandleable") {
-        out = hru_error::run_physics_unhandleable;
-        return true;
-    }
-    if (in == "run_physics_infeasible_state") {
-        out = hru_error::run_physics_infeasible_state;
-        return true;
-    }
-    return false;
-}
-
-bool from_integer(uint8_t in, hru_error& out) {
-    switch(in) {
-        case 1:
-            out = hru_error::run_physics_unhandleable;
-            return true;
-        case 2:
-            out = hru_error::run_physics_infeasible_state;
-            return true;
-        default:
-            return false;
-    }
-}
 
 // File Access Error
 std::string to_string(file_access_error err) {
diff --git a/build/source/global/settings_functions.cpp b/build/source/global/settings_functions.cpp
index 7901454a211111204aea38f217a92906bcea6b6e..1bad737178d907550234c60c9f7b3783a14a7759 100644
--- a/build/source/global/settings_functions.cpp
+++ b/build/source/global/settings_functions.cpp
@@ -170,47 +170,6 @@ HRU_Actor_Settings readHRUActorSettings(std::string json_settings_file) {
         local_atol = 1e-6;
     }
 
-    hru_actor_settings.relTolTempCas = getSettings(json_settings_file, parent_key,
-        "relTolTempCas", hru_actor_settings.relTolTempCas).value_or(local_rtol);
-
-    hru_actor_settings.absTolTempCas = getSettings(json_settings_file, parent_key,
-        "absTolTempCas", hru_actor_settings.absTolTempCas).value_or(local_atol);
-
-    hru_actor_settings.relTolTempVeg = getSettings(json_settings_file, parent_key,
-        "relTolTempVeg", hru_actor_settings.relTolTempVeg).value_or(local_rtol);
-
-    hru_actor_settings.absTolTempVeg = getSettings(json_settings_file, parent_key,
-        "absTolTempVeg", hru_actor_settings.absTolTempVeg).value_or(local_atol);
-
-    hru_actor_settings.relTolWatVeg = getSettings(json_settings_file, parent_key,
-        "relTolWatVeg", hru_actor_settings.relTolWatVeg).value_or(local_rtol);
-
-    hru_actor_settings.absTolWatVeg = getSettings(json_settings_file, parent_key,
-        "absTolWatVeg", hru_actor_settings.absTolWatVeg).value_or(local_atol);
-
-    hru_actor_settings.relTolTempSoilSnow = getSettings(json_settings_file, parent_key,
-        "relTolTempSoilSnow", hru_actor_settings.relTolTempSoilSnow).value_or(local_rtol);
-
-    hru_actor_settings.absTolTempSoilSnow = getSettings(json_settings_file, parent_key,
-        "absTolTempSoilSnow", hru_actor_settings.absTolTempSoilSnow).value_or(local_atol);
-
-    hru_actor_settings.relTolWatSnow = getSettings(json_settings_file, parent_key,
-        "relTolWatSnow", hru_actor_settings.relTolWatSnow).value_or(local_rtol);
-
-    hru_actor_settings.absTolWatSnow = getSettings(json_settings_file, parent_key,
-        "absTolWatSnow", hru_actor_settings.absTolWatSnow).value_or(local_atol);
-
-    hru_actor_settings.relTolMatric = getSettings(json_settings_file, parent_key,
-        "relTolMatric", hru_actor_settings.relTolMatric).value_or(local_rtol);
-
-    hru_actor_settings.absTolMatric = getSettings(json_settings_file, parent_key,
-        "absTolMatric", hru_actor_settings.absTolMatric).value_or(local_atol);
-
-    hru_actor_settings.relTolAquifr = getSettings(json_settings_file, parent_key,
-        "relTolAquifr", hru_actor_settings.relTolAquifr).value_or(local_rtol);
-
-    hru_actor_settings.absTolAquifr = getSettings(json_settings_file, parent_key,
-        "absTolAquifr", hru_actor_settings.absTolAquifr).value_or(local_atol);
 
     return hru_actor_settings;
 }
@@ -257,12 +216,15 @@ void check_settings_from_json(Distributed_Settings &distributed_settings,
 
 
 void generate_config_file() {
+    using json = nlohmann::ordered_json;
     json config_file; 
     config_file["Distributed_Settings"] = {
         {"distributed_mode", false},
         {"port", missing_value},
         {"total_hru_count", missing_value},
         {"num_hru_per_batch", missing_value},
+        {"load_balancing", false},
+        {"num_nodes", missing_value},
         {"servers_list", {
             {{"hostname", "host_1"}},
             {{"hostname", "host_2"}},
@@ -292,6 +254,6 @@ void generate_config_file() {
     };
 
     std::ofstream config_file_stream("config.json");
-    config_file_stream << std::setw(4) << config_file.dump(4) << std::endl;
+    config_file_stream << std::setw(4) << config_file.dump(2) << std::endl;
     config_file_stream.close();
 }
\ 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 60fdb8673261a4759dfadb7c9d89e03f58770277..d99b698e8eac3d91578de7a80c804c3adfa101f1 100644
--- a/build/source/hru_actor/hru_actor.cpp
+++ b/build/source/hru_actor/hru_actor.cpp
@@ -2,13 +2,12 @@
 
 bool hru_extra_logging = false;
 
-namespace caf {
-
-behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
-    HRU_Actor_Settings hru_actor_settings, caf::actor file_access_actor, 
-    caf::actor parent) {
-
-  self->set_exit_handler([=](const exit_msg& msg) {
+using namespace caf;
+behavior hru_actor(stateful_actor<hru_state>* self, int ref_gru, int indx_gru,
+                   HRU_Actor_Settings hru_actor_settings, 
+                   actor file_access_actor, actor parent) {
+            
+  self->set_exit_handler([=](const caf::exit_msg& msg) {
     aout(self) << "HRU Actor: Received Exit Message\n";
   });
   
@@ -16,13 +15,13 @@ behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
   self->state.file_access_actor = file_access_actor;
   self->state.parent            = parent;
   // Indexes into global structures
+  self->state.ref_gru           = ref_gru;
+  self->state.indxGRU           = indx_gru;
   self->state.indxHRU           = 1;
-  self->state.indxGRU           = indxGRU;
-  self->state.refGRU            = refGRU;
   if (hru_extra_logging) {
     aout(self) << "HRU Actor: indxHRU = " << self->state.indxHRU 
                << " indxGRU = " << self->state.indxGRU 
-               << " refGRU = " << self->state.refGRU << "\n";
+               << " ref_gru = " << self->state.ref_gru << "\n";
   }
   // Get the settings for the HRU
   self->state.hru_actor_settings = hru_actor_settings;
@@ -37,46 +36,35 @@ behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
       Initialize_HRU(self);
     },
 
-
-    /* Job actor telling us to run until completions
-        We will interact with the file access actor */
+    /* Run until completion -- only interact with the file access actor */
     [=](update_hru_async) {
       self->request(self->state.file_access_actor, caf::infinite,
-          get_num_output_steps_v).await([=](int num_steps){
+                    get_num_output_steps_v).await([=](int num_steps) {
         self->state.num_steps_until_write = num_steps;
         self->send(self->state.file_access_actor, access_forcing_v, 
-                    self->state.iFile, self);
+                   self->state.iFile, self);
       });
     },
 
     [=](num_steps_before_write, int num_steps) {
-        self->state.num_steps_until_write = num_steps;
-        self->state.output_structure_step_index = 1;
+      self->state.num_steps_until_write = num_steps;
+      self->state.output_structure_step_index = 1;
     },
 
     // Run HRU for a number of timesteps
     [=](run_hru) {
       int err = 0;
-
       while(self->state.num_steps_until_write > 0) {
         if (self->state.forcingStep > self->state.stepsInCurrentFFile) {
           self->send(self->state.file_access_actor, access_forcing_v, 
-              self->state.iFile+1, self);
+                     self->state.iFile+1, self);
           break;
         }
 
         self->state.num_steps_until_write--;
         err = Run_HRU(self); // Simulate a Timestep
         if (err != 0) {
-          #ifdef SUNDIALS_ACTIVE                        
-            get_sundials_tolerances(self->state.hru_data, 
-                &self->state.rtol, &self->state.atol);
-            self->send(self->state.parent, err_atom_v, self, self->state.rtol,
-                self->state.atol);
-          #else                        
-            self->send(self->state.parent, 
-                hru_error::run_physics_unhandleable, self);
-          #endif
+          self->send(self->state.parent, err_atom_v, err, self->state.indxGRU);
           self->quit();
           return;
         }
@@ -100,32 +88,45 @@ behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
 
 
     [=](new_forcing_file, int num_forcing_steps_in_iFile, int iFile) {
-        int err;
-        self->state.iFile = iFile;
-        self->state.stepsInCurrentFFile = num_forcing_steps_in_iFile;
-        setTimeZoneOffset(&self->state.iFile, self->state.hru_data, &err);
-        self->state.forcingStep = 1;
-        self->send(self, run_hru_v);
+      if (hru_extra_logging) {
+        aout(self) << "Recieved New iFile-" << iFile 
+                   << " with " << num_forcing_steps_in_iFile 
+                   << " forcing steps\n";
+      }
+      int err;
+      self->state.iFile = iFile;
+      self->state.stepsInCurrentFFile = num_forcing_steps_in_iFile;
+      setTimeZoneOffset(&self->state.iFile, self->state.hru_data, &err);
+      if (err != 0) {
+        aout(self) << "Error: HRU_Actor - setTimeZoneOffset - HRU = " 
+                   << self->state.indxHRU << " - indxGRU = " 
+                   << self->state.indxGRU << " - refGRU = " 
+                   << self->state.ref_gru << "\n";
+        self->quit();
+        return;
+      }
+      self->state.forcingStep = 1;
+      self->send(self, run_hru_v);
     },
 
     
     [=](done_hru) {
-        self->send(self->state.parent,done_hru_v,self->state.indxGRU);
-        self->quit();
-        return;
+      self->send(self->state.parent,done_hru_v,self->state.indxGRU);
+      self->quit();
+      return;
     },
 
     [=](dt_init_factor, int dt_init_factor) {
-        aout(self) << "Recieved New dt_init_factor to attempt on next run \n";
+      aout(self) << "Recieved New dt_init_factor to attempt on next run \n";
     },
 
     [=](update_timeZoneOffset, int iFile) {
-        if (hru_extra_logging)
-            aout(self) << "Recieved New iFile-" << iFile 
-                       << " to update timeZoneOffset \n";
-        int err;
-        self->state.iFile = iFile;
-        setTimeZoneOffset(&iFile, self->state.hru_data, &err);
+      if (hru_extra_logging)
+          aout(self) << "Recieved New iFile-" << iFile 
+                     << " Updating timeZoneOffset\n";
+      int err;
+      self->state.iFile = iFile;
+      setTimeZoneOffset(&iFile, self->state.hru_data, &err);
     },
 
     // BMI - Functions
@@ -141,8 +142,7 @@ behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
 
       int err = Run_HRU(self);
       if (err != 0) {
-        self->send(self->state.parent, hru_error::run_physics_unhandleable,
-            self);
+        self->send(self->state.parent, err_atom_v, err, self->state.indxGRU);
         self->quit();
         return;
       }
@@ -153,262 +153,99 @@ behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
 
     // Get Fortran Data into C++
     [=](serialize_hru) {
-
-      // std::vector<std::vector<std::vector<double>>> lookup_struct = 
-          // get_lookup_struct(self->state.hru_data);
-
-      self->state.hru_data_serialized.indx_hru = self->state.indxHRU;
-      self->state.hru_data_serialized.indx_gru = self->state.indxGRU;
-      self->state.hru_data_serialized.ref_gru = self->state.refGRU;
-      self->state.hru_data_serialized.timestep = self->state.timestep;
-      self->state.hru_data_serialized.forcing_step = self->state.forcingStep;
-      self->state.hru_data_serialized.num_steps = self->state.num_steps;
-      self->state.hru_data_serialized.iFile = self->state.iFile;
-      self->state.hru_data_serialized.dt_init_factor = 
-          self->state.dt_init_factor;
-      self->state.hru_data_serialized.output_structure_step_index = 
-          self->state.output_structure_step_index; 
-      self->state.hru_data_serialized.dt_init = self->state.dt_init;
-      self->state.hru_data_serialized.upArea = self->state.upArea;
-      self->state.hru_data_serialized.rtol = self->state.rtol;
-      self->state.hru_data_serialized.atol = self->state.atol;
-
-      // Statistic Structures
-      self->state.hru_data_serialized.forc_stat = 
-          get_var_dlength_by_indx(self->state.hru_data, 1); 
-      self->state.hru_data_serialized.prog_stat = 
-          get_var_dlength_by_indx(self->state.hru_data, 2); 
-      self->state.hru_data_serialized.diag_stat = 
-          get_var_dlength_by_indx(self->state.hru_data, 3); 
-      self->state.hru_data_serialized.flux_stat = 
-          get_var_dlength_by_indx(self->state.hru_data, 4); 
-      self->state.hru_data_serialized.indx_stat = 
-          get_var_dlength_by_indx(self->state.hru_data, 5); 
-      self->state.hru_data_serialized.bvar_stat = 
-          get_var_dlength_by_indx(self->state.hru_data, 6);
-      
-      // Primary Data Structures (scalars)
-      self->state.hru_data_serialized.time_struct = 
-          get_var_i_by_indx(self->state.hru_data, 1);
-      self->state.hru_data_serialized.forc_struct = 
-          get_var_d_by_indx(self->state.hru_data, 1);
-      self->state.hru_data_serialized.attr_struct = 
-          get_var_d_by_indx(self->state.hru_data, 2);
-      self->state.hru_data_serialized.type_struct = 
-          get_var_i_by_indx(self->state.hru_data, 2);
-      self->state.hru_data_serialized.id_struct = 
-          get_var_i8_by_indx(self->state.hru_data, 1);
-      
-      // Primary Data Structures (variable length vectors)
-      self->state.hru_data_serialized.indx_struct = 
-          get_var_ilength_by_indx(self->state.hru_data, 1);
-      self->state.hru_data_serialized.mpar_struct = 
-          get_var_dlength_by_indx(self->state.hru_data, 7);      
-      self->state.hru_data_serialized.prog_struct = 
-          get_var_dlength_by_indx(self->state.hru_data, 8);
-      self->state.hru_data_serialized.diag_struct = 
-          get_var_dlength_by_indx(self->state.hru_data, 9);
-      self->state.hru_data_serialized.flux_struct = 
-          get_var_dlength_by_indx(self->state.hru_data, 10);
-
-      // Basin-average structures
-      self->state.hru_data_serialized.bpar_struct = 
-          get_var_d_by_indx(self->state.hru_data, 3);
-      self->state.hru_data_serialized.bvar_struct = 
-          get_var_dlength_by_indx(self->state.hru_data, 11);
-      self->state.hru_data_serialized.dpar_struct = 
-          get_var_d_by_indx(self->state.hru_data, 4);
-
-      // Local HRU data structures
-      self->state.hru_data_serialized.start_time = 
-          get_var_i_by_indx(self->state.hru_data, 3);
-      self->state.hru_data_serialized.end_time = 
-          get_var_i_by_indx(self->state.hru_data, 4);
-      self->state.hru_data_serialized.ref_time = 
-          get_var_i_by_indx(self->state.hru_data, 5);
-      self->state.hru_data_serialized.old_time = 
-          get_var_i_by_indx(self->state.hru_data, 6);
-
-      // Statistic flags
-      self->state.hru_data_serialized.stat_counter = 
-          get_var_i_by_indx(self->state.hru_data, 7);
-      self->state.hru_data_serialized.output_timestep = 
-          get_var_i_by_indx(self->state.hru_data, 8);
-      self->state.hru_data_serialized.reset_stats = 
-          get_flagVec_by_indx(self->state.hru_data, 1);
-      self->state.hru_data_serialized.finalize_stats = 
-          get_flagVec_by_indx(self->state.hru_data, 2);
-
-      get_scalar_data(self->state.hru_data,
-          self->state.hru_data_serialized.frac_jul_day,
-          self->state.hru_data_serialized.tm_zone_offset_frac_day,
-          self->state.hru_data_serialized.year_length,
-          self->state.hru_data_serialized.compute_veg_flux);
-       
-      self->send(self->state.parent, self->state.hru_data_serialized);
+      hru serialized_state;
+      serializeHru(self, serialized_state);
+      self->send(self->state.parent, serialized_state);
     },
 
     [=](reinit_hru, hru hru_data) {
-
-      // Set output structure finalize stats to false for all timesteps of 
-      // the old GRU index
-      setFinalizeStatsFalse(&self->state.indxGRU);
-      // deallocate the old hru_data
-      delete_handle_hru_type(self->state.hru_data);
-      self->state.hru_data = new_handle_hru_type();
-
-
-      self->state.indxHRU = hru_data.indx_hru;
-      self->state.indxGRU = hru_data.indx_gru;
-      self->state.refGRU = hru_data.ref_gru;
-      self->state.timestep = hru_data.timestep;
-      self->state.forcingStep = hru_data.forcing_step;
-      self->state.num_steps = hru_data.num_steps;
-      self->state.iFile = hru_data.iFile;
-      self->state.dt_init_factor = hru_data.dt_init_factor;
-      self->state.output_structure_step_index = 
-          hru_data.output_structure_step_index;
-      self->state.dt_init = hru_data.dt_init;
-      self->state.upArea = hru_data.upArea;
-      self->state.rtol = hru_data.rtol;
-      self->state.atol = hru_data.atol;
-
-      // Statistic Structures
-      set_var_dlength_by_indx(self->state.hru_data, hru_data.forc_stat, 1);
-      set_var_dlength_by_indx(self->state.hru_data, hru_data.prog_stat, 2);
-      set_var_dlength_by_indx(self->state.hru_data, hru_data.diag_stat, 3);
-      set_var_dlength_by_indx(self->state.hru_data, hru_data.flux_stat, 4);
-      set_var_dlength_by_indx(self->state.hru_data, hru_data.indx_stat, 5);
-      set_var_dlength_by_indx(self->state.hru_data, hru_data.bvar_stat, 6);
-
-      // Primary Data Structures (scalars)
-      set_var_i_by_indx(self->state.hru_data, hru_data.time_struct, 1);
-      set_var_d_by_indx(self->state.hru_data, hru_data.forc_struct, 1);
-      set_var_d_by_indx(self->state.hru_data, hru_data.attr_struct, 2);
-      set_var_i_by_indx(self->state.hru_data, hru_data.type_struct, 2);
-      set_var_i8_by_indx(self->state.hru_data, hru_data.id_struct, 1);
-
-      // Primary Data Structures (variable length vectors)
-      set_var_ilength_by_indx(self->state.hru_data, hru_data.indx_struct, 1);
-      set_var_dlength_by_indx(self->state.hru_data, hru_data.mpar_struct, 7);
-      set_var_dlength_by_indx(self->state.hru_data, hru_data.prog_struct, 8);
-      set_var_dlength_by_indx(self->state.hru_data, hru_data.diag_struct, 9);
-      set_var_dlength_by_indx(self->state.hru_data, hru_data.flux_struct, 10);
-
-      // Basin-average structures
-      set_var_d_by_indx(self->state.hru_data, hru_data.bpar_struct, 3);
-      set_var_dlength_by_indx(self->state.hru_data, hru_data.bvar_struct, 11);
-      set_var_d_by_indx(self->state.hru_data, hru_data.dpar_struct, 4);
-
-      // Local HRU data structures
-      set_var_i_by_indx(self->state.hru_data, hru_data.start_time, 3);
-      set_var_i_by_indx(self->state.hru_data, hru_data.end_time, 4);
-      set_var_i_by_indx(self->state.hru_data, hru_data.ref_time, 5);
-      set_var_i_by_indx(self->state.hru_data, hru_data.old_time, 6);
-
-      // statistic flags
-      set_var_i_by_indx(self->state.hru_data, hru_data.stat_counter, 7);
-      set_var_i_by_indx(self->state.hru_data, hru_data.output_timestep, 8);
-      set_flagVec_by_indx(self->state.hru_data, hru_data.reset_stats, 1);
-      set_flagVec_by_indx(self->state.hru_data, hru_data.finalize_stats, 2);
-
-      // scalar data
-      set_scalar_data(self->state.hru_data, hru_data.frac_jul_day,
-          hru_data.tm_zone_offset_frac_day, hru_data.year_length,
-          hru_data.compute_veg_flux);
-
+      deserializeHru(self, hru_data);
       self->send(self->state.parent, reinit_hru_v);
     },
-
   };
 }
 
 
 
 void Initialize_HRU(stateful_actor<hru_state>* self) {
+  int err = 0;
   initHRU(&self->state.indxGRU, &self->state.num_steps, self->state.hru_data, 
-      &self->state.err);
-  if (self->state.err != 0) {
+          &err);
+  if (err != 0) {
     aout(self) << "Error: HRU_Actor - Initialize - HRU = " 
                << self->state.indxHRU  
                << " - indxGRU = " << self->state.indxGRU 
-               << " - refGRU = "<< self->state.refGRU
-               << "\nError Code = " << self->state.err << "\n";
+               << " - refGRU = "<< self->state.ref_gru
+               << "\nError Code = " << err << "\n";
     self->quit();
   }
 
   setupHRUParam(&self->state.indxGRU, &self->state.indxHRU, 
-      self->state.hru_data, &self->state.upArea, &self->state.err);
-  if (self->state.err != 0) {
+                self->state.hru_data, &self->state.upArea, &err);
+  if (err != 0) {
     aout(self) << "Error: HRU_Actor - SetupHRUParam - HRU = " 
                 << self->state.indxHRU
                 << " - indxGRU = " << self->state.indxGRU 
-                << " - refGRU = " << self->state.refGRU << "\n";
+                << " - refGRU = " << self->state.ref_gru << "\n";
     self->quit();
     return;
   }
           
   summa_readRestart(&self->state.indxGRU, &self->state.indxHRU,
-      self->state.hru_data, &self->state.dt_init, &self->state.err);
-  if (self->state.err != 0) {
+                    self->state.hru_data, &self->state.dt_init, &err);
+  if (err != 0) {
     aout(self) << "Error: HRU_Actor - summa_readRestart - HRU = " 
                << self->state.indxHRU
                << " - indxGRU = " << self->state.indxGRU 
-               << " - refGRU = " << self->state.refGRU << "\n";
+               << " - refGRU = " << self->state.ref_gru << "\n";
     self->quit();
     return;
   }
   #ifdef SUNDIALS_ACTIVE
     if (self->state.hru_actor_settings.rel_tol > 0 && 
-        self->state.hru_actor_settings.abs_tol > 0)
+        self->state.hru_actor_settings.abs_tol > 0) {
       set_sundials_tolerances(self->state.hru_data, 
-          &self->state.hru_actor_settings.rel_tol, 
-          &self->state.hru_actor_settings.abs_tol);
+                              &self->state.hru_actor_settings.rel_tol, 
+                              &self->state.hru_actor_settings.abs_tol);
+    }
   #endif           
 }
 
 int Run_HRU(stateful_actor<hru_state>* self) {
-  /**********************************************************************
-  ** READ FORCING
-  **********************************************************************/    
+  int err = 0;
   HRU_readForcing(&self->state.indxGRU, &self->state.timestep, 
-      &self->state.forcingStep, &self->state.iFile, self->state.hru_data, 
-      &self->state.err);
-  if (self->state.err != 0) {
+                  &self->state.forcingStep, &self->state.iFile, 
+                  self->state.hru_data, &err);
+  if (err != 0) {
     aout(self) << "Error---HRU_Actor: ReadForcingHRU\n" 
                << "\tIndxGRU = " << self->state.indxGRU << "\n"
-               << "\tRefGRU = " << self->state.refGRU << "\n"
+               << "\tRefGRU = " << self->state.ref_gru << "\n"
                << "\tForcing Step = " << self->state.forcingStep << "\n"
                << "\tTimestep = " << self->state.timestep << "\n"
                << "\tiFile = " << self->state.iFile << "\n"
                << "\tSteps in Forcing File = " 
                << self->state.stepsInCurrentFFile << "\n";
     self->quit();
-    return -1;
+    return err;
   }
 
-  if (self->state.hru_actor_settings.print_output && self->state.timestep % 
-      self->state.hru_actor_settings.output_frequency == 0) {
-    aout(self) << self->state.refGRU << " - Timestep = " 
+  auto& settings = self->state.hru_actor_settings;
+  if (settings.print_output && self->state.timestep % 
+      settings.output_frequency == 0) {
+    aout(self) << self->state.ref_gru << " - Timestep = " 
                << self->state.timestep << "\n";
   }
     
-
-    /**********************************************************************
-    ** RUN_PHYSICS    
-    **********************************************************************/    
-
-  self->state.err = 0;
   RunPhysics(&self->state.indxHRU, &self->state.timestep, self->state.hru_data, 
-      &self->state.dt_init,  &self->state.dt_init_factor, 
-      &self->state.walltime_timestep, &self->state.err);
-  if (self->state.err != 0) {
+             &self->state.dt_init,  &self->state.dt_init_factor, 
+             &self->state.walltime_timestep, &err);
+  if (err != 0) {
     aout(self) << "Error---RunPhysics:\n"
                << "\tIndxGRU = "  << self->state.indxGRU 
-               << "\tRefGRU = "   << self->state.refGRU 
+               << "\tRefGRU = "   << self->state.ref_gru 
                << "\tTimestep = " << self->state.timestep <<  "\n";
     self->quit();
-    return 20;
+    return err;
   }
 
   if (self->state.timestep != 0){
@@ -417,13 +254,15 @@ int Run_HRU(stateful_actor<hru_state>* self) {
     int y,m,d,h;
 
     hru_writeOutput(&self->state.indxHRU, &self->state.indxGRU,
-        &self->state.timestep, &self->state.output_structure_step_index,
-        self->state.hru_data, &y, &m, &d, &h, &self->state.err);
-    if (self->state.err != 0) {
+                    &self->state.timestep, 
+                    &self->state.output_structure_step_index,
+                    self->state.hru_data, &y, &m, &d, &h, &err);
+    if (err != 0) {
       aout(self) << "Error: HRU_Actor - writeHRUToOutputStructure - HRU = " 
-                  << self->state.indxHRU << " - indxGRU = " 
-                  << self->state.indxGRU << " - refGRU = " << self->state.refGRU
-                  << "\nError = " << self->state.err  << "\n";
+                 << self->state.indxHRU << " - indxGRU = " 
+                 << self->state.indxGRU << " - refGRU = " 
+                 << self->state.ref_gru
+                 << "\nError = " << err  << "\n";
       self->quit();
       return 21;
     }
@@ -441,25 +280,19 @@ int Run_HRU(stateful_actor<hru_state>* self) {
     // check if hru reached a checkpoint, if so it will write restart data to outputsructure and
     // send an update to the FAA
     if (isCheckpoint(self)){
-        self->state.checkpoint++;
-
-        hru_writeRestart(&self->state.indxHRU, 
-                        &self->state.indxGRU,
-                        &self->state.output_structure_step_index,
-                        &self->state.output_structure_step_index, //unused
-                        self->state.hru_data,
-                        &self->state.err);
-                  
-        self->send(self->state.file_access_actor, 
-            write_restart_v,
-            self->state.refGRU,
-            self->state.timestep,
-            self->state.checkpoint,
-            self->state.output_structure_step_index,
-            self->state.currentDate.y,
-            self->state.currentDate.m,
-            self->state.currentDate.d,
-            self->state.currentDate.h);
+      self->state.checkpoint++;
+
+      hru_writeRestart(&self->state.indxHRU, &self->state.indxGRU,
+                       &self->state.output_structure_step_index,
+                       &self->state.output_structure_step_index, //unused
+                       self->state.hru_data, &err);
+                
+      self->send(self->state.file_access_actor, write_restart_v,
+                 self->state.ref_gru, self->state.timestep,
+                 self->state.checkpoint,
+                 self->state.output_structure_step_index,
+                 self->state.currentDate.y, self->state.currentDate.m,
+                 self->state.currentDate.d, self->state.currentDate.h);
     }
 
 
@@ -470,34 +303,32 @@ int Run_HRU(stateful_actor<hru_state>* self) {
 
 // given a hru_actor with a state, compared current date with starting date to deterimine if hru is on a checkpoint
 bool isCheckpoint(stateful_actor<hru_state>* self){
-    switch(self->state.restartFrequency){
-        case 0: // restart not enabled
-            break;
-        case 1: // every timestep
-            return true;
-        case 2: // daily
-            if (self->state.startDate.h == self->state.currentDate.h){
-                return true;
-            }
-            break;
-        case 3: // weekly not supported
-            break;
-        case 4: // monthly
-            if (self->state.startDate.d == self->state.currentDate.d &&
-                self->state.startDate.h == self->state.currentDate.h){
-                return true;
-            }    
-            break;   
-        case 5: // yearly
-            if (self->state.startDate.m == self->state.currentDate.m &&
-                self->state.startDate.d == self->state.currentDate.d &&
-                self->state.startDate.h == self->state.currentDate.h){
-                return true;
-            }
-            break;
-    }
-    return false;
+  switch(self->state.restartFrequency){
+    case 0: // restart not enabled
+      break;
+    case 1: // every timestep
+      return true;
+    case 2: // daily
+      if (self->state.startDate.h == self->state.currentDate.h){
+          return true;
+      }
+      break;
+    case 3: // weekly not supported
+      break;
+    case 4: // monthly
+      if (self->state.startDate.d == self->state.currentDate.d &&
+          self->state.startDate.h == self->state.currentDate.h){
+        return true;
+      }    
+      break;   
+    case 5: // yearly
+      if (self->state.startDate.m == self->state.currentDate.m &&
+          self->state.startDate.d == self->state.currentDate.d &&
+          self->state.startDate.h == self->state.currentDate.h){
+        return true;
+      }
+      break;
+  }
+  return false;
 }
 
-
-}
\ No newline at end of file
diff --git a/build/source/hru_actor/hru_init.f90 b/build/source/hru_actor/hru_init.f90
index e1e99fee294d70178954a414b547a4a2b6f061bb..d0be85341077a36e8f54e750212cb7551cf0079a 100755
--- a/build/source/hru_actor/hru_init.f90
+++ b/build/source/hru_actor/hru_init.f90
@@ -250,6 +250,7 @@ subroutine setupHRUParam(indxGRU,                 & ! ID of hru
   ! ---------------------------------------------------------------------------------------
   USE nrtype                                                  ! variable types, etc.
   USE output_structure_module,only:summa_struct
+  USE summa_init_struc,only:init_struc
   ! subroutines and functions
   use time_utils_module,only:elapsedSec                       ! calculate the elapsed time
   USE mDecisions_module,only:mDecisions                       ! module to read model decisions
@@ -302,41 +303,29 @@ subroutine setupHRUParam(indxGRU,                 & ! ID of hru
   ! ffile_info and mDecisions moved to their own seperate subroutine call
 
   hru_data%oldTime_hru%var(:) = hru_data%startTime_hru%var(:)
-
-  ! Copy the attrStruct
-  hru_data%attrStruct%var(:) = summa_struct(1)%attrStruct%gru(indxGRU)%hru(indxHRU)%var(:)
-  ! Copy the typeStruct
-  hru_data%typeStruct%var(:) = summa_struct(1)%typeStruct%gru(indxGRU)%hru(indxHRU)%var(:)
-  ! Copy the idStruct
-  hru_data%idStruct%var(:) = summa_struct(1)%idStruct%gru(indxGRU)%hru(indxHRU)%var(:)
-
-  ! Copy the mparStruct
-  hru_data%mparStruct%var(:) = summa_struct(1)%mparStruct%gru(indxGRU)%hru(indxHRU)%var(:)
-  ! Copy the bparStruct
-  hru_data%bparStruct%var(:) = summa_struct(1)%bparStruct%gru(indxGRU)%var(:)
-  ! Copy the dparStruct
-  hru_data%dparStruct%var(:) = summa_struct(1)%dparStruct%gru(indxGRU)%hru(indxHRU)%var(:)
-  ! Copy the bvarStruct
-  do ivar=1, size(summa_struct(1)%bvarStruct_init%gru(indxGRU)%var(:))
-    hru_data%bvarStruct%var(ivar)%dat(:) = summa_struct(1)%bvarStruct_init%gru(indxGRU)%var(ivar)%dat(:)
+  hru_data%attrStruct%var(:) = init_struc%attrStruct%gru(indxGRU)%hru(indxHRU)%var(:)
+  hru_data%typeStruct%var(:) = init_struc%typeStruct%gru(indxGRU)%hru(indxHRU)%var(:)
+  hru_data%idStruct%var(:) = init_struc%idStruct%gru(indxGRU)%hru(indxHRU)%var(:)
+  hru_data%mparStruct%var(:) = init_struc%mparStruct%gru(indxGRU)%hru(indxHRU)%var(:)
+  hru_data%bparStruct%var(:) = init_struc%bparStruct%gru(indxGRU)%var(:)
+  hru_data%dparStruct%var(:) = init_struc%dparStruct%gru(indxGRU)%hru(indxHRU)%var(:)
+  do ivar=1, size(init_struc%bvarStruct%gru(indxGRU)%var(:))
+    hru_data%bvarStruct%var(ivar)%dat(:) = init_struc%bvarStruct%gru(indxGRU)%var(ivar)%dat(:)
   enddo
-  ! Copy the lookup Struct if its allocated
 #ifdef V4_ACTIVE
-  if (allocated(summa_struct(1)%lookupStruct%gru(indxGRU)%hru(indxHRU)%z)) then
-    do i_z=1, size(summa_struct(1)%lookupStruct%gru(indxGRU)%hru(indxHRU)%z(:))
-      do iVar=1, size(summa_struct(1)%lookupStruct%gru(indxGRU)%hru(indxHRU)%z(i_z)%var(:))
-        hru_data%lookupStruct%z(i_z)%var(ivar)%lookup(:) = summa_struct(1)%lookupStruct%gru(indxGRU)%hru(indxHRU)%z(i_z)%var(iVar)%lookup(:)
+  if (allocated(init_struc%lookupStruct%gru(indxGRU)%hru(indxHRU)%z)) then
+    do i_z=1, size(init_struc%lookupStruct%gru(indxGRU)%hru(indxHRU)%z(:))
+      do iVar=1, size(init_struc%lookupStruct%gru(indxGRU)%hru(indxHRU)%z(i_z)%var(:))
+        hru_data%lookupStruct%z(i_z)%var(ivar)%lookup(:) = init_struc%lookupStruct%gru(indxGRU)%hru(indxHRU)%z(i_z)%var(iVar)%lookup(:)
       end do
     end do
   endif
 #endif
-  ! Copy the progStruct_init
-  do ivar=1, size(summa_struct(1)%progStruct_init%gru(indxGRU)%hru(indxHRU)%var(:))
-    hru_data%progStruct%var(ivar)%dat(:) = summa_struct(1)%progStruct_init%gru(indxGRU)%hru(indxHRU)%var(ivar)%dat(:)
+  do ivar=1, size(init_struc%progStruct%gru(indxGRU)%hru(indxHRU)%var(:))
+    hru_data%progStruct%var(ivar)%dat(:) = init_struc%progStruct%gru(indxGRU)%hru(indxHRU)%var(ivar)%dat(:)
   enddo
-  ! copy the indexStruct_init
-  do ivar=1, size(summa_struct(1)%indxStruct_init%gru(indxGRU)%hru(indxHRU)%var(:))
-    hru_data%indxStruct%var(ivar)%dat(:) = summa_struct(1)%indxStruct_init%gru(indxGRU)%hru(indxHRU)%var(ivar)%dat(:)
+  do ivar=1, size(init_struc%indxStruct%gru(indxGRU)%hru(indxHRU)%var(:))
+    hru_data%indxStruct%var(ivar)%dat(:) = init_struc%indxStruct%gru(indxGRU)%hru(indxHRU)%var(ivar)%dat(:)
   enddo
 end subroutine setupHRUParam
 
diff --git a/build/source/hru_actor/hru_read.f90 b/build/source/hru_actor/hru_read.f90
index 5ebd87658be6d34a715531976b355fcd45571bac..98b03a2b5f9167d00fadb5a704ab4c82e8ef3228 100644
--- a/build/source/hru_actor/hru_read.f90
+++ b/build/source/hru_actor/hru_read.f90
@@ -25,7 +25,7 @@ contains
 
 ! set the refTimeString and extract the time to set the tmZonOffsetFracDay
 subroutine setTimeZoneOffset(iFile, handle_hru_data, err) bind(C, name="setTimeZoneOffset")
-  USE access_forcing_module,only:forcingDataStruct         ! forcing structure
+  USE forcing_file_info,only:forcingDataStruct         ! forcing structure
   USE time_utils_module,only:extractTime        ! extract time info from units string
   USE time_utils_module,only:fracDay            ! compute fractional day
   USE summafilemanager,only:NC_TIME_ZONE
@@ -73,8 +73,8 @@ subroutine HRU_readForcing(indxGRU, iStep, iRead, iFile, handle_hru_data, err) b
   USE globalData,only:dJulianStart              ! julian day of start time of simulation
   USE globalData,only:refJulDay_data            ! reference time for data files (fractional julian days)
   USE globalData,only:integerMissing            ! integer missing value
-  USE access_forcing_module,only:vecTime
-  USE access_forcing_module,only:forcingDataStruct
+  USE forcing_file_info,only:vecTime
+  USE forcing_file_info,only:forcingDataStruct
   USE globalData,only:time_meta,forc_meta
   USE var_lookup,only:iLookTIME,iLookFORCE
   USE data_types,only:var_i,var_d
@@ -235,8 +235,8 @@ end subroutine HRU_readForcing
 
  ! Find the first timestep within the forcing file
 subroutine getFirstTimestep(iFile, iRead, err)
-  USE access_forcing_module,only:forcingDataStruct         ! forcing structure
-  USE access_forcing_module,only:vecTime                   ! time structure for forcing 
+  USE forcing_file_info,only:forcingDataStruct  ! forcing structure
+  USE forcing_file_info,only:vecTime            ! time structure for forcing 
   USE globalData,only:dJulianStart              ! julian day of start time of simulation
   USE globalData,only:data_step                 ! length of the data step (s)
   USE globalData,only:refJulDay_data            ! reference time for data files (fractional julian days)
diff --git a/build/source/hru_actor/hru_utils.cpp b/build/source/hru_actor/hru_utils.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..87535b73fe70e60e1674ee748fac1c2a3eafea91
--- /dev/null
+++ b/build/source/hru_actor/hru_utils.cpp
@@ -0,0 +1,133 @@
+#include "hru_actor.hpp"
+
+using namespace caf;
+
+
+/*********************************************
+ * HRU Actor Serialization Functions
+ *********************************************/
+void serializeHru(stateful_actor<hru_state>* self, hru& serialized_state) {
+  // std::vector<std::vector<std::vector<double>>> lookup_struct = 
+      // get_lookup_struct(self->state.hru_data);
+  serialized_state.indx_hru = self->state.indxHRU;
+  serialized_state.indx_gru = self->state.indxGRU;
+  serialized_state.ref_gru = self->state.ref_gru;
+  serialized_state.timestep = self->state.timestep;
+  serialized_state.forcing_step = self->state.forcingStep;
+  serialized_state.num_steps = self->state.num_steps;
+  serialized_state.iFile = self->state.iFile;
+  serialized_state.dt_init_factor = self->state.dt_init_factor;
+  serialized_state.output_structure_step_index = 
+      self->state.output_structure_step_index; 
+  serialized_state.dt_init = self->state.dt_init;
+  serialized_state.upArea = self->state.upArea;
+  serialized_state.rtol = self->state.rtol;
+  serialized_state.atol = self->state.atol;
+
+  // Statistic Structures
+  serialized_state.forc_stat = get_var_dlength_by_indx(self->state.hru_data, 1); 
+  serialized_state.prog_stat = get_var_dlength_by_indx(self->state.hru_data, 2); 
+  serialized_state.diag_stat = get_var_dlength_by_indx(self->state.hru_data, 3); 
+  serialized_state.flux_stat = get_var_dlength_by_indx(self->state.hru_data, 4); 
+  serialized_state.indx_stat = get_var_dlength_by_indx(self->state.hru_data, 5); 
+  serialized_state.bvar_stat = get_var_dlength_by_indx(self->state.hru_data, 6);
+  // Primary Data Structures (scalars)
+  serialized_state.time_struct = get_var_i_by_indx(self->state.hru_data, 1);
+  serialized_state.forc_struct = get_var_d_by_indx(self->state.hru_data, 1);
+  serialized_state.attr_struct = get_var_d_by_indx(self->state.hru_data, 2);
+  serialized_state.type_struct = get_var_i_by_indx(self->state.hru_data, 2);
+  serialized_state.id_struct = get_var_i8_by_indx(self->state.hru_data, 1);
+  // Primary Data Structures (variable length vectors)
+  serialized_state.indx_struct = 
+      get_var_ilength_by_indx(self->state.hru_data, 1);
+  serialized_state.mpar_struct = 
+      get_var_dlength_by_indx(self->state.hru_data, 7);      
+  serialized_state.prog_struct = 
+      get_var_dlength_by_indx(self->state.hru_data, 8);
+  serialized_state.diag_struct = 
+      get_var_dlength_by_indx(self->state.hru_data, 9);
+  serialized_state.flux_struct = 
+      get_var_dlength_by_indx(self->state.hru_data, 10);
+  // Basin-average structures
+  serialized_state.bpar_struct = get_var_d_by_indx(self->state.hru_data, 3);
+  serialized_state.bvar_struct = 
+      get_var_dlength_by_indx(self->state.hru_data, 11);
+  serialized_state.dpar_struct = get_var_d_by_indx(self->state.hru_data, 4);
+
+  // Local HRU data structures
+  serialized_state.start_time = get_var_i_by_indx(self->state.hru_data, 3);
+  serialized_state.end_time = get_var_i_by_indx(self->state.hru_data, 4);
+  serialized_state.ref_time = get_var_i_by_indx(self->state.hru_data, 5);
+  serialized_state.old_time = get_var_i_by_indx(self->state.hru_data, 6);
+
+  // Statistic flags
+  serialized_state.stat_counter = get_var_i_by_indx(self->state.hru_data, 7);
+  serialized_state.output_timestep = get_var_i_by_indx(self->state.hru_data, 8);
+  serialized_state.reset_stats = get_flagVec_by_indx(self->state.hru_data, 1);
+  serialized_state.finalize_stats = get_flagVec_by_indx(self->state.hru_data, 2);
+
+  get_scalar_data(self->state.hru_data, serialized_state.frac_jul_day,
+                  serialized_state.tm_zone_offset_frac_day,
+                  serialized_state.year_length,
+                  serialized_state.compute_veg_flux);
+}
+
+void deserializeHru(stateful_actor<hru_state>* self, hru& new_state) {
+  setFinalizeStatsFalse(&self->state.indxGRU);
+
+  // Delete the old hru_data in Fortran
+  delete_handle_hru_type(self->state.hru_data);
+  self->state.hru_data = new_handle_hru_type();
+
+  self->state.indxHRU = new_state.indx_hru;
+  self->state.indxGRU = new_state.indx_gru;
+  self->state.ref_gru = new_state.ref_gru;
+  self->state.timestep = new_state.timestep;
+  self->state.forcingStep = new_state.forcing_step;
+  self->state.num_steps = new_state.num_steps;
+  self->state.iFile = new_state.iFile;
+  self->state.dt_init_factor = new_state.dt_init_factor;
+  self->state.output_structure_step_index = 
+      new_state.output_structure_step_index;
+  self->state.dt_init = new_state.dt_init;
+  self->state.upArea = new_state.upArea;
+  self->state.rtol = new_state.rtol;
+  self->state.atol = new_state.atol;
+  // Statistic Structures
+  set_var_dlength_by_indx(self->state.hru_data, new_state.forc_stat, 1);
+  set_var_dlength_by_indx(self->state.hru_data, new_state.prog_stat, 2);
+  set_var_dlength_by_indx(self->state.hru_data, new_state.diag_stat, 3);
+  set_var_dlength_by_indx(self->state.hru_data, new_state.flux_stat, 4);
+  set_var_dlength_by_indx(self->state.hru_data, new_state.indx_stat, 5);
+  set_var_dlength_by_indx(self->state.hru_data, new_state.bvar_stat, 6);
+ // Primary Data Structures (scalars)
+  set_var_i_by_indx(self->state.hru_data, new_state.time_struct, 1);
+  set_var_d_by_indx(self->state.hru_data, new_state.forc_struct, 1);
+  set_var_d_by_indx(self->state.hru_data, new_state.attr_struct, 2);
+  set_var_i_by_indx(self->state.hru_data, new_state.type_struct, 2);
+  set_var_i8_by_indx(self->state.hru_data, new_state.id_struct, 1);
+  // Primary Data Structures (variable length vectors)
+  set_var_ilength_by_indx(self->state.hru_data, new_state.indx_struct, 1);
+  set_var_dlength_by_indx(self->state.hru_data, new_state.mpar_struct, 7);
+  set_var_dlength_by_indx(self->state.hru_data, new_state.prog_struct, 8);
+  set_var_dlength_by_indx(self->state.hru_data, new_state.diag_struct, 9);
+  set_var_dlength_by_indx(self->state.hru_data, new_state.flux_struct, 10);
+  // Basin-average structures
+  set_var_d_by_indx(self->state.hru_data, new_state.bpar_struct, 3);
+  set_var_dlength_by_indx(self->state.hru_data, new_state.bvar_struct, 11);
+  set_var_d_by_indx(self->state.hru_data, new_state.dpar_struct, 4);
+  // Local HRU data structures
+  set_var_i_by_indx(self->state.hru_data, new_state.start_time, 3);
+  set_var_i_by_indx(self->state.hru_data, new_state.end_time, 4);
+  set_var_i_by_indx(self->state.hru_data, new_state.ref_time, 5);
+  set_var_i_by_indx(self->state.hru_data, new_state.old_time, 6);
+    // statistic flags
+  set_var_i_by_indx(self->state.hru_data, new_state.stat_counter, 7);
+  set_var_i_by_indx(self->state.hru_data, new_state.output_timestep, 8);
+  set_flagVec_by_indx(self->state.hru_data, new_state.reset_stats, 1);
+  set_flagVec_by_indx(self->state.hru_data, new_state.finalize_stats, 2);
+  // scalar data
+  set_scalar_data(self->state.hru_data, new_state.frac_jul_day,
+                  new_state.tm_zone_offset_frac_day, new_state.year_length,
+                  new_state.compute_veg_flux);
+}
\ No newline at end of file
diff --git a/build/source/job_actor/GRU.cpp b/build/source/job_actor/GRU.cpp
index 3f81ab2d39ca9e0d1b8f3711fd1c4aef7485b82e..ecef34302240f17a0110f33f2ecf59a1d6c36986 100644
--- a/build/source/job_actor/GRU.cpp
+++ b/build/source/job_actor/GRU.cpp
@@ -1,119 +1,15 @@
-#include "caf/all.hpp"
 #include "GRU.hpp"
-#include <iostream>
-#include <fstream>
 
-
-int is_success(const gru_state& state) {
-
-  return(state == gru_state::succeeded) ? 1 : 0;
-}
-
-
-GRU::GRU(int global_gru_index, int local_gru_index, caf::actor gru_actor, 
+GRU::GRU(int index_netcdf, int index_job, caf::actor actor_ref, 
          int dt_init_factor, double rel_tol, double abs_tol, int max_attempt) {
-  this->global_gru_index = global_gru_index;
-  this->local_gru_index = local_gru_index;
-  this->gru_actor = gru_actor;
-  this->dt_init_factor = dt_init_factor;
-  this->rel_tol = rel_tol;
-  this->abs_tol = abs_tol;
-  this->attempts_left = max_attempt;
-  this->state = gru_state::running;
-}
-GRU::~GRU() {};
-
-// Getters
-int GRU::getGlobalGRUIndex() {
-  return this->global_gru_index;
-}
-
-int GRU::getLocalGRUIndex() {
-  return this->local_gru_index;
-}
-
-caf::actor GRU::getGRUActor() {
-  return this->gru_actor;
-}
-
-double GRU::getRunTime() {
-  return this->run_time;
-}
-
-double GRU::getInitDuration() {
-  return this->init_duration;
-}
-
-double GRU::getForcingDuration() {
-  return this->forcing_duration;
-}
-
-double GRU::getRunPhysicsDuration() {
-  return this->run_physics_duration;
-}
-
-double GRU::getWriteOutputDuration() {
-  return this->write_output_duration;
-}
-
-double GRU::getRelTol() {
-  return this->rel_tol;
+  index_netcdf_ = index_netcdf;
+  index_job_ = index_job;
+  actor_ref_ = actor_ref;
+  dt_init_factor_ = dt_init_factor;
+  rel_tol_ = rel_tol;
+  abs_tol_ = abs_tol;
+  attempts_left_ = max_attempt;
+  state_ = gru_state::running;
 }
 
-double GRU::getAbsTol() {
-  return this->abs_tol;
-}
-
-double GRU::getAttemptsLeft() {
-  return this->attempts_left;
-}
-
-gru_state GRU::getStatus() {
-  return this->state;
-}
-
-bool GRU::isFailed() {
-  return this->state == gru_state::failed;
-}
-
-// Setters
-void GRU::setRunTime(double run_time) {
-  this->run_time = run_time;
-}
-void GRU::setInitDuration(double init_duration) {
-  this->init_duration = init_duration;
-}
-void GRU::setForcingDuration(double forcing_duration) {
-  this->forcing_duration = forcing_duration;
-}
-void GRU::setRunPhysicsDuration(double run_physics_duration) {
-  this->run_physics_duration = run_physics_duration;
-}
-void GRU::setWriteOutputDuration(double write_output_duration) {
-  this->write_output_duration = write_output_duration;
-}
-
-void GRU::setRelTol(double rel_tol) {
-  this->rel_tol = rel_tol;
-}
-void GRU::setAbsTol(double abs_tol) {
-  this->abs_tol = abs_tol;
-}
-
-void GRU::setSuccess() {
-  this->state = gru_state::succeeded;
-}
-void GRU::setFailed() {
-  this->state = gru_state::failed;
-}
-void GRU::setRunning() {
-  this->state = gru_state::running;
-}
-
-void GRU::decrementAttemptsLeft() {
-  this->attempts_left--;
-}
-
-void GRU::setGRUActor(caf::actor gru_actor) {
-  this->gru_actor = gru_actor;
-}
\ No newline at end of file
+GRU::~GRU() {};
diff --git a/build/source/job_actor/async_mode.cpp b/build/source/job_actor/async_mode.cpp
index e16ddb1b52df4786e7998ba32e57a032546b6f3c..20eacb1e93accdafdb7992880af8e1da2a5ecdc8 100644
--- a/build/source/job_actor/async_mode.cpp
+++ b/build/source/job_actor/async_mode.cpp
@@ -1,29 +1,69 @@
 #include "job_actor.hpp"
-namespace caf {
+
+using namespace caf;
 
 behavior async_mode(stateful_actor<job_state>* self) {
   aout(self) << "Async Mode Started\n";
 
   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);
-      for(auto& gru : self->state.gru_container.gru_list) {
-        self->send(gru->getGRUActor(), init_hru_v);
-        self->send(gru->getGRUActor(), update_hru_async_v);
-      }
     },
 
-    [=](done_hru, int local_gru_index) {
-      aout(self) << "HRU Done: " << local_gru_index << "\n";
-      handleFinishedGRU(self, local_gru_index);
+    [=](done_hru, int gru_job_index) {
+      handleFinishedGRU(self, gru_job_index);
+    },
+
+    [=] (restart_failures) {
+      aout(self) << "Async Mode: Restarting GRUs that Failed\n";
+      if (self->state.hru_actor_settings.rel_tol > 0 && 
+          self->state.hru_actor_settings.abs_tol > 0) {
+        self->state.hru_actor_settings.rel_tol /= 10;
+        self->state.hru_actor_settings.abs_tol /= 10;
+      } else {
+        self->state.hru_actor_settings.dt_init_factor *= 2;
+      }
+
+      // notify file_access_actor
+      self->send(self->state.file_access_actor, restart_failures_v); 
+
+      while(self->state.gru_struc->getNumGRUFailed() > 0) {
+        int job_index = self->state.gru_struc->getFailedIndex();
+        aout(self) << "Async Mode: Restarting GRU: " << job_index << "\n";
+        int netcdf_index = job_index + self->state.gru_struc->getStartGru() - 1;
+        auto gru =  self->spawn(hru_actor, netcdf_index, job_index, 
+                                self->state.hru_actor_settings, 
+                                self->state.file_access_actor, self);
+        self->send(gru, init_hru_v);
+        self->send(gru, update_hru_async_v);
+        self->state.gru_struc->decrementNumGRUFailed();
+        std::unique_ptr<GRU> gru_obj = std::make_unique<GRU>(
+            netcdf_index, job_index, gru, self->state.dt_init_start_factor, 
+            self->state.hru_actor_settings.rel_tol, 
+            self->state.hru_actor_settings.abs_tol, 
+            self->state.max_run_attempts);
+        self->state.gru_struc->addGRU(std::move(gru_obj));
+      }
+      self->state.gru_struc->decrementRetryAttempts();
+
     },
 
     [=](finalize) { finalizeJob(self); },
+
+    /**Error Handling Functions*/
+    [=](err_atom, int err_code, int gru_job_index) {
+      if (gru_job_index == 0) {
+        aout(self) << "Async Mode: File_Access_Actor Error: " 
+                   << err_code << "\n";
+        self->send(self, finalize_v);
+        return;
+      } 
+      aout(self) << "Async Mode: GRU Error: " << err_code << "\n";
+      handleGRUError(self, err_code, gru_job_index);
+    }
     
   };
 }
-
-} // End of Namespace
\ No newline at end of file
diff --git a/build/source/job_actor/data_assimilation_mode.cpp b/build/source/job_actor/data_assimilation_mode.cpp
index 3e12870d1bc34d56f97daecd742cae91b9c4b581..39419031dee69e066d0536f16780853af576d9e3 100644
--- a/build/source/job_actor/data_assimilation_mode.cpp
+++ b/build/source/job_actor/data_assimilation_mode.cpp
@@ -1,11 +1,12 @@
 #include "job_actor.hpp"
 
-namespace caf {
+using namespace caf;
+
 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 ? 
@@ -21,7 +22,7 @@ behavior data_assimilation_mode(stateful_actor<job_state>* self) {
       self->state.stepsInCurrentFFile = num_steps_in_iFile;
       self->state.forcingStep = 1;
       for(auto gru : self->state.gru_container.gru_list) {
-        self->send(gru->getGRUActor(), update_timeZoneOffset_v, 
+        self->send(gru->getActorRef(), update_timeZoneOffset_v, 
             self->state.iFile);
       }
 
@@ -30,7 +31,7 @@ behavior data_assimilation_mode(stateful_actor<job_state>* self) {
 
     [=](update_hru){
       for(auto gru : self->state.gru_container.gru_list) {
-        self->send(gru->getGRUActor(), update_hru_v, self->state.timestep, 
+        self->send(gru->getActorRef(), update_hru_v, self->state.timestep, 
             self->state.forcingStep);
       }      
     },
@@ -52,7 +53,7 @@ behavior data_assimilation_mode(stateful_actor<job_state>* self) {
             if (err != 0) {
               aout(self) << "Job_Actor: Error Writing Output\n";
               for (auto GRU : self->state.gru_container.gru_list)
-                self->send(GRU->getGRUActor(), exit_msg_v);
+                self->send(GRU->getActorRef(), exit_msg_v);
               
               self->send_exit(self->state.file_access_actor, 
                               exit_reason::user_shutdown);
@@ -67,7 +68,7 @@ behavior data_assimilation_mode(stateful_actor<job_state>* self) {
         if (self->state.timestep > self->state.num_steps) {
           aout(self) << "Job_Actor: Done Job\n";
           for (auto GRU : self->state.gru_container.gru_list) {
-            self->send_exit(GRU->getGRUActor(), exit_reason::user_shutdown);
+            self->send_exit(GRU->getActorRef(), exit_reason::user_shutdown);
             GRU->setSuccess();
           }
           self->send(self, finalize_v);
@@ -98,5 +99,4 @@ behavior data_assimilation_mode(stateful_actor<job_state>* self) {
   
 
   };
-}
-} // End of Namespace caf
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/build/source/job_actor/distributed_job_actor.cpp b/build/source/job_actor/distributed_job_actor.cpp
index c4b0088a218ee1e1cb4c3f3935c9cd06d02b4315..8309eb66dfca02c280f34c7e00e766a76d34932e 100644
--- a/build/source/job_actor/distributed_job_actor.cpp
+++ b/build/source/job_actor/distributed_job_actor.cpp
@@ -3,7 +3,9 @@
 #include "node_actor.hpp"
 #include <fstream>
 #include <iostream>
-namespace caf {
+
+
+using namespace caf;
 
 behavior distributed_job_actor(stateful_actor<distributed_job_state>* self,
     int start_gru_global, int num_gru_global, 
@@ -28,7 +30,7 @@ behavior distributed_job_actor(stateful_actor<distributed_job_state>* self,
   self->state.job_actor_settings = job_actor_settings;
   self->state.hru_actor_settings = hru_actor_settings;
 
-  self->state.file_gru = getNumGRUInFile(job_actor_settings.file_manager_path);
+  // self->state.file_gru = getNumGRUInFile(job_actor_settings.file_manager_path);
   if (self->state.file_gru  == -1) 
     aout(self) << "***WARNING***: UNABLE TO VERIFY NUMBER OF GRUS" 
                << " - Job Actor MAY CRASH\n";
@@ -413,5 +415,3 @@ behavior distributed_job_actor(stateful_actor<distributed_job_state>* self,
 }
 
 
-
-} // namespace caf
\ No newline at end of file
diff --git a/build/source/job_actor/gru_struc.cpp b/build/source/job_actor/gru_struc.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78ef42eddf4e2a1ccf52627db6b7f55ffc15e335
--- /dev/null
+++ b/build/source/job_actor/gru_struc.cpp
@@ -0,0 +1,37 @@
+#include "gru_struc.hpp"
+#include <iostream>
+#include <memory>
+
+GruStruc::GruStruc(int start_gru, int num_gru, int num_retry_attempts) {
+  start_gru_ = start_gru;
+  num_gru_ = num_gru;
+  num_retry_attempts_left_ = num_retry_attempts;
+  gru_info_.resize(num_gru);
+}
+
+int GruStruc::ReadDimension() {
+  int err = 0; int num_hru, file_gru, file_hru;
+  std::unique_ptr<char[]> err_msg(new char[256]);
+  read_dimension_fortran(start_gru_, num_gru_, num_hru, file_gru, file_hru,
+                         err, &err_msg);
+  if (err != 0) { 
+    std::cout << "ERROR: GruStruc - ReadDimension\n";
+  }
+  num_hru_ = num_hru;
+  file_gru_ = file_gru;
+  file_hru_ = file_hru;
+  return err;
+}
+
+int GruStruc::ReadIcondNlayers() {
+  int err = 0;
+  std::unique_ptr<char[]> err_msg(new char[256]);
+  read_icond_nlayers_fortran(num_gru_, err, &err_msg);
+  if (err != 0) { 
+    std::cout << "ERROR: GruStruc - ReadIcondNlayers\n";
+  }
+  return 0;
+}
+
+
+
diff --git a/build/source/job_actor/gru_struc.f90 b/build/source/job_actor/gru_struc.f90
new file mode 100644
index 0000000000000000000000000000000000000000..884373935390b2af3c0106f0b20e06c32779c139
--- /dev/null
+++ b/build/source/job_actor/gru_struc.f90
@@ -0,0 +1,101 @@
+module gru_struc_module
+  USE, intrinsic :: iso_c_binding
+  USE globalData,only:integerMissing
+  implicit none
+
+  public::read_dimension_fortran
+  public::read_icond_nlayers_fortran
+  public::deallocate_gru_struc_fortran
+  contains
+
+subroutine read_dimension_fortran(start_gru, num_gru, num_hru, file_gru, &
+                                  file_hru, err, message_r) &
+    bind(C, name="read_dimension_fortran")
+  USE globalData,only:startGRU                               ! index of the GRU for a single GRU run
+  USE globalData,only:checkHRU                               ! index of the HRU for a single HRU run
+  USE globalData,only:iRunMode                               ! define the current running mode    
+  USE globalData,only:iRunModeFull, iRunModeGRU, iRunModeHRU ! define the running modes
+  
+  USE summaFileManager,only:SETTINGS_PATH, LOCAL_ATTRIBUTES
+  USE read_attrb_module,only:read_dimension
+  
+  USE C_interface_module,only:f_c_string_ptr
+  implicit none
+  ! Dummy Variables
+  integer(c_int), intent(in)      :: start_gru
+  integer(c_int), intent(inout)   :: num_gru
+  integer(c_int), intent(inout)   :: num_hru
+  integer(c_int), intent(out)     :: file_gru
+  integer(c_int), intent(out)     :: file_hru
+  integer(c_int), intent(out)     :: err
+  type(c_ptr),    intent(out)     :: message_r
+  ! Local Variables
+  character(len=256)              :: attrFile           ! attributes file name
+  character(len=256)              :: message
+  
+  err = 0
+  message = ""
+  call f_c_string_ptr(trim(message), message_r)
+
+  ! Set variables that were previosuly set by getCommandArguments()
+  startGRU=start_gru
+  iRunMode=iRunModeGRU
+  checkHRU=integerMissing
+
+  attrFile = trim(SETTINGS_PATH)//trim(LOCAL_ATTRIBUTES)
+  if (iRunMode == iRunModeGRU) then
+    call read_dimension(trim(attrFile),file_gru,file_hru,num_gru,num_hru,err,&
+                        message,startGRU=start_gru)
+  else
+    err = 20
+    message = "Error: iRunMode is not set to iRunModeGRU - other modes not supported yet."
+  end if
+  if (err /= 0) then; call f_c_string_ptr(trim(message), message_r); end if
+end subroutine read_dimension_fortran
+
+subroutine read_icond_nlayers_fortran(num_gru, err, message_r)& 
+    bind(C, name="read_icond_nlayers_fortran")
+  USE globalData,only:indx_meta                     ! metadata structures
+  
+  USE summaFileManager,only:SETTINGS_PATH,STATE_PATH,MODEL_INITCOND                    
+  USE read_icond_module,only:read_icond_nlayers               ! module to read initial condition dimensions
+  USE C_interface_module,only:f_c_string_ptr
+  implicit none
+  ! Dummy Variables
+  integer(c_int), intent(in)      :: num_gru
+  integer(c_int), intent(out)     :: err
+  type(c_ptr),    intent(out)     :: message_r
+  ! Local Variables
+  character(len=256)              :: restartFile        ! restart file name
+  character(len=256)              :: message
+
+  err = 0
+  message = ""
+  call f_c_string_ptr(trim(message), message_r)
+
+  ! *****************************************************************************
+  ! *** read the number of snow and soil layers
+  ! *****************************************************************************
+  ! set restart filename and read the number of snow and soil layers from the initial conditions (restart) file
+  if(STATE_PATH == '') then
+    restartFile = trim(SETTINGS_PATH)//trim(MODEL_INITCOND)
+  else
+    restartFile = trim(STATE_PATH)//trim(MODEL_INITCOND)
+  endif
+  call read_icond_nlayers(trim(restartFile),num_gru,indx_meta,err,message)
+  if(err/=0)then; call f_c_string_ptr(trim(message), message_r); endif
+
+end subroutine read_icond_nlayers_fortran
+
+subroutine deallocate_gru_struc_fortran() bind(C, name="deallocate_gru_struc_fortran")
+    USE globalData,only:gru_struc           ! gru->hru mapping structure
+    USE globalData,only:index_map
+    implicit none
+    if(allocated(gru_struc))then; deallocate(gru_struc);endif
+    if(allocated(index_map))then; deallocate(index_map);endif
+end subroutine
+
+
+
+
+end module gru_struc_module
\ No newline at end of file
diff --git a/build/source/job_actor/job_actor.cpp b/build/source/job_actor/job_actor.cpp
index 19f70cf8d21e172712cda807f71075cb03d1df5e..14cd9843969425a4235724edfc03e82cdcb8bc2d 100644
--- a/build/source/job_actor/job_actor.cpp
+++ b/build/source/job_actor/job_actor.cpp
@@ -2,15 +2,13 @@
 
 using json = nlohmann::json;
 using chrono_time = std::chrono::time_point<std::chrono::system_clock>;
-
-namespace caf {
+using namespace caf;
 
 // First Actor that is spawned that is not the Coordinator Actor.
-behavior job_actor(stateful_actor<job_state>* self, 
-    int start_gru, int num_gru, 
-    File_Access_Actor_Settings file_access_actor_settings, 
-    Job_Actor_Settings job_actor_settings, 
-    HRU_Actor_Settings hru_actor_settings, caf::actor parent) {
+behavior job_actor(stateful_actor<job_state>* self, int start_gru, int num_gru, 
+                   File_Access_Actor_Settings file_access_actor_settings, 
+                   Job_Actor_Settings job_actor_settings, 
+                   HRU_Actor_Settings hru_actor_settings, caf::actor parent) {
     
   self->set_down_handler([=](const down_msg& dm) {
       aout(self) << "\n\n ********** DOWN HANDLER ********** \n"
@@ -18,7 +16,7 @@ behavior job_actor(stateful_actor<job_state>* self,
                  << "Reason: " << to_string(dm.reason) << "\n";
   });
 
-  self->set_exit_handler([=](const exit_msg& em) {
+  self->set_exit_handler([=](const caf::exit_msg& em) {
       aout(self) << "\n\n ********** EXIT HANDLER ********** \n"
                  << "Exit Reason: " << to_string(em.reason) << "\n";
   });
@@ -27,6 +25,8 @@ behavior job_actor(stateful_actor<job_state>* self,
   self->state.job_timing = TimingInfo(); 
   self->state.job_timing.addTimePoint("total_duration");
   self->state.job_timing.updateStartPoint("total_duration");
+  self->state.job_timing.addTimePoint("init_duration");
+  self->state.job_timing.updateStartPoint("init_duration");
   // Set Job Variables
   self->state.start_gru = start_gru;
   self->state.num_gru = num_gru;
@@ -42,160 +42,89 @@ behavior job_actor(stateful_actor<job_state>* self,
   char host[HOST_NAME_MAX];
   gethostname(host, HOST_NAME_MAX);
   self->state.hostname = host;
-  
-  /* Calls: summa_SetTimesDirsAndFiles(), summa_defineGlobalData(),
-         read_icond_nlayers(), Allocates time structures */
-  self->state.job_timing.addTimePoint("init_duration");
-  int file_gru = 0;
-  int err = 0;
-  job_init_fortran(self->state.job_actor_settings.file_manager_path.c_str(),
-      &self->state.start_gru, &self->state.num_gru, &self->state.num_hru, 
-      &file_gru, &err);
-  if (err != 0) { 
-    aout(self) << "\nERROR: Job_Actor - job_init_fortran\n"; 
+
+  auto& gru_struc = self->state.gru_struc;
+  gru_struc = std::make_unique<GruStruc>(self->state.start_gru, 
+                                         self->state.num_gru,
+                                         job_actor_settings.max_run_attempts);
+  if (gru_struc->ReadDimension()) {
+    aout(self) << "ERROR: Job_Actor - ReadDimension\n";
+    return {};
+  }
+  if (gru_struc->ReadIcondNlayers()) {
+    aout(self) << "ERROR: Job_Actor - ReadIcondNlayers\n";
     return {};
   }
-
-  self->state.num_gru_info = NumGRUInfo(self->state.start_gru, 
-      self->state.start_gru, self->state.num_gru, self->state.num_gru, 
-      file_gru, false);
-
-  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->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));
+  self->state.summa_init_struc = std::make_unique<SummaInitStruc>();
+  if (self->state.summa_init_struc->allocate(self->state.num_gru) != 0) {
+    aout(self) << "ERROR -- Job_Actor: SummaInitStruc allocation failed\n";
     return {};
-  } else {
-    self->become(async_mode(self));
+  }
+  if (self->state.summa_init_struc->summa_paramSetup() != 0) {
+    aout(self) << "ERROR -- Job_Actor: SummaInitStruc paramSetup failed\n";
     return {};
   }
+  if (self->state.summa_init_struc->summa_readRestart()!= 0) {
+    aout(self) << "ERROR -- Job_Actor: SummaInitStruc readRestart failed\n";
+    return {};
+  }
+  self->state.summa_init_struc->getInitTolerance(self->state.hru_actor_settings);
 
+  self->state.num_gru_info = NumGRUInfo(self->state.start_gru, 
+                                        self->state.start_gru, 
+                                        self->state.num_gru, 
+                                        self->state.num_gru, 
+                                        gru_struc->get_file_gru(), 
+                                        false);
+
+  self->state.file_access_actor = self->spawn(
+      file_access_actor, self->state.num_gru_info, 
+      self->state.file_access_actor_settings, self);
+  self->request(self->state.file_access_actor, caf::infinite, 
+                init_file_access_actor_v, gru_struc->get_file_gru())
+      .await([=](int num_timesteps){
+    
+    if (num_timesteps < 0) {
+      aout(self) << "ERROR: Job_Actor: File Access Actor Not Ready\n"
+                 << "\t VALUE: " << num_timesteps << "\n";
+      self->quit();
+      return;
+    }
 
 
-  return {
-    /*** From file access actor after it spawns ***/
-    // [=](init_file_access_actor, int num_timesteps) {
-    //   self->state.num_steps = num_timesteps;
-    //   aout(self) << "Num Steps: " << self->state.num_steps << "\n";
-      
-    //   // #####################################################
-    //   // # Data Assimilation Mode
-    //   // #####################################################
-    //   if (self->state.job_actor_settings.data_assimilation_mode) {
-    //     aout(self) << "Job_Actor: Data Assimilation Mode\n";
-
-    //     auto& gru_container = self->state.gru_container;
-        
-    //     // Spawn HRUs in batches or individually
-    //     if (self->state.job_actor_settings.batch_size > 1)
-    //       spawnHRUBatches(self);
-    //     else
-    //       spawnHRUActors(self);
-        
-
-    //     aout(self) << "GRUs Initialized\n";
-    //     self->send(self->state.file_access_actor, access_forcing_v, 
-    //                self->state.iFile, self);
-    //   } else {
-    //     // #####################################################
-    //     // # Normal Mode
-    //     // #####################################################
-    //     aout(self) << "Job_Actor: Normal Mode\n";
-    //     spawnHRUActors(self);
-    //   }
-    // },
+    aout(self) << "Job_Actor: File Access Actor Ready\n";  
+    self->state.job_timing.updateEndPoint("init_duration");
+    aout(self) << "Job Actor Initialized \n";
 
-    // #####################################################
-    // # Data Assimilation Mode Start
-    // #####################################################
-    // [=](new_forcing_file, int num_steps_in_iFile, int nextFile) {
-    //   aout(self) << "Job_Actor: New Forcing File\n";
-    //   self->state.iFile = nextFile;
-    //   self->state.stepsInCurrentFFile = num_steps_in_iFile;
-    //   self->state.forcingStep = 1;
-    //   for(auto gru : self->state.gru_container.gru_list) {
-    //     self->send(gru->getGRUActor(), update_timeZoneOffset_v, 
-    //         self->state.iFile);
-    //   }
-
-    //   self->send(self, update_hru_v); // update HRUs
-    // },
+    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);
+  });
+      
 
-    // [=](update_hru){
-    //   // aout(self) << "Job_Actor: Updating HRUs\n";
-    //   for(auto gru : self->state.gru_container.gru_list) {
-    //     self->send(gru->getGRUActor(), update_hru_v, 
-    //                 self->state.timestep, self->state.forcingStep);
-    //   }      
-    // },
+  /**
+   * 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 {
 
     [=](reinit_hru) {
       aout(self) << "Job_Actor: HRU Actor Re-initialized\n";
       self->send(self, update_hru_v);
     },
 
-    // [=](std::vector<actor> hru_actors) {
-    // },
-
-    // #####################################################
-    // # Data Assimilation Mode End
-    // #####################################################
-
-
-
-
-    // #####################################################
-    // # Normal Mode Start
-    // #####################################################
-    // [=](done_hru, int local_gru_index) {
-    //   auto& gru_container = self->state.gru_container;
-    //   using namespace std::chrono;
-      
-    //   chrono_time end_point = high_resolution_clock::now();
-    //   double total_duration = duration_cast<seconds>(end_point - 
-    //       gru_container.gru_start_time).count();
-    //   gru_container.num_gru_done++;
-
-    //   aout(self) << "GRU Finished: " << gru_container.num_gru_done << "/" 
-    //       << gru_container.num_gru_in_run_domain << " -- "
-    //       << "GlobalGRU=" 
-    //       << gru_container.gru_list[local_gru_index-1]->getGlobalGRUIndex()
-    //       << " -- LocalGRU=" << local_gru_index << "\n";
-
-    //   // Update Timing
-    //   gru_container.gru_list[local_gru_index-1]->setRunTime(total_duration);
-    //   gru_container.gru_list[local_gru_index-1]->setInitDuration(-1);
-    //   gru_container.gru_list[local_gru_index-1]->setForcingDuration(-1);
-    //   gru_container.gru_list[local_gru_index-1]->setRunPhysicsDuration(-1);
-    //   gru_container.gru_list[local_gru_index-1]->setWriteOutputDuration(-1);
-
-    //   gru_container.gru_list[local_gru_index-1]->setSuccess();
-
-
-      
-    //   // Check if all GRUs are finished
-    //   if (gru_container.num_gru_done >= gru_container.num_gru_in_run_domain) {
-    //     // Check for failures
-    //     if(self->state.gru_container.num_gru_failed == 0 || 
-    //         self->state.max_run_attempts == 1) {
-    //       self->send(self, finalize_v); 
-    //     } else {
-    //       self->send(self, restart_failures_v);
-    //     }
-    //   }
-
-    // },
-
     [=](restart_failures) {
       aout(self) << "Job_Actor: Restarting GRUs that Failed\n";
 
@@ -209,7 +138,7 @@ behavior job_actor(stateful_actor<job_state>* self,
 
       // Set Sundials tolerance or decrease timestep length
       if (self->state.hru_actor_settings.rel_tol > 0 && 
-        self->state.hru_actor_settings.abs_tol > 0) {
+          self->state.hru_actor_settings.abs_tol > 0) {
         self->state.hru_actor_settings.rel_tol /= 10;
         self->state.hru_actor_settings.abs_tol /= 10;
       } else {
@@ -221,171 +150,43 @@ behavior job_actor(stateful_actor<job_state>* self,
         if(GRU->isFailed()) {
           GRU->setRunning();
           GRU->decrementAttemptsLeft();
-          auto global_gru_index = GRU->getGlobalGRUIndex();
-          auto local_gru_index = GRU->getLocalGRUIndex();
-          auto gru_actor = self->spawn(hru_actor, 
-                                        global_gru_index, 
-                                        local_gru_index, 
-                                        self->state.hru_actor_settings,
-                                        self->state.file_access_actor, 
-                                        self);
-          self->state.gru_container.gru_list[local_gru_index-1]->
-              setGRUActor(gru_actor);
+          auto gru_actor = self->spawn(hru_actor, GRU->getIndexNetcdf(), 
+                                       GRU->getIndexJob(),
+                                       self->state.hru_actor_settings,
+                                       self->state.file_access_actor, self);
+          self->state.gru_container.gru_list[GRU->getIndexJob()-1]->
+              setActorRef(gru_actor);
         }
       }
     },
 
-    // [=](finalize) {            
-    //   std::vector<serializable_netcdf_gru_actor_info> 
-    //       netcdf_gru_info = getGruNetcdfInfo(
-    //         self->state.max_run_attempts,self->state.gru_container.gru_list);
+    // [=](const error& err, caf::actor src) {
+      
+    //   aout(self) << "\n\n ********** ERROR HANDLER \n";
+      
+    //   switch(err.category()) {
         
-            
-    //   self->state.num_gru_failed = std::count_if(netcdf_gru_info.begin(), 
-    //       netcdf_gru_info.end(), [](auto& gru_info) {
-    //     return !gru_info.successful;
-    //   });
-
-    //   self->request(self->state.file_access_actor, infinite, finalize_v).await(
-    //     [=](std::tuple<double, double> read_write_duration) {
-    //       int err = 0;
+    //     case type_id_v<hru_error>:
+    //       aout(self) << "HRU Error: " << to_string(err) << "\n";
+    //       handleGRUError(self, src);
+
+    //       break;
+    //     case type_id_v<file_access_error>:
+    //       if (err == file_access_error::mDecisions_error) {
+    //         aout(self) << "Check mDecisions File For Correctness";
+    //       } else {
+    //         aout(self) << "File Access Error: " << to_string(err) << "No Handling Implemented\n";
+    //       }
     //       for (auto GRU : self->state.gru_container.gru_list) {
-    //         delete GRU;
+    //         self->send_exit(GRU->getGRUActor(), exit_reason::user_shutdown);
     //       }
-    //       self->state.gru_container.gru_list.clear();
-
-    //       self->state.job_timing.updateEndPoint("total_duration");
-
-    //       aout(self) << "\n________________" 
-    //                  << "PRINTING JOB_ACTOR TIMING INFO RESULTS"
-    //                  << "________________\n"
-    //                  << "Total Duration = "
-    //                  << self->state.job_timing.getDuration("total_duration")
-    //                      .value_or(-1.0) << " Seconds\n"
-    //                  << "Total Duration = " 
-    //                  << self->state.job_timing.getDuration("total_duration")
-    //                      .value_or(-1.0) / 60 << " Minutes\n"
-    //                  << "Total Duration = " 
-    //                  << (self->state.job_timing.getDuration("total_duration")
-    //                     .value_or(-1.0) / 60) / 60 << " Hours\n"
-    //                  << "Job Init Duration = " 
-    //                   << self->state.job_timing.getDuration("init_duration")
-    //                       .value_or(-1.0) << " Seconds\n"
-    //                  << "_________________________________" 
-    //                  << "_______________________________________\n\n";
-
-    //       deallocateJobActor(&err);
-
-    //         // Tell Parent we are done
-    //       self->send(self->state.parent, done_job_v, self->state.num_gru_failed, 
-    //           self->state.job_timing.getDuration("total_duration")
-    //               .value_or(-1.0),
-    //           std::get<0>(read_write_duration), 
-    //           std::get<1>(read_write_duration));
     //       self->quit();
-
-    //   });
+    //       break;
+    //     default:
+    //       aout(self) << "Unknown Error: " << to_string(err) << "\n";
+    //       break;
+    //   }
     // },
-
-    // Handle Sundials Error
-    [=](err_atom, caf::actor src, double rtol, double atol) {
-      self->state.hru_actor_settings.rel_tol = rtol;
-      self->state.hru_actor_settings.abs_tol = atol;
-      handleGRUError(self, src);
-    },
-
-    [=](const error& err, caf::actor src) {
-      
-      aout(self) << "\n\n ********** ERROR HANDLER \n";
-      
-      switch(err.category()) {
-        
-        case type_id_v<hru_error>:
-          aout(self) << "HRU Error: " << to_string(err) << "\n";
-          handleGRUError(self, src);
-
-          break;
-        case type_id_v<file_access_error>:
-          if (err == file_access_error::mDecisions_error) {
-            aout(self) << "Check mDecisions File For Correctness";
-          } else {
-            aout(self) << "File Access Error: " << to_string(err) << "No Handling Implemented\n";
-          }
-          for (auto GRU : self->state.gru_container.gru_list) {
-            self->send_exit(GRU->getGRUActor(), exit_reason::user_shutdown);
-          }
-          self->quit();
-          break;
-        default:
-          aout(self) << "Unknown Error: " << to_string(err) << "\n";
-          break;
-      }
-    },
   };
 }
 
-
-
-
-
-
-
-std::vector<serializable_netcdf_gru_actor_info> getGruNetcdfInfo(
-    int max_run_attempts, std::vector<GRU*> &gru_list) {
-  std::vector<serializable_netcdf_gru_actor_info> gru_netcdf_info;
-  
-  for(auto gru : gru_list) {
-    serializable_netcdf_gru_actor_info gru_info;
-    gru_info.run_time = gru->getRunTime();
-    gru_info.init_duration = gru->getInitDuration();
-    gru_info.forcing_duration = gru->getForcingDuration();
-    gru_info.run_physics_duration = gru->getRunPhysicsDuration();
-    gru_info.write_output_duration = gru->getWriteOutputDuration();
-    
-    gru_info.num_attempts = max_run_attempts - gru->getAttemptsLeft() + 1;
-    gru_info.successful = is_success(gru->getStatus());
-    gru_info.rel_tol = gru->getRelTol();
-    gru_info.abs_tol = gru->getAbsTol();
-
-    gru_netcdf_info.push_back(gru_info);
-  }
-  
-  return gru_netcdf_info;
-}
-
-
-
-
-void handleGRUError(stateful_actor<job_state>* self, caf::actor src) {
-  auto it = std::find_if(self->state.gru_container.gru_list.begin(), 
-                          self->state.gru_container.gru_list.end(),
-                          [src](auto& gru) {
-                          return gru->getGRUActor() == src;
-                        });
-
-  if (it != self->state.gru_container.gru_list.end()) {
-    (*it)->setFailed();
-    (*it)->decrementAttemptsLeft();
-
-    self->state.gru_container.num_gru_done++;
-    self->state.gru_container.num_gru_failed++;
-    self->send(self->state.file_access_actor, run_failure_v, (*it)->getLocalGRUIndex());
-  } else {
-    aout(self) << "ERROR: Job_Actor: Could not find GRU in GRU_Container\n";
-  }
-
-  // Check if all GRUs are finished
-  if (self->state.gru_container.num_gru_done >= self->state.gru_container.num_gru_in_run_domain) {
-    // Check for failures
-    if(self->state.gru_container.num_gru_failed == 0 || self->state.max_run_attempts == 1) {
-      self->send(self, finalize_v); 
-    } else {
-      self->send(self, restart_failures_v);
-    }
-  }
-
-}
-
-} // End Namespace caf
-
-
diff --git a/build/source/job_actor/job_actor.f90 b/build/source/job_actor/job_actor.f90
deleted file mode 100644
index f06d610b91831deac022380c3fb17126c4a46abe..0000000000000000000000000000000000000000
--- a/build/source/job_actor/job_actor.f90
+++ /dev/null
@@ -1,167 +0,0 @@
-module job_actor
-  USE, intrinsic :: iso_c_binding
-  
-  ! global data
-  USE globalData,only:integerMissing      ! missing integer value
-  USE globalData,only:realMissing         ! missing double precision value
-    
-    
-  implicit none
-  public::job_init_fortran
-  public::deallocateJobActor
-
-    contains
-
-subroutine job_init_fortran(file_manager, start_gru, num_gru,&
-                            num_hru, file_gru, err) bind(C, name="job_init_fortran")
-  USE nrtype  ! variable types, etc.
-  
-  USE summaFileManager,only:summa_SetTimesDirsAndFiles       ! sets directories and filenames
-  USE summa_globalData,only:summa_defineGlobalData           ! used to define global summa data structures
-  
-  USE cppwrap_auxiliary,only:c_f_string           ! Convert C String to Fortran String
-  
-  ! provide access to file paths
-  USE summaFileManager,only:SETTINGS_PATH                     ! define path to settings files (e.g., parameters, soil and veg. tables)
-  USE summaFileManager,only:STATE_PATH                        ! optional path to state/init. condition files (defaults to SETTINGS_PATH)
-  USE summaFileManager,only:MODEL_INITCOND                    ! name of model initial conditions file
-  USE summaFileManager,only:LOCAL_ATTRIBUTES                  ! name of model initial attributes file
-  
-  ! subroutines and functions: read dimensions (NOTE: NetCDF)
-  USE read_attrb_module,only:read_dimension              ! module to read dimensions of GRU and HRU
-  USE read_icond_module,only:read_icond_nlayers               ! module to read initial condition dimensions
-
-  USE globalData,only:indx_meta                     ! metadata structures
-  USE globalData,only:startTime,finshTime,refTime,oldTime
-  USE allocspace_module,only:allocLocal
-  USE globalData,only:time_meta
-
-  ! Variables that were set by getCommandArguments()
-  USE globalData,only: startGRU          ! index of the starting GRU for parallelization run
-  USE globalData,only: checkHRU          ! index of the HRU for a single HRU run
-  USE globalData,only: iRunMode          ! define the current running mode    
-  USE globalData,only:iRunModeFull, iRunModeGRU, iRunModeHRU  ! define the running modes
-  USE globalData,only:output_fileSuffix                       ! suffix for the output file
-  
-  implicit none
-
-  ! dummy variables
-  character(kind=c_char,len=1),intent(in)   :: file_manager
-  integer(c_int),intent(inout)              :: start_gru
-  integer(c_int),intent(inout)              :: num_gru
-  integer(c_int),intent(inout)              :: num_hru
-  integer(c_int),intent(out)                :: file_gru
-  integer(c_int),intent(out)                :: err
-
-  ! local variables
-  character(len=256)                        :: summaFileManagerIn
-  character(len=256)                        :: restartFile        ! restart file name
-  character(len=256)                        :: attrFile           ! attributes file name
-  integer(i4b)                              :: fileHRU            ! [used for filenames] number of HRUs in the input file
-  character(len=128)                        :: fmtGruOutput       ! a format string used to write start and end GRU in output file names
-
-  
-  character(len=256)                        :: message
-
-  ! Convert C Variables to Fortran Variables
-  call c_f_string(file_manager, summaFileManagerIn, 256)
-  summaFileManagerIn = trim(summaFileManagerIn)
-
-
-  ! Set variables that were previosuly set by getCommandArguments()
-  startGRU=start_gru
-  iRunMode=iRunModeGRU
-  checkHRU=integerMissing
-
-  call summa_SetTimesDirsAndFiles(summaFileManagerIn,err,message)
-  if(err/=0)then; print*, trim(message); return; endif
-
-  call summa_defineGlobalData(err, message)
-  if(err/=0)then; print*, trim(message); return; endif
-  
-  ! *****************************************************************************
-  ! *** read the number of GRUs and HRUs
-  ! *****************************************************************************
-  ! obtain the HRU and GRU dimensions in the LocalAttribute file
-  attrFile = trim(SETTINGS_PATH)//trim(LOCAL_ATTRIBUTES)
-  select case (iRunMode)
-    case(iRunModeFull); err=20; message='iRunModeFull not implemented for Actors Code'
-    case(iRunModeGRU ); call read_dimension(trim(attrFile),file_gru,fileHRU,num_gru,num_hru,err,message,startGRU=start_gru)
-    case(iRunModeHRU ); err=20; message='iRunModeHRU not implemented for Actors Code'
-  end select
-  if(err/=0)then; print*, trim(message); return; endif
-
-  ! *****************************************************************************
-  ! *** read the number of snow and soil layers
-  ! *****************************************************************************
-  ! set restart filename and read the number of snow and soil layers from the initial conditions (restart) file
-  if(STATE_PATH == '') then
-    restartFile = trim(SETTINGS_PATH)//trim(MODEL_INITCOND)
-  else
-    restartFile = trim(STATE_PATH)//trim(MODEL_INITCOND)
-  endif
-  call read_icond_nlayers(trim(restartFile),num_gru,indx_meta,err,message)
-  if(err/=0)then; print*, trim(message); return; endif
-
-
-  ! Allocate the time structures
-  call allocLocal(time_meta, startTime, err=err, message=message)
-  call allocLocal(time_meta, finshTime, err=err, message=message)
-  call allocLocal(time_meta, refTime,   err=err, message=message)
-  call allocLocal(time_meta, oldTime,   err=err, message=message)
-  if(err/=0)then; print*, trim(message); return; endif
-
-end subroutine job_init_fortran
-
-
-subroutine deallocateJobActor(err) bind(C, name="deallocateJobActor")
-    USE globalData,only:structInfo                              ! information on the data structures
-    USE globalData,only:statForc_meta                           ! child metadata for stats
-    USE globalData,only:statProg_meta                           ! child metadata for stats
-    USE globalData,only:statDiag_meta                           ! child metadata for stats
-    USE globalData,only:statFlux_meta                           ! child metadata for stats
-    USE globalData,only:statIndx_meta                           ! child metadata for stats
-    USE globalData,only:statBvar_meta                           ! child metadata for stats
-    USE globalData,only:forcChild_map                           ! index of the child data structure: stats forc
-    USE globalData,only:progChild_map                           ! index of the child data structure: stats prog
-    USE globalData,only:diagChild_map                           ! index of the child data structure: stats diag
-    USE globalData,only:fluxChild_map                           ! index of the child data structure: stats flux
-    USE globalData,only:indxChild_map                           ! index of the child data structure: stats indx
-    USE globalData,only:bvarChild_map                           ! index of the child data structure: stats bvar
-    USE globalData,only:gru_struc                               ! gru->hru mapping structure
-    USE globalData,only:averageFlux_meta
-    USE globalData,only:index_map
-    USE globalData,only:startTime,finshTime,refTime,oldTime
-    USE var_lookup,only:childFLUX_MEAN                          ! look-up values for timestep-average model fluxes
-  
-    implicit none
-    integer(c_int), intent(out)     :: err
-    err=0
-  
-    ! Deallocate Time Varaibles
-    deallocate(startTime%var);
-    deallocate(finshTime%var);
-    deallocate(refTime%var);
-    deallocate(oldTime%var);
-  
-    if(allocated(averageFlux_meta)) then; deallocate(averageFlux_meta); endif
-    if(allocated(statForc_meta)) then; deallocate(statForc_meta); endif
-    if(allocated(statProg_meta)) then; deallocate(statProg_meta); endif
-    if(allocated(statDiag_meta)) then; deallocate(statDiag_meta); endif
-    if(allocated(statFlux_meta)) then; deallocate(statFlux_meta); endif
-    if(allocated(statIndx_meta)) then; deallocate(statIndx_meta); endif
-    if(allocated(statBvar_meta)) then; deallocate(statBvar_meta); endif
-    if(allocated(forcChild_map)) then; deallocate(forcChild_map); endif
-    if(allocated(progChild_map)) then; deallocate(progChild_map); endif
-    if(allocated(diagChild_map)) then; deallocate(diagChild_map); endif
-    if(allocated(fluxChild_map)) then; deallocate(fluxChild_map); endif
-    if(allocated(indxChild_map)) then; deallocate(indxChild_map); endif
-    if(allocated(bvarChild_map)) then; deallocate(bvarChild_map); endif
-    if(allocated(childFLUX_MEAN))then; deallocate(childFLUX_MEAN);endif
-    if(allocated(gru_struc))then; deallocate(gru_struc);endif
-    if(allocated(index_map))then; deallocate(index_map);endif
-end subroutine
-
-
-
-end module
\ No newline at end of file
diff --git a/build/source/job_actor/job_utils.cpp b/build/source/job_actor/job_utils.cpp
index ada32377151afdc4d7afc78a496b87da33eef558..1be82baf9fe952b4fe9091d9eb03654bcb049b07 100644
--- a/build/source/job_actor/job_utils.cpp
+++ b/build/source/job_actor/job_utils.cpp
@@ -1,30 +1,26 @@
 #include "job_actor.hpp"
 
-namespace caf {
+using namespace caf;
 
 void spawnHRUActors(stateful_actor<job_state>* self) {
-  auto& gru_container = self->state.gru_container;
-  gru_container.gru_start_time = std::chrono::high_resolution_clock::now();
-  gru_container.run_attempts_left = self->state.max_run_attempts;
-  gru_container.run_attempts_left--;
-
-  for (int i = 0; i < gru_container.num_gru_in_run_domain; i++) {
-    auto global_gru_index = gru_container.gru_list.size() + 
-        self->state.start_gru;
-    auto local_gru_index = gru_container.gru_list.size() + 1;                                
-
-    auto gru = self->spawn(hru_actor, global_gru_index, local_gru_index,               
-        self->state.hru_actor_settings, self->state.file_access_actor, self);
-
-    // Create the GRU object (Job uses this to keep track of GRU status)
-    gru_container.gru_list.push_back(new GRU(global_gru_index, 
-        local_gru_index, gru, self->state.dt_init_start_factor, 
-        self->state.hru_actor_settings.rel_tol,
-        self->state.hru_actor_settings.abs_tol, self->state.max_run_attempts));  
-    
-    // if (normal_mode) self->send(gru, update_hru_async_v);
-  }                        
-          
+  auto& gru_struc = self->state.gru_struc;
+  for (int i = 0; i < gru_struc->getNumGrus(); i++) {
+    auto netcdf_index = gru_struc->getStartGru() + i;
+    auto job_index = i + 1;
+    // Start GRU
+    auto gru = self->spawn(hru_actor, netcdf_index, job_index, 
+                           self->state.hru_actor_settings, 
+                           self->state.file_access_actor, self);
+    self->send(gru, init_hru_v);
+    self->send(gru, update_hru_async_v);
+    // Save information about the GRU
+    std::unique_ptr<GRU> gru_obj = std::make_unique<GRU>(
+        netcdf_index, job_index, gru, self->state.dt_init_start_factor, 
+        self->state.hru_actor_settings.rel_tol, 
+        self->state.hru_actor_settings.abs_tol, self->state.max_run_attempts);
+    gru_struc->addGRU(std::move(gru_obj));
+  }
+  gru_struc->decrementRetryAttempts();    
 }
 
 void spawnHRUBatches(stateful_actor<job_state>* self) {
@@ -74,23 +70,10 @@ void spawnHRUBatches(stateful_actor<job_state>* self) {
              << gru_container.gru_list.size() << "\n";
 }
 
-
 void finalizeJob(stateful_actor<job_state>* self) {
-  std::vector<serializable_netcdf_gru_actor_info> netcdf_gru_info = 
-      getGruNetcdfInfo(
-          self->state.max_run_attempts,self->state.gru_container.gru_list);
-  
-  self->state.num_gru_failed = std::count_if(netcdf_gru_info.begin(), 
-      netcdf_gru_info.end(), [](auto& gru_info) {
-    return !gru_info.successful;
-  });
-
   self->request(self->state.file_access_actor, infinite, finalize_v).await(
     [=](std::tuple<double, double> read_write_duration) {
       int err = 0;
-      for (auto GRU : self->state.gru_container.gru_list) 
-        delete GRU;
-      self->state.gru_container.gru_list.clear();
       self->state.job_timing.updateEndPoint("total_duration");
       aout(self) << "\n________________" 
                   << "PRINTING JOB_ACTOR TIMING INFO RESULTS"
@@ -109,45 +92,42 @@ void finalizeJob(stateful_actor<job_state>* self) {
                       .value_or(-1.0) << " Seconds\n"
                   << "_________________________________" 
                   << "_______________________________________\n\n";
-      
-      deallocateJobActor(&err);
-      
+            
       // Tell Parent we are done
-      self->send(self->state.parent, done_job_v, self->state.num_gru_failed, 
-          self->state.job_timing.getDuration("total_duration").value_or(-1.0),
-          std::get<0>(read_write_duration), 
-          std::get<1>(read_write_duration));
+      auto total_duration = self->state.job_timing.getDuration("total_duration")
+          .value_or(-1.0);
+      auto num_failed_grus = self->state.gru_struc->getNumGRUFailed();    
+      self->send(self->state.parent, done_job_v, num_failed_grus, 
+                 total_duration, std::get<0>(read_write_duration), 
+                 std::get<1>(read_write_duration));
       self->quit();
     });
 }
 
-void handleFinishedGRU(stateful_actor<job_state>* self, int local_gru_index) {
-  using namespace std::chrono;
-  auto& gru_container = self->state.gru_container;
-  chrono_time end_point = high_resolution_clock::now();
-  double total_duration = duration_cast<seconds>(end_point - 
-      gru_container.gru_start_time).count();
-  gru_container.num_gru_done++;
-
-  aout(self) << "GRU Finished: " << gru_container.num_gru_done << "/" 
-             << gru_container.num_gru_in_run_domain << " -- GlobalGRU=" 
-             << gru_container.gru_list[local_gru_index-1]->getGlobalGRUIndex()
-             << " -- LocalGRU=" << local_gru_index << "\n";
-
-  gru_container.gru_list[local_gru_index-1]->setRunTime(total_duration);
-  gru_container.gru_list[local_gru_index-1]->setInitDuration(-1);
-  gru_container.gru_list[local_gru_index-1]->setForcingDuration(-1);
-  gru_container.gru_list[local_gru_index-1]->setRunPhysicsDuration(-1);
-  gru_container.gru_list[local_gru_index-1]->setWriteOutputDuration(-1);
-  gru_container.gru_list[local_gru_index-1]->setSuccess();
-
-
-  // Check if all GRUs are done
-  if (gru_container.num_gru_done >= gru_container.num_gru_in_run_domain) {
-    if(gru_container.num_gru_failed == 0 || self->state.max_run_attempts == 1)
-      self->send(self, finalize_v);
-    else
-      self->send(self, restart_failures_v);
+void handleFinishedGRU(stateful_actor<job_state>* self, int gru_job_index) {
+  auto& gru_struc = self->state.gru_struc;
+  gru_struc->incrementNumGRUDone();
+  gru_struc->getGRU(gru_job_index)->setSuccess();
+  aout(self) << "GRU Finished: " << gru_struc->getNumGrusDone() << "/" 
+             << gru_struc->getNumGrus() << " -- GlobalGRU=" 
+             << gru_struc->getGRU(gru_job_index)->getIndexNetcdf()
+             << " -- LocalGRU=" 
+             << gru_struc->getGRU(gru_job_index)->getIndexJob() << "\n";
+
+  if (gru_struc->isDone()) {
+    gru_struc->hasFailures() && gru_struc->shouldRetry() ? 
+        self->send(self, restart_failures_v) : self->send(self, finalize_v);
   }
 }
-} // End of Namespace caf
\ No newline at end of file
+
+void handleGRUError(stateful_actor<job_state>* self, int err_code, 
+                    int gru_job_index) {
+  auto& gru_struc = self->state.gru_struc;
+  gru_struc->getGRU(gru_job_index)->setFailed();
+  gru_struc->incrementNumGRUFailed();
+  self->send(self->state.file_access_actor, run_failure_v, gru_job_index);
+  if (gru_struc->isDone()) {
+    gru_struc->hasFailures() && gru_struc->shouldRetry() ? 
+        self->send(self, restart_failures_v) : self->send(self, finalize_v);
+  }
+}
\ No newline at end of file
diff --git a/build/source/job_actor/node_actor.cpp b/build/source/job_actor/node_actor.cpp
index 76d4bca67ca3a4a81cfa404be64ba1f95497585b..b06806c496a7329bb8d595c060ab43a5f5926d85 100644
--- a/build/source/job_actor/node_actor.cpp
+++ b/build/source/job_actor/node_actor.cpp
@@ -75,14 +75,29 @@ behavior node_actor(stateful_actor<node_state>* self, std::string host,
       
       self->state.node_timing.addTimePoint("node_init");
       self->state.node_timing.updateStartPoint("node_init");
-      int err, file_gru_to_remove;
-      job_init_fortran(self->state.job_actor_settings.file_manager_path.c_str(),
-          &start_gru, &num_gru, &num_hru, &file_gru_to_remove, &err);
-      if (err != 0) { 
-        aout(self) << "\nERROR: Job_Actor - job_init_fortran\n"; 
-        self->quit();
+
+
+
+      auto& gru_struc = self->state.gru_struc;
+      gru_struc = std::make_unique<GruStruc>(start_gru, num_gru, 
+                                             job_actor_settings.max_run_attempts);
+      if (gru_struc->ReadDimension()) {
+        aout(self) << "ERROR: Job_Actor - ReadDimension\n";
+        // TODO: Needs to return an error
+        return;
+      }
+      if (gru_struc->ReadIcondNlayers()) {
+        aout(self) << "ERROR: Job_Actor - ReadIcondNlayers\n";
+        // TODO: Needs to return an error
         return;
       }
+      // job_init_fortran(self->state.job_actor_settings.file_manager_path.c_str(),
+      //     &start_gru, &num_gru, &num_hru, &file_gru_to_remove, &err);
+      // if (err != 0) { 
+      //   aout(self) << "\nERROR: Job_Actor - job_init_fortran\n"; 
+      //   self->quit();
+      //   return;
+      // }
       // Spawn the file_access_actor.
       self->state.file_access_actor = self->spawn(file_access_actor, 
           self->state.num_gru_info, self->state.file_access_actor_settings, 
@@ -121,7 +136,7 @@ behavior node_actor(stateful_actor<node_state>* self, std::string host,
       self->state.stepsInCurrentFFile = num_steps_in_iFile;
       self->state.forcingStep = 1;
       for(auto gru : self->state.gru_container.gru_list) {
-        self->send(gru->getGRUActor(), update_timeZoneOffset_v, 
+        self->send(gru->getActorRef(), update_timeZoneOffset_v, 
             self->state.iFile);
       }
       self->send(self->state.current_server, new_forcing_file_v, 
@@ -133,7 +148,7 @@ behavior node_actor(stateful_actor<node_state>* self, std::string host,
       self->state.timestep_start_time 
         = std::chrono::high_resolution_clock::now();
       for (auto gru : self->state.gru_container.gru_list) {
-        self->send(gru->getGRUActor(), update_hru_v, self->state.timestep, 
+        self->send(gru->getActorRef(), update_hru_v, self->state.timestep, 
             self->state.forcingStep);
       }
     },
diff --git a/build/source/main.cpp b/build/source/main.cpp
index 08aef2db990c2f7d5cd8945a8edb1921ad4ff354..d3a52e163b8007f5355646a43fe5db79db753a09 100644
--- a/build/source/main.cpp
+++ b/build/source/main.cpp
@@ -1,23 +1,12 @@
-#include "caf/all.hpp"
-#include "caf/io/all.hpp"
 #include "summa_actor.hpp"
 #include "summa_client.hpp"
 #include "summa_server.hpp"
 #include "summa_backup_server.hpp"
 #include "job_actor.hpp"
 #include "node_actor.hpp"
-#include "global.hpp"
 #include "settings_functions.hpp"
 #include "message_atoms.hpp"
 #include "client.hpp"
-#include <string>
-#include <bits/stdc++.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <iostream>
-#include "json.hpp"
-#include <memory>
-#include <optional>
 #include <filesystem>
 
 using namespace caf;
@@ -72,12 +61,13 @@ class config : public actor_system_config {
 };
 
 
-void run_client(actor_system& system, const config& cfg, Distributed_Settings distributed_settings) {
-    scoped_actor self{system};
+void run_client(actor_system& system, const config& cfg, 
+                Distributed_Settings distributed_settings) {
+  scoped_actor self{system};
 
-    aout(self) << "Starting SUMMA-Client in Distributed Mode\n";
+  aout(self) << "Starting SUMMA-Client in Distributed Mode\n";
     
-    auto client = system.spawn(summa_client, distributed_settings);   
+  auto client = system.spawn(summa_client, distributed_settings);   
 }
 
 void run_server(actor_system& system, const config& cfg, 
@@ -96,23 +86,16 @@ void run_server(actor_system& system, const config& cfg,
 
   // Check if we have are the backup server
   if (cfg.backup_server) {          
-    auto server = system.spawn(summa_backup_server_init,
-                                distributed_settings,
-                                summa_actor_settings,
-                                file_access_actor_settings,
-                                job_actor_settings,
-                                hru_actor_settings);
+    auto server = system.spawn(summa_backup_server_init, distributed_settings,
+                               summa_actor_settings, file_access_actor_settings, 
+                               job_actor_settings, hru_actor_settings);
 
   } else {  
     aout(self) << "\n\n*****Starting SUMMA-Server*****\n\n";
-    auto server = system.spawn(summa_server, 
-                               distributed_settings,
-                               summa_actor_settings, 
-                               file_access_actor_settings, 
-                               job_actor_settings, 
-                               hru_actor_settings);
+    auto server = system.spawn(summa_server, distributed_settings,
+        summa_actor_settings, file_access_actor_settings, job_actor_settings, 
+        hru_actor_settings);
   }
-
 }
 
 
@@ -147,7 +130,7 @@ void caf_main(actor_system& sys, const config& cfg) {
     job_actor_settings.file_manager_path = cfg.master_file;
   
   check_settings_from_json(distributed_settings, summa_actor_settings, 
-                           file_access_actor_settings, job_actor_settings,
+                           file_access_actor_settings, job_actor_settings, 
                            hru_actor_settings);
 
   if (distributed_settings.distributed_mode && 
@@ -155,44 +138,31 @@ void caf_main(actor_system& sys, const config& cfg) {
     // only command line arguments needed are config_file and server-mode
     if (cfg.server_mode) {
       run_server(sys, cfg, distributed_settings, summa_actor_settings, 
-                  file_access_actor_settings, job_actor_settings, 
-                  hru_actor_settings);
+                 file_access_actor_settings, job_actor_settings, 
+                 hru_actor_settings);
     } else {
       run_client(sys,cfg, distributed_settings);
     }
 
   } else if (distributed_settings.distributed_mode &&
-             job_actor_settings.data_assimilation_mode &&
-             cfg.server_mode) {
+             job_actor_settings.data_assimilation_mode && cfg.server_mode) {
     
-    auto dist_summa = sys.spawn(distributed_job_actor,
-                                cfg.startGRU,
-                                cfg.countGRU,
-                                distributed_settings,
+    auto dist_summa = sys.spawn(distributed_job_actor, cfg.startGRU,
+                                cfg.countGRU, distributed_settings, 
                                 file_access_actor_settings,
-                                job_actor_settings,
-                                hru_actor_settings);
+                                job_actor_settings, hru_actor_settings);
   
   } else if (distributed_settings.distributed_mode &&
              job_actor_settings.data_assimilation_mode) {
     
-    auto node = sys.spawn(node_actor, 
-                          cfg.host,
-                          self,
-                          distributed_settings, 
-                          file_access_actor_settings, 
-                          job_actor_settings, 
+    auto node = sys.spawn(node_actor, cfg.host, self, distributed_settings, 
+                          file_access_actor_settings, job_actor_settings, 
                           hru_actor_settings);
 
   } else {
-    auto summa = sys.spawn(summa_actor, 
-                           cfg.startGRU, 
-                           cfg.countGRU, 
-                           summa_actor_settings, 
-                           file_access_actor_settings, 
-                           job_actor_settings, 
-                           hru_actor_settings, 
-                           self);
+    auto summa = sys.spawn(summa_actor, cfg.startGRU, cfg.countGRU, 
+                           summa_actor_settings, file_access_actor_settings, 
+                           job_actor_settings, hru_actor_settings, self);
   }
     
 }
@@ -243,6 +213,5 @@ int main(int argc, char** argv) {
   exec_main_init_meta_objects<io::middleman, id_block::summa>();
   caf::core::init_global_meta_objects(); 
   return exec_main<io::middleman, id_block::summa>(caf_main, argc, argv2);
-
 }
 
diff --git a/build/source/summa_actor/batch.cpp b/build/source/system_initialization/batch.cpp
similarity index 100%
rename from build/source/summa_actor/batch.cpp
rename to build/source/system_initialization/batch.cpp
diff --git a/build/source/summa_actor/batch_container.cpp b/build/source/system_initialization/batch_container.cpp
similarity index 100%
rename from build/source/summa_actor/batch_container.cpp
rename to build/source/system_initialization/batch_container.cpp
diff --git a/build/source/system_initialization/batch_distributer_actor.f90 b/build/source/system_initialization/batch_distributer_actor.f90
new file mode 100644
index 0000000000000000000000000000000000000000..0572972218d76bbbe0da0cd55be0f13c1248668c
--- /dev/null
+++ b/build/source/system_initialization/batch_distributer_actor.f90
@@ -0,0 +1,99 @@
+module batch_distributer
+  USE, intrinsic :: iso_c_binding
+  ! global constants
+  USE globalData,only:integerMissing      ! missing integer value
+  USE globalData,only:realMissing         ! missing double precision value
+  
+  implicit none
+  public::SetTimesDirsAndFiles_fortran
+  public::defineGlobalData_fortran
+  public::deallocateGlobalData_fortran
+
+  contains
+
+subroutine setTimesDirsAndFiles_fortran(summaFileManagerIn_C,err,message_r) &
+    bind(C, name="setTimesDirsAndFiles_fortran")
+  USE C_interface_module
+  USE summaFileManager
+  implicit none
+
+  ! dummy variables
+  character(kind=c_char,len=1),intent(in)   :: summaFileManagerIn_C
+  integer(c_int),intent(out)                :: err
+  type(c_ptr),intent(out)                   :: message_r ! message to return to the caller
+  ! local variables
+  character(len=256)                        :: summaFileManagerIn    
+  character(len=256)                        :: message = ""
+
+
+  ! Convert strings 
+  call f_c_string_ptr(trim(message), message_r);
+  call c_f_string_chars(summaFileManagerIn_C, summaFileManagerIn)
+
+  ! Initialize the file manager
+  call summa_SetTimesDirsAndFiles(summaFileManagerIn, err, message)
+  if (err /= 0) then; call f_c_string_ptr(trim(message), message_r); return; endif
+end subroutine setTimesDirsAndFiles_fortran
+
+
+subroutine defineGlobalData_fortran(err, message_r) bind(C, name="defineGlobalData_fortran")
+  USE C_interface_module
+  USE summa_globalData,only:summa_defineGlobalData           ! used to define global summa data structures
+
+  implicit none
+  ! dummy variables
+  integer(c_int),intent(out)                :: err
+  type(c_ptr),intent(out)                   :: message_r ! message to return to the caller
+  ! local variables
+  character(len=256)                        :: message = "" 
+
+  ! Convert strings
+  call f_c_string_ptr(trim(message), message_r)
+
+  ! Define global data
+  call summa_defineGlobalData(err, message)
+  if (err /= 0) then; call f_c_string_ptr(trim(message), message_r); return; endif
+
+end subroutine defineGlobalData_fortran
+
+subroutine deallocateGlobalData_fortran(err, message_r) bind(C, name="deallocateGlobalData_fortran")
+  USE C_interface_module
+  USE globalData,only:averageFlux_meta
+  USE var_lookup,only:childFLUX_MEAN
+  USE globalData,only:statForc_meta, statProg_meta, statDiag_meta, statFlux_meta, &
+                      statIndx_meta, statBvar_meta
+  USE globalData,only:forcChild_map, progChild_map, diagChild_map, fluxChild_map, &
+                      indxChild_map, bvarChild_map
+
+
+  implicit none
+  ! dummy variables
+  integer(c_int),intent(out)                :: err
+  type(c_ptr),intent(out)                   :: message_r ! message to return to the caller
+  ! local variables
+  character(len=256)                       :: message = "" 
+
+  ! Convert strings
+  call f_c_string_ptr(trim(message), message_r)
+
+  if(allocated(averageFlux_meta)) deallocate(averageFlux_meta)
+  if(allocated(childFLUX_MEAN)) deallocate(childFLUX_MEAN)
+  if(allocated(statForc_meta)) deallocate(statForc_meta)
+  if(allocated(statProg_meta)) deallocate(statProg_meta)
+  if(allocated(statDiag_meta)) deallocate(statDiag_meta)
+  if(allocated(statFlux_meta)) deallocate(statFlux_meta)
+  if(allocated(statIndx_meta)) deallocate(statIndx_meta)
+  if(allocated(statBvar_meta)) deallocate(statBvar_meta)
+  if(allocated(forcChild_map)) deallocate(forcChild_map)
+  if(allocated(progChild_map)) deallocate(progChild_map)
+  if(allocated(diagChild_map)) deallocate(diagChild_map)
+  if(allocated(fluxChild_map)) deallocate(fluxChild_map)
+  if(allocated(indxChild_map)) deallocate(indxChild_map)
+  if(allocated(bvarChild_map)) deallocate(bvarChild_map)
+
+
+
+end subroutine deallocateGlobalData_fortran
+
+
+end module batch_distributer
\ No newline at end of file
diff --git a/build/source/summa_actor/client.cpp b/build/source/system_initialization/client.cpp
similarity index 100%
rename from build/source/summa_actor/client.cpp
rename to build/source/system_initialization/client.cpp
diff --git a/build/source/summa_actor/client_container.cpp b/build/source/system_initialization/client_container.cpp
similarity index 100%
rename from build/source/summa_actor/client_container.cpp
rename to build/source/system_initialization/client_container.cpp
diff --git a/build/source/summa_actor/summa_actor.cpp b/build/source/system_initialization/summa_actor.cpp
similarity index 66%
rename from build/source/summa_actor/summa_actor.cpp
rename to build/source/system_initialization/summa_actor.cpp
index 365a30298cf9916fc9258e5bf4048cef66aae6e5..37be16e12398226742fbb6f3223104dd5698b1b5 100644
--- a/build/source/summa_actor/summa_actor.cpp
+++ b/build/source/system_initialization/summa_actor.cpp
@@ -1,54 +1,68 @@
-#include "caf/all.hpp"
-#include "caf/io/all.hpp"
-#include "message_atoms.hpp"
 #include "summa_actor.hpp"
 #include "global.hpp"
 #include "job_actor.hpp"
 #include "json.hpp"
 #include <iostream>
-#include <chrono>
-#include <string>
 #include <fstream>
 #include <netcdf.h>
 
 using json = nlohmann::json;
 
 namespace caf {
-behavior summa_actor(stateful_actor<summa_actor_state>* self, 
-    int startGRU, int numGRU, 
-    Summa_Actor_Settings summa_actor_settings, 
-    File_Access_Actor_Settings file_access_actor_settings,
-    Job_Actor_Settings job_actor_settings, 
-    HRU_Actor_Settings hru_actor_settings, actor parent) {
-
+behavior summa_actor(stateful_actor<summa_actor_state>* self, int start_gru, 
+                     int num_gru, Summa_Actor_Settings summa_actor_settings, 
+                     File_Access_Actor_Settings file_access_actor_settings,
+                     Job_Actor_Settings job_actor_settings, 
+                     HRU_Actor_Settings hru_actor_settings, actor parent) {
   // Set Timing Variables
   self->state.summa_actor_timing = TimingInfo();
   self->state.summa_actor_timing.addTimePoint("total_duration");
   self->state.summa_actor_timing.updateStartPoint("total_duration");
   // Set Variables
-  self->state.startGRU = startGRU;
-  self->state.numGRU = numGRU;
+  self->state.start_gru = start_gru;
+  self->state.num_gru = num_gru;
   self->state.parent = parent;
   // Set Settings
   self->state.summa_actor_settings = summa_actor_settings;
   self->state.file_access_actor_settings = file_access_actor_settings;
   self->state.job_actor_settings = job_actor_settings;
   self->state.hru_actor_settings = hru_actor_settings;
-  // Double check the number of GRUs in the file
-  self->state.fileGRU = getNumGRUInFile(job_actor_settings.file_manager_path);
-  if (self->state.fileGRU  == -1) 
+
+  // Read in the file Manager
+  auto& file_manager = self->state.file_manager;
+  file_manager = std::make_unique<fileManager>(
+      job_actor_settings.file_manager_path);
+  // Set the directoires for the fortran side
+  auto err_msg = file_manager->setTimesDirsAndFiles();
+  if (!err_msg.empty()) {
+    aout(self) << "\n\nERROR--File Manager: " << err_msg << "\n\n";
+    self->quit(); return {};
+  }
+
+  // Create the global state
+  self->state.global_fortran_state = std::make_unique<summaGlobalData>();
+  auto err = self->state.global_fortran_state->defineGlobalData();
+  if (err != 0) {
+    aout(self) << "ERROR--Global State: Unable To Define Global Data\n";
+    self->quit(); return {};
+  }
+
+  self->state.file_gru = getNumGRUInFile(file_manager->settings_path_, 
+      file_manager->local_attributes_);
+  if (self->state.file_gru  == -1) 
     aout(self) << "***WARNING***: UNABLE TO VERIFY NUMBER OF GRUS" 
-               << " - Job Actor MAY CRASH\n";
+               << " - Job Actor MAY CRASH\n"
+               << "Number of GRUs in File: " << self->state.file_gru << "\n";
 
-  if (self->state.fileGRU > 0) { 
+  if (self->state.file_gru > 0) { 
     // Fix the number of GRUs if it exceeds the number of GRUs in the file
-    if (self->state.startGRU + self->state.numGRU > self->state.fileGRU) {
-      self->state.numGRU = self->state.fileGRU - self->state.startGRU + 1;
+    if (self->state.start_gru + self->state.num_gru > self->state.file_gru) {
+      self->state.num_gru = self->state.file_gru - self->state.start_gru + 1;
     }
   }
   // No else: if we cannot verify we try to run anyway
-  self->state.batch_container = Batch_Container(self->state.startGRU, 
-      self->state.numGRU, 
+  self->state.batch_container = Batch_Container(self->state.start_gru, 
+      self->state.num_gru, 
       self->state.summa_actor_settings.max_gru_per_job);
   
   aout(self) << "Starting SUMMA With "
@@ -56,25 +70,24 @@ behavior summa_actor(stateful_actor<summa_actor_state>* self,
              << " Batches\n"
              << "###################################################\n"
              << self->state.batch_container.getBatchesAsString()
-            << "###################################################\n";
-
+             << "###################################################\n";
   std::optional<Batch> batch = 
       self->state.batch_container.getUnsolvedBatch();
   if (!batch.has_value()) {
     aout(self) << "ERROR--Summa_Actor: No Batches To Solve\n";
-    self->quit(); return {};
+    self->quit(); 
+    return {};
   } 
+
   self->state.current_batch_id = batch->getBatchID();
   aout(self) << "Starting Batch " << self->state.current_batch_id + 1 << "\n";
   auto batch_val = batch.value();
-  self->state.currentJob = self->spawn(job_actor, batch->getStartHRU(), 
+  self->state.current_job = self->spawn(job_actor, batch->getStartHRU(), 
       batch->getNumHRU(), self->state.file_access_actor_settings, 
       self->state.job_actor_settings, self->state.hru_actor_settings, self);
 
   return {
-
-
-    [=](done_job, int numFailed, double job_duration, double read_duration, 
+    [=](done_job, int num_gru_failed, double job_duration, double read_duration, 
         double write_duration) {
       
       self->state.batch_container.updateBatch_success(
@@ -84,13 +97,11 @@ behavior summa_actor(stateful_actor<summa_actor_state>* self,
       aout(self) << "###########################################\n"
                  << "Job Finished: " 
                  << self->state.batch_container.getTotalBatches() - 
-                 self->state.batch_container.getBatchesRemaining() 
+                    self->state.batch_container.getBatchesRemaining() 
                  << "/" << self->state.batch_container.getTotalBatches() << "\n"
                  << "###########################################\n";
       
-      self->state.numFailed += numFailed;
-      
-    
+      self->state.num_gru_failed += num_gru_failed;
       
       if (self->state.batch_container.hasUnsolvedBatches()) {
         spawnJob(self);
@@ -112,7 +123,7 @@ behavior summa_actor(stateful_actor<summa_actor_state>* self,
                    << "Total Duration = " << total_dur_hr << " Hours\n"
                    << "Total Read Duration = " << read_dur_sec << "Seconds\n"
                    << "Total Write Duration = " << write_dur_sec << "Seconds\n"
-                   << "Num Failed = " << self->state.numFailed << "\n"
+                   << "Num Failed = " << self->state.num_gru_failed << "\n"
                    << "___________________Program Finished__________________\n";
         
         self->send(self->state.parent, done_batch_v, total_dur_sec, 
@@ -122,7 +133,7 @@ behavior summa_actor(stateful_actor<summa_actor_state>* self,
       }
     },
 
-    [=](err) {
+    [=](err_atom) {
       aout(self) << "Unrecoverable Error: Attempting To Fail Gracefully\n";
       self->quit();
     }
@@ -136,7 +147,7 @@ void spawnJob(stateful_actor<summa_actor_state>* self) {
   self->state.current_batch_id = batch->getBatchID();
   aout(self) << "Starting Batch " << self->state.current_batch_id + 1 << "\n";
   auto batch_val = batch.value();
-  self->state.currentJob = self->spawn(job_actor, batch->getStartHRU(), 
+  self->state.current_job = self->spawn(job_actor, batch->getStartHRU(), 
       batch->getNumHRU(), self->state.file_access_actor_settings, 
       self->state.job_actor_settings, self->state.hru_actor_settings, 
       self);
@@ -145,38 +156,15 @@ void spawnJob(stateful_actor<summa_actor_state>* self) {
 } // end namespace
 
 
-std::string extractEnclosed(const std::string& line) {
-  std::size_t first_quote = line.find_first_of("'");
-  std::size_t last_quote = line.find_last_of("'");
-  if (first_quote != std::string::npos && last_quote != std::string::npos 
-      && first_quote < last_quote) {
-    return line.substr(first_quote + 1, last_quote - first_quote - 1);
-  }
-  return "";
-}
-
-int getNumGRUInFile(const std::string &file_manager) {
-  std::ifstream file(file_manager);
-  std::string attributeFile, settingPath;
-  if (!file.is_open())
-    return -1;
-  
-  std::string line;
-  while (std::getline(file, line)) {
-    if (line.compare(0, 13, "attributeFile") == 0)
-      attributeFile = extractEnclosed(line);
-    if (line.compare(0, 12, "settingsPath") == 0)
-      settingPath = extractEnclosed(line);
-  }
-
-  file.close();
-
+int getNumGRUInFile(const std::string &settingsPath, 
+                    const std::string &attributeFile) {
   size_t fileGRU = -1;
   int ncid, gru_dim;
-  if (attributeFile.empty() || settingPath.empty())
+
+  if (attributeFile.empty() || settingsPath.empty())
     return fileGRU;
   
-  std::string combined = settingPath + attributeFile;
+  std::string combined = settingsPath + attributeFile;
 
   if (NC_NOERR != nc_open(combined.c_str(), NC_NOWRITE, &ncid))
     return fileGRU;
diff --git a/build/source/summa_actor/summa_backup_server.cpp b/build/source/system_initialization/summa_backup_server.cpp
similarity index 100%
rename from build/source/summa_actor/summa_backup_server.cpp
rename to build/source/system_initialization/summa_backup_server.cpp
diff --git a/build/source/summa_actor/summa_client.cpp b/build/source/system_initialization/summa_client.cpp
similarity index 100%
rename from build/source/summa_actor/summa_client.cpp
rename to build/source/system_initialization/summa_client.cpp
diff --git a/build/source/system_initialization/summa_global_data.cpp b/build/source/system_initialization/summa_global_data.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..84c0cb1181541a69f72e95d5e2af7f7562b8966c
--- /dev/null
+++ b/build/source/system_initialization/summa_global_data.cpp
@@ -0,0 +1,33 @@
+#include "summa_global_data.hpp"
+#include <memory>
+#include <iostream>
+
+summaGlobalData::summaGlobalData() {
+  global_data_ready = false;
+}
+
+summaGlobalData::~summaGlobalData() {
+  if (global_data_ready) {
+    std::unique_ptr<char[]> err_msg(new char[1024]);
+    int err = 0;
+    deallocateGlobalData_fortran(&err, &err_msg);
+    if (err != 0) {
+      std::cout << "\n\nERROR: deallocateGlobalData_fortran() - " 
+                << err_msg.get() << "\n\n";
+    }
+  }
+}
+
+int summaGlobalData::defineGlobalData() {
+  std::unique_ptr<char[]> err_msg(new char[1024]);
+  int err = 0;
+  defineGlobalData_fortran(&err, &err_msg);
+  if (err != 0) {
+    std::cout << "\n\nERROR: defineGlobalData_fortran() - " 
+              << err_msg.get() << "\n\n";
+    global_data_ready = false;
+  } else {
+    global_data_ready = true;
+  }
+  return err;
+}
diff --git a/build/source/summa_actor/summa_server.cpp b/build/source/system_initialization/summa_server.cpp
similarity index 100%
rename from build/source/summa_actor/summa_server.cpp
rename to build/source/system_initialization/summa_server.cpp
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