diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 55dbe85..bac1be6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,3 +4,8 @@ updates: directory: "/" schedule: interval: "monthly" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 799cbed..b42d9ff 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -14,6 +14,6 @@ jobs: with: submodules: true - uses: astral-sh/setup-uv@v7 - - run: uv python install + - run: uv python install 3.13 - run: uv sync - run: uv run pre-commit run --all-files diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d1b6c7e..1fb8d0a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -41,7 +41,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} CIBW_BUILD: ${{ matrix.cibw_build || env.CIBW_BUILD }} - - uses: actions/upload-artifact@v6 + - uses: actions/upload-artifact@v7 with: name: wheels-${{ matrix.os }}-${{ matrix.cibw_archs }} path: ./wheelhouse/*.whl @@ -61,7 +61,7 @@ jobs: - name: Build sdist run: uv build --sdist - - uses: actions/upload-artifact@v6 + - uses: actions/upload-artifact@v7 with: name: sdist path: dist/*.tar.gz @@ -102,9 +102,6 @@ jobs: merge-multiple: true - uses: pypa/gh-action-pypi-publish@v1.13.0 - with: - user: __token__ - password: ${{ secrets.PYPI_API_TOKEN }} upload_testpypi: if: ${{ github.event.release.prerelease }} @@ -121,5 +118,3 @@ jobs: - uses: pypa/gh-action-pypi-publish@v1.13.0 with: repository-url: https://test.pypi.org/legacy/ - user: __token__ - password: ${{ secrets.TEST_PYPI_API_TOKEN }} diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index a5d7ead..78fb7a6 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -14,6 +14,7 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest, windows-11-arm] python: ["3.10", "3.11", "3.12", "3.13", "3.14"] runs-on: ${{ matrix.os }} + timeout-minutes: 30 steps: - uses: actions/checkout@v6 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3285d11..1ffdeb1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,6 +8,9 @@ repos: args: [--fix=lf] - id: end-of-file-fixer - id: trailing-whitespace + - id: check-yaml + - id: check-toml + - id: check-merge-conflict - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.15.1 diff --git a/NonlinearTMM/src/SecondOrderNLTMM.pyx b/NonlinearTMM/src/SecondOrderNLTMM.pyx index 8327499..0301d5c 100644 --- a/NonlinearTMM/src/SecondOrderNLTMM.pyx +++ b/NonlinearTMM/src/SecondOrderNLTMM.pyx @@ -91,9 +91,9 @@ cdef TMMParamCpp TmmParamFromStr(str paramStr): cdef class _Chi2Tensor: """_Chi2Tensor() - This class is helper class for Material to accommodate the second-order + This is a helper class for Material to accommodate the second-order susceptibility tensor. Allows setting nonlinearities by chi2- and by d-values. - Possible to rotate initial tensor around all three axes. + The initial tensor can be rotated around all three axes. """ cdef Chi2TensorCpp* _thisptr; @@ -212,9 +212,10 @@ cdef class _Chi2Tensor: cdef class Material: """Material(wls, ns) - This class describes the optical parameters of nonlinear medium. Default - contructor takes arrays of wavelengths and complex refractive indices and - does linear interpolation. For shortcut __call__ is defined as GetN. + This class describes the optical parameters of a nonlinear medium. The default + constructor takes arrays of wavelengths and complex refractive indices and + performs linear interpolation. As a shortcut, ``__call__`` is defined as an + alias for ``GetN``. Parameters ---------- @@ -276,7 +277,7 @@ cdef class Material: def IsNonlinear(self): """IsNonlinear() - This method returns True if material nonlinearity tensor :any:`chi2` is nonzero, + Returns True if the material nonlinearity tensor ``chi2`` is nonzero, False otherwise. Returns @@ -304,49 +305,50 @@ cdef class _Wave: Standard Gaussian beam with waist size w0 'tukey': Rectangular wave with cosine tapered edges (Tukey window). The width - is given by :any:`w0` and the tapered region is determined by :any:`a`. + is given by ``w0`` and the tapered region is determined by ``a``. 'spdc': Wave used to represent vacuum fluctuations in case of SPDC calculation. + Default is 'planewave'. pwr : float Power of the wave (in watts). Default 1.0. The area of the beam is calculated as w0 * Ly. overrideE0 : bool - if True, then :any:`pwr` is ignored and :any:`E0` is used. Default False. + if True, then ``pwr`` is ignored and ``E0`` is used. Default False. E0 : float Maximum electrical field of the beam in vacuum. w0 : float - Waist size of the beam (in meters). Dafualt is 0.1 mm. + Waist size of the beam (in meters). Default is 0.1 mm. Ly : float Beam size in y-direction (in meters). Default is 1 mm. a : float - Parameter used for Tukey wave. If a = 1, then the wave is perfect - rectangle, if a = 0.5, then half of the profile is tapered by cosines. - Defualt is 0.7. + Parameter used for Tukey wave. If a = 1, then the wave is a perfect + rectangle; if a = 0.5, then half of the profile is tapered by cosines. + Default is 0.7. nPointsInteg : int - Number of points used to represenbt the profile of the wave. + Number of points used to represent the profile of the wave. Default is 100. maxX : float The wave profile is given in x-range (-maxX..maxX). Only used if dynamicMaxX is False. Default is 1 mm. dynamicMaxX : bool Selects between dynamic determination of x-span of the wave (region - where :any:`nPointsInteg` samples are taken) or fixed span by :any:`maxX`. + where ``nPointsInteg`` samples are taken) or fixed span by ``maxX``. Default is True. dynamicMaxXCoef : float Dynamic maxX equals to the beam width (corrected to the angle of - incidence) times :any:`dynamicMaxXCoef`. Default is 2.0. + incidence) times ``dynamicMaxXCoef``. Default is 2.0. dynamicMaxXAddition : float - Constant factor that is added to maxX if :any:`dynamicMaxX` is true. + Constant factor that is added to maxX if ``dynamicMaxX`` is true. Default is 0.0. maxPhi : float - Determines the maximum angle of deviation form the direction of + Determines the maximum angle of deviation from the direction of propagation of the participating fields. Increases the range of x-span - (i.e :any:`maxX`) if it is neccesary to limit the angular distribution of the + (i.e ``maxX``) if it is necessary to limit the angular distribution of the participating plane waves. Default is 0.17 rad. xRange : tuple of floats (xMin, xMax) - Current x-span calculated from :any:`maxX`, :any:`dynamicMaxXCoef` and :any:`maxPhi`. + Current x-span calculated from ``maxX``, ``dynamicMaxXCoef`` and ``maxPhi``. The wave must be solved to access this quantity. betas : ndarray of floats Normalized tangential wave vectors of plane wave expansion. The wave @@ -361,8 +363,8 @@ cdef class _Wave: kzs : ndarray of floats Same information as in betas, but converted to the z-component of the wave vector. The wave must be solved to access this quantity. - fieldProfile : tuple(2,) of ndarray of floats (xs, fiedProfile) - The field profile of the input wave sample by :any:`nPointsInteg` points. The + fieldProfile : tuple(2,) of ndarray of floats (xs, fieldProfile) + The field profile of the input wave sampled by ``nPointsInteg`` points. The wave must be solved to access this quantity. expansionCoefsKx : ndarray of complex Array of plane wave expansion coefs. @@ -558,11 +560,11 @@ cdef class _Intensities: Attributes ---------- inc : complex - Electical field amplitute of the incident plane wave. + Electrical field amplitude of the incident plane wave. r : complex - Electical field amplitute of the reflected plane wave. + Electrical field amplitude of the reflected plane wave. t : complex - Electrical field amplitute of the transmitted plane wave. + Electrical field amplitude of the transmitted plane wave. I : float Intensity of the incident plane wave. R : float @@ -591,16 +593,16 @@ cdef class _Intensities: cdef class _SweepResultNonlinearTMM: """ - Helper class to store the result of the :any:`NonlinearTMM.Sweep` method. + Helper class to store the result of the ``NonlinearTMM.Sweep`` method. Attributes ---------- inc : ndarray of complex - The complex amplitutes of the incident plane waves. + The complex amplitudes of the incident plane waves. r : ndarray of complex - The complex amplitutes of the reflected plane waves. + The complex amplitudes of the reflected plane waves. t : ndarray of complex - The complex amplitutes of the transmitted plane waves. + The complex amplitudes of the transmitted plane waves. Ii : ndarray of double The intensities of the incident plane waves. Ir : ndarray of double @@ -608,9 +610,9 @@ cdef class _SweepResultNonlinearTMM: It : ndarray of double The intensities of the transmitted plane waves. Ia : ndarray of double - The intensities of asborption in the structure. + The intensities of absorption in the structure. enh : ndarray of double - The enhancment values of the electrical field norm. + The enhancement values of the electrical field norm. """ cdef SweepResultNonlinearTMMCpp *_thisptr @@ -659,7 +661,7 @@ cdef class _WaveSweepResultNonlinearTMM: Pt : ndarray of floats The power of the transmitted beam. enh : ndarray of floats - The enhancment of the beam. + The enhancement of the beam. beamArea : ndarray of floats The area of the beam with correction of angle of incidence. @@ -699,12 +701,12 @@ cdef class _FieldsZ: Attributes ---------- E : ndarray(N, 3) of complex - Electrical fields along z-coordinate. First index is determines the - z-coorinate and the second corrorrespond to the x-, y-, z-component + Electrical fields along the z-coordinate. The first index corresponds to + the z-coordinate and the second corresponds to the x-, y-, z-component (0..2). H : ndarray(N, 3) of complex - Magnetic fields along z-coordinate. First index is determines the - z-coorinate and the second corrorrespond to the x-, y-, z-component + Magnetic fields along the z-coordinate. The first index corresponds to + the z-coordinate and the second corresponds to the x-, y-, z-component (0..2). """ @@ -734,29 +736,29 @@ cdef class _FieldsZX: Attributes ---------- Ex : ndarray(N, M) of complex - Electrical field x-component in zx-plane. First index corresponds to - z-coorinate and the second to the x-coordinate. + Electrical field x-component in the zx-plane. First index corresponds to + the z-coordinate and the second to the x-coordinate. Ey : ndarray(N, M) of complex - Electrical field y-component in zx-plane. First index corresponds to - z-coorinate and the second to the x-coordinate. + Electrical field y-component in the zx-plane. First index corresponds to + the z-coordinate and the second to the x-coordinate. Ez : ndarray(N, M) of complex - Electrical field z-component in zx-plane. First index corresponds to - z-coorinate and the second to the x-coordinate. + Electrical field z-component in the zx-plane. First index corresponds to + the z-coordinate and the second to the x-coordinate. EN : ndarray(N, M) of float - Electical field norm in zx-plane. First index corresponds to - z-coorinate and the second to the x-coordinate. + Electrical field norm in the zx-plane. First index corresponds to + the z-coordinate and the second to the x-coordinate. Hx : ndarray(N, M) of complex - Magnetic field x-component in zx-plane. First index corresponds to - z-coorinate and the second to the x-coordinate. + Magnetic field x-component in the zx-plane. First index corresponds to + the z-coordinate and the second to the x-coordinate. Hy : ndarray(N, M) of complex - Magnetic field y-component in zx-plane. First index corresponds to - z-coorinate and the second to the x-coordinate. + Magnetic field y-component in the zx-plane. First index corresponds to + the z-coordinate and the second to the x-coordinate. Hz : ndarray(N, M) of complex - Magnetic field z-component in zx-plane. First index corresponds to - z-coorinate and the second to the x-coordinate. + Magnetic field z-component in the zx-plane. First index corresponds to + the z-coordinate and the second to the x-coordinate. HN : ndarray(N, M) of float - Magnetic field norm in zx-plane. First index corresponds to - z-coorinate and the second to the x-coordinate. + Magnetic field norm in the zx-plane. First index corresponds to + the z-coordinate and the second to the x-coordinate. """ cdef FieldsZXCpp *_thisptr; @@ -845,13 +847,13 @@ cdef class _HomogeneousWave: Parameters ---------- z : float - z-coorinate for the main fields calculation. z=0 is the beginning of + z-coordinate for the main fields calculation. z=0 is the beginning of the layer. Returns ------- ndarray(2,) of complex - The foreard and backward component of the main fields. + The forward and backward component of the main fields. """ # Have to copy, because result is in stack @@ -871,12 +873,12 @@ cdef class _HomogeneousWave: cdef class _NonlinearLayer: """ - Helper class for layer specific data and mathods. + Helper class for layer-specific data and methods. Attributes ---------- d : float - The thikness of the layer. + The thickness of the layer. """ cdef NonlinearLayerCpp *_thisptr @@ -900,12 +902,12 @@ cdef class _NonlinearLayer: def GetIntensity(self, double z): """GetIntensity(z) - Returns intensity of the plane wave at coordinate `z`. + Returns intensity of the plane wave at coordinate ``z``. Parameters ---------- z : float - z-coorinate + z-coordinate Returns ------- @@ -965,40 +967,40 @@ cdef class NonlinearTMM: This class is mainly used to calculate linear propagation of plane waves in stratified medium. It can work like ordinary TMM and calculate the propagation of the input waves. It is also capable of nonlinear calculations, but - for this purpose use specialized class :any:`SecondOrderNLTMM`. + for this purpose use specialized class :class:`SecondOrderNLTMM`. Default constructor takes no arguments. Attributes ---------- E0 : complex - The amplitude of the input plane wave (given in vaccuum, not in the first layer). - Only used if :any:`overrideE0` is set to True (default is False), otherwise intensity - :any:`I0` is used instead. + The amplitude of the input plane wave (given in vacuum, not in the first layer). + Only used if ``overrideE0`` is set to True (default is False); otherwise intensity + ``I0`` is used instead. Default: 1.0. I0 : float The intensity of the input beam in the first medium. Only used if - :any:`overrideE0` is set to False (default). + ``overrideE0`` is set to False (default). Default: 1.0. beta : float Normalized tangential wave vector. Determines the angle of incidence through relation beta = sin(theta) * n_p, where theta is angle of incidence and n_p is the refractive index of the prism. Default: not defined. - layers : list of helper class :any:`_NonlinerLayer` - Allows to access layers by index. + layers : list of :class:`_NonlinearLayer` + Allows accessing layers by index. mode : str - By default "incident" which corresponds to Ordinary TMM. Other mode is, - "nonlinear" but it is automatically set by :any:`SecondOrderNLTMM` (i.e, this + Default is "incident", which corresponds to ordinary TMM. The other mode is + "nonlinear", but it is automatically set by :class:`SecondOrderNLTMM` (i.e, this parameter has to be modified only in special cases). overrideE0 : bool - If True, then parameter :any:`E0` is used, otherwise intensity :any:`I0` is used. + If True, then parameter ``E0`` is used; otherwise intensity ``I0`` is used. Default: False. pol : str "p" or "s" corresponding to p- and s-polarization, respectively. Default: Not defined. - wave : :any:`_Wave` - Innstance of helper class :any:`_Wave` for non plane wave calculations. + wave : :class:`_Wave` + Instance of helper class :class:`_Wave` for non-plane-wave calculations. wl : float Wavelength of calculations in meters. @@ -1049,8 +1051,8 @@ cdef class NonlinearTMM: d : float Thickness of the layer in meters. First and the last medium have infinite thickness. - material : :any:`Material` - Instance of the helper class :any:`Material` + material : :class:`Material` + Instance of the helper class :class:`Material` Examples -------- @@ -1076,7 +1078,7 @@ cdef class NonlinearTMM: """SetParams(**kwargs) Helper method to set the values of all the attributes. See the docstring - of :any:`NonlinearTMM`. + of :class:`NonlinearTMM`. """ for name, value in kwargs.items(): @@ -1098,13 +1100,13 @@ cdef class NonlinearTMM: beta : float, optional Normalized tangential wave vector. E0 : complex, optional - Input plane wave amplitude in vacuum. Only used if :any:`overrideE0` is + Input plane wave amplitude in vacuum. Only used if ``overrideE0`` is True. I0 : float, optional Input plane wave intensity in the first layer. Only used if - :any:`overrideE0` is False. + ``overrideE0`` is False. overrideE0 : bool, optional - Selects between :any:`E0` and :any:`I0`. + Selects between ``E0`` and ``I0``. Examples -------- @@ -1117,12 +1119,12 @@ cdef class NonlinearTMM: def GetIntensities(self): """GetIntensities() - Returns the intensities and amplitutes of incident, reflected and + Returns the intensities and amplitudes of incident, reflected and transmitted wave. The structure must be solved first. Returns ------- - :any:`_Intensities` + :class:`_Intensities` Helper class to hold intensity data. """ cdef IntensitiesCpp resCpp = self._thisptr.GetIntensities() @@ -1133,8 +1135,8 @@ cdef class NonlinearTMM: def Sweep(self, str paramStr, np.ndarray[double, ndim = 1] values, int layerNr = 0, double layerZ = 0.0, bool outPwr = True, bool outAbs = False, outEnh = False): """Sweep(paramStr, values, layerNr = 0, layerZ = 0, outPwr = True, outAbs = False, outEnh = False) - Solves the structure for series of :any:`values` of param :any:`paramStr`. Using - this function is more confortable and faster than just changing params + Solves the structure for a series of ``values`` of param ``paramStr``. Using + this function is more convenient and faster than just changing params and solving the structure. Parameters @@ -1146,24 +1148,25 @@ cdef class NonlinearTMM: normalized tangential wavevector 'I0': intensity of the wave - 'd_i': thikness of layer i (0..N-1) + 'd_i': + thickness of layer i (0..N-1) values : ndarray of floats - Correspondig values of param :any:`paramStr`. + Corresponding values of param ``paramStr``. layerNr : int - Specifies layer, where electrical field enhancment is calculated. + Specifies layer, where electrical field enhancement is calculated. layerZ : double - Specifies z-coordinate of enchncment calculation inside :any:`layerNr`. + Specifies z-coordinate of enhancement calculation inside ``layerNr``. outPwr : bool Turns calculation of intensities on/off. outAbs : bool - Turns calculation of absoprtiopn in the entire structure on/off. + Turns calculation of absorption in the entire structure on/off. outEnh : bool - Turns calculation of enhancment in layer :any:`layerNr` at distance - :any:`layerZ` on/off.values + Turns calculation of enhancement in layer ``layerNr`` at distance + ``layerZ`` on/off. Returns ------- - :any:`_SweepResultNonlinearTMM` + :class:`_SweepResultNonlinearTMM` Helper class to store the result. """ @@ -1193,7 +1196,7 @@ cdef class NonlinearTMM: def GetFields(self, np.ndarray[double, ndim = 1] zs, str dir = "total"): """GetFields(zs, dir = "total") - Calculates electical and magnetic fields along z-axis. The structure + Calculates electrical and magnetic fields along z-axis. The structure must be solved first. Parameters @@ -1206,7 +1209,7 @@ cdef class NonlinearTMM: Returns ------- - :any:`_FieldsZ` + :class:`_FieldsZ` Helper class to store electric and magnetic fields. """ @@ -1219,7 +1222,7 @@ cdef class NonlinearTMM: def GetFields2D(self, np.ndarray[double, ndim = 1] zs, np.ndarray[double, ndim = 1] xs, str dir = "total"): """GetFields2D(zs, xs, dir = "total") - Calculates electical and magnetic fields in xz-plane. Made as fast as + Calculates electrical and magnetic fields in xz-plane. Made as fast as possible. The structure must be solved first. Parameters @@ -1234,7 +1237,7 @@ cdef class NonlinearTMM: Returns ------- - :any:`_FieldsZX` + :class:`_FieldsZX` Helper class to store electric and magnetic fields in regular grid. """ @@ -1260,8 +1263,8 @@ cdef class NonlinearTMM: def GetEnhancement(self, int layerNr, double z = 0.0): """GetEnhancement(layerNr, z = 0.0) - Calculates the enhancement of electical field norm at specified layer at - fixed z-cooridnate. + Calculates the enhancement of electrical field norm at specified layer at + fixed z-coordinate. Parameters ---------- @@ -1273,8 +1276,8 @@ cdef class NonlinearTMM: Returns ------- float - The enhancment of the electrical field norm in comparison to the - input wave in the vacuum. + The enhancement of the electrical field norm in comparison to the + input wave in vacuum. """ cdef double res @@ -1286,8 +1289,8 @@ cdef class NonlinearTMM: def WaveGetPowerFlows(self, int layerNr, double x0 = float("nan"), double x1 = float("nan"), double z = 0.0): """WaveGetPowerFlows(layerNr, x0 = float("nan"), x1 = float("nan"), z = 0.0) - Analogous to the :any:`GetIntensities`, but calculates the powers of the - beams instead of the intensities of the plane-waves. + Analogous to ``GetIntensities``, but calculates the powers of the + beams instead of the intensities of the plane waves. Parameters ---------- @@ -1295,11 +1298,11 @@ cdef class NonlinearTMM: Specifies layer number where to calculate the power of the beam. x0 : float Specifies the starting point of the integration of the power in the - x-direction. By default this parameter is selected by the :any:`_Wave` + x-direction. By default this parameter is selected by the ``_Wave`` class. x1 : float Specifies the end point of the integration of the power in the - x-direction. By default this parameter is selected by the :any:`_Wave` + x-direction. By default this parameter is selected by the ``_Wave`` class. z : float Specifies the z-position of the line through which the integration @@ -1308,8 +1311,8 @@ cdef class NonlinearTMM: Returns ------- tuple of floats (PB, PF) - PB is the power propageted into netagtive infinity and PF denotes - the power propagation to the positive direction of z-axis. + PB is the power propagated into negative infinity and PF denotes + the power propagating in the positive direction of z-axis. """ # NonlinearLayer has its own specific method @@ -1320,8 +1323,8 @@ cdef class NonlinearTMM: def WaveGetEnhancement(self, int layerNr, double z = 0.0): """WaveGetEnhancement(layerNr, z = 0.0) - Calculates enhencment of electical field norm in comparison to the imput - beam in vacuum. Analogous to :any:`GetEnhancement`. + Calculates enhancement of electrical field norm in comparison to the input + beam in vacuum. Analogous to ``GetEnhancement``. Parameters ---------- @@ -1333,8 +1336,8 @@ cdef class NonlinearTMM: Returns ------- float - The enhancment of the electrical field norm in comparison to the - input wave in the vacuum. + The enhancement of the electrical field norm in comparison to the + input wave in vacuum. """ cdef double res @@ -1346,9 +1349,9 @@ cdef class NonlinearTMM: bool outR = False, bool outT = False, bool outEnh = False): """WaveSweep(paramStr, values, layerNr = 0, layerZ = 0.0, outPwr = True, outR = False, outT = False, outEnh = False) - Solves the structure for waves for series of :any:`values` of param - :any:`paramStr`. Using this function is more confortable and faster than just - changing params and solving the structure. Analogous to :any:`Sweep`. + Solves the structure for waves for a series of ``values`` of param + ``paramStr``. Using this function is more convenient and faster than just + changing params and solving the structure. Analogous to ``Sweep``. Parameters ---------- @@ -1360,15 +1363,15 @@ cdef class NonlinearTMM: 'I0': intensity of the wave 'd_i': - thikness of layer i (0..N-1) + thickness of layer i (0..N-1) 'w0': waist size of the input beam values : ndarray of floats - Correspondig values of param :any:`paramStr`. + Corresponding values of param ``paramStr``. layerNr : int - Specifies layer, where electrical field enhancment is calculated. + Specifies layer, where electrical field enhancement is calculated. layerZ : double - Specifies z-coordinate of enchncment calculation inside :any:`layerNr`. + Specifies z-coordinate of enhancement calculation inside ``layerNr``. outPwr : bool Turns calculation of all powers on/off. outR : bool @@ -1376,12 +1379,12 @@ cdef class NonlinearTMM: outT : bool Turns calculation of transmitted power on/off. outEnh : bool - Turns calculation of enhancment in layer layerNr at distance - :any:`layerZ` on/off. + Turns calculation of enhancement in layer ``layerNr`` at distance + ``layerZ`` on/off. Returns ------- - :any:`_SweepResultNonlinearTMM` + :class:`_SweepResultNonlinearTMM` Helper class to store the result. """ @@ -1415,7 +1418,7 @@ cdef class NonlinearTMM: """WaveGetFields2D(zs, xs, dirStr = "total") Calculates 2D electric and magnetic fields of beam propagating in the - structure. Analogous to the :any:`GetFields2D` of plane waves. + structure. Analogous to ``GetFields2D`` of plane waves. Parameters ---------- @@ -1424,12 +1427,12 @@ cdef class NonlinearTMM: first layer is at z = 0. xs : ndarray of floats Points on x-axis where to calculate the fields. - dir : {'total', 'forward', 'backward'} + dirStr : {'total', 'forward', 'backward'} Specifies the components of the output fields. Returns ------- - :any:`_FieldsZX` + :class:`_FieldsZX` Helper class to store electric and magnetic fields in regular grid. """ @@ -1514,14 +1517,14 @@ cdef class _SecondOrderNLIntensities: Attributes ---------- - P1 : :any:`_Intensities` - Instance of `_Intensities` class and holds the intensities of second - inuput wave. - P2 : :any:`_Intensities` - Instance of `_Intensities` class and holds the intensities of first - inuput wave. - Gen : :any:`_Intensities` - Instance of `_Intensities` class and holds the intensities of generated + P1 : :class:`_Intensities` + Instance of ``_Intensities`` class and holds the intensities of the first + input wave. + P2 : :class:`_Intensities` + Instance of ``_Intensities`` class and holds the intensities of the second + input wave. + Gen : :class:`_Intensities` + Instance of ``_Intensities`` class and holds the intensities of the generated wave. """ @@ -1554,16 +1557,16 @@ cdef class _SweepResultSecondOrderNLTMM: Attributes ---------- - P1 : :any:`_SweepResultNonlinearTMM` + P1 : :class:`_SweepResultNonlinearTMM` Sweep results for the first input wave. - P2 : :any:`_SweepResultNonlinearTMM` + P2 : :class:`_SweepResultNonlinearTMM` Sweep results for the second input wave. - Gen : :any:`_SweepResultNonlinearTMM` + Gen : :class:`_SweepResultNonlinearTMM` Sweep results for the generated wave. wlsGen : ndarray of floats Stores the wavelength of the generated wave. betasGen : ndarray of floats - Stores the normalized tangential wave vector the generated wave. + Stores the normalized tangential wave vector of the generated wave. """ cdef SweepResultSecondOrderNLTMMCpp *_thisptr @@ -1606,16 +1609,16 @@ cdef class _WaveSweepResultSecondOrderNLTMM: Attributes ---------- - P1 : :any:`_WaveSweepResultNonlinearTMM` + P1 : :class:`_WaveSweepResultNonlinearTMM` The sweep result of the first input beam. - P1 : :any:`_WaveSweepResultNonlinearTMM` + P2 : :class:`_WaveSweepResultNonlinearTMM` The sweep result of the second input beam. - Gen : :any:`_WaveSweepResultNonlinearTMM` + Gen : :class:`_WaveSweepResultNonlinearTMM` The sweep result of the generated beam. wlsGen : ndarray of floats Stores the wavelength of the generated wave. betasGen : ndarray of floats - Stores the normalized tangential wave vector the generated wave. + Stores the normalized tangential wave vector of the generated wave. """ cdef WaveSweepResultSecondOrderNLTMMCpp *_thisptr @@ -1655,9 +1658,9 @@ cdef class _WaveSweepResultSecondOrderNLTMM: cdef class SecondOrderNLTMM: """SecondOrderNLTMM(mode) - This class calculates second-order nonliner processes (e.g. sum-frequency, - difference frequency generation and SPDC) in layered structures. Relies on the - functionality of `NonlinearTMM` class. + This class calculates second-order nonlinear processes (e.g. sum-frequency, + difference-frequency generation and SPDC) in layered structures. Relies on the + functionality of the ``NonlinearTMM`` class. Parameters ---------- @@ -1665,24 +1668,24 @@ cdef class SecondOrderNLTMM: Attributes ---------- - P1 : :any:`NonlinearTMM` - The inctance of the first pump wave TMM. - P2 : :any:`NonlinearTMM` - The inctance of the second pump wave TMM. - Gen : :any:`NonlinearTMM` - The inctance of the generated wave TMM. + P1 : :class:`NonlinearTMM` + The instance of the first pump wave TMM. + P2 : :class:`NonlinearTMM` + The instance of the second pump wave TMM. + Gen : :class:`NonlinearTMM` + The instance of the generated wave TMM. deltaWlSpdc : float The spectral collection window (in nanometers) of the SPDC signal. - Only used if :any:`mode` is set to :any:`SPDC` + Only used if ``mode`` is set to ``"spdc"``. Default: NaN. solidAngleSpdc : float The collection solid angle (srad) of the detector (given in vacuum). - Only used if :any:`mode` is set to :any:`SPDC` + Only used if ``mode`` is set to ``"spdc"``. Default: NaN. deltaThetaSpdc : float The horizontal collection window (rad) of the detector (given in vacuum). It is used to calculate the vertical span of the detector. - Only used if :any:`mode` is set to :any:`SPDC` + Only used if ``mode`` is set to ``"spdc"``. Default: NaN. """ @@ -1728,7 +1731,7 @@ cdef class SecondOrderNLTMM: """SetParams(**kwargs) Helper method to set the values of all the attributes. See the docstring - of :any:`SecondOrderNLTMM`. + of :class:`SecondOrderNLTMM`. """ for name, value in kwargs.items(): @@ -1746,7 +1749,7 @@ cdef class SecondOrderNLTMM: ---------- d : float layer thickness (m) - material : :any:`Material` + material : :class:`Material` The class containing the material parameters. """ @@ -1769,7 +1772,7 @@ cdef class SecondOrderNLTMM: def UpdateGenParams(self): """UpdateGenParams() - Forces the update of the wavelength and beta of the generated beam :any:`Gen`. + Forces the update of the wavelength and beta of the generated beam ``Gen``. """ self._thisptr.UpdateGenParams() @@ -1777,13 +1780,13 @@ cdef class SecondOrderNLTMM: def GetIntensities(self): """GetIntensities() - Returns the intensities and amplitutes of incident, reflected and - transmitted wave for :any:`P1`, :any:`P2` and :any:`Gen`. + Returns the intensities and amplitudes of incident, reflected and + transmitted wave for ``P1``, ``P2`` and ``Gen``. The structure must be solved first. Returns ------- - :any:`_SecondOrderNLIntensities` + :class:`_SecondOrderNLIntensities` Helper class to hold intensity data. """ cdef SecondOrderNLIntensitiesCpp resCpp; @@ -1796,8 +1799,8 @@ cdef class SecondOrderNLTMM: def Sweep(self, str paramStr, np.ndarray[double, ndim = 1] valuesP1, np.ndarray[double, ndim = 1] valuesP2, int layerNr = 0, double layerZ = 0.0, bool outPwr = True, bool outAbs = False, bool outEnh = False, bool outP1 = True, bool outP2 = True, bool outGen = True): """Sweep(paramStr, valuesP1, valuesP2, layerNr = 0, layerZ = 0.0, outPwr = True, outAbs = False, outEnh = False, outP1 = True, outP2 = True, outGen = True) - Solves the structure for series of :any:`valuesP1` and :any:`valuesP2` - of param :any:`paramStr`. Using this function is more confortable and + Solves the structure for a series of ``valuesP1`` and ``valuesP2`` + of param ``paramStr``. Using this function is more convenient and faster than just changing params and solving the structure (parallelized with OpenMP). @@ -1810,32 +1813,33 @@ cdef class SecondOrderNLTMM: normalized tangential wavevector 'I0': intensity of the wave - 'd_i': thikness of layer i (0..N-1) + 'd_i': + thickness of layer i (0..N-1) valuesP1 : ndarray of floats - Correspondig values of param :any:`paramStr` for :any:`P1`. + Corresponding values of param ``paramStr`` for ``P1``. valuesP2 : ndarray of floats - Correspondig values of param :any:`paramStr` for :any:`P2`. + Corresponding values of param ``paramStr`` for ``P2``. layerNr : int - Specifies layer, where electrical field enhancment is calculated. + Specifies layer, where electrical field enhancement is calculated. layerZ : double - Specifies z-coordinate of enchncment calculation inside :any:`layerNr`. + Specifies z-coordinate of enhancement calculation inside ``layerNr``. outPwr : bool Turns calculation of intensities on/off. outAbs : bool - Turns calculation of absoprtiopn in the entire structure on/off. + Turns calculation of absorption in the entire structure on/off. outEnh : bool - Turns calculation of enhancment in layer :any:`layerNr` at distance - :any:`layerZ` on/off.values + Turns calculation of enhancement in layer ``layerNr`` at distance + ``layerZ`` on/off. outP1 : bool - Turns calculation of the :any:`P1` on/off. + Turns calculation of ``P1`` on/off. outP2 : bool - Turns calculation of the :any:`P2` on/off. + Turns calculation of ``P2`` on/off. outGen : bool - Turns calculation of the :any:`Gen` on/off. + Turns calculation of ``Gen`` on/off. Returns ------- - :any:`_SweepResultSecondOrderNLTMM` + :class:`_SweepResultSecondOrderNLTMM` Helper class to store the result. """ @@ -1870,10 +1874,10 @@ cdef class SecondOrderNLTMM: def WaveGetPowerFlows(self, int layerNr, double x0 = float("nan"), double x1 = float("nan"), double z = 0.0): """WaveGetPowerFlows(layerNr, x0 = float("nan"), x1 = float("nan"), z = 0.0) - Analogous to the :any:`GetIntensities`, but calculates the powers of the - beams instead of the intensities of the plane-waves. Only for the - calculation of the power of generated beam. For pump beams use the - same method of :any:`NonlinearTMM`. + Analogous to ``GetIntensities``, but calculates the powers of the + beams instead of the intensities of the plane waves. Only for the + calculation of the power of the generated beam. For pump beams use the + same method of ``NonlinearTMM``. Parameters ---------- @@ -1881,11 +1885,11 @@ cdef class SecondOrderNLTMM: Specifies layer number where to calculate the power of the beam. x0 : float Specifies the starting point of the integration of the power in the - x-direction. By default this parameter is selected by the :any:`_Wave` + x-direction. By default this parameter is selected by the ``_Wave`` class. x1 : float Specifies the end point of the integration of the power in the - x-direction. By default this parameter is selected by the :any:`_Wave` + x-direction. By default this parameter is selected by the ``_Wave`` class. z : float Specifies the z-position of the line through which the integration @@ -1894,8 +1898,8 @@ cdef class SecondOrderNLTMM: Returns ------- tuple of floats (PB, PF) - PB is the power propageted into netagtive infinity and PF denotes - the power propagation to the positive direction of z-axis. + PB is the power propagated into negative infinity and PF denotes + the power propagating in the positive direction of z-axis. """ cdef pair[double, double] res; @@ -1909,9 +1913,9 @@ cdef class SecondOrderNLTMM: bool outP1 = True, bool outP2 = True, bool outGen = True): """WaveSweep(paramStr, valuesP1, valuesP2, layerNr = 0, layerZ = 0.0, outPwr = True, outR = False, outT = False, outEnh = False, outP1 = True, outP2 = True, outGen = True) - Solves the structure for waves for series of :any:`valuesP1` and :any:`valuesP2` of param - :any:`paramStr`. Using this function is more confortable and faster than just - changing the params and solving the structure. Analogous to :any:`Sweep`. + Solves the structure for waves for a series of ``valuesP1`` and ``valuesP2`` of param + ``paramStr``. Using this function is more convenient and faster than just + changing the params and solving the structure. Analogous to ``Sweep``. Parameters ---------- @@ -1923,17 +1927,17 @@ cdef class SecondOrderNLTMM: 'I0': intensity of the wave 'd_i': - thikness of layer i (0..N-1) + thickness of layer i (0..N-1) 'w0': waist size of the input beam valuesP1 : ndarray of floats - Correspondig values of param :any:`paramStr` for :any:`P1`. + Corresponding values of param ``paramStr`` for ``P1``. valuesP2 : ndarray of floats - Correspondig values of param :any:`paramStr` for :any:`P2`. + Corresponding values of param ``paramStr`` for ``P2``. layerNr : int - Specifies layer, where electrical field enhancment is calculated. + Specifies layer, where electrical field enhancement is calculated. layerZ : double - Specifies z-coordinate of enchncment calculation inside :any:`layerNr`. + Specifies z-coordinate of enhancement calculation inside ``layerNr``. outPwr : bool Turns calculation of all powers on/off. outR : bool @@ -1941,18 +1945,18 @@ cdef class SecondOrderNLTMM: outT : bool Turns calculation of transmitted power on/off. outEnh : bool - Turns calculation of enhancment in layer layerNr at distance - :any:`layerZ` on/off. + Turns calculation of enhancement in layer ``layerNr`` at distance + ``layerZ`` on/off. outP1 : bool - Turns calculation of the :any:`P1` on/off. + Turns calculation of ``P1`` on/off. outP2 : bool - Turns calculation of the :any:`P2` on/off. + Turns calculation of ``P2`` on/off. outGen : bool - Turns calculation of the :any:`Gen` on/off. + Turns calculation of ``Gen`` on/off. Returns ------- - :any:`_WaveSweepResultSecondOrderNLTMM` + :class:`_WaveSweepResultSecondOrderNLTMM` Helper class to store the result. """ @@ -1991,10 +1995,10 @@ cdef class SecondOrderNLTMM: np.ndarray[double, ndim = 1] xs, str dirStr = "total"): """WaveGetFields2D(zs, xs, dirStr = "total") - Calculates 2D electric and magnetic fields of beam propagating in the - structure. Analogous to the :any:`GetFields2D` of plane waves. Only for the - calculation of the power of generated beam. For pump beams use the - same method of :any:`NonlinearTMM`. + Calculates 2D electric and magnetic fields of the beam propagating in the + structure. Analogous to ``GetFields2D`` of plane waves. Only for the + calculation of the generated beam fields. For pump beams use the + same method of ``NonlinearTMM``. Parameters ---------- @@ -2003,12 +2007,12 @@ cdef class SecondOrderNLTMM: first layer is at z = 0. xs : ndarray of floats Points on x-axis where to calculate the fields. - dir : {'total', 'forward', 'backward'} + dirStr : {'total', 'forward', 'backward'} Specifies the components of the output fields. Returns ------- - :any:`_FieldsZX` + :class:`_FieldsZX` Helper class to store electric and magnetic fields in regular grid. """ diff --git a/NonlinearTMM/src/cpp/Common.cpp b/NonlinearTMM/src/cpp/Common.cpp index f5cb3f9..9484ed0 100644 --- a/NonlinearTMM/src/cpp/Common.cpp +++ b/NonlinearTMM/src/cpp/Common.cpp @@ -16,7 +16,6 @@ TMMParamType GetParamType(TMMParam param) { case TMMParam::PARAM_LAYER_D: return TMMParamType::PTYPE_NONLINEAR_LAYER; default: - std::cerr << "Param has no type" << std::endl; throw std::invalid_argument("Param has no type"); } } @@ -251,7 +250,6 @@ pairdd IntegrateWavePower([[maybe_unused]] int layerNr, Polarization pol, double const Eigen::MatrixX2cd& Us, const ArrayXd& kxs, const Eigen::MatrixX2cd& kzs, double x0, double x1, double z, double Ly) { if (x0 != -x1 || z != 0) { - std::cerr << "Currently only x0 = -x1, z = 0 supported." << std::endl; throw std::invalid_argument("Currently only x0 = -x1, z = 0 supported."); } @@ -338,7 +336,6 @@ pairdd IntegrateWavePower([[maybe_unused]] int layerNr, Polarization pol, double resF = Ly / (2.0 * omega * constMu0) * real(integValue2dF); resB = -Ly / (2.0 * omega * constMu0) * real(integValue2dB); } else { - std::cerr << "Unknown polarization." << std::endl; throw std::invalid_argument("Unknown polarization."); } @@ -356,7 +353,6 @@ WaveDirection GetWaveDirection(dcomplex kzF, dcomplex eps, Polarization pol) { break; default: #pragma omp critical - std::cerr << "Unknown polarization." << std::endl; throw std::invalid_argument("Unknown polarization."); } @@ -374,7 +370,6 @@ WaveDirection GetWaveDirection(dcomplex kzF, dcomplex eps, Polarization pol) { } else { // Only if kz = 0.0 #pragma omp critical - std::cerr << "kzF = 0: " << kzF << " " << eps << ": " << pwrFlow << std::endl; throw std::runtime_error("Could not determine wave direction."); } } diff --git a/NonlinearTMM/src/cpp/NonlinearLayer.cpp b/NonlinearTMM/src/cpp/NonlinearLayer.cpp index c073ac8..86553f0 100644 --- a/NonlinearTMM/src/cpp/NonlinearLayer.cpp +++ b/NonlinearTMM/src/cpp/NonlinearLayer.cpp @@ -90,14 +90,12 @@ void HomogeneousWave::Solve(NonlinearLayer* layer_) { } if (imag(kz(iF)) < 0.0) { - // Shold not hapen, checking - std::cerr << "kzF imaginary part negative" << std::endl; + // Should not happen, checking throw std::runtime_error("kzF imaginary part negative"); } if (real(kz(iF)) < 0.0) { - // Shold not hapen, checking - std::cerr << "kzF real part negative" << std::endl; + // Should not happen, checking throw std::runtime_error("kzF real part negative"); } diff --git a/NonlinearTMM/src/cpp/NonlinearTMM.cpp b/NonlinearTMM/src/cpp/NonlinearTMM.cpp index edf22fd..b45b034 100644 --- a/NonlinearTMM/src/cpp/NonlinearTMM.cpp +++ b/NonlinearTMM/src/cpp/NonlinearTMM.cpp @@ -93,7 +93,6 @@ void OuterProductGoodEigenComplexAdd(const ArrayXcd& X, const ArrayXcd& Y, Matri void ThreadSafeMatrixAddNorm(MatrixXcd& mat, const MatrixXcd& toAdd) { if (mat.rows() != toAdd.rows() || mat.cols() != toAdd.cols()) { - std::cerr << "mat and toAdd must be the same size." << std::endl; throw std::invalid_argument("mat and toAdd must be the same size."); } @@ -308,27 +307,22 @@ void NonlinearTMM::CheckPrerequisites(TMMParam toIgnore) { if (mode == NonlinearTmmMode::MODE_VACUUM_FLUCTUATIONS) { if (std::isnan(deltaWlSpdc)) { - std::cerr << "No value for deltaWlSpdc" << std::endl; throw std::invalid_argument("No value for deltaWlSpdc"); } if (std::isnan(solidAngleSpdc)) { - std::cerr << "No value for solidAngleSpdc" << std::endl; throw std::invalid_argument("No value for solidAngleSpdc"); } if (std::isnan(deltaThetaSpdc)) { - std::cerr << "No value for deltaThetaSpdc" << std::endl; throw std::invalid_argument("No value for deltaThetaSpdc"); } if (std::isnan(wlP1Spdc)) { - std::cerr << "No value for wlP1Spdc" << std::endl; throw std::invalid_argument("No value for wlP1Spdc"); } if (std::isnan(betaP1Spdc)) { - std::cerr << "No value for betaP1Spdc" << std::endl; throw std::invalid_argument("No value for betaP1Spdc"); } } @@ -513,7 +507,7 @@ double NonlinearTMM::CalcVacFuctuationsE0() { } double NonlinearTMM::CalcDeltaKxSpdc() { - // TODO: restrict ublic usage + // NOTE: intended for internal use only (called via Cython layer) // Calc deltaKx if (wave.GetWaveType() == WaveType::SPDCWAVE) { @@ -590,7 +584,6 @@ void NonlinearTMM::Solve() { // Check first layer if (beta >= real(layers[0].n)) { - std::cerr << "Light cannot propagate in the first medium." << std::endl; throw std::invalid_argument("Light cannot propagate in the first medium."); } @@ -871,7 +864,6 @@ Wave* NonlinearTMM::GetWave() noexcept { pairdd NonlinearTMM::WaveGetPowerFlows(int layerNr, double x0, double x1, double z) { CheckPrerequisites(); if (mode == NonlinearTmmMode::MODE_NONLINEAR) { - std::cerr << "For nonlinear mode use the method of SecondOrderNLTMM" << std::endl; throw std::runtime_error("For nonlinear mode use the method of SecondOrderNLTMM"); } diff --git a/NonlinearTMM/src/cpp/SecondOrderNLTMM.cpp b/NonlinearTMM/src/cpp/SecondOrderNLTMM.cpp index 5e34433..9375c1d 100644 --- a/NonlinearTMM/src/cpp/SecondOrderNLTMM.cpp +++ b/NonlinearTMM/src/cpp/SecondOrderNLTMM.cpp @@ -59,7 +59,6 @@ void SecondOrderNLTMM::UpdateGenParams() { } if (wlGen <= 0.0) { - std::cerr << "Wavelength cannot be negative." << std::endl; throw std::runtime_error("Wavelength cannot be negative."); } @@ -271,7 +270,8 @@ std::unique_ptr SecondOrderNLTMM::Sweep(TMMParam pa nlTMMCopy.GetP1()->SetParam(param, valuesP1(i), paramLayer); nlTMMCopy.GetP2()->SetParam(param, valuesP2(i), paramLayer); if (GetParamType(param) == TMMParamType::PTYPE_NONLINEAR_LAYER) { - // TODO + // NB: Gen param is set from P2 value; a more accurate approach + // would recompute Gen from both P1 and P2 (e.g. for layer-d sweeps). nlTMMCopy.GetGen()->SetParam(param, valuesP2(i), paramLayer); } @@ -365,7 +365,6 @@ std::unique_ptr SecondOrderNLTMM::WaveGetFields2D(const Eigen::MapTakeSqrt(); } else { - std::cerr << "Only P2 can be incoherent." << std::endl; throw std::invalid_argument("Only P2 can be incoherent."); } @@ -375,7 +374,6 @@ std::unique_ptr SecondOrderNLTMM::WaveGetFields2D(const Eigen::Map tmmP1.LayersCount()) { - std::cerr << "Invalid layer index." << std::endl; throw std::invalid_argument("Invalid layer index."); } UpdateGenParams(); @@ -390,13 +388,13 @@ pairdd SecondOrderNLTMM::WaveGetPowerFlows(int layerNr, double x0, double x1, do double LyP1 = tmmP1.GetWave()->GetLy(); double LyP2 = waveP2->GetLy(); - // TODO + // Wider P2 is required so that the integration x-range derived from P1 + // is fully covered by P2. Relaxing this would need separate x-ranges. if (waveP1->GetW0() > waveP2->GetW0()) { - std::cerr << "Currently P2 must be at least as wide as P1." << std::endl; throw std::invalid_argument("Currently P2 must be at least as wide as P1."); } - // X-range (TODO) + // Default x-range is derived from P1 beam extent auto [xMinP1, xMaxP1] = waveP1->GetXRange(); if (std::isnan(x0)) { x0 = xMinP1; @@ -407,7 +405,6 @@ pairdd SecondOrderNLTMM::WaveGetPowerFlows(int layerNr, double x0, double x1, do // Ly if (LyP1 != LyP2) { - std::cerr << "Both pump waves must have the same Ly." << std::endl; throw std::invalid_argument("Both pump waves must have the same Ly."); } @@ -496,7 +493,6 @@ pairdd SecondOrderNLTMM::WaveGetPowerFlows(int layerNr, double x0, double x1, do res.second += rBwd * dkxP2; } } else { - std::cerr << "Only P2 is allowed to be incoherent." << std::endl; throw std::invalid_argument("Only P2 is allowed to be incoherent."); } @@ -528,7 +524,8 @@ SecondOrderNLTMM::WaveSweep(TMMParam param, const Eigen::Map& valuesP1, nlTMMCopy.GetP1()->SetParam(param, valuesP1(i), paramLayer); nlTMMCopy.GetP2()->SetParam(param, valuesP2(i), paramLayer); if (GetParamType(param) == TMMParamType::PTYPE_NONLINEAR_LAYER) { - // TODO + // NB: Gen param is set from P2 value; a more accurate approach + // would recompute Gen from both P1 and P2 (e.g. for layer-d sweeps). nlTMMCopy.GetGen()->SetParam(param, valuesP2(i), paramLayer); } nlTMMCopy.UpdateGenParams(); diff --git a/NonlinearTMM/src/cpp/Waves.cpp b/NonlinearTMM/src/cpp/Waves.cpp index 2fa0465..498a8f6 100644 --- a/NonlinearTMM/src/cpp/Waves.cpp +++ b/NonlinearTMM/src/cpp/Waves.cpp @@ -40,7 +40,6 @@ void Wave::SolvePlaneWave() { void Wave::SolveFFTWave() { if (nPointsInteg < 2) { - std::cerr << "nPointsInteg too small" << std::endl; throw std::runtime_error("nPointsInteg too small"); } @@ -82,7 +81,6 @@ void Wave::SolveFFTWave() { // Check for backward-propagating waves if (phis.maxCoeff() + thLayer0 >= PI / 2.0) { - std::cerr << "Phi larger than 90 deg." << std::endl; throw std::runtime_error("Phi larger than 90 deg."); } @@ -96,7 +94,6 @@ void Wave::SolveFFTWave() { void Wave::SolveSpdcWave() { // Checks if (std::isnan(deltaKxSpdc)) { - std::cerr << "SPDC wave can only be used through SecondOrderNLTMM" << std::endl; throw std::runtime_error("SPDC wave can only be used through SecondOrderNLTMM"); } maxXThis = (0.5 * w0 / std::cos(thLayer0)); @@ -307,7 +304,6 @@ double Wave::GetDouble(TMMParam param) const { pairdd Wave::GetXRange() const { if (!solved) { - std::cerr << "Wave must be solved first." << std::endl; throw std::runtime_error("Wave must be solved first."); } return pairdd(-maxXThis, maxXThis); @@ -315,7 +311,6 @@ pairdd Wave::GetXRange() const { ArrayXd Wave::GetBetas() const { if (!solved) { - std::cerr << "Wave must be solved first." << std::endl; throw std::runtime_error("Wave must be solved first."); } return kxs / k0; @@ -327,7 +322,6 @@ ArrayXd Wave::GetPhis() const noexcept { ArrayXd Wave::GetKxs() const { if (!solved) { - std::cerr << "Wave must be solved first." << std::endl; throw std::runtime_error("Wave must be solved first."); } return kxs; @@ -335,7 +329,6 @@ ArrayXd Wave::GetKxs() const { ArrayXd Wave::GetKzs() const { if (!solved) { - std::cerr << "Wave must be solved first." << std::endl; throw std::runtime_error("Wave must be solved first."); } return kzs; @@ -343,7 +336,6 @@ ArrayXd Wave::GetKzs() const { ArrayXd Wave::GetFieldProfileXs() const { if (!solved) { - std::cerr << "Wave must be solved first." << std::endl; throw std::runtime_error("Wave must be solved first."); } return fieldProfileXs; @@ -351,7 +343,6 @@ ArrayXd Wave::GetFieldProfileXs() const { ArrayXd Wave::GetFieldProfile() const { if (!solved) { - std::cerr << "Wave must be solved first." << std::endl; throw std::runtime_error("Wave must be solved first."); } return fieldProfile; @@ -359,7 +350,6 @@ ArrayXd Wave::GetFieldProfile() const { ArrayXcd Wave::GetExpansionCoefsKx() const { if (!solved) { - std::cerr << "Wave must be solved first." << std::endl; throw std::runtime_error("Wave must be solved first."); } return expansionCoefsKx; @@ -367,7 +357,6 @@ ArrayXcd Wave::GetExpansionCoefsKx() const { double Wave::GetBeamArea() const { if (!solved) { - std::cerr << "Wave must be solved first." << std::endl; throw std::runtime_error("Wave must be solved first."); } return beamArea; diff --git a/Tests/conftest.py b/Tests/conftest.py new file mode 100644 index 0000000..8e7a994 --- /dev/null +++ b/Tests/conftest.py @@ -0,0 +1,7 @@ +from __future__ import annotations + +import sys +from pathlib import Path + +# Ensure Tests/ and Tests/LabPy/ are importable +sys.path.insert(0, str(Path(__file__).resolve().parent)) diff --git a/Tests/test_MaterialConstructors.py b/Tests/test_MaterialConstructors.py new file mode 100644 index 0000000..beea253 --- /dev/null +++ b/Tests/test_MaterialConstructors.py @@ -0,0 +1,85 @@ +"""Tests for Material constructors and basic error paths.""" + +from __future__ import annotations + +import numpy as np +import pytest + +from NonlinearTMM import TMM, Material + +# --------------------------------------------------------------------------- +# Material.Static +# --------------------------------------------------------------------------- + + +class TestMaterialStatic: + def test_real_refractive_index(self): + mat = Material.Static(1.5) + assert mat.GetN(532e-9) == pytest.approx(1.5) + + def test_complex_refractive_index(self): + n = 0.054007 + 3.4290j + mat = Material.Static(n) + assert mat.GetN(532e-9) == pytest.approx(n) + + def test_wavelength_independent(self): + mat = Material.Static(2.0) + n400 = mat.GetN(400e-9) + n800 = mat.GetN(800e-9) + assert n400 == pytest.approx(n800) + + +# --------------------------------------------------------------------------- +# Material(wls, ns) constructor +# --------------------------------------------------------------------------- + + +class TestMaterialConstructor: + def test_interpolation(self): + wls = np.array([400e-9, 600e-9, 800e-9]) + ns = np.array([1.5, 1.4, 1.3], dtype=complex) + mat = Material(wls, ns) + # Interior point should be interpolated + n_mid = mat.GetN(600e-9) + assert n_mid == pytest.approx(1.4) + # Value between endpoints + n_500 = mat.GetN(500e-9) + assert 1.3 < np.real(n_500) < 1.5 + + def test_complex_ns(self): + wls = np.array([400e-9, 800e-9]) + ns = np.array([1.5 + 0.1j, 1.3 + 0.2j], dtype=complex) + mat = Material(wls, ns) + n = mat.GetN(400e-9) + assert np.real(n) == pytest.approx(1.5) + assert np.imag(n) == pytest.approx(0.1) + + +# --------------------------------------------------------------------------- +# Error path tests +# --------------------------------------------------------------------------- + + +class TestTMMErrors: + def test_invalid_polarization(self): + with pytest.raises((ValueError, RuntimeError)): + TMM(wl=532e-9, pol="x", I0=1.0) + + def test_sweep_no_layers(self): + tmm = TMM(wl=532e-9, pol="p", I0=1.0) + with pytest.raises((ValueError, RuntimeError)): + betas = np.linspace(0, 1, 10) + tmm.Sweep("beta", betas) + + +# --------------------------------------------------------------------------- +# Public API surface test +# --------------------------------------------------------------------------- + + +class TestPublicAPI: + def test_all_exports_importable(self): + import NonlinearTMM + + for name in NonlinearTMM.__all__: + assert hasattr(NonlinearTMM, name), f"{name} listed in __all__ but not importable" diff --git a/docs/GettingStarted.rst b/docs/GettingStarted.rst index eeef1eb..ecdad84 100644 --- a/docs/GettingStarted.rst +++ b/docs/GettingStarted.rst @@ -49,24 +49,24 @@ Class :class:`TMM` (alias of :class:`NonlinearTMM`) has all the standard TMM fea * Both p- and s-polarization * Arbitrary angle of incidence -* Calculation of reflection, transmission and absorption of plane waves (:any:`GetIntensities ` and :any:`GetAbsorbedIntensity `) -* Calculation of electric and magnetic fields inside structure (:any:`GetFields ` and :any:`GetFields2D `) -* Calculation of field enhancement (:any:`GetEnhancement `) -* Sweep over any parameter (:any:`Sweep `) +* Calculation of reflection, transmission and absorption of plane waves (:meth:`GetIntensities ` and :meth:`GetAbsorbedIntensity `) +* Calculation of electric and magnetic fields inside structure (:meth:`GetFields ` and :meth:`GetFields2D `) +* Calculation of field enhancement (:meth:`GetEnhancement `) +* Sweep over any parameter (:meth:`Sweep `) In addition to those standard features, the class has similar functionality to work with waves with arbitrary profile (e.g. Gaussian beam). The configuration -of the beam is done through attribute :any:`wave ` (see class :any:`_Wave`). +of the beam is done through attribute :attr:`wave ` (see class :class:`_Wave`). The interface for the calculations with arbitrary beams is similar to standard TMM: -* Calculation of reflection, transmission and absorption of beams (:any:`WaveGetPowerFlows `) -* Calculation of electric and magnetic fields inside structure (:any:`WaveGetFields2D `) -* Calculation of field enhancement (:any:`WaveGetEnhancement `) -* Sweep over any parameter (:any:`WaveSweep `) +* Calculation of reflection, transmission and absorption of beams (:meth:`WaveGetPowerFlows `) +* Calculation of electric and magnetic fields inside structure (:meth:`WaveGetFields2D `) +* Calculation of field enhancement (:meth:`WaveGetEnhancement `) +* Sweep over any parameter (:meth:`WaveSweep `) Finally, :class:`SecondOrderNLTMM` class is capable of calculating second-order nonlinear processes like second-harmonic generation, sum-frequency generation and -difference frequency generation. This has a similar interface to :any:`TMM` - it +difference frequency generation. This has a similar interface to :class:`TMM` - it supports both plane waves and beams. Standard TMM @@ -83,10 +83,10 @@ the following steps: 1. Specifying material refractive indices. 2. Initializing :class:`TMM`, setting params and adding layers. -3. By using :any:`Sweep ` calculate the dependence of reflection, transmission and enhancement factor on the angle of incidence. +3. By using :meth:`Sweep ` calculate the dependence of reflection, transmission and enhancement factor on the angle of incidence. 4. Find the plasmonic resonance from the maximum enhancement. -5. Calculate 1D fields at plasmonic resonance by :any:`GetFields `. -6. Calculate 2D fields at plasmonic resonance by :any:`GetFields2D `. +5. Calculate 1D fields at plasmonic resonance by :meth:`GetFields `. +6. Calculate 2D fields at plasmonic resonance by :meth:`GetFields2D `. 7. Plot all results .. literalinclude:: ../Examples/ExampleTMM.py @@ -106,7 +106,7 @@ Gaussian wave example The previous example was entirely about standard TMM. Now, the calculations are extended to beams, in this case a Gaussian beam. The steps of the calculations remain the same, except :class:`_Wave` parameters must be set (:class:`TMM` has -attribute :any:`TMM.wave`). The Gaussian beam power is set to 10 mW and the waist size +attribute :attr:`TMM.wave`). The Gaussian beam power is set to 10 mW and the waist size to 10 μm. .. literalinclude:: ../Examples/ExampleTMMForWaves.py diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index 7755b9a..0000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -SPHINXPROJ = NonlinearTMM -SOURCEDIR = . -BUILDDIR = ../../NonlinearTMM-docs - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/conf.py b/docs/conf.py index e7106a2..a25b222 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,21 +1,5 @@ from __future__ import annotations -# -# NonlinearTMM documentation build configuration file, created by -# sphinx-quickstart on Thu Mar 16 11:48:15 2017. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# import importlib.metadata import sys from pathlib import Path @@ -24,120 +8,72 @@ # -- General configuration ------------------------------------------------ -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. extensions = [ "sphinx.ext.autodoc", "sphinx.ext.doctest", + "sphinx.ext.intersphinx", "sphinx.ext.todo", - "sphinx.ext.imgmath", + "sphinx.ext.mathjax", "sphinx.ext.viewcode", "sphinx.ext.githubpages", "sphinx.ext.autosummary", "numpydoc", ] -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] source_suffix = ".rst" - -# The root toctree document. root_doc = "index" -# General information about the project. project = "NonlinearTMM" copyright = "2017-2026, Ardi Loot" author = "Ardi Loot" -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# - __version__ = importlib.metadata.version("NonlinearTMM") - -# The short X.Y version. version = __version__ -# The full version, including alpha/beta/rc tags. release = __version__ -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. language = "en" +exclude_patterns = ["_build", "_autosummary", "Thumbs.db", ".DS_Store"] +todo_include_todos = True -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# These patterns also affect html_static_path and html_extra_path -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +# Suppress :any: cross-reference warnings from numpydoc — these are parameter +# names (e.g. paramStr, layerNr) that numpydoc converts to :any: roles but +# that have no matching Sphinx targets. +suppress_warnings = ["ref.any"] -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" +# -- autosummary ----------------------------------------------------------- -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True +autosummary_generate = True +# -- numpydoc -------------------------------------------------------------- -# -- Options for HTML output ---------------------------------------------- +numpydoc_xref_param_type = False +numpydoc_show_class_members = False -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = "alabaster" +# -- intersphinx ----------------------------------------------------------- -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -html_theme_options = { - "page_width": "1200px", - "sidebar_width": "300px", +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), + "numpy": ("https://numpy.org/doc/stable", None), + "scipy": ("https://docs.scipy.org/doc/scipy", None), } -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] +# -- Options for HTML output ---------------------------------------------- + +html_theme = "furo" +html_theme_options = { + "navigation_with_keys": True, +} # -- Options for HTMLHelp output ------------------------------------------ -# Output file base name for HTML help builder. htmlhelp_basename = "NonlinearTMMdoc" # -- Options for LaTeX output --------------------------------------------- -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} +latex_elements = {} -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). latex_documents = [ (root_doc, "NonlinearTMM.tex", "NonlinearTMM Documentation", "Ardi Loot", "manual"), ] @@ -145,16 +81,11 @@ # -- Options for manual page output --------------------------------------- -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). man_pages = [(root_doc, "nonlineartmm", "NonlinearTMM Documentation", [author], 1)] # -- Options for Texinfo output ------------------------------------------- -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) texinfo_documents = [ ( root_doc, diff --git a/docs/index.rst b/docs/index.rst index 13ab0da..d3e0bb8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,8 +1,3 @@ -.. NonlinearTMM documentation master file, created by - sphinx-quickstart on Thu Mar 16 11:48:15 2017. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - Welcome to NonlinearTMM's documentation! ######################################## diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 8d2cb19..0000000 --- a/docs/make.bat +++ /dev/null @@ -1,36 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=. -set BUILDDIR=_build -set SPHINXPROJ=NonlinearTMM - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% - -:end -popd diff --git a/pyproject.toml b/pyproject.toml index 5a9d265..39c119f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,17 @@ requires-python = ">=3.10" authors = [ { name = "Ardi Loot", email = "ardi.loot@outlook.com" }, ] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Topic :: Scientific/Engineering :: Physics", +] dynamic = ["version"] dependencies = [ "numpy>=2", @@ -25,7 +36,7 @@ dependencies = [ ] [dependency-groups] -dev = ["pyyaml", "pytest", "pre-commit", "ty", "matplotlib", "sphinx", "numpydoc"] +dev = ["pyyaml", "pytest", "pre-commit", "ty", "matplotlib", "sphinx", "furo", "numpydoc"] [project.urls] Homepage = "https://github.com/ardiloot/NonlinearTMM" diff --git a/uv.lock b/uv.lock index d88a483..6093407 100644 --- a/uv.lock +++ b/uv.lock @@ -7,6 +7,18 @@ resolution-markers = [ "python_full_version < '3.11'", ] +[[package]] +name = "accessible-pygments" +version = "0.0.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bc/c1/bbac6a50d02774f91572938964c582fff4270eee73ab822a4aeea4d8b11b/accessible_pygments-0.0.5.tar.gz", hash = "sha256:40918d3e6a2b619ad424cb91e556bd3bd8865443d9f22f1dcdf79e33c8046872", size = 1377899, upload-time = "2024-05-10T11:23:10.216Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/3f/95338030883d8c8b91223b4e21744b04d11b161a3ef117295d8241f50ab4/accessible_pygments-0.0.5-py3-none-any.whl", hash = "sha256:88ae3211e68a1d0b011504b2ffc1691feafce124b845bd072ab6f9f66f34d4b7", size = 1395903, upload-time = "2024-05-10T11:23:08.421Z" }, +] + [[package]] name = "alabaster" version = "1.0.0" @@ -25,6 +37,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, ] +[[package]] +name = "beautifulsoup4" +version = "4.14.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, +] + [[package]] name = "certifi" version = "2026.1.4" @@ -428,6 +453,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/4e/ce75a57ff3aebf6fc1f4e9d508b8e5810618a33d900ad6c19eb30b290b97/fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371", size = 1148996, upload-time = "2025-12-12T17:31:21.03Z" }, ] +[[package]] +name = "furo" +version = "2025.12.19" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "accessible-pygments" }, + { name = "beautifulsoup4" }, + { name = "pygments" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "sphinx-basic-ng" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ec/20/5f5ad4da6a5a27c80f2ed2ee9aee3f9e36c66e56e21c00fde467b2f8f88f/furo-2025.12.19.tar.gz", hash = "sha256:188d1f942037d8b37cd3985b955839fea62baa1730087dc29d157677c857e2a7", size = 1661473, upload-time = "2025-12-19T17:34:40.889Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/b2/50e9b292b5cac13e9e81272c7171301abc753a60460d21505b606e15cf21/furo-2025.12.19-py3-none-any.whl", hash = "sha256:bb0ead5309f9500130665a26bee87693c41ce4dbdff864dbfb6b0dae4673d24f", size = 339262, upload-time = "2025-12-19T17:34:38.905Z" }, +] + [[package]] name = "identify" version = "2.6.16" @@ -766,6 +809,7 @@ dependencies = [ [package.dev-dependencies] dev = [ + { name = "furo" }, { name = "matplotlib" }, { name = "numpydoc" }, { name = "pre-commit" }, @@ -786,6 +830,7 @@ requires-dist = [ [package.metadata.requires-dev] dev = [ + { name = "furo" }, { name = "matplotlib" }, { name = "numpydoc" }, { name = "pre-commit" }, @@ -1387,6 +1432,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" }, ] +[[package]] +name = "soupsieve" +version = "2.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, +] + [[package]] name = "sphinx" version = "8.1.3" @@ -1480,6 +1534,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/73/f7/b1884cb3188ab181fc81fa00c266699dab600f927a964df02ec3d5d1916a/sphinx-9.1.0-py3-none-any.whl", hash = "sha256:c84fdd4e782504495fe4f2c0b3413d6c2bf388589bb352d439b2a3bb99991978", size = 3921742, upload-time = "2025-12-31T15:09:25.561Z" }, ] +[[package]] +name = "sphinx-basic-ng" +version = "1.0.0b2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/0b/a866924ded68efec7a1759587a4e478aec7559d8165fac8b2ad1c0e774d6/sphinx_basic_ng-1.0.0b2.tar.gz", hash = "sha256:9ec55a47c90c8c002b5960c57492ec3021f5193cb26cebc2dc4ea226848651c9", size = 20736, upload-time = "2023-07-08T18:40:54.166Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/dd/018ce05c532a22007ac58d4f45232514cd9d6dd0ee1dc374e309db830983/sphinx_basic_ng-1.0.0b2-py3-none-any.whl", hash = "sha256:eb09aedbabfb650607e9b4b68c9d240b90b1e1be221d6ad71d61c52e29f7932b", size = 22496, upload-time = "2023-07-08T18:40:52.659Z" }, +] + [[package]] name = "sphinxcontrib-applehelp" version = "2.0.0"