def __init__(self, *expressions): Operator.__init__(self, expressions) # Checks indexset = set(self.ufl_operands[0].ufl_free_indices) if not all(not (indexset ^ set(e.ufl_free_indices)) for e in self.ufl_operands): error("Can't combine subtensor expressions with different sets of free indices.")
def __init__(self, arg1, arg2): Operator.__init__(self, (arg1, arg2)) if isinstance(arg1, (ComplexValue, complex)) or isinstance(arg2, (ComplexValue, complex)): raise TypeError("Atan2 does not support complex numbers.") if not is_true_ufl_scalar(arg1): error("Expecting scalar argument 1.") if not is_true_ufl_scalar(arg2): error("Expecting scalar argument 2.")
def __init__(self, summand, index): j, = index fi = summand.ufl_free_indices fid = summand.ufl_index_dimensions pos = fi.index(j.count()) self._dimension = fid[pos] self.ufl_free_indices = fi[:pos] + fi[pos + 1:] self.ufl_index_dimensions = fid[:pos] + fid[pos + 1:] Operator.__init__(self, (summand, index))
def __init__(self, arg1, arg2): Operator.__init__(self, (arg1, arg2)) if isinstance(arg1, (ComplexValue, complex)) or isinstance( arg2, (ComplexValue, complex)): raise TypeError("Atan2 does not support complex numbers.") if not is_true_ufl_scalar(arg1): error("Expecting scalar argument 1.") if not is_true_ufl_scalar(arg2): error("Expecting scalar argument 2.")
def __init__(self, summand, index): j, = index fi = summand.ufl_free_indices fid = summand.ufl_index_dimensions pos = fi.index(j.count()) self._dimension = fid[pos] self.ufl_free_indices = fi[:pos] + fi[pos+1:] self.ufl_index_dimensions = fid[:pos] + fid[pos+1:] Operator.__init__(self, (summand, index))
def __init__(self, *expressions): Operator.__init__(self, expressions) # Checks indexset = set(self.ufl_operands[0].ufl_free_indices) if not all(not (indexset ^ set(e.ufl_free_indices)) for e in self.ufl_operands): error( "Can't combine subtensor expressions with different sets of free indices." )
def __init__(self, expression, multiindex): # Store operands Operator.__init__(self, (expression, multiindex)) # Error checking if not isinstance(expression, Expr): error("Expecting Expr instance, not %s." % ufl_err_str(expression)) if not isinstance(multiindex, MultiIndex): error("Expecting MultiIndex instance, not %s." % ufl_err_str(multiindex)) shape = expression.ufl_shape # Error checking if len(shape) != len(multiindex): error("Invalid number of indices (%d) for tensor " "expression of rank %d:\n\t%s\n" % (len(multiindex), len( expression.ufl_shape), ufl_err_str(expression))) if any( int(di) >= int(si) or int(di) < 0 for si, di in zip(shape, multiindex) if isinstance(di, FixedIndex)): error("Fixed index out of range!") # Build tuples of free index ids and dimensions if 1: efi = expression.ufl_free_indices efid = expression.ufl_index_dimensions fi = list(zip(efi, efid)) for pos, ind in enumerate(multiindex._indices): if isinstance(ind, Index): fi.append((ind.count(), shape[pos])) fi = unique_sorted_indices(sorted(fi)) if fi: fi, fid = zip(*fi) else: fi, fid = (), () else: mfiid = [(ind.count(), shape[pos]) for pos, ind in enumerate(multiindex._indices) if isinstance(ind, Index)] mfi, mfid = zip(*mfiid) if mfiid else ((), ()) fi, fid = merge_unique_indices(expression.ufl_free_indices, expression.ufl_index_dimensions, mfi, mfid) # Cache free index and dimensions self.ufl_free_indices = fi self.ufl_index_dimensions = fid
def __init__(self, expression, label=None): # Conversion expression = as_ufl(expression) if label is None: label = Label() # Checks if not isinstance(expression, Expr): error("Expecting Expr.") if not isinstance(label, Label): error("Expecting a Label.") if expression.ufl_free_indices: error("Variable cannot wrap an expression with free indices.") Operator.__init__(self, (expression, label))
def __init__(self, expression, multiindex): # Store operands Operator.__init__(self, (expression, multiindex)) # Error checking if not isinstance(expression, Expr): error("Expecting Expr instance, not %s." % ufl_err_str(expression)) if not isinstance(multiindex, MultiIndex): error("Expecting MultiIndex instance, not %s." % ufl_err_str(multiindex)) shape = expression.ufl_shape # Error checking if len(shape) != len(multiindex): error("Invalid number of indices (%d) for tensor " "expression of rank %d:\n\t%s\n" % (len(multiindex), len(expression.ufl_shape), ufl_err_str(expression))) if any(int(di) >= int(si) for si, di in zip(shape, multiindex) if isinstance(di, FixedIndex)): error("Fixed index out of range!") # Build tuples of free index ids and dimensions if 1: efi = expression.ufl_free_indices efid = expression.ufl_index_dimensions fi = list(zip(efi, efid)) for pos, ind in enumerate(multiindex._indices): if isinstance(ind, Index): fi.append((ind.count(), shape[pos])) fi = unique_sorted_indices(sorted(fi)) if fi: fi, fid = zip(*fi) else: fi, fid = (), () else: mfiid = [(ind.count(), shape[pos]) for pos, ind in enumerate(multiindex._indices) if isinstance(ind, Index)] mfi, mfid = zip(*mfiid) if mfiid else ((), ()) fi, fid = merge_unique_indices(expression.ufl_free_indices, expression.ufl_index_dimensions, mfi, mfid) # Cache free index and dimensions self.ufl_free_indices = fi self.ufl_index_dimensions = fid
def ufl_domains(self): # Because this type can act like a terminal if it has no # operands, we need to override some recursive operations if self.ufl_operands: return Operator.ufl_domains() else: return []
def __new__(cls, *expressions): # All lists and tuples should already be unwrapped in # as_tensor if any(not isinstance(e, Expr) for e in expressions): error("Expecting only UFL expressions in ListTensor constructor.") # Get properties of the first expression e0 = expressions[0] sh = e0.ufl_shape fi = e0.ufl_free_indices fid = e0.ufl_index_dimensions # Obviously, each subexpression must have the same shape if any(sh != e.ufl_shape for e in expressions[1:]): error( "Cannot create a tensor by joining subexpressions with different shapes." ) if any(fi != e.ufl_free_indices for e in expressions[1:]): error( "Cannot create a tensor where the components have different free indices." ) if any(fid != e.ufl_index_dimensions for e in expressions[1:]): error( "Cannot create a tensor where the components have different free index dimensions." ) # Simplify to Zero if possible if all(isinstance(e, Zero) for e in expressions): shape = (len(expressions), ) + sh return Zero(shape, fi, fid) return Operator.__new__(cls)
def __new__(cls, a, b): # Conversion a = as_ufl(a) b = as_ufl(b) # Type checking # TODO: Enabled workaround for nonscalar division in __div__, # so maybe we can keep this assertion. Some algorithms may # need updating. if not is_ufl_scalar(a): error("Expecting scalar nominator in Division.") if not is_true_ufl_scalar(b): error("Division by non-scalar is undefined.") if isinstance(b, Zero): error("Division by zero!") # Simplification # Simplification a/b -> a if isinstance(a, Zero) or (isinstance(b, ScalarValue) and b._value == 1): return a # Simplification "literal a / literal b" -> "literal value of # a/b". Avoiding integer division by casting to float if isinstance(a, ScalarValue) and isinstance(b, ScalarValue): return as_ufl(float(a._value) / float(b._value)) # Simplification "a / a" -> "1" # if not a.ufl_free_indices and not a.ufl_shape and a == b: # return as_ufl(1) # Construction self = Operator.__new__(cls) self._init(a, b) return self
def __new__(cls, *expressions): # All lists and tuples should already be unwrapped in # as_tensor if any(not isinstance(e, Expr) for e in expressions): error("Expecting only UFL expressions in ListTensor constructor.") # Get properties of the first expression e0 = expressions[0] sh = e0.ufl_shape fi = e0.ufl_free_indices fid = e0.ufl_index_dimensions # Obviously, each subexpression must have the same shape if any(sh != e.ufl_shape for e in expressions[1:]): error("Cannot create a tensor by joining subexpressions with different shapes.") if any(fi != e.ufl_free_indices for e in expressions[1:]): error("Cannot create a tensor where the components have different free indices.") if any(fid != e.ufl_index_dimensions for e in expressions[1:]): error("Cannot create a tensor where the components have different free index dimensions.") # Simplify to Zero if possible if all(isinstance(e, Zero) for e in expressions): shape = (len(expressions),) + sh return Zero(shape, fi, fid) return Operator.__new__(cls)
def _ufl_expr_reconstruct_(self, expressions, indices): # Special case for simplification as_tensor(A[ii], ii) -> A if isinstance(expressions, Indexed): A, ii = expressions.ufl_operands if indices == ii: return A return Operator._ufl_expr_reconstruct_(self, expressions, indices)
def __new__(cls, a, b): # Conversion a = as_ufl(a) b = as_ufl(b) # Type checking if not is_true_ufl_scalar(a): error("Cannot take the power of a non-scalar expression %s." % ufl_err_str(a)) if not is_true_ufl_scalar(b): error("Cannot raise an expression to a non-scalar power %s." % ufl_err_str(b)) # Simplification if isinstance(a, ScalarValue) and isinstance(b, ScalarValue): return as_ufl(a._value**b._value) if isinstance(b, Zero): return IntValue(1) if isinstance(a, Zero) and isinstance(b, ScalarValue): if isinstance(b, ComplexValue): error("Cannot raise zero to a complex power.") bf = float(b) if bf < 0: error("Division by zero, cannot raise 0 to a negative power.") else: return zero() if isinstance(b, ScalarValue) and b._value == 1: return a # Construction self = Operator.__new__(cls) self._init(a, b) return self
def __new__(cls, arg1, arg2): if isinstance(arg1, (RealValue, Zero)) and isinstance( arg2, (RealValue, Zero)): return FloatValue(math.atan2(float(arg1), float(arg2))) if isinstance(arg1, (ComplexValue)) or isinstance(arg2, (ComplexValue)): raise TypeError("Atan2 does not support complex numbers.") return Operator.__new__(cls)
def __init__(self, expression, indices): if not isinstance(expression, Expr): error("Expecting ufl expression.") if expression.ufl_shape != (): error("Expecting scalar valued expression.") if not isinstance(indices, MultiIndex): error("Expecting a MultiIndex.") if not all(isinstance(i, Index) for i in indices): error("Expecting sequence of Index objects, not %s." % indices._ufl_err_str_()) Operator.__init__(self, (expression, indices)) fi, fid, sh = remove_indices(expression.ufl_free_indices, expression.ufl_index_dimensions, [ind.count() for ind in indices]) self.ufl_free_indices = fi self.ufl_index_dimensions = fid self.ufl_shape = sh
def __init__(self, name, classname, nu, argument): if not is_true_ufl_scalar(nu): error("Expecting scalar nu.") if not is_true_ufl_scalar(argument): error("Expecting scalar argument.") # Use integer representation if suitable fnu = float(nu) inu = int(nu) if fnu == inu: nu = as_ufl(inu) else: nu = as_ufl(fnu) Operator.__init__(self, (nu, argument)) self._classname = classname self._name = name
def __new__(cls, expression, indices): # Simplify if isinstance(expression, Zero): fi, fid, sh = remove_indices(expression.ufl_free_indices, expression.ufl_index_dimensions, [ind.count() for ind in indices]) return Zero(sh, fi, fid) # Construct return Operator.__new__(cls)
def __init__(self, condition, true_value, false_value): if not isinstance(condition, Condition): error("Expectiong condition as first argument.") true_value = as_ufl(true_value) false_value = as_ufl(false_value) tsh = true_value.ufl_shape fsh = false_value.ufl_shape if tsh != fsh: error("Shape mismatch between conditional branches.") tfi = true_value.ufl_free_indices ffi = false_value.ufl_free_indices if tfi != ffi: error("Free index mismatch between conditional branches.") if isinstance(condition, (EQ, NE)): if not all((condition.ufl_operands[0].ufl_shape == (), condition.ufl_operands[0].ufl_free_indices == (), condition.ufl_operands[1].ufl_shape == (), condition.ufl_operands[1].ufl_free_indices == ())): error("Non-scalar == or != is not allowed.") Operator.__init__(self, (condition, true_value, false_value))
def __new__(cls, a): a = as_ufl(a) # Simplification if isinstance(a, (Abs, Real, Imag, Zero)): return a if isinstance(a, Conj): return a.ufl_operands[0] if isinstance(a, ScalarValue): return as_ufl(a._value.conjugate()) return Operator.__new__(cls)
def __new__(cls, a): a = as_ufl(a) # Simplification if isinstance(a, (Zero, Abs)): return a if isinstance(a, Conj): return Abs(a.ufl_operands[0]) if isinstance(a, ScalarValue): return as_ufl(abs(a._value)) return Operator.__new__(cls)
def __new__(cls, a): a = as_ufl(a) # Simplification if isinstance(a, Zero): return a if isinstance(a, (Real, Imag, Abs)): return Zero(a.ufl_shape, a.ufl_free_indices, a.ufl_index_dimensions) if isinstance(a, ScalarValue): return as_ufl(a.imag()) return Operator.__new__(cls)
def __new__(cls, a): a = as_ufl(a) # Simplification if isinstance(a, Conj): a = a.ufl_operands[0] if isinstance(a, Zero): return a if isinstance(a, ScalarValue): return as_ufl(a.real()) if isinstance(a, Real): a = a.ufl_operands[0] return Operator.__new__(cls)
def __new__(cls, a, b): # Make sure everything is an Expr a = as_ufl(a) b = as_ufl(b) # Assert consistent tensor properties sh = a.ufl_shape fi = a.ufl_free_indices fid = a.ufl_index_dimensions if b.ufl_shape != sh: error("Can't add expressions with different shapes.") if b.ufl_free_indices != fi: error("Can't add expressions with different free indices.") if b.ufl_index_dimensions != fid: error("Can't add expressions with different index dimensions.") # Skip adding zero if isinstance(a, Zero): return b elif isinstance(b, Zero): return a # Handle scalars specially and sort operands sa = isinstance(a, ScalarValue) sb = isinstance(b, ScalarValue) if sa and sb: # Apply constant propagation return as_ufl(a._value + b._value) elif sa: # Place scalar first # operands = (a, b) pass # a, b = a, b elif sb: # Place scalar first # operands = (b, a) a, b = b, a # elif a == b: # # Replace a+b with 2*foo # return 2*a else: # Otherwise sort operands in a canonical order # operands = (b, a) a, b = sorted_expr((a, b)) # construct and initialize a new Sum object self = Operator.__new__(cls) self._init(a, b) return self
def __new__(cls, a, b): # Conversion a = as_ufl(a) b = as_ufl(b) # Type checking # Make sure everything is scalar if a.ufl_shape or b.ufl_shape: error("Product can only represent products of scalars, " "got\n\t%s\nand\n\t%s" % (ufl_err_str(a), ufl_err_str(b))) # Simplification if isinstance(a, Zero) or isinstance(b, Zero): # Got any zeros? Return zero. fi, fid = merge_unique_indices(a.ufl_free_indices, a.ufl_index_dimensions, b.ufl_free_indices, b.ufl_index_dimensions) return Zero((), fi, fid) sa = isinstance(a, ScalarValue) sb = isinstance(b, ScalarValue) if sa and sb: # const * const = const # FIXME: Handle free indices like with zero? I think # IntValue may be index annotated now? return as_ufl(a._value * b._value) elif sa: # 1 * b = b if a._value == 1: return b # a, b = a, b elif sb: # a * 1 = a if b._value == 1: return a a, b = b, a # elif a == b: # a * a = a**2 # TODO: Why? Maybe just remove this? # if not a.ufl_free_indices: # return a**2 else: # a * b = b * a # Sort operands in a semi-canonical order # (NB! This is fragile! Small changes here can have large effects.) a, b = sorted_expr((a, b)) # Construction self = Operator.__new__(cls) self._init(a, b) return self
def __new__(cls, expression, multiindex): if isinstance(expression, Zero): # Zero-simplify indexed Zero objects shape = expression.ufl_shape efi = expression.ufl_free_indices efid = expression.ufl_index_dimensions fi = list(zip(efi, efid)) for pos, ind in enumerate(multiindex._indices): if isinstance(ind, Index): fi.append((ind.count(), shape[pos])) fi = unique_sorted_indices(sorted(fi)) if fi: fi, fid = zip(*fi) else: fi, fid = (), () return Zero(shape=(), free_indices=fi, index_dimensions=fid) else: return Operator.__new__(cls)
def __new__(cls, summand, index): # Error checks if not isinstance(summand, Expr): error("Expecting Expr instance, got %s" % ufl_err_str(summand)) if not isinstance(index, MultiIndex): error("Expecting MultiIndex instance, got %s" % ufl_err_str(index)) if len(index) != 1: error("Expecting a single Index but got %d." % len(index)) # Simplification to zero if isinstance(summand, Zero): sh = summand.ufl_shape j, = index fi = summand.ufl_free_indices fid = summand.ufl_index_dimensions pos = fi.index(j.count()) fi = fi[:pos] + fi[pos + 1:] fid = fid[:pos] + fid[pos + 1:] return Zero(sh, fi, fid) return Operator.__new__(cls)
def __new__(cls, summand, index): # Error checks if not isinstance(summand, Expr): error("Expecting Expr instance, got %s" % ufl_err_str(summand)) if not isinstance(index, MultiIndex): error("Expecting MultiIndex instance, got %s" % ufl_err_str(index)) if len(index) != 1: error("Expecting a single Index but got %d." % len(index)) # Simplification to zero if isinstance(summand, Zero): sh = summand.ufl_shape j, = index fi = summand.ufl_free_indices fid = summand.ufl_index_dimensions pos = fi.index(j.count()) fi = fi[:pos] + fi[pos+1:] fid = fid[:pos] + fid[pos+1:] return Zero(sh, fi, fid) return Operator.__new__(cls)
def __new__(cls, arg1, arg2): if isinstance(arg1, (ScalarValue, Zero)) and isinstance( arg2, (ScalarValue, Zero)): return FloatValue(math.atan2(float(arg1), float(arg2))) return Operator.__new__(cls)
def __init__(self, left, right): Operator.__init__(self, (left, right)) if not (is_true_ufl_scalar(left) and is_true_ufl_scalar(right)): error("Expecting scalar arguments.")
def __init__(self, *operands): Operator.__init__(self, operands) if not all(isinstance(i, Expr) for i in operands): error("Expecting Expr in ExprList.")
def __init__(self, *operands): Operator.__init__(self, operands) if not all(isinstance(e, Expr) for e in operands): error("Expecting Expr in ExprMapping.")
def __new__(cls, arg1, arg2): if isinstance(arg1, (RealValue, Zero)) and isinstance(arg2, (RealValue, Zero)): return FloatValue(math.atan2(float(arg1), float(arg2))) if isinstance(arg1, (ComplexValue)) or isinstance(arg2, (ComplexValue)): raise TypeError("Atan2 does not support complex numbers.") return Operator.__new__(cls)
def __init__(self, name, argument): Operator.__init__(self, (argument,)) if not is_true_ufl_scalar(argument): error("Expecting scalar argument.") self._name = name
def __init__(self, f): if not isinstance(f, FormArgument): error("Can only take reference value of form arguments.") Operator.__init__(self, (f,))
def __init__(self, name, argument): Operator.__init__(self, (argument, )) if not is_true_ufl_scalar(argument): error("Expecting scalar argument.") self._name = name
def __init__(self, f): Operator.__init__(self, (f, ))
def __init__(self, arg1, arg2): Operator.__init__(self, (arg1, arg2)) if not is_true_ufl_scalar(arg1): error("Expecting scalar argument 1.") if not is_true_ufl_scalar(arg2): error("Expecting scalar argument 2.")
def __init__(self, f): Operator.__init__(self, (f,))
def __init__(self, operands): Operator.__init__(self, operands)
def __init__(self, a, b): Operator.__init__(self)