|
| 1 | +#include <math.h> |
| 2 | +#include <time.h> |
| 3 | +#include <stdio.h> |
| 4 | +#include <stdlib.h> |
| 5 | +#include <string.h> |
| 6 | +#include <string.h> |
| 7 | +#include "constants.h" |
| 8 | +#include "intvector.h" |
| 9 | +#include "vector2.h" |
| 10 | +#include "vector3.h" |
| 11 | +#include "sparse2.h" |
| 12 | +#include "basis.h" |
| 13 | +#include "dwt.h" |
| 14 | +#include "WEM.h" |
| 15 | +#include "WEMRHS.h" |
| 16 | +#include "WEMPCG.h" |
| 17 | +#include "WEMPGMRES.h" |
| 18 | +#include "compression.h" |
| 19 | +#include "init_points.h" |
| 20 | +#include "interpolate.h" |
| 21 | +#include "read_points.h" |
| 22 | +#include "postproc.h" |
| 23 | +#include "topology.h" |
| 24 | +#include "energy.h" |
| 25 | +#include "cubature.h" |
| 26 | +#include "data.h" |
| 27 | +#include "kern.h" |
| 28 | +#include "gauss_square.h" |
| 29 | +#include "dalton_wem.h" |
| 30 | + |
| 31 | + |
| 32 | +#if !defined pi |
| 33 | + #define pi 3.1415926535897932385 |
| 34 | +#endif |
| 35 | + |
| 36 | +sparse2 S; /* komprimierte Steifigkeitsmatrix */ |
| 37 | +vector3 *P; /* Punkteliste der Einskalenbasis */ |
| 38 | +unsigned int **F; /* Elementliste der Einskalenbasis */ |
| 39 | +vector3 ****T; /* Oberflaecheninterpolation */ |
| 40 | +vector3 ***U; /* Knotenpunkte */ |
| 41 | +unsigned int nf; /* Laenge von F */ |
| 42 | +unsigned int p; /* Anzahl der Patches */ |
| 43 | +unsigned int M; /* 2^M*2^M Elemente pro Patch */ |
| 44 | +element *E; /* hierarchische Elementliste */ |
| 45 | +wavelet *W; /* Liste der Wavelets */ |
| 46 | +double *v; /* approximierter Dichtevektor */ |
| 47 | + |
| 48 | +/* |
| 49 | + * Initializes the great WEM machine! |
| 50 | + * |
| 51 | + * int (out) - number of potential points |
| 52 | + * |
| 53 | + * return 0 - if all ok |
| 54 | + * |
| 55 | + */ |
| 56 | +int dalton_wem_initialize_(int *num_points, double *da, double *db, double *ddp, |
| 57 | + double *apriori, double *aposteriori){ |
| 58 | + |
| 59 | + char filename[80]="cavity.dat"; |
| 60 | + |
| 61 | + *da=a; |
| 62 | + *db=b; |
| 63 | + *ddp=dp; |
| 64 | + |
| 65 | + /* Initialisierung */ |
| 66 | + read_points(&U,&p,&M,filename); |
| 67 | + nf = p*(1<<M)*(1<<M); /* Anzahl der Patches */ |
| 68 | + |
| 69 | + /* Topologie bestimmen */ |
| 70 | + init_interpolate(&T,U,p,M); |
| 71 | + gennet(&P,&F,U,p,M); |
| 72 | + free_points(&U,p,M); |
| 73 | + |
| 74 | + /* erstelle Element-/Waveletliste */ |
| 75 | + generate_elementlist(&E,P,F,p,M); |
| 76 | + generate_waveletlist(&W,E,p,M); |
| 77 | + set_quadrature_level(W,E,p,M); |
| 78 | + simplify_waveletlist(W,E,p,M); |
| 79 | + complete_elementlist(W,E,p,M); |
| 80 | + |
| 81 | + /* berechne a-priori Kompression */ |
| 82 | + compression(&S,W,E,p,M,apriori); |
| 83 | + |
| 84 | + /* Steifigkeitsmatrix aufstellen */ |
| 85 | + WEM(&S,W,P,E,T,p,M); |
| 86 | + |
| 87 | + /* berechne a-posteriori */ |
| 88 | + postproc(&S,W,E,p,M,aposteriori); |
| 89 | + |
| 90 | + /* Number of potential points should be something like |
| 91 | + * [Number of parameter domains]*[2^(patch level)]**2*[quadrature level]**2 |
| 92 | + */ |
| 93 | + |
| 94 | + // Small chance for an error here.. |
| 95 | + *num_points = nf * (general_quadrature_level+1)*(general_quadrature_level+1); |
| 96 | + |
| 97 | + v = NULL; |
| 98 | + |
| 99 | + if(general_quadrature_level!=0) { |
| 100 | + printf("Varo saatana! general_quadrature_level!=0!\n"); |
| 101 | + return -1; |
| 102 | + } |
| 103 | + |
| 104 | + return 0; // perhaps one should check for unsufficient memory etc. |
| 105 | +} |
| 106 | + |
| 107 | +/* |
| 108 | + * Gets points for potential evaluation |
| 109 | + * |
| 110 | + * data[number of potential points] (out) : |
| 111 | + * [parameter domain][patch_level_y][patch_level_x][quadrature point] |
| 112 | + * double * (out) - [x1,x2, ...] |
| 113 | + * double * (out) - [y1,y2, ...] |
| 114 | + * double * (out) - [z1,z2, ...] |
| 115 | + * memory should be provided by dalton |
| 116 | + * |
| 117 | + */ |
| 118 | +void dalton_wem_get_potential_coordinates_(double *xp, double *yp, double *zp, double *carea){ |
| 119 | + |
| 120 | + unsigned int i1, i2, i3, k, g, index; |
| 121 | + unsigned int n = 1 << M; |
| 122 | + vector2 s,t; |
| 123 | + vector3 res; |
| 124 | + double h = 1./n; |
| 125 | + cubature *Q; |
| 126 | + double totalArea=0.0; |
| 127 | + |
| 128 | + g = general_quadrature_level; |
| 129 | + init_Gauss_Square(&Q,g+1); |
| 130 | + |
| 131 | + index = 0; |
| 132 | + for (i1=0; i1<p; i1++){ /* sum over parameter domains */ |
| 133 | + s.y = 0; |
| 134 | + for (i2=0; i2<n; i2++){ |
| 135 | + s.x = 0; |
| 136 | + for (i3=0; i3<n; i3++){ /* sum over patches */ |
| 137 | + |
| 138 | + for (k=0; k<Q[g].nop; k++){ /* sum over quadrature (g=2->nop=3*3) */ |
| 139 | + t = vector2_add(s,vector2_Smul(h,Q[g].xi[k])); |
| 140 | + res = Chi(t,T[i1],M); |
| 141 | + xp[index] = res.x; |
| 142 | + yp[index] = res.y; |
| 143 | + zp[index] = res.z; |
| 144 | + totalArea += h*h*Q[g].w[k]*vector3_norm(n_Chi(t,T[i1],M)); |
| 145 | + index += 1; |
| 146 | + } |
| 147 | + |
| 148 | + s.x += h; |
| 149 | + } |
| 150 | + s.y += h; |
| 151 | + } |
| 152 | + } |
| 153 | + |
| 154 | + *carea=totalArea; |
| 155 | +} |
| 156 | + |
| 157 | + |
| 158 | +void dalton_wem_get_areas_normals_(double *as, double *xn, double *yn, double *zn){ |
| 159 | + |
| 160 | + unsigned int i1, i2, i3, k, g, index; |
| 161 | + unsigned int n = 1 << M; |
| 162 | + vector2 s,t; |
| 163 | + vector3 res; |
| 164 | + double h = 1./n; |
| 165 | + cubature *Q; |
| 166 | + //double totalArea=0.0; |
| 167 | + |
| 168 | + g = general_quadrature_level; |
| 169 | + init_Gauss_Square(&Q,g+1); |
| 170 | + |
| 171 | + index = 0; |
| 172 | + for (i1=0; i1<p; i1++){ /* sum over parameter domains */ |
| 173 | + s.y = 0; |
| 174 | + for (i2=0; i2<n; i2++){ |
| 175 | + s.x = 0; |
| 176 | + for (i3=0; i3<n; i3++){ /* sum over patches */ |
| 177 | + |
| 178 | + for (k=0; k<Q[g].nop; k++){ /* sum over quadrature (g=2->nop=3*3) */ |
| 179 | + t = vector2_add(s,vector2_Smul(h,Q[g].xi[k])); |
| 180 | + res = n_Chi(t,T[i1],M); |
| 181 | + xn[index] = res.x; |
| 182 | + yn[index] = res.y; |
| 183 | + zn[index] = res.z; |
| 184 | + as[index] = h*h*Q[g].w[k]*vector3_norm(n_Chi(t,T[i1],M)); |
| 185 | + index += 1; |
| 186 | + } |
| 187 | + |
| 188 | + s.x += h; |
| 189 | + } |
| 190 | + s.y += h; |
| 191 | + } |
| 192 | + } |
| 193 | +} |
| 194 | + |
| 195 | + |
| 196 | +/* |
| 197 | + * Calculates surface polarization charges |
| 198 | + * |
| 199 | + * int * (in) - maximum number of charge points |
| 200 | + * int * (out) - number of charges |
| 201 | + * double * (in) - potential values at pre-specified points |
| 202 | + * double * (out) - resulting charges at the same points |
| 203 | + * (allocate in DALTON, should be larger than #(potential)) |
| 204 | + * double * (out) - positions of charges [x1,x2, ...] |
| 205 | + * double * (out) - positions of charges [y1,y2, ...] |
| 206 | + * double * (out) - positions of charges [z1,z2, ...] |
| 207 | + * |
| 208 | + */ |
| 209 | +void dalton_wem_get_charges_(int *max_charges, int *num_charges, double *potential, double *charges){ |
| 210 | + |
| 211 | + // This version uses only potential (not field) |
| 212 | + |
| 213 | + unsigned int i; |
| 214 | + |
| 215 | + // nf on oikea maara varauksille! |
| 216 | + // potentiaalia voidaan evaluoida useammassakin paikkaa, mutta se on painotettu |
| 217 | + // quadraturen kertoimilla s.e. varaus on vakio (tai varaus*quadrature * potentiaal) |
| 218 | + |
| 219 | + *num_charges=nf*(general_quadrature_level+1)*(general_quadrature_level+1); |
| 220 | + if(*max_charges<*num_charges) { |
| 221 | + *num_charges=0; |
| 222 | + return; |
| 223 | + } |
| 224 | + |
| 225 | + if(v==NULL) v = (double*) calloc(*num_charges,sizeof(double)); /* initial guess? */ |
| 226 | + memset(v,*num_charges*sizeof(double),0); |
| 227 | + memset(charges,*max_charges*sizeof(double),0); |
| 228 | + |
| 229 | + WEMRHS2D(charges,W,E,T,p,M,potential); |
| 230 | + WEMPCG(&S,charges,v,eps,p,M); |
| 231 | + |
| 232 | + tdwtKon(v,M,nf); |
| 233 | + |
| 234 | + double h=1.0/(1<<M); |
| 235 | + for(i=0;i<nf;i++) charges[i]=v[i]*h; // kertaa quadrature level... <- oikeasti kunnon quadrature kertoimilla |
| 236 | + // *num_charges=nf; |
| 237 | +} |
| 238 | + |
| 239 | +void dalton_wem_get_charges2_(int *max_charges, int *num_charges, double *fieldx, |
| 240 | + double *fieldy,double *fieldz, double *charges){ |
| 241 | + |
| 242 | + // Field version |
| 243 | + |
| 244 | + unsigned int i; |
| 245 | + |
| 246 | + // nf on oikea maara varauksille! |
| 247 | + // potentiaalia voidaan evaluoida useammassakin paikkaa, mutta se on painotettu |
| 248 | + // quadraturen kertoimilla s.e. varaus on vakio (tai varaus*quadrature * potentiaal) |
| 249 | + |
| 250 | + *num_charges=nf*(general_quadrature_level+1)*(general_quadrature_level+1); |
| 251 | + if(*max_charges<*num_charges) { |
| 252 | + *num_charges=0; |
| 253 | + return; |
| 254 | + } |
| 255 | + |
| 256 | + if(v==NULL) v = (double*) calloc(*num_charges,sizeof(double)); /* initial guess? */ |
| 257 | + |
| 258 | + WEMRHS1D(charges,W,E,T,p,M,fieldx,fieldy,fieldz); |
| 259 | + WEMPGMRES1(&S,charges,v,eps,p,M); |
| 260 | + |
| 261 | + tdwtKon(v,M,nf); |
| 262 | + |
| 263 | + double h=1.0/(1<<M); |
| 264 | + // kertaa quadrature level... <- oikeasti pitäis painottaa potentiaalia quadraturella (kai) |
| 265 | + for(i=0;i<nf;i++) charges[i]=v[i]*h; |
| 266 | + *num_charges=nf; |
| 267 | +} |
| 268 | + |
| 269 | + |
| 270 | +/* |
| 271 | + * Calculates the total energy |
| 272 | + * |
| 273 | + * double *potential; Potential points! |
| 274 | + * double *energy; Results |
| 275 | + * |
| 276 | + */ |
| 277 | +void dalton_wem_energy_(double *potential, double *energy){ |
| 278 | + |
| 279 | + unsigned int n = 1 << M; /* n*n Patches pro Parametergebiet */ |
| 280 | + unsigned int i1, i2, i3; /* Laufindizes fuer Ansatzfunktion */ |
| 281 | + unsigned int zi; /* Zeilenindex hieraus: zi = i1*(n*n)+i2*n+i3 */ |
| 282 | + cubature *Q; /* Kubatur-Formeln */ |
| 283 | + /*unsigned int g = 2; */ /* Quadraturgrad */ |
| 284 | + unsigned int g = 0; /* g=1, no difference wrt g=2 */ |
| 285 | + unsigned int k; /* Laufindex fuer Quadratur */ |
| 286 | + vector2 s; /* Linker, unterer Eckpunkt des Patches zi */ |
| 287 | + vector2 t; /* Auswertepunkte der Gaussquadratur */ |
| 288 | + double E; /* Energie */ |
| 289 | + double h = 1./n; /* Schrittweite */ |
| 290 | + double C = 0.0; |
| 291 | + unsigned int index; |
| 292 | + |
| 293 | + if(v==NULL) exit(-102); |
| 294 | + |
| 295 | + /* Initialisierung */ |
| 296 | + g = general_quadrature_level; |
| 297 | + init_Gauss_Square(&Q,g+1); /* Kubatur-Formeln */ |
| 298 | + |
| 299 | + /* Berechnung des Fehlers */ |
| 300 | + index=0; |
| 301 | + E = zi = 0; |
| 302 | + for (i1=0; i1<p; i1++) /* sum over parameter domains */ |
| 303 | + { s.y = 0; |
| 304 | + for (i2=0; i2<n; i2++) |
| 305 | + { s.x = 0; |
| 306 | + for (i3=0; i3<n; i3++) /* zeilenweise Durchnumerierung der Patches zi = (i1,i2,i3) */ |
| 307 | + { for (k=0; k<Q[g].nop; k++) /* sum over quadrature points (nop=3*3 for g=2) */ |
| 308 | + { t = vector2_add(s,vector2_Smul(h,Q[g].xi[k])); |
| 309 | + /* E += Q[g].w[k]*v[zi]*f(Chi(t,T[i1],m)); */ |
| 310 | + E += Q[g].w[k]*v[zi]*potential[index]; |
| 311 | + index += 1; |
| 312 | + C += Q[g].w[k]*v[zi]; |
| 313 | + } |
| 314 | + s.x += h; |
| 315 | + zi++; |
| 316 | + } |
| 317 | + s.y += h; |
| 318 | + } |
| 319 | + } |
| 320 | + E = -0.5*h*E; /* correct scaling */ |
| 321 | + |
| 322 | + free_Gauss_Square(&Q,g+1); |
| 323 | + *energy=E; |
| 324 | +} |
| 325 | + |
| 326 | +void dalton_wem_finalize_(){ |
| 327 | + if(v!=NULL) free(v); |
| 328 | + free_waveletlist(&W,p,M); |
| 329 | + free_elementlist(&E,p,M); |
| 330 | + free_interpolate(&T,p,M); |
| 331 | + free_patchlist(&F,nf); |
| 332 | + free_sparse2(&S); |
| 333 | + free(P); |
| 334 | +} |
| 335 | + |
0 commit comments