A probabilistic earthquake source inversion framework. Designed and crafted in Mordor. https://pyrocko.org/grond/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

130 lines
3.8 KiB

  1. import numpy as num
  2. import logging
  3. from pyrocko import gf, util
  4. from pyrocko.guts import String, Float, Dict, Int
  5. from grond.meta import expand_template, Parameter, has_get_plot_classes, \
  6. GrondError
  7. from ..base import Problem, ProblemConfig
  8. guts_prefix = 'grond'
  9. logger = logging.getLogger('grond.problems.rectangular.problem')
  10. km = 1e3
  11. as_km = dict(scale_factor=km, scale_unit='km')
  12. class RectangularProblemConfig(ProblemConfig):
  13. ranges = Dict.T(String.T(), gf.Range.T())
  14. decimation_factor = Int.T(default=1)
  15. distance_min = Float.T(default=0.)
  16. nthreads = Int.T(default=4)
  17. def get_problem(self, event, target_groups, targets):
  18. if self.decimation_factor != 1:
  19. logger.warn(
  20. 'Decimation factor for rectangular source set to %i. Results '
  21. 'may be inaccurate.' % self.decimation_factor)
  22. base_source = gf.RectangularSource.from_pyrocko_event(
  23. event,
  24. anchor='top',
  25. decimation_factor=self.decimation_factor)
  26. subs = dict(
  27. event_name=event.name,
  28. event_time=util.time_to_str(event.time))
  29. problem = RectangularProblem(
  30. name=expand_template(self.name_template, subs),
  31. base_source=base_source,
  32. distance_min=self.distance_min,
  33. target_groups=target_groups,
  34. targets=targets,
  35. ranges=self.ranges,
  36. norm_exponent=self.norm_exponent,
  37. nthreads=self.nthreads)
  38. return problem
  39. @has_get_plot_classes
  40. class RectangularProblem(Problem):
  41. # nucleation_x
  42. # nucleation_y
  43. # time
  44. # stf
  45. problem_parameters = [
  46. Parameter('east_shift', 'm', label='Easting', **as_km),
  47. Parameter('north_shift', 'm', label='Northing', **as_km),
  48. Parameter('depth', 'm', label='Depth', **as_km),
  49. Parameter('length', 'm', label='Length', **as_km),
  50. Parameter('width', 'm', label='Width', **as_km),
  51. Parameter('slip', 'm', label='Slip'),
  52. Parameter('strike', 'deg', label='Strike'),
  53. Parameter('dip', 'deg', label='Dip'),
  54. Parameter('rake', 'deg', label='Rake')
  55. ]
  56. problem_waveform_parameters = [
  57. Parameter('nucleation_x', 'offset', label='Nucleation X'),
  58. Parameter('nucleation_y', 'offset', label='Nucleation Y'),
  59. Parameter('time', 's', label='Time'),
  60. ]
  61. dependants = []
  62. distance_min = Float.T(default=0.0)
  63. def pack(self, source):
  64. arr = self.get_parameter_array(source)
  65. for ip, p in enumerate(self.parameters):
  66. if p.name == 'time':
  67. arr[ip] -= self.base_source.time
  68. return arr
  69. def get_source(self, x):
  70. d = self.get_parameter_dict(x)
  71. p = {}
  72. for k in self.base_source.keys():
  73. if k in d:
  74. p[k] = float(
  75. self.ranges[k].make_relative(self.base_source[k], d[k]))
  76. source = self.base_source.clone(**p)
  77. return source
  78. def random_uniform(self, xbounds, rstate, fixed_magnitude=None):
  79. if fixed_magnitude is not None:
  80. raise GrondError(
  81. 'Setting fixed magnitude in random model generation not '
  82. 'supported for this type of problem.')
  83. x = num.zeros(self.nparameters)
  84. for i in range(self.nparameters):
  85. x[i] = rstate.uniform(xbounds[i, 0], xbounds[i, 1])
  86. return x
  87. def preconstrain(self, x):
  88. # source = self.get_source(x)
  89. # if any(self.distance_min > source.distance_to(t)
  90. # for t in self.targets):
  91. # raise Forbidden()
  92. return x
  93. @classmethod
  94. def get_plot_classes(cls):
  95. plots = super(RectangularProblem, cls).get_plot_classes()
  96. return plots
  97. __all__ = '''
  98. RectangularProblem
  99. RectangularProblemConfig
  100. '''.split()