code: def get_fermi(self, c, T, rtol=0.01, nstep=50, step=0.1, precision=8):
          
          fermi = self.efermi  # initialize target fermi
          for _ in range(precision):
              frange = np.arange(-nstep, nstep + 1) * step + fermi
              calc_doping = np.array([self.get_doping(f, T) for f in frange])
              relative_error = abs(calc_doping / c - 1.0)
              fermi = frange[np.argmin(relative_error)]
              step /= 10.0
          if min(relative_error) > rtol:
              raise ValueError('Could not find fermi within {}% of c={}'.format(
                  rtol * 100, c))
          return fermi
docs: Finds the fermi level at which the doping concentration at the given
          temperature (T) is equal to c. A greedy algorithm is used where the
          relative error is minimized by calculating the doping at a grid which
          is continuously become finer.
  
          Args:
              c (float): doping concentration. c<0 represents n-type doping and
                  c>0 represents p-type doping (i.e. majority carriers are holes)
              T (float): absolute temperature in Kelvin
              rtol (float): maximum acceptable relative error
              nstep (int): number of steps checked around a given fermi level
              step (float): initial step in fermi level when searching
              precision (int): essentially the decimal places of calculated fermi
  
          Returns (float): the fermi level. Note that this is different from the
              default dos.efermi.