XYCurve Object
The XYCurve object is a general OpenDSS library object used by several circuit elements. For example, the PVSystem device uses this class of object for both efficiency curves and power‐temperature curves. An XYCurve object may be used for other somewhat arbitrary purposes as well. A user can define an XYCurve object then interpolate (or extrapolate) values from the curve, which might be useful for any of several purposes.
An XYCurve object may be defined and accessed through both the text scripting interface and the COM interface. The basic idea is to first define a curve. Then pass either an X or Y value and get the other value from the curve. This is handled internally via public properties in the object that other objects can access, but the user can also do this from external means on any XYcurve currently defined. One obvious application is that users writing external code to drive the COM interface do not have to write code to manage any curves they might wish to include in their custom model. Simply use an XYCurve object.
The XYCurve object uses linear interpolation. Points past the end of the defined curve are extrapolated using the last two points in the curve.
Recently, shifting and scaling properties were added to the objects so that one may define a base curve and then shift it around to represent other sizes of elements, for examples.
TEXT INTERFACE DESCRIPTION
Property |
Description |
(1) npts |
Max number of points to expect in curve. This could get reset to the actual number of points defined if less than specified. |
(2) Points |
One way to enter the points in a curve. Enter x and y values as one array in the order [x1, y1, x2, y2,...]. For example: Points=[1,100 2,200 3, 300] Values separated by commas or white space. Zero fills arrays if insufficient number of values. |
(3) Yarray |
Alternate way to enter Y values. Enter an array of Y values corresponding to the X values. You can also use the syntax: Yarray = (file=filename) !for text file one value per line Yarray = (dblfile=filename) !for packed file of doubles Yarray = (sngfile=filename) !for packed file of singles Note: this property will reset Npts to a smaller value if the number of values in the files are fewer |
(4) Xarray |
Alternate way to enter X values. Enter an array of X values corresponding to the Y values. You can also use the syntax: Xarray = (file=filename) !for text file one value per line Xarray = (dblfile=filename) !for packed file of doubles Xarray = (sngfile=filename) !for packed file of singles Note: this property will reset Npts to a smaller value if the number of values in the files are fewer. |
(5) csvfile |
Switch input of X‐Y curve data to a CSV file containing X, Y points one per line. NOTE: This action may reset the number of points to a lower value. |
(6) sngfile |
Switch input of X‐Y curve data to a binary file of SINGLES containing X, Y points packed one after another. NOTE: This action may reset the number of points to a lower value. |
(7) dblfile |
Switch input of X‐Y curve data to a binary file of DOUBLES containing X, Y points packed one after another. NOTE: This action may reset the number of points to a lower value. |
(8) x |
Enter a value and then retrieve the interpolated Y value from the Y property. On input, shifted then scaled to original curve. Scaled then shifted on output. |
(9) y |
Enter a value and then retrieve the interpolated X value from the X property. On input, shifted then scaled to original curve. Scaled then shifted on output. |
(10) Xshift |
Shift X property values (in/out) by this amount of offset. Default = 0. Does not change original definition of arrays. |
(11) Yshift |
Shift Y property values (in/out) by this amount of offset. Default = 0. Does not change original definition of arrays. |
(12) Xscale |
Scale X property values (in/out) by this factor. Default = 1.0. Does not change original definition of arrays. |
(13) Yscale |
Scale Y property values (in/out) by this factor. Default = 1.0. Does not change original definition of arrays. |
(14) like |
Make like another object, e.g.: New XYCurve.Curve2 Like=Curve1 |
EXAMPLE SCRIPT
You can use the script below to exercise an XYCurve object. A circuit must be defined, but you can exercise the object with no elements other than the initial Vsource.
clear
New Circuit.XYCurve basekv=12.47 Isc3=1000 Isc1=900
// P-T curve is per unit of rated Pmpp vs temperature
// This one is for a Pmpp stated at 25 deg
New XYCurve.MyPvsT npts=4 xarray=[0 25 75 100] yarray=[1.2 1.0 0.8 0.6]
// efficiency curve is per unit eff vs per unit power
New XYCurve.MyEff npts=4 xarray=[.1 .2 .4 1.0] yarray=[.86 .9 .93 .97]
XYCurve.MyEff.x=0.6 ! set x value to 0.6
? XYCurve.MyEff.y ! return corresponding Y in Result window
/*
Returns 0.94333333 in Result window
i.e., for 60% power, the inverter efficiency is 94.3333%
*/
XYCurve.MyPvsT.Yscale=0.5 X=75
? XYCurve.MyPvsT.Y
/*
Returns 0.4 in Result window (half of 0.8)
*/
COM INTERFACE
Concise Pascal Definition of XYCurves Interface
This is one of the more concise listings of the available interface properties. If you are using VBA or MATLAB to drive the COM interface, these are the names of the properties you will use. Refer to this list if your development environment is not kind enough to prompt you for them.
This interface uses a set of functions similar to what are used in most other OpenDSS interfaces. The idea is to find an object of this class, set it active, and operate on it. If you know the name of the XYCurve object, you can set it active directly by the Name property. Or you can search through the list
by the First..Next iterators until you find the one you want or operate on all as you go through the list.
You can get/set the values of the X and Y arrays used to define the curves. Then you can get/set shifting and scaling factors and interpolate X and Y values just like in the text interface. This should be somewhat faster because the values don’t have to be converted to and from text.
// *********************************************************************//
// DispIntf: IXYCurvesDisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {97AA7680-E994-4A0C-BAC3-9B67BA49825C}
// *********************************************************************//
IXYCurvesDisp = dispinterface
['{97AA7680-E994-4A0C-BAC3-9B67BA49825C}']
property Count: Integer readonly dispid 201;
property First: Integer readonly dispid 202;
property Next: Integer readonly dispid 203;
property Name: WideString dispid 204;
property Npts: Integer dispid 205;
property Xarray: OleVariant dispid 206;
function Yarray: OleVariant; dispid 207;
property x: Double dispid 208;
property y: Double dispid 209;
property Xshift: Double dispid 210;
property Yshift: Double dispid 211;
property Xscale: Double dispid 212;
property Yscale: Double dispid 213;
end;
A listing in IDL format is also included below for those programmers more familiar with that format. The files are available in the Source code repository.
EXAMPLE IN VBA
This example subroutine assumes the existence of a public variable DSSCircuit and sets a local variable to the XYCurves interface that is created when OpenDSSEngine is started. Thus, we only have to use the DSSCurves variable to access any or all of the XYCurve object presently defined.
This sub first prints out the names of all XYCurve object presently defined. The typical First .. Next iterators are used for this. Then it sets the last one active using the Name property. Like other interfaces in OpenDSS, once this object is set active, you can operate on it with other appropriate interfaces such as DSSElement. Then, the code exercises several properties in the interface and prints out their values to confirm that their actions.
You can put this VBA code in MS Excel and execute it there in the usual manner. (See SampleDSSDriver.XLS if you are not familiar with this.) You will obviously have to load in a circuit definition that has XYCurve objects defined.
Public Sub TestXYCurve()
Dim DSSCurves As XYCurves
Dim i As Long
Dim V As Variant
Dim LastName As String
Set DSSCurves = DSSCircuit.XYCurves
Debug.Print "Version: "; DSSobj.Version
Debug.Print "Count="; DSSCurves.Count
i = DSSCurves.First
Do While i > 0
LastName = DSSCurves.Name
Debug.Print i; ", "; LastName
i = DSSCurves.Next
Loop
DSSCurves.Name = LastName ' set active by name
Debug.Print "Active curve="; DSSCurves.Name ' check to make sure it worked
Debug.Print "Num Points = "; DSSCurves.Npts
V = DSSCurves.Xarray
Debug.Print "Xarray=';"
For i = LBound(V) To UBound(V)
Debug.Print V(i); ", ";
Next i
Debug.Print " "
V = DSSCurves.Yarray
Debug.Print "Yarray=';"
For i = LBound(V) To UBound(V)
Debug.Print V(i); ", ";
Next i
Debug.Print " "
' test x and y actions
With DSSCurves
.x = 0.4
Debug.Print "For X="; .x; " Y="; .y
' Scale curve down
.Yscale = 0.5 ' derated by half
.x = 0.4
Debug.Print "For X="; .x; " and Yscale="; .Yscale; " Y="; .y
.Yscale = 1#
.Yshift = 1# ' shift curve up by 1
.x = 0.4
Debug.Print "For X="; .x; " and Yshift="; .Yshift; " Y="; .y
' now go the other way ... set Y and get x
.y = 1.93 ' shift is still in effect
Debug.Print "For Y="; .y; " and Yshift="; .Yshift; " X="; .x
' back to original
.Yshift = 0#
.y = 0.93 ' shift is still in effect
Debug.Print "For Y="; .y; " and Yshift="; .Yshift; " X="; .x
End With
End Sub
COM INTERFACE DEFINITION IN IDL FORMAT
[
uuid(97AA7680-E994-4A0C-BAC3-9B67BA49825C),
helpstring("Dispatch interface for XYCurves Object"),
dual,
oleautomation
]
interface IXYCurves: IDispatch
{
[propget, id(0x000000C9), helpstring("Number of XYCurve Objects")]
HRESULT _stdcall Count([out, retval] long* Value);
[propget, id(0x000000CA), helpstring("Sets first XYcurve object active; returns 0
if none.")]
HRESULT _stdcall First([out, retval] long* Value);
[propget, id(0x000000CB), helpstring("Advances to next XYCurve object; returns 0
if no more objects of this class")]
HRESULT _stdcall Next([out, retval] long* Value);
[propget, id(0x000000CC), helpstring("Name of active XYCurve Object")]
HRESULT _stdcall Name([out, retval] BSTR* Value);
[propput, id(0x000000CC), helpstring("Get Name of active XYCurve Object")]
HRESULT _stdcall Name([in] BSTR Value);
[propget, id(0x000000CD), helpstring("Get/Set Number of points in X-Y curve")]
HRESULT _stdcall Npts([out, retval] long* Value);
[propput, id(0x000000CD), helpstring("Get/Set Number of Points in X-Y curve")]
HRESULT _stdcall Npts([in] long Value);
[propget, id(0x000000CE), helpstring("Get/Set X values as a Variant array of
doubles. Set Npts to max number expected if setting")]
HRESULT _stdcall Xarray([out, retval] VARIANT* Value);
[propput, id(0x000000CE), helpstring("Get/Set X values as a Variant array of
doubles. Set Npts to max number expected if setting")]
HRESULT _stdcall Xarray([in] VARIANT Value);
[propget, id(0x000000CF), helpstring("Get/Set Y values in curve; Set Npts to max
number expected if setting")]
HRESULT _stdcall Yarray([out, retval] VARIANT* Value);
[propput, id(0x000000CF), helpstring("Get/Set Y values in curve; Set Npts to max
number expected if setting")]
void _stdcall Yarray([in] VARIANT Value);
[propget, id(0x000000D0), helpstring("Set X value or get interpolated value after
setting Y")]
HRESULT _stdcall x([out, retval] double* Value);
[propput, id(0x000000D0)]
HRESULT _stdcall x([in] double Value);
[propget, id(0x000000D1), helpstring("Y value for present X or set this value then
get corresponding X")]
HRESULT _stdcall y([out, retval] double* Value);
[propput, id(0x000000D1), helpstring("Set Y value or get interpolated Y value
after setting X")]
HRESULT _stdcall y([in] double Value);
[propget, id(0x000000D2), helpstring("Amount to shift X value from original
curve")]
HRESULT _stdcall Xshift([out, retval] double* Value);
[propput, id(0x000000D2)]
HRESULT _stdcall Xshift([in] double Value);
[propget, id(0x000000D3), helpstring("amount to shift Y valiue from original
curve")]
HRESULT _stdcall Yshift([out, retval] double* Value);
[propput, id(0x000000D3)]
HRESULT _stdcall Yshift([in] double Value);
[propget, id(0x000000D4), helpstring("Factor to scale X values from original
curve")]
HRESULT _stdcall Xscale([out, retval] double* Value);
[propput, id(0x000000D4), helpstring("Factor to scale X values from original
curve")]
HRESULT _stdcall Xscale([in] double Value);
[propget, id(0x000000D5), helpstring("Factor to scale Y values from original
curve")]
HRESULT _stdcall Yscale([out, retval] double* Value);
[propput, id(0x000000D5), helpstring("Amount to scale Y values from original
curve. Represents a curve shift.")]
HRESULT _stdcall Yscale([in] double Value);
};