Ejemplo n.º 1
0
    def __init__(self, visID, solDomain, solver):

        self.visType = "probe"
        self.visID = visID
        self.xLabel = "t (s)"

        self.probeNum = catchInput(solver.paramDict,
                                   "probeNum" + str(self.visID), -2) - 1
        assert (
            self.probeNum >=
            0), "Must provide positive integer probe number for probe" + str(
                self.visID)
        assert (self.probeNum < solver.numProbes), "probeNum" + str(
            self.visID) + " must correspond to a valid probe"

        super().__init__(solDomain, solver)

        # image file on disk
        visName = ""
        for visVar in self.visVar:
            visName += "_" + visVar
        figName = "probe" + visName + "_" + str(
            self.probeNum) + "_" + solver.simType + ".png"
        self.figFile = os.path.join(const.imageOutputDir, figName)

        # check that requested variables are being probed
        for visVar in self.visVar:
            assert (
                visVar
                in solver.probeVars), "Must probe " + visVar + " to plot it"
Ejemplo n.º 2
0
    def __init__(self, paramDict):
        super().__init__(paramDict)
        self.timeType = "implicit"
        self.subiterMax = catchInput(paramDict, "subiterMax",
                                     const.subiterMaxImpDefault)
        self.resTol = catchInput(paramDict, "resTol", const.l2ResTolDefault)

        # dual time-stepping, robustness controls
        self.dualTime = catchInput(paramDict, "dualTime", True)
        self.dtau = catchInput(paramDict, "dtau", const.dtauDefault)
        if (self.dualTime):
            self.adaptDTau = catchInput(paramDict, "adaptDTau", False)
        else:
            self.adaptDTau = False
        self.CFL = catchInput(
            paramDict, "CFL",
            const.CFLDefault)  # reference CFL for advective control of dtau
        self.VNN = catchInput(
            paramDict, "VNN", const.VNNDefault
        )  # von Neumann number for diffusion control of dtau
        self.refConst = catchInput(paramDict, "refConst",
                                   [None])  # constants for limiting dtau
        self.relaxConst = catchInput(paramDict, "relaxConst", [None])  #
Ejemplo n.º 3
0
	def __init__(self, gasDict):

		# gas composition
		self.numSpeciesFull     = int(gasDict["numSpecies"])				# total number of species in case
		self.molWeights         = gasDict["molWeights"].astype(realType)	# molecular weights, g/mol
		self.enthRef            = gasDict["enthRef"].astype(realType) 		# reference enthalpy, J/kg
		self.Cp                 = gasDict["Cp"].astype(realType)			# heat capacity at constant pressure, J/(kg-K)
		self.Pr                 = gasDict["Pr"].astype(realType)			# Prandtl number
		self.Sc                 = gasDict["Sc"].astype(realType)			# Schmidt number
		self.muRef              = gasDict["muRef"].astype(realType)			# reference dynamic viscosity for Sutherland model
		self.tempRef            = gasDict["tempRef"].astype(realType)		# reference temperature for Sutherland model, K

		# Arrhenius factors
		# TODO: modify these to allow for multiple global reactions
		self.nu                 = gasDict["nu"].astype(realType) 		# global reaction stoichiometric "forward" coefficients
		self.nuArr              = gasDict["nuArr"].astype(realType) 	# global reaction concentration exponents
		self.actEnergy          = float(gasDict["actEnergy"])			# global reaction Arrhenius activation energy, divided by RUniv, ?????
		self.preExpFact         = float(gasDict["preExpFact"]) 			# global reaction Arrhenius pre-exponential factor		

		# misc calculations
		self.RGas               = RUniv / self.molWeights 			# specific gas constant of each species, J/(K*kg)	
		self.molWeightNu        = self.molWeights * self.nu 
		self.suthLaw            = catchInput(gasDict, "suthLaw", False)

		# dealing with single-species option
		if (self.numSpeciesFull == 1):
			self.numSpecies	    = self.numSpeciesFull
		else:
			self.numSpecies     = self.numSpeciesFull - 1		# last species is not directly solved for

		self.massFracSlice  = np.arange(self.numSpecies)
		self.mwInv          = 1.0 / self.molWeights
		self.mwInvDiffs     = self.mwInv[self.massFracSlice] - self.mwInv[-1]
		self.CpDiffs        = self.Cp[self.massFracSlice] - self.Cp[-1]
		self.enthRefDiffs   = self.enthRef[self.massFracSlice] - self.enthRef[-1]

		self.numEqs         = self.numSpecies + 3			# pressure, velocity, temperature, and species transport

		# mass matrices for calculating viscosity and thermal conductivity mixing laws
		self.mixMassMatrix 		= np.zeros((self.numSpeciesFull, self.numSpeciesFull), dtype=realType)
		self.mixInvMassMatrix 	= np.zeros((self.numSpeciesFull, self.numSpeciesFull), dtype=realType)
		self.precompMixMassMatrices()
Ejemplo n.º 4
0
	def __init__(self, solDomain, solver):

		romDict = readInputFile(solver.romInputs)
		self.romDict = romDict

		# load model parameters
		self.romMethod 		= str(romDict["romMethod"])
		self.numModels 		= int(romDict["numModels"])
		self.latentDims 	= catchList(romDict, "latentDims", [0], lenHighest=self.numModels)
		modelVarIdxs 		= catchList(romDict, "modelVarIdxs", [[-1]], lenHighest=self.numModels)

		# check model parameters
		for i in self.latentDims: assert (i > 0), "latentDims must contain positive integers"
		if (self.numModels == 1):
			assert (len(self.latentDims) == 1), "Must provide only one value of latentDims when numModels = 1"
			assert (self.latentDims[0] > 0), "latentDims must contain positive integers"
		else:
			if (len(self.latentDims) == self.numModels):
				pass
			elif (len(self.latentDims) == 1):	
				print("Only one value provided in latentDims, applying to all models")
				sleep(1.0)
				self.latentDims = [self.latentDims[0]] * self.numModels
			else:
				raise ValueError("Must provide either numModels or 1 entry in latentDims")

		# load and check modelVarIdxs
		for modelIdx in range(self.numModels):
			assert (modelVarIdxs[modelIdx][0] != -1), "modelVarIdxs input incorrectly, probably too few lists"
		assert (len(modelVarIdxs) == self.numModels), "Must specify modelVarIdxs for every model"
		modelVarSum = 0
		for modelIdx in range(self.numModels):
			modelVarSum += len(modelVarIdxs[modelIdx])
			for modelVarIdx in modelVarIdxs[modelIdx]:
				assert (modelVarIdx >= 0), "modelVarIdxs must be non-negative integers"
				assert (modelVarIdx < solDomain.gasModel.numEqs), "modelVarIdxs must less than the number of governing equations"
		assert (modelVarSum == solDomain.gasModel.numEqs), ("Must specify as many modelVarIdxs entries as governing equations (" +
														str(modelVarSum) + " != " + str(solDomain.gasModel.numEqs) + ")")
		modelVarIdxsOneList = sum(modelVarIdxs, [])
		assert (len(modelVarIdxsOneList) == len(set(modelVarIdxsOneList))), "All entries in modelVarIdxs must be unique"
		self.modelVarIdxs = modelVarIdxs 

		# load and check model input locations
		self.modelDir 	= str(romDict["modelDir"])
		modelFiles = romDict["modelFiles"]
		self.modelFiles = [None] * self.numModels
		assert (len(modelFiles) == self.numModels), "Must provide modelFiles for each model"
		for modelIdx in range(self.numModels):
			inFile = os.path.join(self.modelDir, modelFiles[modelIdx])
			assert (os.path.isfile(inFile)), "Could not find model file at " + inFile
			self.modelFiles[modelIdx] = inFile

		# load standardization profiles, if they are required
		self.normSubConsIn 	= catchList(romDict, "normSubConsIn", [""])
		self.normFacConsIn 	= catchList(romDict, "normFacConsIn", [""])
		self.centConsIn 	= catchList(romDict, "centConsIn", [""])
		self.normSubPrimIn 	= catchList(romDict, "normSubPrimIn", [""])
		self.normFacPrimIn 	= catchList(romDict, "normFacPrimIn", [""])
		self.centPrimIn 	= catchList(romDict, "centPrimIn", [""])

		# load low-dimensional initial condition state, if desired
		self.loadInitCode(romDict)

		self.setModelFlags()

		self.adaptiveROM = catchInput(romDict, "adaptiveROM", False)

		# set up hyper-reduction, if necessary
		self.hyperReduc = catchInput(romDict, "hyperReduc", False)
		if (self.isIntrusive and self.hyperReduc):
			self.loadHyperReduc(solDomain, solver)

		# initialize models for domain
		self.modelList = [None] * self.numModels
		for modelIdx in range(self.numModels):

			if (self.romMethod == "linearGalerkinProj"):
				self.modelList[modelIdx] = linearGalerkinProj(modelIdx, self, solver, solDomain)
			elif (self.romMethod == "linearLSPGProj"):
				raise ValueError("linearLSPGProj ROM not implemented yet")
			elif (self.romMethod == "linearSPLSVTProj"):
				raise ValueError("linearSPLSVTProj ROM not implemented yet")
			elif (self.romMethod == "autoencoderGalerkinProjTF"):
				raise ValueError("autoencoderGalerkinProjTF ROM not implemented yet")
			elif (self.romMethod == "autoencoderLSPGProjTF"):
				raise ValueError("autoencoderLSPGProjTF ROM not implemented yet")
			elif (self.romMethod == "autoencoderSPLSVTProjTF"):
				raise ValueError("autoencoderSPLSVTProjTF ROM not implemented yet")
			elif (self.romMethod == "liftAndLearn"):
				raise ValueError("liftAndLearn ROM not implemented yet")
			elif (self.romMethod == "tcnNonintrusive"):
				raise ValueError("tcnNonintrusive ROM not implemented yet")
			else:
				raise ValueError("Invalid ROM method name: "+self.romMethod)

			# initialize state
			if self.initROMFromFile[modelIdx]:
				self.modelList[modelIdx].initFromCode(self.code0[modelIdx], solDomain, solver)
			else:
				self.modelList[modelIdx].initFromSol(solDomain, solver)
		
		solDomain.solInt.updateState(fromCons=self.targetCons)

		# get time integrator, if necessary
		# TODO: move this selection to an external function? This is repeated in solutionDomain
		# TODO: timeScheme should be specific to the romDomain, not the solver
		if self.hasTimeIntegrator:
			if (solver.timeScheme == "bdf"):
				self.timeIntegrator = bdf(solver.paramDict)
			elif (solver.timeScheme == "rkExp"):
				self.timeIntegrator = rkExplicit(solver.paramDict)
			else:
				raise ValueError("Invalid choice of timeScheme: "+solver.timeScheme)

			# initialize code history
			# TODO: this is necessary for non-time-integrated methods, e.g. TCN
			for model in self.modelList:
				model.codeHist = [model.code.copy()] * (self.timeIntegrator.timeOrder+1)

		else:
			self.timeIntegrator = None 	# TODO: this might be pointless
Ejemplo n.º 5
0
	def loadHyperReduc(self, solDomain, solver):
		"""
		Loads direct sampling indices and determines cell indices for calculating fluxes and gradients
		"""

		raise ValueError("Hyper-reduction temporarily out of commission for development")

		# TODO: add some explanations for what each index array accomplishes

		# load and check sample points
		sampFile = catchInput(self.romDict, "sampFile", "")
		assert (sampFile != ""), "Must supply sampFile if performing hyper-reduction"
		sampFile = os.path.join(self.modelDir, sampFile)
		assert (os.path.isfile(sampFile)), ("Could not find sampFile at " + sampFile)

		# NOTE: assumed that sample indices are zero-indexed
		solDomain.directSampIdxs = np.load(sampFile).flatten()
		solDomain.directSampIdxs = (np.sort(solDomain.directSampIdxs)).astype(np.int32)
		solDomain.numSampCells = len(solDomain.directSampIdxs)
		assert (solDomain.numSampCells <= solver.mesh.numCells), "Cannot supply more sampling points than cells in domain."
		assert (np.amin(solDomain.directSampIdxs) >= 0), "Sampling indices must be non-negative integers"
		assert (np.amax(solDomain.directSampIdxs) < solver.mesh.numCells), "Sampling indices must be less than the number of cells in the domain"
		assert (len(np.unique(solDomain.directSampIdxs)) == solDomain.numSampCells), "Sampling indices must be unique"

		# TODO: should probably shunt these over to a function for when indices get updated in adaptive method

		# compute indices for inviscid flux calculations
		# NOTE: have to account for fact that boundary cells are prepended/appended
		solDomain.fluxSampLIdxs = np.zeros(2 * solDomain.numSampCells, dtype=np.int32)
		solDomain.fluxSampLIdxs[0::2] = solDomain.directSampIdxs
		solDomain.fluxSampLIdxs[1::2] 	= solDomain.directSampIdxs + 1

		solDomain.fluxSampRIdxs = np.zeros(2 * solDomain.numSampCells, dtype=np.int32)
		solDomain.fluxSampRIdxs[0::2] = solDomain.directSampIdxs + 1
		solDomain.fluxSampRIdxs[1::2] 	= solDomain.directSampIdxs + 2

		# eliminate repeated indices
		solDomain.fluxSampLIdxs = np.unique(solDomain.fluxSampLIdxs)
		solDomain.fluxSampRIdxs = np.unique(solDomain.fluxSampRIdxs)
		solDomain.numFluxFaces  = len(solDomain.fluxSampLIdxs)

		# Roe average
		if (solver.spaceScheme == "roe"):
			zerosProf        = np.zeros((solDomain.gasModel.numEqs, solDomain.numFluxFaces), dtype=const.realType)
			solDomain.solAve = solutionPhys(solDomain, zerosProf, zerosProf, solDomain.numFluxFaces, solver)

		# to slice flux when calculating RHS
		solDomain.fluxRHSIdxs = np.zeros(solDomain.numSampCells, np.int32)
		for i in range(1,solDomain.numSampCells):
			if (solDomain.directSampIdxs[i] == (solDomain.directSampIdxs[i-1]+1)):
				solDomain.fluxRHSIdxs[i] = solDomain.fluxRHSIdxs[i-1] + 1
			else:
				solDomain.fluxRHSIdxs[i] = solDomain.fluxRHSIdxs[i-1] + 2

		# compute indices for gradient calculations
		# NOTE: also need to account for prepended/appended boundary cells
		# TODO: generalize for higher-order schemes
		if (solver.spaceOrder > 1):
			if (solver.spaceOrder == 2):
				solDomain.gradIdxs = np.concatenate((solDomain.directSampIdxs+1, solDomain.directSampIdxs, solDomain.directSampIdxs+2))
				solDomain.gradIdxs = np.unique(solDomain.gradIdxs)
				# exclude left neighbor of inlet, right neighbor of outlet
				if (solDomain.gradIdxs[0] == 0): solDomain.gradIdxs = solDomain.gradIdxs[1:]
				if (solDomain.gradIdxs[-1] == (solver.mesh.numCells+1)):  solDomain.gradIdxs = solDomain.gradIdxs[:-1]
				solDomain.numGradCells = len(solDomain.gradIdxs)

				# neighbors of gradient cells
				solDomain.gradNeighIdxs = np.concatenate((solDomain.gradIdxs-1, solDomain.gradIdxs+1))
				solDomain.gradNeighIdxs = np.unique(solDomain.gradNeighIdxs)
				# exclude left neighbor of inlet, right neighbor of outlet
				if (solDomain.gradNeighIdxs[0] == -1): solDomain.gradNeighIdxs = solDomain.gradNeighIdxs[1:]
				if (solDomain.gradNeighIdxs[-1] == (solver.mesh.numCells+2)):  solDomain.gradNeighIdxs = solDomain.gradNeighIdxs[:-1]

				# indices of gradIdxs in gradNeighIdxs
				_, _, solDomain.gradNeighExtract = np.intersect1d(solDomain.gradIdxs, solDomain.gradNeighIdxs, return_indices=True)

				# indices of gradIdxs in fluxSampLIdxs and fluxSampRIdxs, and vice versa
				_, solDomain.gradLExtract, solDomain.fluxLExtract = np.intersect1d(solDomain.gradIdxs, solDomain.fluxSampLIdxs, return_indices=True)
				_, solDomain.gradRExtract, solDomain.fluxRExtract = np.intersect1d(solDomain.gradIdxs, solDomain.fluxSampRIdxs, return_indices=True)

			else:
				raise ValueError("Sampling for higher-order schemes not implemented yet")

		# copy indices for ease of use
		self.numSampCells = solDomain.numSampCells
		self.directSampIdxs = solDomain.directSampIdxs

		# paths to hyper-reduction files (unpacked later)
		hyperReducFiles = self.romDict["hyperReducFiles"]
		self.hyperReducFiles = [None] * self.numModels
		assert (len(hyperReducFiles) == self.numModels), "Must provide hyperReducFiles for each model"
		for modelIdx in range(self.numModels):
			inFile = os.path.join(self.modelDir, hyperReducFiles[modelIdx])
			assert (os.path.isfile(inFile)), "Could not find hyper-reduction file at " + inFile
			self.hyperReducFiles[modelIdx] = inFile

		# load hyper reduction dimensions and check validity
		self.hyperReducDims = catchList(self.romDict, "hyperReducDims", [0], lenHighest=self.numModels)
		for i in self.hyperReducDims: assert (i > 0), "hyperReducDims must contain positive integers"
		if (self.numModels == 1):
			assert (len(self.hyperReducDims) == 1), "Must provide only one value of hyperReducDims when numModels = 1"
			assert (self.hyperReducDims[0] > 0), "hyperReducDims must contain positive integers"
		else:
			if (len(self.hyperReducDims) == self.numModels):
				pass
			elif (len(self.hyperReducDims) == 1):	
				print("Only one value provided in hyperReducDims, applying to all models")
				sleep(1.0)
				self.hyperReducDims = [self.hyperReducDims[0]] * self.numModels
			else:
				raise ValueError("Must provide either numModels or 1 entry in hyperReducDims")
Ejemplo n.º 6
0
	def setModelFlags(self):
		"""
		Set universal ROM method flags that dictate various execution behaviors
		"""

		self.hasTimeIntegrator 	= False 	# whether the model uses numerical time integration to advance the solution
		self.isIntrusive 		= False 	# whether the model requires access to the ODE RHS calculation
		self.targetCons 		= False 	# whether the ROM models the conservative variables
		self.targetPrim 		= False 	# whether the ROM models the primitive variables

		self.hasConsNorm 		= False 	# whether the model must load conservative variable normalization profiles
		self.hasConsCent 		= False 	# whether the model must load conservative variable centering profile
		self.hasPrimNorm 		= False		# whether the model must load primitive variable normalization profiles
		self.hasPrimCent 		= False		# whether the model must load primitive variable centering profile

		if (self.romMethod == "linearGalerkinProj"):
			self.hasTimeIntegrator 	= True
			self.isIntrusive 	   	= True
			self.targetCons 		= True
			self.hasConsNorm 		= True
			self.hasConsCent 		= True
		elif (self.romMethod == "linearLSPGProj"):
			self.hasTimeIntegrator 	= True
			self.isIntrusive 	   	= True
			self.targetCons 		= True
			self.hasConsNorm 		= True
			self.hasConsCent 		= True
		elif (self.romMethod == "linearSPLSVTProj"):
			self.hasTimeIntegrator 	= True
			self.isIntrusive 	   	= True
			self.targetPrim 		= True
			self.hasConsNorm 		= True
			self.hasPrimNorm 		= True
			self.hasPrimCent 		= True
		elif (self.romMethod == "autoencoderGalerkinProjTF"):
			self.hasTimeIntegrator 	= True
			self.isIntrusive 	   	= True
			self.targetCons 		= True
			self.hasConsNorm 		= True
			self.hasConsCent 		= True
		elif (self.romMethod == "autoencoderLSPGProjTF"):
			self.hasTimeIntegrator 	= True
			self.isIntrusive 	   	= True
			self.targetCons 		= True
			self.hasConsNorm 		= True
			self.hasConsCent 		= True
		elif (self.romMethod == "autoencoderSPLSVTProjTF"):
			self.hasTimeIntegrator 	= True
			self.isIntrusive 	   	= True
			self.targetPrim 		= True
			self.hasConsNorm 		= True
			self.hasPrimNorm 		= True
			self.hasPrimCent 		= True
		elif (self.romMethod == "liftAndLearn"):
			# TODO: the cons/prim dichotomy doesn't work for lifted variables
			self.hasTimeIntegrator 	= True
			raise ValueError("Finalize settings of method parameters for lift and learn")
		elif (self.romMethod == "tcnNonintrusive"):
			# TODO: TCN does not **need** to target one or the other
			self.targetCons = catchInput(self.romDict, "targetCons", False)
			self.targetPrim = catchInput(self.romDict, "targetPrim", False)
		else:
			raise ValueError("Invalid ROM method name: "+self.romMethod)

		# TODO: not strictly true for the non-intrusive models
		assert (self.targetCons != self.targetPrim), "Model must target either the primitive or conservative variables"
Ejemplo n.º 7
0
    def __init__(self, solDomain, solver):

        paramDict = solver.paramDict

        self.visShow = catchInput(paramDict, "visShow", True)
        self.visSave = catchInput(paramDict, "visSave", False)
        self.visInterval = catchInput(paramDict, "visInterval", 1)
        self.niceVis = catchInput(paramDict, "niceVis", False)

        # if not saving or showing, don't even draw the plots
        self.visDraw = True
        if ((not self.visShow) and (not self.visSave)):
            self.visDraw = False
            return

        # count number of visualizations requested
        self.numVisPlots = 0
        plotCount = True
        while plotCount:
            try:
                keyName = "visType" + str(self.numVisPlots + 1)
                plotType = str(paramDict[keyName])
                # TODO: should honestly just fail for incorrect input
                assert (plotType in [
                    "field", "probe", "residual"
                ]), (keyName +
                     " must be either \"field\", \"probe\", or \"residual\"")
                self.numVisPlots += 1
            except:
                plotCount = False

        if (self.numVisPlots == 0):
            print("WARNING: No visualization plots selected...")
            sleep(1.0)
        self.visList = [None] * self.numVisPlots

        # initialize each figure object
        for visIdx in range(1, self.numVisPlots + 1):

            visType = str(paramDict["visType" + str(visIdx)])

            if (visType == "field"):
                self.visList[visIdx - 1] = fieldPlot(visIdx, self.visInterval,
                                                     solDomain, solver)
            elif (visType == "probe"):
                self.visList[visIdx - 1] = probePlot(visIdx, solDomain, solver)
            elif (visType == "residual"):
                raise ValueError("Residual plot not implemented yet")
            else:
                raise ValueError("Invalid visualization selection: " + visType)

        # set plot positions/dimensions
        if (self.niceVis and self.visShow):
            try:
                self.movePlots()
            except:
                for vis in self.visList:
                    vis.fig, vis.ax = plt.subplots(nrows=vis.numRows,
                                                   ncols=vis.numCols,
                                                   num=vis.visID,
                                                   figsize=(figWidthDefault,
                                                            figHeightDefault))
        else:
            for vis in self.visList:
                vis.fig, vis.ax = plt.subplots(nrows=vis.numRows,
                                               ncols=vis.numCols,
                                               num=vis.visID,
                                               figsize=(figWidthDefault,
                                                        figHeightDefault))
Ejemplo n.º 8
0
    def __init__(self, solver):

        paramDict = solver.paramDict

        # time integrator
        if (solver.timeScheme == "bdf"):
            self.timeIntegrator = bdf(paramDict)
        elif (solver.timeScheme == "rkExp"):
            self.timeIntegrator = rkExplicit(paramDict)
        else:
            raise ValueError("Invalid choice of timeScheme: " +
                             solver.timeScheme)

        # gas model
        gasFile = str(paramDict["gasFile"])  # gas properties file (string)
        gasDict = readInputFile(gasFile)
        gasType = catchInput(gasDict, "gasType", "cpg")
        if (gasType == "cpg"):
            self.gasModel = caloricallyPerfectGas(gasDict)
        else:
            raise ValueError("Ivalid choice of gasType: " + gasType)
        gas = self.gasModel

        # solution
        solPrim0 = getInitialConditions(self, solver)
        self.solInt = solutionInterior(gas, solPrim0, solver,
                                       self.timeIntegrator)
        self.solIn = solutionInlet(gas, solver)
        self.solOut = solutionOutlet(gas, solver)

        # average solution for Roe scheme
        if (solver.spaceScheme == "roe"):
            onesProf = np.ones(
                (self.gasModel.numEqs, self.solInt.numCells + 1),
                dtype=const.realType)
            self.solAve = solutionPhys(gas, onesProf, self.solInt.numCells + 1)

        # for flux calculations
        onesProf = np.ones((self.gasModel.numEqs, self.solInt.numCells + 1),
                           dtype=const.realType)
        self.solL = solutionPhys(gas, onesProf, self.solInt.numCells + 1)
        self.solR = solutionPhys(gas, onesProf, self.solInt.numCells + 1)

        # to avoid repeated concatenation of ghost cell states
        self.solPrimFull = np.zeros(
            (self.gasModel.numEqs, self.solIn.numCells + self.solInt.numCells +
             self.solOut.numCells),
            dtype=const.realType)
        self.solConsFull = np.zeros(self.solPrimFull.shape,
                                    dtype=const.realType)

        # probe storage (as this can include boundaries as well)
        self.probeLocs = catchList(paramDict, "probeLocs", [None])
        self.probeVars = catchList(paramDict, "probeVars", [None])
        if ((self.probeLocs[0] is not None)
                and (self.probeVars[0] is not None)):
            self.numProbes = len(self.probeLocs)
            self.numProbeVars = len(self.probeVars)
            self.probeVals = np.zeros(
                (self.numProbes, self.numProbeVars, solver.numSteps),
                dtype=const.realType)

            # get probe locations
            self.probeIdxs = [None] * self.numProbes
            self.probeSecs = [None] * self.numProbes
            for idx, probeLoc in enumerate(self.probeLocs):
                if (probeLoc > solver.mesh.xR):
                    self.probeSecs[idx] = "outlet"
                elif (probeLoc < solver.mesh.xL):
                    self.probeSecs[idx] = "inlet"
                else:
                    self.probeSecs[idx] = "interior"
                    self.probeIdxs[idx] = np.absolute(solver.mesh.xCell -
                                                      probeLoc).argmin()

            assert (not ((("outlet" in self.probeSecs) or ("inlet" in self.probeSecs))
               and (("source" in self.probeVars) or ("rhs" in self.probeVars))) ), \
               "Cannot probe source or RHS in inlet/outlet"

        else:
            self.numProbes = 0

        # copy this for use with plotting functions
        solver.numProbes = self.numProbes
        solver.probeVars = self.probeVars

        # TODO: include initial conditions in probeVals, timeVals
        self.timeVals = np.linspace(solver.dt * (solver.timeIter),
                                    solver.dt *
                                    (solver.timeIter + solver.numSteps),
                                    solver.numSteps,
                                    dtype=const.realType)

        # for compatability with hyper-reduction
        # are overwritten if actually using hyper-reduction
        self.numSampCells = solver.mesh.numCells
        self.numFluxFaces = solver.mesh.numCells + 1
        self.numGradCells = solver.mesh.numCells
        self.directSampIdxs = np.arange(0, solver.mesh.numCells)
        self.fluxSampLIdxs = np.arange(0, solver.mesh.numCells + 1)
        self.fluxSampRIdxs = np.arange(1, solver.mesh.numCells + 2)
        self.gradIdxs = np.arange(1, solver.mesh.numCells + 1)
        self.gradNeighIdxs = np.arange(0, solver.mesh.numCells + 2)
        self.gradNeighExtract = np.arange(1, solver.mesh.numCells + 1)
        self.fluxLExtract = np.arange(1, solver.mesh.numCells + 1)
        self.fluxRExtract = np.arange(0, solver.mesh.numCells)
        self.gradLExtract = np.arange(0, solver.mesh.numCells)
        self.gradRExtract = np.arange(0, solver.mesh.numCells)
        self.fluxRHSIdxs = np.arange(0, solver.mesh.numCells)
Ejemplo n.º 9
0
    def __init__(self):

        # input parameters from solverParams.inp
        paramFile = os.path.join(const.workingDir, const.paramInputs)
        paramDict = readInputFile(paramFile)
        self.paramDict = paramDict

        # spatial domain
        meshFile = str(paramDict["meshFile"])  # mesh properties file (string)
        meshDict = readInputFile(meshFile)
        self.mesh = mesh.mesh(meshDict)
        # TODO: selection for different meshes, when implemented
        # meshType 	= str(meshDict["meshType"])
        # if (meshType == "uniform"):
        # 	self.mesh 	= mesh.uniformMesh(meshDict)
        # else:
        # 	raise ValueError("Invalid choice of meshType: " + meshType)

        # initial condition file
        try:
            self.initFile = str(paramDict["initFile"])
        except:
            self.initFile = None

        # temporal discretization
        self.dt = float(paramDict["dt"])  # physical time step
        self.timeScheme = str(paramDict["timeScheme"])
        self.runSteady = catchInput(paramDict, "runSteady",
                                    False)  # run "steady" simulation
        self.numSteps = int(
            paramDict["numSteps"])  # total number of physical time iterations
        self.iter = 1  # iteration number for current run
        self.solTime = 0.0  # physical time
        self.timeIter = 1  # physical time iteration number

        if self.runSteady:
            self.steadyTol = catchInput(
                paramDict, "steadyTol",
                const.l2SteadyTolDefault)  # threshold on convergence

        # spatial discretization parameters
        self.spaceScheme = catchInput(
            paramDict, "spaceScheme",
            "roe")  # spatial discretization scheme (string)
        self.spaceOrder = catchInput(
            paramDict, "spaceOrder",
            1)  # spatial discretization order of accuracy (int)
        self.gradLimiter = catchInput(
            paramDict, "gradLimiter",
            "")  # gradient limiter for higher-order face reconstructions
        self.viscScheme = catchInput(paramDict, "viscScheme",
                                     0)  # 0 for inviscid, 1 for viscous

        # restart files
        # TODO: could move this to solutionDomain, not terribly necessary
        self.saveRestarts = catchInput(paramDict, "saveRestarts",
                                       False)  # whether to save restart files
        if self.saveRestarts:
            self.restartInterval = catchInput(
                paramDict, "restartInterval",
                100)  # number of steps between restart file saves
            self.numRestarts = catchInput(
                paramDict, "numRestarts",
                20)  # number of restart files to keep saved
            self.restartIter = 1  # file number counter
        self.initFromRestart = catchInput(paramDict, "initFromRestart", False)

        if ((self.initFile == None) and (not self.initFromRestart)):
            try:
                self.icParamsFile = str(paramDict["icParamsFile"])
            except:
                raise KeyError(
                    "If not providing IC profile or restarting from restart file, must provide icParamsFile"
                )

        # unsteady output
        self.outInterval = catchInput(
            paramDict, "outInterval",
            1)  # iteration interval to save data (int)
        self.primOut = catchInput(
            paramDict, "primOut",
            True)  # whether to save the primitive variables
        self.consOut = catchInput(
            paramDict, "consOut",
            False)  # whether to save the conservative variables
        self.sourceOut = catchInput(
            paramDict, "sourceOut",
            False)  # whether to save the species source term
        self.RHSOut = catchInput(paramDict, "RHSOut",
                                 False)  # whether to save the RHS vector
        self.numSnaps = int(self.numSteps / self.outInterval)

        # misc
        self.velAdd = catchInput(paramDict, "velAdd", 0.0)
        self.resNormPrim = catchInput(paramDict, "steadyNorm", [None])
        self.sourceOn = catchInput(paramDict, "sourceOn", True)
        self.solveFailed = False

        # visualization
        self.numProbes = 0
        self.probeVars = []

        # ROM flag
        self.calcROM = catchInput(paramDict, "calcROM", False)
        if not self.calcROM:
            self.simType = "FOM"
        else:
            self.simType = "ROM"
            self.romInputs = os.path.join(const.workingDir, const.romInputs)