{ "info": { "author": "Sigvald Marholm", "author_email": "marholm@marebakken.com", "bugtrack_url": null, "classifiers": [ "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "Langmuir\n========\n\n.. image:: https://travis-ci.com/langmuirproject/langmuir.svg?branch=master\n :target: https://travis-ci.com/langmuirproject/langmuir\n\n.. image:: https://coveralls.io/repos/github/langmuirproject/langmuir/badge.svg?branch=master\n :target: https://coveralls.io/github/langmuirproject/langmuir?branch=master\n\n.. image:: https://img.shields.io/pypi/pyversions/langmuir.svg\n :target: https://pypi.org/project/langmuir\n\n.. image:: https://zenodo.org/badge/149759145.svg\n :target: https://zenodo.org/badge/latestdoi/149759145\n\nProgrammatically accessible current-voltage characteristics for ideal and non-ideal Langmuir probes.\n\nInstallation\n------------\nInstall from PyPI using ``pip`` (preferred method)::\n\n pip install langmuir\n\nOr download the GitHub repository https://github.com/langmuirproject/langmuir.git and run::\n\n python setup.py install\n\nGetting Started\n---------------\nThe Langmuir library contains a collection of functions that compute the current collected by a Langmuir probe according to various theories and models. These functions take as arguments the probe geometry, for instance ``Cylinder``, and a plasma, where a plasma may consist of one or more ``Species``.\n\nAs an example, consider a 25mm long cylindrical probe with radius 0.255mm. The plasma consists of electrons and singly charged oxygen ions, both with a density of 1e11 and a temperature of 1000K. The current-voltage charactersitic according to OML theory is easily computed and plotted::\n\n >>> from langmuir import *\n >>> import numpy as np\n >>> import matplotlib.pyplot as plt\n\n >>> plasma = []\n >>> plasma.append(Species('electron' , n=1e11, T=1000))\n >>> plasma.append(Species(amu=16, Z=1, n=1e11, T=1000))\n\n >>> Vs = np.linspace(-2, 2, 100)\n >>> Is = OML_current(Cylinder(r=0.255e-3, l=25e-3), plasma, Vs)\n\n >>> fig = plt.figure()\n >>> ax = fig.add_subplot(111)\n\n >>> ax.plot(Vs, -Is*1e6)\n >>> ax.set_xlabel(r'$V_{\\mathrm{p}} [\\mathrm{V}]$')\n >>> ax.set_ylabel(r'$I_{\\mathrm{p}} [\\mathrm{\\mu A}]$')\n >>> ax.grid(True)\n >>> plt.show()\n\n.. image:: IV_characteristics.png\n\nNotice that the characteristic includes all regions (ion saturation, electron retardation and electron saturation), and do not rely on approximations to the OML theory requiring the voltage to be within a certain range. What's more, it's easy to take into account for instance finite-radius effects, by replacing ``OML_current()`` with ``finite_radius_current()``.\n\nSpecifying a species\n--------------------\nA species is specified using a range of keyword arguments upon initialization of a ``Species`` object.\nAt the very least, you must specify the density and the temperature (or thermal speed)::\n\n >>> Species(n=1e11, T=1000)\n\nSince nothing more is specified, this represents Maxwellian-distributed electrons. The full set of keywords is as follows:\n\n+---------------------------+-----------+--------------------------+------------------+\n| Quantity | Keyword | Units | Default value |\n+===========================+===========+==========================+==================+\n| Charge | ``q`` | Coulombs | electron |\n| +-----------+--------------------------+ charge |\n| | ``Z`` | elementary charges | |\n+---------------------------+-----------+--------------------------+------------------+\n| Mass | ``m`` | kilograms | electron |\n| +-----------+--------------------------+ mass |\n| | ``amu`` | atomic mass units | |\n+---------------------------+-----------+--------------------------+------------------+\n| Density | ``n`` | partices per cubic meter | |\n+---------------------------+-----------+--------------------------+------------------+\n| Temperature/thermal speed | ``T`` | Kelvin | |\n| +-----------+--------------------------+ |\n| | ``eV`` | electron-volts | |\n| +-----------+--------------------------+ |\n| | ``vth`` | meters per second | |\n+---------------------------+-----------+--------------------------+------------------+\n| Spectral index kappa | ``kappa`` | dimensionless | ``float('inf')`` |\n+---------------------------+-----------+--------------------------+------------------+\n| Spectral index alpha | ``alpha`` | dimensionless | ``0`` |\n+---------------------------+-----------+--------------------------+------------------+\n\nThe Langmuir library supports the general Kappa-Cairns velocity distribution, but defaults to Maxwellian, which is a special case of the Kappa-Cairns distribution.Kappa, Cairns or Kappa-Cairns distributed particles are obtained by specifying ``kappa``, ``alpha`` or both, respectively.\n\nThe charge and mass can also be specified using one of three self-descriptive flag:\n\n- ``'electron'``\n- ``'positron'``\n- ``'proton'``\n\nThis must come before the keyword arguments, for instance::\n\n >>> Species('proton', n=1e11, eV=0.1)\n\nComputing fundamental plasma parameters\n---------------------------------------\nThe Langmuir library is also convenient to use for quick computations of fundamental plasma parameters, since ``Species`` computes these upon initialization. For instance, to get the electron Debye length of a plasma with a certain density and temperature::\n\n >>> Species(n=1e11, eV=0.1).debye\n 0.007433942027347403\n\nThe following member variables and methods are accessible in ``Species``:\n\n+-----------------+---------------------------------+\n| Member | Description |\n+=================+=================================+\n| ``debye`` | The Debye length |\n+-----------------+---------------------------------+\n| ``omega_p`` | The angular plasma frequency |\n+-----------------+---------------------------------+\n| ``freq_p`` | The linear plasma frequency |\n+-----------------+---------------------------------+\n| ``period_p`` | The plasma period |\n+-----------------+---------------------------------+\n| ``omega_c(B)`` | The angular cyclotron frequency |\n+-----------------+---------------------------------+\n| ``freq_c(B)`` | The linear cyclotron frequency |\n+-----------------+---------------------------------+\n| ``period_c(B)`` | The cyclotron period |\n+-----------------+---------------------------------+\n| ``larmor(B)`` | The larmor radius |\n+-----------------+---------------------------------+\n\nThe latter four members are methods which take the magnitude of the magnetic flux density as an argument. In addition, every valid keyword argument is also a valid member variable::\n\n >>> Species(n=1e11, T=1000).eV\n 0.08617330337217212\n\nFinally, the total Debye length of a plasma consisting of multiple species can be obtained using the ``debye()`` function::\n\n >>> plasma = []\n >>> plasma.append(Species('electron' , n=1e11, T=1000))\n >>> plasma.append(Species(amu=16, Z=1, n=1e11, T=1000))\n >>> debye(plasma)\n 0.004879671013271479\n\nSpecifying the geometry\n-----------------------\nLangmuir supports two probe geometries, with self-descriptive names and the following signatures:\n\n- ``Sphere(r)``\n- ``Cylinder(r, l)``\n\n``r`` and ``l`` representes the radius and length, respectively, of the geometry.\n\nModels for collected current\n----------------------------\nLangmuir comes with several models for the collected current. Each model is represented by a function which takes a ``geometry`` and a ``species`` argument. The ``geometry`` is one of the above probe geometries, and the ``species`` parameters is either a single ``Species`` object or a list of such if it is desirable to take into account the effect of all species in a plasma. Most models also depend on the potential of the probe with respect to the background plasma. The potential can either be specified in volts using th ``V`` argument, or in terms of normalized voltage e*V/(k*T) using the ``eta`` argument. If these are Numpy arrays, the output will be a Numpy array of collected currents. The ``normalization`` argument can be set to ``'th'``, ``'thmax'``, ``'oml'`` to return currents normalized by the thermal current, Maxwellian thermal current, or OML current, respectively, rather than Amp\u00e9re. Below is a description of all models:\n\n- ``OML_current(geometry, species, V=None, eta=None, normalization=None)``\n Current collected by a probe according to the Orbital Motion Limited (OML)\n theory. The model assumes a probe of infinitely small radius compared to\n the Debye length, and for a cylindrical probe, that it is infinitely long.\n Probes with radii up to 0.2 Debye lengths (for spherical probes) or 1.0\n Debye lengths (for cylindrical probes) are very well approximated by this\n theory, although the literature is diverse as to how long cylindrical probes\n must be for this theory to be a good approximation.\n\n- ``finite_radius_current(geometry, species, V=None, eta=None, table='laframboise-darian-marholm', normalization=None)``\n A current model taking into account the effects of finite radius by\n interpolating between tabulated normalized currents. The model only\n accounts for the attracted-species currents (for which eta<0). It does\n not extrapolate, but returns ``nan`` when the input parameters are outside\n the domain of the model. This happens when the normalized potential for any\n given species is less than -25, when kappa is less than 4, when alpha is\n more than 0.2 or when the radius is more than 10 or sometimes all the way\n up towards 100 (as the distribution approaches Maxwellian). Normally finite\n radius effects are negligible for radii less than 0.2 Debye lengths (spheres)\n or 1.0 Debye lengths (cylinders).\n\n- ``finite_length_current(geometry, species, V=None, eta=None, normalization=None)``\n The Marholm-Marchand model for finite-length probes. Works for normalized\n voltages up to 100.\n\n- ``finite_length_current_density(geometry, species, V=None, eta=None, z=None, zeta=None, normalization=None)``\n The current per unit length according to the Marholm-Marchand model for\n finite-length probes. Works for normalized voltages up to 100. ``z`` is\n position on the probe, and ``zeta`` is position normalized by the Debye\n length.\n\n- ``thermal_current(geometry, species, normalization=None)``\n Returns the thermal current for the given species and geometry. The\n thermal current is the current the species contributes to a probe at zero\n potential with respect to the background plasma due to random thermal\n movements of particles.\n\n- ``normalization_current(geometry, species)``\n Returns the normalization current for the given species and geometry.\n The normalization current is the current the species would have contributed\n to a probe at zero potential with respect to the background plasma due to\n random thermal movements of particles, if the species had been Maxwellian.\n\nAs an example, the following snippet computes the normalized electron current of a probe of 3 Debye lengths radius and normalized voltage of -10::\n\n >>> sp = Species(n=1e11, T=1000)\n >>> geo = Cylinder(r=3*sp.debye, l=1)\n >>> I = finite_radius_current(geo, sp, eta=-10, normalization='th')\n\nNotice that setting ``l==1`` means you get the current per unit length.\n\nInverse problems\n----------------\nSometimes the collected current of one or more probes is known and one would like to solve for one or more other parameters. The Langmuir library do not address this analytically in part due to the vast number of such inverse problems, and in part due to some characteristics not being invertible (for instance those who are of tabulated values). However, it is in principle possible to apply numerical methods of root solving, least squares, etc. along with the models in Langmuir.\n\nConsider a cylindrical probe with known dimensions and a positive but unknown voltage collecting a current of -0.4uA in a Maxwellian plasma with known density and temperature. What is the voltage? We shall neglect the current due to ions, and define a residual function. This residual is the difference between the current collected by a probe at a given potential, and the actual collected current, and it is used by a least squares algorithm to compute the voltage::\n\n >>> from langmuir import *\n >>> from scipy.optimize import leastsq\n\n >>> sp = Species(n=1e11, T=1000)\n >>> geo = Cylinder(1e-3, 25e-3)\n >>> I = -0.4e-6\n\n >>> def residual(V):\n >>> return finite_radius_current(geo, sp, V) - I\n\n >>> x, c = leastsq(residual, 0)\n >>> print(x[0])\n 0.6265540484991013\n\nThe reader may verify that this voltage indeed results in the correct current. Notice also that we were in fact able to invert the model ``finite_radius_current``, which consists of tabulated values.\n\nA slightly more interesting inversion problem, is that of determining the ionospheric density from four cylindrical Langmuir probes with known bias voltages with respect to a spacecraft, but an unknown floating potential ``V0`` of the spacecraft with respect to the plasma. We shall assume the bias voltages to be 2.5, 4.0, 5.5 and 7.0 volts. In the below example, we first construct the currents for such probes by assuming a floating potential and a set of plasma parameters, but we do not use this knowledge in the inversion. We do, however, make an initial guess ``x0`` which we believe are somewhat close to the answer::\n\n >>> from langmuir import *\n >>> from scipy.optimize import leastsq\n\n >>> geo = Cylinder(1e-3, 25e-3)\n >>> V0 = -0.5\n >>> V = np.array([2.5, 4.0, 5.5, 7.0])\n >>> I = OML_current(geo, Species(n=120e10, T=1000), V+V0)\n\n >>> def residual(x):\n >>> n, V0 = x\n >>> return OML_current(geo, Species(n=n, T=1500), V+V0) - I\n\n >>> x0 = [10e10, -0.3]\n >>> x, c = leastsq(residual, x0)\n >>> n, V0 = x\n\n >>> print(n)\n 1199899818493.931\n\n >>> print(V0)\n -0.5417515655165968\n\nThe method correctly determined the density to be 120e10. However, the floating potential ``V0`` is off by almost ten percent. The reason is that the temperature is considered unknown, and assumed to be 1500K when solving the problem, while it is actually 1000K. Since we have four measurements (four equations) and only two unknowns, it is tempting to also include the temperature as an unknown parameter and try to solve for it. However, if this is done the least squares algorithm will fail miserably. The reason is that the set of equations arising for the attracted-species current of cylindrical probes are singular and cannot be solved for even analytically. Fortunately, both the temperature and floating potential can be eliminated from the equation when analytically solving for the density, and similarly it also works to obtain the density from the least squares algorithm. Since the floating potential and temperature represent a coupled unknown which cannot be solved for, an error in assuming one is reflected as an error in the other.\n\nThis demonstrates the usefulness as well as challenges and subtleties of solving inverse Langmuir problems.", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/sigvaldm/langmuir.git", "keywords": "", "license": "LGPL", "maintainer": "", "maintainer_email": "", "name": "langmuir", "package_url": "https://pypi.org/project/langmuir/", "platform": "", "project_url": "https://pypi.org/project/langmuir/", "project_urls": { "Homepage": "https://github.com/sigvaldm/langmuir.git" }, "release_url": "https://pypi.org/project/langmuir/0.6.0/", "requires_dist": null, "requires_python": "", "summary": "Functions for work on Langmuir probe theory", "version": "0.6.0" }, "last_serial": 5902102, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "45c6de5d0e49e9ebfe1da26448bdec76", "sha256": "e4415186378b3d21fdeacd3024fab3ca053305e57809ace174c39af5b4020aac" }, "downloads": -1, "filename": "langmuir-0.1.0.tar.gz", "has_sig": false, "md5_digest": "45c6de5d0e49e9ebfe1da26448bdec76", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2666, "upload_time": "2018-09-21T12:56:28", "url": "https://files.pythonhosted.org/packages/f6/99/2cdfea11f47c2e20ed6d8d5982909706e2ccd34867188233335dc3a0f487/langmuir-0.1.0.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "8d2bf0a3c769590475dfd7e5af171768", "sha256": "2d372ef5a8c8828b091f24c88c2616ab801e1be4890ce225558b3b3e3080fb76" }, "downloads": -1, "filename": "langmuir-0.2.0.tar.gz", "has_sig": false, "md5_digest": "8d2bf0a3c769590475dfd7e5af171768", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3841, "upload_time": "2018-09-21T14:35:03", "url": "https://files.pythonhosted.org/packages/ab/d4/dd93648afd20fbea2cefc913895d916b4d1e796cf98202e384f40aaa60f0/langmuir-0.2.0.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "dbac1178b6f2c825d208565f1106d9a6", "sha256": "fd1341fc8161e4e9f4bf3795bc1d8c5b480cf05fd1aba2023a90f50aa68c9690" }, "downloads": -1, "filename": "langmuir-0.3.0.tar.gz", "has_sig": false, "md5_digest": "dbac1178b6f2c825d208565f1106d9a6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26039, "upload_time": "2018-12-18T18:22:44", "url": "https://files.pythonhosted.org/packages/63/bf/20cda8855a65d2d62e199eeee872248ab909b976414894da45d1c9b6b846/langmuir-0.3.0.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "1b1924d841632831440ab9fb87702be7", "sha256": "855d95116ff534b48c4540e709ea9533df0c9e55be5c31be5bd12b0190233918" }, "downloads": -1, "filename": "langmuir-0.4.0.tar.gz", "has_sig": false, "md5_digest": "1b1924d841632831440ab9fb87702be7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31043, "upload_time": "2019-07-04T09:44:15", "url": "https://files.pythonhosted.org/packages/c4/7f/590d832f55addf0402c7d87606c6bf70a51b02e5df58fe5776a2e4323c78/langmuir-0.4.0.tar.gz" } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "9a41cb0572243c821085fe76a004f504", "sha256": "ae5cc9d55a5dbd11d27b6f1f2a8a4087965d34f45b70c92551d814db52533ecf" }, "downloads": -1, "filename": "langmuir-0.5.0.tar.gz", "has_sig": false, "md5_digest": "9a41cb0572243c821085fe76a004f504", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30945, "upload_time": "2019-08-27T12:50:22", "url": "https://files.pythonhosted.org/packages/93/22/b708ff6f3ff929434af4db15877c44f03ab4e11d84a51b9aa8791acd5931/langmuir-0.5.0.tar.gz" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "18a58135cc6b7f0c8197b0f31cde8a18", "sha256": "03f4bd527b323c72e13c31352a1f82eddc0549f6a6728bfb44dc459e0f464eb6" }, "downloads": -1, "filename": "langmuir-0.6.0.tar.gz", "has_sig": false, "md5_digest": "18a58135cc6b7f0c8197b0f31cde8a18", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31972, "upload_time": "2019-09-29T08:28:06", "url": "https://files.pythonhosted.org/packages/16/c4/149ac00d2bc3339968525e5576ca804dcb4b1470b5a4339d1d4d7ecb0eb2/langmuir-0.6.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "18a58135cc6b7f0c8197b0f31cde8a18", "sha256": "03f4bd527b323c72e13c31352a1f82eddc0549f6a6728bfb44dc459e0f464eb6" }, "downloads": -1, "filename": "langmuir-0.6.0.tar.gz", "has_sig": false, "md5_digest": "18a58135cc6b7f0c8197b0f31cde8a18", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31972, "upload_time": "2019-09-29T08:28:06", "url": "https://files.pythonhosted.org/packages/16/c4/149ac00d2bc3339968525e5576ca804dcb4b1470b5a4339d1d4d7ecb0eb2/langmuir-0.6.0.tar.gz" } ] }