Calculate following Validate

Discusses use of CAPE-OPEN interfaces in DWSIM, an open-source piece of sofware developed by Daniel WAGNER.

Moderator: DanW

Calculate following Validate

Postby greTol » 20 October 2017, 13:22

Hi Daniel,

I have a request regarding calling 'validate' and 'calculate' of CAPE-OPEN unit operations in DWSIM.
My ScaledMixerSplitter CAPE-OPEN unit operation already runs in COFE 3.2 and Aspen Plus v9, but unfortunately not yet in DWSIM.

The problem seems to be that the unit operation is somehow resetted (or a new object is created?) after calling 'validate', and before calling 'calculate'. The unit forgets its 'CapeValidationStatus'.

Here some code snippets:

ScaledMixerSplitter.h
Code: Select all
class ScaledMixerSplitter :
     public ICapeUnit,
     public ICapeUtilities {

     CapeValidationStatus valStatus;
     valStatus=CAPE_NOT_VALIDATED;
}


ScaledMixerSplitter.cpp
Code: Select all
STDMETHODIMP ScaledMixerSplitter::Validate(/*[in, out]*/ BSTR *message, /*[out, retval]*/ VARIANT_BOOL *isOK) {
     valStatus = CAPE_VALID;
}

STDMETHODIMP ScaledMixerSplitter::Calculate() {
     BEGIN_TRY(L"ICapeUnit");
     //first let us make sure we are in a valid state
     if (valStatus == CAPE_INVALID){
          throw COException(L"Unit is not valid");
     }
     if (valStatus == CAPE_NOT_VALIDATED){
          throw COException(L"Unit has not been validated");
     }
     END_TRY(L"ICapeUnit");
}

<edit>: I added BEGIN_TRY and END_TRY after reading Jaspers post in order to avoid showing wrong code. This does not change the logic of the code or my question. </edit>

I know that 'validate' is called, because when I throw an exception in validate, the execution immediately stops.
When I do not throw this exception in validate, I get the error message "Unit has not been validated" in 'calculate' (see attached screenshot).

Of course one workaround would be to always call 'validate' inside 'calculate', but I do not think this is the best solution (I do not want to validate again and again when no parameters and ports have changed between two calls of 'calculate'). And I do not want to remove the check for the validation status from 'calculate'.

Is it possible to change the behaviour fo DWSIM in a way that I do not have to change my unit operation?
I can provide full source code if necessary to investigate.

With best regards,

greTol
Attachments
DWSIM_error_not_validated.png
error: unit has not been validated
DWSIM_error_not_validated.png (79.96 KiB) Viewed 10486 times
Last edited by greTol on 23 October 2017, 12:42, edited 2 times in total.
greTol
 
Posts: 20
Joined: 26 August 2013, 14:45

Re: Calculate following Validate

Postby jasper » 21 October 2017, 09:56

You cannot throw exceptions like that. You need to catch them inside your calculation routine and translate the exceptions into CAPE-OPEN errors.

Presuming this is built on the COM CAPE-OPEN wizard, you are missing BEGIN_TRY, END_TRY

Code: Select all
STDMETHODIMP ScaledMixerSplitter::Calculate() {
     BEGIN_TRY(L"ICapeUnit")
     //first let us make sure we are in a valid state
     if (valStatus == CAPE_INVALID){
          throw COException(L"Unit is not valid");
     }
     if (valStatus == CAPE_NOT_VALIDATED){
          throw COException(L"Unit has not been validated");
     }
     END_TRY(L"ICapeUnit")
}


See the definition of END_TRY:

Code: Select all
#define END_TRY(iface) \
   } catch (COException &ex) { \
      SetError(ex.wwhat(),__FUNCTIONW__,iface); \
      return ex.getCode(); \
   } catch (exception &ex) { \
      SetError(UTF8toUTF16(ex.what()),__FUNCTIONW__,iface); \
      return ECapeUnknownHR; \
   } catch (...) { \
      SetError(L"Unhandled exception",__FUNCTIONW__,iface); \
      return ECapeUnknownHR; \
   } \
   return NO_ERROR;


Perhaps this does not resolve your original issue - but nevertheless - you cannot throw directly from a COM function.
User avatar
jasper
 
Posts: 1128
Joined: 24 October 2012, 15:33
Location: Spain

Re: Calculate following Validate

Postby greTol » 30 November 2017, 15:52

This discussion continued in the DWSIM forum
(https://sourceforge.net/p/dwsim/discuss ... /3682f2f1/).
Here are my conclusions:

In the DWSIM socket we have/had
1) Validate()
2) RestorePorts() -> this invalidates the unit operation, because the "portConnectionChanged" event is fired and we cannot gurantee that the state is still valid.
3) Calculate() -> check for validation fails

The CO interface specification for Unit Operations (CO_Unit_Operations_v6.25) says, regarding 'Validate':
"However, Validate must be called before Calculate in case any (one or more) changes to the following
configuration aspects of the Unit Operation have changed since the last call to Calculate:
• ...
• connecting an object to a port
• disconnecting an object from a port
• ... "

So calling Validate() after RestorePorts() is fix to this particular problem.
greTol
 
Posts: 20
Joined: 26 August 2013, 14:45


Return to DWSIM

Who is online

Users browsing this forum: No registered users and 1 guest

cron