Home | Mathematics | * Applied Mathematics | * Storage Tank Modeling |     Share This Page
Trapezoidal Storage Tanks: Java Listing
The Java program source listing for trapezoidal tank computations

Copyright © 2009, Paul LutusMessage Page

(double-click any word to see its definition)

 
/**************************************************************************
 *   Copyright (C) 2009, Paul Lutus                                        *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

public class RectTankVolume {
  
  // tank dimensions
  double xb;
  double xt;
  double zb;
  double zt;
  double yb;
  double yt;
  
  double minVolume, maxVolume;
  
  // volume or height mode selector
  boolean vmode;
  
  // root finder accuracy criteria
  double rootFinderEpsilon = 1e-8;
  int rootFinderMaxTries = 64;
  
  /*
   * xb = x axis bottom width
   * xt = x axis top width
   * zb = z axis bottom width
   * zt = z axis top width
   * yb  = y bottom value
   * yt  = y top value
   * y   = y argument for volume
   *
   * computes integral between yb and y
   */
  
  double compVolume(double y) {
    return (y*(2*(xb - xt)*
        Math.pow(y,2)*(zb - zt) +
        6*(xt*yb - xb*yt)*
        (-(yt*zb) + yb*zt) +
        3*y*(-2*xb*yt*zb +
          xt*(yb + yt)*zb -
          2*xt*yb*zt + xb*
      (yb + yt)*zt))
    )/(6.*Math.pow(yb - yt,2));
  }
  
  // root finder that computes
  // height for volume argument
  double compHeight(double v) {
    // trap volume range errors
    if(v < minVolume || v > maxVolume) {
      return Double.NaN;
    }
    int n = 0;
    double dy = (yt-yb);
    // initial y must be (max + min) / 2
    double y = dy * 0.5 + yb;
    double dv;
    while(n++ < rootFinderMaxTries && Math.abs(dv = compVolume(y) - v) > rootFinderEpsilon) {
      dy *= 0.5;
      y += (dv < 0)?dy:-dy;
    }
    return y;
  }
  
  double compValue(double arg,boolean vmode) {
    return (vmode)?compVolume(arg):compHeight(arg);
  }
  
  void displayResult(String s, String os) {
    // print string only if not a
    // duplicate of prior string
    if(!s.equals(os)) {
      System.out.println(s);
    }
  }
  
  String showResult(String y, String v, String os) {
    String s = String.format("%16s,%16s",y,v);
    displayResult(s,os);
    return s;
  }
  
  String showResult(double y, double v, String os) {
    String s;
    if(Double.isNaN(v)) {
      s = String.format("%16.6f,%16s",y,"Out of Range");
    }
    else {
      s = String.format("%16.6f,%16.6f",y,v);
    }
    
    displayResult(s,os);
    return s;
  }
  
  void process(String args[]) {
    int len = args.length;
    if((len != 8 && len != 10) || (!args[0].equals("-h") && !args[0].equals("-v"))) {
      System.out.println("Usage:  -v(olume for height) or -h(eight for volume),");
      System.out.println("        x bottom width, x top width,");
      System.out.println("        z bottom width, z top width,");
      System.out.println("        y bottom value, y top value,");
      System.out.println("        single argument for one result or");
      System.out.println("        start, end, step size for table of results");
      System.out.println("        (all on one line, delimited by spaces)");
    }
    else {
      int n = 0;
      vmode = args[n++].equals("-v");
      if(vmode) {
        showResult("Height","Volume","");
      }
      else {
        showResult("Volume","Height","");
      }
      xb = Double.parseDouble(args[n++]);
      xt = Double.parseDouble(args[n++]);
      zb = Double.parseDouble(args[n++]);
      zt = Double.parseDouble(args[n++]);
      yb = Double.parseDouble(args[n++]);
      yt = Double.parseDouble(args[n++]);
      minVolume = compValue(yb,true);
      maxVolume = compValue(yt,true);
      double v,y,ys,ye,ss;
      if(len == 8) { // single-result mode
        y = Double.parseDouble(args[n++]);
        v = compValue(y,vmode);
        showResult(y,v,"");
      }
      else { // table mode
        // get y start, y end, step size
        ys  = Double.parseDouble(args[n++]);
        ye  = Double.parseDouble(args[n++]);
        ss  = Double.parseDouble(args[n++]);
        // table of results between a and b inclusive
        String s = "";
        for(y = ys;y <= ye;y += ss) {
          v = compValue(y,vmode);
          s = showResult(y,v,"");
        }
        // show a final table value only if it
        // won't duplicate the prior value
        v = compValue(ye,vmode);
        s = showResult(ye,v,s);
      } // end table mode block
    }
  }
  
  static public void main(String[] args) throws Exception {
    new RectTankVolume().process(args);
  }
};
 

Home | Mathematics | * Applied Mathematics | * Storage Tank Modeling |     Share This Page