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 id_str(self, msl: bool = True, data_id: bool = True): """Name with accuracy information. Args: msl: bool, include msl in identifier. data_id: bool, include data_id in identifier. """ acc_str = f"-{self.msl}" if msl else "" data_id_str = f"-{self.data_id}" if data_id else "" return safe_str(f"{self.name}{acc_str}{data_id_str}")
def sim_model_path( self, sim_params: SimParams, ext: str, append: str = "", dirname: Optional[str] = None, ) -> str: """Deterministic path for a FE model file. :param sim_params: simulation parameters. :param ext: extension of the output file without the dot. :param dirname: directory name of output file. Defaults to FEMRunner.name. :param append: append to the filename (before the extension). :return: path for the output file. """ param_str = sim_params.id_str() append = append if len(append) == 0 else f"-{append}" filename = f"{self.c.bridge.id_str()}-params={param_str}{append}" if dirname is None: dirname = self.name dirname = safe_str(dirname) return shorten_path( self.c, safe_str(self.c.get_data_path(dirname, filename)) + f".{ext}")
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 uls_contour_plot(c: Config, x_i: int, z_i: int, response_type: ResponseType): 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})") plt.landscape() plt.subplot(2, 1, 1) healthy = list( ILMatrix.load_wheel_track( c=c, response_type=response_type, fem_runner=OSRunner(c), load_z_frac=c.bridge.z_frac(wheel_z), run_only=False, indices=[x_i], ))[0].resize() top_view_bridge(bridge=c.bridge, compass=False, abutments=True, piers=True) plot_contour_deck(c=c, responses=healthy, sci_format=True, decimals=6) plt.title("Healthy") c = transverse_crack().use(c)[0] cracked = list( ILMatrix.load_wheel_track( c=c, response_type=response_type, fem_runner=OSRunner(c), load_z_frac=c.bridge.z_frac(wheel_z), run_only=False, indices=[x_i], ))[0].resize() plt.subplot(2, 1, 2) top_view_bridge(bridge=c.bridge, compass=False, abutments=True, piers=True) plot_contour_deck(c=c, responses=cracked, sci_format=True, decimals=6) plt.title("Cracked") plt.tight_layout() plt.savefig( c.get_image_path( "verification", safe_str( f"uls-contour-x-{wheel_x}-z-{wheel_z}-{response_type.name()}") + ".pdf", ))
def make_normal_mv_load_animations(c: Config, per_axle: bool = False): """Make animations of a pload moving across a bridge.""" plt.close() mv_load = MovingLoad.from_vehicle(x_frac=0, vehicle=sample_vehicle(c), lane=0) per_axle_str = f"-peraxle" if per_axle else "" for response_type in ResponseType: animate_mv_load( c, mv_load, response_type, OSRunner(c), per_axle=per_axle, save=safe_str( c.image_path(f"animations/{c.bridge.name}-{OSRunner(c).name}" + f"-{response_type.name()}{per_axle_str}" + f"-load-{mv_load.str_id()}")).lower() + ".mp4", )
def build_with_refinement(refinement_radii): sim_params = SimParams( response_types=[response_type], ploads=[pload], refinement_radii=refinement_radii, ) # Build and save the model file. if build: build_model_3d( c=min_config, expt_params=ExptParams([sim_params]), os_runner=OSRunner(min_config), ) # Load and plot fem. if plot: sim_responses = load_fem_responses( c=min_config, sim_runner=OSRunner(min_config), response_type=response_type, sim_params=sim_params, run=True, ) for scatter in [True, False]: top_view_bridge(min_config.bridge, abutments=True, piers=True, lanes=True) plot_contour_deck( c=min_config, responses=sim_responses, scatter=scatter, levels=100, ) plt.title(f"{refinement_radii}") plt.savefig( min_config.get_image_path( "debugging", safe_str( f"{response_type.name()}-{refinement_radii}-scatter-{scatter}" ) + ".pdf", )) plt.close()
def id_str(self): """String representing the simulation parameters. NOTE: Response types are not included in the ID string because it is currently assumed that a simulation saves all output files. """ load_str = "" for pier_settlement in self.pier_settlement: load_str += pier_settlement.id_str() if self.axial_delta_temp is not None: load_str += f"temp-axial-{self.axial_delta_temp}" if self.moment_delta_temp is not None: load_str += f"temp-moment-{self.moment_delta_temp}" if len(self.ploads) > 0: pl_str = ",".join(pl.id_str() for pl in self.ploads) load_str += f"[{pl_str}]" if len(self.pier_settlement) > 0: load_str += ",".join(ps.id_str() for ps in self.pier_settlement) return safe_str(load_str)
def make_event_plots(c: Config): """Make plots of events in different scenarios.""" from plot.features import plot_events_from_traffic fem_runner = OSRunner(c) bridge_scenario = BridgeScenarioNormal() max_time, time_step, lam, min_d = 20, 0.01, 5, 2 c.time_step = time_step sensor_zs = [lane.z_center() for lane in c.bridge.lanes] points = [Point(x=35, y=0, z=z) for z in sensor_zs] for response_type in [ResponseType.YTranslation]: for traffic_scenario in [ normal_traffic(c=c, lam=lam, min_d=min_d), heavy_traffic_1(c=c, lam=lam, min_d=min_d, prob_heavy=0.01), ]: # Generate traffic under a scenario. traffic, start_index = traffic_scenario.traffic( bridge=c.bridge, max_time=max_time, time_step=time_step) traffic = traffic[start_index:] # Plot events from traffic. plot_events_from_traffic( c=c, bridge=c.bridge, bridge_scenario=bridge_scenario, traffic_name=traffic_scenario.name, traffic=traffic, start_time=start_index * time_step, time_step=time_step, response_type=ResponseType.YTranslation, points=points, fem_runner=OSRunner(c), save=c.get_image_path( "events", safe_str( f"bs-{bridge_scenario.name}-ts-{traffic_scenario.name}" f"-rt-{response_type.name()}"), ), )
def transverse_crack( length: float = 0.5, width: Optional[float] = None, at_x: Optional[float] = None, at_z: Optional[float] = None, ) -> CrackedScenario: """A bridge with a transverse crack.""" def crack_area(bridge: Bridge) -> CrackArea: nonlocal width nonlocal at_x nonlocal at_z if width is None: width = bridge.width / 2 if at_x is None: at_x = bridge.x_min + (bridge.length / 2) if at_z is None: at_z = bridge.z_min return at_x, at_z, at_x + length, at_z + width return CrackedScenario( name=safe_str(f"transverse-{length}-{width}-{at_x}-{at_z}"), crack_area=crack_area, )
def crack_time_series( c: Config, traffic_array, traffic_array_mins: float, sensor: Point, crack_frac: float, damage, temps: List[float], solar: List[float], ): """Time series of sensor fem, vertical translation and strain XXB. Returns a NumPy array of dimensions (2 x len(traffic_array)). Args: c: Config, global configuration object. traffic_array: TrafficArray, traffic flowing over the bridge. traffic_array_mins: float, minutes of the the traffic flow. sensor: Point, point at which to collect fem. crack_frac: float, fraction of time series where crack occurs. damage: DamageScenario, scenarios that occurs at crack_frac. temps: List[float], list of air temperature, per temperature minute. solar: List[float], list of solar radiance, per temperature minute. """ assert 0 <= crack_frac <= 1 response_types = [ResponseType.YTranslation, ResponseType.Strain] half_i = int(len(traffic_array) * crack_frac) traffic_array_0, traffic_array_1 = traffic_array[:half_i], traffic_array[ half_i:] assert len(traffic_array_0) + len(traffic_array_1) == len(traffic_array) half_t = int(len(temps) * crack_frac) assert len(temps) == len(solar) # Get the effect of temperature for both response types and damages. # In each case we have the full days worth of temperature fem. temp_effect = [] for response_type in response_types: temp_effect_damages = [] for di, ds in enumerate([HealthyDamage(), damage]): bots_tops, new_temp_effect = temperature.effect( c=ds.use(c)[0], response_type=response_type, points=[sensor], # One hour temperature data per minute of traffic data. len_per_hour=int(len(traffic_array) / traffic_array_mins) if di == 0 else None, temps=temps if di == 0 else None, solar=solar if di == 0 else None, temps_bt=bots_tops.T[int(len(bots_tops.T) / 2):].T if di == 1 else None, ret_temps_bt=True, ) bots_tops = np.array(bots_tops) temp_effect_damages.append( new_temp_effect[0] if di == 1 else new_temp_effect[0][:int(len(new_temp_effect[0]) / 2)]) temp_effect.append(np.concatenate(temp_effect_damages)) print(f"len(temps) = {len(temps)}") print(f"len_per_hour = {int(len(traffic_array) / traffic_array_mins)}") print(f"Temperature shape = {temp_effect[-1].shape}") plt.plot(temp_effect[-1]) plt.savefig( c.get_image_path("crack", safe_str(f"save-temps-{response_type}.pdf"))) plt.close() responses = [] for ri, rt in enumerate(response_types): responses_healthy_cracked = [] for ds, ta in [(HealthyDamage(), traffic_array_0), (damage, traffic_array_1)]: print( f"Sections in scenarios scenario = {len(ds.use(c)[0].bridge.sections)}" ) responses_healthy_cracked.append( responses_to_traffic_array( c=c, traffic_array=ta, response_type=rt, damage_scenario=ds, points=[sensor], ).T[0]) # Responses from a single point. responses.append(np.concatenate(responses_healthy_cracked)) print(f"shape fem without temp = {responses[-1].shape}") print(f"shape of temp effect = {temp_effect[ri].shape}") if rt == ResponseType.Strain: responses[ri] = resize_units("")[0](responses[ri]) responses[ri] += temperature.apply(temp_effect[ri], responses[ri]) responses = np.array(responses) print(f"Responses shape = {responses.shape}") return responses
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 _traffic_name(c: Config, traffic_scenario: TrafficScenario, max_time: float): return safe_str( f"{traffic_scenario.name} {c.il_num_loads} {max_time} {c.sensor_hz}" )
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 wagen_1_contour_plot( c: Config, x: int, crack_x: float, response_type: ResponseType, scatter: bool, run: bool, length: float, outline: bool, wheels: bool, temp: bool, ): original_c = c LOADS = False temp_bottom, temp_top = [17, 25] time = wagen1.time_at(x=x, bridge=c.bridge) def plot_wheels(): if wheels: wagen1.plot_wheels(c=c, time=time, label="Truck 1 wheels", zorder=100) center = c.bridge.x_max / 2 min_x, max_x = center - 20, center + 20 min_z, max_z = c.bridge.z_min, c.bridge.z_max def zoom_in(): plt.ylim(min_z, max_z) plt.xlim(min_x, max_x) loads = wagen1.to_wheel_track_loads(c=c, time=time, flat=True) crack_f = lambda: transverse_crack(length=length, at_x=crack_x) c = healthy_damage_w_transverse_crack_nodes(crack_f).use(original_c)[0] deck_shells = get_bridge_shells(c.bridge)[0] healthy_responses = load_fem_responses( c=c, sim_params=SimParams(ploads=loads), response_type=response_type, sim_runner=OSRunner(c), run=run, ).at_shells(deck_shells) # Convert fem to one per shell. if response_type in [ResponseType.Strain, ResponseType.StrainZZB]: # Resize by E-6 from microstrain to strain to match temperature units. healthy_responses = healthy_responses.resize() before_temp = healthy_responses.at_deck(Point(x=51, z=-8.4), interp=False) if temp: healthy_deck_points = healthy_responses.deck_points() # Point of fem. temp_effect = temperature.effect( c=c, response_type=response_type, points=healthy_deck_points, temps_bt=([temp_bottom], [temp_top]), ).T[0] # Temperature effect at existing response points. healthy_responses = healthy_responses.add(temp_effect, healthy_deck_points) after_temp = healthy_responses.at_deck(Point(x=51, z=-8.4), interp=False) print_i(f"Healthy, before/after = {before_temp}, {after_temp}") if response_type in [ResponseType.Strain, ResponseType.StrainZZB]: healthy_responses = healthy_responses.map(lambda x: x * 1e6) else: healthy_responses = healthy_responses.resize() # Responses in cracked scenario. c = crack_f().use(original_c)[0] crack_responses = load_fem_responses( c=c, sim_params=SimParams(ploads=loads), response_type=response_type, sim_runner=OSRunner(c), run=run, ).at_shells(deck_shells) if response_type in [ResponseType.Strain, ResponseType.StrainZZB]: # Resize by E-6 from microstrain to strain to match temperature units. crack_responses = crack_responses.resize() before_temp = crack_responses.at_deck(Point(x=51, z=-8.4), interp=False) if temp: crack_deck_points = crack_responses.deck_points() # Point of fem. temp_effect = temperature.effect( c=c, response_type=response_type, points=healthy_deck_points, temps_bt=([temp_bottom], [temp_top]), ).T[0] # Temperature effect at existing response points. crack_responses = crack_responses.add(temp_effect, healthy_deck_points) after_temp = crack_responses.at_deck(Point(x=51, z=-8.4), interp=False) print_i(f"Crack, before/after = {before_temp}, {after_temp}") if response_type in [ResponseType.Strain, ResponseType.StrainZZB]: crack_responses = crack_responses.map(lambda x: x * 1e6) else: crack_responses = crack_responses.resize() # Limit to points in crack zone. without_cm = 35 print(f"Avoid {without_cm} cm around crack zone") _without_crack_zone = crack_f().without(c.bridge, without_cm / 100) without_crack_zone = lambda p: not _without_crack_zone(p) if response_type in [ResponseType.Strain, ResponseType.StrainZZB]: healthy_responses = healthy_responses.without(without_crack_zone) crack_responses = crack_responses.without(without_crack_zone) # Norm calculation. vmin = min(healthy_responses.values()) vmax = max(healthy_responses.values()) vmin = min(vmin, min(crack_responses.values())) vmax = max(vmax, max(crack_responses.values())) norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax) print(f"Norm min/max = {vmin}, {vmax}") plt.portrait() plt.subplot(3, 1, 1) plot_contour_deck( c=c, responses=healthy_responses, ploads=loads if LOADS else [], scatter=scatter, norm=norm, decimals=2, ) c_x_start, c_z_start, c_x_end, c_z_end = list( map(round_m, crack_f().crack_area(c.bridge))) def plot_outline(label="Crack zone"): if outline: plt.gca().add_patch( mpl.patches.Rectangle( (c_x_start, c_z_start), c_x_end - c_x_start, c_z_end - c_z_start, fill=not scatter, edgecolor="black", facecolor="white", alpha=1, label=label, )) top_view_bridge(bridge=c.bridge, compass=False, abutments=True, piers=True) plot_outline(label="Responses not considered") plot_wheels() zoom_in() def legend(): plt.legend( loc="upper right", borderpad=0.2, labelspacing=0.2, borderaxespad=0, handletextpad=0.2, columnspacing=0.2, ) legend() plt.title(f"Healthy bridge") plt.xlabel("") plt.tick_params(bottom=False, labelbottom=False) plt.subplot(3, 1, 2) plot_contour_deck( c=c, responses=crack_responses, ploads=loads if LOADS else [], scatter=scatter, norm=norm, decimals=2, ) top_view_bridge(bridge=c.bridge, compass=False, abutments=True, piers=True) plot_outline() plot_wheels() zoom_in() legend() plt.title(f"Cracked bridge") plt.xlabel("") plt.tick_params(bottom=False, labelbottom=False) plt.subplot(3, 1, 3) responses = [] for x in healthy_responses.deck_xs: for z in healthy_responses.zs[x][0]: responses.append(( bridge_sim.sim.responses.responses[0][x][0][z] - crack_responses.at_deck(Point(x=x, z=z), interp=False), Point(x=x, z=z), )) # try: # fem.append(( # healthy_responses.fem[0][x][0][z] # - crack_responses.fem[0][x][0][z], # Point(x=x, z=z) # )) # except KeyError: # pass # diff_responses = responses = Responses( response_type=response_type, responses=responses, units=healthy_responses.units, ) plot_contour_deck( c=c, responses=diff_responses, ploads=loads if LOADS else [], cmap=mpl.cm.get_cmap("PiYG"), scatter=scatter, decimals=2, ) print("********") print("********") print("********") grid_x, grid_z = 600, 200 grid_points = list( filter( lambda p: not without_crack_zone(p), [ Point(x=x, y=0, z=z) for x in np.linspace(c.bridge.x_min, c.bridge.x_max, grid_x) for z in np.linspace(c.bridge.z_min, c.bridge.z_max, grid_z) ], )) print(f"Amount grid points = {len(grid_points)}") grid_x_len = c.bridge.length / grid_x grid_z_len = c.bridge.width / grid_z grid_area = grid_x_len * grid_z_len print(f"Grid area = {grid_area}") print("Interpolating diff fem") interp_diff_responses = diff_responses.at_decks(grid_points) count_interp = len(interp_diff_responses) interp_diff_responses = interp_diff_responses[~np. isnan(interp_diff_responses)] print( f"Removed {count_interp - len(interp_diff_responses)} of {count_interp} fem, remaining = {len(interp_diff_responses)}" ) print("Finished interpolating diff fem") count_min, count_max = 0, 0 d_min, d_max = min(diff_responses.values()), max(diff_responses.values()) print(f"diff min, max = {d_min}, {d_max}") d_min08, d_max08 = d_min * 0.8, d_max * 0.8 for interp_r in interp_diff_responses: if interp_r < d_min08: count_min += 1 if interp_r > d_max08: count_max += 1 print(f"Count = {count_min}, {count_max}") save_path = original_c.get_image_path( "verification", safe_str( f"truck1-contour-x-{x}{crack_x}{length}-{response_type.name()}-{temp}" ), ) with open(save_path + ".txt", "w") as f: f.write(f"{count_min}, {count_max}\n") f.write(f"{count_min * grid_area}, {count_max * grid_area}") print(f"Wrote results to {save_path}.txt") top_view_bridge(bridge=c.bridge, compass=False, abutments=True, piers=True) plot_outline() plot_wheels() zoom_in() legend() temp_str = f"\nT_bot = {temp_bottom} °C, T_top = {temp_top} °C" if temp else "" plt.title(f"Difference of healthy & cracked bridge") rt_name = (f"Microstrain {response_type.ss_direction()}" if response_type in [ResponseType.Strain, ResponseType.StrainZZB ] else response_type.name()) plt.suptitle(f"{rt_name}: Truck 1 on healthy & cracked bridge{temp_str}") plt.tight_layout(rect=[0, 0.03, 1, 0.93 if temp else 0.95]) plt.savefig(save_path + ".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 id_str(self): return safe_str(f"{np.around(self.settlement, 3)}-{self.pier}")
def id_str(self): """String uniquely representing this point load.""" return safe_str( f"({np.around(self.x, DIST_DECIMALS)}, {np.around(self.z, DIST_DECIMALS)}, {np.around(self.load, DIST_DECIMALS)})" )
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()