Computer Science with Applications 1 & 2

Buoyancy

Due: Monday, Oct. 25th at 10pm

When designing the Oasis of the Sea, the world's largest cruise ship, engineers needed to ensure that the ship could clear the Great Belt Fixed Link, a low bridge in Denmark, as it traveled from Finland to Florida. To make sure the ship would clear the bridge safely, engineers needed to determine how high the ship would sit in the water and how much water it would displace. Precision was essential as the ship cleared the bridge by less than two feet.

In this assignment you will use adaptive integration and the principals of buoyancy to determine the draft of a ship, that is, how high it sits in the water.

You may work alone or in a pair.

Using adaptive integration

The trapezoid rule is one way to approximate the area under a curve f(x) on the interval [a,b]:
  • Divide the interval into subintervals of various widths. Let S = {x0, x1, ... , xn} be the set of endpoints of subintervals in [a,b].
  • Approximate the area of f(x) on each subinterval, [xm-1, xm], using a trapezoid:
  • Sum over the subinterval approximations:

How do you choose the sub-intervals? One possibility is to spread the sub-intervals uniformly across the interval. This approach can waste computation when a very small sub-interval may be required to get a good approximation in some parts of the curve, but not in others. An alternative approach, called adaptive integration uses recursion to choose different sub-interval sizes for different parts of the curve depending on the quality of the approximation for given part of the curve.

The idea behind adaptive integration is: given an interval compare the approximation for that interval obtained using the trapezoid rule with the result obtained by splitting the interval in two and applying the trapezoid rules to both halves. 

To set bounds on the size of a sub-interval, we can use an extra parameter, level, to track the depth of the recursion. To ensure that intervals are at least of a particular size (ensuring some degree of accuracy), we will continue to split the interval (even if the approximation is good enough) until the level is at least MIN_LEVEL. To limit the minimum size for an interval, we will stop when the level reaches MAX_LEVEL (even if the approximation is above the tolerance).

We have provided a skeleton for your adaptive integration code in Integral.java. Note: The type of f, the function you are integrating, will be Dbl2Dbl. The Dbl2Dbl interface specifies that any class that implements it must provide a value method for evaluating the function, To obtain the value of f(x), use the expression f.value(x).

Hint #1: You will need to write a helper function that takes the atrap arguments plus the extra level argument. This helper function does the real work necessary to integrate. atrap merely calls the helper function with the appropriate arguments and then returns the result.

Hint #2: atrap's tolerance parameter specifies the error tolerance over the whole integral. What are the implications of that definition for how you process sub-intervals?

The main function of Integral.java contains test cases for your integration code. Make sure you pass these tests before moving on.

Our implementation, including the helper function, is roughly 30 lines of code.

 

Determining the draft of a ship in water

Complete the function draft in ShipDraft.java. This function should compute the draft of a ship

The draft of a boat is the depth of water needed to float the boat. From Archimedes Principle, we know that the weight of water that a floating object displaces is equal to the weight of the object. The weight of the displaced water is the volume times the density of the water (1027 kg/m^3 for salt water). Let a be the vertical location of the bottom of the object defined by f. If this object has water up a distance d from the bottom of the object then the volume of water that is being displaced is the integral of a function f(x) on the interval[a,a+d]. Thus if w is the weight of the object we want to find the root of the function

Equation 1 
where f is the function determining the object's hull or outer boundary. This root tells us the draft of the object. If the object does not float, the function is always negative, so we cannot find a root. If we know the object floats, we know that h is negative at d=0 and positive when d is the height of the object.

You can use two methods to find the root of the function. The most straight-forward, but not the most efficient, way is start at the bottom of the object (d=0) and slowly grow it in increments until h(d) crosses from negative to positive. I would recommend using a step-size that is one one thousandth of the height of the object (height*.001).

A much better method is to use bisection, which evaluates the function h at the middle of an interval containing the root and selects a new interval containing the root based in the sign of the middle value. Each pass decreases the length of the interval by a factor of two. You should stop when the length of the interval is short enough. You will need to decide when to stop bisecting, it probably is sufficient to get the draft to a half a percent of the height of the object.

You can use either method.

We have provided test code in ShipDraft.java

Our implementations of these methods are under 15 lines of code each.

Getting started:

We have seeded your PhoenixForge account with a directory named hw3 that contains the following files:

You will modify Integral.java and ShipDraft.java, but not any of the other files.

Just for your information, the file Ship.java contains a class for representing the ship. The remaining files contain classes will allow you to implement and test a version of adaptive integration that will work for any function of one variable, not just the ship function.

Submission

To submit, check your code into your PhoenixForge account. We strongly recommend that you check your code into GForge at regular intervals!