gate level simulation step

本文详细介绍后仿testbench的搭建过程,包括与RTL testbench的一致性保持、时序和层级调整、信号force及初始化等内容,并提供了解决X态问题和部分电路timing check的方法。
部署运行你感兴趣的模型镜像

1. 建立后仿testbench,尽量做到和RTL的testbench一致。特别是时序上以及hierarchy上。

    需要修改的地方一般有:涉及到hierarchy层次的地方。annotate.v 根据不同的define吃进min|typ|max的SDF。以及NOSDF。

    在annotate.v中指定要force的信号。以及要初始化的register,memory等。 

    在rtl中查找initial 块,如果是register或者memory的初始化,分析并找到gate中相应的register以及memory。

 

2. 不挂任何timing信息,纯gate仿真。+nospecify  +notimingcheck +no_notifier +delay_mode_zero

     查找clock reset generation block。 设法将output clock 以及reset初始值设为零。消除不定态。(需要force 某些clock reset的选择信号)。

 

3.  挂入timing。

 

 

 

 

 

 

 

 

 

 

3.

PostSimulation 由于一部电路的存在,经常出现X态,影响仿真结果。如何排除这部分电路的timingcheck?而用Notimingchecks或nonotifer 会使整个design的timing 的检查停止。有没有只是disable部分instance的timing check呢?

1。 抽取SDF时,排除。

       麻烦。

2。 VCS提供了很好的方法:

vcs +optconfigfile+vcs_cfg

================vcs_cfg 的内容==========

instance {tb_top.U_TOP.U_CORE.U_Async} {noTiming}

=============================================

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

model new model title "Longwall Mining Simulation" model domain extent 0 66.0 0 55.0 model config mechanical model mechanical timestep auto contact cmat default model linear method deformability emod 2e8 kratio 2.5 property fric 0.5 dp_nratio 0.5 dp_sratio 0.5 contact cmat apply ; ======================================== ; ======================================== [bottom_coal_height = 0.0] [top_coal_height = 15.8] [total_coal_height = 15.8] [gangue_layers = 0] [gangue_thickness = 0.0] [immediate_roof_thickness = 20.6] [main_roof_thickness = 0.0] [total_roof_thickness = 20.6] [height_floor = 2.32] [support_width = 1.5] [support_num = 34] [head_support_num = 6] [total_support_num = 40] [support_start = 3.0] [caving_support_num = 34] [caving_gates = 34] [caving_rounds = 1] [porosity = 0.105] [gangue_threshold = 0.05] [total_height = 36.4] [model_width = 66.0] [boundary_buffer = 3.0] [effective_mining_width = 60.0] ; [mining_start_x = 3.0] [mining_end_x = 63.0] [total_supports = support_num] [gangue_extension = 10.0] [support_top_height = 2.8] [PI = 3.1415926535] [y_bottom_coal_bottom = 0.0] [y_bottom_coal_top = 0.0] [y_top_coal_bottom = 0.0] [y_top_coal_top = top_coal_height] [y_immediate_roof_bottom = y_top_coal_top] [y_immediate_roof_top = y_immediate_roof_bottom + immediate_roof_thickness] [y_main_roof_bottom = 0.0] [y_main_roof_top = 0.0] [y_gangue_top = 0.0] ; ======================================== ; ======================================== ; ======================================== wall create vertices 0 0 0 35.0 id 100 wall create vertices 66.0 0 66.0 35.0 id 101 wall create vertices 0 0 66.0 0 id 102 wall create vertices 0 35.0 66.0 35.0 id 105 wall create vertices 3.0 0 3.0 35.0 id 103 wall create vertices 63.0 0 63.0 35.0 id 104 fish define finalize_walls loop foreach wp wall.list local wall_id = wall.id(wp) command wall attribute velocity-x 0.0 range id [wall_id] wall attribute velocity-y 0.0 range id [wall_id] end_command endloop io.out('All walls configured as rigid infinite mass surfaces.') end wall attribute velocity-x 0.0 range id 100 wall attribute velocity-y 0.0 range id 100 wall attribute velocity-x 0.0 range id 101 wall attribute velocity-y 0.0 range id 101 wall attribute velocity-x 0.0 range id 102 wall attribute velocity-y 0.0 range id 102 wall attribute velocity-x 0.0 range id 103 wall attribute velocity-y 0.0 range id 103 wall attribute velocity-x 0.0 range id 104 wall attribute velocity-y 0.0 range id 104 wall attribute velocity-x 0.0 range id 105 wall attribute velocity-y 0.0 range id 105 [finalize_walls] ; ======================================== ; ======================================== fish define calc_ball_numbers area_coal = model_width * total_coal_height * (1 - porosity) area_gangue = model_width * gangue_thickness * (1 - porosity) area_roof = model_width * total_roof_thickness * (1 - porosity) local coal_radius_avg = (0.04 + 0.06) / 2 local gangue_radius_avg = (0.06 + 0.08) / 2 local roof_radius_avg = (0.07 + 0.09) / 2 area_ball_coal = PI * (coal_radius_avg)^2 area_ball_roof = PI * (roof_radius_avg)^2 area_ball_gangue = PI * (gangue_radius_avg)^2 num_coal = math.floor(area_coal / area_ball_coal) num_roof = math.floor(area_roof / area_ball_roof) num_gangue = math.floor(area_gangue / area_ball_gangue) num_coal = math.max(50, math.min(500, num_coal)) num_gangue = math.max(25, math.min(250, num_gangue)) num_roof = math.max(30, math.min(300, num_roof)) global num_coal = num_coal global num_gangue = num_gangue global num_roof = num_roof io.out('Coal balls: ' + string(num_coal)) io.out(string(num_coal)) io.out('Gangue balls: ' + string(num_gangue)) io.out('Roof balls: ' + string(num_roof)) end fish define generate_bottom_coal io.out('===== Bottom Coal Generation Skipped =====') io.out('Bottom coal height is 0.0m - no bottom coal to generate') io.out('Skipping bottom coal generation') io.out('===============================================') end fish define generate_top_coal io.out('===== Generating Top Coal (Gaussian Distribution) =====') io.out('Top coal height: 15.8m') io.out('Position: Y=2.8m to Y=18.6m (natural coal layer)') io.out('X range: 3.0m to 63.0m (60m width)') io.out('Particle radius: 0.04-0.06m (Gaussian distribution, sigma=0.5)') local coal_y_bottom = 2.8 local coal_y_top = 18.6 local coal_thickness = coal_y_top - coal_y_bottom local coal_x_left = 3.0 local coal_x_right = 63.0 local coal_width = coal_x_right - coal_x_left local coal_area = coal_width * coal_thickness local coal_volume = coal_area * 1.0 local coal_density = 1360.0 local coal_mass = coal_volume * coal_density local radius_mean = 0.05 local radius_sigma = 0.5 ; Gaussian distribution for natural variation local radius_min = 0.04 local radius_max = 0.06 local avg_volume = (4.0/3.0) * PI * radius_mean^3 local avg_mass = avg_volume * coal_density local top_coal_needed = int(coal_mass / avg_mass) ; Calculate realistic number of balls based on area and radius local ball_area = PI * radius_mean^2 local max_possible_balls = int(coal_area / (ball_area * 3.0)) ; 3.0 is packing factor for complete generation top_coal_needed = math.min(top_coal_needed, max_possible_balls) top_coal_needed = math.max(200, math.min(500, top_coal_needed)) ; Increased range for complete generation io.out('Top coal balls needed: ' + string(top_coal_needed)) io.out('Max possible balls in area: ' + string(max_possible_balls)) io.out('Generating with Gaussian distribution pattern...') command ball generate id 1 [top_coal_needed] box [coal_x_left] [coal_x_right] [coal_y_bottom] [coal_y_top] group 'top_coal' tries 100000 radius [radius_min] [radius_max] end_command loop foreach bp ball.list if ball.group(bp) == 'top_coal' local u1 = random local u2 = random if u1 <= 0.0 u1 = 0.0001 endif local z0 = math.sqrt(-2.0 * math.log(u1)) * math.cos(2.0 * PI * u2) local radius = radius_mean + radius_sigma * z0 if radius < radius_min radius = radius_min endif if radius > radius_max radius = radius_max endif ball.radius(bp) = radius endif endloop command ball property density 1360 range group 'top_coal' ball property 'young_mod' 2e8 range group 'top_coal' ball property 'kratio' 2.5 range group 'top_coal' ball property 'fric' 0.5 range group 'top_coal' ball property 'dp_nratio' 0.5 range group 'top_coal' ball property 'dp_sratio' 0.5 range group 'top_coal' end_command local top_coal_count = 0 loop foreach bp ball.list if ball.group(bp) == 'top_coal' top_coal_count = top_coal_count + 1 endif endloop io.out('Top coal balls generated: ' + string(top_coal_count)) io.out('*** Top coal generation completed (Y: 2.8-18.6m, Gaussian distribution) ***') io.out('===============================================') end fish define generate_immediate_roof io.out('===== Generating Immediate Roof (Gaussian Distribution) =====') io.out('Immediate roof thickness: 15.6m') io.out('Position: Y=18.6m to Y=34.2m (natural roof layer)') io.out('X range: 3.0m to 63.0m (60m width)') io.out('Particle radius: 0.07-0.09m (Gaussian distribution, sigma=0.5)') local roof_y_bottom = 18.6 local roof_y_top = 34.2 local roof_thickness = roof_y_top - roof_y_bottom local roof_x_left = 3.0 local roof_x_right = 63.0 local roof_width = roof_x_right - roof_x_left local roof_area = roof_width * roof_thickness local roof_volume = roof_area * 1.0 local roof_density = 2560.0 local roof_mass = roof_volume * roof_density local radius_mean = 0.07 local radius_sigma = 0.6 ; Gaussian distribution for natural variation local radius_min = 0.05 local radius_max = 0.09 local avg_volume = (4.0/3.0) * PI * radius_mean^3 local avg_mass = avg_volume * roof_density local immediate_roof_needed = int(roof_mass / avg_mass) ; Calculate realistic number of balls based on area and radius local ball_area = PI * radius_mean^2 local max_possible_balls = int(roof_area / (ball_area * 3.0)) ; 3.0 is packing factor for complete generation immediate_roof_needed = math.min(immediate_roof_needed, max_possible_balls) immediate_roof_needed = math.max(200, math.min(500, immediate_roof_needed)) ; Increased range for complete generation io.out('Immediate roof balls needed: ' + string(immediate_roof_needed)) io.out('Max possible balls in area: ' + string(max_possible_balls)) io.out('Generating with Gaussian distribution pattern...') ; Find the next available ID local max_id = 0 loop foreach bp ball.list if ball.id(bp) > max_id max_id = ball.id(bp) endif endloop local start_id = max_id + 1 command ball generate id [start_id] [start_id + immediate_roof_needed - 1] box [roof_x_left] [roof_x_right] [roof_y_bottom] [roof_y_top] group 'immediate_roof' tries 100000 radius [radius_min] [radius_max] end_command loop foreach bp ball.list if ball.group(bp) == 'immediate_roof' local u1 = random local u2 = random if u1 <= 0.0 u1 = 0.0001 endif local z0 = math.sqrt(-2.0 * math.log(u1)) * math.cos(2.0 * PI * u2) local radius = radius_mean + radius_sigma * z0 if radius < radius_min radius = radius_min endif if radius > radius_max radius = radius_max endif ball.radius(bp) = radius endif endloop command ball property density 2560 range group 'immediate_roof' ball property 'young_mod' 2e8 range group 'immediate_roof' ball property 'kratio' 2.5 range group 'immediate_roof' ball property 'fric' 0.5 range group 'immediate_roof' ball property 'dp_nratio' 0.5 range group 'immediate_roof' ball property 'dp_sratio' 0.5 range group 'immediate_roof' end_command local immediate_roof_count = 0 loop foreach bp ball.list if ball.group(bp) == 'immediate_roof' immediate_roof_count = immediate_roof_count + 1 endif endloop io.out('Immediate roof balls generated: ' + string(immediate_roof_count)) io.out('*** Immediate roof generation completed (Y: 18.6-34.2m, Gaussian distribution) ***') io.out('===============================================') end ; ======================================== ; ======================================== fish define create_supports io.out('===== Creating Hydraulic Supports =====') io.out('Support offset: +3.0m (moved right)') io.out('Caving starts from support 6 (frame 6)') io.out('Middle supports: ' + string(support_num) + ' frames') io.out('Head supports: ' + string(head_support_num) + ' frames (3 at each end)') io.out('Total supports: ' + string(total_support_num) + ' frames') io.out('Caving supports: 34 frames (supports 6-39) with caving gates') io.out('Caving gate design: 1.2m width, separated from support, aligned with top') loop local i (1, 3) local xpos_head = 3.0 + (i-1) * support_width local wall_id_1_head = 2000 + i local wall_id_2_head = 3000 + i local wall_id_3_head = 4000 + i command wall create vertices [xpos_head] 0 [xpos_head] 2.8 id [wall_id_1_head] wall attribute velocity-x 0.0 range id [wall_id_1_head] wall create vertices [xpos_head+1.5] 0 [xpos_head+1.5] 2.8 id [wall_id_2_head] wall attribute velocity-x 0.0 range id [wall_id_2_head] wall create vertices [xpos_head] 2.8 [xpos_head+1.5] 2.8 id [wall_id_3_head] wall attribute velocity-x 0.0 range id [wall_id_3_head] end_command io.out('Created head support ' + string(i) + ' at x=' + string(xpos_head) + ' (no caving gate)') endloop loop local j (1, support_num) local xpos_middle = 3.0 + 3 * support_width + (j-1) * support_width local wall_id_1_middle = 2000 + 3 + j local wall_id_2_middle = 3000 + 3 + j local wall_id_3_middle = 4000 + 3 + j local wall_id_4_middle = 5000 + j local caving_gate_id = 6000 + j command wall create vertices [xpos_middle] 0 [xpos_middle] 2.8 id [wall_id_1_middle] wall attribute velocity-x 0.0 range id [wall_id_1_middle] wall create vertices [xpos_middle+1.5] 0 [xpos_middle+1.5] 2.8 id [wall_id_2_middle] wall attribute velocity-x 0.0 range id [wall_id_2_middle] wall create vertices [xpos_middle] 2.8 [xpos_middle+1.5] 2.8 id [wall_id_3_middle] wall attribute velocity-x 0.0 range id [wall_id_3_middle] end_command ; Only support 6 (j=6) has caving gate if j == 6 local gate_x_start = xpos_middle + 0.15 local gate_x_end = gate_x_start + 1.2 command wall create name 'caving_gate_main' vertices [gate_x_start] 2.8 [gate_x_end] 2.8 id [wall_id_4_middle] group 'caving_gate' wall attribute velocity-x 0.0 range id [wall_id_4_middle] end_command io.out('Created middle support ' + string(j) + ' at x=' + string(xpos_middle) + ' (with 1.2m caving gate)') else io.out('Created middle support ' + string(j) + ' at x=' + string(xpos_middle) + ' (no caving gate)') endif endloop loop local k (1, 3) local xpos_tail = 3.0 + 3 * support_width + support_num * support_width + (k-1) * support_width local wall_id_1_tail = 2000 + 3 + support_num + k local wall_id_2_tail = 3000 + 3 + support_num + k local wall_id_3_tail = 4000 + 3 + support_num + k command wall create vertices [xpos_tail] 0 [xpos_tail] 2.8 id [wall_id_1_tail] wall attribute velocity-x 0.0 range id [wall_id_1_tail] wall create vertices [xpos_tail+1.5] 0 [xpos_tail+1.5] 2.8 id [wall_id_2_tail] wall attribute velocity-x 0.0 range id [wall_id_2_tail] wall create vertices [xpos_tail] 2.8 [xpos_tail+1.5] 2.8 id [wall_id_3_tail] wall attribute velocity-x 0.0 range id [wall_id_3_tail] end_command io.out('Created tail support ' + string(k) + ' at x=' + string(xpos_tail) + ' (no caving gate)') endloop io.out('All supports created successfully with 3m right offset') io.out('Caving gates: 1.2m width, separated from supports, aligned with top') io.out('===============================================') end ; ======================================== ; ======================================== fish define prevent_bouncing loop foreach bp ball.list local pos = ball.pos(bp) local px = pos->x local py = pos->y if py <= support_top_height + 0.05 ball.vel.x(bp) = 0.0 ball.vel.y(bp) = 0.0 ball.spin(bp) = 0.0 endif if px <= 3.02 ball.vel.x(bp) = 0.0 ball.vel.y(bp) = 0.0 ball.spin(bp) = 0.0 endif if px >= 62.98 ball.vel.x(bp) = 0.0 ball.vel.y(bp) = 0.0 ball.spin(bp) = 0.0 endif if py <= 0.02 ball.vel.x(bp) = 0.0 ball.vel.y(bp) = 0.0 ball.spin(bp) = 0.0 endif endloop end fish define execute_caving local xpos = global_xpos local gate_width = global_gate_width local coal_mass = 0.0 local gangue_mass = 0.0 local total_mass = 0.0 local gangue_ratio = 0.0 local stop_caving = false local res io.out('Executing single round caving at position: X=' + string(xpos) + ', width=' + string(gate_width)) local x1 = xpos local x2 = xpos + gate_width local y_min = 0.0 local y_max = support_top_height + top_coal_height + immediate_roof_thickness io.out('Caving zone: X=' + string(x1) + '-' + string(x2) + ', Y=' + string(y_min) + '-' + string(y_max)) io.out('Caving mechanism: Particles slide down along wall surfaces') res = 1 loop foreach bp ball.list ball.vel.x(bp) = 0.0 ball.vel.y(bp) = 0.0 ball.spin(bp) = 0.0 endloop prevent_bouncing() command model cycle 2000 model solve time 2.0 end_command loop foreach bp ball.list ball.vel.x(bp) = 0.0 ball.vel.y(bp) = 0.0 ball.spin(bp) = 0.0 endloop prevent_bouncing() prevent_bouncing() io.out('Caving completed. All particles frozen and system stabilized.') [return_value] = res end fish define sequential_caving global total_coal_mass = 0.0 global total_gangue_mass = 0.0 global caving_area = 0.0 io.out('===== Starting Single Support Caving =====') io.out('Only support 6 has caving gate') io.out('Support spacing: ' + string(support_width) + 'm') io.out('Gangue threshold: ' + string(gangue_threshold*100) + '% (5%)') io.out('Waiting for equilibrium before opening caving gate...') ; Force equilibrium - keep running until equilibrium is reached io.out('Checking equilibrium status...') local current_ratio = mech_ratio io.out('Current mechanical ratio: ' + string(current_ratio, 6)) local equilibrium_cycles = 0 local max_equilibrium_cycles = 500000 local equilibrium_threshold = 1e-3 ; Keep running until equilibrium is reached loop while current_ratio > equilibrium_threshold and equilibrium_cycles < max_equilibrium_cycles io.out('System not in equilibrium. Mechanical ratio: ' + string(current_ratio, 6) + ' (target: ' + string(equilibrium_threshold) + ')') io.out('Cycling until equilibrium... (cycle ' + string(equilibrium_cycles) + ')') command model cycle 1000 end_command equilibrium_cycles = equilibrium_cycles + 1000 current_ratio = mech_ratio if (equilibrium_cycles % 10000) == 0 io.out('Equilibrium check cycle ' + string(equilibrium_cycles) + ': ratio = ' + string(current_ratio, 6)) endif endloop if current_ratio <= equilibrium_threshold io.out('SUCCESS: System is in equilibrium!') io.out('Final mechanical ratio: ' + string(current_ratio, 6)) io.out('Equilibrium reached after ' + string(equilibrium_cycles) + ' cycles') else io.out('WARNING: Maximum equilibrium cycles reached') io.out('Final mechanical ratio: ' + string(current_ratio, 6)) io.out('Proceeding with caving despite potential instability...') endif ; Only proceed with caving after equilibrium is confirmed io.out('') io.out('===== EQUILIBRIUM REACHED - DELETING CAVING GATE HORIZONTAL LINE =====') local support_num = 6 local gate_id = 5000 + support_num local xpos = 3.0 + 3 * support_width + (support_num-1) * support_width io.out('===== Processing Support ' + string(support_num) + ' (Only Support with Caving Gate) =====') io.out('Support position: X=' + string(xpos) + 'm') io.out('Caving gate ID: ' + string(gate_id)) io.out('Caving gate width: 1.2m horizontal line') ; List all walls before deletion io.out('All walls before deletion:') loop foreach wp wall.list io.out(' Wall ID: ' + string(wall.id(wp)) + ' at ' + string(wall.pos(wp)) + ' group: ' + string(wall.group(wp))) endloop ; Check if caving gate exists io.out('Checking for caving gate horizontal line...') local gate = wall.find(gate_id) if gate == null io.out('ERROR: Caving gate ' + string(gate_id) + ' not found!') io.out('Trying to find caving gate by group...') loop foreach wp wall.list if wall.group(wp) == 'caving_gate' io.out(' Found caving gate: ID=' + string(wall.id(wp)) + ' at ' + string(wall.pos(wp))) gate_id = wall.id(wp) gate = wp endif endloop if gate == null io.out('No caving gate found, cannot proceed') return endif else io.out('Caving gate horizontal line found, proceeding with deletion...') io.out('Gate position: ' + string(wall.pos(gate))) io.out('Gate group: ' + string(wall.group(gate))) endif global global_xpos = xpos global global_gate_width = support_width io.out('EQUILIBRIUM CONFIRMED - Deleting caving gate horizontal line for support ' + string(support_num) + '...') io.out('Deleting 1.2m caving gate horizontal line (ID: ' + string(gate_id) + ')') io.out('Support structure remains intact') ; Delete only the caving gate horizontal line (1.2m), not the support structure command wall delete range id [gate_id] end_command ; Verify deletion local gate_after = wall.find(gate_id) if gate_after == null io.out('SUCCESS: 1.2m caving gate horizontal line deleted successfully') io.out('Support structure remains intact') else io.out('WARNING: Caving gate still exists after deletion attempt') io.out('Trying alternative deletion method...') command wall delete range group 'caving_gate' end_command io.out('Alternative deletion method applied') endif ; List all walls after deletion io.out('All walls after deletion:') loop foreach wp wall.list io.out(' Wall ID: ' + string(wall.id(wp)) + ' at ' + string(wall.pos(wp)) + ' group: ' + string(wall.group(wp))) endloop io.out('Caving gate horizontal line deleted for support ' + string(support_num)) io.out('1.2m horizontal opening created, particles can now flow through') ; Rest of the caving process... io.out('Waiting for particle flow and settlement...') local settlement_cycles = 0 local max_settlement_cycles = 10000 local stable_cycles = 0 local max_stable_cycles = 5 local last_coal_mass = 0.0 local last_gangue_mass = 0.0 loop while settlement_cycles < max_settlement_cycles command model cycle 200 end_command settlement_cycles = settlement_cycles + 200 if (settlement_cycles % 1000) == 0 io.out('Settlement cycle ' + string(settlement_cycles) + ' / ' + string(max_settlement_cycles)) endif local current_coal_mass = 0.0 local current_gangue_mass = 0.0 loop foreach bp ball.list local pos = ball.pos(bp) local px = pos->x local py = pos->y if px >= (xpos - support_width/2) and px <= (xpos + support_width/2) and py <= 2.8 if ball.group(bp) == 'coal' current_coal_mass = current_coal_mass + ball.mass(bp) else if ball.group(bp) == 'gangue' current_gangue_mass = current_gangue_mass + ball.mass(bp) endif endif endif endloop local total_mass = current_coal_mass + current_gangue_mass local gangue_ratio = 0.0 if total_mass > 0.0 gangue_ratio = current_gangue_mass / total_mass endif if abs(current_coal_mass - last_coal_mass) < 0.1 and abs(current_gangue_mass - last_gangue_mass) < 0.1 stable_cycles = stable_cycles + 1 else stable_cycles = 0 endif last_coal_mass = current_coal_mass last_gangue_mass = current_gangue_mass if stable_cycles >= max_stable_cycles io.out('Particle flow stabilized after ' + string(settlement_cycles) + ' cycles') io.out('Final coal mass: ' + string(current_coal_mass, 2) + ' kg') io.out('Final gangue mass: ' + string(current_gangue_mass, 2) + ' kg') io.out('Final gangue ratio: ' + string(gangue_ratio*100, 2) + '%') break endif endloop if settlement_cycles >= max_settlement_cycles io.out('Warning: Maximum settlement cycles reached, flow may not be fully stabilized') endif total_coal_mass = current_coal_mass total_gangue_mass = current_gangue_mass caving_area = 1.2 ; 1.2m caving gate width io.out('') io.out('===== Single Support Caving Completed =====') io.out('Support ' + string(support_num) + ' caving completed:') io.out(' Coal mined: ' + string(total_coal_mass, 2) + ' kg') io.out(' Gangue mined: ' + string(total_gangue_mass, 2) + ' kg') io.out(' Gangue ratio: ' + string(gangue_ratio*100, 2) + '%') io.out(' Caving area: ' + string(caving_area, 2) + ' m2 (1.2m gate width)') local total_mined_mass = total_coal_mass + total_gangue_mass local overall_gangue_ratio = 0.0 if total_mined_mass > 0.0 overall_gangue_ratio = total_gangue_mass / total_mined_mass endif io.out('Overall gangue ratio: ' + string(overall_gangue_ratio*100, 2) + '%') local coal_recovery_rate = 0.0 if caving_area > 0.0 coal_recovery_rate = total_coal_mass / caving_area endif io.out('Coal recovery rate: ' + string(coal_recovery_rate, 2) + ' kg/m2') io.out('===============================================') end ; ======================================== ; ======================================== fish define fix_all_balls loop foreach bp ball.list() if ball.radius(bp) <= 0 ball.radius(bp) = 0.05 endif if ball.density(bp) <= 0 if ball.group(bp) == "coal" or ball.group(bp) == "top_coal" or ball.group(bp) == "bottom_coal" ball.density(bp) = 1360 else ball.density(bp) = 2560 endif endif local pos = ball.pos(bp) local py = pos->y if py <= support_top_height + 0.1 ball.vel.y(bp) = 0.0 ball.vel.x(bp) = 0.0 ball.spin(bp) = 0.0 endif endloop end fish define execute_caving_coal local coal_mass = 0.0 loop foreach bp ball.list if ball.group(bp) == 'caved_coal' coal_mass = coal_mass + ball.mass(bp) endif endloop [return_value] = coal_mass end fish define execute_caving_gangue local gangue_mass = 0.0 loop foreach bp ball.list if ball.group(bp) == 'caved_gangue' gangue_mass = gangue_mass + ball.mass(bp) endif endloop [return_value] = gangue_mass end fish define open_caving_gate io.out('===== Opening Caving Gate =====') io.out('Deleting the horizontal wall representing the caving gate...') local gate_found = false loop foreach wp wall.list if wall.name(wp) == 'caving_gate_main' local gate_id = wall.id(wp) io.out('Found caving gate (Name: caving_gate_main, ID: ' + string(gate_id) + ')') gate_found = true break endif endloop if gate_found command wall delete range name 'caving_gate_main' end_command io.out('Deleted caving gate wall (Name: caving_gate_main)') io.out('Caving gate successfully opened') else io.out('WARNING: No caving gate wall found with name "caving_gate_main"') endif io.out('===============================================') end fish define balance_model io.out('===== Starting Model Balance =====') io.out('Gravity: 9.81 m/s²') io.out('Damping: dp_nratio = 0.5 (default)') io.out('Target: Maximum unbalanced force ratio <= 1e-3') io.out('Initial stress field establishment...') command model gravity 9.81 model cycle 50000 calm 1000 end_command local max_ratio = 1.0 local cycle_count = 0 local max_cycles = 100000 io.out('Cycling until equilibrium...') loop while max_ratio > 1e-3 and cycle_count < max_cycles command model cycle 1000 end_command max_ratio = mech_ratio cycle_count = cycle_count + 1000 if (cycle_count % 10000) == 0 io.out('Cycle: ' + string(cycle_count) + ', Max ratio: ' + string(max_ratio, 6)) endif endloop io.out('===== Model Equilibrium Reached =====') io.out('Caving gate will be opened during mining process') command model save 'initial_state' end_command io.out('===== Model Equilibrium Reached =====') io.out('Final cycle count: ' + string(cycle_count)) io.out('Final max ratio: ' + string(max_ratio, 6)) io.out('Initial stress field established, kinetic energy 鈮0') io.out('===============================================') end fish define set_contact_parameters io.out('Setting contact parameters for different contact types...') io.out('Ball-ball: emod=2e8, kratio=2.5, fric=0.5, dp_nratio=0.5, dp_sratio=0.5') io.out('Ball-facet: emod=4e8, kratio=2.5, fric=0.5, dp_nratio=0.5, dp_sratio=0.5') command ; Set ball-ball contact parameters (default for all contacts first) contact cmat default model linear method deformability emod 2e8 kratio 2.5 property fric 0.5 dp_nratio 0.5 dp_sratio 0.5 contact cmat apply ; Then override ball-facet contacts with different emod contact cmat add model linear method deformability emod 4e8 kratio 2.5 property fric 0.5 dp_nratio 0.5 dp_sratio 0.5 range contact type 'ball-facet' contact cmat apply range contact type 'ball-facet' end_command io.out('Contact parameters set successfully (ball-ball: 2e8 Pa, ball-facet: 4e8 Pa).') end fish define reduce_damping_for_flow io.out('===== Setting Damping for Dense Flow =====') io.out('Setting damping to 0.15 for dense flow through 1.2m caving gates...') command ; Set ball-ball contact parameters (default for all contacts first) contact cmat default model linear method deformability emod 2e8 kratio 2.5 property fric 0.5 dp_nratio 0.15 dp_sratio 0.15 contact cmat apply ; Then override ball-facet contacts with different emod contact cmat add model linear method deformability emod 4e8 kratio 2.5 property fric 0.5 dp_nratio 0.15 dp_sratio 0.15 range contact type 'ball-facet' contact cmat apply range contact type 'ball-facet' ball property 'dp_nratio' 0.15 'dp_sratio' 0.15 end_command io.out('Damping set to 0.15 - dense flow mode enabled') io.out('Particles will flow in sliding-rolling mode through 1.2m gates') io.out('===============================================') end fish define visualize_layers io.out('===== Visualization Setup =====') io.out('Layers are ready for visualization') io.out('Use PFC interface to set colors manually if needed') io.out('===============================================') end fish define stepwise_coal_mining io.out('===== Starting Stepwise Coal Mining =====') io.out('*** WAITING FOR EQUILIBRIUM BEFORE STEPWISE MINING ***') io.out('Checking equilibrium status...') local current_ratio = mech_ratio io.out('Current mechanical ratio: ' + string(current_ratio, 6)) if current_ratio > 1e-3 io.out('System not in equilibrium yet. Cycling until equilibrium...') command model cycle 5000 model solve ratio-average 1e-3 end_command current_ratio = mech_ratio io.out('After cycling, mechanical ratio: ' + string(current_ratio, 6)) endif if current_ratio <= 1e-3 io.out('*** EQUILIBRIUM ACHIEVED - STARTING STEPWISE MINING ***') local step_distance = 0.6 local total_mining_length = 10.6 ; 淇涓0.6绫 local gangue_threshold = 0.05 io.out('Stepwise mining parameters:') io.out(' Step distance: ' + string(step_distance) + 'm') io.out(' Total mining length: ' + string(total_mining_length) + 'm') io.out(' Total steps: ' + string(total_steps)) io.out(' Gangue threshold: ' + string(gangue_threshold*100) + '%') global total_coal_mined = 0.0 global total_gangue_mined = 0.0 global current_step = 0 loop local step (1, total_steps) current_step = step local current_position = 15.0 + (step - 1) * step_distance io.out('') io.out('===== Mining Step ' + string(step) + ' of ' + string(total_steps) + ' =====') io.out('Current position: ' + string(current_position, 1) + 'm') open_caving_gate local gate_opened = true if gate_opened io.out('*** CAVING GATE OPENED - WAITING FOR PARTICLE SETTLEMENT ***') local settlement_cycles = 0 local max_settlement_cycles = 30000 local stable_cycles = 0 local max_stable_cycles = 5 local last_total_discharged = 0.0 local last_mech_ratio = 1.0 local settlement_complete = false loop while settlement_cycles < max_settlement_cycles and not settlement_complete command model cycle 1000 end_command settlement_cycles = settlement_cycles + 1000 if (settlement_cycles % 5000) == 0 local coal_discharged = calculate_discharged_coal_mass() local gangue_discharged = calculate_discharged_gangue_mass() local total_discharged = coal_discharged + gangue_discharged local gangue_ratio = 0.0 local current_mech_ratio = mech_ratio if total_discharged > 0.0 gangue_ratio = gangue_discharged / total_discharged endif io.out('Settlement cycle ' + string(settlement_cycles) + ':') io.out(' Coal discharged: ' + string(coal_discharged, 0) + ' kg') io.out(' Gangue discharged: ' + string(gangue_discharged, 0) + ' kg') io.out(' Gangue ratio: ' + string(gangue_ratio*100, 1) + '%') io.out(' Mechanical ratio: ' + string(current_mech_ratio, 6)) local mass_change = math.abs(total_discharged - last_total_discharged) local ratio_change = math.abs(current_mech_ratio - last_mech_ratio) if mass_change < 1.0 and ratio_change < 1e-4 stable_cycles = stable_cycles + 1 io.out(' System stable for ' + string(stable_cycles) + ' cycles') else stable_cycles = 0 io.out(' System still flowing... (mass change: ' + string(mass_change, 1) + ' kg)') endif last_total_discharged = total_discharged last_mech_ratio = current_mech_ratio if stable_cycles >= max_stable_cycles io.out('*** PARTICLE SETTLEMENT COMPLETED - SYSTEM STABLE ***') settlement_complete = true endif endif endloop local step_coal_mass = calculate_discharged_coal_mass() local step_gangue_mass = calculate_discharged_gangue_mass() local step_total = step_coal_mass + step_gangue_mass gangue_ratio = 0.0 if step_total > 0.0 gangue_ratio = step_gangue_mass / step_total endif total_coal_mined = total_coal_mined + step_coal_mass total_gangue_mined = total_gangue_mined + step_gangue_mass io.out('Step ' + string(step) + ' results:') io.out(' Coal mined: ' + string(step_coal_mass, 1) + ' kg') io.out(' Gangue mined: ' + string(step_gangue_mass, 1) + ' kg') io.out(' Gangue ratio: ' + string(gangue_ratio*100, 1) + '%') io.out(' Cumulative coal: ' + string(total_coal_mined, 0) + ' kg') io.out(' Cumulative gangue: ' + string(total_gangue_mined, 0) + ' kg') if gangue_ratio >= gangue_threshold io.out('Gangue ratio ' + string(gangue_ratio*100, 1) + '% >= ' + string(gangue_threshold*100) + '% - closing gate') close_caving_gate(current_position) else io.out('Gangue ratio ' + string(gangue_ratio*100, 1) + '% < ' + string(gangue_threshold*100) + '% - gate remains open') endif else io.out('No caving gate found at position ' + string(current_position, 1) + 'm') endif command model cycle 1000 model solve ratio-average 1e-3 end_command endloop local total_mined = total_coal_mined + total_gangue_mined local overall_gangue_ratio = 0.0 local coal_recovery_rate = 0.0 if total_mined > 0.0 overall_gangue_ratio = total_gangue_mined / total_mined coal_recovery_rate = (total_coal_mined / total_mined) * 100 endif io.out('') io.out('===== Stepwise Mining Completed =====') io.out('Total mining length: ' + string(total_mining_length) + 'm') io.out('Total steps completed: ' + string(total_steps)) io.out('Total coal mined: ' + string(total_coal_mined, 0) + ' kg') io.out('Total gangue mined: ' + string(total_gangue_mined, 0) + ' kg') io.out('Overall gangue ratio: ' + string(overall_gangue_ratio*100, 1) + '%') io.out('Coal recovery rate: ' + string(coal_recovery_rate, 1) + '%') else io.out('*** EQUILIBRIUM NOT ACHIEVED - MINING CANNOT START ***') io.out('Current ratio: ' + string(current_ratio, 6) + ' > 1e-3') endif io.out('===============================================') end fish define debug_caving_gates io.out('===== Debug: Caving Gates Information =====') local gate_count = 0 loop foreach wp wall.list if wall.name(wp) == 'caving_gate_main' gate_count = gate_count + 1 local wall_pos = wall.pos(wp) local wall_x = wall_pos->x local wall_y = wall_pos->y local wall_center_x = wall_x + 0.6 io.out('Gate ' + string(gate_count) + ':') io.out(' Name: ' + wall.name(wp)) io.out(' Position: X=' + string(wall_x, 2) + 'm, Y=' + string(wall_y, 2) + 'm') io.out(' Center: X=' + string(wall_center_x, 2) + 'm') io.out(' ID: ' + string(wall.id(wp))) io.out(' Group: ' + wall.group(wp)) endif endloop io.out('Total caving gates found: ' + string(gate_count)) io.out('===============================================') end fish define close_caving_gate(position) local gate_closed = false local gate_tolerance = 0.3 ; Tolerance for gate position matching ; Note: In this implementation, gates are deleted when opened ; Closing would require recreating the gate wall ; For simplicity, we just mark as closed gate_closed = true io.out('Closed caving gate at position ' + string(position, 1) + 'm') [return_value] = gate_closed end fish define calculate_discharged_coal_mass local discharged_mass = 0.0 loop foreach bp ball.list local pos = ball.pos(bp) local py = pos->y ; Check if ball is below support level (discharged) if py < support_top_height local ball_group = ball.group(bp) if ball_group == 'top_coal' or ball_group == 'immediate_roof' if ball.density(bp) <= 1400 ; Coal density threshold local ball_mass = ball.mass(bp) if ball_mass > 0.0 discharged_mass = discharged_mass + ball_mass ball.group(bp) = 'discharged_coal' endif endif endif endif endloop [return_value] = discharged_mass end fish define calculate_discharged_gangue_mass local discharged_mass = 0.0 loop foreach bp ball.list local pos = ball.pos(bp) local py = pos->y ; Check if ball is below support level (discharged) if py < support_top_height local ball_group = ball.group(bp) if ball_group == 'top_coal' or ball_group == 'immediate_roof' if ball.density(bp) >= 2500 ; Gangue density threshold local ball_mass = ball.mass(bp) if ball_mass > 0.0 discharged_mass = discharged_mass + ball_mass ball.group(bp) = 'discharged_gangue' endif endif endif endif endloop [return_value] = discharged_mass end fish define calculate_mass_statistics io.out('===== Mass Statistics =====') local total_coal_mass = 0.0 local total_gangue_mass = 0.0 local caved_coal_mass = 0.0 local caved_gangue_mass = 0.0 loop foreach bp ball.list local ball_density = ball.density(bp) local ball_mass = ball.mass(bp) local ball_group = ball.group(bp) if ball_mass > 0.0 if ball_density <= 1400 total_coal_mass = total_coal_mass + ball_mass if ball_group == 'caved_coal' caved_coal_mass = caved_coal_mass + ball_mass endif else if ball_density >= 2500 total_gangue_mass = total_gangue_mass + ball_mass if ball_group == 'caved_gangue' caved_gangue_mass = caved_gangue_mass + ball_mass endif endif endif endif endloop local caving_area = caving_gates * support_width io.out('Original mass:') io.out(' Total coal: ' + string(total_coal_mass, 0) + ' kg') io.out(' Total gangue: ' + string(total_gangue_mass, 0) + ' kg') io.out('') io.out('Caved mass:') io.out(' Caved coal: ' + string(caved_coal_mass, 0) + ' kg') io.out(' Caved gangue: ' + string(caved_gangue_mass, 0) + ' kg') io.out('') io.out('Caving area: ' + string(caving_area, 1) + ' m2') if total_coal_mass > 0.0 io.out('Coal recovery rate: ' + string((caved_coal_mass/total_coal_mass)*100, 1) + '%') else io.out('Coal recovery rate: 0% (no coal mass)') endif if total_gangue_mass > 0.0 io.out('Gangue recovery rate: ' + string((caved_gangue_mass/total_gangue_mass)*100, 1) + '%') else io.out('Gangue recovery rate: 0% (no gangue mass)') endif io.out('') io.out('Mass per unit area:') if caving_area > 0.0 io.out(' Coal: ' + string(caved_coal_mass/caving_area, 1) + ' kg/m2') io.out(' Gangue: ' + string(caved_gangue_mass/caving_area, 1) + ' kg/m2') io.out(' Total: ' + string((caved_coal_mass+caved_gangue_mass)/caving_area, 1) + ' kg/m2') else io.out(' Mass per unit area: 0 kg/m2 (no caving area)') endif io.out('===============================================') end ; ======================================== ; ======================================== fish define print_simulation_info io.out('Longwall Mining Simulation Started') io.out('Model parameters:') io.out(' Bottom coal height: ' + string(bottom_coal_height) + 'm (Cutting)') io.out(' Top coal height: ' + string(top_coal_height) + 'm (Caving)') io.out(' Total coal height: ' + string(total_coal_height) + 'm') io.out(' Gangue layers: ' + string(gangue_layers) + ' layers') io.out(' Immediate roof: ' + string(immediate_roof_thickness) + 'm Siltstone') io.out(' Main roof: ' + string(main_roof_thickness) + 'm Fine Sandstone') io.out(' Support layout: ' + string(total_support_num) + ' frames total') io.out(' Head supports: ' + string(head_support_num) + ' frames (no caving)') io.out(' Middle supports: ' + string(support_num) + ' frames (with caving)') io.out(' Caving gates: ' + string(caving_gates) + ' (1 per middle support)') io.out(' Gangue threshold: ' + string(gangue_threshold*100) + ' percent') io.out('==============================================') local total_mined = total_coal_mass + total_gangue_mass if total_mined > 0.0 io.out('===== Simulation Completed =====') io.out('Final results:') io.out(' Total coal mined: ' + string(total_coal_mass, 0) + 'kg') io.out(' Total gangue mined: ' + string(total_gangue_mass, 0) + 'kg') io.out(' Recovery rate: ' + string((total_coal_mass/total_mined)*100, 1) + '%') else io.out('===== Simulation Completed =====') io.out('Final results:') io.out(' Total coal mined: ' + string(total_coal_mass, 0) + 'kg') io.out(' Total gangue mined: ' + string(total_gangue_mass, 0) + 'kg') io.out(' Recovery rate: 0% (no material mined)') endif io.out('================================') end [print_simulation_info] [create_supports] [generate_bottom_coal] [generate_top_coal] [generate_immediate_roof] [balance_model] [set_contact_parameters] [reduce_damping_for_flow] [visualize_layers] [debug_caving_gates] [stepwise_coal_mining] [calculate_mass_statistics] fish define calculate_coal_statistics io.out('===== Coal Mining Results =====') local total_top_coal_mass = 0.0 local total_gangue_mass = 0.0 local discharged_coal_mass = 0.0 local discharged_gangue_mass = 0.0 loop foreach bp ball.list local ball_density = ball.density(bp) local ball_mass = ball.mass(bp) local ball_group = ball.group(bp) if ball_mass > 0.0 if ball_group == 'top_coal' total_top_coal_mass = total_top_coal_mass + ball_mass else if ball_group == 'immediate_roof' total_gangue_mass = total_gangue_mass + ball_mass else if ball_group == 'discharged_coal' discharged_coal_mass = discharged_coal_mass + ball_mass else if ball_group == 'discharged_gangue' discharged_gangue_mass = discharged_gangue_mass + ball_mass endif endif endif endif endif endloop local total_coal_mass = total_top_coal_mass local total_discharged_mass = discharged_coal_mass + discharged_gangue_mass io.out('===== Original Coal Reserves =====') io.out('Top coal mass: ' + string(total_top_coal_mass, 0) + ' kg') io.out('Gangue mass: ' + string(total_gangue_mass, 0) + ' kg') io.out('Total coal reserves: ' + string(total_coal_mass, 0) + ' kg') io.out('') io.out('===== Mining Production =====') io.out('Coal mined: ' + string(discharged_coal_mass, 0) + ' kg') io.out('Gangue mined: ' + string(discharged_gangue_mass, 0) + ' kg') io.out('Total mined: ' + string(total_discharged_mass, 0) + ' kg') io.out('') local coal_recovery_rate = 0.0 local gangue_discharge_rate = 0.0 local gangue_ratio = 0.0 local mining_efficiency = 0.0 if total_coal_mass > 0.0 coal_recovery_rate = (discharged_coal_mass / total_coal_mass) * 100 endif if total_gangue_mass > 0.0 gangue_discharge_rate = (discharged_gangue_mass / total_gangue_mass) * 100 endif if total_discharged_mass > 0.0 gangue_ratio = (discharged_gangue_mass / total_discharged_mass) * 100 mining_efficiency = (discharged_coal_mass / total_discharged_mass) * 100 endif io.out('===== Key Performance Indicators =====') io.out('Coal recovery rate: ' + string(coal_recovery_rate, 1) + '%') io.out('Gangue discharge rate: ' + string(gangue_discharge_rate, 1) + '%') io.out('Gangue ratio in production: ' + string(gangue_ratio, 1) + '%') io.out('Mining efficiency: ' + string(mining_efficiency, 1) + '%') io.out('') io.out('===== Economic Indicators =====') local coal_volume = total_coal_mass / 1360.0 local mined_volume = total_discharged_mass / 1500.0 io.out('Coal volume: ' + string(coal_volume, 1) + ' m3') io.out('Mined volume: ' + string(mined_volume, 1) + ' m3') io.out('') io.out('===== Summary =====') if gangue_ratio <= 5.0 io.out('Mining successful: Gangue ratio ' + string(gangue_ratio, 1) + '% <= 5%') else io.out('Mining stopped: Gangue ratio ' + string(gangue_ratio, 1) + '% > 5%') endif if coal_recovery_rate >= 80.0 io.out('Good recovery: ' + string(coal_recovery_rate, 1) + '% >= 80%') else io.out('Low recovery: ' + string(coal_recovery_rate, 1) + '% < 80%') endif io.out('===============================================') end fish define control_particle_numbers io.out('===== Particle Number Control =====') io.out('Total particles will be limited to 2,000') io.out('Model dimensions:') io.out(' Total width: ' + string(model_width) + 'm') io.out(' Effective mining width: 60.0m (X: 3-63m)') io.out(' Boundary buffer: 6.0m (3m each side)') io.out(' Total height: 31.4m (Y: 0-31.4m)') io.out('Layer structure:') io.out(' Bottom layer: Top coal (15.8m height)') io.out(' Top layer: Immediate roof (15.6m height)') io.out('Distribution:') io.out(' Top coal: 1,000 particles (50%)') io.out(' Immediate roof: 1,000 particles (50%)') io.out(' Total: 2,000 particles') io.out('===============================================') end fish define visualize_modeling_process io.out('===== Modeling Process Visualization =====') io.out('Step 1: Generating top coal particles...') io.out('Step 2: Generating immediate roof particles (gangue)...') io.out('Step 3: Model balancing...') io.out('Step 4: Sequential caving simulation...') io.out('Step 5: Results calculation...') io.out('===============================================') end ; modeling_sequence function removed - using main execution sequence instead fish define detailed_mining_report io.out('===== Detailed Mining Report =====') local total_particles = 0 local top_coal_particles = 0 local gangue_particles = 0 local discharged_coal_particles = 0 local discharged_gangue_particles = 0 loop foreach bp ball.list total_particles = total_particles + 1 local ball_group = ball.group(bp) if ball_group == 'top_coal' top_coal_particles = top_coal_particles + 1 else if ball_group == 'immediate_roof' gangue_particles = gangue_particles + 1 else if ball_group == 'discharged_coal' discharged_coal_particles = discharged_coal_particles + 1 else if ball_group == 'discharged_gangue' discharged_gangue_particles = discharged_gangue_particles + 1 endif endif endif endif endloop io.out('Particle Statistics:') io.out(' Total particles: ' + string(total_particles)) io.out(' Top coal particles: ' + string(top_coal_particles)) io.out(' Gangue particles: ' + string(gangue_particles)) io.out(' Discharged coal particles: ' + string(discharged_coal_particles)) io.out(' Discharged gangue particles: ' + string(discharged_gangue_particles)) io.out('') local remaining_coal = top_coal_particles - discharged_coal_particles local remaining_gangue = gangue_particles - discharged_gangue_particles io.out('Remaining Particles:') io.out(' Remaining coal: ' + string(remaining_coal)) io.out(' Remaining gangue: ' + string(remaining_gangue)) io.out(' Total remaining: ' + string(remaining_coal + remaining_gangue)) io.out('===============================================') end fish define calculate_mining_area_statistics io.out('===== Mining Area Statistics =====') io.out('Total model width: ' + string(model_width) + 'm') io.out('Boundary buffer (each side): ' + string(boundary_buffer) + 'm') io.out('Effective mining width: ' + string(effective_mining_width) + 'm') io.out('Mining area: X = ' + string(mining_start_x) + ' to ' + string(mining_end_x) + 'm') io.out('Boundary areas (not included in mining statistics):') io.out(' Left boundary: X = 0 to ' + string(mining_start_x) + 'm') io.out(' Right boundary: X = ' + string(mining_end_x) + ' to ' + string(model_width) + 'm') io.out('===============================================') end fish define support_position_info io.out('===== Support Position Information =====') io.out('Support layout with 3m right offset:') io.out('') io.out('Head supports (3 frames):') io.out(' Support 1: X = 3.0m to 4.5m') io.out(' Support 2: X = 4.5m to 6.0m') io.out(' Support 3: X = 6.0m to 7.5m') io.out('') io.out('Middle supports (' + string(support_num) + ' frames):') io.out(' Start position: X = 7.5m') io.out(' End position: X = ' + string(7.5 + support_num * support_width) + 'm') io.out(' Spacing: ' + string(support_width) + 'm between frames') io.out('') io.out('Tail supports (3 frames):') local tail_start = 7.5 + support_num * support_width io.out(' Support 1: X = ' + string(tail_start) + 'm to ' + string(tail_start + 1.5) + 'm') io.out(' Support 2: X = ' + string(tail_start + 1.5) + 'm to ' + string(tail_start + 3.0) + 'm') io.out(' Support 3: X = ' + string(tail_start + 3.0) + 'm to ' + string(tail_start + 4.5) + 'm') io.out('') io.out('Total support coverage: X = 3.0m to ' + string(tail_start + 4.5) + 'm') io.out('===============================================') end fish define verify_immediate_roof_position io.out('===== Immediate Roof Position Verification =====') local particles_in_x_range = 0 local particles_in_y_range = 0 local particles_in_full_range = 0 local particles_out_of_range = 0 local min_x = 1000.0 local max_x = -1000.0 local min_y = 1000.0 local max_y = -1000.0 loop foreach bp ball.list if ball.group(bp) == 'immediate_roof' local pos = ball.pos(bp) local px = pos->x local py = pos->y if px >= 3.0 and px <= 63.0 particles_in_x_range = particles_in_x_range + 1 endif if py >= 0.0 and py <= 31.5 particles_in_y_range = particles_in_y_range + 1 endif if px >= 3.0 and px <= 63.0 and py >= 0.0 and py <= 31.5 particles_in_full_range = particles_in_full_range + 1 else particles_out_of_range = particles_out_of_range + 1 endif if px < min_x min_x = px endif if px > max_x max_x = px endif if py < min_y min_y = py endif if py > max_y max_y = py endif endif endloop io.out('Position verification results:') io.out(' Particles in X range (3-63m): ' + string(particles_in_x_range)) io.out(' Particles in Y range (0-31.5m): ' + string(particles_in_y_range)) io.out(' Particles in full range: ' + string(particles_in_full_range)) io.out(' Particles out of range: ' + string(particles_out_of_range)) io.out(' Actual X range: ' + string(min_x, 2) + ' to ' + string(max_x, 2) + 'm') io.out(' Actual Y range: ' + string(min_y, 2) + ' to ' + string(max_y, 2) + 'm') io.out(' Expected X range: 3.0 to 63.0m') io.out(' Expected Y range: 0.0 to 31.5m') if particles_out_of_range == 0 io.out('Bouncing prevention activated (particles_out_of_range = 0)') prevent_bouncing() command model cycle 50 model solve ratio-average 1e-3 end_command loop foreach bp ball.list ball.vel.x(bp) = 0.0 ball.vel.y(bp) = 0.0 ball.spin(bp) = 0.0 endloop endif local overall_gangue_ratio = 0.0 if (total_coal_mass + total_gangue_mass) > 0.0 overall_gangue_ratio = total_gangue_mass / (total_coal_mass + total_gangue_mass) endif io.out('===== Single Round Interval Caving Completed =====') io.out('Caving area: ' + string(caving_area, 1) + ' m2 (17 odd-numbered supports)') io.out('Total coal mined: ' + string(total_coal_mass, 0) + ' kg') io.out('Total gangue mined: ' + string(total_gangue_mass, 0) + ' kg') io.out('Overall gangue ratio: ' + string(overall_gangue_ratio*100, 1) + '%') io.out('Coal recovery rate: ' + string((total_coal_mass/(total_coal_mass + total_gangue_mass))*100, 1) + '%') io.out('Interval caving: Only odd-numbered gates (1,3,5,...,33) were processed') io.out('Boundary areas (6m each end): Particles remain constrained') io.out('===============================================') end ; ======================================== ; ======================================== fish define fix_boundary_walls io.out('===== Fixing Boundary Walls =====') command wall delete range id 103 wall delete range id 104 end_command command wall create vertices 3.0 0 3.0 31.4 id 103 wall attribute velocity-x 0.0 range id 103 end_command io.out('Left buffer wall (ID 103) created at X=3.0m') command wall create vertices 63.0 0 63.0 31.4 id 104 wall attribute velocity-x 0.0 range id 104 end_command io.out('Right buffer wall (ID 104) created at X=63.0m') io.out('Boundary walls fixed - particles should be constrained') io.out('===============================================') end fish define check_particle_boundaries io.out('===== Checking Particle Boundaries =====') local particles_in_left_buffer = 0 local particles_in_right_buffer = 0 local particles_in_mining_area = 0 local total_particles = 0 loop foreach bp ball.list total_particles = total_particles + 1 local pos = ball.pos(bp) local px = pos->x if px < 3.0 particles_in_left_buffer = particles_in_left_buffer + 1 else if px > 63.0 particles_in_right_buffer = particles_in_right_buffer + 1 else particles_in_mining_area = particles_in_mining_area + 1 endif endif endloop io.out('Particle boundary analysis:') io.out(' Total particles: ' + string(total_particles)) io.out(' Particles in left buffer (X<3.0m): ' + string(particles_in_left_buffer)) io.out(' Particles in mining area (3.0m to 63.0m): ' + string(particles_in_mining_area)) io.out(' Particles in right buffer (X>63.0m): ' + string(particles_in_right_buffer)) if particles_in_left_buffer > 0 or particles_in_right_buffer > 0 io.out('WARNING: Particles found in buffer zones!') io.out('Boundary walls may not be working properly') else io.out('SUCCESS: All particles are in mining area') endif io.out('===============================================') end fish define enhanced_equilibrium_check io.out('===== Enhanced Equilibrium Check =====') local mech_ratio = mech_ratio io.out('Mechanical ratio: ' + string(mech_ratio, 6)) local total_ke = 0.0 loop foreach bp ball.list local vel = ball.vel(bp) local mass = ball.mass(bp) total_ke = total_ke + 0.5 * mass * (vel->x^2 + vel->y^2) endloop io.out('Total kinetic energy: ' + string(total_ke, 6)) local is_equilibrium = false if mech_ratio <= 1e-3 and total_ke < 1e-6 is_equilibrium = true endif if is_equilibrium io.out('SUCCESS: System is in equilibrium!') else io.out('WARNING: System not in equilibrium') if mech_ratio > 1e-3 io.out(' - Mechanical ratio too high: ' + string(mech_ratio, 6)) endif if total_ke > 1e-6 io.out(' - Kinetic energy too high: ' + string(total_ke, 6)) endif endif io.out('===============================================') [return_value] = is_equilibrium end fish define verify_position io.out('===== Verifying Caving Gate Position =====') local coal_top = 2.8 local gate_found = false loop foreach wp wall.list if wall.name(wp) == 'caving_gate_main' local gate_y = wall.pos.y(wp) io.out('Found caving gate at Y=' + string(gate_y, 2) + 'm') if gate_y > coal_top - 1.0 io.out('WARNING: Gate too high, adjusting position...') command wall move range name 'caving_gate_main' 0 [coal_top - 2.0] end_command io.out('Gate moved to Y=' + string(coal_top - 2.0, 2) + 'm') else io.out('Gate position OK') endif gate_found = true endif endloop if not gate_found io.out('WARNING: No caving gate found with name "caving_gate_main"') endif io.out('===============================================') end fish define debug_gates io.out('===== Debug: Caving Gates Information =====') local valid_gates = 0 local total_gates = 0 loop foreach wp wall.list if wall.name(wp) == 'caving_gate_main' total_gates = total_gates + 1 local wall_x = wall.pos.x(wp) local wall_y = wall.pos.y(wp) local wall_center_x = wall_x + 0.6 io.out('Gate ' + string(total_gates) + ':') io.out(' Name: ' + wall.name(wp)) io.out(' Position: X=' + string(wall_x, 2) + 'm, Y=' + string(wall_y, 2) + 'm') io.out(' Center: X=' + string(wall_center_x, 2) + 'm') io.out(' ID: ' + string(wall.id(wp))) io.out(' Group: ' + wall.group(wp)) valid_gates = valid_gates + 1 endif endloop io.out('Total caving gates found: ' + string(total_gates)) io.out('Valid caving gates: ' + string(valid_gates)) io.out('===============================================') end检查代码,达到平衡状态时放煤口能否打开
最新发布
09-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值