def plot_of_unit_loads(c: Config): """Make a contour plot of response at unit load position.""" fem_runner = OSRunner(c) response_type = ResponseType.YTranslation X, Z, R = [], [], [] for x in np.linspace(c.bridge.x_min, c.bridge.x_max, int(c.bridge.length)): X.append([]) Z.append([]) R.append([]) for z in np.linspace(c.bridge.z_min, c.bridge.z_max, int(c.bridge.width)): pload = PointLoad(x_frac=c.bridge.x_frac(x), z_frac=c.bridge.z_frac(z), kn=100) fem_params = SimParams(ploads=[pload], response_types=[response_type]) fem_responses = load_fem_responses( c=c, fem_params=fem_params, response_type=response_type, fem_runner=fem_runner, ) X[-1].append(x) Z[-1].append(z) R[-1].append(fem_responses._at(x=x, y=0, z=z)) cmap = get_cmap("bwr") plt.contourf(X, Z, R, levels=50, cmap=cmap) plt.show()
def run_uls( c: Config, piers: bool, healthy: bool, cracked: bool, crack_x: Optional[int] = None, crack_length: Optional[int] = None, ): """Run all unit load simulations.""" def crack_f(): return transverse_crack(at_x=crack_x, length=crack_length) print_i( f"Running simulations with crack zone at x = {crack_x}, length = {crack_length}" ) response_type = ResponseType.YTranslation if piers: # Pier settlement. list( PSResponses.load(c=c, response_type=response_type, fem_runner=OSRunner(c))) if healthy: c = healthy_damage_w_crack_nodes(crack_f=crack_f).use(c)[0] # Unit load simulations (healthy bridge). ULResponses.load_wheel_tracks( c=c, response_type=response_type, sim_runner=OSRunner(c), wheel_zs=c.bridge.wheel_track_zs(c), run_only=True, ) elif cracked: # Unit load simulations (cracked bridge). c = crack_f().use(c)[0] ULResponses.load_wheel_tracks( c=c, response_type=response_type, sim_runner=OSRunner(c), wheel_zs=c.bridge.wheel_track_zs(c), run_only=True, )
def run_ulm(c: Config, healthy: bool, cracked: bool, x_i: float, z_i: float): """Run all unit load simulations.""" response_type = ResponseType.YTranslation wheel_xs = c.bridge.wheel_track_xs(c) wheel_x = wheel_xs[x_i] wheel_zs = c.bridge.wheel_track_zs(c) wheel_z = wheel_zs[z_i] print_i(f"Wheel (x, z) = ({wheel_x}, {wheel_z})") point = Point(x=wheel_x, y=0, z=wheel_z) if healthy: ULResponses.load_ulm( c=c, response_type=response_type, points=[point], sim_runner=OSRunner(c), ) if cracked: c = transverse_crack().use(c)[0] ULResponses.load_ulm( c=c, response_type=response_type, points=[point], sim_runner=OSRunner(c), )
def cover_photo(c: Config, x: float, deformation_amp: float): """ TODO: SimParams takes any loads iterable, to be flattened. TODO: Wrap SimRunner into Config. TODO: Ignore response type in SimParams (fill in by load_sim_responses). """ response_type = ResponseType.YTranslation sim_responses = load_fem_responses( c=c, sim_runner=OSRunner(c), response_type=response_type, sim_params=SimParams( response_types=[response_type], ploads=list( chain.from_iterable( truck1.to_point_loads( bridge=c.bridge, time=truck1.time_at(x=x, bridge=c.bridge), ))), ), ) shells = contour_responses_3d(c=c, sim_responses=sim_responses) for cmap in [ parula_cmap, get_cmap("jet"), get_cmap("coolwarm"), get_cmap("viridis"), ]: contour_responses_3d( c=c, sim_responses=sim_responses, deformation_amp=deformation_amp, shells=shells, cmap=cmap, ) plt.axis("off") plt.grid(False) plt.savefig( c.get_image_path( "cover-photo", f"cover-photo-deform-{deformation_amp}" f"-cmap-{cmap.name}.pdf", )) plt.close()
def oneclass(c: Config): normal_traffic_array, traffic_scenario = load_normal_traffic_array(c) bridge_scenarios = [HealthyScenario()] + each_pier_scenarios(c) response_type = ResponseType.YTranslation points = [ Point(x=x, y=0, z=z) for x, z in itertools.product( np.linspace(c.bridge.x_min, c.bridge.x_max / 2, 20), np.linspace(c.bridge.z_min, c.bridge.z_max / 2, 3), ) ] results = [] for b, bridge_scenario in enumerate(bridge_scenarios): print_i(f"One class: bridge scenario {bridge_scenario.name}") responses = responses_to_traffic_array( c=c, traffic_array=normal_traffic_array, response_type=response_type, bridge_scenario=bridge_scenario, points=points, fem_runner=OSRunner(c), ).T print(len(normal_traffic_array)) print(responses.shape) # Fit on the healthy scenario. if b == 0: assert len(responses) == len(points) clfs = [] for r, rs in enumerate(responses): print_i(f"Training classifier {r} / {len(responses)}") clfs.append(OneClassSVM().fit(rs.reshape(-1, 1))) scenario_results = [] for p, _ in enumerate(points): print_i(f"Predicting points {p} / {len(points)}") prediction = clfs[p].predict(responses[p].reshape(-1, 1)) print(prediction) print(len(prediction[prediction < 0])) print(len(prediction[prediction > 0]))
def gradient_pier_displacement_plot( c: Config, pier_disp: PierSettlementScenario, response_type: ResponseType, title: str, ): """Contour plot of piers displaced in an increasing gradient.""" # 10 x 10 grid of points on the bridge deck where to record fem. points = [ Point(x=x, y=0, z=z) for x, z in itertools.product( np.linspace(c.bridge.x_min, c.bridge.x_max, 10), np.linspace(c.bridge.z_min, c.bridge.z_max, 10), ) ] # Create empty traffic array and collect fem. response_array = responses_to_traffic_array( c=c, traffic_array=np.zeros( (1, len(c.bridge.wheel_tracks(c)) * c.il_num_loads)), response_type=response_type, bridge_scenario=pier_disp, points=points, fem_runner=OSRunner(c), ) top_view_bridge(c.bridge, abutments=True, piers=True) responses = Responses.from_responses( response_type=response_type, responses=[(response_array[0][p], point) for p, point in enumerate(points)], ) plot_contour_deck(c=c, responses=responses, center_norm=True) plt.title(title) plt.savefig( c.get_image_path("pier-scenarios", f"pier-displacement-{safe_str(title)}")) plt.close()
def number_of_uls_plot(c: Config): """Plot error as a function of number of unit load simulations.""" if not c.shorten_paths: raise ValueError("This plot requires --shorten-paths true") response_type = ResponseType.YTranslation num_ulss = np.arange(100, 2000, 10) chosen_uls = 600 point = Point(x=c.bridge.x_max - (c.bridge.length / 2), y=0, z=-8.4) wagen1_time = truck1.time_at(x=point.x, bridge=c.bridge) print_i(f"Wagen 1 time at x = {point.x:.3f} is t = {wagen1_time:.3f}") # Determine the reference value. truck_loads = flatten( truck1.to_point_load_pw(time=wagen1_time, bridge=c.bridge), PointLoad) print_i(f"Truck loads = {truck_loads}") sim_responses = load_fem_responses( c=c, response_type=response_type, sim_runner=OSRunner(c), sim_params=SimParams(ploads=truck_loads, response_types=[response_type]), ) ref_value = sim_responses.at_deck(point, interp=True) * 1000 print_i(f"Reference value = {ref_value}") # Collect the data. total_load = [] num_loads = [] responses = [] for num_uls in num_ulss: c.il_num_loads = num_uls # Nested in here because it depends on the setting of 'il_num_loads'. truck_loads = flatten( truck1.to_wheel_track_loads(c=c, time=wagen1_time), PointLoad) num_loads.append(len(truck_loads)) total_load.append(sum(map(lambda l: l.kn, truck_loads))) sim_responses = load_fem_responses( c=c, response_type=response_type, sim_runner=OSRunner(c), sim_params=SimParams(ploads=truck_loads, response_types=[response_type]), ) responses.append(sim_responses.at_deck(point, interp=True) * 1000) # Plot the raw fem, then error on the second axis. plt.landscape() # plt.plot(num_ulss, fem) # plt.ylabel(f"{response_type.name().lower()} (mm)") plt.xlabel("ULS") error = np.abs(np.array(responses) - ref_value).flatten() * 100 # ax2 = plt.twinx() plt.plot(num_ulss, error) plt.ylabel("Error (%)") plt.title( f"Error in {response_type.name()} to Truck 1 as a function of ULS") # Plot the chosen number of ULS. chosen_error = np.interp([chosen_uls], num_ulss, error)[0] plt.axhline( chosen_error, label=f"At {chosen_uls} ULS, error = {np.around(chosen_error, 2)} %", color="black", ) plt.axhline(0, color="red", label="Response from direct simulation (no wheel tracks)") plt.legend() plt.tight_layout() plt.savefig(c.get_image_path("paramselection", "uls.pdf")) plt.close() # Additional verification plots. plt.plot(num_ulss, total_load) plt.savefig(c.get_image_path("paramselection", "uls-verify-total-load.pdf")) plt.close() plt.plot(num_ulss, num_loads) plt.savefig(c.get_image_path("paramselection", "uls-verify-num-loads.pdf")) plt.close()
def events(c: Config, x: float, z: float): """Plot events due to normal traffic.""" point = Point(x=x, y=0, z=z) # 10 seconds of 'normal' traffic. max_time = 10 traffic_scenario = normal_traffic(c=c, lam=5, min_d=2) # Create the 'TrafficSequence' and 'TrafficArray'. traffic_sequence = traffic_scenario.traffic_sequence( bridge=c.bridge, max_time=max_time ) traffic_array = to_traffic_array( c=c, traffic_sequence=traffic_sequence, max_time=max_time ) # Find when the simulation has warmed up, and when 'TrafficArray' begins. warmed_up_at = traffic_sequence[0][0].time_left_bridge(c.bridge) traffic_array_starts = (int(warmed_up_at / c.sensor_hz) + 1) * c.sensor_hz print(f"warmed up at = {warmed_up_at}") print(f"traffic_array_starts = {traffic_array_starts}") traffic_array_ends = traffic_array_starts + (len(traffic_array) * c.sensor_hz) print(f"traffic_array_ends = {traffic_array_ends}") point_lane_ind = c.bridge.closest_lane(z) vehicles = list(set(ts[0] for ts in traffic_sequence)) print(len(vehicles)) print(vehicles[0]) vehicles = sorted( set(ts[0] for ts in traffic_sequence if ts[0].lane == point_lane_ind), key=lambda v: -v.init_x_frac, ) print(len(vehicles)) print(vehicles[0]) event_indices = [] vehicle_times = [v.time_at(x=x - 2, bridge=c.bridge) for v in vehicles] for v, t in zip(vehicles, vehicle_times): print(f"Vehicle {v.init_x_frac} {v.mps} at time {t}") start_time = int(t / c.sensor_hz) * c.sensor_hz print(f"start_time = {start_time}") ta_start_time = np.around(start_time - traffic_array_starts, 8) print(f"ta start time = {ta_start_time}") ta_start_index = int(ta_start_time / c.sensor_hz) print(f"ta start index = {ta_start_index}") ta_end_index = ta_start_index + int(c.event_time_s / c.sensor_hz) print(f"ta end index = {ta_end_index}") if ta_start_index >= 0 and ta_end_index < len(traffic_array): event_indices.append((ta_start_index, ta_end_index)) print(event_indices) responses = ( responses_to_traffic_array( c=c, traffic_array=traffic_array, response_type=ResponseType.YTranslation, damage_scenario=healthy_scenario, points=[point], sim_runner=OSRunner(c), ) * 1000 ) # fem = add_displa_noise(fem) print(responses.shape) plt.portrait() for event_ind, (event_start, event_end) in enumerate(event_indices): plt.subplot(len(event_indices), 1, event_ind + 1) plt.plot(responses[event_start : event_end + 1]) plt.tight_layout() plt.savefig(c.get_image_path("classify/events", "events.pdf")) plt.close()
def comparison_plots_705(c: Config, run_only: bool, scatter: bool): """Make contour plots for all verification points on bridge 705.""" # from classify.scenario.bridge import transverse_crack # c = transverse_crack().use(c)[0] positions = [ # (52, -8.4, "a"), (34.95459, 26.24579 - 16.6, "a"), (51.25051, 16.6 - 16.6, "b"), (89.98269, 9.445789 - 16.6, "c"), (102.5037, 6.954211 - 16.6, "d"), # (34.95459, 29.22606 - 16.6, "a"), # (51.25051, 16.6 - 16.6, "b"), # (92.40638, 12.405 - 16.6, "c"), # (101.7649, 3.973938 - 16.6, "d"), ] diana_values = pd.read_csv("validation/diana-screenshots/min-max.csv") response_types = [ResponseType.YTranslation, ResponseType.Strain] # For each response type and loading position first create contour plots for # OpenSees. Then finally create subplots comparing to Diana. cmap = diana_cmap_r for load_x, load_z, label in positions: for response_type in response_types: # Setup the metadata. if response_type == ResponseType.YTranslation: rt_str = "displa" unit_str = "mm" elif response_type == ResponseType.Strain: rt_str = "strain" unit_str = "E-6" else: raise ValueError("Unsupported response type") row = diana_values[diana_values["name"] == f"{label}-{rt_str}"] dmin, dmax = float(row["dmin"]), float(row["dmax"]) omin, omax = float(row["omin"]), float(row["omax"]) amin, amax = max(dmin, omin), min(dmax, omax) levels = np.linspace(amin, amax, 16) # Create the OpenSees plot. loads = [ PointLoad( x_frac=c.bridge.x_frac(load_x), z_frac=c.bridge.z_frac(load_z), kn=100, ) ] fem_responses = load_fem_responses( c=c, response_type=response_type, sim_runner=OSRunner(c), sim_params=SimParams(ploads=loads, response_types=response_types), ) if run_only: continue title = ( f"{response_type.name()} from a {loads[0].kn} kN point load at" + f"\nx = {load_x:.3f}m, z = {load_z:.3f}m, with ") save = lambda prefix: c.get_image_path( "validation/diana-comp", safe_str(f"{prefix}{response_type.name()}") + ".pdf", ) top_view_bridge(c.bridge, piers=True, abutments=True) fem_responses = fem_responses.resize() sci_format = response_type == ResponseType.Strain plot_contour_deck( c=c, responses=fem_responses, ploads=loads, cmap=cmap, levels=levels, sci_format=sci_format, decimals=4, scatter=scatter, ) plt.title(title + "OpenSees") plt.tight_layout() plt.savefig(save(f"{label}-")) plt.close() # Finally create label/title the Diana plot. if label is not None: # First plot and clear, just to have the same colorbar. plot_contour_deck(c=c, responses=fem_responses, ploads=loads, cmap=cmap, levels=levels) plt.cla() # Then plot the bridge and top_view_bridge(c.bridge, piers=True, abutments=True) plt.imshow( mpimg.imread( f"validation/diana-screenshots/{label}-{rt_str}.png"), extent=( c.bridge.x_min, c.bridge.x_max, c.bridge.z_min, c.bridge.z_max, ), ) dmin_s = f"{dmin:.4e}" if sci_format else f"{dmin:.4f}" dmax_s = f"{dmax:.4e}" if sci_format else f"{dmax:.4f}" dabs_s = (f"{abs(dmin - dmax):.4e}" if sci_format else f"{abs(dmin - dmax):.4f}") for point, leg_label, color, alpha in [ ((load_x, load_z), f"{loads[0].kn} kN load", "r", 1), ((0, 0), f"min = {dmin_s} {fem_responses.units}", "r", 0), ((0, 0), f"max = {dmax_s} {fem_responses.units}", "r", 0), ((0, 0), f"|min-max| = {dabs_s} {fem_responses.units}", "r", 0), ]: plt.scatter( [point[0]], [point[1]], label=leg_label, marker="o", color=color, alpha=alpha, ) plt.legend() plt.title(title + "Diana") plt.xlabel("X position (m)") plt.ylabel("Z position (m)") plt.tight_layout() plt.savefig(save(f"{label}-diana-")) plt.close()
def piers_displaced(c: Config): """Contour plots of pier displacement for the given pier indices.""" pier_indices = [4, 5] response_types = [ResponseType.YTranslation, ResponseType.Strain] axis_values = pd.read_csv("validation/axis-screenshots/piers-min-max.csv") for r_i, response_type in enumerate(response_types): for p in pier_indices: # Run the simulation and collect fem. sim_responses = load_fem_responses( c=c, response_type=response_type, sim_runner=OSRunner(c), sim_params=SimParams(displacement_ctrl=PierSettlement( displacement=c.pd_unit_disp, pier=p), ), ) # In the case of stress we map from kn/m2 to kn/mm2 (E-6) and then # divide by 1000, so (E-9). assert c.pd_unit_disp == 1 if response_type == ResponseType.Strain: sim_responses.to_stress(c.bridge).map(lambda r: r * 1e-9) # Get min and max values for both Axis and OpenSees. rt_str = ("displa" if response_type == ResponseType.YTranslation else "stress") row = axis_values[axis_values["name"] == f"{p}-{rt_str}"] dmin, dmax = float(row["dmin"]), float(row["dmax"]) omin, omax = float(row["omin"]), float(row["omax"]) amin, amax = max(dmin, omin), min(dmax, omax) levels = np.linspace(amin, amax, 16) # Plot and save the image. If plotting strains use Axis values for # colour normalization. # norm = None from plot import axis_cmap_r cmap = axis_cmap_r top_view_bridge(c.bridge, abutments=True, piers=True) plot_contour_deck(c=c, cmap=cmap, responses=sim_responses, levels=levels) plt.tight_layout() plt.title( f"{sim_responses.response_type.name()} from 1mm pier settlement with OpenSees" ) plt.savefig( c.get_image_path( "validation/pier-displacement", safe_str(f"pier-{p}-{sim_responses.response_type.name()}") + ".pdf", )) plt.close() # First plot and clear, just to have the same colorbar. plot_contour_deck(c=c, responses=sim_responses, cmap=cmap, levels=levels) plt.cla() # Save the axis plots. axis_img = mpimg.imread( f"validation/axis-screenshots/{p}-{rt_str}.png") top_view_bridge(c.bridge, abutments=True) plt.imshow( axis_img, extent=( c.bridge.x_min, c.bridge.x_max, c.bridge.z_min, c.bridge.z_max, ), ) # Plot the load and min, max values. for point, leg_label, color in [ ((0, 0), f"min = {np.around(dmin, 3)} {sim_responses.units}", "r"), ((0, 0), f"max = {np.around(dmax, 3)} {sim_responses.units}", "r"), ( (0, 0), f"|min-max| = {np.around(abs(dmax - dmin), 3)} {sim_responses.units}", "r", ), ]: plt.scatter( [point[0]], [point[1]], label=leg_label, marker="o", color=color, alpha=0, ) if response_type == ResponseType.YTranslation: plt.legend() # Title and save. plt.title( f"{response_type.name()} from 1mm pier settlement with AxisVM") plt.xlabel("X position (m)") plt.ylabel("Z position (m)") plt.tight_layout() plt.savefig( c.get_image_path( "validation/pier-displacement", f"{p}-axis-{rt_str}.pdf", )) plt.close()
def point_load_response_plots(c: Config, x: float, z: float, kn: int = 1000, run: bool = False): """Response to a point load per scenarios scenario.""" response_types = [ResponseType.YTranslation, ResponseType.Strain] # scenarios = all_scenarios(c) damage_scenarios = [HealthyScenario(), transverse_crack()] # 10 x 10 grid of points on the bridge deck where to record fem. points = [ Point(x=x, y=0, z=z) for x, z in itertools.product( np.linspace(c.bridge.x_min, c.bridge.x_max, 30), np.linspace(c.bridge.z_min, c.bridge.z_max, 100), ) ] for response_type in response_types: all_responses = [] for damage_scenario in damage_scenarios: sim_params = SimParams( response_types=[response_type], ploads=[ PointLoad(x_frac=c.bridge.x_frac(x), z_frac=c.bridge.z_frac(z), kn=kn) ], ) use_c, sim_params = damage_scenario.use(c=c, sim_params=sim_params) all_responses.append( load_fem_responses( c=use_c, sim_params=sim_params, response_type=response_type, sim_runner=OSRunner(use_c), run=run, ).resize()) amin, amax = np.inf, -np.inf for sim_responses in all_responses: responses = np.array(list(sim_responses.values())) amin = min(amin, min(responses)) amax = max(amax, max(responses)) for d, damage_scenario in enumerate(damage_scenarios): top_view_bridge(c.bridge, abutments=True, piers=True) plot_contour_deck( c=c, responses=all_responses[d], levels=100, norm=colors.Normalize(vmin=amin, vmax=amax), decimals=10, ) plt.title(damage_scenario.name) plt.tight_layout() plt.savefig( c.get_image_path( "contour/point-load", safe_str( f"x-{x:.2f}-z-{z:.2f}-kn-{kn}-{response_type.name()}-{damage_scenario.name}" ) + ".pdf", )) plt.close()