x = [0.4] # acosh only defined for 1 <= x <= pi if func == 'acosh': x[0] = 1.4 f = ot.SymbolicFunction(['x'], ['2.0*' + func + '(x)']) print('f=', f) print('f(', x[0], ')=%.4e' % f(x)[0]) try: df = f.gradient(x)[0, 0] except: pass else: f.setGradient( ot.CenteredFiniteDifferenceGradient( ot.ResourceMap.GetAsScalar( 'CenteredFiniteDifferenceGradient-DefaultEpsilon'), f.getEvaluation())) df2 = f.gradient(x)[0, 0] print('df(', x[0], ')=%.4e' % df, 'df (FD)=%.4e' % df2) if abs(df) > 1e-5: err_g = abs(df2 / df - 1.) else: err_g = abs(df - df2) if err_g > 1e-5: print('GRADIENT ERROR! check ' + func + ' gradient, err=%.12g' % err_g) try: d2f = f.hessian(x)[0, 0, 0] except: pass else:
# the characteristic of the considered difference steps. def myPythonFunction(X): x1, x2, x3, x4 = X return [np.cos(x2 * x2 + x4) / (x1 * x1 + 1. + x3**4)] myFunc = ot.PythonFunction(4, 1, myPythonFunction) # %% # For instance, a user-defined constant step value can be considered gradEpsilon = [1e-8] * 4 hessianEpsilon = [1e-7] * 4 gradStep = ot.ConstantStep(gradEpsilon) # Costant gradient step hessianStep = ot.ConstantStep(hessianEpsilon) # Constant Hessian step myFunc.setGradient( ot.CenteredFiniteDifferenceGradient(gradStep, myFunc.getEvaluation())) myFunc.setHessian( ot.CenteredFiniteDifferenceHessian(hessianStep, myFunc.getEvaluation())) # %% # Alternatively, we can consider a finite difference step value which # depends on the location in the input space by relying on the BlendedStep class: gradEpsilon = [1e-8] * 4 hessianEpsilon = [1e-7] * 4 gradStep = ot.BlendedStep(gradEpsilon) # Costant gradient step hessianStep = ot.BlendedStep(hessianEpsilon) # Constant Hessian step myFunc.setGradient( ot.CenteredFiniteDifferenceGradient(gradStep, myFunc.getEvaluation())) myFunc.setHessian( ot.CenteredFiniteDifferenceHessian(hessianStep, myFunc.getEvaluation()))
# %% # When the considered function has no analytical expression, the gradient may not be known. # In this case, a constant step finite difference gradient definition may be used. # %% def cantilever_beam_python(X): E, F, L, I = X return [F*L**3/(3*E*I)] cbPythonFunction = ot.PythonFunction(4, 1, func=cantilever_beam_python) epsilon = [1e-8]*4 # Here, a constant step of 1e-8 is used for every dimension gradStep = ot.ConstantStep(epsilon) cbPythonFunction.setGradient(ot.CenteredFiniteDifferenceGradient(gradStep, cbPythonFunction.getEvaluation())) G = ot.CompositeRandomVector(cbPythonFunction, vect) event = ot.ThresholdEvent(G, ot.Greater(), 0.3) event.setName("deviation") # %% # However, given the different nature of the model variables, a blended (variable) # finite difference step may be preferable: # The step depends on the location in the input space gradStep = ot.BlendedStep(epsilon) cbPythonFunction.setGradient(ot.CenteredFiniteDifferenceGradient(gradStep, cbPythonFunction.getEvaluation())) G = ot.CompositeRandomVector(cbPythonFunction, vect) event = ot.ThresholdEvent(G, ot.Greater(), 0.3) event.setName("deviation")
#! /usr/bin/env python from __future__ import print_function import openturns as ot eps = 1e-2 # Instance creation myFunc = ot.Function(['x1', 'x2'], ['f1', 'f2', 'f3'], ['x1*sin(x2)', 'cos(x1+x2)', '(x2+1)*exp(x1-2*x2)']) print("myFunc (before substitution) = ", repr(myFunc)) epsilon = ot.Point(myFunc.getInputDimension(), eps) inPoint = ot.Point(epsilon.getDimension(), 1.0) myGradient = ot.CenteredFiniteDifferenceGradient(epsilon, myFunc.getEvaluation()) print("myGradient=", repr(myGradient)) print("myFunc.gradient(", repr(inPoint), ")=", repr(myFunc.gradient(inPoint))) print("myGradient.gradient(", repr(inPoint), ")=", repr(myGradient.gradient(inPoint))) # Substitute the gradient myFunc.setGradient(myGradient) print("myFunc (after substitution) = ", repr(myFunc)) print("myFunc.gradient(", repr(inPoint), ")=", repr(myFunc.gradient(inPoint)), " (after substitution)")