Exemple #1
0
    def verifySettings(self):
        """
        Verify that all (mandatory) settings are set and consistent.
        """
        if self.type in [
                TYPE_UNIFORM, TYPE_BIUNIFORM, TYPE_UNIFORM_THETA,
                TYPE_BIUNIFORM_THETA, TYPE_CUSTOM
        ]:
            if self.nxi is None or self.nxi <= 0:
                raise DREAMException(
                    "XiGrid {}: Invalid value assigned to 'nxi': {}. Must be > 0."
                    .format(self.name, self.nxi))
        else:
            raise DREAMException(
                "XiGrid {}: Unrecognized grid type specified: {}.".format(
                    self.name, self.type))
        if self.type == TYPE_BIUNIFORM:
            if self.nxisep is not None and (self.nxisep <= 0
                                            or self.nxisep >= self.nxi):
                raise DREAMException(
                    "XiGrid {}: Invalid value assigned to 'nxisep': {}. Must be > 0 and < nxi."
                    .format(self.name, self.nxisep))
            if self.nxisep_frac is not None and (self.nxisep_frac <= 0
                                                 or self.nxisep_frac >= 1):
                raise DREAMException(
                    "XiGrid {}: Invalid value assigned to 'nxisep_frac': {}. Must be > 0 and < 1."
                    .format(self.name, self.nxisep))
            elif self.nxisep is None and self.nxisep_frac is None:
                raise DREAMException(
                    "XiGrid {}: Neither 'nxisep' nor 'nxisep_frac' have been specified."
                    .format(self.name))
            elif self.xisep is None or self.xisep <= -1 or self.xisep >= 1:
                raise DREAMException(
                    "XiGrid {}: Invalid value assigned to 'xisep': {}. Must be > -1 and < 1."
                    .format(self.name, self.xisep))

        elif self.type == TYPE_BIUNIFORM_THETA:
            if self.nthetasep is not None and (self.nthetasep <= 0
                                               or self.nthetasep >= self.nxi):
                raise DREAMException(
                    "XiGrid {}: Invalid value assigned to 'nthetasep': {}. Must be > 0 and < nxi."
                    .format(self.name, self.nthetasep))
            elif self.nthetasep_frac is not None and (
                    self.nthetasep_frac <= 0 or self.nthetasep_frac >= 1):
                raise DREAMException(
                    "XiGrid {}: Invalid value assigned to 'nthetasep_frac': {}. Must be > 0 and < 1."
                    .format(self.name, self.nthetasep_frac))
            elif self.nthetasep is None and self.nthetasep_frac is None:
                raise DREAMException(
                    "XiGrid {}: Neither 'nthetasep' nor 'nthetasep_frac' have been specified."
                    .format(self.name))
            elif self.thetasep is None or self.thetasep <= 0 or self.thetasep >= np.pi:
                raise DREAMException(
                    "XiGrid {}: Invalid value assigned to 'thetasep': {}. Must be > 0 and < pi."
                    .format(self.name, self.thetasep))
 def verifySettings(self):
     """
     Verify that all (mandatory) settings are set and consistent.
     """
     if self.type == TYPE_PXI:
         if self.enabled:
             self.pgrid.verifySettings()
             self.xigrid.verifySettings()
     elif self.type == TYPE_PPARPPERP:
         raise DREAMException("{}: No support implemented yet for 'ppar/pperp' grids.".format(self.name))
     else:
         raise DREAMException("{}: Unrecognized momentum grid type specified: {}.".format(self.name, self.type))
    def set(self, enabled=True, ttype=1, np=100, nxi=1, pmax=None):
        """
        Set all settings for this hot-tail grid.
        """
        self.enabled = enabled

        self.type = ttype
        if self.type == TYPE_PXI:
            self.pgrid = PGrid(self.name, np=np, pmax=pmax)
            self.xigrid = XiGrid(self.name, nxi=nxi)
        elif self.type == TYPE_PPARPPERP:
            raise DREAMException("No support implemented yet for 'ppar/pperp' grids.")
        else:
            raise DREAMException("Unrecognized momentum grid type specified: {}.".format(ttype))
    def setNp(self, np):
        if np <= 0:
            raise DREAMException("{}: Invalid value assigned to 'np': {}. Must be > 0.".format(self.name, np))
        elif np == 1:
            print("WARNING: {}: np = 1. Consider disabling the hot-tail grid altogether.".format(self.name))

        self.pgrid.setNp(np)
Exemple #5
0
    def setPmax(self, pmax):
        if pmax <= 0:
            raise DREAMException(
                "PGrid {}: Invalid value assigned to 'pmax': {}. Must be > 0.".
                format(self.name, pmax))

        self.pmax = float(pmax)
Exemple #6
0
    def fromdict(self, data):
        """
        Load settings from the given dictionary.
        """
        def scal(v):
            if type(v) == np.ndarray: return v[0]
            else: return v

        self.type = data['type']

        if 'wall_radius' in data:
            self.b = data['wall_radius']
            if type(self.b) == np.ndarray:
                self.b = float(self.b[0])
            else:
                self.b = float(self.b)

        if self.type == TYPE_CYLINDRICAL or self.type == TYPE_ANALYTIC_TOROIDAL or self.type == TYPE_NUMERICAL:
            self.a = data['a']
            self.nr = data['nr']
            self.r0 = data['r0']
            if 'r_f' in data:
                self.r_f = data['r_f']

        if self.type == TYPE_CYLINDRICAL:
            self.B0 = data['B0']
        elif self.type == TYPE_ANALYTIC_TOROIDAL:
            self.R0 = data['R0']
            self.ntheta = data['ntheta']

            self.Delta = data['Delta']['x']
            self.Delta_r = data['Delta']['r']
            self.delta = data['delta']['x']
            self.delta_r = data['delta']['r']
            self.GOverR0 = data['GOverR0']['x']
            self.GOverR0_r = data['GOverR0']['r']
            self.kappa = data['kappa']['x']
            self.kappa_r = data['kappa']['r']
            self.psi_p0 = data['psi_p0']['x']
            self.psi_p0_r = data['psi_p0']['r']
        elif self.type == TYPE_NUMERICAL:
            self.num_filename = data['filename']
            self.ntheta = data['ntheta']

            if 'fileformat' in data:
                self.num_fileformat = data['fileformat']
        else:
            raise DREAMException(
                "RadialGrid: Unrecognized grid type specified: {}.".format(
                    self.type))

        if 'ripple' in data:
            self.ripple_ncoils = int(scal(data['ripple']['ncoils']))
            self.ripple_deltacoils = float(scal(data['ripple']['deltacoils']))
            self.ripple_m = data['ripple']['m']
            self.ripple_n = data['ripple']['n']
            self.ripple_dB_B = data['ripple']['x']
            self.ripple_r = data['ripple']['r']
            self.ripple_t = data['ripple']['t']
Exemple #7
0
 def setType(self, ttype):
     """
     Set the type of p grid generator.
     """
     if ttype == TYPE_UNIFORM or ttype == TYPE_BIUNIFORM:
         self.type = ttype
     else:
         raise DREAMException(
             "PGrid {}: Unrecognized grid type specified: {}.".format(
                 self.name, self.type))
Exemple #8
0
    def setMajorRadius(self, R0):
        """
        (Analytic toroidal)
        Set the tokamak major radius.
        """
        if R0 <= 0:
            raise DREAMException(
                "RadialGrid: Invalid value assigned to major radius 'R0': {}".
                format(R0))

        self.R0 = float(R0)
Exemple #9
0
 def setType(self, ttype):
     """
     Set the type of radial grid to use.
     """
     types = [TYPE_CYLINDRICAL, TYPE_ANALYTIC_TOROIDAL, TYPE_NUMERICAL]
     if ttype in types:
         self.type = ttype
     else:
         raise DREAMException(
             "RadialGrid: Unrecognized grid type specified: {}.".format(
                 ttype))
Exemple #10
0
 def setBiuniform(self, psep, npsep=None, npsep_frac=None):
     self.type = TYPE_BIUNIFORM
     self.psep = psep
     if npsep is not None:
         self.npsep = npsep
         self.npsep_frac = None
     elif npsep_frac is not None:
         self.npsep = None
         self.npsep_frac = npsep_frac
     else:
         raise DREAMException(
             "PGrid biuniform {}: npsep or npsep_frac must be set.")
Exemple #11
0
    def setNtheta(self, ntheta):
        """
        (Analytic toroidal and numerical)
        Set the number of grid points to use for the poloidal grid on which bounce
        averages are calculated.
        """
        if ntheta <= 0:
            raise DREAMException(
                "RadialGrid: Invalid value assigned to 'ntheta': {}".format(
                    ntheta))

        self.ntheta = ntheta
    def fromdict(self, name, data):
        """
        Loads a momentum grid from the specified dictionary.
        """
        self.name    = name
        self.enabled = data['enabled']
        self.type    = data['type']

        if self.enabled:
            if self.type == TYPE_PXI:
                self.pgrid = PGrid(name, data=data)
                self.xigrid = XiGrid(name, data=data)
            elif self.type == TYPE_PPARPPERP:
                raise DREAMException("No support implemented yet for loading 'ppar/pperp' grids.")
            else:
                raise DREAMException("Unrecognized momentum grid type specified: {}.".format(self.type))
        else:
            # Set default grid
            self.set(enabled=False, ttype=self.type)

        self.verifySettings()
Exemple #13
0
 def setType(self, ttype):
     """
     Set the type of xi grid generator.
     """
     if ttype in [
             TYPE_UNIFORM, TYPE_BIUNIFORM, TYPE_UNIFORM_THETA,
             TYPE_BIUNIFORM_THETA
     ]:
         self.type = ttype
     else:
         raise DREAMException(
             "XiGrid {}: Unrecognized grid type specified: {}.".format(
                 self.name, self.type))
Exemple #14
0
    def verifySettingsShapeParameter(self, shapeparam):
        """
        Verify the settings of the named shape parameter.
        
        :param str shapeparam: Name of shape parameter to verify settings for.
        """
        v = getattr(self, shapeparam)
        r = getattr(self, shapeparam + '_r')

        if v is None or type(v) != np.ndarray:
            raise DREAMException(
                "RadialGrid: Invalid type of shape parameter '{}': {}.".format(
                    shapeparam, type(v)))
        elif r is None or type(r) != np.ndarray:
            raise DREAMException(
                "RadialGrid: Invalid type of radial grid for shape parameter '{}': {}."
                .format(shapeparam, type(r)))

        if v.shape != r.shape:
            raise DREAMException(
                "RadialGrid: Dimensions mismatch between shape parameter '{}' {} and its radial grid {}."
                .format(shapeparam, v.shape, r.shape))
Exemple #15
0
    def todict(self, verify=True):
        """
        Returns the settings in this object as a Python dictionary.
        """
        if verify:
            self.verifySettings()

        data = {'type': self.type}

        if self.type == TYPE_CYLINDRICAL or self.type == TYPE_ANALYTIC_TOROIDAL or self.type == TYPE_NUMERICAL:
            data['a'] = self.a
            data['nr'] = self.nr
            data['r0'] = self.r0
            data['wall_radius'] = self.b
            if self.r_f is not None:
                data['r_f'] = self.r_f

        if self.type == TYPE_CYLINDRICAL:
            data['B0'] = self.B0
        elif self.type == TYPE_ANALYTIC_TOROIDAL:
            data['R0'] = self.R0
            data['ntheta'] = self.ntheta

            data['Delta'] = {'x': self.Delta, 'r': self.Delta_r}
            data['delta'] = {'x': self.delta, 'r': self.delta_r}
            data['GOverR0'] = {'x': self.GOverR0, 'r': self.GOverR0_r}
            data['kappa'] = {'x': self.kappa, 'r': self.kappa_r}
            data['psi_p0'] = {'x': self.psi_p0, 'r': self.psi_p0_r}
        elif self.type == TYPE_NUMERICAL:
            data['filename'] = self.num_filename
            data['ntheta'] = self.ntheta

            if self.num_fileformat is not None:
                data['fileformat'] = self.num_fileformat
        else:
            raise DREAMException(
                "RadialGrid: Unrecognized grid type specified: {}.".format(
                    self.type))

        if self.ripple_ncoils > 0 or self.ripple_deltacoils > 0:
            data['ripple'] = {
                'ncoils': self.ripple_ncoils,
                'deltacoils': self.ripple_deltacoils,
                'm': self.ripple_m,
                'n': self.ripple_n,
                'x': self.ripple_dB_B,
                'r': self.ripple_r,
                't': self.ripple_t
            }

        return data
    def todict(self, verify=True):
        """
        Returns a Python dictionary containing all settings of
        this MomentumGrid object.
        """
        if verify:
            self.verifySettings()

        data = {
            'enabled': self.enabled,
            'type':    self.type
        }

        if not self.enabled: return data

        if self.type == TYPE_PXI:
            data = {**data, **(self.pgrid.todict()), **(self.xigrid.todict())}
        elif self.type == TYPE_PPARPPERP:
            raise DREAMException("No support implemented yet for saving 'ppar/pperp' grids.")
        else:
            raise DREAMException("Unrecognized momentum grid type specified: {}.".format(self.type))

        return data
Exemple #17
0
    def setNr(self, nr):
        """
        (Cylindrical, Analytic toroidal)
        Set the number of radial grid points to use.
        """
        if nr <= 0:
            raise DREAMException(
                "RadialGrid: Invalid value assigned to 'nr': {}".format(nr))
        if self.r_f is not None:
            print(
                "*WARNING* RadialGrid: Prescibing 'Nr' overrides the custom radial grid 'r_f'."
            )
            self.r_f = None

        self.nr = int(nr)
Exemple #18
0
    def setBiuniform(self,
                     xisep=None,
                     nxisep=None,
                     nxisep_frac=None,
                     thetasep=None,
                     nthetasep=None,
                     nthetasep_frac=None):

        if xisep is not None:
            self.type = TYPE_BIUNIFORM
            self.xisep = float(xisep)
            if nxisep is not None:
                self.nxisep = int(nxisep)
                self.nxisep_frac = None
            elif nxisep_frac is not None:
                self.nxisep = None
                self.nxisep_frac = nxisep_frac
            else:
                raise DREAMException(
                    "XiGrid biuniform {}: nxisep or nxisep_frac must be set.")
        elif thetasep is not None:
            self.type = TYPE_BIUNIFORM_THETA
            self.thetasep = float(thetasep)
            if nthetasep is not None:
                self.nthetasep = int(nthetasep)
                self.nthetasep_frac = None
            elif nthetasep_frac is not None:
                self.nthetasep = None
                self.nthetasep_frac = nthetasep_frac
            else:
                raise DREAMException(
                    "XiGrid biuniform theta {}: nthetasep or nthetasep_frac must be set."
                )
        else:
            raise DREAMException(
                "XiGrid biuniform  {}: thetasep or xisep must be set.")
Exemple #19
0
    def setMinorRadius(self, a):
        """
        (Cylindrical, Analytic toroidal)
        Set the plasma minor radius.
        """
        if a <= 0:
            raise DREAMException(
                "RadialGrid: Invalid value assigned to minor radius 'a': {}".
                format(a))
        if self.r_f is not None:
            print(
                "*WARNING* RadialGrid: Prescibing 'Minor radius' a overrides the custom radial grid 'r_f'."
            )
            self.r_f = None

        self.a = float(a)
Exemple #20
0
    def visualize(self, *args, ax=None, show=None, **kwargs):
        """
        Visualize the current magnetic field.

        :param int nr:     Number of flux surfaces to show.
        :param int ntheta: Number of poloidal angles per flux surface.
        """
        # Ensure that settings are valid...
        self.verifySettings()

        if self.type == TYPE_ANALYTIC_TOROIDAL:
            self.visualize_analytic(*args, ax=ax, show=show, **kwargs)
        elif self.type == TYPE_NUMERICAL:
            self.num_magneticfield.visualize(*args, ax=ax, show=show, **kwargs)
        else:
            raise DREAMException(
                "RadialGrid: Can only visualize the analytic toroidal magnetic field."
            )
Exemple #21
0
    def setShapeParameter(self, name, data, r=0.0):
        """
        (Analytic toroidal)
        Set a specific magnetic field shape parameter.
        """
        if name not in ['Delta', 'delta', 'GOverR0', 'kappa', 'psi_p0']:
            raise DREAMException(
                "RadialGrid: Invalid name of shape parameter specified: '{}'.".
                format(name))

        if type(data) in [float, int]:
            data = np.array([float(data)])
        elif type(data) == list:
            data = np.array(data)

        if type(r) in [float, int]:
            r = np.array([float(r)])
        elif type(r) == list:
            r = np.array(r)

        setattr(self, name, data)
        setattr(self, name + '_r', r)
Exemple #22
0
    def todict(self, verify=True):
        """
        Returns a Python dictionary containing all settings of
        this XiGrid object.
        """
        if verify:
            self.verifySettings()

        data = {
            'xigrid': self.type,
            'nxi': self.nxi,
        }
        if self.type == TYPE_BIUNIFORM:
            if self.nxisep is not None:
                data['nxisep'] = self.nxisep
            elif self.nxisep_frac is not None:
                #data['nxisep'] = int(round(self.nxi*self.nxisep_frac))
                data['nxisep_frac'] = self.nxisep_frac
            else:
                raise DREAMException(
                    "XiGrid {}: Neither 'nxisep' nor 'nxisep_frac' have been specified."
                    .format(self.name))

            data['xisep'] = self.xisep

        elif self.type == TYPE_BIUNIFORM_THETA:
            if self.nthetasep is not None:
                data['nxisep'] = self.nthetasep
            elif self.nthetasep_frac is not None:
                #data['nxisep'] = int(round(self.nxi*self.nthetasep_frac))
                data['nxisep_frac'] = self.nthetasep_frac

            data['xisep'] = self.thetasep
        elif self.type == TYPE_CUSTOM:
            data['xi_f'] = self.xi_f

        return data
Exemple #23
0
 def verifySettings(self):
     """
     Verify that all (mandatory) settings are set and consistent.
     """
     if self.type == TYPE_UNIFORM or self.type == TYPE_BIUNIFORM or self.type == TYPE_CUSTOM:
         if self.np is None or self.np <= 0:
             raise DREAMException(
                 "PGrid {}: Invalid value assigned to 'np': {}. Must be > 0."
                 .format(self.name, self.np))
         elif self.pmax is None or self.pmax <= 0:
             raise DREAMException(
                 "PGrid {}: Invalid value assigned to 'pmax': {}. Must be > 0."
                 .format(self.name, self.pmax))
     else:
         raise DREAMException(
             "PGrid {}: Unrecognized grid type specified: {}.".format(
                 self.name, self.type))
     if self.type == TYPE_BIUNIFORM:
         if self.npsep is not None and (self.npsep <= 0
                                        or self.npsep >= self.np):
             raise DREAMException(
                 "PGrid {}: Invalid value assigned to 'npsep': {}. Must be > 0 and < np."
                 .format(self.name, self.npsep))
         elif self.npsep_frac is not None and (self.npsep_frac <= 0
                                               or self.npsep_frac >= 1):
             raise DREAMException(
                 "PGrid {}: Invalid value assigned to 'npsep_frac': {}. Must be > 0 and < np."
                 .format(self.name, self.npsep_frac))
         elif self.npsep is None and self.npsep_frac is None:
             raise DREAMException(
                 "PGrid {}: Neither 'npsep' nor 'npsep_frac' have been set."
                 .format(self.name))
         elif self.psep is None or self.psep <= 0 or self.psep >= self.pmax:
             raise DREAMException(
                 "PGrid {}: Invalid value assigned to 'psep': {}. Must be > 0 and < pmax."
                 .format(self.name, self.psep))
    def setNxi(self, nxi):
        if nxi <= 0:
            raise DREAMException("{}: Invalid value assigned to 'nxi': {}. Must be > 0.".format(self.name, nxi))

        self.xigrid.setNxi(nxi)
Exemple #25
0
    def verifySettings(self):
        """
        Verfiy that the RadialGrid settings are consistent.
        """
        types = [TYPE_CYLINDRICAL, TYPE_ANALYTIC_TOROIDAL, TYPE_NUMERICAL]
        if self.type in types:
            if (self.a is None or self.a <= 0) and self.r_f is None:
                raise DREAMException(
                    "RadialGrid: Invalid value assigned to minor radius 'a': {}"
                    .format(self.a))
            elif (self.r0 is None or self.r0 < 0) and self.r_f is None:
                raise DREAMException(
                    "RadialGrid: Invalid value assigned to innermost simulated radius 'r0': {}"
                    .format(self.r0))
            elif self.b is None or self.b < self.a:
                raise DREAMException(
                    "RadialGrid: Invalid value assigned to wall radius 'b' (must be explicitly set to >= 'a' using 'setWallRadius'): "
                    .format(self.b))
            if self.r0 >= self.a and self.r_f is None:
                raise DREAMException(
                    "RadialGrid: 'r0' must be strictly less than 'a'.")
            if self.nr <= 0 and self.r_f is None:
                raise DREAMException(
                    "RadialGrid: Invalid value assigned 'nr': {}. Must be > 0."
                    .format(self.nr))
            if not np.isscalar(self.b):
                raise DREAMException(
                    "RadialGrid: The specified wall radius is not a scalar: {}."
                    .format(self.b))

        if self.type == TYPE_CYLINDRICAL:
            if self.B0 is None or self.B0 <= 0:
                raise DREAMException(
                    "RadialGrid: Invalid value assigned to 'B0': {}".format(
                        self.B0))
        elif self.type == TYPE_ANALYTIC_TOROIDAL:
            if self.R0 is None or self.R0 <= 0:
                raise DREAMException(
                    "RadialGrid: Invalid value assigned to tokamak major radius 'R0': {}"
                    .format(self.R0))
            elif self.ntheta <= 0:
                raise DREAMException(
                    "RadialGrid: Invalid value assigned to 'ntheta': {}. Must be > 0."
                    .format(self.ntheta))

            self.verifySettingsShapeParameter('Delta')
            self.verifySettingsShapeParameter('delta')
            self.verifySettingsShapeParameter('GOverR0')
            self.verifySettingsShapeParameter('kappa')
            self.verifySettingsShapeParameter('psi_p0')

            if np.size(self.Delta_r) > 1:
                if self.Delta_r[0] == 0 and self.Delta[0] != 0:
                    print(
                        "*WARNING* RadialGrid: Shape parameter 'Delta' (Shafranov shift) is non-zero at r=0, which is inconsistent (add Delta(0) to the major radius R0 instead)"
                    )
            elif self.Delta != 0:
                print(
                    "*WARNING* RadialGrid: Shape parameter 'Delta' (Shafranov shift) is assigned a constant non-zero value. It is recommended to add its value to the major radius R0 instead"
                )
            if np.size(self.delta_r) > 1:
                if self.delta_r[0] == 0 and self.delta[0] != 0:
                    print(
                        "*WARNING* RadialGrid: Shape parameter 'delta' (triangularity) is non-zero at r=0, which is inconsistent with Grad-Shafranov"
                    )
        elif self.type == TYPE_NUMERICAL:
            if type(self.num_filename) != str:
                raise DREAMException(
                    "RadialGrid: No numerical magnetic field file specified.")
            elif not pathlib.Path(self.num_filename).is_file():
                raise DREAMException(
                    "RadialGrid: The specified numerical magnetic field file does not exist."
                )
            elif self.ntheta <= 0:
                raise DREAMException(
                    "RadialGrid: Invalid value assigned to 'ntheta': {}. Must be > 0."
                    .format(self.ntheta))

            formats = [FILE_FORMAT_LUKE]
            if (self.num_fileformat is not None) and (self.num_fileformat
                                                      not in formats):
                raise DREAMException(
                    "RadialGrid: Unrecognized file format specified for numerical magnetic field: {}."
                    .format(self.num_fileformat))
        else:
            raise DREAMException(
                "RadialGrid: Unrecognized grid type specified: {}.".format(
                    self.type))

        # Ripple settings
        if self.ripple_ncoils > 0 or self.ripple_deltacoils > 0:
            if type(self.ripple_m) != np.ndarray or self.ripple_m.ndim != 1:
                raise EquationException(
                    "RadialGrid: Invalid type or shape of 'ripple_m'.")
            elif type(self.ripple_n) != np.ndarray or self.ripple_n.ndim != 1:
                raise EquationException(
                    "RadialGrid: Invalid type or shape of 'ripple_n'.")
            elif self.ripple_m.size != self.ripple_n.size:
                raise EquationException(
                    "RadialGrid: 'ripple_m' and 'ripple_n' must have the same number of elements."
                )
            elif type(self.ripple_r) != np.ndarray or self.ripple_r.ndim != 1:
                raise EquationException(
                    "RadialGrid: Invalid type or shape of 'ripple_r'.")
            elif type(self.ripple_t) != np.ndarray or self.ripple_t.ndim != 1:
                raise EquationException(
                    "RadialGrid: Invalid type or shape of 'ripple_t'.")
            elif type(self.ripple_dB_B
                      ) != np.ndarray or self.ripple_dB_B.shape != (
                          self.ripple_m.size, self.ripple_t.size,
                          self.ripple_r.size):
                raise EquationException(
                    "RadialGrid: Invalid type or shape of 'ripple_dB_B'.".
                    format(self.ripple_dB_B))