コード例 #1
0
    def getSensitivity(self, f, g=None, **subs):
        """
        Calculates the sensitivity of the solution of an input factor ``f``
        in direction ``g``.

        :param f: the input factor to be investigated. ``f`` may be of rank 0
                  or 1.
        :type f: `Symbol`
        :param g: the direction(s) of change.
                  If not present, it is *g=eye(n)* where ``n`` is the number of
                  components of ``f``.
        :type g: ``list`` or single of ``float``, ``numpy.array`` or `Data`.
        :param subs: Substitutions for all symbols used in the coefficients
                     including unknown *u* and the input factor ``f`` to be
                     investigated
        :return: the sensitivity
        :rtype: `Data` with shape  *u.getShape()+(len(g),)* if *len(g)>1* or
                *u.getShape()* if *len(g)==1*
        """
        s_f = f.getShape()
        if len(s_f) == 0:
            len_f = 1
        elif len(s_f) == 1:
            len_f = s_f[0]
        else:
            raise ValueError("rank of input factor must be zero or one.")

        if not g is None:
            if len(s_f) == 0:
                if not isinstance(g, list): g = [g]
            else:
                if isinstance(g, list):
                    if len(g) == 0:
                        raise ValueError("no direction given.")
                    if len(getShape(g[0])) == 0:
                        g = [
                            g
                        ]  # if g[0] is a scalar we assume that the list g is to be interprested a data object
                else:
                    g = [g]
            # at this point g is a list of directions:
            len_g = len(g)
            for g_i in g:
                if not getShape(g_i) == s_f:
                    raise ValueError(
                        "shape of direction (=%s) must match rank of input factor (=%s)"
                        % (getShape(g_i), s_f))
        else:
            len_g = len_f

        #*** at this point g is a list of direction or None and len_g is the
        #    number of directions to be investigated.

        # now we make sure that the operator in the lpde is set (it is the same
        # as for the Newton-Raphson scheme)
        # if the solution etc are cached this could be omitted:
        constants = {}
        expressions = {}
        for n, e in sorted(self._set_coeffs.items(), key=lambda x: x[0]):
            if n not in self.__COEFFICIENTS:
                if symb.isSymbol(e):
                    expressions[n] = e
                else:
                    constants[n] = e
        self._lpde.setValue(**constants)
        self._updateMatrix(self, expressions, subs)
        #=====================================================================
        self._lpde.getSolverOptions().setAbsoluteTolerance(0.)
        self._lpde.getSolverOptions().setTolerance(self._rtol)
        self._lpde.getSolverOptions().setVerbosity(self._debug > self.DEBUG1)
        #=====================================================================
        #
        #   evaluate the derivatives of X, etc with respect to f:
        #
        ev = symb.Evaluator()
        names = []
        if hasattr(self, "_r"):
            if symb.isSymbol(self._r):
                names.append('r')
                ev.addExpression(self._r.diff(f))
        for n in sorted(self._set_coeffs.keys()):
            if n in self.__COEFFICIENTS and symb.isSymbol(self._set_coeffs[n]):
                if n == "X" or n == "X_reduced":
                    T0 = time()
                    B, A = symb.getTotalDifferential(self._set_coeffs[n], f, 1)
                    if n == 'X_reduced':
                        self.trace3(
                            "Computing A_reduced, B_reduced took %f seconds." %
                            (time() - T0))
                        names.append('A_reduced')
                        ev.addExpression(A)
                        names.append('B_reduced')
                        ev.addExpression(B)
                    else:
                        self.trace3("Computing A, B took %f seconds." %
                                    (time() - T0))
                        names.append('A')
                        ev.addExpression(A)
                        names.append('B')
                        ev.addExpression(B)
                elif n == "Y" or n == "Y_reduced":
                    T0 = time()
                    D, C = symb.getTotalDifferential(self._set_coeffs[n], f, 1)
                    if n == 'Y_reduced':
                        self.trace3(
                            "Computing C_reduced, D_reduced took %f seconds." %
                            (time() - T0))
                        names.append('C_reduced')
                        ev.addExpression(C)
                        names.append('D_reduced')
                        ev.addExpression(D)
                    else:
                        self.trace3("Computing C, D took %f seconds." %
                                    (time() - T0))
                        names.append('C')
                        ev.addExpression(C)
                        names.append('D')
                        ev.addExpression(D)
                elif n in ("y", "y_reduced", "y_contact", "y_contact_reduced",
                           "y_dirac"):
                    names.append('d' + name[1:])
                    ev.addExpression(self._set_coeffs[name].diff(f))
                    relevant_symbols['d' +
                                     name[1:]] = self._set_coeffs[name].diff(f)
        res = ev.evaluate()
        if len(names) == 1: res = [res]
        self.trace3("RHS expressions evaluated in %f seconds." % (time() - T0))
        if self._debug > self.DEBUG2:
            for i in range(len(names)):
                self.trace3("util.Lsup(%s)=%s" % (names[i], util.Lsup(res[i])))
        coeffs_f = dict(zip(names, res))
        #

        # now we are ready to calculate the right hand side coefficients into
        # args by multiplication with g and grad(g).
        if len_g > 1:
            if self.getNumSolutions() == 1:
                u_g = Data(0., (len_g, ),
                           self._lpde.getFunctionSpaceForSolution())
            else:
                u_g = Data(0., (self.getNumSolutions(), len_g),
                           self._lpde.getFunctionSpaceForSolution())

        for i in range(len_g):
            # reset coefficients may be set at previous calls:
            args = {}
            for n in self.__COEFFICIENTS:
                args[n] = Data()
            args['r'] = Data()
            if g is None:  # g_l=delta_{il} and len_f=len_g
                for n, v in coeffs_f:
                    name = None
                    if len_f > 1:
                        val = v[:, i]
                    else:
                        val = v
                    if n.startswith("d"):
                        name = 'y' + n[1:]
                    elif n.startswith("D"):
                        name = 'Y' + n[1:]
                    elif n.startswith("r"):
                        name = 'r' + n[1:]
                    if name: args[name] = val
            else:
                g_i = g[i]
                for n, v in coeffs_f:
                    name = None
                    if n.startswith("d"):
                        name = 'y' + n[1:]
                        val = self.__mm(v, g_i)
                    elif n.startswith("r"):
                        name = 'r'
                        val = self.__mm(v, g_i)
                    elif n.startswith("D"):
                        name = 'Y' + n[1:]
                        val = self.__mm(v, g_i)
                    elif n.startswith("B") and isinstance(g_i, Data):
                        name = 'Y' + n[1:]
                        val = self.__mm(v, grad(g_i))
                    elif n.startswith("C"):
                        name = 'X' + n[1:]
                        val = matrix_multiply(v, g_i)
                    elif n.startswith("A") and isinstance(g_i, Data):
                        name = 'X' + n[1:]
                        val = self.__mm(v, grad(g_i))
                    if name:
                        if name in args:
                            args[name] += val
                        else:
                            args[name] = val
            self._lpde.setValue(**args)
            u_g_i = self._lpde.getSolution()

            if len_g > 1:
                if self.getNumSolutions() == 1:
                    u_g[i] = -u_g_i
                else:
                    u_g[:, i] = -u_g_i
            else:
                u_g = -u_g_i

        return u_g
コード例 #2
0
ファイル: nonlinearPDE.py プロジェクト: svn2github/Escript
    def getSensitivity(self, f, g=None, **subs):
        """
        Calculates the sensitivity of the solution of an input factor ``f``
        in direction ``g``.

        :param f: the input factor to be investigated. ``f`` may be of rank 0
                  or 1.
        :type f: `Symbol`
        :param g: the direction(s) of change.
                  If not present, it is *g=eye(n)* where ``n`` is the number of
                  components of ``f``.
        :type g: ``list`` or single of ``float``, ``numpy.array`` or `Data`.
        :param subs: Substitutions for all symbols used in the coefficients
                     including unknown *u* and the input factor ``f`` to be
                     investigated
        :return: the sensitivity
        :rtype: `Data` with shape  *u.getShape()+(len(g),)* if *len(g)>1* or
                *u.getShape()* if *len(g)==1*
        """
        s_f=f.getShape()
        if len(s_f) == 0:
            len_f=1
        elif len(s_f) == 1:
            len_f=s_f[0]
        else:
            raise ValueError("rank of input factor must be zero or one.")

        if not g is None:
           if len(s_f) == 0:
               if not isinstance(g, list): g=[g]
           else:
              if isinstance(g, list):
                  if len(g) == 0:
                      raise ValueError("no direction given.")
                  if len(getShape(g[0])) == 0: g=[g] # if g[0] is a scalar we assume that the list g is to be interprested a data object
              else:
                 g=[g]
           # at this point g is a list of directions:
           len_g=len(g)
           for g_i in g:
                if not getShape(g_i) == s_f:
                    raise ValueError("shape of direction (=%s) must match rank of input factor (=%s)"%(getShape(g_i) , s_f) )
        else:
           len_g=len_f

        #*** at this point g is a list of direction or None and len_g is the
        #    number of directions to be investigated.

        # now we make sure that the operator in the lpde is set (it is the same
        # as for the Newton-Raphson scheme)
        # if the solution etc are cached this could be omitted:
        constants={}
        expressions={}
        for n, e in sorted(self._set_coeffs.items(), key=lambda x: x[0]):
            if n not in self.__COEFFICIENTS:
                if symb.isSymbol(e):
                    expressions[n]=e
                else:
                    constants[n]=e
        self._lpde.setValue(**constants)
        self._updateMatrix(self, expressions, subs)
        #=====================================================================
        self._lpde.getSolverOptions().setAbsoluteTolerance(0.)
        self._lpde.getSolverOptions().setTolerance(self._rtol)
        self._lpde.getSolverOptions().setVerbosity(self._debug > self.DEBUG1)
        #=====================================================================
        #
        #   evaluate the derivatives of X, etc with respect to f:
        #
        ev=symb.Evaluator()
        names=[]
        if hasattr(self, "_r"):
             if symb.isSymbol(self._r):
                 names.append('r')
                 ev.addExpression(self._r.diff(f))
        for n in sorted(self._set_coeffs.keys()):
            if n in self.__COEFFICIENTS and symb.isSymbol(self._set_coeffs[n]):
                   if n=="X" or n=="X_reduced":
                      T0=time()
                      B,A=symb.getTotalDifferential(self._set_coeffs[n], f, 1)
                      if n=='X_reduced':
                          self.trace3("Computing A_reduced, B_reduced took %f seconds."%(time()-T0))
                          names.append('A_reduced'); ev.addExpression(A)
                          names.append('B_reduced'); ev.addExpression(B)
                      else:
                          self.trace3("Computing A, B took %f seconds."%(time()-T0))
                          names.append('A'); ev.addExpression(A)
                          names.append('B'); ev.addExpression(B)
                   elif n=="Y" or n=="Y_reduced":
                      T0=time()
                      D,C=symb.getTotalDifferential(self._set_coeffs[n], f, 1)
                      if n=='Y_reduced':
                         self.trace3("Computing C_reduced, D_reduced took %f seconds."%(time()-T0))
                         names.append('C_reduced'); ev.addExpression(C)
                         names.append('D_reduced'); ev.addExpression(D)
                      else:
                         self.trace3("Computing C, D took %f seconds."%(time()-T0))
                         names.append('C'); ev.addExpression(C)
                         names.append('D'); ev.addExpression(D)
                   elif n in ("y", "y_reduced", "y_contact", "y_contact_reduced",  "y_dirac"):
                          names.append('d'+name[1:]); ev.addExpression(self._set_coeffs[name].diff(f))
                          relevant_symbols['d'+name[1:]]=self._set_coeffs[name].diff(f)
        res=ev.evaluate()
        if len(names)==1: res=[res]
        self.trace3("RHS expressions evaluated in %f seconds."%(time()-T0))
        if self._debug > self.DEBUG2:
            for i in range(len(names)):
                self.trace3("util.Lsup(%s)=%s"%(names[i],util.Lsup(res[i])))
        coeffs_f=dict(zip(names,res))
        #

        # now we are ready to calculate the right hand side coefficients into
        # args by multiplication with g and grad(g).
        if len_g >1:
            if self.getNumSolutions() == 1:
                u_g=Data(0., (len_g,), self._lpde.getFunctionSpaceForSolution())
            else:
                u_g=Data(0., (self.getNumSolutions(), len_g), self._lpde.getFunctionSpaceForSolution())

        for i in range(len_g):
              # reset coefficients may be set at previous calls:
              args={}
              for n in self.__COEFFICIENTS: args[n]=Data()
              args['r']=Data()
              if g is None: # g_l=delta_{il} and len_f=len_g
                  for n,v in coeffs_f:
                      name=None
                      if len_f > 1:
                          val=v[:,i]
                      else:
                          val=v
                      if n.startswith("d"):
                           name='y'+n[1:]
                      elif n.startswith("D"):
                          name='Y'+n[1:]
                      elif n.startswith("r"):
                          name='r'+n[1:]
                      if name: args[name]=val
              else:
                    g_i=g[i]
                    for n,v in coeffs_f:
                      name=None
                      if n.startswith("d"):
                          name = 'y'+n[1:]
                          val = self.__mm(v, g_i)
                      elif n.startswith("r"):
                          name= 'r'
                          val = self.__mm(v, g_i)
                      elif n.startswith("D"):
                          name = 'Y'+n[1:]
                          val = self.__mm(v, g_i)
                      elif n.startswith("B") and isinstance(g_i, Data):
                          name = 'Y'+n[1:]
                          val = self.__mm(v, grad(g_i))
                      elif n.startswith("C"):
                          name = 'X'+n[1:]
                          val = matrix_multiply(v, g_i)
                      elif n.startswith("A") and isinstance(g_i, Data):
                          name = 'X'+n[1:]
                          val = self.__mm(v, grad(g_i))
                      if name:
                          if name in args:
                              args[name]+=val
                          else:
                              args[name]=val
              self._lpde.setValue(**args)
              u_g_i=self._lpde.getSolution()

              if len_g >1:
                 if self.getNumSolutions() == 1:
                     u_g[i]=-u_g_i
                 else:
                     u_g[:,i]=-u_g_i
              else:
                  u_g=-u_g_i

        return u_g
コード例 #3
0
    def setValue(self, **coefficients):
        """
        Sets new values to one or more coefficients.

        :param coefficients: new values assigned to coefficients

        :param coefficients: new values assigned to coefficients
        :keyword X: value for coefficient ``X``
        :type X: `Symbol` or any type that can be cast to a `Data` object
        :keyword Y: value for coefficient ``Y``
        :type Y: `Symbol` or any type that can be cast to a `Data` object
        :keyword y: value for coefficient ``y``
        :type y: `Symbol` or any type that can be cast to a `Data` object
        :keyword y_contact: value for coefficient ``y_contact``
        :type y_contact: `Symbol` or any type that can be cast to a `Data` object
        :keyword y_dirac: value for coefficient ``y_dirac``
        :type y_dirac: `Symbol` or any type that can be cast to a `Data` object
        :keyword q: mask for location of constraint
        :type q: any type that can be cast to a `Data` object
        :keyword r: value of solution prescribed by constraint
        :type r: `Symbol` or any type that can be cast to a `Data` object
        :raise IllegalCoefficient: if an unknown coefficient keyword is used
        :raise IllegalCoefficientValue: if a supplied coefficient value has an
                                        invalid shape
        """

        u = self._unknown
        for name, val in sorted(coefficients.items(), key=lambda x: x[0]):
            shape = util.getShape(val)
            if not shape == self.getShapeOfCoefficient(name):
                raise lpe.IllegalCoefficientValue(
                    "%s has shape %s but must have shape %s" %
                    (name, shape, self.getShapeOfCoefficient(name)))
            rank = len(shape)
            if name == "q":
                self._lpde.setValue(q=val)
            elif name == "r":
                self._r = val
            elif name == "X" or name == "X_reduced":
                if rank != u.getRank() + 1:
                    raise lpe.IllegalCoefficientValue("%s must have rank %d" %
                                                      (name, u.getRank() + 1))
                T0 = time()
                B, A = symb.getTotalDifferential(val, u, 1)
                if name == 'X_reduced':
                    self.trace3(
                        "Computing A_reduced, B_reduced took %f seconds." %
                        (time() - T0))
                    self._set_coeffs['A_reduced'] = A
                    self._set_coeffs['B_reduced'] = B
                    self._set_coeffs['X_reduced'] = val
                else:
                    self.trace3("Computing A, B took %f seconds." %
                                (time() - T0))
                    self._set_coeffs['A'] = A
                    self._set_coeffs['B'] = B
                    self._set_coeffs['X'] = val
            elif name == "Y" or name == "Y_reduced":
                if rank != u.getRank():
                    raise lpe.IllegalCoefficientValue("%s must have rank %d" %
                                                      (name, u.getRank()))
                T0 = time()
                D, C = symb.getTotalDifferential(val, u, 1)
                if name == 'Y_reduced':
                    self.trace3(
                        "Computing C_reduced, D_reduced took %f seconds." %
                        (time() - T0))
                    self._set_coeffs['C_reduced'] = C
                    self._set_coeffs['D_reduced'] = D
                    self._set_coeffs['Y_reduced'] = val
                else:
                    self.trace3("Computing C, D took %f seconds." %
                                (time() - T0))
                    self._set_coeffs['C'] = C
                    self._set_coeffs['D'] = D
                    self._set_coeffs['Y'] = val
            elif name in ("y", "y_reduced", "y_contact", "y_contact_reduced", \
                    "y_dirac"):
                y = val
                if rank != u.getRank():
                    raise lpe.IllegalCoefficientValue("%s must have rank %d" %
                                                      (name, u.getRank()))
                if not hasattr(y, 'diff'):
                    d = numpy.zeros(u.getShape() + u.getShape())
                else:
                    d = y.diff(u)
                self._set_coeffs[name] = y
                self._set_coeffs['d' + name[1:]] = d
            else:
                raise lpe.IllegalCoefficient(
                    "Attempt to set unknown coefficient %s" % name)
コード例 #4
0
ファイル: nonlinearPDE.py プロジェクト: svn2github/Escript
    def setValue(self,**coefficients):
        """
        Sets new values to one or more coefficients.

        :param coefficients: new values assigned to coefficients

        :param coefficients: new values assigned to coefficients
        :keyword X: value for coefficient ``X``
        :type X: `Symbol` or any type that can be cast to a `Data` object
        :keyword Y: value for coefficient ``Y``
        :type Y: `Symbol` or any type that can be cast to a `Data` object
        :keyword y: value for coefficient ``y``
        :type y: `Symbol` or any type that can be cast to a `Data` object
        :keyword y_contact: value for coefficient ``y_contact``
        :type y_contact: `Symbol` or any type that can be cast to a `Data` object
        :keyword y_dirac: value for coefficient ``y_dirac``
        :type y_dirac: `Symbol` or any type that can be cast to a `Data` object
        :keyword q: mask for location of constraint
        :type q: any type that can be cast to a `Data` object
        :keyword r: value of solution prescribed by constraint
        :type r: `Symbol` or any type that can be cast to a `Data` object
        :raise IllegalCoefficient: if an unknown coefficient keyword is used
        :raise IllegalCoefficientValue: if a supplied coefficient value has an
                                        invalid shape
        """

        u=self._unknown
        for name,val in sorted(coefficients.items(), key=lambda x: x[0]):
            shape=util.getShape(val)
            if not shape == self.getShapeOfCoefficient(name):
                raise lpe.IllegalCoefficientValue("%s has shape %s but must have shape %s"%(name, shape, self.getShapeOfCoefficient(name)))
            rank=len(shape)
            if name == "q":
                self._lpde.setValue(q=val)
            elif name == "r":
                self._r=val
            elif name=="X" or name=="X_reduced":
                if rank != u.getRank()+1:
                    raise lpe.IllegalCoefficientValue("%s must have rank %d"%(name,u.getRank()+1))
                T0=time()
                B,A=symb.getTotalDifferential(val, u, 1)
                if name=='X_reduced':
                    self.trace3("Computing A_reduced, B_reduced took %f seconds."%(time()-T0))
                    self._set_coeffs['A_reduced']=A
                    self._set_coeffs['B_reduced']=B
                    self._set_coeffs['X_reduced']=val
                else:
                    self.trace3("Computing A, B took %f seconds."%(time()-T0))
                    self._set_coeffs['A']=A
                    self._set_coeffs['B']=B
                    self._set_coeffs['X']=val
            elif name=="Y" or name=="Y_reduced":
                if rank != u.getRank():
                    raise lpe.IllegalCoefficientValue("%s must have rank %d"%(name,u.getRank()))
                T0=time()
                D,C=symb.getTotalDifferential(val, u, 1)
                if name=='Y_reduced':
                    self.trace3("Computing C_reduced, D_reduced took %f seconds."%(time()-T0))
                    self._set_coeffs['C_reduced']=C
                    self._set_coeffs['D_reduced']=D
                    self._set_coeffs['Y_reduced']=val
                else:
                    self.trace3("Computing C, D took %f seconds."%(time()-T0))
                    self._set_coeffs['C']=C
                    self._set_coeffs['D']=D
                    self._set_coeffs['Y']=val
            elif name in ("y", "y_reduced", "y_contact", "y_contact_reduced", \
                    "y_dirac"):
                y=val
                if rank != u.getRank():
                    raise lpe.IllegalCoefficientValue("%s must have rank %d"%(name,u.getRank()))
                if not hasattr(y, 'diff'):
                    d=numpy.zeros(u.getShape()+u.getShape())
                else:
                    d=y.diff(u)
                self._set_coeffs[name]=y
                self._set_coeffs['d'+name[1:]]=d
            else:
                raise lpe.IllegalCoefficient("Attempt to set unknown coefficient %s"%name)