def make_node_plots(original_c: Config): """Make all variations of 3d scatter plots of nodes.""" for damage_scenario in healthy_and_cracked_scenarios: c, sim_params = damage_scenario.use(original_c, SimParams([])) for ctx, ctx_name in [ (BuildContext(add_loads=[Point(x=85, y=0, z=0)]), "refined"), (None, "unrefined"), ]: bridge_nodes = get_bridge_nodes(bridge=c.bridge, ctx=ctx) deck_nodes = set(flatten(bridge_nodes[0], Node)) pier_nodes = set(flatten(bridge_nodes[1], Node)) all_nodes = set(flatten(bridge_nodes, Node)) # For each combination of parameters plot the nodes. for nodes_name, nodes in [ ("all", all_nodes), ("deck", deck_nodes), ("pier", pier_nodes), ]: node_scatter_3d(nodes=nodes) plt.title(f"Nodes of {c.bridge.name}") plt.savefig( c.get_image_path( f"geometry/nodes-{ctx_name}", safe_str(f"{nodes_name}") + ".pdf", )) plt.close()
def test_to_wheel_track_loads(): # As Truck 1 enters the bridge, total load is less than Truck 1. enter_times = np.linspace(entering_time, entered_time - 0.001, 100) for time in enter_times: loads = truck1.to_wheel_track_loads(c=c, time=time) flat_loads = flatten(loads, PointLoad) total_kn = sum(map(lambda l: l.load, flat_loads)) assert total_kn < truck1.total_kn() # As Truck 1 is fully on the bridge, total load equals that of Truck 1. on_times = np.linspace(entered_time, leaving_time, 100) truck_front_x = np.arange(8, 102) more_times = np.array( [truck1.time_at(x=x, bridge=c.bridge) for x in truck_front_x]) on_times = np.concatenate((on_times, more_times)) for time in on_times: loads = truck1.to_wheel_track_loads(c=c, time=time) flat_loads = flatten(loads, PointLoad) total_kn = sum(map(lambda l: l.load, flat_loads)) assert np.isclose(total_kn, truck1.total_kn()) # As Truck 1 is leaving the bridge, total load is less than Truck 1. leave_times = np.linspace(leaving_time + 0.001, left_time, 100) for time in leave_times: loads = truck1.to_wheel_track_loads(c=c, time=time) flat_loads = flatten(loads, PointLoad) total_kn = sum(map(lambda l: l.load, flat_loads)) assert total_kn < truck1.total_kn()
def test_loads_to_traffic_array(): # First with one point load per wheel. wagen1_loads = [ flatten(truck1.to_point_load_pw(time=time, bridge=c.bridge), PointLoad) for time in np.linspace(entered_time, leaving_time, 1000) ] for row in loads_to_traffic_array(c=c, loads=wagen1_loads): assert sum(row) == truck1.total_kn() # Then with point loads based on wheel tracks. wagen1_loads = [ flatten(truck1.to_wheel_track_loads(c=c, time=time), PointLoad) for time in np.linspace(entered_time, leaving_time, 1000) ] for row in loads_to_traffic_array(c=c, loads=wagen1_loads): assert np.isclose(sum(row), truck1.total_kn())
def to_point_load_pw( self, time: float, bridge: Bridge, list: bool = False ) -> Union[List[Tuple[PointLoad, PointLoad]], List[PointLoad]]: """A tuple of point load per axle, one point load per wheel.""" z0, z1 = self.wheel_tracks_zs(bridge=bridge, meters=True) assert z0 < z1 kn_per_axle = self.kn_per_axle() result = [] # For each axle. for x_i, x in enumerate(self.xs_at(time=time, bridge=bridge)): # Skip axle if not on the bridge. if (x < bridge.x_min and not np.isclose(x, bridge.x_min)) or ( x > bridge.x_max and not np.isclose(x, bridge.x_max) ): continue # Two wheel load intensities. kn_wheel = kn_per_axle[x_i] / 2 result.append( ( PointLoad(x=x, z=z0, load=kn_wheel), PointLoad(x=x, z=z1, load=kn_wheel), ) ) if list: return flatten(result, PointLoad) return result
def compare_load_positions(c: Config): """Compare load positions (normal vs. buckets).""" c.il_num_loads = 10 num_times = 1000 # Wagen 1 from the experimental campaign. point = Point(x=c.bridge.x_max / 2, y=0, z=-8.4) end_time = uni_axle_vehicle.time_left_bridge(bridge=c.bridge) vehicle_times = list(np.linspace(0, end_time, num_times)) plt.portrait() pw_loads = [ flatten(uni_axle_vehicle.to_point_load_pw(time=time, bridge=c.bridge), PointLoad) for time in vehicle_times ] pw_load_xs = [[c.bridge.x(l.x_frac) for l in pw_loads[time_ind]] for time_ind in range(len(pw_loads))] plt.subplot(3, 1, 1) # for l in pw_load_xs: # print(l) plt.plot([l[0] for l in pw_load_xs]) plt.plot([l[1] for l in pw_load_xs]) wt_loads = [ flatten(uni_axle_vehicle.to_wheel_track_loads(c=c, time=time), PointLoad) for time in vehicle_times ] wt_load_xs = [[c.bridge.x(l.x_frac) for l in wt_loads[time_ind]] for time_ind in range(len(wt_loads))] plt.subplot(3, 1, 2) plt.scatter(vehicle_times, [l[0] for l in wt_load_xs], label="0") plt.scatter(vehicle_times, [l[1] for l in wt_load_xs], label="1") plt.legend() wt_load_kn = [[l.kn for l in wt_loads[time_ind]] for time_ind in range(len(wt_loads))] plt.subplot(3, 1, 3) for l in wt_load_kn: print(l) plt.scatter(vehicle_times, [l[0] for l in wt_load_kn], label="0") plt.scatter(vehicle_times, [l[1] for l in wt_load_kn], label="1") plt.legend() plt.tight_layout() plt.savefig(c.get_image_path("verification", "compare-load-positions.pdf")) plt.close()
def make_shell_properties_3d(original_c: Config): """Make plots of the shells in 3D, coloured by material property.""" # For each scenarios scenario build the model and extract the shells. for damage_scenario in healthy_and_cracked_scenarios: c, sim_params = damage_scenario.use(original_c, SimParams([])) for ctx, ctx_name in [ (BuildContext(add_loads=[Point(x=85, y=0, z=0)]), "refined"), (None, "unrefined"), ]: bridge_shells = get_bridge_shells(bridge=c.bridge, ctx=ctx) deck_shells = flatten(bridge_shells[0], Shell) pier_shells = flatten(bridge_shells[1], Shell) all_shells = flatten(bridge_shells, Shell) # For each combination of parameters plot the shells. for shells_name, shells in [ ("pier", pier_shells), ("all", all_shells), ("deck", deck_shells), ]: for outline, label in itertools.product([True, False], [True, False]): for prop_name, prop_units, prop_f in [ ("Thickness", "m", lambda s: s.thickness), ("Density", "kg/m", lambda s: s.density), ("Poisson's ratio", "m/m", lambda s: s.poissons), ("Young's modulus", "MPa", lambda s: s.youngs), ]: for cmap in [default_cmap, get_cmap("tab10")]: shell_properties_3d( shells=shells, prop_units=prop_units, prop_f=prop_f, cmap=cmap, outline=outline, label=label, colorbar=not label, ) plt.title(f"{prop_name} of {c.bridge.name}") plt.savefig( c.get_image_path( f"geometry/shells-{ctx_name}-3d", safe_str( f"{shells_name}-{prop_name}-outline-{outline}-{cmap.name}" ) + ".pdf", )) plt.close()
def test_to_point_load_pw(): # As Truck 1 enters the bridge. wagen1_times = np.linspace(entering_time, entered_time - 0.001, 100) for time in wagen1_times: loads = truck1.to_point_load_pw(time=time, bridge=c.bridge) flat_loads = flatten(loads, PointLoad) total_kn = sum(map(lambda l: l.load, flat_loads)) assert total_kn < truck1.total_kn() # As Truck 1 is fully on the bridge. wagen1_times = np.linspace(entered_time, leaving_time, 100) for time in wagen1_times: loads = truck1.to_point_load_pw(time=time, bridge=c.bridge) flat_loads = flatten(loads, PointLoad) total_kn = sum(map(lambda l: l.load, flat_loads)) assert total_kn == truck1.total_kn() # As Truck 1 is leaving the bridge. wagen1_times = np.linspace(leaving_time + 0.001, left_time, 100) for time in wagen1_times: loads = truck1.to_point_load_pw(time=time, bridge=c.bridge) flat_loads = flatten(loads, PointLoad) total_kn = sum(map(lambda l: l.load, flat_loads)) assert total_kn < truck1.total_kn()
def to_wheel_track_loads( self, c: "Config", time: float, flat: bool = False ) -> List[Tuple[List[PointLoad], List[PointLoad]]]: z0, z1 = self.wheel_tracks_zs(bridge=c.bridge, meters=True) assert z0 < z1 result = [] for axle_loads in self.to_wheel_track_loads_(c=c, time=time): left, right = [], [] left_loads, right_loads = axle_loads for load_x, load_kn in left_loads: left.append(PointLoad(x=load_x, z=z0, load=load_kn)) for load_x, load_kn in right_loads: right.append(PointLoad(x=load_x, z=z1, load=load_kn)) result.append((left, right)) if flat: return flatten(result, PointLoad) return result
def to_wheel_track_loads_( self, c: "Config", time: float, flat: bool = False, wheel_track_xs: Optional[List[float]] = None, ): """Load intensities and positions per axle, per wheel. "Bucketed" to fit onto wheel tracks. NOTE: In each tuple of two point loads, one tuple per wheel, each point load is for a unit load position in the wheel track. Each point load is weighted by the distance to the unit load. """ if wheel_track_xs is None: wheel_track_xs = c.bridge.wheel_track_xs(c) xs = self.xs_at(time=time, bridge=c.bridge) kns = self.kn_per_axle() result = [] assert len(xs) == len(kns) # For each axle. for x, kn in zip(xs, kns): # Skip axle if not on the bridge. if (x < c.bridge.x_min and not np.isclose(x, c.bridge.x_min)) or ( x > c.bridge.x_max and not np.isclose(x, c.bridge.x_max) ): continue left, right = [], [] for (load_x, load_frac) in self.to_wheel_track_xs( c=c, wheel_x=x, wheel_track_xs=wheel_track_xs, ): if load_frac > 0: bucket_kn = kn / 2 * load_frac left.append((load_x, bucket_kn)) right.append((load_x, bucket_kn)) result.append((left, right)) if flat: return flatten(result, PointLoad) return result
def responses_to_vehicles_d( c: Config, response_type: ResponseType, points: List[Point], mv_vehicles: List[Vehicle], times: List[float], binned: bool = True, damage_scenario: Scenario = HealthyScenario(), ): """Response vehicles via direct simulation (not using superposition). """ if not isinstance(damage_scenario, HealthyScenario): raise ValueError("Only HealthyDamage supported in direct simulation") if binned: loads = [[v.to_wheel_track_loads(c=c, time=time) for v in mv_vehicles] for time in times] else: print_w(f"Not using fractions of wheel track bins in simulation") loads = [[ v.to_point_load_pw(time=time, bridge=c.bridge) for v in mv_vehicles ] for time in times] loads = [flatten(vehicle_loads, PointLoad) for vehicle_loads in loads] print([len(load_) for load_ in loads]) print(loads[0]) print(loads[-1]) assert isinstance(loads, list) assert isinstance(loads[0], list) assert isinstance(loads[0][0], PointLoad) return responses_to_loads_d( c=c, response_type=response_type, points=points, loads=loads, damage_scenario=damage_scenario, )
def top_view_plot(c: Config, max_time: int, skip: int, damage_scenario): response_type = ResponseType.YTranslation # Create the traffic. traffic_scenario = normal_traffic(c=c, lam=5, min_d=2) traffic_sequence, traffic, traffic_array = load_traffic( c=c, traffic_scenario=traffic_scenario, max_time=max_time, ) assert len(traffic) == traffic_array.shape[0] # Points on the deck to collect fem. deck_points = [ Point(x=x, y=0, z=z) for x in np.linspace( c.bridge.x_min, c.bridge.x_max, num=int(c.bridge.length * 2)) for z in np.linspace( c.bridge.z_min, c.bridge.z_max, num=int(c.bridge.width * 2)) # for x in np.linspace(c.bridge.x_min, c.bridge.x_max, num=30) # for z in np.linspace(c.bridge.z_min, c.bridge.z_max, num=10) ] point = Point(x=21, y=0, z=-8.4) # Point to plot deck_points.append(point) # Traffic array to fem array. responses_array = responses_to_traffic_array( c=c, traffic_array=traffic_array, damage_scenario=damage_scenario, points=deck_points, response_type=response_type, ) # Temperature effect July 1st. temps_2019 = temperature.load("holly-springs") temps_2019["temp"] = temperature.resize(temps_2019["temp"]) effect_2019 = temperature.effect( c=c, response_type=response_type, points=deck_points, temps=temps_2019["temp"], solar=temps_2019["solar"], len_per_hour=60, ).T # The effect is ordered by time series and then by points. (104910, 301) assert len(effect_2019) == len(temps_2019) july_2019_i, july_2019_j = temperature.from_to_indices( temps_2019, datetime.fromisoformat(f"2019-10-01T00:00"), datetime.fromisoformat(f"2019-10-01T23:59"), ) temp_effect = [] for i in range(len(deck_points)): temp_effect.append( temperature.apply( # Effect for July 1st, for the current point.. effect=effect_2019.T[i][july_2019_i:july_2019_j], # ..for the length of the time series. responses=responses_array, )) temp_effect = np.array(temp_effect) plt.subplot(2, 1, 1) plt.plot(effect_2019.T[-1]) plt.subplot(2, 1, 2) plt.plot(temp_effect[-1]) plt.show() # Determine response due to pier settlement. pd_response_at_point = 0 if isinstance(damage_scenario, PierDispDamage): pd_expt = list( DCMatrix.load(c=c, response_type=response_type, fem_runner=OSRunner(c))) for pier_displacement in damage_scenario.pier_disps: pd_sim_responses = pd_expt[pier_displacement.pier] pd_response_at_point += pd_sim_responses.at_deck( point, interp=False) * (pier_displacement.displacement / c.pd_unit_disp) # Resize fem if applicable to response type. resize_f, units = resize_units(response_type.units()) if resize_f is not None: responses_array = resize_f(responses_array) temp_effect = resize_f(temp_effect.T).T print(np.mean(temp_effect[-1])) pd_response_at_point = resize_f(pd_response_at_point) responses_w_temp = responses_array + temp_effect.T # Determine levels of the colourbar. amin, amax = np.amin(responses_array), np.amax(responses_array) # amin, amax = min(amin, -amax), max(-amin, amax) levels = np.linspace(amin, amax, 25) # All vehicles, for colour reference. all_vehicles = flatten(traffic, Vehicle) # Iterate through each time index and plot results. warmed_up_at = traffic_sequence[0][0].time_left_bridge(c.bridge) # Plot for each time step. for t_ind in range(len(responses_array))[::skip]: plt.landscape() # Plot the bridge top view. plt.subplot2grid((3, 1), (0, 0), rowspan=2) top_view_bridge(c.bridge, compass=False, lane_fill=False, piers=True) top_view_vehicles( bridge=c.bridge, mv_vehicles=flatten(traffic[t_ind], Vehicle), time=warmed_up_at + t_ind * c.sensor_hz, all_vehicles=all_vehicles, ) responses = Responses( response_type=response_type, responses=[(responses_array[t_ind][p_ind], deck_points[p_ind]) for p_ind in range(len(deck_points))], units=units, ) plot_contour_deck(c=c, responses=responses, levels=levels, mm_legend=False) plt.scatter( [point.x], [point.z], label=f"Sensor in bottom plot", marker="o", color="red", zorder=10, ) plt.legend(loc="upper right") plt.title( f"{response_type.name()} after {np.around(t_ind * c.sensor_hz, 4)} seconds" ) # Plot the fem at a point. plt.subplot2grid((3, 1), (2, 0)) time = t_ind * c.sensor_hz plt.axvline(x=time, color="black", label=f"Current time = {np.around(time, 4)} s") plt.plot( np.arange(len(responses_array)) * c.sensor_hz, responses_w_temp.T[-1], color="red", label="Total effect", ) if isinstance(damage_scenario, PierDispDamage): plt.plot( np.arange(len(responses_array)) * c.sensor_hz, np.ones(temp_effect[-1].shape) * pd_response_at_point, color="green", label="Pier settlement effect", ) plt.plot( np.arange(len(responses_array)) * c.sensor_hz, temp_effect[-1], color="blue", label="Temperature effect", ) plt.ylabel(f"{response_type.name()} ({responses.units})") plt.xlabel("Time (s)") plt.title(f"{response_type.name()} at sensor in top plot") plt.legend(loc="upper right", framealpha=1) # Finally save the image. name = f"{damage_scenario.name}-{response_type.name()}-{t_ind}" plt.tight_layout() plt.savefig(c.get_image_path("classify/top-view", f"{name}.pdf")) plt.savefig(c.get_image_path("classify/top-view/png", f"{name}.png")) plt.close()
def compare_responses(c: Config): """Compare fem to Truck 1, direct simulation and matmul.""" assert c.il_num_loads == 600 num_times = 50 close_times = 200 # Running time: # responses_to_vehicles_d: num_times * 8 # responses_to_vehicles_d: 4 * il_num_loads # responses_to_loads_m: 0 (4 * il_num_loads) # responses_to_loads_m: 0 (4 * il_num_loads) # Wagen 1 from the experimental campaign. point = Point(x=c.bridge.x_max - (c.bridge.length / 2), y=0, z=-8.4) end_time = wagen1.time_left_bridge(bridge=c.bridge) wagen1_times = list(np.linspace(0, end_time, num_times)) more_wagen1_times = list( np.linspace( wagen1.time_at(x=point.x - 2, bridge=c.bridge), wagen1.time_at(x=point.x + 2, bridge=c.bridge), close_times, )) wagen1_times = sorted(wagen1_times + more_wagen1_times) plt.portrait() # Start with fem from direct simulation. responses_not_binned = responses_to_vehicles_d( c=c, response_type=ResponseType.YTranslation, points=[point], mv_vehicles=[wagen1], times=wagen1_times, sim_runner=OSRunner(c), binned=False, ) plt.subplot(4, 1, 1) plt.title(f"{len(wagen1_times)} fem") plt.plot(wagen1_times, responses_not_binned) # Then fem from direct simulation with binning. c.shorten_paths = True responses_binned = responses_to_vehicles_d( c=c, response_type=ResponseType.YTranslation, points=[point], mv_vehicles=[wagen1], times=wagen1_times, sim_runner=OSRunner(c), binned=True, ) c.shorten_paths = False plt.subplot(4, 1, 2) plt.title(f"{len(wagen1_times)} fem (binned)") plt.plot(wagen1_times, responses_binned) xlim = plt.xlim() num_times = int(end_time / c.sensor_hz) wagen1_times = np.linspace(0, end_time, num_times) # Then from 'TrafficArray' we get fem, without binning. wagen1_loads = [ flatten(wagen1.to_point_load_pw(time=time, bridge=c.bridge), PointLoad) for time in wagen1_times ] responses_ulm = responses_to_traffic_array( c=c, traffic_array=loads_to_traffic_array(c=c, loads=wagen1_loads), response_type=ResponseType.YTranslation, damage_scenario=healthy_scenario, points=[point], sim_runner=OSRunner(c), ) plt.subplot(4, 1, 3) plt.title(f"{num_times} fem with ULS = {c.il_num_loads} traffic_array") plt.plot(wagen1_times, np.array(responses_ulm).reshape(-1, 1)) plt.xlim(xlim) # # Then from 'TrafficArray' we get fem, with binning. wagen1_loads = [ flatten(wagen1.to_wheel_track_loads(c=c, time=time), PointLoad) for time in wagen1_times ] responses_ulm_binned = responses_to_traffic_array( c=c, traffic_array=loads_to_traffic_array(c=c, loads=wagen1_loads), response_type=ResponseType.YTranslation, damage_scenario=healthy_scenario, points=[point], sim_runner=OSRunner(c), ) plt.subplot(4, 1, 4) plt.title( f"{num_times} fem from {c.il_num_loads} il_num_loads\ntraffic_array binned" ) plt.plot(wagen1_times, np.array(responses_ulm_binned).reshape(-1, 1)) plt.xlim(xlim) plt.tight_layout() plt.savefig( c.get_image_path("system-verification", "compare-time-series.pdf"))
def compare_axles(c: Config): """Compare fem between uniaxle vehicles and Truck 1.""" assert c.il_num_loads == 600 point = Point(x=c.bridge.x_max / 2, y=0, z=-8.4) end_time = wagen1.time_left_bridge(bridge=c.bridge) num_times = int(end_time / c.sensor_hz) wagen1_times = np.linspace(0, end_time, num_times) plt.portrait() wagen1_loads = [ flatten(wagen1.to_wheel_track_loads(c=c, time=time), PointLoad) for time in wagen1_times ] responses_ulm = responses_to_traffic_array( c=c, traffic_array=loads_to_traffic_array(c=c, loads=wagen1_loads), response_type=ResponseType.YTranslation, damage_scenario=healthy_scenario, points=[point], sim_runner=OSRunner(c), ) plt.subplot(3, 1, 1) plt.title( f"{num_times} fem with ULS = {c.il_num_loads} (Wagen 1 (4 axles))") plt.plot(wagen1_times, np.array(responses_ulm).reshape(-1, 1)) bi_axle_loads = [ flatten(bi_axle_vehicle.to_wheel_track_loads(c=c, time=time), PointLoad) for time in wagen1_times ] responses_ulm = responses_to_traffic_array( c=c, traffic_array=loads_to_traffic_array(c=c, loads=bi_axle_loads), response_type=ResponseType.YTranslation, damage_scenario=healthy_scenario, points=[point], sim_runner=OSRunner(c), ) plt.subplot(3, 1, 2) plt.title(f"{num_times} fem with ULS = {c.il_num_loads} (2 axles)") plt.plot(wagen1_times, np.array(responses_ulm).reshape(-1, 1)) uni_axle_loads = [ flatten(uni_axle_vehicle.to_wheel_track_loads(c=c, time=time), PointLoad) for time in wagen1_times ] responses_ulm = responses_to_traffic_array( c=c, traffic_array=loads_to_traffic_array(c=c, loads=uni_axle_loads), response_type=ResponseType.YTranslation, damage_scenario=healthy_scenario, points=[point], sim_runner=OSRunner(c), ) plt.subplot(3, 1, 3) plt.title(f"{num_times} fem with ULS = {c.il_num_loads} (1 axle)") plt.plot(wagen1_times, np.array(responses_ulm).reshape(-1, 1)) plt.tight_layout() plt.savefig(c.get_image_path("system-verification", "compare-axles.pdf"))
def make_shell_properties_top_view( c: Config, shells_name_: str, prop_name_: str, refined_: bool, outline: bool, lanes: bool, ): """Make plots of the shells in top view, coloured by material property.""" original_c = c # For each scenarios scenario build the model and extract the shells. for damage_scenario, damage_name in zip(healthy_and_cracked_scenarios, [None, "cracked"]): c, sim_params = damage_scenario.use(original_c) for ctx, ctx_name, refined, in [ ( BuildContext( add_loads=[Point(x=85, y=0, z=0)], refinement_radii=[2, 1, 0.5], ), "refined", True, ), (None, "unrefined", False), ]: if refined != refined_: continue bridge_shells = get_bridge_shells(bridge=c.bridge, ctx=ctx) deck_shells = flatten(bridge_shells[0], Shell) pier_shells = flatten(bridge_shells[1], Shell) all_shells = pier_shells + deck_shells for shells_name, shells in [ ("piers", pier_shells), ("deck", deck_shells), ]: if shells_name != shells_name_: continue for prop_name, prop_units, prop_f in [ ("Mesh", "", None), ("Thickness", "m", lambda s: np.around(s.thickness, 3)), ("Density", "kg/m", lambda s: np.around(s.density, 3)), ("Poisson's ratio", "m/m", lambda s: s.poissons), ("Young's modulus", "MPa", lambda s: np.around(s.youngs, 1)), ]: if prop_name_ not in prop_name.lower(): continue for cmap in [parula_cmap, default_cmap]: def top_view(): top_view_bridge( bridge=c.bridge, abutments=True, piers=True, lanes=lanes, compass=prop_f is not None, ) top_view() shell_properties_top_view( shells=shells, prop_f=prop_f, prop_units=prop_units, cmap=cmap, colorbar=prop_f is not None, # label=prop_f is not None, outline=outline, ) top_view() damage_str = "" if damage_name is None else f" ({damage_name})" plt.title( f"{prop_name} of bridge 705's {shells_name}{damage_str}" ) plt.savefig( c.get_image_path( f"geometry/{shells_name}-shells-{ctx_name}-top-view", safe_str( f"{prop_name}-{cmap.name}-outline-{outline}-lanes-{lanes}" ) + ".pdf", )) plt.close() if prop_f is None: break
def sum_loads(loads): """Sum of the load intensity (kn) of all given loads.""" return sum(map(lambda l: l.load, flatten(loads, PointLoad)))
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 truck_1_time_series(c: Config): """Time series of 3 sensors to Truck 1's movement.""" side_s = 7 side = int(side_s * (1 / c.sensor_hz)) assert wagen1.x_at(time=0, bridge=c.bridge) == 0 # Get times and loads for Truck 1. end_time = wagen1.time_left_bridge(c.bridge) wagen1_times = np.linspace(-end_time, end_time * 2, int((end_time * 3) / c.sensor_hz)) print_i("Calculating Truck 1 loads") wagen1_loads = [ flatten(wagen1.to_wheel_track_loads(c=c, time=time), PointLoad) # flatten(wagen1.to_point_load_pw(time=time, bridge=c.bridge), PointLoad) for time in wagen1_times ] print_i("Calculated Truck 1 loads") def set_labels(ylabel: str, xlabel: str): for i, y, x in [ (1, True, False), (2, False, False), (3, True, False), (4, False, False), (5, True, True), (6, False, True), ]: plt.subplot(3, 2, i) ax = plt.gca() if y: plt.ylabel(ylabel) else: ax.axes.yaxis.set_ticklabels([]) if x: plt.xlabel(xlabel) ax.axes.xaxis.set_ticklabels([]) ymin, ymax = np.inf, -np.inf for i in range(1, 6 + 1): plt.subplot(3, 2, i) ymin = min(ymin, plt.ylim()[0]) ymax = max(ymax, plt.ylim()[1]) for i in range(1, 6 + 1): plt.subplot(3, 2, i) plt.ylim((ymin, ymax)) ################ # Vert. trans. # ################ plt.portrait() # Find points of each sensor. displa_labels = ["U13", "U26", "U29"] displa_points = [ Point(x=sensor_x, y=0, z=sensor_z) for sensor_x, sensor_z in [displa_sensor_xz(displa_label) for displa_label in displa_labels] ] # Ensure points and truck are on the same lane. assert all(p.z < 0 for p in displa_points) # Results from simulation. responses_truck1 = responses_to_traffic_array( c=c, traffic_array=loads_to_traffic_array(c=c, loads=wagen1_loads), response_type=ResponseType.YTranslation, damage_scenario=healthy_scenario, points=displa_points, ).T for s_i, sensor_responses in enumerate(responses_truck1): plt.subplot(len(displa_points), 2, (s_i * 2) + 1) # Find the center of the plot, minimum point in the data. data_center = 0 for i in range(len(sensor_responses)): if sensor_responses[i] < sensor_responses[data_center]: data_center = i # sensor_responses = add_displa_noise(sensor_responses) * 1000 sensor_responses = sensor_responses * 1000 plt.plot(sensor_responses[data_center - side:data_center + side]) plt.title(f"{displa_labels[s_i]} in simulation") # Results from experiment. side = int(side / ((1 / c.sensor_hz) / 100)) print_i(f"{side} points each side of center") for s_i, displa_label in enumerate(displa_labels): plt.subplot(len(displa_points), 2, (s_i * 2) + 2) with open(f"validation/experiment/D1a-{displa_label}.txt") as f: data = list(map(float, f.readlines())) side_expt = int(side_s * (len(data) / 240)) # Find the center of the plot, minimum point in first 15000 points. data_center = 0 for i in range(15000): if data[i] < data[data_center]: data_center = i plt.plot(data[data_center - side_expt:data_center + side_expt]) plt.title(f"{displa_label} in dynamic test") set_labels("Y translation (mm)", "Time") plt.tight_layout() plt.savefig( c.get_image_path("validation/truck-1", "time-series-vert-trans.pdf")) plt.close() ########## # Strain # ########## plt.portrait() # Find points of each sensor. strain_labels = ["T1", "T10", "T11"] strain_points = [ Point(x=sensor_x, y=0, z=sensor_z) for sensor_x, sensor_z in [strain_sensor_xz(strain_label) for strain_label in strain_labels] ] # Results from simulation. responses_truck1 = responses_to_traffic_array( c=c, traffic_array=loads_to_traffic_array(c=c, loads=wagen1_loads), response_type=ResponseType.Strain, damage_scenario=healthy_scenario, points=strain_points, ).T for s_i, sensor_responses in enumerate(responses_truck1): plt.subplot(len(strain_points), 2, (s_i * 2) + 1) # Find the center of the plot, minimum point in the data. data_center = 0 for i in range(len(sensor_responses)): if sensor_responses[i] > sensor_responses[data_center]: data_center = i # sensor_responses = add_strain_noise(sensor_responses) # plt.plot(sensor_responses) plt.plot(sensor_responses[data_center - side:data_center + side]) # plt.plot(sensor_responses[data_center - side : data_center + side]) plt.title(f"{strain_labels[s_i]} in simulation") # Results from experiment. print_i(f"{side} points each side of center") for s_i, strain_label in enumerate(strain_labels): plt.subplot(len(strain_points), 2, (s_i * 2) + 2) with open(f"validation/experiment/D1a-{strain_label}.txt") as f: data = list(map(float, f.readlines())) side_expt = int(side_s * (len(data) / 240)) # Find the center of the plot, minimum point in first 15000 points. data_center = 0 for i in range(15000): if data[i] < data[data_center]: data_center = i # plt.plot(data) plt.plot(data[data_center - side_expt:data_center + side_expt]) # plt.plot(data[data_center - side_expt : data_center + side_expt]) plt.title(f"{strain_label} in dynamic test") set_labels("Microstrain", "Time") plt.tight_layout() plt.savefig( c.get_image_path("validation/truck-1", "time-series-strain.pdf")) plt.close()