def allProps(clsEOS, dicSAM, clsIO, clsUNI): iERR = 0 nComp = clsEOS.NC nUser = clsEOS.NU nSplt = clsEOS.NP nSamp = clsEOS.NS print("allProps: Attempting to assign Component Properties") #-- Find the type (Library or SCN) of first Nc-1 components --------- for iC in range(nUser - 1): cName = clsEOS.gPP("CN", iC) typC = typeC.get(cName) if typC == None: print("allProps: Component ", iC + 1, cName, " is not Library or SCN - Error") iERR = -1 return iERR #print("iC,cNam,typC ",iC,cName,typC) #== Library Components ================================================ if typC == 'L': isLibComp(iC, cName, clsEOS) #== SCN Components ==================================================== elif typC == 'S': #-- SCN Component molWt = scnMW[cName] heavyComp(molWt, -1.0, iC, clsEOS) print( "Component ({:2d}) = {:4s} is assumed to be a SCN - Properties Assigned/Calculated" .format(iC + 1, cName)) #== Not Library or SCN ================================================ else: print("Component Name ", cName, " Not Recognised - Error") iERR = -1 #======================================================================= # Process the Plus Fraction(s) # If more than one sample, split using Whitson Quadrature Method #======================================================================= #-- Mole Weight of Penultimate Component: 'Last' component = nComp-1 -- cPlus = clsEOS.gPP("CN", nUser - 1) #-- Name of the User Plus Fraction if nSamp > 1 or nSplt > 1: print( "Component ({:2d}) = {:4s} is Plus Fraction to be Split into {:1d} Pseudos" .format(nUser, cPlus, nSplt)) iERR = splitPlus(dicSAM, clsEOS) if iERR < 0: return iERR print("Plus Fraction Splitting Completed") else: molWt = dicSAM[0].mPlus specG = dicSAM[0].sPlus print( "Component ({:2d}) = {:4s} is Plus Fraction with No Split Requested - Properties Calculated" .format(nUser + 1, cPlus)) heavyComp(molWt, specG, nUser - 1, clsEOS) #======================================================================= # Sort the Binary Interaction Parameters #======================================================================= nComp = clsEOS.NC #print("compProps: Set BICs, N = ",nComp) assignBIPs(clsEOS) print("Binary Interaction Parameters (BIPs) Assigned/Calculated") #======================================================================== # Do we need to sort the components? Most to Least Volatility #======================================================================== clsEOS, dicSAM = sortComponents(clsEOS, dicSAM) #======================================================================== # Output the data #======================================================================== sTit = "Initialisation" WO.outputProps(clsIO, clsEOS, dicSAM, sTit) #======================================================================== # Write Fluid Description to the SAV file #======================================================================== WO.outputSave(sTit, clsEOS, dicSAM, clsIO) #====================================================================== # Generate (Approximate) Phase Plots #====================================================================== CP.allSamplesPhasePlot(clsEOS, dicSAM, clsIO) #====================================================================== # End of Routine #====================================================================== return iERR
def readDef(clsIO, dicSAM, clsUNI): iERR = 0 iCnt = 0 fInP = clsIO.fInP fOut = clsIO.fOut macEPS = calcMacEPS() #-- Compute Machine Epsilon #--------------------------------------------------------------------- # Parse Input File Line by Line #--------------------------------------------------------------------- for curL in fInP: iCnt += 1 #-- Current Line in curL; split into List tokS tokS = curL.split() nTok = len(tokS) #-- Blank or Comment? ----------------------------------------------- if nTok == 0: #-- Blank line pass else: if tokS[0][:2] == "--": pass elif tokS[0][:4].upper() == "ENDD": break elif tokS[0][:3].upper() == "DEB": iERR = RE.readDebug(clsIO) elif tokS[0].upper() == "EOS": #-- Equation of State ----------------------------------------------- EOS = tokS[1].upper() clsEOS = classEoS(EOS) print("Equation of State Specified as ", EOS) sCom = "--" WO.outputHeader(fOut, sCom, clsIO) WO.outputEOS(fOut, sCom, clsIO, clsEOS) elif tokS[0].upper() == "NCOMP": nComp = int(tokS[1]) clsEOS.NC = nComp clsEOS.setNComp(nComp) #-- Dimension the Arrays elif tokS[0].upper() == "NSAMP": nSamp = int(tokS[1]) clsEOS.NS = nSamp elif tokS[0].upper() == "PROPS": curL = next(fInP) #-- Property Names curL = next(fInP) #-- Property Units for iC in range(nComp): curL = next(fInP) tokS = curL.split() nTok = len(tokS) if nTok != 17: print("DEFINE PROPS: Expecting 17 Columns, Only ", nTok, " Read") iERR = -1 break sN = tokS[0] Mw = float(tokS[1]) Tc = float(tokS[2]) Pc = float(tokS[3]) Vc = float(tokS[4]) Zc = float(tokS[5]) AF = float(tokS[6]) Tb = float(tokS[7]) SG = float(tokS[8]) PA = float(tokS[9]) SS = float(tokS[10]) MA = float(tokS[11]) MB = float(tokS[12]) CA = float(tokS[13]) CB = float(tokS[14]) CC = float(tokS[15]) CD = float(tokS[16]) clsEOS.sPP("CN", iC, sN) clsEOS.sPP("MW", iC, Mw) clsEOS.sPP("TC", iC, Tc) clsEOS.sPP("PC", iC, Pc) clsEOS.sPP("VC", iC, Vc) clsEOS.sPP("ZC", iC, Zc) clsEOS.sPP("AF", iC, AF) clsEOS.sPP("TB", iC, Tb) clsEOS.sPP("SG", iC, SG) clsEOS.sPP("PA", iC, PA) clsEOS.sPP("SS", iC, SS) clsEOS.sPP("MA", iC, MA) clsEOS.sPP("MB", iC, MB) clsEOS.sPP("CA", iC, CA) clsEOS.sPP("CB", iC, CB) clsEOS.sPP("CC", iC, CC) clsEOS.sPP("CD", iC, CD) elif tokS[0].upper() == "BIP": curL = next(fInP) #-- Component Names for iC in range(nComp): curL = next(fInP) tokS = curL.split() nTok = len(tokS) if nTok != nComp + 1: print("DEFINE BIP: Expecting ", nComp + 1, " Columns, Only ", nTok, " Read") iERR = -1 break iTok = 1 while iTok < nTok: KIJ = float(tokS[iTok]) clsEOS.sIJ(iC, iTok - 1, KIJ) iTok += 1 elif tokS[0].upper() == "SAMPLES": curL = next(fInP) #-- Sample Names tokS = curL.split() nTok = len(tokS) for iSamp in range(nSamp): sName = tokS[iSamp + 1] csSAM = RS.classSample(sName) dicSAM[iSamp] = csSAM dicSAM[iSamp].setNComp(nComp) for iC in range(nComp): curL = next(fInP) tokS = curL.split() if nTok != nSamp + 1: print("DEFINE SAMPLES: Expecting ", nSamp + 1, " Columns, Only ", nTok, " Read") iERR = -1 break for iSamp in range(nSamp): ZI = float(tokS[iSamp + 1]) if ZI < macEPS: ZI = 1.0E-20 #-- Protect against Z = 0 dicSAM[iSamp].sZI(iC, ZI) else: pass #======================================================================== # Has any slop crept into the sample definitions? #======================================================================== for iSamp in range(nSamp): sumT = 0.0 for iC in range(nComp): sumT = sumT + dicSAM[iSamp].gZI(iC) sumT = 1.0 / sumT for iC in range(nComp): zI = sumT * dicSAM[iSamp].gZI(iC) dicSAM[iSamp].sZI(iC, zI) #== Back-calculate the C7+ Properties ================================= backCalcPlusFracProps(clsEOS, dicSAM) #======================================================================== # Do we need to sort the components? Most to Least Volatility #======================================================================== clsEOS, dicSAM = CR.sortComponents(clsEOS, dicSAM) #======================================================================== # Output the data #======================================================================== sTit = "Initialisation from a saved DEFINE" WO.outputProps(clsIO, clsEOS, dicSAM, sTit) #======================================================================== # Write Fluid Description to the SAV file #======================================================================== WO.outputSave(sTit, clsEOS, dicSAM, clsIO) #====================================================================== # Generate (Approximate) Phase Plots #====================================================================== CP.allSamplesPhasePlot(clsEOS, dicSAM, clsIO) #== Return values ===================================================== return iERR, clsEOS, dicSAM
def readGroup(clsIO,clsEOS0,clsEOSG,dicSAM0,dicSAMG,dicEXP0,clsUNI) : print("Reading User Data for Grouping") iERR = 0 iLine = 0 nOld = clsEOS0.NC #-- "Old" Number of Components in "Old" Class nNew = 0 nTst = 0 iSam = 0 #-- By default, we will weight by Sample[0] qExp = False fInP = clsIO.fInP dicGRP = {} #-- Dictionary to hold the new Groups #== Loop over lines in the Input File ================================= for curL in fInP : iLine += 1 if iLine > 100 : print("Too Many Lines of GROUP Data - Error") iERR = -1 break tokS = curL.split() nTok = len(tokS) if nTok == 0 : pass #-- Blank line! elif tokS[0][:2] == "--" : pass #-- Comment! elif tokS[0][:4].upper() == "ENDG" : break #-- ENDGROUP => Exit elif tokS[0][:3].upper() == "DEB" : #-- DEBUG iERR = RG.readDebug(clsIO) if iERR < 0 : break elif tokS[0][:4].upper() == "RUNE" : qExp = True #-- Run Experiments elif tokS[0][:2].upper() == "SA" : #-- SAMPLE for weighting samNam = tokS[1] iSam = checkSamp4Grp(samNam,dicSAM0) if iSam < 0 : print("Sample ",samNam," Proposed for Weighting Not Found - Error") iERR = -1 return iERR else : #== Must be reading New Name and Old-Names ============================ newNam = tokS[0] clsGRP = classGRP(newNam) #-- Create the New Group dicGRP[nNew] = clsGRP #-- Add to the Dictionary of Groups nNew += 1 #-- Increment the Counter oldNam = [] iTok = 1 while iTok < nTok : oldNam.append(tokS[iTok]) nTst += 1 #-- Test the number of "old" comps iTok += 1 clsGRP.setOldNames(oldNam) #---------------------------------------------------------------------- # Process Data #---------------------------------------------------------------------- #print("nOld,nNew,nTst ",nOld,nNew,nTst) c*K = [False for i in range(nOld)] if nTst != nOld : print("Currently have ",nOld," Components defined: Only ",nTst," Read - Error") iERR = -1 return iERR,clsEOS0,dicSAM0,dicEXP0 for iNew in range(nNew) : oldNam = dicGRP[iNew].oldNam oldNum = [] nGrp = len(oldNam) for iGrp in range(nGrp) : sCom = oldNam[iGrp] iCom = checkComp4Grp(sCom,clsEOS0) if iCom < 0 : print("Old Component Name ",sCom," Not Found - Error") iERR = -1 return iERR,clsEOS0,dicSAM0,dicEXP0 else: oldNum.append(iCom) c*K[iCom] = True dicGRP[iNew].setOldNums(oldNum) #-- Do we have all 'old' components used? --------------------------- for iC in range(nOld) : if not c*K[iC] : sCom = clsEOS0.gPP("CN",iC) print("Component " + sCom + " Not Found Amongst 'Old' Components - Error") iERR = -1 return iERR,clsEOS0,dicSAM0,dicEXP0 #== Do we want experiments run before and after grouping? ============ if qExp : dicEXPG = deepcopy(dicEXP0) sExt = " - Before Grouping" CX.calcExps(sExt,clsEOS0,dicSAM0,dicEXP0,clsIO,clsUNI) #====================================================================== # Perform the Grouping #====================================================================== iERR = calcGroup(iSam,dicGRP,clsEOS0,clsEOSG,dicSAM0,dicSAMG) if iERR == 0 : print("Grouping Performed") else : print("Grouping Failed: Program Stopping") return iERR,clsEOS0,dicSAM0,dicEXP0 #-- Write New System to the Output File ----------------------------- sTit = "Grouping From " + str(nOld) + " Components To " + str(nNew) #WO.outputGroup(clsIO,nOld,nNew) WO.outputProps(clsIO,clsEOSG,dicSAMG,sTit) #-- Save the new EoS/Sample Definitions ----------------------------- sTit = "Grouping From " + str(nOld) + " Components To " + str(nNew) WO.outputSave(sTit,clsEOSG,dicSAMG,clsIO) #---------------------------------------------------------------------- # Re-run existing experiments? #---------------------------------------------------------------------- if qExp : sExt = " - After Grouping" for iExp in range(len(dicEXPG)) : dicEXPG[iExp].IsAct = True CX.calcExps(sExt,clsEOSG,dicSAMG,dicEXPG,clsIO,clsUNI) qReg = False GP.regPlots(clsIO,dicEXP0,dicEXPG,dicSAMG,qReg,clsUNI) #---------------------------------------------------------------------- # Perform deepcopy to put Grouped EOS/Samples into Main Sets #---------------------------------------------------------------------- clsEOS0 = deepcopy(clsEOSG) dicSAM0 = deepcopy(dicSAMG) if qExp : dicEXP0 = deepcopy(dicEXPG) #== End of Routine ==================================================== return iERR,clsEOS0,dicSAM0,dicEXP0
def runRegression(mIter, clsIO, clsEOS0, dicSAM0, dicEXP0, dicREG, qExp, clsUNI): #== Set Output File Name [rootName.reg] =============================== if not clsIO.qReg: pathReg = clsIO.patR + ".reg" fReg = open(pathReg, 'w') clsIO.setQREG(True) clsIO.setFREG(fReg) else: fReg = clsIO.fReg sCom = "--" WO.outputHeader(fReg, sCom, clsIO) WO.outputEOS(fReg, sCom, clsIO, clsEOS0) #== Number of Variables =============================================== nVar = len(dicREG) #-- Initial (normalised) variables ---------------------------------- xVec = NP.ones(nVar) #-------------------------------------------------------------------- # Run the experiments with the initial EoS and set of sample info #-------------------------------------------------------------------- runRegExps(clsIO, clsEOS0, dicSAM0, dicEXP0, qExp) #== Initial residuals vector ========================================== qWrt = True fReg.write("\n") fReg.write( "============================================================\n") fReg.write(" Regression Output: Initial Residuals\n") fReg.write( "============================================================\n") fReg.write("\n") ssq0, regI = calcResSSQ(qWrt, dicEXP0, qExp, clsIO) nReg = len(regI) #-- Number of items in Residual Vector iTer = 0 #print("iVar,ssqI {:2d}{:10.5f}".format(iTer,ssq0)) #== Take a (deep) copy of the EoS class and Samples dictionary ======== clsEOS1 = deepcopy(clsEOS0) dicSAM1 = deepcopy(dicSAM0) dicEXP1 = deepcopy(dicEXP0) #======================================================================== # Main Loop #======================================================================== qConv = False nIter = 1 while not qConv: #====================================================================== # Build Jacobian by perturbing each variable in turn #====================================================================== jacO = calcJaco(clsIO, dicREG, clsEOS0, clsEOS1, dicSAM0, dicSAM1, dicEXP1, qExp, xVec, regI) #====================================================================== # Calculate the Gradient and Hessian #====================================================================== Grad = NP.dot(jacO, regI) Hess = NP.dot(jacO, jacO.T) #-- Note Transpose! #====================================================================== # Calculate the update vector delX #====================================================================== delX = rotDisc(nIter, Grad, Hess, dicREG, dicSAM1, clsEOS1, clsIO) #writeVector("Grad ",Grad) #writeVector("xVec[B]",xVec) #writeVector("delX ",delX) #====================================================================== # Check if Variables Bounded? #====================================================================== delX, Grad = checkBounds(nIter, clsEOS0, dicREG, dicSAM0, xVec, delX, Grad, Hess, clsIO) #====================================================================== # Line Search #====================================================================== ssq1, xVec, regI = lineSearch(clsIO, dicREG, dicSAM0, dicSAM1, clsEOS0, clsEOS1, dicEXP1, qExp, ssq0, xVec, delX, Grad) #writeVector("xVec[A]",xVec) #====================================================================== # Progress in SSQ? #====================================================================== if abs((ssq1 - ssq0) / ssq1) < 1.0E-04: print("Regression converged!") qConv = True else: ssq0 = ssq1 nIter += 1 if nIter > mIter: print("Regression - Reached Max-Iterations = ", mIter) break #== Plot Before/After Results ========================================= qReg = True GP.regPlots(clsIO, dicEXP0, dicEXP1, dicSAM1, qReg, clsUNI) #====================================================================== # (Deep) copy the working EoS/Samples back to the main EoS/Samples #====================================================================== clsEOS0 = deepcopy(clsEOS1) dicSAM0 = deepcopy(dicSAM1) dicEXP0 = deepcopy(dicEXP1) #====================================================================== # Write Final Set of Residuals #====================================================================== fReg.write("\n") fReg.write( "============================================================\n") fReg.write(" Regression Output: Final Residuals\n") fReg.write( "============================================================\n") fReg.write("\n") ssq0, regI = calcResSSQ(qWrt, dicEXP0, qExp, clsIO) #====================================================================== # Write New EoS & Experiments to Print File #====================================================================== iERR, sTyp = regVarType(dicREG) if sTyp == "REG": sExt = "Regular EOS Variables" elif sTyp == "PLS": sExt = "Plus Fraction Variables" elif sTyp == "LBC": sExt = "LBC Viscosity Variables" sTit = "Regression Using " + sExt WO.outputProps(clsIO, clsEOS0, dicSAM0, sTit) #-- Only Print the Regession "Active" Experiments [qExp] ------------ nExp = len(dicEXP0) qSav = [True for i in range(nExp)] for iExp in range(nExp): qSav[iExp] = qExp[iExp] clsEXP0 = dicEXP0[iExp] clsEXP0.IsAct = qExp[iExp] #-- Print the Experiments ------------------------------------------- WO.outputExps(clsIO, dicEXP0, dicSAM0, clsUNI) #-- Restore the IsAct Flag ------------------------------------------ for iExp in range(nExp): clsEXP0 = dicEXP0[iExp] clsEXP0.IsAct = qSav[iExp] sTit = "Regression Using " + sTyp + " Variable Types" WO.outputSave(sTit, clsEOS0, dicSAM0, clsIO) return clsEOS0, dicSAM0, dicEXP0