original_docstring: 
          Ensure mass conservation that may result from using OGGM's glacier dynamics model. This will be resolved on an 
          annual basis, and since the glacier dynamics are updated annually, the melt and runoff will be adjusted on a
          monthly-scale based on percent changes.
          
          OGGM's dynamic model limits mass loss based on the ice thickness and flux divergence. As a result, the actual
          volume change, glacier runoff, glacier melt, etc. may be less than that recorded by the mb_model. For PyGEM
          this is important because the glacier runoff and all parameters should be mass conserving.
          
          Note: other dynamical models (e.g., mass redistribution curves, volume-length-area scaling) are based on the 
          total volume change and therefore do not impose limitations like this because they do not estimate the flux
          divergence. As a result, they may systematically overestimate mass loss compared to OGGM's dynamical model.
          
docstring: Ensure mass conservation that may result from using OGGM's glacier dynamics model. This will be resolved on an
  annual basis, and since the glacier dynamics are updated annually, the melt and runoff will be adjusted on a
  monthly-scale based on percent changes.
  
  OGGM's dynamic model limits mass loss based on the ice thickness and flux divergence. As a result, the actual
  volume change, glacier runoff, glacier melt, etc. may be less than that recorded by the mb_model. For PyGEM
  this is important because the glacier runoff and all parameters should be mass conserving.
  
  other dynamical models  are based on the
  total volume change and therefore do not impose limitations like this because they do not estimate the flux
  divergence. As a result, they may systematically overestimate mass loss compared to OGGM's dynamical model.
docstring_tokens: Ensure mass conservation that may result from using OGGM ' s glacier dynamics model . This will be resolved on an annual basis and since the glacier dynamics are updated annually the melt and runoff will be adjusted on a monthly - scale based on percent changes . OGGM ' s dynamic model limits mass loss based on the ice thickness and flux divergence . As a result the actual volume change glacier runoff glacier melt etc . may be less than that recorded by the mb_model . For PyGEM this is important because the glacier runoff and all parameters should be mass conserving . other dynamical models are based on the total volume change and therefore do not impose limitations like this because they do not estimate the flux divergence . As a result they may systematically overestimate mass loss compared to OGGM ' s dynamical model .
code: def ensure_mass_conservation(self, diag):
          """
          Ensure mass conservation that may result from using OGGM's glacier dynamics model. This will be resolved on an 
          annual basis, and since the glacier dynamics are updated annually, the melt and runoff will be adjusted on a
          monthly-scale based on percent changes.
          
          OGGM's dynamic model limits mass loss based on the ice thickness and flux divergence. As a result, the actual
          volume change, glacier runoff, glacier melt, etc. may be less than that recorded by the mb_model. For PyGEM
          this is important because the glacier runoff and all parameters should be mass conserving.
          
          Note: other dynamical models (e.g., mass redistribution curves, volume-length-area scaling) are based on the 
          total volume change and therefore do not impose limitations like this because they do not estimate the flux
          divergence. As a result, they may systematically overestimate mass loss compared to OGGM's dynamical model.
          """
          # Compute difference between volume change 
          vol_change_annual_mbmod = (self.glac_wide_massbaltotal.reshape(-1,12).sum(1) * 
                                     pygem_prms.density_water / pygem_prms.density_ice)
          vol_change_annual_diag = diag.volume_m3.values[1:] - diag.volume_m3.values[:-1]
          vol_change_annual_dif = vol_change_annual_diag - vol_change_annual_mbmod
  
          # Reduce glacier melt by the difference
          vol_change_annual_mbmod_melt = (self.glac_wide_melt.reshape(-1,12).sum(1) * 
                                          pygem_prms.density_water / pygem_prms.density_ice)
          vol_change_annual_melt_reduction = np.zeros(vol_change_annual_mbmod.shape)
          chg_idx = vol_change_annual_mbmod.nonzero()[0]
          chg_idx_posmbmod = vol_change_annual_mbmod_melt.nonzero()[0]
          chg_idx_melt = list(set(chg_idx).intersection(chg_idx_posmbmod))
          
  #        print('change_idx:', chg_idx_melt)
  #        print('vol_change_annual_dif:', vol_change_annual_dif[chg_idx_melt])
  #        print('vol_change_annual_mbmod_melt:', vol_change_annual_mbmod_melt[chg_idx_melt])
          
          vol_change_annual_melt_reduction[chg_idx_melt] = (
                  1 - vol_change_annual_dif[chg_idx_melt] / vol_change_annual_mbmod_melt[chg_idx_melt])      
          
          vol_change_annual_melt_reduction_monthly = np.repeat(vol_change_annual_melt_reduction, 12)
          
          # Glacier-wide melt (m3 w.e.)
          self.glac_wide_melt = self.glac_wide_melt * vol_change_annual_melt_reduction_monthly
          
  #        # Reduce glacier accumulation by difference if there was no melt
  #        print('Do not need to do this.  Differences should be very small due to rounding error only')
  #        chg_idx_acc = np.setdiff1d(chg_idx,chg_idx_posmbmod)
  #        if len(chg_idx_acc) > 0:
  #            print('change_idx_acc:', chg_idx_acc)
  #            
  #            vol_change_annual_mbmod_acc = (self.glac_wide_acc.reshape(-1,12).sum(1) * 
  #                                           pygem_prms.density_water / pygem_prms.density_ice)
  #            
  #            print('glac_wide_massbaltotal:', self.glac_wide_massbaltotal.reshape(-1,12).sum(1) * 1000 / 900)
  #            print('vol_change_annual_mbmod all:', vol_change_annual_mbmod)
  #            print('vol_change_annual_mbmod:', vol_change_annual_mbmod[chg_idx_acc])
  #            print('vol_change_annual_diag:', vol_change_annual_diag[chg_idx_acc])
  #            print('vol_change_annual_dif:', vol_change_annual_dif[chg_idx_acc])
  #            print('vol_change_annual_mbmod_acc:', vol_change_annual_mbmod_acc[chg_idx_acc])
  #            
  #            vol_change_annual_acc_reduction = np.zeros(vol_change_annual_mbmod.shape)
  #            vol_change_annual_acc_reduction[chg_idx_acc] = (
  #                    vol_change_annual_dif[chg_idx_acc] / vol_change_annual_mbmod_acc[chg_idx_acc])
  #            
  #            print('vol_change_annual_acc_reduction:', vol_change_annual_acc_reduction[chg_idx_acc])
  #            
  #            vol_change_annual_acc_reduction_monthly = np.repeat(vol_change_annual_acc_reduction, 12)
  #            
  #            # Glacier-wide accumulation (m3 w.e.)
  #            self.glac_wide_acc = self.glac_wide_acc * vol_change_annual_acc_reduction_monthly
          
          # Glacier-wide total mass balance (m3 w.e.)
          if np.abs(self.glac_wide_frontalablation.sum()) > 0:
              print('\n\nCHECK IF FRONTAL ABLATION IS POSITIVE OR NEGATIVE - WHETHER ADD OR SUBTRACT BELOW HERE')
              assert True==False, 'Need to account for frontal ablation properly here'
          self.glac_wide_massbaltotal = (self.glac_wide_acc + self.glac_wide_refreeze - self.glac_wide_melt -
                                         self.glac_wide_frontalablation)
          
          # Glacier-wide runoff (m3)
          self.glac_wide_runoff = self.glac_wide_prec + self.glac_wide_melt - self.glac_wide_refreeze
          
          self.glac_wide_volume_change_ignored_annual = vol_change_annual_dif
code_tokens: def ensure_mass_conservation ( self , diag ) : vol_change_annual_mbmod = ( self . glac_wide_massbaltotal . reshape ( - 1 , 12 ) . sum ( 1 ) * pygem_prms . density_water / pygem_prms . density_ice ) vol_change_annual_diag = diag . volume_m3 . values [ 1 : ] - diag . volume_m3 . values [ : - 1 ] vol_change_annual_dif = vol_change_annual_diag - vol_change_annual_mbmod vol_change_annual_mbmod_melt = ( self . glac_wide_melt . reshape ( - 1 , 12 ) . sum ( 1 ) * pygem_prms . density_water / pygem_prms . density_ice ) vol_change_annual_melt_reduction = np . zeros ( vol_change_annual_mbmod . shape ) chg_idx = vol_change_annual_mbmod . nonzero ( ) [ 0 ] chg_idx_posmbmod = vol_change_annual_mbmod_melt . nonzero ( ) [ 0 ] chg_idx_melt = list ( set ( chg_idx ) . intersection ( chg_idx_posmbmod ) ) vol_change_annual_melt_reduction [ chg_idx_melt ] = ( 1 - vol_change_annual_dif [ chg_idx_melt ] / vol_change_annual_mbmod_melt [ chg_idx_melt ] ) vol_change_annual_melt_reduction_monthly = np . repeat ( vol_change_annual_melt_reduction , 12 ) self . glac_wide_melt = self . glac_wide_melt * vol_change_annual_melt_reduction_monthly if np . abs ( self . glac_wide_frontalablation . sum ( ) ) > 0 : print ( '\n\nCHECK IF FRONTAL ABLATION IS POSITIVE OR NEGATIVE - WHETHER ADD OR SUBTRACT BELOW HERE' ) assert True == False , 'Need to account for frontal ablation properly here' self . glac_wide_massbaltotal = ( self . glac_wide_acc + self . glac_wide_refreeze - self . glac_wide_melt - self . glac_wide_frontalablation ) self . glac_wide_runoff = self . glac_wide_prec + self . glac_wide_melt - self . glac_wide_refreeze self . glac_wide_volume_change_ignored_annual = vol_change_annual_dif
short_docstring: Ensure mass conservation that may result from using OGGM's glacier dynamics model.
short_docstring_tokens: Ensure mass conservation that may result from using OGGM ' s glacier dynamics model .
comment: """
          Ensure mass conservation that may result from using OGGM's glacier dynamics model. This will be resolved on an 
          annual basis, and since the glacier dynamics are updated annually, the melt and runoff will be adjusted on a
          monthly-scale based on percent changes.
          
          OGGM's dynamic model limits mass loss based on the ice thickness and flux divergence. As a result, the actual
          volume change, glacier runoff, glacier melt, etc. may be less than that recorded by the mb_model. For PyGEM
          this is important because the glacier runoff and all parameters should be mass conserving.
          
          Note: other dynamical models (e.g., mass redistribution curves, volume-length-area scaling) are based on the 
          total volume change and therefore do not impose limitations like this because they do not estimate the flux
          divergence. As a result, they may systematically overestimate mass loss compared to OGGM's dynamical model.
          """$SEP$# Compute difference between volume change $SEP$# Reduce glacier melt by the difference$SEP$#        print('change_idx:', chg_idx_melt)$SEP$#        print('vol_change_annual_dif:', vol_change_annual_dif[chg_idx_melt])$SEP$#        print('vol_change_annual_mbmod_melt:', vol_change_annual_mbmod_melt[chg_idx_melt])$SEP$# Glacier-wide melt (m3 w.e.)$SEP$#        # Reduce glacier accumulation by difference if there was no melt$SEP$#        print('Do not need to do this.  Differences should be very small due to rounding error only')$SEP$#        chg_idx_acc = np.setdiff1d(chg_idx,chg_idx_posmbmod)$SEP$#        if len(chg_idx_acc) > 0:$SEP$#            print('change_idx_acc:', chg_idx_acc)$SEP$#            $SEP$#            vol_change_annual_mbmod_acc = (self.glac_wide_acc.reshape(-1,12).sum(1) * $SEP$#                                           pygem_prms.density_water / pygem_prms.density_ice)$SEP$#            $SEP$#            print('glac_wide_massbaltotal:', self.glac_wide_massbaltotal.reshape(-1,12).sum(1) * 1000 / 900)$SEP$#            print('vol_change_annual_mbmod all:', vol_change_annual_mbmod)$SEP$#            print('vol_change_annual_mbmod:', vol_change_annual_mbmod[chg_idx_acc])$SEP$#            print('vol_change_annual_diag:', vol_change_annual_diag[chg_idx_acc])$SEP$#            print('vol_change_annual_dif:', vol_change_annual_dif[chg_idx_acc])$SEP$#            print('vol_change_annual_mbmod_acc:', vol_change_annual_mbmod_acc[chg_idx_acc])$SEP$#            $SEP$#            vol_change_annual_acc_reduction = np.zeros(vol_change_annual_mbmod.shape)$SEP$#            vol_change_annual_acc_reduction[chg_idx_acc] = ($SEP$#                    vol_change_annual_dif[chg_idx_acc] / vol_change_annual_mbmod_acc[chg_idx_acc])$SEP$#            $SEP$#            print('vol_change_annual_acc_reduction:', vol_change_annual_acc_reduction[chg_idx_acc])$SEP$#            $SEP$#            vol_change_annual_acc_reduction_monthly = np.repeat(vol_change_annual_acc_reduction, 12)$SEP$#            $SEP$#            # Glacier-wide accumulation (m3 w.e.)$SEP$#            self.glac_wide_acc = self.glac_wide_acc * vol_change_annual_acc_reduction_monthly$SEP$# Glacier-wide total mass balance (m3 w.e.)$SEP$# Glacier-wide runoff (m3)