Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The result of OpenDSSDirect is different from that of OpenDs.exe in x64. #137

Open
HHuuuhh666 opened this issue Dec 26, 2024 · 8 comments
Open

Comments

@HHuuuhh666
Copy link

HHuuuhh666 commented Dec 26, 2024

No description provided.

@PMeira
Copy link
Member

PMeira commented Jan 6, 2025

It seems you already handled it, but I'll leave a few comments before closing this.

  • OpenDSSDirect.py has no direct relation to OpenDSS.exe. The upcoming version will support the official OpenDSSDirect.DLL again, but the current stable release is based only on the AltDSS/DSS C-API codebase.
  • Across different OpenDSS binaries, even the official EPRI binaries, results can be different when running on different CPU architectures due to different instruct sets. Even old basic SIMD instructions such as SSE are a base of the x64 instruct set, but not typically enabled for Intel x86 builds. You may be able to detect tiny differences across different processor models, even from the same manufacturer (some common math like basic operations and sine and cosine functions have domain and error ranges specified in the datasheets).
  • Notably, Intel x86 builds of the Delphi version of OpenDSS may use extended, 80-bit floating-point numbers; even this varies when running the .EXE or using the DLL through COM, and the hosting process settings. Extended floats are nowadays deprecated due to lack of support in mainstream processors. As far as I now, there are no SIMD instructions for 80-bit floating point numbers anywhere. This is a common issue some users have found in the past, but this typically only show up on circuits with exaggerated parameters (typically, tiny impedances somewhere). Check the forum on SourceForge for more on this.
    • On this aspect, the new OpenDSS-C (also by EPRI) has different behavior. Personally, I consider x86 builds deprecated and don't see any reason to use them besides integration with very old software.

Regarding the shorter version of the sample posted before:

Clear
New Circuit.Circuit1 Phases=3 bus1=Bus1.1.2.3 basekv=220 pu=1.0 angle=0 MVAsc3=11297 MVAsc1=11297 x1r1=10 x0r0=10
New Capacitor.PCap1 Phases=3 bus1=Bus1.1.2.3 Conn=Delta Kv=20.2 Kvar=0 R=[0 0 0] XL=[9.95 9.95 9.95] Cmatrix=[332.68|0 332.68|0 0 332.68]
set DefaultBaseFrequency=50
set Basefrequency=50
set Frequency=50
set Algorithm=Newton
set Maxiter=50
set voltagebases=[220.0, 20.2]
calcvoltagebases
solve
  • set DefaultBaseFrequency=50: it's a good idea to move this right after the Clear command. On EPRI's current OpenDSS.exe, COM DLL, and OpenDSSDirect.DLL (again, not to be confused with OpenDSSDirect.py), the default base frequency is initially loaded from the Windows Registry settings, and it could be set to 60 Hz, resulting in different values.
  • set Basefrequency=50: you don't typically need this.
  • set Algorithm=Newton: the old Newton algorithm is not very useful nowadays; it is not a classic Newton-Raphson power flow method based on power injections. The Normal algorithm has been tweaked throughout the years and the Newton alternative shouldn't help much, if anything. There is a new NCIM method in the latest version of OpenDSS, and it will be included here on DSS-Extensions shortly (it still has some limitations). There are some notes on the official docs at https://opendss.epri.com/

In general, I'd recommend new users to check the sample circuits. We maintain a copy of them at https://github.com/dss-extensions/electricdss-tst (contains minor modifications when compared to the ones distributed with EPRI's OpenDSS installation).

@PMeira PMeira closed this as completed Jan 6, 2025
@PMeira
Copy link
Member

PMeira commented Jan 6, 2025

Oh, I forgot to mention that different versions of OpenDSS may contain changes in the models and some numeric values that will result in different values. The versions on DSS-Extensions are not coupled with the versions from the official EPRI releases, for various reasons.

@HHuuuhh666
Copy link
Author

It seems you already handled it, but I'll leave a few comments before closing this.

  • OpenDSSDirect.py has no direct relation to OpenDSS.exe. The upcoming version will support the official OpenDSSDirect.DLL again, but the current stable release is based only on the AltDSS/DSS C-API codebase.

  • Across different OpenDSS binaries, even the official EPRI binaries, results can be different when running on different CPU architectures due to different instruct sets. Even old basic SIMD instructions such as SSE are a base of the x64 instruct set, but not typically enabled for Intel x86 builds. You may be able to detect tiny differences across different processor models, even from the same manufacturer (some common math like basic operations and sine and cosine functions have domain and error ranges specified in the datasheets).

  • Notably, Intel x86 builds of the Delphi version of OpenDSS may use extended, 80-bit floating-point numbers; even this varies when running the .EXE or using the DLL through COM, and the hosting process settings. Extended floats are nowadays deprecated due to lack of support in mainstream processors. As far as I now, there are no SIMD instructions for 80-bit floating point numbers anywhere. This is a common issue some users have found in the past, but this typically only show up on circuits with exaggerated parameters (typically, tiny impedances somewhere). Check the forum on SourceForge for more on this.

    • On this aspect, the new OpenDSS-C (also by EPRI) has different behavior. Personally, I consider x86 builds deprecated and don't see any reason to use them besides integration with very old software.

Regarding the shorter version of the sample posted before:

Clear
New Circuit.Circuit1 Phases=3 bus1=Bus1.1.2.3 basekv=220 pu=1.0 angle=0 MVAsc3=11297 MVAsc1=11297 x1r1=10 x0r0=10
New Capacitor.PCap1 Phases=3 bus1=Bus1.1.2.3 Conn=Delta Kv=20.2 Kvar=0 R=[0 0 0] XL=[9.95 9.95 9.95] Cmatrix=[332.68|0 332.68|0 0 332.68]
set DefaultBaseFrequency=50
set Basefrequency=50
set Frequency=50
set Algorithm=Newton
set Maxiter=50
set voltagebases=[220.0, 20.2]
calcvoltagebases
solve
  • set DefaultBaseFrequency=50: it's a good idea to move this right after the Clear command. On EPRI's current OpenDSS.exe, COM DLL, and OpenDSSDirect.DLL (again, not to be confused with OpenDSSDirect.py), the default base frequency is initially loaded from the Windows Registry settings, and it could be set to 60 Hz, resulting in different values.
  • set Basefrequency=50: you don't typically need this.
  • set Algorithm=Newton: the old Newton algorithm is not very useful nowadays; it is not a classic Newton-Raphson power flow method based on power injections. The Normal algorithm has been tweaked throughout the years and the Newton alternative shouldn't help much, if anything. There is a new NCIM method in the latest version of OpenDSS, and it will be included here on DSS-Extensions shortly (it still has some limitations). There are some notes on the official docs at https://opendss.epri.com/

In general, I'd recommend new users to check the sample circuits. We maintain a copy of them at https://github.com/dss-extensions/electricdss-tst (contains minor modifications when compared to the ones distributed with EPRI's OpenDSS installation).

I haven't solved this problem yet, I just overlooked it, thanks for your answer.
This is my complete dss file,
Clear
New Circuit.Circuit1 Phases=3 bus1=Bus1.1.2.3 basekv=220 pu=1.0 angle=0 MVAsc3=11297 MVAsc1=11297 x1r1=10 x0r0=10
New Capacitor.Filter1 Phases=3 bus1=Bus3.1.2.3.0 Conn=Wye Kv=35 Cuf=93.37 XL=3.94 R=0
New Capacitor.Filter2 Phases=3 bus1=Bus3.1.2.3.0 Conn=Wye Kv=35 Cuf=119.76 XL=1.72756 R=0
New Capacitor.Filter3 Phases=3 bus1=Bus3.1.2.3.0 Conn=Wye Kv=35 Cuf=119.76 XL=1.10552 R=0
New Line.Line1 bus1=Bus1.1.2.3 bus2=Bus2.1.2.3 Length=4.26 units=km R1=0.054 X1=0.308 C1=0 R0=0.054 X0=0.308 C0=0
New LineCode.Line1 Nphases=3 Rmatrix=[0|0 0|0 0 0] Xmatrix=[0|0 0|0 0 0]
New Load.Load1 Phases=3 bus1=Bus3.1.2.3.0 Conn=Wye vminpu=0.8 vmaxpu=1.2 Kv=35 kVA=155000 Pf=0.78 rneut=0 xneut=0 model=1
New Load.Load2 Phases=3 bus1=Bus3.1.2.3.0 Conn=Wye vminpu=0.8 vmaxpu=1.2 Kv=35 kVA=26000 Pf=0.85 rneut=0 xneut=0 model=1
New Load.Load3 Phases=3 bus1=Bus3.1.2.3.0 Conn=Wye vminpu=0.8 vmaxpu=1.2 Kv=35 Kw=0 kvar=180000 rneut=0 xneut=0 model=1
New Capacitor.PCap1 Phases=1 bus1=Bus4.1.0 Conn=Wye Kv=20.2 Kvar=0 R=[0 0 0] XL=[9.95 9.95 9.95] Cmatrix=[332.68|0 332.68|0 0 332.68]
New Capacitor.PCap2 Phases=1 bus1=Bus5.2.0 Conn=Wye Kv=20.2 Kvar=0 R=[0 0 0] XL=[9.95 9.95 9.95] Cmatrix=[332.68|0 332.68|0 0 332.68]
New Capacitor.PCap3 Phases=1 bus1=Bus6.3.0 Conn=Wye Kv=20.2 Kvar=0 R=[0 0 0] XL=[9.95 9.95 9.95] Cmatrix=[332.68|0 332.68|0 0 332.68]
New Reactor.PRea1 Phases=1 bus1=Bus4.1.0 Conn=Wye Kv=20.2 Kvar=0 Rmatrix=[650|0 650|0 0 650] Xmatrix=[0|0 0|0 0 0]
New Reactor.PRea2 Phases=1 bus1=Bus5.2.0 Conn=Wye Kv=20.2 Kvar=0 Rmatrix=[650|0 650|0 0 650] Xmatrix=[0|0 0|0 0 0]
New Reactor.PRea3 Phases=1 bus1=Bus6.3.0 Conn=Wye Kv=20.2 Kvar=0 Rmatrix=[650|0 650|0 0 650] Xmatrix=[0|0 0|0 0 0]
New Capacitor.SCap1 Phases=1 bus1=Bus3.1.0 bus2=Bus4.1.0 Conn=Wye Kv=20.2 Kvar=0 R=[0 0 0] XL=[0 0 0] Cmatrix=[110.8933|0 110.8933|0 0 110.8933]
New Capacitor.SCap2 Phases=1 bus1=Bus3.2.0 bus2=Bus5.2.0 Conn=Wye Kv=20.2 Kvar=0 R=[0 0 0] XL=[0 0 0] Cmatrix=[110.8933|0 110.8933|0 0 110.8933]
New Capacitor.SCap3 Phases=1 bus1=Bus3.3.0 bus2=Bus6.3.0 Conn=Wye Kv=20.2 Kvar=0 R=[0 0 0] XL=[0 0 0] Cmatrix=[110.8933|0 110.8933|0 0 110.8933]
New Transformer.T2w1 Phases=3 XHL=13 %imag=0 %Noloadloss=0 Windings=2 Wdg=1 bus=Bus2.1.2.3.0 Conn=Wye Kv=220 Kva=160000 %R=0 Tap=1 rneut=0 xneut=0 Wdg=2 bus=Bus3.1.2.3 Conn=Delta Kv=35 Kva=160000 %R=0 Tap=1
set DefaultBaseFrequency=50
set Basefrequency=50
set Frequency=50
set Algorithm=Newton
set Maxiter=50
set voltagebases=[220.0, 35.0, 20.2]
calcvoltagebases
solve
export voltages

The results of OpenDSSDirect are very different from those of the OpenDSS.exe X64 version, Is this normal?

@PMeira
Copy link
Member

PMeira commented Jan 6, 2025

The results of OpenDSSDirect are very different from those of the OpenDSS.exe X64 version, Is this normal?

Not typically, I'll try to check what's happening this Monday. Could you list the versions you're using of both OpenDSS.exe and OpenDSSDirect.py?

@PMeira PMeira reopened this Jan 6, 2025
@HHuuuhh666
Copy link
Author

The results of OpenDSSDirect are very different from those of the OpenDSS.exe X64 version, Is this normal?

Not typically, I'll try to check what's happening this Monday. Could you list the versions you're using of both OpenDSS.exe and OpenDSSDirect.py?

OpenDSS.exe [ Version 10.0.0.1 - Columbus ]
OpenDSSDirect.py [ version: 0.9.4 ]

@PMeira
Copy link
Member

PMeira commented Jan 8, 2025

The main issue that's causing the difference could be a bug (in both engines, EPRI's and ours): for a capacitor, if you provide CMatrix and XL, XL is applied by inverting the initial YPrim for the capacitor created from CMatrix, but this YPrim can be singular. Currently, there's no check for that and the "inverted" matrix (even if wrong or incomplete) was being used. After applying the modification from (R+jXL), the matrix is inverted again to obtain the final YPrim. The results are probably different due to specifics of each compiler, but I wouldn't trust either of them in this case.

As a workaround, for this single-phase capacitors, you could provide CuF instead of CMatrix, since they should be equivalent, right? The capacitores Filter1, Filter2 and Filter3 already used that style in your original code. When using CuF and XL, for Wye connections, the initial YPrim is already includes (R+jXL), so no need to invert the matrix to add it later. For Delta connections, it is already slightly modified to make it invertible.

With that change to use CuF, the YPrim for the capacitors (PCap1, PCap2, PCap3) seem to make a bit more sense. The voltages at buses 4 to 6 are still very low, but I'll leave that for you to check. The results match across the different DSS engines.

Here's the modified script so far:

Clear
set DefaultBaseFrequency=50
New Circuit.Circuit1-modified Phases=3 bus1=Bus1.1.2.3 basekv=220 pu=1.0 angle=0 MVAsc3=11297 MVAsc1=11297 x1r1=10 x0r0=10
New Capacitor.Filter1 Phases=3 bus1=Bus3.1.2.3.0 Conn=Wye kV=35 Cuf=93.37 XL=3.94 R=0
New Capacitor.Filter2 Phases=3 bus1=Bus3.1.2.3.0 Conn=Wye kV=35 Cuf=119.76 XL=1.72756 R=0
New Capacitor.Filter3 Phases=3 bus1=Bus3.1.2.3.0 Conn=Wye kV=35 Cuf=119.76 XL=1.10552 R=0
New Line.Line1 bus1=Bus1.1.2.3 bus2=Bus2.1.2.3 Length=4.26 units=km R1=0.054 X1=0.308 C1=0 R0=0.054 X0=0.308 C0=0
New Load.Load1 Phases=3 bus1=Bus3.1.2.3.0 Conn=Wye vminpu=0.8 vmaxpu=1.2 kV=35 kVA=155000 Pf=0.78 rneut=0 xneut=0 model=1
New Load.Load2 Phases=3 bus1=Bus3.1.2.3.0 Conn=Wye vminpu=0.8 vmaxpu=1.2 kV=35 kVA=26000 Pf=0.85 rneut=0 xneut=0 model=1
New Load.Load3 Phases=3 bus1=Bus3.1.2.3.0 Conn=Wye vminpu=0.8 vmaxpu=1.2 kV=35 kW=0 kvar=180000 rneut=0 xneut=0 model=1
New Capacitor.PCap1 Phases=1 bus1=Bus4.1.0 Conn=Wye kV=20.2 R=0 XL=9.95 CuF=332.68
New Capacitor.PCap2 Phases=1 bus1=Bus5.2.0 Conn=Wye kV=20.2 R=0 XL=9.95 CuF=332.68
New Capacitor.PCap3 Phases=1 bus1=Bus6.3.0 Conn=Wye kV=20.2 R=0 XL=9.95 CuF=332.68
New Reactor.PRea1 Phases=1 bus1=Bus4.1.0 Conn=Wye kV=20.2 Rmatrix=[650] Xmatrix=[0]
New Reactor.PRea2 Phases=1 bus1=Bus5.2.0 Conn=Wye kV=20.2 Rmatrix=[650] Xmatrix=[0]
New Reactor.PRea3 Phases=1 bus1=Bus6.3.0 Conn=Wye kV=20.2 Rmatrix=[650] Xmatrix=[0]
New Capacitor.SCap1 Phases=1 bus1=Bus3.1.0 bus2=Bus4.1.0 Conn=Wye kV=20.2 R=0 XL=0 Cmatrix=[110.8933]
New Capacitor.SCap2 Phases=1 bus1=Bus3.2.0 bus2=Bus5.2.0 Conn=Wye kV=20.2 R=0 XL=0 Cmatrix=[110.8933]
New Capacitor.SCap3 Phases=1 bus1=Bus3.3.0 bus2=Bus6.3.0 Conn=Wye kV=20.2 R=0 XL=0 Cmatrix=[110.8933]
New Transformer.T2w1 Phases=3 XHL=13 %imag=0 %Noloadloss=0 Windings=2 Wdg=1 bus=Bus2.1.2.3.0 Conn=Wye kV=220 Kva=160000 %R=0 Tap=1 rneut=0 xneut=0 Wdg=2 bus=Bus3.1.2.3 Conn=Delta kV=35 Kva=160000 %R=0 Tap=1
set voltagebases=[220.0, 35.0, 20.2]
calcvoltagebases
solve
export voltages

Other comments:

  • You don't use this LineCode in the circuit, so it shouldn't cause issues, but it's invalid (you cannot have all zeros there):
New LineCode.Line1 Nphases=3 Rmatrix=[0|0 0|0 0 0] Xmatrix=[0|0 0|0 0 0]
  • Some definitions don't make sense. You set the capacitors and reactors to be single phase elements, but provide 3x3 matrices. It might have worked here (most likely the extra elements were ignored), but there are some places where it will silently corrupt some data. The next version of our engine will give more errors when it finds those situations, but there are some functions in EPRI's distribution that don't correctly handle that.

    • For the capacitors, Note that the sizes for R and XL are given by the number of steps of the capacitor, not the phases.
  • You are overspecifying the components. For example, providing kvar=0 does nothing useful since the value is ignored when passing XMatrix and CMatrix (for Reactors and Capacitors, respectively) afterwards.

  • Note that when R is zero in the input data before XL, it is initialized to 0.001*XL automatically.

@HHuuuhh666
Copy link
Author

Thank you very much, Paulo.
The results are consistent after using Cuf.
For Capacitor, if numsteps is set to 3, can I use Cuf=[c11 c22 c33] instead of Cmatrix=[c11 | -c21 c22 | -c31 -c32 c33]?

@PMeira
Copy link
Member

PMeira commented Jan 18, 2025

No, NumSteps and multiple values for either CuF or kvar are typically used for controlled capacitors. You can use it to specify multiple XL or Harm to specify filters, but: when using multiple steps, a separate YPrim is built for each step that is on (according to the States array property), and then summed into the final YPrim for the capacitor.

When you use Phases=3 CuF=c11, c11 would be used for all phases, respecting the connection (delta or wye).

(If you indeed need to specify CMatrix and XL, our next release should work.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants