University of California, Berkeley
E119 Applied Java Programming
Spring 2000
by
Professor Carey
Project Four
Team Members :
Eric Wang
Michael Whelton
April 12, 2000
1. Work Breakdown Structure
Eric / Michael / Joint workCalculation / Graphics / Deliverables
2. Program Source Code
A copy of the program is enclosed as follows. It includes comment statements documenting the variables and procedures used.
/****************************************************************
* iwallmodified.java is a program that computes and prints to
* the console window or an output file
* It is developed by Michael Whelton and Eric Wang at University of California,
* Berkeley in April 2000
/ *****************************************************************/
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.text.*;
//CCCCCCCCC class definition for statept which
// holds variables for a state point
class statept {
// default constructor is supplied by Java
// define variables used by this class here
double t;
double x;
double y;
}
//EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
class InputFrame extends JFrame
{
public InputFrame() // constructor
{
super();
setTitle("newiwall Input"); // sets titlebar acros top of window
setBounds(100, 150, 300, 600); // sets initial window size
// and location
// this makes the window closeable
WindowListener exitOnClose1 = new Terminator();
addWindowListener(exitOnClose1);
Container contentPane = getContentPane();
contentPane.add(new ButtonPanel()); // add ButtonPanel to InputFrame
}
}
//EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
//CCCCCCCCC class defintion for panel on which we put input stuff
class ButtonPanel extends JPanel
implements ActionListener
{
public ButtonPanel() // constructor
{
super();
setBackground(Color.lightGray);
// this specifies a layout with 6 rows and two columns
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
// statements below add labels, buttons and textfields to the panel
label0 = new JLabel(" PROGRAM INPUT ", JLabel.LEFT);
label0.setForeground(Color.red);
add(label0);
runButton = new JButton("Run Program");
Color blueGreen = new Color(0,128,128);
runButton.setBackground(Color.yellow);
add(runButton);
runButton.addActionListener(this);
label00=new JLabel("Initial Inside Temperature is:", JLabel.LEFT);
label00.setForeground(Color.blue);
textField00=new JTextField("600",4);
add(label00);
add(textField00);
label1 = new JLabel("Time step (Delt T) is: ",
JLabel.LEFT);
label1.setForeground(Color.blue);
textField1 = new JTextField("2.000",5);
add(label1);
add(textField1);
label2 = new JLabel("Delt X is: ",
JLabel.LEFT);
label2.setForeground(Color.blue);
textField2 = new JTextField("0.0025",6);
add(label2);
add(textField2);
label3 = new JLabel("Delt Y is: ", JLabel.LEFT);
label3.setForeground(Color.blue);
add(label3);
textField3 = new JTextField("0.0025", 6);
add(textField3);
label4=new JLabel("Number of nodes in X direction:", JLabel.LEFT);
label4.setForeground(Color.blue);
textField4 = new JTextField("41",2);
add(label4);
add(textField4);
label5 = new JLabel("Number of nodes in Y direction: ", JLabel.LEFT);
label5.setForeground(Color.blue);
add(label5);
textField5=new JTextField("41", 2);
add(textField5);
label6 = new JLabel("Rib Length (in number of nodes): ", JLabel.LEFT);
label6.setForeground(Color.blue);
add(label6);
textField6=new JTextField("20", 2);
add(textField6);
label7 = new JLabel("Number of time steps: ", JLabel.LEFT);
label7.setForeground(Color.blue);
add(label7);
textField7=new JTextField("4000", 4);
add(textField7);
label8 = new JLabel("Thermal diffusive alpha: ", JLabel.LEFT);
label8.setForeground(Color.blue);
add(label8);
textField8=new JTextField("0.036e-05", 9);
add(textField8);
label88=new JLabel("Inside Temperature then Changed to:", JLabel.LEFT);
label88.setForeground(Color.blue);
textField88=new JTextField("30",4);
add(label88);
add(textField88);
label99=new JLabel("And lasted for How Long (in time steps)?", JLabel.LEFT);
label99.setForeground(Color.blue);
textField99=new JTextField("0",4);
add(label99);
add(textField99);
label9=new JLabel("Comments from System Administrator:",JLabel.LEFT);
label9.setForeground(Color.red);
add(label9);
textField9=new JTextField("", 30);
textField9.setForeground(Color.red);
//textField9.setEditable(true);
add(textField9);
clearButton = new JButton("Exit Program");
clearButton.setForeground(Color.blue);
clearButton.setBackground(Color.yellow);
add(clearButton);
clearButton.addActionListener(this);
frame2 = new PlotFrame();
frame2.show();
}
// MMMMMMMMMMMM method actionPerformed reacts to buttons
public void actionPerformed(ActionEvent evt)
{ Object source = evt.getSource();
if (source == runButton)
{
doPanelCalc(); // run method that does calculations,
// writes to file and plots the profile
}
if (source == clearButton)
{ System.exit(0);
//here we repaint the plot window without the plotted points
//Graphics g = frame2.j1.getGraphics(); // get panel graphics object
//g.setColor(Color.yellow);
//g.fillRect(56, 344, 120, 120);
//frame2.j1.repaint();
//g.dispose(); // release panel graphics object
}
}
//EM end method
public void doPanelCalc()
{
// BBBBBBBBBBB Definition of constants
TAMB = 25.; // ambient temp deg C
TIN = Double.parseDouble(textField00.getText()); // inside temp deg C
TIN2=Double.parseDouble(textField88.getText()); //second internal temperature after the first round
ALFA = Double.parseDouble(textField8.getText()); // thermal diffusivity of wall (m**2/s)
DX = Double.parseDouble(textField2.getText()); // node spacing in x direction (m)
NX = Integer.parseInt(textField4.getText()); // total number of nodes in x direction
DY = Double.parseDouble(textField3.getText()); // node spacing in y direction (m)
NY = Integer.parseInt(textField5.getText()); // total number of nodes in y direction
NR = Integer.parseInt(textField6.getText()); // rib length in y direction
//note that rib spacing is 2*(NY-1)*DX
NSTEPS = Integer.parseInt(textField7.getText()); // number of time steps to be done
NSTEPS2=Integer.parseInt(textField99.getText()); //number of time steps that the second internal termperature last
DT = Double.parseDouble(textField1.getText()); // time step in seconds l
// EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
if (ALFA*DT/(DX*DX)>0.5) {
textField9.setText ("Unstable result! Change input!");
}
else {
textField9.setEditable(true);
textField9.setText("Thank you! Please see results!");
int i, j, k, L;
// creating an array of variables that can store (point to)
// objects of class statept
npt = new statept[NX][NY];
nptl = new statept[NX][NY];
// now construct the objects they store (point to) using the constructor
for (i = 0; i < NX; i++){
for (j = 0; j < NY; j++){
npt[i][j] = new statept();
nptl[i][j] = new statept();
}
}
// now store properties in the statept objects
// initialize nodes
for (i = 0; i < NX; i++){
for (j = 0; j < NY; j++){
npt[i][j].t = TAMB;
nptl[i][j].t = TAMB;
}
}
for (i = 0; i < NX; i++){
npt[i][0].t = TIN;
nptl[i][0].t = TIN;
}
for (j = 1; j < NR+1; j++){
npt[0][j].t = TIN;
nptl[0][j].t = TIN;
}
k=0;
// loop to step simulation through time steps
while (k < NSTEPS) {
//ellapsed time
delt = ((double) (k + 1))*DT;
// advance solution in interior of mesh using explicit finite difference
for (j=1;j<NY-1;j++){
for (i=1;i<NX-1;i++){
// energy transport equation
npt[i][j].t = nptl[i][j].t;
npt[i][j].t += ALFA*DT*(nptl[i][j+1].t-2.*nptl[i][j].t+nptl[i][j-1].t)/(DY*DY);
npt[i][j].t += ALFA*DT*(nptl[i+1][j].t-2.*nptl[i][j].t+nptl[i-1][j].t)/(DX*DX);
}
}
// set temperature at zero gradient planes
for (j=NR;j<NY-1;j++){
npt[0][j].t = npt[1][j].t;
}
for (j=1;j<NY-1;j++){
npt[NX-1][j].t = npt[NX-2][j].t;
}
for (i = 0; i < NX; i++){
npt[i][NY-1].t = npt[i][NY-2].t ;
}
System.out.println(" time step " + k + " completed" );
// store new results as last values for next iteration
for (j=0;j<NY;j++){
for (i=0;i<NX;i++){
nptl[i][j] = npt[i][j];
}
}
k++;
doFieldPlot();
} // end of iterative step while loop
L=0;
// loop to step simulation through time steps
while (L< NSTEPS2) {
//ellapsed time
delt = ((double) (L + 1))*DT;
for (i = 0; i < NX; i++){
nptl[i][0].t = TIN2;
}
for (j = 1; j < NR+1; j++){
nptl[0][j].t = TIN2;
}
// advance solution in interior of mesh using explicit finite difference
for (j=1;j<NY-1;j++){
for (i=1;i<NX-1;i++){
// energy transport equation
npt[i][j].t = nptl[i][j].t;
npt[i][j].t += ALFA*DT*(nptl[i][j+1].t-2.*nptl[i][j].t+nptl[i][j-1].t)/(DY*DY);
npt[i][j].t += ALFA*DT*(nptl[i+1][j].t-2.*nptl[i][j].t+nptl[i-1][j].t)/(DX*DX);
}
}
// set temperature at zero gradient planes
for (j=NR;j<NY-1;j++){
npt[0][j].t = npt[1][j].t;
}
for (j=1;j<NY-1;j++){
npt[NX-1][j].t = npt[NX-2][j].t;
}
for (i = 0; i < NX; i++){
npt[i][NY-1].t = npt[i][NY-2].t ;
}
System.out.println(" time step " + L + " completed" );
// store new results as last values for next iteration
for (j=0;j<NY;j++){
for (i=0;i<NX;i++){
nptl[i][j] = npt[i][j];
}
}
L++;
doFieldPlot();
} // end of iterative step while loop
// print temperature field after last timestep
DecimalFormat df = new DecimalFormat( "000.00" );
for (i=NX-1;i>-1;i--){
System.out.println("");
for (j=0;j<NY;j++){
System.out.print(" " + df.format(npt[i][j].t));
}
}
}
}
public void doFieldPlot()
{
// here we paint the temperature field
int i, j, k;
double xmax, ymax;
Graphics g = frame2.j1.getGraphics(); // get panel graphics object
Color wine = new Color(127,0,58);
Color amber = new Color(223,105,0);
Color blueGreen = new Color(40,170,200);
for (i=0; i < NX; i++){
for (j=0; j < NY; j++){
if (npt[i][j].t > 550.) g.setColor(Color.red);
if (npt[i][j].t > 500. & npt[i][j].t <= 550.) g.setColor(Color.yellow);
if (npt[i][j].t > 450. & npt[i][j].t <= 500.) g.setColor(amber);
if (npt[i][j].t > 400. & npt[i][j].t <= 450.) g.setColor(Color.magenta);
if (npt[i][j].t > 350. & npt[i][j].t <= 400.) g.setColor(wine);
if (npt[i][j].t > 300. & npt[i][j].t <= 350.) g.setColor(Color.green);
if (npt[i][j].t > 250. & npt[i][j].t <= 300.) g.setColor(blueGreen);
if (npt[i][j].t > 200. & npt[i][j].t <= 250.) g.setColor(Color.blue);
if (npt[i][j].t <= 200.) g.setColor(Color.gray);
g.fillRect(50+3*(i+1), 350-3*(j+1), 3, 3);
}
}
g.setColor(Color.black);
xmax = (NX-1)*DX;
ymax = (NY-1)*DY;
DecimalFormat df = new DecimalFormat( "0.0000" );
g.drawString(" y = " + df.format(ymax) + " m" , 2, 220);
g.drawString(" x = " + df.format(xmax) +" m", 50+3*NX, 370);
g.drawString("(0,0)", 20, 355);
g.setColor(Color.white);
g.fillRect(2, 385, 150, 20);
g.setColor(Color.black);
g.drawString(" time = " + df.format(delt) + " sec", 2, 400);
g.dispose(); // release panel graphics object
}
// define variables used by this class
private int NX, NY, NL, NR, NSTEPS, NSTEPS2, PINT;
private double DX, DY, KA, ALFA, TIN, TIN2, TAMB;
private double DT, EPS, delt;
statept[][] npt;
statept[][] nptl;
private JButton runButton;
private JButton clearButton;
private JLabel label0;
private JLabel label00;
private JLabel label1;
private JLabel label2;
private JLabel label3;
private JLabel label4;
private JLabel label5;
private JLabel label6;
private JLabel label7;
private JLabel label8;
private JLabel label88;
private JLabel label99;
private JLabel label9;
public JTextField textField1;
public JTextField textField00;
public JTextField textField2;
public JTextField textField3;
public JTextField textField4;
public JTextField textField5;
public JTextField textField6;
public JTextField textField7;
public JTextField textField8;
public JTextField textField88;
public JTextField textField99;
public JTextField textField9;
public PlotFrame frame2;
PrintWriter pw;
FileWriter fw;
}
//CCCCCCCCC class defintion for frame to hold plot
class PlotFrame extends JFrame
{
public PlotFrame() // constructor
{ setTitle("Temperature Field"); //sets titlebar acros top
setBounds(450, 40, 500, 520); // sets initial window size and location
WindowListener exitOnClose2 = new Terminator(); //make it closeable
addWindowListener(exitOnClose2);
Container contentPane = getContentPane();
j1 = new PlotPanel();
JScrollPane spp = new JScrollPane(j1);
contentPane.add(spp, "Center"); //add JScrollPane to PlotFrame
//contentPane.add(j1); // add PlotPanel to JFrame
}
// define variables used by this class
PlotPanel j1;
}
//EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
//CCCCCCCCCCC class defintion for panel to hold temperature plot
class PlotPanel extends JPanel
{
public PlotPanel() // constructor
{
setPreferredSize(new Dimension(400, 520));
}
public void paintComponent(Graphics g)
{
//do the stuff usually done by the parent class
super.paintComponent(g);
// now add the new stuff we want: lines and labels for the plot
g.setColor(Color.black);
g.drawString("Temperature Field in Insulated Wall with Metal Skin ", 40, 40);
Color wine = new Color(127,0,58);
Color amber = new Color(223,105,0);
Color blueGreen = new Color(40,170,200);
g.setColor(Color.red);
g.fillRect(320, 160, 10, 10);
g.setColor(Color.yellow);
g.fillRect(320, 175, 10, 10);
g.setColor(amber);
g.fillRect(320, 190, 10, 10);
g.setColor(Color.magenta);
g.fillRect(320, 205, 10, 10);
g.setColor(wine);
g.fillRect(320, 220, 10, 10);
g.setColor(Color.green);
g.fillRect(320, 235, 10, 10);
g.setColor(blueGreen);
g.fillRect(320, 250, 10, 10);
g.setColor(Color.blue);
g.fillRect(320, 265, 10, 10);
g.setColor(Color.gray);
g.fillRect(320, 280, 10, 10);
g.setColor(Color.black);
g.drawString(" > 550 C", 340, 170);
g.drawString(" 500 to 550 C", 340, 185);
g.drawString(" 450 to 500 C", 340, 200);
g.drawString(" 400 to 450 C", 340, 215);
g.drawString(" 350 to 400 C", 340, 230);
g.drawString(" 300 to 350 C", 340, 245);
g.drawString(" 250 to 300 C", 340, 260);
g.drawString(" 200 to 250 C", 340, 275);
g.drawString(" < 200 C", 340, 290);
}
}
//EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
//CCCCCCC definition of class of objects needed to make windows closeable
class Terminator extends WindowAdapter
{
public void windowClosing(WindowEvent e) {
System.exit(0);}
// this overrides the windowClosing method for WindowAdapter
}
//EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
//CCCCCCC definition of class iwall with the method main
// (where everything starts)
public class iwallmodified
{
public static void main(String[] args) // main() where it all begins
{
//reassign standard output to a file named iwallout.txt
try
{FileOutputStream fs1 = new FileOutputStream("iwallmodifiedout.txt");
System.setOut(new PrintStream(fs1));}
catch(IOException e)
{ System.out.print("Error: " + e);
System.exit(1);
}
frame1=new InputFrame();
frame1.show();
}
public static InputFrame frame1;
}
//EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
3. Features Description
The program graphical user interface has been laid out as in the following diagram. The GUI input frame allows the user to enter all variables for the wall heat transfer problem including time step used for calculation, grid spacing in X and Y directions, the number of nodes in each direction, the length of the rib in number of nodes, the number of time steps and the thermal diffusivity.
Also it allows the user to enter the second internal temperature as well as the time this second temperature lasts. Then the program can go on calculating the temperature change based on the results of the first round.
After the user has entered the above information, the program will do a stability check. If the stability condition is not met, the program will warn the user in the "Comments from the System Administrator" text field in the input panel "Unstable Results! Change Input!" and will not allow the user to move on with the calculation to save the user's time and computing resources. If the user enters information that can generate useful results, the above comments board will show "Thank you. Please see results" after finishing the calculation and graphical illustration.
The “Exit Program” button allows the user to exit the program after it finishes execution.
The plot frame is programmed so that a 41 x 41 mesh can be generated for the analysis. The program plot size remained the same as the original, but was configured to represent the new mesh. The following diagram shows the plot frame.
4. Changes implemented
For changing the grid size from 21 x 21 to 41 x 41, the following modifications have been made to the skeleton program (these changes were not represented in the attached code because they were later replaced by input from the Input Panel):
DX=0.0025;
NX=41;
DY=0.0025;
NY=41;
NR=20;
……..
To accomplish the plot to match the 41 x 41 grid, the following changes are made:
g.fillRect (50+3*(I+1), 350-3*(j+1), 3, 3);
……..
g.drawString(" y = " + df.format(ymax) + " m" , 2, 220);
g.drawString(" x = " + df.format(xmax) +" m", 50+3*NX, 370);
To write the output to a file, the following changes are made:
Try {FileOutputStream fs1 = new FileOutputStream("iwallmodifiedout.txt");
System.setOut(new PrintStream(fs1));}
catch(IOException e)
{ System.out.print("Error: " + e);
System.exit(1);
}
Besides, the program changes the structure of the skeleton program to make the main class independent of the calculations. The purpose of doing this is to make the main class smaller and easy to understand. This also complies with good programming practices. The final main class is as follows:
public class iwallmodified
{
public static void main(String[] args) // main() where it all begins
{
//reassign standard output to a file named iwallout.txt
try
{FileOutputStream fs1 = new FileOutputStream("iwallmodifiedout.txt");
System.setOut(new PrintStream(fs1));}
catch(IOException e)
{ System.out.print("Error: " + e);
System.exit(1);
}
frame1=new InputFrame();
frame1.show();
}
public static InputFrame frame1;
}
The GUI stability indicator is programmed as follows:
public void actionPerformed(ActionEvent evt)
{ Object source = evt.getSource();
if (source == runButton)
{
doPanelCalc(); // run method that does calculations,
// writes to file and plots the profile
}
if (source == clearButton)
{ System.exit(0);
…………
public void doPanelCalc()
{
………….
if (ALFA*DT/(DX*DX)>0.5) {
textField9.setText ("Unstable result! Change input!");
}
else {
…………….
}
The changes made to allow for calculating the second internal temperature input as well as its given duration:
The program asks the user to input information of the second internal temperature as well as its lasting time. Then it adds to another WHILE loop based on the final information inherited from the first round calculation. The code is as follows:
L=0;
// loop to step simulation through time steps
while (L< NSTEPS2) {
//ellapsed time
delt = ((double) (L + 1))*DT;
for (i = 0; i < NX; i++){
nptl[i][0].t = TIN2;
}
for (j = 1; j < NR+1; j++){
nptl[0][j].t = TIN2;
}
// advance solution in interior of mesh using explicit finite difference
for (j=1;j<NY-1;j++){
for (i=1;i<NX-1;i++){
// energy transport equation
npt[i][j].t = nptl[i][j].t;
npt[i][j].t += ALFA*DT*(nptl[i][j+1].t-2.*nptl[i][j].t+nptl[i][j-1].t)/(DY*DY);
npt[i][j].t += ALFA*DT*(nptl[i+1][j].t-2.*nptl[i][j].t+nptl[i-1][j].t)/(DX*DX);
}
}
// set temperature at zero gradient planes
for (j=NR;j<NY-1;j++){
npt[0][j].t = npt[1][j].t;
}
for (j=1;j<NY-1;j++){
npt[NX-1][j].t = npt[NX-2][j].t;
}
for (i = 0; i < NX; i++){
npt[i][NY-1].t = npt[i][NY-2].t ;
}
System.out.println(" time step " + L + " completed" );
// store new results as last values for next iteration
for (j=0;j<NY;j++){
for (i=0;i<NX;i++){
nptl[i][j] = npt[i][j];
}
}
L++;
doFieldPlot();
} // end of iterative step while loop
- Answers to Questions
A. Rib Length vs. Insulation Thickness:
@ Lr value = 0cm Insulation Thickness = 9.5cm
@ Lr value = 3 cm Insulation Thickness = 10 cm
@ Lr value = 5 cm Insulation Thickness = 11.25 cm
@ Lr value = 10 cm Insulation Thickness = 12.5cm
The following figure shows the increase in insulation thickness with the increase in rib length.
- Fourier Number
To the authors’ observation, when the time step reaches 8.7 seconds, the plots begin to lose stability. Therefore 8.7 seconds is a critical point. Plug this number into the Fourier Number which is equal to alpha * time step / square (delta X), we have the calculation results as:
Fourier Number = 3.5 x 10–7 x 8.7 / 0.00252 = 0.50112
Which is very close to the theoretical value of 0.5.
- Second Temperature
After the inner wall’s temperature is reduced to 30C and lasts for 2 hours, 100% of the insulation cools down according to the simulation results.
- Summary of Findings
The insulation thickness should be increased as the rib length increases so that the out wall temperature will not reach over 250 C after being exposed to the internal temperature of 600C for two hours. The insulation wall should have a minimum thickness of 9.5 cm even the rib length is zero.
The Fourier Number plays an important role in ensuring the computation simulation result is sound and reliable. The Fourier Number obtained from the simulation results is very close to the theoretical result of 0.5.
After the inner wall’s temperature is reduced to 30C and lasts for 2 hours, 100% of the insulation cools down.