PGM Example - Relaxed Cross Page Connector

From SysCAD Documentation
Jump to navigation Jump to search

Navigation: PGMs ➔ Example PGM Files ➔ Relaxed Cross Page Connector

Example User Defined Classes
Set Species Splits Agitator
Power
Reaction
Finder
Aq Feed Conc
Calculator
Evaporation
Correlation
Bayer Liquor
Class
Check
Element Bal
Optimise Controllers
for sensitive PIDs
Relaxed Cross Page Connector

Related Links: Defining a Class


NOTE: Some PGM functions used by this example requires Build 139.32366 or later.

PGM Example - Relaxed Cross Page Connector

This example file allows the user to "break" the existing cross-page connection, and "manually" transfer the sink material flow to the Feeder. This can be useful when the closed loop is very sensitive to flow change, and user can tell the feeder to apply the change "slower". Please note that if the change is too slow, the resulting source and target flows may not match. When that happens, try increase the rate of change or solve for longer.

;--- SysCAD General Controller (PGM) program logic file ---
; Revision: 1     Date: January 2023    Author: SysCAD Team

EnumDropList XPgConnOptions{MassFlow = 0, MassFrac = 1, XpgConnected =2}

class Class_RelaxedCrossPageConnection
	ClassAsGroup 
	TextLabel "  ----------------------------------------------------------"
	TextLabel "  Used to transfer data from a Sink to the Feeder"
	TextLabel "  ----------------------------------------------------------"
	string  FeederTag@{Tag}{Comment("Expect a valid Feeder Tag (Class instance name)")}
	Bit     ValidTag, ValidModelType, ValidReference@
	string  SourceConnector@{Tag}{Comment("Uses the FeederTag's CrossPage ConnectedTo Tag")}
	Bit     ValidXPGConTag@
	TextBreak
	XPgConnOptions ConnectionType*
	Memo		ConnectionStatus@
	TextBreak
	real    Relaxation*<1e-5,1><<0.5>>{Comment("use < 1 for gradual change")}
	TextLabel "  NOTE:Relaxation applied when setting the Feeder Flow", "  Allows for a slower change for sensitive loops"
	TextBreak
	TextLabel "  Data Checking:"
	checkbox Converged@
	real    RelativeTolerance*("Frac","Frac")<1e-10,1e-2><<0.001>>
	real    Tolerance*("Qm","kg/s")<1e-10,1e-2><<0.001>>
	TextLabel "  NOTE:These are done at the Termination step", "  Checks if the actual data set matches the source data" 
	
	StrArray InputTags{}, OutputTags{}
	TextLabel "  ----------------------------------------------------------"
	TextBreak
	
	Sub CheckVersion()
		Bit BuildOK
		Const long VersionNumber = 32530
		BuildOK = PM.Version(0)>=9 AND PM.Version(1)>=3 AND PM.Version(2)>=139 AND PM.Version(3)>=VersionNumber
		If NOT BuildOK
			StopSolver("Incorrect version of SysCAD, needs SysCAD9.3 Build139.", IntToStr(VersionNumber)," or later.")
		Endif
	EndSub

	Sub SanityCheck() 
		Str  UnitType
		FeederTag       = ClassTag()
		ValidTag        = DynTagExists(Concatenate(FeederTag,".Tag"))
		SourceConnector = [Str Concatenate(FeederTag, ".ConnectTo")]
		ValidXPGConTag  = NOT IsEmpty(SourceConnector)

		if (NOT ValidTag)
			StopSolver("UnitTag ", FeederTag, " not found!", " Expect Class_instance declared = valid feeder name in the project" )
			ValidReference = 0
		Elseif 	(NOT ValidXPGConTag)
			StopSolver("Expect '", FeederTag, "' - CrossPage Connection - ConnectedTo field be specified.", " This is used as the SourceConnector " )
			ValidReference = 0
		else
			UnitType   = [str concatenate(FeederTag, ".UnitType")]
			ValidModelType = (strcmp(UnitType, "FeederSink")==0)
			If (NOT ValidModelType) 
				StopSolver("Expect '", FeederTag, "' to be a FeederSink") ;note single quotes around the tag to enable right-click access from the message window
				ValidReference = 0
			Else
				ValidReference = 1
			Endif
		Endif	
	EndSub
	
	sub Init()
		integer i
		SanityCheck()
		CheckVersion()		
		If ValidReference
			If ConnectionType < 2
				;ensure the Feeder is not using cross page connection and set to the General operation mode.
				[concatenate(FeederTag,".Operation")]=0
				[concatenate(FeederTag,".ConnectionOn")] = 0
				[concatenate(FeederTag,".CF.When")] = 0
				;Allow two extra tags for T and P.
				InputTags.SetLen(SDB.SpeciesCount()+2)
				OutputTags.SetLen(SDB.SpeciesCount()+2)
				i = 0
				while (i < SDB.SpeciesCount())
					if (ConnectionType == MassFrac)
						InputTags.SetAt(i,concatenate(SourceConnector,".QProd.MF.",SDB.SpShortName(i)))
						OutputTags.SetAt(i,concatenate(FeederTag,".Content.MF.",SDB.SpShortName(i)))
						ConnectionStatus = "Using Relaxation Mode"
					else
						InputTags.SetAt(i,concatenate(SourceConnector,".QProd.QM.",SDB.SpShortName(i)))
						OutputTags.SetAt(i,concatenate(FeederTag,".Content.QM.",SDB.SpShortName(i)))
					endif
					i = i + 1
				EndWhile
				InputTags.SetAt(SDB.SpeciesCount(),concatenate(SourceConnector,".QProd.T (C)"))
				OutputTags.SetAt(SDB.SpeciesCount(),concatenate(FeederTag,".T_Reqd (C)"))
				InputTags.SetAt(SDB.SpeciesCount()+1,concatenate(SourceConnector,".QProd.P (kPa)"))
				OutputTags.SetAt(SDB.SpeciesCount()+1,concatenate(FeederTag,".P_Reqd (kPa)"))
			else
				[concatenate(FeederTag,".ConnectionOn")] = 1
				ConnectionStatus = "Using full cross page connection Mode, relaxation not in use."
			Endif
		Endif	
	EndSub
	
	sub DoTransfer()
		real OldVal
		;do the relaxed transfer of mass flow
		integer i
		If ValidReference and ConnectionType < 2
			i = 0
			while (i < InputTags.GetLen())
				OldVal = [OutputTags[i]]
				[OutputTags[i]] = OldVal + Relaxation * ([InputTags[i]] - OldVal)
				i = i + 1
			EndWhile
		Endif
	endSub

	sub Final_Check()
		;ensure it is converged
		integer i
		If ValidReference and ConnectionType < 2
			i = 0
			while (i < InputTags.GetLen())
				real Out, In, RelErr, Err
				Out = [OutputTags[i]]
				In = [InputTags[i]]
				Err = abs(Out - In)                      
				RelErr = Err/max(In,1e-10)
				if ((RelErr > RelativeTolerance) and (Err > Tolerance))
					LogError(" '", FeederTag, "' relaxed cross page connection not converged for ",InputTags[i],": ",FltToStr(RelErr*100)," %")
					LogError(" '", FeederTag, "' relaxed cross page connection not converged.  Maximum error for ",InputTags[i],": ",FltToStr(Err)," kg/s")
					Converged = 0
				else
					Converged = 1
				endif
				i = i + 1
			EndWhile
			LogNote(" '", FeederTag, "' using Relaxation mode for cross page connector.")
		Endif
	EndSub
EndClass

;-----------------------------------------------------
;Using the Class in the project
PageLabel "CrossPageConnection" 
	TextBreak
;Declare the class instances, here we are using the Feeder tag name as the class instance name.  
	Class_RelaxedCrossPageConnection From_CCD_UF, From_NiCo_Filter

;Initialise the tags
Sub PreStart()
;In this example, the feeder was setup with cross-page connector previously, so we can fetch the tag as the "SourceConnector".
	ForEachClass(Class_RelaxedCrossPageConnection, Init())
EndSub	

;Do the mass transfer, this is done every iteration.
	ForEachClass(Class_RelaxedCrossPageConnection, DoTransfer())

;Check feeder condition at termination
Sub TerminateSolution()
	ForEachClass(Class_RelaxedCrossPageConnection, Final_Check())
EndSub

$