00001
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <string.h>
00011 #include <complex.h>
00012 #include <math.h>
00013
00014 #include "fastsum.h"
00015 #include "fields_fastsum.h"
00016 #include "kernels.h"
00017
00019 void fields_fastsum_init(fields_fastsum_plan *plan, int N_total, unsigned flags, int nn, int m, int p, double eps_I, double eps_B) {
00020 double *kernel_param;
00021
00022 kernel_param = (double *)malloc(sizeof(double));
00023 kernel_param[0] = 0.0;
00024 plan->N_total = N_total;
00025 plan->q = (double *)malloc(N_total*(sizeof(double)));
00026 plan->r = (double *)malloc(3*N_total*(sizeof(double)));
00027 plan->E = (double *)malloc(3*N_total*(sizeof(double)));
00028
00029 fastsum_init_guru(&plan->fsum, 3, N_total, N_total, one_over_cube, kernel_param, flags, nn, m, p, eps_I, eps_B);
00030 }
00031
00033 void fields_fastsum_finalize(fields_fastsum_plan *plan) {
00034 free(plan->fsum.kernel_param);
00035 fastsum_finalize(&plan->fsum);
00036
00037 free(plan->E);
00038 free(plan->r);
00039 free(plan->q);
00040 }
00041
00043 void fields_fastsum_exact(fields_fastsum_plan *plan) {
00044 int j;
00045 int l;
00046 double s;
00047 double E_pre = 1 / (4*PI*EPSILON_0);
00048 double diff[3];
00049 double sum[3];
00050
00051 for(j = 0; j < plan->N_total; j++) {
00052 sum[0] = 0.0;
00053 sum[1] = 0.0;
00054 sum[2] = 0.0;
00055 for(l = 0; l < plan->N_total; l++) {
00056 if (j == l) {
00057 continue;
00058 }
00059 diff[0] = plan->r[j*3] - plan->r[l*3];
00060 diff[1] = plan->r[j*3+1] - plan->r[l*3+1];
00061 diff[2] = plan->r[j*3+2] - plan->r[l*3+2];
00062 s = diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2];
00063 s = plan->q[l] / sqrt(s*s*s);
00064 sum[0] += s * diff[0];
00065 sum[1] += s * diff[1];
00066 sum[2] += s * diff[2];
00067 }
00068 plan->E[j*3] = E_pre * sum[0];
00069 plan->E[j*3+1] = E_pre * sum[1];
00070 plan->E[j*3+2] = E_pre * sum[2];
00071 }
00072 }
00073
00075 void fields_fastsum_simple(fields_fastsum_plan *plan) {
00076 int k;
00077 int t;
00078 int j;
00079 int l;
00080 double E_pre = 1 / (4*PI*EPSILON_0);
00081
00082 for(k = 0; k < plan->N_total; k++) {
00083 for(t = 0; t < 3; t++) {
00084 plan->fsum.x[k*3+t] = plan->r[k*3+t];
00085 plan->fsum.y[k*3+t] = plan->r[k*3+t];
00086 }
00087 plan->fsum.alpha[k] = plan->q[k];
00088 }
00089
00090
00091 fastsum_precompute(&plan->fsum);
00092 fastsum_trafo(&plan->fsum);
00093 for(j = 0; j < plan->N_total; j++) {
00094 for(t = 0; t < 3; t++) {
00095 plan->E[j*3+t] = plan->r[j*3+t] * creal(plan->fsum.f[j]);
00096 }
00097 }
00098
00099 for(t = 0; t < 3; t++) {
00100 for(k = 0; k < plan->N_total; k++) {
00101 for(l = 0; l < 3; l++) {
00102 plan->fsum.x[k*3+l] = plan->r[k*3+l];
00103 plan->fsum.y[k*3+l] = plan->r[k*3+l];
00104 }
00105 }
00106 for(l = 0; l < plan->N_total; l++) {
00107 plan->fsum.alpha[l] = plan->q[l] * plan->r[l*3+t];
00108 }
00109
00110
00111 fastsum_precompute(&plan->fsum);
00112 fastsum_trafo(&plan->fsum);
00113 for(j = 0; j < plan->N_total; j++) {
00114 plan->E[j*3+t] -= creal(plan->fsum.f[j]);
00115 plan->E[j*3+t] *= E_pre;
00116 }
00117 }
00118 }
00119
00121 void FieldsSearchTree(double *result, int t, double *x, complex *alpha, double *xmin, double *xmax, int N, complex (*kernel)(double , int , const double *), const double *param, int Ad, double *Add, int p, unsigned flags)
00122 {
00123 int m=N/2;
00124 double Min=xmin[t], Max=xmax[t], Median=x[m*3+t];
00125 double a=fabs(Max-Min)/2;
00126 double r;
00127 double kernel_value;
00128 double q;
00129
00130 if (N==0)
00131 return;
00132
00133 if (Min>Median)
00134 FieldsSearchTree(result, (t+1)%3,x+(m+1)*3,alpha+(m+1),xmin,xmax,N-m-1,kernel,param,Ad,Add,p,flags);
00135 else if (Max<Median)
00136 FieldsSearchTree(result, (t+1)%3,x,alpha,xmin,xmax,m,kernel,param,Ad,Add,p,flags);
00137 else
00138 {
00139 if (x[m*3]>xmin[0] && x[m*3]<xmax[0] && x[m*3+1]>xmin[1] && x[m*3+1]<xmax[1] && x[m*3+2]>xmin[2] && x[m*3+2]<xmax[2])
00140 {
00141 r = (xmin[0]+a-x[m*3])*(xmin[0]+a-x[m*3]) + (xmin[1]+a-x[m*3+1])*(xmin[1]+a-x[m*3+1]) + (xmin[2]+a-x[m*3+2])*(xmin[2]+a-x[m*3+2]);
00142
00143 r=sqrt(r);
00144 if (fabs(r)<a)
00145 {
00146 kernel_value = kernel(r,0,param);
00147 if (flags & EXACT_NEARFIELD)
00148 kernel_value -= regkern(kernel,r,p,param,a,1.0/16.0);
00149 else
00150 kernel_value -= kubintkern(r,Add,Ad,a);
00151
00152 q = creal(alpha[m]);
00153
00154 result[0] += (xmin[0]+a-x[m*3])*q*kernel_value;
00155 result[1] += (xmin[1]+a-x[m*3+1])*q*kernel_value;
00156 result[2] += (xmin[2]+a-x[m*3+2])*q*kernel_value;
00157 }
00158 }
00159 FieldsSearchTree(result,(t+1)%3,x+(m+1)*3,alpha+(m+1),xmin,xmax,N-m-1,kernel,param,Ad,Add,p,flags);
00160 FieldsSearchTree(result,(t+1)%3,x,alpha,xmin,xmax,m,kernel,param,Ad,Add,p,flags);
00161 }
00162 }
00163
00165 void fields_fastsum_precompute(fields_fastsum_plan *plan) {
00166 int k;
00167 int t;
00168 double time;
00169
00170 time=nfft_second();
00171
00172 for(k = 0; k < plan->N_total; k++) {
00173 for(t = 0; t < 3; t++) {
00174 plan->fsum.x[k*3+t] = plan->r[k*3+t];
00175 plan->fsum.y[k*3+t] = plan->r[k*3+t];
00176 }
00177 plan->fsum.alpha[k] = plan->q[k];
00178 }
00179
00180 fastsum_precompute(&plan->fsum);
00181 }
00182
00183
00185 void fields_fastsum_trafo(fields_fastsum_plan *plan) {
00186 int j,k,t;
00187 double E_pre = 1 / (4*PI*EPSILON_0);
00188
00190 double ymin[3], ymax[3];
00191
00193 nfft_adjoint(&(plan->fsum.mv1));
00194
00196 for (k=0; k<plan->fsum.mv2.N_total; k++)
00197 plan->fsum.mv2.f_hat[k] = plan->fsum.b[k] * plan->fsum.mv1.f_hat[k];
00198
00200 nfft_trafo(&(plan->fsum.mv2));
00201 for(j = 0; j < plan->N_total; j++) {
00202 plan->E[j*3] = plan->r[j*3] * creal(plan->fsum.mv2.f[j]);
00203 plan->E[j*3+1] = plan->r[j*3+1] * creal(plan->fsum.mv2.f[j]);
00204 plan->E[j*3+2] = plan->r[j*3+2] * creal(plan->fsum.mv2.f[j]);
00205 }
00206
00207 for(t = 0; t < 3; t++) {
00209 for(k = 0; k < plan->N_total; k++)
00210 plan->fsum.mv1.f[k] = plan->fsum.alpha[k] * plan->fsum.x[3*k+t];
00211 nfft_adjoint(&(plan->fsum.mv1));
00212
00214 for (k=0; k<plan->fsum.mv2.N_total; k++)
00215 plan->fsum.mv2.f_hat[k] = plan->fsum.b[k] * plan->fsum.mv1.f_hat[k];
00216
00218 nfft_trafo(&(plan->fsum.mv2));
00219 for(j = 0; j < plan->N_total; j++)
00220 plan->E[j*3+t] -= creal(plan->fsum.mv2.f[j]);
00221 }
00222
00224 for (j=0; j<plan->fsum.M_total; j++)
00225 {
00226 ymin[0] = plan->fsum.y[3*j] - plan->fsum.eps_I;
00227 ymax[0] = plan->fsum.y[3*j] + plan->fsum.eps_I;
00228 ymin[1] = plan->fsum.y[3*j+1] - plan->fsum.eps_I;
00229 ymax[1] = plan->fsum.y[3*j+1] + plan->fsum.eps_I;
00230 ymin[2] = plan->fsum.y[3*j+2] - plan->fsum.eps_I;
00231 ymax[2] = plan->fsum.y[3*j+2] + plan->fsum.eps_I;
00232
00233 FieldsSearchTree(plan->E+3*j, 0, plan->fsum.x, plan->fsum.alpha, ymin, ymax, plan->fsum.N_total, plan->fsum.kernel, plan->fsum.kernel_param, plan->fsum.Ad, plan->fsum.Add, plan->fsum.p, plan->fsum.flags);
00234
00235 plan->E[j*3] *= E_pre;
00236 plan->E[j*3+1] *= E_pre;
00237 plan->E[j*3+2] *= E_pre;
00238 }
00239 }
00240