def log_sum_exp(X): """ Computes log sum_i exp(X_i). Useful if you want to solve log \int f(x)p(x) dx where you have samples from p(x) and can compute log f(x) """ # extract minimum X0=X.min() X_without_X0=delete(X,X.argmin()) return X0+log(1+sum(exp(X_without_X0-X0)))
def Solve(self): ''' This method builds System Matrix and gets Solution ''' if self.SimulationContext.Id != self.NetworkMesh.Id: raise self.SimulationContext.XMLIdError() try: self.TimeStep = self.SimulationContext.Context['timestep'] self.SquareTimeStep = self.TimeStep*self.TimeStep except KeyError: print "Error, Please set timestep in Simulation Context XML File" raise try: self.Period = self.SimulationContext.Context['period'] self.TimeStepFreq = int(self.Period/self.TimeStep) except KeyError: print "Error, Please set period in Simulation Context XML File" raise try: self.Cycles = self.SimulationContext.Context['cycles'] self.NumberOfIncrements = (self.Cycles*self.TimeStepFreq) except KeyError: print "Error, Please set cycles number in Simulation Context XML File" raise history = [] assembler = Assembler() assembler.SetNetworkMesh(self.NetworkMesh) assembler.SetBoundaryConditions(self.BoundaryConditions) info = {'dofmap':assembler.DofMap,'solution':None,'incrementNumber':self.IncrementNumber,'history':history} self.Evaluator.SetInfo(info) self.PrescribedPressures = assembler.AssembleBoundaryConditions(self.SimulationContext) self.LinearZeroOrderGlobalMatrix, self.LinearFirstOrderGlobalMatrix, self.LinearSecondOrderGlobalMatrix = \ assembler.AssembleInit(self.SimulationContext, self.Evaluator) self.ZeroOrderGlobalMatrix = assembler.ZeroOrderGlobalMatrix self.FirstOrderGlobalMatrix = assembler.FirstOrderGlobalMatrix self.SecondOrderGlobalMatrix = assembler.SecondOrderGlobalMatrix NumberOfGlobalDofs = assembler.GetNumberOfGlobalDofs() # number of dofs self.UnknownPressures = arange(0,NumberOfGlobalDofs).reshape(NumberOfGlobalDofs,1) # unknown pressures self.UnknownPressures = delete(self.UnknownPressures, s_[self.PrescribedPressures[:,0]], axis=0) PressuresMatrix = zeros((NumberOfGlobalDofs, self.NumberOfIncrements)) self.p = zeros((NumberOfGlobalDofs,1)) self.pt = zeros((NumberOfGlobalDofs,1)) self.ptt = zeros((NumberOfGlobalDofs,1)) self.dp = zeros((NumberOfGlobalDofs,1)) self.ddp = zeros((NumberOfGlobalDofs,1)) self.dpt = zeros((NumberOfGlobalDofs,1)) self.ddpt = zeros((NumberOfGlobalDofs,1)) self.fe = zeros((NumberOfGlobalDofs,1)) self.fet = zeros((NumberOfGlobalDofs,1)) self.dfe = zeros((NumberOfGlobalDofs,1)) self.dfet = zeros((NumberOfGlobalDofs,1)) self.fi = zeros((NumberOfGlobalDofs,1)) self.fit = zeros((NumberOfGlobalDofs,1)) self.sumv = zeros((NumberOfGlobalDofs,1)) sumvbk = zeros((NumberOfGlobalDofs,1)) nonLinear = False for el in self.NetworkMesh.Elements: if el.IsNonLinear() == True: nonLinear = True break while self.IncrementNumber<=self.NumberOfIncrements: icc = (self.IncrementNumber%self.TimeStepFreq) if icc == 0: icc = self.TimeStepFreq #for flow in self.BoundaryConditions.elementFlow: for el in self.BoundaryConditions.elementFlow: if self.steady == True: self.Flow = assembler.BoundaryConditions.GetSteadyFlow(el, self.TimeStep,icc*self.TimeStep) else: self.Flow = assembler.BoundaryConditions.GetTimeFlow(el, icc*self.TimeStep) self.fe[assembler.FlowDof[el.Id]]= self.Flow CoeffRelax = 0.9 nltol = self.nltol self.pi = None pI = None sumvbk[:,:] = self.sumv[:,:] counter = 0 while True: #Build the algebric equation system for the increment SystemMatrix = (2.0/self.TimeStep)*self.SecondOrderGlobalMatrix + self.FirstOrderGlobalMatrix + (self.TimeStep/2.0)*self.ZeroOrderGlobalMatrix #system matrix RightVector = self.fe + (2.0/self.TimeStep)*dot(self.SecondOrderGlobalMatrix,(self.pt)) + dot(self.SecondOrderGlobalMatrix,(self.dpt)) - dot(self.ZeroOrderGlobalMatrix,(self.sumv))-(self.TimeStep/2.0)*dot(self.ZeroOrderGlobalMatrix,(self.pt)) # right hand side vector #The reduced (partioned) system of equations is generated. RightVector[:,:] = RightVector[:,:] - dot(SystemMatrix[:,self.PrescribedPressures[:,0]],self.PrescribedPressures[:,1:]) SystemMatrix = SystemMatrix[:,s_[self.UnknownPressures[:,0]]] if SystemMatrix.shape[0]> 0.0: SystemMatrix = SystemMatrix[s_[self.UnknownPressures[:,0]],:] RightVector = RightVector[s_[self.UnknownPressures[:,0]],:] #Unknown nodal point values are solved from this system. # Prescribed nodal values are inserted in the solution vector. Solution = solve(SystemMatrix,RightVector) # solutions, unknown pressures self.p[self.UnknownPressures,0] = Solution[:,:] self.p[self.PrescribedPressures[:,0],0] = self.PrescribedPressures[:,1] #Calculating derivatives. #Calculating internal nodal flow values. self.dp = dot((2.0/self.TimeStep),(self.p-self.pt)) - self.dpt self.ddp = dot((4.0/self.SquareTimeStep),(self.p-self.pt)) - dot((4.0/self.TimeStep),self.dpt) -self.ddpt self.sumv = sumvbk + dot((self.TimeStep/2.0),(self.pt+self.p)) self.fi = dot(self.SecondOrderGlobalMatrix,(self.dp)) + dot(self.FirstOrderGlobalMatrix,(self.p)) + dot(self.ZeroOrderGlobalMatrix,(self.sumv)) if not nonLinear : break if self.pi == None: self.pi = zeros((NumberOfGlobalDofs,1)) self.pi[:,:] = self.pt[:,:] pI = CoeffRelax * self.p + self.pi * (1.0-CoeffRelax) self.p[:,:] = pI[:,:] den = norm(self.pi,Inf) if den < 1e-12: den = 1.0 nlerr = norm(self.p-self.pi,Inf) / den info = {'dofmap':assembler.DofMap,'solution':[self.p, self.pt, self.ptt],'incrementNumber':self.IncrementNumber,'history':history} self.Evaluator.SetInfo(info) assembler.Assemble(self.SimulationContext, self.Evaluator, self.LinearZeroOrderGlobalMatrix, self.LinearFirstOrderGlobalMatrix, self.LinearSecondOrderGlobalMatrix) self.ZeroOrderGlobalMatrix = assembler.ZeroOrderGlobalMatrix self.FirstOrderGlobalMatrix = assembler.FirstOrderGlobalMatrix self.SecondOrderGlobalMatrix = assembler.SecondOrderGlobalMatrix #Dynamic nonlinear relaxing coefficient if counter == 100: print "relaxing..." print nlerr, nltol, CoeffRelax counter = 0 self.pi[:,:] = None self.sumv[:,:] = sumvbk[:,:] CoeffRelax *= 0.6 nltol *= 0.95 if nlerr < nltol: nltol = self.nltol counter = 0 break counter+=1 self.pi[:,:] = self.p[:,:] self.ptt[:,:] = self.pt[:,:] self.pt[:,:] = self.p[:,:] self.dpt[:,:] = self.dp[:,:] self.ddpt[:,:] = self.ddp[:,:] self.fet[:,:] = self.fe[:,:] self.fit[:,:] = self.fi[:,:] PressuresMatrix[:,(self.IncrementNumber-1)] = self.p[:,0] history.insert(0,self.IncrementNumber) history = history[:3] if self.steady == True: self.MinimumIncrementNumber = 0.01* self.NumberOfIncrements if norm(self.fi-self.fe,Inf)<self.convergence and self.IncrementNumber > self.MinimumIncrementNumber: self.IncrementNumber = self.NumberOfIncrements else: pass if self.IncrementNumber==ceil(0.05*self.NumberOfIncrements): print "->5%" if self.IncrementNumber==ceil(0.25*self.NumberOfIncrements): print "->25%" if self.IncrementNumber==ceil(0.5*self.NumberOfIncrements): print "->50%" if self.IncrementNumber==ceil(0.70*self.NumberOfIncrements): print "->70%" if self.IncrementNumber==ceil(0.90*self.NumberOfIncrements): print "->90%" if self.IncrementNumber==ceil(0.99*self.NumberOfIncrements): print "->99%" self.IncrementNumber = self.IncrementNumber+1 self.EndIncrementTime = self.EndIncrementTime + self.TimeStep # increment info = {'dofmap':assembler.DofMap,'solution':[self.p, self.pt, self.ptt],'incrementNumber':self.IncrementNumber,'history':history,'allSolution':PressuresMatrix} self.Evaluator.SetInfo(info) self.Solutions = PressuresMatrix return PressuresMatrix
def exponential(self, estimates): logging.debug("Entering") # find a strict lower bound on the estimates and remove it from list bound = estimates.min() bound_idx = estimates.argmin() estimates = delete(estimates, bound_idx) estimates = estimates - bound # find an integer close to the mean of the transformed estimates and divide E = max(int(round(abs(mean(estimates)))), 1) estimates = estimates / E logging.info("Using %f as lower bound on estimates" % bound) logging.info("Computing product of E=%d RR estimates" % E) logging.info("Std-deviation after scaling is %f" % std(estimates)) # index for iterating through the used estimates # (might be averaged, so might be lower than the number of available estimates # if the block size is greater than one estimate_idx = 0 samples = zeros(E) for iteration in range(E): weight = 1 # start with x^0 which is 1 samples[iteration] = 1 term = 1 # index for computed samples series_term_idx = 1 while weight > 0: # update current term of infinite series # average over block x_inner = self.get_estimate(estimates, estimate_idx) term *= (x_inner / series_term_idx) # if summation has reached threshold, update weights if abs(term) < self.threshold: q = term / self.threshold if rand() < q: # continue and update weight weight = weight / q else: # stop summation weight = 0 samples[iteration] += weight * term; estimate_idx += 1 series_term_idx += 1 logging.info("RR estimate %d/%d with threshold %.2f is %.4f and took %d series terms" % (iteration + 1, E, self.threshold, samples[iteration], series_term_idx)) # now put things together. Note that samples contains an unbiased estimate # which might be quite small. However, due to the removal of the bound, # this will not cause an underflow and we can just take the log. logging.debug("Leaving") return bound + sum(log(samples));
def Solve(self): ''' This method builds System Matrix and gets Solution ''' if self.SimulationContext.Id != self.NetworkMesh.Id: raise self.SimulationContext.XMLIdError() try: self.TimeStep = self.SimulationContext.Context['timestep'] self.SquareTimeStep = self.TimeStep * self.TimeStep except KeyError: print "Error, Please set timestep in Simulation Context XML File" raise try: self.Period = self.SimulationContext.Context['period'] self.TimeStepFreq = int(self.Period / self.TimeStep) except KeyError: print "Error, Please set period in Simulation Context XML File" raise try: self.Cycles = self.SimulationContext.Context['cycles'] self.NumberOfIncrements = (self.Cycles * self.TimeStepFreq) except KeyError: print "Error, Please set cycles number in Simulation Context XML File" raise history = [] assembler = Assembler() assembler.SetNetworkMesh(self.NetworkMesh) assembler.SetBoundaryConditions(self.BoundaryConditions) info = { 'dofmap': assembler.DofMap, 'solution': None, 'incrementNumber': self.IncrementNumber, 'history': history } self.Evaluator.SetInfo(info) self.PrescribedPressures = assembler.AssembleBoundaryConditions( self.SimulationContext) self.LinearZeroOrderGlobalMatrix, self.LinearFirstOrderGlobalMatrix, self.LinearSecondOrderGlobalMatrix = \ assembler.AssembleInit(self.SimulationContext, self.Evaluator) self.ZeroOrderGlobalMatrix = assembler.ZeroOrderGlobalMatrix self.FirstOrderGlobalMatrix = assembler.FirstOrderGlobalMatrix self.SecondOrderGlobalMatrix = assembler.SecondOrderGlobalMatrix NumberOfGlobalDofs = assembler.GetNumberOfGlobalDofs( ) # number of dofs self.UnknownPressures = arange(0, NumberOfGlobalDofs).reshape( NumberOfGlobalDofs, 1) # unknown pressures self.UnknownPressures = delete(self.UnknownPressures, s_[self.PrescribedPressures[:, 0]], axis=0) PressuresMatrix = zeros((NumberOfGlobalDofs, self.NumberOfIncrements)) self.p = zeros((NumberOfGlobalDofs, 1)) self.pt = zeros((NumberOfGlobalDofs, 1)) self.ptt = zeros((NumberOfGlobalDofs, 1)) self.dp = zeros((NumberOfGlobalDofs, 1)) self.ddp = zeros((NumberOfGlobalDofs, 1)) self.dpt = zeros((NumberOfGlobalDofs, 1)) self.ddpt = zeros((NumberOfGlobalDofs, 1)) self.fe = zeros((NumberOfGlobalDofs, 1)) self.fet = zeros((NumberOfGlobalDofs, 1)) self.dfe = zeros((NumberOfGlobalDofs, 1)) self.dfet = zeros((NumberOfGlobalDofs, 1)) self.fi = zeros((NumberOfGlobalDofs, 1)) self.fit = zeros((NumberOfGlobalDofs, 1)) self.sumv = zeros((NumberOfGlobalDofs, 1)) sumvbk = zeros((NumberOfGlobalDofs, 1)) nonLinear = False for el in self.NetworkMesh.Elements: if el.IsNonLinear() == True: nonLinear = True break while self.IncrementNumber <= self.NumberOfIncrements: icc = (self.IncrementNumber % self.TimeStepFreq) if icc == 0: icc = self.TimeStepFreq #for flow in self.BoundaryConditions.elementFlow: for el in self.BoundaryConditions.elementFlow: if self.steady == True: self.Flow = assembler.BoundaryConditions.GetSteadyFlow( el, self.TimeStep, icc * self.TimeStep) else: self.Flow = assembler.BoundaryConditions.GetTimeFlow( el, icc * self.TimeStep) self.fe[assembler.FlowDof[el.Id]] = self.Flow CoeffRelax = 0.9 nltol = self.nltol self.pi = None pI = None sumvbk[:, :] = self.sumv[:, :] counter = 0 while True: #Build the algebric equation system for the increment SystemMatrix = ( 2.0 / self.TimeStep ) * self.SecondOrderGlobalMatrix + self.FirstOrderGlobalMatrix + ( self.TimeStep / 2.0) * self.ZeroOrderGlobalMatrix #system matrix RightVector = self.fe + (2.0 / self.TimeStep) * dot( self.SecondOrderGlobalMatrix, (self.pt)) + dot( self.SecondOrderGlobalMatrix, (self.dpt)) - dot( self.ZeroOrderGlobalMatrix, (self.sumv)) - (self.TimeStep / 2.0) * dot( self.ZeroOrderGlobalMatrix, (self.pt)) # right hand side vector #The reduced (partioned) system of equations is generated. RightVector[:, :] = RightVector[:, :] - dot( SystemMatrix[:, self.PrescribedPressures[:, 0]], self.PrescribedPressures[:, 1:]) SystemMatrix = SystemMatrix[:, s_[self.UnknownPressures[:, 0]]] if SystemMatrix.shape[0] > 0.0: SystemMatrix = SystemMatrix[ s_[self.UnknownPressures[:, 0]], :] RightVector = RightVector[s_[self.UnknownPressures[:, 0]], :] #Unknown nodal point values are solved from this system. # Prescribed nodal values are inserted in the solution vector. Solution = solve(SystemMatrix, RightVector) # solutions, unknown pressures self.p[self.UnknownPressures, 0] = Solution[:, :] self.p[self.PrescribedPressures[:, 0], 0] = self.PrescribedPressures[:, 1] #Calculating derivatives. #Calculating internal nodal flow values. self.dp = dot((2.0 / self.TimeStep), (self.p - self.pt)) - self.dpt self.ddp = dot((4.0 / self.SquareTimeStep), (self.p - self.pt)) - dot( (4.0 / self.TimeStep), self.dpt) - self.ddpt self.sumv = sumvbk + dot((self.TimeStep / 2.0), (self.pt + self.p)) self.fi = dot(self.SecondOrderGlobalMatrix, (self.dp)) + dot( self.FirstOrderGlobalMatrix, (self.p)) + dot(self.ZeroOrderGlobalMatrix, (self.sumv)) if not nonLinear: break if self.pi == None: self.pi = zeros((NumberOfGlobalDofs, 1)) self.pi[:, :] = self.pt[:, :] pI = CoeffRelax * self.p + self.pi * (1.0 - CoeffRelax) self.p[:, :] = pI[:, :] den = norm(self.pi, Inf) if den < 1e-12: den = 1.0 nlerr = norm(self.p - self.pi, Inf) / den info = { 'dofmap': assembler.DofMap, 'solution': [self.p, self.pt, self.ptt], 'incrementNumber': self.IncrementNumber, 'history': history } self.Evaluator.SetInfo(info) assembler.Assemble(self.SimulationContext, self.Evaluator, self.LinearZeroOrderGlobalMatrix, self.LinearFirstOrderGlobalMatrix, self.LinearSecondOrderGlobalMatrix) self.ZeroOrderGlobalMatrix = assembler.ZeroOrderGlobalMatrix self.FirstOrderGlobalMatrix = assembler.FirstOrderGlobalMatrix self.SecondOrderGlobalMatrix = assembler.SecondOrderGlobalMatrix #Dynamic nonlinear relaxing coefficient if counter == 100: print "relaxing..." print nlerr, nltol, CoeffRelax counter = 0 self.pi[:, :] = None self.sumv[:, :] = sumvbk[:, :] CoeffRelax *= 0.6 nltol *= 0.95 if nlerr < nltol: nltol = self.nltol counter = 0 break counter += 1 self.pi[:, :] = self.p[:, :] self.ptt[:, :] = self.pt[:, :] self.pt[:, :] = self.p[:, :] self.dpt[:, :] = self.dp[:, :] self.ddpt[:, :] = self.ddp[:, :] self.fet[:, :] = self.fe[:, :] self.fit[:, :] = self.fi[:, :] PressuresMatrix[:, (self.IncrementNumber - 1)] = self.p[:, 0] history.insert(0, self.IncrementNumber) history = history[:3] if self.steady == True: self.MinimumIncrementNumber = 0.01 * self.NumberOfIncrements if norm( self.fi - self.fe, Inf ) < self.convergence and self.IncrementNumber > self.MinimumIncrementNumber: self.IncrementNumber = self.NumberOfIncrements else: pass if self.IncrementNumber == ceil(0.05 * self.NumberOfIncrements): print "->5%" if self.IncrementNumber == ceil(0.25 * self.NumberOfIncrements): print "->25%" if self.IncrementNumber == ceil(0.5 * self.NumberOfIncrements): print "->50%" if self.IncrementNumber == ceil(0.70 * self.NumberOfIncrements): print "->70%" if self.IncrementNumber == ceil(0.90 * self.NumberOfIncrements): print "->90%" if self.IncrementNumber == ceil(0.99 * self.NumberOfIncrements): print "->99%" self.IncrementNumber = self.IncrementNumber + 1 self.EndIncrementTime = self.EndIncrementTime + self.TimeStep # increment info = { 'dofmap': assembler.DofMap, 'solution': [self.p, self.pt, self.ptt], 'incrementNumber': self.IncrementNumber, 'history': history, 'allSolution': PressuresMatrix } self.Evaluator.SetInfo(info) self.Solutions = PressuresMatrix return PressuresMatrix