@@ -41,6 +41,8 @@ public class MultiStreamHeatExchanger extends Heater implements MultiStreamHeatE
41
41
protected double temperatureOut = 0 ;
42
42
43
43
protected double dT = 0.0 ;
44
+ private double temperatureApproach = 0.0 ;
45
+
44
46
45
47
private double UAvalue = 500.0 ; // Overall heat transfer coefficient times area
46
48
private double duty = 0.0 ;
@@ -455,94 +457,183 @@ public void setDeltaT(double deltaT) {
455
457
*/
456
458
@ Override
457
459
public void run (UUID id ) {
458
- if (useDeltaT ) {
459
- runDeltaT (id );
460
- return ;
461
- }
462
-
463
- if (getSpecification ().equals ("out stream" )) {
464
- runSpecifiedStream (id );
465
- } else if (firstTime ) {
460
+ if (firstTime ) {
466
461
firstTime = false ;
467
- // Initialize all outStreams with guessed temperatures
468
- for (StreamInterface outStream : outStreams ) {
469
- SystemInterface systemOut =
470
- inStreams .get (outStreams .indexOf (outStream )).getThermoSystem ().clone ();
471
- outStream .setThermoSystem (systemOut );
472
- outStream .getThermoSystem ().setTemperature (guessOutTemperature , guessOutTemperatureUnit );
473
- outStream .run (id );
474
- }
475
- run (id );
476
- } else {
477
- // Ensure all input streams are run
478
- for (StreamInterface inStream : inStreams ) {
462
+
463
+ // 1. Identify the hottest and coldest inlet streams
464
+ double hottestTemperature = Double .NEGATIVE_INFINITY ;
465
+ double coldestTemperature = Double .POSITIVE_INFINITY ;
466
+ int hottestIndex = -1 ;
467
+ int coldestIndex = -1 ;
468
+
469
+ for (int i = 0 ; i < inStreams .size (); i ++) {
470
+ StreamInterface inStream = inStreams .get (i );
471
+ // Ensure the inlet stream is run to get the latest temperature
479
472
inStream .run ();
473
+ double currentTemp = inStream .getThermoSystem ().getTemperature ("K" );
474
+
475
+ if (currentTemp > hottestTemperature ) {
476
+ hottestTemperature = currentTemp ;
477
+ hottestIndex = i ;
478
+ }
479
+
480
+ if (currentTemp < coldestTemperature ) {
481
+ coldestTemperature = currentTemp ;
482
+ coldestIndex = i ;
483
+ }
480
484
}
481
485
482
- // Clone thermo systems for all out streams
483
- List <SystemInterface > systemsOut = new ArrayList <>();
484
- for (StreamInterface inStream : inStreams ) {
485
- systemsOut .add (inStream .getThermoSystem ().clone ());
486
+ // Check if valid indices were found
487
+ if (hottestIndex == -1 || coldestIndex == -1 ) {
488
+ throw new IllegalStateException ("Unable to determine hottest or coldest inlet streams." );
486
489
}
487
490
488
- // Set thermo systems to out streams
491
+ // 2. Set the outlet temperatures accordingly
489
492
for (int i = 0 ; i < outStreams .size (); i ++) {
490
- outStreams .get (i ).setThermoSystem (systemsOut .get (i ));
491
- // Set temperature based on some logic, e.g., maintaining a certain delta T
492
- outStreams .get (i ).setTemperature (inStreams .get (i ).getTemperature () + 10 , "K" );
493
- if (!outStreams .get (i ).getSpecification ().equals ("TP" )) {
494
- outStreams .get (i ).runTPflash ();
493
+ StreamInterface outStream = outStreams .get (i );
494
+ SystemInterface systemOut = inStreams .get (i ).getThermoSystem ().clone ();
495
+ outStream .setThermoSystem (systemOut );
496
+
497
+ if (i == hottestIndex ) {
498
+ // Set the outlet temperature of the hottest inlet stream to the coldest inlet temperature
499
+ outStream .getThermoSystem ().setTemperature (coldestTemperature + temperatureApproach , "K" );
500
+ } else if (i == coldestIndex ) {
501
+ // Set the outlet temperature of the coldest inlet stream to the hottest inlet temperature
502
+ outStream .getThermoSystem ().setTemperature (hottestTemperature - temperatureApproach , "K" );
503
+ } else {
504
+ // Set the outlet temperature of other streams to the hottest inlet temperature
505
+ outStream .getThermoSystem ().setTemperature (hottestTemperature - temperatureApproach , "K" );
495
506
}
496
- outStreams .get (i ).run (id );
507
+
508
+ // Run the outlet stream with the given ID
509
+ outStream .run (id );
497
510
}
498
511
499
- // Calculate enthalpy changes and capacity rates
500
- List <Double > deltaEnthalpies = new ArrayList <>();
501
- List <Double > capacities = new ArrayList <>();
502
- for (int i = 0 ; i < inStreams .size (); i ++) {
503
- double deltaH = outStreams .get (i ).getThermoSystem ().getEnthalpy ()
504
- - inStreams .get (i ).getThermoSystem ().getEnthalpy ();
505
- deltaEnthalpies .add (deltaH );
506
- double C = Math .abs (deltaH ) / Math .abs (outStreams .get (i ).getThermoSystem ().getTemperature ()
507
- - inStreams .get (i ).getThermoSystem ().getTemperature ());
508
- capacities .add (C );
512
+ // Finalize the setup
513
+ run ();
514
+ return ;
515
+ }
516
+
517
+ else {
518
+ // Run all input and output streams to ensure they are up-to-date
519
+ for (StreamInterface inStream : inStreams ) {
520
+ inStream .run (id );
521
+ }
522
+ for (StreamInterface outStream : outStreams ) {
523
+ outStream .run (id );
509
524
}
510
525
511
- // Determine Cmin and Cmax among all streams
512
- double Cmin = capacities .stream ().min (Double ::compare ).orElse (1.0 );
513
- double Cmax = capacities .stream ().max (Double ::compare ).orElse (1.0 );
514
- double Cr = Cmin / Cmax ;
526
+ // Identify heated and cooled streams
527
+ List <Integer > heatedStreamIndices = new ArrayList <>();
528
+ List <Integer > cooledStreamIndices = new ArrayList <>();
529
+ double totalHeatGained = 0.0 ; // Total Q for heated streams
530
+ double totalHeatLost = 0.0 ; // Total Q for cooled streams
515
531
516
- // Calculate NTU and thermal effectiveness
517
- NTU = UAvalue / Cmin ;
518
- thermalEffectiveness = calcThermalEffectiveness (NTU , Cr );
532
+ for (int i = 0 ; i < inStreams .size (); i ++) {
533
+ double enthalpyIn = inStreams .get (i ).getThermoSystem ().getEnthalpy ();
534
+ double enthalpyOut = outStreams .get (i ).getThermoSystem ().getEnthalpy ();
535
+ double deltaH = enthalpyOut - enthalpyIn ;
536
+
537
+ if (deltaH > 0 ) {
538
+ // Stream is being heated
539
+ heatedStreamIndices .add (i );
540
+ totalHeatGained += deltaH ;
541
+ } else if (deltaH < 0 ) {
542
+ // Stream is being cooled
543
+ cooledStreamIndices .add (i );
544
+ totalHeatLost += Math .abs (deltaH );
545
+ }
546
+ // Streams with deltaH == 0 are neither heated nor cooled
547
+ }
519
548
520
- // Adjust enthalpies based on effectiveness
521
- duty = 0.0 ;
522
- for (int i = 0 ; i < deltaEnthalpies .size (); i ++) {
523
- deltaEnthalpies .set (i , thermalEffectiveness * deltaEnthalpies .get (i ));
524
- duty += deltaEnthalpies .get (i );
549
+ logger .debug (": Total Heat Gained = " + totalHeatGained + " J" );
550
+ logger .debug (": Total Heat Lost = " + totalHeatLost + " J" );
551
+
552
+ // Determine the limiting side
553
+ double limitingHeat ;
554
+ boolean heatingIsLimiting ;
555
+
556
+ if (totalHeatGained < totalHeatLost ) {
557
+ limitingHeat = totalHeatGained ;
558
+ heatingIsLimiting = true ;
559
+ logger .debug ("Limiting side: Heating" );
560
+ } else {
561
+ limitingHeat = totalHeatLost ;
562
+ heatingIsLimiting = false ;
563
+ logger .debug ("Limiting side: Cooling" );
525
564
}
526
565
527
- // Update thermo systems based on adjusted enthalpies
528
- for (int i = 0 ; i < outStreams .size (); i ++) {
529
- ThermodynamicOperations thermoOps =
530
- new ThermodynamicOperations (outStreams .get (i ).getThermoSystem ());
531
- thermoOps .PHflash (inStreams .get (i ).getThermoSystem ().getEnthalpy () - deltaEnthalpies .get (i ),
532
- 0 );
533
- if (Math .abs (thermalEffectiveness - 1.0 ) > 1e-10 ) {
534
- thermoOps = new ThermodynamicOperations (outStreams .get (i ).getThermoSystem ());
535
- thermoOps .PHflash (
536
- inStreams .get (i ).getThermoSystem ().getEnthalpy () + deltaEnthalpies .get (i ), 0 );
566
+ // Calculate scaling factors for each side
567
+ double scalingFactor = 1.0 ;
568
+
569
+ if (heatingIsLimiting ) {
570
+ // Scale down the heat lost by cooled streams
571
+ scalingFactor = limitingHeat / totalHeatLost ;
572
+ logger .debug ("Scaling factor for cooled streams: " + scalingFactor );
573
+ } else {
574
+ // Scale down the heat gained by heated streams
575
+ scalingFactor = limitingHeat / totalHeatGained ;
576
+ logger .debug ("Scaling factor for heated streams: " + scalingFactor );
577
+ }
578
+
579
+ // Apply scaling factors to adjust outlet enthalpies
580
+ double maxTemperatureChange = 0.0 ;
581
+
582
+ for (int i : cooledStreamIndices ) {
583
+ StreamInterface inStream = inStreams .get (i );
584
+ StreamInterface outStream = outStreams .get (i );
585
+
586
+ double enthalpyIn = inStream .getThermoSystem ().getEnthalpy ();
587
+ double targetDeltaH =
588
+ -(outStream .getThermoSystem ().getEnthalpy () - enthalpyIn ) * scalingFactor ;
589
+
590
+ // Adjust the outlet enthalpy
591
+ double adjustedEnthalpyOut = enthalpyIn - (Math .abs (targetDeltaH ));
592
+ ThermodynamicOperations ops = new ThermodynamicOperations (outStream .getThermoSystem ());
593
+ ops .PHflash (adjustedEnthalpyOut );
594
+
595
+ // Calculate temperature change for convergence check
596
+ double oldTemp = outStream .getThermoSystem ().getTemperature ("K" );
597
+ outStream .run (id ); // Re-run to update temperature based on adjusted enthalpy
598
+ double newTemp = outStream .getThermoSystem ().getTemperature ("K" );
599
+ double tempChange = Math .abs (newTemp - oldTemp );
600
+ if (tempChange > maxTemperatureChange ) {
601
+ maxTemperatureChange = tempChange ;
537
602
}
603
+
604
+ logger .debug ("Adjusted cooled stream " + i + ": ΔH = " + targetDeltaH );
538
605
}
539
606
540
- hotColdDutyBalance = 1.0 ; // Adjust as needed for specific applications
541
- }
607
+ scalingFactor = 1.0 ;
608
+ for (int i : heatedStreamIndices ) {
609
+ StreamInterface inStream = inStreams .get (i );
610
+ StreamInterface outStream = outStreams .get (i );
611
+
612
+ double enthalpyIn = inStream .getThermoSystem ().getEnthalpy ();
613
+ double targetDeltaH =
614
+ (outStream .getThermoSystem ().getEnthalpy () - enthalpyIn ) * scalingFactor ;
615
+
616
+ // Adjust the outlet enthalpy
617
+ double adjustedEnthalpyOut = enthalpyIn + (Math .abs (targetDeltaH ));
618
+ ThermodynamicOperations ops = new ThermodynamicOperations (outStream .getThermoSystem ());
619
+ ops .PHflash (adjustedEnthalpyOut );
620
+
621
+ // Calculate temperature change for convergence check
622
+ double oldTemp = outStream .getThermoSystem ().getTemperature ("K" );
623
+ outStream .run (id ); // Re-run to update temperature based on adjusted enthalpy
624
+ double newTemp = outStream .getThermoSystem ().getTemperature ("K" );
625
+ double tempChange = Math .abs (newTemp - oldTemp );
626
+ if (tempChange > maxTemperatureChange ) {
627
+ maxTemperatureChange = tempChange ;
628
+ }
542
629
630
+ logger .debug ("Adjusted heated stream " + i + ": ΔH = " + targetDeltaH );
631
+ }
632
+ }
543
633
setCalculationIdentifier (id );
544
634
}
545
635
636
+
546
637
/**
547
638
* Runs the heat exchanger simulation using a specified stream approach.
548
639
*
@@ -553,13 +644,12 @@ public void runSpecifiedStream(UUID id) {
553
644
// This method needs to be defined based on specific requirements
554
645
}
555
646
556
- /**
557
- * Runs the heat exchanger simulation using a delta T approach.
558
- *
559
- * @param id Unique identifier for the run
560
- */
561
- public void runDeltaT (UUID id ) {
562
- // Implementation similar to the two-stream case but generalized for multiple streams
563
- // This method needs to be defined based on specific requirements
647
+
648
+ public double getTemperatureApproach () {
649
+ return temperatureApproach ;
650
+ }
651
+
652
+ public void setTemperatureApproach (double temperatureApproach ) {
653
+ this .temperatureApproach = temperatureApproach ;
564
654
}
565
655
}
0 commit comments