From 1605d293d0c9a11974b1622480af75a927da7158 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 10 Dec 2021 22:06:27 +0100 Subject: [PATCH] Add function integ to control language Trapezoidal rule for integrating a vector. --- examples/various/integrate1.cir | 28 ++++++++++++++++++ src/frontend/evaluate.c | 2 +- src/frontend/parse.c | 1 + src/include/ngspice/fteext.h | 1 + src/maths/cmaths/cmath4.c | 50 +++++++++++++++++++++++++++++++++ src/maths/cmaths/cmath4.h | 2 ++ 6 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 examples/various/integrate1.cir diff --git a/examples/various/integrate1.cir b/examples/various/integrate1.cir new file mode 100644 index 000000000..98629d265 --- /dev/null +++ b/examples/various/integrate1.cir @@ -0,0 +1,28 @@ +Test of integ + +i1 0 1 1 +R1 1 2 1 +C1 2 3 1 ic=0 +Vm1 3 0 0 + +v2 11 0 dc 0 sin (0 1 2) + +v3 31 0 dc 0 pulse (0 1 0.1 0.1 0.1 0.1 0.6) + +.tran 0.01 1 + +.control +run +display +let int1 = integ(Vm1#branch) + +plot int1 v(2) + +let int2 = integ(v(11)) +plot v(11) int2 + +let int3 = integ(v(31)) +plot v(31) int3 + +.endc +.end diff --git a/src/frontend/evaluate.c b/src/frontend/evaluate.c index b13a24d7a..ef0a31308 100644 --- a/src/frontend/evaluate.c +++ b/src/frontend/evaluate.c @@ -838,7 +838,7 @@ apply_func_funcall(struct func *func, struct dvec *v, int *newlength, short int /* Modified for passing necessary parameters to the derive function - A.Roldan */ if (eq(func->fu_name, "interpolate") || eq(func->fu_name, "deriv") || eq(func->fu_name, "group_delay") - || eq(func->fu_name, "fft") || eq(func->fu_name, "ifft")) /* Ack */ + || eq(func->fu_name, "fft") || eq(func->fu_name, "ifft") || eq(func->fu_name, "integ")) { void * (*f) (void *data, short int type, int length, int *newlength, short int *newtype, diff --git a/src/frontend/parse.c b/src/frontend/parse.c index 867950aa2..0f3ce0337 100644 --- a/src/frontend/parse.c +++ b/src/frontend/parse.c @@ -363,6 +363,7 @@ struct func ft_funcs[] = { { "vecd", cx_d }, { "interpolate", (cx_function_t*) cx_interpolate }, { "deriv", (cx_function_t*) cx_deriv }, + { "integ", (cx_function_t*) cx_integ }, { "fft", (cx_function_t*) cx_fft }, { "ifft", (cx_function_t*) cx_ifft }, { "v", NULL }, diff --git a/src/include/ngspice/fteext.h b/src/include/ngspice/fteext.h index 5fc9e77ac..5907badb4 100644 --- a/src/include/ngspice/fteext.h +++ b/src/include/ngspice/fteext.h @@ -123,6 +123,7 @@ extern void *cx_not(void *, short int , int , int *, short int *); extern void *cx_interpolate(void *, short int , int , int *, short int *, struct plot *, struct plot *, int ); extern void *cx_deriv(void *, short int , int , int *, short int *, struct plot *, struct plot *, int ); +extern void *cx_integ(void *, short int , int , int *, short int *, struct plot *, struct plot *, int ); extern void *cx_group_delay(void *, short int , int , int *, short int *, struct plot *, struct plot *, int ); extern void *cx_fft(void *, short int , int , int *, short int *, struct plot *, struct plot *, int ); extern void *cx_ifft(void *, short int , int , int *, short int *, struct plot *, struct plot *, int ); diff --git a/src/maths/cmaths/cmath4.c b/src/maths/cmaths/cmath4.c index c21581c00..174b32f06 100644 --- a/src/maths/cmaths/cmath4.c +++ b/src/maths/cmaths/cmath4.c @@ -435,6 +435,56 @@ cx_deriv(void *data, short int type, int length, int *newlength, short int *newt } +/* integrate a vector using trapezoidal rule */ +void* +cx_integ(void* data, short int type, int length, int* newlength, short int* newtype, struct plot* pl, struct plot* newpl, int grouping) +{ + if (grouping == 0) + grouping = length; + /* First do some sanity checks. */ + if (!pl || !pl->pl_scale || !newpl || !newpl->pl_scale) { + fprintf(cp_err, "Internal error: cx_integ: bad scale\n"); + return (NULL); + } + + *newlength = length; + *newtype = type; + + if (type == VF_COMPLEX) { + fprintf(cp_err, "Error: Function integ is not supported for complex data\n"); + return (NULL); + } + else + { + /* all-real case */ + double* outdata, * indata; + double* scale; + int i; + double delta; + + indata = (double*)data; + outdata = alloc_d(length); + scale = alloc_d(length); + + /* Modified to deal with complex frequency vector */ + if (iscomplex(pl->pl_scale)) + for (i = 0; i < length; i++) + scale[i] = realpart(pl->pl_scale->v_compdata[i]); + else + for (i = 0; i < length; i++) + scale[i] = pl->pl_scale->v_realdata[i]; + + /* use trapezoidal rule */ + outdata[0] = 0; + for (i = 1; i < length; i++) { + delta = scale[i] - scale[i - 1]; + outdata[i] = outdata[i - 1] + (indata[i] + indata[i - 1]) * delta / 2.; + } + + tfree(scale); + return (char*)outdata; + } +} void * cx_group_delay(void *data, short int type, int length, int *newlength, short int *newtype, struct plot *pl, struct plot *newpl, int grouping) diff --git a/src/maths/cmaths/cmath4.h b/src/maths/cmaths/cmath4.h index 723306d17..82f9e6179 100644 --- a/src/maths/cmaths/cmath4.h +++ b/src/maths/cmaths/cmath4.h @@ -13,6 +13,8 @@ void * cx_interpolate(void *data, short int type, int length, int *newlength, short int *newtype, struct plot *pl, struct plot *newpl, int grouping); void * cx_deriv(void *data, short int type, int length, int *newlength, short int *newtype, struct plot *pl, struct plot *newpl, int grouping); +void * cx_integ(void *data, short int type, int length, int *newlength, short int *newtype, + struct plot *pl, struct plot *newpl, int grouping); void * cx_group_delay(void *data, short int type, int length, int *newlength, short int *newtype, struct plot *pl, struct plot *newpl, int grouping); void * cx_fft(void *data, short int type, int length, int *newlength, short int *newtype,