.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "tutorial/polar_transform.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_tutorial_polar_transform.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_tutorial_polar_transform.py:


=========================
Polar Transformation
=========================

.. GENERATED FROM PYTHON SOURCE LINES 7-17

As another example, if we were interested in transforming Cartesian coordinates to polar form:

.. math::
   \begin{align}
   p_r &= \sqrt{x^2 + y^2} \\
   p_{\theta} &= \tan^{-1}\left(\frac{y}{x}\right)
   \end{align}

We can implement this with an ``ExplicitSystem`` by declaring the inputs and outputs
of this system as follows:

.. GENERATED FROM PYTHON SOURCE LINES 17-29

.. code-block:: Python


    import condor as co
    from condor.backend import operators as ops
    class PolarTransform(co.ExplicitSystem):
        x = input()
        y = input()

        output.r = ops.sqrt(x**2 + y**2)
        #output.theta = ops.atan2(y, x)
        output.theta = ops.atan(y/x)









.. GENERATED FROM PYTHON SOURCE LINES 30-32

In general, once you've defined any system in Condor, you can just evaulate it
numerically by passing in numbers:

.. GENERATED FROM PYTHON SOURCE LINES 32-36

.. code-block:: Python


    p = PolarTransform(x=3, y=4)
    print(p)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    <PolarTransform: x=3, y=4>




.. GENERATED FROM PYTHON SOURCE LINES 37-42

The output returned by such a call is designed for inspection to the extent that we
recommend working in an interactive session or debugger, especially when getting
accustomed to Condor features.

For example, the outputs of an explicit system are accessible directly:

.. GENERATED FROM PYTHON SOURCE LINES 42-45

.. code-block:: Python


    print(p.r)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    [5.]




.. GENERATED FROM PYTHON SOURCE LINES 46-47

They can also be retrieved collectively:

.. GENERATED FROM PYTHON SOURCE LINES 47-50

.. code-block:: Python


    print(p.output)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    PolartransformOutput(r=array([5.]), theta=array([0.92729522]))




.. GENERATED FROM PYTHON SOURCE LINES 51-52

You can of course call it again with different arguments

.. GENERATED FROM PYTHON SOURCE LINES 52-56

.. code-block:: Python


    print(PolarTransform(x=1, y=0).output.asdict())






.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    {'r': array([1.]), 'theta': array([0.])}




.. GENERATED FROM PYTHON SOURCE LINES 57-72

While the *binding* of the results in a datastructure is nice, the real benefit of
constructing condor models is in calling iterative solvers. For example, we could
perform symbolic manipulation to define  another ``ExplicitSystem`` with :math:`x =
r\cos\theta` and :math:`y = r\sin\theta`. Or we can we use Condor to
numerically solve this algebraic system of equations using an ``AlgebraicSystem`` by
declaring the input radius and angle as ``parameter``\s and the solving variables for
:math:`x` and :math:`y`. Mathematically, we are defining the system of algebraic
equations 

.. math::
   r &= p_r (x^*, y^*) \\
   \theta &= p_{\theta} (x^*, y^*)

and letting an iterative solver find the solution :math:`x^*,y^*` satisfying both
residual equations given parameters :math:`r` and :math:`\theta`. In Condor,

.. GENERATED FROM PYTHON SOURCE LINES 72-93

.. code-block:: Python


    class CartesianTransform(co.AlgebraicSystem):
        # r and theta are input parameters
        r = parameter()
        theta = parameter()

        # solver will vary x and y to satisfy the residuals
        x = variable(initializer=1)
        y = variable(initializer=0)

        # get r, theta from solver's x, y
        p = PolarTransform(x=x, y=y)

        # residuals to converge to 0
        residual(r == p.r)
        residual(theta == p.theta)


    out = CartesianTransform(r=1, theta=ops.pi / 4)
    print(out.x, out.y)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    [0.70710678] [0.70710678]




.. GENERATED FROM PYTHON SOURCE LINES 94-100

Note also that passing the inputs (or any intermediates) to plain numeric functions
that can handle symbolic objects as well as pure numerical objects (float or numpy
arrays) could work for this simple example. However, since we *embedded* the
``PolarTransform`` model in this solver, the system evaluated with the solved variable
values is directly accessible if the ``bind_embedded_models`` option is ``True``
(which it is by default), as in:

.. GENERATED FROM PYTHON SOURCE LINES 100-104

.. code-block:: Python



    print(out.p.output)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    PolartransformOutput(r=array([1.]), theta=array([0.78539816]))




.. GENERATED FROM PYTHON SOURCE LINES 105-110

Note that this has multiple solutions due to the form of the algebraic relationship of
the polar/rectangular transformation. The :class:`AlgebraicSystem` uses Newton's
method as the solver, so the solution that is found depends on the initial conditions.
The :attr:`initializer` attribute on the :attr:`variable` field determines the initial
position. For example,

.. GENERATED FROM PYTHON SOURCE LINES 110-116

.. code-block:: Python


    CartesianTransform.set_initial(x=-1, y=-1)
    out = CartesianTransform(r=1, theta=ops.pi / 4)
    print(out.variable)






.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    CartesiantransformVariable(x=array([-0.70710678]), y=array([-0.70710678]))




.. GENERATED FROM PYTHON SOURCE LINES 117-119

An additional :attr:`warm_start` attribute determines whether the initializer is
over-wrriten. Since the default is true, we can inspect the initializer values, 

.. GENERATED FROM PYTHON SOURCE LINES 119-122

.. code-block:: Python


    print(CartesianTransform.x.initializer, CartesianTransform.y.initializer)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    [-0.70710678] [-0.70710678]




.. GENERATED FROM PYTHON SOURCE LINES 123-124

and re-solve with attr:`warm_start` False

.. GENERATED FROM PYTHON SOURCE LINES 124-127

.. code-block:: Python


    CartesianTransform.y.warm_start = False 









.. rst-class:: sphx-glr-timing

   **Total running time of the script:** (0 minutes 0.025 seconds)


.. _sphx_glr_download_tutorial_polar_transform.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: polar_transform.ipynb <polar_transform.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: polar_transform.py <polar_transform.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: polar_transform.zip <polar_transform.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_