diff --git a/gprMax/materials.py b/gprMax/materials.py index 712ab373..275e8c60 100644 --- a/gprMax/materials.py +++ b/gprMax/materials.py @@ -213,6 +213,373 @@ class DispersiveMaterial(Material): er -= ersum return er + + +class PeplinskiSoil: + """Soil objects that are characterised according to a mixing model + by Peplinski (http://dx.doi.org/10.1109/36.387598). + """ + + def __init__(self, ID, sandfraction, clayfraction, bulkdensity, + sandpartdensity, watervolfraction): + """ + Args: + ID: string for name of the soil. + sandfraction: float of sand fraction of the soil. + clayfraction: float of clay fraction of the soil. + bulkdensity: float of bulk density of the soil (g/cm3). + sandpartdensity: float of density of the sand particles in the + soil (g/cm3). + watervolfraction: tuple of floats of two numbers that specify a + range for the volumetric water fraction of the + soil. + """ + + self.ID = ID + self.S = sandfraction + self.C = clayfraction + self.rb = bulkdensity + self.rs = sandpartdensity + self.mu = watervolfraction + self.startmaterialnum = 0 #This is not used anymore and code that uses it can be removed + # store all of the material IDs in a list instead of storing only the first number of the material + # and assume that all must be sequentially numbered. This allows for more general mixing models + self.matID = [] + + def calculate_properties(self, nbins, G): + """Calculates the real and imaginery part of a Debye model for the soil + as well as a conductivity. It uses an approximation to a semi-empirical + model (http://dx.doi.org/10.1109/36.387598). + + Args: + nbins: int for number of bins to use to create the different materials. + G: FDTDGrid class describing a grid in a model. + """ + + # Debye model properties of water at 25C & zero salinity + T = 25 + S = 0 + watereri, waterer, watertau, watersig = calculate_water_properties(T, S) + f = 1.3e9 + w = 2 * np.pi * f + erealw = watereri + ((waterer - watereri) / (1 + (w * watertau)**2)) + + a = 0.65 # Experimentally derived constant + es = (1.01 + 0.44 * self.rs)**2 - 0.062 #  Relative permittivity of sand particles + b1 = 1.2748 - 0.519 * self.S - 0.152 * self.C + b2 = 1.33797 - 0.603 * self.S - 0.166 * self.C + + # For frequencies in the range 0.3GHz to 1.3GHz + sigf = 0.0467 + 0.2204 * self.rb - 0.411 * self.S + 0.6614 * self.C + # For frequencies in the range 1.4GHz to 18GHz + # sigf = -1.645 + 1.939 * self.rb - 2.25622 * self.S + 1.594 * self.C + + # Generate a set of bins based on the given volumetric water fraction + # values. Changed to make sure mid points are contained completely within the ranges. + # The limiting values of the ranges are not included in this. + + #mubins = np.linspace(self.mu[0], self.mu[1], nbins) + mubins = np.linspace(self.mu[0], self.mu[1], nbins + 1) + # Generate a range of volumetric water fraction values the mid-point of + # each bin to make materials from + #mumaterials = mubins + (mubins[1] - mubins[0]) / 2 + mumaterials = 0.5 * (mubins[1:nbins+1] + mubins[0:nbins]) + + # Create an iterator + muiter = np.nditer(mumaterials, flags=['c_index']) + while not muiter.finished: + # Real part for frequencies in the range 1.4GHz to 18GHz + er = (1 + (self.rb / self.rs) * ((es**a) - 1) + (muiter[0]**b1 * erealw**a) + - muiter[0]) ** (1 / a) + # Real part for frequencies in the range 0.3GHz to 1.3GHz (linear + # correction to 1.4-18GHz value) + er = 1.15 * er - 0.68 + + # Permittivity at infinite frequency + eri = er - (muiter[0]**(b2 / a) * DispersiveMaterial.waterdeltaer) + + # Effective conductivity + sig = muiter[0]**(b2 / a) * ((sigf * (self.rs - self.rb)) / (self.rs * muiter[0])) + + # Check to see if the material already exists before creating a new one + requiredID = '|{:.4f}|'.format(float(muiter[0])) + material = next((x for x in G.materials if x.ID == requiredID), None) + if muiter.index == 0: + if material: + self.startmaterialnum = material.numID + self.matID.append(material.numID) + else: + self.startmaterialnum = len(G.materials) + if not material: + m = DispersiveMaterial(len(G.materials), requiredID) + m.type = 'debye' + m.averagable = False + m.poles = 1 + if m.poles > config.get_model_config().materials['maxpoles']: + config.get_model_config().materials['maxpoles'] = m.poles + m.er = eri + m.se = sig + m.deltaer.append(er - eri) + m.tau.append(DispersiveMaterial.watertau) + G.materials.append(m) + self.matID.append(m.numID) + + muiter.iternext() + + +class RangeMaterial: + """Material defined with a given range of parameters to be used for fractal + spatial distributions. + """ + + def __init__(self, ID, er_range, sigma_range, mu_range, ro_range): + """ + Args: + ID: string for name of the material. + er_range: tuple of floats for relative permittivity range of the + material. + sigma_range: tuple of floats for electric conductivity range of the + material. + mu_range: tuple of floats for magnetic permeability of material. + ro_range: tuple of floats for magnetic loss range of material. + """ + + self.ID = ID + self.er = er_range + self.sig = sigma_range + self.mu = mu_range + self.ro = ro_range + self.startmaterialnum = 0 #This is not really needed anymore and code that uses it can be removed. + # store all of the material IDs in a list instead of storing only the first number of the material + # and assume that all must be sequentially numbered. This allows for more general mixing models + self.matID = [] + + def calculate_properties(self, nbins, G): + """Calculates the properties of the materials. + + Args: + nbins: int for number of bins to use to create the different materials. + G: FDTDGrid class describing a grid in a model. + """ + + # Generate a set of relative permittivity bins based on the given range + erbins = np.linspace(self.er[0], self.er[1], nbins+1) + + # Generate a range of relative permittivity values the mid-point of + # each bin to make materials from + #ermaterials = erbins + np.abs((erbins[1] - erbins[0])) / 2 + ermaterials = 0.5 * (erbins[1:nbins+1] + erbins[0:nbins]) + + # Generate a set of conductivity bins based on the given range + sigmabins = np.linspace(self.sig[0], self.sig[1], nbins + 1) + + # Generate a range of conductivity values the mid-point of + # each bin to make materials from + #sigmamaterials = sigmabins + (sigmabins[1] - sigmabins[0]) / 2 + sigmamaterials = 0.5 * (sigmabins[1:nbins+1] + sigmabins[0:nbins]) + + # Generate a set of magnetic permeability bins based on the given range + mubins = np.linspace(self.mu[0], self.mu[1], nbins + 1) + + # Generate a range of magnetic permeability values the mid-point of + # each bin to make materials from + #mumaterials = mubins + np.abs((mubins[1] - mubins[0])) / 2 + mumaterials = 0.5 * (mubins[1:nbins+1] + mubins[0:nbins]) + + # Generate a set of magnetic loss bins based on the given range + robins = np.linspace(self.ro[0], self.ro[1], nbins + 1) + + # Generate a range of magnetic loss values the mid-point of each bin to + # make materials from + #romaterials = robins + np.abs((robins[1] - robins[0])) / 2 + romaterials = 0.5 * (robins[1:nbins+1] + robins[0:nbins]) + + + # Iterate over the bins + for iter in np.arange(nbins): + # Relative permittivity + er = ermaterials[iter] + # Effective conductivity + se = sigmamaterials[iter] + # Magnetic permeability + mr = mumaterials[iter] + # Magnetic loss + sm = romaterials[iter] + + # Check to see if the material already exists before creating a new one + requiredID = f'|{float(er):.4f}+{float(se):.4f}+{float(mr):.4f}+{float(sm):.4f}|' + material = next((x for x in G.materials if x.ID == requiredID), None) + if iter == 0: + if material: + self.startmaterialnum = material.numID + self.matID.append(material.numID) + else: + self.startmaterialnum = len(G.materials) + if not material: + m = Material(len(G.materials), requiredID) + m.type = '' + m.averagable = True + m.er = er + m.se = se + m.mr = mr + m.sm = sm + G.materials.append(m) + self.matID.append(m.numID) + + +class ListMaterial: + """A list of predefined materials to be used for fractal spatial + distributions. This command does not create new materials but collects + them to be used in a stochastic distribution by a fractal box. + """ + + def __init__(self, ID, listofmaterials): + """ + Args: + ID: string for name of the material. + listofmaterials: A list of material IDs. + + """ + + self.ID = ID + self.mat = listofmaterials + self.startmaterialnum = 0 #This is not really needed anymore + # store all of the material IDs in a list instead of storing only the first number of the material + # and assume that all must be sequentially numbered. This allows for more general mixing models + # this is important here as this model assumes predefined materials. + self.matID = [] + + + def calculate_properties(self, nbins, G): + """Calculates the properties of the materials. + + Args: + nbins: int for number of bins to use to create the different materials. + G: FDTDGrid class describing a grid in a model. + """ + + # Iterate over the bins + for iter in np.arange(nbins): + #requiredID = '|{:}_in_{:}|'.format((self.mat[iter]),(self.ID)) + requiredID = self.mat[iter] + # Check if the material already exists before creating a new one + material = next((x for x in G.materials if x.ID == requiredID), None) + self.matID.append(material.numID) + + #if iter == 0: + # if material: + # self.startmaterialnum = material.numID + # else: + # self.startmaterialnum = len(G.materials) + + #if not material: + # temp = next((x for x in G.materials if x.ID == self.mat[iter]), None) + # m = copy.deepcopy(temp) #This needs to import copy in order to work + # m.ID = requiredID + # m.numID = len(G.materials) + # G.materials.append(m) + + if not material: + logger.exception(self.__str__() + f' material(s) {material} do not exist') + raise ValueError + + +def create_built_in_materials(G): + """Creates pre-defined (built-in) materials. + + Args: + G: FDTDGrid class describing a grid in a model. + """ + + m = Material(0, 'pec') + m.se = float('inf') + m.type = 'builtin' + m.averagable = False + G.materials.append(m) + + m = Material(1, 'free_space') + m.type = 'builtin' + G.materials.append(m) + + +def calculate_water_properties(T=25, S=0): + """Get extended Debye model properties for water. + + Args: + T: float for emperature of water (degrees centigrade). + S: float for salinity of water (part per thousand). + + Returns: + eri: float for relative permittivity at infinite frequency. + er: float for static relative permittivity. + tau: float for relaxation time (s). + sig: float for conductivity (Siemens/m). + """ + + # Properties of water from: https://doi.org/10.1109/JOE.1977.1145319 + eri = 4.9 + er = 88.045 - 0.4147 * T + 6.295e-4 * T**2 + 1.075e-5 * T**3 + tau = (1 / (2 * np.pi)) * (1.1109e-10 - 3.824e-12 * T + 6.938e-14 * T**2 - + 5.096e-16 * T**3) + + delta = 25 - T + beta = (2.033e-2 + 1.266e-4 * delta + 2.464e-6 * delta**2 - S * + (1.849e-5 - 2.551e-7 * delta + 2.551e-8 * delta**2)) + sig_25s = S * (0.182521 - 1.46192e-3 * S + 2.09324e-5 * S**2 - 1.28205e-7 * S**3) + sig = sig_25s * np.exp(-delta * beta) + + return eri, er, tau, sig + + +def create_water(G, T=25, S=0): + """Creates single-pole Debye model for water with specified temperature and + salinity. + + Args: + T: float for temperature of water (degrees centigrade). + S: float for salinity of water (part per thousand). + G: FDTDGrid class describing a grid in a model. + """ + + eri, er, tau, sig = calculate_water_properties(T, S) + + m = DispersiveMaterial(len(G.materials), 'water') + m.averagable = False + m.type = 'builtin, debye' + m.poles = 1 + m.er = eri + m.se = sig + m.deltaer.append(er - eri) + m.tau.append(tau) + G.materials.append(m) + if config.get_model_config().materials['maxpoles'] == 0: + config.get_model_config().materials['maxpoles'] = 1 + + +def create_grass(G): + """Creates single-pole Debye model for grass + + Args: + G: FDTDGrid class describing a grid in a model. + """ + + # Properties of grass from: http://dx.doi.org/10.1007/BF00902994 + er = 18.5087 + eri = 12.7174 + tau = 1.0793e-11 + sig = 0 + + m = DispersiveMaterial(len(G.materials), 'grass') + m.averagable = False + m.type = 'builtin, debye' + m.poles = 1 + m.er = eri + m.se = sig + m.deltaer.append(er - eri) + m.tau.append(tau) + G.materials.append(m) + if config.get_model_config().materials['maxpoles'] == 0: + config.get_model_config().materials['maxpoles'] = 1 def process_materials(G): @@ -283,392 +650,4 @@ def process_materials(G): materialtext.append(material.averagable) materialsdata.append(materialtext) - return materialsdata - - -class PeplinskiSoil: - """Soil objects that are characterised according to a mixing model - by Peplinski (http://dx.doi.org/10.1109/36.387598). - """ - - def __init__(self, ID, sandfraction, clayfraction, bulkdensity, - sandpartdensity, watervolfraction): - """ - Args: - ID: string for name of the soil. - sandfraction: float of sand fraction of the soil. - clayfraction: float of clay fraction of the soil. - bulkdensity: float of bulk density of the soil (g/cm3). - sandpartdensity: float of density of the sand particles in the - soil (g/cm3). - watervolfraction: tuple of floats of two numbers that specify a - range for the volumetric water fraction of the - soil. - """ - - self.ID = ID - self.S = sandfraction - self.C = clayfraction - self.rb = bulkdensity - self.rs = sandpartdensity - self.mu = watervolfraction - self.startmaterialnum = 0 #This is not used anymore and code that uses it can be removed - # store all of the material IDs in a list instead of storing only the first number of the material - # and assume that all must be sequentially numbered. This allows for more general mixing models - self.matID = [] - - def calculate_properties(self, nbins, G): - """Calculates the real and imaginery part of a Debye model for the soil - as well as a conductivity. It uses an approximation to a semi-empirical - model (http://dx.doi.org/10.1109/36.387598). - - Args: - nbins: int for number of bins to use to create the different materials. - G: FDTDGrid class describing a grid in a model. - """ - - # Debye model properties of water at 25C & zero salinity - T = 25 - S = 0 - watereri, waterer, watertau, watersig = calculate_water_properties(T, S) - f = 1.3e9 - w = 2 * np.pi * f - erealw = watereri + ((waterer - watereri) / (1 + (w * watertau)**2)) - - a = 0.65 # Experimentally derived constant - es = (1.01 + 0.44 * self.rs)**2 - 0.062 #  Relative permittivity of sand particles - b1 = 1.2748 - 0.519 * self.S - 0.152 * self.C - b2 = 1.33797 - 0.603 * self.S - 0.166 * self.C - - # For frequencies in the range 0.3GHz to 1.3GHz - sigf = 0.0467 + 0.2204 * self.rb - 0.411 * self.S + 0.6614 * self.C - # For frequencies in the range 1.4GHz to 18GHz - # sigf = -1.645 + 1.939 * self.rb - 2.25622 * self.S + 1.594 * self.C - - # Generate a set of bins based on the given volumetric water fraction - # values. Changed to make sure mid points are contained completely within the ranges. - # The limiting values of the ranges are not included in this. - - #mubins = np.linspace(self.mu[0], self.mu[1], nbins) - mubins = np.linspace(self.mu[0], self.mu[1], nbins+1) - # Generate a range of volumetric water fraction values the mid-point of - # each bin to make materials from - #mumaterials = mubins + (mubins[1] - mubins[0]) / 2 - mumaterials = 0.5*(mubins[1:nbins+1] + mubins[0:nbins]) - - - # Create an iterator - muiter = np.nditer(mumaterials, flags=['c_index']) - while not muiter.finished: - # Real part for frequencies in the range 1.4GHz to 18GHz - er = (1 + (self.rb / self.rs) * ((es**a) - 1) + (muiter[0]**b1 * erealw**a) - - muiter[0]) ** (1 / a) - # Real part for frequencies in the range 0.3GHz to 1.3GHz (linear - # correction to 1.4-18GHz value) - er = 1.15 * er - 0.68 - - # Permittivity at infinite frequency - eri = er - (muiter[0]**(b2 / a) * DispersiveMaterial.waterdeltaer) - - # Effective conductivity - sig = muiter[0]**(b2 / a) * ((sigf * (self.rs - self.rb)) / (self.rs * muiter[0])) - - # Check to see if the material already exists before creating a new one - requiredID = '|{:.4f}|'.format(float(muiter[0])) - material = next((x for x in G.materials if x.ID == requiredID), None) - if muiter.index == 0: - if material: - self.startmaterialnum = material.numID - self.matID.append(material.numID) - else: - self.startmaterialnum = len(G.materials) - if not material: - m = DispersiveMaterial(len(G.materials), requiredID) - m.type = 'debye' - m.averagable = False - m.poles = 1 - if m.poles > config.get_model_config().materials['maxpoles']: - config.get_model_config().materials['maxpoles'] = m.poles - m.er = eri - m.se = sig - m.deltaer.append(er - eri) - m.tau.append(DispersiveMaterial.watertau) - G.materials.append(m) - self.matID.append(m.numID) - - muiter.iternext() - - - -class RangeMaterial: - """Material defined with a given range of parameters to be used for - factal spatial disttibutions - """ - - def __init__(self, ID, er_range, sigma_range, mu_range, ro_range): - """ - Args: - ID: string for name of the material. - er_range: tuple of floats for relative permittivity range of the material. - sigma_range: tuple of floats for electric conductivity range of the material. - mu_range: tuple of floats for magnetic permeability of material. - ro_range: tuple of floats for magnetic loss range of material. - """ - - self.ID = ID - self.er = er_range - self.sig = sigma_range - self.mu = mu_range - self.ro = ro_range - self.startmaterialnum = 0 #This is not really needed anymore and code that uses it can be removed. - # store all of the material IDs in a list instead of storing only the first number of the material - # and assume that all must be sequentially numbered. This allows for more general mixing models - self.matID = [] - - - def calculate_properties(self, nbins, G): - """Calculates the properties of the materials. - - Args: - nbins: int for number of bins to use to create the different materials. - G: FDTDGrid class describing a grid in a model. - """ - - # Generate a set of relative permittivity bins based on the given range - erbins = np.linspace(self.er[0], self.er[1], nbins+1) - # Generate a range of relative permittivity values the mid-point of - # each bin to make materials from - #ermaterials = erbins + np.abs((erbins[1] - erbins[0])) / 2 - ermaterials = 0.5*(erbins[1:nbins+1] + erbins[0:nbins]) - - # Generate a set of conductivity bins based on the given range - sigmabins = np.linspace(self.sig[0], self.sig[1], nbins+1) - # Generate a range of conductivity values the mid-point of - # each bin to make materials from - #sigmamaterials = sigmabins + (sigmabins[1] - sigmabins[0]) / 2 - sigmamaterials = 0.5*(sigmabins[1:nbins+1] + sigmabins[0:nbins]) - - # Generate a set of magnetic permeability bins based on the given range - mubins = np.linspace(self.mu[0], self.mu[1], nbins+1) - # Generate a range of magnetic permeability values the mid-point of - # each bin to make materials from - #mumaterials = mubins + np.abs((mubins[1] - mubins[0])) / 2 - mumaterials = 0.5*(mubins[1:nbins+1] + mubins[0:nbins]) - - # Generate a set of magnetic loss bins based on the given range - robins = np.linspace(self.ro[0], self.ro[1], nbins+1) - # Generate a range of magnetic loss values the mid-point of - # each bin to make materials from - #romaterials = robins + np.abs((robins[1] - robins[0])) / 2 - romaterials = 0.5*(robins[1:nbins+1] + robins[0:nbins]) - - - # Iterate over the bins - for iter in np.arange(0,nbins): - - # Relative permittivity - er = ermaterials[iter] - - # Effective conductivity - se = sigmamaterials[iter] - - # magnetic permeability - mr = mumaterials[iter] - - # magnetic loss - sm = romaterials[iter] - - # Check to see if the material already exists before creating a new one - requiredID = '|{:.4f}+{:.4f}+{:.4f}+{:.4f}|'.format(float(er),float(se),float(mr),float(sm)) - material = next((x for x in G.materials if x.ID == requiredID), None) - if iter == 0: - if material: - self.startmaterialnum = material.numID - self.matID.append(material.numID) - else: - self.startmaterialnum = len(G.materials) - if not material: - m = Material(len(G.materials), requiredID) - m.type = '' - m.averagable = True - m.er = er - m.se = se - m.mr = mr - m.sm = sm - G.materials.append(m) - self.matID.append(m.numID) - - - -class ListMaterial: - """A list of predefined materials to be used for - factal spatial disttibutions. This command does not create new materials but collects them to be used in a - stochastic distribution by a fractal box. - """ - - def __init__(self, ID, listofmaterials): - """ - Args: - ID: string for name of the material. - listofmaterials: A list of material IDs. - - """ - - self.ID = ID - self.mat = listofmaterials - self.startmaterialnum = 0 #This is not really needed anymore - # store all of the material IDs in a list instead of storing only the first number of the material - # and assume that all must be sequentially numbered. This allows for more general mixing models - # this is important here as this model assumes predefined materials. - self.matID = [] - - - def calculate_properties(self, nbins, G): - """Calculates the properties of the materials. No Debye is used but name kept the same as used in other - class that needs Debye - - Args: - nbins: int for number of bins to use to create the different materials. - G: FDTDGrid class describing a grid in a model. - """ - - - # Iterate over the bins - for iter in np.arange(0,nbins): - - # Check to see if the material already exists before creating a new one - #requiredID = '|{:}_in_{:}|'.format((self.mat[iter]),(self.ID)) - requiredID = self.mat[iter] - material = next((x for x in G.materials if x.ID == requiredID), None) - self.matID.append(material.numID) - - #if iter == 0: - # if material: - # self.startmaterialnum = material.numID - # else: - # self.startmaterialnum = len(G.materials) - - #if not material: - # temp = next((x for x in G.materials if x.ID == self.mat[iter]), None) - # m = copy.deepcopy(temp) #This needs to import copy in order to work - # m.ID = requiredID - # m.numID = len(G.materials) - # G.materials.append(m) - - - if not material: - logger.exception(self.__str__() + f' material(s) {material} do not exist') - raise ValueError - - - - - -def create_built_in_materials(G): - """Creates pre-defined (built-in) materials. - - Args: - G: FDTDGrid class describing a grid in a model. - """ - - G.n_built_in_materials = len(G.materials) - - m = Material(0, 'pec') - m.se = float('inf') - m.type = 'builtin' - m.averagable = False - G.materials.append(m) - - m = Material(1, 'free_space') - m.type = 'builtin' - G.materials.append(m) - - G.n_built_in_materials = len(G.materials) - - -def calculate_water_properties(T=25, S=0): - """Get extended Debye model properties for water. - - Args: - T: float for emperature of water (degrees centigrade). - S: float for salinity of water (part per thousand). - - Returns: - eri: float for relative permittivity at infinite frequency. - er: float for static relative permittivity. - tau: float for relaxation time (s). - sig: float for conductivity (Siemens/m). - """ - - # Properties of water from: https://doi.org/10.1109/JOE.1977.1145319 - eri = 4.9 - er = 88.045 - 0.4147 * T + 6.295e-4 * T**2 + 1.075e-5 * T**3 - tau = (1 / (2 * np.pi)) * (1.1109e-10 - 3.824e-12 * T + 6.938e-14 * T**2 - - 5.096e-16 * T**3) - - delta = 25 - T - beta = (2.033e-2 + 1.266e-4 * delta + 2.464e-6 * delta**2 - S * - (1.849e-5 - 2.551e-7 * delta + 2.551e-8 * delta**2)) - sig_25s = S * (0.182521 - 1.46192e-3 * S + 2.09324e-5 * S**2 - 1.28205e-7 * S**3) - sig = sig_25s * np.exp(-delta * beta) - - return eri, er, tau, sig - - -def create_water(G, T=25, S=0): - """Creates single-pole Debye model for water with specified temperature and - salinity. - - Args: - T: float for temperature of water (degrees centigrade). - S: float for salinity of water (part per thousand). - G: FDTDGrid class describing a grid in a model. - """ - - eri, er, tau, sig = calculate_water_properties(T, S) - - G.n_built_in_materials = len(G.materials) - - m = DispersiveMaterial(len(G.materials), 'water') - m.averagable = False - m.type = 'builtin, debye' - m.poles = 1 - m.er = eri - m.se = sig - m.deltaer.append(er - eri) - m.tau.append(tau) - G.materials.append(m) - if config.get_model_config().materials['maxpoles'] == 0: - config.get_model_config().materials['maxpoles'] = 1 - - G.n_built_in_materials = len(G.materials) - - -def create_grass(G): - """Creates single-pole Debye model for grass - - Args: - G: FDTDGrid class describing a grid in a model. - """ - - # Properties of grass from: http://dx.doi.org/10.1007/BF00902994 - er = 18.5087 - eri = 12.7174 - tau = 1.0793e-11 - sig = 0 - - G.n_built_in_materials = len(G.materials) - - m = DispersiveMaterial(len(G.materials), 'grass') - m.averagable = False - m.type = 'builtin, debye' - m.poles = 1 - m.er = eri - m.se = sig - m.deltaer.append(er - eri) - m.tau.append(tau) - G.materials.append(m) - if config.get_model_config().materials['maxpoles'] == 0: - config.get_model_config().materials['maxpoles'] = 1 - - G.n_built_in_materials = len(G.materials) \ No newline at end of file + return materialsdata \ No newline at end of file diff --git a/gprMax/subgrids/user_objects.py b/gprMax/subgrids/user_objects.py index 1136ea01..1e700fc9 100644 --- a/gprMax/subgrids/user_objects.py +++ b/gprMax/subgrids/user_objects.py @@ -123,7 +123,7 @@ class SubGridBase(UserObjectMulti): self.subgrid = sg # Copy over built in materials - sg.materials = [copy(m) for m in grid.materials if m.numID in range(0, grid.n_built_in_materials + 1)] + sg.materials = [copy(m) for m in grid.materials if m.type == 'builtin'] # Don't mix and match different subgrid types for sg_made in grid.subgrids: