Skip to content

Commit

Permalink
change function to read in presample stress and fault points
Browse files Browse the repository at this point in the history
  • Loading branch information
wangwj679 committed Jun 5, 2024
1 parent 3fa7fb1 commit da625e0
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 11 deletions.
70 changes: 60 additions & 10 deletions SOSAT/risk_analysis/user_prescribed_fault.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,32 @@ def CreateOrientations(self, Nsamples=1e6):

return n_shmax, n_fault, n_fault_p, ss_azi, strike_fault, dip_fault

def EvaluatePfail(self, Npressures=20, Nsamples=1e6):
def SampleStressPoints(self, Nsamples=1e6):
"""
A method to sample three principal stress points
from the joint stress posterior distribution
Parameters
----------
Nsamples : int
The number of stress samples to use for the analysis
Returns
-------
shmin, shmax, sv: arrays containing samples of the three
principal stress
"""
Nsamples = int(Nsamples)
# generate samples of stress state
stress_sampler = RejectionSampler(self.ss)
shmin, shmax, sv = stress_sampler.GenerateSamples(Nsamples)

return shmin, shmax, sv

def EvaluatePfail(self, Npressures=20, Nsamples=1e6,
shmin=None, shmax=None, sv=None,
n_fault_p=None):
"""
A method to evaluate the failure probability at pressures
between the native pore pressure at self.dPmax.
Expand All @@ -267,6 +292,16 @@ def EvaluatePfail(self, Npressures=20, Nsamples=1e6):
Nsamples : int
The number of stress samples to use for the analysis
shmin, shmax, sv: `numpy.ndarray`
arrays containing samples of the three
principal stress; default to be None; They can be calculated
using self.SampleStressPoints(Nsamples=1e6)
n_fault_p: `numpy.ndarray`
array containing the fault normal vectors in the
principal coordinate system; default to be None;
It can be calculated using self.CreateOrientations(Nsamples=1e6)
Returns
-------
P, pfail : `numpy.ndarray`
Expand All @@ -276,9 +311,13 @@ def EvaluatePfail(self, Npressures=20, Nsamples=1e6):
Nsamples = int(Nsamples)
Npressures = int(Npressures)

# Generate samples of stress state magnitudes
stress_sampler = RejectionSampler(self.ss)
shmin, shmax, sv = stress_sampler.GenerateSamples(Nsamples)
# generate samples of stress state if there is no stress inputs
if shmin is None or shmax is None or sv is None:
stress_sampler = RejectionSampler(self.ss)
shmin, shmax, sv = stress_sampler.GenerateSamples(Nsamples)
else:
# make sure the Nsamples equals to the given length of shmin
Nsamples = len(sv)

# Generate samples of stress path coefficients
gamma = self.gamma_dist.rvs(Nsamples)
Expand All @@ -287,8 +326,16 @@ def EvaluatePfail(self, Npressures=20, Nsamples=1e6):
mu = self.mu_dist.rvs(Nsamples)

# Create orientations for stress state and fault
n_shmax, n_fault, n_fault_p, ss_azi, strike_fault, dip_fault = \
self.CreateOrientations(Nsamples)
if n_fault_p is None:
_, _, n_fault_p, _, _, _ = \
self.CreateOrientations(Nsamples)
elif len(n_fault_p) != Nsamples:
error_message = 'The number of fault samples inputted should \
equal to the number of stress samples. \
Use the regenerated fault samples instead.'
print(error_message)
_, _, n_fault_p, _, _, _ = \
self.CreateOrientations(Nsamples)

Po = self.ss.pore_pressure
dP_array = np.linspace(0.0, self.dPmax, Npressures)
Expand Down Expand Up @@ -327,14 +374,17 @@ def EvaluatePfail(self, Npressures=20, Nsamples=1e6):
def PlotFailureProbability(self,
Npressures=20,
Nsamples=1e6,
figwidth=5.0):
figwidth=5.0,
n_fault_p=None):

P, Pfail = self.EvaluatePfail(Npressures, Nsamples)
P, Pfail = self.EvaluatePfail(Npressures, Nsamples,
n_fault_p=n_fault_p)
dP = P - self.ss.pore_pressure

fig = plt.figure(figsize=(figwidth, figwidth * 0.7))
ax = fig.add_subplot(111)
ax.plot(P, Pfail, "k")
ax.set_xlabel("Pore Pressure")
ax.plot(dP, Pfail, "k") # change to plot dP versus Pfail
ax.set_xlabel("Pore Pressure Change (" + self.ss.stress_unit + ")")
ax.set_ylabel("Probability of Fault Activation")
plt.tight_layout()

Expand Down
26 changes: 25 additions & 1 deletion tests/risk_analysis/test_user_fault_activation_risk.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ def test_upfa():
fault_K=fault_K)
n_shmax, n_fault, n_fault_p, ss_azi, strike_fault, dip_fault =\
upfa.CreateOrientations()

# case 1: didn't pre-sample stress and fault points
pressures, Pfail = upfa.EvaluatePfail()

print("mean ss_azi = ", np.mean(ss_azi))
Expand All @@ -59,6 +61,28 @@ def test_upfa():
pressures[-1] == pytest.approx(ss.pore_pressure + dPmax)
Pfail[-1] == pytest.approx(0.5153, rel=0.5e-1)

fig = upfa.PlotFailureProbability()
# case 2: pre-sample stress points
shmin, shmax, sv = upfa.SampleStressPoints()
pressures, Pfail = upfa.EvaluatePfail(
shmin=shmin, shmax=shmax, sv=sv)

pressures[0] == pytest.approx(12.227, rel=1e-2)
Pfail[0] == pytest.approx(0.0533, rel=0.5e-1)
pressures[-1] == pytest.approx(ss.pore_pressure + dPmax)
Pfail[-1] == pytest.approx(0.5153, rel=0.5e-1)

# case 3: pre-sample stress points and fault points
_, _, n_fault_p, _, _, _ = upfa.CreateOrientations()
pressures, Pfail = upfa.EvaluatePfail(
shmin=shmin, shmax=shmax, sv=sv, n_fault_p=n_fault_p)

pressures[0] == pytest.approx(12.227, rel=1e-2)
Pfail[0] == pytest.approx(0.0533, rel=0.5e-1)
pressures[-1] == pytest.approx(ss.pore_pressure + dPmax)
Pfail[-1] == pytest.approx(0.5153, rel=0.5e-1)

fig = upfa.PlotFailureProbability()
fig.savefig("User_Fault_Activation_Probability.png")

fig = upfa.PlotFailureProbability(n_fault_p=n_fault_p)
fig.savefig("User_Fault_Activation_Probability_inputfault.png")

0 comments on commit da625e0

Please sign in to comment.