def calc_gmfs_fast(oqparam, sitecol): """ Build all the ground motion fields for the whole site collection in a single step. """ max_dist = oqparam.maximum_distance correl_model = get_correl_model(oqparam) seed = oqparam.random_seed imts = get_imts(oqparam) [gsim] = get_gsims(oqparam) trunc_level = oqparam.truncation_level n_gmfs = oqparam.number_of_ground_motion_fields rupture = get_rupture(oqparam) res = gmf.ground_motion_fields( rupture, sitecol, imts, gsim, trunc_level, n_gmfs, correl_model, filters.rupture_site_distance_filter(max_dist), seed, ) return {str(imt): matrix for imt, matrix in res.items()}
def test(self): def fake_filter(rupture, integration_distance, sites): if rupture == 1: return None # all filtered out elif rupture == 2: # partial filtering return sites3 # nothing filtered out elif rupture == 3: return sites1 sites1 = object() sites2 = object() sites3 = object() sites = [sites1, sites2, sites1] ruptures = [1, 2, 3] with mock.patch('openquake.hazardlib.calc.filters.' 'filter_sites_by_distance_to_rupture', fake_filter): filter_func = filters.rupture_site_distance_filter(13) filtered = filter_func(zip(ruptures, sites)) self.assertIsInstance(filtered, GeneratorType) rupt, sites = next(filtered) self.assertIs(rupt, ruptures[1]) self.assertIs(sites, sites3) rupt, sites = next(filtered) self.assertIs(rupt, ruptures[2]) self.assertIs(sites, sites1) self.assertEqual(list(filtered), [])
def test(self): class FakeRupture(object): def __init__(self, integration_distance, sites_mapping): self.integration_distance = integration_distance self.sites_mapping = sites_mapping @property def source_typology(self): return self def filter_sites_by_distance_to_rupture(self, rupture, integration_distance, sites): assert rupture is self assert integration_distance is self.integration_distance return self.sites_mapping[sites] sites1 = object() sites2 = object() sites3 = object() ruptures = [FakeRupture(13, {sites1: None}), # all filtered out FakeRupture(13, {sites2: sites3}), # partial filtering FakeRupture(13, {sites1: sites1})] # nothing filtered out sites = [sites1, sites2, sites1] filter_func = filters.rupture_site_distance_filter(13) filtered = filter_func(izip(ruptures, sites)) self.assertIsInstance(filtered, GeneratorType) source, sites = next(filtered) self.assertIs(source, ruptures[1]) self.assertIs(sites, sites3) source, sites = next(filtered) self.assertIs(source, ruptures[2]) self.assertIs(sites, sites1) self.assertEqual(list(filtered), [])
def sites_of_interest(self, rupture, maximum_distance): """ :param openquake.hazardlib.source.rupture.Rupture rupture: Rupture to calculate ground motion fields radiated from. :returns: a 2-tuple with 1) an :class:`openquake.engine.db.models.SiteCollection` object holding the sites that are within ``hazard_maximum_distance`` from the `rupture`. 2) the indices of the filtered sites in the whole ``sites`` collection of fields """ # filtering ruptures/sites rupture_sites = list( filters.rupture_site_distance_filter(maximum_distance)([ (rupture, self.sites) ])) if not rupture_sites: return [], [] [(rupture, sites_filtered)] = rupture_sites # convert the hazard lib site collection to engine one # that supports a fast __contains__ method and holds the site enhanced # by with ids sites_filtered = self.sites.subcollection(sites_filtered.indices) # find the indices in the site collection site_ids_indexes = [self.sites_dict[s.id] for s in sites_filtered] return sites_filtered, site_ids_indexes
def __init__(self, source_model, sites, gmpes, imls, imts, truncation_level=None, source_integration_dist=None, rupture_integration_dist=None): """ Instatiate and preprocess :param float source_integration_dist: Integration distance for sources :param float rupture_integration_dist: Integration distance for ruptures """ self.source_model = source_model self.sites = sites self.gmpes = gmpes self.imls = imls self.imts = imts self.truncation_level = truncation_level if source_integration_dist: self.src_filter = filters.source_site_distance_filter( source_integration_dist) else: self.src_filter = filters.source_site_noop_filter if rupture_integration_dist: self.rup_filter = filters.rupture_site_distance_filter( rupture_integration_dist) else: self.rup_filter = filters.rupture_site_noop_filter self.preprocess_inputs()
def classical(sources, sitecol, gsims_assoc, monitor): """ :param sources: a non-empty sequence of sources of homogeneous tectonic region type :param sitecol: a SiteCollection instance :param gsims_assoc: associations trt_model_id -> gsims :param monitor: a monitor instance :returns: an AccumDict rlz -> curves """ max_dist = monitor.oqparam.maximum_distance truncation_level = monitor.oqparam.truncation_level imtls = monitor.oqparam.imtls trt_model_id = sources[0].trt_model_id gsims = gsims_assoc[trt_model_id] curves_by_gsim = hazard_curves_per_trt( sources, sitecol, imtls, gsims, truncation_level, source_site_filter=source_site_distance_filter(max_dist), rupture_site_filter=rupture_site_distance_filter(max_dist), monitor=monitor) dic = dict(monitor=monitor) for gsim, curves in zip(gsims, curves_by_gsim): dic[trt_model_id, str(gsim)] = curves return dic
def sites_of_interest(self, rupture, maximum_distance): """ :param openquake.hazardlib.source.rupture.Rupture rupture: Rupture to calculate ground motion fields radiated from. :returns: a 2-tuple with 1) an :class:`openquake.engine.db.models.SiteCollection` object holding the sites that are within ``hazard_maximum_distance`` from the `rupture`. 2) the indices of the filtered sites in the whole ``sites`` collection of fields """ # filtering ruptures/sites rupture_sites = list( filters.rupture_site_distance_filter( maximum_distance)([(rupture, self.sites)])) if not rupture_sites: return [], [] [(rupture, sites_filtered)] = rupture_sites # convert the hazard lib site collection to engine one # that supports a fast __contains__ method and holds the site enhanced # by with ids sites_filtered = self.sites.subcollection(sites_filtered.indices) # find the indices in the site collection site_ids_indexes = [self.sites_dict[s.id] for s in sites_filtered] return sites_filtered, site_ids_indexes
def test(self): def fake_filter(rupture, integration_distance, sites): if rupture == 1: return None # all filtered out elif rupture == 2: # partial filtering return sites3 # nothing filtered out elif rupture == 3: return sites1 sites1 = object() sites2 = object() sites3 = object() sites = [sites1, sites2, sites1] ruptures = [1, 2, 3] with mock.patch( 'openquake.hazardlib.calc.filters.' 'filter_sites_by_distance_to_rupture', fake_filter): filter_func = filters.rupture_site_distance_filter(13) filtered = filter_func(izip(ruptures, sites)) self.assertIsInstance(filtered, GeneratorType) rupt, sites = next(filtered) self.assertIs(rupt, ruptures[1]) self.assertIs(sites, sites3) rupt, sites = next(filtered) self.assertIs(rupt, ruptures[2]) self.assertIs(sites, sites1) self.assertEqual(list(filtered), [])
def _compute_gmf(params, imt, gsims, site_coll, ruptures, rupture_seeds): """ Compute a ground motion field value for each rupture, for all the points affected by that rupture, for the given IMT. Returns a dictionary with the nonzero contributions to each site id, and a dictionary with the ids of the contributing ruptures for each site id. assert len(ruptures) == len(rupture_seeds) :param params: a dictionary containing the keys correl_model, truncation_level, maximum_distance :param imt: a hazardlib IMT instance :param gsims: a dictionary {tectonic region type -> GSIM instance} :param site_coll: a SiteCollection instance :param ruptures: a list of SESRupture objects :param rupture_seeds: a list with the seeds associated to the ruptures """ gmvs_per_site = collections.defaultdict(list) ruptures_per_site = collections.defaultdict(list) # Compute and save ground motion fields for i, rupture in enumerate(ruptures): gmf_calc_kwargs = { 'rupture': rupture.rupture, 'sites': site_coll, 'imts': [imt], 'gsim': gsims[rupture.rupture.tectonic_region_type], 'truncation_level': params['truncation_level'], 'realizations': DEFAULT_GMF_REALIZATIONS, 'correlation_model': params['correl_model'], 'rupture_site_filter': filters.rupture_site_distance_filter( params['maximum_distance']), } numpy.random.seed(rupture_seeds[i]) # there is a single imt => a single entry in the return dict [gmf_1_realiz] = gmf.ground_motion_fields(**gmf_calc_kwargs).values() # since DEFAULT_GMF_REALIZATIONS is 1, gmf_1_realiz is a matrix # with n_sites rows and 1 column for site, gmv in zip(site_coll, gmf_1_realiz): gmv = float(gmv) # convert a 1x1 matrix into a float if gmv: # nonzero contribution to site gmvs_per_site[site.id].append(gmv) ruptures_per_site[site.id].append(rupture.id) return gmvs_per_site, ruptures_per_site
def calc_gmfs_fast(oqparam, sitecol): """ Build all the ground motion fields for the whole site collection in a single step. """ max_dist = oqparam.maximum_distance correl_model = get_correl_model(oqparam) seed = oqparam.random_seed imts = get_imts(oqparam) [gsim] = get_gsims(oqparam) trunc_level = oqparam.truncation_level n_gmfs = oqparam.number_of_ground_motion_fields rupture = get_rupture(oqparam) res = gmf.ground_motion_fields( rupture, sitecol, imts, gsim, trunc_level, n_gmfs, correl_model, filters.rupture_site_distance_filter(max_dist), seed) return {str(imt): matrix for imt, matrix in res.items()}
def compute_gmf_cache(hc, gsims, ruptures, rupture_ids): """ Compute a ground motion field value for each rupture, for all the points affected by that rupture, for all IMTs. """ imts = [haz_general.imt_to_hazardlib(x) for x in hc.intensity_measure_types] correl_model = None if hc.ground_motion_correlation_model is not None: correl_model = haz_general.get_correl_model(hc) n_points = len(hc.site_collection) # initialize gmf_cache, a dict imt -> {gmvs, rupture_ids} gmf_cache = dict((imt, dict(gmvs=numpy.empty((n_points, 0)), rupture_ids=[])) for imt in imts) for rupture, rupture_id in zip(ruptures, rupture_ids): # Compute and save ground motion fields gmf_calc_kwargs = { 'rupture': rupture, 'sites': hc.site_collection, 'imts': imts, 'gsim': gsims[rupture.tectonic_region_type], 'truncation_level': hc.truncation_level, 'realizations': DEFAULT_GMF_REALIZATIONS, 'correlation_model': correl_model, 'rupture_site_filter': filters.rupture_site_distance_filter( hc.maximum_distance), } gmf_dict = gmf.ground_motion_fields(**gmf_calc_kwargs) # update the gmf cache: for imt_key, v in gmf_dict.iteritems(): gmf_cache[imt_key]['gmvs'] = numpy.append( gmf_cache[imt_key]['gmvs'], v, axis=1) gmf_cache[imt_key]['rupture_ids'].append(rupture_id) return gmf_cache
def ses_and_gmfs(job_id, src_ids, lt_rlz_id, task_seed, result_grp_ordinal): """ Celery task for the stochastic event set calculator. Samples logic trees and calls the stochastic event set calculator. Once stochastic event sets are calculated, results will be saved to the database. See :class:`openquake.engine.db.models.SESCollection`. Optionally (specified in the job configuration using the `ground_motion_fields` parameter), GMFs can be computed from each rupture in each stochastic event set. GMFs are also saved to the database. Once all of this work is complete, a signal will be sent via AMQP to let the control noe know that the work is complete. (If there is any work left to be dispatched, this signal will indicate to the control node that more work can be enqueued.) :param int job_id: ID of the currently running job. :param src_ids: List of ids of parsed source models from which we will generate stochastic event sets/ruptures. :param lt_rlz_id: Id of logic tree realization model to calculate for. :param int task_seed: Value for seeding numpy/scipy in the computation of stochastic event sets and ground motion fields. :param int result_grp_ordinal: The result group in which the calculation results will be placed. This ID basically corresponds to the sequence number of the task, in the context of the entire calculation. """ logs.LOG.debug(('> starting `stochastic_event_sets` task: job_id=%s, ' 'lt_realization_id=%s') % (job_id, lt_rlz_id)) numpy.random.seed(task_seed) hc = models.HazardCalculation.objects.get(oqjob=job_id) cmplt_lt_ses = None if hc.complete_logic_tree_ses: cmplt_lt_ses = models.SES.objects.get( ses_collection__output__oq_job=job_id, complete_logic_tree_ses=True) if hc.ground_motion_fields: # For ground motion field calculation, we need the points of interest # for the calculation. points_to_compute = hc.points_to_compute() imts = [haz_general.imt_to_hazardlib(x) for x in hc.intensity_measure_types] correl_model = None if hc.ground_motion_correlation_model is not None: correl_model = haz_general.get_correl_model(hc) lt_rlz = models.LtRealization.objects.get(id=lt_rlz_id) ltp = logictree.LogicTreeProcessor(hc.id) apply_uncertainties = ltp.parse_source_model_logictree_path( lt_rlz.sm_lt_path) gsims = ltp.parse_gmpe_logictree_path(lt_rlz.gsim_lt_path) sources = list(haz_general.gen_sources( src_ids, apply_uncertainties, hc.rupture_mesh_spacing, hc.width_of_mfd_bin, hc.area_source_discretization)) # Compute stochastic event sets # For each rupture generated, we can optionally calculate a GMF for ses_rlz_n in xrange(1, hc.ses_per_logic_tree_path + 1): logs.LOG.debug('> computing stochastic event set %s of %s' % (ses_rlz_n, hc.ses_per_logic_tree_path)) # This is the container for all ruptures for this stochastic event set # (specified by `ordinal` and the logic tree realization). # NOTE: Many tasks can contribute ruptures to this SES. ses = models.SES.objects.get( ses_collection__lt_realization=lt_rlz, ordinal=ses_rlz_n) sources_sites = ((src, hc.site_collection) for src in sources) ssd_filter = filters.source_site_distance_filter(hc.maximum_distance) # Get the filtered sources, ignore the site collection: filtered_sources = (src for src, _ in ssd_filter(sources_sites)) # Calculate stochastic event sets: logs.LOG.debug('> computing stochastic event sets') if hc.ground_motion_fields: gmf_cache = _create_gmf_cache(len(points_to_compute), imts) logs.LOG.debug('> computing also ground motion fields') # This will be the "container" for all computed ground motion field # results for this stochastic event set. gmf_set = models.GmfSet.objects.get( gmf_collection__lt_realization=lt_rlz, ses_ordinal=ses_rlz_n) ses_poissonian = stochastic.stochastic_event_set_poissonian( filtered_sources, hc.investigation_time) logs.LOG.debug('> looping over ruptures') rupture_ordinal = 0 for rupture in ses_poissonian: rupture_ordinal += 1 # Prepare and save SES ruptures to the db: logs.LOG.debug('> saving SES rupture to DB') _save_ses_rupture( ses, rupture, cmplt_lt_ses, result_grp_ordinal, rupture_ordinal) logs.LOG.debug('> done saving SES rupture to DB') # Compute ground motion fields (if requested) logs.LOG.debug('compute ground motion fields? %s' % hc.ground_motion_fields) if hc.ground_motion_fields: # Compute and save ground motion fields gmf_calc_kwargs = { 'rupture': rupture, 'sites': hc.site_collection, 'imts': imts, 'gsim': gsims[rupture.tectonic_region_type], 'truncation_level': hc.truncation_level, 'realizations': DEFAULT_GMF_REALIZATIONS, 'correlation_model': correl_model, 'rupture_site_filter': filters.rupture_site_distance_filter( hc.maximum_distance), } logs.LOG.debug('> computing ground motion fields') gmf_dict = gmf_calc.ground_motion_fields(**gmf_calc_kwargs) logs.LOG.debug('< done computing ground motion fields') # update the gmf cache: for k, v in gmf_dict.iteritems(): gmf_cache[k] = numpy.append( gmf_cache[k], v, axis=1) logs.LOG.debug('< Done looping over ruptures') logs.LOG.debug('%s ruptures computed for SES realization %s of %s' % (rupture_ordinal, ses_rlz_n, hc.ses_per_logic_tree_path)) logs.LOG.debug('< done computing stochastic event set %s of %s' % (ses_rlz_n, hc.ses_per_logic_tree_path)) if hc.ground_motion_fields: # save the GMFs to the DB logs.LOG.debug('> saving GMF results to DB') _save_gmfs( gmf_set, gmf_cache, points_to_compute, result_grp_ordinal) logs.LOG.debug('< done saving GMF results to DB') logs.LOG.debug('< task complete, signalling completion') base.signal_task_complete(job_id=job_id, num_items=len(src_ids))
def test_point_sources(self): sources = [ openquake.hazardlib.source.PointSource( source_id='point1', name='point1', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=1, occurrence_rates=[5] ), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0.0, dip=90.0, rake=0.0)) ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship= openquake.hazardlib.scalerel.PeerMSR(), rupture_aspect_ratio=2, temporal_occurrence_model=PoissonTOM(1.), rupture_mesh_spacing=1.0, location=Point(10, 10) ), openquake.hazardlib.source.PointSource( source_id='point2', name='point2', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=2, occurrence_rates=[5, 6, 7] ), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0, dip=90, rake=0.0)), ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship= openquake.hazardlib.scalerel.PeerMSR(), rupture_aspect_ratio=2, temporal_occurrence_model=PoissonTOM(1.), rupture_mesh_spacing=1.0, location=Point(10, 11) ), ] sites = [openquake.hazardlib.site.Site(Point(11, 10), 1, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 16), 2, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.6), 3, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.7), 4, True, 2, 3)] sitecol = openquake.hazardlib.site.SiteCollection(sites) from openquake.hazardlib.gsim.sadigh_1997 import SadighEtAl1997 gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()} truncation_level = 1 imts = {openquake.hazardlib.imt.PGA(): [0.1, 0.5, 1.3]} from openquake.hazardlib.calc import filters source_site_filter = self.SitesCounterSourceFilter( filters.source_site_distance_filter(30) ) rupture_site_filter = self.SitesCounterRuptureFilter( filters.rupture_site_distance_filter(30) ) hazard_curves( iter(sources), sitecol, imts, gsims, truncation_level, source_site_filter=source_site_filter, rupture_site_filter=rupture_site_filter ) # there are two sources and four sites. The first source contains only # one rupture, the second source contains three ruptures. # # the first source has 'maximum projection radius' of 0.707 km # the second source has 'maximum projection radius' of 500.0 km # # the epicentral distances for source 1 are: [ 109.50558394, # 667.16955987, 66.71695599, 77.83644865] # the epicentral distances for source 2 are: [ 155.9412148 , # 555.97463322, 44.47797066, 33.35847799] # # Considering that the source site filtering distance is set to 30 km, # for source 1, all sites have epicentral distance larger than # 0.707 + 30 km. This means that source 1 ('point 1') is not considered # in the calculation because too far. # for source 2, the 1st, 3rd and 4th sites have epicentral distances # smaller than 500.0 + 30 km. This means that source 2 ('point 2') is # considered in the calculation for site 1, 3, and 4. # # JB distances for rupture 1 in source 2 are: [ 155.43860273, # 555.26752644, 43.77086388, 32.65137121] # JB distances for rupture 2 in source 2 are: [ 150.98882575, # 548.90356541, 37.40690285, 26.28741018] # JB distances for rupture 3 in source 2 are: [ 109.50545819, # 55.97463322, 0. , 0. ] # # Considering that the rupture site filtering distance is set to 30 km, # rupture 1 (magnitude 4) is not considered because too far, rupture 2 # (magnitude 6) affect only the 4th site, rupture 3 (magnitude 8) # affect the 3rd and 4th sites. self.assertEqual(source_site_filter.counts, [('point2', [1, 3, 4])]) self.assertEqual(rupture_site_filter.counts, [(6, [4]), (8, [3, 4])])
def test_point_sources(self): sources = [ openquake.hazardlib.source.PointSource(source_id='point1', name='point1', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD(min_mag=4, bin_width=1, occurrence_rates=[5]), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0.0, dip=90.0, rake=0.0)) ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship = openquake.hazardlib.scalerel.PeerMSR(), rupture_aspect_ratio=2, rupture_mesh_spacing=1.0, location=Point(10, 10) ), openquake.hazardlib.source.PointSource(source_id='point2', name='point2', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD(min_mag=4, bin_width=2, occurrence_rates=[5, 6, 7]), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0, dip=90, rake=0.0)), ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship = openquake.hazardlib.scalerel.PeerMSR(), rupture_aspect_ratio=2, rupture_mesh_spacing=1.0, location=Point(10, 11) ), ] sites = [openquake.hazardlib.site.Site(Point(11, 10), 1, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 16), 2, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.6), 3, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.7), 4, True, 2, 3)] sitecol = openquake.hazardlib.site.SiteCollection(sites) from openquake.hazardlib.gsim.sadigh_1997 import SadighEtAl1997 gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()} truncation_level = 1 time_span = 1.0 imts = {openquake.hazardlib.imt.PGA(): [0.1, 0.5, 1.3]} from openquake.hazardlib.calc import filters source_site_filter = self.SitesCounterSourceFilter( filters.source_site_distance_filter(30) ) rupture_site_filter = self.SitesCounterRuptureFilter( filters.rupture_site_distance_filter(30) ) hazard_curves_poissonian( iter(sources), sitecol, imts, time_span, gsims, truncation_level, source_site_filter=source_site_filter, rupture_site_filter=rupture_site_filter ) # there are two sources and four sites. first source should # be filtered completely since it is too far from all the sites. # the second one should take only three sites -- all except (10, 16). # it generates three ruptures with magnitudes 4, 6 and 8, from which # the first one doesn't affect any of sites and should be ignored, # second only affects site (10, 10.7) and the last one affects all # three. self.assertEqual(source_site_filter.counts, [('point2', [1, 3, 4])]) self.assertEqual(rupture_site_filter.counts, [(6, [4]), (8, [1, 3, 4])])
def ses_and_gmfs(job_id, src_ids, ses, task_seed): """ Celery task for the stochastic event set calculator. Samples logic trees and calls the stochastic event set calculator. Once stochastic event sets are calculated, results will be saved to the database. See :class:`openquake.engine.db.models.SESCollection`. Optionally (specified in the job configuration using the `ground_motion_fields` parameter), GMFs can be computed from each rupture in each stochastic event set. GMFs are also saved to the database. :param int job_id: ID of the currently running job. :param src_ids: List of ids of parsed source models from which we will generate stochastic event sets/ruptures. :param lt_rlz_id: Id of logic tree realization model to calculate for. :param int task_seed: Value for seeding numpy/scipy in the computation of stochastic event sets and ground motion fields. """ numpy.random.seed(task_seed) hc = models.HazardCalculation.objects.get(oqjob=job_id) # complete_logic_tree_ses flag cmplt_lt_ses = None if hc.complete_logic_tree_ses: cmplt_lt_ses = models.SES.objects.get( ses_collection__output__oq_job=job_id, ordinal=None) # preparing sources ltp = logictree.LogicTreeProcessor(hc.id) lt_rlz = ses.ses_collection.lt_realization apply_uncertainties = ltp.parse_source_model_logictree_path( lt_rlz.sm_lt_path) gsims = ltp.parse_gmpe_logictree_path(lt_rlz.gsim_lt_path) source_iter = haz_general.gen_sources( src_ids, apply_uncertainties, hc.rupture_mesh_spacing, hc.width_of_mfd_bin, hc.area_source_discretization) src_filter = filters.source_site_distance_filter(hc.maximum_distance) rup_filter = filters.rupture_site_distance_filter(hc.maximum_distance) with EnginePerformanceMonitor( 'reading site collection', job_id, ses_and_gmfs): site_collection = hc.site_collection # Compute and save stochastic event sets # For each rupture generated, we can optionally calculate a GMF with EnginePerformanceMonitor('computing ses', job_id, ses_and_gmfs): ruptures = list(stochastic.stochastic_event_set_poissonian( source_iter, hc.investigation_time, site_collection, src_filter, rup_filter)) if not ruptures: return with EnginePerformanceMonitor('saving ses', job_id, ses_and_gmfs): rupture_ids = _save_ses_ruptures(ses, ruptures, cmplt_lt_ses) if hc.ground_motion_fields: with EnginePerformanceMonitor( 'computing gmfs', job_id, ses_and_gmfs): gmf_cache = compute_gmf_cache( hc, gsims, ruptures, rupture_ids) with EnginePerformanceMonitor('saving gmfs', job_id, ses_and_gmfs): _save_gmfs(ses, gmf_cache, site_collection)
def test_point_sources(self): sources = [ openquake.hazardlib.source.PointSource( source_id='point1', name='point1', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=1, occurrence_rates=[5]), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0.0, dip=90.0, rake=0.0)) ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=openquake.hazardlib.scalerel. PeerMSR(), rupture_aspect_ratio=2, temporal_occurrence_model=PoissonTOM(1.), rupture_mesh_spacing=1.0, location=Point(10, 10)), openquake.hazardlib.source.PointSource( source_id='point2', name='point2', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=2, occurrence_rates=[5, 6, 7]), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0, dip=90, rake=0.0)), ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=openquake.hazardlib.scalerel. PeerMSR(), rupture_aspect_ratio=2, temporal_occurrence_model=PoissonTOM(1.), rupture_mesh_spacing=1.0, location=Point(10, 11)), ] sites = [ openquake.hazardlib.site.Site(Point(11, 10), 1, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 16), 2, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.6), 3, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.7), 4, True, 2, 3) ] sitecol = openquake.hazardlib.site.SiteCollection(sites) from openquake.hazardlib.gsim.sadigh_1997 import SadighEtAl1997 gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()} truncation_level = 1 imts = {'PGA': [0.1, 0.5, 1.3]} from openquake.hazardlib.calc import filters source_site_filter = self.SitesCounterSourceFilter( filters.source_site_distance_filter(30)) rupture_site_filter = self.SitesCounterRuptureFilter( filters.rupture_site_distance_filter(30)) calc_hazard_curves(sources, sitecol, imts, gsims, truncation_level, source_site_filter=source_site_filter, rupture_site_filter=rupture_site_filter) # there are two sources and four sites. The first source contains only # one rupture, the second source contains three ruptures. # # the first source has 'maximum projection radius' of 0.707 km # the second source has 'maximum projection radius' of 500.0 km # # the epicentral distances for source 1 are: [ 109.50558394, # 667.16955987, 66.71695599, 77.83644865] # the epicentral distances for source 2 are: [ 155.9412148 , # 555.97463322, 44.47797066, 33.35847799] # # Considering that the source site filtering distance is set to 30 km, # for source 1, all sites have epicentral distance larger than # 0.707 + 30 km. This means that source 1 ('point 1') is not considered # in the calculation because too far. # for source 2, the 1st, 3rd and 4th sites have epicentral distances # smaller than 500.0 + 30 km. This means that source 2 ('point 2') is # considered in the calculation for site 1, 3, and 4. # # JB distances for rupture 1 in source 2 are: [ 155.43860273, # 555.26752644, 43.77086388, 32.65137121] # JB distances for rupture 2 in source 2 are: [ 150.98882575, # 548.90356541, 37.40690285, 26.28741018] # JB distances for rupture 3 in source 2 are: [ 109.50545819, # 55.97463322, 0. , 0. ] # # Considering that the rupture site filtering distance is set to 30 km, # rupture 1 (magnitude 4) is not considered because too far, rupture 2 # (magnitude 6) affect only the 4th site, rupture 3 (magnitude 8) # affect the 3rd and 4th sites. self.assertEqual(source_site_filter.counts, [('point2', [1, 3, 4])]) self.assertEqual(rupture_site_filter.counts, [(6, [4]), (8, [3, 4])])
def test_point_sources(self): sources = [ openquake.hazardlib.source.PointSource( source_id='point1', name='point1', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=1, occurrence_rates=[5] ), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0.0, dip=90.0, rake=0.0)) ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship= openquake.hazardlib.scalerel.PeerMSR(), rupture_aspect_ratio=2, rupture_mesh_spacing=1.0, location=Point(10, 10) ), openquake.hazardlib.source.PointSource( source_id='point2', name='point2', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=2, occurrence_rates=[5, 6, 7] ), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0, dip=90, rake=0.0)), ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship= openquake.hazardlib.scalerel.PeerMSR(), rupture_aspect_ratio=2, rupture_mesh_spacing=1.0, location=Point(10, 11) ), ] sites = [openquake.hazardlib.site.Site(Point(11, 10), 1, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 16), 2, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.6), 3, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.7), 4, True, 2, 3)] sitecol = openquake.hazardlib.site.SiteCollection(sites) from openquake.hazardlib.gsim.sadigh_1997 import SadighEtAl1997 gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()} truncation_level = 1 time_span = 1.0 imts = {openquake.hazardlib.imt.PGA(): [0.1, 0.5, 1.3]} from openquake.hazardlib.calc import filters source_site_filter = self.SitesCounterSourceFilter( filters.source_site_distance_filter(30) ) rupture_site_filter = self.SitesCounterRuptureFilter( filters.rupture_site_distance_filter(30) ) hazard_curves_poissonian( iter(sources), sitecol, imts, time_span, gsims, truncation_level, source_site_filter=source_site_filter, rupture_site_filter=rupture_site_filter ) # there are two sources and four sites. first source should # be filtered completely since it is too far from all the sites. # the second one should take only three sites -- all except (10, 16). # it generates three ruptures with magnitudes 4, 6 and 8, from which # the first one doesn't affect any of sites and should be ignored, # second only affects site (10, 10.7) and the last one affects all # three. self.assertEqual(source_site_filter.counts, [('point2', [1, 3, 4])]) self.assertEqual(rupture_site_filter.counts, [(6, [4]), (8, [1, 3, 4])])