예제 #1
0
def x(posdata, a1_index, a2_index):
    (sphere_sizes, sphere_positions, sphere_rotations, dumbbell_sizes,
     dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells,
     element_sizes, element_positions, element_deltax, num_elements,
     num_elements_array, element_type, uv_start, uv_size,
     element_start_count) = posdata_data(posdata)
    return (element_positions[a2_index] - element_positions[a1_index])
예제 #2
0
def generate_output_FTSUOE(posdata,
                           frameno,
                           timestep,
                           input_number,
                           last_generated_Minfinity_inverse,
                           regenerate_Minfinity,
                           input_form,
                           cutoff_factor,
                           printout,
                           use_XYZd_values,
                           use_drag_Minfinity,
                           use_Minfinity_only,
                           extract_force_on_wall_due_to_dumbbells,
                           last_velocities,
                           last_velocity_vector,
                           checkpoint_start_from_frame,
                           box_bottom_left,
                           box_top_right,
                           feed_every_n_timesteps=0):
    (sphere_sizes, sphere_positions, sphere_rotations, dumbbell_sizes,
     dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells,
     element_sizes, element_positions, element_deltax, num_elements,
     num_elements_array, element_type, uv_start, uv_size,
     element_start_count) = posdata_data(posdata)
    # Get inputs first time in "video" mode, i.e. no complex calculations for Fa_in, etc. This is really just to get the values of box_bottom_left and box_top_right.
    (Fa_in, Ta_in, Sa_in, Sa_c_in, Fb_in, DFb_in, Ua_in, Oa_in, Ea_in, Ea_c_in,
     Ub_in, DUb_in, input_description, U_infinity, O_infinity,
     centre_of_background_flow, amplitude, frequency, box_bottom_left,
     box_top_right, mu) = input_ftsuoe(input_number,
                                       posdata,
                                       frameno,
                                       timestep,
                                       last_velocities,
                                       input_form=input_form,
                                       video=True)

    solve_time_start = time.time()
    force_on_wall_due_to_dumbbells = 0

    if input_form == "stokes_drag_dumbbells_only":
        Fbeads = 0.5 * np.concatenate([
            np.array(Fb_in) + np.array(DFb_in),
            np.array(Fb_in) - np.array(DFb_in)
        ])
        a = dumbbell_sizes[0]
        drag_coeff = mu * a
        Ubeads = Fbeads / drag_coeff
        Nbeads = len(Fbeads)
        (Fa_out, Ta_out, Sa_out, Fb_out,
         DFb_out) = (Fa_in[:], Ta_in[:], Sa_in[:], Fb_in[:], DFb_in[:])
        (Ua_out, Oa_out, Ea_out) = (Fa_in[:], Fa_in[:], Ea_in[:])
        Ub_out = 0.5 * (Ubeads[:Nbeads / 2] + Ubeads[Nbeads / 2:])
        DUb_out = 0.5 * (
            Ubeads[:Nbeads / 2] - Ubeads[Nbeads / 2:]
        )  # Because DUb is actually Half Delta Ub (shit notation, I know)
        gen_times = [0, 0, 0]

    else:
        if not np.array_equal(box_bottom_left - box_top_right,
                              np.array([0, 0, 0])):
            # periodic
            (grand_resistance_matrix, heading,
             last_generated_Minfinity_inverse,
             gen_times) = generate_grand_resistance_matrix_periodic(
                 posdata,
                 last_generated_Minfinity_inverse,
                 box_bottom_left,
                 box_top_right,
                 regenerate_Minfinity=regenerate_Minfinity,
                 cutoff_factor=cutoff_factor,
                 printout=printout,
                 use_XYZd_values=use_XYZd_values,
                 use_drag_Minfinity=use_drag_Minfinity,
                 use_Minfinity_only=use_Minfinity_only,
                 frameno=frameno,
                 checkpoint_start_from_frame=checkpoint_start_from_frame,
                 feed_every_n_timesteps=feed_every_n_timesteps,
                 O_infinity=O_infinity,
                 E_infinity=Ea_in[0],
                 timestep=timestep,
                 centre_of_background_flow=centre_of_background_flow,
                 mu=mu,
                 amplitude=amplitude,
                 frequency=frequency)
        else:
            # non-periodic
            (grand_resistance_matrix, heading,
             last_generated_Minfinity_inverse,
             gen_times) = generate_grand_resistance_matrix(
                 posdata,
                 last_generated_Minfinity_inverse,
                 regenerate_Minfinity=regenerate_Minfinity,
                 cutoff_factor=cutoff_factor,
                 printout=printout,
                 use_XYZd_values=use_XYZd_values,
                 use_drag_Minfinity=use_drag_Minfinity,
                 use_Minfinity_only=use_Minfinity_only,
                 frameno=frameno,
                 checkpoint_start_from_frame=checkpoint_start_from_frame,
                 feed_every_n_timesteps=feed_every_n_timesteps,
                 mu=mu)

        num_spheres = len(Ua_in)
        num_dumbbells = len(Ub_in)
        if input_form == 'fts':
            try:
                force_vector = construct_force_vector_from_fts(
                    posdata, Fa_in, Ta_in, Sa_in, Fb_in, DFb_in)
            except:
                throw_error(
                    "FTS mode has been selected but not all values of F, T and S have been provided."
                )
            velocity_vector = np.linalg.solve(grand_resistance_matrix,
                                              force_vector)
            (Ua_out, Oa_out, Ea_out, Ub_out,
             DUb_out) = deconstruct_velocity_vector_for_fts(
                 posdata, velocity_vector)
            (Fa_out, Ta_out, Sa_out, Fb_out,
             DFb_out) = (Fa_in[:], Ta_in[:], Sa_in[:], Fb_in[:], DFb_in[:])
            if num_spheres == 0:
                Ea_out = Ea_in

        elif input_form == 'fte':
            # Call this the same name to reduce memory requirements (no need to reproduce)
            grand_resistance_matrix = fts_to_fte_matrix(
                posdata, grand_resistance_matrix)

            # Get inputs a second time not in video mode, putting in the grand resistance matrix which is needed for some calculations with friction.
            (Fa_in, Ta_in, Sa_in, Sa_c_in, Fb_in, DFb_in, Ua_in, Oa_in, Ea_in,
             Ea_c_in, Ub_in, DUb_in, input_description, U_infinity, O_infinity,
             centre_of_background_flow, amplitude, frequency, box_bottom_left,
             box_top_right, mu) = input_ftsuoe(
                 input_number,
                 posdata,
                 frameno,
                 timestep,
                 last_velocities,
                 input_form=input_form,
                 grand_resistance_matrix_fte=grand_resistance_matrix)
            try:
                force_vector = construct_force_vector_from_fts(
                    posdata, Fa_in, Ta_in, Ea_in, Fb_in, DFb_in)
            except:
                throw_error(
                    "FTE mode has been selected but not all values of F, T and E have been provided."
                )
            velocity_vector = np.linalg.solve(grand_resistance_matrix,
                                              force_vector)
            (Ua_out, Oa_out, Sa_out, Ub_out,
             DUb_out) = deconstruct_velocity_vector_for_fts(
                 posdata, velocity_vector)
            (Fa_out, Ta_out, Ea_out, Fb_out,
             DFb_out) = (Fa_in[:], Ta_in[:], Ea_in[:], Fb_in[:], DFb_in[:])
            if num_spheres == 0:
                Ea_out = Ea_in

        elif input_form == 'ufte':
            num_fixed_velocity_spheres = num_spheres - Ua_in.count(
                ['pippa', 'pippa', 'pippa'])
            try:
                force_vector = construct_force_vector_from_fts(
                    posdata, Ua_in[0:num_fixed_velocity_spheres] +
                    Fa_in[num_fixed_velocity_spheres:num_spheres], Ta_in,
                    Ea_in, Fb_in, DFb_in)
            except:
                throw_error(
                    "UFTE mode has been selected but not enough values of U, F, T and E have been provided. At a guess, not all your spheres have either a U or an F."
                )
            force_vector = np.array(force_vector, np.float)
            grand_resistance_matrix_fte = fts_to_fte_matrix(
                posdata, grand_resistance_matrix)
            grand_resistance_matrix_ufte = fte_to_ufte_matrix(
                num_fixed_velocity_spheres, posdata,
                grand_resistance_matrix_fte)
            if extract_force_on_wall_due_to_dumbbells:
                grand_mobility_matrix_ufte = np.linalg.inv(
                    grand_resistance_matrix_ufte)
                velocity_vector = np.dot(grand_mobility_matrix_ufte,
                                         force_vector)
            else:
                velocity_vector = np.linalg.solve(grand_resistance_matrix_ufte,
                                                  force_vector)
                (FUa_out, Oa_out, Sa_out, Ub_out,
                 DUb_out) = deconstruct_velocity_vector_for_fts(
                     posdata, velocity_vector)
                Fa_out = [['chen', 'chen', 'chen']
                          for i in xrange(num_spheres)]
                Ua_out = [['chen', 'chen', 'chen']
                          for i in xrange(num_spheres)]
                Fa_out[0:num_fixed_velocity_spheres] = FUa_out[
                    0:num_fixed_velocity_spheres]
                Fa_out[num_fixed_velocity_spheres:num_spheres] = Fa_in[
                    num_fixed_velocity_spheres:num_spheres]
                Ua_out[0:num_fixed_velocity_spheres] = Ua_in[
                    0:num_fixed_velocity_spheres]
                Ua_out[num_fixed_velocity_spheres:num_spheres] = FUa_out[
                    num_fixed_velocity_spheres:num_spheres]
                (Ta_out, Ea_out, Fb_out, DFb_out) = (Ta_in[:], Ea_in[:],
                                                     Fb_in[:], DFb_in[:])

            if extract_force_on_wall_due_to_dumbbells:
                # For finding effect of the dumbbells on the measured Force on the walls.
                # Since   Fafixed = ()Uafixed + ()Fafree + ()Ta + ()E +   ()Fb  + ()DFb       ,
                #                                                       | want this bit |
                force_on_wall_due_to_dumbbells_matrix = grand_mobility_matrix_ufte[:
                                                                                   num_fixed_velocity_spheres
                                                                                   *
                                                                                   3,
                                                                                   11
                                                                                   *
                                                                                   num_spheres:]
                dumbbell_forces = force_vector[11 * num_spheres:]
                force_on_wall_due_to_dumbbells_flat = np.dot(
                    force_on_wall_due_to_dumbbells_matrix, dumbbell_forces)
                force_on_wall_due_to_dumbbells = force_on_wall_due_to_dumbbells_flat.reshape(
                    len(force_on_wall_due_to_dumbbells_flat) / 3, 3)

        elif input_form == 'ufteu':
            num_fixed_velocity_spheres = num_spheres - Ua_in.count(
                ['pippa', 'pippa', 'pippa'])
            num_fixed_velocity_dumbbells = num_dumbbells - Ub_in.count(
                ['pippa', 'pippa', 'pippa'])
            try:
                force_vector = construct_force_vector_from_fts(
                    posdata, Ua_in[0:num_fixed_velocity_spheres] +
                    Fa_in[num_fixed_velocity_spheres:num_spheres], Ta_in,
                    Ea_in, Ub_in[0:num_fixed_velocity_dumbbells] +
                    Fb_in[num_fixed_velocity_dumbbells:num_dumbbells],
                    DUb_in[0:num_fixed_velocity_dumbbells] +
                    DFb_in[num_fixed_velocity_dumbbells:num_dumbbells])
            except:
                throw_error(
                    "UFTEU mode has been selected but not enough values of U, F, T and E and U(dumbbell) have been provided. At a guess, not all your spheres/dumbbells have either a U or an F."
                )

            force_vector = np.array(force_vector, np.float)
            grand_resistance_matrix_fte = fts_to_fte_matrix(
                posdata, grand_resistance_matrix)
            grand_resistance_matrix_ufte = fte_to_ufte_matrix(
                num_fixed_velocity_spheres, posdata,
                grand_resistance_matrix_fte)
            grand_resistance_matrix_ufteu = ufte_to_ufteu_matrix(
                num_fixed_velocity_dumbbells, num_fixed_velocity_spheres,
                posdata, grand_resistance_matrix_ufte)
            velocity_vector = np.linalg.solve(grand_resistance_matrix_ufteu,
                                              force_vector)

            (FUa_out, Oa_out, Sa_out, FUb_out,
             DFUb_out) = deconstruct_velocity_vector_for_fts(
                 posdata, velocity_vector)
            Fa_out = [['chen', 'chen', 'chen'] for i in xrange(num_spheres)]
            Ua_out = [['chen', 'chen', 'chen'] for i in xrange(num_spheres)]
            Fa_out[0:num_fixed_velocity_spheres] = FUa_out[
                0:num_fixed_velocity_spheres]
            Fa_out[num_fixed_velocity_spheres:num_spheres] = Fa_in[
                num_fixed_velocity_spheres:num_spheres]
            Ua_out[0:num_fixed_velocity_spheres] = Ua_in[
                0:num_fixed_velocity_spheres]
            Ua_out[num_fixed_velocity_spheres:num_spheres] = FUa_out[
                num_fixed_velocity_spheres:num_spheres]
            (Ta_out, Ea_out) = (Ta_in[:], Ea_in[:])
            Fb_out = [['chen', 'chen', 'chen'] for i in xrange(num_dumbbells)]
            Ub_out = [['chen', 'chen', 'chen'] for i in xrange(num_dumbbells)]
            Fb_out[0:num_fixed_velocity_dumbbells] = FUb_out[
                0:num_fixed_velocity_dumbbells]
            Fb_out[num_fixed_velocity_dumbbells:num_dumbbells] = Fb_in[
                num_fixed_velocity_dumbbells:num_dumbbells]
            Ub_out[0:num_fixed_velocity_dumbbells] = Ub_in[
                0:num_fixed_velocity_dumbbells]
            Ub_out[num_fixed_velocity_dumbbells:num_dumbbells] = FUb_out[
                num_fixed_velocity_dumbbells:num_dumbbells]
            DFb_out = [['chen', 'chen', 'chen'] for i in xrange(num_dumbbells)]
            DUb_out = [['chen', 'chen', 'chen'] for i in xrange(num_dumbbells)]
            DFb_out[0:num_fixed_velocity_dumbbells] = DFUb_out[
                0:num_fixed_velocity_dumbbells]
            DFb_out[num_fixed_velocity_dumbbells:num_dumbbells] = DFb_in[
                num_fixed_velocity_dumbbells:num_dumbbells]
            DUb_out[0:num_fixed_velocity_dumbbells] = DUb_in[
                0:num_fixed_velocity_dumbbells]
            DUb_out[num_fixed_velocity_dumbbells:num_dumbbells] = DFUb_out[
                num_fixed_velocity_dumbbells:num_dumbbells]
            if extract_force_on_wall_due_to_dumbbells:
                print "WARNING: Cannot extract force on wall due to dumbbells in UFTEU mode. Use UFTE mode instead."

        elif input_form == 'duf':  #Dumbbells only, some imposed velocities
            num_fixed_velocity_dumbbells = num_dumbbells - Ub_in.count(
                ['pippa', 'pippa', 'pippa'])
            try:
                force_vector = construct_force_vector_from_fts(
                    posdata, Fa_in, Ta_in, Ea_in,
                    Ub_in[0:num_fixed_velocity_dumbbells] +
                    Fb_in[num_fixed_velocity_dumbbells:num_dumbbells],
                    DUb_in[0:num_fixed_velocity_dumbbells] +
                    DFb_in[num_fixed_velocity_dumbbells:num_dumbbells])
            except:
                throw_error(
                    "DUF mode has been selected but not enough values of U (dumbbell) and F (dumbbell) have been provided. At a guess, not all your dumbbells have either a U or an F."
                )
            force_vector = np.array(force_vector, np.float)
            grand_resistance_matrix_duf = fts_to_duf_matrix(
                num_fixed_velocity_dumbbells, posdata, grand_resistance_matrix)
            velocity_vector = np.linalg.solve(grand_resistance_matrix_duf,
                                              force_vector)
            (Fa_out, Oa_out, Sa_out, FUb_out,
             DFUb_out) = deconstruct_velocity_vector_for_fts(
                 posdata, velocity_vector)
            Fb_out = [['chen', 'chen', 'chen'] for i in xrange(num_dumbbells)]
            Ub_out = [['chen', 'chen', 'chen'] for i in xrange(num_dumbbells)]
            DFb_out = [['chen', 'chen', 'chen'] for i in xrange(num_dumbbells)]
            DUb_out = [['chen', 'chen', 'chen'] for i in xrange(num_dumbbells)]
            Fb_out[0:num_fixed_velocity_dumbbells] = FUb_out[
                0:num_fixed_velocity_dumbbells]
            Fb_out[num_fixed_velocity_dumbbells:num_dumbbells] = Fb_in[
                num_fixed_velocity_dumbbells:num_dumbbells]
            Ub_out[0:num_fixed_velocity_dumbbells] = Ub_in[
                0:num_fixed_velocity_dumbbells]
            Ub_out[num_fixed_velocity_dumbbells:num_dumbbells] = FUb_out[
                num_fixed_velocity_dumbbells:num_dumbbells]
            DFb_out[0:num_fixed_velocity_dumbbells] = DFUb_out[
                0:num_fixed_velocity_dumbbells]
            DFb_out[num_fixed_velocity_dumbbells:num_dumbbells] = DFb_in[
                num_fixed_velocity_dumbbells:num_dumbbells]
            DUb_out[0:num_fixed_velocity_dumbbells] = DUb_in[
                0:num_fixed_velocity_dumbbells]
            DUb_out[num_fixed_velocity_dumbbells:num_dumbbells] = DFUb_out[
                num_fixed_velocity_dumbbells:num_dumbbells]
            (Fa_out, Ta_out, Ea_out) = (Fa_in[:], Ta_in[:], Ea_in[:])
            Ua_out, Oa_out = np.array([]), np.array([])

        Fa_out = np.asarray(Fa_out, np.float)
        Ta_out = np.asarray(Ta_out, np.float)
        Ea_out = np.asarray(Ea_out, np.float)
        Ua_out = np.asarray(Ua_out, np.float)
        Oa_out = np.asarray(Oa_out, np.float)
        Ub_out = np.asarray(Ub_out, np.float)
        DUb_out = np.asarray(DUb_out, np.float)

    elapsed_solve_time = time.time() - solve_time_start
    gen_times.append(elapsed_solve_time)

    if (printout > 0):
        print "Velocities on particles 0-9"
        print np.asarray(Ua_out[0:10])
        print np.asarray(Ub_out[0:10])
        print "Half Delta U velocity 0-9"
        print np.asarray(DUb_out[0:10])
        print "Omegas on particles 0-9"
        print np.asarray(Oa_out[0:10])
        print "Forces 0-9 (F)"
        print np.asarray(Fa_out[0:10])
        print np.asarray(Fb_out[0:10])
        print "Delta F forces 0-9 (DF)"
        print np.asarray(DFb_out[0:10])
        print "Torques 0-9 (T)"
        print np.asarray(Ta_out[0:10])
        print "Strain rate"
        print np.asarray(Ea_out)
        print "Stresslets 0-9 (S)"
        print np.asarray(Sa_out[0:10])

    return Fa_out, Ta_out, Sa_out, Fb_out, DFb_out, Ua_out, Oa_out, Ea_out, Ub_out, DUb_out, last_generated_Minfinity_inverse, gen_times, U_infinity, O_infinity, centre_of_background_flow, force_on_wall_due_to_dumbbells, last_velocity_vector
예제 #3
0
def generate_R2Bexact(posdata,
                      printout=0,
                      cutoff_factor=2,
                      frameno=0,
                      checkpoint_start_from_frame=0,
                      feed_every_n_timesteps=0,
                      mu=1):
    from functions_shared import close_particles
    global fully_2d_problem, size_ratio_matrix, average_size_matrix, upper_triangle
    (sphere_sizes, sphere_positions, sphere_rotations, dumbbell_sizes,
     dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells,
     element_sizes, element_positions, element_deltax, num_elements,
     num_elements_array, element_type, uv_start, uv_size,
     element_start_count) = posdata_data(posdata)
    R2Bexact_sidelength = 11 * num_spheres + 6 * num_dumbbells
    R2Bexact = lil_matrix((R2Bexact_sidelength, R2Bexact_sidelength),
                          dtype=np.float)
    bead_positions = np.concatenate([
        sphere_positions, dumbbell_positions - 0.5 * dumbbell_deltax,
        dumbbell_positions + 0.5 * dumbbell_deltax
    ])
    bead_sizes = np.concatenate([sphere_sizes, dumbbell_sizes, dumbbell_sizes])

    if printout > 0 and feed_every_n_timesteps > 0:
        print "number of dumbbells in functions_generate_R2Bexact: ", dumbbell_sizes.shape, num_dumbbells

    closer_than_cutoff_pairs_scaled, displacements_pairs_scaled, distances_pairs_scaled, size_ratios = close_particles(
        bead_positions, bead_sizes, cutoff_factor)

    uv_power = [[1, 2, 2, 1, 1], [2, 3, 3, 2, 2], [2, 3, 3, 2, 2],
                [1, 2, 2, 1, 1], [1, 2, 2, 1, 1]]

    ii = 0
    for a1_index, a2_index in closer_than_cutoff_pairs_scaled:
        r = displacements_pairs_scaled[ii]  # vector r
        s_dash = distances_pairs_scaled[ii]  # np.linalg.norm(x)
        if a1_index != a2_index:
            d = r / s_dash
        lam = size_ratios[ii]
        lam_index = np.where(lam_range_with_reciprocals == lam)[0][0]
        lam_index_recip = np.where(lam_range_with_reciprocals == 1. /
                                   lam)[0][0]
        largest_size = max(bead_sizes[a1_index], bead_sizes[a2_index])
        if a1_index < num_spheres and a2_index < num_spheres:
            # Sphere to sphere
            A_coords = np.s_[a1_index * 3:(a1_index + 1) * 3,
                             a2_index * 3:(a2_index + 1) * 3]
            Bt_coords = np.s_[a1_index * 3:(a1_index + 1) * 3,
                              3 * num_spheres + a2_index * 3:3 * num_spheres +
                              (a2_index + 1) * 3]
            Bt_coords_21 = np.s_[a2_index * 3:(a2_index + 1) * 3,
                                 3 * num_spheres +
                                 a1_index * 3:3 * num_spheres +
                                 (a1_index + 1) * 3]
            Gt_coords = np.s_[a1_index * 3:(a1_index + 1) * 3,
                              6 * num_spheres + a2_index * 5:6 * num_spheres +
                              (a2_index + 1) * 5]
            Gt_coords_21 = np.s_[a2_index * 3:(a2_index + 1) * 3,
                                 6 * num_spheres +
                                 a1_index * 5:6 * num_spheres +
                                 (a1_index + 1) * 5]
            C_coords = np.s_[3 * num_spheres + a1_index * 3:3 * num_spheres +
                             (a1_index + 1) * 3, 3 * num_spheres +
                             a2_index * 3:3 * num_spheres + (a2_index + 1) * 3]
            Ht_coords = np.s_[3 * num_spheres + a1_index * 3:3 * num_spheres +
                              (a1_index + 1) * 3,
                              6 * num_spheres + a2_index * 5:6 * num_spheres +
                              (a2_index + 1) * 5]
            Ht_coords_21 = np.s_[3 * num_spheres +
                                 a2_index * 3:3 * num_spheres +
                                 (a2_index + 1) * 3, 6 * num_spheres +
                                 a1_index * 5:6 * num_spheres +
                                 (a1_index + 1) * 5]
            M_coords = np.s_[6 * num_spheres + a1_index * 5:6 * num_spheres +
                             (a1_index + 1) * 5, 6 * num_spheres +
                             a2_index * 5:6 * num_spheres + (a2_index + 1) * 5]
            if a1_index == a2_index:
                nearby_beads = []
                nearby_beads_displacements = []
                nearby_beads_distances = []
                for kk in xrange(len(closer_than_cutoff_pairs_scaled)):
                    (i, j) = closer_than_cutoff_pairs_scaled[kk]
                    if (i == a1_index and i != j):
                        nearby_bead = j
                        nearby_beads_displacements.append(
                            displacements_pairs_scaled[kk])
                        nearby_beads.append(nearby_bead)
                        nearby_beads_distances.append(
                            distances_pairs_scaled[kk])
                    if (j == a1_index and i != j):
                        nearby_bead = i
                        nearby_beads_displacements.append(
                            -displacements_pairs_scaled[kk])  # Note minus sign
                        nearby_beads.append(nearby_bead)
                        nearby_beads_distances.append(
                            distances_pairs_scaled[kk])
                A_sum = 0
                Bt_sum = 0
                C_sum = 0
                Gt_sum = 0
                Ht_sum = 0
                M_sum = 0
                pp = 0
                for p_index in nearby_beads:
                    lam_p = bead_sizes[p_index] / bead_sizes[a1_index]
                    largest_size_p = max(bead_sizes[a1_index],
                                         bead_sizes[p_index])
                    if lam_p not in lam_range_with_reciprocals:
                        print "ERROR (Code point D): lambda not in the table of calculated values"
                    lam_index_p = np.where(
                        lam_range_with_reciprocals == lam_p)[0][0]
                    lam_index_recip_p = np.where(
                        lam_range_with_reciprocals == 1. / lam_p)[0][0]
                    r_p = nearby_beads_displacements[pp]
                    s_dash_p = nearby_beads_distances[pp]
                    d_p = r_p / s_dash_p
                    A_sum = A_sum + np.asarray([[
                        Af(0, d_p, lam_index_p, s_dash_p, i, j,
                           fully_2d_problem) * largest_size_p**uv_power[0][0]
                        for j in xrange(3)
                    ] for i in xrange(3)])
                    Bt_sum = Bt_sum + np.asarray([[
                        Bf(0, d_p, lam_index_p, s_dash_p, j, i,
                           fully_2d_problem) * largest_size_p**uv_power[0][1]
                        for j in xrange(3)
                    ] for i in xrange(3)])
                    C_sum = C_sum + np.asarray([[
                        Cf(0, d_p, lam_index_p, s_dash_p, i, j,
                           fully_2d_problem) * largest_size_p**uv_power[1][1]
                        for j in xrange(3)
                    ] for i in xrange(3)])
                    Gt_sum = Gt_sum + np.asarray([[
                        con_Gf(0, d_p, lam_index_p, s_dash_p, j, i,
                               fully_2d_problem) *
                        largest_size_p**uv_power[0][2] for j in xrange(5)
                    ] for i in xrange(3)])
                    Ht_sum = Ht_sum + np.asarray([[
                        con_Hf(0, d_p, lam_index_p, s_dash_p, j, i,
                               fully_2d_problem) *
                        largest_size_p**uv_power[1][2] for j in xrange(5)
                    ] for i in xrange(3)])
                    M_sum = M_sum + np.asarray([[
                        con_Mf(0, d_p, lam_index_p, s_dash_p, i, j,
                               fully_2d_problem) *
                        largest_size_p**uv_power[2][2] for j in xrange(5)
                    ] for i in xrange(5)])
                    pp = pp + 1
                R2Bexact[A_coords] = A_sum
                R2Bexact[Bt_coords] = Bt_sum
                R2Bexact[C_coords] = C_sum
                R2Bexact[Gt_coords] = Gt_sum
                R2Bexact[Ht_coords] = Ht_sum
                R2Bexact[M_coords] = M_sum

            else:
                R2Bexact[A_coords] = [[
                    Af(1, d, lam_index, s_dash, i, j, fully_2d_problem) *
                    largest_size**uv_power[0][0] for j in xrange(3)
                ] for i in xrange(3)]
                R2Bexact[Bt_coords] = [[
                    Bf(1, -d, lam_index_recip, s_dash, j, i, fully_2d_problem)
                    * largest_size**uv_power[0][1] for j in xrange(3)
                ] for i in xrange(3)]
                R2Bexact[C_coords] = [[
                    Cf(1, d, lam_index, s_dash, i, j, fully_2d_problem) *
                    largest_size**uv_power[1][1] for j in xrange(3)
                ] for i in xrange(3)]
                R2Bexact[Gt_coords] = [[
                    con_Gf(1, -d, lam_index_recip, s_dash, j, i,
                           fully_2d_problem) * largest_size**uv_power[0][2]
                    for j in xrange(5)
                ] for i in xrange(3)]
                R2Bexact[Ht_coords] = [[
                    con_Hf(1, -d, lam_index_recip, s_dash, j, i,
                           fully_2d_problem) * largest_size**uv_power[1][2]
                    for j in xrange(5)
                ] for i in xrange(3)]
                R2Bexact[M_coords] = [[
                    con_Mf(1, d, lam_index, s_dash, i, j, fully_2d_problem) *
                    largest_size**uv_power[2][2] for j in xrange(5)
                ] for i in xrange(5)]
                if lam == 1:
                    R2Bexact[Bt_coords_21] = -R2Bexact[Bt_coords]
                    R2Bexact[Gt_coords_21] = -R2Bexact[Gt_coords]
                    R2Bexact[Ht_coords_21] = R2Bexact[Ht_coords]
                else:
                    R2Bexact[Bt_coords_21] = [[
                        Bf(1, d, lam_index, s_dash, j, i, fully_2d_problem) *
                        largest_size**uv_power[0][1] for j in xrange(3)
                    ] for i in xrange(3)]
                    R2Bexact[Gt_coords_21] = [[
                        con_Gf(1, d, lam_index, s_dash, j, i, fully_2d_problem)
                        * largest_size**uv_power[0][2] for j in xrange(5)
                    ] for i in xrange(3)]
                    R2Bexact[Ht_coords_21] = [[
                        con_Hf(1, d, lam_index, s_dash, j, i, fully_2d_problem)
                        * largest_size**uv_power[1][2] for j in xrange(5)
                    ] for i in xrange(3)]

        elif a1_index < num_spheres and a2_index >= num_spheres and a2_index < num_spheres + num_dumbbells:
            # Sphere to dumbbell bead 1
            a2_index_d = a2_index - num_spheres
            R14_coords = np.s_[a1_index * 3:(a1_index + 1) * 3,
                               11 * num_spheres +
                               a2_index_d * 3:11 * num_spheres +
                               (a2_index_d + 1) * 3]
            R24_coords = np.s_[3 * num_spheres + a1_index * 3:3 * num_spheres +
                               (a1_index + 1) * 3, 11 * num_spheres +
                               a2_index_d * 3:11 * num_spheres +
                               (a2_index_d + 1) * 3]
            R34_coords = np.s_[6 * num_spheres + a1_index * 5:6 * num_spheres +
                               (a1_index + 1) * 5, 11 * num_spheres +
                               a2_index_d * 3:11 * num_spheres +
                               (a2_index_d + 1) * 3]

            R2Bexact[R14_coords] = [[
                Af(1, d, lam_index, s_dash, i, j, fully_2d_problem) *
                largest_size**uv_power[0][0] for j in xrange(3)
            ] for i in xrange(3)]
            R2Bexact[R24_coords] = [[
                Bf(1, d, lam_index, s_dash, i, j, fully_2d_problem) *
                largest_size**uv_power[0][1] for j in xrange(3)
            ] for i in xrange(3)]
            R2Bexact[R34_coords] = [[
                con_Gf(1, d, lam_index, s_dash, i, j, fully_2d_problem) *
                largest_size**uv_power[0][2] for j in xrange(3)
            ] for i in xrange(5)]

        elif a1_index < num_spheres and a2_index >= num_spheres + num_dumbbells:
            # Sphere to dumbbell bead 2
            a2_index_d = a2_index - num_spheres - num_dumbbells
            R15_coords = np.s_[a1_index * 3:(a1_index + 1) * 3,
                               11 * num_spheres + 3 * num_dumbbells +
                               a2_index_d * 3:11 * num_spheres +
                               3 * num_dumbbells + (a2_index_d + 1) * 3]
            R25_coords = np.s_[3 * num_spheres + a1_index * 3:3 * num_spheres +
                               (a1_index + 1) * 3,
                               11 * num_spheres + 3 * num_dumbbells +
                               a2_index_d * 3:11 * num_spheres +
                               3 * num_dumbbells + (a2_index_d + 1) * 3]
            R35_coords = np.s_[6 * num_spheres + a1_index * 5:6 * num_spheres +
                               (a1_index + 1) * 5,
                               11 * num_spheres + 3 * num_dumbbells +
                               a2_index_d * 3:11 * num_spheres +
                               3 * num_dumbbells + (a2_index_d + 1) * 3]

            R2Bexact[R15_coords] = [[
                Af(1, d, lam_index, s_dash, i, j, fully_2d_problem) *
                largest_size**uv_power[0][0] for j in xrange(3)
            ] for i in xrange(3)]
            R2Bexact[R25_coords] = [[
                Bf(1, d, lam_index, s_dash, i, j, fully_2d_problem) *
                largest_size**uv_power[0][1] for j in xrange(3)
            ] for i in xrange(3)]
            R2Bexact[R35_coords] = [[
                con_Gf(1, d, lam_index, s_dash, i, j, fully_2d_problem) *
                largest_size**uv_power[0][2] for j in xrange(3)
            ] for i in xrange(5)]

        elif a1_index >= num_spheres and a1_index < num_spheres + num_dumbbells and a2_index >= num_spheres and a2_index < num_spheres + num_dumbbells:
            # Dumbbell bead 1 to dumbbell bead 1
            a1_index_d = a1_index - num_spheres
            a2_index_d = a2_index - num_spheres
            R44_coords = np.s_[11 * num_spheres +
                               a1_index_d * 3:11 * num_spheres +
                               (a1_index_d + 1) * 3, 11 * num_spheres +
                               a2_index_d * 3:11 * num_spheres +
                               (a2_index_d + 1) * 3]
            if a1_index == a2_index:
                nearby_beads = []
                nearby_beads_displacements = []
                nearby_beads_distances = []
                for kk in xrange(len(closer_than_cutoff_pairs_scaled)):
                    (i, j) = closer_than_cutoff_pairs_scaled[kk]
                    if (i == a1_index and i != j):
                        nearby_bead = j
                        nearby_beads_displacements.append(
                            displacements_pairs_scaled[kk])
                        nearby_beads.append(nearby_bead)
                        nearby_beads_distances.append(
                            distances_pairs_scaled[kk])
                    if (j == a1_index and i != j):
                        nearby_bead = i
                        nearby_beads_displacements.append(
                            -displacements_pairs_scaled[kk])  # Note minus sign
                        nearby_beads.append(nearby_bead)
                        nearby_beads_distances.append(
                            distances_pairs_scaled[kk])
                A_sum = 0
                pp = 0
                for p_index in nearby_beads:
                    lam_p = bead_sizes[p_index] / bead_sizes[
                        a1_index]  # size_ratio_matrix[a1_index,p_index]
                    largest_size_p = max(bead_sizes[a1_index],
                                         bead_sizes[p_index])
                    if lam_p not in lam_range_with_reciprocals:
                        print "ERROR (Code point D): lambda not in the table of calculated values"
                    lam_index_p = np.where(
                        lam_range_with_reciprocals == lam_p)[0][0]
                    lam_index_recip_p = np.where(
                        lam_range_with_reciprocals == 1. / lam_p)[0][0]
                    r_p = nearby_beads_displacements[pp]
                    s_dash_p = nearby_beads_distances[pp]
                    d_p = r_p / s_dash_p
                    A_sum = A_sum + np.asarray([[
                        Af(0, d_p, lam_index_p, s_dash_p, i, j,
                           fully_2d_problem) * largest_size_p**uv_power[0][0]
                        for j in xrange(3)
                    ] for i in xrange(3)])
                    pp = pp + 1
                R2Bexact[R44_coords] = A_sum
            else:
                if bead_bead_interactions:
                    R2Bexact[R44_coords] = [[
                        Af(1, d, lam_index, s_dash, i, j, fully_2d_problem) *
                        largest_size**uv_power[0][0] for j in xrange(3)
                    ] for i in xrange(3)]

        elif a1_index >= num_spheres and a1_index < num_spheres + num_dumbbells and a2_index >= num_spheres + num_dumbbells:
            # Dumbbell bead 1 to dumbbell bead 2
            if bead_bead_interactions:
                a1_index_d = a1_index - num_spheres
                a2_index_d = a2_index - num_spheres - num_dumbbells
                R45_coords = np.s_[11 * num_spheres +
                                   a1_index_d * 3:11 * num_spheres +
                                   (a1_index_d + 1) * 3,
                                   11 * num_spheres + 3 * num_dumbbells +
                                   a2_index_d * 3:11 * num_spheres +
                                   3 * num_dumbbells + (a2_index_d + 1) * 3]
                R2Bexact[R45_coords] = [[
                    Af(1, d, lam_index, s_dash, i, j, fully_2d_problem) *
                    largest_size**uv_power[0][0] for j in xrange(3)
                ] for i in xrange(3)]

        else:
            # Dumbbell bead 2 to dumbbell bead 2
            a1_index_d = a1_index - num_spheres - num_dumbbells
            a2_index_d = a2_index - num_spheres - num_dumbbells
            R55_coords = np.s_[11 * num_spheres + 3 * num_dumbbells +
                               a1_index_d * 3:11 * num_spheres +
                               3 * num_dumbbells + (a1_index_d + 1) * 3,
                               11 * num_spheres + 3 * num_dumbbells +
                               a2_index_d * 3:11 * num_spheres +
                               3 * num_dumbbells + (a2_index_d + 1) * 3]
            if a1_index == a2_index:
                nearby_beads = []
                nearby_beads_displacements = []
                nearby_beads_distances = []
                for kk in xrange(len(closer_than_cutoff_pairs_scaled)):
                    (i, j) = closer_than_cutoff_pairs_scaled[kk]
                    if (i == a1_index and i != j):
                        nearby_bead = j
                        nearby_beads_displacements.append(
                            displacements_pairs_scaled[kk])
                        nearby_beads.append(nearby_bead)
                        nearby_beads_distances.append(
                            distances_pairs_scaled[kk])
                    if (j == a1_index and i != j):
                        nearby_bead = i
                        nearby_beads_displacements.append(
                            -displacements_pairs_scaled[kk])  # Note minus sign
                        nearby_beads.append(nearby_bead)
                        nearby_beads_distances.append(
                            distances_pairs_scaled[kk])
                A_sum = 0
                pp = 0
                for p_index in nearby_beads:
                    lam_p = bead_sizes[p_index] / bead_sizes[
                        a1_index]  # size_ratio_matrix[a1_index,p_index]
                    largest_size_p = max(bead_sizes[a1_index],
                                         bead_sizes[p_index])
                    if lam_p not in lam_range_with_reciprocals:
                        print "ERROR (Code point D): lambda not in the table of calculated values"
                    lam_index_p = np.where(
                        lam_range_with_reciprocals == lam_p)[0][0]
                    lam_index_recip_p = np.where(
                        lam_range_with_reciprocals == 1. / lam_p)[0][0]
                    r_p = nearby_beads_displacements[pp]
                    s_dash_p = nearby_beads_distances[pp]
                    d_p = r_p / s_dash_p
                    A_sum = A_sum + np.asarray([[
                        Af(0, d_p, lam_index_p, s_dash_p, i, j,
                           fully_2d_problem) * largest_size_p**uv_power[0][0]
                        for j in xrange(3)
                    ] for i in xrange(3)])
                    pp = pp + 1
                R2Bexact[R55_coords] = A_sum
            else:
                if bead_bead_interactions:
                    R2Bexact[R55_coords] = [[
                        Af(1, d, lam_index, s_dash, i, j, fully_2d_problem) *
                        largest_size**uv_power[0][0] for j in xrange(3)
                    ] for i in xrange(3)]

        ii = ii + 1

    # Scale by 6pi
    R2Bexact = R2Bexact * 6 * np.pi

    # symmetrise
    R2Bexact = sparse.triu(R2Bexact) + sparse.triu(R2Bexact, k=1).transpose()

    # Row and column ops I want are equivalent to doing
    # [ 1  0  0 ]   [ a b c ]   [ 1  0  0 ]
    # [ 0  1  1 ] . [ d e f ] . [ 0  1 -1 ]
    # [ 0 -1  1 ]   [ g h i ]   [ 0  1  1 ]
    #   "L"                         "R"

    # I know that we could generate L and R elsewhere rather than doing it every timestep but it takes 0.01s for a few thousand dumbbells so for now I don't mind
    Lrow = np.array([i for i in xrange(11 * num_spheres + 6 * num_dumbbells)] +
                    [i + 11 * num_spheres
                     for i in xrange(3 * num_dumbbells)] + [
                         i + 11 * num_spheres + 3 * num_dumbbells
                         for i in xrange(3 * num_dumbbells)
                     ])
    Lcol = np.array([i
                     for i in xrange(11 * num_spheres + 6 * num_dumbbells)] + [
                         i + 11 * num_spheres + 3 * num_dumbbells
                         for i in xrange(3 * num_dumbbells)
                     ] +
                    [i + 11 * num_spheres for i in xrange(3 * num_dumbbells)])
    Ldata = np.array([1
                      for i in xrange(11 * num_spheres + 9 * num_dumbbells)] +
                     [-1 for i in xrange(3 * num_dumbbells)])
    L = coo_matrix((Ldata, (Lrow, Lcol)),
                   shape=(11 * num_spheres + 6 * num_dumbbells,
                          11 * num_spheres + 6 * num_dumbbells))
    R = L.transpose()
    return (mu * (L * R2Bexact * R), "R2Bexact")
예제 #4
0
def fts_to_fte_matrix(posdata, grand_mobility_matrix):
    (sphere_sizes, sphere_positions, sphere_rotations,  dumbbell_sizes, dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells, element_sizes, element_positions, element_deltax,  num_elements, num_elements_array, element_type, uv_start, uv_size, element_start_count) = posdata_data(posdata)
    M = grand_mobility_matrix
    C0 = 0
    C1 = 3*num_spheres
    C2 = 6*num_spheres
    C3 = 11*num_spheres
    C4 = 11*num_spheres + 3*num_dumbbells
    C5 = 11*num_spheres + 6*num_dumbbells

    gt = M[C0:C1,C2:C3]
    g = gt.transpose()
    ht = M[C1:C2,C2:C3]
    h = ht.transpose()
    m =  M[C2:C3,C2:C3]
    m34= M[C2:C3,C3:C4]
    m43 = m34.transpose()
    m35= M[C2:C3,C4:C5]
    m53 = m35.transpose()

    # Not possible to have dumbbells only because this is an FTS to FTE conversion, and E is only there for spheres.
    if num_spheres > 0 and num_dumbbells > 0:
        items_in_vector = 5
    else:
        items_in_vector = 3

    starts = [C0,C1,C2,C3,C4,C5]

    m_inv = np.linalg.inv(m)
    crosspoint = 2 #corresponds to the ghm row/col
    if num_spheres > 0 and num_dumbbells > 0:
        vec1 = [gt,ht,m,m43,m53]
        vec2 = [g, h, m,m34,m35]
    if num_spheres > 0 and num_dumbbells == 0:
        vec1 = [gt,ht,m]
        vec2 = [g, h, m]

    MFTE = M - vecmat_mat_vecmat(vec1,m_inv,vec2,C5,items_in_vector,starts) - vec_mat_cross(vec1,m_inv,vec2,C5,items_in_vector,starts,crosspoint)

    return MFTE
def input_ftsuoe(n,posdata,frameno,timestep,last_velocities,input_form='undefined',video=False,grand_resistance_matrix_fte=0):
    # Initialise all vectors in the left and right-hand sides. Then define num_spheres and num_dumbbells
    (Fa_in, Ta_in, Sa_in, Sa_c_in, Fb_in, DFb_in, Ua_in, Oa_in, Ea_in, Ea_c_in, Ub_in, DUb_in) = empty_vectors(posdata)
    (sphere_sizes, sphere_positions, sphere_rotations,  dumbbell_sizes, dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells, element_sizes, element_positions, element_deltax,  num_elements, num_elements_array, element_type, uv_start, uv_size, element_start_count) = posdata_data(posdata)

    # Fa_in:  Forces on spheres
    # Ta_in:  Torque on spheres
    # Sa_in:  Stresslets on spheres
    # Fb_in:  Forces on dumbbells (total force on dumbbell, F1+F2)
    # DFb_in: Internal force on dumbbells (Delta F = F2-F1)
    # Ua_in:  Velocity of spheres
    # Oa_in:  Angular velocity of spheres
    # Ea_in:  Rate of strain, E^infinity
    # Ub_in:  Velocity of dumbbells
    # DUb_in: HALF the velocity difference of the dumbbells ((U2-U1)/2)

    # Give values. You must give at least half the total number of U/O/E/F/T/S values.
    # If you are giving a mix of F and U values for spheres,   you must put label the spheres   s.t. the fixed velocity spheres   are numbered first.
    # If you are giving a mix of F and U values for dumbbells, you must put label the dumbbells s.t. the fixed velocity dumbbells are numbered first.

    # Defaults
    mu = 1
    desc = ""
    box_bottom_left = np.array([0,0,0])
    box_top_right = np.array([0,0,0])
    # Background velocity is given by u^infinity = U^infinity + Omega^infinity cross x + E^infinity dot x
    # U^infinity and O^infinity are reset here and are changed for each case if required.
    # E^infinity is input for each case as Ea_in, and is also reset here if you're using FTE form.
    U_infinity = np.array([0,0,0])
    O_infinity = np.array([0,0,0])
    if input_form == "fte":
        Fa_in[:] = [[0,0,0] for i in xrange(num_spheres)]
        Ta_in[:] = [[0,0,0] for i in xrange(num_spheres)]
        Ea_in[:] = [[[0,0,0],[0,0,0],[0,0,0]] for i in xrange(num_spheres)]
        Fb_in[:] = [[0,0,0] for i in xrange(num_dumbbells)]
        DFb_in[:] = [[0,0,0] for i in xrange(num_dumbbells)]
    elif input_form == "fts":
        Fa_in[:] = [[0,0,0] for i in xrange(num_spheres)]
        Ta_in[:] = [[0,0,0] for i in xrange(num_spheres)]
        Sa_in[:] = [[[0,0,0],[0,0,0],[0,0,0]] for i in xrange(num_spheres)]
        Fb_in[:] = [[0,0,0] for i in xrange(num_dumbbells)]
        DFb_in[:] = [[0,0,0] for i in xrange(num_dumbbells)]
    if input_form == "ufte":
        Ta_in[:] = [[0,0,0] for i in xrange(num_spheres)]
        Ea_in[:] = [[[0,0,0],[0,0,0],[0,0,0]] for i in xrange(num_spheres)]
        Fb_in[:] = [[0,0,0] for i in xrange(num_dumbbells)]
        DFb_in[:] = [[0,0,0] for i in xrange(num_dumbbells)]
    centre_of_background_flow = np.array([0,0,0])
    amplitude = 0
    frequency = 0
    num_sphere_in_each_lid = 0

    if n == 1:
        # Gravity
        Fa_in[:] = [[0,0,-1] for i in xrange(num_spheres)]
        desc = "gravity"

    elif n == 2:
        # Gravity in periodic domain
        Fa_in[:] = [[0,0,-1] for i in xrange(num_spheres)]
        sphere_positions,box_bottom_left,box_top_right = simple_cubic_8(8)
        # sphere_positions is ignored here, but to activate periodicity, you have to set box_bottom_left and box_top_right.
        desc = "gravity-periodic"

    elif n == 3:
        # Oscillatory background flow, about the point (2.25,0,2.25)
        natural_deltax = 2.
        spring_constant = -1
        DFb_in[:] = [list(spring_constant*(dumbbell_deltax[i]-natural_deltax*dumbbell_deltax[i]/np.linalg.norm(dumbbell_deltax[i]))) for i in range(num_dumbbells)]
        # Simple shear with speed gammadot
        startfromframe = 0
        # amplitude is amplitude at z = 1
        (Ea_in, U_infinity, O_infinity, centre_of_background_flow, amplitude, frequency) = oscillatory_shear(amplitude=1./3., period=1, start_from_frame=0,  centre_of_background_flow=np.array([2.25,0,2.25]), frameno=frameno, timestep=timestep, num_spheres=num_spheres)
        desc = "oscillatory-background-flow"

    elif n == 4:
        # Repulsive force
        (Fa_in, Fb_in, DFb_in) = repulsion_forces(100, 20, num_spheres, num_dumbbells, sphere_positions, dumbbell_positions, dumbbell_deltax, sphere_sizes, dumbbell_sizes, num_sphere_in_each_lid, Fa_in, Fb_in, DFb_in)
        desc = "repulsion"

    elif n == 5:
        # Force half the spheres to move to the left with a given velocity, and force the rest to move to the right.
        Ua_in[:] = [[-1,0,0] for i in xrange(num_spheres/2)] + [[1,0,0] for i in xrange(num_spheres/2,num_spheres)]

    elif n == 6:
        # Continuous shear
        gammadot = 1
        O_infinity = np.array([0,0.5*gammadot,0])
        Ea_in = [[[0,0,0.5*gammadot],[0,0,0],[0.5*gammadot,0,0]] for i in xrange(max(1,num_spheres))]
        desc = "continuous-shear"

    elif n == 7:
        # Gravity
        Fa_in[1] = [0,0,-1]
        desc = "gravity"

    else:
        Fa_in = np.array([[99999,-31415,21718]]) # Just something to flag up on the other side that there's a problem

    return Fa_in, Ta_in, Sa_in, Sa_c_in, Fb_in, DFb_in, Ua_in, Oa_in, Ea_in, Ea_c_in, Ub_in, DUb_in, desc, U_infinity, O_infinity, centre_of_background_flow, amplitude, frequency, box_bottom_left, box_top_right, mu
예제 #6
0
def construct_force_vector_from_fts(posdata, f_spheres, t_spheres, s_spheres, f_dumbbells, deltaf_dumbbells):
    (sphere_sizes, sphere_positions, sphere_rotations,  dumbbell_sizes, dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells, element_sizes, element_positions, element_deltax,  num_elements, num_elements_array, element_type, uv_start, uv_size, element_start_count) = posdata_data(posdata)
    s_spheres_condensed = [['pippa' for i in xrange(5)] for j in xrange(num_spheres)]
    for i in xrange(num_spheres):
        for j in xrange(5):
            s_spheres_condensed[i][j] = sum([sum([contraction(j,k,l)*s_spheres[i][k][l] for k in xrange(3)]) for l in xrange(3)])

    if num_spheres == 0 and num_dumbbells == 0:
        force_vector = np.array([])
    if num_spheres > 0 and num_dumbbells == 0:
        fs = [item for sublist in f_spheres for item in sublist]
        ts = [item for sublist in t_spheres for item in sublist]
        ss = [item for sublist in s_spheres_condensed for item in sublist]
        force_vector = np.fromiter(chain.from_iterable(np.array([fs, ts, ss]).flatten()),float)
    if num_spheres == 0 and num_dumbbells > 0:
        force_vector = np.array([f_dumbbells, deltaf_dumbbells]).flatten()
    if num_spheres > 0 and num_dumbbells > 0:
        fs = [item for sublist in f_spheres for item in sublist]
        ts = [item for sublist in t_spheres for item in sublist]
        ss = [item for sublist in s_spheres_condensed for item in sublist]
        fd = [item for sublist in f_dumbbells for item in sublist]
        dfd= [item for sublist in deltaf_dumbbells for item in sublist]
        force_vector = np.hstack(np.array([fs, ts, ss, fd, dfd]).flat)
    return force_vector
예제 #7
0
def deconstruct_velocity_vector_for_fts(posdata, velocity_vector):
    (sphere_sizes, sphere_positions, sphere_rotations,  dumbbell_sizes, dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells, element_sizes, element_positions, element_deltax,  num_elements, num_elements_array, element_type, uv_start, uv_size, element_start_count) = posdata_data(posdata)
    N1 = 3*num_spheres
    N2 = 6*num_spheres
    N3 = 11*num_spheres
    N4 = 11*num_spheres + 3*num_dumbbells
    N5 = 11*num_spheres + 6*num_dumbbells
    u_spheres = velocity_vector[0:N1].reshape(num_spheres,3)
    o_spheres = velocity_vector[N1:N2].reshape(num_spheres,3)
    e_spheres_condensed = velocity_vector[N2:N3].reshape(num_spheres,5)
    u_dumbbells = velocity_vector[N3:N4].reshape(num_dumbbells,3)
    half_deltau_dumbbells = velocity_vector[N4:N5].reshape(num_dumbbells,3)
    e_spheres = np.zeros([num_spheres,3,3])
    for i in xrange(num_spheres):
        e_spheres[i,0,0] = (np.sqrt(3)+3)/6. * e_spheres_condensed[i,0] + (np.sqrt(3)-3)/6. * e_spheres_condensed[i,2]
        e_spheres[i,0,1] = e_spheres_condensed[i,1]/np.sqrt(2)
        e_spheres[i,0,2] = e_spheres_condensed[i,3]/np.sqrt(2)
        e_spheres[i,1,0] = e_spheres[i,0,1]
        e_spheres[i,1,1] = (np.sqrt(3)-3)/6. * e_spheres_condensed[i,0] + (np.sqrt(3)+3)/6. * e_spheres_condensed[i,2]
        e_spheres[i,1,2] = e_spheres_condensed[i,4]/np.sqrt(2)
        e_spheres[i,2,0] = e_spheres[i,0,2]
        e_spheres[i,2,1] = e_spheres[i,1,2]
        e_spheres[i,2,2] = -e_spheres[i,1,1] - e_spheres[i,0,0]
    return (u_spheres, o_spheres, e_spheres, u_dumbbells, half_deltau_dumbbells)
예제 #8
0
def ufte_to_ufteu_matrix(num_fixed_velocity_dumbbells,num_fixed_velocity_spheres,posdata, grand_mobility_matrix_ufte):
    (sphere_sizes, sphere_positions, sphere_rotations,  dumbbell_sizes, dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells, element_sizes, element_positions, element_deltax,  num_elements, num_elements_array, element_type, uv_start, uv_size, element_start_count) = posdata_data(posdata)
    M = grand_mobility_matrix_ufte
    C0 = 0
    C05= 3*num_fixed_velocity_spheres
    C1 = 3*num_spheres
    C2 = 6*num_spheres
    C3 = 11*num_spheres
    C35 = 11*num_spheres + 3*num_fixed_velocity_dumbbells
    C4 = 11*num_spheres + 3*num_dumbbells
    C45 = 11*num_spheres + 3*num_dumbbells + 3*num_fixed_velocity_dumbbells
    C5 = 11*num_spheres + 6*num_dumbbells

    starts = [C0,C05,C1,C2,C3,C35,C4,C45,C5]

    # now m44 and m55 have been split up into x (fixed velocity particles) and r (free velocity particles)
    # M = [axx   axr   btx  gtx  m14xx m14xr m15xx m15xr]
    #     [arx   arr   btr  gtr  m14rx m14rr m15rx m15rr]
    #     [bx    br    c    ht   m24x  m24r  m25x  m25r ]
    #     [gx    gr    h    m    m34x  m34r  m35x  m35r ]
    #     [m41xx m41rx m42x m43x m44xx m44xr m45xx m45xr]
    #     etc

    # Step 1. Swap the m44xx row and column

    m41xx =  M[C3:C35,C0:C05]
    m41rx =  M[C3:C35,C05:C1]
    m42x =  M[C3:C35,C1:C2]
    m43x =  M[C3:C35,C2:C3]
    m44xx =  M[C3:C35,C3:C35]
    m44xr =  M[C3:C35,C35:C4]
    m45xx =  M[C3:C35,C4:C45]
    m45xr =  M[C3:C35,C45:C5]
    m14xx = -m41xx.transpose()
    m14rx = m41rx.transpose()
    m24x = m42x.transpose()
    m34x = -m43x.transpose()  
    m44rx = m44xr.transpose()
    m54xx = m45xx.transpose()
    m54rx = m45xr.transpose()

    # Currently I haven't put in dumbbells only because there's no point I think. Since this comes from an FTE conversion, and E is only for spheres, that would need dealing with first.
    # If there are no dumbbells then doing this is pointless, so I am assuming there are dumbbells.
    items_in_vector = 7+1

    m44xx_inv = np.linalg.inv(m44xx)

    crosspoint=4  #corresponds to the m44xx row/col
    vec1 = [m14xx,m14rx,m24x,m34x,m44xx,m44rx,m54xx,m54rx] #down
    vec2 = [m41xx,m41rx,m42x,m43x,m44xx,m44xr,m45xx,m45xr] # across

    MUFTEU1 = M - vecmat_mat_vecmat(vec1,m44xx_inv,vec2,C5,items_in_vector,starts) - vec_mat_cross(vec1,m44xx_inv,vec2,C5,items_in_vector,starts,crosspoint)

    # Step 2. Swap the m55xx row and column

    M = MUFTEU1

    m51xx =  M[C4:C45,C0:C05]
    m51rx =  M[C4:C45,C05:C1]
    m52x =  M[C4:C45,C1:C2]
    m53x =  M[C4:C45,C2:C3]
    m54xx =  M[C4:C45,C3:C35]
    m54xr =  M[C4:C45,C35:C4]
    m55xx =  M[C4:C45,C4:C45]
    m55xr =  M[C4:C45,C45:C5]
    m15xx = -m51xx.transpose()
    m15rx = m51rx.transpose()
    m25x = m52x.transpose()
    m35x = -m53x.transpose()
    m45xx = -m54xx.transpose()
    m45rx = m54xr.transpose()
    m55rx = m55xr.transpose()

    m55xx_inv = np.linalg.inv(m55xx)

    crosspoint=6  #corresponds to the m55xx row/col
    vec1 = [m15xx,m15rx,m25x,m35x,m45xx,m45rx,m55xx,m55rx] #down
    vec2 = [m51xx,m51rx,m52x,m53x,m54xx,m54xr,m55xx,m55xr] # across

    MUFTEU = M - vecmat_mat_vecmat(vec1,m55xx_inv,vec2,C5,items_in_vector,starts) - vec_mat_cross(vec1,m55xx_inv,vec2,C5,items_in_vector,starts,crosspoint)


    return MUFTEU
예제 #9
0
def fts_to_duf_matrix(num_fixed_velocity_dumbbells,posdata, grand_mobility_matrix_fts):
    (sphere_sizes, sphere_positions, sphere_rotations,  dumbbell_sizes, dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells, element_sizes, element_positions, element_deltax,  num_elements, num_elements_array, element_type, uv_start, uv_size, element_start_count) = posdata_data(posdata)
    M = grand_mobility_matrix_fts
    C3 = 0
    C35 = 3*num_fixed_velocity_dumbbells
    C4 = 3*num_dumbbells
    C45 = 3*num_dumbbells + 3*num_fixed_velocity_dumbbells
    C5 = 6*num_dumbbells

    starts = [C3,C35,C4,C45,C5]

    # now m44 and m55 have been split up into x (fixed velocity particles) and r (free velocity particles)
    # M = [m44xx m44xr m45xx m45xr]
    #     [m44rx m44rr m45rx m45rr]
    #     etc

    # Step 1. Swap the m44xx row and column

    m44xx =  M[C3:C35,C3:C35]
    m44xr =  M[C3:C35,C35:C4]
    m45xx =  M[C3:C35,C4:C45]
    m45xr =  M[C3:C35,C45:C5]
    m44rx = m44xr.transpose()
    m54xx = m45xx.transpose()
    m54rx = m45xr.transpose()

    # Currently I haven't put in dumbbells only because there's no point I think. Since this comes from an FTE conversion, and E is only for spheres, that would need dealing with first.
    # If there are no dumbbells then doing this is pointless, so I am assuming there are dumbbells.
    items_in_vector = 4

    m44xx_inv = np.linalg.inv(m44xx)

    crosspoint=0  #corresponds to the m44xx row/col
    vec1 = [m44xx,m44rx,m54xx,m54rx] #down
    vec2 = [m44xx,m44xr,m45xx,m45xr] # across

    MDUF1 = M - vecmat_mat_vecmat(vec1,m44xx_inv,vec2,C5,items_in_vector,starts) - vec_mat_cross(vec1,m44xx_inv,vec2,C5,items_in_vector,starts,crosspoint)

    # Step 2. Swap the m55xx row and column

    M = MDUF1

    m54xx =  M[C4:C45,C3:C35]
    m54xr =  M[C4:C45,C35:C4]
    m55xx =  M[C4:C45,C4:C45]
    m55xr =  M[C4:C45,C45:C5]
    m45xx = -m54xx.transpose()
    m45rx = m54xr.transpose()
    m55rx = m55xr.transpose()

    m55xx_inv = np.linalg.inv(m55xx)

    crosspoint=2  #corresponds to the m55xx row/col
    vec1 = [m45xx,m45rx,m55xx,m55rx] #down
    vec2 = [m54xx,m54xr,m55xx,m55xr] # across

    MDUF = M - vecmat_mat_vecmat(vec1,m55xx_inv,vec2,C5,items_in_vector,starts) - vec_mat_cross(vec1,m55xx_inv,vec2,C5,items_in_vector,starts,crosspoint)


    return MDUF
예제 #10
0
def empty_vectors(posdata):
    (sphere_sizes, sphere_positions, sphere_rotations,  dumbbell_sizes, dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells, element_sizes, element_positions, element_deltax,  num_elements, num_elements_array, element_type, uv_start, uv_size, element_start_count) = posdata_data(posdata)
    return ([['pippa' for j in xrange(3)] for i in xrange(num_spheres)],
            [['pippa' for j in xrange(3)] for i in xrange(num_spheres)],
            [[['pippa' for k in xrange(3)] for j in xrange(3)] for i in xrange(num_spheres)],
            [['pippa' for j in xrange(5)] for i in xrange(num_spheres)],
            [['pippa' for j in xrange(3)] for i in xrange(num_dumbbells)],
            [['pippa' for j in xrange(3)] for i in xrange(num_dumbbells)],
            [['pippa' for j in xrange(3)] for i in xrange(num_spheres)],
            [['pippa' for j in xrange(3)] for i in xrange(num_spheres)],
            [[['pippa' for k in xrange(3)] for j in xrange(3)] for i in xrange(num_spheres)],
            [['pippa' for j in xrange(5)] for i in xrange(num_spheres)],
            [['pippa' for j in xrange(3)] for i in xrange(num_dumbbells)],
            [['pippa' for j in xrange(3)] for i in xrange(num_dumbbells)])
예제 #11
0
def fte_to_ufte_matrix(num_fixed_velocity_spheres,posdata, grand_mobility_matrix_fte):
    (sphere_sizes, sphere_positions, sphere_rotations,  dumbbell_sizes, dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells, element_sizes, element_positions, element_deltax,  num_elements, num_elements_array, element_type, uv_start, uv_size, element_start_count) = posdata_data(posdata)
    M = grand_mobility_matrix_fte
    C0 = 0
    C05= 3*num_fixed_velocity_spheres
    C1 = 3*num_spheres
    C2 = 6*num_spheres
    C3 = 11*num_spheres
    C4 = 11*num_spheres + 3*num_dumbbells
    C5 = 11*num_spheres + 6*num_dumbbells

    # a has been split up into x (fixed velocity particles) and r (free velocity particles)
    # M = [axx axr btx gtx m14x m15x]
    #     [arx arr btr gtr m14r m15r]
    #     [bx  br  c   ht  m24  m25 ]
    #     [gx  gr  h   m   m34  m35

    axx =  M[C0:C05,C0:C05]
    axr =  M[C0:C05,C05:C1]
    arx =  M[C05:C1,C0:C05]
    btx = M[C0:C05,C1:C2]
    bx = btx.transpose()
    gtx = M[C0:C05,C2:C3]
    gx = -gtx.transpose() #note MFTE has slightly different sign symmetries
    m14x= M[C0:C05,C3:C4]
    m15x= M[C0:C05,C4:C5]
    m51x = m15x.transpose() # these don't need a minus sign.
    m41x = m14x.transpose() #

    # Not possible to have dumbbells only because this is an FTS to FTE conversion, and E is only there for spheres.
    if num_spheres > 0 and num_dumbbells > 0:
        items_in_vector = 5+1
    else:
        items_in_vector = 3+1

    starts = [C0,C05,C1,C2,C3,C4,C5]

    axx_inv = np.linalg.inv(axx)
    gx = np.asarray(gx)

    crosspoint=0  #corresponds to the ghm row/col
    if num_spheres > 0 and num_dumbbells > 0:
        vec1 = [axx,arx,bx,gx,m41x,m51x]
        vec2 = [axx,axr,btx,gtx,m14x,m15x]
    if num_spheres > 0 and num_dumbbells == 0:
        vec1 = [axx,arx,bx,gx]
        vec2 = [axx,axr,btx,gtx]

    MFTE = M - vecmat_mat_vecmat(vec1,axx_inv,vec2,C5,items_in_vector,starts) - vec_mat_cross(vec1,axx_inv,vec2,C5,items_in_vector,starts,crosspoint)

    return MFTE
예제 #12
0
def zero_force_vectors(posdata):
    (sphere_sizes, sphere_positions, sphere_rotations,  dumbbell_sizes, dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells, element_sizes, element_positions, element_deltax,  num_elements, num_elements_array, element_type, uv_start, uv_size, element_start_count) = posdata_data(posdata)
    return (np.zeros([num_spheres,3]),np.zeros([num_spheres,3]),np.zeros([num_spheres,3,3]),np.zeros([num_spheres,5]),np.zeros([num_dumbbells,3]),np.zeros([num_dumbbells,3]))
예제 #13
0
def generate_grand_resistance_matrix(posdata,
                                     last_generated_Minfinity_inverse,
                                     regenerate_Minfinity=False,
                                     cutoff_factor=2,
                                     printout=0,
                                     use_XYZd_values=True,
                                     use_drag_Minfinity=False,
                                     use_Minfinity_only=False,
                                     frameno=0,
                                     checkpoint_start_from_frame=0,
                                     feed_every_n_timesteps=0,
                                     mu=1):
    '''
    if use_XYZd_values:
        d = "-d"
    else:
        d = ""
    '''
    d = "-d"

    Minfinity_start_time = time.time()
    if not (use_drag_Minfinity):
        if regenerate_Minfinity:
            (Minfinity, headingM) = generate_Minfinity(posdata,
                                                       printout,
                                                       frameno=frameno,
                                                       mu=mu)
            Minfinity_elapsed_time = time.time() - Minfinity_start_time
            Minfinity_inverse_start_time = time.time()
            Minfinity_inverse = linalg.inv(Minfinity)
            if printout > 0:
                print "Minfinity[0:12]"
                print np.array_str(Minfinity[0:12, 0:12],
                                   max_line_width=100000)
        else:
            Minfinity_elapsed_time = time.time() - Minfinity_start_time
            Minfinity_inverse_start_time = time.time()
            Minfinity_inverse = last_generated_Minfinity_inverse
        Minfinity_inverse_elapsed_time = time.time(
        ) - Minfinity_inverse_start_time
    else:
        (sphere_sizes, sphere_positions, sphere_rotations, dumbbell_sizes,
         dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells,
         element_sizes, element_positions, element_deltax, num_elements,
         num_elements_array, element_type, uv_start, uv_size,
         element_start_count) = posdata_data(posdata)
        Minfinity_inverse = mu * np.diag(
            [sphere_sizes[i / 3] for i in xrange(3 * num_spheres)] + [
                1 / 0.75 * sphere_sizes[i / 3]**3
                for i in xrange(3 * num_spheres)
            ] + [
                1 / 0.9 * sphere_sizes[i / 5]**3
                for i in xrange(5 * num_spheres)
            ] + [2 * dumbbell_sizes[i / 3]
                 for i in xrange(3 * num_dumbbells)] +
            [2 * dumbbell_sizes[i / 3] for i in xrange(3 * num_dumbbells)])
        Minfinity_elapsed_time = 0
        Minfinity_inverse_elapsed_time = 0

    if printout > 0:
        print "Minfinity_inverse"
        print np.array_str(Minfinity_inverse, max_line_width=100000)

    if not use_Minfinity_only:
        R2Bexact_start_time = time.time()
        # Whether we use the d values or not is selected in inputs.py where we read in XYZ_raw.
        if printout > 1:
            print "cutoff_factor is ", cutoff_factor
        (R2Bexact, heading) = generate_R2Bexact(
            posdata,
            printout,
            cutoff_factor=cutoff_factor,
            frameno=frameno,
            checkpoint_start_from_frame=checkpoint_start_from_frame,
            feed_every_n_timesteps=feed_every_n_timesteps,
            mu=mu)
        R2Bexact_elapsed_time = time.time() - R2Bexact_start_time
        if printout > 0:
            print "R2Bexact"
            print np.array_str(R2Bexact.toarray(), max_line_width=100000)

        grand_resistance_matrix = Minfinity_inverse + R2Bexact.toarray()
        if printout > 0:
            print "grand R"
            print np.array_str(grand_resistance_matrix, max_line_width=100000)

    else:
        grand_resistance_matrix = Minfinity_inverse
        R2Bexact = 0
        heading = ""
        R2Bexact_elapsed_time = 0

    if (printout > 1):
        print "M infinity"
        print np.array_str(Minfinity, max_line_width=100000)
        print "\n\nR2Bexact"
        print np.array_str(R2Bexact.toarray(), max_line_width=100000)
        print "\n\nGrand resistance matrix"
        print np.array_str(grand_resistance_matrix, max_line_width=100000)
        save_matrix(grand_resistance_matrix, "Grand Resistance Matrix",
                    "R-" + str(frameno) + ".txt")

    gen_times = [
        Minfinity_elapsed_time, Minfinity_inverse_elapsed_time,
        R2Bexact_elapsed_time
    ]
    return (grand_resistance_matrix, heading, Minfinity_inverse, gen_times)
예제 #14
0
def generate_grand_resistance_matrix_periodic(
        posdata,
        last_generated_Minfinity_inverse,
        box_bottom_left,
        box_top_right,
        regenerate_Minfinity=False,
        cutoff_factor=2,
        printout=0,
        use_XYZd_values=True,
        use_drag_Minfinity=False,
        use_Minfinity_only=False,
        frameno=0,
        checkpoint_start_from_frame=0,
        feed_every_n_timesteps=0,
        O_infinity=np.array([0, 0, 0]),
        E_infinity=np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0]]),
        timestep=0.1,
        centre_of_background_flow=np.array([0, 0, 0]),
        mu=1,
        amplitude=1,
        frequency=1):
    d = "-d"

    if not (use_drag_Minfinity):  # i.e. if we should do Minfinity properly:
        Minfinity_start_time = time.time()
        if regenerate_Minfinity:
            (Minfinity, headingM) = generate_Minfinity_periodic(
                posdata,
                box_bottom_left,
                box_top_right,
                printout,
                frameno=frameno,
                O_infinity=O_infinity,
                E_infinity=E_infinity,
                timestep=timestep,
                centre_of_background_flow=centre_of_background_flow,
                mu=mu,
                frequency=frequency,
                amplitude=amplitude)
            Minfinity_elapsed_time = time.time() - Minfinity_start_time
            Minfinity_inverse_start_time = time.time()
            Minfinity_inverse = linalg.inv(Minfinity)
        else:
            Minfinity_elapsed_time = time.time() - Minfinity_start_time
            Minfinity_inverse_start_time = time.time()
            Minfinity_inverse = last_generated_Minfinity_inverse
        Minfinity_inverse_elapsed_time = time.time(
        ) - Minfinity_inverse_start_time
    else:
        (sphere_sizes, sphere_positions, sphere_rotations, dumbbell_sizes,
         dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells,
         element_sizes, element_positions, element_deltax, num_elements,
         num_elements_array, element_type, uv_start, uv_size,
         element_start_count) = posdata_data(posdata)
        Minfinity_inverse = mu * np.diag(
            [sphere_sizes[i / 3] for i in xrange(3 * num_spheres)] + [
                1 / 0.75 * sphere_sizes[i / 3]**3
                for i in xrange(3 * num_spheres)
            ] + [
                1 / 0.9 * sphere_sizes[i / 5]**3
                for i in xrange(5 * num_spheres)
            ] + [2 * dumbbell_sizes[i / 3]
                 for i in xrange(3 * num_dumbbells)] +
            [2 * dumbbell_sizes[i / 3] for i in xrange(3 * num_dumbbells)])
        Minfinity_elapsed_time = 0
        Minfinity_inverse_elapsed_time = 0

    if not use_Minfinity_only:
        R2Bexact_start_time = time.time()
        (R2Bexact, heading) = generate_R2Bexact_periodic(
            posdata,
            box_bottom_left,
            box_top_right,
            printout,
            cutoff_factor=cutoff_factor,
            frameno=frameno,
            checkpoint_start_from_frame=checkpoint_start_from_frame,
            feed_every_n_timesteps=feed_every_n_timesteps,
            O_infinity=O_infinity,
            E_infinity=E_infinity,
            timestep=timestep,
            centre_of_background_flow=centre_of_background_flow,
            mu=mu,
            frequency=frequency,
            amplitude=amplitude)
        R2Bexact_elapsed_time = time.time() - R2Bexact_start_time
        grand_resistance_matrix = Minfinity_inverse + R2Bexact.toarray()
    else:
        grand_resistance_matrix = Minfinity_inverse
        R2Bexact = 0
        heading = ""
        R2Bexact_elapsed_time = 0

    gen_times = [
        Minfinity_elapsed_time, Minfinity_inverse_elapsed_time,
        R2Bexact_elapsed_time
    ]
    return (grand_resistance_matrix, heading, Minfinity_inverse, gen_times)
def generate_Minfinity_periodic(posdata, box_bottom_left, box_top_right, printout=0, cutoff_factor=2,frameno=0,O_infinity=np.array([0,0,0]),E_infinity=np.array([[0,0,0],[0,0,0],[0,0,0]]),timestep=0.1,centre_of_background_flow=np.array([0,0,0]),mu=1,frequency=1,amplitude=1):
    # NOTE: Centre of background flow currently not implemented - 27/1/2017
    (sphere_sizes, sphere_positions, sphere_rotations, dumbbell_sizes, dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells, element_sizes, element_positions, element_deltax,  num_elements, num_elements_array, element_type, uv_start, uv_size, element_start_count) = posdata_data(posdata)
    R2Bexact_sidelength = 11*num_spheres + 6*num_dumbbells
    R2Bexact = np.zeros((R2Bexact_sidelength, R2Bexact_sidelength), dtype=np.float)
    bead_positions = np.concatenate([sphere_positions,dumbbell_positions - 0.5*dumbbell_deltax, dumbbell_positions + 0.5*dumbbell_deltax])
    bead_sizes = np.concatenate([sphere_sizes, dumbbell_sizes, dumbbell_sizes])
    c = 1./(8*pi*mu)
    # Set lamb, the 'switch' between real and wavespace. Beenakker says set this as lambda = sqrt(pi)/L
    Lx = box_top_right[0] - box_bottom_left[0]
    Ly = box_top_right[1] - box_bottom_left[1]
    Lz = box_top_right[2] - box_bottom_left[2]
    L = (Lx*Ly*Lz)**(1./3.)
    lamb = math.sqrt(math.pi)/L
    gridpoints_x = [i for i in range(-how_far_to_reproduce_gridpoints,how_far_to_reproduce_gridpoints+1)]
    gridpoints_y = [i for i in range(-how_far_to_reproduce_gridpoints,how_far_to_reproduce_gridpoints+1)]
    gridpoints_z = [i for i in range(-how_far_to_reproduce_gridpoints,how_far_to_reproduce_gridpoints+1)]
    X_lmn_canonical = np.array([[ll,mm,nn] for ll in gridpoints_x for mm in gridpoints_y for nn in gridpoints_z])

    basis_canonical = np.array([[Lx,0,0],[0,Ly,0],[0,0,Lz]])
    # NOTE: For CONTINUOUS shear, set the following
    #time_t = frameno*timestep
    #sheared_basis_vectors_add_on = (np.cross(np.array(O_infinity)*time_t,basis_canonical).transpose() + np.dot(np.array(E_infinity)*time_t,(basis_canonical).transpose())).transpose()# + basis_canonical
    # NOTE: For OSCILLATORY shear, set the following (basically there isn't a way to find out shear given E)
    time_t = frameno*timestep
    gamma = amplitude*np.sin(time_t*frequency)
    Ot_infinity = np.array([0,0.5*gamma,0])
    Et_infinity = [[0,0,0.5*gamma],[0,0,0],[0.5*gamma,0,0]]
    sheared_basis_vectors_add_on = (np.cross(Ot_infinity,basis_canonical).transpose() + np.dot(Et_infinity,(basis_canonical).transpose())).transpose()

    sheared_basis_vectors_add_on_mod  = np.mod(sheared_basis_vectors_add_on,[Lx,Ly,Lz])
    sheared_basis_vectors = basis_canonical + sheared_basis_vectors_add_on_mod
    X_lmn_sheared = np.dot(X_lmn_canonical,sheared_basis_vectors)
    X_lmn_sheared_inside_radius = X_lmn_sheared[np.linalg.norm(X_lmn_sheared,axis=1)<=1.4142*how_far_to_reproduce_gridpoints*L] # NOTE: If you change this you have to change it in K_lmn as well!

    X_lmn = X_lmn_sheared_inside_radius
    Xdash_lmn = X_lmn_sheared_inside_radius[np.linalg.norm(X_lmn_sheared_inside_radius,axis=1)>0]
    Sdash_lmn = np.linalg.norm(Xdash_lmn,axis=1)
    erfcs_Sdash_lmn = [generate_erfcs(s,lamb) for s in Sdash_lmn]

    num_X_points = X_lmn.shape[0]
    num_Xdash_points = Xdash_lmn.shape[0]

    k_basis_vectors = 2*np.pi*L**(-3)*np.array([np.cross(sheared_basis_vectors[0],sheared_basis_vectors[2]),np.cross(sheared_basis_vectors[2],sheared_basis_vectors[1]),np.cross(sheared_basis_vectors[0],sheared_basis_vectors[1])])
    K_lmn = np.dot(X_lmn_canonical,k_basis_vectors)[np.logical_and(np.linalg.norm(X_lmn_sheared,axis=1)<=1.4142*how_far_to_reproduce_gridpoints*L,np.linalg.norm(X_lmn_sheared,axis=1)>0)]
    Ks_lmn = np.linalg.norm(K_lmn,axis=1)
    num_K_points = K_lmn.shape[0]
    RR_K = [-8*math.pi/ks**4 * (1 + ks**2/(4*lamb**2) + ks**4/(8*lamb**4)) * math.exp(-ks**2/(4*lamb**2)) for ks in Ks_lmn]

    for a1_index,a2_index in [(u,v) for u in range(len(bead_sizes)) for v in range(u,len(bead_sizes))]:
        r = (bead_positions[a2_index] - bead_positions[a1_index])
        a1 = bead_sizes[a1_index]
        a2 = bead_sizes[a2_index]
        s = norm(r)

        if s > 1e-8 and 2*s/(a1+a2) < 2.001:
            ss_out = 2.001*(a1+a2)/2
            r = [r[0]*ss_out/s,r[1]*ss_out/s,r[2]*ss_out/s]
            s = ss_out

        if a1_index < num_spheres and a2_index < num_spheres:
            # Sphere to sphere
            A_coords =  np.s_[              a1_index*3 :               (a1_index+1)*3,               a2_index*3 :               (a2_index+1)*3]
            Bt_coords = np.s_[              a1_index*3 :               (a1_index+1)*3, 3*num_spheres+a2_index*3 : 3*num_spheres+(a2_index+1)*3]
            Bt_coords_21 = np.s_[           a2_index*3 :               (a2_index+1)*3, 3*num_spheres+a1_index*3 : 3*num_spheres+(a1_index+1)*3]
            Gt_coords = np.s_[              a1_index*3 :               (a1_index+1)*3, 6*num_spheres+a2_index*5 : 6*num_spheres+(a2_index+1)*5]
            Gt_coords_21 = np.s_[           a2_index*3 :               (a2_index+1)*3, 6*num_spheres+a1_index*5 : 6*num_spheres+(a1_index+1)*5]
            C_coords =  np.s_[3*num_spheres+a1_index*3 : 3*num_spheres+(a1_index+1)*3, 3*num_spheres+a2_index*3 : 3*num_spheres+(a2_index+1)*3]
            Ht_coords = np.s_[3*num_spheres+a1_index*3 : 3*num_spheres+(a1_index+1)*3, 6*num_spheres+a2_index*5 : 6*num_spheres+(a2_index+1)*5]
            Ht_coords_21 = np.s_[3*num_spheres+a2_index*3 : 3*num_spheres+(a2_index+1)*3, 6*num_spheres+a1_index*5 : 6*num_spheres+(a1_index+1)*5]
            M_coords =  np.s_[6*num_spheres+a1_index*5 : 6*num_spheres+(a1_index+1)*5, 6*num_spheres+a2_index*5 : 6*num_spheres+(a2_index+1)*5]

            erfcs = generate_erfcs(s,lamb)
            R2Bexact[A_coords] =  [[M11(r,s,a1,a2,i,j,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu)  for j in range(3)] for i in range(3)]
            R2Bexact[Bt_coords] = [[M12(r,s,a1,a2,i,j,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu) for j in range(3)] for i in range(3)]
            R2Bexact[Bt_coords_21] = -R2Bexact[Bt_coords]
            R2Bexact[C_coords] =  [[M22(r,s,a1,a2,i,j,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu) for j in range(3)] for i in range(3)]
            R2Bexact[Gt_coords] = [[con_M13(r,s,a1,a2,i,j,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu) for j in range(5)] for i in range(3)]
            R2Bexact[Gt_coords_21] = -R2Bexact[Gt_coords]
            R2Bexact[Ht_coords] = [[con_M23(r,s,a1,a2,i,j,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu) for j in range(5)] for i in range(3)]
            R2Bexact[Ht_coords_21] = R2Bexact[Ht_coords]
            R2Bexact[M_coords] = [[con_M33(r,s,a1,a2,i,j,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu) for j in range(5)] for i in range(5)]


        elif a1_index < num_spheres and a2_index >= num_spheres and a2_index < num_spheres + num_dumbbells:
            # Sphere to dumbbell bead 1
            mr = [-r[0],-r[1],-r[2]]
            a2_index_d = a2_index-num_spheres
            R14_coords = np.s_[a1_index*3:(a1_index+1)*3,                             11*num_spheres+a2_index_d*3 : 11*num_spheres +(a2_index_d+1)*3]
            R24_coords = np.s_[3*num_spheres+a1_index*3:3*num_spheres+(a1_index+1)*3, 11*num_spheres+a2_index_d*3 : 11*num_spheres +(a2_index_d+1)*3]
            R34_coords = np.s_[6*num_spheres+a1_index*5:6*num_spheres+(a1_index+1)*5, 11*num_spheres+a2_index_d*3 : 11*num_spheres +(a2_index_d+1)*3]

            R2Bexact[R14_coords] = [[M11(r,s,a1,a2,i,j,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu)  for j in range(3)] for i in range(3)]
            R2Bexact[R24_coords] = [[M12(mr,s,a2,a1,j,i,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu)  for j in range(3)] for i in range(3)]
            R2Bexact[R34_coords] = [[con_M13(mr,s,a1,a2,j,i,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu)  for j in range(3)] for i in range(5)]


        elif a1_index < num_spheres and a2_index >= num_spheres + num_dumbbells:
            # Sphere to dumbbell bead 2
            mr = [-r[0],-r[1],-r[2]]
            a2_index_d = a2_index-num_spheres-num_dumbbells
            R15_coords = np.s_[a1_index*3:(a1_index+1)*3, 11*num_spheres+3*num_dumbbells+a2_index_d*3 : 11*num_spheres+3*num_dumbbells+(a2_index_d+1)*3]
            R25_coords = np.s_[3*num_spheres+a1_index*3:3*num_spheres+(a1_index+1)*3, 11*num_spheres+3*num_dumbbells+a2_index_d*3 : 11*num_spheres+3*num_dumbbells+(a2_index_d+1)*3]
            R35_coords = np.s_[6*num_spheres+a1_index*5:6*num_spheres+(a1_index+1)*5, 11*num_spheres+3*num_dumbbells+a2_index_d*3 : 11*num_spheres+3*num_dumbbells+(a2_index_d+1)*3]

            R2Bexact[R15_coords] = [[M11(r,s,a1,a2,i,j,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu)  for j in range(3)] for i in range(3)]
            R2Bexact[R25_coords] = [[M12(mr,s,a2,a1,j,i,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu)  for j in range(3)] for i in range(3)]
            R2Bexact[R35_coords] = [[con_M13(mr,s,a1,a2,j,i,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu)  for j in range(3)] for i in range(5)]

        elif a1_index >= num_spheres and a1_index < num_spheres + num_dumbbells and a2_index >= num_spheres and a2_index < num_spheres + num_dumbbells:
            # Dumbbell bead 1 to dumbbell bead 1
            a1_index_d = a1_index-num_spheres
            a2_index_d = a2_index-num_spheres
            if bead_bead_interactions or a1_index_d == a2_index_d:
                R44_coords = np.s_[11*num_spheres+a1_index_d*3:11*num_spheres+(a1_index_d+1)*3, 11*num_spheres+a2_index_d*3 : 11*num_spheres+(a2_index_d+1)*3]
                erfcs = generate_erfcs(s,lamb)
                R2Bexact[R44_coords] = [[M11(r,s,a1,a2,i,j,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu)  for j in range(3)] for i in range(3)]

                s_lmn = np.linalg.norm(r + X_lmn,axis=1)

        elif a1_index >= num_spheres and a1_index < num_spheres + num_dumbbells and a2_index >= num_spheres + num_dumbbells:
            # Dumbbell bead 1 to dumbbell bead 2
            a1_index_d = a1_index-num_spheres
            a2_index_d = a2_index-num_spheres-num_dumbbells
            if bead_bead_interactions or a1_index_d == a2_index_d:
                R45_coords = np.s_[11*num_spheres+a1_index_d*3:11*num_spheres+(a1_index_d+1)*3, 11*num_spheres+3*num_dumbbells+a2_index_d*3 : 11*num_spheres+3*num_dumbbells+(a2_index_d+1)*3]
                erfcs = generate_erfcs(s,lamb)
                R2Bexact[R45_coords] = [[M11(r,s,a1,a2,i,j,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu)  for j in range(3)] for i in range(3)]

        else:
            # Dumbbell bead 2 to dumbbell bead 2
            a1_index_d = a1_index-num_spheres-num_dumbbells
            a2_index_d = a2_index-num_spheres-num_dumbbells
            if bead_bead_interactions or a1_index_d == a2_index_d:
                R55_coords = np.s_[11*num_spheres+3*num_dumbbells+a1_index_d*3:11*num_spheres+3*num_dumbbells+(a1_index_d+1)*3, 11*num_spheres+3*num_dumbbells+a2_index_d*3 : 11*num_spheres+3*num_dumbbells+(a2_index_d+1)*3]
                erfcs = generate_erfcs(s,lamb)
                R2Bexact[R55_coords] = [[M11(r,s,a1,a2,i,j,erfcs, L, lamb, X_lmn, Xdash_lmn, Sdash_lmn, erfcs_Sdash_lmn, K_lmn, Ks_lmn, RR_K, num_X_points, num_Xdash_points, num_K_points,c,mu)  for j in range(3)] for i in range(3)]

    #symmetrise
    R2Bexact = np.triu(R2Bexact) + np.triu(R2Bexact,k=1).transpose()

    # Row and column ops I want are equivalent to doing
    #   [ 1    0    0 ]   [ a b c ]   [ 1    0    0 ]
    #   [ 0  1/2  1/2 ] . [ d e f ] . [ 0  1/2 -1/2 ]
    #   [ 0 -1/2  1/2 ]   [ g h i ]   [ 0  1/2  1/2 ]
    #        "L"                       "R"

    # I know that we could generate L and R elsewhere rather than doing it every timestep but it takes 0.01s for a few thousand dumbbells so for now I don't mind
    Lrow = np.array([i for i in range(11*num_spheres + 6*num_dumbbells)] + [i + 11*num_spheres for i in range(3*num_dumbbells)] + [i + 11*num_spheres + 3*num_dumbbells for i in range(3*num_dumbbells)])
    Lcol = np.array([i for i in range(11*num_spheres + 6*num_dumbbells)] + [i + 11*num_spheres + 3*num_dumbbells for i in range(3*num_dumbbells)] + [i + 11*num_spheres for i in range(3*num_dumbbells)])
    Ldata = np.array([1 for i in range(11*num_spheres)] + [0.5 for i in range(9*num_dumbbells)] + [-0.5 for i in range(3*num_dumbbells)])
    L = coo_matrix((Ldata, (Lrow, Lcol)), shape=(11*num_spheres+6*num_dumbbells, 11*num_spheres+6*num_dumbbells))
    R = L.transpose()
    return ((L*R2Bexact*R), "Minfinity")
def generate_Minfinity(posdata, printout=0, cutoff_factor=2, frameno=0, mu=1):
    (sphere_sizes, sphere_positions, sphere_rotations, dumbbell_sizes,
     dumbbell_positions, dumbbell_deltax, num_spheres, num_dumbbells,
     element_sizes, element_positions, element_deltax, num_elements,
     num_elements_array, element_type, uv_start, uv_size,
     element_start_count) = posdata_data(posdata)
    R2Bexact_sidelength = 11 * num_spheres + 6 * num_dumbbells
    R2Bexact = np.zeros((R2Bexact_sidelength, R2Bexact_sidelength),
                        dtype=np.float)
    bead_positions = np.concatenate([
        sphere_positions, dumbbell_positions - 0.5 * dumbbell_deltax,
        dumbbell_positions + 0.5 * dumbbell_deltax
    ])
    bead_sizes = np.concatenate([sphere_sizes, dumbbell_sizes, dumbbell_sizes])

    c = 1. / (8 * pi * mu)

    for a1_index, a2_index in [(u, v) for u in xrange(len(bead_sizes))
                               for v in xrange(u, len(bead_sizes))]:
        r = -(bead_positions[a2_index] - bead_positions[a1_index])
        a1 = bead_sizes[a1_index]
        a2 = bead_sizes[a2_index]
        s = norm(r)
        if s > 1e-8 and 2 * s / (a1 + a2) < 2.001:
            ss_out = 2.001 * (a1 + a2) / 2
            r = np.array(
                [r[0] * ss_out / s, r[1] * ss_out / s, r[2] * ss_out / s])
            s = ss_out

        if a1_index < num_spheres and a2_index < num_spheres:
            # Sphere to sphere
            A_coords = np.s_[a1_index * 3:(a1_index + 1) * 3,
                             a2_index * 3:(a2_index + 1) * 3]
            Bt_coords = np.s_[a1_index * 3:(a1_index + 1) * 3,
                              3 * num_spheres + a2_index * 3:3 * num_spheres +
                              (a2_index + 1) * 3]
            Bt_coords_21 = np.s_[a2_index * 3:(a2_index + 1) * 3,
                                 3 * num_spheres +
                                 a1_index * 3:3 * num_spheres +
                                 (a1_index + 1) * 3]
            Gt_coords = np.s_[a1_index * 3:(a1_index + 1) * 3,
                              6 * num_spheres + a2_index * 5:6 * num_spheres +
                              (a2_index + 1) * 5]
            Gt_coords_21 = np.s_[a2_index * 3:(a2_index + 1) * 3,
                                 6 * num_spheres +
                                 a1_index * 5:6 * num_spheres +
                                 (a1_index + 1) * 5]
            C_coords = np.s_[3 * num_spheres + a1_index * 3:3 * num_spheres +
                             (a1_index + 1) * 3, 3 * num_spheres +
                             a2_index * 3:3 * num_spheres + (a2_index + 1) * 3]
            Ht_coords = np.s_[3 * num_spheres + a1_index * 3:3 * num_spheres +
                              (a1_index + 1) * 3,
                              6 * num_spheres + a2_index * 5:6 * num_spheres +
                              (a2_index + 1) * 5]
            Ht_coords_21 = np.s_[3 * num_spheres +
                                 a2_index * 3:3 * num_spheres +
                                 (a2_index + 1) * 3, 6 * num_spheres +
                                 a1_index * 5:6 * num_spheres +
                                 (a1_index + 1) * 5]
            M_coords = np.s_[6 * num_spheres + a1_index * 5:6 * num_spheres +
                             (a1_index + 1) * 5, 6 * num_spheres +
                             a2_index * 5:6 * num_spheres + (a2_index + 1) * 5]

            R2Bexact[A_coords] = [[
                M11(r[i], r[j], s, a1, a2, i, j, c, mu) for j in xrange(3)
            ] for i in xrange(3)]
            R2Bexact[Bt_coords] = [[
                M12(r, s, a1, a2, i, j, c, mu) for j in xrange(3)
            ] for i in xrange(3)]
            R2Bexact[C_coords] = [[
                M22(r, s, a1, a2, i, j, c, mu) for j in xrange(3)
            ] for i in xrange(3)]
            R2Bexact[Gt_coords] = [[
                con_M13(r, s, a1, a2, i, j, c, mu) for j in xrange(5)
            ] for i in xrange(3)]
            R2Bexact[Ht_coords] = [[
                con_M23(r, s, a1, a2, i, j, c, mu) for j in xrange(5)
            ] for i in xrange(3)]
            R2Bexact[M_coords] = [[
                con_M33(r, s, a1, a2, i, j, c, mu) for j in xrange(5)
            ] for i in xrange(5)]
            # NOTE Next line - and indeed all 12/21s stuff - is patently false if a1 != a2
            if a1 == a2:
                R2Bexact[Bt_coords_21] = -R2Bexact[Bt_coords]
                R2Bexact[Gt_coords_21] = -R2Bexact[Gt_coords]
                R2Bexact[Ht_coords_21] = R2Bexact[Ht_coords]
            else:
                R2Bexact[Bt_coords_21] = [[
                    M12(-r, s, a2, a1, i, j, c, mu) for j in xrange(3)
                ] for i in xrange(3)]
                R2Bexact[Gt_coords_21] = [[
                    con_M13(-r, s, a2, a1, i, j, c, mu) for j in xrange(5)
                ] for i in xrange(3)]
                R2Bexact[Ht_coords_21] = [[
                    con_M23(-r, s, a2, a1, i, j, c, mu) for j in xrange(5)
                ] for i in xrange(3)]

        elif a1_index < num_spheres and a2_index >= num_spheres and a2_index < num_spheres + num_dumbbells:
            # Sphere to dumbbell bead 1
            mr = [-r[0], -r[1], -r[2]]
            a2_index_d = a2_index - num_spheres
            R14_coords = np.s_[a1_index * 3:(a1_index + 1) * 3,
                               11 * num_spheres +
                               a2_index_d * 3:11 * num_spheres +
                               (a2_index_d + 1) * 3]
            R24_coords = np.s_[3 * num_spheres + a1_index * 3:3 * num_spheres +
                               (a1_index + 1) * 3, 11 * num_spheres +
                               a2_index_d * 3:11 * num_spheres +
                               (a2_index_d + 1) * 3]
            R34_coords = np.s_[6 * num_spheres + a1_index * 5:6 * num_spheres +
                               (a1_index + 1) * 5, 11 * num_spheres +
                               a2_index_d * 3:11 * num_spheres +
                               (a2_index_d + 1) * 3]

            R2Bexact[R14_coords] = [[
                M11(r[i], r[j], s, a1, a2, i, j, c, mu) for j in xrange(3)
            ] for i in xrange(3)]
            R2Bexact[R24_coords] = [[
                M12(mr, s, a2, a1, j, i, c, mu) for j in xrange(3)
            ] for i in xrange(3)]
            R2Bexact[R34_coords] = [[
                con_M13(mr, s, a1, a2, j, i, c, mu) for j in xrange(3)
            ] for i in xrange(5)]

        elif a1_index < num_spheres and a2_index >= num_spheres + num_dumbbells:
            # Sphere to dumbbell bead 2
            mr = [-r[0], -r[1], -r[2]]
            a2_index_d = a2_index - num_spheres - num_dumbbells
            R15_coords = np.s_[a1_index * 3:(a1_index + 1) * 3,
                               11 * num_spheres + 3 * num_dumbbells +
                               a2_index_d * 3:11 * num_spheres +
                               3 * num_dumbbells + (a2_index_d + 1) * 3]
            R25_coords = np.s_[3 * num_spheres + a1_index * 3:3 * num_spheres +
                               (a1_index + 1) * 3,
                               11 * num_spheres + 3 * num_dumbbells +
                               a2_index_d * 3:11 * num_spheres +
                               3 * num_dumbbells + (a2_index_d + 1) * 3]
            R35_coords = np.s_[6 * num_spheres + a1_index * 5:6 * num_spheres +
                               (a1_index + 1) * 5,
                               11 * num_spheres + 3 * num_dumbbells +
                               a2_index_d * 3:11 * num_spheres +
                               3 * num_dumbbells + (a2_index_d + 1) * 3]

            R2Bexact[R15_coords] = [[
                M11(r[i], r[j], s, a1, a2, i, j, c, mu) for j in xrange(3)
            ] for i in xrange(3)]
            R2Bexact[R25_coords] = [[
                M12(mr, s, a2, a1, j, i, c, mu) for j in xrange(3)
            ] for i in xrange(3)]
            R2Bexact[R35_coords] = [[
                con_M13(mr, s, a1, a2, j, i, c, mu) for j in xrange(3)
            ] for i in xrange(5)]

        elif a1_index >= num_spheres and a1_index < num_spheres + num_dumbbells and a2_index >= num_spheres and a2_index < num_spheres + num_dumbbells:
            # Dumbbell bead 1 to dumbbell bead 1
            a1_index_d = a1_index - num_spheres
            a2_index_d = a2_index - num_spheres
            if bead_bead_interactions or a1_index_d == a2_index_d:
                R44_coords = np.s_[11 * num_spheres +
                                   a1_index_d * 3:11 * num_spheres +
                                   (a1_index_d + 1) * 3, 11 * num_spheres +
                                   a2_index_d * 3:11 * num_spheres +
                                   (a2_index_d + 1) * 3]
                R2Bexact[R44_coords] = [[
                    M11(r[i], r[j], s, a1, a2, i, j, c, mu) for j in xrange(3)
                ] for i in xrange(3)]

        elif a1_index >= num_spheres and a1_index < num_spheres + num_dumbbells and a2_index >= num_spheres + num_dumbbells:
            if bead_bead_interactions:
                # Dumbbell bead 1 to dumbbell bead 2
                a1_index_d = a1_index - num_spheres
                a2_index_d = a2_index - num_spheres - num_dumbbells
                R45_coords = np.s_[11 * num_spheres +
                                   a1_index_d * 3:11 * num_spheres +
                                   (a1_index_d + 1) * 3,
                                   11 * num_spheres + 3 * num_dumbbells +
                                   a2_index_d * 3:11 * num_spheres +
                                   3 * num_dumbbells + (a2_index_d + 1) * 3]
                R2Bexact[R45_coords] = [[
                    M11(r[i], r[j], s, a1, a2, i, j, c, mu) for j in xrange(3)
                ] for i in xrange(3)]

        else:
            # Dumbbell bead 2 to dumbbell bead 2
            a1_index_d = a1_index - num_spheres - num_dumbbells
            a2_index_d = a2_index - num_spheres - num_dumbbells
            if bead_bead_interactions or a1_index_d == a2_index_d:
                R55_coords = np.s_[11 * num_spheres + 3 * num_dumbbells +
                                   a1_index_d * 3:11 * num_spheres +
                                   3 * num_dumbbells + (a1_index_d + 1) * 3,
                                   11 * num_spheres + 3 * num_dumbbells +
                                   a2_index_d * 3:11 * num_spheres +
                                   3 * num_dumbbells + (a2_index_d + 1) * 3]
                R2Bexact[R55_coords] = [[
                    M11(r[i], r[j], s, a1, a2, i, j, c, mu) for j in xrange(3)
                ] for i in xrange(3)]

    #symmetrise
    R2Bexact = np.triu(R2Bexact) + np.triu(R2Bexact, k=1).transpose()

    # Row and column ops I want are equivalent to doing
    #   [ 1    0    0 ]   [ a b c ]   [ 1    0    0 ]
    #   [ 0  1/2  1/2 ] . [ d e f ] . [ 0  1/2 -1/2 ]
    #   [ 0 -1/2  1/2 ]   [ g h i ]   [ 0  1/2  1/2 ]
    #        "L"                       "R"

    # I know that we could generate L and R elsewhere rather than doing it every timestep but it takes 0.01s for a few thousand dumbbells so for now I don't mind
    Lrow = np.array([i for i in xrange(11 * num_spheres + 6 * num_dumbbells)] +
                    [i + 11 * num_spheres
                     for i in xrange(3 * num_dumbbells)] + [
                         i + 11 * num_spheres + 3 * num_dumbbells
                         for i in xrange(3 * num_dumbbells)
                     ])
    Lcol = np.array([i
                     for i in xrange(11 * num_spheres + 6 * num_dumbbells)] + [
                         i + 11 * num_spheres + 3 * num_dumbbells
                         for i in xrange(3 * num_dumbbells)
                     ] +
                    [i + 11 * num_spheres for i in xrange(3 * num_dumbbells)])
    Ldata = np.array([1 for i in xrange(11 * num_spheres)] +
                     [0.5 for i in xrange(9 * num_dumbbells)] +
                     [-0.5 for i in xrange(3 * num_dumbbells)])
    L = coo_matrix((Ldata, (Lrow, Lcol)),
                   shape=(11 * num_spheres + 6 * num_dumbbells,
                          11 * num_spheres + 6 * num_dumbbells))
    R = L.transpose()

    return ((L * R2Bexact * R), "Minfinity")