void mmm2d_set_dielectric_contrasts(void *rd, fcs_float delta_top, fcs_float delta_bot) { mmm2d_data_struct *d = (mmm2d_data_struct*)rd; if (!fcs_float_is_equal(delta_top, d->delta_mid_top) || !fcs_float_is_equal(delta_bot, d->delta_mid_bot)) { if (delta_top != 0.0 || delta_bot != 0.0) { d->dielectric_contrast_on=1; d->delta_mid_top= delta_top; d->delta_mid_bot= delta_bot; } else { d->dielectric_contrast_on=0; d->delta_mid_top= 0.; d->delta_mid_bot= 0.; } } }
void mmm2d_set_box_a(void* rd, fcs_float a) { mmm2d_data_struct *d = (mmm2d_data_struct*)rd; if (!fcs_float_is_equal(a, d->box_l[0])) d->needs_tuning = 1; d->box_l[0] = a; d->box_l_i[0] = 1./a; }
void mmm2d_set_box_c(void* rd, fcs_float c) { mmm2d_data_struct *d = (mmm2d_data_struct*)rd; if (!fcs_float_is_equal(c, d->box_l[2])) d->needs_tuning = 1; d->box_l[2] = c; d->box_l_i[2] = 1./c; }
void mmm1d_set_far_switch_radius_2(void *rd, fcs_float rad2) { mmm1d_data_struct *d = (mmm1d_data_struct*)rd; if (!fcs_float_is_equal(rad2, d->far_switch_radius_2)) d->bessel_calculated = 1; d->far_switch_radius_2 = rad2; printf("set radius %e\n",d->far_switch_radius_2); }
void mmm2d_set_box_b(void* rd, fcs_float b) { mmm2d_data_struct *d = (mmm2d_data_struct*)rd; if (!fcs_float_is_equal(b, d->box_l[1])) d->needs_tuning = 1; d->box_l[1] = b; d->box_l_i[1] = 1./b; }
void ifcs_p3m_set_alpha(void *rd, fcs_float alpha) { ifcs_p3m_data_struct *d = (ifcs_p3m_data_struct*)rd; if (!fcs_float_is_equal(alpha, d->alpha)) d->needs_retune = 1; d->alpha = alpha; d->tune_alpha = 0; }
void ifcs_p3m_set_r_cut(void *rd, fcs_float r_cut) { ifcs_p3m_data_struct *d = (ifcs_p3m_data_struct*)rd; if (!fcs_float_is_equal(r_cut, d->r_cut)) d->needs_retune = 1; d->r_cut = r_cut; d->tune_r_cut = 0; }
void mmm2d_set_far_cutoff(void *rd, fcs_float cutoff) { mmm2d_data_struct *d = (mmm2d_data_struct*)rd; if (!fcs_float_is_equal(cutoff, d->far_cut)) { d->calculate_far = 0; d->far_cut = cutoff; d->needs_tuning = 1; } }
void mmm1d_set_bessel_cutoff(void *rd, fcs_int cutoff) { mmm1d_data_struct *d = (mmm1d_data_struct*)rd; if (!fcs_float_is_equal(cutoff, d->bessel_cutoff)) d->bessel_calculated = 1; d->bessel_cutoff = cutoff; }
void mmm2d_set_maxPWerror(void *rd, fcs_float maxPWerror) { mmm2d_data_struct *d = (mmm2d_data_struct*)rd; if (!fcs_float_is_equal(maxPWerror, d->maxPWerror)) d->needs_tuning = 1; d->maxPWerror = maxPWerror; }
void ifcs_p3m_set_tolerance_field(void *rd, fcs_float tolerance_field) { ifcs_p3m_data_struct *d = (ifcs_p3m_data_struct*)rd; if (!fcs_float_is_equal(tolerance_field, d->tolerance_field)) d->needs_retune = 1; d->tolerance_field = tolerance_field; }
void mmm2d_set_skin(void *rd, fcs_float skin) { mmm2d_data_struct *d = (mmm2d_data_struct*)rd; if (!fcs_float_is_equal(skin, d->skin)) d->needs_tuning = 1; d->skin=skin; }
void mmm1d_set_box_c(void* rd, fcs_float c) { mmm1d_data_struct *d = (mmm1d_data_struct*)rd; if (!fcs_float_is_equal(c, d->box_l[2])) d->needs_retune = 1; d->box_l[2] = c; }
void mmm1d_set_box_b(void* rd, fcs_float b) { mmm1d_data_struct *d = (mmm1d_data_struct*)rd; if (!fcs_float_is_equal(b, d->box_l[1])) d->needs_retune = 1; d->box_l[1] = b; }
void mmm1d_set_box_a(void* rd, fcs_float a) { mmm1d_data_struct *d = (mmm1d_data_struct*)rd; if (!fcs_float_is_equal(a, d->box_l[0])) d->needs_retune = 1; d->box_l[0] = a; }
FCSResult fcs_fmm_check(FCS handle) { const fcs_float *a,*b,*c; const fcs_int *periodicity; int i,p; fcs_int absrel; fcs_fmm_get_absrel(handle, &absrel); if (absrel == -1) return fcs_result_create(FCS_ERROR_MISSING_ELEMENT, __func__, "fmm: absrel not set"); fcs_float deltaE; fcs_fmm_get_deltaE(handle, &deltaE); if (deltaE == -1.0) return fcs_result_create(FCS_ERROR_MISSING_ELEMENT, __func__, "fmm: deltaE not set"); a = fcs_get_box_a(handle); b = fcs_get_box_b(handle); c = fcs_get_box_c(handle); periodicity = fcs_get_periodicity(handle); p = 0; for (i = 0; i < 3; ++i) if (periodicity[i]) p++; switch(p) { case 0: return FCS_RESULT_SUCCESS; case 1: for (i = 0; i < 3; ++i) if (periodicity[i]) break; switch(i) { case 0: if (!( (fcs_norm(a) >= fcs_norm(b)) && (fcs_norm(a) >= fcs_norm(c)) )) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: longest box vector not in direction of 1D-periodicity direction"); return FCS_RESULT_SUCCESS; case 1: if (!( (fcs_norm(b) >= fcs_norm(a)) && (fcs_norm(b) >= fcs_norm(a)) )) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: longest box vector not in direction of 1D-periodicity direction"); return FCS_RESULT_SUCCESS; case 2: if (!( (fcs_norm(c) >= fcs_norm(a)) && (fcs_norm(c) >= fcs_norm(b)) )) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: longest box vector not in direction of 1D-periodicity direction"); return FCS_RESULT_SUCCESS; } case 2: for (i = 0; i < 3; ++i) if (!periodicity[i]) break; switch(i) { case 0: if (!( (fcs_float_is_equal(fcs_norm(b),fcs_norm(c))) && (fcs_norm(b) >= fcs_norm(a)) )) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: longest box vector not in direction of 2D-periodicity direction"); return FCS_RESULT_SUCCESS; case 1: if (!( (fcs_float_is_equal(fcs_norm(a),fcs_norm(c))) && (fcs_norm(a) >= fcs_norm(b)) )) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: longest box vector not in direction of 2D-periodicity direction"); return FCS_RESULT_SUCCESS; case 2: if (!( (fcs_float_is_equal(fcs_norm(a),fcs_norm(b))) && (fcs_norm(a) >= fcs_norm(c)) )) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: longest box vector not in direction of 2D-periodicity direction"); return FCS_RESULT_SUCCESS; } case 3: if (!(fcs_uses_principal_axes(a,b,c))) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: cannot use a non-cubic system in 3D-periodicity"); return FCS_RESULT_SUCCESS; } return FCS_RESULT_SUCCESS; }
void ifcs_p3m_set_box_c(void *rd, fcs_float c) { ifcs_p3m_data_struct *d = (ifcs_p3m_data_struct*)rd; if (!fcs_float_is_equal(c, d->box_l[2])) d->needs_retune = 1; d->box_l[2] = c; }
void ifcs_p3m_set_box_b(void *rd, fcs_float b) { ifcs_p3m_data_struct *d = (ifcs_p3m_data_struct*)rd; if (!fcs_float_is_equal(b, d->box_l[1])) d->needs_retune = 1; d->box_l[1] = b; }
void ifcs_p3m_set_box_a(void* rd, fcs_float a) { ifcs_p3m_data_struct *d = (ifcs_p3m_data_struct*)rd; if (!fcs_float_is_equal(a, d->box_l[0])) d->needs_retune = 1; d->box_l[0] = a; }
void mmm1d_set_maxPWerror(void *rd, fcs_float maxPWerror) { mmm1d_data_struct *d = (mmm1d_data_struct*)rd; if (!fcs_float_is_equal(maxPWerror, d->maxPWerror)) d->bessel_calculated = 1; d->maxPWerror = maxPWerror; }
/* method to check if fmm parameters are consistent with requirements */ FCSResult fcs_fmm_check(FCS handle, fcs_int local_particles) { const fcs_float *a,*b,*c; fcs_float norm[3],period_length; const fcs_int *periodicity; MPI_Comm comm; fcs_int total_particles; int comm_size; int i,p,ok; fcs_int absrel; fcs_fmm_get_absrel(handle, &absrel); if (absrel == -1) return fcs_result_create(FCS_ERROR_MISSING_ELEMENT, __func__, "fmm: absrel not set"); fcs_float tolerance_energy; fcs_fmm_get_tolerance_energy(handle, &tolerance_energy); if (tolerance_energy == -1.0) return fcs_result_create(FCS_ERROR_MISSING_ELEMENT, __func__, "fmm: energy tolerance not set"); comm = fcs_get_communicator(handle); MPI_Comm_size(comm, &comm_size); total_particles = fcs_get_total_particles(handle); if (total_particles < comm_size) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: there have to be at least as much particles as processes"); if (local_particles <= 0) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: each process has to receive at least one particle"); a = fcs_get_box_a(handle); norm[0] = fcs_norm(a); b = fcs_get_box_b(handle); norm[1] = fcs_norm(b); c = fcs_get_box_c(handle); norm[2] = fcs_norm(c); periodicity = fcs_get_periodicity(handle); p = 0; ok = 1; for (i = 0; i < 3; ++i) if (periodicity[i]) { if (0==p) period_length = norm[i]; else ok = ok && fcs_float_is_equal( period_length, norm[i] ); p++; } if (p && !(fcs_uses_principal_axes(a,b,c))) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: with periodic boundaries, box must be arranged along principle axes"); if (p && !ok) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: all periodic directions must have equal length"); if (p && (p<3)) { ok = 1; for (i = 0; i < 3; ++i) if (!periodicity[i]) ok = ok && (norm[i] <= period_length); if (!ok) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: axes in non-periodic directions must not be longer than periodic ones"); } return FCS_RESULT_SUCCESS; }