Source code for pyrocko.fomosto.ahfullgreen

# http://pyrocko.org - GPLv3
#
# The Pyrocko Developers, 21st Century
# ---|P------/S----------~Lg----------

import numpy as num
import logging
import os
import math
import signal

from pyrocko.guts import Object, clone
from pyrocko import trace, cake, gf
from pyrocko.ahfullgreen import add_seismogram, AhfullgreenSTFImpulse, \
    AhfullgreenSTF
from pyrocko.moment_tensor import MomentTensor, symmat6

km = 1000.

guts_prefix = 'pf'

logger = logging.getLogger('pyrocko.fomosto.ahfullgreen')

# how to call the programs
program_bins = {
    'ahfullgreen': 'ahfullgreen',
}

components = 'x y z'.split()


def example_model():
    material = cake.Material(vp=3000., vs=1000., rho=3000., qp=200., qs=100.)
    layer = cake.HomogeneousLayer(
        ztop=0., zbot=30*km, m=material, name='fullspace')
    mod = cake.LayeredModel()
    mod.append(layer)
    return mod


class AhfullgreenError(gf.store.StoreError):
    pass


[docs]class AhfullgreenConfig(Object): stf = AhfullgreenSTF.T(default=AhfullgreenSTFImpulse.D())
def make_traces(material, source_mech, deltat, norths, easts, source_depth, receiver_depth, stf): if isinstance(source_mech, MomentTensor): m6 = source_mech.m6() f = (0., 0., 0.) elif isinstance(source_mech, tuple): m6 = (0., 0., 0., 0., 0., 0.) f = source_mech npad = 120 traces = [] for isource, (north, east) in enumerate(zip(norths, easts)): d3d = math.sqrt( north**2 + east**2 + (receiver_depth - source_depth)**2) tmin = (math.floor(d3d / material.vp / deltat) - npad) * deltat tmax = (math.ceil(d3d / material.vs / deltat) + npad) * deltat ns = int(round((tmax - tmin) / deltat)) outx = num.zeros(ns) outy = num.zeros(ns) outz = num.zeros(ns) x = (north, east, receiver_depth-source_depth) add_seismogram( material.vp, material.vs, material.rho, material.qp, material.qs, x, f, m6, 'displacement', deltat, tmin, outx, outy, outz, stf=stf) for i_comp, o in enumerate((outx, outy, outz)): comp = components[i_comp] tr = trace.Trace('', '%04i' % isource, '', comp, tmin=tmin, ydata=o, deltat=deltat, meta=dict(isource=isource)) traces.append(tr) return traces class AhfullGFBuilder(gf.builder.Builder): def __init__(self, store_dir, step, shared, block_size=None, force=False): self.store = gf.store.Store(store_dir, 'w') block_size = { 'A': (1, 2000), 'B': (1, 1, 2000), 'C': (1, 1, 2)}[self.store.config.short_type] gf.builder.Builder.__init__( self, self.store.config, step, block_size=block_size, force=force) self.ahfullgreen_config = self.store.get_extra('ahfullgreen') def cleanup(self): self.store.close() def work_block(self, index): store_type = self.store.config.short_type if store_type == 'A': (sz, firstx), (sz, lastx), (ns, nx) = \ self.get_block_extents(index) rz = self.store.config.receiver_depth sy = 0.0 elif store_type == 'B': (rz, sz, firstx), (rz, sz, lastx), (nr, ns, nx) = \ self.get_block_extents(index) sy = 0.0 elif store_type == 'C': (sz, sy, firstx), (sz, sy, lastx), (nz, ny, nx) = \ self.get_block_extents(index) rz = self.store.config.receiver.depth logger.info('Starting block %i / %i' % (index+1, self.nblocks)) dx = self.gf_config.deltas[-1] xs = num.linspace(firstx, firstx + (nx-1)*dx, nx).tolist() mmt1 = (MomentTensor(m=symmat6(1, 0, 0, 1, 0, 0)), {'x': (0, +1), 'y': (3, +1), 'z': (5, +1)}) mmt2 = (MomentTensor(m=symmat6(0, 0, 0, 0, 1, 1)), {'x': (1, +1), 'y': (4, +1), 'z': (6, +1)}) mmt3 = (MomentTensor(m=symmat6(0, 0, 1, 0, 0, 0)), {'x': (2, +1), 'z': (7, +1)}) mmt4 = (MomentTensor(m=symmat6(0, 1, 0, 0, 0, 0)), {'x': (8, +1), 'z': (9, +1)}) mmt0 = (MomentTensor(m=symmat6(1, 1, 1, 0, 0, 0)), {'x': (0, +1), 'z': (1, +1)}) component_scheme = self.store.config.component_scheme if component_scheme == 'elastic8': gfmapping = [mmt1, mmt2, mmt3] elif component_scheme == 'elastic10': gfmapping = [mmt1, mmt2, mmt3, mmt4] elif component_scheme == 'elastic2': gfmapping = [mmt0] elif component_scheme == 'elastic5': gfmapping = [ ((1., 1., 0.), {'x': (1, +1), 'z': (4, +1), 'y': (2, +1)}), ((0., 0., 1.), {'x': (0, +1), 'z': (3, +1)})] elif component_scheme == 'elastic18': gfmapping = [] for im in range(6): m6 = [0.0] * 6 m6[im] = 1.0 gfmapping.append( (MomentTensor(m=symmat6(*m6)), {'x': (im, +1), 'y': (6+im, +1), 'z': (12+im, +1)})) else: raise gf.UnavailableScheme( 'fomosto backend "ahfullgreen" cannot handle component scheme ' '"%s"' % component_scheme) for source_mech, gfmap in gfmapping: if component_scheme != 'elastic18': norths = xs easts = num.zeros_like(xs) else: receiver = self.store.config.receiver data = [] for x in xs: source = clone(self.store.config.source_origin) source.north_shift = x source.east_shift = sy source.depth = sz data.append(receiver.offset_to(source)) norths, easts = -num.array(data).T rawtraces = make_traces( self.store.config.earthmodel_1d.require_homogeneous(), source_mech, 1.0/self.store.config.sample_rate, norths, easts, sz, rz, self.ahfullgreen_config.stf) interrupted = [] def signal_handler(signum, frame): interrupted.append(True) original = signal.signal(signal.SIGINT, signal_handler) self.store.lock() duplicate_inserts = 0 try: for itr, tr in enumerate(rawtraces): if tr.channel not in gfmap: logger.debug('%s not in gfmap' % tr.channel) continue x = xs[tr.meta['isource']] if x > firstx + (nx-1)*dx: logger.error('x out of range') continue ig, factor = gfmap[tr.channel] args = { 'A': (sz, x, ig), 'B': (rz, sz, x, ig), 'C': (sz, sy, x, ig)}[store_type] tr = tr.snap() gf_tr = gf.store.GFTrace.from_trace(tr) gf_tr.data *= factor try: self.store.put(args, gf_tr) except gf.store.DuplicateInsert: duplicate_inserts += 1 finally: if duplicate_inserts: logger.warning('%i insertions skipped (duplicates)' % duplicate_inserts) self.store.unlock() signal.signal(signal.SIGINT, original) if interrupted: raise KeyboardInterrupt() logger.info('Done with block %i / %i' % (index+1, self.nblocks)) def init(store_dir, variant, config_params=None): assert variant is None modelling_code_id = 'ahfullgreen' store_id = os.path.basename(os.path.realpath(store_dir)) ahfullgreen = AhfullgreenConfig() d = dict( id=store_id, ncomponents=10, sample_rate=20., receiver_depth=0*km, source_depth_min=1*km, source_depth_max=10*km, source_depth_delta=1*km, distance_min=1*km, distance_max=20*km, distance_delta=1*km, earthmodel_1d=example_model(), modelling_code_id=modelling_code_id, tabulated_phases=[ gf.meta.TPDef( id='anyP', definition='P,p,\\P,\\p'), gf.meta.TPDef( id='anyS', definition='S,s,\\S,\\s')]) if config_params is not None: d.update(config_params) config = gf.meta.ConfigTypeA(**d) config.validate() return gf.store.Store.create_editables( store_dir, config=config, extra={'ahfullgreen': ahfullgreen}) def build(store_dir, force=False, nworkers=None, continue_=False, step=None, iblock=None): return AhfullGFBuilder.build( store_dir, force=force, nworkers=nworkers, continue_=continue_, step=step, iblock=iblock)