def get_fermi(self, c, T, rtol=0.01, nstep=50, step=0.1, precision=8):
        """
        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.
        """
        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