def test_success(): # should fail because z is positive success, u, grad_u = dc3d0wrapper(1.0, [0.0, 0.0, 1.0], 1.0, 90, [1.0, 0.0, 0.0, 0.0]) assert (success == 2) success, u, grad_u = dc3dwrapper(1.0, [0.0, 0.0, 1.0], 0.0, 90, [-0.7, 0.7], [-0.7, 0.7], [1.0, 0.0, 0.0]) assert (success == 2)
def test_success(): # should fail because z is positive success, u, grad_u = dc3d0wrapper(1.0, [0.0, 0.0, 1.0], 1.0, 90, [1.0, 0.0, 0.0, 0.0]); assert(success == 2) success, u, grad_u = dc3dwrapper(1.0, [0.0, 0.0, 1.0], 0.0, 90, [-0.7, 0.7], [-0.7, 0.7], [1.0, 0.0, 0.0]) assert(success == 2)
def compute_surface_disp_point(params, inputs, x, y): # A major compute loop for each source object at an x/y point. # x/y in the same coordinate system as the fault object. u_disp = 0 v_disp = 0 w_disp = 0 for fault in inputs.source_object: # Fault parameters L = conversion_math.get_strike_length(fault.xstart, fault.xfinish, fault.ystart, fault.yfinish) W = conversion_math.get_downdip_width(fault.top, fault.bottom, fault.dipangle) depth = fault.top dip = fault.dipangle strike_slip = fault.rtlat * -1 # The dc3d coordinate system has left-lateral positive. dip_slip = fault.reverse # Preparing to rotate to a fault-oriented coordinate system. theta = fault.strike - 90 theta = np.deg2rad(theta) R = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]) R2 = np.array([[np.cos(-theta), -np.sin(-theta)], [np.sin(-theta), np.cos(-theta)]]) # Compute the position relative to the translated, rotated fault. translated_pos = np.array([[x - fault.xstart], [y - fault.ystart]]) xy = R.dot(translated_pos) # Solve for displacements at the surface if fault.potency != []: success, u, grad_u = dc3d0wrapper( params.alpha, [xy[0], xy[1], 0.0], depth, dip, [ fault.potency[0], fault.potency[1], fault.potency[2], fault.potency[3] ]) u = u * 1e-6 # Unit correction: potency from N-m results in displacements in microns. else: success, u, grad_u = dc3dwrapper(params.alpha, [xy[0], xy[1], 0.0], depth, dip, [0, L], [-W, 0], [strike_slip, dip_slip, 0.0]) urot = R2.dot(np.array([[u[0]], [u[1]]])) # Update the displacements from all sources u_disp = u_disp + urot[0] v_disp = v_disp + urot[1] w_disp = w_disp + u[2] # vertical return u_disp, v_disp, w_disp
def compute_strains_stresses_from_one_fault(source, x, y, z, alpha): """ The main math of DC3D Operates on a source object (e.g., fault), and an xyz position in the same cartesian reference frame. """ L = fault_vector_functions.get_strike_length(source.xstart, source.xfinish, source.ystart, source.yfinish) W = fault_vector_functions.get_downdip_width(source.top, source.bottom, source.dipangle) depth = source.top dip = source.dipangle strike_slip = source.rtlat * -1 # The dc3d coordinate system has left-lateral positive. dip_slip = source.reverse # Preparing to rotate to a fault-oriented coordinate system. theta = source.strike - 90 theta = np.deg2rad(theta) R = np.array([[np.cos(theta), -np.sin(theta), 0], [np.sin(theta), np.cos(theta), 0], [0, 0, 1]]) # horizontal rotation into strike-aligned coordinates. R2 = np.array([[np.cos(-theta), -np.sin(-theta), 0], [np.sin(-theta), np.cos(-theta), 0], [0, 0, 1]]) # Compute the position relative to the translated, rotated fault. translated_pos = np.array([[x - source.xstart], [y - source.ystart], [-z]]) xyz = R.dot(translated_pos) if source.potency: success, u, grad_u = dc3d0wrapper( alpha, [xyz[0], xyz[1], xyz[2]], depth, dip, [ source.potency[0], source.potency[1], source.potency[2], source.potency[3] ]) grad_u = grad_u * 1e-9 # DC3D0 Unit correction: potency from N-m results in strain in nanostrain u = u * 1e-6 # Unit correction: potency from N-m results in displacements in microns. else: success, u, grad_u = dc3dwrapper( alpha, [xyz[0], xyz[1], xyz[2]], depth, dip, [0, L], [-W, 0], [strike_slip, dip_slip, source.tensile]) grad_u = grad_u * 1e-3 # DC3D Unit correction. # Solve for displacement gradients at certain xyz position # Rotate grad_u back into the unprimed coordinates. desired_coords_grad_u = np.dot(R2, np.dot(grad_u, R2.T)) desired_coords_u = R2.dot(np.array([[u[0]], [u[1]], [u[2]]])) return desired_coords_grad_u, desired_coords_u
def test_dc3d0(): source_depth, obs_depth, poisson_ratio, mu, dip, alpha = get_params() n = (100, 100) x = linspace(-1, 1, n[0]) y = linspace(-1, 1, n[1]) ux = zeros((n[0], n[1])) for i in range(100): for j in range(100): success, u, grad_u = dc3d0wrapper(alpha, [x[i], y[j], -obs_depth], source_depth, dip, [1.0, 0.0, 0.0, 0.0]) assert (success == 0) ux[i, j] = u[0] cntrf = contourf(x, y, log(abs(ux.T))) contour(x, y, log(abs(ux.T)), colors='k', linestyles='solid') xlabel('x') ylabel('y') cbar = colorbar(cntrf) cbar.set_label('$\log(u_{\\textrm{x}})$') show()
def test_dc3d0(): source_depth, obs_depth, poisson_ratio, mu, dip, alpha = get_params() n = (100, 100) x = linspace(-1, 1, n[0]) y = linspace(-1, 1, n[1]) ux = zeros((n[0], n[1])) for i in range(100): for j in range(100): success, u, grad_u = dc3d0wrapper(alpha, [x[i], y[j], -obs_depth], source_depth, dip, [1.0, 0.0, 0.0, 0.0]); assert(success == 0) ux[i, j] = u[0] cntrf = contourf(x, y, log(abs(ux.T))) contour(x, y, log(abs(ux.T)), colors = 'k', linestyles = 'solid') xlabel('x') ylabel('y') cbar = colorbar(cntrf) cbar.set_label('$\log(u_{\\textrm{x}})$') show()
def compute_strains_stresses(params, inputs): # Pseudocode: # For each receiver, at the center point, sum up the strain and stress for each source. # Return : source object, receiver object, shear stress, normal stress, and coulomb stress on each receiver. # The values we're actually going to output. receiver_shear = [] receiver_normal = [] receiver_coulomb = [] for receiver in inputs.receiver_object: centercoords = conversion_math.get_fault_center(receiver) normal_sum = 0 shear_sum = 0 coulomb_sum = 0 for source in inputs.source_object: # A major compute loop for each source object. L = conversion_math.get_strike_length(source.xstart, source.xfinish, source.ystart, source.yfinish) W = conversion_math.get_downdip_width(source.top, source.bottom, source.dipangle) depth = source.top dip = source.dipangle strike_slip = source.rtlat * -1 # The dc3d coordinate system has left-lateral positive. dip_slip = source.reverse # Preparing to rotate to a fault-oriented coordinate system. theta = source.strike - 90 theta = np.deg2rad(theta) R = np.array([[np.cos(theta), -np.sin(theta), 0], [np.sin(theta), np.cos(theta), 0], [0, 0, 1]]) # horizontal rotation into strike-aligned coordinates. R2 = np.array([[np.cos(-theta), -np.sin(-theta), 0], [np.sin(-theta), np.cos(-theta), 0], [0, 0, 1]]) # Compute the position relative to the translated, rotated fault. translated_pos = np.array([[centercoords[0] - source.xstart], [centercoords[1] - source.ystart], [-centercoords[2]]]) xyz = R.dot(translated_pos) if source.potency != []: success, u, grad_u = dc3d0wrapper( params.alpha, [xyz[0], xyz[1], xyz[2]], depth, dip, [ source.potency[0], source.potency[1], source.potency[2], source.potency[3] ]) grad_u = grad_u * 1e-9 # DC3D0 Unit correction: potency from N-m results in displacements in nanostrain else: success, u, grad_u = dc3dwrapper(params.alpha, [xyz[0], xyz[1], xyz[2]], depth, dip, [0, L], [-W, 0], [strike_slip, dip_slip, 0.0]) grad_u = grad_u * 1e-3 # DC3D Unit correction. # Solve for displacement gradients at center of receiver fault # Rotate grad_u back into the unprimed coordinates. Divide by 1000 because coordinate units (km) and slip units (m) are different by 1000. desired_coords_grad_u = np.dot(R2, np.dot(grad_u, R2.T)) # Then rotate again into receiver coordinates. strain_tensor = conversion_math.get_strain_tensor( desired_coords_grad_u) stress_tensor = conversion_math.get_stress_tensor( strain_tensor, params.lame1, params.mu) # Then compute shear, normal, and coulomb stresses. [normal, shear, coulomb] = conversion_math.get_coulomb_stresses( stress_tensor, receiver.strike, receiver.rake, receiver.dipangle, inputs.FRIC) normal_sum = normal_sum + normal shear_sum = shear_sum + shear coulomb_sum = coulomb_sum + coulomb receiver_normal.append(normal_sum) receiver_shear.append(shear_sum) receiver_coulomb.append(coulomb_sum) # return lists of normal, shear, coulomb values for each receiver. return [receiver_normal, receiver_shear, receiver_coulomb]