gpe.Examples.piston
===================

.. py:module:: gpe.Examples.piston


Attributes
----------

.. autoapisummary::

   gpe.Examples.piston.u


Classes
-------

.. autoapisummary::

   gpe.Examples.piston.Experiment
   gpe.Examples.piston.PistonMixin
   gpe.Examples.piston.State
   gpe.Examples.piston.StateTube
   gpe.Examples.piston.StateAxial
   gpe.Examples.piston._State


Module Contents
---------------

.. py:data:: u

.. py:class:: Experiment(_local_dict=None, **kw)

   Bases: :py:obj:`gpe.utils.ExperimentBase`


   Base for Experiment classes.

   Inherit from this class to provide an interface to the problem.  It's main role
   should be to accept experimentally relevant parameters, and then produce an
   appropriate initial state that representing the experimental protocol.

   See `gpe.utils.ExperimentExample` for a demonstration of how to use
   this class.

   Note: All times are expressed in terms of `t_unit` such that `t_ =
   t/t_unit`.  We try to consistently use the name `t_` for such dimensionless
   quantities except in class variables which are assumed to be in the
   specified `t_unit`.

   1. Also provides a mechanism for recording time-dependent parameters.
      These should be provided through a set of methods names `*_t_()` which
      take the normalized time `t_` as an argument and return the
      time-dependent value of this parameter.  For plotting purposes an
      accompanying method `*_info()` should be defined which returns the
      corresponding unit value and a label.
   2. Internal methods should use the `get(param, t_)` method which will
      delegate to the appropriate time-dependent function if it exists (or
      fall back to the basic parameter access).

   Simulations and Imaging
   =======================
   The idea of an "Experiment" is some sort of simulation run defined by a set
   of parameters (attributes of this class) that is evolved through a set of
   `image_ts_` under a set of "normal" experimental conditions.  These states would be
   what is observed in "in situ imaging".  Typically, however, from these states, one
   evolves for an additional time `t__image` without any interactions or traps to allow
   the clouds to "expand", after which an "expansion image" is taken, usually resolving
   better details like vortices and domain walls.


   .. py:attribute:: State
      :value: None



   .. py:attribute:: t_unit
      :value: 63.50779925891489



   .. py:attribute:: t_name
      :value: 'ms'



   .. py:attribute:: t__image
      :value: 7



   .. py:attribute:: species


   .. py:attribute:: gs
      :value: None



   .. py:attribute:: trapping_frequencies_Hz
      :value: (2.4, 229.0, 222.0)



   .. py:attribute:: Nx
      :value: None



   .. py:attribute:: Lx
      :value: 464.0



   .. py:attribute:: dx
      :value: 0.071



   .. py:attribute:: Nr
      :value: None



   .. py:attribute:: R
      :value: None



   .. py:attribute:: cooling_phase
      :value: 1.0



   .. py:attribute:: tube
      :value: True



   .. py:attribute:: basis_type
      :value: '1D'



   .. py:attribute:: x_TF
      :value: 200.0



   .. py:attribute:: v_p
      :value: 0.0314921950270423



   .. py:attribute:: r_p
      :value: 4.0



   .. py:attribute:: V_p
      :value: 10.0



   .. py:property:: dim


   .. py:method:: init()

      Overload this to perform any initial computations.



   .. py:method:: get_Vext(state, fiducial=False, expt=False)

      Return the external potential.

      For `state.t > state.t_final`, all the potentials are set to zero.

      :param state: Current state.  Use this to get the time `state.t` and
                    abscissa `state.basis.xyz`.
      :type state: IState
      :param fiducial: If `True`, then return the potential that should be used to
                       define the initial state in terms of the Thomas Fermi
                       radius of the cloud `x_TF`.
      :type fiducial: bool
      :param expt: If `True`, then return the proper experimental potential
                   rather than the potential used in the simulation.
      :type expt: bool

      .. seealso:: * interface.IExperiment.get_Vext



   .. py:method:: get_state(expt=False, initialize=True)

      Quickly return an appropriate initial state.



   .. py:method:: get_initial_state(perturb=0.0, E_tol=1e-12, psi_tol=1e-12, disp=1, tries=20, cool_steps=100, cool_dt_t_scale=0.1, minimize=True, **kw)

      Return an initial state with the specified population fractions.

      This initial state is prepared in state[0] with the potentials as
      they are at time `t=0`, then the `initial_imbalance` is transferred as
      specified simulating an RF pulse by simply the appropriate fraction in each
      state.  Phases are kept the same as in the state[0].



   .. py:method:: get_Vtrap_expt(state, xyz, ws=None)

      Return the external trapping potential used in the experiment.

      This is used to determine the chemical potential and
      `fidcucial_V_TF` from a value of `x_TF`.  It uses the
      experimental trapping frequencies stored in `ws_expt`.

      :param state: Current state.
      :type state: State
      :param xyz: Use these abscissa (not state.xyz) to compute the
                  potential.  This is likely being applied to a much larger
                  state in order to compute the `fiducial_V_TF`.
      :type xyz: [array]
      :param ws: These are the trapping frequencies.  This is just a
                 convenience if your get_Vtrap needs to compute a harmonic
                 potential.
      :type ws: [float]



   .. py:method:: get_Vtrap(state, xyz)

      Return the experimental trapping potential `Vtrap(xyz)`.

      This should return the trapping potential that is used in
      cases, both when determining x_TF, and when cooling into the
      initial state.  It should not include time-dependent potential
      like the bucket that are used for preparing the initial state
      but NOT used when determining x_TF.

      :param state: Current state.
      :type state: State
      :param xyz: Use these abscissa (not state.xyz) to compute the
                  potential.  This is likely being applied to a much larger
                  state in order to compute the `fiducial_V_TF`.
      :type xyz: [array]



   .. py:method:: get_Vt(state)

      Optional time-dependent trapping potentials.

      These potentials are not included in the fiducial state used
      to determine the initial conditions, however, if `Vt` is
      non-zero at time `t=0`, then this *will* be included in the
      initial state preparation.

      .. seealso:: * interface.IExperiment.get_Vext



   .. py:property:: fiducial_V_TF

      This may be slow to calculate, so we defer calculation until we
      really need it.


   .. py:method:: get_fiducial_V_TF(t_=0.0, Nx=2**12, Lx_factor=1.1)

      Return the V_TF required to initialize the state.

      If V_TF is None or not defined, then compute the V_TF that defines the
      state in terms of the Thomas-Fermi radius x_TF along the x axis using a
      Harmonic trapping potential with frequencies `ws_expt` as follows:

      1. Construct an axially symmetric state using a CylindricalBasis with
         enough points to model the harmonically trapped cloud in the TF
         approximation.  The assumption is made here that the extremities of
         the cloud are harmonic.  Inside, the potential need not be
         harmonic.  This construction uses `self.ws_expt`.
      2. Compute `V_TF` from `self.x_TF` and `self.ws_expt` assuming harmonic
         extremities.
      3. Get the external potential using this state by calling
         `get_Vext(expt_state, fiducial=True, expt=True)`.  This allows the
         function `get_Vext()` to customize what is meant by the fiducial
         state (i.e. including or excluding parts of the time-varying
         potential.)
      4. Set the initial state and compute the total particle number in the
         TF approximation using:

         `expt_state.set_initial_state(V_TF=V_TF, fiducial=True, expt=True)`

      5. Adjust V_TF to reproduce the total particle number in the TF
         approximation using:

         `expt_state.set_initial_state(V_TF=V_TF, fiducial=False, expt=True)`

         This allows one to simulate a long time cooling into the ground
         with a different potential, while fixing `x_TF` without that
         potential.



.. py:class:: PistonMixin

   State for piston experiment.

   This class depends on an Experiment() instance to define the time-dependent
   properties.

   In addition, the following attributes are expected in experiments:

   `experiment.t_unit`:
      All experiment times are specified in this unit `t_ = t/t_unit`.
   `state.t_final`:
      For `t > state.t_final`, all the potentials are set to
      zero.
   `experiment.t__image`:
      If imaging is performed (see `image_ts_` in the Simulation class), then
      expansion occurs for this length of time (previously this was
      `t__expand`).


   .. py:attribute:: experiment
      :value: None



   .. py:method:: get_mu_from_V_TF(V_TF)

      Return the corrected chemical potential from V_TF.

      :param V_TF: External potential at the Thomas Fermi "radius".  (The external
                   potential is evaluated at this position and this is used to get
                   `mu`.)
      :type V_TF: float



   .. py:method:: get_V_TF_from_mu(mu)

      Return V_TF from the chemical potential mu.

      :param mu: Physical chemical potential (i.e. what you would pass to the
                 minimizer).
      :type mu: float



   .. py:method:: get_Vext(mu=None, fiducial=False, expt=False)

      Return the external potential).

      This method just delegates to the experiment, and provides some simple
      memoization for performance.

      :param mu: If None, then subtract `self.mu`.  This will minimize the phase
                 rotations during time evolution, but is undesirable when computing
                 initial states.  In the latter case, set `mu=0`.
      :type mu: float, None



   .. py:method:: get_n_TF(V_TF, fiducial=False, expt=False)

      Return the TF densities.  Assumes gaa = gbb = gab and populates only
      the lower band.



   .. py:method:: set_initial_state(V_TF=None, fiducial=False, expt=False)

      Set the state using the Thomas Fermi (TF) approximation.

      This will overload the base class versions to pass the `fiducial` and
      `expt` arguments to the experiments.  See `get_fiducial_V_TF()` for
      details about the meaning of these parameters.  This also sets more
      appropriate phases for the state.

      :param V_TF: Value of the external potential at the Thomas-Fermi "radius".  Note:
                   this is the chemical potential without any corrections from the tube
                   is applied directly to the external potential to get the
                   densities.  These are then transformed into components using the
                   spin-quasimomentum map.
      :type V_TF: float
      :param fiducial: If True, then use the fiducial initial state - i.e. do not
                       include the barrier potential.
      :type fiducial: bool
      :param expt: If True, then initialize the state using experimental
                   parameters.  This is needed, for example, if the desired
                   state is homogeneous (`wx=0`) but we want to initialize the
                   state with the experimental `x_TF` parameter.  the
                   `expt=True` flag should be used when initializing a
                   (typically) larger state with `Lx=Lx_expt` and frequencies
                   `wx=wx_expt` to compute the `fiducial_V_TF` in the presence
                   of a barrier potential.
      :type expt: bool



   .. py:method:: get_ws_perp(t=None)

      Return the frequencies at time `t`.  Required by tube2 classes.



   .. py:property:: t_unit

      Get the time unit from the experiment.


   .. py:property:: g

      Get g from experiment so it can manipulate them.


   .. py:property:: ws

      Get ws from experiment so it can manipulate them.


   .. py:method:: get(name, t_=None)

      Return the value of the parameter `name` at time `self.t`.

      This just delegates to `self.experiment.get()`.



   .. py:method:: get_density_x()

      Return the density along x.

      For periodic boxes, this is the average density in the transverse plane
      (which is the central density if the transverse plane is
      translationally invariant) and the integrated 1D line density for tube
      and axial codes.



.. py:class:: State(experiment, **kw)

   Bases: :py:obj:`PistonMixin`, :py:obj:`gpe.bec.State`


   State for piston experiment.

   This class depends on an Experiment() instance to define the time-dependent
   properties.

   In addition, the following attributes are expected in experiments:

   `experiment.t_unit`:
      All experiment times are specified in this unit `t_ = t/t_unit`.
   `state.t_final`:
      For `t > state.t_final`, all the potentials are set to
      zero.
   `experiment.t__image`:
      If imaging is performed (see `image_ts_` in the Simulation class), then
      expansion occurs for this length of time (previously this was
      `t__expand`).


   .. py:attribute:: experiment


   .. py:attribute:: _time_independent_Vext
      :value: False



   .. py:attribute:: _Vext
      :value: [None, None]



.. py:class:: StateTube(experiment, **kw)

   Bases: :py:obj:`PistonMixin`, :py:obj:`gpe.tube.StateGPEdrZ`


   State for piston experiment.

   This class depends on an Experiment() instance to define the time-dependent
   properties.

   In addition, the following attributes are expected in experiments:

   `experiment.t_unit`:
      All experiment times are specified in this unit `t_ = t/t_unit`.
   `state.t_final`:
      For `t > state.t_final`, all the potentials are set to
      zero.
   `experiment.t__image`:
      If imaging is performed (see `image_ts_` in the Simulation class), then
      expansion occurs for this length of time (previously this was
      `t__expand`).


   .. py:attribute:: single_band
      :value: False



   .. py:attribute:: experiment


   .. py:attribute:: _time_independent_Vext
      :value: False



   .. py:attribute:: _Vext
      :value: [None, None]



.. py:class:: StateAxial(experiment, **kw)

   Bases: :py:obj:`PistonMixin`, :py:obj:`gpe.axial.StateAxial`


   State for piston experiment.

   This class depends on an Experiment() instance to define the time-dependent
   properties.

   In addition, the following attributes are expected in experiments:

   `experiment.t_unit`:
      All experiment times are specified in this unit `t_ = t/t_unit`.
   `state.t_final`:
      For `t > state.t_final`, all the potentials are set to
      zero.
   `experiment.t__image`:
      If imaging is performed (see `image_ts_` in the Simulation class), then
      expansion occurs for this length of time (previously this was
      `t__expand`).


   .. py:attribute:: experiment


   .. py:attribute:: _time_independent_Vext
      :value: False



   .. py:attribute:: _Vext
      :value: [None, None]



.. py:class:: _State(experiment, Nxyz=(256 * 8, ), Lxyz=(250.0 * u.micron, ), x_TF=80 * u.micron, v_p=2 * u.mm / u.s, r_p=4 * u.micron, V_p=10.0, **kw)

   Bases: :py:obj:`gpe.tube.StateGPEdrZ`


   Effective 1D model for the GPE in harmonic cigars.

   This class combines the NPSEQ to derive an effective 1D equation for the dynamics of
   a harmonically trapped cloud with the scaling solution of Castin and Dum to allow
   for expansion dynamics.


   .. py:attribute:: twist
      :value: 0



   .. py:attribute:: experiment


   .. py:attribute:: v_p
      :value: 0.0314921950270423



   .. py:attribute:: x_p0
      :value: 125.0



   .. py:attribute:: r_p
      :value: 4.0



   .. py:attribute:: V_p
      :value: 10.0



   .. py:method:: get_ws_perp(t)


   .. py:method:: get_Vext()


