Ejemplo n.º 1
0
def make_snowpack(thickness, microstructure_model, density,
                  interface=None,
                  surface=None,
                  substrate=None,
                  atmosphere=None,
                  **kwargs):
    """
    build a multi-layered snowpack. Each parameter can be an array, list or a constant value.

    :param thickness: thicknesses of the layers in meter (from top to bottom). The last layer thickness can be "numpy.inf"
    for a semi-infinite layer.
    :param microstructure_model: microstructure_model to use (e.g. sticky_hard_spheres or independent_sphere or exponential).
    :param surface: type of surface interface, flat/fresnel is the default.  If surface and interface are both set,
    the interface must be a constant refering to all the "internal" interfaces.
    :param interface: type of interface, flat/fresnel is the default. It is usually a string for the interfaces
    without parameters (e.g. Flat or Transparent) or is created with :py:func:`~smrt.core.interface.make_interface` in more complex cases.
    Interface can be a constant or a list. In the latter case, its length must be the same as the number of layers,
    and interface[0] refers to the surface interface.
    :param density: densities of the layers.
    :param substrate: set the substrate of the snowpack. Another way to add a substrate is to use the + operator
    (e.g. snowpack + substrate).
    :param **kwargs: All the other parameters (temperature, microstructure parameters, emmodel, etc.) are given as optional arguments
    (e.g. temperature=[270, 250]).
    They are passed for each layer to the function :py:func:`~smrt.inputs.make_medium.make_snow_layer`.
    Thus, the documentation of this function is the reference. It describes precisely the available parameters.
    The microstructure parameter(s) depend on the microstructure_model used and is documented in each microstructure_model module.

    e.g.::

        sp = make_snowpack([1, 10], "exponential", density=[200,300], temperature=[240, 250], corr_length=[0.2e-3, 0.3e-3])

"""

    sp = Snowpack(substrate=substrate, atmosphere=atmosphere)

    if not isinstance(thickness, collections.abc.Iterable):
        raise SMRTError("The thickness argument must be iterable, that is, a list of numbers, numpy array or pandas Series or DataFrame.")

    lib.check_argument_size(density, len(thickness), "density")
    lib.check_argument_size(kwargs, len(thickness))

    if surface is not None and lib.is_sequence(interface):
        raise SMRTError("Setting both 'surface' and 'interface' arguments is ambiguous when inteface is a list or any sequence.")

    for i, dz in enumerate(thickness):
        layer = make_snow_layer(dz, lib.get(microstructure_model, i, "microstructure_model"),
                                density=lib.get(density, i, "density"),
                                **lib.get(kwargs, i))

        # add the interface
        linterface = lib.get(interface, i, "interface") if (i > 0) or (surface is None) else surface
        sp.append(layer, interface=make_interface(linterface))

    return sp
Ejemplo n.º 2
0
def make_interface(inst_class_or_modulename, broadcast=True, **kwargs):
    """return an instannce class corresponding to the interface model.

    This function import the correct module if necessary and if possible and return the class. It is used internally and should not be needed for normal usage.

    :param class_or_modulename: a class or name of the python module in smrt/interface
    """

    # import the module
    if inst_class_or_modulename is None:
        from ..interface.flat import Flat  # core should not depend on something defined in interface...
        interface_cls = Flat
    elif isinstance(inst_class_or_modulename, str):
        interface_cls = import_class("interface", inst_class_or_modulename)
    elif inspect.isclass(inst_class_or_modulename):
        interface_cls = inst_class_or_modulename
    elif hasattr(inst_class_or_modulename, "specular_reflection_matrix"):
        # we have an instance... good we can directly return it
        return inst_class_or_modulename
    else:
        raise SMRTError(
            "The interface must be either the name of a module in the smrt.interface directory, or a class that implements the interface behavior."
        )

    if broadcast and kwargs:
        l = [len(k) for k in kwargs.values() if lib.is_sequence(k)]
        if l:
            return [interface_cls(**lib.get(kwargs, i)) for i in range(max(l))]

    return interface_cls(**kwargs)  # try to create it without argument
Ejemplo n.º 3
0
def make_interface(inst_class_or_modulename, broadcast=True, **kwargs):
    """return an instance corresponding to the interface model with the provided arguments.

    This function imports the interface module if necessary and
    return an instance of the interface class with the provided arguments in **kwargs.

    :param inst_class_or_modulename: a class, and instance or the name of the python module in smrt/interface
    :param **kwargs: all the arguments required by the interface class
    """

    # import the module
    if inst_class_or_modulename is None:
        from ..interface.flat import Flat  # core should not depend on something defined in interface...
        interface_cls = Flat
    elif isinstance(inst_class_or_modulename, str):
        interface_cls = import_class("interface", inst_class_or_modulename)
    elif inspect.isclass(inst_class_or_modulename):
        interface_cls = inst_class_or_modulename
    elif hasattr(inst_class_or_modulename, "specular_reflection_matrix"):
        # we have an instance... good we can directly return it
        return inst_class_or_modulename
    else:
        raise SMRTError("The interface must be either the name of a module in the smrt.interface directory,"
                        " or a class that implements the interface behavior.")

    if broadcast and kwargs:
        lengths = [len(k) for k in kwargs.values() if lib.is_sequence(k)]
        if lengths:
            return [interface_cls(**lib.get(kwargs, i)) for i in range(max(lengths))]

    return interface_cls(**kwargs)  # create an instance of the interface class
Ejemplo n.º 4
0
def make_snowpack(thickness,
                  microstructure_model,
                  density,
                  interface=None,
                  substrate=None,
                  **kwargs):
    """
    build a multi-layered snowpack. Each parameter can be an array, list or a constant value.

    :param thickness: thicknesses of the layers in meter (from top to bottom). The last layer thickness can be "numpy.inf" for a semi-infinite layer.
    :param microstructure_model: microstructure_model to use (e.g. sticky_hard_spheres or independent_sphere or exponential).
    :param interface: type of interface, flat/fresnel is the default.
    :param density: densities of the layers.
    :param substrate: set the substrate of the snowpack. Another way to add a substrate is to use the + operator (e.g. snowpack + substrate).
    All the other parameters (temperature, microstructure parameters, emmodel, etc, etc) are given as optional arguments (e.g. temperature=[270, 250]).
    They are passed for each layer to the function :py:func:`~smrt.inputs.make_medium.make_snow_layer`. Thus, the documentation of this function is the reference. It describes precisely the available parameters.
    The microstructure parameter(s) depend on the microstructure_model used and is documented in each microstructure_model module.

    e.g.::

        sp = make_snowpack([1, 10], "exponential", density=[200,300], temperature=[240, 250], corr_length=[0.2e-3, 0.3e-3])

"""

    sp = Snowpack(substrate=substrate)

    if not isinstance(thickness, collections.Iterable):
        raise SMRTError(
            "The thickness argument must be iterable, that is, a list of numbers, numpy array or pandas Series or DataFrame."
        )

    lib.check_argument_size(density, len(thickness), "density")
    lib.check_argument_size(kwargs, len(thickness))

    for i, dz in enumerate(thickness):
        layer = make_snow_layer(dz,
                                lib.get(microstructure_model, i,
                                        "microstructure_model"),
                                density=lib.get(density, i, "density"),
                                **lib.get(kwargs, i))

        # add the interface
        sp.append(layer,
                  interface=make_interface(lib.get(interface, i, "interface")))

    return sp
Ejemplo n.º 5
0
def make_generic_stack(thickness,
                       temperature=273,
                       ks=0,
                       ka=0,
                       effective_permittivity=1,
                       interface=None,
                       substrate=None,
                       atmosphere=None):
    """
    build a multi-layered medium with prescribed scattering and absorption coefficients and effective permittivity. Must be used with presribed_kskaeps emmodel.

    :param thickness: thicknesses of the layers in meter (from top to bottom). The last layer thickness can be "numpy.inf" for a semi-infinite layer.
    :param temperature: temperature of layers in K
    :param ks: scattering coefficient of layers in m^-1
    :param ka: absorption coefficient of layers in m^-1
    :param interface: type of interface, flat/fresnel is the default

"""
    # TODO: Add an example
    #    e.g.::
    #
    #        sp = make_snowpack([1, 10], "exponential", density=[200,300], temperature=[240, 250], corr_length=[0.2e-3, 0.3e-3])
    #
    #"""

    sp = Snowpack(substrate=substrate, atmosphere=atmosphere)

    if not isinstance(thickness, collections.abc.Iterable):
        raise SMRTError(
            "The thickness argument must be iterable, that is, a list of numbers, numpy array or pandas Series or DataFrame."
        )

    for i, dz in enumerate(thickness):
        layer = make_generic_layer(dz,
                                   ks=lib.get(ks, i, "ks"),
                                   ka=lib.get(ka, i, "ka"),
                                   effective_permittivity=lib.get(
                                       effective_permittivity, i,
                                       "effective_permittivity"),
                                   temperature=lib.get(temperature, i,
                                                       "temperature"))

        sp.append(layer, lib.get(interface, i))

    return sp
Ejemplo n.º 6
0
def make_ice_column(ice_type,
                    thickness,
                    temperature,
                    microstructure_model,
                    brine_inclusion_shape='spheres',
                    salinity=0.,
                    brine_volume_fraction=None,
                    brine_permittivity_model=None,
                    ice_permittivity_model=None,
                    saline_ice_permittivity_model=None,
                    porosity=0,
                    density=None,
                    add_water_substrate=True,
                    interface=None,
                    substrate=None,
                    atmosphere=None,
                    **kwargs):
    """Build a multi-layered ice column. Each parameter can be an array, list or a constant value.

    ice_type variable determines the type of ice, which has a big impact on how the medium is modelled and the parameters:
    - First year ice is modelled as scattering brines embedded in a pure ice background
    - Multi year ice is modelled as scattering air bubbles in a saline ice background (but brines are non-scattering in this case).
    - Fresh ice is modelled as scattering air bubbles in a pure ice background (but brines are non-scattering in this case).

    First-year and multi-year ice is equivalent only if scattering and porosity are nulls. It is important to understand that in multi-year ice
    scattering by brine pockets is neglected because scattering is due to air bubbles and the emmodel implemented up to now are not able to deal with
    three-phase media.

    :param ice_type: Ice type. Options are "firstyear", "multiyear", "fresh"
    :param thickness: thicknesses of the layers in meter (from top to bottom). The last layer thickness can be "numpy.inf" for a semi-infinite layer.
    :param temperature: temperature of ice/water in K
    :param brine_inclusion_shape: assumption for shape of brine inclusions. So far, "spheres" or "random_needles" (i.e. elongated ellipsoidal inclusions), and "mix" (a mix of the two) are implemented, 
    :param salinity: salinity of ice/water in kg/kg (see PSU constant in smrt module). Default is 0. If neither salinity nor brine_volume_fraction are given, the ice column is considered to consist of fresh water ice.
    :param brine_volume_fraction: brine / liquid water fraction in sea ice, optional parameter, if not given brine volume fraction is calculated from temperature and salinity in ~.smrt.permittivity.brine_volume_fraction
    :param density: density of ice layer in kg m :sup:`-3`
    :param porosity: porosity of ice layer (0 - 1). Default is 0.
    :param add_water_substrate: Adds a substrate made of water below the ice column.
    Possible arguments are True (default) or False. If True looks for ice_type to determine if a saline or fresh water layer is added and/or uses the
    optional arguments 'water_temperature', 'water_salinity' of the water substrate.
    :param interface: type of interface, flat/fresnel is the default
    :param substrate: if add_water_substrate is False, the substrate can be prescribed with this argument.

    All the other optional arguments are passed for each layer to the function :py:func:`~smrt.inputs.make_medium.make_ice_layer`.
    The documentation of this function describes in detail the parameters used/required depending on ice_type.

"""

    # add a substrate underneath the ice (if wanted):
    if add_water_substrate:
        wp = water_parameters(ice_type, **kwargs)

        # create a permittivity_function that depends only on frequency and temperature by setting other arguments
        permittivity_model = lambda f, t: wp.water_permittivity_model(
            f, t, wp.water_salinity)
        substrate = Flat(temperature=wp.water_temperature,
                         permittivity_model=permittivity_model)
    else:
        substrate = substrate

    sp = Snowpack(substrate=substrate, atmosphere=atmosphere)

    n = len(thickness)
    for name in [
            "temperature", "salinity", "microstructure_model",
            "brine_inclusion_shape", "brine_volume_fraction", "porosity",
            "density", "brine_permittivity_model", "ice_permittivity_model",
            "saline_ice_permittivity_model", "interface", "kwargs"
    ]:
        lib.check_argument_size(locals()[name], n)

    for i, dz in enumerate(thickness):
        layer = make_ice_layer(
            ice_type,
            dz,
            temperature=lib.get(temperature, i),
            salinity=lib.get(salinity, i),
            microstructure_model=lib.get(microstructure_model, i),
            brine_inclusion_shape=lib.get(brine_inclusion_shape, i),
            brine_volume_fraction=lib.get(brine_volume_fraction, i),
            porosity=lib.get(porosity, i),
            density=lib.get(density, i),
            brine_permittivity_model=lib.get(brine_permittivity_model, i),
            ice_permittivity_model=lib.get(ice_permittivity_model, i),
            saline_ice_permittivity_model=lib.get(
                saline_ice_permittivity_model, i),
            **lib.get(kwargs, i))
        sp.append(layer, interface=make_interface(lib.get(interface, i)))

    return sp