2
\$\begingroup\$

I'm relatively experienced with Java and C++ so picking up PHP wasn't too difficult. I wanted to get some feedback on my first PHP class. There's nothing extremely complicated as of now, but its nice to get feedback.

The only part I feel that I will definitely get feedback is for the readCSV() function. I made it specifically this way as I need to read the csv file row by row for each column rather than column by column. I couldn't figure out how to do that with foreach so I had to revert to the regular for loop.

<?php

/**
 * Description of Refrigerant
 * Class for the refrigerant. Stores information about the refrigerant as well
 * as functions to calculate values including but not limited to
 * SEI, COP, Enthalpy, Pressure temp
 * @author Eric
 */
class Refrigerant {
    /*
     * ===================================================================
     * ===================================================================
     *                       Variable Declaration
     * ===================================================================
     * ===================================================================
     */

    // public variables to be accessed straight from the object
    public $refrigerantType;    // Type of refrigerant -> a string value
    // "r22" "r404a" etc
    // protected variables only to be accessed within the class and sub classes
    // Arrays of charts, temperature[key] will link to the pressure[key]
    protected $temperature;     // temperature chart
    protected $pressure;        // pressure chart
    protected $liquidEnthalpy;  // liquid enthalpy chart
    protected $vaporEnthalpy;   // vapor enthalpy chart
    protected $ratio;           // ratio of the liquid, suction and discharge factors

    /*
     * ===================================================================
     * ===================================================================
     *                       Constructor & Destructor
     * ===================================================================
     * ===================================================================
     */

    /**
     * Constructor for the refrigerant class
     * Only requires a type of refrigerant to be declared
     * @param string $rtype     ex. "r22", "r404a"
     */
    function __construct($rtype) {
        $this->refrigerantType = $rtype;
        $this->temperature = [];
        $this->pressure = [];
        $this->liquidEnthalpy = [];
        $this->vaporEnthalpy = [];
        $this->ratio = [];
    }

    /*
     * ===================================================================
     * ===================================================================
     *                       Reading CSV Functions
     * ===================================================================
     * ===================================================================
     */

    /**
     * Attempts to read a .csv file with the specific delimeter character
     * @param string $file      filename to open
     * @param char $delimiter   delimter to use
     */
    function readCSV($file, $delimiter) {

        // Read the file into a 2D array and store it in data
        $data = $this->get2DArrayFromCsv($file, $delimiter);

        // Read the data column by column and save the information based on the 
        // header of the column
        // Find how many columns we are reading
        $cols = count($data[0]);
        for ($col = 0; $col < $cols; $col++) {

            // For each column
            $rows = count($data);
            for ($row = 0; $row < $rows; $row++) {

                // This will not execute anything if the cell is empty
                if ($data[$row][$col] == "") {
                    break;
                }
                // Dont parse any of the header data
                if ($row > 0) {
                    switch ($data[0][$col]) {
                        case 'Temperature':
                            array_push($this->temperature, $data[$row][$col]);
                            break;
                        case 'Pressure':
                            array_push($this->pressure, $data[$row][$col]);
                            break;
                        case 'Liquid Ent':
                            array_push($this->liquidEnthalpy, $data[$row][$col]);
                            break;
                        case 'Vapor Ent':
                            array_push($this->vaporEnthalpy, $data[$row][$col]);
                            break;
                        case 'Liquid':
                            $this->ratio = $this->array_push_assoc($this->ratio, 'Liquid', (float) $data[$row][$col]);
                            break;
                        case 'Discharge':
                            $this->ratio = $this->array_push_assoc($this->ratio, 'Discharge', (float) $data[$row][$col]);
                            break;
                        case 'Suction':
                            $this->ratio = $this->array_push_assoc($this->ratio, 'Suction', (float) $data[$row][$col]);
                            break;
                    }
                }
            }
            /* Only if some rows will have less columns than the previous
              if ($col + 1 < count($data)) {
              $cols = count($data[$col + 1]);
              } */
        }
    }

    /**
     * Reads the csv file and returns the data in a 2d array to be parsed
     * @param string $file          file name
     * @param string $delimiter     delimeter
     * @return array                2d array of the data
     */
    private function get2DArrayFromCsv($file, $delimiter) {
        if (($handle = fopen($file, "r")) !== FALSE) {
            $i = 0;
            while (($lineArray = fgetcsv($handle, 4000, $delimiter)) !== FALSE) {
                for ($j = 0; $j < count($lineArray); $j++) {
                    $data2DArray[$i][$j] = $lineArray[$j];
                }
                $i++;
            }
            fclose($handle);
        }
        return $data2DArray;
    }

    /*
     * ===================================================================
     * ===================================================================
     *                       Calculating Values Functions
     * ===================================================================
     * ===================================================================
     */

    /**
     * Finds the pressure temperature based on the pressure passed to the 
     * function. Accesses the temperature and pressure charts to find the new
     * temperature value using interpolation
     * @param double $newPressure   pressure value 
     * @return double               temperature corresponding to the new pressure
     */
    function pressureTemp($newPressure) {


        $values = $this->findBoundValues($this->pressure, $this->temperature, $newPressure);
        // interpolate the values
        $lowPressure = $values[0];
        $highPressure = $values[1];
        $lowTemp = $values[2];
        $highTemp = $values[3];

        if ($values[4] == "int") {
            $temp = $this->interpolate($lowPressure, $highPressure, $lowTemp, $highTemp, $newPressure);
        } else if ($values[4] == "ext") {
            $temp = $this->extrapolate($lowPressure, $highPressure, $lowTemp, $highTemp, $newPressure);
        }


        // We want to find temp, so first two values are pressure
        // second two are temperatures, and last is the new presssure
        /*
          print "{$lowPressure} -- {$lowTemp}<br>";
          print "{$newPressure} -- {$temp}<br>";
          print "{$highPressure} -- {$highTemp}<br>";
         * 
         */
        return $temp;
    }

    /**
     * Finds the subcooling value by subtracting the dlt from sat
     * Used by the liquid state
     * @param double $sat       Saturating condensing temperature
     * @param double $dlt       Drop leg temperature
     * @return double           subcooling value
     */
    function subcooling($sat, $dlt) {
        return $sat - $dlt;
    }

    /**
     * Finds the superheat value by subtracting the state pressure temp from
     * the state temperature
     * Discharge temperature - Discharge pressure temperature
     * Suction temperature - Suction pressure temperature
     * @param double $stateTemp             discharge/suction temperature
     * @param double $statePressureTemp     discharge/suction pressure temperature
     * @return double                       superheat value
     */
    function superheat($stateTemp, $statePressureTemp) {
        return $stateTemp - $statePressureTemp;
    }

    /**
     * Finds the enthalpy value of the given state, using temp1 and temp2 values
     * @param string $state     Liquid, Discharge, Suction 
     * @param double $temp1     Pressure used to find the pressure temp 
     * @param double $temp2     for liquid drop leg temp
     * @return double           enthalpy value for the specific state
     */
    function enthalpy($state, $temp1, $temp2) {
        switch ($state) {
            case 'Liquid':
                // Liquid - Subcooling
                $sct = $this->pressureTemp($temp1);
                $values = $this->findBoundValues($this->temperature, $this->liquidEnthalpy, $sct);
                $intVal = $this->interpolate($values[0], $values[1], $values[2], $values[3], $values[4]);
                return $intVal - ($this->subcooling($sct, $temp2) * $this->ratio['Liquid']);
            //break;
            case 'Discharge':
                // Discharge - Superheat
                $dsct = $this->pressureTemp($temp1);
                $values = $this->findBoundValues($this->temperature, $this->vaporEnthalpy, $dsct);
                $intVal = $this->interpolate($values[0], $values[1], $values[2], $values[3], $values[4]);
                return $intVal + ($this->superheat($dsct, $temp2) * $this->ratio['Discharge']);

            case 'Suction':
                // Suction - Superheat
                $sst = $this->pressureTemp($temp1);
                $values = $this->findBoundValues($this->temperature, $this->vaporEnthalpy, $sst);
                $intVal = $this->interpolate($values[0], $values[1], $values[2], $values[3], $values[4]);
                return $intVal + ($this->superheat($sst, $temp2) * $this->ratio['Discharge']);

            default:
                echo "enthalpy default case";
        }
    }

    /**
     * Finds the three enthalpy values, then uses them to calculate the COP
     * 
     * @param double $temp1     pressure used to find the pressure temp 
     * @param double $temp2     
     * @return double           COP value
     */
    function COP($temp1, $temp2) {
        $liquid = $this->enthalpy('Liquid', $temp1, $temp2);
        $suction = $this->enthalpy('Suction', $temp1, $temp2);
        $discharge = $this->enthalpy('Discharge', $temp1, $temp2);

        return ($suction - $liquid) / ($discharge - $liquid);
    }

    /**
     * 
     * @param type $outdoorTemp     outdoor air temp in celsius
     * @param double $temp1         pressure used to find the pressure temp 
     * @param double $temp2
     * @return double               SEI value      
     */
    function SEI($outdoorTemp, $temp1, $temp2) {

        // Convert outdoor air temp to kelvin
        $a = $outdoorTemp + 273;

        $d = $this->enthalpy('Suction', $temp1, $temp2) + 273;

        $t = $d / ($a - $d);

        $cop = $this->COP($temp1, $temp2);

        return $cop / $t * 100;

    }

    /*
     * ===================================================================
     * ===================================================================
     *                       Functions used by Calculations
     * ===================================================================
     * ===================================================================
     */

    /**
     * Finds the lower and upper bounds of the two variables being used for
     * interpolation or extrapolation calculations. It also returns if it 
     * is a interpolation or extrapolation calculation
     * @param array $xArray     array of values which x actual will be in
     * @param array $yArray     array of values which will contain the coressponding value to xActual
     * @param double $xActual   the actual value we are using to find the coressponding value
     * @return array            values stored 0 through 4
     *              0 - double - lower bound of xArray
     *              1 - double - higher bound of xArray
     *              2 - double - lower bound of yArray
     *              3 - double - higher bound of yArray
     *              4 - string - ext or int for extrapolation or interpolation
     */
    function findBoundValues($xArray, $yArray, $xActual) {

        $values = [];
        // Check to see if the new pressure is below the lowest known point    
        // or if it is above the highest known point
        $numPoints = count($xArray);
        // If the new pressure is lower than the lowest point we have
        if ($xActual <= $xArray[0]) {

            // Set the lowest and highest pressure/temperatures to the first
            // and second lowest and extrapolate from there
            $values[0] = $xArray[0];
            $values[1] = $xArray[1];

            $values[2] = $yArray[0];
            $values[3] = $yArray[1];
            $values[4] = "ext";
            return $values;
        } else if ($xActual >= $xArray[$numPoints - 1]) {
            // If the new pressure is higher than the highest point we have
            // Set the lowest and highest pressure/temperatures to the first
            // and second lowest and extrapolate from there
            $values[0] = $xArray[$numPoints - 2];
            $values[1] = $xArray[$numPoints - 1];

            $values[2] = $yArray[$numPoints - 2];
            $values[3] = $yArray[$numPoints - 1];
            $values[4] = "ext";

            return $values;
        } else {
            // New pressure point is somewhere in the range of values on the chart
            foreach ($xArray as $key => $value) {
                // The current value is higher than the new pressure, so set
                // the higher bound values, lower bound will already be set
                if ($value > $xActual) {
                    $values[1] = $value;
                    $values[3] = $yArray[$key];
                    break;
                } else {
                    // Every time we pass a point that is lower than the new pressure
                    // we set the lower bound values
                    $values[0] = $value;
                    $values[2] = $yArray[$key];
                }
            }
            $values[4] = "int";
            return $values;
        }
    }

    /**
     * interpolate function
     * @param double $x1        low end of left side
     * @param double $x2        high end of left side
     * @param double $y1        low end of right side
     * @param double $y2        high end of right side
     * @param double $xActual   value inbetween x1 and x2
     * @return double           the value matching the xActual value on 
     *                          the scale of the Y values
     */
    function interpolate($x1, $x2, $y1, $y2, $xActual) {

        $xDiff = abs($x1 - $x2);
        $yDiff = abs($y1 - $y2);


        $xPer = abs($x1 - $xActual) / abs($xDiff);
        $newY = $y1 + ($xPer * $yDiff);

        return $newY;
    }

    /**
     * extrapolate function - the new point is not
     * @param double $x1        low end of left side
     * @param double $x2        high end of left side
     * @param double $y1        low end of right side
     * @param double $y2        high end of right side
     * @param double $xActual   value inbetween x1 and x2
     * @return double           the value matching the xActual value on
     *                          the scale of the Y values
     */
    function extrapolate($x1, $x2, $y1, $y2, $xActual) {

        $xDiff = abs($x1 - $x2);
        $yDiff = abs($y1 - $y2);

        $xPer = abs($x1 - $xActual) / abs($xDiff);

        // If the actual value is below, we subtract it from the lower value
        // If the acutal value is higher, we add it to the higher value
        if ($xActual <= $x1) {
            $newY = $y1 - ($xPer * $yDiff);
        } else if ($xActual >= $x2) {
            $newY = $y2 + ($xPer * $yDiff);
        }
        return $newY;
    }

    /*
     * ===================================================================
     * ===================================================================
     *                       Quality of Life (QoL) Functions
     * ===================================================================
     * ===================================================================
     */

    /**
     * Adds a value to an associative array 
     * @param array $array      array to add a value to
     * @param string $key       key of the array to add to
     * @param double $value     value to be added
     * @return array            the array being modified
     */
    function array_push_assoc($array, $key, $value) {
        $array[$key] = $value;
        return $array;
    }

}
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$
  • function enthalpy surely looks strange. Three cases are not at all connected, and I don't see a reason to combine them into single function like this.

    Also, I fail to see the difference between Discharge and Suction cases. Shouldn't it be ratio['Suction'] in the latter case?

    If I am correct, the recommendation is to negate values of ratio['Liquid'], and rewrite it as

    function enthalpy($state, $temp1, $temp2) {
        $sct = $this->pressureTemp($temp1);
        $values = $this->findBoundValues($this->temperature, $this->liquidEnthalpy, $sct);
        $intVal = $this->interpolate($values[0], $values[1], $values[2], $values[3], $values[4]);
        return $intVal + ($this->subcooling($sct, $temp2) * $this->ratio[state]);
    }
    
  • Since you // Dont parse any of the header data, it is much cleaner to start the row loop from 1, and do not check if (row > 0) at all.

  • I don't follow why do you want to read the file like that. PHP allows accessing members by name, like $this->$name[$col], where $name array is constructed from the values of row[0].

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.