Ejemplo n.º 1
0
 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)))
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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));
Ejemplo n.º 4
0
    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