예제 #1
0
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()
예제 #2
0
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()
예제 #3
0
def effect(
    c: Config,
    response_type: ResponseType,
    points: List[Point],
    temps_bt: Optional[Tuple[List[float], List[float]]] = None,
    len_per_hour: Optional[int] = None,
    temps: Optional[List[float]] = None,
    solar: Optional[List[float]] = None,
    d: bool = False,
    ret_temps_bt: bool = False,
) -> List[List[float]]:
    """Temperature effect at given points for a number of given temperatures.

    The result is of shape (number of points, number of temperatures).

    NOTE: The 'ThermalDamage' method 'to_strain' multiplies the results by E-6,
        which is called by this function. So take note that the strain values
        are already multiplied by E-6 (from microstrain to strain), and do not
        need to be resized.

    Args:
        c: Config, global configuration object.
        response_type: ResponseType, type of sensor response to temp. effect.
        points: List[Point], points at which to calculate temperature effect.
        temps_bt: A 2-tuple of arrays, the first array is for the temperatures
            at the bottom of the bridge, and the second array is for the
            temperatures at the top of the bridge. If this argument is given
            then 'temps', 'solar', 'len_per_hour' must not be given.
        len_per_hour: Optional[int], if given then temps and solar must also be
            given. The temperature fem are interpolated such that there
            are 'len_per_hour' fem for every hour of temperature data. It
            is assumed the temperature data is one data point per minute.
        temps: Optional[List[float]], first see 'len_per_hour'. Air temperature
            data given at one data point per minute.
        solar: Optional[List[float]], first see 'len_per_hour'. Solar irradiance
            data given at one data point per minute, same as 'temps'.

    """
    if temps_bt is not None:
        if any(x is not None for x in [len_per_hour, temps, solar]):
            raise ValueError(
                "Must only pass 'temps_bt', or ('len_per_hour', 'temps' & 'solar')"
            )

    original_c = c
    # Unit effect from uniform temperature loading.
    unit_uniform = ThermalScenario(axial_delta_temp=c.unit_axial_delta_temp_c)
    c, sim_params = unit_uniform.use(original_c)
    uniform_responses = load_fem_responses(
        c=c,
        sim_runner=OSRunner,
        response_type=response_type,
        sim_params=sim_params,
    )
    # Unit effect from linear temperature loading.
    unit_linear = ThermalScenario(moment_delta_temp=c.unit_moment_delta_temp_c)
    c, sim_params = unit_linear.use(original_c)
    linear_responses = load_fem_responses(
        c=c,
        sim_runner=OSRunner,
        response_type=response_type,
        sim_params=sim_params,
    )
    print_i("Loaded unit uniform and linear temperature fem")

    # Convert uniform fem to correct type (thermal post-processing).
    if response_type in [
            ResponseType.Strain,
            ResponseType.StrainT,
            ResponseType.StrainZZB,
    ]:
        uniform_responses = unit_uniform.to_strain(
            c=c, sim_responses=uniform_responses)
    elif response_type == ResponseType.Stress:
        uniform_responses = unit_uniform.to_stress(
            c=c, sim_responses=uniform_responses)
    unit_uniforms = np.array(uniform_responses.at_decks(points))
    print(f"Unit uniform temperature per point, shape = {unit_uniforms.shape}")

    # Convert linear fem to correct type (thermal post-processing).
    if response_type in [
            ResponseType.Strain,
            ResponseType.StrainT,
            ResponseType.StrainZZB,
    ]:
        linear_responses = unit_linear.to_strain(
            c=c, sim_responses=linear_responses)
    elif response_type == ResponseType.Stress:
        linear_responses = unit_linear.to_stress(
            c=c, sim_responses=linear_responses)
    unit_linears = np.array(linear_responses.at_decks(points))

    # Determine temperature gradient throughout the bridge.
    if temps_bt is None:
        temps_bottom, temps_top = temps_bottom_top(c=c,
                                                   temps=temps,
                                                   solar=solar,
                                                   len_per_hour=len_per_hour)
    else:
        temps_bottom, temps_top = temps_bt
        temps_bottom, temps_top = np.array(temps_bottom), np.array(temps_top)

    temps_half = (temps_bottom + temps_top) / 2
    temps_linear = temps_top - temps_bottom
    temps_uniform = temps_half - c.bridge.ref_temp_c

    # print(f"temps_bottom.shape = {temps_bottom.shape}")
    # print(f"temps_top.shape = {temps_top.shape}")
    # print(f"temps_half.shape = {temps_half.shape}")
    print_d(D, f"tb = {temps_bottom[:3]}")
    print_d(D, f"tt = {temps_top[:3]}")
    print_d(D, f"th = {temps_half[:3]}")
    print_d(D, f"temps linear = {temps_linear[:3]}")
    print_d(D, f"temps uniform = {temps_uniform[:3]}")

    # Combine uniform and linear fem.
    uniform_responses = np.array(
        [unit_uniform * temps_half for unit_uniform in unit_uniforms])
    linear_responses = np.array(
        [unit_linear * temps_linear for unit_linear in unit_linears])
    # print(f"uniform_responses.shape = {uniform_responses.shape}")
    # print(f"linear_responses.shape = {linear_responses.shape}")
    print_d(D, f"uniform fem = {uniform_responses[:3]}")
    print_d(D, f"linear fem = {linear_responses[:3]}")
    if d:
        return temps_uniform, temps_linear, uniform_responses + linear_responses
    if ret_temps_bt:
        return ((temps_bottom, temps_top),
                uniform_responses + linear_responses)
    return uniform_responses + linear_responses
예제 #4
0
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()
예제 #5
0
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()
예제 #6
0
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()
예제 #7
0
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()