Exemplo n.º 1
0
    def initialize_magnetic_fields(self):

        if ('initialize_B' in dir(self.initialize)):

            B1, B2, B3 = self.initialize.initialize_B(self.q1_center,
                                                      self.q2_center,
                                                      self.params)

        # elif('initialize_A' in dir(self.initialize)):

        #     A1, A2, A3 = self.initialize.initialize_A(self.q1_center,
        #                                               self.q2_center,
        #                                               self.params
        #                                              )

        #     A1_hat = 2 * fft2(A1) / (self.N_q1 * self.N_q2)
        #     A2_hat = 2 * fft2(A2) / (self.N_q1 * self.N_q2)
        #     A3_hat = 2 * fft2(A3) / (self.N_q1 * self.N_q2)

        #     B1 =  ifft2(A3_hat * 1j * self.k_q2)
        #     B2 = -ifft2(A3_hat * 1j * self.k_q1)
        #     B3 =  ifft2(A2_hat * 1j * self.k_q1 - A1_hat * 1j * self.k_q2)

        elif ('initialize_A3_B3' in dir(self.initialize)):

            A3 = self.initialize.initialize_A3_B3(self.q1_center,
                                                  self.q2_center,
                                                  self.params)[0]

            A3_hat = fft2(A3)

            B1 = ifft2(A3_hat * 1j * self.k_q2)
            B2 = -ifft2(A3_hat * 1j * self.k_q1)

            B3 = self.initialize.initialize_A3_B3(self.q1_center,
                                                  self.q2_center,
                                                  self.params)[1]
            B3 = af.cast(B3, af.Dtype.c64)

        else:
            raise NotImplementedError(
                'Initialization method for magnetic fields not valid/found')

        af.eval(B1, B2, B3)
        return (B1, B2, B3)
Exemplo n.º 2
0
    def get_dist_func(self):
        """
        Returns the distribution function in the same
        format as the nonlinear solver thereby allowing
        direct comparison with the distribution funcition
        of the nonlinear solver.
        """
        f = 0.5 * self.N_q2 * self.N_q1 * \
            af.real(ifft2(self.f_hat))

        return(f)
Exemplo n.º 3
0
def dump_distribution_function(self, file_name):
    """
    This function is used to dump distribution function to a file for
    later usage.This dumps the complete 5D distribution function which
    can be used for post-processing

    Parameters
    ----------

    file_name : The distribution_function array will be dumped to this
                provided file name.

    Returns
    -------

    This function returns None. However it creates a file 'file_name.h5',
    containing the data of the distribution function

    Examples
    --------
    
    >> solver.dump_distribution_function('distribution_function')

    The above statement will create a HDF5 file which contains the
    distribution function. The data is always stored with the key 
    'distribution_function'

    This can later be accessed using

    >> import h5py
    
    >> h5f = h5py.File('distribution_function', 'r')
    
    >> f   = h5f['distribution_function'][:]
    
    >> h5f.close()

    Alternatively, it can also be used with the load function to resume
    a long-running calculation.

    >> solver.load_distribution_function('distribution_function')
    """
    array_to_dump = 0.5 * self.N_q2 * self.N_q1 * af.real(ifft2(self.f_hat))
    array_to_dump.to_ndarray(self._glob_f_array)

    viewer = PETSc.Viewer().createHDF5(file_name + '.h5', 'w')
    viewer(self._glob_f)
Exemplo n.º 4
0
def RK5_step(self, dt):
    """
    Evolves the physical system defined using an RK5
    integrator. This method is 5th order accurate.

    Parameters
    ----------

    dt: double
        The timestep size.

    """
    # For purely collisional cases:
    if (self.physical_system.params.instantaneous_collisions == True):

        f0 = self._source(
            0.5 * self.N_q1 * self.N_q2 * af.real(ifft2(self.f_hat)),
            self.time_elapsed, self.q1_center, self.q2_center, self.p1_center,
            self.p2_center, self.p3_center, self.compute_moments,
            self.physical_system.params, True)

        self.f_hat = 2 * fft2(f0) / (self.N_q1 * self.N_q2)

    if (self.physical_system.params.fields_enabled == True
            and self.physical_system.params.fields_type == 'electrodynamic'):
        # Since the fields and the distribution function are coupled,
        # we evolve the system by making use of a coupled integrator
        # which ensures that throughout the timestepping they are
        # evaluated at the same temporal locations.
        self.f_hat, self.fields_solver.fields_hat = \
            integrators.RK5_coupled(df_hat_dt, self.f_hat,
                                    dfields_hat_dt, self.fields_solver.fields_hat,
                                    dt, self
                                   )
        af.eval(self.f_hat)
        af.eval(self.fields_solver.fields_hat)

    else:
        self.f_hat = integrators.RK5(df_hat_dt, self.f_hat, dt,
                                     self.fields_solver.fields_hat, self)
        af.eval(self.f_hat)

    return
Exemplo n.º 5
0
time_array = np.arange(0, params.t_final + dt, dt)
n_data_nls = np.zeros([time_array.size])
n_data_ls = np.zeros([time_array.size])
E_data_nls = np.zeros([time_array.size])
E_data_ls = np.zeros([time_array.size])

# Storing data at time t = 0:
n_data_nls[0] = af.max(
    nls.compute_moments('density')[:, :, N_g:-N_g, N_g:-N_g])
n_data_ls[0] = af.max(ls.compute_moments('density'))

E_data_nls[0] = af.max(nls.fields_solver.cell_centered_EM_fields[:, :,
                                                                 N_g:-N_g,
                                                                 N_g:-N_g])

E1_ls = af.real(0.5 * (ls.N_q1 * ls.N_q2) * ifft2(ls.fields_solver.E1_hat))

E_data_ls[0] = af.max(E1_ls)

for time_index, t0 in enumerate(time_array[1:]):

    print('Computing For Time =', t0)
    nls.strang_timestep(dt)
    # ls.RK5_timestep(dt)

    n_data_nls[time_index + 1] = af.max(
        nls.compute_moments('density')[:, :, N_g:-N_g, N_g:-N_g])
    n_data_ls[time_index + 1] = af.max(ls.compute_moments('density'))

    E_data_nls[time_index + 1] = \
        af.max(nls.fields_solver.cell_centered_EM_fields[:, :, N_g:-N_g, N_g:-N_g])
Exemplo n.º 6
0
def dfields_hat_dt(f_hat, fields_hat, self):
    """
    Returns the value of the derivative of the fields_hat with respect to time 
    respect to time. This is used to evolve the fields with time. 
    
    NOTE:All the fields quantities are included in fields_hat as follows:

    E1_hat = fields_hat[0]
    E2_hat = fields_hat[1]
    E3_hat = fields_hat[2]

    B1_hat = fields_hat[3]
    B2_hat = fields_hat[4]
    B3_hat = fields_hat[5]

    Input:
    ------

      f_hat  : Fourier mode values for the distribution function at which the slope is computed
               At t = 0 the initial state of the system is passed to this function:

      fields_hat  : Fourier mode values for the fields at which the slope is computed
                    At t = 0 the initial state of the system is passed to this function:

    Output:
    -------
    df_dt : The time-derivative of f_hat
    """
    eps = self.physical_system.params.eps
    mu = self.physical_system.params.mu

    B1_hat = fields_hat[3]
    B2_hat = fields_hat[4]
    B3_hat = fields_hat[5]

    if (self.physical_system.params.hybrid_model_enabled == True):

        # curlB_x =  dB3/dq2
        curlB_1 = B3_hat * 1j * self.k_q2
        # curlB_y = -dB3/dq1
        curlB_2 = -B3_hat * 1j * self.k_q1
        # curlB_z = (dB2/dq1 - dB1/dq2)
        curlB_3 = (B2_hat * 1j * self.k_q1 - B1_hat * 1j * self.k_q2)

        # c --> inf limit: J = (∇ x B) / μ
        J1_hat = curlB_1 / mu
        J2_hat = curlB_2 / mu
        J3_hat = curlB_3 / mu

    else:

        J1_hat = multiply(self.physical_system.params.charge,
                          self.compute_moments('mom_v1_bulk', f_hat=f_hat))
        J2_hat = multiply(self.physical_system.params.charge,
                          self.compute_moments('mom_v2_bulk', f_hat=f_hat))
        J3_hat = multiply(self.physical_system.params.charge,
                          self.compute_moments('mom_v3_bulk', f_hat=f_hat))

    # Summing along all species:
    J1_hat = af.sum(J1_hat, 1)
    J2_hat = af.sum(J2_hat, 1)
    J3_hat = af.sum(J3_hat, 1)

    # Checking that there is no mean field component:
    # try:
    #     assert(af.mean(af.abs(B1_hat[:, 0, 0])) < 1e-12)
    #     assert(af.mean(af.abs(B2_hat[:, 0, 0])) < 1e-12)
    #     assert(af.mean(af.abs(B3_hat[:, 0, 0])) < 1e-12)
    # except:
    #     raise SystemExit('Linear Solver cannot solve for non-zero mean magnetic fields')

    # Equations Solved:
    # dE1/dt = + dB3/dq2 - J1
    # dE2/dt = - dB3/dq1 - J2
    # dE3/dt = dB2/dq1 - dB1/dq2 - J3

    if (self.physical_system.params.hybrid_model_enabled == True):

        # Using Generalized Ohm's Law for electric field:
        n_i_hat = self.compute_moments('density', f_hat=f_hat)

        n_i = af.real(ifft2(0.5 * self.N_q2 * self.N_q1 * n_i_hat))
        v1 = af.real(
            ifft2(0.5 * self.N_q2 * self.N_q1 *
                  self.compute_moments('mom_v1_bulk', f_hat=f_hat))) / n_i
        v2 = af.real(
            ifft2(0.5 * self.N_q2 * self.N_q1 *
                  self.compute_moments('mom_v2_bulk', f_hat=f_hat))) / n_i
        v3 = af.real(
            ifft2(0.5 * self.N_q2 * self.N_q1 *
                  self.compute_moments('mom_v3_bulk', f_hat=f_hat))) / n_i

        B1 = af.real(ifft2(0.5 * self.N_q2 * self.N_q1 * B1_hat))
        B2 = af.real(ifft2(0.5 * self.N_q2 * self.N_q1 * B2_hat))
        B3 = af.real(ifft2(0.5 * self.N_q2 * self.N_q1 * B3_hat))

        J1 = af.real(ifft2(0.5 * self.N_q2 * self.N_q1 * J1_hat))
        J2 = af.real(ifft2(0.5 * self.N_q2 * self.N_q1 * J2_hat))
        J3 = af.real(ifft2(0.5 * self.N_q2 * self.N_q1 * J3_hat))

        T_e = self.physical_system.params.fluid_electron_temperature
        # Computing the quantities needed and then doing FT again:
        # # (v X B)_x = B3 * v2 - B2 * v3
        # v_cross_B_1 = B3 * v2 - B2 * v3
        # # (v X B)_y = B1 * v3 - B3 * v1
        # v_cross_B_2 = B1 * v3 - B3 * v1
        # # (v X B)_z = B2 * v1 - B1 * v2
        # v_cross_B_3 = B2 * v1 - B1 * v2

        # # (J X B)_x = B3 * J2 - B2 * J3
        # J_cross_B_1 = B3 * J2 - B2 * J3
        # # (J X B)_y = B1 * J3 - B3 * J1
        # J_cross_B_2 = B1 * J3 - B3 * J1
        # # (J X B)_z = B2 * J1 - B1 * J2
        # J_cross_B_3 = B2 * J1 - B1 * J2

        # # Using a 4th order stencil:
        # dn_q1 = (-     af.shift(n_i, 0, 0, -2) + 8 * af.shift(n_i, 0, 0, -1)
        #          - 8 * af.shift(n_i, 0, 0,  1) +     af.shift(n_i, 0, 0,  2)
        #         ) / (12 * self.dq1)

        # dn_q2 = (-     af.shift(n_i, 0, 0, 0, -2) + 8 * af.shift(n_i, 0, 0, 0, -1)
        #          - 8 * af.shift(n_i, 0, 0, 0,  1) +     af.shift(n_i, 0, 0, 0,  2)
        #         ) / (12 * self.dq2)

        # # E = -(v X B) + (J X B) / (en) - T ∇n / (en)
        # E1 = - v_cross_B_1 + J_cross_B_1 / multiply(self.physical_system.params.charge, n_i) \
        #      - T_e * dn_q1 / multiply(self.physical_system.params.charge, n_i)

        # E2 = - v_cross_B_2 + J_cross_B_2 / multiply(self.physical_system.params.charge, n_i) \
        #      - T_e * dn_q2 / multiply(self.physical_system.params.charge, n_i)

        # E3 = - v_cross_B_3 + J_cross_B_3 / multiply(self.physical_system.params.charge, n_i)

        # E1_hat = 2 * fft2(E1) / (self.N_q1 * self.N_q2)
        # E2_hat = 2 * fft2(E2) / (self.N_q1 * self.N_q2) - T_e * n_i_hat * self.k_q2 / af.mean(n_i)
        # E3_hat = 2 * fft2(E3) / (self.N_q1 * self.N_q2)

        # background magnetic fields == 0 ALWAYS:
        # (v X B)_x = B3 * v2 - B2 * v3
        v_cross_B_1_hat = B3_hat * af.mean(v2) - B2_hat * af.mean(v3)
        # (v X B)_y = B1 * v3 - B3 * v1
        v_cross_B_2_hat = B1_hat * af.mean(v3) - B3_hat * af.mean(v1)
        # (v X B)_z = B2 * v1 - B1 * v2
        v_cross_B_3_hat = B2_hat * af.mean(v1) - B1_hat * af.mean(v2)

        # (J X B)_x = B3 * J2 - B2 * J3
        J_cross_B_1_hat = B3_hat * af.mean(J2) - B2_hat * af.mean(J3)
        # (J X B)_y = B1 * J3 - B3 * J1
        J_cross_B_2_hat = B1_hat * af.mean(J3) - B3_hat * af.mean(J1)
        # (J X B)_z = B2 * J1 - B1 * J2
        J_cross_B_3_hat = B2_hat * af.mean(J1) - B1_hat * af.mean(J2)

        E1_hat = - v_cross_B_1_hat + multiply(J_cross_B_1_hat, 1 / self.physical_system.params.charge) / af.mean(n_i) \
                 - T_e * n_i_hat * self.k_q1 / af.mean(n_i)

        E2_hat = - v_cross_B_2_hat + multiply(J_cross_B_2_hat, 1 / self.physical_system.params.charge) / af.mean(n_i) \
                 - T_e * n_i_hat * self.k_q2 / af.mean(n_i)

        E3_hat = -v_cross_B_3_hat + multiply(
            J_cross_B_3_hat,
            1 / self.physical_system.params.charge) / af.mean(n_i)

        self.fields_solver.fields_hat[0] = E1_hat
        self.fields_solver.fields_hat[1] = E2_hat
        self.fields_solver.fields_hat[2] = E3_hat

    else:

        E1_hat = fields_hat[0]
        E2_hat = fields_hat[1]
        E3_hat = fields_hat[2]

    dE1_hat_dt = B3_hat * 1j * self.k_q2 / (mu * eps) - J1_hat / eps
    dE2_hat_dt = -B3_hat * 1j * self.k_q1 / (mu * eps) - J2_hat / eps
    dE3_hat_dt =  (B2_hat * 1j * self.k_q1 - B1_hat * 1j * self.k_q2) / (mu * eps) \
                 -J3_hat / eps

    # dB1/dt = - dE3/dq2
    # dB2/dt = + dE3/dq1
    # dB3/dt = - (dE2/dq1 - dE1/dq2)

    dB1_hat_dt = -E3_hat * 1j * self.k_q2
    dB2_hat_dt = E3_hat * 1j * self.k_q1
    dB3_hat_dt = E1_hat * 1j * self.k_q2 - E2_hat * 1j * self.k_q1

    dfields_hat_dt = af.join(0, af.join(0, dE1_hat_dt, dE2_hat_dt, dE3_hat_dt),
                             dB1_hat_dt, dB2_hat_dt, dB3_hat_dt)

    af.eval(dfields_hat_dt)
    return (dfields_hat_dt)
Exemplo n.º 7
0
def dump_EM_fields(self, file_name):
    """
    This function is used to EM fields to a file for later usage.
    This dumps all the EM fields quantities E1, E2, E3, B1, B2, B3 
    which can then be used later for post-processing

    Parameters
    ----------

    file_name : The EM_fields array will be dumped to this
                provided file name.

    Returns
    -------

    This function returns None. However it creates a file 'file_name.h5',
    containing the data of the EM fields.

    Examples
    --------
    
    >> solver.dump_EM_fields('data_EM_fields')

    The above statement will create a HDF5 file which contains the
    EM fields data. The data is always stored with the key 
    'EM_fields'

    This can later be accessed using

    >> import h5py
    
    >> h5f = h5py.File('data_EM_fields.h5', 'r')
    
    >> EM_fields = h5f['EM_fields'][:]

    >> E1 = EM_fields[:, :, 0]
    
    >> E2 = EM_fields[:, :, 1]
    
    >> E3 = EM_fields[:, :, 2]
    
    >> B1 = EM_fields[:, :, 3]
    
    >> B2 = EM_fields[:, :, 4]
    
    >> B3 = EM_fields[:, :, 5]

    >> h5f.close()

    Alternatively, it can also be used with the load function to resume
    a long-running calculation.

    >> solver.load_EM_fields('data_EM_fields')
    """
    array_to_dump = 0.5 * self.N_q2 * self.N_q1 * af.real(
        ifft2(self.fields_solver.fields_hat))
    array_to_dump.to_ndarray(self.fields_solver._glob_fields_array)

    viewer = PETSc.Viewer().createHDF5(file_name + '.h5', 'w')
    viewer(self.fields_solver._glob_fields)

    return
Exemplo n.º 8
0
n_data_ls  = np.zeros_like(time_array)
n_data_nls = np.zeros_like(time_array)

for time_index, t0 in enumerate(time_array):
    
    if(time_index%100 == 0):
        
        print('Computing For Time =', t0)
        
        nls.dump_distribution_function('dump_f/%04d'%time_index)
        # nls.dump_moments('dump_moments/%04d'%time_index)

    E_data_nls[time_index] = af.sum(nls.fields_solver.cell_centered_EM_fields[:, :, N_g:-N_g, N_g:-N_g]**2)
    E1_ls                  = af.real(0.5 * (ls.N_q1 * ls.N_q2) 
                                         * ifft2(ls.fields_solver.E1_hat)
                                    )

    E_data_ls[time_index]  = af.sum(E1_ls**2)

    n_data_nls[time_index] = af.max(nls.compute_moments('density'))
    n_data_ls[time_index]  = af.max(ls.compute_moments('density'))

    nls.strang_timestep(dt)
    ls.RK4_timestep(dt)

h5f = h5py.File('data.h5', 'w')
h5f.create_dataset('electrical_energy_ls', data = E_data_ls)
h5f.create_dataset('electrical_energy_nls', data = E_data_nls)
h5f.create_dataset('density_ls', data = n_data_ls)
h5f.create_dataset('density_nls', data = n_data_nls)
Exemplo n.º 9
0
def df_hat_dt(f_hat, fields_hat, self):
    """
    Returns the value of the derivative of the f_hat with respect to time 
    respect to time. This is used to evolve the system in time.

    Input:
    ------

      f_hat  : Fourier mode values for the distribution function at which the slope is computed
               At t = 0 the initial state of the system is passed to this function:

      fields_hat  : Fourier mode values for the fields at which the slope is computed
                    At t = 0 the initial state of the system is passed to this function:

    Output:
    -------
    df_dt : The time-derivative of f_hat
    """
    (A_q1, A_q2) = self._A_q(self.time_elapsed, self.q1_center, self.q2_center,
                             self.p1_center, self.p2_center, self.p3_center,
                             self.physical_system.params)

    df_hat_dt = -1j * (multiply(self.k_q1, A_q1) +
                       multiply(self.k_q2, A_q2)) * f_hat

    if (self.physical_system.params.source_enabled == True):

        # Scaling Appropriately:
        f = af.real(ifft2(0.5 * self.N_q2 * self.N_q1 * f_hat))

        C_f_hat = 2 * fft2(
            self._source(
                f, self.time_elapsed, self.q1_center, self.q2_center,
                self.p1_center, self.p2_center, self.p3_center,
                self.compute_moments,
                self.physical_system.params)) / (self.N_q2 * self.N_q1)

        df_hat_dt += C_f_hat

    if (self.physical_system.params.fields_enabled == True):

        if (self.physical_system.params.fields_type == 'electrostatic'):

            rho_hat = multiply(self.physical_system.params.charge,
                               self.compute_moments('density', f_hat=f_hat))
            self.fields_solver.compute_electrostatic_fields(rho_hat)

        elif (self.physical_system.params.fields_type == 'electrodynamic'):
            # Handled by dfields_hat_dt
            pass

        # Used in debugging; advection tests for p-space where fields are to be held constant
        elif (self.physical_system.params.fields_type == 'None'):
            pass

        else:
            raise NotImplementedError('Invalid option for fields solver!')

        # get_fields for linear solver returns the mode amplitudes of the fields
        # So, we obtain A_p1_hat, A_p2_hat, A_p3_hat
        (A_p1_hat, A_p2_hat, A_p3_hat) = af.broadcast(
            self._A_p, self.time_elapsed, self.q1_center, self.q2_center,
            self.p1_center, self.p2_center, self.p3_center, self.fields_solver,
            self.physical_system.params)

        fields_term =   multiply(A_p1_hat, self.dfdp1_background) \
                      + multiply(A_p2_hat, self.dfdp2_background) \
                      + multiply(A_p3_hat, self.dfdp3_background)

        # Including the mean magnetic field term:
        # TODO: Maybe wrong to add mean magnetic fields since e^{ikx} term won't cancel out. Check again
        # Multiplying by q_center**0 to get the values in the array of required dimension
        # Dividing by 2 to normalize appropriately(look at the initialization sector):
        B1_mean = af.mean(
            self.fields_solver.fields_hat[3, 0, 0, 0]) * self.q1_center**0 / 2
        B2_mean = af.mean(
            self.fields_solver.fields_hat[4, 0, 0, 0]) * self.q1_center**0 / 2
        B3_mean = af.mean(
            self.fields_solver.fields_hat[5, 0, 0, 0]) * self.q1_center**0 / 2

        e = self.physical_system.params.charge
        m = self.physical_system.params.mass

        # Converting delta_f array to velocity_expanded form:
        f_hat_p_expanded = af.moddims(f_hat, self.N_p1, self.N_p2, self.N_p3,
                                      self.N_species * self.N_q1 * self.N_q2)

        # Computing ddelta_f_dp using a 4th order finite different stencil:
        ddelta_f_dp1 = multiply((-af.shift(f_hat_p_expanded, -2) +
                                 8 * af.shift(f_hat_p_expanded, -1) +
                                 af.shift(f_hat_p_expanded, 2) -
                                 8 * af.shift(f_hat_p_expanded, 1)),
                                1 / (12 * self.dp1))

        ddelta_f_dp2 = multiply((-af.shift(f_hat_p_expanded, 0, -2) +
                                 8 * af.shift(f_hat_p_expanded, 0, -1) +
                                 af.shift(f_hat_p_expanded, 0, 2) -
                                 8 * af.shift(f_hat_p_expanded, 0, 1)),
                                1 / (12 * self.dp2))

        ddelta_f_dp3 = multiply((-af.shift(f_hat_p_expanded, 0, 0, -2) +
                                 8 * af.shift(f_hat_p_expanded, 0, 0, -1) +
                                 af.shift(f_hat_p_expanded, 0, 0, 2) -
                                 8 * af.shift(f_hat_p_expanded, 0, 0, 1)),
                                1 / (12 * self.dp3))

        # Converting back to positions expanded:
        ddelta_f_dp1 = af.moddims(ddelta_f_dp1,
                                  self.N_p1 * self.N_p2 * self.N_p3,
                                  self.N_species, self.N_q1, self.N_q2)

        ddelta_f_dp2 = af.moddims(ddelta_f_dp2,
                                  self.N_p1 * self.N_p2 * self.N_p3,
                                  self.N_species, self.N_q1, self.N_q2)

        ddelta_f_dp3 = af.moddims(ddelta_f_dp3,
                                  self.N_p1 * self.N_p2 * self.N_p3,
                                  self.N_species, self.N_q1, self.N_q2)

        fields_term_mean_magnetic_fields = \
            multiply(e/m, (  (multiply(self.p2_center, B3_mean) - multiply(self.p3_center, B2_mean)) * ddelta_f_dp1
                           + (multiply(self.p3_center, B1_mean) - multiply(self.p1_center, B3_mean)) * ddelta_f_dp2
                           + (multiply(self.p1_center, B2_mean) - multiply(self.p2_center, B1_mean)) * ddelta_f_dp3
                          )
                    )

        df_hat_dt -= fields_term + fields_term_mean_magnetic_fields

    af.eval(df_hat_dt)
    return (df_hat_dt)
Exemplo n.º 10
0
def compute_moments(self, moment_name, f=None, f_hat=None):
    """
    Used in computing the moments of the distribution function.
    The moment definitions which are passed to physical system
    are used in computing these moment quantities.

    Parameters
    ----------

    moments_name : str
                   Pass the moment name which needs to be computed.
                   It must be noted that this needs to be defined by the
                   user under moments under src and passed to the 
                   physical_system object.

    f/f_hat: np.ndarray
             Pass this argument as well when you want to compute the 
             moments of the input array and not the one stored by the state vector
             of the object.

    Examples
    --------
    
    >> solver.compute_moments('density')

    Will return the density of the system at its current state.
    """
    if(f_hat is None and f is None):
        # af.broadcast(function, *args) performs batched operations on function(*args):
        moment_hat = af.broadcast(getattr(self.physical_system.moments, 
                                          moment_name
                                         ), self.f_hat, 
                                  self.p1_center, self.p2_center, self.p3_center,
                                  self.dp3 * self.dp2 * self.dp1
                                 )

        # Scaling Appropriately:
        moment_hat = 0.5 * self.N_q2 * self.N_q1 * moment_hat
        moment     = af.real(ifft2(moment_hat))
        
        af.eval(moment)
        return(moment)
    
    elif(f_hat is not None and f is None):
        moment_hat = af.broadcast(getattr(self.physical_system.moments, 
                                          moment_name
                                         ), f_hat,
                                  self.p1_center, self.p2_center, self.p3_center,
                                  self.dp3 * self.dp2 * self.dp1
                                 )

        af.eval(moment_hat)
        return(moment_hat)

    elif(f_hat is None and f is not None):
        moment = af.broadcast(getattr(self.physical_system.moments, 
                                      moment_name
                                     ), f,
                              self.p1_center, self.p2_center, self.p3_center,
                              self.dp3 * self.dp2 * self.dp1
                             )
        af.eval(moment)
        return(moment)

    else:
        raise BaseException('Invalid Option: Both f and f_hat cannot \
                             be provided as arguments'
                           )