First challenge is to 'construct' earth dam itself, let's do it using @whuber idea. Add minimum and maximum elevation values to location line connecting same elevation contours:
Convert line to raster and expand it by few cells, call it DAM_FLAT_TOP. We need dam to be flat on the top for trucks/cars access. Expand it by 1 cell and call it BIGGER_TOP. Compute Euclidean distance to DAM_FLAT_TOP and use raster calculator to compute intermediate raster called SLOPES:
43.0-"e_Distance"/2
43 here is average of [55,32], 2 defines the slopes of dam, i.e. rise/run here is 1/2.
Compute new DEM using:
Con("SLOPES" > "DEM","SLOPES","DEM")
Use Hydrology Fill to compute depth and extent of old and new depressions:
Con("FILLED" > "new_DEM",1) ---> LAKES
Con("FILLED" > "new_DEM","FILLED" - "new_DEM") ---> DEPTH
Isolate just one lake upstream from dam:
CostAllocation_sa("BIGGER_TOP", "LAKES", "thisLake")
Note the use of BIGGER_TOP.
Run zonal statistics as table to get volume of that lake:
in this case it is 4.620094*79812 = 368738
So, modify script below to get accurate elevation estimate for your target volume.
Note extra bonus: compare new DEM with original to estimate amount of earthwork required. You might pick another dam location if too much work needed.
from arcpy.sa import *
from arcpy import env
env.overwriteOutput = True
env.workspace = "in_memory"
bottom,top = 32.0,55.0
targetVolume = 250000
eDistance = Raster('e_Distance')
DEM = Raster("DEM")
bigTOP = Raster("BIGGER_TOP")
outTable = "in_memory/abc"
arcpy.management.Delete("in_memory")
while True:
arcpy.management.Delete("in_memory")
mid = (top+bottom)/2
SLOPES = mid - eDistance/2
newDEM = Con(SLOPES > DEM, SLOPES,DEM)
newDEM.save("Filled")
Filled = Fill(newDEM)
LAKES = Con(Filled>newDEM,1)
LAKES.save("LAKES")
DEPTH = Con(Filled>newDEM,Filled-newDEM)
DEPTH.save("DEPTH")
del Filled
thisLake = CostAllocation(bigTOP, "LAKES", "", "", "", "Value")
thisLake.save("thisLake")
arcpy.gp.ZonalStatisticsAsTable_sa("thisLake", "Value", "DEPTH", outTable, "DATA", "MEAN")
A,D = arcpy.da.TableToNumPyArray(outTable,("AREA","MEAN"))[0]
volume = A*D
arcpy.AddMessage("Current volume = %i" %volume)
if top-bottom <0.1:break
if volume>targetVolume:top=mid
else:bottom=mid
arcpy.management.Delete("in_memory")
arcpy.AddMessage("Use elevation of %s" %mid)
Script messages:
Current volume = 408901
Current volume = 90259
Current volume = 212356
Current volume = 299914
Current volume = 253515
Current volume = 232290
Current volume = 242747
Current volume = 248087
Current volume = 250793
Use elevation of 41.298828125
As one can see it took 9 iterations to find solution with 10cm accuracy for possible range of values equal to 33m(!)