Skip to content

Commit

Permalink
point source experiments
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin Milner committed Jun 27, 2024
1 parent d22833a commit 4e247d5
Show file tree
Hide file tree
Showing 4 changed files with 2,125 additions and 287 deletions.
134 changes: 134 additions & 0 deletions src/main/java/scratch/kevin/pointSources/DistCalcBenchmark.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package scratch.kevin.pointSources;

import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.jfree.data.Range;
import org.opensha.commons.calc.magScalingRelations.MagLengthRelationship;
import org.opensha.commons.calc.magScalingRelations.magScalingRelImpl.WC1994_MagLengthRelationship;
import org.opensha.commons.data.function.DiscretizedFunc;
import org.opensha.commons.data.function.EvenlyDiscretizedFunc;
import org.opensha.commons.geo.Location;
import org.opensha.commons.gui.plot.HeadlessGraphPanel;
import org.opensha.commons.gui.plot.PlotCurveCharacterstics;
import org.opensha.commons.gui.plot.PlotLineType;
import org.opensha.commons.gui.plot.PlotSpec;
import org.opensha.commons.gui.plot.PlotUtils;
import org.opensha.commons.mapping.gmt.elements.GMT_CPT_Files;
import org.opensha.commons.util.cpt.CPT;
import org.opensha.sha.faultSurface.RuptureSurface;

import com.google.common.base.Stopwatch;

class DistCalcBenchmark {

private enum SurfType {
PT_SURF_FOOTWALL("Point Surface (footwall)"),
PT_SURF_HANGING_WALL("Point Surface (hanging wall)"),
FINITE_QUAD("Finite Quad Surface"),
FINITE_GRIDDED("Finite Gridded Surface");

private String label;

private SurfType(String label) {
this.label = label;
}

public RuptureSurface buildSurface(PointSurfaceBuilder builder) {
switch (this) {
case PT_SURF_FOOTWALL:
builder.footwall(true);
return builder.buildPointSurface();
case PT_SURF_HANGING_WALL:
builder.footwall(false);
return builder.buildPointSurface();
case FINITE_GRIDDED:
return builder.buildGriddedSurface();
case FINITE_QUAD:
return builder.buildQuadSurface();

default:
throw new IllegalStateException();
}
}
}

public static void main(String[] args) throws IOException {
PointSurfaceBuilder builder = new PointSurfaceBuilder(new Location(0d, 0d));

EvenlyDiscretizedFunc refFunc = new EvenlyDiscretizedFunc(5d, 8.5d, 30);

SurfType[] types = SurfType.values();
EvenlyDiscretizedFunc[] timeFuncs = new EvenlyDiscretizedFunc[types.length];
for (int i=0; i<types.length; i++) {
timeFuncs[i] = refFunc.deepClone();
timeFuncs[i].setName(types[i].label);
}

MagLengthRelationship WC94 = new WC1994_MagLengthRelationship();

builder.dip(90d);
builder.strike(0d);

Location[] testLocs = new Location[100000];
for (int i=0; i<testLocs.length; i++)
testLocs[i] = new Location(2*Math.random() - 1d, 2*Math.random() - 1d);

// start at -1 to do a burn in run first that we discard
for (int i=-1; i<refFunc.size(); i++) {
double mag = i >= 0 ? refFunc.getX(i) : refFunc.getMaxX();
System.out.println("Doing M"+(mag));

double length = WC94.getMedianLength(mag);
double aspectWidth = length / 1.5;

builder.length(length);
builder.upperDepth(0);
builder.lowerDepth(Math.min(aspectWidth, 14d));

for (int t=0; t<types.length; t++) {
RuptureSurface surf = types[t].buildSurface(builder);

Stopwatch watch = Stopwatch.createStarted();
for (Location loc : testLocs) {
surf.getDistanceJB(loc);
surf.getDistanceRup(loc);
surf.getDistanceX(loc);
}
watch.stop();

double secs = watch.elapsed(TimeUnit.MILLISECONDS)/1000d;
if (i >= 0)
timeFuncs[t].set(i, secs);
}
}

List<DiscretizedFunc> funcs = new ArrayList<>();
List<PlotCurveCharacterstics> chars = new ArrayList<>();

CPT cpt = GMT_CPT_Files.CATEGORICAL_BATLOW_UNIFORM.instance();
double maxY = 0d;
for (int i=0; i<timeFuncs.length; i++) {
maxY = Math.max(maxY, timeFuncs[i].getMaxY());
funcs.add(timeFuncs[i]);
Color color = cpt.get(i).minColor;
chars.add(new PlotCurveCharacterstics(PlotLineType.SOLID, 3f, color));
}

PlotSpec spec = new PlotSpec(funcs, chars, " ", "Magnitude", "Time For "+testLocs.length+" Distance Calcs (s)");
spec.setLegendVisible(true);

HeadlessGraphPanel gp = PlotUtils.initHeadless();

Range xRange = new Range(refFunc.getMinX(), refFunc.getMaxX());
Range yRange = new Range(0d, maxY*1.2);
gp.drawGraphPanel(spec, false, false, xRange, yRange);

PlotUtils.writePlots(new File("/tmp"), "pt_src_dist_calcs", gp, 800, 800, true, false, false);
}

}
153 changes: 153 additions & 0 deletions src/main/java/scratch/kevin/pointSources/FiniteApproxPointSurface.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package scratch.kevin.pointSources;

import org.opensha.commons.exceptions.InvalidRangeException;
import org.opensha.commons.geo.Location;
import org.opensha.commons.geo.Region;
import org.opensha.sha.earthquake.rupForecastImpl.PointSource13b.PointSurface13b;
import org.opensha.sha.faultSurface.PointSurface;
import org.opensha.sha.faultSurface.utils.GriddedSurfaceUtils;
import org.opensha.sha.faultSurface.utils.PtSrcDistCorr;

/**
* Point surface implementation that approximates finite surfaces when calculating 3-D distances (e.g., rRup and
* rSeis). It relies on the {@link PtSrcDistCorr} setting to calculate overall distance corrections (applied to rJB).
*
* Sign of rX is set according to the passed in footwall boolean.
*
* Based on {@link PointSurface13b}
*/
public class FiniteApproxPointSurface extends PointSurface {

// inputs
private double zTop;
private double zBot;
private boolean footwall;
private double length;

// calculated
private double dipRad;
private double horzWidth;

public FiniteApproxPointSurface(Location loc, double dip, double zTop, double zBot, boolean footwall, double length) {
super(loc);
this.aveDip = dip;
this.zTop = zTop;
this.zBot = zBot;
this.footwall = footwall;
this.length = length;

dipRad = Math.toRadians(dip);
calcWidths();
}

private void calcWidths() {
if (aveDip == 90d || zBot == zTop) {
aveWidth = zBot - zTop;
horzWidth = 0d;
} else {
aveWidth = (zBot-zTop)/Math.sin(dipRad);
horzWidth = aveWidth * Math.cos(dipRad);
}
}

@Override
public double getAveRupTopDepth() {
return getDepth();
}

@Override
public double getDepth() {
// overridden to not key depth to point location
return zTop;
}

@Override
public void setDepth(double depth) {
// overridden to not cause creation of new Location in parent
zTop = depth;
// recalculate widths
calcWidths();
}

@Override
public void setAveDip(double aveDip) throws InvalidRangeException {
super.setAveDip(aveDip);
// recalculate widths
calcWidths();
}

@Override
public void setAveWidth(double aveWidth) {
throw new UnsupportedOperationException("Width is calculated, cannot be set");
}

@Override
public double getAveLength() {
return length;
}

@Override
public double getArea() {
return getAveLength() * getAveWidth();
}

@Override
public double getAreaInsideRegion(Region region) {
if (region.contains(getLocation()))
return getArea();
return 0d;
}

@Override
public double getDistanceX(Location loc) {
double rJB = getDistanceJB(loc);
return footwall ? -rJB : rJB + horzWidth;
}

@Override
public double getDistanceRup(Location loc) {
double rJB = getDistanceJB(loc);

return getDistanceRup(rJB);
}

public double getDistanceRup(double rJB) {
return getCorrDistRup(rJB, zTop, zBot, dipRad, horzWidth, footwall);
}

@Override
public double getDistanceSeis(Location loc) {
double rJB = getDistanceJB(loc);

return getCorrDistRup(rJB, Math.max(GriddedSurfaceUtils.SEIS_DEPTH, zTop),
Math.max(GriddedSurfaceUtils.SEIS_DEPTH, zBot), dipRad, horzWidth, footwall);
}

public static double getCorrDistRup(double rJB, double zTop, double zBot, double dipRad, double horzWidth, boolean footwall) {
if (footwall) return hypot2(rJB, zTop);

double rCut = zBot * Math.tan(dipRad);

if (rJB > rCut) return hypot2(rJB, zBot);

// rRup when rJB is 0 -- we take the minimum the site-to-top-edge
// and site-to-normal of rupture for the site being directly over
// the down-dip edge of the rupture
double rRup0 = Math.min(hypot2(horzWidth, zTop), zBot * Math.cos(dipRad));
// rRup at cutoff rJB
double rRupC = zBot / Math.cos(dipRad);
// scale linearly with rJB distance
return (rRupC - rRup0) * rJB / rCut + rRup0;
}

public boolean isOnFootwall() {
return footwall;
}

/**
* Same as {@code Math.hypot()} without regard to under/over flow.
*/
private static final double hypot2(double v1, double v2) {
return Math.sqrt(v1 * v1 + v2 * v2);
}
}
Loading

0 comments on commit 4e247d5

Please sign in to comment.