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

class of property Solution.Mode is not double as with COM-Interface #21

Open
Hell3000 opened this issue Nov 4, 2024 · 1 comment
Open

Comments

@Hell3000
Copy link

Hell3000 commented Nov 4, 2024

Hi Paulo. It is Janis again. (We're aso talking in the DSS Discussion Forum.)

I had just this small error switching from COM to altDSS. I think it is easy to fix.

After this here is some - hopefully excecutably - code which should print

=== DSS Interface: COM ===

original Solution properties: Mode = 0 ModeID = Snap
class for Solve Mode = double

Trying to set ModeID to <yearly>
Error setting Mode ID
Invoke Error: Incorrect number of arguments

Error in Issue_Solution_Mode_difference (line 57)
        Solution_I.ModeID = ModeID;
Solution properties: Mode = 0 ModeID = Snap

Trying to set Mode to <2>
Solution properties: Mode = 2 ModeID = Yearly

Trying to set original solve Mode <0>
Solution properties: Mode = 0 ModeID = Snap


=== DSS Interface: altDSS ===

original Solution properties: Mode = 0 ModeID = Snap
class for Solve Mode = DSS_MATLAB.SolveModes

Trying to set ModeID to <yearly>
Solution properties: Mode = 0 ModeID = Snap

Trying to set Mode to <2>
Solution properties: Mode = 2 ModeID = Yearly

Trying to set original solve Mode <0>
Error using calllib
Array must be numeric or logical.

Error in DSS_MATLAB.ISolution/set.Mode (line 434)
            calllib(obj.libname, 'ctx_Solution_Set_Mode', obj.dssctx, Value);

Error in Issue_Solution_Mode_difference (line 81)
        Solution_I.Mode = Mode_original;
Solution properties: Mode = 2 ModeID = Yearly

Trying to set original solve Mode <0> with type conversion to double
Solution properties: Mode = 0 ModeID = Snap
commands = {
    'Clear'
    'set defaultbasefreq=50' % 50 Hz
    'New Circuit.ckt Angle=0 Mvasc3=1e7 basekv=0.4 bus1=n1 frequency=50 phases=3 pu=1.0 x1r1=10'
    'New Linecode.nayy4x120 C0=365.9 C1=797.3 R0=1.02 R1=0.255 X0=0.292 X1=0.08 NormAmps=245.0 units=km'
    'New Line.l1 bus1=n1 bus2=n2 length=0.3 linecode=nayy4x120'
    'solve mode=snap'
    'solve algorithm=newton'
    'Set Maxiter=75'
    };


for phase = 1:3
    commands{end+1} = sprintf('New Load.rl_1_ph%1$d bus1=n2.%1$d phases=1 kv=0.4 kW=0 kvar=0', phase); %#ok<SAGROW>
end


for interface = {'COM', 'altDSS'}
    
    current_dir = pwd;
    switch interface{1}
        case 'COM'
            DSS_I = actxserver('OpenDSSEngine.DSS');
        case 'altDSS'
            DSS_I = DSS_MATLAB.IDSS;
    end
    cd(current_dir)
    fprintf(1, '\n\n=== DSS Interface: %s ===\n\n', interface{1})
    
    Text_I = DSS_I.Text;
    Circuit_I = DSS_I.ActiveCircuit;
    Solution_I = Circuit_I.Solution;
    
    for c = reshape2rowVec(commands)
        Text_I.Command = c{1};
    end
    
    Text_I.command = 'set voltagebases=0.4';
    Text_I.command = 'calcvoltagebases';
    Solution_I.Solve;
    
    fprintf(1, 'original Solution properties: Mode = %d ModeID = %s\n', Solution_I.Mode, Solution_I.ModeID)
    
    Mode_original = Solution_I.Mode;
    
    fprintf(1, 'class for Solve Mode = %s\n', class(Mode_original))
    
    %%
    
    ModeID = 'yearly';
    
    fprintf(1, '\nTrying to set ModeID to <%s>\n', ModeID)
    
    try
        Solution_I.ModeID = ModeID;
    catch err
        fprintf(2, 'Error setting Mode ID\n%s\n', err.getReport)
    end
    
    fprintf(1, 'Solution properties: Mode = %d ModeID = %s\n', Solution_I.Mode, Solution_I.ModeID)
    
    %%
    Mode = 2;
    
    fprintf(1, '\nTrying to set Mode to <%d>\n', Mode)
    
    try
        Solution_I.Mode = Mode;
    catch err
        fprintf(2, '%s\n', err.getReport)
    end
    
    fprintf(1, 'Solution properties: Mode = %d ModeID = %s\n', Solution_I.Mode, Solution_I.ModeID)
    
    %%
    fprintf(1, '\nTrying to set original solve Mode <%d>\n', Mode_original)
    
    try
        Solution_I.Mode = Mode_original;
    catch err
        fprintf(2, '%s\n', err.getReport)
        fprintf(1, 'Solution properties: Mode = %d ModeID = %s\n', Solution_I.Mode, Solution_I.ModeID)
        
        fprintf(1, '\nTrying to set original solve Mode <%d> with type conversion to double\n', Mode_original)
        
        Solution_I.Mode = double(Mode_original);
        
    end
    
    fprintf(1, 'Solution properties: Mode = %d ModeID = %s\n', Solution_I.Mode, Solution_I.ModeID)    
    
end

I experienced these 2 differences.

1

With COM numerical Solution ModeID is read-only. It errors when trying to set. with DSS_Matlab setting is possible without error but it does not set it. I would suggest to make the property in ISolution.m read-only by:

    properties (SetAccess = private)
        ModeID        
    end

2

Solution_I.Mode returns double with COM.

Solution_I.Mode returns enumeration or sth with DSS_Matlab.

When trying to set Mode again with this datatype there is an error.

That could be fixed in the ISolution.m class itself by casting to double:

     function result = get.Mode(obj)
            % Set present solution mode (by a text code - see DSS Help)
            result = double(DSS_MATLAB.SolveModes(calllib(obj.libname, 'ctx_Solution_Get_Mode', obj.dssctx)));
            obj.CheckForError();
        end
@PMeira
Copy link
Member

PMeira commented Nov 4, 2024

An issue you might find is that for DSS_MATLAB we always convert the DSS errors using MException in that CheckForError() function. I think we can add the option to deactivate this for backwards compatibility -- most of the other projects already have this option. This still will be left enabled as the default since most users do not check for errors manually (leading to silent invalid results).
Another quick note on this: for the official engine, this handling will only be enabled when AllowsForms is set to false, since the GUI popups (Delphi version) or text output (OpenDSS-C) consume the error information.

   properties (SetAccess = private)

Good idea, I'll add that in the next update to all read-only properties.

        result = double(DSS_MATLAB.SolveModes(calllib(obj.libname, 'ctx_Solution_Get_Mode', obj.dssctx)));

We can just remove DSS_MATLAB.SolveModes there, as well as most enum stuff on other getters -- some of these are recent-ish changes in DSS_MATLAB. API functions returns 32-bit integers (which matches COM), and in both cases (COM and calllib with our C-API), MATLAB "promotes" the integer to double.

Indeed it seems forcing enums in MATLAB deviate a bit too much from the original behavior since they require a cast. Better to remove most of them for now, maybe revisit it on the future. We could add a cast to integers to allow users to provide enums in the setters.

Note that the COM API does use enums in a few places, for example ActiveCircuit.Loads.Status. It doesn't model the enums at the MATLAB level, probably because it doesn't provide a simple way to access the enums. For Loads.Status, MATLAB accepts both the enum name (string) or integer (e.g. dssLoadExempt or 2), so we should reproduce that.

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