file: Hlib/src/Basis.c
/**************************************************************************/
// //
// Author: T.Warburton // // Design: T.Warburton && S.Sherwin //
// Date : 12/4/96
// // // // Copyright notice: This code shall not
be replicated or used without // // the permission of the author. // //
// /**************************************************************************/
#include <stdio.h>
#include <math.h>
#include <veclib.h>
#include <polylib.h> #include "hotel.h"
/* zeros weights info */ typedef struct
zwinfo
{ int q;
/* number of quadrature points */ char dir;
/* direction of
zeros/weights either 'a', 'b' or 'c' */ double *z;
/* zeros */ double *w;
/* weigths */ struct zwinfo *next;
}
ZWinfo;
/*-------------------------------------------------------------------*
* link list for zeros and weights for jacobi polynomial in [0,1] * * at
the gauss points. Note: alpha > -1 , beta > -1 * *-------------------------------------------------------------------*/
static ZWinfo *zwinf,*zwbase;
static ZWinfo
*addzw(int, char);
void
getzw(int
q, double **z, double **w, char dir){ /* check link list */ for(zwinf
= zwbase;
zwinf;
zwinf = zwinf->next) if(zwinf->q
== q) if(zwinf->dir == dir){ *z = zwinf->z;
*w = zwinf->w;
return;
} /* else add new zeros and weights */ zwinf = zwbase;
zwbase = addzw(q,dir);
zwbase->next = zwinf;
*z =
zwbase->z;
*w = zwbase->w;
return;
} /*--------------------------------------------------------------------------*
* This function gets the zeros and weights in [-1,1]. In the 'a' direction
* * alpha = 0, beta = 0. In the 'b' alpha = 1, beta = 0 and in the 'c'
* * direction alpha = 2, beta = 0. * * Note: that the 'b','c' direction
weights are scaled by (1/2)^alpha * * to be consistent with the jacobean
d(r,s)/d(t,s) * *--------------------------------------------------------------------------*/
static ZWinfo *addzw(int n,
char dir){ ZWinfo *zw = (ZWinfo
*)calloc(1,sizeof(ZWinfo));
zw->q = n;
zw->dir =
dir;
zw->z = dvector(0,n-1);
zw->w = dvector(0,n-1);
#ifndef COMPRESS switch(dir){
case 'a': zwgll(zw->z,zw->w,n);
break;
case 'b': zwgrj(zw->z,zw->w,n,1.0,0.0);
dscal(n,0.5,zw->w,1);
break;
case 'c': zwgrj(zw->z,zw->w,n,2.0,0.0);
dscal(n,0.25,zw->w,1);
break;
case 'g': /* just Gauss points */ zwgl
(zw->z,zw->w,n);
break;
case 'h': /* Gauss points with 1,0 weight */
zwgj (zw->z,zw->w,n,1.0,0.0);
dscal(n,0.5,zw->w,1);
break;
case 'i': zwgj (zw->z,zw->w,n,2.0,0.0);
dscal(n,0.25,zw->w,1);
break;
default: fprintf(stderr,"addzw - incorect
direction specified");
break;
} #else int i;
switch(dir){ case 'a': zwgll(zw->z,zw->w,n);
break;
case 'b': zwgrj(zw->z,zw->w,n,0.0,0.0);
for(i = 0;
i <
n;
++i) zw->w[i] *= (1-zw->z[i])*0.5;
break;
case 'c':
zwgrj(zw->z,zw->w,n,0.0,0.0);
for(i
= 0;
i <
n;
++i){ zw->w[i] *= (1-zw->z[i])*0.5;
zw->w[i] *= (1-zw->z[i])*0.5;
} break;
case 'g': /* just Gauss points */ zwgl
(zw->z,zw->w,n);
break;
case 'h': /* Gauss points with 1,0 weight */
zwgj (zw->z,zw->w,n,0.0,0.0);
for(i =
0;
i <
n;
++i) zw->w[i] *= (1-zw->z[i])*0.5;
break;
case 'i': zwgj
(zw->z,zw->w,n,0.0,0.0);
for(i = 0;
i <
n;
++i){ zw->w[i] *= (1-zw->z[i])*0.5;
zw->w[i] *= (1-zw->z[i])*0.5;
} break;
case 'j': zwgrj(zw->z,zw->w,n,0.0,0.0);
break;
default: fprintf(stderr,"addzw - incorect direction specified");
break;
} #endif return zw;
} typedef struct
iminfo
{ int q1;
/* number of quadrature points */ int q2;
InterpDir
dir;
/* direction of zeros/weights either 'a', 'b' or 'c' */ double **im;
/* zeros */ struct iminfo *next;
}
IMinfo;
/*---------------------------------------------------------------------*
* link list for interpolation matrices: * * InterpDir
: a2b go from gll points to grj_(1,0) points * * b2a go from grj_(1,0)
points to gll points * * b2c go from grj_(1,0) points to grj_(2,0) points
* * c2b go from grj_(2,0) points to grj_(2,0) points * *---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*
* Matrix storage for interpolation matrices: * * InterpDir
: a2a go from gll points to gll points * * a2b go from gll points to grj_(1,0)
points * * a2g go from gll points to gl points * * b2a go from grj_(1,0)
points to gll points * * b2g go from grj_(1,0) points to glj_(2,0) points
* * b2c go from grj_(1,0) points to grj_(2,0) points * * b2g go from grj_(1,0)
points to gl points * * c2b go from grj_(2,0) points to grj_(1,0) points
* * c2c go from grj_(2,0) points to grj_(2,0) points * * c2g go from grj_(2,0)
points to gl points * *---------------------------------------------------------------------*/
static IMinfo *iminf,*imbase;
static IMinfo
*addim(int,int,InterpDir);
//OVERLOAD CALL: addim: Basis.c(?), Basis.c(?)
void
getim(int q1, int q2, double ***im, InterpDir
dir){ /* check link list */ for(iminf = imbase;
iminf;
iminf = iminf->next)
if(iminf->q1 == q1) if(iminf->q2
== q2) if(iminf->dir == dir){ *im = iminf->im;
return;
} /* else add new interpolation matrix */ iminf = imbase;
imbase
= addim(q1,q2,dir);
//OVERLOAD CALL: addim: Basis.c(?),
Basis.c(?) imbase->next = iminf;
*im =
imbase->im;
return;
} #ifndef COMPRESS static IMinfo
*addim(int n1, int n2, InterpDir
dir){ IMinfo *im = (IMinfo
*)malloc(sizeof(IMinfo));
double *z1,*z2,*w;
im->q1
= n1;
im->q2 = n2;
im->dir = dir;
im->im = dmatrix(0,n2-1,0,n1-1);
switch(dir){
case a2a: /* interpolate a to a */ { getzw(n1,&
z1,&
w,'a');
getzw(n2,&
z2,&
w,'a');
igllm(im->im,z1,z2,n1,n2);
break;
} case a2b: /* interpolate a to b */ { getzw(n1,&
z1,&
w,'a');
getzw(n2,&
z2,&
w,'b');
igllm(im->im,z1,z2,n1,n2);
break;
} case a2g: /* interpolate a to g (gauss) */ { getzw(n1,&
z1,&
w,'a');
getzw(n2,&
z2,&
w,'g');
igllm(im->im,z1,z2,n1,n2);
break;
} case b2a: /* interpolate b to a */ { getzw(n1,&
z1,&
w,'b');
getzw(n2,&
z2,&
w,'a');
igrjm(im->im,z1,z2,n1,n2,1.0,0.0);
break;
} case b2b: /* interpolate b to b */ { getzw(n1,&
z1,&
w,'b');
getzw(n2,&
z2,&
w,'b');
igrjm(im->im,z1,z2,n1,n2,1.0,0.0);
break;
} case b2c: /* interpolate b to c */ { getzw(n1,&
z1,&
w,'b');
getzw(n2,&
z2,&
w,'c');
igrjm(im->im,z1,z2,n1,n2,1.0,0.0);
break;
} case b2g: /* interpolate b to g (gauss) */ { getzw(n1,&
z1,&
w,'b');
getzw(n2,&
z2,&
w,'g');
igrjm(im->im,z1,z2,n1,n2,1.0,0.0);
break;
} case b2h: /* interpolate b (Radau) to h (gauss) */ { getzw(n1,&
z1,&
w,'b');
getzw(n2,&
z2,&
w,'h');
igrjm(im->im,z1,z2,n1,n2,1.0,0.0);
break;
} case c2b: /* interpolate c to b */ { getzw(n1,&
z1,&
w,'c');
getzw(n2,&
z2,&
w,'b');
igrjm(im->im,z1,z2,n1,n2,2.0,0.0);
break;
} case c2c: /* interpolate c to c */ { getzw(n1,&
z1,&
w,'c');
getzw(n2,&
z2,&
w,'c');
igrjm(im->im,z1,z2,n1,n2,2.0,0.0);
break;
} case c2g: /* interpolate c to g (gauss) */ { getzw(n1,&
z1,&
w,'c');
getzw(n2,&
z2,&
w,'g');
igrjm(im->im,z1,z2,n1,n2,2.0,0.0);
break;
} case c2h: /* interpolate c (Radau1) to h (gauss) */ { getzw(n1,&
z1,&
w,'c');
getzw(n2,&
z2,&
w,'h');
igrjm(im->im,z1,z2,n1,n2,2.0,0.0);
break;
} case g2g: /* interpolate g (gauss) to g (gauss) */ { getzw(n1,&
z1,&
w,'g');
getzw(n2,&
z2,&
w,'g');
igjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case g2a: /* interpolate g (gauss) to g (gauss) */ { getzw(n1,&
z1,&
w,'g');
getzw(n2,&
z2,&
w,'a');
igjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case g2b: { getzw(n1,&
z1,&
w,'g');
getzw(n2,&
z2,&
w,'b');
igjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case h2b: { getzw(n1,&
z1,&
w,'h');
getzw(n2,&
z2,&
w,'b');
igjm(im->im,z1,z2,n1,n2,1.0,0.0);
break;
} case h2c: { getzw(n1,&
z1,&
w,'h');
getzw(n2,&
z2,&
w,'c');
igjm(im->im,z1,z2,n1,n2,1.0,0.0);
break;
} default: fprintf(stderr,"addim - incorect direction specified");
break;
} return im;
} #else static IMinfo *addim(int
n1, int n2, InterpDir dir){ IMinfo
*im = (IMinfo *)malloc(sizeof(IMinfo));
double *z1,*z2,*w;
im->q1 = n1;
im->q2 = n2;
im->dir = dir;
im->im = dmatrix(0,n2-1,0,n1-1);
switch(dir){ case a2a: /* interpolate a to a */ { getzw(n1,&
z1,&
w,'a');
getzw(n2,&
z2,&
w,'a');
igllm(im->im,z1,z2,n1,n2);
break;
} case a2b: /* interpolate a to b */ { getzw(n1,&
z1,&
w,'a');
getzw(n2,&
z2,&
w,'b');
igllm(im->im,z1,z2,n1,n2);
break;
} case a2g: /* interpolate a to g (gauss) */ { getzw(n1,&
z1,&
w,'a');
getzw(n2,&
z2,&
w,'g');
igllm(im->im,z1,z2,n1,n2);
break;
} case b2a: /* interpolate b to a */ { getzw(n1,&
z1,&
w,'b');
getzw(n2,&
z2,&
w,'a');
igrjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case b2b: /* interpolate b to b */ { getzw(n1,&
z1,&
w,'b');
getzw(n2,&
z2,&
w,'b');
igrjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case b2c: /* interpolate b to c */ { getzw(n1,&
z1,&
w,'b');
getzw(n2,&
z2,&
w,'c');
igrjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case b2g: /* interpolate b to g (gauss) */ { getzw(n1,&
z1,&
w,'b');
getzw(n2,&
z2,&
w,'g');
igrjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case b2h: /* interpolate b (Radau) to h (gauss) */ { getzw(n1,&
z1,&
w,'b');
getzw(n2,&
z2,&
w,'h');
igrjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case c2b: /* interpolate c to b */ { getzw(n1,&
z1,&
w,'c');
getzw(n2,&
z2,&
w,'b');
igrjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case c2c: /* interpolate c to c */ { getzw(n1,&
z1,&
w,'c');
getzw(n2,&
z2,&
w,'c');
igrjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case c2g: /* interpolate c to g (gauss) */ { getzw(n1,&
z1,&
w,'c');
getzw(n2,&
z2,&
w,'g');
igrjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case c2h: /* interpolate c (Radau1) to h (gauss) */ { getzw(n1,&
z1,&
w,'c');
getzw(n2,&
z2,&
w,'h');
igrjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case g2g: /* interpolate g (gauss) to g (gauss) */ { getzw(n1,&
z1,&
w,'g');
getzw(n2,&
z2,&
w,'g');
igjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case g2a: /* interpolate g (gauss) to g (gauss) */ { getzw(n1,&
z1,&
w,'g');
getzw(n2,&
z2,&
w,'a');
igjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case g2b: { getzw(n1,&
z1,&
w,'g');
getzw(n2,&
z2,&
w,'b');
igjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case g2c: { getzw(n1,&
z1,&
w,'g');
getzw(n2,&
z2,&
w,'c');
igjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case h2b: { getzw(n1,&
z1,&
w,'h');
getzw(n2,&
z2,&
w,'b');
igjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} case h2c: { getzw(n1,&
z1,&
w,'h');
getzw(n2,&
z2,&
w,'c');
igjm(im->im,z1,z2,n1,n2,0.0,0.0);
break;
} default: fprintf(stderr,"addim - incorect direction specified");
break;
} return im;
} #endif // L_2 normalise a void
normalise_mode(int
q, double *v, char dir){ if(option("TWOTWO")){
double *z, *w, d, hd;
double *tmp = dvector(0, q-1);
double *tmp1 = dvector(0,
q-1);
getzw(q, &
z, &
w, dir);
dvmul(q, v, 1,
v, 1, tmp, 1);
d = ddot(q, tmp, 1, w, 1);
hd = sqrt(d);
dscal(q, 1./hd,
v, 1);
free(tmp);
free(tmp1);
} return;
} void
normalised_iprod_1d(int
q, double *h, int L, double *m, double *res, double *invnorm, char
dir){ double *wk = dvector(0, q-1);
double *z, *w;
getzw(q,
&
z, &
w, dir);
dvmul(q, w, 1, h, 1, wk, 1);
dgemv('T', q, L, 1.,
m, q, wk, 1, 0.0, res, 1);
dvmul(L, invnorm, 1, res, 1, res, 1);
free(wk);
} // assumes 'a'x'a' // interior modes.. void
quad_normalised_iprod_2d(int
q, double *h, int L, double *m, double *res, double *invnorm) { int
i;
double *wk = dvector(0, q*q-1);
double *wk1 = dvector(0, q*q-1);
double
*z, *w;
getzw(q, &
z, &
w, 'a');
// multiply
field by weights for(i = 0;
i <
q;
++i) dvmul(q, w, 1, h+i*q,1, wk+i*q,1);
for(i = 0;
i <
q;
++i) dvmul(q, w, 1, wk+i,q, wk+i,q);
dgemm('T','N',
L, q, q, 1.0, m, q, wk, q, 0.0, wk1, L);
// 'a' direction dgemm('N','N',
L, L, q, 1.0, wk, L, m, q, 0.0, res, L);
// 'b' direction dvmul(L*L, invnorm,
1, res, 1, res, 1);
free(wk);
free(wk1);
} // assumes 'a'x'b' // interior
modes.. void
tri_normalised_iprod_2d(int
qa, char dira, char dirb, int qb, double *h, int L, double *ma, double
*mb, double *res, double *invnorm) { int i;
double *wk = dvector(0,
max(qa, qb)*max(qa,qb)
-1);
double *wk1 = dvector(0, max(qa, qb)*max(qa,qb)
-1);
double *z, *w, *wk1_a, *res_a;
// multiply field by weights getzw(qa,
&
z, &
w, dira);
for(i = 0;
i <
qb;
++i) dvmul(qa, w,1, h+i*qa,
1, wk+i*qa, 1);
getzw(qb, &
z, &
w, dirb);
for(i
= 0;
i <
qb;
++i) dscal(qa, w[i], wk+i*qa, 1);
// 'a' direction integrals
dgemm('T','N',qb, L, qa, 1.0, wk, qa, ma, qa, 0.0, wk1, qb);
// 'b' direction
integrals wk1_a = wk1;
res_a = res;
// +1 -- ignore first edge mode
for(i = 0;
i <
L;
mb += qb*(L-i+1), wk1_a += qb, res_a+=L-i, ++i) dgemv('T',
qb, L-i, 1.0, mb, qb, wk1_a, 1, 0.0, res_a, 1);
dvmul(L*(L+1)/2, invnorm,
1, res, 1, res, 1);
free(wk);
free(wk1);
} static double
norm(int
np, double *d, char dir){ double fac =0.;
double *tmp = dvector(0,
np-1);
double *z, *w;
getzw(np, &
z, &
w, dir);
dvmul(np, d, 1, d, 1, tmp, 1);
fac = sqrt(ddot(np, tmp, 1, w, 1));
free(tmp);
return fac;
} /* interpolation matrix */ static double ***BasisA_G, ***BasisA_GL,
***BasisA_GR;
static double ****BasisB_G, ****BasisB_GR;
static double
****BasisC_GR, ****BasisC_G;
/* This function initialises the orthogonal
basis statically defined matrices based
on QGmax. These arrays may be accessed form
[1-QGmax]*/ void
init_ortho_basis(void){
BasisA_G = (double ***) calloc(QGmax, sizeof(double **));
BasisA_G -= 1;
BasisA_GL = (double ***) calloc(QGmax, sizeof(double **));
BasisA_GL-=
1;
BasisA_GR = (double ***) calloc(QGmax, sizeof(double **));
BasisA_GR-=
1;
BasisB_G = (double ****)calloc(QGmax, sizeof(double ***));
BasisB_G
-= 1;
BasisB_GR = (double ****)calloc(QGmax, sizeof(double ***));
BasisB_GR-=
1;
BasisC_GR = (double ****)calloc(QGmax, sizeof(double ***));
BasisC_GR-=
1;
BasisC_G = (double ****)calloc(QGmax, sizeof(double ***));
BasisC_G-=
1;
} /* Gets the values of "mode" (0..LGmax)
degree Leg. poly on "size" Gauss points, stores
the result in BasisA_G[size][mode] array
*/ void
get_moda_G (int size, double ***mat){
if (!BasisA_G[size]){ double *w, *z;
int
i;
BasisA_G[size] = dmatrix(0,LGmax-1,0,size-1);
getzw(size,&
z,&
w,'g');
for (i=0;
i <
LGmax;
++i){ jacobf(size,
z, BasisA_G[size][i], i, 0.0, 0.0);
/* normalise so that (g,g)=1*/ #ifndef
NONORM dscal(size,sqrt(0.5*(2.0*i+1.0)),BasisA_G[size][i],1);
#endif }
} *mat = BasisA_G[size];
return;
} /* computes the values of a_mode[mode_a][j],
mode_a=0..LGmax, j=0..size-1, at size Gauss-Lob. points, stores the result
in BasisA_GL[size][mode_a] array */ void
get_moda_GL
(int size, double ***mat){ if (!BasisA_GL[size]){
double *w, *z;
int i;
double *tmp = dvector(0, size-1);
BasisA_GL[size]
= dmatrix(0,LGmax-1,0,size-1);
getzw(size,&
z,&
w,'a');
for (i=0;
i <
LGmax;
++i){ jacobf(size,
z, BasisA_GL[size][i], i, 0.0, 0.0);
#ifndef NONORM /* normalise so that
(g,g)=1*/ dscal(size,sqrt(0.5*(2.0*i+1.0)),BasisA_GL[size][i],1);
#endif
} free(tmp);
} *mat = BasisA_GL[size];
return;
} /* computes the values
of a_mode[mode_a][j], mode_a=0..LGmax, j=0..size-1, at size Gauss-Lob.
points, stores the result in BasisA_GL[size][mode_a] array */ void
get_moda_GR
(int size, double ***mat){ if (!BasisA_GR[size]){
double *w, *z;
int i;
double *tmp = dvector(0, size-1);
BasisA_GR[size]
= dmatrix(0,LGmax-1,0,size-1);
getzw(size,&
z,&
w,'b');
for (i=0;
i <
LGmax;
++i){ jacobf(size,
z, BasisA_GR[size][i], i, 0.0, 0.0);
#ifndef NONORM /* normalise so that
(g,g)=1*/ dscal(size,sqrt(0.5*(2.0*i+1.0)),BasisA_GR[size][i],1);
#endif
} free(tmp);
} *mat = BasisA_GR[size];
return;
} /* computes the values
of b dependent modes at either the gauss or gauss radau points depending
on the function and stores the result in BasisB_G
array */ static double ***get_Bmodes(int size,
double *z);
static double ***get_Cmodes(int size,
double *z);
void
get_modb_G (int size,
double ****mat){ if (!BasisB_G[size]){
double *w,*z;
getzw (size,&
z,&
w,'h');
BasisB_G[size]
= get_Bmodes(size,z);
} *mat = BasisB_G[size];
return;
} void
get_modb_GR (int size,
double ****mat){ if (!BasisB_GR[size]){
double *w,*z;
getzw (size,&
z,&
w,'b');
BasisB_GR[size]
= get_Bmodes(size,z);
} *mat = BasisB_GR[size];
return;
} static double ***get_Bmodes(int size,
double *z){ double ***mat;
double fac;
int i,j,cnt;
/* declare matrix
*/ mat = (double ***)malloc(LGmax*sizeof(double **));
mat[0] = (double
**) malloc(LGmax*(LGmax+1)/2*sizeof(double *));
mat[0][0] = (double *)
malloc(LGmax*(LGmax+1)/2*size*sizeof(double));
for(i = 0,cnt=0;
i <
LGmax;
cnt+=LGmax-i,++i) mat[i] = mat[0] + cnt;
for(i = 0,cnt=0;
i <
LGmax;
++i) for(j = 0;
j <
LGmax-i;
++j,++cnt) mat[i][j] = mat[0][0]
+ size*cnt;
dfill(size,1.0,mat[0][0],1);
for(j = 1;
j <
LGmax;
++j){
jacobf(size,z,mat[0][j],j,1.0,0.0);
dvmul(size,mat[0][0],1,mat[0][j],1,mat[0][j],1);
} if(LGmax
> 1){ for(i = 0;
i <
size;
++i) mat[1][0][i] = 1.0 - z[i];
for(j = 1;
j <
LGmax-1;
++j){ jacobf(size,z,mat[1][j],j,3.0,0.0);
dvmul(size,mat[1][0],1,mat[1][j],1,mat[1][j],1);
} for(i = 2;
i <
LGmax;
++i){ dvmul(size,mat[1][0],1,mat[i-1][0],1,mat[i][0],1);
for(j = 1;
j <
LGmax-i;
++j){ jacobf(size,z,mat[i][j],j,2.0*i+1.0,0.0);
dvmul(size,mat[i][0],1,mat[i][j],1,mat[i][j],1);
} } } #ifndef NONORM /*
normalise (recalling factor of
2 for weight (1-b)/2 */ for(i =0, fac = 1.0;
i <
LGmax;
++i, fac *=
0.25) for(j = 0;
j <
LGmax-i;
++j) dscal(size,sqrt((i+j+1.0)*fac),mat[i][j],1);
#endif return mat;
} void
get_modc_GR
(int size, double ****mat){ if (!BasisC_GR[size]){
double *w,*z;
getzw (size,&
z,&
w,'c');
BasisC_GR[size]
= get_Cmodes(size,z);
} *mat = BasisC_GR[size];
return;
} void
get_modc_G (int size, double
****mat){ if (!BasisC_G[size]){ double
*w,*z;
getzw (size,&
z,&
w,'h');
BasisC_G[size]
= get_Cmodes(size,z);
} *mat = BasisC_G[size];
return;
} static double ***get_Cmodes(int size,
double *z){ double ***mat;
double fac;
int i,j,cnt;
/* declare matrix
*/ mat = (double ***)malloc(LGmax*sizeof(double **));
mat[0] = (double
**) malloc(LGmax*(LGmax+1)/2*sizeof(double *));
mat[0][0] = (double *)
malloc(LGmax*(LGmax+1)/2*size*sizeof(double));
for(i = 0,cnt=0;
i <
LGmax;
cnt+=LGmax-i,++i) mat[i] = mat[0] + cnt;
for(i = 0,cnt=0;
i <
LGmax;
++i) for(j = 0;
j <
LGmax-i;
++j,++cnt) mat[i][j] = mat[0][0]
+ size*cnt;
dfill(size,1.0,mat[0][0],1);
for(j = 1;
j <
LGmax;
++j){
jacobf(size,z,mat[0][j],j,2.0,0.0);
dvmul(size,mat[0][0],1,mat[0][j],1,mat[0][j],1);
} if(LGmax
> 1){ for(i = 0;
i <
size;
++i) mat[1][0][i] = 1.0 - z[i];
for(j = 1;
j <
LGmax-1;
++j){ jacobf(size,z,mat[1][j],j,4.0,0.0);
dvmul(size,mat[1][0],1,mat[1][j],1,mat[1][j],1);
} for(i = 2;
i <
LGmax;
++i){ dvmul(size,mat[1][0],1,mat[i-1][0],1,mat[i][0],1);
for(j = 1;
j <
LGmax-i;
++j){ jacobf(size,z,mat[i][j],j,2.0*i+2.0,0.0);
dvmul(size,mat[i][0],1,mat[i][j],1,mat[i][j],1);
} } } #ifndef NONORM /*
normalise (recalling factor of
2 for weight (1-b)/2 */ for(i =0, fac = 1.;
i <
LGmax;
++i, fac *= 0.25)
for(j = 0;
j <
LGmax-i;
++j) dscal(size,sqrt((i+j+1.5)*fac),mat[i][j],1);
#endif return mat;
} void Tri_reset_basis(void);
void Quad_reset_basis(void);
void Tet_reset_basis(void);
void Pyr_reset_basis(void);
void Prism_reset_basis(void);
void Hex_reset_basis(void);
void
reset_bases(){
Tri_reset_basis();
Quad_reset_basis();
Tet_reset_basis();
Pyr_reset_basis();
Prism_reset_basis();
Hex_reset_basis();
} static Basis ****Tri_bbase=NULL;
static
Basis ****Quad_bbase=NULL;
static Basis
*Tet_bbinf=NULL,*Tet_bbase=NULL;
static Basis
*Pyr_bbinf=NULL,*Pyr_bbase=NULL;
static Basis
*Prism_bbinf=NULL,*Prism_bbase=NULL;
static Basis
*Hex_bbinf=NULL,*Hex_bbase=NULL;
static Basis
*Tri_addbase(int L, int qa, int qb, int qc);
static Basis *Quad_addbase(int
L, int qa, int qb, int qc);
static Basis
*Tet_addbase(int L, int qa, int qb, int qc);
static Basis *Pyr_addbase(int
L, int qa, int qb, int qc);
static Basis
*Prism_addbase(int L, int qa, int qb, int
qc);
static Basis *Hex_addbase(int
L, int qa, int qb, int qc);
static void Tri_normalise(Basis
*b, int qa, int qb, int qc);
static void Quad_normalise(Basis
*b, char type );
static void Tet_normalise(Basis
*b, int , int , int );
static void Pyr_normalise(Basis
*, int , int , int );
static void Prism_normalise(Basis
*, int , int , int );
static void Hex_normalise(Basis
*, int , int , int );
/* Function name: Element::getbasis
Function Purpose: Function Notes: */ Basis
*Tri::getbasis(){ int
i,j;
if(!Tri_bbase){ Tri_bbase = (Basis****)
calloc(LGmax+1, sizeof(Basis***));
for(i=0;
i<
LGmax+1;
++i){
Tri_bbase[i] = (Basis***) calloc(QGmax+1,
sizeof(Basis**));
for(j=0;
j<
QGmax+1;
++j)
Tri_bbase[i][j] = (Basis**) calloc(QGmax+1,
sizeof(Basis*));
} } if(!Tri_bbase[lmax][qa][qb])
Tri_bbase[lmax][qa][qb] = Tri_addbase(lmax,qa,qb,qc);
return Tri_bbase[lmax][qa][qb];
} Basis
*Quad::getbasis(){
int i,j;
if(!Quad_bbase){ Quad_bbase
= (Basis****) calloc(LGmax+1, sizeof(Basis***));
for(i=0;
i<
LGmax+1;
++i){ Quad_bbase[i] = (Basis***)
calloc(QGmax+1, sizeof(Basis**));
for(j=0;
j<
QGmax+1;
++j)
Quad_bbase[i][j] = (Basis**) calloc(QGmax+1,
sizeof(Basis*));
} } if(!Quad_bbase[lmax][qa][qb])
Quad_bbase[lmax][qa][qb] = Quad_addbase(lmax,qa,qb,qc);
return Quad_bbase[lmax][qa][qb];
} Basis
*Tet::getbasis(){ /*
check link list */ for(Tet_bbinf = Tet_bbase;
Tet_bbinf;
Tet_bbinf = Tet_bbinf->next)
if(Tet_bbinf->id == lmax){ return Tet_bbinf;
} /* else add new zeros and weights */ Tet_bbinf = Tet_bbase;
Tet_bbase
= Tet_addbase(lmax,qa,qb,qc);
Tet_bbase->next
= Tet_bbinf;
return Tet_bbase;
} Basis
*Pyr::getbasis(){ /*
check link list */ for(Pyr_bbinf = Pyr_bbase;
Pyr_bbinf;
Pyr_bbinf = Pyr_bbinf->next)
if(Pyr_bbinf->id == lmax){ return Pyr_bbinf;
} /* else add new zeros and weights */ Pyr_bbinf = Pyr_bbase;
Pyr_bbase
= Pyr_addbase(lmax,qa,qb,qc);
Pyr_bbase->next
= Pyr_bbinf;
return Pyr_bbase;
} Basis
*Prism::getbasis(){
/* check link list */ for(Prism_bbinf = Prism_bbase;
Prism_bbinf;
Prism_bbinf
= Prism_bbinf->next) if(Prism_bbinf->id
== lmax){ return Prism_bbinf;
} /* else add new zeros and weights */ Prism_bbinf
= Prism_bbase;
Prism_bbase = Prism_addbase(lmax,qa,qb,qc);
Prism_bbase->next = Prism_bbinf;
return Prism_bbase;
} Basis
*Hex::getbasis(){ /*
check link list */ for(Hex_bbinf = Hex_bbase;
Hex_bbinf;
Hex_bbinf = Hex_bbinf->next)
if(Hex_bbinf->id == lmax){ return Hex_bbinf;
} /* else add new zeros and weights */ Hex_bbinf = Hex_bbase;
Hex_bbase
= Hex_addbase(lmax,qa,qb,qc);
Hex_bbase->next
= Hex_bbinf;
return Hex_bbase;
} Basis
*Element::getbasis(){return
(Basis*)NULL;
} static Basis
*Tri_addbase(int L, int qa, int qb, int qc){
Basis *b = Tri_mem_base(L,qa,qb,qc);
/* set up storage */ Tri_mem_modes(b);
/*
set up vertices */ Tri_set_vertices(b->vert,qa,'a');
Tri_set_vertices(b->vert,qb,'b');
if(L>2){
Tri_set_edges(b,qa,'a');
Tri_set_edges(b,qb,'b');
} if(L>3) Tri_set_faces(b,qb,'b');
if(option("Normalise")) Tri_normalise(b,qa,qb,qc);
/* normalise basis so that L2 of each
mode = 1 */ return b;
} static Basis
*Quad_addbase(int L, int qa, int qb, int qc){
Basis *b = Quad_mem_base(L,qa,qb,qc);
/* set up storage */ Quad_mem_modes(b);
/*
set up vertices */ Quad_set_vertices(b,qa,'a');
Quad_set_vertices(b,qb,'b');
if(L>2){
Quad_set_edges(b,qa,'a');
Quad_set_edges(b,qb,'b');
} if(L>2) Quad_set_faces(b,qb,'b');
/* normalise basis so that L2 of each
mode = 1 */ if(option("Normalise"))
Quad_normalise(b,'B');
return b;
} static
Basis *Tet_addbase(int
L, int qa, int qb, int qc){ Basis
*b = Tet_mem_base(L,qa,qb,qc);
/* set up storage
*/ Tet_mem_modes(b);
/* set up vertices */
Tet_set_vertices(b->vert,qa,'a');
Tet_set_vertices(b->vert,qb,'b');
Tet_set_vertices(b->vert,qc,'c');
if(L>2){
Tet_set_edges(b,qa,'a');
Tet_set_edges(b,qb,'b');
Tet_set_edges(b,qc,'c');
} if(L>3){
Tet_set_faces(b,qa,'a');
Tet_set_faces(b,qb,'b');
Tet_set_faces(b,qc,'c');
} if(option("Normalise"))
Tet_normalise(b,qa,qb,qc);
/* normalise basis
so that L2 of each mode = 1 */ return
b;
} static Basis *Pyr_addbase(int
L, int qa, int qb, int qc){ Basis
*b = Pyr_mem_base(L,qa,qb,qc);
/* set up storage
*/ Pyr_mem_modes(b);
/* set up vertices */
Pyr_set_vertices(b->vert,qa,'a');
Pyr_set_vertices(b->vert,qb,'b');
Pyr_set_vertices(b->vert,qc,'c');
if(L>2){
Pyr_set_edges(b,qa,'a');
Pyr_set_edges(b,qa,'b');
Pyr_set_edges(b,qc,'c');
} if(L>3){
Pyr_set_faces(b,qa,'a');
Pyr_set_faces(b,qa,'b');
Pyr_set_faces(b,qc,'c');
} if(option("Normalise"))
Pyr_normalise(b,qa,qb,qc);
/* normalise basis
so that L2 of each mode = 1 */ return
b;
} static Basis *Prism_addbase(int
L, int qa, int qb, int qc){ Basis
*b = Prism_mem_base(L,qa,qb,qc);
/* set up
storage */ Prism_mem_modes(b);
/* set up
vertices */ Prism_set_vertices(b->vert,qa,'a');
Prism_set_vertices(b->vert,qb,'b');
Prism_set_vertices(b->vert,qc,'c');
if(L>2){ Prism_set_edges(b,qa,'a');
Prism_set_edges(b,qa,'b');
Prism_set_edges(b,qc,'c');
} if(L>3){ Prism_set_faces(b,qa,'a');
Prism_set_faces(b,qa,'b');
Prism_set_faces(b,qc,'c');
} if(option("Normalise")) Prism_normalise(b,qa,qb,qc);
/* normalise basis so that L2 of each
mode = 1 */ return b;
} static Basis
*Hex_addbase(int L, int qa, int qb, int qc){
Basis *b = Hex_mem_base(L,qa,qb,qc);
/* set up storage */ Hex_mem_modes(b);
/*
set up vertices */ Hex_set_vertices(b->vert,qa,'a');
if(L>2) Hex_set_edges(b,qa,'a');
if(L>2) Hex_set_faces(b,qa,'a');
if(option("Normalise")) Hex_normalise(b,qa,qb,qc);
/* normalise basis so that L2 of each
mode = 1 */ return b;
} void
Tri_reset_basis(void){
int i,j,k;
if(Tri_bbase){ for(i=0;
i<
LGmax+1;
++i)
for(j=0;
j<
QGmax+1;
++j) for(k=0;
k<
QGmax+1;
++k) if(Tri_bbase[i][j][k]){
free(Tri_bbase[i][j][k]->vert[2].a);
free(Tri_bbase[i][j][k]->vert[2].b);
free(Tri_bbase[i][j][k]->vert);
free(Tri_bbase[i][j][k]->edge);
free(Tri_bbase[i][j][k]->face);
free(Tri_bbase[i][j][k]);
} for(i=0;
i<
LGmax+1;
++i){ for(j=0;
j<
QGmax+1;
++j)
free(Tri_bbase[i][j]);
free(Tri_bbase[i]);
} free(Tri_bbase);
Tri_bbase
= NULL;
} } void
Quad_reset_basis(void){
int i,j,k;
if(Quad_bbase){ for(i=0;
i<
LGmax+1;
++i)
for(j=0;
j<
QGmax+1;
++j) for(k=0;
k<
QGmax+1;
++k) if(Quad_bbase[i][j][k]){
free(Quad_bbase[i][j][k]->vert[1].a);
free(Quad_bbase[i][j][k]->vert[2].b);
free(Quad_bbase[i][j][k]->vert);
free(Quad_bbase[i][j][k]->edge);
free(Quad_bbase[i][j][k]->face);
free(Quad_bbase[i][j][k]);
} for(i=0;
i<
LGmax+1;
++i){ for(j=0;
j<
QGmax+1;
++j)
free(Quad_bbase[i][j]);
free(Quad_bbase[i]);
} free(Quad_bbase);
Quad_bbase
= NULL;
} } void
Tet_reset_basis(void){
for(Tet_bbinf = Tet_bbase;
Tet_bbinf;
Tet_bbinf = Tet_bbinf->next){ free(Tet_bbinf->vert[2].a);
free(Tet_bbinf->vert[3].b);
free(Tet_bbinf->vert[3].c);
free(Tet_bbinf->vert);
free(Tet_bbinf->edge);
free(Tet_bbinf->face);
free(Tet_bbinf->intr);
}
if(Tet_bbase) while(Tet_bbase){ Tet_bbinf
= Tet_bbase->next;
free(Tet_bbase);
Tet_bbase = Tet_bbinf;
} Tet_bbase
= (Basis *)NULL;
} void
Pyr_reset_basis(void){
for(Pyr_bbinf = Pyr_bbase;
Pyr_bbinf;
Pyr_bbinf = Pyr_bbinf->next){ free(Pyr_bbinf->vert[4].a);
// small leak here free(Pyr_bbinf->vert);
free(Pyr_bbinf->edge);
free(Pyr_bbinf->face);
free(Pyr_bbinf->intr);
} if(Pyr_bbase)
while(Pyr_bbase){ Pyr_bbinf = Pyr_bbase->next;
free(Pyr_bbase);
Pyr_bbase
= Pyr_bbinf;
} Pyr_bbase = (Basis *)NULL;
} void
Prism_reset_basis(void){
for(Prism_bbinf = Prism_bbase;
Prism_bbinf;
Prism_bbinf = Prism_bbinf->next){
free(Prism_bbinf->vert[4].a);
// small leak here free(Prism_bbinf->vert);
free(Prism_bbinf->edge);
free(Prism_bbinf->face);
free(Prism_bbinf->intr);
} if(Prism_bbase) while(Prism_bbase){ Prism_bbinf
= Prism_bbase->next;
free(Prism_bbase);
Prism_bbase = Prism_bbinf;
} Prism_bbase
= (Basis *)NULL;
} void
Hex_reset_basis(void){
for(Hex_bbinf = Hex_bbase;
Hex_bbinf;
Hex_bbinf = Hex_bbinf->next){ free(Hex_bbinf->vert[0].a);
free(Hex_bbinf->vert);
free(Hex_bbinf->edge);
free(Hex_bbinf->face);
}
if(Hex_bbase) while(Hex_bbase){ Hex_bbinf
= Hex_bbase->next;
free(Hex_bbase);
Hex_bbase = Hex_bbinf;
} Hex_bbase
= (Basis *)NULL;
} /* set up pointer
structure for basis */ Basis
*Tri_mem_base(int L, int qa, int qb, int qc)
{ register int i,j;
Basis *b = (Basis
*)calloc(1,sizeof(Basis));
Mode
*m;
b->id = L;
b->qa = qa;
b->qb = qb;
b->qc = qc;
/* set up basis
so that all mode structure * * are consequative
from Basis->v[0] */ b->vert = m = mvector(0,NTri_verts
+ NTri_edges*(L-2) + (L-3)*(L-2)/2);
m += NTri_verts;
/* set up edges
*/ b->edge = (Mode **)calloc(NTri_edges,sizeof(Mode
*));
if(L>2) for(i = 0 ;
i <
NTri_edges;
++i,m+=(L-2)) b->edge[i] = m;
/* set up faces */ b->face = (Mode
***)calloc(NTri_faces,sizeof(Mode
**));
if(L>3){ for(i = 0;
i <
NTri_faces;
++i){ b->face[i] = (Mode **)calloc((L-3),sizeof(Mode
*));
for(j = 0;
j <
L-3;
m+= (L-3-j),++j) b->face[i][j] = m;
} } return
b;
} // vertex == 1 mode // edge == L-2
modes // face == (L-2)*(L-2) modes /* set up pointer structure for basis
*/ Basis *Quad_mem_base(int
L, int qa, int qb, int qc) { register int i,j;
Basis
*b = (Basis *)malloc(sizeof(Basis));
Mode *m;
b->id = L;
b->qa = qa;
b->qb
= qb;
b->qc = qc;
/* set up basis so
that all mode structure * * are consequative
from Basis->v[0] */ b->vert = m = mvector(0,NQuad_verts
+ NQuad_edges*(L-2) + (L-2)*(L-2));
m += NQuad_verts;
/* set up edges
*/ b->edge = (Mode **)malloc(NQuad_edges*sizeof(Mode
*));
if(L>2) for(i = 0 ;
i <
NQuad_edges;
++i,m+=(L-2)) b->edge[i] = m;
/* set up faces */ b->face = (Mode
***)malloc(NQuad_faces*sizeof(Mode
**));
if(L>2){ for(i = 0;
i <
NQuad_faces;
++i){ b->face[i] = (Mode **)malloc((L-2)*sizeof(Mode
*));
for(j = 0;
j <
L-2;
m+= (L-2),++j) b->face[i][j] = m;
} } return
b;
} /* set up pointer structure for basis
*/ Basis *Tet_mem_base(int
L, int qa, int qb, int qc) { register int i,j;
Basis
*b = (Basis *)malloc(sizeof(Basis));
Mode *m;
b->id = L;
b->qa = qa;
b->qb
= qb;
b->qc = qc;
/* set up basis so
that all mode structure * * are consequative
from Basis->v[0] */ b->vert = m = mvector(0,NTet_verts
+ NTet_edges*(L-2) + NTet_faces*(L-3)*(L-2)/2
+ (L-4)*(L-3)*(L-2)/6-1);
m += NTet_verts;
/* set up edges */ b->edge = (Mode **)malloc(NTet_edges*sizeof(Mode
*));
if(L>2) for(i = 0 ;
i <
NTet_edges;
++i,m+=(L-2)) b->edge[i] = m;
/* set up faces */ b->face = (Mode
***)malloc(NTet_faces*sizeof(Mode
**));
if(L>3){ for(i = 0;
i <
NTet_faces;
++i){ b->face[i] = (Mode **)malloc((L-3)*sizeof(Mode
*));
for(j = 0;
j <
L-3;
m+= (L-3-j),++j) b->face[i][j] = m;
} } /*
set up interior (3D) */ if(L>4){ b->intr
= (Mode ***)malloc((L-4)*sizeof(Mode
**));
for(i = 0;
i <
L-4;
++i){ b->intr[i] = (Mode
**)malloc((L-4)*sizeof(Mode *));
for(j
= 0;
j <
L-4-i;
m+= (L-4-i-j),++j) b->intr[i][j] = m;
} } return b;
} /* set up pointer structure for basis
*/ Basis *Pyr_mem_base(int
L, int qa, int qb, int qc) { register int i,j;
Basis
*b = (Basis *)malloc(sizeof(Basis));
Mode *m;
b->id = L;
b->qa = qa;
b->qb
= qb;
b->qc = qc;
/* set up basis so
that all mode structure * * are consequative
from Basis->v[0] */ b->vert = m = mvector(0,NPyr_verts
+ NPyr_edges*(L-2) + (L-2)*(L-2)
+ 4*(L-3)*(L-2)/2 + (L-3)*(L-2)*(L-1)/6);
// interior m += NPyr_verts;
/* set up edges */ b->edge = (Mode **)malloc(NPyr_edges*sizeof(Mode
*));
if(L>2) for(i = 0 ;
i <
NPyr_edges;
++i,m+=(L-2)) b->edge[i] = m;
/* set up faces */ b->face = (Mode
***)malloc(NPyr_faces*sizeof(Mode
**));
if(L>2){ b->face[0] = (Mode
**)malloc((L-2)*sizeof(Mode *));
for(j
= 0;
j <
L-2;
m+= (L-2),++j) b->face[0][j] = m;
for(i=1;
i<
NPyr_faces;
++i){
b->face[i] = (Mode **)malloc((L-3)*sizeof(Mode
*));
for(j = 0;
j <
L-3;
m+= (L-3-j),++j) b->face[i][j] = m;
} } /*
set up interior (3D) */ // here if(L>3){
b->intr = (Mode ***)malloc((L-3)*sizeof(Mode
**));
for(i = 0;
i <
L-3;
++i){ b->intr[i] = (Mode
**)malloc((L-3)*sizeof(Mode *));
for(j
= 0;
j <
L-3-i;
m += L-3-i-j, ++j){ b->intr[i][j] = m;
} } } return
b;
} /* set up pointer structure for basis
*/ Basis *Prism_mem_base(int
L, int qa, int qb, int qc) { register int i,j;
Basis
*b = (Basis *)calloc(1,sizeof(Basis));
Mode *m;
b->id = L;
b->qa = qa;
b->qb
= qb;
b->qc = qc;
/* set up basis so
that all mode structure * * are consequative
from Basis->v[0] */ b->vert = m = mvector(0,NPrism_verts
+ NPrism_edges*(L-2) + 3*(L-2)*(L-2)
+ 2*(L-3)*(L-2)/2 + (L-2)*(L-3)*(L-2)/2-1);
m += NPrism_verts;
/* set up edges */ b->edge = (Mode **)calloc(NPrism_edges,sizeof(Mode
*));
if(L>2) for(i = 0 ;
i <
NPrism_edges;
++i,m+=(L-2)) b->edge[i] = m;
/* set up faces */ b->face = (Mode
***)calloc(NPrism_faces,sizeof(Mode
**));
if(L>2){ b->face[0] = (Mode
**)malloc((L-2)*sizeof(Mode *));
for(j
= 0;
j <
L-2;
m+= (L-2),++j) b->face[0][j] = m;
if(L>3){
b->face[1] = (Mode **)malloc((L-3)*sizeof(Mode
*));
for(j = 0;
j <
L-3;
m+= (L-3-j),++j) b->face[1][j] = m;
} b->face[2]
= (Mode **)malloc((L-2)*sizeof(Mode
*));
for(j = 0;
j <
L-2;
m+= (L-2),++j) b->face[2][j] = m;
if(L>3){
b->face[3] = (Mode **)malloc((L-3)*sizeof(Mode
*));
for(j = 0;
j <
L-3;
m+= (L-3-j),++j) b->face[3][j] = m;
} b->face[4]
= (Mode **)malloc((L-2)*sizeof(Mode
*));
for(j = 0;
j <
L-2;
m+= (L-2),++j) b->face[4][j] = m;
} /* set
up interior (3D) */ if(L>3){ b->intr =
(Mode ***)malloc((L-3)*sizeof(Mode
**));
for(i = 0;
i <
L-3;
++i){ b->intr[i] = (Mode
**)malloc((L-2)*sizeof(Mode *));
for(j
= 0;
j <
L-2;
m+= L-3-i,++j) b->intr[i][j] = m;
} } return b;
} /* set
up pointer structure for basis */ Basis
*Hex_mem_base(int L, int qa, int qb, int qc)
{ register int i,j;
Basis *b = (Basis
*)malloc(sizeof(Basis));
Mode
*m;
b->id = L;
b->qa = qa;
b->qb = qb;
b->qc = qc;
/* set up basis
so that all mode structure * * are consequative
from Basis->v[0] */ b->vert = m = mvector(0,NHex_verts
+ NHex_edges*(L-2) + NHex_faces*(L-2)*(L-2)
+ (L-2)*(L-2)*(L-2)-1);
m += NHex_verts;
/* set up edges */ b->edge = (Mode **)malloc(NHex_edges*sizeof(Mode
*));
if(L>2) for(i = 0 ;
i <
NHex_edges;
++i,m+=(L-2)) b->edge[i] = m;
/* set up faces */ b->face = (Mode
***)malloc(NHex_faces*sizeof(Mode
**));
if(L>2){ for(i = 0;
i <
NHex_faces;
++i){ b->face[i] = (Mode **)malloc((L-2)*sizeof(Mode
*));
for(j = 0;
j <
L-2;
m+= (L-2),++j) b->face[i][j] = m;
} } /* set
up interior (3D) */ if(L>2){ b->intr =
(Mode ***)malloc((L-2)*sizeof(Mode
**));
for(i = 0;
i <
L-2;
++i){ b->intr[i] = (Mode
**)malloc((L-2)*sizeof(Mode *));
for(j
= 0;
j <
L-2;
m+= L-2,++j) b->intr[i][j] = m;
} } return b;
} /*----------------------------------------------------------------------------*
* Set up memory for modal storage.
Not all modes need to have independent * * storage since the modes are
repeated. The independent terms in 'a' 'b' * * * * 'a' 'b' * * 1.0 1.0
(3d only ) * * (1+a)/2 (1+b)/2 * * (1-a)/2 (1-b)/2 * * (1-a)/2 (1+a)/2
(1-b)/2 (1+b)/2 P_{m-1}^{1,1}(b) * * (1-a)/2 (1+a)/2 P_1^{1,1}(a) {(1-b)/2}^l
* * (1-a)/2 (1+a)/2 P_{l-2}^{1,1}(a) {(1-b)/2}^2 (1+b)/2 P_{m-1}^{3,1}(b)
* * {(1-b)/2}^l (1+b)/2 P_{m-1}^{2l-1,1}(b) * * * * Each polynomial in
a,b,c are stored contiguously in this order and then * * the appropriate
pointers are assigned to the correct position in this * * vector.
This allows matrix operations in sumfactorisation routines * //OVERLOAD
CALL: vector: Coords.c(?), Curvi.c(?)
*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*
* this routine sets up the storage in continuous vectors as described above
* * it also sets up the pointer system so that the modes can be accessed
* * individually * *---------------------------------------------------------------------------*/
void
Tri_mem_modes(Basis
*b){ register int i,j;
const int L = b->id, qa = b->qa, qb = b->qb;
double *s;
Mode *v = b->vert, **e = b->edge,
***f = b->face;
/* allocate memory
for 'a' polynomials */ s = dvector(0,qa*(L+1)-1);
v[2].a = s;
s += qa;
/* set up pointers */ v[1].a = s;
s += qa;
v[0].a = s;
s += qa;
for(i =
0;
i <
L-2;
++i, s+=qa){ e[0][i].a = s;
e[1][i].a = v[1].a;
e[2][i].a
= v[0].a;
} for(i = 0;
i <
L-3;
++i) for(j = 0;
j <
L-3-i;
++j){
f[0][i][j].a = e[0][i].a;
} /* allocation for b */ s = dvector(0,qb*(L+(L-2)*(L-1)/2)-1);
v[2].b = s;
s += qb;
v[0].b = s;
v[1].b = s;
s += qb;
for(i = 0;
i <
L-2;
++i, s+=qb){ e[1][i].b = s;
e[2][i].b = e[1][i].b;
} for(i = 0;
i
<
L-2;
++i){ e[0][i].b = s;
s+=qb;
for(j = 0;
j <
L-3-i;
++j,s+=qb){
f[0][i][j].b = s;
} } } /*--------------------------------------------------------------------------*
* Set up memory for modal storage.
Not all modes need to have independent * * storage since the modes are
repeated. The independent terms in 'a' 'b' * * 'a' 'b' * * (1+a)/2 (1+b)/2
* * (1-a)/2 (1-b)/2 * * (1-a)/2 (1+a)/2 (1-b)/2 (1+b)/2 * * (1-a)/2 (1+a)/2
P_1^{1,1}(a) (1-b)/2 (1+b)/2 P_1^{1,1}(b) * * (1-a)/2 (1+a)/2 P_{l-2}^{1,1}(a)
(1-b)/2 (1+b)/2 P_{l-2}^{1,1}(b) * * * * * * Each polynomial in a,b,c are
stored contiguously in this order and then * * the appropriate pointers
are assigned to the correct position in this * * vector. This allows
matrix operations in sumfactorisation routines * //OVERLOAD CALL: vector:
Coords.c(?), Curvi.c(?)
*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*
* this routine sets up the storage in continuous vectors as described above*
* it also sets up the pointer system so that the modes can be accessed
* * individually * *--------------------------------------------------------------------------*/
// DONE -- checked void
Quad_mem_modes(Basis
*b){ register int i,j;
const int L = b->id, qa = b->qa, qb = b->qb;
double *s;
Mode *v = b->vert, **e = b->edge,
***f = b->face;
// count up number of different modes /* allocate memory
for 'a' polynomials */ s = dvector(0,qa*L-1);
/* set up pointers */ v[1].a
= v[2].a = s;
s += qa;
v[0].a = v[3].a = s;
s += qa;
for(i = 0;
i <
L-2;
++i, s+=qa){ e[0][i].a = s;
e[1][i].a = v[1].a;
e[2][i].a = s;
e[3][i].a
= v[0].a;
} for(i = 0;
i <
L-2;
++i) for(j = 0;
j <
L-2;
++j) f[0][i][j].a
= e[0][i].a;
/* allocation for b */ s = dvector(0,qb*L-1);
v[3].b = v[2].b
= s;
s += qb;
v[1].b = v[0].b = s;
s += qb;
for(i = 0;
i <
L-2;
++i,
s+=qb){ e[0][i].b = v[1].b;
e[1][i].b = s;
e[2][i].b = v[2].b;
e[3][i].b
= s;
} for(i = 0;
i <
L-2;
++i) for(j = 0;
j <
L-2;
++j) f[0][i][j].b
= e[1][j].b;
} /*----------------------------------------------------------------------------*
* Set up memory for modal storage.
Not all modes need to have independent * * storage since the modes are
repeated. The independent terms in 'a' 'b' * * and 'c' are: * * * * 'a'
'b' * * 1.0 1.0 (3d only ) * * (1+a)/2 (1+b)/2 * * (1-a)/2 (1-b)/2 * *
(1-a)/2 (1+a)/2 (1-b)/2 (1+b)/2 P_{m-1}^{1,1}(b) * * (1-a)/2 (1+a)/2 P_1^{1,1}(a)
{(1-b)/2}^l * * (1-a)/2 (1+a)/2 P_{l-2}^{1,1}(a) {(1-b)/2}^2 (1+b)/2 P_{m-1}^{3,1}(b)
* * {(1-b)/2}^l (1+b)/2 P_{m-1}^{2l-1,1}(b) * * * * 'c' * * (1+c)/2 * *
(1-c)/2 * * {(1-c)/2}^2 * * {(1-c)/2}^{l+m} * * (1-c)/2 (1+c)/2 P_{n-1}^{1,1}(c)
* * {(1-c)/2}^2 (1+c)/2 P_{n-1}^{3,1}(c) * * {(1-c)/2}^{l+m} (1+c)/2 P_{n-1}^{2L+2m-1,1}(c)
* * * * Each polynomial in a,b,c are stored contiguously in this order
and then * * the appropriate pointers are assigned to the correct position
in this * * vector. This allows matrix operations in sumfactorisation
routines * //OVERLOAD CALL: vector: Coords.c(?),
Curvi.c(?) *---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*
* this routine sets up the storage in continuous vectors as described above
* * it also sets up the pointer system so that the modes can be accessed
* * individually * *---------------------------------------------------------------------------*/
void
Tet_mem_modes(Basis
*b){ register int i,j;
const int L = b->id, qa = b->qa, qb = b->qb;
double *s;
Mode *v = b->vert, **e = b->edge,
***f = b->face;
register int k;
int qc = b->qc;
Mode
***in = b->intr;
/* allocate memory
for 'a' polynomials */ s = dvector(0,qa*(L+1)-1);
v[2].a = s;
s += qa;
/* set up pointers */ v[1].a = s;
s += qa;
v[0].a = s;
s += qa;
v[3].a
= v[2].a;
for(i = 0;
i <
L-2;
++i, s+=qa){ e[0][i].a = s;
e[1][i].a
= v[1].a;
e[2][i].a = v[0].a;
e[3][i].a = v[0].a;
e[4][i].a = v[1].a;
e[5][i].a
= v[2].a;
} for(i = 0;
i <
L-3;
++i) for(j = 0;
j <
L-3-i;
++j){
f[0][i][j].a = e[0][i].a;
f[1][i][j].a = e[0][i].a;
f[2][i][j].a = e[1][i].a;
f[3][i][j].a = e[2][i].a;
} for(i = 0;
i <
L-4;
++i) for(j = 0;
j <
L-4-i;
++j) for(k = 0;
k <
L-4-i-j;
++k) in[i][j][k].a = f[0][i][j].a;
/* allocation for b */ s = dvector(0,qb*(L+(L-2)*(L-1)/2+1)-1);
/* set
up modal pointers */ v[3].b = s;
s += qb;
v[2].b = s;
s += qb;
v[0].b =
v[1].b = s;
s+=qb;
for(i = 0;
i <
L-2;
++i, s+=qb){ e[1][i].b = s;
e[2][i].b
= e[1][i].b;
e[3][i].b = v[0].b;
e[4][i].b = v[1].b;
e[5][i].b = v[2].b;
} for(i = 0;
i <
L-2;
++i){ e[0][i].b = s;
s+=qb;
for(j = 0;
j <
L-3-i;
++j,s+=qb){ f[0][i][j].b = s;
f[1][i][j].b = e[0][i].b;
f[2][i][j].b
= e[1][i].b;
f[3][i][j].b = e[2][i].b;
} } for(i = 0;
i <
L-4;
++i)
for(j = 0;
j <
L-4-i;
++j) for(k = 0;
k <
L-4-i-j;
++k) in[i][j][k].b
= f[0][i][j].b;
/* allocation for c */ s = dvector(0,qc*(L+(L-2)*(L-1)/2)-1);
v[3].c = s;
s += qc;
v[0].c = v[1].c = v[2].c = s;
s += qc;
for(i = 0;
i <
L-2;
++i, s+=qc){ e[0][i].c = s;
e[1][i].c = e[0][i].c;
e[2][i].c
= e[0][i].c;
} for(i = 0;
i <
L-2;
++i, s+=qc){ e[3][i].c = s;
e[4][i].c
= e[3][i].c;
e[5][i].c = e[3][i].c;
} for(i = 0;
i <
L-3;
++i) for(j
= 0;
j <
L-3-i;
++j,s+=qc){ f[1][i][j].c = s;
f[2][i][j].c = f[1][i][j].c;
f[3][i][j].c = f[2][i][j].c;
} for(i = 0;
i <
L-3;
++i) for(j = 0;
j
<
(L-3-i);
++j) f[0][i][j].c = e[0][j+i+1].c;
for(i = 0;
i <
L-4;
++i) for(j = 0;
j <
L-4-i;
++j) for(k = 0;
k <
L-4-i-j;
++k) in[i][j][k].c
= f[1][j+i+1][k].c;
} /*----------------------------------------------------------------------------*
* Set up memory for modal storage.
Not all modes need to have independent * * storage since the modes are
repeated. The independent terms in 'a' 'b' * * and 'c' are: * * * * 'a'
'b' * * (1-a)/2 * (1+a)/2 (1-b)/2 * * (1-a)/2 (1+a)/2 (1-b)/2 (1+b)/2 P_{m-1}^{1,1}(b)
* * (1-a)/2 (1+a)/2 P_1^{1,1}(a) {(1-b)/2}^l * * (1-a)/2 (1+a)/2 P_{l-2}^{1,1}(a)
{(1-b)/2}^2 (1+b)/2 P_{m-1}^{3,1}(b) * * {(1-b)/2}^l (1+b)/2 P_{m-1}^{2l-1,1}(b)
* * * * 'c' * * (1+c)/2 * * (1-c)/2 * * {(1-c)/2}^2 * * {(1-c)/2}^{l+m}
* * (1-c)/2 (1+c)/2 P_{n-1}^{1,1}(c) * * {(1-c)/2}^2 (1+c)/2 P_{n-1}^{3,1}(c)
* * {(1-c)/2}^{l+m} (1+c)/2 P_{n-1}^{2L+2m-1,1}(c) * * * * Each polynomial
in a,b,c are stored contiguously in this order and then * * the appropriate
pointers are assigned to the correct position in this * * vector.
This allows matrix operations in sumfactorisation routines * //OVERLOAD
CALL: vector: Coords.c(?), Curvi.c(?)
*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*
* this routine sets up the storage in continuous vectors as described above
* * it also sets up the pointer system so that the modes can be accessed
* * individually * *---------------------------------------------------------------------------*/
void
Pyr_mem_modes(Basis
*b){ register int i,j,k;
const int L = b->id, qa = b->qa, qc = b->qc;
double *sa, *onea, *v1a, *v2a, *eia;
double *sc, *onec, *v1c, *v2c, *eic;
Mode *v = b->vert, **e = b->edge, ***f
= b->face;
Mode ***intr = b->intr;
/*
allocate memory for 'a' polynomials
*/ sa = dvector(0,qa*(L+1)-1);
sc = dvector(0,qc*(1+L+L-2+ (L-2)*(L-2)+(L-3)*(L-2)/2+
(L-3)*(L-2)*(L-1)/6)-1);
// interior onea = sa;
sa += qa;
onec = sc;
sc+=qc;
v1a = sa;
sa += qa;
v1c = sc;
sc+=qc;
eia = sa;
sa += (L-2)*qa;
v2a = sa;
sa += qa;
v2c = sc;
sc+=qc;
// done v[0].a = v1a;
v[0].b = v1a;
v[0].c
= v1c;
v[1].a = v2a;
v[1].b = v1a;
v[1].c = v1c;
v[2].a = v2a;
v[2].b =
v2a;
v[2].c = v1c;
v[3].a = v1a;
v[3].b = v2a;
v[3].c = v1c;
v[4].a = onea;
v[4].b = onea;
v[4].c = v2c;
sa = eia;
for(i = 0;
i <
L-2;
++i, sa+=qa,
sc += qc){ eia = sa;
eic = sc;
e[0][i].a = eia;
e[0][i].b = v1a;
e[1][i].a
= v2a;
e[1][i].b = eia;
e[2][i].a = eia;
e[2][i].b = v2a;
e[3][i].a = v1a;
e[3][i].b = eia;
e[4][i].a = v1a;
e[4][i].b = v1a;
e[4][i].c = eic;
e[5][i].a
= v2a;
e[5][i].b = v1a;
e[5][i].c = eic;
e[6][i].a = v2a;
e[6][i].b = v2a;
e[6][i].c = eic;
e[7][i].a = v1a;
e[7][i].b = v2a;
e[7][i].c = eic;
} for(i
= 0;
i <
L-2;
++i, sc += qc) e[3][i].c = e[2][i].c = e[1][i].c = e[0][i].c
= sc;
for(i = 0;
i <
L-2;
++i) for(j = 0;
j <
L-2;
++j,sc+=qc){ f[0][i][j].a
= e[0][j].a;
f[0][i][j].b = e[0][i].a;
f[0][i][j].c = sc;
} for(i = 0;
i <
L-3;
++i) for(j = 0;
j <
L-3-i;
++j, sc += qc){ f[1][i][j].a
= e[0][i].a;
f[1][i][j].b = v1a;
f[1][i][j].c = sc;
f[3][i][j].a = e[0][i].a;
f[3][i][j].b = v2a;
f[3][i][j].c = sc;
f[2][i][j].a = v2a;
f[2][i][j].b
= e[0][i].a;
f[2][i][j].c = sc;
f[4][i][j].a = v1a;
f[4][i][j].b = e[0][i].a;
f[4][i][j].c = sc;
} // interior // here for(i = 0;
i <
L-3;
++i) for(j
= 0;
j <
L-3-i;
++j) for(k = 0;
k <
L-3-i-j;
++k,sc+=qc){ intr[i][j][k].a
= e[0][i].a;
intr[i][j][k].b = e[0][j].a;
intr[i][j][k].c = sc;
} } /*----------------------------------------------------------------------------*
* Set up memory for modal storage.
Not all modes need to have independent * * storage since the modes are
repeated. The independent terms in 'a' 'b' * * and 'c' are: * * * * 'a'
'b' * * (1-a)/2 * (1+a)/2 (1-b)/2 * * (1-a)/2 (1+a)/2 (1-b)/2 (1+b)/2 P_{m-1}^{1,1}(b)
* * (1-a)/2 (1+a)/2 P_1^{1,1}(a) {(1-b)/2}^l * * (1-a)/2 (1+a)/2 P_{l-2}^{1,1}(a)
{(1-b)/2}^2 (1+b)/2 P_{m-1}^{3,1}(b) * * {(1-b)/2}^l (1+b)/2 P_{m-1}^{2l-1,1}(b)
* * * * 'c' * * (1+c)/2 * * (1-c)/2 * * {(1-c)/2}^2 * * {(1-c)/2}^{l+m}
* * (1-c)/2 (1+c)/2 P_{n-1}^{1,1}(c) * * {(1-c)/2}^2 (1+c)/2 P_{n-1}^{3,1}(c)
* * {(1-c)/2}^{l+m} (1+c)/2 P_{n-1}^{2L+2m-1,1}(c) * * * * Each polynomial
in a,b,c are stored contiguously in this order and then * * the appropriate
pointers are assigned to the correct position in this * * vector.
This allows matrix operations in sumfactorisation routines * //OVERLOAD
CALL: vector: Coords.c(?), Curvi.c(?)
*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*
* this routine sets up the storage in continuous vectors as described above
* * it also sets up the pointer system so that the modes can be accessed
* * individually * *---------------------------------------------------------------------------*/
void
Prism_mem_modes(Basis
*b){ register int i,j,k;
const int L = b->id, qa = b->qa, qc = b->qc;
double *sa, *onea, *v1a, *v2a, *eia;
double *sc, *onec, *v1c, *v2c, *eic;
Mode *v = b->vert, **e = b->edge, ***f
= b->face;
Mode ***intr = b->intr;
/*
allocate memory for 'a' polynomials
*/ sa = dvector(0,qa*(L+1)-1);
sc = dvector(0,qc*(1+L+L-2+(L-3)*(L-2)/2)-1);
onea = sa;
sa += qa;
onec = sc;
sc+=qc;
v1a = sa;
sa += qa;
v1c = sc;
sc+=qc;
eia = sa;
sa += (L-2)*qa;
v2a = sa;
sa += qa;
v2c = sc;
sc+=qc;
// done
v[0].a = v1a;
v[0].b = v1a;
v[0].c = v1c;
v[1].a = v2a;
v[1].b = v1a;
v[1].c
= v1c;
v[2].a = v2a;
v[2].b = v2a;
v[2].c = v1c;
v[3].a = v1a;
v[3].b =
v2a;
v[3].c = v1c;
v[4].a = onea;
v[4].b = v1a;
v[4].c = v2c;
v[5].a =
onea;
v[5].b = v2a;
v[5].c = v2c;
sa = eia;
for(i = 0;
i <
L-2;
++i,
sa+=qa, sc += qc){ eia = sa;
eic = sc;
e[0][i].a = eia;
e[0][i].b = v1a;
e[1][i].a = v2a;
e[1][i].b = eia;
e[1][i].c = v1c;
e[2][i].a = eia;
e[2][i].b
= v2a;
e[3][i].a = v1a;
e[3][i].b = eia;
e[3][i].c = v1c;
e[4][i].a = v1a;
e[4][i].b = v1a;
e[4][i].c = eic;
e[5][i].a = v2a;
e[5][i].b = v1a;
e[5][i].c
= eic;
e[6][i].a = v2a;
e[6][i].b = v2a;
e[6][i].c = eic;
e[7][i].a = v1a;
e[7][i].b = v2a;
e[7][i].c = eic;
e[8][i].a = onea;
e[8][i].b = eia;
e[8][i].c
= v2c;
} for(i = 0;
i <
L-2;
++i, sc += qc) e[2][i].c = e[0][i].c =
sc;
for(i = 0;
i <
L-2;
++i) for(j = 0;
j <
L-2;
++j){ eia = e[0][j].a;
eic = e[4][i].c;
f[0][i][j].a = eia;
f[0][j][i].b = eia;
f[0][i][j].c =
e[0][j].c;
f[2][i][j].a = v2a;
f[2][i][j].b = eia;
f[2][i][j].c = eic;
f[4][i][j].b = eia;
f[4][i][j].a = v1a;
f[4][i][j].c = eic;
} for(i = 0;
i <
L-3;
++i) for(j = 0;
j <
L-3-i;
++j, sc += qc){ f[1][i][j].a
= e[0][i].a;
f[1][i][j].b = v1a;
f[1][i][j].c = sc;
f[3][i][j].a = e[0][i].a;
f[3][i][j].b = v2a;
f[3][i][j].c = sc;
} for(i = 0;
i <
L-3;
++i) for(j
= 0;
j <
L-2;
++j) for(k = 0;
k <
L-3-i;
++k){ intr[i][j][k].a =
e[0][i].a;
intr[i][j][k].b = e[0][j].a;
intr[i][j][k].c = f[1][i][k].c;
} } /*----------------------------------------------------------------------------*
* Set up memory for modal storage.
Not all modes need to have independent * * storage since the modes are
repeated. The independent terms in 'a' 'b' * * and 'c' are: * * * * 'a'
'b' * * (1-a)/2 * (1+a)/2 (1-b)/2 * * (1-a)/2 (1+a)/2 (1-b)/2 (1+b)/2 P_{m-1}^{1,1}(b)
* * (1-a)/2 (1+a)/2 P_1^{1,1}(a) {(1-b)/2}^l * * (1-a)/2 (1+a)/2 P_{l-2}^{1,1}(a)
{(1-b)/2}^2 (1+b)/2 P_{m-1}^{3,1}(b) * * {(1-b)/2}^l (1+b)/2 P_{m-1}^{2l-1,1}(b)
* * * * 'c' * * (1+c)/2 * * (1-c)/2 * * {(1-c)/2}^2 * * {(1-c)/2}^{l+m}
* * (1-c)/2 (1+c)/2 P_{n-1}^{1,1}(c) * * {(1-c)/2}^2 (1+c)/2 P_{n-1}^{3,1}(c)
* * {(1-c)/2}^{l+m} (1+c)/2 P_{n-1}^{2L+2m-1,1}(c) * * * * Each polynomial
in a,b,c are stored contiguously in this order and then * * the appropriate
pointers are assigned to the correct position in this * * vector.
This allows matrix operations in sumfactorisation routines * //OVERLOAD
CALL: vector: Coords.c(?), Curvi.c(?)
*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*
* this routine sets up the storage in continuous vectors as described above
* * it also sets up the pointer system so that the modes can be accessed
* * individually * *---------------------------------------------------------------------------*/
void
Hex_mem_modes(Basis
*b){ register int i,j,k;
const int L = b->id, qa = b->qa;
double *s,
*v1, *v2, *ei, *eia, *eja;
Mode *v =
b->vert, **e = b->edge, ***f = b->face;
Mode
***intr = b->intr;
/* allocate memory
for 'a' polynomials */ s = dvector(0,qa*L-1);
v1 = s;
s+= qa;
ei = s;
s+=
qa*(L-2);
v2 = s;
s+= qa;
v[0].a = v1;
v[0].b = v1;
v[0].c = v1;
v[1].a
= v2;
v[1].b = v1;
v[1].c = v1;
v[2].a = v2;
v[2].b = v2;
v[2].c = v1;
v[3].a = v1;
v[3].b = v2;
v[3].c = v1;
v[4].a = v1;
v[4].b = v1;
v[4].c
= v2;
v[5].a = v2;
v[5].b = v1;
v[5].c = v2;
v[6].a = v2;
v[6].b = v2;
v[6].c = v2;
v[7].a = v1;
v[7].b = v2;
v[7].c = v2;
for(i = 0;
i <
L-2;
++i, ei+=qa){ e[0][i].a = ei;
e[0][i].b = v1;
e[0][i].c = v1;
e[1][i].b
= ei;
e[1][i].a = v2;
e[1][i].c = v1;
e[2][i].a = ei;
e[2][i].b = v2;
e[2][i].c
= v1;
e[3][i].b = ei;
e[3][i].a = v1;
e[3][i].c = v1;
e[4][i].c = ei;
e[4][i].a
= v1;
e[4][i].b = v1;
e[5][i].c = ei;
e[5][i].a = v2;
e[5][i].b = v1;
e[6][i].c
= ei;
e[6][i].a = v2;
e[6][i].b = v2;
e[7][i].c = ei;
e[7][i].a = v1;
e[7][i].b
= v2;
e[8][i].a = ei;
e[8][i].b = v1;
e[8][i].c = v2;
e[9][i].b = ei;
e[9][i].a
= v2;
e[9][i].c = v2;
e[10][i].a = ei;
e[10][i].b = v2;
e[10][i].c = v2;
e[11][i].b = ei;
e[11][i].a = v1;
e[11][i].c = v2;
} for(i = 0;
i <
L-2;
++i) for(j = 0;
j <
L-2;
++j){ eia = e[0][j].a;
eja = e[0][i].a;
f[0][i][j].a = eia;
f[0][i][j].b = eja;
f[0][i][j].c = v1;
f[1][i][j].a
= eia;
f[1][i][j].b = v1;
f[1][i][j].c = eja;
f[2][i][j].a = v2;
f[2][i][j].b
= eia;
f[2][i][j].c = eja;
f[3][i][j].a = eia;
f[3][i][j].b = v2;
f[3][i][j].c
= eja;
f[4][i][j].a = v1;
f[4][i][j].b = eia;
f[4][i][j].c = eja;
f[5][i][j].a
= eia;
f[5][i][j].b = eja;
f[5][i][j].c = v2;
} for(i = 0;
i <
L-2;
++i) for(j = 0;
j <
L-2;
++j) for(k = 0;
k <
L-2;
++k){ intr[i][j][k].a
= e[0][k].a;
intr[i][j][k].b = e[0][j].a;
intr[i][j][k].c = e[0][i].a;
} } void
Tri_set_vertices(Mode
*v, int q, char dir){ double one = 1.0,*z,*w;
getzw(q,&
z,&
w,dir);
switch (dir){ case 'a': dvsub(q,&
one,0,z,1,v[0].a,1);
dscal(q,0.5,v[0].a,1);
dsadd(q,one,z,1,v[1].a,1);
dscal(q,0.5,v[1].a,1);
dfill(q,one,v[2].a,1);
break;
case 'b': dvsub(q,&
one,0,z,1,v[0].b,1);
dscal(q,0.5,v[0].b,1);
dsadd(q,one,z,1,v[2].b,1);
dscal(q,0.5,v[2].b,1);
break;
} } void
Quad_set_vertices(Basis
*b, int q, char dir){ double one = 1.0,*z,*w;
Mode
*v = b->vert;
getzw(q,&
z,&
w,'a');
switch (dir){
case 'a': dvsub(q,&
one,0,z,1,v[0].a,1);
dscal(q,0.5,v[0].a,1);
dsadd(q,one,z,1,v[1].a,1);
dscal(q,0.5,v[1].a,1);
break;
case 'b': dvsub(q,&
one,0,z,1,v[1].b,1);
dscal(q,0.5,v[1].b,1);
dsadd(q,one,z,1,v[3].b,1);
dscal(q,0.5,v[3].b,1);
break;
} } void
Tet_set_vertices(Mode
*v, int q, char dir){ double one = 1.0,*z,*w;
getzw(q,&
z,&
w,dir);
switch (dir){ case 'a': dvsub(q,&
one,0,z,1,v[0].a,1);
dsmul(q,0.5,v[0].a,1,v[0].a,1);
dsadd(q,one,z,1,v[1].a,1);
dsmul(q,0.5,v[1].a,1,v[1].a,1);
dfill(q,one,v[2].a,1);
break;
case 'b': dvsub(q,&
one,0,z,1,v[0].b,1);
dsmul(q,0.5,v[0].b,1,v[0].b,1);
dsadd(q,one,z,1,v[2].b,1);
dsmul(q,0.5,v[2].b,1,v[2].b,1);
dfill(q,one,v[3].b,1);
break;
case 'c': dvsub(q,&
one,0 ,z,1,v[0].c,1);
dsmul(q,0.5,v[0].c,1,v[0].c,1);
dsadd(q,one,z,1,v[3].c,1);
dsmul(q,0.5,v[3].c,1,v[3].c,1);
break;
} } void
Pyr_set_vertices(Mode
*v, int q, char dir){ double one = 1.0,*z,*w;
switch (dir){ case 'a':
getzw(q,&
z,&
w,'a');
dvsub(q,&
one,0,z,1,v[0].a,1);
dscal(q,0.5,v[0].a,1);
// (1-a)/2 dsadd(q,one,z,1,v[1].a,1);
dscal(q,0.5,v[1].a,1);
// (1+a)/2 dfill(q,one,v[4].a,1);
// 1 break;
case 'b': // already set
up in 'a' break;
case 'c': getzw(q,&
z,&
w,'c');
dvsub(q,&
one,0,z,1,v[0].c,1);
dscal(q,0.5,v[0].c,1);
// (1-c)/2 dsadd(q,one,z,1,v[4].c,1);
dscal(q,0.5,v[4].c,1);
// (1+c)/2 break;
} } void
Prism_set_vertices(Mode
*v, int q, char dir){ double one = 1.0,*z,*w;
switch (dir){ case 'a':
getzw(q,&
z,&
w,'a');
dvsub(q,&
one,0,z,1,v[0].a,1);
dscal(q,0.5,v[0].a,1);
// (1-a)/2 dsadd(q,one,z,1,v[1].a,1);
dscal(q,0.5,v[1].a,1);
// (1+a)/2 dfill(q,one,v[4].a,1);
// 1 break;
case 'b': // already set
up in 'a' break;
case 'c': getzw(q,&
z,&
w,'b');
dvsub(q,&
one,0,z,1,v[0].c,1);
dscal(q,0.5,v[0].c,1);
// (1-c)/2 dsadd(q,one,z,1,v[4].c,1);
dscal(q,0.5,v[4].c,1);
// (1+c)/2 break;
} } void
Hex_set_vertices(Mode
*v, int q, char dir){ double one = 1.0,*z,*w;
getzw(q,&
z,&
w,'a');
switch (dir){ case 'a': dvsub(q,&
one,0,z,1,v[0].a,1);
dsmul(q,0.5,v[0].a,1,v[0].a,1);
dsadd(q,one,z,1,v[1].a,1);
dsmul(q,0.5,v[1].a,1,v[1].a,1);
break;
case
'b': break;
case 'c': break;
} } void
Tri_set_edges(Basis
*b, int q, char dir){ register int i;
int L = b->id-2;
double *z,*w;
Mode *v = b->vert, **e = b->edge;
getzw(q,&
z,&
w,dir);
switch (dir){ case 'a': dvmul(q,v[0].a,1,v[1].a,1,e[0][0].a,1);
for(i =
1;
i <
L;
++i){ jacobf(q,z,e[0][i].a,i,1.0,1.0);
dvmul (q,e[0][0].a,1,e[0][i].a,1,e[0][i].a,1);
} break;
case 'b': dvmul(q,v[0].b,1,v[0].b,1,e[0][0].b,1);
dvmul(q,v[1].b,1,v[2].b,1,e[1][0].b,1);
for(i = 1;
i <
L;
++i){ dvmul
(q,e[0][i-1].b,1,v[0].b,1,e[0][i].b,1);
jacobf(q,z,e[1][i].b,i,1.0,1.0);
dvmul (q,e[1][0].b,1,e[1][i].b,1,e[1][i].b,1);
} break;
} } void
Quad_set_edges(Basis
*b, int q, char dir){ register int i;
int L = b->id-2;
double *z,*w;
Mode *v = b->vert, **e = b->edge;
getzw(q,&
z,&
w,'a');
switch (dir){ case 'a': dvmul(q,v[0].a,1,v[1].a,1,e[0][0].a,1);
for(i =
1;
i <
L;
++i){ jacobf(q,z,e[0][i].a,i,1.0,1.0);
dvmul (q,e[0][0].a,1,e[0][i].a,1,e[0][i].a,1);
} break;
case 'b': dvmul(q,v[0].b,1,v[2].b,1,e[1][0].b,1);
for(i = 1;
i <
L;
++i){ jacobf(q,z,e[1][i].b,i,1.0,1.0);
dvmul (q,e[1][0].b,1,e[1][i].b,1,e[1][i].b,1);
} break;
} } void
Tet_set_edges(Basis
*b, int q, char dir){ register int i;
int L = b->id-2;
double *z,*w;
Mode *v = b->vert, **e = b->edge;
double
alpha = 1.;
double beta = 1.;
if(option("TWOTWO")){
alpha += 1.;
beta += 1.;
} getzw(q,&
z,&
w,dir);
switch (dir){ case 'a': dvmul(q,v[0].a,1,v[1].a,1,e[0][0].a,1);
for(i =
1;
i <
L;
++i){ jacobf(q,z,e[0][i].a,i,alpha,beta);
dvmul (q,e[0][0].a,1,e[0][i].a,1,e[0][i].a,1);
} break;
case 'b': dvmul(q,v[0].b,1,v[0].b,1,e[0][0].b,1);
dvmul(q,v[1].b,1,v[2].b,1,e[1][0].b,1);
for(i = 1;
i <
L;
++i){ dvmul
(q,e[0][i-1].b,1,v[0].b,1,e[0][i].b,1);
jacobf(q,z,e[1][i].b,i,alpha,beta);
dvmul (q,e[1][0].b,1,e[1][i].b,1,e[1][i].b,1);
} break;
case 'c': dvmul(q,v[0].c,1,v[0].c,1,e[0][0].c,1);
dvmul(q,v[2].c,1,v[3].c,1,e[3][0].c,1);
for(i = 1;
i <
L;
++i){ dvmul
(q,e[0][i-1].c,1,v[0].c,1,e[0][i].c,1);
jacobf(q,z,e[3][i].c,i,alpha,beta);
dvmul (q,e[3][0].c,1,e[3][i].c,1,e[3][i].c,1);
} break;
} } void
Pyr_set_edges(Basis
*b, int q, char dir){ register int i;
int L = b->id-2;
double *z,*w;
Mode *v = b->vert, **e = b->edge;
double
alpha = 1., beta = 1.;
if(option("TWOTWO")){
alpha += 1.;
beta += 1.;
} switch (dir){ case 'a': getzw(q,&
z,&
w,'a');
dvmul(q,v[0].a,1,v[1].a,1,e[0][0].a,1);
for(i = 1;
i <
L;
++i){ jacobf(q,z,e[0][i].a,i,alpha,beta);
dvmul (q,e[0][0].a,1,e[0][i].a,1,e[0][i].a,1);
} break;
case 'b': break;
case 'c': getzw(q,&
z,&
w,'c');
// dfill(q,one,e[1][0].c,
1);
dvmul(q, v[0].c, 1, v[0].c, 1, e[0][0].c, 1);
for(i=1;
i<
L;
++i) dvmul(q,
v[0].c, 1, e[0][i-1].c, 1, e[0][i].c, 1);
dvmul(q,v[0].c,1,v[4].c,1,e[4][0].c,1);
for(i = 1;
i <
L;
++i){ jacobf(q,z,e[4][i].c,i,alpha,beta);
dvmul (q,e[4][0].c,1,e[4][i].c,1,e[4][i].c,1);
} break;
} } void
Prism_set_edges(Basis
*b, int q, char dir){ register int i;
int L = b->id-2;
double *z,*w;
Mode *v = b->vert, **e = b->edge;
double
alpha = 1.;
double beta = 1.;
if(option("TWOTWO")){
alpha += 1.;
beta += 1.;
} switch (dir){ case 'a': getzw(q,&
z,&
w,'a');
dvmul(q,v[0].a,1,v[1].a,1,e[0][0].a,1);
for(i = 1;
i <
L;
++i){ jacobf(q,z,e[0][i].a,i,alpha,beta);
dvmul (q,e[0][0].a,1,e[0][i].a,1,e[0][i].a,1);
} break;
case 'b': break;
case 'c': getzw(q,&
z,&
w,'b');
// dfill(q,one,e[1][0].c,
1);
dvmul(q, v[0].c, 1, v[0].c, 1, e[0][0].c, 1);
for(i=1;
i<
L;
++i) dvmul(q,
v[0].c, 1, e[0][i-1].c, 1, e[0][i].c, 1);
dvmul(q,v[0].c,1,v[4].c,1,e[4][0].c,1);
for(i = 1;
i <
L;
++i){ jacobf(q,z,e[4][i].c,i,alpha,beta);
dvmul (q,e[4][0].c,1,e[4][i].c,1,e[4][i].c,1);
} break;
} } void
Hex_set_edges(Basis
*b, int q, char dir){ register int i;
int L = b->id-2;
double *z,*w;
Mode *v = b->vert, **e = b->edge;
double
alpha = 1.;
double beta = 1.;
if(option("TWOTWO")){
alpha += 1.;
beta += 1.;
} getzw(q,&
z,&
w,'a');
switch (dir){ case 'a': dvmul(q,v[0].a,1,v[1].a,1,e[0][0].a,1);
for(i =
1;
i <
L;
++i){ jacobf(q,z,e[0][i].a,i,alpha,beta);
dvmul (q,e[0][0].a,1,e[0][i].a,1,e[0][i].a,1);
} break;
case 'b': break;
case 'c': break;
} } void
Tri_set_faces(Basis
*b, int q, char dir){ register int i,j;
int L = b->id;
double *z,*w;
Mode *v = b->vert, **e = b->edge, ***f
= b->face;
switch (dir){ case 'a': break;
case 'b': getzw(q,&
z,&
w,dir);
for(i = 0;
i <
L-3;
++i) dvmul(q,v[2].b,1,e[0][i].b,1,f[0][i][0].b,1);
for(i = 0;
i <
L-3;
++i) for(j = 1;
j <
L-3-i;
++j){ jacobf(q,z,f[0][i][j].b,j,2.0*i+3.0,1.0);
dvmul (q,f[0][i][0].b,1,f[0][i][j].b,1,f[0][i][j].b,1);
} break;
} } void
Quad_set_faces(Basis
*, int , char ){ // already set by memory
pointer to edge modes } void
Tet_set_faces(Basis
*b, int q, char dir){ register int i,j;
int L = b->id;
double *z,*w;
Mode *v = b->vert, **e = b->edge, ***f
= b->face;
double alpha = 1.;
double beta = 1.;
if(option("TWOTWO")){
alpha += 1.;
beta += 1.;
} switch (dir){ case 'a': break;
case 'b': getzw(q,&
z,&
w,dir);
for(i = 0;
i <
L-3;
++i){ dvmul(q,v[2].b,1,e[0][i].b,1,f[0][i][0].b,1);
} for(i = 0;
i <
L-3;
++i) for(j = 1;
j <
L-3-i;
++j){ alpha = 2.0*i+3.;
beta = 1.;
if(option("TWOTWO")){ alpha
+= 1.;
beta += 1.;
} jacobf(q,z,f[0][i][j].b,j,alpha,beta);
dvmul (q,f[0][i][0].b,1,f[0][i][j].b,1,f[0][i][j].b,1);
} break;
case 'c':
getzw(q,&
z,&
w,dir);
for(i = 0;
i <
L-3;
++i){ dvmul(q,v[3].c,1,e[0][i].c,1,f[1][i][0].c,1);
} for(i = 0;
i <
L-3;
++i) for(j = 1;
j <
L-3-i;
++j){ alpha = 2.0*i+3.;
beta = 1.;
if(option("TWOTWO")){
alpha += 1.;
beta += 1.;
} jacobf(q,z,f[1][i][j].c,j,alpha,beta);
dvmul (q,f[1][i][0].c,1,f[1][i][j].c,1,f[1][i][j].c,1);
} break;
} } void
Pyr_set_faces(Basis
*b, int q, char dir){ int L = b->id, i,j,k;
Mode
*v = b->vert, **e = b->edge, ***f = b->face, ***in = b->intr;
double *w,
*z;
int cnt = 0;
double alpha, beta;
switch (dir){ case 'a': break;
case
'b': break;
case 'c': getzw(q,&
z,&
w,'c');
for(i = 0;
i <
L-2;
++i) for(j = 0;
j <
L-2;
++j){ k = min(L,
i+j);
dcopy(q, e[0][k].c, 1, f[0][i][j].c, 1);
} // dvmul(q, e[0][j].c,
1, e[0][i].c, 1,f[0][i][j].c,1);
for(i = 0;
i <
L-3;
++i){ dvmul(q,v[4].c,1,e[0][i].c,1,f[1][i][0].c,1);
} for(i = 0;
i <
L-3;
++i) for(j = 1;
j <
L-3-i;
++j){ alpha = 2.*i+3.;
beta = 1.;
if(option("TWOTWO")){ alpha
+= 1.;
beta += 1.;
} jacobf(q,z,f[1][i][j].c,j,alpha,beta);
dvmul (q,f[1][i][0].c,1,f[1][i][j].c,1,f[1][i][j].c,1);
} // interior for(i
= 0;
i <
L-3;
++i) for(j = 0;
j <
L-3-i;
++j) for(k=0;
k <
L-3-i-j;
++k){
alpha = 2.*(i+j)+3.;
beta = 1.;
if(option("TWOTWO")){
alpha += 1.;
beta += 1.;
} // jacobf(q,z,in[i][j][k].c,k,2.0*(i+j)+3.0,1.0);
jacobf(q,z,in[i][j][k].c,k,alpha,beta);
dvmul (q,f[0][i][j].c,1,in[i][j][k].c,1,in[i][j][k].c,1);
dvmul (q, v[4].c,1,in[i][j][k].c,1,in[i][j][k].c,1);
++cnt;
} break;
} } void
Prism_set_faces(Basis
*b, int q, char dir){ int L = b->id, i,j;
Mode
*v = b->vert, **e = b->edge, ***f = b->face;
double *w, *z;
double alpha,
beta;
switch (dir){ case 'a': break;
case 'b': break;
case 'c': getzw(q,&
z,&
w,'b');
for(i = 0;
i <
L-3;
++i){ dvmul(q,v[4].c,1,e[0][i].c,1,f[1][i][0].c,1);
} for(i = 0;
i <
L-3;
++i) for(j = 1;
j <
L-3-i;
++j){ alpha = 2.0*i+3.;
beta = 1.;
if(option("TWOTWO")){ alpha
+= 1.;
beta += 1.;
} jacobf(q,z,f[1][i][j].c,j,alpha,beta);
dvmul (q,f[1][i][0].c,1,f[1][i][j].c,1,f[1][i][j].c,1);
} break;
} } void
Hex_set_faces(Basis
*b, int q, char dir){ switch (dir){ case 'a': break;
case 'b': break;
case 'c': break;
} } /* normalised basis
in an L2 fashion. * * don't want to normalise vertices since have a collocation
* * property that would be destroyed by it. Want normalisation * * of edges
and faces to match so that can match expansion * * coefficients for C^0
continuity */ static void
Tri_normalise(Basis
*b, int qa, int qb, int qc){ register int i;
double *wa,*wb,*s,integral;
double *tmp;
const int L = b->id;
qc=qc;
// compiler fix getzw(qa,&
wa,&
wa,'a');
getzw(qb,&
wb,&
wb,'b');
tmp = dvector(0,QGmax-1);
/* sort out edge normalisation using side 1 `a' component */ if(L>2){
s = b->edge[0][0].a;
for(i = 0;
i <
L-2;
++i, s+=qa){ dvmul(qa,s,1,wa,1,tmp,1);
integral = 1.0/sqrt(ddot(qa,s,1,tmp,1));
dscal(qa,integral,s,1);
dscal(qb,integral,b->edge[1][i].b,1);
} } /* normalise face modes using `b' component */ if(L>3){
s = b->face[0][0][0].b;
for(i = 0;
i <
(L-3)*(L-2)/2;
++i,s+=qb){ dvmul(qb,s,1,wb,1,tmp,1);
integral = 1.0/sqrt(ddot(qb,s,1,tmp,1));
dscal(qb,integral,s,1);
} } free(tmp);
} static void
Quad_normalise(Basis
*b, char type ){ register int i;
int L = b->id;
int qa = b->qa;
int
qb = b->qb;
switch(type){ case 'B': /* babuska and Szabo's normalisation
*/ if(L > 2){ for(i = 0;
i <
L-2;
++i){
dscal(qa,sqrt((2*i+3)*2)/(double)(i+1),b->edge[0][i].a,1);
dscal(qa,sqrt((2*i+3)*2)/(double)(i+1),b->edge[2][i].a,1);
dscal(qb,sqrt((2*i+3)*2)/(double)(i+1),b->edge[1][i].b,1);
dscal(qb,sqrt((2*i+3)*2)/(double)(i+1),b->edge[3][i].b,1);
} } break;
default: error_msg("type not known");
//OVERLOAD CALL:
error_msg: gen_utils.h(?), hotel.h(?)
} } /* normalised basis in an L2 fashion.
* * don't want to normalise vertices since have a collocation * * property
that would be destroyed by it. Want normalisation * * of edges and faces
to match so that can match expansion * * coefficients for C^0 continuity
*/ static void
Tet_normalise(Basis
*b, int , int , int ){ } /* normalised basis
in an L2 fashion. * * don't want to normalise vertices since have a collocation
* * property that would be destroyed by it. Want normalisation * * of edges
and faces to match so that can match expansion * * coefficients for C^0
continuity */ static void
Pyr_normalise(Basis
*, int , int , int ){ } /* normalised basis
in an L2 fashion. * * don't want to normalise vertices since have a collocation
* * property that would be destroyed by it. Want normalisation * * of edges
and faces to match so that can match expansion * * coefficients for C^0
continuity */ static void
Prism_normalise(Basis
*, int , int , int ){ } /* normalised basis
in an L2 fashion. * * don't want to normalise vertices since have a collocation
* * property that would be destroyed by it. Want normalisation * * of edges
and faces to match so that can match expansion * * coefficients for C^0
continuity */ static void
Hex_normalise(Basis
*, int , int , int ){ } /* Function name: Element::fillElmt
Function Purpose: Argument 1: Mode *v
Purpose: Function Notes: */ void Tri::fillElmt(Mode
*v){ register int i;
for(i = 0;
i <
qb;
++i) dcopy(qa,v->a,1,h[i],1);
for(i = 0;
i <
qb;
++i) dscal(qa,v->b[i],h[i],1);
} void Quad::fillElmt(Mode
*v){ register int i;
for(i = 0;
i <
qb;
++i) dcopy(qa,v->a,1,h[i],1);
for(i = 0;
i <
qb;
++i) dscal(qa,v->b[i],h[i],1);
} void Tet::fillElmt(Mode
*v){ register int i, j;
for(i = 0;
i <
qb*qc;
++i) dcopy(qa,v->a,1,(*h_3d)[i],1);
for(i = 0;
i <
qc;
++i) for(j = 0;
j <
qb;
++j) dsmul(qa,v->b[j],h_3d[i][j],1,h_3d[i][j],1);
for(i = 0;
i <
qc;
++i) dsmul(qa*qb,v->c[i],*(h_3d[i]),1,*(h_3d[i]),1);
} void Pyr::fillElmt(Mode
*v){ register int i, j;
for(i = 0;
i <
qb*qc;
++i) dcopy(qa,v->a,1,(*h_3d)[i],1);
for(i = 0;
i <
qc;
++i) for(j = 0;
j <
qb;
++j) dsmul(qa,v->b[j],h_3d[i][j],1,h_3d[i][j],1);
for(i = 0;
i <
qc;
++i) dsmul(qa*qb,v->c[i],*(h_3d[i]),1,*(h_3d[i]),1);
} void Prism::fillElmt(Mode
*v){ register int i, j;
for(i = 0;
i <
qb*qc;
++i) dcopy(qa,v->a,1,(*h_3d)[i],1);
for(i = 0;
i <
qc;
++i) for(j = 0;
j <
qb;
++j) dsmul(qa,v->b[j],h_3d[i][j],1,h_3d[i][j],1);
for(i = 0;
i <
qc;
++i) dsmul(qa*qb,v->c[i],*(h_3d[i]),1,*(h_3d[i]),1);
} void Hex::fillElmt(Mode
*v){ register int i, j;
for(i = 0;
i <
qb*qc;
++i) dcopy(qa,v->a,1,(*h_3d)[i],1);
for(i = 0;
i <
qc;
++i) for(j = 0;
j <
qb;
++j) dsmul(qa,v->b[j],h_3d[i][j],1,h_3d[i][j],1);
for(i = 0;
i <
qc;
++i) dsmul(qa*qb,v->c[i],*(h_3d[i]),1,*(h_3d[i]),1);
} void Element::fillElmt(Mode
*){ERR;
} //OVERLOAD CALL: ERR: Element.c(?),
hotel.h(?)
C++ to HTML Conversion by ctoohtml