<commit_before>import numpy as np
import properties
from scipy.constants import mu_0

from ...simulation import BaseSimulation
from ... import props
from ..frequency_domain.survey import Survey


class Simulation1DRecursive(BaseSimulation):
    """
    Simulation class for the 1D MT problem using recursive solution.

    This solution is defined with z +ve upward and a :math:`+i\\omega t`
    Fourier convention. First, let:

    .. math::
        \\alpha_i^2 = i\\omega\\mu_i\\sigma_i

    The complex impedance in layer :math:`i` is given by:

    .. math::
        Z_i = \\dfrac{\\alpha_i}{\\sigma_i} \\Bigg [
        \\dfrac{\\sigma_i Z_{i+1} - \\alpha_i tanh(\\alpha_i h_i)}
        {\\alpha_i - \\sigma_i Z_{i+1}tanh(\\alpha_i h_i)} \\Bigg ]

    where the complex impedance in the bottom half-space is given by:

    .. math::
        Z_N = - \\frac{\\alpha_N}{\\sigma_N}


    """

    sigma, sigmaMap, sigmaDeriv = props.Invertible("Electrical conductivity (S/m)")
    rho, rhoMap, rhoDeriv = props.Invertible("Electrical resistivity (Ohm m)")
    props.Reciprocal(sigma, rho)

    # Add layer thickness as invertible property
    thicknesses, thicknessesMap, thicknessesDeriv = props.Invertible(
        "thicknesses of the layers starting from the bottom of the mesh"
    )

    # Must be 1D survey object
    survey = properties.Instance("a frequency_domain survey", Survey, required=True)
    fix_Jmatrix = False

    # TODO: These should be moved to geoana
    def _get_recursive_impedances(self, frequencies, thicknesses, sigmas):
        """
        For a given layered Earth model, this returns the complex impedances
        at the surface for all frequencies.

        Parameters
        ----------
        frequencies : (n_freq, ) np.ndarray<commit_msg>remove properties from natural_source<commit_after>import numpy as np
from scipy.constants import mu_0

from ...simulation import BaseSimulation
from ... import props
from ...utils import validate_type
from ..frequency_domain.survey import Survey


class Simulation1DRecursive(BaseSimulation):
    """
    Simulation class for the 1D MT problem using recursive solution.

    This solution is defined with z +ve upward and a :math:`+i\\omega t`
    Fourier convention. First, let:

    .. math::
        \\alpha_i^2 = i\\omega\\mu_i\\sigma_i

    The complex impedance in layer :math:`i` is given by:

    .. math::
        Z_i = \\dfrac{\\alpha_i}{\\sigma_i} \\Bigg [
        \\dfrac{\\sigma_i Z_{i+1} - \\alpha_i tanh(\\alpha_i h_i)}
        {\\alpha_i - \\sigma_i Z_{i+1}tanh(\\alpha_i h_i)} \\Bigg ]

    where the complex impedance in the bottom half-space is given by:

    .. math::
        Z_N = - \\frac{\\alpha_N}{\\sigma_N}


    """

    sigma, sigmaMap, sigmaDeriv = props.Invertible("Electrical conductivity (S/m)")
    rho, rhoMap, rhoDeriv = props.Invertible("Electrical resistivity (Ohm m)")
    props.Reciprocal(sigma, rho)

    # Add layer thickness as invertible property
    thicknesses, thicknessesMap, thicknessesDeriv = props.Invertible(
        "thicknesses of the layers starting from the bottom of the mesh"
    )

    def __init__(self, survey=None, fix_Jmatrix=False, **kwargs):
        super().__init__(mesh=None, survey=survey, **kwargs)
        self.fix_Jmatrix = fix_Jmatrix

    @property
    def survey(self):
        """The simulations survey.

        Returns
        -------
        SimPEG.electromagnetics.frequency_domain.survey.Survey
        """
        if self._survey is None:
            raise AttributeError("Simulation must have a survey set")
        return self._survey

    @survey.setter
    def survey(self, value):
        if value is not None:
            value = validate_type("survey", value, Survey, cast=False)
        self._survey = value

    @property
    def fix_Jmatrix(self):
        """Whether to fix the sensitivity matrix.

        Returns
        -------
        bool
        """
        return self._fix_Jmatrix

    @fix_Jmatrix.setter
    def fix_Jmatrix(self, value):
        self._fix_Jmatrix = validate_type("fix_Jmatrix", value, bool)

    # TODO: These should be moved to geoana
    def _get_recursive_impedances(self, frequencies, thicknesses, sigmas):
        """
        For a given layered Earth model, this returns the complex impedances
        at the surface for all frequencies.

        Parameters
        ----------
        frequencies : (n_freq, ) np.ndarray
{'fraction_non_alphanumeric': 0.10970368694865415, 'fraction_numerical': 0.002940511196561864, 'mean_word_length': 2.563255439161966, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1367588', 'n_tokens_mistral': 1382, 'n_tokens_neox': 1306, 'n_words': 401}