mirror of
https://github.com/CoolProp/CoolProp.git
synced 2026-04-23 03:00:17 -04:00
log14dec2015.txt
This commit is contained in:
@@ -1,21 +1,21 @@
|
||||
{
|
||||
Project 4: CoolProp Graphic Demo
|
||||
Bruce Wernick, 13 December 2015
|
||||
}
|
||||
|
||||
program Project4;
|
||||
|
||||
uses
|
||||
Forms,
|
||||
main in 'main.pas' {MainForm},
|
||||
uMolChart in 'uMolChart.pas',
|
||||
cpIntf in 'cpIntf.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.MainFormOnTaskbar := True;
|
||||
Application.CreateForm(TMainForm, MainForm);
|
||||
Application.Run;
|
||||
end.
|
||||
{
|
||||
Project 4: CoolProp Graphic Demo
|
||||
Bruce Wernick, 13 December 2015
|
||||
}
|
||||
|
||||
program Project4;
|
||||
|
||||
uses
|
||||
Forms,
|
||||
main in 'main.pas' {MainForm},
|
||||
uMolChart in 'uMolChart.pas',
|
||||
cpIntf in 'cpIntf.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.MainFormOnTaskbar := True;
|
||||
Application.CreateForm(TMainForm, MainForm);
|
||||
Application.Run;
|
||||
end.
|
||||
|
||||
@@ -1,39 +1,21 @@
|
||||
CoolProp Delphi Wrapper Demo
|
||||
============================
|
||||
|
||||
Bruce Wernick,
|
||||
info@coolit.co.za
|
||||
Created: 13 December 2015
|
||||
|
||||
This demo is based on the win32 shared DLL downloaded from the CoolProp site.
|
||||
|
||||
There are two parts to the demo:
|
||||
1. The actual DLL interface.
|
||||
2. A simple ph-chart builder.
|
||||
|
||||
The original CoolProp code is written in C++. In the source folder, you can find the text file exports.txt
|
||||
that details the complete list of functions exported by the CoolProp DLL. I have only implemented
|
||||
the essential ones but it would be easy to add any ones I have omitted. The interface mimics the
|
||||
C header file but there are a few options. The returning string is an array of character. In Delphi,
|
||||
you could use an array of AnsiChar parameter. Instead, I chose to use the PAnsiChar because it makes
|
||||
the dll interface cleaner and more universal. One thing you have to be aware of - the calling
|
||||
program has to create a buffer for the result. If this is not sized sufficiently, then a blank string
|
||||
is returned. This could happen, for example, if a lot of fluids are added to the file.
|
||||
|
||||
The graphical part draws the saturation curve on conventional log(p) vs enthalpy axes. The program main
|
||||
form has a Delphi VCL TListView and a TPaintBox. On startup, the program uses the DLL to populate the
|
||||
ListView with all of the available fluids. The PaintBox is a very basic components that is basically
|
||||
just a canvas. The main program creates a TMolChart class that does all the work on a canvas. When
|
||||
the OnPaint fires in the main form, the chart is re-drawn.
|
||||
|
||||
The chart is auto scaled around the critical point and atmospheric pressure (where possible). This
|
||||
makes it quite convenient for comparing the shape of the various saturation curves. What it needs is
|
||||
some isotherms and some isentropic lines. If anyone has the urge to add these I would like to get an
|
||||
update.
|
||||
|
||||
|
||||
Lazarus users
|
||||
-------------
|
||||
With some minor changes, you could quite easily run this code with Lazarus.
|
||||
|
||||
|
||||
CoolProp Delphi Wrapper Demo.
|
||||
Bruce Wernick, info@coolit.co.za
|
||||
13 December 2015
|
||||
|
||||
This demo is based on the win32 shared DLL downloaded from the CoolProp site.
|
||||
|
||||
There are two parts to the demo:
|
||||
1. The actual DLL interface.
|
||||
2. A simple ph-chart builder.
|
||||
|
||||
The original code was written in C++. In the source folder, you can find the text file exports.txt that details the complete list of functions exported by the CoolProp DLL. I have only implemented the essential ones but it would be easy to add any ones I have omitted. The interface mimics the C header file but there are a few options. The returning string is an array of char. In Delphi, you could use an array of char parameter. Instead, I chose to use the PAnsiChar because it makes the dll interface simplere and more universal. One thing you have to be aware of - the calling program has to create a buffer for the result. If this is not sized sufficiently, then a blank string is returned. This could happen, for example, if a lot of fluids are added to the file.
|
||||
|
||||
The graphical part draws the saturation curve on conventional log(p) vs enthalpy axes. The program main form has a Delphi VCL TListView and a TPaintBox. On startup, the program uses the DLL to populate the ListView with all of the available fluids. The PaintBox is a very basic components that is basically just a canvas. The main program creates a TMolChart class that does all the work on a canvas. When the OnPaint fires in the main form, the chart is re-drawn.
|
||||
|
||||
The chart is auto scaled around the critical point and atmospheric pressure (where possible). This makes it quite convenient for comparing the shape of the various saturation curves. What it needs is some isotherms and some isentropic lines. If anyone has the urge to add these I would like to get an update.
|
||||
|
||||
|
||||
Lazarus users
|
||||
With some minor changes, you could quite easily run this code with Lazarus.
|
||||
|
||||
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
{
|
||||
Delphi Interface for CoolProp
|
||||
Bruce Wernick, 13 December 2015
|
||||
|
||||
Notes:
|
||||
All of the char parameters are PAnsiChar, the floating point numbers are
|
||||
Double and the integer types are either LongInt or Integer depending on the
|
||||
type in the dll. Where there is an output string, the calling program must
|
||||
create the space for the result. Be aware here that insufficient space will
|
||||
result in a empty string. So for example, you should ensure sufficient space
|
||||
for the refrigerant list.
|
||||
}
|
||||
|
||||
unit cpIntf;
|
||||
|
||||
interface
|
||||
|
||||
const
|
||||
cpdll = 'CoolProp.dll';
|
||||
|
||||
function get_global_param_string(
|
||||
param: PAnsiChar;
|
||||
res: PAnsiChar;
|
||||
n: Integer): LongInt; stdcall;
|
||||
external cpdll name '_get_global_param_string@12';
|
||||
|
||||
function get_fluid_param_string(
|
||||
fluid: PAnsiChar;
|
||||
param: PAnsiChar;
|
||||
res: PAnsiChar;
|
||||
n: Integer): Longint; stdcall;
|
||||
external cpdll name '_get_fluid_param_string@12';
|
||||
|
||||
function PropsSI(
|
||||
spec: PAnsiChar;
|
||||
prop1: PAnsiChar; val1: Double;
|
||||
prop2: PAnsiChar; val2: Double;
|
||||
fluid: PAnsiChar): Double; stdcall;
|
||||
external cpdll name '_PropsSI@32';
|
||||
|
||||
function Props1SI(
|
||||
fluid: PAnsiChar;
|
||||
res: PAnsiChar): Double; stdcall;
|
||||
external cpdll name '_Props1SI@8';
|
||||
|
||||
function HAPropsSI(
|
||||
spec: PAnsiChar;
|
||||
prop1: PAnsiChar; val1: Double;
|
||||
prop2: PAnsiChar; val2: Double;
|
||||
prop3: PAnsiChar; val3: Double): Double; stdcall;
|
||||
external cpdll name '_HAPropsSI@40';
|
||||
|
||||
implementation
|
||||
|
||||
initialization
|
||||
{Disable floating point exception
|
||||
This is a problem with the Delphi compiler only}
|
||||
Set8087CW($133f);
|
||||
end.
|
||||
{
|
||||
Delphi Interface for CoolProp
|
||||
Bruce Wernick, 13 December 2015
|
||||
|
||||
Notes:
|
||||
All of the char parameters are PAnsiChar, the floating point numbers are
|
||||
Double and the integer types are either LongInt or Integer depending on the
|
||||
type in the dll. Where there is an output string, the calling program must
|
||||
create the space for the result. Be aware here that insufficient space will
|
||||
result in a empty string. So for example, you should ensure sufficient space
|
||||
for the refrigerant list.
|
||||
}
|
||||
|
||||
unit cpIntf;
|
||||
|
||||
interface
|
||||
|
||||
const
|
||||
cpdll = 'CoolProp.dll';
|
||||
|
||||
function get_global_param_string(
|
||||
param: PAnsiChar;
|
||||
res: PAnsiChar;
|
||||
n: Integer): LongInt; stdcall;
|
||||
external cpdll name '_get_global_param_string@12';
|
||||
|
||||
function get_fluid_param_string(
|
||||
fluid: PAnsiChar;
|
||||
param: PAnsiChar;
|
||||
res: PAnsiChar;
|
||||
n: Integer): Longint; stdcall;
|
||||
external cpdll name '_get_fluid_param_string@12';
|
||||
|
||||
function PropsSI(
|
||||
spec: PAnsiChar;
|
||||
prop1: PAnsiChar; val1: Double;
|
||||
prop2: PAnsiChar; val2: Double;
|
||||
fluid: PAnsiChar): Double; stdcall;
|
||||
external cpdll name '_PropsSI@32';
|
||||
|
||||
function Props1SI(
|
||||
fluid: PAnsiChar;
|
||||
res: PAnsiChar): Double; stdcall;
|
||||
external cpdll name '_Props1SI@8';
|
||||
|
||||
function HAPropsSI(
|
||||
spec: PAnsiChar;
|
||||
prop1: PAnsiChar; val1: Double;
|
||||
prop2: PAnsiChar; val2: Double;
|
||||
prop3: PAnsiChar; val3: Double): Double; stdcall;
|
||||
external cpdll name '_HAPropsSI@40';
|
||||
|
||||
implementation
|
||||
|
||||
initialization
|
||||
{Disable floating point exception
|
||||
This is a problem with the Delphi compiler only}
|
||||
Set8087CW($133f);
|
||||
end.
|
||||
|
||||
@@ -1,62 +1,63 @@
|
||||
object MainForm: TMainForm
|
||||
Left = 0
|
||||
Top = 0
|
||||
Caption = 'CoolProp Demo'
|
||||
ClientHeight = 372
|
||||
ClientWidth = 595
|
||||
Color = clBtnFace
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -11
|
||||
Font.Name = 'Tahoma'
|
||||
Font.Style = []
|
||||
OldCreateOrder = False
|
||||
OnActivate = FormActivate
|
||||
OnCreate = FormCreate
|
||||
DesignSize = (
|
||||
595
|
||||
372)
|
||||
PixelsPerInch = 96
|
||||
TextHeight = 13
|
||||
object PaintBox1: TPaintBox
|
||||
Left = 175
|
||||
Top = 40
|
||||
Width = 412
|
||||
Height = 301
|
||||
Anchors = [akLeft, akTop, akRight, akBottom]
|
||||
OnMouseDown = PaintBox1MouseDown
|
||||
OnMouseLeave = PaintBox1MouseLeave
|
||||
OnMouseMove = PaintBox1MouseMove
|
||||
OnPaint = PaintBox1Paint
|
||||
end
|
||||
object ListBox1: TListBox
|
||||
Left = 8
|
||||
Top = 40
|
||||
Width = 161
|
||||
Height = 324
|
||||
Anchors = [akLeft, akTop, akBottom]
|
||||
ItemHeight = 13
|
||||
TabOrder = 0
|
||||
OnClick = ListBox1Click
|
||||
end
|
||||
object StaticText1: TStaticText
|
||||
Left = 175
|
||||
Top = 347
|
||||
Width = 412
|
||||
Height = 17
|
||||
Anchors = [akLeft, akRight, akBottom]
|
||||
AutoSize = False
|
||||
BorderStyle = sbsSunken
|
||||
Caption = 'Chart position...'
|
||||
TabOrder = 1
|
||||
end
|
||||
object Button1: TButton
|
||||
Left = 8
|
||||
Top = 8
|
||||
Width = 49
|
||||
Height = 25
|
||||
Caption = 'Copy'
|
||||
TabOrder = 2
|
||||
OnClick = Button1Click
|
||||
end
|
||||
end
|
||||
object MainForm: TMainForm
|
||||
Left = 0
|
||||
Top = 0
|
||||
Caption = 'CoolProp Demo'
|
||||
ClientHeight = 372
|
||||
ClientWidth = 595
|
||||
Color = clBtnFace
|
||||
DoubleBuffered = True
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -11
|
||||
Font.Name = 'Tahoma'
|
||||
Font.Style = []
|
||||
OldCreateOrder = False
|
||||
OnActivate = FormActivate
|
||||
OnCreate = FormCreate
|
||||
DesignSize = (
|
||||
595
|
||||
372)
|
||||
PixelsPerInch = 96
|
||||
TextHeight = 13
|
||||
object PaintBox1: TPaintBox
|
||||
Left = 175
|
||||
Top = 40
|
||||
Width = 412
|
||||
Height = 301
|
||||
Anchors = [akLeft, akTop, akRight, akBottom]
|
||||
OnMouseDown = PaintBox1MouseDown
|
||||
OnMouseLeave = PaintBox1MouseLeave
|
||||
OnMouseMove = PaintBox1MouseMove
|
||||
OnPaint = PaintBox1Paint
|
||||
end
|
||||
object ListBox1: TListBox
|
||||
Left = 8
|
||||
Top = 40
|
||||
Width = 161
|
||||
Height = 324
|
||||
Anchors = [akLeft, akTop, akBottom]
|
||||
ItemHeight = 13
|
||||
TabOrder = 0
|
||||
OnClick = ListBox1Click
|
||||
end
|
||||
object StaticText1: TStaticText
|
||||
Left = 175
|
||||
Top = 347
|
||||
Width = 412
|
||||
Height = 17
|
||||
Anchors = [akLeft, akRight, akBottom]
|
||||
AutoSize = False
|
||||
BorderStyle = sbsSunken
|
||||
Caption = 'Chart position...'
|
||||
TabOrder = 1
|
||||
end
|
||||
object Button1: TButton
|
||||
Left = 8
|
||||
Top = 8
|
||||
Width = 49
|
||||
Height = 25
|
||||
Caption = '&Copy'
|
||||
TabOrder = 2
|
||||
OnClick = Button1Click
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,132 +1,132 @@
|
||||
{
|
||||
CoolProp Graphic Demo - Main form
|
||||
Bruce Wernick, 13 December 2015
|
||||
}
|
||||
|
||||
unit main;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Messages, SysUtils, Variants, Classes, Graphics,
|
||||
Controls, Forms, Dialogs, StdCtrls, ExtCtrls,
|
||||
uMolChart;
|
||||
|
||||
type
|
||||
TMainForm = class(TForm)
|
||||
ListBox1: TListBox;
|
||||
PaintBox1: TPaintBox;
|
||||
StaticText1: TStaticText;
|
||||
Button1: TButton;
|
||||
procedure FormActivate(Sender: TObject);
|
||||
procedure ListBox1Click(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure PaintBox1Paint(Sender: TObject);
|
||||
procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
|
||||
procedure PaintBox1MouseLeave(Sender: TObject);
|
||||
procedure Button1Click(Sender: TObject);
|
||||
procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
||||
private
|
||||
fluid: AnsiString;
|
||||
ref: PAnsiChar;
|
||||
MolChart: TMolChart;
|
||||
public
|
||||
end;
|
||||
|
||||
var
|
||||
MainForm: TMainForm;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
uses
|
||||
clipbrd,
|
||||
cpIntf;
|
||||
|
||||
procedure TMainForm.FormCreate(Sender: TObject);
|
||||
const
|
||||
n = 80;
|
||||
var
|
||||
res: AnsiString;
|
||||
begin
|
||||
Caption := 'CoolProp Demo';
|
||||
SetLength(res, n);
|
||||
get_global_param_string('version', PAnsiChar(res), n);
|
||||
Caption := Caption + ' ' + 'Version ' + string(res);
|
||||
get_global_param_string('gitrevision', PAnsiChar(res), n);
|
||||
Caption := Caption + ' ' + 'Revision ' + string(res);
|
||||
|
||||
MolChart := TMolChart.Create(PaintBox1.Canvas);
|
||||
fluid := 'R22'; // initial fluid
|
||||
ref := PAnsiChar(fluid)
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormActivate(Sender: TObject);
|
||||
const
|
||||
n = 2048;
|
||||
var
|
||||
res: AnsiString;
|
||||
begin
|
||||
SetLength(res, n);
|
||||
get_global_param_string('FluidsList', PAnsiChar(res), n);
|
||||
ListBox1.Items.CommaText := string(res);
|
||||
ListBox1.ItemIndex := ListBox1.Items.IndexOf(ref)
|
||||
end;
|
||||
|
||||
procedure TMainForm.ListBox1Click(Sender: TObject);
|
||||
begin
|
||||
fluid := AnsiString(ListBox1.Items[ListBox1.ItemIndex]);
|
||||
ref := PAnsiChar(fluid);
|
||||
PaintBox1.Refresh
|
||||
end;
|
||||
|
||||
procedure TMainForm.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
||||
var
|
||||
h, p: Double;
|
||||
begin
|
||||
h := MolChart.P2X(X); p := MolChart.P2Y(Y);
|
||||
Clipboard.AsText := format('h:%0.3f, p:%0.3f', [h, p]);
|
||||
end;
|
||||
|
||||
procedure TMainForm.PaintBox1MouseLeave(Sender: TObject);
|
||||
begin
|
||||
StaticText1.Caption := fluid
|
||||
end;
|
||||
|
||||
procedure TMainForm.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
|
||||
const
|
||||
k0 = 273.15;
|
||||
fmt = '%s: t=%0.2fC, p=%0.3f MPa, h=%0.3f kJ/kg, s=%0.4f kJ/kg-K';
|
||||
var
|
||||
h, p, t, s: Double;
|
||||
begin
|
||||
h := MolChart.P2X(X); p := MolChart.P2Y(Y);
|
||||
t := PropsSI('T', 'P', 1e6*p, 'H', 1e3*h, ref);
|
||||
s := 1e-3*PropsSI('S', 'P', 1e6*p, 'T', t+k0, ref);
|
||||
StaticText1.Caption := format(fmt, [fluid, t-k0, p, h, s])
|
||||
end;
|
||||
|
||||
procedure TMainForm.PaintBox1Paint(Sender: TObject);
|
||||
begin
|
||||
StaticText1.Caption := fluid;
|
||||
MolChart.DrawChart(ref, PaintBox1.Width, PaintBox1.Height)
|
||||
end;
|
||||
|
||||
procedure TMainForm.Button1Click(Sender: TObject);
|
||||
var
|
||||
MyFormat: Word;
|
||||
AData: THandle;
|
||||
APalette: HPALETTE;
|
||||
bmp: TBitmap;
|
||||
begin
|
||||
bmp := self.GetFormImage;
|
||||
try
|
||||
bmp.SaveToClipBoardFormat(MyFormat, AData, APalette);
|
||||
ClipBoard.SetAsHandle(MyFormat,AData);
|
||||
finally
|
||||
bmp.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
{
|
||||
CoolProp Graphic Demo - Main form
|
||||
Bruce Wernick, 13 December 2015
|
||||
}
|
||||
|
||||
unit main;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Messages, SysUtils, Variants, Classes, Graphics,
|
||||
Controls, Forms, Dialogs, StdCtrls, ExtCtrls,
|
||||
uMolChart;
|
||||
|
||||
type
|
||||
TMainForm = class(TForm)
|
||||
ListBox1: TListBox;
|
||||
PaintBox1: TPaintBox;
|
||||
StaticText1: TStaticText;
|
||||
Button1: TButton;
|
||||
procedure FormActivate(Sender: TObject);
|
||||
procedure ListBox1Click(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure PaintBox1Paint(Sender: TObject);
|
||||
procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
|
||||
procedure PaintBox1MouseLeave(Sender: TObject);
|
||||
procedure Button1Click(Sender: TObject);
|
||||
procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
||||
private
|
||||
fluid: AnsiString;
|
||||
ref: PAnsiChar;
|
||||
MolChart: TMolChart;
|
||||
public
|
||||
end;
|
||||
|
||||
var
|
||||
MainForm: TMainForm;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
uses
|
||||
clipbrd,
|
||||
cpIntf;
|
||||
|
||||
procedure TMainForm.FormCreate(Sender: TObject);
|
||||
const
|
||||
n = 80;
|
||||
var
|
||||
res: AnsiString;
|
||||
begin
|
||||
Caption := 'CoolProp Demo';
|
||||
SetLength(res, n);
|
||||
get_global_param_string('version', PAnsiChar(res), n);
|
||||
Caption := Caption + ' ' + 'Version ' + string(res);
|
||||
get_global_param_string('gitrevision', PAnsiChar(res), n);
|
||||
Caption := Caption + ' ' + 'Revision ' + string(res);
|
||||
|
||||
MolChart := TMolChart.Create(PaintBox1.Canvas);
|
||||
fluid := 'R22'; // initial fluid
|
||||
ref := PAnsiChar(fluid)
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormActivate(Sender: TObject);
|
||||
const
|
||||
n = 2048;
|
||||
var
|
||||
res: AnsiString;
|
||||
begin
|
||||
SetLength(res, n);
|
||||
get_global_param_string('FluidsList', PAnsiChar(res), n);
|
||||
ListBox1.Items.CommaText := string(res);
|
||||
ListBox1.ItemIndex := ListBox1.Items.IndexOf(string(ref))
|
||||
end;
|
||||
|
||||
procedure TMainForm.ListBox1Click(Sender: TObject);
|
||||
begin
|
||||
fluid := AnsiString(ListBox1.Items[ListBox1.ItemIndex]);
|
||||
ref := PAnsiChar(fluid);
|
||||
PaintBox1.Refresh
|
||||
end;
|
||||
|
||||
procedure TMainForm.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
||||
var
|
||||
h, p: Double;
|
||||
begin
|
||||
h := MolChart.P2X(X); p := MolChart.P2Y(Y);
|
||||
Clipboard.AsText := format('h:%0.3f, p:%0.3f', [h, p]);
|
||||
end;
|
||||
|
||||
procedure TMainForm.PaintBox1MouseLeave(Sender: TObject);
|
||||
begin
|
||||
StaticText1.Caption := string(fluid)
|
||||
end;
|
||||
|
||||
procedure TMainForm.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
|
||||
const
|
||||
k0 = 273.15;
|
||||
fmt = '%s: t=%0.2fC, p=%0.3f MPa, h=%0.3f kJ/kg, s=%0.4f kJ/kg-K';
|
||||
var
|
||||
h, p, t, s: Double;
|
||||
begin
|
||||
h := MolChart.P2X(X); p := MolChart.P2Y(Y);
|
||||
t := PropsSI('T', 'P', 1e6*p, 'H', 1e3*h, ref);
|
||||
s := 1e-3*PropsSI('S', 'P', 1e6*p, 'T', t+k0, ref);
|
||||
StaticText1.Caption := format(fmt, [fluid, t-k0, p, h, s])
|
||||
end;
|
||||
|
||||
procedure TMainForm.PaintBox1Paint(Sender: TObject);
|
||||
begin
|
||||
StaticText1.Caption := string(fluid);
|
||||
MolChart.DrawChart(ref, PaintBox1.Width, PaintBox1.Height)
|
||||
end;
|
||||
|
||||
procedure TMainForm.Button1Click(Sender: TObject);
|
||||
var
|
||||
MyFormat: Word;
|
||||
AData: THandle;
|
||||
APalette: HPALETTE;
|
||||
bmp: TBitmap;
|
||||
begin
|
||||
bmp := self.GetFormImage;
|
||||
try
|
||||
bmp.SaveToClipBoardFormat(MyFormat, AData, APalette);
|
||||
ClipBoard.SetAsHandle(MyFormat,AData);
|
||||
finally
|
||||
bmp.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@@ -1,191 +1,191 @@
|
||||
{
|
||||
Mollier Chart (ph-chart) generator
|
||||
Bruce Wernick, 13 December 2015
|
||||
}
|
||||
|
||||
unit uMolChart;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, Windows, Graphics, Classes,
|
||||
cpIntf;
|
||||
|
||||
type
|
||||
fvec = array of Double;
|
||||
TMolChart = class
|
||||
private
|
||||
FCanvas: TCanvas;
|
||||
R: TRect;
|
||||
FMargin: Integer;
|
||||
x0, x1, y0, y1: Double;
|
||||
lny0, lny1: Double;
|
||||
xf, yf: Double;
|
||||
procedure CalcScaleFactor;
|
||||
public
|
||||
constructor Create(Canvas: TCanvas);
|
||||
function X2P(x: Double): Integer;
|
||||
function Y2P(y: Double): Integer;
|
||||
function P2X(p: Integer): Double;
|
||||
function P2Y(p: Integer): Double;
|
||||
procedure MoveTo(x, y: Double);
|
||||
procedure Lineto(x, y: Double);
|
||||
procedure DrawPoint(x, y: Double; Color: TColor);
|
||||
procedure DrawLine(x0, y0, x1, y1: Double; Color: TColor; PenWidth: Integer);
|
||||
procedure DrawVec(x, y: fvec; Color: TColor; PenWidth: Integer);
|
||||
procedure DrawChart(ref: PAnsiChar; Width, Height: Integer);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
Math;
|
||||
|
||||
constructor TMolChart.Create(Canvas: TCanvas);
|
||||
begin
|
||||
FMargin := 25;
|
||||
FCanvas := Canvas
|
||||
end;
|
||||
|
||||
procedure TMolChart.CalcScaleFactor;
|
||||
{calculate the scale factor}
|
||||
begin
|
||||
xf := (x1-x0)/(R.Right-R.Left);
|
||||
lny0 := ln(y0);
|
||||
lny1 := ln(y1);
|
||||
yf := (lny1-lny0)/(R.Top-R.Bottom)
|
||||
end;
|
||||
|
||||
function TMolChart.X2P(x: Double): Integer;
|
||||
{X scale value to chart pixel value}
|
||||
begin
|
||||
Result := Trunc(R.Left+(x-x0)/xf)
|
||||
end;
|
||||
|
||||
function TMolChart.Y2P(y: Double): Integer;
|
||||
{Y scale value to chart pixel value}
|
||||
begin
|
||||
Result := Trunc(R.Bottom+(ln(y)-lny0)/yf)
|
||||
end;
|
||||
|
||||
function TMolChart.P2X(p: Integer): Double;
|
||||
{pixel point to x scale value}
|
||||
begin
|
||||
Result := x0+(p-R.Left)*xf
|
||||
end;
|
||||
|
||||
function TMolChart.P2Y(p: Integer): Double;
|
||||
{pixel point to y scale value}
|
||||
begin
|
||||
Result := exp(lny0+(p-R.Bottom)*yf)
|
||||
end;
|
||||
|
||||
procedure TMolChart.MoveTo(x, y: Double);
|
||||
{move to (x,y) scale position}
|
||||
begin
|
||||
FCanvas.MoveTo(X2P(x), Y2P(y))
|
||||
end;
|
||||
|
||||
procedure TMolChart.LineTo(x, y: Double);
|
||||
{line to (x,y) scale position}
|
||||
begin
|
||||
FCanvas.LineTo(X2P(x), Y2P(y))
|
||||
end;
|
||||
|
||||
procedure TMolChart.DrawPoint(x, y: Double; Color: TColor);
|
||||
{draw a square at (x,y) scale position}
|
||||
var
|
||||
px, py: Integer;
|
||||
begin
|
||||
FCanvas.Pen.Color := Color;
|
||||
px := X2P(x);
|
||||
py := Y2P(y);
|
||||
FCanvas.Rectangle(px-1, py+1, px+1, py-1)
|
||||
end;
|
||||
|
||||
procedure TMolChart.DrawLine(x0, y0, x1, y1: Double; Color: TColor; PenWidth: Integer);
|
||||
{draw a line from (x0,y0) to (x1,y1) scale co-ordinates}
|
||||
begin
|
||||
FCanvas.Pen.Color := Color;
|
||||
FCanvas.Pen.Width := PenWidth;
|
||||
MoveTo(x0, y0);
|
||||
LineTo(x1, y1)
|
||||
end;
|
||||
|
||||
procedure TMolChart.DrawVec(x, y: fvec; Color: TColor; PenWidth: Integer);
|
||||
{draw a (xi,yi) vector}
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
FCanvas.Pen.Color := Color;
|
||||
FCanvas.Pen.Width := PenWidth;
|
||||
MoveTo(x[0], y[0]);
|
||||
for i := 1 to length(x)-1 do
|
||||
LineTo(x[i], y[i])
|
||||
end;
|
||||
|
||||
procedure TMolChart.DrawChart(ref: PAnsiChar; Width, Height: Integer);
|
||||
{draw the mollier chart}
|
||||
const
|
||||
n = 23;
|
||||
var
|
||||
i, Count: Integer;
|
||||
pc, tc, dc, hc: Double;
|
||||
p, hf, hg: fvec;
|
||||
dx, dy: Double;
|
||||
_hf, _hg: Double;
|
||||
begin
|
||||
R := Rect(0, 0, Width, Height);
|
||||
FCanvas.Brush.Color := $00f8fcfa;
|
||||
FCanvas.FillRect(R);
|
||||
InflateRect(R, -FMargin, -FMargin);
|
||||
FCanvas.Pen.Color := clGray;
|
||||
FCanvas.Pen.Width := 1;
|
||||
FCanvas.Rectangle(R);
|
||||
pc := 1e-6*Props1SI('PCRIT', ref);
|
||||
tc := Props1SI('TCRIT', ref);
|
||||
dc := Props1SI('RHOCRIT', ref);
|
||||
hc := 1e-3*PropsSI('H', 'T', tc, 'D', dc, ref);
|
||||
y0 := 0.1;
|
||||
y1 := pc;
|
||||
// test for fluid critical pressure < 1 Mpa
|
||||
if y1 <= y0 then y0 := 0.1*y1;
|
||||
// generate n points
|
||||
SetLength(p, n);
|
||||
SetLength(hf, n);
|
||||
SetLength(hg, n);
|
||||
Count := 0;
|
||||
for i := 0 to n-1 do begin
|
||||
p[i] := y0 + i*(y1-y0)/n;
|
||||
_hf := 1e-3*PropsSI('H', 'P', 1e6*p[i], 'Q', 0, ref);
|
||||
_hg := 1e-3*PropsSI('H', 'P', 1e6*p[i], 'Q', 1, ref);
|
||||
if IsInfinite(_hf) or IsInfinite(_hg) then continue;
|
||||
if (_hf=0) or (_hg=0) then continue;
|
||||
hf[Count] := _hf;
|
||||
hg[Count] := _hg;
|
||||
Count := Count + 1;
|
||||
end;
|
||||
SetLength(p, Count);
|
||||
SetLength(hf, Count);
|
||||
SetLength(hg, Count);
|
||||
|
||||
// adjust the scale
|
||||
x0 := MinValue(hf);
|
||||
_hg := MinValue(hg);
|
||||
if _hg < x0 then x0 := _hg;
|
||||
x1 := MaxValue(hg);
|
||||
_hf := MaxValue(hf);
|
||||
if _hf > x1 then x1 := _hf;
|
||||
dx := x1-x0;
|
||||
dy := y1-y0;
|
||||
x0 := x0-0.1*dx;
|
||||
x1 := x1+0.4*dx;
|
||||
y1 := y1+0.1*dy;
|
||||
CalcScaleFactor;
|
||||
|
||||
DrawVec(hf, p, clGreen, 2); // liquid line
|
||||
DrawVec(hg, p, clRed, 2); // vapor line
|
||||
DrawPoint(hc, pc, clBlue) // critical point
|
||||
end;
|
||||
|
||||
end.
|
||||
{
|
||||
Mollier Chart (ph-chart) generator
|
||||
Bruce Wernick, 13 December 2015
|
||||
}
|
||||
|
||||
unit uMolChart;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, Windows, Graphics, Classes,
|
||||
cpIntf;
|
||||
|
||||
type
|
||||
fvec = array of Double;
|
||||
TMolChart = class
|
||||
private
|
||||
FCanvas: TCanvas;
|
||||
R: TRect;
|
||||
FMargin: Integer;
|
||||
x0, x1, y0, y1: Double;
|
||||
lny0, lny1: Double;
|
||||
xf, yf: Double;
|
||||
procedure CalcScaleFactor;
|
||||
public
|
||||
constructor Create(Canvas: TCanvas);
|
||||
function X2P(x: Double): Integer;
|
||||
function Y2P(y: Double): Integer;
|
||||
function P2X(p: Integer): Double;
|
||||
function P2Y(p: Integer): Double;
|
||||
procedure MoveTo(x, y: Double);
|
||||
procedure Lineto(x, y: Double);
|
||||
procedure DrawPoint(x, y: Double; Color: TColor);
|
||||
procedure DrawLine(x0, y0, x1, y1: Double; Color: TColor; PenWidth: Integer);
|
||||
procedure DrawVec(x, y: fvec; Color: TColor; PenWidth: Integer);
|
||||
procedure DrawChart(ref: PAnsiChar; Width, Height: Integer);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
Math;
|
||||
|
||||
constructor TMolChart.Create(Canvas: TCanvas);
|
||||
begin
|
||||
FMargin := 25;
|
||||
FCanvas := Canvas
|
||||
end;
|
||||
|
||||
procedure TMolChart.CalcScaleFactor;
|
||||
{calculate the scale factor}
|
||||
begin
|
||||
xf := (x1-x0)/(R.Right-R.Left);
|
||||
lny0 := ln(y0);
|
||||
lny1 := ln(y1);
|
||||
yf := (lny1-lny0)/(R.Top-R.Bottom)
|
||||
end;
|
||||
|
||||
function TMolChart.X2P(x: Double): Integer;
|
||||
{X scale value to chart pixel value}
|
||||
begin
|
||||
Result := Trunc(R.Left+(x-x0)/xf)
|
||||
end;
|
||||
|
||||
function TMolChart.Y2P(y: Double): Integer;
|
||||
{Y scale value to chart pixel value}
|
||||
begin
|
||||
Result := Trunc(R.Bottom+(ln(y)-lny0)/yf)
|
||||
end;
|
||||
|
||||
function TMolChart.P2X(p: Integer): Double;
|
||||
{pixel point to x scale value}
|
||||
begin
|
||||
Result := x0+(p-R.Left)*xf
|
||||
end;
|
||||
|
||||
function TMolChart.P2Y(p: Integer): Double;
|
||||
{pixel point to y scale value}
|
||||
begin
|
||||
Result := exp(lny0+(p-R.Bottom)*yf)
|
||||
end;
|
||||
|
||||
procedure TMolChart.MoveTo(x, y: Double);
|
||||
{move to (x,y) scale position}
|
||||
begin
|
||||
FCanvas.MoveTo(X2P(x), Y2P(y))
|
||||
end;
|
||||
|
||||
procedure TMolChart.LineTo(x, y: Double);
|
||||
{line to (x,y) scale position}
|
||||
begin
|
||||
FCanvas.LineTo(X2P(x), Y2P(y))
|
||||
end;
|
||||
|
||||
procedure TMolChart.DrawPoint(x, y: Double; Color: TColor);
|
||||
{draw a square at (x,y) scale position}
|
||||
var
|
||||
px, py: Integer;
|
||||
begin
|
||||
FCanvas.Pen.Color := Color;
|
||||
px := X2P(x);
|
||||
py := Y2P(y);
|
||||
FCanvas.Rectangle(px-1, py+1, px+1, py-1)
|
||||
end;
|
||||
|
||||
procedure TMolChart.DrawLine(x0, y0, x1, y1: Double; Color: TColor; PenWidth: Integer);
|
||||
{draw a line from (x0,y0) to (x1,y1) scale co-ordinates}
|
||||
begin
|
||||
FCanvas.Pen.Color := Color;
|
||||
FCanvas.Pen.Width := PenWidth;
|
||||
MoveTo(x0, y0);
|
||||
LineTo(x1, y1)
|
||||
end;
|
||||
|
||||
procedure TMolChart.DrawVec(x, y: fvec; Color: TColor; PenWidth: Integer);
|
||||
{draw a (xi,yi) vector}
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
FCanvas.Pen.Color := Color;
|
||||
FCanvas.Pen.Width := PenWidth;
|
||||
MoveTo(x[0], y[0]);
|
||||
for i := 1 to length(x)-1 do
|
||||
LineTo(x[i], y[i])
|
||||
end;
|
||||
|
||||
procedure TMolChart.DrawChart(ref: PAnsiChar; Width, Height: Integer);
|
||||
{draw the mollier chart}
|
||||
const
|
||||
n = 23;
|
||||
var
|
||||
i, Count: Integer;
|
||||
pc, tc, dc, hc: Double;
|
||||
p, hf, hg: fvec;
|
||||
dx, dy: Double;
|
||||
_hf, _hg: Double;
|
||||
begin
|
||||
R := Rect(0, 0, Width, Height);
|
||||
FCanvas.Brush.Color := $00f8fcfa;
|
||||
FCanvas.FillRect(R);
|
||||
InflateRect(R, -FMargin, -FMargin);
|
||||
FCanvas.Pen.Color := clGray;
|
||||
FCanvas.Pen.Width := 1;
|
||||
FCanvas.Rectangle(R);
|
||||
pc := 1e-6*Props1SI('PCRIT', ref);
|
||||
tc := Props1SI('TCRIT', ref);
|
||||
dc := Props1SI('RHOCRIT', ref);
|
||||
hc := 1e-3*PropsSI('H', 'T', tc, 'D', dc, ref);
|
||||
y0 := 0.1;
|
||||
y1 := pc;
|
||||
// test for fluid critical pressure < 1 Mpa
|
||||
if y1 <= y0 then y0 := 0.1*y1;
|
||||
// generate n points
|
||||
SetLength(p, n);
|
||||
SetLength(hf, n);
|
||||
SetLength(hg, n);
|
||||
Count := 0;
|
||||
for i := 0 to n-1 do begin
|
||||
p[i] := y0 + i*(y1-y0)/n;
|
||||
_hf := 1e-3*PropsSI('H', 'P', 1e6*p[i], 'Q', 0, ref);
|
||||
_hg := 1e-3*PropsSI('H', 'P', 1e6*p[i], 'Q', 1, ref);
|
||||
if IsInfinite(_hf) or IsInfinite(_hg) then continue;
|
||||
if (_hf=0) or (_hg=0) then continue;
|
||||
hf[Count] := _hf;
|
||||
hg[Count] := _hg;
|
||||
Count := Count + 1;
|
||||
end;
|
||||
SetLength(p, Count);
|
||||
SetLength(hf, Count);
|
||||
SetLength(hg, Count);
|
||||
|
||||
// adjust the scale
|
||||
x0 := MinValue(hf);
|
||||
_hg := MinValue(hg);
|
||||
if _hg < x0 then x0 := _hg;
|
||||
x1 := MaxValue(hg);
|
||||
_hf := MaxValue(hf);
|
||||
if _hf > x1 then x1 := _hf;
|
||||
dx := x1-x0;
|
||||
dy := y1-y0;
|
||||
x0 := x0-0.1*dx;
|
||||
x1 := x1+0.4*dx;
|
||||
y1 := y1+0.1*dy;
|
||||
CalcScaleFactor;
|
||||
|
||||
DrawVec(hf, p, clGreen, 2); // liquid line
|
||||
DrawVec(hg, p, clRed, 2); // vapor line
|
||||
DrawPoint(hc, pc, clBlue) // critical point
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user