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)
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
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