# Volume of a graph

I have the following list:

AA={
{0.,0.,0.,0.,0.,0.,0.,0.},
{0.,-10.9421,-17.3061,-19.0045,-19.0045,-17.3061,-10.9421,0.},
{0.,-16.8109,-27.6012,-24.8577,-24.8577,-27.6012,-16.8109,0.},
{0.,-19.9862,-34.0245,-28.3369,-28.3369,-34.0245,-19.9862,0.},
{0.,-19.9862,-34.0245,-28.3369,-28.3369,-34.0245,-19.9862,0.},
{0.,-16.8109,-27.6012,-24.8577,-24.8577,-27.6012,-16.8109,0.},
{0.,-10.9421,-17.3061,-19.0045,-19.0045,-17.3061,-10.9421,0.},
{0.,0.,0.,0.,0.,0.,0.,0.}
};


This list is the input for a 3D Plot:

ListPlot3D[AA, DataRange -> {{0, 4000}, {0, 4000}},
InterpolationOrder -> 1, Filling -> Axis, PlotRange -> All]


How can I calculate the volume of this graph? I've tried NIntegrate but it didn't work out for me.

-
Define "didnt' work." What happened? Can you give more details on what you tried? – rcollyer Aug 12 '13 at 14:36

If you want the volume for InterpolationOrder -> 1, you can use the fact that volume of a segment over a subrectangle is the area of the base times the mean of the altitudes of the four vertices.

In your case, the total 4000 x 4000 area is divided into 7 x 7 rectangles.

(4000/7)^2 * Total[Partition[AA, {2, 2}, {1, 1}], 4]/4 // Abs
(* 2.59749*10^8 *)


Comparing with Mark McClure's method (and adjusting the InterpolationOrder) we see they agree.

indexedData = Flatten[MapIndexed[{4000 (#2[[1]] - 1)/7, 4000 (#2[[2]] - 1)/7, #} &,
AA, {2}], 1];
if = Interpolation[indexedData, InterpolationOrder -> 1];
Abs[NIntegrate[if[x, y], {x, 0, 4000}, {y, 0, 4000}]]
(* 2.59749*10^8 *)


In the special case of linear interpolation, this direct method sometimes has an advantage over NIntegrate:

n = 100;
data = Accumulate[Accumulate /@ RandomReal[0.1, {n, n}]];

indexedData = Flatten[MapIndexed[{#2[[1]], #2[[2]], #} &, data, {2}], 1];
if = Interpolation[indexedData, InterpolationOrder -> 1];
Abs[NIntegrate[if[x, y], {x, 1, n}, {y, 1, n}]] // Timing

(* NIntegrate::slwcon, NIntegrate::eincr messages *)
(* {3.515700, 1.23965*10^6} *)

Total[Partition[data, {2, 2}, {1, 1}], 4]/4 // Timing
(* {0.001392, 1.23965*10^6} *)

-

You can use Interpolation to construct a function from your data that can be passed to NIntegrate. Here's how:

data={
{0.,0.,0.,0.,0.,0.,0.,0.},
{0.,-10.9421,-17.3061,-19.0045,-19.0045,-17.3061,-10.9421,0.},
{0.,-16.8109,-27.6012,-24.8577,-24.8577,-27.6012,-16.8109,0.},
{0.,-19.9862,-34.0245,-28.3369,-28.3369,-34.0245,-19.9862,0.},
{0.,-19.9862,-34.0245,-28.3369,-28.3369,-34.0245,-19.9862,0.},
{0.,-16.8109,-27.6012,-24.8577,-24.8577,-27.6012,-16.8109,0.},
{0.,-10.9421,-17.3061,-19.0045,-19.0045,-17.3061,-10.9421,0.},
{0.,0.,0.,0.,0.,0.,0.,0.}
};
indexedData = Flatten[
MapIndexed[{4000(#2[[1]]-1)/7,4000(#2[[2]]-1)/7,#}&,data,{2}],
1];
if = Interpolation[indexedData];
Plot3D[if[x, y], {x, 0, 4000}, {y, 0, 4000}]


Note that the plot looks just like your ListPlot. Now, we can NIntegrate it:

Abs[NIntegrate[if[x, y], {x, 0, 4000}, {y, 0, 4000}]]

(* Out: 2.72285*10^8 *)

-