From 528e99cdf6e5a25d14d64a151f78c6815da079d3 Mon Sep 17 00:00:00 2001
From: Kyle Klenk <kyle.klenk@usask.ca>
Date: Thu, 14 Apr 2022 14:41:44 -0600
Subject: [PATCH] added the ability to write data as an array

---
 build/source/driver/summaActors_init.f90      |   2 +-
 .../driver/summaActors_wOutputStruc.f90       |   9 +-
 build/source/engine/alloc_file_access.f90     |   4 +-
 build/source/engine/allocspaceActors.f90      |   6 +-
 build/source/engine/ffile_info.f90            |   1 -
 .../file_access_actor/cppwrap_fileAccess.f90  |  96 +++----
 .../interface/job_actor/cppwrap_job.f90       |   2 +-
 build/source/netcdf/writeOutput.f90           | 235 ++++++++++--------
 config/Summa_Actors_Settings.json             |   2 +-
 9 files changed, 178 insertions(+), 179 deletions(-)

diff --git a/build/source/driver/summaActors_init.f90 b/build/source/driver/summaActors_init.f90
index b9b26e5..99b6872 100755
--- a/build/source/driver/summaActors_init.f90
+++ b/build/source/driver/summaActors_init.f90
@@ -78,7 +78,7 @@ contains
   USE nrtype                                                  ! variable types, etc.
   USE time_utils_module,only:elapsedSec                       ! calculate the elapsed time
   ! subroutines and functions: allocate space
-  USE allocspace4chm_module,only:allocGlobal4chm              ! module to allocate space for global data structures
+  USE allocspace4chm_module,only:allocGlobal              ! module to allocate space for global data structures
   USE allocspace4chm_module,only:allocLocal
   ! timing variables
   USE globalData,only:startInit,endInit                       ! date/time for the start and end of the initialization
diff --git a/build/source/driver/summaActors_wOutputStruc.f90 b/build/source/driver/summaActors_wOutputStruc.f90
index 5802231..34f78b4 100644
--- a/build/source/driver/summaActors_wOutputStruc.f90
+++ b/build/source/driver/summaActors_wOutputStruc.f90
@@ -175,9 +175,8 @@ subroutine summaActors_writeToOutputStruc(&
   err=0; message='summa_manageOutputFiles/'
   ! identify the start of the writing
   call date_and_time(values=startWrite)
-  ! print*, "HRU WRite timestep = ", modelTimeStep
-  ! print*, "OutputStep = ", outputStep
-  ! ! initialize the statistics flags
+
+  ! initialize the statistics flags
   if(modelTimeStep==1)then
 
     ! initialize time step index
@@ -226,7 +225,7 @@ subroutine summaActors_writeToOutputStruc(&
       if(err/=0)then; message=trim(message)//trim(cmessage)//'['//trim(structInfo(iStruct)%structName)//']'; return; endif
     end do  ! (looping through structures)
 
-    !   ! write GRU parameters
+    ! write GRU parameters
     call writeParm(indxGRU,indxHRU,integerMissing,bparStruct,bpar_meta,'bpar',err,cmessage)
     if(err/=0)then; message=trim(message)//trim(cmessage); return; endif 
     
@@ -266,7 +265,7 @@ subroutine summaActors_writeToOutputStruc(&
   call writeTime(indxGRU,indxHRU,outputStep,finalizeStats%dat, &
                 time_meta,timeStruct%var,err,message)
 
-  ! write the model output to the NetCDF file
+  ! write the model output to the OutputStructure
   ! Passes the full metadata structure rather than the stats metadata structure because
   ! we have the option to write out data of types other than statistics.
   ! Thus, we must also pass the stats parent->child maps from childStruct.
diff --git a/build/source/engine/alloc_file_access.f90 b/build/source/engine/alloc_file_access.f90
index 7a9a024..5a83a89 100644
--- a/build/source/engine/alloc_file_access.f90
+++ b/build/source/engine/alloc_file_access.f90
@@ -191,7 +191,7 @@ subroutine allocateDat_rkind_nSteps(metadata,varData,nSnow, nSoil, &
   nLayers = nSnow+nSoil
   do iStep=1, nSteps
       do iVar=1, nVars
-          select case(metadata(iVar)%vartype)
+        select case(metadata(iVar)%vartype)
           case(iLookVarType%scalarv); allocate(varData%var(iVar)%tim(iStep)%dat(1),stat=err)
           case(iLookVarType%wLength); allocate(varData%var(iVar)%tim(iStep)%dat(nBand),stat=err)
           case(iLookVarType%midSnow); allocate(varData%var(iVar)%tim(iStep)%dat(nSnow),stat=err)
@@ -207,7 +207,7 @@ subroutine allocateDat_rkind_nSteps(metadata,varData,nSnow, nSoil, &
           case default
               err=40; message=trim(message)//"1. unknownVariableType[name='"//trim(metadata(iVar)%varname)//"'; type='"//trim(get_varTypeName(metadata(iVar)%vartype))//"']"
               return
-          end select
+        end select
       end do
   end do
 
diff --git a/build/source/engine/allocspaceActors.f90 b/build/source/engine/allocspaceActors.f90
index fa49fb0..f10d43a 100755
--- a/build/source/engine/allocspaceActors.f90
+++ b/build/source/engine/allocspaceActors.f90
@@ -65,7 +65,7 @@ USE var_lookup,only:maxvarFreq             ! allocation dimension (output freque
 ! privacy
 implicit none
 private
-public::allocGlobal4chm
+public::allocGlobal
 public::allocLocal
 public::resizeData
 
@@ -75,7 +75,7 @@ contains
  ! ************************************************************************************************
  ! public subroutine allocGlobal4chm: allocate space for global data structures
  ! ************************************************************************************************
- subroutine allocGlobal4chm(metaStruct,dataStruct,err,message)
+ subroutine allocGlobal(metaStruct,dataStruct,err,message)
  ! NOTE: safety -- ensure only used in allocGlobal4chm
  USE globalData,only: gru_struc     ! gru-hru mapping structures
  implicit none
@@ -113,7 +113,7 @@ contains
   ! end association to info in data structures
   end associate
 
- end subroutine allocGlobal4chm
+ end subroutine allocGlobal
 
  ! ************************************************************************************************
  ! public subroutine allocLocal: allocate space for local data structures
diff --git a/build/source/engine/ffile_info.f90 b/build/source/engine/ffile_info.f90
index dd1dab4..1dcaccf 100755
--- a/build/source/engine/ffile_info.f90
+++ b/build/source/engine/ffile_info.f90
@@ -41,7 +41,6 @@ subroutine ffile_info(indxGRU,forcFileInfo,numFiles,err,message)
   USE summaActors_FileManager,only:SETTINGS_PATH            ! path for metadata files
   USE summaActors_FileManager,only:FORCING_PATH             ! path for forcing files
   USE summaActors_FileManager,only:FORCING_FILELIST         ! list of model forcing files
-  USE summaActors_FileManager,only:FORCING_FREQ
   USE summaActors_FileManager,only:FORCING_START
   USE globalData,only:data_step
   USE globalData,only:forc_meta                      ! forcing metadata
diff --git a/build/source/interface/file_access_actor/cppwrap_fileAccess.f90 b/build/source/interface/file_access_actor/cppwrap_fileAccess.f90
index 8173c57..0c53413 100644
--- a/build/source/interface/file_access_actor/cppwrap_fileAccess.f90
+++ b/build/source/interface/file_access_actor/cppwrap_fileAccess.f90
@@ -55,7 +55,6 @@ subroutine mDecisions_C(num_steps,err) bind(C, name='mDecisions_C')
   integer(c_int),intent(inout)        :: num_steps
   integer(c_int),intent(inout)        :: err                ! Error Code
   ! local variables
-  integer(i4b)                        :: iStruct
   character(len=256)                  :: message            ! error message 
   character(LEN=256)                  :: cmessage           ! error message of downwind routine
 
@@ -199,12 +198,8 @@ subroutine Create_Output_File(&
   type(var_i),pointer                  :: ncid              ! ncid of the output file
   character(LEN=256)                   :: startGRUString    ! String Variable to convert startGRU
   character(LEN=256)                   :: numGRUString      ! String Varaible to convert numGRU
-  character(LEN=256)                   :: message
   character(LEN=256)                   :: cmessage
   integer(i4b)                         :: iGRU
-  integer(i4b)                         :: iStruct
-  integer(i4b)                         :: iStep
-  integer(i4b)                         :: iFreq
 
   call c_f_pointer(handle_ncid, ncid)
 
@@ -289,25 +284,17 @@ subroutine FileAccessActor_WriteOutput(&
                                 indxGRU,          & ! index of GRU we are currently writing for
                                 indxHRU,          & ! index of HRU we are currently writing for
                                 err) bind(C, name="FileAccessActor_WriteOutput")
-  USE globalData,only:fileout
-  USE summaActors_FileManager,only:OUTPUT_PATH,OUTPUT_PREFIX         ! define output file
-  USE def_output_module,only:def_output                       ! module to define model output
   USE globalData,only:gru_struc
   USE var_lookup,only:maxVarFreq                               ! # of available output frequencies
-  USE writeOutput_module,only:writeParm,writeBasin,writeTime,writeData
+  USE writeOutput_module,only:writeBasin,writeTime,writeData
   USE globalData,only:structInfo
   USE globalData,only:outputStructure
-  USE globalData,only:attr_meta                 ! attributes metadata structure
-  USE globalData,only:type_meta                 ! veg/soil type metadata structure
-  USE globalData,only:mpar_meta                 ! local parameter metadata structure
-  USE globalData,only:bpar_meta                 ! basin parameter metadata structure
   USE var_lookup,only:iLookFreq                 ! named variables for the frequency structure
   USE globalData,only:bvarChild_map             ! index of the child data structure: stats bvar
   USE netcdf_util_module,only:nc_file_close 
   USE netcdf_util_module,only:nc_file_open 
 
   USE globalData,only:outputTimeStep
-  USE globalData,only:finalizeStats
   USE netcdf
 
   implicit none
@@ -320,11 +307,8 @@ subroutine FileAccessActor_WriteOutput(&
   
   ! local variables 
   type(var_i),pointer                  :: ncid
-  character(LEN=256)                   :: startGRUString
-  character(LEN=256)                   :: numGRUString
   character(LEN=256)                   :: message
   character(LEN=256)                   :: cmessage
-  integer(i4b)                         :: iGRU
   integer(i4b)                         :: iStruct
   integer(i4b)                         :: iStep
   integer(i4b)                         :: iFreq
@@ -345,62 +329,46 @@ subroutine FileAccessActor_WriteOutput(&
     ! write time information
     call writeTime(ncid,outputTimeStep(indxGRU)%dat(:),iStep,time_meta, &
               outputStructure(1)%timeStruct(1)%gru(indxGRU)%hru(indxHRU)%var,err,cmessage)
-    
-    do iStruct=1,size(structInfo)
-      select case(trim(structInfo(iStruct)%structName))
-        case('forc')
-          call writeData(ncid,outputTimeStep(indxGRU)%dat(:),nHRUrun,maxLayers,indxGRU,iStep,forc_meta, &
-                        outputStructure(1)%forcStat(1),outputStructure(1)%forcStruct(1),'forc', &
-                        forcChild_map,outputStructure(1)%indxStruct(1),err,cmessage)
-        case('prog')
-          call writeData(ncid,outputTimeStep(indxGRU)%dat(:),nHRUrun,maxLayers,indxGRU,iStep,prog_meta, & 
-                        outputStructure(1)%progStat(1),outputStructure(1)%progStruct(1),'prog', &
-                        progChild_map,outputStructure(1)%indxStruct(1),err,cmessage)
-        case('diag')
-          call writeData(ncid,outputTimeStep(indxGRU)%dat(:),nHRUrun,maxLayers,indxGRU,iStep,diag_meta, &
-                        outputStructure(1)%diagStat(1),outputStructure(1)%diagStruct(1),'diag', &
-                        diagChild_map,outputStructure(1)%indxStruct(1),err,cmessage)
-        case('flux')
-          call writeData(ncid,outputTimeStep(indxGRU)%dat(:),nHRUrun,maxLayers,indxGRU,iStep,flux_meta, &
-                        outputStructure(1)%fluxStat(1),outputStructure(1)%fluxStruct(1),'flux', &
-                        fluxChild_map,outputStructure(1)%indxStruct(1),err,cmessage)
-        case('indx')
-          call writeData(ncid,outputTimeStep(indxGRU)%dat(:),nHRUrun,maxLayers,indxGRU,iStep,indx_meta, &
-                        outputStructure(1)%indxStat(1),outputStructure(1)%indxStruct(1),'indx', &
-                        indxChild_map,outputStructure(1)%indxStruct(1),err,cmessage)
-      end select
-      if(err/=0)then; message=trim(message)//trim(cmessage)//'['//trim(structInfo(iStruct)%structName)//']'; return; endif
-    end do  ! (looping through structures)
-    do iFreq = 1,maxvarFreq
-      if(outputStructure(1)%finalizeStats(1)%gru(indxGRU)%hru(1)%tim(iStep)%dat(iFreq)) outputTimeStep(indxGRU)%dat(iFreq) = outputTimeStep(indxGRU)%dat(iFreq) + 1
-    end do ! ifreq
   end do ! istep
+  
+  do iStruct=1,size(structInfo)
+    select case(trim(structInfo(iStruct)%structName))
+      case('forc')
+        call writeData(ncid,outputTimeStep(indxGRU)%dat(:),nHRUrun,maxLayers,indxGRU,nSteps,forc_meta, &
+                      outputStructure(1)%forcStat(1),outputStructure(1)%forcStruct(1),'forc', &
+                      forcChild_map,outputStructure(1)%indxStruct(1),err,cmessage)
+      case('prog')
+        call writeData(ncid,outputTimeStep(indxGRU)%dat(:),nHRUrun,maxLayers,indxGRU,nSteps,prog_meta, & 
+                      outputStructure(1)%progStat(1),outputStructure(1)%progStruct(1),'prog', &
+                      progChild_map,outputStructure(1)%indxStruct(1),err,cmessage)
+      case('diag')
+        call writeData(ncid,outputTimeStep(indxGRU)%dat(:),nHRUrun,maxLayers,indxGRU,nSteps,diag_meta, &
+                      outputStructure(1)%diagStat(1),outputStructure(1)%diagStruct(1),'diag', &
+                      diagChild_map,outputStructure(1)%indxStruct(1),err,cmessage)
+      case('flux')
+        call writeData(ncid,outputTimeStep(indxGRU)%dat(:),nHRUrun,maxLayers,indxGRU,nSteps,flux_meta, &
+                      outputStructure(1)%fluxStat(1),outputStructure(1)%fluxStruct(1),'flux', &
+                      fluxChild_map,outputStructure(1)%indxStruct(1),err,cmessage)
+      case('indx')
+        call writeData(ncid,outputTimeStep(indxGRU)%dat(:),nHRUrun,maxLayers,indxGRU,nSteps,indx_meta, &
+                      outputStructure(1)%indxStat(1),outputStructure(1)%indxStruct(1),'indx', &
+                      indxChild_map,outputStructure(1)%indxStruct(1),err,cmessage)
+    end select
+    if(err/=0)then; message=trim(message)//trim(cmessage)//'['//trim(structInfo(iStruct)%structName)//']'; return; endif
+  end do  ! (looping through structures)
+  ! do iFreq = 1,maxvarFreq
+  !   if(outputStructure(1)%finalizeStats(1)%gru(indxGRU)%hru(1)%tim(iStep)%dat(iFreq)) outputTimeStep(indxGRU)%dat(iFreq) = outputTimeStep(indxGRU)%dat(iFreq) + 1
+  ! end do ! ifreq
+
 end subroutine
 
 subroutine FileAccessActor_DeallocateStructures(handle_forcFileInfo, handle_ncid) bind(C,name="FileAccessActor_DeallocateStructures")
-  USE globalData,only:forcingDataStruct     
   USE netcdf_util_module,only:nc_file_close 
+  USE globalData,only:forcingDataStruct     
   USE globalData,only:structInfo                              ! information on the data structures
   USE globalData,only:vecTime
-  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:averageFlux_meta                        ! metadata for time-step average fluxes
-  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 var_lookup,only:childFLUX_MEAN                          ! look-up values for timestep-average model fluxes
-  USE globalData,only:gru_struc                               ! gru->hru mapping structure
-  USE globalData,only:index_map  
   USE globalData,only:outputTimeStep
   USE summaActors_deallocateOuptutStruct,only:deallocateOutputStruc
-  USE globalData,only:startTime,finshTime,refTime,oldTime
   implicit none
   type(c_ptr),intent(in), value        :: handle_forcFileInfo
   type(c_ptr),intent(in), value        :: handle_ncid
diff --git a/build/source/interface/job_actor/cppwrap_job.f90 b/build/source/interface/job_actor/cppwrap_job.f90
index fdb62f7..8422764 100644
--- a/build/source/interface/job_actor/cppwrap_job.f90
+++ b/build/source/interface/job_actor/cppwrap_job.f90
@@ -154,7 +154,7 @@ subroutine cleanUpJobActor(err) bind(C, name='cleanUpJobActor')
 
   implicit none
   integer(c_int), intent(inout)     :: err
-
+  err = 0
 
   ! Deallocate Time Varaibles
   deallocate(startTime%var);
diff --git a/build/source/netcdf/writeOutput.f90 b/build/source/netcdf/writeOutput.f90
index 363a63c..471c892 100644
--- a/build/source/netcdf/writeOutput.f90
+++ b/build/source/netcdf/writeOutput.f90
@@ -149,7 +149,7 @@ end subroutine writeParm
     ! **************************************************************************************
     ! public subroutine writeData: write model time-dependent data
     ! **************************************************************************************
-subroutine writeData(ncid,outputTimestep,nHRUrun,maxLayers,iGRU,iStep, & 
+subroutine writeData(ncid,outputTimestep,nHRUrun,maxLayers,iGRU,nSteps, & 
             meta,stat,dat,structName,map,indx,err,message)
 USE data_types,only:var_info                       ! metadata type
 USE var_lookup,only:maxVarStat                     ! index into stats structure
@@ -168,13 +168,13 @@ integer(i4b)  ,intent(inout)     :: outputTimestep(:) ! output time step
 integer(i4b)  ,intent(in)        :: nHRUrun           ! number of HRUs in the run domain
 integer(i4b)  ,intent(in)        :: maxLayers         ! maximum number of layers
 integer(i4b)  ,intent(in)        :: iGRU
-integer(i4b)  ,intent(in)        :: iStep             ! number of timeSteps
+integer(i4b)  ,intent(in)        :: nSteps             ! number of timeSteps
 type(var_info),intent(in)        :: meta(:)           ! meta data
 class(*)      ,intent(in)        :: stat              ! stats data
 class(*)      ,intent(in)        :: dat               ! timestep data
 character(*)  ,intent(in)        :: structName
 integer(i4b)  ,intent(in)        :: map(:)            ! map into stats child struct
-type(gru_hru_time_intVec) ,intent(in) :: indx              ! index data
+type(gru_hru_time_intVec) ,intent(in) :: indx         ! index data
 integer(i4b)  ,intent(out)       :: err               ! error code
 character(*)  ,intent(out)       :: message           ! error message
 ! local variables
@@ -189,13 +189,16 @@ integer(i4b)                     :: nLayers           ! total number of layers
 ! output arrays
 integer(i4b)                     :: datLength         ! length of each data vector
 integer(i4b)                     :: maxLength         ! maximum length of each data vector
-real(rkind)                      :: timeVal           ! timeVal to copy
-real(rkind)                      :: realVec(nHRUrun)  ! real vector for all HRUs in the run domain
-real(rkind)                      :: realArray(nHRUrun,maxLayers+1)  ! real array for all HRUs in the run domain
-integer(i4b)                     :: intArray(nHRUrun,maxLayers+1)   ! integer array for all HRUs in the run domain
+real(rkind)                      :: timeVec(nSteps)   ! timeVal to copy
+real(rkind)                      :: realVec(nSteps)   ! real vector for all HRUs in the run domain
+real(rkind)                      :: realArray(nSteps,maxLayers+1)  ! real array for all HRUs in the run domain
+integer(i4b)                     :: intArray(nSteps,maxLayers+1)   ! integer array for all HRUs in the run domain
 integer(i4b)                     :: dataType          ! type of data
 integer(i4b),parameter           :: ixInteger=1001    ! named variable for integer
 integer(i4b),parameter           :: ixReal=1002       ! named variable for real
+integer(i4b)                     :: stepCounter     ! counter to know how much data we have to write
+integer(i4b)                     :: iStep
+integer(i4b)                     :: outputTimeStepUpdateVal(maxVarFreq)
 ! initialize error control
 err=0;message="writeData/"
 ! loop through output frequencies
@@ -203,106 +206,136 @@ do iFreq=1,maxvarFreq
   ! skip frequencies that are not needed
   if(.not.outFreq(iFreq)) cycle
 
-  ! check that we have finalized statistics for a given frequency
-  if(.not.outputStructure(1)%finalizeStats(1)%gru(iGRU)%hru(1)%tim(iStep)%dat(iFreq)) cycle
-
   ! loop through model variables
   do iVar = 1,size(meta)
-    
-    ! handle time first
-    if (meta(iVar)%varName=='time')then
-      ! get variable index
-      err = nf90_inq_varid(ncid%var(iFreq),trim(meta(iVar)%varName),ncVarID)
-      call netcdf_err(err,message); if (err/=0) return
-      ! define HRUs and GRUs (only write once)
-      ! data bound write
-        if(structName == "forc")then
-          timeVal = outputStructure(1)%forcStruct(1)%gru(iGRU)%hru(1)%var(iVar)%tim(iStep)
-          err = nf90_put_var(ncid%var(iFreq),ncVarID,(/timeVal/),start=(/outputTimestep(iFreq)/),count=(/1/))
-          call netcdf_err(err,message); if (err/=0)then; print*, "err"; return; endif
-          cycle
-        end if
-    end if  ! id time
-
-    ! define the statistics index
-    iStat = meta(iVar)%statIndex(iFreq)
-    ! check that the variable is desired
-    if (iStat==integerMissing.or.trim(meta(iVar)%varName)=='unknown') cycle
-
-      do iHRU=1,gru_struc(iGRU)%hruCount
-        ! stats output: only scalar variable type
-        if(meta(iVar)%varType==iLookVarType%scalarv) then
-          select type(stat)
-            class is (gru_hru_time_doubleVec)
-              realVec(1) = stat%gru(iGRU)%hru(iHRU)%var(map(iVar))%tim(iStep)%dat(iFreq)
-              err = nf90_put_var(ncid%var(iFreq),meta(iVar)%ncVarID(iFreq),realVec,start=(/iGRU,outputTimestep(iFreq)/),count=(/1,1/))
-            class default; err=20; message=trim(message)//'stats must be scalarv and of type gru_hru_doubleVec'; return
-          end select  ! stat
-        
-        ! non-scalar variables: regular data structures
-        else
-
-          ! initialize the data vectors
-          select type (dat)
-            class is (gru_hru_time_doubleVec); realArray(:,:) = realMissing;    dataType=ixReal
-            class is (gru_hru_time_intVec);     intArray(:,:) = integerMissing; dataType=ixInteger
-            class default; err=20; message=trim(message)//'data must not be scalarv and either of type gru_hru_doubleVec or gru_hru_intVec'; return
-          end select
-
-
-          ! get the model layers
-          nSoil   = indx%gru(iGRU)%hru(iHRU)%var(iLookIndex%nSoil)%tim(iStep)%dat(1)
-          nSnow   = indx%gru(iGRU)%hru(iHRU)%var(iLookIndex%nSnow)%tim(iStep)%dat(1)
-          nLayers = indx%gru(iGRU)%hru(iHRU)%var(iLookIndex%nLayers)%tim(iStep)%dat(1)
-
-          ! get the length of each data vector
-          select case (meta(iVar)%varType)
-              case(iLookVarType%wLength); datLength = maxSpectral
-              case(iLookVarType%midToto); datLength = nLayers
-              case(iLookVarType%midSnow); datLength = nSnow
-              case(iLookVarType%midSoil); datLength = nSoil
-              case(iLookVarType%ifcToto); datLength = nLayers+1
-              case(iLookVarType%ifcSnow); datLength = nSnow+1
-              case(iLookVarType%ifcSoil); datLength = nSoil+1
-              case default; cycle
-          end select ! vartype
+    stepCounter = 0
+
+      if (meta(iVar)%varName=='time' .and. structName == 'forc')then
+        ! get variable index
+        err = nf90_inq_varid(ncid%var(iFreq),trim(meta(iVar)%varName),ncVarID)
+        call netcdf_err(err,message); if (err/=0) return
+        do iStep = 1, nSteps
+          ! check if we want this timestep
+          if(.not.outputStructure(1)%finalizeStats(1)%gru(iGRU)%hru(1)%tim(iStep)%dat(iFreq)) cycle
+          stepCounter = stepCounter+1
+          timeVec(stepCounter) = outputStructure(1)%forcStruct(1)%gru(iGRU)%hru(1)%var(iVar)%tim(iStep)
+        end do ! iStep
+        ! Write the values
+        err = nf90_put_var(ncid%var(iFreq),ncVarID,timeVec(1:stepCounter),start=(/outputTimestep(iFreq)/),count=(/stepCounter/))
+        call netcdf_err(err,message); if (err/=0)then; print*, "err"; return; endif
+        ! save the value of the number of steps to update outputTimestep at the end of the function
+        outputTimeStepUpdateVal(iFreq) = stepCounter
+        cycle
+      end if  ! id time
+
+      ! define the statistics index
+      iStat = meta(iVar)%statIndex(iFreq)
+      ! check that the variable is desired
+      if (iStat==integerMissing.or.trim(meta(iVar)%varName)=='unknown') cycle
 
-          ! get the data vectors
-          select type (dat)
-              class is (gru_hru_time_doubleVec); realArray(1,1:datLength) = dat%gru(iGRU)%hru(iHRU)%var(iVar)%tim(iStep)%dat(:)
-              class is (gru_hru_time_intVec);     intArray(1,1:datLength) = dat%gru(iGRU)%hru(iHRU)%var(iVar)%tim(iStep)%dat(:)
+        do iHRU=1,gru_struc(iGRU)%hruCount
+          ! stats output: only scalar variable type
+          if(meta(iVar)%varType==iLookVarType%scalarv) then
+            select type(stat)
+              class is (gru_hru_time_doubleVec)
+                do iStep = 1, nSteps
+                  if(.not.outputStructure(1)%finalizeStats(1)%gru(iGRU)%hru(1)%tim(iStep)%dat(iFreq)) cycle
+                  stepCounter = stepCounter + 1
+                  realVec(stepCounter) = stat%gru(iGRU)%hru(iHRU)%var(map(iVar))%tim(iStep)%dat(iFreq)
+                end do
+                err = nf90_put_var(ncid%var(iFreq),meta(iVar)%ncVarID(iFreq),realVec(1:stepCounter),start=(/iGRU,outputTimestep(iFreq)/),count=(/1,stepCounter/))
+                if (outputTimeStepUpdateVal(iFreq) /= stepCounter ) then
+                  print*, "ERROR Missmatch in Steps"
+                  return
+                endif
+              class default; err=20; message=trim(message)//'stats must be scalarv and of type gru_hru_doubleVec'; return
+            end select  ! stat
+          
+          ! non-scalar variables: regular data structures
+          else
+
+            ! initialize the data vectors
+            select type (dat)
+              class is (gru_hru_time_doubleVec); realArray(:,:) = realMissing;    dataType=ixReal
+              class is (gru_hru_time_intVec);     intArray(:,:) = integerMissing; dataType=ixInteger
               class default; err=20; message=trim(message)//'data must not be scalarv and either of type gru_hru_doubleVec or gru_hru_intVec'; return
-          end select
-
-          ! get the maximum length of each data vector
-          select case (meta(iVar)%varType)
-            case(iLookVarType%wLength); maxLength = maxSpectral
-            case(iLookVarType%midToto); maxLength = maxLayers
-            case(iLookVarType%midSnow); maxLength = maxLayers-nSoil
-            case(iLookVarType%midSoil); maxLength = nSoil
-            case(iLookVarType%ifcToto); maxLength = maxLayers+1
-            case(iLookVarType%ifcSnow); maxLength = (maxLayers-nSoil)+1
-            case(iLookVarType%ifcSoil); maxLength = nSoil+1
-            case default; cycle
-          end select ! vartype
-
-          ! write the data vectors
-          select case(dataType)
-            case(ixReal);    err = nf90_put_var(ncid%var(iFreq),meta(iVar)%ncVarID(iFreq),realArray,start=(/iGRU,1,outputTimestep(iFreq)/),count=(/1,maxLength,1/))
-            case(ixInteger); err = nf90_put_var(ncid%var(iFreq),meta(iVar)%ncVarID(iFreq),intArray,start=(/iGRU,1,outputTimestep(iFreq)/),count=(/1,maxLength,1/))
-          case default; err=20; message=trim(message)//'data must be of type integer or real'; return
-          end select ! data type
-
-        end if ! not scalarv
-      end do ! HRU Loop
-
-    ! process error code
-    if (err/=0) message=trim(message)//trim(meta(iVar)%varName)//'_'//trim(get_statName(iStat))
-    call netcdf_err(err,message); if (err/=0) return
+            end select
+
+
+            ! get the model layers
+            nSoil   = indx%gru(iGRU)%hru(iHRU)%var(iLookIndex%nSoil)%tim(iStep)%dat(1)
+            nSnow   = indx%gru(iGRU)%hru(iHRU)%var(iLookIndex%nSnow)%tim(iStep)%dat(1)
+            nLayers = indx%gru(iGRU)%hru(iHRU)%var(iLookIndex%nLayers)%tim(iStep)%dat(1)
+
+            ! get the length of each data vector
+            select case (meta(iVar)%varType)
+                case(iLookVarType%wLength); datLength = maxSpectral
+                case(iLookVarType%midToto); datLength = nLayers
+                case(iLookVarType%midSnow); datLength = nSnow
+                case(iLookVarType%midSoil); datLength = nSoil
+                case(iLookVarType%ifcToto); datLength = nLayers+1
+                case(iLookVarType%ifcSnow); datLength = nSnow+1
+                case(iLookVarType%ifcSoil); datLength = nSoil+1
+                case default; cycle
+            end select ! vartype
+
+            ! get the data vectors
+            select type (dat)
+                class is (gru_hru_time_doubleVec)
+                  do iStep = 1, nSteps
+                    if(.not.outputStructure(1)%finalizeStats(1)%gru(iGRU)%hru(1)%tim(iStep)%dat(iFreq)) cycle
+                    stepCounter = stepCounter + 1
+                    realArray(stepCounter,1:datLength) = dat%gru(iGRU)%hru(iHRU)%var(iVar)%tim(iStep)%dat(:)
+                  end do
+
+                class is (gru_hru_time_intVec)
+                  do iStep = 1, nSteps
+                    if(.not.outputStructure(1)%finalizeStats(1)%gru(iGRU)%hru(1)%tim(iStep)%dat(iFreq)) cycle
+                    stepCounter = stepCounter + 1
+                    intArray(stepCounter,1:datLength) = dat%gru(iGRU)%hru(iHRU)%var(iVar)%tim(iStep)%dat(:)
+                  end do
+                class default; err=20; message=trim(message)//'data must not be scalarv and either of type gru_hru_doubleVec or gru_hru_intVec'; return
+            end select
+
+            ! get the maximum length of each data vector
+            select case (meta(iVar)%varType)
+              case(iLookVarType%wLength); maxLength = maxSpectral
+              case(iLookVarType%midToto); maxLength = maxLayers
+              case(iLookVarType%midSnow); maxLength = maxLayers-nSoil
+              case(iLookVarType%midSoil); maxLength = nSoil
+              case(iLookVarType%ifcToto); maxLength = maxLayers+1
+              case(iLookVarType%ifcSnow); maxLength = (maxLayers-nSoil)+1
+              case(iLookVarType%ifcSoil); maxLength = nSoil+1
+              case default; cycle
+            end select ! vartype
+
+            ! write the data vectors
+            select case(dataType)
+              case(ixReal)
+                err = nf90_put_var(ncid%var(iFreq),meta(iVar)%ncVarID(iFreq),realArray(1:stepCounter,:),start=(/iGRU,1,outputTimestep(iFreq)/),count=(/1,maxLength,stepCounter/))
+                if (outputTimeStepUpdateVal(iFreq) /= stepCounter ) then
+                  print*, "ERROR Missmatch in Steps"
+                  return
+                endif
+              case(ixInteger)
+                err = nf90_put_var(ncid%var(iFreq),meta(iVar)%ncVarID(iFreq),intArray(1:stepCounter,:),start=(/iGRU,1,outputTimestep(iFreq)/),count=(/1,maxLength,stepCounter/))
+                if (outputTimeStepUpdateVal(iFreq) /= stepCounter ) then
+                  print*, "ERROR Missmatch in Steps"
+                  return
+                endif
+              case default; err=20; message=trim(message)//'data must be of type integer or real'; return
+            end select ! data type
+
+          end if ! not scalarv
+        end do ! HRU Loop
 
-  end do ! iVar
-end do ! iFreq
+      ! process error code
+      if (err/=0) message=trim(message)//trim(meta(iVar)%varName)//'_'//trim(get_statName(iStat))
+      call netcdf_err(err,message); if (err/=0) return
 
+    end do ! iVar
+    outputTimeStep(iFreq) = outputTimeStep(iFreq) + outputTimeStepUpdateVal(iFreq) 
+  end do ! iFreq
 
 end subroutine writeData
 
diff --git a/config/Summa_Actors_Settings.json b/config/Summa_Actors_Settings.json
index b20a2ee..75e7a3c 100644
--- a/config/Summa_Actors_Settings.json
+++ b/config/Summa_Actors_Settings.json
@@ -1,7 +1,7 @@
 {
     "SummaActor": {
         "OuputStrucureSize": 250,
-        "maxGRUPerJob": 1
+        "maxGRUPerJob": 500
     },
     
     "JobActor": {
-- 
GitLab