def heat_transfer_callback(self, theta): """ A callback used by PDSimCore.derivs to calculate the heat transfer to the gas in the working chamber. We return an arraym instance the same length as the number of CV in existence More code (a proper heat transfer model) could be included here, like in PDSim.recip.core """ return arraym([0.0] * self.CVs.N)
def heat_transfer_callback(self, theta): """ A callback used by PDSimCore.derivs to calculate the heat transfer to the gas in the working chamber. We return an arraym instance the same length as the number of CV in existence More code (a proper heat transfer model) could be included here, like in PDSim.recip.core """ return arraym([0.0]*self.CVs.N)
def step_callback(self,t,h,Itheta): """ Here we test whether the control volumes need to be a) Split b) Adjusted because you are at the discharge angle """ #This gets called at every step, or partial step self.beta=t def angle_difference(angle1,angle2): # Due to the periodicity of angles, you need to handle the case where the # angles wrap around - suppose theta_d is 6.28 and you are at an angles of 0.1 rad #, the difference should be around 0.1, not -6.27 # # This brilliant method is from http://blog.lexique-du-net.com/index.php?post/Calculate-the-real-difference-between-two-angles-keeping-the-sign # and the comment of user tk return (angle1-angle2+pi)%(2*pi)-pi def IsAtSplit(): if t > 3.5 and t < 2*pi-self.theta_d: return True else: return False disable=False if t<2*pi-self.theta_d<t+h and self.__before_discharge2__==False: #Take a step almost up to the discharge angle using the old definitions disable=True h=2*pi-self.theta_d-t-1e-10 self.__before_discharge2__=True elif self.__before_discharge2__==True: #At the discharge angle print('At the discharge angle') ######################## #Reassign chambers ######################## #Find chambers with a discharge_becomes flag for key in self.CVs.exists_keys: if self.CVs[key].discharge_becomes in self.CVs.keys: #Set the state of the "new" chamber to be the old chamber oldCV=self.CVs[key] #print 'setting',key,'to',oldCV.discharge_becomes if oldCV.exists==True: newCV=self.CVs[oldCV.discharge_becomes] newCV.State.update({'T':oldCV.State.T,'D':oldCV.State.rho}) oldCV.exists = False newCV.exists = True else: raise AttributeError("old CV doesn't exist") self.__before_discharge2__ = False self.__before_discharge1__ = True self.update_existence() #Re-calculate the CV volumes V,dV = self.CVs.volumes(t) #Update the matrices using the new CV definitions self.T[self.CVs.exists_indices,Itheta]=self.CVs.T self.p[self.CVs.exists_indices,Itheta]=self.CVs.p self.m[self.CVs.exists_indices,Itheta]=arraym(self.CVs.rho)*V self.rho[self.CVs.exists_indices,Itheta]=arraym(self.CVs.rho) # Adaptive makes steps of h/4 3h/8 12h/13 and h/2 and h # Make sure step does not hit any *right* at theta_d # That is why it is 2.2e-10 rather than 2.0e-10 h=2.2e-10 disable=True elif self.CVs['sss'].exists and IsAtSplit(): #Build the volume vector using the old set of control volumes (pre-merge) V,dV=self.CVs.volumes(t) print('splitting') if self.__hasLiquid__==False: T = self.CVs['sss'].State.T rho = self.CVs['sss'].State.rho self.CVs['s1'].State.update({'T':T,'D':rho}) self.CVs['s2'].State.update({'T':T,'D':rho}) self.CVs['ss'].State.update({'T':T,'D':rho}) self.CVs['sss'].exists = False self.CVs['s1'].exists = True self.CVs['s2'].exists = True self.CVs['ss'].exists = True self.update_existence() #Re-calculate the CV V,dV=self.CVs.volumes(t) self.T[self.CVs.exists_indices,Itheta] = self.CVs.T self.p[self.CVs.exists_indices,Itheta] = self.CVs.p self.m[self.CVs.exists_indices,Itheta] = arraym(self.CVs.rho)*V self.rho[self.CVs.exists_indices,Itheta] = arraym(self.CVs.rho) else: raise NotImplementedError('no flooding yet') h = 1e-8 disable=True elif t > 2*pi - self.theta_d: self.__before_discharge1__ = False disable = False return disable, h
def derivs(self, t0, xold): return arraym([xold[0]])
def get_initial_array(self): return arraym([1.0])