PROGRAM PLC_PRG
VAR
LoadDemoConfigurations : BOOL := TRUE; // set this to load configurations from code into memory
WellOnTestInternal : DINT; // the cached value of the well on test from the HMI
WellConfig : WellCompleteConfig; // the configuration of the well that is actually on test
WellConfigStatus : WellTestConfigStatus;
ConfirmConfigCount : INT := 0; // a delay counter when waiting to validate the config
ConfigBad : BOOL := FALSE; // set when the config fails validation
MaxWellOnTest : INT; // set the maximum well on test
BatchUserId : DINT; // set the batch user ID to all flow runs
PurgeComplete : BOOL := FALSE; // set when the purge is complete
SetBatchIds : BOOL; // whether the batch user IDs need to be set explicitly
SetIdsCounter : INT;
// time variables
TimeNowS : UDINT; // unix seconds
TestStartTime : UDINT;
TestEndTime : UDINT;
TestStartTimeLocal : UDINT;
TestEndTimeLocal : UDINT;
TestTimeRemaining : UDINT; // seconds
TestStartTimeLocalDt : DATE_AND_TIME;
TestEndTimeLocalDt : DATE_AND_TIME;
CurrentStateString : STRING(32); // exposes the internal state as a string for the HMI
// convert timestamps from the flow computer into values
// that can be displayed in the HMI.
LastBatchStartTimeLocal : UDINT;
LastBatchEndTimeLocal : UDINT;
LastBatchStartTimeLocalDt : DATE_AND_TIME;
LastBatchEndTimeLocalDt : DATE_AND_TIME;
CompleteDelayCount : INT :=0; // a delay counter for the 'complete' state
StopDelayCount : INT := 0; // a delay counter for the 'stop' state
// Auto mode
WellOnTestAuto : INT := 0; // track the well on test when in auto mode
// make sure apps are connected
GasFlowConnected : BOOL := FALSE;
LiquidFlowConnected : BOOL := FALSE;
WaterFlowConnected : BOOL := FALSE;
Connected : BOOL := FALSE;
// just set the color in code instead of using alarms
// this keeps things simpler for demo. Default to red
// frame. 16#FFCCCCCC = grey default frame color
ConnectedColor : DWORD := 16#FFFF0000;
// a delay counter to only check the apps'
// exec counts periodically on not every cycle
ConnectedCounter : INT := 0;
// cache the last exec counts from the app. These
// counts must be changing when connected to the apps.
GasLastExecCount : UDINT := 0;
LiquidLastExecCount : UDINT := 0;
WaterLastExecCount : UDINT := 0;
InitConnected : BOOL := FALSE;
// track app alarms in a basic way.
// one bool for all runs
FlowComputerAlarmsActive : BOOL := FALSE;
FlowComputerAlarmsColor : DWORD := 16#FFCCCCCC;
END_VAR
//************************************************************************
// Section Start/Stop
// map radio button for start/stop test to booleans that are used internally
// only do this in manual mode
IF(GVL.ManualAutoMode = 0) THEN
IF(GVL.StartStopTest = 0) THEN
GVL.StopTest := TRUE;
GVL.StartTest := FALSE;
ELSE
GVL.StartTest := TRUE;
GVL.StopTest := FALSE;
END_IF
END_IF
IF(CONNECTED = FALSE AND GVL.TestState <> TestStates.Waiting) THEN
// we are not connected and not in the waiting state,
// stop the test, which will then take us to the waiting state
// we can't leave the waiting state until we are connected
GVL.StopTest := TRUE;
GVL.StartStopTest := 0;
END_IF
//************************************************************************
//************************************************************************
// Section Main State Machine
// main state machine. Do whatever is required depending on the internal state
// set the max well on test based on whether
// we are using hardcoded demo configs or
// real configs
IF(GVL.UseDemoConfigs = TRUE) THEN
MaxWellOnTest := 5;
ELSE
MaxWellOnTest := 32;
END_IF
IF(GVL.TestState = TestStates.Waiting) THEN
// waiting to start
IF(Connected = TRUE) THEN
// only leave this state if we are connected, otherwise don't do anything
IF(GVL.ManualAutoMode = 1) THEN
// handle automatic mode
WellOnTestAuto := WellOnTestAuto + 1;
IF(WellOnTestAuto > MaxWellOnTest) THEN
// loop back around after max wells
WellOnTestAuto := 1;
END_IF
// start a test automatically in the waiting state when in auto mode
WellOnTestInternal := WellOnTestAuto;
GVL.WellOnTestOut := WellOnTestAuto;
GVL.WellOnTestIn := WellOnTestAuto;
// choose whether to use demo or real configs
// real configs must be loaded and enabled
// before this can be used
IF(GVL.UseDemoConfigs = TRUE) THEN
// use demo configs which are hard coded in this app
WellConfig := GVL.DemoWellConfigurations[WellOnTestInternal - 1];
ELSE
// use real configs. These MUST be loaded via external tags
// before being used
WellConfig := GVL.RealWellConfigurations[WellOnTestInternal - 1];
WellConfigStatus := GVL.RealWellTestConfigStatus[WellOnTestInternal - 1];
END_IF
TestTimeRemaining := 0;
GVL.StartTest := TRUE;
GVL.StopTest := FALSE;
GVL.StartStopTest := 1;
GVL.TestState := TestStates.ValidateConfig;
ELSE
// handle manual mode
IF(GVL.WellOnTestIn >= 1 AND GVL.WellOnTestIn <= MaxWellOnTest) THEN
// always set the config so that the user sees the test info
// even if the test is not started
IF(GVL.UseDemoConfigs = TRUE) THEN
// use demo configs which are hard coded in this app
WellConfig := GVL.DemoWellConfigurations[WellOnTestInternal - 1];
ELSE
// use real configs. These MUST be loaded via external tags
// before being used
WellConfig := GVL.RealWellConfigurations[WellOnTestInternal - 1];
WellConfigStatus := GVL.RealWellTestConfigStatus[WellOnTestInternal - 1];
END_IF
END_IF
IF(GVL.StartTest = TRUE) THEN
IF(GVL.WellOnTestIn >= 1 AND GVL.WellOnTestIn <= MaxWellOnTest) THEN
// the well on test value is valid
// cache the well on test internally so that
// we're fine if the value changes during
// the test. Also store the config
WellOnTestInternal := GVL.WellOnTestIn;
GVL.WellOnTestOut := GVL.WellOnTestIn;
TestTimeRemaining := 0;
GVL.TestState := TestStates.ValidateConfig;
// have auto test start track the manual
// value set the by the user. Then we can start
// auto mode at a spefific test
WellOnTestAuto := UDINT_TO_INT(GVL.WellOnTestIn - 1);
ELSE
// the well on test number is not valid, set start to false
GVL.StartTest := FALSE;
END_IF;
END_IF
// always force stop test to false in manual mode while waiting
GVL.StopTest := FALSE;
// set batch control to all flow runs to 'Stop Batch'
GVL.GF01.Control_batchControl := 0;
GVL.LF01.Control_batchControl := 0;
GVL.WT01.Control_batchControl := 0;
WellOnTestAuto := 0;
// end manual mode
END_IF
END_IF
// end waiting state
ELSIF(GVL.TestState = TestStates.ValidateConfig) THEN
IF(GVL.UseDemoConfigs = TRUE) THEN
// we are using hard coded demo configs,
// no need to validate, move to the next state
GVL.TestState := TestStates.SiteSpecific;
ELSE
// we are using real configs. Is the config loaded and enabled?
IF(WellConfigStatus.Enabled = FALSE OR
WellConfigStatus.Loaded = FALSE) THEN
// the configuration is not loaded or not enabled, go
// back to the waiting state
GVL.TestState := TestStates.Waiting;
ELSE
// the config is loaded and enabled, go
// to the site specific state
GVL.TestState := TestStates.Waiting;
END_IF
END_IF
// end validate config state
ELSIF(GVL.TestState = TestStates.SiteSpecific) THEN
// place holder state to do site specific work, like opening and closing valves, etc
IF(GVL.StopTest = TRUE) THEN
// user asked to stop
GVL.TestState := TestStates.Stop;
ELSE
// do work here then move to the next state
GVL.TestState := TestStates.Configure;
END_IF;
// end site specific
ELSIF(GVL.TestState = TestStates.Configure) THEN
// configure the flow runs
IF(GVL.StopTest = TRUE) THEN
// user asked to stop
GVL.TestState := TestStates.Stop;
ELSE
// push the configuration to the flow computers
// gas
GVL.GF01.Compressibility_fractionMethane_w := WellConfig.GasFlowRunConfig.Compressibility_fractionMethane;
GVL.GF01.Compressibility_fractionNitrogen_w := WellConfig.GasFlowRunConfig.Compressibility_fractionNitrogen;
GVL.GF01.Compressibility_fractionCarbonDi_w := WellConfig.GasFlowRunConfig.Compressibility_fractionCarbonDi;
GVL.GF01.Compressibility_fractionEthane_w := WellConfig.GasFlowRunConfig.Compressibility_fractionEthane;
GVL.GF01.Compressibility_fractionPropane_w := WellConfig.GasFlowRunConfig.Compressibility_fractionPropane;
GVL.GF01.Compressibility_fractionIbutane_w := WellConfig.GasFlowRunConfig.Compressibility_fractionIbutane;
GVL.GF01.Compressibility_fractionNbutane_w := WellConfig.GasFlowRunConfig.Compressibility_fractionNbutane;
GVL.GF01.Compressibility_fractionIpentane_w := WellConfig.GasFlowRunConfig.Compressibility_fractionIpentane;
GVL.GF01.Compressibility_fractionNpentane_w := WellConfig.GasFlowRunConfig.Compressibility_fractionNpentane;
GVL.GF01.Compressibility_fractionNhexane_w := WellConfig.GasFlowRunConfig.Compressibility_fractionNhexane;
GVL.GF01.Compressibility_fractionNheptane_w := WellConfig.GasFlowRunConfig.Compressibility_fractionNheptane;
GVL.GF01.Compressibility_fractionNoctane_w := WellConfig.GasFlowRunConfig.Compressibility_fractionNoctane;
GVL.GF01.Compressibility_fractionNnonane_w := WellConfig.GasFlowRunConfig.Compressibility_fractionNnonane;
GVL.GF01.Compressibility_fractionNdecane_w := WellConfig.GasFlowRunConfig.Compressibility_fractionNdecane;
GVL.GF01.Compressibility_fractionHydrogen_w := WellConfig.GasFlowRunConfig.Compressibility_fractionHydrogen;
GVL.GF01.Compressibility_fractionOxygen_w := WellConfig.GasFlowRunConfig.Compressibility_fractionOxygen;
GVL.GF01.Compressibility_fractionCarbonMo_w := WellConfig.GasFlowRunConfig.Compressibility_fractionCarbonMo;
GVL.GF01.Compressibility_fractionWater_w := WellConfig.GasFlowRunConfig.Compressibility_fractionWater;
GVL.GF01.Compressibility_fractionH2s_w := WellConfig.GasFlowRunConfig.Compressibility_fractionH2s;
GVL.GF01.Compressibility_fractionHelium_w := WellConfig.GasFlowRunConfig.Compressibility_fractionHelium;
GVL.GF01.Compressibility_fractionArgon_w := WellConfig.GasFlowRunConfig.Compressibility_fractionArgon;
// liquid
GVL.LF01.FlowCalculation_liqProdType_w := WellConfig.LiquidFlowRunConfig.LiquidProductType;
GVL.LF01.Inputs_densityType_w := WellConfig.LiquidFlowRunConfig.DensityType;
GVL.LF01.Inputs_fixedDensity_w := WellConfig.LiquidFlowRunConfig.FixedDensity;
GVL.LF01.FlowCalculation_baseDensityOil_w := WellConfig.LiquidFlowRunConfig.BaseDensityOil;
GVL.LF01.FlowCalculation_corrFactOil_w := WellConfig.LiquidFlowRunConfig.CorrectionFactorOil;
// water
GVL.WT01.FlowCalculation_corrFactWater_w := WellConfig.WaterFlowRunConfig.CorrectionFactorWater;
// set up asset ID. This allows us to link generated records together by asset ID
// which makes reporting easy.
// asset ID is just the well on test number.
// First write to the preset tag then write to the 'set' tag so that app knows to process the value
// gas
GVL.GF01.Control_assetIdPreset := WellOnTestInternal;
// liquid
GVL.LF01.Control_assetIdPreset := WellOnTestInternal;
// water
GVL.WT01.Control_assetIdPreset := WellOnTestInternal;
// batch user ID. All flow runs should have the same batch ID.
// Use the 'Next Batch ID' parameter to see what the IDs are. If they
// are not the same then choose the highest value and push that
// out to the flow computers. It doesn't matter exactly what the ID is,
// what matters is that they are the same for all runs
IF(GVL.GF01.FlowStatus_nextBatchUserId <> GVL.LF01.FlowStatus_nextBatchUserId OR
GVL.GF01.FlowStatus_nextBatchUserId <> GVL.WT01.FlowStatus_nextBatchUserId OR
GVL.LF01.FlowStatus_nextBatchUserId <> GVL.WT01.FlowStatus_nextBatchUserId) THEN
// the batch user IDs are different, need to set them so that the next batch starts with the same IDs
// Note that the parameter holds the next ID, not the last ID, so we want to preset to the next ID - 1
BatchUserId := GVL.GF01.FlowStatus_nextBatchUserId;
IF(GVL.LF01.FlowStatus_nextBatchUserId > BatchUserId) THEN
BatchUserId := GVL.LF01.FlowStatus_nextBatchUserId;
END_IF;
IF(GVL.WT01.FlowStatus_nextBatchUserId > BatchUserId) THEN
BatchUserId := GVL.WT01.FlowStatus_nextBatchUserId;
END_IF
// BatchUserId should now have the highest ID from all runs. This is the next ID
// Set all runs to use this batch ID.
// gas
GVL.GF01.Control_batchUserIdPreset := BatchUserId;
// liquid
GVL.LF01.Control_batchUserIdPreset := BatchUserId;
// water
GVL.WT01.Control_batchUserIdPreset := BatchUserId;
SetBatchIds := TRUE;
ELSE
// ELSE IDs are equal, nothing to do
SetBatchIds := FALSE;
END_IF;
// move to the next state
GVL.TestState := TestStates.SetIds;
SetIdsCounter := 0;
// reset counter as we enter the next state
ConfirmConfigCount := 0;
ConfigBad := FALSE;
END_IF;
// end configure state
ELSIF(GVL.TestState = TestStates.SetIds) THEN
// the tags that contain the IDs were set in the previous state.
// signal the apps to process the new values
IF(SetIdsCounter = 0) THEN
// Asset ID is always set, batch ID
// is only set when we need to
GVL.GF01.Control_setAssetId := TRUE;
GVL.LF01.Control_setAssetId := TRUE;
GVL.WT01.Control_setAssetId := TRUE;
IF(SetBatchIds = TRUE) THEN
GVL.GF01.Control_setBatchUserId := TRUE;
GVL.LF01.Control_setBatchUserId := TRUE;
GVL.WT01.Control_setBatchUserId := TRUE;
END_IF
ELSE
IF(SetIdsCounter >= 15) THEN
// wait for the asset IDs to be processed
// then move to the next state
GVL.TestState := TestStates.ConfirmConfig;
END_IF
END_IF
SetIdsCounter := SetIdsCounter + 1;
// end set IDs state
ELSIF(GVL.TestState = TestStates.ConfirmConfig) THEN
IF(GVL.StopTest = TRUE) THEN
// use asked to stop
GVL.TestState := TestStates.Stop;
ELSE
// wait 5 seconds before checking the configuration. We really only need a couple of seconds
// but a longer wait allows the batch and asset IDs to get fully processed. When in
// automatic mode, if a test fails, and then the next one is started, the asset
// ID does not get processed properly. 5000 ms / 200 ms callback time = 25 callbacks
// There are two ways to validate the the flow computers are configured correctly:
// 1. Check the "config invalid" tag for each group of interest
// 2. Check that the _r tag matches the _w tag. This means that the config change was accepted by the app
// We'll just do number 1 for the demo, but number 2 allows you to pinpoint which parameter(s) were not accepted
ConfirmConfigCount := ConfirmConfigCount + 1;
IF(ConfirmConfigCount > 25) THEN
ConfigBad := GVL.GF01.ConfigurationGroupStatus_compressGrpInVld OR
GVL.LF01.ConfigurationGroupStatus_flwCalcGrpVld OR
GVL.LF01.ConfigurationGroupStatus_inputGrpVld OR
GVL.WT01.ConfigurationGroupStatus_flwCalcGrpVld;
IF(ConfigBad = TRUE) THEN
// the configuration is not good.
// stop. Add additional error codes or logging here
GVL.StartStopTest := 0;
GVL.TestState := TestStates.Stop;
ELSE
// move to the next state
GVL.TestState := TestStates.StartPurge;
PurgeComplete := FALSE;
END_IF;
END_IF;
END_IF;
// end confirm config
ELSIF(GVL.TestState = TestStates.StartPurge) THEN
IF(GVL.StopTest = TRUE) THEN
// user asked to stop
GVL.TestState := TestStates.Stop;
ELSE
// send the purge start command to all flow runs
GVl.GF01.Control_batchControl := 1;
GVl.LF01.Control_batchControl := 1;
GVl.WT01.Control_batchControl := 1;
// go to the next state
GVL.TestState := TestStates.Purge;
END_IF;
ELSIF(GVL.TestState = TestStates.Purge) THEN
IF(GVL.StopTest = TRUE) THEN
// user asked to stop
GVL.TestState := TestStates.Stop;
ELSE
// wait until purge is complete
// check the actual purge volumes against the configured limits
// When all flow runs have exceeded their limit, move to the next state
PurgeComplete := GVL.GF01.BatchCurrentStatus_prgVolBase >= WellConfig.PurgeVolumeGas AND
GVL.LF01.BatchStatus_prgVol >= WellConfig.PurgeVolumeLiquid AND
GVL.WT01.BatchStatus_prgVol >= WellConfig.PurgeVolumeWater;
IF(PurgeComplete = TRUE) THEN
// go to the next state
GVL.TestState := TestStates.StartBatch;
END_IF;
END_IF;
// end of purge
ELSIF(GVL.TestState = TestStates.StartBatch) THEN
IF(GVL.StopTest = TRUE) THEN
// user asked to stop
GVL.TestState := TestStates.Stop;
ELSE
// send the start batch command for all runs
GVl.GF01.Control_batchControl := 2;
GVl.LF01.Control_batchControl := 2;
GVl.WT01.Control_batchControl := 2;
// cache the start time and calculate the end time
// time stamps are stored as unix millizeconds, milliseconds since Jan 1 1970
TimeNowS := SysTimeRtcGet(TimeNowS);
// get test start time as seconds, not milliseconds
TestStartTime := TimeNowS; // ULINT_TO_UDINT(TimeNowMs/1000);
// test duration is stored as seconds
TestEndTime := TestStartTime + WellConfig.TestDuration;
TestTimeRemaining := WellConfig.TestDuration; // TestEndTime - TestStartTime;
// get start time and end as local time for HMI
SysTimeRTCConvertUTCToLocal(TestStartTime, TestStartTimeLocal);
SysTimeRTCConvertUTCToLocal(TestEndTime, TestEndTimeLocal);
TestStartTimeLocalDt := TO_DT(TestStartTimeLocal);
TestEndTimeLocalDt := TO_DT(TestEndTimeLocal);
// go to the next state
GVL.TestState := TestStates.Test;
END_IF;
ELSIF(GVL.TestState = TestStates.Test) THEN
IF(GVL.StopTest = TRUE) THEN
// user asked to stop
GVL.TestState := TestStates.Stop;
ELSE
// see if we have exceeded the configured test time, and if so, stop the test
TimeNowS := SysTimeRtcGet(TimeNowS);
IF(TestEndTime >= TimeNowS) THEN
// this will alwyas be 0 or a positive number
TestTimeRemaining := TestEndTime - TimeNowS;
ELSE
TestTimeRemaining := 0;
END_IF;
IF(TestTimeRemaining = 0) THEN
// Stop batches
GVl.GF01.Control_batchControl := 0;
GVl.LF01.Control_batchControl := 0;
GVl.WT01.Control_batchControl := 0;
// go to the next state
GVL.TestState := TestStates.Complete;
TestTimeRemaining := 0;
END_IF
END_IF;
// end test state
ELSIF(GVL.TestState = TestStates.Complete) THEN
// do things when the test ends normally, clear state markers and go back to waiting state
TestTimeRemaining := 0;
TestStartTime := 0;
TestEndTime := 0;
TestStartTimeLocal := 0;
TestEndTimeLocal := 0;
TestStartTimeLocalDt := TO_DT(TestStartTimeLocal);
TestEndTimeLocalDt := TO_DT(TestEndTimeLocal);
CompleteDelayCount := CompleteDelayCount + 1;
IF(CompleteDelayCount >= 10) THEN
// change state after some delay
CompleteDelayCount := 0;
GVL.TestState := TestStates.Waiting;
GVL.StartStopTest := 0;
END_IF
// end complete state
ELSIF(GVL.TestState = TestStates.Stop) THEN
// stop was requested by the user
// stop batches, clear state markers and go back to waiting state
GVl.GF01.Control_batchControl := 0;
GVl.LF01.Control_batchControl := 0;
GVl.WT01.Control_batchControl := 0;
TestTimeRemaining := 0;
TestStartTime := 0;
TestEndTime := 0;
TestStartTimeLocal := 0;
TestEndTimeLocal := 0;
TestStartTimeLocalDt := TO_DT(TestStartTimeLocal);
TestEndTimeLocalDt := TO_DT(TestEndTimeLocal);
StopDelayCount := StopDelayCount +1;
IF(StopDelayCount >= 10) THEN
// change state after some delay
StopDelayCount := 0;
GVL.TestState := TestStates.Waiting;
END_IF
// end stop state
END_IF;
// end section Main State Machine
//************************************************************************
//************************************************************************
// Section HMI State
// get the current state string
// no need to show all internal states, just
// show ones that take some time
IF(GVL.TestState = TestStates.Waiting) THEN
CurrentStateString := 'Waiting';
ELSIF(GVL.TestState = TestStates.Configure) THEN
CurrentStateString := 'Configure';
ELSIF(GVL.TestState = TestStates.ConfirmConfig) THEN
CurrentStateString := 'Validate';
ELSIF(GVL.TestState = TestStates.Purge) THEN
CurrentStateString := 'Purge';
ELSIF(GVL.TestState = TestStates.Test) THEN
CurrentStateString := 'Test';
END_IF;
//************************************************************************
//************************************************************************
// Section Convert Timestamps
// convert batch history timestamps to DATE_AND_TIME values so that they can be displayed
// timestamps are stored by the well test application as unix seconds UTC
SysTimeRTCConvertUTCToLocal(GVL.GF01.BatchHistory_bchHisStartTs_001, LastBatchStartTimeLocal);
SysTimeRTCConvertUTCToLocal(GVL.GF01.BatchHistory_bchHisEndTs_001, LastBatchEndTimeLocal);
LastBatchStartTimeLocalDt := TO_DT(LastBatchStartTimeLocal);
LastBatchEndTimeLocalDt := TO_DT(LastBatchEndTimeLocal);
//************************************************************************
//************************************************************************
// Section Connection State
(* check connection state of apps. Wait 50 callbacks and see if the exec count for each app is changing *)
IF(ConnectedCounter >= 50) THEN
(* The delay timer has expired. Reset the delay timer
and then see if we're connected by comparing the execution counts
to the execution counts from the last time that we executed
this code section *)
ConnectedCounter := 0;
(* an app is connected if the counts have changed *)
GasFlowConnected := GVL.GF01.ApplicationInfo_execCount <> GasLastExecCount;
LiquidFlowConnected := GVL.LF01.ApplicationInfo_execCount <> LiquidLastExecCount;
WaterFlowConnected := GVL.WT01.ApplicationInfo_execCount <> WaterLastExecCount;
(* update the counts for each app *)
GasLastExecCount := GVL.GF01.ApplicationInfo_execCount;
LiquidLastExecCount := GVL.LF01.ApplicationInfo_execCount;
WaterLastExecCount := GVL.WT01.ApplicationInfo_execCount;
END_IF
(* always increment the delay counter *)
ConnectedCounter := ConnectedCounter + 1;
(* connected is true only if all apps are connected *)
Connected := GasFlowConnected AND LiquidFlowConnected AND WaterFlowConnected;
// set the color
IF(Connected = TRUE) THEN
ConnectedColor := 16#FFCCCCCC; // grey
ELSE
ConnectedColor := 16#FFFF0000; // red
END_IF;
//************************************************************************
//************************************************************************
// Section Alarms Active
// get the overall alarm status. Set the bool active if tehre
// are any alarms on any run. More granular information is
// available from each app if so desired. Each alarm type
// has an indivisual status tag.
// Only let this go true if we are actually connected. When
// not connected, this will be always be false;
FlowComputerAlarmsActive := (GVL.GF01.InputAlarmStatus_alarmActive OR
GVL.LF01.InputAlarmStatus_alarmActive OR
GVL.WT01.InputAlarmStatus_alarmActive) AND
Connected;
IF(FlowComputerAlarmsActive = TRUE) THEN
FlowComputerAlarmsColor := 16#FFFF0000; // red
ELSE
FlowComputerAlarmsColor := 16#FFCCCCCC; // grey
END_IF
//************************************************************************
//************************************************************************
// Section Well Confirurations
// configure wells to test
// do this once when the
// program is started
IF LoadDemoConfigurations = TRUE THEN
// only load configurations once
LoadDemoConfigurations := FALSE;
//***********************************************************************************
// well 1, index 0
GVL.DemoWellConfigurations[0].WellNumber := 0;
GVL.DemoWellConfigurations[0].PurgeVolumeGas := 1.0; // m3
GVL.DemoWellConfigurations[0].PurgeVolumeLiquid := 0.5; // m3
GVL.DemoWellConfigurations[0].PurgeVolumeWater := 0.5; // m3
GVl.DemoWellConfigurations[0].TestDuration := 7200; // seconds
// gas
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionMethane := 0.79675;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionNitrogen := 0.0081;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionCarbonDi := 0.016;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionEthane := 0.00525;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionPropane := 0.01805;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionWater := 0.01862;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionH2s := 0.01772;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionHydrogen := 0.00985;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionCarbonMo := 0.00798;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionOxygen := 0.00306;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionIbutane := 0.00462;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionNbutane := 0.01882;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionIpentane := 0.00796;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionNpentane := 0.01444;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionNhexane := 0.00078;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionNheptane := 0.01479;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionNoctane := 0.00297;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionNnonane := 0.00868;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionNdecane := 0.00885;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionHelium := 0.00991;
GVL.DemoWellConfigurations[0].GasFlowRunConfig.Compressibility_fractionArgon := 0.0068;
// liquid
GVL.DemoWellConfigurations[0].LiquidFlowRunConfig.DensityType := 0; // live density
GVL.DemoWellConfigurations[0].LiquidFlowRunConfig.FixedDensity := 757.43;
GVL.DemoWellConfigurations[0].LiquidFlowRunConfig.LiquidProductType := 0; // crude oil
GVL.DemoWellConfigurations[0].LiquidFlowRunConfig.CorrectionFactorOil := 1.0;
GVL.DemoWellConfigurations[0].LiquidFlowRunConfig.BaseDensityOil := 600.0; // kg/m3
GVL.DemoWellConfigurations[0].LiquidFlowRunConfig.BaseDensityWater := 1000.0; // kg/m3
// water
GVL.DemoWellConfigurations[0].WaterFlowRunConfig.CorrectionFactorWater := 1.0;
// end well 1, index 0
//***********************************************************************************
//***********************************************************************************
// well 2, index 1
GVL.DemoWellConfigurations[1].WellNumber := 1;
GVL.DemoWellConfigurations[1].PurgeVolumeGas := 1.0; // m3
GVL.DemoWellConfigurations[1].PurgeVolumeLiquid := 0.25; // m3
GVL.DemoWellConfigurations[1].PurgeVolumeWater := 0.25; // m3
GVl.DemoWellConfigurations[1].TestDuration := 4800; // seconds
// gas
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionMethane := 0.81754;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionNitrogen := 0.01956;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionCarbonDi := 0.0089;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionEthane := 0.00935;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionPropane := 0.0159;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionWater := 0.00993;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionH2s := 0.01296;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionHydrogen := 0.00015;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionCarbonMo := 0.00269;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionOxygen := 0.01688;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionIbutane := 0.00436;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionNbutane := 0.00203;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionIpentane := 0.01276;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionNpentane := 0.01413;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionNhexane := 0.00825;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionNheptane := 0.0125;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionNoctane := 0.00165;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionNnonane := 0.00345;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionNdecane := 0.0;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionHelium := 0.01903;
GVL.DemoWellConfigurations[1].GasFlowRunConfig.Compressibility_fractionArgon := 0.00798;
// liquid
GVL.DemoWellConfigurations[1].LiquidFlowRunConfig.DensityType := 1; // fixed density
GVL.DemoWellConfigurations[1].LiquidFlowRunConfig.FixedDensity := 612.43;
GVL.DemoWellConfigurations[1].LiquidFlowRunConfig.LiquidProductType := 4; // gasonline is unrealistic for a test, but this is just a demo
GVL.DemoWellConfigurations[1].LiquidFlowRunConfig.CorrectionFactorOil := 1.1;
GVL.DemoWellConfigurations[1].LiquidFlowRunConfig.BaseDensityOil := 650.0;
GVL.DemoWellConfigurations[1].LiquidFlowRunConfig.BaseDensityWater := 1000.0; // kg/m3
// water
GVL.DemoWellConfigurations[1].WaterFlowRunConfig.CorrectionFactorWater := 0.9;
// end well 2, index 1
//***********************************************************************************
//***********************************************************************************
// well 3, index 2
// this gas composition is intentionally bad and cannot be loaded.
GVL.DemoWellConfigurations[2].WellNumber := 2;
GVL.DemoWellConfigurations[2].PurgeVolumeGas := 2.0; // m3
GVL.DemoWellConfigurations[2].PurgeVolumeLiquid := 1.0; // m3
GVL.DemoWellConfigurations[2].PurgeVolumeWater := 0.0; // m3
GVl.DemoWellConfigurations[2].TestDuration := 600; // seconds
// gas
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionMethane := 0.7776;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionNitrogen := 0.00721;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionCarbonDi := 0.01813;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionEthane := 0.01355;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionPropane := 0.01582;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionWater := 0.01054;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionH2s := 0.01669;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionHydrogen := 0.01648;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionCarbonMo := 0.00409;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionOxygen := 0.00105;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionIbutane := 0.00944;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionNbutane := 0.0092;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionIpentane := 0.01874;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionNpentane := 0.00747;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionNhexane := 0.00229;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionNheptane := 0.00448;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionNoctane := 0.0151;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionNnonane := 0.0114;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionNdecane := 0.01387;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionHelium := 0.0152;
GVL.DemoWellConfigurations[2].GasFlowRunConfig.Compressibility_fractionArgon := 0.01165;
// liquid
GVL.DemoWellConfigurations[2].LiquidFlowRunConfig.DensityType := 0; // live density
GVL.DemoWellConfigurations[2].LiquidFlowRunConfig.FixedDensity := 698.32;
GVL.DemoWellConfigurations[2].LiquidFlowRunConfig.LiquidProductType := 0; // crude oil
GVL.DemoWellConfigurations[2].LiquidFlowRunConfig.CorrectionFactorOil := 0.9;
GVL.DemoWellConfigurations[2].LiquidFlowRunConfig.BaseDensityOil := 605.0;
GVL.DemoWellConfigurations[2].LiquidFlowRunConfig.BaseDensityWater := 1000.0; // kg/m3
// water
GVL.DemoWellConfigurations[2].WaterFlowRunConfig.CorrectionFactorWater := 1.1;
// end well 3, index 2
//***********************************************************************************
//***********************************************************************************
// well 4, index 3
GVL.DemoWellConfigurations[3].WellNumber := 3;
GVL.DemoWellConfigurations[3].PurgeVolumeGas := 1.0; // m3
GVL.DemoWellConfigurations[3].PurgeVolumeLiquid := 1.0; // m3
GVL.DemoWellConfigurations[3].PurgeVolumeWater := 1.0; // m3
GVl.DemoWellConfigurations[3].TestDuration := 3600; // seconds
// gas
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionMethane := 0.81061;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionNitrogen := 0.00518;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionCarbonDi := 0.00786;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionEthane := 0.0173;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionPropane := 0.01503;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionWater := 0.00918;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionH2s := 0.00871;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionHydrogen := 0.00875;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionCarbonMo := 0.00554;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionOxygen := 0.01932;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionIbutane := 0.00343;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionNbutane := 0.01543;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionIpentane := 0.003;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionNpentane := 0.01873;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionNhexane := 0.0102;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionNheptane := 0.00698;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionNoctane := 0.00261;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionNnonane := 0.00244;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionNdecane := 0.01714;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionHelium := 0.00825;
GVL.DemoWellConfigurations[3].GasFlowRunConfig.Compressibility_fractionArgon := 0.00431;
// liquid
GVL.DemoWellConfigurations[3].LiquidFlowRunConfig.DensityType := 0; // live density
GVL.DemoWellConfigurations[3].LiquidFlowRunConfig.FixedDensity := 703.2;
GVL.DemoWellConfigurations[3].LiquidFlowRunConfig.LiquidProductType := 0; // crude oil
GVL.DemoWellConfigurations[3].LiquidFlowRunConfig.CorrectionFactorOil := 1.0;
GVL.DemoWellConfigurations[3].LiquidFlowRunConfig.BaseDensityOil := 700.0;
GVL.DemoWellConfigurations[3].LiquidFlowRunConfig.BaseDensityWater := 1000.0; // kg/m3
// water
GVL.DemoWellConfigurations[3].WaterFlowRunConfig.CorrectionFactorWater := 1.2;
// end well 4, index 3
//***********************************************************************************
//***********************************************************************************
// well 5, index 4
GVL.DemoWellConfigurations[4].WellNumber := 4;
GVL.DemoWellConfigurations[4].PurgeVolumeGas := 1.5; // m3
GVL.DemoWellConfigurations[4].PurgeVolumeLiquid := 1.5; // m3
GVL.DemoWellConfigurations[4].PurgeVolumeWater := 1.5; // m3
GVl.DemoWellConfigurations[4].TestDuration := 7200; // seconds
// gas
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionMethane := 0.84489;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionNitrogen := 0.0153;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionCarbonDi := 0.00023;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionEthane := 0.00564;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionPropane := 0.00318;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionWater := 0.00757;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionH2s := 0.00477;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionHydrogen := 0.01197;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionCarbonMo := 0.00725;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionOxygen := 0.00178;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionIbutane := 0.00229;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionNbutane := 0.01697;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionIpentane := 0.01493;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionNpentane := 0.01806;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionNhexane := 0.0093;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionNheptane := 0.01125;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionNoctane := 0.01047;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionNnonane := 0.0;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionNdecane := 0.0;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionHelium := 0.01415;
GVL.DemoWellConfigurations[4].GasFlowRunConfig.Compressibility_fractionArgon := 0.0;
// liquid
GVL.DemoWellConfigurations[4].LiquidFlowRunConfig.DensityType := 1; // fixed density
GVL.DemoWellConfigurations[4].LiquidFlowRunConfig.FixedDensity := 800.0;
GVL.DemoWellConfigurations[4].LiquidFlowRunConfig.LiquidProductType := 1; // fuel oil
GVL.DemoWellConfigurations[4].LiquidFlowRunConfig.CorrectionFactorOil := 1.0;
GVL.DemoWellConfigurations[4].LiquidFlowRunConfig.BaseDensityOil := 605.0;
GVL.DemoWellConfigurations[4].LiquidFlowRunConfig.BaseDensityWater := 1000.0; // kg/m3
// water
GVL.DemoWellConfigurations[4].WaterFlowRunConfig.CorrectionFactorWater := 1.0;
// end well 4, index 5
//***********************************************************************************
END_IF;
// end section Well Configurations
//************************************************************************