Skip to content

Question: behavior of sigmoid and Indicators #320

@nkoukpaizan

Description

@nkoukpaizan

A couple of thoughts on the sigmoid and indicator functions in IEEET1 and Tgov1.

  1. In Modify Smooth Approximation of Limits #313, I moved the definition of these math functions to a common file, such that all models will use the same functions. However, I am finding out in testing PhasorDynamics simulations with sparse Jacobians #312 that the values of $\mu$ for finite numerical derivatives is not the same for IEEET1 and Tgov1. I need a lower value of $\mu$ for the IEEET1 example after the fault ($\sim 12$ versus $240$). To me, this points to the need to normalize the variables in the exponential form $\left( \dfrac{1}{1+e^{-\alpha x}} \to \dfrac{1}{1+e^{-\alpha x/x_{ref}}} \right)$ to ensure the derivative is finite. Otherwise, it will always be possible to pass values of $x$ that will break the derivative, even if we set $\mu$ to lower values. The alternative would be to revert to the absolute value form, whose derivative is less sensitive.
  2. The behavior of the indicator is significantly different when $f \simeq 0$ versus $\lvert f\rvert >> 0$ and I am concerned this will affect the verification with other tools. In particular below is a plot with $\sigma(f)\rvert_{0} =0.5$, where the indicator values are 0.5 outside of the target range. I've included $\sigma(f)\rvert_{-0.25} = 0$ and $\sigma(f)\rvert_{0.25} = 1$ results as well for comparison. If I read the equations correctly, the desired value outside of the target range is 0.

$\sigma(f)\rvert_{-0.25} = 0$
Image

$\sigma(f)\rvert_{0} =0.5$
Image

$\sigma(f)\rvert_{0.25} = 1$
Image

Below is the code I used to plot, with the parameter choices
import numpy as np
import matplotlib.pyplot as plt
import ipywidgets as widgets
from ipywidgets import interact
# Enable the matplotlib widget backend in a Jupyter environment
%matplotlib widget 

plt.rc('text', usetex=False)
plt.rc('font', family='serif')
plt.rc('figure', figsize=(12,5))
opacity   = 0.9
linewidthVal = 2.0
fontsizeVal = 16
colors = ['k', 'b', 'r', 'c', 'y', 'm', 'g']

def sigmoid_exp(x):
    MU = 240.0
    return 1.0 / (1.0 + np.exp(-MU * x))

def sigmoid_abs(x):
    MU = 40000
    return (0.5 * MU * x) / (1.0 + np.abs(MU * x)) + 0.5

def sigmoid(x):
    return sigmoid_exp(x)

def indicator_low(limit_min, x, f):
    return sigmoid(limit_min - x) * sigmoid(-f)

def indicator_high(limit_max, x, f):
    return sigmoid(x - limit_max) * sigmoid(f)

def indicator(limit_min, limit_max, x, f):
    return (1.0 - indicator_low(limit_min, x, f)) * (1.0 - indicator_high(limit_max, x, f))

def make_plot(func):
    x_min = -0.5
    x_max = 0.5
    x = np.linspace(2*x_min, 2*x_max, 1000)
    
    plt.clf()
    plt.plot(x, sigmoid_exp(x), '-', linewidth=linewidthVal, color=colors[0], label='sigmoid_exp (240)')
    plt.plot(x, indicator_low(x_min, x, func), '-', linewidth=linewidthVal, color=colors[1], label='indicator_low')
    plt.plot(x, indicator_high(x_max, x, func), '-', linewidth=linewidthVal, color=colors[2], label='indicator_high')
    plt.plot(x, indicator(x_min, x_max, x, func), '-', linewidth=linewidthVal, color=colors[3], label='indicator')
    plt.xlabel('x', fontsize=fontsizeVal*1.2, style='italic')
    plt.ylabel('y', fontsize=fontsizeVal*1.2, style='italic')
    plt.legend(fontsize=fontsizeVal)
    plt.xticks(fontsize=fontsizeVal)
    plt.yticks(fontsize=fontsizeVal)
    plt.show()

interact(make_plot, func=(-1.0, 1.0, 0.25));

Thoughts?
CC @pelesh @abirchfield @lukelowry

Metadata

Metadata

Assignees

Labels

questionFurther information is requested

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions