/*Calcola il minimo di dr2 fra tutte le immagini Viene calcolato per tutte le particelle. Le due liste passate sono le liste di particelle a istanti di tempo diversi Deve essere chiamata da r_squared_save */ inline double r_squared_calc ( particle_s * list_0, particle_s * list_1){ unsigned int i,k; double sum = 0; double rdiff[N]; double distance, min; double rdiff2[2]={0,0}; int x,y; particle_s temp_part; for ( i = 0; i< number_of_particles;i++){ min = DBL_MAX; for ( x= -1; x < 2 ; x++){ for ( y = -1; y<2 ; y++){ temp_part = list_0[i]; temp_part.position[0] += x; temp_part.position[1] += y; diff(list_1[i].position,temp_part.position,rdiff); distance = scalar_prod(rdiff,rdiff); if( distance < min ){ min = distance; for ( k = 0; k<N;k++){ rdiff2[k] = rdiff[k]; } } } } sum += scalar_prod(rdiff2,rdiff2); } return sum/(double)number_of_particles; }
double reweighting_factor_nd(const int N, const int repro) { int i, n_iter; double sq_norm, corr, sum=0., sq_sum = 0., temp1; double mu1, mu2; _Complex double temp2; mu1 = g_mu1; mu2 = g_mu1; /* Use spinor_field 2,3,5 */ /* in order not to conflict with anything else... */ for(i = 0; i < N; ++i) { random_spinor_field_eo(g_chi_up_spinor_field[2], repro, RN_GAUSS); random_spinor_field_eo(g_chi_dn_spinor_field[2], repro, RN_GAUSS); zero_spinor_field(g_chi_up_spinor_field[3], VOLUME/2); zero_spinor_field(g_chi_dn_spinor_field[3], VOLUME/2); temp1 = phmc_ptilde_cheby_coef[0]; phmc_ptilde_cheby_coef[0] = temp1 - 1; Ptilde_ndpsi(g_chi_up_spinor_field[3], g_chi_dn_spinor_field[3], phmc_ptilde_cheby_coef, phmc_ptilde_n_cheby, g_chi_up_spinor_field[2], g_chi_dn_spinor_field[2], &Qtm_pm_ndpsi); phmc_ptilde_cheby_coef[0] = temp1; temp2 = scalar_prod(g_chi_up_spinor_field[2], g_chi_up_spinor_field[3], VOLUME / 2, 1); if(cimag(temp2) > 1.0e-8) { printf("!!! WARNING Immaginary part of CORR-UP LARGER than 10^-8 !!! \n"); printf(" CORR-UP: Re=%12.10e Im=%12.10e \n", creal(temp2), cimag(temp2)); } corr = temp2; printf(" CORR-UP: Re=%12.10e \n", corr); temp2 = scalar_prod(g_chi_dn_spinor_field[2], g_chi_dn_spinor_field[3], VOLUME / 2, 1); if(cimag(temp2) > 1.0e-8) { printf("!!! WARNING Immaginary part of CORR_DN LARGER than 10^-8 !!! \n"); printf(" CORR-DN: Re=%12.10e Im=%12.10e \n", creal(temp2), cimag(temp2)); } corr += temp2; printf(" CORR-DN: Re=%12.10e \n", cimag(temp2)); temp1 = -corr; sum += temp1; sq_sum += temp1 * temp1; printf("rew: n_iter = %d, sq_norm = %e, corr = %e\n", n_iter, sq_norm, corr); } sum /= N; sq_sum /= N; printf("rew: factor = %e, err = %e\n", sum, sqrt(sum * sum - sq_sum) / (N - 1)); return(sum); }
int main(int argc, char **argv) { /* Initialize the random number generator */ rlxd_init(2, 12345); /* Initialize the lattice geometry */ init_lattice(X1, X2); //Testing the hermiticity of gam5D_wilson //Operator is Hermitian if for any vectors x and y (y, Ax) = (Ay, x) //1. Write the procedure which fills a spinor field with gaussian-distributed complex random numbers such that <z z*> = 1 //2. Initialize two random spinor fields X and Y (arrays of type spinor and size GRIDPOINTS) //3. Check that (y, Ax) = (Ay, x) spinor X[GRIDPOINTS], Y[GRIDPOINTS], tmp[GRIDPOINTS]; rand_spinor(X); rand_spinor(Y); //Calculating p1 = (y, Ax) gam5D_wilson(tmp, X); complex double p1 = scalar_prod(Y, tmp); //Calculating p2 = (Ax, y) gam5D_wilson(tmp, Y); complex double p2 = scalar_prod(tmp, X); //Check that p1 and p2 are equal double epsilon = cabs(p1 - p2); printf("\n\n\t Hermiticity check: |p1 - p2| = %2.2E - %s \n\n", epsilon, (epsilon < 1E-14)? "OK":"No"); //Testing the performance of the Conjugate Gradient Solver //1. In order to monitor the progress of the solver, #define MONITOR_CG_PROGRESS in linalg.h // This will print the squared norm of the residue at each iteration to the screen //2. Initialize the gauge fields with the coldstart() procedure //3. Generate a random spinor field Y and use cg(X, Y, ITER_MAX, DELTACG, &gam5D_SQR_wilson) // to solve the equation (gamma_5 D)^2 X = Y // (gamma_5 D)^2 is implemented as gam5D_SQR_wilson(out, temp, in), see Dirac.h //4. Now apply gam5D_SQR_wilson to X, subtract Y and calculate the norm of the result //5. Do the same with hotstart() and see how the number of CG iterations changes coldstart(); spinor Y1[GRIDPOINTS]; rand_spinor(Y); cg(X, Y, ITER_MAX, DELTACG, &gam5D_SQR_wilson); gam5D_SQR_wilson(Y1, tmp, X); diff(tmp, Y1, Y); epsilon = sqrt(square_norm(tmp)); printf("\n\n\t Test of CG inverter: |Q X - Y| = %2.2E - %s \n\n", epsilon, (epsilon < 1E-6)? "OK":"No"); free(left1); free(left2); free(right1); free(right2); system("PAUSE"); return 0; }
/******************************************************************************* * plane_intersect: Calculate intersection between a plane (with normal n including the point w) * and a line thourhg x along the direction k. * returns 0 when no intersection is found (i.e. line is parallel to the plane) * returns 1 or -1 when intersection length is positive and negative, respectively *******************************************************************************/ int plane_intersect(double *l, double x, double y, double z, double kx, double ky, double kz, double nx, double ny, double nz, double wx, double wy, double wz) { double s,k2; k2=scalar_prod(kx,ky,kz,kx,ky,kz); s=scalar_prod(kx,ky,kz,nx,ny,nz); if (k2<FLT_EPSILON || fabs(s)<FLT_EPSILON) return 0; *l = - sqrt(k2)*scalar_prod(nx,ny,nz,x-wx,y-wy,z-wz)/s; if (*l<0) return -1; else return 1; } /* plane_intersect */
void addproj_q_invsqrt(spinor * const Q, spinor * const P, const int n, const int N) { int j; spinor *aux; complex cnorm, lambda; static double save_ev[2]={-1.,-1.}; static int * ev_sign = NULL; if(eigenvls[0] != save_ev[0] && eigenvls[1] != save_ev[1] ) { if(g_proc_id == 0 && g_debug_level > 1) { printf("# Recomputing eigenvalue signs!\n"); fflush(stdout); } for(j = 0; j < 2; j++) { save_ev[j] = eigenvls[j]; } free(ev_sign); ev_sign = (int*) malloc(n * sizeof(int)); aux=lock_Dov_WS_spinor(1); for(j=0; j < n; j++) { D_psi(aux, &(eigenvectors[j*evlength])); gamma5(aux, aux, N); lambda = scalar_prod(&(eigenvectors[j*evlength]), aux, N, 1); if (lambda.re < 0) { ev_sign[j] = -1; } else { ev_sign[j] = 1; } } unlock_Dov_WS_spinor(1); /* free(aux_); */ } for(j = 0; j < n; j++) { cnorm = scalar_prod(&(eigenvectors[j*evlength]), P, N, 1); cnorm.re *= (double)ev_sign[j]; cnorm.im *= (double)ev_sign[j]; assign_add_mul(Q, &(eigenvectors[j*evlength]), cnorm, N); } return; }
t_color get_ambiant_light(t_scene scene, t_vector ray, t_obj object, t_point inter) { t_llst *tmp; t_point light_inter; double norm; tmp = scene.lst_light; scene.color = new_color(0, 0, 0); while (tmp) { light_inter = new_point(inter.x - tmp->light->body.center.x, inter.y - tmp->light->body.center.y, inter.z - tmp->light->body.center.z); norm = sqrt(pow(light_inter.x, 2) + pow(light_inter.y, 2) + pow(light_inter.z, 2)); scene.normal = object.normal(object, inter, ray); light_inter = new_point((double)light_inter.x / norm, light_inter.y / norm, light_inter.z / norm); scene.scal = scalar_prod(light_inter, scene.normal); scene.ray = ray.dir; if (norm_is_shit(scene, *(tmp->light), inter, norm) && scene.scal >= 0.000000000000000000001) scene.color = calc_color(get_spec(scene, *(tmp->light), light_inter, object), object.texturing(object, inter, ray), *(tmp->light), scene.scal); tmp = tmp->next; } return (scene.color); }
/// Returns signed 2 theta (signed scattering angle w.r.t. to beam direction). double DetectorInfo::signedTwoTheta(const std::pair<size_t, size_t> &index) const { if (isMonitor(index)) throw std::logic_error( "Two theta (scattering angle) is not defined for monitors."); const auto samplePos = samplePosition(); const auto beamLine = samplePos - sourcePosition(); if (beamLine.nullVector()) { throw Kernel::Exception::InstrumentDefinitionError( "Source and sample are at same position!"); } // Get the axis defining the sign const auto &instrumentUpAxis = m_instrument->getReferenceFrame()->vecThetaSign(); const auto sampleDetVec = position(index) - samplePos; double angle = sampleDetVec.angle(beamLine); const auto cross = beamLine.cross_prod(sampleDetVec); const auto normToSurface = beamLine.cross_prod(instrumentUpAxis); if (normToSurface.scalar_prod(cross) < 0) { angle *= -1; } return angle; }
int check_distance (){ int i,j; double distance = 0; double diff_v[N]; int x,y; particle_s temp_part; for (i = 0 ; i< number_of_particles ; i++){ for(j = i+1;j <number_of_particles ; j++){ for ( x= -1; x < 2 ; x++){ for ( y = -1; y<2 ; y++){ temp_part = particleList[j]; temp_part.position[0] += x; temp_part.position[1] += y; diff(particleList[i].position,temp_part.position,diff_v); distance = sqrt(scalar_prod(diff_v,diff_v)); if( distance <SIGMA){ printf("Sfere (%d,%d) troppo vicine!\n",i,j); return (1); } } } } } return (0); }
void int_quad(t_inter *pt, void *e, t_ray ray, t_light *light) { t_quad quad; double t; t_vec inter; quad = *((t_quad *)e); t = get_dist(ray, quad); if (t < 0) return ; if (pt->dist == NULL || *(pt->dist) > t) { if (pt->dist == NULL) pt->dist = malloc(sizeof(double)); free_info(pt); *(pt->dist) = t; inter = get_inter(ray, t); pt->normal = get_normal_quad(inter, quad); if (scalar_prod(pt->normal, ray.dir) > 0) pt->normal = mult_scalar(pt->normal, -1); pt->refl = get_refl(ray, pt->normal); pt->color = quad.color; pt->inter = inter; get_info(pt, light, inter); } }
/*Calcola energia cinetica*/ double kin_en ( void) { int i = 0; double sum = 0; for ( i = 0; i< number_of_particles ; i++){ sum += scalar_prod(particleList[i].speed, particleList[i].speed); } return sum/2.0; }
// off_intersectPoly *********************************************************** //gives the intersection vertex between ray [a,b) and polygon p and its parametric value on (a b) //based on http://geometryalgorithms.com/Archive/algorithm_0105/algorithm_0105.htm int off_intersectPoly(intersection *inter, Coords a, Coords b, polygon p) { //direction vector of [a,b] Coords dir = {b.x-a.x, b.y-a.y, b.z-a.z}; //the normal vector to the polygon Coords normale=p.normal; //off_normal(&normale, p); done at the init stage //direction vector from a to a vertex of the polygon Coords w0 = {a.x-p.p[0], a.y-p.p[1], a.z-p.p[2]}; //scalar product MCNUM nw0 =-scalar_prod(normale.x,normale.y,normale.z,w0.x,w0.y,w0.z); MCNUM ndir = scalar_prod(normale.x,normale.y,normale.z,dir.x,dir.y,dir.z); inter->time = inter->edge = inter->in_out=0; inter->v = inter->normal = coords_set(0,0,1); if (fabs(ndir) < EPSILON) // ray is parallel to polygon plane { if (nw0 == 0) // ray lies in polygon plane (infinite number of solution) return 0; else return 0; // ray disjoint from plane (no solution) } // get intersect point of ray with polygon plane inter->time = nw0 / ndir; //parametric value the point on line (a,b) inter->v = coords_set(a.x + inter->time * dir.x,// intersect point of ray and plane a.y + inter->time * dir.y, a.z + inter->time * dir.z); int res=off_pnpoly(p,inter->v); inter->edge=(res==-1); if (ndir<0) inter->in_out=1; //the negative dot product means we enter the surface else inter->in_out=-1; inter->normal=p.normal; return res; //true if the intersection point lies inside the poly } /* off_intersectPoly */
/*Calcola momento totale (in norma)*/ double total_momentum (){ int i,j; double sum[2] = {0,0}; for ( i = 0; i< number_of_particles ; i++){ for ( j = 0; j< N ; j++){ sum[j] += particleList[i].speed[j]; } } return sqrt(scalar_prod(sum,sum)); }
/*Salva il modulo della velocità in un file per poter fare un istogramma */ inline void boltzmann_file_save ( void ){ int i = 0; double speed_squared = 0; FILE *f = fopen ("data/boltzmann.dat","a"); for (i = 0; i< number_of_particles ; i++){ speed_squared = sqrt(scalar_prod(particleList[i].speed,particleList[i].speed)); fprintf(f,"%e\n",speed_squared); } fclose(f); }
static void restart(double *x, double *x_old, double *y, double *y_old, double *tmp_var_p, double *tmp_var_p2, int n){ double test; vec_sub(y_old,x,tmp_var_p,n); vec_sub(x,x_old,tmp_var_p2,n); test = scalar_prod(tmp_var_p,tmp_var_p2,n); if (test > 0) { copy_vec_part(x_old,y,n); copy_vec_part(x_old,x,n); } }
int mr(spinor * const P, spinor * const Q, const int max_iter, const double eps_sq, const int rel_prec, const int N, const int parallel, matrix_mult f){ int i=0; double norm_r,beta; _Complex double alpha; spinor * r; spinor ** solver_field = NULL; const int nr_sf = 3; if(N == VOLUME) { init_solver_field(&solver_field, VOLUMEPLUSRAND, nr_sf); } else { init_solver_field(&solver_field, VOLUMEPLUSRAND/2, nr_sf); } r = solver_field[0]; zero_spinor_field(P, N); f(solver_field[2], P); diff(r, Q, solver_field[2], N); norm_r=square_norm(solver_field[0], N, parallel); if(g_proc_id == g_stdio_proc && g_debug_level > 2) { printf("MR iteration number: %d, |res|^2 = %e\n", i, norm_r); fflush( stdout ); } while((norm_r > eps_sq) && (i < max_iter)){ i++; f(solver_field[1], r); alpha=scalar_prod(solver_field[1], r, N, parallel); beta=square_norm(solver_field[1], N, parallel); alpha /= beta; assign_add_mul(P, r, alpha, N); if(i%50 == 0){ f(solver_field[2], P); } else{ assign_add_mul(solver_field[2], solver_field[1], alpha, N); } diff(r, Q, solver_field[2], N); norm_r=square_norm(solver_field[0], N, parallel); if(g_proc_id == g_stdio_proc && g_debug_level > 2) { printf("# MR iteration= %d |res|^2= %g\n", i, norm_r); fflush(stdout); } } finalize_solver(solver_field, nr_sf); if(norm_r > eps_sq){ return(-1); } return(i); }
/* Q=Q-sum_i lambda_i |eigen_i><eigen_i|P> */ void sub_lowest_eigenvalues(spinor * const Q, spinor * const P, const int n, const int N) { int i; complex c; for(i = 0; i < n; i++){ c = scalar_prod(&(eigenvectors[i*evlength]), P, N, 1); c.re *= -eigenvls[i]; c.im *= -eigenvls[i]; assign_add_mul(Q, &eigenvectors[i*evlength], c, N); } }
float compute_diehdral_angle(const own_vector_t *a1, const own_vector_t *a2,const own_vector_t *a3, const own_vector_t *a4){ /* Computes the dihedral angle */ own_vector_t *P1, *P2, *M, *r1, *r2, *r3; double mod_P1, mod_P2; double W; P1 = Malloc(own_vector_t,1); P2 = Malloc(own_vector_t,1); M = Malloc(own_vector_t,1); r1 = Malloc(own_vector_t,1); r2 = Malloc(own_vector_t,1); r3 = Malloc(own_vector_t,1); //Computing distances sub_vector(r1,a1,a2); sub_vector(r2,a2,a3); sub_vector(r3,a3,a4); cross_product(P1,r1,r2); cross_product(P2,r2,r3); mod_P1 = mod_vector(P1); mod_P2 = mod_vector(P2); W = acos(scalar_prod(P1,P2)/(mod_P1*mod_P2)); //Check if is necessary change the signal of W cross_product(M,P1,P2); if (scalar_prod(M,r2) < 0){ W = W *(-1); } //Deallocating variables free(P1); free(P2); free(M); free(r1); free(r2); free(r3); return W; }
/* Calcola il tempo minimo fra le 9 immagini */ double calc_min ( int i , int j){ double x,y; double min= DBL_MAX; double r_diff[N]; double v_diff[N]; double det; double temp; particle_s temp_part; for ( x= -1; x < 2 ; x++){ for ( y = -1; y<2 ; y++){ temp_part = particleList[j]; temp_part.position[0] += x; temp_part.position[1] += y; diff(particleList[i].position,temp_part.position, r_diff); diff( particleList[i].speed,temp_part.speed, v_diff); if( scalar_prod( r_diff, v_diff) < 0){ det = scalar_prod(r_diff,v_diff)*scalar_prod(r_diff,v_diff) - scalar_prod(v_diff,v_diff)*( scalar_prod(r_diff,r_diff) -SIGMA*SIGMA); if (det > 0){ //uso debug: printf("Scalar prod: %e \n",(scalar_prod(v_diff,v_diff))); temp = ( - scalar_prod( r_diff, v_diff) - sqrt( det ))/ (scalar_prod(v_diff,v_diff) ); if ( temp < min ){ min = temp; } } } } } return min; }
/* Q = Q + sum_i 1/lambda_i |eigen_i><eigen_i|P> */ void assign_add_invert_subtracted_part(spinor * const Q, spinor * const P, const int n, const int N) { int i=0; complex c; double rev=0; for(i = 0; i < n; i++){ c = scalar_prod(&eigenvectors[i*evlength], P, N, 1); rev = 1./eigenvls[i]; c.re *= rev; c.im *= rev; assign_add_mul(Q, &eigenvectors[i*evlength], c, N); } }
double Vector3D::angle(Vector3D another) { double cos_angle = scalar_prod(another) / (length()*another.length()); if (cos_angle > 1.0) { cos_angle = 1.0;} else if (cos_angle < -1.0) { cos_angle = -1.0; }; double angle_degr = degrees(acos(cos_angle)); return angle_degr; };
/*Evolve il sistema di uno step * Volendo calcolar dr2(t) l'evoluzioneva di step din step e tiene conto del fatto se facendo lo step temporale che porta alla collisione successiva si supera lo step temporale * fissato per il dr2(t) */ void evolve ( ) { double deltaV_pre[N]; double deltaV_post[N]; double deltaV[N]; unsigned int j = 0; //Calcola la prossima coppia che si scontra e mette il tempo di collisione in time_collision search_min_coll(); //Mfp da calcolare prima che si siano scambiate le velocità mean_free_path(); // /* Ossia: time_prec è l'ultimo tempo in cui si son salvati i dati total_time è il tempo corrente DeltaT è la larghezza di step temporale a cui si vuole calcolare dr2 if ( total_time + time_collision <time_prec+DeltaT ){ */ // Se non ha superato lo step temporale, muovi sempre prendere dati if ( total_time + time_collision - DeltaT -time_prec < 0){ step(time_collision); } /* Supererebbe lo step: * ~ muovi del tempo necessario per arrivare allo step * ~ prende dati * ~ muove del tempo necessario per arrivare a time_collision */ else{ time_counted++; step( time_prec + DeltaT - total_time); for ( j = 0; j< number_of_particles;j++){ time_list[time_counted*number_of_particles+j] = particleList[j]; } step( total_time+ time_collision - time_prec - DeltaT); time_prec += DeltaT; } diff(particleList[index_collision[0]].speed,particleList[index_collision[1]].speed,deltaV_pre); switch_speeds(); //calcoli pressione diff(particleList[index_collision[0]].speed,particleList[index_collision[1]].speed,deltaV_post); diff(deltaV_pre,deltaV_post,deltaV); //condizioni al bordo particleList[index_collision[0]].last_time_collision=total_time; particleList[index_collision[1]].last_time_collision=total_time; fix_boundaries(); substract_t0(); update_coll_table(); numOfCollisions ++; total_time+=time_collision; pression += sqrt(scalar_prod(deltaV,deltaV)); }
void vel_file_save ( ){ int i = 0; FILE *f = fopen("data/v2.dat","a"); FILE *fx = fopen ("data/vx.dat","a"); FILE *fy = fopen("data/vy.dat","a"); for (i = 0; i< number_of_particles ; i++){ fprintf(fx,"%e\n",particleList[i].speed[0]); fprintf(fy,"%e\n",particleList[i].speed[1]); fprintf(f,"%e\n",scalar_prod(particleList[i].speed,particleList[i].speed)); } fclose(fx); fclose(fy); fclose(f); }
void Proj_A_psi(spinor * const y, spinor * const x){ double mtheta = -p_theta; int i; /* y = A*x */ p_A_psi(y, x); /* y = -theta*x+y*/ _FT(daxpy)(&p_n2, &mtheta, (double*) x, &ONE, (double*) y, &ONE); /* p_work = Q^dagger*y */ for(i = 0; i < p_k; i++) { p_work[i] = scalar_prod((spinor*)(p_Q+i*p_lda), (spinor*) y, p_n*sizeof(_Complex double)/sizeof(spinor), 1); } /* y = y - Q*p_work */ _FT(zgemv)(fupl_n, &p_n, &p_k, &CMONE, p_Q, &p_lda, (_Complex double*) p_work, &ONE, &CONE, (_Complex double*) y, &ONE, 1); }
/*Modifica le velocità delle particelle coinvolte nella collisione*/ void switch_speeds(){ int j; int x,y; double temp_r_diff[N]; /* Vettore differenza temporaneo per le 9 immagini*/ double v_diff[N]; double rdiff[2]={0,0}; /*Vero vettore differenza*/ /* temp_r_diff = R0 - R1 * v_diff = V0 _ V1 */ double min = DBL_MAX; double tmp_dbl; particle_s temp_part; double v_temp; for ( x= -1; x < 2 ; x++){ for ( y = -1; y<2 ; y++){ temp_part = particleList[index_collision[1]]; temp_part.position[0] += x; temp_part.position[1] += y; diff(particleList[index_collision[0]].position,temp_part.position, temp_r_diff); /*vettore differenza salvato in temp_r_diff*/ tmp_dbl = scalar_prod(temp_r_diff,temp_r_diff) ; if ( tmp_dbl < min){ min = tmp_dbl; for ( j= 0; j<N; j++){ rdiff[j] = temp_r_diff[j]; } } } } diff( particleList[index_collision[0]].speed, particleList[index_collision[1]].speed, v_diff); scalar_mult( 1/(sqrt(scalar_prod(rdiff,rdiff))), rdiff); v_temp = scalar_prod(v_diff,rdiff); for ( j = 0 ; j < N ; j++){ particleList[index_collision[0]].speed[j] -= v_temp*rdiff[j]; particleList[index_collision[1]].speed[j] += v_temp*rdiff[j]; } }
void invert_eigenvalue_part(spinor * const Q, spinor * const P, const int n, const int N) { int i=0; complex c; double rev=0; /* c = scalar_prod(&eigenvectors[0], P, N, 1); */ /* rev = 1./eigenvls[0]; */ /* c.re *= rev; */ /* c.im *= rev; */ /* mul(Q, c, &eigenvectors[0], N); */ assign(Q, P, N); for(i = 0; i < n; i++){ c = scalar_prod(&eigenvectors[i*evlength], P, N, 1); c.re *= -inv_eigenvls[i]; c.im *= -inv_eigenvls[i]; assign_add_mul(Q, &eigenvectors[i*evlength], c, N); } }
static t_color get_spec(t_scene scene, t_light light, t_point light_inter, t_obj object) { t_point r; float dot; float reflet; reflet = 2.0f * scene.scal; r = new_point(light_inter.x - reflet * scene.normal.x, light_inter.y - reflet * scene.normal.y, light_inter.z - reflet * scene.normal.z); dot = scalar_prod(scene.ray, r); if (dot < 0.0f) { reflet = powf(dot, 20) * object.spec * light.intensity; scene.color = new_color(scene.color.red + reflet * light.color.red, scene.color.blue + reflet * light.color.blue, scene.color.green + reflet * light.color.green); } return (scene.color); }
/** * A map detector ID and Q ranges * This method looks unnecessary as it could be calculated on the fly but * the parallelization means that lazy instantation slows it down due to the * necessary CRITICAL sections required to update the cache. The Q range * values are required very frequently so the total time is more than * offset by this precaching step */ DetectorAngularCache initAngularCaches(const MatrixWorkspace *const workspace) { const size_t nhist = workspace->getNumberHistograms(); std::vector<double> thetas(nhist); std::vector<double> thetaWidths(nhist); std::vector<double> detectorHeights(nhist); auto inst = workspace->getInstrument(); const auto samplePos = inst->getSample()->getPos(); const V3D upDirVec = inst->getReferenceFrame()->vecPointingUp(); for (size_t i = 0; i < nhist; ++i) // signed for OpenMP { IDetector_const_sptr det; try { det = workspace->getDetector(i); } catch (Exception::NotFoundError &) { // Catch if no detector. Next line tests whether this happened - test // placed // outside here because Mac Intel compiler doesn't like 'continue' in a // catch // in an openmp block. } // If no detector found, skip onto the next spectrum if (!det || det->isMonitor()) { thetas[i] = -1.0; // Indicates a detector to skip thetaWidths[i] = -1.0; continue; } // We have to convert theta from radians to degrees const double theta = workspace->detectorSignedTwoTheta(*det) * rad2deg; thetas[i] = theta; /** * Determine width from shape geometry. A group is assumed to contain * detectors with the same shape & r, theta value, i.e. a ring mapped-group * The shape is retrieved and rotated to match the rotation of the detector. * The angular width is computed using the l2 distance from the sample */ if (auto group = boost::dynamic_pointer_cast<const DetectorGroup>(det)) { // assume they all have same shape and same r,theta auto dets = group->getDetectors(); det = dets[0]; } const auto pos = det->getPos() - samplePos; double l2(0.0), t(0.0), p(0.0); pos.getSpherical(l2, t, p); // Get the shape auto shape = det->shape(); // Defined in its own reference frame with centre at 0,0,0 BoundingBox bbox = shape->getBoundingBox(); auto maxPoint(bbox.maxPoint()); auto minPoint(bbox.minPoint()); auto span = maxPoint - minPoint; detectorHeights[i] = span.scalar_prod(upDirVec); thetaWidths[i] = 2.0 * std::fabs(std::atan((detectorHeights[i] / 2) / l2)) * 180.0 / M_PI; } DetectorAngularCache cache; cache.thetas = thetas; cache.thetaWidths = thetaWidths; cache.detectorHeights = detectorHeights; return cache; }
/* k output , l input */ int bicg(spinor * const k, spinor * const l, double eps_sq, const int rel_prec) { double err, d1, squarenorm=0.; complex rho0, rho1, omega, alpha, beta, nom, denom; int iteration, N=VOLUME/2; spinor * r, * p, * v, *hatr, * s, * t, * P, * Q; if(ITER_MAX_BCG > 0) { hatr = g_spinor_field[DUM_SOLVER]; r = g_spinor_field[DUM_SOLVER+1]; v = g_spinor_field[DUM_SOLVER+2]; p = g_spinor_field[DUM_SOLVER+3]; s = g_spinor_field[DUM_SOLVER+4]; t = g_spinor_field[DUM_SOLVER+5]; P = k; Q = l; squarenorm = square_norm(Q, VOLUME/2, 1); Mtm_plus_psi(r, P); gamma5(g_spinor_field[DUM_SOLVER], l, VOLUME/2); diff(p, hatr, r, N); assign(r, p, N); assign(hatr, p, N); rho0 = scalar_prod(hatr, r, N, 1); for(iteration = 0; iteration < ITER_MAX_BCG; iteration++){ err = square_norm(r, N, 1); if(g_proc_id == g_stdio_proc && g_debug_level > 1) { printf("BiCGstab: iterations: %d res^2 %e\n", iteration, err); fflush(stdout); } if (((err <= eps_sq) && (rel_prec == 0)) || ((err <= eps_sq*squarenorm) && (rel_prec == 1))){ break; } Mtm_plus_psi(v, p); denom = scalar_prod(hatr, v, N, 1); _div_complex(alpha, rho0, denom); assign(s, r, N); assign_diff_mul(s, v, alpha, N); Mtm_plus_psi(t, s); omega = scalar_prod(t,s, N, 1); d1 = square_norm(t, N, 1); omega.re/=d1; omega.im/=d1; assign_add_mul_add_mul(P, p, s, alpha, omega, N); assign(r, s, N); assign_diff_mul(r, t, omega, N); rho1 = scalar_prod(hatr, r, N, 1); _mult_assign_complex(nom, alpha, rho1); _mult_assign_complex(denom, omega, rho0); _div_complex(beta, nom, denom); omega.re=-omega.re; omega.im=-omega.im; assign_mul_bra_add_mul_ket_add(p, v, r, omega, beta, N); rho0.re = rho1.re; rho0.im = rho1.im; } if(g_proc_id==0 && g_debug_level > 0) { printf("BiCGstab: iterations: %d eps_sq: %1.4e\n", iteration, eps_sq); } } else{ iteration = ITER_MAX_BCG; gamma5(k, l, VOLUME/2); } /* if bicg fails, redo with conjugate gradient */ if(iteration>=ITER_MAX_BCG){ iteration = solve_cg(k,l,eps_sq, rel_prec); /* Save the solution for reuse! not needed since Chronological inverter is there */ /* assign(g_spinor_field[DUM_DERI+6], k, VOLUME/2); */ Qtm_minus_psi(k, k);; } return iteration; }
int cr(spinor * const P, spinor * const Q, const int m, const int max_restarts, const double eps_sq, const int rel_prec, const int N, const int precon, matrix_mult f) { int k, l, restart, i, iter = 0; double norm_sq, err; spinor * xi, * Axi, * chi, * Achi, *tmp; _Complex double alpha, beta; static _Complex double one = 1.0; double norm, rAr, newrAr; double atime, etime; spinor ** solver_field = NULL; const int nr_sf = 5; int save_sloppy = g_sloppy_precision; if(N == VOLUME) { init_solver_field(&solver_field, VOLUMEPLUSRAND, nr_sf); } else { init_solver_field(&solver_field, VOLUMEPLUSRAND/2, nr_sf); } atime = gettime(); xi = solver_field[0]; Axi = solver_field[1]; chi = solver_field[2]; Achi = solver_field[3]; tmp = solver_field[4]; norm_sq = square_norm(Q, N, 1); if(norm_sq < 1.e-32) { norm_sq = 1.; } dfl_sloppy_prec = 0; f(tmp, P); diff(chi, Q, tmp, N); assign(xi, chi, N); f(Axi, xi); f(Achi, chi); rAr = scalar_prod(chi, Achi, N, 1); err = square_norm(chi, N, 1); if(((err <= eps_sq) && (rel_prec == 0)) || ((err <= eps_sq*norm_sq) && (rel_prec == 1))) { finalize_solver(solver_field, nr_sf); return(iter); } for(k = 0; k < m; k++) { dfl_sloppy_prec = 1; norm = square_norm(Axi, N, 1); alpha = rAr/norm; assign_add_mul(P, xi, alpha, N); /* get the new residual */ assign_diff_mul(chi, Axi, alpha, N); err = square_norm(chi, N, 1); iter ++; etime = gettime(); if(g_proc_id == g_stdio_proc && g_debug_level > 3){ printf("# CR: %d\t%g iterated residue, time spent %f s\n", iter, err, (etime - atime)); fflush(stdout); } /* Precision reached? */ if((k == m-1) || ((err <= eps_sq) && (rel_prec == 0)) || ((err <= eps_sq*norm_sq) && (rel_prec == 1))) { break; } #ifdef _USE_HALFSPINOR if(((err*err <= eps_sq) && (rel_prec == 0)) || ((err*err <= eps_sq*norm_sq) && (rel_prec == 1))) { if (g_sloppy_precision_flag == 1) { g_sloppy_precision = 1; if(g_debug_level > 2 && g_proc_id == g_stdio_proc) { printf("sloppy precision on\n"); fflush( stdout); } } } #endif f(Achi, chi); newrAr = scalar_prod(chi, Achi, N, 1); beta = newrAr/rAr; assign_mul_add_mul(xi, beta, chi, one, N); assign_mul_add_mul(Axi,beta, Achi, one, N); rAr = newrAr; } g_sloppy_precision = save_sloppy; finalize_solver(solver_field, nr_sf); return(-1); }
int main(int argc,char *argv[]) { char spinorfilename[100]; char * filename = NULL; int sample=0, ts=0, ss=1, typeflag = 1, t0=0, piononly = 0, ext_sourceflag = 0; int is, ic, j, filenameflag = 0, appendflag = 0; complex co; int c; int prec=32; verbose = 0; g_use_clover_flag = 0; nstore = 0; L=0; T=0; #ifdef MPI MPI_Init(&argc, &argv); #endif #ifdef OMP /* FIXME: in principle this should not be set like this as it could result in thread oversubscription when more than one process is run locally unfortunately, there does not seem to be a standard way to determine the number of "local" MPI processes */ omp_num_threads = omp_get_max_threads(); init_openmp(); #endif while ((c = getopt(argc, argv, "h?NCpOEdao:L:T:n:t:s:S:P:")) != -1) { switch (c) { case 'L': L = atoi(optarg); LX = L; LY = L; LZ = L; break; case 'T': T = atoi(optarg); T_global = T; break; case 'N': typeflag = 0; break; case 'd': prec = 64; break; case 'O': piononly = 1; break; case 'n': nstore = atoi(optarg); break; case 's': sample = atoi(optarg); break; case 't': t0 = atoi(optarg); break; case 'S': ss = atoi(optarg); break; case 'P': ts = atoi(optarg); break; case 'o': filename = calloc(200, sizeof(char)); strcpy(filename,optarg); break; case 'E': ext_sourceflag = 1; break; case 'p': filenameflag = 1; break; case 'a': appendflag = 1; break; case 'h': case '?': default: usage(); break; } } if(ts == 0) { ts = T; } if(filename == NULL){ filename = "source"; } if(L==0 || T==0) { if(g_proc_id == 0) { fprintf(stderr, "L and T must be specified! Aborting...\n"); fflush( stderr ); } exit(1); } tmlqcd_mpi_init(argc, argv); j = init_geometry_indices(VOLUMEPLUSRAND); if ( j!= 0) { fprintf(stderr, "Not enough memory for geometry_indices! Aborting...\n"); exit(0); } if(!ext_sourceflag) { j = init_spinor_field(VOLUMEPLUSRAND/2, 2); } else { j = init_spinor_field(VOLUMEPLUSRAND/2, 4); } if ( j!= 0) { fprintf(stderr, "Not enough memory for spinor fields! Aborting...\n"); exit(0); } /* define the geometry */ geometry(); if(!piononly) { for(is = 0; is < 4; is ++) { for(ic = 0; ic < 3; ic++) { if(!filenameflag && !appendflag) { sprintf(spinorfilename, "%s.%.4d.%.4d.%.2d.%.2d", filename, nstore, sample, t0, 3*is+ic); } else if(!filenameflag && appendflag) { sprintf(spinorfilename, "%s.%.4d.%.4d.%.2d", filename, nstore, sample, t0); } else{ sprintf(spinorfilename, "%s.%.2d", filename, 3*is+ic); } if(!appendflag || (is == 0 && ic ==0)) { printf("Generating source %s!\n", spinorfilename); fflush(stdout); } source_generation_nucleon(g_spinor_field[0], g_spinor_field[1], is, ic, t0, ts, ss, sample, nstore, typeflag); co = scalar_prod(g_spinor_field[1], g_spinor_field[1], VOLUME/2, 1); if((is == 0 && ic == 0) || appendflag == 0) { write_source_type(0, spinorfilename); } write_source(g_spinor_field[0], g_spinor_field[1], spinorfilename, 1, prec); } } } else { if(!ext_sourceflag) { if(!filenameflag) { sprintf(spinorfilename, "%s.%.4d.%.4d.%.2d", filename, nstore, sample, t0); } else { sprintf(spinorfilename, "%s", filename); } printf("Generating source %s!\n", spinorfilename); fflush(stdout); source_generation_pion_only(g_spinor_field[0], g_spinor_field[1], t0, sample, nstore); co = scalar_prod(g_spinor_field[1], g_spinor_field[1], VOLUME/2, 1); write_source_type(0, spinorfilename); write_source(g_spinor_field[0], g_spinor_field[1], spinorfilename, 1, prec); } else { if(!filenameflag) { sprintf(spinorfilename, "%s.%.4d.%.4d.%.2d.inverted", filename, nstore, sample, t0); } else { sprintf(spinorfilename, "%s.inverted", filename); } read_lime_spinor(g_spinor_field[0], g_spinor_field[1], spinorfilename, 0); printf("Generating ext. pion source %s!\n", spinorfilename); extended_pion_source(g_spinor_field[2], g_spinor_field[3], g_spinor_field[0], g_spinor_field[1], t0, 0., 0., 0.); if(!filenameflag) { sprintf(spinorfilename, "g%s.%.4d.%.4d.%.2d", filename, nstore, sample, t0); } else { sprintf(spinorfilename, "g%s", filename); } write_source_type(0, spinorfilename); write_source(g_spinor_field[2], g_spinor_field[3], spinorfilename, 1, prec); } } #ifdef MPI MPI_Finalize(); #endif free_geometry_indices(); free_spinor_field(); return(0); }