msfz751

ProsperCalculation Classs

Jun 13th, 2015
553
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ' ####################################################
  2. ' #         ProsperCalculation Class Module          #
  3. ' ####################################################
  4. ' Auxiliary library to work with Petroleum Experts (TM) OpenServer.
  5. ' Part of the SimpleOpenServer package, developed by Patricio Panichelli.
  6. ' Some rights reserved (c) www.SimpleOpenServer.com/license
  7. ' For documentation, visit www.SimpleOpenServer.com/docs
  8. ' SOS Version:              1.0.0
  9. ' Developed & tested with:  IPM 9.0
  10. '
  11. Option Explicit
  12. Option Base 0
  13. Private xCalculationType As osCalculationType, xFixedVars() As Variant, xFixedValues() As Variant, xFixedVarsCount As Long, _
  14.     xResetSensitivities As Boolean, xRememberSetVariables As Boolean, xUseRawValues As Boolean, xRegressionStatus As osRegressionStatus, _
  15.     xXvalues, xFluidType As osFluidType
  16. Enum osFluidType
  17.     [Oil and Water]
  18.     [Dry and Wet Gas]
  19.     [Retrograde Condensate]
  20. End Enum
  21. Enum osRegressionStatus
  22.     [No Regression Done]
  23.     Converged
  24.     [Solution Not Found In Range]
  25.     [Loops Exceeded]
  26.     [No Solution Found]
  27. End Enum
  28. Enum osInputVariable
  29.     [Water Cut]
  30.     GOR
  31.     CGR
  32.     WGR
  33.     [Top Node Pressure]
  34.     [Reservoir Pressure]
  35.     [Reservoir Temperature]
  36.     [Productivity Index]
  37.     Permeability
  38.     Skin
  39.     [Tubing Correlation]
  40.     [Surface Correlation]
  41.     [Flow Rate (Gradient)]
  42.     [Bottomhole Pressure (Gradient)]
  43.     [Tubing Roughness]
  44.     [Heat Transfer Coefficient]
  45.     [_Sens DB]
  46.     [Pump Operating Frequency (ESP)]
  47.     [Pump Wear Factor (ESP)]
  48.     [Pump MD (ESP)]
  49.     [Pump Number of Stages (ESP)]
  50.     [Pump Speed (SRP)]
  51.     [Gaslift Gas Injection Rate]
  52.     [Gaslift Injection Depth]
  53.     [Gaslift Casing Pressure]
  54. End Enum
  55. Enum osSolutionVariable
  56.     [_Exists]
  57.     [Q Liquid]
  58.     [Q Oil]
  59.     [Q Water]
  60.     [Q Gas]
  61.     [Solution Node Pressure]
  62.     [Bottomhole Pressure]
  63.     [dP Friction]
  64.     [dP Gravity]
  65.     [Wellhead Pressure]
  66.     [Wellhead Temperature]
  67.     [First Node Pressure]
  68.     [First Node Temperature]
  69.     [Pump Intake Pressure]
  70.     [Pump Discharge Pressure]
  71.     [Average Rate Through Pump]
  72.     [Pump Head Generated]
  73.     [Pump Power Requirement]
  74.     [Pump Efficiency]
  75.     [Motor Amps Requirement]
  76.     [Motor Power Generated]
  77. End Enum
  78. Enum rv
  79.     [Liquid rate]
  80.     [Oil rate]
  81.     [Water rate]
  82.     [Gas rate]
  83.     [IPR Pressure]
  84.     [VLP Pressure]
  85.     [dP Frict.]
  86.     [dP Grav.]
  87.     [Pump Intake Press.]
  88.     [Pump Discharge Press.]
  89.     [Pump Power Req.]
  90. End Enum
  91. Enum dv
  92.     [Label]
  93.     [Measured Depth]
  94.     [True Vertical Depth]
  95.     [Pressure]
  96.     [Temperature]
  97.     [Pressure Gradient]
  98.     [Holdup]
  99.     [Flow Regime Number]
  100.     [Static Gradient]
  101.     [Friction Gradient]
  102.     [Total NoSlip Velocity]
  103.     [Turner Velocity]
  104. End Enum
  105. Enum osCalculationType
  106.     Inflow
  107.     System
  108.     VLP
  109.     Gradient
  110. End Enum
  111.  
  112. ' ++++++++++++++++++++++++++++
  113. ' Private sub Class_Initialize
  114. ' ++++++++++++++++++++++++++++
  115. ' Initializes the class with the defaults
  116. Private Sub Class_Initialize()
  117.     xCalculationType = System
  118.     xResetSensitivities = True
  119.     xRememberSetVariables = True
  120.     xUseRawValues = False
  121.     xFluidType = -1
  122.     xRegressionStatus = [No Regression Done]
  123.     xXvalues = 0
  124. End Sub
  125. ' +++++++++++++++++++++++++
  126. ' Private sub pGetFluidType
  127. ' +++++++++++++++++++++++++
  128. ' Sets the xFluidType variable
  129. Private Sub pGetFluidType()
  130.     Debug.Print "GET " & "PROSPER.Sin.Sum.Fluid = " & DoGet("PROSPER.Sin.Sum.Fluid")
  131.     xFluidType = CInt(DoGet("PROSPER.Sin.Sum.Fluid"))
  132. End Sub
  133.  
  134. ' ++++++++++++++++++++++
  135. ' Public sub setVariable
  136. ' ++++++++++++++++++++++
  137. ' adds a variable to the xSensVars list
  138. ' parses its values using interpretValue
  139. ' and adds the values to xSensValues list
  140. ' checks for duplicate setVariable statements & overrites
  141. ' keeps track of xSensVarsCount
  142. Public Sub setVar(variable As osInputVariable, value As Variant)
  143.     Dim index As Long
  144.     index = pFindInArray(what:=variable, inArray:=xFixedVars)
  145.     If index < 0 Then
  146.         ReDim Preserve xFixedVars(xFixedVarsCount), xFixedValues(xFixedVarsCount)
  147.         index = xFixedVarsCount
  148.         xFixedVarsCount = xFixedVarsCount + 1
  149.     End If
  150.     ' Add to xFixedVars()
  151.    xFixedVars(index) = variable
  152.     ' Add values to xFixedValues
  153.    xFixedValues(index) = value
  154. End Sub
  155.  
  156. ' ++++++++++++++++++++++
  157. ' Public Function vector
  158. ' ++++++++++++++++++++++
  159. ' Returns an array with depths or rates in the (0) index, and the desired value in the (1) index
  160. ' Thus, the Variable can be either a depthVector variable (listed in the dv enumerable)
  161. ' or a rateVector variable (listed in the rv enumerable)
  162. Public Function Vector(variable As Long) As Vector
  163.     Dim result As String, values, i As Integer, returnedVec() As Double
  164.     If xCalculationType = Gradient Then
  165.         result = pGet(Replace(accessString_osDepthVector(variable), "[i][j][k]", "[0][0][0]"))
  166.     Else
  167.         result = pGet(Replace(accessString_osRateVector(variable), "[#]", "[0]"))
  168.     End If
  169.     pGetXvalues
  170.     values = pVectorize(result)
  171.     ReDim returnedVec(0 To 1, 0 To UBound(values)) As Double
  172.     For i = 0 To UBound(values)
  173.         returnedVec(0, i) = xXvalues(i)
  174.         returnedVec(1, i) = values(i)
  175.     Next
  176.     Dim V As New Vector
  177.     V.newFromValues returnedVec
  178.     Set Vector = V
  179. End Function
  180.  
  181. ' +++++++++++++++++++++++++++
  182. ' Private Function pVectorize
  183. ' +++++++++++++++++++++++++++
  184. ' Splits a multi-value string returned by an $ access string
  185. ' Returns a variant array with the values.
  186. ' If values are Doubles, then returns Doubles
  187. Private Function pVectorize(st As String) As Variant
  188.     Dim vec
  189.     If Right(st, 1) = "|" Then st = Mid(st, 1, Len(st) - 1)
  190.     vec = Split(st, "|")
  191.     If IsNumeric(vec(0)) Then
  192.         Dim dblVec() As Double, i As Long
  193.         ReDim dblVec(0 To UBound(vec))
  194.         For i = LBound(vec) To UBound(vec)
  195.             dblVec(i) = CDbl(vec(i))
  196.         Next
  197.         pVectorize = dblVec
  198.     Else
  199.         pVectorize = vec
  200.     End If
  201. End Function
  202.  
  203. ' +++++++++++++++++++++++
  204. ' Private Sub pGetXvalues
  205. ' +++++++++++++++++++++++
  206. ' Ensures that the xXvalues vector is set
  207. Private Sub pGetXvalues()
  208.     If TypeName(xXvalues) = "Integer" Then
  209.        
  210.         Dim result As String
  211.         If calculationType = Gradient Then
  212.             result = pGet(Replace(accessString_osDepthVector([Measured Depth]), "[i][j][k]", "[0][0][0]"))
  213.         Else
  214.             If fluidType = [Oil and Water] Then
  215.                 result = pGet(Replace(accessString_osRateVector([Liquid rate]), "[#]", "[0]"))
  216.             Else
  217.                 result = pGet(Replace(accessString_osRateVector([Gas rate]), "[#]", "[0]"))
  218.             End If
  219.         End If
  220.        
  221.         xXvalues = pVectorize(result)
  222.     End If
  223. End Sub
  224.  
  225. ' ++++++++++++++++++++++++
  226. ' Public function solution
  227. ' ++++++++++++++++++++++++
  228. ' returns any of the solution values of SYSTEM calculation
  229. ' optional Index can obtain any index solution
  230. Public Function solution(variable As osSolutionVariable, Optional index As Variant) As Double
  231.     If IsMissing(index) Then index = 0
  232.     solution = CDbl(pGet(Replace(accessString_osSolution(variable), "#", CStr(index))))
  233. End Function
  234.  
  235. ' ++++++++++++++++++++
  236. ' Public sub calculate
  237. ' ++++++++++++++++++++
  238. ' populates the xCombinations array first,
  239. ' then runs the calculations
  240. ' and saves the results in xRecordValues
  241. Public Sub calculate(Optional loops As Variant)
  242.     If xResetSensitivities Then pResetSensDB
  243.     pSetFixedVars
  244.     pMakeCalculation
  245. End Sub
  246.  
  247. ' ++++++++++++++++++++++++++++
  248. ' Private sub pMakeCalculation
  249. ' ++++++++++++++++++++++++++++
  250. ' Actually makes the doCmd for the calculation
  251. Private Sub pMakeCalculation()
  252.     Select Case xCalculationType
  253.         Case Is = osCalculationType.Gradient
  254.             Debug.Print "CMD PROSPER.ANL.GRD.CALC"
  255.             DoCmd "PROSPER.ANL.GRD.CALC"
  256.         Case Is = osCalculationType.Inflow
  257.             Debug.Print "CMD PROSPER.ANL.INF.CALC"
  258.             DoCmd "PROSPER.ANL.INF.CALC"
  259.         Case Is = osCalculationType.System
  260.             Debug.Print "CMD PROSPER.ANL.SYS.CALC"
  261.             DoCmd "PROSPER.ANL.SYS.CALC"
  262.         Case Is = osCalculationType.VLP
  263.             Debug.Print "CMD PROSPER.ANL.VLP.CALC"
  264.             DoCmd "PROSPER.ANL.VLP.CALC"
  265.     End Select
  266.     xXvalues = 0
  267. End Sub
  268.  
  269.  
  270. ' +++++++++++++++++++++++++
  271. ' Private sub pSetFixedVars
  272. ' +++++++++++++++++++++++++
  273. ' Actually makes the doSet in the prosper file for all
  274. ' variables that were set before using setVar
  275. Private Sub pSetFixedVars()
  276.     Dim i As Long, sensDBVars As Long, accstr As Variant, rv As String
  277.     If xUseRawValues Then rv = ".RAWVAL"
  278.     For i = 0 To xFixedVarsCount - 1
  279.         accstr = accessString(CLng(xFixedVars(i)))
  280.         If IsNumeric(accstr) Then
  281.             Debug.Print "SET " & accessString(osInputVariable.[_Sens DB]) & ".Vars[" & CStr(sensDBVars) & "] to " & CStr(accstr)
  282.             DoSet accessString(osInputVariable.[_Sens DB]) & ".Vars[" & CStr(sensDBVars) & "]", CStr(accstr)
  283.             Debug.Print "SET " & accessString(osInputVariable.[_Sens DB]) & ".Sens[" & CStr(pIndexFromSensVar(CLng(accstr))) & "].Vals[0]" & rv & " to " & xFixedValues(i)
  284.             DoSet accessString(osInputVariable.[_Sens DB]) & ".Sens[" & CStr(pIndexFromSensVar(CLng(accstr))) & "].Vals[0]" & rv, xFixedValues(i)
  285.             sensDBVars = sensDBVars + 1
  286.         ElseIf accstr <> "N/A" Then
  287.             Debug.Print "SET " & accessString(CLng(xFixedVars(i))) & rv & " to " & xFixedValues(i)
  288.             DoSet accessString(CLng(xFixedVars(i))) & rv, xFixedValues(i)
  289.         End If
  290.     Next
  291. End Sub
  292.  
  293. ' +++++++++++++++++++
  294. ' Private sub pSetVar
  295. ' +++++++++++++++++++
  296. ' sets a variable to the given value for calculation
  297. ' does not reset the SensDB
  298. ' if variable is a SensDB variable, assumes that SensDB is prepared for receiving the variable
  299. ' used in regression calculations
  300. Private Sub pSetVar(accstr As String, value As Double)
  301.     Dim rv As String
  302.     If xUseRawValues Then rv = ".RAWVAL"
  303.     If IsNumeric(accstr) Then
  304.         Debug.Print "SET " & accessString(osInputVariable.[_Sens DB]) & ".Sens[" & CStr(pIndexFromSensVar(CLng(accstr))) & "].Vals[0]" & rv & " to " & value
  305.         DoSet accessString(osInputVariable.[_Sens DB]) & ".Sens[" & CStr(pIndexFromSensVar(CLng(accstr))) & "].Vals[0]" & rv, value
  306.     ElseIf accstr <> "N/A" Then
  307.         Debug.Print "SET " & accstr & rv & " to " & value
  308.         DoSet accstr & rv, value
  309.     End If
  310. End Sub
  311.  
  312. ' +++++++++++++++++++++
  313. ' Private function pGet
  314. ' +++++++++++++++++++++
  315. ' Performs the DoGet function, with the raw value if needed
  316. Private Function pGet(accstr As String) As String
  317.     If xUseRawValues Then
  318.         Debug.Print "GET " & accstr & ".RAWVAL"
  319.         pGet = DoGet(accstr & ".RAWVAL")
  320.     Else
  321.         Debug.Print "GET " & accstr
  322.         pGet = DoGet(accstr)
  323.     End If
  324. End Function
  325.  
  326. ' ++++++++++++++++++++++++
  327. ' Private sub pResetSensDB
  328. ' ++++++++++++++++++++++++
  329. ' Resets the sensitivity database
  330. Private Sub pResetSensDB()
  331.     Dim accstr As String
  332.     accstr = accessString(osInputVariable.[_Sens DB]) & ".Clear"
  333.     Debug.Print "SET " & accstr & " to 1"
  334.     DoSet accstr, 1
  335. End Sub
  336.  
  337.  
  338. ' ###############################################
  339. ' ################ PROPERTIES ###################
  340. ' ###############################################
  341.  
  342.  
  343. ' +++++++++++++++++++++++++++++++
  344. ' Public property calculationType
  345. ' +++++++++++++++++++++++++++++++
  346. ' defines what calculation is going to be done
  347. ' defaults to System, has getter and a setter
  348. Public Property Get calculationType() As osCalculationType
  349.     calculationType = xCalculationType
  350. End Property
  351. Public Property Let calculationType(RHS As osCalculationType)
  352.     xCalculationType = RHS
  353. End Property
  354.  
  355. ' ++++++++++++++++++++++++++++++++++
  356. ' Public property resetSensitivities
  357. ' ++++++++++++++++++++++++++++++++++
  358. ' defines whether the sensDB is cleared every time
  359. ' defaults to true, has getter and setter
  360. Public Property Get resetSensitivities() As Boolean
  361.     resetSensitivities = xResetSensitivities
  362. End Property
  363. Public Property Let resetSensitivities(RHS As Boolean)
  364.     xResetSensitivities = RHS
  365. End Property
  366.  
  367. ' ++++++++++++++++++++++++++++++++++++
  368. ' Public property rememberSetVariables
  369. ' ++++++++++++++++++++++++++++++++++++
  370. ' defines whether the set variables are remembered or cleared after calc
  371. ' defaults to true, has getter and setter
  372. Public Property Get rememberSetVariables() As Boolean
  373.     rememberSetVariables = xRememberSetVariables
  374. End Property
  375. Public Property Let rememberSetVariables(RHS As Boolean)
  376.     xRememberSetVariables = RHS
  377. End Property
  378.  
  379. ' ++++++++++++++++++++++++++++
  380. ' Public property useRawValues
  381. ' ++++++++++++++++++++++++++++
  382. ' defines whether the all calls are done using Raw Values
  383. ' (both doSet and doGet)
  384. Public Property Get useRawValues() As Boolean
  385.     useRawValues = xUseRawValues
  386. End Property
  387. Public Property Let useRawValues(RHS As Boolean)
  388.     xUseRawValues = RHS
  389. End Property
  390.  
  391. ' +++++++++++++++++++++++++
  392. ' Public property fluidType
  393. ' +++++++++++++++++++++++++
  394. ' read only. Returns the fluid type of the PROSPER model
  395. Public Property Get fluidType() As osFluidType
  396.     If xFluidType < 0 Then pGetFluidType
  397.     fluidType = xFluidType
  398. End Property
  399.  
  400. ' ++++++++++++++++++++++++++++++++
  401. ' Public property regressionStatus
  402. ' ++++++++++++++++++++++++++++++++
  403. ' read only. exhibits the regression status after a regression call
  404. Public Property Get regressionStatus() As osRegressionStatus
  405.     regressionStatus = xRegressionStatus
  406. End Property
  407.  
  408.  
  409. ' #########################################################
  410. ' ################ REGRESSION FUNCTIONS ###################
  411. ' #########################################################
  412.  
  413. ' ++++++++++++++++++++
  414. ' Public function find
  415. ' ++++++++++++++++++++
  416. ' Regression Function
  417. ' Will try to match the desired objective variable to a target, with the specified precision
  418. ' by changing an input variable in PROSPER
  419. ' Precision defaults to 2% of target
  420. ' Works best for monotonic series (i.e. no local extremes)
  421. ' Needs the extremes to be in either side of the desired value
  422. ' Returns the matched value & updates the regressionStatus property of this object
  423. ' As all regression algorithms, this can be improved. If you want to contribute,
  424. ' see contact details in www.SimpleOpenServer.com
  425. Function find(valueOf As osInputVariable, thatMakes As osSolutionVariable, equalTo As Double, betweenValue As Double, andValue As Double, Optional precision As Variant) As Double
  426.    
  427.     If IsMissing(precision) Then precision = 0.02 * Abs(equalTo)
  428.  
  429.     Dim accstr As String, x0 As Double, x1 As Double, x2 As Double, y0 As Double, y1  As Double, y2 As Double, dx As Double, f As Double, loops As Integer
  430.     accstr = accessString(CLng(valueOf))
  431.    
  432.     x0 = betweenValue
  433.     setVar valueOf, x0
  434.     calculate
  435.     y0 = solution(thatMakes) - equalTo
  436.    
  437.     x2 = andValue
  438.     pSetVar accstr, x2
  439.     pMakeCalculation
  440.     y2 = solution(thatMakes) - equalTo
  441.    
  442.     f = y0 / (y0 - y2)
  443.    
  444.     If f < 0 Or f > 1 Then
  445.         ' Solution does not fall between extremes
  446.        xRegressionStatus = [Solution Not Found In Range]
  447.         If f < 0 Then
  448.             find = x0
  449.         Else
  450.             find = x2
  451.         End If
  452.     Else
  453.         ' Solution falls between extremes, start regression
  454.        
  455.         x1 = (x2 - x0) * f + x0
  456.         pSetVar accstr, x1
  457.         pMakeCalculation
  458.         y1 = solution(thatMakes) - equalTo
  459.        
  460.         Do While Abs(y1) > precision And loops <= 8
  461.        
  462.             If Math.Sgn(y1) = Math.Sgn(y0) Then
  463.                 ' Sigo con x1 y x2
  464.                x0 = x1
  465.                 y0 = y1
  466.             Else
  467.                 ' Sigo con x0 y x1
  468.                x2 = x1
  469.                 y2 = y1
  470.             End If
  471.            
  472.             f = y0 / (y0 - y2)
  473.             x1 = (x2 - x0) * f + x0
  474.             pSetVar accstr, x1
  475.             pMakeCalculation
  476.             y1 = solution(thatMakes) - equalTo
  477.        
  478.         Loop
  479.         If loops > 8 Then
  480.             xRegressionStatus = [Loops Exceeded]
  481.         Else
  482.             xRegressionStatus = Converged
  483.         End If
  484.         find = x1
  485.     End If
  486.    
  487. End Function
  488.  
  489. ' +++++++++++++++++++++
  490. ' Public function match
  491. ' +++++++++++++++++++++
  492. ' Regression Function
  493. ' Will try to match the desired vector, with the specified precision
  494. ' by changing an input variable in PROSPER
  495. ' Precision defaults to 2% of target
  496. ' As all regression algorithms, this can be improved. If you want to contribute,
  497. ' see contact details in www.SimpleOpenServer.com
  498. Function match(curve As Long, toPoints As Vector, byChanging As osInputVariable, betweenValue As Double, andValue As Double, Optional precision As Variant) As Double
  499.  
  500.     Dim X(4) As Double, Y(4) As Double, i As Integer, accstr As String, loopCount As Integer, x_min As Double, x_min_old As Double, estimationChange As Double, y_min As Double, y_min_old As Double, theVector As New Vector
  501.     accstr = accessString(CLng(byChanging))
  502.    
  503.     loopCount = 0
  504.     X(0) = betweenValue
  505.     X(4) = andValue
  506.     y_min = -1000
  507.    
  508.     ' Calcular los 5 puntos
  509.    
  510.     ' Calculo el 1ro
  511.    setVar byChanging, X(0)
  512.     calculate
  513.     Set theVector = Me.Vector(curve)
  514.     Y(0) = theVector.MSE(toPoints)
  515.    
  516.     ' Calculo los otros 4
  517.    For i = 1 To 4
  518.         X(i) = X(0) + (X(4) - X(0)) * i / 4
  519.         pSetVar accstr, X(i)
  520.         pMakeCalculation
  521.         Set theVector = Me.Vector(Vector)
  522.         Y(i) = theVector.MSE(toPoints)
  523.     Next
  524.    
  525.     GoTo 1
  526.    
  527.     Do
  528.         x_min_old = x_min
  529.    
  530.         ' Calculo los 3 pts que faltan
  531.        For i = 1 To 3
  532.             X(i) = X(0) + (X(4) - X(0)) * i / 4
  533.             pSetVar accstr, X(i)
  534.             pMakeCalculation
  535.             Set theVector = Me.Vector(Vector)
  536.             Y(i) = theVector.MSE(toPoints)
  537.         Next
  538.    
  539. 1
  540.         ' Find the min
  541.        i = 1
  542.         Do
  543.             If Y(i) > Y(i - 1) Then Exit Do
  544.             i = i + 1
  545.         Loop Until i = 5
  546.         i = i - 1
  547.        
  548.         Dim coeffs As Variant
  549.         If i = 0 Then
  550.             i = 1
  551.         ElseIf i = 4 Then
  552.             i = 3
  553.         End If
  554.         coeffs = pFitQuad(X(i - 1), Y(i - 1), X(i), Y(i), X(i + 1), Y(i + 1))
  555.         ' Prepare array for next run
  556.        X(0) = X(i - 1)
  557.         Y(0) = Y(i - 1)
  558.         X(4) = X(i + 1)
  559.         Y(4) = Y(i + 1)
  560.        
  561.         If coeffs(0) < 0 Then
  562.             ' Tenemos un MAXIMO en vez de MINIMO.
  563.            ' No se encontro resultado
  564.            xRegressionStatus = [No Solution Found]
  565.             match = -1
  566.             Exit Function
  567.         Else
  568.             x_min = -coeffs(1) / 2 / coeffs(0)
  569.             If x_min > X(4) Or x_min < X(0) Then
  570.                 ' El minimo esta afuera
  571.                xRegressionStatus = [Solution Not Found In Range]
  572.                 match = X(0)
  573.                 If Y(4) < Y(0) Then match = X(4)
  574.                 Exit Function
  575.             Else
  576.                 If y_min = -1000 Then
  577.                     y_min_old = Y(0)
  578.                     i = 1
  579.                     Do
  580.                         If Y(i) < Y(i - 1) Then y_min_old = Y(i)
  581.                         i = i + 1
  582.                     Loop Until i = 5
  583.                     If IsMissing(precision) Then precision = 0.02
  584.                 Else
  585.                     y_min_old = y_min
  586.                 End If
  587.                 pSetVar accstr, x_min
  588.                 pMakeCalculation
  589.                 y_min = theVector.MSE(toPoints)
  590.             End If
  591.         End If
  592.        
  593.         estimationChange = Abs(x_min - x_min_old) / x_min
  594.        
  595.         loopCount = loopCount + 1
  596.  
  597.     Loop While loopCount <= 3 And estimationChange > precision
  598.     If estimationChange > precision Then
  599.         xRegressionStatus = [Loops Exceeded]
  600.     Else
  601.         xRegressionStatus = Converged
  602.     End If
  603.     match = x_min
  604.  
  605. End Function
  606.  
  607.  
  608. ' ++++++++++++++++++++++++
  609. ' Public function maximize
  610. ' ++++++++++++++++++++++++
  611. ' Regression Function
  612. ' Will try to maximize the desired objective variable, with the specified precision
  613. ' by changing an input variable in PROSPER
  614. ' Precision defaults to 2% of target
  615. ' Unpredictable when having multiple maximi
  616. ' Not recommended for discontinuous curves
  617. ' As all regression algorithms, this can be improved. If you want to contribute,
  618. ' see contact details in www.SimpleOpenServer.com
  619. Function maximize(variable As osSolutionVariable, byChanging As osInputVariable, betweenValue As Double, andValue As Double, Optional precision As Variant) As Double
  620.  
  621.     Dim X(4) As Double, Y(4) As Double, i As Integer, accstr As String, loopCount As Integer, x_max As Double, y_max As Double, y_max_old As Double, coeffs As Variant
  622.     accstr = accessString(CLng(byChanging))
  623.     loopCount = 0
  624.     X(0) = betweenValue
  625.     X(4) = andValue
  626.     y_max = -1000
  627.    
  628.     ' Calcular los 5 puntos
  629.  
  630.     ' Calculo el 1ro, usando setVar y calculate
  631.    setVar byChanging, X(0)
  632.     calculate
  633.     Y(0) = CDbl(solution(variable))
  634.    
  635.     ' Calculo los otros 4, usando pSetVar y pMakeCalculation
  636.    For i = 1 To 4
  637.         X(i) = X(0) + (X(4) - X(0)) * i / 4
  638.         pSetVar accstr, X(i)
  639.         pMakeCalculation
  640.         Y(i) = CDbl(solution(variable))
  641.     Next
  642.    
  643.     GoTo 1
  644.    
  645.     Do
  646.    
  647.         ' Calculo los 3 pts que faltan
  648.        For i = 1 To 3
  649.             X(i) = X(0) + (X(4) - X(0)) * i / 4
  650.             pSetVar accstr, X(i)
  651.             pMakeCalculation
  652.             Y(i) = CDbl(solution(variable))
  653.         Next
  654.    
  655. 1
  656.         ' Busco el max
  657.        i = 1
  658.         Do
  659.             If Y(i) < Y(i - 1) Then Exit Do
  660.             i = i + 1
  661.         Loop Until i = 5
  662.         i = i - 1
  663.        
  664.         If i = 0 Then
  665.             i = 1
  666.         ElseIf i = 4 Then
  667.             i = 3
  668.         End If
  669.         coeffs = pFitQuad(X(i - 1), Y(i - 1), X(i), Y(i), X(i + 1), Y(i + 1))
  670.         ' Prepare array for next run
  671.        X(0) = X(i - 1)
  672.         Y(0) = Y(i - 1)
  673.         X(4) = X(i + 1)
  674.         Y(4) = Y(i + 1)
  675.        
  676.         If coeffs(0) > 0 Then
  677.             ' Tenemos un MINIMO en vez de MAXIMO.
  678.            ' No se encontro resultado
  679.            xRegressionStatus = [No Solution Found]
  680.             maximize = -1
  681.             Exit Function
  682.         Else
  683.             x_max = -coeffs(1) / 2 / coeffs(0)
  684.             If x_max > X(4) Or x_max < X(0) Then
  685.                 ' El maximo esta afuera
  686.                xRegressionStatus = [Solution Not Found In Range]
  687.                 maximize = X(0)
  688.                 If Y(4) > Y(0) Then maximize = X(4)
  689.                 Exit Function
  690.             Else
  691.                 If y_max = -1000 Then
  692.                     y_max_old = Y(0)
  693.                     i = 1
  694.                     Do
  695.                         If Y(i) > Y(i - 1) Then y_max_old = Y(i)
  696.                         i = i + 1
  697.                     Loop Until i = 5
  698.                     If IsMissing(precision) Then precision = 0.02 * y_max_old
  699.                 Else
  700.                     y_max_old = y_max
  701.                 End If
  702.                 pSetVar accstr, x_max
  703.                 pMakeCalculation
  704.                 y_max = CDbl(solution(variable))
  705.             End If
  706.         End If
  707.        
  708.         loopCount = loopCount + 1
  709.  
  710.     Loop While Abs(y_max_old - y_max) > precision And loopCount <= 3
  711.     If Abs(y_max_old - y_max) > precision Then
  712.         xRegressionStatus = [Loops Exceeded]
  713.     Else
  714.         xRegressionStatus = Converged
  715.     End If
  716.     maximize = x_max
  717. End Function
  718.  
  719. ' ++++++++++++++++++++++++
  720. ' Public function minimize
  721. ' ++++++++++++++++++++++++
  722. ' Regression Function
  723. ' Will try to minimize the desired objective variable, with the specified precision
  724. ' by changing an input variable in PROSPER
  725. ' Precision defaults to 2% of target
  726. ' Unpredictable when having multiple minimi
  727. ' Not recommended for discontinuous curves
  728. ' As all regression algorithms, this can be improved. If you want to contribute,
  729. ' see contact details in www.SimpleOpenServer.com
  730. Function minimize(variable As osSolutionVariable, byChanging As osInputVariable, betweenValue As Double, andValue As Double, Optional precision As Variant) As Double
  731.  
  732.     Dim X(4) As Double, Y(4) As Double, i As Integer, accstr As String, loopCount As Integer, x_min As Double, y_min As Double, y_min_old As Double
  733.     accstr = accessString(CLng(byChanging))
  734.     loopCount = 0
  735.     X(0) = betweenValue
  736.     X(4) = andValue
  737.     y_min = -1000
  738.    
  739.     ' Calcular los 5 puntos
  740.  
  741.     ' Calculo el 1ro
  742.    setVar byChanging, X(0)
  743.     calculate
  744.     Y(0) = CDbl(solution(variable))
  745.    
  746.     ' Calculo los otros 4
  747.    For i = 1 To 4
  748.         X(i) = X(0) + (X(4) - X(0)) * i / 4
  749.         pSetVar accstr, X(i)
  750.         pMakeCalculation
  751.         Y(i) = CDbl(solution(variable))
  752.     Next
  753.    
  754.     GoTo 1
  755.    
  756.     Do
  757.    
  758.         ' Calculo los 3 pts intermedios
  759.        For i = 1 To 3
  760.             X(i) = X(0) + (X(4) - X(0)) * i / 4
  761.             pSetVar accstr, X(i)
  762.             pMakeCalculation
  763.             Y(i) = CDbl(solution(variable))
  764.         Next
  765.    
  766. 1
  767.         ' Find the min
  768.        i = 1
  769.         Do
  770.             If Y(i) > Y(i - 1) Then Exit Do
  771.             i = i + 1
  772.         Loop Until i = 5
  773.         i = i - 1
  774.        
  775.         Dim coeffs As Variant
  776.         If i = 0 Then
  777.             i = 1
  778.         ElseIf i = 4 Then
  779.             i = 3
  780.         End If
  781.         coeffs = pFitQuad(X(i - 1), Y(i - 1), X(i), Y(i), X(i + 1), Y(i + 1))
  782.         ' Prepare array for next run
  783.        X(0) = X(i - 1)
  784.         Y(0) = Y(i - 1)
  785.         X(4) = X(i + 1)
  786.         Y(4) = Y(i + 1)
  787.        
  788.         If coeffs(0) < 0 Then
  789.             ' Tenemos un MAXIMO en vez de MINIMO.
  790.            ' No se encontro resultado
  791.            xRegressionStatus = [No Solution Found]
  792.             minimize = -1
  793.             Exit Function
  794.         Else
  795.             x_min = -coeffs(1) / 2 / coeffs(0)
  796.             If x_min > X(4) Or x_min < X(0) Then
  797.                 ' El maximo esta afuera
  798.                xRegressionStatus = [Solution Not Found In Range]
  799.                 minimize = X(0)
  800.                 If Y(4) < Y(0) Then minimize = X(4)
  801.                 Exit Function
  802.             Else
  803.                 If y_min = -1000 Then
  804.                     y_min_old = Y(0)
  805.                     i = 1
  806.                     Do
  807.                         If Y(i) < Y(i - 1) Then y_min_old = Y(i)
  808.                         i = i + 1
  809.                     Loop Until i = 5
  810.                     If IsMissing(precision) Then precision = 0.02 * y_min_old
  811.                 Else
  812.                     y_min_old = y_min
  813.                 End If
  814.                 pSetVar accstr, x_min
  815.                 pMakeCalculation
  816.                 y_min = CDbl(solution(variable))
  817.             End If
  818.         End If
  819.        
  820.         loopCount = loopCount + 1
  821.  
  822.     Loop While Abs(y_min_old - y_min) > precision And loopCount <= 3
  823.     If Abs(y_min_old - y_min) > precision Then
  824.         xRegressionStatus = [Loops Exceeded]
  825.     Else
  826.         xRegressionStatus = Converged
  827.     End If
  828.     minimize = x_min
  829. End Function
  830.  
  831. ' ++++++++++++++++++++++++++++
  832. ' Public function rateOfChange
  833. ' ++++++++++++++++++++++++++++
  834. ' Will evaluate the rate of change of one variable
  835. ' when changing another, around a center point (atValue)
  836. Function rateOfChange(of As osSolutionVariable, whenChanging As osInputVariable, atValue As Double)
  837.     ' Generar un rango de valores, segun el X
  838.    ' 3 valores. evaluar, sacar coeficientes quad y evaluar la derivada en el del medio
  839.    Dim X(2) As Double, Y(2) As Double, i As Integer, accstr As String, dx As Double, coeffs As Variant
  840.     dx = 0.02 * atValue
  841.     accstr = accessString(CLng(whenChanging))
  842.     X(0) = atValue - dx
  843.     X(1) = atValue
  844.     X(2) = atValue + dx
  845.    
  846.     ' Calcular los 3 puntos
  847.    i = 0
  848.     ' Calculo el 1ro
  849.    setVar whenChanging, X(i)
  850.     calculate
  851.     Y(i) = CDbl(solution(of))
  852.    
  853.     ' Calculo los otros 4
  854.    For i = 1 To 2
  855.         pSetVar accstr, X(i)
  856.         pMakeCalculation
  857.         Y(i) = CDbl(solution(of))
  858.     Next
  859.    
  860.     coeffs = pFitQuad(X(0), Y(0), X(1), Y(1), X(2), Y(2))
  861.    
  862.     rateOfChange = 2 * coeffs(0) * atValue + coeffs(1)
  863. End Function
  864.  
  865. ' +++++++++++++++++++++++++++++
  866. ' Private function accessString
  867. ' +++++++++++++++++++++++++++++
  868. ' Used for INPUT variables.
  869. ' returns the access string that corresponds to the variable and the
  870. ' calculation type that is being performed. Will return N/A if the
  871. ' variable is not enabled for the set calculation type
  872. Private Function accessString(osVariable As Long) As String
  873.     accessString = Array(Array("PROSPER.ANL.INF.WC", "PROSPER.ANL.INF.GOR", "PROSPER.ANL.INF.CGR", "N/A", "N/A", "1", "53", "3", "51", "2", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "PROSPER.ANL.INF.Sens.SensDB", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A"), _
  874.                          Array("PROSPER.ANL.SYS.WC", "PROSPER.ANL.SYS.GOR", "PROSPER.ANL.SYS.CGR", "PROSPER.ANL.SYS.WGR", "PROSPER.ANL.SYS.Pres", "1", "53", "3", "51", "2", "PROSPER.ANL.SYS.Tubing", "PROSPER.ANL.SYS.Pipe", "N/A", "N/A", "26", "334", "PROSPER.ANL.SYS.Sens.SensDB", "35", "37", "38", "41", "326", "22", "31", "29"), _
  875.                          Array("PROSPER.ANL.VL3.WC", "PROSPER.ANL.VL3.WC", "PROSPER.ANL.VL3.CGR", "PROSPER.ANL.VL3.WGR", "PROSPER.ANL.VL3.Pres", "N/A", "N/A", "N/A", "N/A", "N/A", "PROSPER.ANL.VL3.Tubing", "PROSPER.ANL.VL3.Pipe", "N/A", "N/A", "26", "334", "PROSPER.ANL.VL3.Sens.SensDB", "35", "37", "38", "41", "326", "22", "31", "29"), _
  876.                          Array("PROSPER.ANL.GRD.WC", "PROSPER.ANL.GRD.GOR", "PROSPER.ANL.GRD.CGR", "PROSPER.ANL.GRD.WGR", "PROSPER.ANL.GRD.Pres", "N/A", "N/A", "N/A", "N/A", "N/A", "PROSPER.ANL.GRD.Tubing", "PROSPER.ANL.GRD.Pipe", "PROSPER.ANL.GRD.Rate", "PROSPER.ANL.GRD.Pres", "26", "334", "PROSPER.ANL.GRD.Sens.SensDB", "35", "37", "38", "41", "326", "22", "31", "29")) _
  877.         (xCalculationType)(osVariable)
  878. End Function
  879.  
  880. ' ++++++++++++++++++++++++++++++++++++++++
  881. ' Private function accessString_osSolution
  882. ' ++++++++++++++++++++++++++++++++++++++++
  883. ' Used for SOLUTION variables
  884. ' returns the access string that corresponds to the variable.
  885. Private Function accessString_osSolution(osSolutionVar As Long) As String
  886.     accessString_osSolution = Array("Exists", "PROSPER.OUT.SYS.Results[#].Sol.LiqRate", "PROSPER.OUT.SYS.Results[#].Sol.OilRate", "PROSPER.OUT.SYS.Results[#].Sol.WatRate", "PROSPER.OUT.SYS.Results[#].Sol.GasRate", "PROSPER.OUT.SYS.Results[#].Sol.BHP", "PROSPER.OUT.SYS.Results[#].Sol.BHP", "PROSPER.OUT.SYS.Results[#].Sol.PRFRIC", "PROSPER.OUT.SYS.Results[#].Sol.PRSTAT", "PROSPER.OUT.SYS.Results[#].Sol.WHPressure", "PROSPER.OUT.SYS.Results[#].Sol.WHTemperature", "PROSPER.OUT.SYS.Results[#].Sol.FNPressure", "PROSPER.OUT.SYS.Results[#].Sol.FNTemperature", "PROSPER.OUT.SYS.Results[#].Sol.PIP", _
  887.     "PROSPER.OUT.SYS.Results[#].Sol.PDP", "PROSPER.OUT.SYS.Results[#].Sol.PumpAvRate", "PROSPER.OUT.SYS.Results[#].Sol.PumpHead", "PROSPER.OUT.SYS.Results[#].Sol.PumpPower", "PROSPER.OUT.SYS.Results[#].Sol.PumpEfficiency", "PROSPER.OUT.SYS.Results[#].Sol.MotorAmps", "PROSPER.OUT.SYS.Results[#].Sol.MotorPower") _
  888.         (osSolutionVar)
  889. End Function
  890.  
  891. ' ++++++++++++++++++++++++++++++++++++++++++
  892. ' Private function accessString_osRateVector
  893. ' ++++++++++++++++++++++++++++++++++++++++++
  894. ' Used for RATE VECTOR variables
  895. ' returns the access string that corresponds to the variable and the
  896. ' calculation type that is being performed. Will return N/A if the
  897. ' variable is not enabled for the set calculation type
  898. Private Function accessString_osRateVector(osVariable As Long) As String
  899.     accessString_osRateVector = Array(Array("PROSPER.OUT.INF.RESULTS[#].LiqRate[$]", "PROSPER.OUT.INF.RESULTS[#].OilRate[$]", "PROSPER.OUT.INF.RESULTS[#].WatRate[$]", "PROSPER.OUT.INF.RESULTS[#].GasRate[$]", "PROSPER.OUT.INF.RESULTS[#].IPRPres[$]", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A"), _
  900.                                       Array("PROSPER.OUT.SYS.RESULTS[#].LiqRate[$]", "PROSPER.OUT.SYS.RESULTS[#].OilRate[$]", "PROSPER.OUT.SYS.RESULTS[#].WatRate[$]", "PROSPER.OUT.SYS.RESULTS[#].GasRate[$]", "PROSPER.OUT.SYS.RESULTS[#].IPRPres[$]", "PROSPER.OUT.SYS.RESULTS[#].VLPPres[$]", "PROSPER.OUT.SYS.Results[#].PrFric[$]", "PROSPER.OUT.SYS.Results[#].PrStat[$]", "PROSPER.OUT.SYS.Results[#].PIP[$]", "PROSPER.OUT.SYS.Results[#].PDP[$]", "PROSPER.OUT.SYS.Results[#].POW[$]"), _
  901.                                       Array("PROSPER.OUT.VLP.RESULTS[#].LiqRate[$]", "PROSPER.OUT.VLP.RESULTS[#].OilRate[$]", "PROSPER.OUT.VLP.RESULTS[#].WatRate[$]", "PROSPER.OUT.VLP.RESULTS[#].GasRate[$]", "N/A", "PROSPER.OUT.VLP.RESULTS[#].VLPPres[$]", "PROSPER.OUT.VLP.Results[#].PrFric[$]", "PROSPER.OUT.VLP.Results[#].PrStat[$]", "PROSPER.OUT.VLP.Results[#].PIP[$]", "PROSPER.OUT.VLP.Results[#].PDP[$]", "PROSPER.OUT.VLP.Results[#].POW[$]")) _
  902.         (xCalculationType)(osVariable)
  903. End Function
  904.  
  905. ' +++++++++++++++++++++++++++++++++++++++++++
  906. ' Private function accessString_osDepthVector
  907. ' +++++++++++++++++++++++++++++++++++++++++++
  908. ' Used for DEPTH VECTOR variables
  909. ' returns the access string that corresponds to the variable and the
  910. ' calculation type that is being performed. Will return N/A if the
  911. ' variable is not enabled for the set calculation type
  912. Private Function accessString_osDepthVector(osVariable As Long) As String
  913.     accessString_osDepthVector = Array("PROSPER.OUT.GRD.RESULTS[i][j][k].LABEL[$]", "PROSPER.OUT.GRD.RESULTS[i][j][k].MSD[$]", "PROSPER.OUT.GRD.RESULTS[i][j][k].TVD[$]", "PROSPER.OUT.GRD.RESULTS[i][j][k].PRES[$]", "PROSPER.OUT.GRD.RESULTS[i][j][k].TEMP[$]", "PROSPER.OUT.GRD.RESULTS[i][j][k].GRAD[$]", "PROSPER.OUT.GRD.RESULTS[i][j][k].HOLDUP[$]", _
  914.     "PROSPER.OUT.GRD.RESULTS[i][j][k].REGIME[$]", "PROSPER.OUT.GRD.RESULTS[i][j][k].GRSTAT[$]", "PROSPER.OUT.GRD.RESULTS[i][j][k].GRFRIC[$]", "PROSPER.OUT.GRD.RESULTS[i][j][k].VLTOTL[$]", "PROSPER.OUT.GRD.RESULTS[i][j][k].VLTURN[$]") _
  915.         (osVariable)
  916. End Function
  917.  
  918. ' +++++++++++++++++++++++++++++
  919. ' Private function pFindInArray
  920. ' +++++++++++++++++++++++++++++
  921. ' returns the first occurrance of "what" in "inArray"
  922. ' returns -1 otherwhise (e.g. inArray is not an array or not found)
  923. Private Function pFindInArray(what As Variant, inArray As Variant) As Long
  924.     On Error GoTo err:
  925.     Dim i As Long
  926.     For i = 0 To UBound(inArray)
  927.         If inArray(i) = what Then Exit For
  928.     Next
  929.     If i > UBound(inArray) Then
  930. err:
  931.         pFindInArray = -1
  932.     Else
  933.         pFindInArray = i
  934.     End If
  935. End Function
  936.  
  937. ' +++++++++++++++++++++++++
  938. ' Private function pFitQuad
  939. ' +++++++++++++++++++++++++
  940. ' given three points 1,2,3: fits them using a quadratic function ax2 + bx + c
  941. ' returns [ a, b, c ]
  942. Private Function pFitQuad(x1 As Double, y1 As Double, x2 As Double, y2 As Double, x3 As Double, y3 As Double) As Variant
  943.     Dim result(2), X(1 To 3, 1 To 3) As Double, Y(1 To 3, 1 To 1) As Double, c
  944.     X(1, 1) = 1
  945.     X(1, 2) = x1
  946.     X(1, 3) = x1 * x1
  947.     X(2, 1) = 1
  948.     X(2, 2) = x2
  949.     X(2, 3) = x2 * x2
  950.     X(3, 1) = 1
  951.     X(3, 2) = x3
  952.     X(3, 3) = x3 * x3
  953.     Y(1, 1) = y1
  954.     Y(2, 1) = y2
  955.     Y(3, 1) = y3
  956.     c = Application.MMult(Application.MInverse(X()), Y())
  957.     result(0) = c(3, 1)
  958.     result(1) = c(2, 1)
  959.     result(2) = c(1, 1)
  960.     pFitQuad = result
  961. End Function
  962.  
  963. ' ++++++++++++++++++++++++++++++++++
  964. ' Private function pIndexFromSensVar
  965. ' ++++++++++++++++++++++++++++++++++
  966. ' Index function to change the Sens Var number to a sens var index,
  967. ' due to the unexplicable logic behind sens vars and sens values in PROSPER.
  968. Private Function pIndexFromSensVar(num As Long) As Long
  969.     Select Case num
  970.     Case Is = 1
  971.     pIndexFromSensVar = 1
  972.     Case Is = 2
  973.     pIndexFromSensVar = 27
  974.     Case Is = 3
  975.     pIndexFromSensVar = 3
  976.     Case Is = 22
  977.     pIndexFromSensVar = 138
  978.     Case Is = 26
  979.     pIndexFromSensVar = 144
  980.     Case Is = 29
  981.     pIndexFromSensVar = 142
  982.     Case Is = 31
  983.     pIndexFromSensVar = 140
  984.     Case Is = 35
  985.     pIndexFromSensVar = 148
  986.     Case Is = 37
  987.     pIndexFromSensVar = 150
  988.     Case Is = 38
  989.     pIndexFromSensVar = 151
  990.     Case Is = 41
  991.     pIndexFromSensVar = 157
  992.     Case Is = 51
  993.     pIndexFromSensVar = 7
  994.     Case Is = 53
  995.     pIndexFromSensVar = 2
  996.     Case Is = 326
  997.     pIndexFromSensVar = 187
  998.     Case Is = 334
  999.     pIndexFromSensVar = 195
  1000.     End Select
  1001. End Function
Advertisement
Add Comment
Please, Sign In to add comment