Skip to content

Commit

Permalink
API: Add functions to the DSSEvents interface. Docs updated.
Browse files Browse the repository at this point in the history
Already tested; final integration still required in the downstream projects.
Added only for compatibility.
  • Loading branch information
PMeira committed Jun 26, 2023
1 parent c05289f commit 795ff04
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 14 deletions.
2 changes: 1 addition & 1 deletion OPENDSS_LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
* Copyright (c) 2008-2021, Electric Power Research Institute, Inc.
* Copyright (c) 2008-2023, Electric Power Research Institute, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ Since 2019-03-05, the `dss_capi` repository contains all the Pascal code used to

See [the changelog](https://github.com/dss-extensions/dss_capi/blob/master/docs/changelog.md) for a detailed list.

- **2023-06-11 / version 0.13.3: Bugfix release for some components (notably Capacitor, Reactor, UPFC). See the changelog or release page for details.**
- **2023-06-26 / version 0.13.4: Bugfix release (CapControl), incremental improvements. See the changelog or release page for details.**
- 2023-06-11 / version 0.13.3: Bugfix release for some components (notably Capacitor, Reactor, UPFC). See the changelog or release page for details.
- 2023-05-24 / version 0.13.2: Minor release, includes updates to JSON exports, some more error-checking, internal code refactoring, header updates, and minor ports from the official OpenDSS.
- 2023-04-01 / version 0.13.1: Minor release to address a few PVSystem properties
- 2023-03-29 / version 0.13.0: Various updates, including bugfixes and several OpenDSS feature ports; the reference is now OpenDSS v9.6.1.1.
Expand Down
10 changes: 8 additions & 2 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,16 @@

# Versions 0.13.x

## Version 0.13.4 (2023-06-xx)
## Version 0.13.4 (2023-06-26)

Bugfix release (upcoming)
Bugfix release for `CapControl`, couple with some incremental improvements.

This version should match OpenDSS v9.6.1.3 (SVN r3623).

- Ported from the official OpenDSS SVN code:
- `CapControl`, port SVN 3622: "Solves a bug introduced in version 9.6.1.2 when using CapControl in time or follow control modes." (by davismont).

- Added `DSSEvents`: Implement an initial set of functions analog to the COM interface. This was added for historical compatibility since use of `DSSEvents` is rarely seen. [This document from EPRI (2011)](https://restservice.epri.com/publicdownload/000000000001020090/0/Product) presents the equivalent in the COM interface. Examples will be added in our downstream projects when time allows (feel free to request one to signal interest in this feature).
- Handle better how the internal `SolutionAbort` is used. Some invalid states where not being handled on absence of float-point exceptions, leading to potential useless results (NaN) and even crashes.
- `VSource`: Abort the solution if Z1 is zero.

Expand Down
9 changes: 9 additions & 0 deletions include/dss_capi.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ extern "C" {
*/
typedef int32_t (*dss_callback_plot_t)(void* ctx, char* jsonParams);
typedef int32_t (*dss_callback_message_t)(void* ctx, char* messageStr, int32_t messageType);
typedef void (*dss_callback_solution_t)(void* ctx);

/* Functions start here */

Expand Down Expand Up @@ -288,6 +289,14 @@ extern "C" {
DSS_CAPI_DLL void DSS_RegisterPlotCallback(dss_callback_plot_t cb);
DSS_CAPI_DLL void DSS_RegisterMessageCallback(dss_callback_message_t cb);

/*! Functions to register and unregister callbacks for the solution events (DSSEvents in COM) */
DSS_CAPI_DLL uint16_t DSSEvents_RegisterInitControls(dss_callback_solution_t cb);
DSS_CAPI_DLL uint16_t DSSEvents_RegisterCheckControls(dss_callback_solution_t cb);
DSS_CAPI_DLL uint16_t DSSEvents_RegisterStepControls(dss_callback_solution_t cb);
DSS_CAPI_DLL uint16_t DSSEvents_UnregisterInitControls(dss_callback_solution_t cb);
DSS_CAPI_DLL uint16_t DSSEvents_UnregisterCheckControls(dss_callback_solution_t cb);
DSS_CAPI_DLL uint16_t DSSEvents_UnregisterStepControls(dss_callback_solution_t cb);

DSS_CAPI_DLL void DSS_NewCircuit(const char* Value);

/*!
Expand Down
8 changes: 8 additions & 0 deletions include/dss_capi_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ extern "C" {
DSS_CAPI_DLL void ctx_DSS_RegisterPlotCallback(void* ctx, dss_callback_plot_t cb);
DSS_CAPI_DLL void ctx_DSS_RegisterMessageCallback(void* ctx, dss_callback_message_t cb);

/*! Functions to register and unregister callbacks for the solution events (DSSEvents in COM) */
DSS_CAPI_DLL uint16_t ctx_DSSEvents_RegisterInitControls(void* ctx, dss_callback_solution_t cb);
DSS_CAPI_DLL uint16_t ctx_DSSEvents_RegisterCheckControls(void* ctx, dss_callback_solution_t cb);
DSS_CAPI_DLL uint16_t ctx_DSSEvents_RegisterStepControls(void* ctx, dss_callback_solution_t cb);
DSS_CAPI_DLL uint16_t ctx_DSSEvents_UnregisterInitControls(void* ctx, dss_callback_solution_t cb);
DSS_CAPI_DLL uint16_t ctx_DSSEvents_UnregisterCheckControls(void* ctx, dss_callback_solution_t cb);
DSS_CAPI_DLL uint16_t ctx_DSSEvents_UnregisterStepControls(void* ctx, dss_callback_solution_t cb);

DSS_CAPI_DLL void ctx_DSS_NewCircuit(void* ctx, const char* Value);

/*!
Expand Down
70 changes: 70 additions & 0 deletions src/CAPI/CAPI_DSS.pas
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ function DSS_SetActiveClass(const ClassName: PAnsiChar): Integer; CDECL;
function DSS_Get_AllowForms(): TAPIBoolean; CDECL;
procedure DSS_Set_AllowForms(Value: TAPIBoolean); CDECL;

// These were originally implemented (very differently) in the DSSEvents interface,
// but they are simple functions here.
function DSSEvents_RegisterInitControls(cb: dss_callback_solution_t): TAPIBoolean; CDECL;
function DSSEvents_RegisterCheckControls(cb: dss_callback_solution_t): TAPIBoolean; CDECL;
function DSSEvents_RegisterStepControls(cb: dss_callback_solution_t): TAPIBoolean; CDECL;
function DSSEvents_UnregisterInitControls(cb: dss_callback_solution_t): TAPIBoolean; CDECL;
function DSSEvents_UnregisterCheckControls(cb: dss_callback_solution_t): TAPIBoolean; CDECL;
function DSSEvents_UnregisterStepControls(cb: dss_callback_solution_t): TAPIBoolean; CDECL;

// Extensions
function DSS_Get_AllowEditor(): TAPIBoolean; CDECL;
procedure DSS_Set_AllowEditor(Value: TAPIBoolean); CDECL;
Expand Down Expand Up @@ -311,4 +320,65 @@ procedure DSS_Set_CompatFlags(Value: LongWord); CDECL;
SelectAs2pVersion((DSS_EXTENSIONS_COMPAT and ord(TDSSCompatFlags.BadPrecision)) <> 0);
end;
//------------------------------------------------------------------------------
function removeFromArray(var cbs: dss_callbacks_solution_t; target: dss_callback_solution_t): Boolean;
var
i, j: Integer;
begin
Result := False;
for i := 0 to High(cbs) do
begin
if @cbs[i] = @target then
begin
// Move any other callbacks back and resize
for j := i + 1 to High(cbs) do
begin
cbs[j - 1] := @cbs[j];
end;
SetLength(cbs, Length(cbs) - 1);
Result := True;
Exit;
end;
end;
end;

function appendToArray(var cbs: dss_callbacks_solution_t; target: dss_callback_solution_t): Boolean;
var
cb: dss_callback_solution_t;
begin
Result := False;
for cb in cbs do
begin
if @cb = @target then
Exit; // already added, ignore
end;
SetLength(cbs, Length(cbs) + 1);
cbs[High(cbs)] := @target;
Result := True;
end;

function DSSEvents_RegisterInitControls(cb: dss_callback_solution_t): TAPIBoolean; CDECL;
begin
Result := appendToArray(DSSPrime.DSSInitControlsCallbacks, @cb);
end;
function DSSEvents_RegisterCheckControls(cb: dss_callback_solution_t): TAPIBoolean; CDECL;
begin
Result := appendToArray(DSSPrime.DSSCheckControlsCallbacks, @cb);
end;
function DSSEvents_RegisterStepControls(cb: dss_callback_solution_t): TAPIBoolean; CDECL;
begin
Result := appendToArray(DSSPrime.DSSStepControlsCallbacks, @cb);
end;
function DSSEvents_UnregisterInitControls(cb: dss_callback_solution_t): TAPIBoolean; CDECL;
begin
Result := removeFromArray(DSSPrime.DSSInitControlsCallbacks, @cb);
end;
function DSSEvents_UnregisterCheckControls(cb: dss_callback_solution_t): TAPIBoolean; CDECL;
begin
Result := removeFromArray(DSSPrime.DSSCheckControlsCallbacks, @cb);
end;
function DSSEvents_UnregisterStepControls(cb: dss_callback_solution_t): TAPIBoolean; CDECL;
begin
Result := removeFromArray(DSSPrime.DSSStepControlsCallbacks, @cb);
end;
//------------------------------------------------------------------------------
end.
61 changes: 60 additions & 1 deletion src/Common/DSSClass.pas
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

unit DSSClass;
// ----------------------------------------------------------
// Copyright (c) 2018-2022, Paulo Meira, DSS-Extensions contributors
// Copyright (c) 2018-2023, Paulo Meira, DSS-Extensions contributors
// Copyright (c) 2008-2015, Electric Power Research Institute, Inc.
// All rights reserved.
// ----------------------------------------------------------
Expand Down Expand Up @@ -241,6 +241,8 @@ TDSSContext = class;

dss_callback_plot_t = function (DSS: TDSSContext; jsonParams: PChar): Integer; CDECL;
dss_callback_message_t = function (DSS: TDSSContext; messageStr: PChar; messageType: Integer): Integer; CDECL;
dss_callback_solution_t = procedure (DSS: TDSSContext); CDECL;
dss_callbacks_solution_t = Array of dss_callback_solution_t;

// Base for all collection classes
TDSSClass = class;
Expand Down Expand Up @@ -487,6 +489,9 @@ TDSSContext = class(TObject)

DSSPlotCallback: dss_callback_plot_t;
DSSMessageCallback: dss_callback_message_t;
DSSInitControlsCallbacks: dss_callbacks_solution_t;
DSSCheckControlsCallbacks: dss_callbacks_solution_t;
DSSStepControlsCallbacks: dss_callbacks_solution_t;

// Parallel Machine state
{$IFDEF DSS_CAPI_PM}
Expand Down Expand Up @@ -615,6 +620,11 @@ TDSSContext = class(TObject)
property SolutionAbort: Boolean READ get_SolutionAbort WRITE set_SolutionAbort;
function GetROFileStream(fn: String): TStream;
procedure NewDSSClass(Value: Pointer);

// For the DSSEvents interface
procedure Fire_InitControls();
procedure Fire_CheckControls();
procedure Fire_StepControls();
End;

VAR
Expand Down Expand Up @@ -836,6 +846,9 @@ constructor TDSSContext.Create(_Parent: TDSSContext; _IsPrime: Boolean);

DSSPlotCallback := nil;
DSSMessageCallback := nil;
DSSInitControlsCallbacks := nil;
DSSCheckControlsCallbacks := nil;
DSSStepControlsCallbacks := nil;

ClassNames := NIL;
DSSClassList := NIL;
Expand Down Expand Up @@ -984,6 +997,52 @@ destructor TDSSContext.Destroy;
inherited Destroy;
end;


procedure TDSSContext.Fire_InitControls();
var
cb: dss_callback_solution_t;
begin
if Length(DSSInitControlsCallbacks) = 0 then
Exit;

for cb in DSSInitControlsCallbacks do
begin
if (@cb) = NIL then
continue;
cb(self);
end;
end;

procedure TDSSContext.Fire_CheckControls();
var
cb: dss_callback_solution_t;
begin
if Length(DSSCheckControlsCallbacks) = 0 then
Exit;

for cb in DSSCheckControlsCallbacks do
begin
if (@cb) = NIL then
continue;
cb(self);
end;
end;

procedure TDSSContext.Fire_StepControls();
var
cb: dss_callback_solution_t;
begin
if Length(DSSStepControlsCallbacks) = 0 then
Exit;

for cb in DSSStepControlsCallbacks do
begin
if (@cb) = NIL then
continue;
cb(self);
end;
end;

function TDSSContext.CurrentDSSDir(): String;
begin
if DSS_CAPI_ALLOW_CHANGE_DIR then
Expand Down
13 changes: 4 additions & 9 deletions src/Common/Solution.pas
Original file line number Diff line number Diff line change
Expand Up @@ -584,9 +584,8 @@ procedure TSolutionObj.Solve;
else
DefaultGrowthFactor := IntPower(DefaultGrowthRate, (year - 1));
end;
{$IFDEF DLL_ENGINE}
Fire_InitControls;
{$ENDIF}
DSS.Fire_InitControls();

// CheckFaultStatus; ???? needed here??

{$IFDEF DSS_CAPI_PM}
Expand Down Expand Up @@ -1183,9 +1182,7 @@ function TSolutionObj.SolveSnap: Integer; // solve for now once

Result := SolveCircuit; // Do circuit solution w/o checking controls
{Now Check controls}
{$IFDEF DLL_ENGINE}
Fire_CheckControls;
{$ENDIF}
DSS.Fire_CheckControls();
CheckControls;

{For reporting max iterations per control iteration}
Expand All @@ -1205,9 +1202,7 @@ function TSolutionObj.SolveSnap: Integer; // solve for now once
if DSS.ActiveCircuit.LogEvents then
LogThisEvent(DSS, 'Solution Done');

{$IFDEF DLL_ENGINE}
Fire_StepControls;
{$ENDIF}
DSS.Fire_StepControls();

{$IFDEF MSWINDOWS}
QueryPerformanceCounter(SolveEndTime);
Expand Down
6 changes: 6 additions & 0 deletions src/dss_capi.lpr
Original file line number Diff line number Diff line change
Expand Up @@ -2000,6 +2000,12 @@

DSS_RegisterPlotCallback,
DSS_RegisterMessageCallback,
DSSEvents_RegisterInitControls,
DSSEvents_RegisterCheckControls,
DSSEvents_RegisterStepControls,
DSSEvents_UnregisterInitControls,
DSSEvents_UnregisterCheckControls,
DSSEvents_UnregisterStepControls,

DSS_ExtractSchema,
DSS_Dispose_String,
Expand Down

0 comments on commit 795ff04

Please sign in to comment.