-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Kevin Milner
committed
Jun 27, 2024
1 parent
d22833a
commit 4e247d5
Showing
4 changed files
with
2,125 additions
and
287 deletions.
There are no files selected for viewing
134 changes: 134 additions & 0 deletions
134
src/main/java/scratch/kevin/pointSources/DistCalcBenchmark.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
153
src/main/java/scratch/kevin/pointSources/FiniteApproxPointSurface.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
Oops, something went wrong.