Calculate following Validate

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

Moderator: DanW

Post Reply
greTol
Posts: 20
Joined: 26 August 2013, 14:45

Calculate following Validate

Post by greTol »

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
error: unit has not been validated
error: unit has not been validated
DWSIM_error_not_validated.png (79.96 KiB) Viewed 19192 times
Last edited by greTol on 23 October 2017, 12:42, edited 2 times in total.
User avatar
jasper
Posts: 1129
Joined: 24 October 2012, 15:33
Location: Spain
Contact:

Re: Calculate following Validate

Post by jasper »

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.
greTol
Posts: 20
Joined: 26 August 2013, 14:45

Re: Calculate following Validate

Post by greTol »

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.
Post Reply

Return to “DWSIM”