Пример #1
0
/*
 * Bracketing root solver using False-Position method
 *
 * Takes a function pointer (*f) for the function to be solved, expects
 * inital guesses for upper and lower bounds, and the error tolerance.
 * Returns the solution as a double.
 *
 * @param *f	double(*_)(double) function pointer to the function for which we want to find a root
 * @param lower		double with the initial lower bracket
 * @param upper		double with the initial upper bracket
 * @param numIterations		int reference to count and pass back the number of iterations required to solve this problem
 * @param errLimit	double providing the error tolerance
 * @return double	return the root solution within the bracket
 */
double rootSolvers::falsePosition(double (*f)(double), double lower,
		double upper, int& numIterations, double errLimit)
{
	double root = upper;
	numIterations = 0;
	double err = 1.0;
	int upperStaleCounter = 0;
	int lowerStaleCounter = 0;

	double f_l = f(lower);
	double f_u = f(upper);
	double f_r = f(root);

//	while ((fabs(f_r)) > errLimit)

	while (err > errLimit)
	{
		double root_old = root;
		root = (upper - ((f_u * (lower - upper)) / (f_l - f_u)));
		f_r = f(root);
		++numIterations;

		std::cout << "It: " << numIterations << "\n";
		std::cout << "root: " << root << "\n";

		if (root != 0.0)
		{
			err = relErr(root, root_old);
		}

		double test = f_l * f_r;
		if (test < 0.0)
		{
			upper = root;
			f_u = f_r;
			upperStaleCounter = 0;
			lowerStaleCounter++;
			if (lowerStaleCounter >= 2)
			{
				f_l = f_l / 2.0;
			}
		}
		else if (test > 0.0)
		{
			lower = root;
			f_l = f_r;
			lowerStaleCounter = 0;
			upperStaleCounter++;
			if (upperStaleCounter >= 2)
			{
				f_u = f_u / 2.0;
			}
		}
		else
			err = 0.0;
	}
	return root;
}
Пример #2
0
int NonLinearLSQ::curvefit() {

  size_t n(nSize());
  size_t p(nParms());

  //  Initialize the solver function information
  _nlsqPointer d = { this };
  gsl_multifit_function_fdf mf;
  mf.f      = &f;
  mf.df     = &df;
  mf.fdf    = &fdf;
  mf.n      =  n;
  mf.p      = p;
  mf.params =  &d;

  const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder;
  gsl_multifit_fdfsolver *s = gsl_multifit_fdfsolver_alloc(T, n, p);

  _fitParms = guess();
  gsl_vector *x = NlsqTogsl(_fitParms);
  gsl_matrix *covar = gsl_matrix_alloc(p, p);
  gsl_multifit_fdfsolver_set(s, &mf, x);

  _nIters = 0;
  checkIteration(_nIters, gslToNlsq(s->x), NLVector(p,999.0),
                  gsl_blas_dnrm2(s->f), GSL_CONTINUE);


  do {
    _nIters++;

    _status = gsl_multifit_fdfsolver_iterate(s);
    _fitParms = gslToNlsq(s->x);

    gsl_multifit_covar(s->J, 0.0, covar);
    _uncert = getUncertainty(covar);

    _status = checkIteration(_nIters, _fitParms, _uncert, gsl_blas_dnrm2(s->f),
                             _status);
    if ( _status  ) { break; }
    if(!doContinue()) { break; }

    _status = gsl_multifit_test_delta(s->dx, s->x, absErr(), relErr());
  } while ((_status == GSL_CONTINUE) && (_nIters < _maxIters));

  // Clean up
  gsl_multifit_fdfsolver_free(s);
  gsl_matrix_free(covar);

  return (_status);
}
Пример #3
0
/*
 * Open Newton-Raphson method root solver
 *
 * Takes a function pointer (*f) for the function to be solved, expects
 * an inital guess for the root x_0, and the error tolerance.
 * Returns the solution.
 *
 * @param *f	double(*_)(double) function pointer to the function for which we want to find a root
 * @param root		double with initial guess for the root location
 * @param numIterations		int reference to count and pass back the number of iterations required to solve this problem
 * @param errLimit	double providing the error tolerance
 * @return double	return the root solution within the bracket
 */
double rootSolvers::newton(double (*f)(double), double (*f_prime)(double),
		double root, int& numIterations, double errLimit)
{
	numIterations = 0;
	double err = 1.0;

	while ((err > errLimit) && (numIterations < 10000))
	{
		double r_old = root;
		double slope_tangent = f_prime(r_old);

		std::cout << "It: " << numIterations << "\n";
		std::cout << "root: " << root << "\n";
//		std::cout << "Slope at r_old: " << slope_tangent << "\n";

		if (relErr(0.0, slope_tangent) < 0.000001)
		{
			throw std::runtime_error(
					"slope_tangent == 0, Newton method failed.");
		}
		root = (r_old - (f(r_old) / f_prime(r_old)));
		numIterations++;
		if (root != 0.0)
		{
			err = relErr(root, r_old);
		}
	}
	double solution_check = f(root);

	if ((relErr(0.0, solution_check) > 0.01) || (numIterations == 100000))
	{
		throw std::runtime_error("No convergence, Newton method failed.");
	}

	return root;
}
Пример #4
0
int main(int argc, char**argv)
{
    int err;
    int i;
    double t0, t1;
    FmmvHandle _FMMV;
    FmmvHandle *FMMV = &_FMMV;
    void (*GEN_M)(FmmvHandle *FMMV, Box *box);
    void (*EVAL_M)(FmmvHandle *FMMV, Box *target, Box *source);
    void (*EVAL_L)(FmmvHandle *FMMV, Box *box);
    void (*GEN_L)(FmmvHandle *FMMV, Box *target, Box *source);
    void (*GEN_L_EVAL_M)(FmmvHandle *FMMV, Box *target, Box *source);
    void (*EVAL_DIRECT)(FmmvHandle *FMMV, Box *target, Box *source) = FMMV->eval_direct;

    Box _box_A;
    Box _box_B;

    Box *box_A = &_box_A;
    Box *box_B = &_box_B;

    Box _child_A[4];
    Box _child_B[4];

    int NParticles = 100;
    int NTargets = 100;
     _FLOAT_ (*particles)[2];
     _FLOAT_ (*targets)[2] = NULL;
     _FLOAT_ *charges;
     _FLOAT_ (*dipoleMoments)[2] = NULL;
     _FLOAT_ x, y;
     _FLOAT_ *potM;
     _FLOAT_ *potL;
     _FLOAT_ (*gradM)[2] = NULL;
     _FLOAT_ (*gradL)[2] = NULL;
     _FLOAT_ *exPot;
     _FLOAT_ (*exGrad)[2] = NULL;
     _FLOAT_ errL2, errL2grad;
     double beta = 0.0;
     int pM = 8;
     int pL = 8;
     int s = 8;
     int *perm;
     int *permTargets;
     int with_dipoleSources=0;
     int with_gradients=0;
     int LM_combined=0;
     int with_M2M=0;
     int with_L2L=0;
     int printResult=0;
#ifdef USE_SINGLE_PRECISION 
     int exAcc=1;
#else     
     int exAcc=2;
#endif
     //int exAcc=0;

    _FLOAT_ x_A = .125;
    _FLOAT_ y_A = .125;
    double size_A = .0625;
    int level_A = 2;
    _FLOAT_ x_B = .875;
    _FLOAT_ y_B = .875;
    double size_B = .0625;
    int level_B = 2;

    feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );


    set_from_command_line_double(argc, argv, "beta", &beta);
    set_from_command_line_bool(argc, argv, "dipoleSources", &with_dipoleSources);
    set_from_command_line_bool(argc, argv, "gradients", &with_gradients);
    set_from_command_line_bool(argc, argv, "printResult", &printResult);
    set_from_command_line_bool(argc, argv, "LM_combined", &LM_combined);
    set_from_command_line_bool(argc, argv, "M2M", &with_M2M);
    set_from_command_line_bool(argc, argv, "L2L", &with_L2L);
    set_from_command_line_int(argc, argv, "directEvalAccuracy", &exAcc);
 
        if (with_dipoleSources) {
            if (with_gradients) {
                FMMV->dataKind = FMM_ST_DIPOLE_GRAD;
                GEN_M = gen_M_ST_dipole_grad;
                EVAL_M = eval_M_ST_dipole_grad;
                GEN_L = gen_L_ST_dipole_grad;
                EVAL_L = eval_L_ST_dipole_grad;
                GEN_L_EVAL_M = gen_L_eval_M_dipole_grad;
                switch (exAcc) {
                    case 0: EVAL_DIRECT = eval_direct_ST_dipole_grad_acc0; break;
                    case 1: EVAL_DIRECT = eval_direct_ST_dipole_grad_acc1; break;
#if FMM_PRECISION==1
                    case 2: EVAL_DIRECT = eval_direct_ST_dipole_grad_acc2; break;
#endif                
                }    
            }
            else {
                FMMV->dataKind = FMM_ST_DIPOLE;
                GEN_M = gen_M_ST_dipole;
                EVAL_M = eval_M_ST_dipole;
                GEN_L = gen_L_ST_dipole;
                EVAL_L = eval_L_ST_dipole;
                GEN_L_EVAL_M = gen_L_eval_M_dipole;
                switch (exAcc) {
                    case 0: EVAL_DIRECT = eval_direct_ST_dipole_acc0; break;
                    case 1: EVAL_DIRECT = eval_direct_ST_dipole_acc1; break;
#if FMM_PRECISION==1
                    case 2: EVAL_DIRECT = eval_direct_ST_dipole_acc2; break;
#endif                
                }    
            }
        }
        else {
            if (with_gradients) {
                FMMV->dataKind = FMM_ST_GRAD;
                GEN_M = gen_M_ST_grad;
                EVAL_M = eval_M_ST_grad;
                GEN_L = gen_L_ST_grad;
                EVAL_L = eval_L_ST_grad;
                GEN_L_EVAL_M = gen_L_eval_M_grad;
                switch (exAcc) {
                    case 0: EVAL_DIRECT = eval_direct_ST_grad_acc0; break;
                    case 1: EVAL_DIRECT = eval_direct_ST_grad_acc1; break;
#if FMM_PRECISION==1
                    case 2: EVAL_DIRECT = eval_direct_ST_grad_acc2; break;
#endif                
                }    
            }
            else {
                FMMV->dataKind = FMM_ST_STANDARD;
                GEN_M = gen_M_ST_standard;
                EVAL_M = eval_M_ST_standard;
                GEN_L = gen_L_ST_standard;
                EVAL_L = eval_L_ST_standard;
                GEN_L_EVAL_M = gen_L_eval_M_standard;
                switch (exAcc) {
                    case 0: EVAL_DIRECT = eval_direct_ST_standard_acc0; break;
                    case 1: EVAL_DIRECT = eval_direct_ST_standard_acc1; break;
#if FMM_PRECISION==1
                    case 2: EVAL_DIRECT = eval_direct_ST_standard_acc2; break;
#endif                
                }    
            }
        }

    set_from_command_line_int(argc, argv, "NParticles", &NParticles);
    set_from_command_line_int(argc, argv, "NTargets", &NTargets);
    set_from_command_line_int(argc, argv, "pM", &pM);
    set_from_command_line_int(argc, argv, "pL", &pL);
    set_from_command_line_int(argc, argv, "s", &s);
    set_from_command_line_int(argc, argv, "level_A", &level_A);
    set_from_command_line_int(argc, argv, "level_B", &level_B);
//    set_from_command_line_double(argc, argv, "size_A", &size_A);
//    set_from_command_line_double(argc, argv, "size_B", &size_B);
    size_A = ldexp(1.0, -level_A);
    size_B = ldexp(1.0, -level_B);
    
    particles = (_FLOAT_ (*)[2]) calloc(NParticles, 2*sizeof(_FLOAT_));  
    charges = (_FLOAT_ *) calloc(NParticles, sizeof(_FLOAT_));  
    perm = (int *) calloc(NParticles, sizeof(int));  
    permTargets = (int *) calloc(NTargets, sizeof(int));  
    targets = (_FLOAT_ (*)[2]) calloc(NTargets, 2*sizeof(_FLOAT_));  
    potM = (_FLOAT_ *) calloc(NTargets, sizeof(_FLOAT_));
    potL = (_FLOAT_ *) calloc(NTargets, sizeof(_FLOAT_));
    exPot = (_FLOAT_ *) calloc(NTargets, sizeof(_FLOAT_));
    if (with_gradients) {
	gradM = (_FLOAT_ (*)[2]) calloc(NTargets, 2*sizeof(_FLOAT_));  
	gradL = (_FLOAT_ (*)[2]) calloc(NTargets, 2*sizeof(_FLOAT_));  
	exGrad = (_FLOAT_ (*)[2]) calloc(NTargets, 2*sizeof(_FLOAT_));  
    }	   
    if (with_dipoleSources) {
	dipoleMoments = (_FLOAT_ (*)[2]) calloc(NParticles, 2*sizeof(_FLOAT_));  
    }

    FMMV->beta = beta;
    FMMV->pM = pM;
    FMMV->pL = pL;
    FMMV->s_eps = s;
    FMMV->particles = particles;
    FMMV->charges = charges;
    FMMV->dipoleMoments = dipoleMoments;
    FMMV->perm = perm;
    FMMV->NParticles = NParticles;
    FMMV->targets = targets;
    FMMV->permTargets = permTargets;
    FMMV->NTargets = NTargets;
    FMMV->scale = 1.0;
    FMMV->lambda = 0;

    my_srand(1481765933);

    box_A->firstParticle = 0;
    box_A->noOfParticles = NParticles;
    box_A->x = x_A;
    box_A->y = y_A;
    box_A->level = level_A;
    box_A->M = 0; 
    /* if (with_M2M) */ {
        int m = NParticles/4;
        double d = 0.25*size_A;
        int c;
        for (c=0; c<4; c++) {
            box_A->child[c] = &_child_A[c];
            box_A->child[c]->level = level_A + 1;
            box_A->child[c]->M = 0;
            box_A->child[c]->firstParticle = c*m;
            box_A->child[c]->noOfParticles = m;
        }
        box_A->child[3]->noOfParticles = NParticles - box_A->child[3]->firstParticle;
         
        box_A->child[SW]->x = x_A - d;
        box_A->child[SW]->y = y_A - d;

        box_A->child[NW]->x = x_A - d;
        box_A->child[NW]->y = y_A + d;

        box_A->child[SE]->x = x_A + d;
        box_A->child[SE]->y = y_A - d;

        box_A->child[NE]->x = x_A + d;
        box_A->child[NE]->y = y_A + d;

        for (c=0; c<4; c++) {
            for (i = box_A->child[c]->firstParticle; i < box_A->child[c]->firstParticle+box_A->child[c]->noOfParticles; i++) {
                x = box_A->child[c]->x + 2.0*d*(my_rand() / (_FLOAT_) MY_RAND_MAX) - d;
                y = box_A->child[c]->y + 2.0*d*(my_rand() / (_FLOAT_) MY_RAND_MAX) - d;
                particles[i][0] = x;
                particles[i][1] = y;
            }
        }
    }
    /* else {
        double d = size_A/2.0;
        for (i=0;i<NParticles;i++) {
            x = x_A + size_A*(my_rand() / (_FLOAT_) MY_RAND_MAX) - d;
            y = y_A + size_A*(my_rand() / (_FLOAT_) MY_RAND_MAX) - d;
            particles[i][0] = x;
            particles[i][1] = y;
        }    
    }*/
    for (i=0;i<NParticles;i++) {
        perm[i] = i;
        charges[i] = 1.0;
    }
    if (with_dipoleSources) {
        for (i=0;i<NParticles;i++) {
            x = (my_rand() / (_FLOAT_) MY_RAND_MAX) - 0.5;
            y = (my_rand() / (_FLOAT_) MY_RAND_MAX) - 0.5;
            dipoleMoments[i][0] = x;
            dipoleMoments[i][1] = y;

        }
    }

    box_B->firstTarget = 0;
    box_B->noOfTargets = NTargets;
    box_B->x = x_B;
    box_B->y = y_B;
    box_B->level = level_B;
    box_B->L = 0; 
    /* if (with_L2L)  */ { 
        int m = NTargets/4;
        double d = 0.25*size_B;
        int c;
        for (c=0; c<4; c++) {
            box_B->child[c] = &_child_B[c];
            box_B->child[c]->level = level_B + 1;
            box_B->child[c]->L = 0;
            box_B->child[c]->firstTarget = c*m;
            box_B->child[c]->noOfTargets = m;
        }
        box_B->child[3]->noOfTargets = NTargets - box_B->child[3]->firstTarget;
         
        box_B->child[SW]->x = x_B - d;
        box_B->child[SW]->y = y_B - d;

        box_B->child[NW]->x = x_B - d;
        box_B->child[NW]->y = y_B + d;

        box_B->child[SE]->x = x_B + d;
        box_B->child[SE]->y = y_B - d;

        box_B->child[NE]->x = x_B + d;
        box_B->child[NE]->y = y_B + d;

        for (c=0; c<4; c++) {
            for (i = box_B->child[c]->firstTarget; i < box_B->child[c]->firstTarget+box_B->child[c]->noOfTargets; i++) {
                x = box_B->child[c]->x + 2.0*d*(my_rand() / (_FLOAT_) MY_RAND_MAX) - d;
                y = box_B->child[c]->y + 2.0*d*(my_rand() / (_FLOAT_) MY_RAND_MAX) - d;
                targets[i][0] = x;
                targets[i][1] = y;
            }
        }
    }
    /* else {
        double d = size_B/2.0;
        for (i=0;i<NTargets;i++) {
            x = x_B + size_B*(my_rand() / (_FLOAT_) MY_RAND_MAX) - d;
            y = y_B + size_B*(my_rand() / (_FLOAT_) MY_RAND_MAX) - d;
            targets[i][0] = x;
            targets[i][1] = y;
        }    
    } */
    for (i=0;i<NTargets;i++) {
        permTargets[i] = i;
    }
    


    init_all(FMMV);

    err = ida_allocate(FMMV);
    copy_particles(FMMV);
    copy_charges(FMMV);
    
    zero_pot(FMMV);
    t0 = (double) clock()/CLOCKS_PER_SEC;
    EVAL_DIRECT(FMMV, box_B, box_A);
    t1 = (double) clock()/CLOCKS_PER_SEC - t0;
    printf("time (eval_direct)  : %7.4f\n", t1);
    FMMV->potentials = exPot;
    FMMV->gradients = exGrad;
    backcopy_pot(FMMV);
    if (with_M2M||with_L2L) { // in init_M2M is initialisation als necessary for L2L
        init_M2M(FMMV, -1);
    }
    if (with_M2M) {
        int c;
        t0 = (double) clock()/CLOCKS_PER_SEC;
        for (c=0; c<4; c++) {
            GEN_M(FMMV, box_A->child[c]);    
        }
        t1 = (double) clock()/CLOCKS_PER_SEC - t0;
        printf("time (GEN_M)        : %7.4f\n", t1);
        //init_M2M(FMMV, -1);
        init_M2M(FMMV, level_A);
        t0 = (double) clock()/CLOCKS_PER_SEC;
        M2M(FMMV, box_A);
        t1 = (double) clock()/CLOCKS_PER_SEC - t0;
        printf("time (M2M)          : %7.4f\n", t1);
    }
    else {
        t0 = (double) clock()/CLOCKS_PER_SEC;
        GEN_M(FMMV, box_A);
        t1 = (double) clock()/CLOCKS_PER_SEC - t0;
        printf("time (GEN_M)        : %7.4f\n", t1);
    }    
/*
    printf("M:\n");
    for (i=0;i<=pM;i++) {
        printf("%3i %24.16e %24.16e\n", i, box_A->M[2*i], box_A->M[2*i+1]);
    }	
*/
    		
        zero_pot(FMMV);
        t0 = (double) clock()/CLOCKS_PER_SEC;
        EVAL_M(FMMV, box_B, box_A);
        t1 = (double) clock()/CLOCKS_PER_SEC - t0;
        printf("time (EVAL_M)       : %7.4f\n", t1);
        FMMV->potentials = potM;
        FMMV->gradients = gradM;
        backcopy_pot(FMMV);

        t0 = (double) clock()/CLOCKS_PER_SEC;
        GEN_L(FMMV, box_B, box_A);
        t1 = (double) clock()/CLOCKS_PER_SEC - t0;
        printf("time (GEN_L)        : %7.4f\n", t1);

    zero_pot(FMMV);
    if (with_L2L) {
        int c;
        init_L2L(FMMV, -1);
        init_L2L(FMMV, level_B);
        t0 = (double) clock()/CLOCKS_PER_SEC;
        L2L(FMMV, box_B);
        t1 = (double) clock()/CLOCKS_PER_SEC - t0;
        printf("time (L2L)          : %7.4f\n", t1);
        t0 = (double) clock()/CLOCKS_PER_SEC;
        for (c=0; c<4; c++) {
            EVAL_L(FMMV, box_B->child[c]);    
        }
        t1 = (double) clock()/CLOCKS_PER_SEC - t0;
        printf("time (EVAL_L)       : %7.4f\n", t1);
        printf("L:\n");
        for (i=0;i<=pL;i++) {
            printf("%3i %24.16e %24.16e\n", i, box_B->child[3]->L[2*i], box_B->child[3]->L[2*i+1]);
        }	
    }
    else {
        t0 = (double) clock()/CLOCKS_PER_SEC;
        EVAL_L(FMMV, box_B);
        t1 = (double) clock()/CLOCKS_PER_SEC - t0;
        printf("time (EVAL_L)       : %7.4f\n", t1);
        printf("L:\n");
        for (i=0;i<=pL;i++) {
            printf("%3i %24.16e %24.16e\n", i, box_B->L[2*i], box_B->L[2*i+1]);
        }	
    }
    FMMV->potentials = potL;
    FMMV->gradients = gradL;
    backcopy_pot(FMMV);

    ida_free(FMMV);

    if (with_gradients) {
	relL2Err(0, 0, 0); /* init */
	relL2Err2(0, NULL, NULL); /* init */

	if (printResult) {
  	    printf("\n          Pot(M)   Pot(exact)     rel.err.  rel.err.(grad)\n");
	    printf("============================================================\n");
	}	
	for (i=0; i<NTargets; i++) {
	    relL2Err(1, potM[i], exPot[i]); /* accumulate */
	    relL2Err2(1, gradM[i], exGrad[i]); /* accumulate */
	    if (printResult) {
	        printf("%3i %12.4e %12.4e %12.4e %12.4e\n", i, (double) potM[i], (double) exPot[i], (double) relErr(potM[i], exPot[i]),(_FLOAT_) relErr2(gradM[i], exGrad[i]));
	    }	
  	}
	errL2 = relL2Err(2, 0, 0); /*finalize*/ 
	errL2grad = relL2Err2(2, NULL, NULL); /*finalize*/ 
	printf ("\nerr_L2(potM) = %.4e  err_L2(gradM) = %.4e\n", errL2, errL2grad);

        printf("%24.16e %24.16e\n", exGrad[0][0], exGrad[0][1]);
        printf("%24.16e %24.16e\n", gradM[0][0], gradM[0][1]);
        
	relL2Err(0, 0, 0); /* init */
	relL2Err2(0, NULL, NULL); /* init */

	if (printResult) {
  	    printf("\n          Pot(L)   Pot(exact)     rel.err.  rel.err.(grad)\n");
	    printf("============================================================\n");
	}	
	for (i=0; i<NTargets; i++) {
	    relL2Err(1, potL[i], exPot[i]); /* accumulate */
	    relL2Err2(1, gradL[i], exGrad[i]); /* accumulate */
	    if (printResult) {
	        printf("%3i %12.4e %12.4e %12.4e %12.4e\n", i, (double) potL[i], (double) exPot[i], (double) relErr(potL[i], exPot[i]),(_FLOAT_) relErr2(gradL[i], exGrad[i]));
	    }	
  	}
	errL2 = relL2Err(2, 0, 0); /*finalize*/ 
	errL2grad = relL2Err2(2, NULL, NULL); /*finalize*/ 
	printf ("\nerr_L2(potL) = %.4e  err_L2(gradL) = %.4e\n", errL2, errL2grad);

        printf("%24.16e %24.16e\n", exGrad[0][0], exGrad[0][1]);
        printf("%24.16e %24.16e\n", gradL[0][0], gradL[0][1]);
    }
    else {
        relL2Err(0, 0, 0);
        if (printResult) {
            printf("\n          Pot(M)   Pot(exact)     rel.err.\n");
            printf("============================================\n");
        }
        for (i=0; i<NTargets; i++) {
            relL2Err(1, potM[i], exPot[i]); /* accumulate */
            if (printResult) {
	       printf("%3i %12.4e %12.4e %12.4e\n", i, (double) potM[i], (double) exPot[i], (double) relErr(potM[i], exPot[i]));
            }   
        }
        errL2 = relL2Err(2, 0, 0); /*finalize*/ 
        printf ("\nerr_L2(potM) = %.4e\n", errL2);
    
        relL2Err(0, 0, 0);
        if (printResult) {
            printf("\n          Pot(L)   Pot(exact)     rel.err.\n");
            printf("============================================\n");
        }
        for (i=0; i<NTargets; i++) {
            relL2Err(1, potL[i], exPot[i]); /* accumulate */
            if (printResult) {
	       printf("%3i %12.4e %12.4e %12.4e\n", i, (double) potL[i], (double) exPot[i], (double) relErr(potL[i], exPot[i]));
            }   
        }
        errL2 = relL2Err(2, 0, 0); /*finalize*/ 
        printf ("\nerr_L2(potL) = %.4e\n", errL2);
    }
    
    // TODO: deallocate...
    finish_all(FMMV);

    return 0;
}
Пример #5
0
int main(int argc, char**argv)
{
    int err;
    int i;
    FmmvHandle _FMMV;
    FmmvHandle *FMMV = &_FMMV;
    void (*GEN_M)(FmmvHandle *FMMV, Box *box);
    void (*GEN_L)(FmmvHandle *FMMV, Box *target, Box *source);
    void (*EVAL_L)(FmmvHandle *FMMV, Box *box);
    void (*EVAL_DIRECT)(FmmvHandle *FMMV, Box *target, Box *source) = FMMV->eval_direct;

    _FLOAT_ X1[8*FMM_S_EXP_MAX];
    _FLOAT_ X2[8*FMM_S_EXP_MAX];
    _FLOAT_ X[FMM_S_EXP_MAX];
    _FLOAT_ D[FMM_S_EXP_MAX];


    Box _box_A;
    Box _box_B;
    Box _parent_A;
    Box _parent_B;
    int which_child_A = SWD;
    int which_child_B = SWD;


    Box *box_A = &_box_A;
    Box *box_B = &_box_B;
    Box *parent_A = &_parent_A;
    Box *parent_B = &_parent_B;

    int NParticles = 100;
    int NTargets = 100;
     _FLOAT_ (*particles)[3];
     _FLOAT_ (*targets)[3] = NULL;
     _FLOAT_ *charges;
     _FLOAT_ x, y, z;
     _FLOAT_ x_B, y_B, z_B;
     _FLOAT_ x_A, y_A, z_A;
     _FLOAT_ *potX;
     _FLOAT_ *potL;
     _FLOAT_ *exPot;
     _FLOAT_ errL2;
     double beta = 0.0;
     int pM = 8;
     int pL = 8;
     int s = 8;
     int *perm;
     int *permTargets;
     int printResult=0;

    int level = 2;
    _FLOAT_ size;
    
    _FLOAT_ dx = 1;
    _FLOAT_ dy = 1;
    _FLOAT_ dz = 2;

  feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );


    FMMV->dataKind = FMM_ST_STANDARD;
    GEN_M = gen_M_ST_standard;
    GEN_L = gen_L_ST_standard;
    EVAL_L = eval_L_ST_standard;
#if (FMM_PRECISION==0)
    EVAL_DIRECT = eval_direct_ST_standard_acc1; 
#else
    EVAL_DIRECT = eval_direct_ST_standard_acc2;
#endif

    set_from_command_line_double(argc, argv, "beta", &beta);
    set_from_command_line_bool(argc, argv, "printResult", &printResult);
    set_from_command_line_int(argc, argv, "NParticles", &NParticles);
    set_from_command_line_int(argc, argv, "NTargets", &NTargets);
    set_from_command_line_int(argc, argv, "pM", &pM);
    set_from_command_line_int(argc, argv, "pL", &pL);
    set_from_command_line_int(argc, argv, "s", &s);
    set_from_command_line_int(argc, argv, "level", &level);
    size = ldexp(1.0, -level);
    
    particles = (_FLOAT_ (*)[3]) calloc(NParticles, 3*sizeof(_FLOAT_));  
    charges = (_FLOAT_ *) calloc(NParticles, sizeof(_FLOAT_));  
    perm = (int *) calloc(NParticles, sizeof(int));  
    permTargets = (int *) calloc(NTargets, sizeof(int));  
    targets = (_FLOAT_ (*)[3]) calloc(NTargets, 3*sizeof(_FLOAT_));  
    potX = (_FLOAT_ *) calloc(NTargets, sizeof(_FLOAT_));
    potL = (_FLOAT_ *) calloc(NTargets, sizeof(_FLOAT_));
    exPot = (_FLOAT_ *) calloc(NTargets, sizeof(_FLOAT_));

    FMMV->beta = beta;
    FMMV->pM = pM;
    FMMV->pL = pL;
    FMMV->s_eps = s;
    FMMV->particles = particles;
    FMMV->charges = charges;
    FMMV->perm = perm;
    FMMV->NParticles = NParticles;
    FMMV->targets = targets;
    FMMV->permTargets = permTargets;
    FMMV->NTargets = NTargets;
    FMMV->scale = 1.0;
    FMMV->lambda = 0;

    my_srand(1481765933);
    x_A = 0.5*size;
    y_A = 0.5*size;
    z_A = 0.5*size;

    box_A->firstParticle = 0;
    box_A->noOfParticles = NParticles;
    parent_A->firstParticle = 0;
    parent_A->noOfParticles = NParticles;
    box_A->x = x_A;
    box_A->y = y_A;
    box_A->z = z_A;
    box_A->level = level;
    parent_A->level = level-1;
    box_A->M = 0; 
    
    x_B = x_A + size*dx;
    y_B = y_A + size*dy;
    z_B = z_A + size*dz;

    box_B->firstTarget = 0;
    box_B->noOfTargets = NTargets;
    parent_B->firstTarget = 0;
    parent_B->noOfTargets = NTargets;
    box_B->x = x_B;
    box_B->y = y_B;
    box_B->z = z_B;
    box_B->level = level;
    parent_B->level = level-1;
    box_B->L = 0; 
    
    for (i=0; i<8; i++) {
        parent_A->child[i] = 0;
        parent_B->child[i] = 0;
    }
    
    parent_A->child[which_child_A] = box_A;
    parent_B->child[which_child_B] = box_B;
    
    for (i=0;i<NParticles;i++) {
        x = x_A + size*(my_rand() / (_FLOAT_) MY_RAND_MAX - 0.5);
        y = y_A + size*(my_rand() / (_FLOAT_) MY_RAND_MAX - 0.5);
        z = z_A + size*(my_rand() / (_FLOAT_) MY_RAND_MAX - 0.5);
        particles[i][0] = x;
        particles[i][1] = y;
        particles[i][2] = z;
    }    
    for (i=0;i<NParticles;i++) {
        perm[i] = i;
        charges[i] = 1.0;
    }

    for (i=0;i<NTargets;i++) {
        x = x_B + size*(my_rand() / (_FLOAT_) MY_RAND_MAX - 0.5);
        y = y_B + size*(my_rand() / (_FLOAT_) MY_RAND_MAX - 0.5);
        z = z_B + size*(my_rand() / (_FLOAT_) MY_RAND_MAX - 0.5);
        targets[i][0] = x;
        targets[i][1] = y;
        targets[i][2] = z;
    }    

    for (i=0;i<NTargets;i++) {
        permTargets[i] = i;
    }
    
    init_all(FMMV);

    err = ida_allocate(FMMV);
    copy_particles(FMMV);
    copy_charges(FMMV);
    
    zero_pot(FMMV);
    EVAL_DIRECT(FMMV, box_B, box_A);
    FMMV->potentials = exPot;
    backcopy_pot(FMMV);

    GEN_M(FMMV, box_A);

    GEN_L(FMMV, box_B, box_A);

    zero_pot(FMMV);
    EVAL_L(FMMV, box_B);
    FMMV->potentials = potL;
    backcopy_pot(FMMV);

    /**********************************************/
    for (i=0;i<6;i++) {
       box_B->X[i] = 0;
    }
    box_B->X[XU] = X;
    for (i=0;i<pL*(pL+1);i++) {
       box_B->L[i] = 0.0;
    }   

    init_M2L(FMMV, -1);
    init_M2L(FMMV, level);

    M2X(FMMV, 0, parent_A, X1, X2);
    gen_diag_X2X(ldexp(beta,-level), FMMV->lambda, FMMV->M, FMMV->s_eps, FMMV->s_exp, dx, dy, dz, D); 
    VEC_MUL_C(FMMV->s_exp/2, D, X1+FMMV->s_exp*which_child_A, box_B->X[XU]);
    X2L(FMMV, 0, parent_B, 0);

    finish_M2L(FMMV);

    zero_pot(FMMV);
    EVAL_L(FMMV, box_B);
    FMMV->potentials = potX;
    backcopy_pot(FMMV);
    /**********************************************/


    ida_free(FMMV);

    relL2Err(0, 0, 0);
    if (printResult) {
        printf("\n          Pot(L)   Pot(exact)     rel.err.\n");
        printf("============================================\n");
    }
    for (i=0; i<NTargets; i++) {
        relL2Err(1, potL[i], exPot[i]); /* accumulate */
        if (printResult) {
            printf("%3i %12.4e %12.4e %12.4e\n", i, (double) potL[i], (double) exPot[i], (double) relErr(potL[i], exPot[i]));
        }   
    }
    errL2 = relL2Err(2, 0, 0); /*finalize*/ 
    printf ("\nerr_L2(potL) = %.4e\n", errL2);

    relL2Err(0, 0, 0);
    if (printResult) {
        printf("\n          Pot(X)   Pot(exact)     rel.err.\n");
        printf("============================================\n");
    }
    for (i=0; i<NTargets; i++) {
        relL2Err(1, potX[i], exPot[i]); /* accumulate */
        if (printResult) {
            printf("%3i %12.4e %12.4e %12.4e\n", i, (double) potX[i], (double) exPot[i], (double) relErr(potX[i], exPot[i]));
        }   
    }
    errL2 = relL2Err(2, 0, 0); /*finalize*/ 
    printf ("\nerr_L2(potX) = %.4e\n", errL2);
  
    // TODO: deallocate...
    finish_all(FMMV);

    return 0;
}