예제 #1
0
    def unrotated_center(self):
        c_lng = rotations.get_center_angle(self.max_longitude,
                                           self.min_longitude)
        c_lat = rotations.colat2lat(
            rotations.get_center_angle(rotations.lat2colat(self.max_latitude),
                                       rotations.lat2colat(self.min_latitude)))

        Point = collections.namedtuple("CenterPoint",
                                       ["longitude", "latitude"])
        return Point(longitude=c_lng, latitude=c_lat)
예제 #2
0
파일: domain.py 프로젝트: krischer/LASIF
    def unrotated_center(self):
        c_lng = rotations.get_center_angle(self.max_longitude,
                                           self.min_longitude)
        c_lat = rotations.colat2lat(rotations.get_center_angle(
            rotations.lat2colat(self.max_latitude),
            rotations.lat2colat(self.min_latitude)))

        Point = collections.namedtuple("CenterPoint", ["longitude",
                                                       "latitude"])
        return Point(longitude=c_lng, latitude=c_lat)
예제 #3
0
        def _on_button_press(event):
            if event.button != 1 or not event.inaxes:
                return
            lon, lat = m(event.xdata, event.ydata, inverse=True)
            # Convert to colat to ease indexing.
            colat = rotations.lat2colat(lat)

            x_range = (self.setup["physical_boundaries_x"][1] -
                self.setup["physical_boundaries_x"][0])
            x_frac = (colat - self.setup["physical_boundaries_x"][0]) / x_range
            x_index = int(((self.setup["boundaries_x"][1] -
                self.setup["boundaries_x"][0]) * x_frac) +
                self.setup["boundaries_x"][0])
            y_range = (self.setup["physical_boundaries_y"][1] -
                self.setup["physical_boundaries_y"][0])
            y_frac = (lon - self.setup["physical_boundaries_y"][0]) / y_range
            y_index = int(((self.setup["boundaries_y"][1] -
                self.setup["boundaries_y"][0]) * y_frac) +
                self.setup["boundaries_y"][0])

            plt.figure(1, figsize=(3, 8))
            depths = available_depths
            values = data[x_index, y_index, :]
            plt.plot(values, depths)
            plt.grid()
            plt.ylim(depths[-1], depths[0])
            plt.show()
            plt.close()
            plt.figure(0)
예제 #4
0
        def _on_button_press(event):
            if event.button != 1 or not event.inaxes:
                return
            lon, lat = m(event.xdata, event.ydata, inverse=True)
            # Convert to colat to ease indexing.
            colat = rotations.lat2colat(lat)

            x_range = (self.setup["physical_boundaries_x"][1] -
                       self.setup["physical_boundaries_x"][0])
            x_frac = (colat - self.setup["physical_boundaries_x"][0]) / x_range
            x_index = int(((self.setup["boundaries_x"][1] -
                            self.setup["boundaries_x"][0]) * x_frac) +
                          self.setup["boundaries_x"][0])
            y_range = (self.setup["physical_boundaries_y"][1] -
                       self.setup["physical_boundaries_y"][0])
            y_frac = (lon - self.setup["physical_boundaries_y"][0]) / y_range
            y_index = int(((self.setup["boundaries_y"][1] -
                            self.setup["boundaries_y"][0]) * y_frac) +
                          self.setup["boundaries_y"][0])

            plt.figure(1, figsize=(3, 8))
            depths = available_depths
            values = data[x_index, y_index, :]
            plt.plot(values, depths)
            plt.grid()
            plt.ylim(depths[-1], depths[0])
            plt.show()
            plt.close()
            plt.figure(0)
예제 #5
0
    def write(self, outdir, verbose=True):
        """Write input files(setup, event_x, event_list, recfile_x, stf) to given directory
        """
        outdir = outdir
        if not os.path.isdir(outdir):
            os.makedirs(outdir)
        self.events.write(outdir, config=self.config)
        self.stalst.write(outdir)
        stf_fname = outdir + '/stf'
        # Note: header is mandatory for stf file!!!
        np.savetxt(stf_fname,
                   self.config.source_time_function,
                   header='\n \n \n')

        if self.config.is_dissipative and (
                not os.path.isfile(outdir + '/relax')):
            print outdir
            raise AttributeError('relax file not exists!')
        setup_file_template = (
            "MODEL ==============================================================="
            "================================================================="
            "=====\n"
            "{theta_min:<44.6f}! theta_min (colatitude) in degrees\n"
            "{theta_max:<44.6f}! theta_max (colatitude) in degrees\n"
            "{phi_min:<44.6f}! phi_min (longitude) in degrees\n"
            "{phi_max:<44.6f}! phi_max (longitude) in degrees\n"
            "{z_min:<44.6f}! z_min (radius) in m\n"
            "{z_max:<44.6f}! z_max (radius) in m\n"
            "{is_diss:<44d}! is_diss\n"
            "{model_type:<44d}! model_type\n"
            "COMPUTATIONAL SETUP (PARALLELISATION) ==============================="
            "================================================================="
            "=====\n"
            "{nx_global:<44d}! nx_global, "
            "(nx_global+px = global # elements in theta direction)\n"
            "{ny_global:<44d}! ny_global, "
            "(ny_global+py = global # elements in phi direction)\n"
            "{nz_global:<44d}! nz_global, "
            "(nz_global+pz = global # of elements in r direction)\n"
            "{lpd:<44d}! lpd, LAGRANGE polynomial degree\n"
            "{px:<44d}! px, processors in theta direction\n"
            "{py:<44d}! py, processors in phi direction\n"
            "{pz:<44d}! pz, processors in r direction\n"
            "ADJOINT PARAMETERS =================================================="
            "================================================================="
            "=====\n"
            "{adjoint_flag:<44d}! adjoint_flag (0=normal simulation, "
            "1=adjoint forward, 2=adjoint reverse)\n"
            "{samp_ad:<44d}! samp_ad, sampling rate of forward field\n"
            "{adjoint_wavefield_folder}")
        EARTH_RADIUS = 6371 * 1000.
        adjointdict = {
            'normal simulation': 0,
            'adjoint forward': 1,
            'adjoint reverse': 2
        }
        setup_file = setup_file_template.format(
            # Colatitude! Swaps min and max.
            theta_min=rotations.lat2colat(float(
                self.config.mesh_max_latitude)),
            theta_max=rotations.lat2colat(float(
                self.config.mesh_min_latitude)),
            phi_min=float(self.config.mesh_min_longitude),
            phi_max=float(self.config.mesh_max_longitude),
            # Min/max radius and depth are inverse to each other.
            z_min=EARTH_RADIUS -
            (float(self.config.mesh_max_depth_in_km) * 1000.0),
            z_max=EARTH_RADIUS -
            (float(self.config.mesh_min_depth_in_km) * 1000.0),
            is_diss=1 if self.config.is_dissipative else 0,
            model_type=3,
            lpd=int(self.config.lagrange_polynomial_degree),
            # Computation setup.
            nx_global=self.config.nx_global,
            ny_global=self.config.ny_global,
            nz_global=self.config.nz_global,
            px=self.config.px,
            py=self.config.py,
            pz=self.config.pz,
            adjoint_flag=adjointdict[self.config.simulation_type],
            samp_ad=self.config.adjoint_forward_sampling_rate,
            adjoint_wavefield_folder=self.config.
            adjoint_forward_wavefield_output_folder)
        setup_fname = outdir + '/setup'
        with open(setup_fname, 'wb') as f:
            f.writelines(setup_file)
        return
예제 #6
0
    def write(self,
              outdir,
              config=None,
              nt=None,
              dt=None,
              output_folder=None,
              ssamp=None,
              outdisp=None):
        """Write event file to ouput directory 
        """
        try:
            nt = config.number_of_time_steps
            dt = config.time_increment_in_s
            output_folder = config.output_folder
            ssamp = config.displacement_snapshot_sampling
            outdisp = config.output_displacement
        except:
            if nt == None or dt == None or output_folder == None or ssamp == None or outdisp == None:
                raise ValueError('Wrong input for events writer!')
        if not os.path.isdir(outdir):
            os.makedirs(outdir)
        eventlst = outdir + '/event_list'
        L = len(self.events)
        lst_template = ("{L:<44d}! n_events = number of events\n")
        lst_file = lst_template.format(L=int(L))
        with open(eventlst, 'wb') as f:
            f.writelines(lst_file)
            for i in xrange(L):
                f.writelines('%d \n' % (i + 1))
        event_template = (
            "SIMULATION PARAMETERS ==============================================="
            "===================================\n"
            "{nt:<44d}! nt, number of time steps\n"
            "{dt:<44.6f}! dt in sec, time increment\n"
            "SOURCE =============================================================="
            "===================================\n"
            "{xxs:<44.6f}! xxs, theta-coord. center of source in degrees\n"
            "{yys:<44.6f}! yys, phi-coord. center of source in degrees\n"
            "{zzs:<44.6f}! zzs, source depth in (m)\n"
            "{srctype:<44d}! srctype, 1:f_x, 2:f_y, 3:f_z, 10:M_ij\n"
            "{m_tt:<44.6e}! M_theta_theta\n"
            "{m_pp:<44.6e}! M_phi_phi\n"
            "{m_rr:<44.6e}! M_r_r\n"
            "{m_tp:<44.6e}! M_theta_phi\n"
            "{m_tr:<44.6e}! M_theta_r\n"
            "{m_pr:<44.6e}! M_phi_r\n"
            "OUTPUT DIRECTORY ===================================================="
            "==================================\n"
            "{output_folder}\n"
            "OUTPUT FLAGS ========================================================"
            "==================================\n"
            "{ssamp:<44d}! ssamp, snapshot sampling\n"
            "{output_displacement:<44d}! output_displacement, output displacement "
            "field (1=yes,0=no)")

        for i in xrange(L):
            eventname = outdir + '/event_%d' % (i + 1)
            with open(eventname, 'wb') as f:
                lat = self.events[i].origins[0].latitude
                lon = self.events[i].origins[0].longitude
                evdp = self.events[i].origins[0].depth * 1000.
                m_tt = self.events[i].focal_mechanisms[
                    0].moment_tensor.tensor.m_tt
                m_rr = self.events[i].focal_mechanisms[
                    0].moment_tensor.tensor.m_rr
                m_pp = self.events[i].focal_mechanisms[
                    0].moment_tensor.tensor.m_pp
                m_tp = self.events[i].focal_mechanisms[
                    0].moment_tensor.tensor.m_tp
                m_tr = self.events[i].focal_mechanisms[
                    0].moment_tensor.tensor.m_rt
                m_pr = self.events[i].focal_mechanisms[
                    0].moment_tensor.tensor.m_rp

                event_file = event_template.format(
                    nt=int(nt),
                    dt=float(dt),
                    # Colatitude!
                    xxs=rotations.lat2colat(lat),
                    yys=lon,
                    zzs=evdp,
                    srctype=10,
                    m_tt=float(m_tt),
                    m_pp=float(m_pp),
                    m_rr=float(m_rr),
                    m_tp=float(m_tp),
                    m_tr=float(m_tr),
                    m_pr=float(m_pr),
                    output_folder=output_folder,
                    ssamp=int(ssamp),
                    output_displacement=outdisp)
                f.writelines(event_file)
        return
예제 #7
0
파일: actions.py 프로젝트: Debesys/LASIF
    def finalize_adjoint_sources(self, iteration_name, event_name):
        """
        Finalizes the adjoint sources.
        """
        from itertools import izip
        import numpy as np

        from lasif import rotations

        all_coordinates = []
        _i = 0

        window_manager = self.comm.windows.get(event_name, iteration_name)
        event = self.comm.events.get(event_name)
        iteration = self.comm.iterations.get(iteration_name)
        iteration_event_def = iteration.events[event["event_name"]]
        iteration_stations = iteration_event_def["stations"]

        event_weight = iteration_event_def["event_weight"]

        output_folder = self.comm.project.get_output_folder(
            "adjoint_sources__ITERATION_%s__%s" % (iteration_name, event_name))

        l = sorted(window_manager.list())
        for station, windows in itertools.groupby(
                l, key=lambda x: ".".join(x.split(".")[:2])):
            if station not in iteration_stations:
                continue
            station_weight = iteration_stations[station]["station_weight"]
            channels = {}
            for w in windows:
                w = window_manager.get(w)
                channel_weight = 0
                srcs = []
                for window in w:
                    ad_src = window.adjoint_source
                    if not ad_src["adjoint_source"].ptp():
                        continue
                    srcs.append(ad_src["adjoint_source"] * window.weight)
                    channel_weight += window.weight
                if not srcs:
                    continue
                # Final adjoint source for that channel and apply all weights.
                adjoint_source = np.sum(srcs, axis=0) / channel_weight * \
                    event_weight * station_weight
                channels[w.channel_id[-1]] = adjoint_source
            if not channels:
                continue
            # Now all adjoint sources of a window should have the same length.
            length = set(len(v) for v in channels.values())
            assert len(length) == 1
            length = length.pop()
            # All missing channels will be replaced with a zero array.
            for c in ["Z", "N", "E"]:
                if c in  channels:
                    continue
                channels[c] = np.zeros(length)

            # Get the station coordinates
            coords = self.comm.query.get_coordinates_for_station(event_name,
                                                                 station)

            # Rotate. if needed
            rec_lat = coords["latitude"]
            rec_lng = coords["longitude"]
            domain = self.comm.project.domain

            if domain["rotation_angle"]:
                # Rotate the adjoint source location.
                r_rec_lat, r_rec_lng = rotations.rotate_lat_lon(
                    rec_lat, rec_lng, domain["rotation_axis"],
                    -domain["rotation_angle"])
                # Rotate the adjoint sources.
                channels["N"], channels["E"], channels["Z"] = \
                    rotations.rotate_data(
                        channels["N"], channels["E"],
                        channels["Z"], rec_lat, rec_lng,
                        domain["rotation_axis"],
                        -domain["rotation_angle"])
            else:
                r_rec_lat = rec_lat
                r_rec_lng = rec_lng
            r_rec_depth = 0.0
            r_rec_colat = rotations.lat2colat(r_rec_lat)

            CHANNEL_MAPPING = {"X": "N", "Y": "E", "Z": "Z"}

            _i += 1

            adjoint_src_filename = os.path.join(output_folder,
                                                "ad_src_%i" % _i)

            all_coordinates.append((r_rec_colat, r_rec_lng, r_rec_depth))

            # Actually write the adjoint source file in SES3D specific format.
            with open(adjoint_src_filename, "wt") as open_file:
                open_file.write("-- adjoint source ------------------\n")
                open_file.write("-- source coordinates (colat,lon,depth)\n")
                open_file.write("%f %f %f\n" % (r_rec_colat, r_rec_lng,
                                                r_rec_depth))
                open_file.write("-- source time function (x, y, z) --\n")
                for x, y, z in izip(-1.0 * channels[CHANNEL_MAPPING["X"]],
                                    channels[CHANNEL_MAPPING["Y"]],
                                    channels[CHANNEL_MAPPING["Z"]]):
                    open_file.write("%e %e %e\n" % (x, y, z))
                open_file.write("\n")

        # Write the final file.
        with open(os.path.join(output_folder, "ad_srcfile"), "wt") as fh:
            fh.write("%i\n" % _i)
            for line in all_coordinates:
                fh.write("%.6f %.6f %.6f\n" % (line[0], line[1], line[2]))
            fh.write("\n")

        print "Wrote %i adjoint sources to %s." % (
            _i, os.path.relpath(output_folder))
예제 #8
0
파일: actions.py 프로젝트: Phlos/LASIF
    def finalize_adjoint_sources(self, iteration_name, event_name):
        """
        Finalizes the adjoint sources.
        """
        from itertools import izip
        import numpy as np
        from lasif import rotations

        window_manager = self.comm.windows.get(event_name, iteration_name)
        event = self.comm.events.get(event_name)
        iteration = self.comm.iterations.get(iteration_name)
        iteration_event_def = iteration.events[event["event_name"]]
        iteration_stations = iteration_event_def["stations"]

        # For now assume that the adjoint sources have the same
        # sampling rate as the synthetics which in LASIF's workflow
        # actually has to be true.
        dt = iteration.get_process_params()["dt"]

        # Current domain and solver.
        domain = self.comm.project.domain
        solver = iteration.solver_settings["solver"].lower()

        adjoint_source_stations = set()

        if "ses3d" in solver:
            ses3d_all_coordinates = []

        event_weight = iteration_event_def["event_weight"]

        output_folder = self.comm.project.get_output_folder(
            type="adjoint_sources",
            tag="ITERATION_%s__%s" % (iteration_name, event_name))

        l = sorted(window_manager.list())
        for station, windows in itertools.groupby(
                l, key=lambda x: ".".join(x.split(".")[:2])):
            if station not in iteration_stations:
                continue
            print ".",
            station_weight = iteration_stations[station]["station_weight"]
            channels = {}
            try:
                for w in windows:
                    w = window_manager.get(w)
                    channel_weight = 0
                    srcs = []
                    for window in w:
                        ad_src = window.adjoint_source
                        if not ad_src["adjoint_source"].ptp():
                            continue
                        srcs.append(ad_src["adjoint_source"] * window.weight)
                        channel_weight += window.weight
                    if not srcs:
                        continue
                    # Final adjoint source for that channel and apply all
                    # weights.
                    adjoint_source = np.sum(srcs, axis=0) / channel_weight * \
                        event_weight * station_weight
                    channels[w.channel_id[-1]] = adjoint_source
            except LASIFError as e:
                print("Could not calculate adjoint source for iteration %s "
                      "and station %s. Repick windows? Reason: %s" % (
                          iteration.name, station, str(e)))
                continue
            if not channels:
                continue
            # Now all adjoint sources of a window should have the same length.
            length = set(len(v) for v in channels.values())
            assert len(length) == 1
            length = length.pop()
            # All missing channels will be replaced with a zero array.
            for c in ["Z", "N", "E"]:
                if c in channels:
                    continue
                channels[c] = np.zeros(length)

            # Get the station coordinates
            coords = self.comm.query.get_coordinates_for_station(event_name,
                                                                 station)

            # Rotate. if needed
            rec_lat = coords["latitude"]
            rec_lng = coords["longitude"]

            # The adjoint sources depend on the solver.
            if "ses3d" in solver:
                # Rotate if needed.
                if domain.rotation_angle_in_degree:
                    # Rotate the adjoint source location.
                    r_rec_lat, r_rec_lng = rotations.rotate_lat_lon(
                        rec_lat, rec_lng, domain.rotation_axis,
                        -domain.rotation_angle_in_degree)
                    # Rotate the adjoint sources.
                    channels["N"], channels["E"], channels["Z"] = \
                        rotations.rotate_data(
                            channels["N"], channels["E"],
                            channels["Z"], rec_lat, rec_lng,
                            domain.rotation_axis,
                            -domain.rotation_angle_in_degree)
                else:
                    r_rec_lat = rec_lat
                    r_rec_lng = rec_lng
                r_rec_depth = 0.0
                r_rec_colat = rotations.lat2colat(r_rec_lat)

                # Now once again map from ZNE to the XYZ of SES3D.
                CHANNEL_MAPPING = {"X": "N", "Y": "E", "Z": "Z"}
                adjoint_source_stations.add(station)
                adjoint_src_filename = os.path.join(
                    output_folder, "ad_src_%i" % len(adjoint_source_stations))
                ses3d_all_coordinates.append(
                    (r_rec_colat, r_rec_lng, r_rec_depth))

                # Actually write the adjoint source file in SES3D specific
                # format.
                with open(adjoint_src_filename, "wt") as open_file:
                    open_file.write("-- adjoint source ------------------\n")
                    open_file.write(
                        "-- source coordinates (colat,lon,depth)\n")
                    open_file.write("%f %f %f\n" % (r_rec_colat, r_rec_lng,
                                                    r_rec_depth))
                    open_file.write("-- source time function (x, y, z) --\n")
                    # Revert the X component as it has to point south in SES3D.
                    for x, y, z in izip(-1.0 * channels[CHANNEL_MAPPING["X"]],
                                        channels[CHANNEL_MAPPING["Y"]],
                                        channels[CHANNEL_MAPPING["Z"]]):
                        open_file.write("%e %e %e\n" % (x, y, z))
                    open_file.write("\n")
            elif "specfem" in solver:
                s_set = iteration.solver_settings["solver_settings"]
                if "adjoint_source_time_shift" not in s_set:
                    warnings.warn("No <adjoint_source_time_shift> tag in the "
                                  "iteration XML file. No time shift for the "
                                  "adjoint sources will be applied.",
                                  LASIFWarning)
                    src_time_shift = 0
                else:
                    src_time_shift = float(s_set["adjoint_source_time_shift"])
                adjoint_source_stations.add(station)
                # Write all components. The adjoint sources right now are
                # not time shifted.
                for component in ["Z", "N", "E"]:
                    # XXX: M band code could be different.
                    adjoint_src_filename = os.path.join(
                        output_folder, "%s.MX%s.adj" % (station, component))
                    adj_src = channels[component]
                    l = len(adj_src)
                    to_write = np.empty((l, 2))
                    to_write[:, 0] = \
                        np.linspace(0, (l - 1) * dt, l) + src_time_shift

                    # SPECFEM expects non-time reversed adjoint sources and
                    # the sign is different for some reason.
                    to_write[:, 1] = -1.0 * adj_src[::-1]

                    np.savetxt(adjoint_src_filename, to_write)
            else:
                raise NotImplementedError(
                    "Adjoint source writing for solver '%s' not yet "
                    "implemented." % iteration.solver_settings["solver"])

        if not adjoint_source_stations:
            print("Could not create a single adjoint source.")
            return

        if "ses3d" in solver:
            with open(os.path.join(output_folder, "ad_srcfile"), "wt") as fh:
                fh.write("%i\n" % len(adjoint_source_stations))
                for line in ses3d_all_coordinates:
                    fh.write("%.6f %.6f %.6f\n" % (line[0], line[1], line[2]))
                fh.write("\n")
        elif "specfem" in solver:
            adjoint_source_stations = sorted(list(adjoint_source_stations))
            with open(os.path.join(output_folder, "STATIONS_ADJOINT"),
                      "wt") as fh:
                for station in adjoint_source_stations:
                    coords = self.comm.query.get_coordinates_for_station(
                        event_name, station)
                    fh.write("{sta} {net} {lat} {lng} {ele} {dep}\n".format(
                        sta=station.split(".")[1],
                        net=station.split(".")[0],
                        lat=coords["latitude"],
                        lng=coords["longitude"],
                        ele=coords["elevation_in_m"],
                        dep=coords["local_depth_in_m"]))

        print "Wrote adjoint sources for %i station(s) to %s." % (
            len(adjoint_source_stations), os.path.relpath(output_folder))
예제 #9
0
    def finalize_adjoint_sources(self, iteration_name, event_name):
        """
        Finalizes the adjoint sources.
        """

        import numpy as np
        from lasif import rotations

        window_manager = self.comm.windows.get(event_name, iteration_name)
        event = self.comm.events.get(event_name)
        iteration = self.comm.iterations.get(iteration_name)
        iteration_event_def = iteration.events[event["event_name"]]
        iteration_stations = iteration_event_def["stations"]

        # For now assume that the adjoint sources have the same
        # sampling rate as the synthetics which in LASIF's workflow
        # actually has to be true.
        dt = iteration.get_process_params()["dt"]

        # Current domain and solver.
        domain = self.comm.project.domain
        solver = iteration.solver_settings["solver"].lower()

        adjoint_source_stations = set()

        if "ses3d" in solver:
            ses3d_all_coordinates = []

        event_weight = iteration_event_def["event_weight"]

        output_folder = self.comm.project.get_output_folder(
            type="adjoint_sources",
            tag="ITERATION_%s__%s" % (iteration_name, event_name))

        l = sorted(window_manager.list())
        for station, windows in itertools.groupby(
                l, key=lambda x: ".".join(x.split(".")[:2])):
            if station not in iteration_stations:
                continue
            print(".", end=' ')
            station_weight = iteration_stations[station]["station_weight"]
            channels = {}
            try:
                for w in windows:
                    w = window_manager.get(w)
                    channel_weight = 0
                    srcs = []
                    for window in w:
                        ad_src = window.adjoint_source
                        if not ad_src["adjoint_source"].ptp():
                            continue
                        srcs.append(ad_src["adjoint_source"] * window.weight)
                        channel_weight += window.weight
                    if not srcs:
                        continue
                    # Final adjoint source for that channel and apply all
                    # weights.
                    adjoint_source = np.sum(srcs, axis=0) / channel_weight * \
                        event_weight * station_weight
                    channels[w.channel_id[-1]] = adjoint_source
            except LASIFError as e:
                print(("Could not calculate adjoint source for iteration %s "
                       "and station %s. Repick windows? Reason: %s" %
                       (iteration.name, station, str(e))))
                continue
            if not channels:
                continue
            # Now all adjoint sources of a window should have the same length.
            length = set(len(v) for v in list(channels.values()))
            assert len(length) == 1
            length = length.pop()
            # All missing channels will be replaced with a zero array.
            for c in ["Z", "N", "E"]:
                if c in channels:
                    continue
                channels[c] = np.zeros(length)

            # Get the station coordinates
            coords = self.comm.query.get_coordinates_for_station(
                event_name, station)

            # Rotate. if needed
            rec_lat = coords["latitude"]
            rec_lng = coords["longitude"]

            # The adjoint sources depend on the solver.
            if "ses3d" in solver:
                # Rotate if needed.
                if domain.rotation_angle_in_degree:
                    # Rotate the adjoint source location.
                    r_rec_lat, r_rec_lng = rotations.rotate_lat_lon(
                        rec_lat, rec_lng, domain.rotation_axis,
                        -domain.rotation_angle_in_degree)
                    # Rotate the adjoint sources.
                    channels["N"], channels["E"], channels["Z"] = \
                        rotations.rotate_data(
                            channels["N"], channels["E"],
                            channels["Z"], rec_lat, rec_lng,
                            domain.rotation_axis,
                            -domain.rotation_angle_in_degree)
                else:
                    r_rec_lat = rec_lat
                    r_rec_lng = rec_lng
                r_rec_depth = 0.0
                r_rec_colat = rotations.lat2colat(r_rec_lat)

                # Now once again map from ZNE to the XYZ of SES3D.
                CHANNEL_MAPPING = {"X": "N", "Y": "E", "Z": "Z"}
                adjoint_source_stations.add(station)
                adjoint_src_filename = os.path.join(
                    output_folder, "ad_src_%i" % len(adjoint_source_stations))
                ses3d_all_coordinates.append(
                    (r_rec_colat, r_rec_lng, r_rec_depth))

                # Actually write the adjoint source file in SES3D specific
                # format.
                with open(adjoint_src_filename, "wt") as open_file:
                    open_file.write("-- adjoint source ------------------\n")
                    open_file.write(
                        "-- source coordinates (colat,lon,depth)\n")
                    open_file.write("%f %f %f\n" %
                                    (r_rec_colat, r_rec_lng, r_rec_depth))
                    open_file.write("-- source time function (x, y, z) --\n")
                    # Revert the X component as it has to point south in SES3D.
                    for x, y, z in zip(-1.0 * channels[CHANNEL_MAPPING["X"]],
                                       channels[CHANNEL_MAPPING["Y"]],
                                       channels[CHANNEL_MAPPING["Z"]]):
                        open_file.write("%e %e %e\n" % (x, y, z))
                    open_file.write("\n")
            elif "specfem" in solver:
                s_set = iteration.solver_settings["solver_settings"]
                if "adjoint_source_time_shift" not in s_set:
                    warnings.warn(
                        "No <adjoint_source_time_shift> tag in the "
                        "iteration XML file. No time shift for the "
                        "adjoint sources will be applied.", LASIFWarning)
                    src_time_shift = 0
                else:
                    src_time_shift = float(s_set["adjoint_source_time_shift"])
                adjoint_source_stations.add(station)
                # Write all components. The adjoint sources right now are
                # not time shifted.
                for component in ["Z", "N", "E"]:
                    # XXX: M band code could be different.
                    adjoint_src_filename = os.path.join(
                        output_folder, "%s.MX%s.adj" % (station, component))
                    adj_src = channels[component]
                    l = len(adj_src)
                    to_write = np.empty((l, 2))
                    to_write[:, 0] = \
                        np.linspace(0, (l - 1) * dt, l) + src_time_shift

                    # SPECFEM expects non-time reversed adjoint sources and
                    # the sign is different for some reason.
                    to_write[:, 1] = -1.0 * adj_src[::-1]

                    np.savetxt(adjoint_src_filename, to_write)
            else:
                raise NotImplementedError(
                    "Adjoint source writing for solver '%s' not yet "
                    "implemented." % iteration.solver_settings["solver"])

        if not adjoint_source_stations:
            print("Could not create a single adjoint source.")
            return

        if "ses3d" in solver:
            with open(os.path.join(output_folder, "ad_srcfile"), "wt") as fh:
                fh.write("%i\n" % len(adjoint_source_stations))
                for line in ses3d_all_coordinates:
                    fh.write("%.6f %.6f %.6f\n" % (line[0], line[1], line[2]))
                fh.write("\n")
        elif "specfem" in solver:
            adjoint_source_stations = sorted(list(adjoint_source_stations))
            with open(os.path.join(output_folder, "STATIONS_ADJOINT"),
                      "wt") as fh:
                for station in adjoint_source_stations:
                    coords = self.comm.query.get_coordinates_for_station(
                        event_name, station)
                    fh.write("{sta} {net} {lat} {lng} {ele} {dep}\n".format(
                        sta=station.split(".")[1],
                        net=station.split(".")[0],
                        lat=coords["latitude"],
                        lng=coords["longitude"],
                        ele=coords["elevation_in_m"],
                        dep=coords["local_depth_in_m"]))

        print("Wrote adjoint sources for %i station(s) to %s." %
              (len(adjoint_source_stations), os.path.relpath(output_folder)))
예제 #10
0
    def write(self, outdir, verbose=True):
        """Write input files(setup, event_x, event_list, recfile_x, stf) to given directory
        """
        outdir=outdir
        if not os.path.isdir(outdir):
            os.makedirs(outdir)
        self.events.write(outdir, config=self.config)
        self.stalst.write(outdir)
        stf_fname=outdir+'/stf'
        # Note: header is mandatory for stf file!!!
        np.savetxt(stf_fname, self.config.source_time_function, header = '\n \n \n')

        if self.config.is_dissipative and ( not os.path.isfile(outdir+'/relax') ):
            print outdir
            raise AttributeError('relax file not exists!')
        setup_file_template = (
            "MODEL ==============================================================="
            "================================================================="
            "=====\n"
            "{theta_min:<44.6f}! theta_min (colatitude) in degrees\n"
            "{theta_max:<44.6f}! theta_max (colatitude) in degrees\n"
            "{phi_min:<44.6f}! phi_min (longitude) in degrees\n"
            "{phi_max:<44.6f}! phi_max (longitude) in degrees\n"
            "{z_min:<44.6f}! z_min (radius) in m\n"
            "{z_max:<44.6f}! z_max (radius) in m\n"
            "{is_diss:<44d}! is_diss\n"
            "{model_type:<44d}! model_type\n"
            "COMPUTATIONAL SETUP (PARALLELISATION) ==============================="
            "================================================================="
            "=====\n"
            "{nx_global:<44d}! nx_global, "
            "(nx_global+px = global # elements in theta direction)\n"
            "{ny_global:<44d}! ny_global, "
            "(ny_global+py = global # elements in phi direction)\n"
            "{nz_global:<44d}! nz_global, "
            "(nz_global+pz = global # of elements in r direction)\n"
            "{lpd:<44d}! lpd, LAGRANGE polynomial degree\n"
            "{px:<44d}! px, processors in theta direction\n"
            "{py:<44d}! py, processors in phi direction\n"
            "{pz:<44d}! pz, processors in r direction\n"
            "ADJOINT PARAMETERS =================================================="
            "================================================================="
            "=====\n"
            "{adjoint_flag:<44d}! adjoint_flag (0=normal simulation, "
            "1=adjoint forward, 2=adjoint reverse)\n"
            "{samp_ad:<44d}! samp_ad, sampling rate of forward field\n"
            "{adjoint_wavefield_folder}")
        EARTH_RADIUS = 6371 * 1000.
        adjointdict={'normal simulation': 0, 'adjoint forward': 1, 'adjoint reverse': 2}
        setup_file = setup_file_template.format(
            # Colatitude! Swaps min and max.
            theta_min=rotations.lat2colat(float( self.config.mesh_max_latitude)),
            theta_max=rotations.lat2colat(float( self.config.mesh_min_latitude)),
            phi_min=float(self.config.mesh_min_longitude),
            phi_max=float(self.config.mesh_max_longitude),
            # Min/max radius and depth are inverse to each other.
            z_min=EARTH_RADIUS - (float(self.config.mesh_max_depth_in_km) * 1000.0),
            z_max=EARTH_RADIUS - (float(self.config.mesh_min_depth_in_km) * 1000.0),
            is_diss=1 if self.config.is_dissipative else 0,
            model_type=3,
            lpd=int(self.config.lagrange_polynomial_degree),
            # Computation setup.
            nx_global=self.config.nx_global,
            ny_global=self.config.ny_global,
            nz_global=self.config.nz_global,
            px=self.config.px,
            py=self.config.py,
            pz=self.config.pz,
            adjoint_flag=adjointdict[self.config.simulation_type],
            samp_ad=self.config.adjoint_forward_sampling_rate,
            adjoint_wavefield_folder=self.config.adjoint_forward_wavefield_output_folder)
        setup_fname=outdir+'/setup'
        with open(setup_fname, 'wb') as f:
            f.writelines(setup_file)
        return