Finer error handling.
Former-commit-id: f30b79d2cc321fc06030374176f5013ff179ffc8
This commit is contained in:
parent
2798fcce49
commit
3ebc1af946
|
@ -59,6 +59,11 @@ qpms_errno_t qpms_sph_bessel_realx_fill(qpms_bessel_t typ, qpms_l_t lmax, double
|
|||
return retval;
|
||||
break;
|
||||
case QPMS_BESSEL_SINGULAR: //FIXME: is this precise enough? Would it be better to do it one-by-one?
|
||||
if(QPMS_UNLIKELY(x == 0)) {
|
||||
for (int l = 0; l <= lmax; ++l)
|
||||
result_array[l] = NAN;
|
||||
return QPMS_ESING; // GSL would have returned GSL_EDOM without setting NANs.
|
||||
}
|
||||
retval = gsl_sf_bessel_yl_array(lmax,x,tmparr);
|
||||
for (int l = 0; l <= lmax; ++l) result_array[l] = tmparr[l];
|
||||
return retval;
|
||||
|
@ -69,6 +74,11 @@ qpms_errno_t qpms_sph_bessel_realx_fill(qpms_bessel_t typ, qpms_l_t lmax, double
|
|||
for (int l = 0; l <= lmax; ++l) result_array[l] = tmparr[l];
|
||||
if(retval) return retval;
|
||||
retval = gsl_sf_bessel_yl_array(lmax, x, tmparr);
|
||||
if(QPMS_UNLIKELY(x == 0)) {
|
||||
for (int l = 0; l <= lmax; ++l)
|
||||
result_array[l] += I * NAN;
|
||||
return QPMS_ESING; // GSL would have returned GSL_EDOM without setting NANs.
|
||||
}
|
||||
if (typ==QPMS_HANKEL_PLUS)
|
||||
for (int l = 0; l <= lmax; ++l) result_array[l] += I * tmparr[l];
|
||||
else
|
||||
|
@ -76,10 +86,9 @@ qpms_errno_t qpms_sph_bessel_realx_fill(qpms_bessel_t typ, qpms_l_t lmax, double
|
|||
return retval;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
//return GSL_EDOM;
|
||||
QPMS_INVALID_ENUM(typ);
|
||||
}
|
||||
assert(0);
|
||||
QPMS_WTF;
|
||||
}
|
||||
|
||||
// TODO DOC
|
||||
|
@ -119,7 +128,7 @@ qpms_errno_t qpms_sph_bessel_fill(qpms_bessel_t typ, qpms_l_t lmax, complex doub
|
|||
}
|
||||
break;
|
||||
default:
|
||||
QPMS_WTF;
|
||||
QPMS_INVALID_ENUM(typ);
|
||||
}
|
||||
// TODO check for underflows? (nz != 0)
|
||||
if (ierr == 0 || ierr == 3) {
|
||||
|
|
|
@ -83,6 +83,8 @@ qpms_dbgmsg_flags qpms_dbgmsg_enable(qpms_dbgmsg_flags types);
|
|||
|
||||
#define QPMS_WTF qpms_pr_error_at_flf(__FILE__,__LINE__,__func__,"Unexpected error.")
|
||||
|
||||
#define QPMS_INVALID_ENUM(x) qpms_pr_error_at_flf(__FILE__,__LINE__,__func__,"Invalid enum value (" #x " == %d)", (int) (x))
|
||||
|
||||
#define QPMS_UNTESTED {\
|
||||
static _Bool already_bitched = 0; \
|
||||
if (QPMS_UNLIKELY(!already_bitched)) {\
|
||||
|
@ -93,9 +95,9 @@ qpms_dbgmsg_flags qpms_dbgmsg_enable(qpms_dbgmsg_flags types);
|
|||
|
||||
#define QPMS_PR_ERROR(msg, ...) qpms_pr_error_at_flf(__FILE__,__LINE__,__func__,msg, ##__VA_ARGS__)
|
||||
|
||||
// TODO replace this macro with an inline function?
|
||||
/// Raises an error if \a x is not zero.
|
||||
#define QPMS_ENSURE_SUCCESS(x) { \
|
||||
int errorcode = (x); \
|
||||
int errorcode = (x); /* evaluate x only once */ \
|
||||
if(QPMS_UNLIKELY(errorcode)) \
|
||||
qpms_pr_error_at_flf(__FILE__,__LINE__,__func__,"Unexpected error (%d)", errorcode); \
|
||||
}
|
||||
|
@ -107,6 +109,17 @@ qpms_dbgmsg_flags qpms_dbgmsg_enable(qpms_dbgmsg_flags types);
|
|||
qpms_pr_error_at_flf(__FILE__,__LINE__,__func__,msg, ##__VA_ARGS__); \
|
||||
}
|
||||
|
||||
/// Raises an error if \a x is not zero or one of the values listed in arguments.
|
||||
#define QPMS_ENSURE_SUCCESS_OR(x, ...) { \
|
||||
int errorcode = (x); /* evaluate x only once */ \
|
||||
static const int allowed_errorcodes[] = {0, ##__VA_ARGS__};\
|
||||
static const int n_allowed = sizeof(allowed_errorcodes) / sizeof(int); \
|
||||
int i; \
|
||||
for(i = 0; i < n_allowed; ++i) \
|
||||
if (errorcode == allowed_errorcodes[i]) break; \
|
||||
if (QPMS_UNLIKELY(i >= n_allowed)) \
|
||||
qpms_pr_error_at_flf(__FILE__,__LINE__,__func__,"Unexpected error (%d)", errorcode); \
|
||||
}
|
||||
|
||||
#define QPMS_ENSURE(x, msg, ...) {if(QPMS_UNLIKELY(!(x))) qpms_pr_error_at_flf(__FILE__,__LINE__,__func__,msg, ##__VA_ARGS__); }
|
||||
|
||||
|
|
|
@ -78,13 +78,14 @@ typedef enum {
|
|||
typedef unsigned long long qpms_uvswfi_t;
|
||||
|
||||
/// Error codes / return values for certain numerical functions.
|
||||
/** These are de facto a subset of the GSL error codes. */
|
||||
/** Those with values between -2 and 32 are subset of the GSL error codes. */
|
||||
typedef enum {
|
||||
QPMS_SUCCESS = 0, ///< Success.
|
||||
QPMS_ERROR = 1, ///< Unspecified error.
|
||||
QPMS_ERROR = -1, ///< Unspecified error.
|
||||
QPMS_FAILURE = QPMS_ERROR,
|
||||
QPMS_ENOMEM = 8, ///< Out of memory.
|
||||
QPMS_ESING = 21, ///< Apparent singularity detected.
|
||||
QPMS_NAN_ENCOUNTERED = 1024 ///< NaN value encountered in data processing.
|
||||
|
||||
} qpms_errno_t;
|
||||
|
||||
|
||||
|
|
|
@ -2039,7 +2039,7 @@ ccart3_t qpms_scatsys_scattered_E__alt(const qpms_scatsys_t *ss,
|
|||
qpms_tmn2uvswfi(QPMS_VSWF_ELECTRIC, 0, 1),
|
||||
qpms_tmn2uvswfi(QPMS_VSWF_ELECTRIC, +1, 1),
|
||||
},
|
||||
.lMax=1, .lMax_M=1, .lMax_N=1, .lMax_L=-1,
|
||||
.lMax=1, .lMax_M=0, .lMax_N=1, .lMax_L=-1,
|
||||
.capacity=0,
|
||||
.norm = ss->c->normalisation,
|
||||
};
|
||||
|
|
|
@ -231,7 +231,8 @@ qpms_errno_t qpms_vswf_fill_csph(csphvec_t *const longtarget,
|
|||
csph_t kr, qpms_bessel_t btyp, const qpms_normalisation_t norm) {
|
||||
assert(lMax >= 1);
|
||||
complex double *bessel = malloc((lMax+1)*sizeof(complex double));
|
||||
QPMS_ENSURE_SUCCESS(qpms_sph_bessel_fill(btyp, lMax, kr.r, bessel));
|
||||
qpms_errno_t bessel_retval = qpms_sph_bessel_fill(btyp, lMax, kr.r, bessel);
|
||||
QPMS_ENSURE_SUCCESS_OR(bessel_retval, QPMS_ESING);
|
||||
qpms_pitau_t pt = qpms_pitau_get(kr.theta, lMax, qpms_normalisation_t_csphase(norm));
|
||||
complex double const *pbes = bessel + 1; // starting from l = 1
|
||||
double const *pleg = pt.leg;
|
||||
|
@ -282,7 +283,7 @@ qpms_errno_t qpms_vswf_fill_csph(csphvec_t *const longtarget,
|
|||
}
|
||||
free(bessel);
|
||||
qpms_pitau_free(pt);
|
||||
return QPMS_SUCCESS;
|
||||
return bessel_retval;
|
||||
}
|
||||
|
||||
qpms_errno_t qpms_vswf_fill(csphvec_t *const longtarget,
|
||||
|
|
|
@ -177,6 +177,11 @@ csphvec_t qpms_vswf_L00(
|
|||
*
|
||||
* Does not evaluate the zeroth-order wave \f$ \mathbf{L}_0^0 \f$.
|
||||
* If you need that, use qpms_vswf_L00().
|
||||
*
|
||||
* If \a kdrj.r == 0 and \a btyp != QPMS_BESSEL_REGULAR, returns QPMS_ESING and fills
|
||||
* targets with NaNs.
|
||||
*
|
||||
* \return 0 (QPMS_SUCCESS) on success, otherwise.
|
||||
*/
|
||||
qpms_errno_t qpms_vswf_fill(
|
||||
csphvec_t *resultL, //< Target array for longitudinal VSWFs.
|
||||
|
|
|
@ -6,6 +6,7 @@ waves at origin
|
|||
"""
|
||||
|
||||
from qpms import Particle, CTMatrix, lorentz_drude, EpsMuGenerator, TMatrixGenerator, BaseSpec, FinitePointGroup, ScatteringSystem, TMatrixInterpolator, EpsMu, dbgmsg_enable, dbgmsg_disable, dbgmsg_active, BesselType,eV, hbar
|
||||
from qpms.qpms_c import set_gsl_pythonic_error_handling
|
||||
from qpms.symmetries import point_group_info
|
||||
import numpy as np
|
||||
eh = eV/hbar
|
||||
|
@ -15,6 +16,8 @@ dbgmsg_enable(2)
|
|||
part_radius = 80e-9
|
||||
p = 1580e-9
|
||||
|
||||
set_gsl_pythonic_error_handling()
|
||||
|
||||
sym = FinitePointGroup(point_group_info['D4h'])
|
||||
bspec1 = BaseSpec(lMax=3)
|
||||
medium=EpsMuGenerator(EpsMu(1.52**2))
|
||||
|
@ -36,7 +39,7 @@ for i in range(ss.fecv_size):
|
|||
E = ssw.scattered_E(fvc, points)
|
||||
E_alt = ssw.scattered_E(fvc, points,alt=True)
|
||||
diff = abs(E-E_alt)
|
||||
reldiffavg = np.average(diff/(abs(E)+abs(E_alt)))
|
||||
reldiffavg = np.nanmean(diff/(abs(E)+abs(E_alt)))
|
||||
fail = reldiffavg > 1e-3
|
||||
fails += fail
|
||||
|
||||
|
|
Loading…
Reference in New Issue