{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# 2D Streamlines {#2d_streamlines_example}\n\nIntegrate a vector field to generate streamlines on a 2D surface.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        ""
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "This example generates streamlines of flow around a cylinder in cross\nflow.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import pyvista as pv\nfrom pyvista import examples"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "The data is multiblock with the fluid data as the first block. The data\nlies in the [xy]{.title-ref} plane, i.e. [z=0]{.title-ref}, with no\n[z]{.title-ref} velocity.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "mesh = examples.download_cylinder_crossflow()\nfluid_mesh = mesh[0]\nprint(fluid_mesh)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "The default behavior of the `streamlines()\n<pyvista.DataSetFilters.streamlines>`{.interpreted-text role=\"func\"}\nfilter is to use a 3D sphere source as the seed points. This often will\nnot generate any seed points on the 2D plane of interest. Instead, a\nsingle streamline can be generated using the `start_position` argument.\nThe `surface_streamlines=True` argument is also needed if the dataset\nhas nonzero normal velocity component. This is not the case in this\ndataset.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "one_streamline = fluid_mesh.streamlines(\n    start_position=(0.0, 0.4, 0.0),\n    max_time=100.0,\n    compute_vorticity=False,  # vorticity already exists in dataset\n)\n\nclim = [0, 20]\ncamera_position = [(7, 0, 20.0), (7, 0.0, 0.0), (0.0, 1.0, 0.0)]\n\np = pv.Plotter()\nfor i in range(1, len(mesh)):\n    p.add_mesh(mesh[i], color='k')\np.add_mesh(one_streamline.tube(radius=0.05), scalars=\"vorticity_mag\", clim=clim)\np.view_xy()\np.show(cpos=camera_position)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "To generate multiple streamlines, a line source can be used with the\n`pointa` and `pointb` parameters.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "line_streamlines = fluid_mesh.streamlines(\n    pointa=(0, -5, 0),\n    pointb=(0, 5, 0),\n    n_points=25,\n    max_time=100.0,\n    compute_vorticity=False,  # vorticity already exists in dataset\n)\n\np = pv.Plotter()\nfor i in range(1, len(mesh)):\n    p.add_mesh(mesh[i], color='k')\np.add_mesh(line_streamlines.tube(radius=0.05), scalars=\"vorticity_mag\", clim=clim)\np.view_xy()\np.show(cpos=camera_position)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "The behavior immediately downstream of the cylinder is still not\napparent using streamlines at the inlet.\n\nAnother method is to use `streamlines_evenly_spaced_2D()\n<pyvista.DataSetFilters.streamlines_evenly_spaced_2D>`{.interpreted-text\nrole=\"func\"}. This filter only works with 2D data that lies on the xy\nplane. This method can quickly run of memory, so particular attention\nmust be paid to the input parameters. The defaults are in cell length\nunits.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "line_streamlines = fluid_mesh.streamlines_evenly_spaced_2D(\n    start_position=(4, 0.1, 0.0),\n    separating_distance=3,\n    separating_distance_ratio=0.2,\n    compute_vorticity=False,  # vorticity already exists in dataset\n)\n\np = pv.Plotter()\nfor i in range(1, len(mesh)):\n    p.add_mesh(mesh[i], color='k')\np.add_mesh(line_streamlines.tube(radius=0.02), scalars=\"vorticity_mag\", clim=clim)\np.view_xy()\np.show(cpos=camera_position)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "The streamlines are only approximately evenly spaced and capture the\nvortex pair downstream of the cylinder with appropriate choice of\n`start_position`.\n"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.2"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}