def render(self, screen, position, width): # Calculate the number of cores per line # First find all factor pairs for the core count core_count = len(self.cpu.cores) candidates = [i for i in range(1, core_count) if core_count % i == 0] # Then select one that does't make the bars too short cores_par_line = 1 for i, candidate in enumerate(candidates): if (width / candidate) < 12: break cores_per_line = candidate # Work out the size of display bars core_bar_length = int(width / cores_per_line) core_line_length = core_bar_length * cores_per_line mem_bar_length = int(core_line_length / 2) # Render memory info mem_position = vec2(position.x + (core_line_length - mem_bar_length), position.y) mem_lines = self.mem.render(screen, mem_position, mem_bar_length) # Render CPU info to window cpu_position = vec2(position.x, position.y + mem_lines) cpu_lines = self.cpu.render(screen, cpu_position, width, cores_per_line) # Return the vertical size of the render return cpu_lines + mem_lines
def sample_bilinear(x, source_pos, stagger): I, p_grid = pos_to_stagger_idx(source_pos, stagger) f = p_grid - I g = 1 - f return x[I] * (g[0] * g[1]) + x[I + vec2(1, 0)] * (f[0] * g[1]) + x[ I + vec2(0, 1)] * (g[0] * f[1]) + x[I + vec2(1, 1)] * (f[0] * f[1])
def render(self, screen, position, width): # Render the host status lines = self.render_status(screen, position, width) # Only render stats if the host is online or pending if self.status != RM_HOST_OFFLINE: lines = self.stat.render(screen, vec2(position.x, position.y), width) # Return the number of lines used on this host return vec2(width, lines)
def scatter_vp(grid_v, grid_m, xp, vp, stagger): inv_dx = vec2(1.0 / grid_x, 1.0 / grid_y).cast(ti.f32) base = (xp * inv_dx - (stagger + 0.5)).cast(ti.i32) fx = xp * inv_dx - (base.cast(ti.f32) + stagger) w = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2] # Bspline for i in ti.static(range(3)): for j in ti.static(range(3)): offset = vec2(i, j) weight = w[i][0] * w[j][1] grid_v[base + offset] += weight * vp grid_m[base + offset] += weight
def init_particles(): for i, j, ix, jx in particle_positions: if cell_type[i, j] == utils.FLUID: particle_type[i, j, ix, jx] = P_FLUID else: particle_type[i, j, ix, jx] = 0 px = i * grid_x + (ix + random.random()) * pspace_x py = j * grid_y + (jx + random.random()) * pspace_y particle_positions[i, j, ix, jx] = vec2(px, py) particle_velocities[i, j, ix, jx] = vec2(0.0, 0.0) cp_x[i, j, ix, jx] = vec2(0.0, 0.0) cp_y[i, j, ix, jx] = vec2(0.0, 0.0)
def P2G(): stagger_u = vec2(0.0, 0.5) stagger_v = vec2(0.5, 0.0) for p in ti.grouped(particle_positions): if particle_type[p] == P_FLUID: xp = particle_positions[p] if ti.static(algorithm == 'FLIP/PIC'): scatter_vp(u, u_weight, xp, particle_velocities[p][0], stagger_u) scatter_vp(v, v_weight, xp, particle_velocities[p][1], stagger_v) elif ti.static(algorithm == 'APIC'): scatter_vp_apic(u, u_weight, xp, particle_velocities[p][0], cp_x[p], stagger_u) scatter_vp_apic(v, v_weight, xp, particle_velocities[p][1], cp_y[p], stagger_v)
def pos_to_stagger_idx(pos, stagger): pos[0] = clamp(pos[0], stagger[0] * grid_x, w - 1e-4 - grid_x + stagger[0] * grid_x) pos[1] = clamp(pos[1], stagger[1] * grid_y, h - 1e-4 - grid_y + stagger[1] * grid_y) p_grid = pos / vec2(grid_x, grid_y) - stagger I = ti.cast(ti.floor(p_grid), ti.i32) return I, p_grid
def gather_vp(grid_v, grid_vlast, xp, stagger): inv_dx = vec2(1.0 / grid_x, 1.0 / grid_y).cast(ti.f32) base = (xp * inv_dx - (stagger + 0.5)).cast(ti.i32) fx = xp * inv_dx - (base.cast(ti.f32) + stagger) w = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2] # Bspline v_pic = 0.0 v_flip = 0.0 for i in ti.static(range(3)): for j in ti.static(range(3)): offset = vec2(i, j) weight = w[i][0] * w[j][1] v_pic += weight * grid_v[base + offset] v_flip += weight * (grid_v[base + offset] - grid_vlast[base + offset]) return v_pic, v_flip
def render(self, screen, position, length): # Draw the memory bar self.render_mem(screen, position, length) # Draw the swap bar swap_position = vec2(position.x, position.y + 1) self.render_swap(screen, swap_position, length) # Return number of lines used return 2
def mark_cell(): for i, j in cell_type: if not is_solid(i, j): cell_type[i, j] = utils.AIR for i, j, ix, jx in particle_positions: if particle_type[i, j, ix, jx] == P_FLUID: pos = particle_positions[i, j, ix, jx] idx = ti.cast(ti.floor(pos / vec2(grid_x, grid_y)), ti.i32) if not is_solid(idx[0], idx[1]): cell_type[idx] = utils.FLUID
def G2P(): stagger_u = vec2(0.0, 0.5) stagger_v = vec2(0.5, 0.0) for p in ti.grouped(particle_positions): if particle_type[p] == P_FLUID: # update velocity xp = particle_positions[p] u_pic, u_flip = gather_vp(u, u_last, xp, stagger_u) v_pic, v_flip = gather_vp(v, v_last, xp, stagger_v) new_v_pic = vec2(u_pic, v_pic) if ti.static(algorithm == 'FLIP/PIC'): new_v_flip = particle_velocities[p] + vec2(u_flip, v_flip) particle_velocities[p] = FLIP_blending * new_v_flip + ( 1 - FLIP_blending) * new_v_pic elif ti.static(algorithm == 'APIC'): particle_velocities[p] = new_v_pic cp_x[p] = gather_cp(u, xp, stagger_u) cp_y[p] = gather_cp(v, xp, stagger_v)
def gather_cp(grid_v, xp, stagger): inv_dx = vec2(1.0 / grid_x, 1.0 / grid_y).cast(ti.f32) base = (xp * inv_dx - (stagger + 0.5)).cast(ti.i32) fx = xp * inv_dx - (base.cast(ti.f32) + stagger) w = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2] # Bspline w_grad = [fx - 1.5, -2 * (fx - 1), fx - 3.5] # Bspline gradient cp = vec2(0.0, 0.0) for i in ti.static(range(3)): for j in ti.static(range(3)): offset = vec2(i, j) # dpos = offset.cast(ti.f32) - fx # weight = w[i][0] * w[j][1] # cp += 4 * weight * dpos * grid_v[base + offset] * inv_dx[0] weight_grad = vec2(w_grad[i][0] * w[j][1], w[i][0] * w_grad[j][1]) cp += weight_grad * grid_v[base + offset] return cp
def render(self, screen, position, width, cores_per_line): # Temporary core position math core_bar_length = int(width / cores_per_line) # For all cores core_position = vec2(position.x, position.y) for i in range(0, len(self.cores)): # Render the core to the window at the specified position self.cores[i].render(screen, core_position, core_bar_length) # Calculate position of next core bar if i % cores_per_line == cores_per_line - 1: core_position.x = position.x core_position.y += 1 else: core_position.x += core_bar_length # Return the number of lines used for cores return ceil(len(self.cores) / cores_per_line)
def redraw(screen, hosts): screen.erase() screen_max_y, screen_max_x = screen.getmaxyx() # Host positioning width = screen_max_x position = vec2(0, 0) more_string = 'V MORE V' # Print the hosts try: for i in range(0, len(hosts)): # Render the host size = hosts[i].render(screen, position, width) position.y += size.y # Print a divider line if i != len(hosts) - 1: screen.move(position.y, position.x) for j in range(0, screen_max_x): screen.addstr('-') position.y += 1 # This happens when printing runs off the end of the terminal (usually) except curses.error: screen_max_y, screen_max_x = screen.getmaxyx() screen.move(screen_max_y - 1, 0) screen.clrtoeol() screen.move(screen_max_y - 1, int( (screen_max_x - len(more_string)) / 2)) screen.addstr(more_string) # Refresh the screen screen.refresh()
def sample_velocity(pos, u, v): u_p = sample_bilinear(u, pos, vec2(0, 0.5)) v_p = sample_bilinear(v, pos, vec2(0.5, 0)) return vec2(u_p, v_p)
def semi_Largrange(x, x_temp, stagger, dt): m, n = x.shape for i, j in ti.ndrange(m, n): pos = (vec2(i, j) + stagger) * vec2(grid_x, grid_y) source_pos = backtrace(pos, dt) x_temp[i, j] = sample_bilinear(x, source_pos, stagger)
def advection_kernel(dt: ti.f32): semi_Largrange(u, u_temp, vec2(0, 0.5), dt) semi_Largrange(v, v_temp, vec2(0.5, 0), dt)