Add a generator for SEE (single event effects) pulses as a code model.

To be used like
aseegen1 NULL [%id(xcell.n1 m1) %id(xcell.n2 m2) %id(xcell.n1 m1) %id(xcell.n2 m2)] seemod1
.model seemod1 seegen (tdelay = 11n tperiod=25n tfall='tfall' trise='trise' let='let' cdepth='d')
see README.SEEgenerator for details
This commit is contained in:
Holger Vogt
2025-07-29 10:39:58 +02:00
parent 878d7e1ff9
commit b628032d7d
20 changed files with 1185 additions and 0 deletions
+1
View File
@@ -10,3 +10,4 @@ zener
memristor
sidiode
pswitch
seegenerator
@@ -0,0 +1,231 @@
/*.......1.........2.........3.........4.........5.........6.........7.........8
================================================================================
FILE seegenerator/cfunc.mod
Public Domain
Universty Duisburg-Essen
Duisburg, Germany
Project Flowspace
AUTHORS
19 May 2025 Holger Vogt
MODIFICATIONS
SUMMARY
This file contains the model-specific routines used to
functionally describe the see (single event effects) generator code model.
INTERFACES
FILE ROUTINE CALLED
REFERENCED FILES
Inputs from and outputs to ARGS structure.
NON-STANDARD FEATURES
NONE
===============================================================================*/
/*=== INCLUDE FILES ====================*/
/*=== CONSTANTS ========================*/
/*=== MACROS ===========================*/
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
static void
cm_seegen_callback(ARGS, Mif_Callback_Reason_t reason)
{
switch (reason) {
case MIF_CB_DESTROY: {
double *last_t_value = STATIC_VAR (last_t_value);
if (last_t_value)
free(last_t_value);
STATIC_VAR (last_t_value) = NULL;
int *pulse_number = STATIC_VAR (pulse_number);
if (pulse_number)
free(pulse_number);
STATIC_VAR (pulse_number) = NULL;
break;
double *last_ctrl = STATIC_VAR (last_ctrl);
if (last_ctrl)
free(last_ctrl);
STATIC_VAR (last_ctrl) = NULL;
}
}
}
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
/*==============================================================================
FUNCTION void cm_seegen()
AUTHORS
19 May 2025 Holger Vogt
SUMMARY
This function implements the see generator code model.
INTERFACES
FILE ROUTINE CALLED
CMutil.c void cm_smooth_corner();
void cm_smooth_discontinuity();
void cm_climit_fcn()
RETURNED VALUE
Returns inputs and outputs via ARGS structure.
GLOBAL VARIABLES
NONE
NON-STANDARD FEATURES
model source:
Ygor Quadros de Aguiar, Frédéric Wrobel. Jean-Luc Autran, Rubén García Alía
Single-Event Effects, from Space to Accelerator Environments
Springer 2025
==============================================================================*/
/*=== CM_SEEGEN ROUTINE ===*/
void cm_seegen(ARGS) /* structure holding parms,
inputs, outputs, etc. */
{
double tfall; /* pulse fall time */
double trise; /* pulse rise time */
double tdelay; /* delay until first pulse */
double inull; /* max. current of pulse */
double let; /* linear energy transfer */
double cdepth; /* charge collection depth */
double angle; /* particle entrance angle */
double tperiod; /* pulse repetition period */
double ctrlthres; /* control voltage threshold */
double ctrl; /* control input */
double out; /* output current */
double *last_t_value; /* static storage of next pulse time */
int *pulse_number; /* static storage of next pulse time */
double *last_ctrl; /* static storage of last ctrl value */
double tcurr = TIME; /* current simulation time */
if (ANALYSIS == MIF_AC) {
return;
}
/* Retrieve frequently used parameters... */
tfall = PARAM(tfall);
trise = PARAM(trise);
tdelay = PARAM(tdelay);
tperiod = PARAM(tperiod);
inull = PARAM(inull);
let = PARAM(let);
cdepth = PARAM(cdepth);
angle = PARAM(angle);
ctrlthres = PARAM(ctrlthres);
if (PORT_NULL(ctrl))
ctrl = 1;
else
ctrl = INPUT(ctrl);
if (INIT==1) {
/* Allocate storage for last_t_value */
STATIC_VAR(last_t_value) = (double *) malloc(sizeof(double));
last_t_value = (double *) STATIC_VAR(last_t_value);
*last_t_value = tdelay;
STATIC_VAR(pulse_number) = (int *) malloc(sizeof(int));
pulse_number = (int *) STATIC_VAR(pulse_number);
*pulse_number = 1;
STATIC_VAR(last_ctrl) = (double *) malloc(sizeof(double));
last_ctrl = (double *) STATIC_VAR(last_ctrl);
*last_ctrl = ctrl;
/* set breakpoints at first pulse start and pulse maximum times */
double tatmax = *last_t_value + tfall * trise * log(trise/tfall) / (trise - tfall);
cm_analog_set_perm_bkpt(*last_t_value);
cm_analog_set_perm_bkpt(tatmax);
}
else {
last_t_value = (double *) STATIC_VAR(last_t_value);
pulse_number = (int *) STATIC_VAR(pulse_number);
last_ctrl = (double *) STATIC_VAR(last_ctrl);
if (*last_ctrl < ctrlthres && ctrl >= ctrlthres) {
*last_t_value = *last_t_value + tcurr;
*last_ctrl = ctrl;
}
/* the double exponential current pulse function */
if (tcurr < *last_t_value)
out = 0;
else {
if (inull == 0) {
double LETeff = let/cos(angle);
double Qc = 1.035e-14 * LETeff * cdepth;
inull = Qc / (tfall - trise);
}
out = inull * (exp(-(tcurr-*last_t_value)/tfall) - exp(-(tcurr-*last_t_value)/trise));
}
if (tcurr > *last_t_value + tperiod * 0.9) {
/* return some info */
cm_message_printf("port name: out, node pair no.: %d, \nnode names: %s, %s, pulse time: %e",
*pulse_number, cm_get_node_name("out", *pulse_number - 1),
cm_get_neg_node_name("out", *pulse_number - 1), *last_t_value);
/* set the time for the next pulse */
*last_t_value = *last_t_value + tperiod;
/* set breakpoints at new pulse start and pulse maximum times */
double tatmax = *last_t_value + tfall * trise * log(trise/tfall) / (trise - tfall);
cm_analog_set_perm_bkpt(*last_t_value);
cm_analog_set_perm_bkpt(tatmax);
(*pulse_number)++;
if (*pulse_number > PORT_SIZE(out)) {
if (PARAM(perlim) == FALSE)
*pulse_number = 1;
else
*last_t_value = 1e12; /* stop any output */
}
}
if (*pulse_number - 1 < PORT_SIZE(out))
OUTPUT(out[*pulse_number - 1]) = out;
}
}
@@ -0,0 +1,120 @@
/*.......1.........2.........3.........4.........5.........6.........7.........8
================================================================================
Public Domain
Universty Duisburg-Essen
Duisburg, Germany
Project Flowspace
AUTHORS
Holger Vogt 19 May 2025
SUMMARY
This file contains the interface specification file for the
analog seegen code model.
===============================================================================*/
NAME_TABLE:
C_Function_Name: cm_seegen
Spice_Model_Name: seegen
Description: "single event effect generator"
PORT_TABLE:
Port_Name: ctrl out
Description: "control input" "output"
Direction: in out
Default_Type: v i
Allowed_Types: [v,vd,i,id] [i,id]
Vector: no yes
Vector_Bounds: - [1 -]
Null_Allowed: yes no
PARAMETER_TABLE:
Parameter_Name: tfall trise
Description: "pulse fall time" "pulse rise time"
Data_Type: real real
Default_Value: 500e-12 20e-12
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: tdelay inull
Description: "pulse delay" "max current"
Data_Type: real real
Default_Value: 0 0
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: tperiod ctrlthres
Description: "pulse repetition" "control voltage threshold"
Data_Type: real real
Default_Value: 0 0.5
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: let cdepth
Description: "lin energy transfer" "charge collection depth"
Data_Type: real real
Default_Value: 10 1
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: angle perlim
Description: "particle angle" "pulse repetition"
Data_Type: real boolean
Default_Value: 0 TRUE
Limits: [0 1.57079] -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
STATIC_VAR_TABLE:
Static_Var_Name: last_t_value
Data_Type: pointer
Vector: no
Description: "next pulse start time"
STATIC_VAR_TABLE:
Static_Var_Name: pulse_number
Data_Type: pointer
Vector: no
Description: "number of pulse"
STATIC_VAR_TABLE:
Static_Var_Name: last_ctrl
Data_Type: pointer
Vector: no
Description: "last control value"