Exemplo n.º 1
0
      def __call__(self, rk=None):
	  self.niter += 1
	  if self._disp:
	      print('iter %3i\trk = %s' % (self.niter, str(rk)))

    Lub_Mob = np.zeros((6,6))
    for p in range(6):
      #print(p)
      force_torque *= 0.0
      force_torque[p] = 1.0
      #print force_torque
      # Set right hand side
      RHS = np.reshape(np.concatenate([slip, -force_torque]), (System_size))       
      # Solve preconditioned linear system # callback=make_callback()
      counter = gmres_counter()
      (sol_precond, info_precond) = utils.gmres(A, RHS, tol=read.solver_tolerance, M=PC, maxiter=1000, restart=1000, callback=counter) 
      # Extract velocities and constraint forces on blobs
      velocity = sol_precond[3*Nblobs: 3*Nblobs + 6*num_bodies]
      lambda_blobs = sol_precond[0: 3*Nblobs]
      
      Lub_Mob[:,p] = velocity
    
    Res_Mob = np.linalg.pinv(Lub_Mob)
    mob_coefs = np.array([height, Lub_Mob[2,2], Lub_Mob[0,0], Lub_Mob[4,0], Lub_Mob[5,5], Lub_Mob[3,3]])
    res_coefs = np.array([height, Res_Mob[2,2], Res_Mob[0,0], Res_Mob[4,0], Res_Mob[5,5], Res_Mob[3,3]])
    mob_coef[d_count,:] = mob_coefs
    res_coef[d_count,:] = res_coefs
    #print(mob_coefs)
    #print(res_coefs)

Exemplo n.º 2
0
  def compute_stochastic_velocity(self, dt):
    '''
    Compute stochastic torque and velocity. First,
    solve for the torque
    
    M_rr * T = -kT*div_t(M_rt) - sqrt(2*kT) * (N^{1/2}*W)_r,

    then set linear velocity
    
    v_stoch = M_tr * T + sqrt(2*kT) * (N^{1/2}*W)_t + kT*div_t(M_tt).

    Here N = (M_tt M_tr; M_rt M_rr) is the grand mobility matrix.
    We use random finite difference to compute the divergence
    terms. Note that in principle we should include the term
    div_r(M_rr) in the torque equation and div_r(M_tr) in the
    velocity equation but they are zero for a roller.

    This function returns the stochastic velocity v_stoch.
    '''
    # Create auxiliar variables
    Nblobs = len(self.bodies)
    blob_mass = 1.0

    # Get blobs coordinates
    r_vectors_blobs = np.empty((Nblobs, 3))
    for k, b in enumerate(self.bodies):
      r_vectors_blobs[k] = b.location

    # Generate random vector
    z = np.random.randn(6 * Nblobs)
    
    # Define grand mobility matrix
    def grand_mobility_matrix(force_torque, r_vectors = None, eta = None, a = None, periodic_length = None):
      half_size = force_torque.size / 2
      # velocity = self.mobility_trans_times_force_torque(r_vectors, force_torque[0:half_size], force_torque[half_size:], eta, a, periodic_length = periodic_length)
      velocity  = self.mobility_trans_times_force(r_vectors, force_torque[0:half_size], eta, a, periodic_length = periodic_length)
      velocity += self.mobility_trans_times_torque(r_vectors, force_torque[half_size:], eta, a, periodic_length = periodic_length)
      angular_velocity  = self.mobility_rot_times_force(r_vectors, force_torque[0:half_size], eta, a, periodic_length = periodic_length)
      angular_velocity += self.mobility_rot_times_torque(r_vectors, force_torque[half_size:], eta, a, periodic_length = periodic_length)      
      return np.concatenate([velocity, angular_velocity])
    partial_grand_mobility_matrix = partial(grand_mobility_matrix, 
                                            r_vectors = r_vectors_blobs, 
                                            eta = self.eta, 
                                            a = self.a,
                                            periodic_length = self.periodic_length)

    # Generate noise term sqrt(2*kT) * N^{1/2} * z
    velocities_noise, it_lanczos = stochastic.stochastic_forcing_lanczos(factor = np.sqrt(2*self.kT / dt),
                                                                         tolerance = self.tolerance, 
                                                                         dim = self.Nblobs * 6, 
                                                                         mobility_mult = partial_grand_mobility_matrix,
                                                                         z = z,
                                                                         print_residual = self.print_residual)
    self.stoch_iterations_count += it_lanczos

    # Compute divergence terms div_t(M_rt) and div_t(M_tt)
    if self.kT > 0.0 and self.domain != 'no_wall':
      # 1. Generate random displacement
      dx_stoch = np.reshape(np.random.randn(Nblobs * 3), (Nblobs, 3))
      # 2. Displace blobs
      r_vectors_blobs += dx_stoch * (self.rf_delta * self.a * 0.5)
      # 3. Compute M_rt(r+0.5*dx) * dx_stoch
      div_M_rt = self.mobility_rot_times_force(r_vectors_blobs, np.reshape(dx_stoch, dx_stoch.size), self.eta, self.a, 
                                                                 periodic_length = self.periodic_length)
      div_M_tt = self.mobility_trans_times_force(r_vectors_blobs, np.reshape(dx_stoch, dx_stoch.size), self.eta, self.a, 
                                                                   periodic_length = self.periodic_length)
      # 4. Displace blobs in the other direction
      r_vectors_blobs -= dx_stoch * self.rf_delta * self.a 

      # 5. Compute -M_rt(r-0.5*dx) * dx_stoch
      div_M_rt -= self.mobility_rot_times_force(r_vectors_blobs, np.reshape(dx_stoch, dx_stoch.size), self.eta, self.a, 
                                                                  periodic_length = self.periodic_length)
      div_M_tt -= self.mobility_trans_times_force(r_vectors_blobs, np.reshape(dx_stoch, dx_stoch.size), self.eta, self.a, 
                                                                    periodic_length = self.periodic_length)
    
      # Reset blobs location
      r_vectors_blobs += dx_stoch * (self.rf_delta * self.a * 0.5)
    else:
      div_M_rt = np.zeros(Nblobs * 3)
      div_M_tt = np.zeros(Nblobs * 3)

    # Use constraint motion or free kinematics
    if self.free_kinematics == 'False':
       # Set RHS = -kT*div_t(M_rt) - sqrt(2*kT) * (N^{1/2}*W)_r,
      RHS = -velocities_noise[velocities_noise.size / 2:] - div_M_rt * (self.kT / (self.rf_delta * self.a))

      # Set linear operator
      system_size = 3 * len(self.bodies)
      def mobility_rot_torque(torque, r_vectors = None, eta = None, a = None, periodic_length = None):
        return self.mobility_rot_times_torque(r_vectors, torque, eta, a, periodic_length = periodic_length)
      linear_operator_partial = partial(mobility_rot_torque, r_vectors = r_vectors_blobs, eta = self.eta, a = self.a, periodic_length = self.periodic_length)
      A = spla.LinearOperator((system_size, system_size), matvec = linear_operator_partial, dtype='float64')

      # Scale RHS to norm 1
      RHS_norm = np.linalg.norm(RHS)
      if RHS_norm > 0:
        RHS = RHS / RHS_norm

      # Solve linear system 
      counter = gmres_counter(print_residual = self.print_residual)
      (sol_precond, info_precond) = utils.gmres(A, 
                                                RHS, 
                                                tol=self.tolerance, 
                                                maxiter=1000,
                                                callback=counter) 
      self.det_iterations_count += counter.niter

      # Scale solution with RHS norm
      if RHS_norm > 0:
        sol_precond = sol_precond * RHS_norm
    else:
      # This is free kinematics, stochastic torque set to zero
      # because we only care for the translational degrees of freedom
      sol_precond = np.zeros(3 * Nblobs)

    # Compute stochastic velocity v_stoch = M_tr * T + sqrt(2*kT) * (N^{1/2}*W)_t + kT*div_t(M_tt).
    v_stoch = self.mobility_trans_times_torque(r_vectors_blobs, sol_precond, self.eta, self.a, periodic_length = self.periodic_length)
    v_stoch += velocities_noise[0 : velocities_noise.size / 2] + (self.kT / (self.rf_delta * self.a)) * div_M_tt 
    return v_stoch
Exemplo n.º 3
0
  def compute_deterministic_velocity_and_torque(self):
    '''
    Compute the torque on bodies rotating with a prescribed
    angular velocity and subject to forces, i.e., solve the
    linear system
    
    M_rr * T = omega - M_rt * forces
    
    Then compute the translational velocity

    v = M_tr * T + M_tt * forces
    
    It returns the velocities and torques (v,T).
    '''
    # Create auxiliar variables
    Nblobs = len(self.bodies)
    blob_mass = 1.0

    # Get blobs coordinates
    r_vectors_blobs = np.empty((Nblobs, 3))
    for k, b in enumerate(self.bodies):
      r_vectors_blobs[k] = b.location

    # Compute one-blob forces (same function for all blobs)
    # force = np.zeros(r_vectors_blobs.size)
    force = self.calc_one_blob_forces(r_vectors_blobs, blob_radius = self.a, blob_mass = blob_mass)

    # Compute blob-blob forces (same function for all pair of blobs)
    force += self.calc_blob_blob_forces(r_vectors_blobs, blob_radius = self.a)  
    force = np.reshape(force, force.size)

    # Use constraint motion or free kinematics
    if self.free_kinematics == 'False':
      # Set rollers angular velocity
      omega = np.empty(3 * len(self.bodies))
      for i in range(len(self.bodies)):
        omega[3*i : 3*(i+1)] = self.get_omega_one_roller()

      # Set RHS = omega - M_rt * force 
      RHS = omega - self.mobility_rot_times_force(r_vectors_blobs, force, self.eta, self.a, periodic_length = self.periodic_length)

      # Set linear operator 
      system_size = 3 * len(self.bodies)
      def mobility_rot_torque(torque, r_vectors = None, eta = None, a = None, periodic_length = None):
        return self.mobility_rot_times_torque(r_vectors, torque, eta, a, periodic_length = periodic_length)
      linear_operator_partial = partial(mobility_rot_torque, r_vectors = r_vectors_blobs, eta = self.eta, a = self.a, periodic_length = self.periodic_length)
      A = spla.LinearOperator((system_size, system_size), matvec = linear_operator_partial, dtype='float64')

      # Scale RHS to norm 1
      RHS_norm = np.linalg.norm(RHS)
      if RHS_norm > 0:
        RHS = RHS / RHS_norm

      # Solve linear system 
      counter = gmres_counter(print_residual = self.print_residual)
      (sol_precond, info_precond) = utils.gmres(A, 
                                                RHS, 
                                                x0=self.deterministic_torque_previous_step, 
                                                tol=self.tolerance, 
                                                maxiter=1000,
                                                callback = counter) 
      self.det_iterations_count += counter.niter
      self.deterministic_torque_previous_step = sol_precond

      # Scale solution with RHS norm
      if RHS_norm > 0:
        sol_precond = sol_precond * RHS_norm
    else:
      # This is free kinematics, compute torque
      sol_precond = self.get_torque()

    # Compute linear velocity
    velocity  = self.mobility_trans_times_force(r_vectors_blobs, force, self.eta, self.a, periodic_length = self.periodic_length)
    if np.any(sol_precond):
      velocity += self.mobility_trans_times_torque(r_vectors_blobs, sol_precond, self.eta, self.a, periodic_length = self.periodic_length)
    
    # Return linear velocity and torque
    return velocity, sol_precond
                                         read.blob_radius,
                                         M_inv=M_inv)
                mobility_bodies[k] = N

            # 4. Pack preconditioner
            PC_partial = partial(block_diagonal_preconditioner, bodies=bodies, mobility_bodies=mobility_bodies, \
             mobility_inv_blobs=mobility_inv_blobs, Nblobs=Nblobs)
            PC = spla.LinearOperator((System_size, System_size),
                                     matvec=PC_partial,
                                     dtype='float64')

            # Solve preconditioned linear system # callback=make_callback()
            (sol_precond,
             info_precond) = utils.gmres(A,
                                         RHS,
                                         tol=read.solver_tolerance,
                                         M=PC,
                                         maxiter=1000,
                                         restart=60)

            # Extract velocities and constraint forces on blobs
            velocity = np.reshape(
                sol_precond[3 * Nblobs:3 * Nblobs + 6 * num_bodies],
                (num_bodies, 6))
            lambda_blobs = np.reshape(sol_precond[0:3 * Nblobs], (Nblobs, 3))

            if d_count == 0:
                f = open(
                    "tetra_particle_2_velocities_12_dist_" + str(dist) +
                    ".dat", "w")
                np.savetxt(f, np.array([height]), newline=" ")
                f = open(
    for k, b in enumerate(bodies):
      # 1. Compute blobs mobility and invert it
      M = b.calc_mobility_blobs(read.eta, read.blob_radius)
      M_inv = np.linalg.inv(M)
      mobility_inv_blobs.append(M_inv)
      # 2. Compute body mobility
      N = b.calc_mobility_body(read.eta, read.blob_radius, M_inv = M_inv)
      mobility_bodies[k] = N

    # 4. Pack preconditioner
    PC_partial = partial(multi_bodies.block_diagonal_preconditioner, bodies=bodies, mobility_bodies=mobility_bodies, \
                           mobility_inv_blobs=mobility_inv_blobs, Nblobs=Nblobs)
    PC = spla.LinearOperator((System_size, System_size), matvec = PC_partial, dtype='float64')

    # Solve preconditioned linear system # callback=make_callback()
    (sol_precond, info_precond) = utils.gmres(A, RHS, tol=read.solver_tolerance, M=PC, maxiter=1000, restart=60) 
    
    # Extract velocities and constraint forces on blobs
    velocity = np.reshape(sol_precond[3*Nblobs: 3*Nblobs + 6*num_bodies], (num_bodies, 6))
    lambda_blobs = np.reshape(sol_precond[0: 3*Nblobs], (Nblobs, 3))

    # Save velocity
    name = read.output_name + '.velocity.dat'
    np.savetxt(name, velocity, delimiter='  ')
    print('Time to solve mobility problem =', time.time() - start_time )

    # Plot velocity field
    if read.plot_velocity_field.size > 1: 
      print('plot_velocity_field')
      plot_velocity_field(read.plot_velocity_field, r_vectors_blobs, lambda_blobs, read.blob_radius, read.eta, read.output_name, read.tracer_radius,
                          mobility_vector_prod_implementation = read.mobility_vector_prod_implementation)
    def solve_mobility_problem(self,
                               RHS=None,
                               noise=None,
                               noise_FT=None,
                               AB=None,
                               x0=None,
                               save_first_guess=False,
                               PC_partial=None,
                               *args,
                               **kwargs):
        ''' 
    Solve the mobility problem using preconditioned GMRES. Compute 
    velocities on the bodies subject to active slip and enternal 
    forces-torques.

    The linear and angular velocities are sorted like
    velocities = (v_1, w_1, v_2, w_2, ...)
    where v_i and w_i are the linear and angular velocities of body i.
    '''
        while True:
            System_size = self.Nblobs * 3 + len(self.bodies) * 3

            # Get blobs coordinates
            r_vectors_blobs = self.get_blobs_r_vectors(self.bodies,
                                                       self.Nblobs)

            # If RHS = None set RHS = [slip, -force_torque]
            if RHS is None:
                # Calculate slip on blobs
                if self.calc_slip is not None:
                    slip = self.calc_slip(self.bodies, self.Nblobs)
                else:
                    slip = np.zeros((self.Nblobs, 3))
                # Calculate force-torque on bodies
                force_torque = np.zeros(
                    (self.Nblobs, 3)
                )  ######self.force_torque_calculator(self.bodies, r_vectors_blobs)
                # Add noise to the force/torque
                if noise_FT is not None:
                    force_torque += noise_FT
                # Set right hand side
                RHS = np.reshape(np.concatenate([slip, -force_torque]),
                                 (System_size))

            # Add noise to the slip
            if noise is not None:
                RHS[0:System_size] -= noise

            # Calculate K matrix
            K = self.calc_K_matrix_bodies(self.bodies, self.Nblobs)

            # Set linear operators
            linear_operator_partial = partial(
                self.linear_operator,
                bodies=self.bodies,
                r_vectors=r_vectors_blobs,
                eta=self.eta,
                a=self.a,
                K_bodies=K,
                periodic_length=self.periodic_length)
            A = spla.LinearOperator((System_size, System_size),
                                    matvec=linear_operator_partial,
                                    dtype='float64')

            #      e_i = np.identity(System_size)
            #      for k in range(System_size):
            #		print A.matvec(e_i[:,k])

            # Set preconditioner
            if PC_partial is None:
                PC_partial = self.build_block_diagonal_preconditioner(
                    self.bodies, r_vectors_blobs, self.Nblobs, self.eta,
                    self.a, *args, **kwargs)
            PC = spla.LinearOperator((System_size, System_size),
                                     matvec=PC_partial,
                                     dtype='float64')

            # Scale RHS to norm 1
            RHS_norm = np.linalg.norm(RHS)
            if RHS_norm > 0:
                RHS = RHS / RHS_norm

            # Solve preconditioned linear system
            counter = gmres_counter(print_residual=self.print_residual)
            (sol_precond, info_precond) = utils.gmres(A,
                                                      RHS,
                                                      x0=x0,
                                                      tol=self.tolerance,
                                                      M=PC,
                                                      maxiter=1000,
                                                      restart=60,
                                                      callback=counter)
            self.det_iterations_count += counter.niter

            if save_first_guess:
                self.first_guess = sol_precond

            # Scale solution with RHS norm
            if RHS_norm > 0:
                sol_precond = sol_precond * RHS_norm
            else:
                sol_precond[:] = 0.0

            # Return solution
            return sol_precond