Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

calculate storage from Basin / profile #280

Merged
merged 4 commits into from
Jun 14, 2023
Merged

calculate storage from Basin / profile #280

merged 4 commits into from
Jun 14, 2023

Conversation

visr
Copy link
Member

@visr visr commented Jun 6, 2023

Fixes #225

This removes the need to provide the storage for a profile. We can calculate it ourselves by integrating over A(h) to get A(S) and h(S).

First this updates the test models to a correct storage in the profile. Then we calculate the profile and get the same results. Then we remove the storage from the schemas and docs.

I hoped this would help with #80 but based on the plot I added there it doesn't seem to. This does not yet add all the validation and extrapolation for lookup tables as described in #279, that can be done separately.

@visr visr mentioned this pull request Jun 6, 2023
@visr visr requested a review from SouthEndMusic June 7, 2023 14:20
@SouthEndMusic
Copy link
Collaborator

I'll try adding the proper interpolation.

@SouthEndMusic
Copy link
Collaborator

SouthEndMusic commented Jun 13, 2023

I suggest something like this for the interpolation:

function get_area_and_level(basin::Basin, state_idx::Int, storage::Float64)
   storage_discrete = basin.storage[state_idx]
   area_discrete = basin.storage[state_idx]
   level_discrete = basin.store[state_idx]
  
   # storage_idx: smallest index such that storage_discrete[storage_idx] >= storage
   storage_idx = searchsortedfirst(storage_discrete,storage)

   if storage_idx == 1 # If the lowest discrete_storage level 0, this can only happen if the storage is 0 since storage is never negative
      level = level_discrete[1]
      area = area_discrete[1]

   else
      if storage_idx == length(storage_discrete)+1
         # These values yield linear extrapolation of area(level) based on the last 2 values
         area_higher = area_discrete[end]
         area_lower = area_discrete[end-1]
         level_higher = level_discrete[end]
         level_lower = level_discrete[end-1]
         storage_lower = storage_discrete[end]
      else
         area_higher = area_discrete[storage_idx]
         area_lower = area_discrete[storage_idx-1]
         level_higher = level_discrete[storage_idx]
         level_lower = level_discrete[storage_idx-]
         storage_lower = storage_discrete[storage_idx-1]
        
      area_diff = area_higher - area_lower
      level_diff = level_higher - level_lower # This should never be 0, validate?

      if area_diff == 0
         # Constant area means linear interpolation of level
         area = area_lower

         storage_higher = storage_discrete[storage_idx]
         level = level_lower + level_diff*(storage-storage_lower)/(storage_higher-storage_lower)
         
      else
         area = sqrt(area_lower^2 + 2*(storage-storage_lower)*area_diff/level_diff)
         level = level_lower + level_diff*(area-area_lower)/area_diff
      end
   end

   return area, level
end

Here I assume that the discrete storage variables are normal vectors. Should we also require that the profile is given by at least 2 height values?

@SouthEndMusic SouthEndMusic merged commit fb54b00 into main Jun 14, 2023
@SouthEndMusic SouthEndMusic deleted the storage branch June 14, 2023 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

remove storage from Basin / profile
2 participants