iNumWellModels = iNumWellModels + 1
The next stage is to create the layers for this well. We use the same principal of reading through the layer indices until we get an error message warning that no more layers are left.
iIprFound = 1
iIPRNo = 0 Do
Call the command to read the well from the MBI file again. This time we are interested in the layer data so we set the IPRNUM to read the next layer (starting at layer zero).
DoSet "MBAL.RL.SMBWELLDATA.MBIHANDLE",
iMBIHandle
DoSet "MBAL.RL.SMBWELLDATA.HANDLE", iWellNo DoSet "MBAL.RL.SMBWELLDATA.IPRNUM", iIPRNo iCommand = 9 ' Get well data command
DoSet "MBAL.RL.SMBWELLDATA.COMMAND", iCommand
DoCmd "MBAL.RL.WELLDATA"
Check if a layer was found. If we have got to the end of the layer list we get an error code=216. Otherwise the command will have successfully loaded the next layer data into the SMBWELLDATA data block.
iErrorCode = DoGet("MBAL.RL.SMBERRORDATA.CODE")
If (iErrorCode = 216) Then ' IPR not found iIprFound = 0
Else
Before creating the layer model, we have to find the index of the tank to which the layer is connected. Now the last command will return the name of the connected tank in the TANKNAME variable. Just after reading the tanks from the MBI file we read and stored the names of the tank in the szTankNames VBA variable for each tank index. So by searching through the szTankNames list we can find the index of the connected tank.
szTankName = DoGet("MBAL.RL.SMBWELLDATA.
TANKNAME")
For i = 0 To iNumTanks - 1
If (szTankName = szTankNames(i)) Then
DoSet "MBAL.RL.SMBWELLDATA.TANKNUM", i
End If Next I
Finally we call the command to create an IPR/layer model and connect it to the well model. The data used to initialize the IPR model is taken from the SMBWELLDATA data block. This is the same data that was loaded with the layer data by the last command, so we are simply transferring it from the layer in the MBI file to the layer model just created.
DoSet "MBAL.RL.SMBWELLDATA.MBIHANDLE", iMBIHandle
DoSet "MBAL.RL.SMBWELLDATA.HANDLE", iWellModel(iWellIndex)
DoSet "MBAL.RL.SMBWELLDATA.IPRNUM", iIPRNo
iCommand = 35 ' Add an IPR command
DoSet "MBAL.RL.SMBWELLDATA.COMMAND", iCommand
DoCmd "MBAL.RL.WELLDATA"
End If
iIPRNo = iIPRNo + 1 Loop While (iIprFound) End If
iWellNo = iWellNo + 1 Loop While (iWellFound)
We have now created the tank, well and layer/IPR models that mirror the objects in the MBI file.
By default, the well model is created assuming there is one instance of the well model.
This next fragment shows how it is possible to model more than one well being drilled of the same type. Load the MBI handle as usual. Load 2nd well model handle in the HANDLE variable as we wish to modify the Gas Lift well. Load the number of wells to drill in NUMWELL. Load –1 in the variable IPRNUM, as this indicates that the command is not specific to a particular layer.
DoSet "MBAL.RL.SMBWELLDATA.MBIHANDLE", iMBIHandle DoSet "MBAL.RL.SMBWELLDATA.HANDLE", iWellModel(1) DoSet "MBAL.RL.SMBWELLDATA.NUMWELL", 2
DoSet "MBAL.RL.SMBWELLDATA.IPRNUM", -1 iCommand = 13 ' Set number of wells
DoSet "MBAL.RL.SMBWELLDATA.COMMAND", iCommand DoCmd "MBAL.RL.WELLDATA"
The next sub-section shows how to set a downtime factor for the 1st well, the Oil Well. A downtime of zero means that the well is always producing. A downtime of 1.0 means that the well is never producing, and the method is much the same as for setting the number of wells.
DoSet "MBAL.RL.SMBWELLDATA.MBIHANDLE", iMBIHandle DoSet "MBAL.RL.SMBWELLDATA.HANDLE", iWellModel(0) DoSet "MBAL.RL.SMBWELLDATA.DOWNTIME", 0.2
DoSet "MBAL.RL.SMBWELLDATA.IPRNUM", -1 iCommand = 12 ' Set downtime command
DoSet "MBAL.RL.SMBWELLDATA.COMMAND", iCommand DoCmd "MBAL.RL.WELLDATA"
This next section shows how to set a start and end time for a well model. This code fragment also shows an important point concerning the use of times. In the Direct Access OpenServer, times are in internal units which are the number of days since 1900. Obviously these are not very convenient units, and if calendar dates e.g.
01/01/1994 are being used, we provide a command to convert calendar dates to internal times (and back again). To do this set the DATE variable to the calender date required, then call the DATETOTIME command. The answer can then be retrieved from the TIME variable. To do the reverse calculation ,use the command TIMETODATE.
We first convert the two calendar dates required to internal times, and then set the STARTTIME and ENDTIME variables to these two internal time values. We set the HANDLE to the well model handle for the third well (Gas Well), and finally set the Command ID=14 to set the start and end times.
DoSet "MBAL.RL.DATE", "31/01/1990"
DoCmd "MBAL.RL.DATETOTIME"
dStartTime = DoGet("MBAL.RL.TIME") DoSet "MBAL.RL.DATE", "02/03/1990"
DoCmd "MBAL.RL.DATETOTIME"
dEndTime = DoGet("MBAL.RL.TIME")
DoSet "MBAL.RL.SMBWELLDATA.MBIHANDLE", iMBIHandle DoSet "MBAL.RL.SMBWELLDATA.HANDLE", iWellModel(3) DoSet "MBAL.RL.SMBWELLDATA.STARTTIME", dStartTime
DoSet "MBAL.RL.SMBWELLDATA.ENDTIME", dEndTime DoSet "MBAL.RL.SMBWELLDATA.IPRNUM", -1
iCommand = 14 ' Set start and end time command DoSet "MBAL.RL.SMBWELLDATA.COMMAND", iCommand DoCmd "MBAL.RL.WELLDATA"
We have now completed the initialization and are ready to go into the prediction loop.
The rest of the source code listings are within the main prediction loop which does a time step for each time through the loop.
The first code fragment from within the loop is used to display the current time on the sheet. It shows how to convert an internal time (in number of days since 1900) to a calendar date, note that it will use the current international date settings on the PC.
DoSet "MBAL.RL.TIME", CUMTIM
DoCmd "MBAL.RL.TIMETODATE"
Range("B" + CStr(16 + iStep)) = DoGet("MBAL.RL.
DATE")
The first main task in the prediction step is to initialize the layers to the current tank conditions. First, update the PVT properties with those calculated in the tanks at the current pressure. Then calculate the breakthroughs i.e., GOR, WCT, CGR, and WGR, etc., using the current fluid properties and saturations.
We can update the PVT properties with a single command for each well. Load the MBI file handle, the well model index and set the layer number to –1 to indicate all layers should be recalculated. If a specific layer number is specified, then only that layer is calculated.
iIPRNo = -1
DoSet "MBAL.RL.SMBWELLDATA.IPRNUM", iIPRNo
DoSet "MBAL.RL.SMBWELLDATA.MBIHANDLE", iMBIHandle
DoSet "MBAL.RL.SMBWELLDATA.HANDLE", iWellModel (iWellNo)
iCommand = 23 ' Update PVT from tank command DoSet "MBAL.RL.SMBWELLDATA.COMMAND", iCommand
DoCmd "MBAL.RL.WELLDATA"
In this example we calculate the GOR, etc., layer by layer. This is partly as demonstration, but also because we wish to read the pressure of each layer. We again use the technique of iterating through the layers until we get an error message that no more layers are available. First set up the IPR number to the next layer and call the command with command ID=6 to calculate the breakthroughs. If the layer/IPR index is not valid, an error code=216 will be reported.
iIPRNo = 0 iIprFound = 1 Do
DoSet "MBAL.RL.SMBWELLDATA.MBIHANDLE", iMBIHandle
DoSet "MBAL.RL.SMBWELLDATA.HANDLE", iWellModel(iWellNo)
DoSet "MBAL.RL.SMBWELLDATA.IPRNUM", iIPRNo iCommand = 6 ' Calculate breakthroughs command
DoSet "MBAL.RL.SMBWELLDATA.COMMAND", iCommand
DoCmd "MBAL.RL.WELLDATA"
iErrorCode = DoGet("MBAL.RL.SMBERRORDATA.
CODE")
If (iErrorCode = 216) Then ' IPR not found iIprFound = 0