Exemplo n.º 1
0
    def cleanup_xspecfem2d_run(self, choice=None):
        """
        Do some cleanup after running the SPECFEM2D binaries to make sure files
        are in the correct locations, and rename the OUTPUT_FILES directory so
        that it does not get overwritten by subsequent runs

        :type choice: str
        :param choice: Rename the OUTPUT_FILES directory with a suffix tag
            msut be 'INIT' or 'TRUE'. If None, will not rename but the
        """
        cd(self.workdir_paths.workdir)
        print("> Cleaning up after xspecfem2d, setting up for new run")

        # SPECFEM2D outputs its models in the DATA/ directory by default,
        # while SeisFlows3 expects this in the OUTPUT_FILES/ directory (which is
        # the default in SPECFEM3D)
        mv(glob.glob("DATA/*bin"), self.workdir_paths.output)

        if choice == "INIT":
            mv(self.workdir_paths.output, self.workdir_paths.model_init)
            # Create a new OUTPUT_FILES/ directory for TRUE run
            rm(self.workdir_paths.output)
            mkdir(self.workdir_paths.output)
        elif choice == "TRUE":
            mv(self.workdir_paths.output, self.workdir_paths.model_true)
Exemplo n.º 2
0
 def clean(self):
     """
     Clean up solver-dependent run directory by removing the OUTPUT_FILES/
     directory
     """
     unix.cd(self.cwd)
     unix.rm("OUTPUT_FILES")
     unix.mkdir("OUTPUT_FILES")
Exemplo n.º 3
0
    def clean(self):
        """
        Cleans directories in which function and gradient evaluations were
        carried out
        """
        self.logger.info(msg.mnr("CLEANING WORKDIR FOR NEXT ITERATION"))

        unix.rm(PATH.GRAD)
        unix.rm(PATH.FUNC)
        unix.mkdir(PATH.GRAD)
        unix.mkdir(PATH.FUNC)
Exemplo n.º 4
0
    def finalize_search(self):
        """
        Prepares algorithm machinery and scratch directory for next model update

        Removes old model/search parameters, moves current parameters to old,
        sets up new current parameters and writes statistic outputs
        """
        self.logger.info(msg.sub("FINALIZING LINE SEARCH"))

        g = self.load(self.g_new)
        p = self.load(self.p_new)
        x = self.line_search.search_history()[0]
        f = self.line_search.search_history()[1]

        # Clean scratch directory
        unix.cd(PATH.OPTIMIZE)

        # Remove the old model parameters
        if self.iter > 1:
            self.logger.info("removing previously accepted model files (old)")
            for fid in [self.m_old, self.f_old, self.g_old, self.p_old]:
                unix.rm(fid)

        self.logger.info(
            "shifting current model (new) to previous model (old)")
        unix.mv(self.m_new, self.m_old)
        unix.mv(self.f_new, self.f_old)
        unix.mv(self.g_new, self.g_old)
        unix.mv(self.p_new, self.p_old)

        self.logger.info("setting accepted line search model as current model")
        unix.mv(self.m_try, self.m_new)
        self.savetxt(self.f_new, f.min())
        self.logger.info(f"current misfit is {self.f_new}={f.min():.3E}")

        # !!! TODO Describe what stats are being written here
        self.logger.info(f"writing optimization stats to: {CFGPATHS.STATSDIR}")
        self.write_stats(self.log_factor,
                         value=-dot(g, g)**-0.5 * (f[1] - f[0]) /
                         (x[1] - x[0]))
        self.write_stats(self.log_gradient_norm_L1, value=np.linalg.norm(g, 1))
        self.write_stats(self.log_gradient_norm_L2, value=np.linalg.norm(g, 2))
        self.write_stats(self.log_misfit, value=f[0])
        self.write_stats(self.log_restarted, value=self.restarted)
        self.write_stats(self.log_slope, value=(f[1] - f[0]) / (x[1] - x[0]))
        self.write_stats(self.log_step_count,
                         value=self.line_search.step_count)
        self.write_stats(self.log_step_length, value=x[f.argmin()])
        self.write_stats(self.log_theta, value=180. * np.pi**-1 * angle(p, -g))

        self.logger.info("resetting line search step count to 0")
        self.line_search.step_count = 0
Exemplo n.º 5
0
    def adjoint(self):
        """
        Calls SPECFEM3D adjoint solver, creates the `SEM` folder with adjoint
        traces which is required by the adjoint solver
        """
        setpar(key="SIMULATION_TYPE", val="3", file="DATA/Par_file")
        setpar(key="SAVE_FORWARD", val=".false.", file="DATA/Par_file")
        setpar(key="ATTENUATION", val=".false.", file="DATA/Par_file")

        unix.rm("SEM")
        unix.ln("traces/adj", "SEM")

        call_solver(mpiexec=PAR.MPIEXEC, executable="bin/xspecfem3D")
    def setup_specfem2d_for_model_true(self):
        """
        Overwrites MODEL TRUE creation from EX1

        Make some adjustments to the parameter file to create the final velocity
        model. This function assumes it is running from inside the
        SPECFEM2D/DATA directory
        """
        cd(self.workdir_paths.data)
        assert (os.path.exists("Par_file")), f"I cannot find the Par_file!"

        print("> EX: Updating SPECFEM2D to set checkerboard model as "
              "MODEL_TRUE")
        self.sf.sempar("model", "legacy")  # read model_velocity.dat_checker
        rm("proc000000_model_velocity.dat_input")
        ln("model_velocity.dat_checker", "proc000000_model_velocity.dat_input")
Exemplo n.º 7
0
    def initialize_solver_directories(self):
        """
        Creates solver directories in serial using a single node.
        Should only be run by master job.

        Differs from Base initialize_solver_directories() as this serial task
        will create directory structures for each source, rather than having
        each source create its own. However the internal dir structure is the
        same.
        """
        for source_name in self.source_names:
            cwd = os.path.join(PATH.SOLVER, source_name)
            # Remove any existing scratch directory
            unix.rm(cwd)

            # Create internal directory structure, change into directory to make
            # all actions RELATIVE path actions
            unix.mkdir(cwd)
            unix.cd(cwd)
            for cwd_dir in [
                    "bin", "DATA", "OUTPUT_FILES/DATABASES_MPI", "traces/obs",
                    "traces/syn", "traces/adj"
            ]:
                unix.mkdir(cwd_dir)

            # Copy exectuables
            src = glob(os.path.join(PATH.SPECFEM_BIN, "*"))
            dst = os.path.join("bin", "")
            unix.cp(src, dst)

            # Copy all input files except source files
            src = glob(os.path.join(PATH.SPECFEM_DATA, "*"))
            src = [_ for _ in src if self.source_prefix not in _]
            dst = os.path.join("DATA", "")
            unix.cp(src, dst)

            # symlink event source specifically
            src = os.path.join(PATH.SPECFEM_DATA,
                               f"{self.source_prefix}_{source_name}")
            dst = os.path.join("DATA", self.source_prefix)
            unix.ln(src, dst)

            if source_name == self.mainsolver:
                # Symlink taskid_0 as mainsolver in solver directory
                unix.ln(source_name, os.path.join(PATH.SOLVER, "mainsolver"))
                # Only check the solver parameters once
                self.check_solver_parameter_files()
Exemplo n.º 8
0
    def clean(self):
        """
        Determine if forward simulation from line search can be carried over.
        We assume clean() is the final flow() argument so that we can update
        the thrifty status here.
        """
        self.update_status()

        if self.thrifty:
            self.logger.info(
                msg.mnr("THRIFTY CLEANING  WORKDIR FOR NEXT "
                        "ITERATION"))
            unix.rm(PATH.GRAD)
            unix.mv(PATH.FUNC, PATH.GRAD)
            unix.mkdir(PATH.FUNC)
        else:
            super().clean()
Exemplo n.º 9
0
    def setup_specfem2d_for_model_init(self):
        """
        Make some adjustments to the original parameter file to.
        This function assumes it is running from inside the SPECFEM2D/DATA dir

        """
        cd(self.workdir_paths.data)
        assert (os.path.exists("Par_file")), f"I cannot find the Par_file!"

        print("> Setting the SPECFEM2D Par_file for SeisFlows3 compatiblility")

        self.sf.sempar("setup_with_binary_database", 1)  # create .bin files
        self.sf.sempar("save_model", "binary")  # output model in .bin format
        self.sf.sempar("save_ASCII_kernels", ".false.")  # kernels also .bin

        rm(self.workdir_paths.output)
        mkdir(self.workdir_paths.output)
Exemplo n.º 10
0
    def adjoint(self):
        """
        Calls SPECFEM2D adjoint solver, creates the `SEM` folder with adjoint
        traces which is required by the adjoint solver
        """
        setpar(key="SIMULATION_TYPE", val="3", file="DATA/Par_file")
        setpar(key="SAVE_FORWARD", val=".false.", file="DATA/Par_file")

        unix.rm("SEM")
        unix.ln("traces/adj", "SEM")

        # Deal with different SPECFEM2D name conventions for regular traces and
        # "adjoint" traces
        if PAR.FORMAT.upper == "SU":
            unix.rename(old=".su",
                        new=".su.adj",
                        names=glob(os.path.join("traces", "adj", "*.su")))

        call_solver(mpiexec=PAR.MPIEXEC, executable="bin/xmeshfem2D")
        call_solver(mpiexec=PAR.MPIEXEC, executable="bin/xspecfem2D")
Exemplo n.º 11
0
    def setup(self):
        """ 
        Prepares solver for inversion or migration.
        Sets up directory structure expected by SPECFEM and copies or generates
        seismic data to be inverted or migrated

        .. note:;
            As input for an inversion or migration, users can choose between
            providing data, or providing a target model from which data are
            generated on the fly.
            In the former case, a value for PATH.DATA must be supplied;
            in the latter case, a value for PATH.MODEL_TRUE must be provided.
        """
        # Clean up for new inversion
        unix.rm(self.cwd)
        self.initialize_solver_directories()

        # Determine where observation data will come from
        if PAR.CASE.upper() == "SYNTHETIC" and PATH.MODEL_TRUE is not None:
            if self.taskid == 0:
                self.logger.info(
                    "generating 'data' with MODEL_TRUE synthetics")
            # Generate synthetic data on the fly using the true model
            self.generate_data(model_path=PATH.MODEL_TRUE,
                               model_name="model_true",
                               model_type="gll")
        elif PATH.DATA is not None and os.path.exists(PATH.DATA):
            # If Data provided by user, copy directly into the solver directory
            unix.cp(src=glob(os.path.join(PATH.DATA, self.source_name, "*")),
                    dst=os.path.join("traces", "obs"))

        # Prepare initial model
        if self.taskid == 0:
            self.logger.info("running mesh generation for MODEL_INIT")
        self.generate_mesh(model_path=PATH.MODEL_INIT,
                           model_name="model_init",
                           model_type="gll")

        # Create blank adjoint traces to be overwritten
        self.initialize_adjoint_traces()
    def finalize_specfem2d_par_file(self):
        """
        Final changes to the SPECFEM2D Par_file before running SeisFlows.
        Par_file will be used to control all the child specfem2d directories.
        Need to tell them to read models from .bin files, and to use existing
        station files rather than create them from the Par_file
        """
        print("> EX2: Finalizing SPECFEM2D Par_file for SeisFlows3 inversion")

        cd(self.workdir_paths.data)
        self.sf.sempar("model", "gll")  # GLL so SPECFEM reads .bin files
        self.sf.sempar("use_existing_stations", ".true.")  # Use STATIONS file
        # Assign STATIONS_checker file which has 132 stations
        rm("STATIONS")

        # Only write the first 10 lines to get 10 stations in inversion
        with open("STATIONS_checker", "r") as f:
            lines = f.readlines()

        print(f"> EX2: Using {self.nsta} stations in this inversion workflow")
        with open("STATIONS", "w") as f:
            f.writelines(lines[:self.nsta])
Exemplo n.º 13
0
    def create_specfem2d_working_directory(self):
        """
        Create the working directory where we will generate our initial and
        final models using one of the SPECFEM2D examples
        """
        assert (os.path.exists(self.sem2d_paths["example"])), (
            f"SPECFEM2D/EXAMPLE directory: '{self.sem2d['example']}' "
            f"does not exist, please check this path and try again.")

        # Incase this example has written before, remove dir. that were created
        rm(self.workdir_paths.workdir)
        mkdir(self.workdir_paths.workdir)

        # Copy the binary executables and DATA from the SPECFEM2D example
        cp(self.sem2d_paths.bin, self.workdir_paths.bin)
        cp(self.sem2d_paths.example_data, self.workdir_paths.data)

        # Make sure that SPECFEM2D can find the expected files in the DATA/ dir
        cd(self.workdir_paths.data)
        rm("SOURCE")
        ln("SOURCE_001", "SOURCE")
        rm("Par_file")
        ln("Par_file_Tape2007_onerec", "Par_file")
"""
Create a test directory structure with actual data to test individual modules
"""
import os
from seisflows3.tools import unix
from seisflows3.config import CFGPATHS, ROOT_DIR


testdir = os.path.join(ROOT_DIR, "tests", "test_data")
workdir = os.path.join(testdir, "workdir")
for key, path in CFGPATHS.__dict__.items():
    full_path = os.path.join(workdir, path)
    if os.path.exists(full_path):
        unix.rm(full_path)
    # Identify files by the separator between filename and extension
    if "." in path:
        open(full_path, "w")
    else:
        unix.mkdir(os.path.join(workdir, path))

# Make the scratch solver directory
scratchdir = os.path.join(workdir, CFGPATHS.SCRATCHDIR)
solverdir = os.path.join(scratchdir, "solver", "001")
tracesdir = os.path.join(solverdir, "traces")
for dir_ in [scratchdir, solverdir, tracesdir]:
    unix.mkdir(dir_)

for dir_ in ["obs", "syn", "adj"]:
    unix.mkdir(os.path.join(tracesdir, dir_))