@@ -388,6 +388,40 @@ def evaluate(self, x, mapping, component, index_values):
388388 return math .erf (a )
389389
390390
391+ @ufl_type (is_scalar = True , num_ops = 4 )
392+ class Hypergeometric2F1 (Operator ):
393+ """Class for hypergeometric 2F1 functions."""
394+
395+ __slots__ = "_name"
396+
397+ def __init__ (self , a , b , c , argument ):
398+ """Initialise."""
399+ if not all (is_true_ufl_scalar (f ) for f in (a , b , c )):
400+ raise ValueError ("Expecting scalar (a, b, c)." )
401+ if not is_true_ufl_scalar (argument ):
402+ raise ValueError ("Expecting scalar argument." )
403+
404+ Operator .__init__ (self , (a , b , c , argument ))
405+
406+ self ._name = "hyp2f1"
407+
408+ def evaluate (self , x , mapping , component , index_values ):
409+ """Evaluate."""
410+ try :
411+ import scipy .special # type: ignore
412+ except ImportError :
413+ raise ValueError (
414+ "You must have scipy installed to evaluate hypergeometric functions in python."
415+ )
416+ func = getattr (scipy .special , self ._name )
417+ return func (* (arg .evaluate (x , mapping , component , index_values ) for arg in self .ufl_operands ))
418+
419+ def __str__ (self ):
420+ """Format as a string."""
421+ return f"{ self ._name } ({ self .ufl_operands [0 ]} , { self .ufl_operands [1 ]} , { self .ufl_operands [2 ]} , { self .ufl_operands [3 ]} )"
422+
423+
424+
391425@ufl_type (is_abstract = True , is_scalar = True , num_ops = 2 )
392426class BesselFunction (Operator ):
393427 """Base class for all bessel functions."""
0 commit comments