Mode frequency calculations for empty lattices.
Former-commit-id: ca14f8d765399c5bf92bb64cc7f1dc6722d53ebb
This commit is contained in:
parent
658c564a0c
commit
0f03509dde
|
@ -585,3 +585,18 @@ const PGenClassInfo PGen_xyWeb = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
size_t PGen_xyWeb_sizecap(cart2_t b1, cart2_t b2, double rtol, cart2_t offset,
|
||||||
|
double minR, bool inc_minR, double maxR, bool inc_maxR)
|
||||||
|
{
|
||||||
|
l2d_reduceBasis(b1, b2, &b1, &b2);
|
||||||
|
LatticeFlags lf = l2d_detectRightAngles(b1, b2, rtol);
|
||||||
|
double layer_min_height = l2d_hexWebInCircleRadius(b1, b2);
|
||||||
|
long layer = ceil(minR / layer_min_height);
|
||||||
|
if(!inc_minR && (layer * layer_min_height) <= minR)
|
||||||
|
++layer;
|
||||||
|
long last_layer = floor(maxR / layer_min_height);
|
||||||
|
if(!inc_maxR && (last_layer * layer_min_height) >= maxR)
|
||||||
|
--(last_layer);
|
||||||
|
// TODO less crude estimate (this one should be safe, however)
|
||||||
|
return ((lf & ORTHOGONAL_01) ? 4 : 6) * (last_layer - layer + 1);
|
||||||
|
}
|
||||||
|
|
|
@ -542,7 +542,7 @@ static inline PGenCart3ReturnData PGen_next_cart3(PGen *g) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ǧenerate a point in a 2D real space (cartesian coordinates).
|
/// Generate a point in a 2D real space (cartesian coordinates).
|
||||||
static inline PGenCart2ReturnData PGen_next_cart2(PGen *g) {
|
static inline PGenCart2ReturnData PGen_next_cart2(PGen *g) {
|
||||||
if (g->c->next_cart2)
|
if (g->c->next_cart2)
|
||||||
return g->c->next_cart2(g);
|
return g->c->next_cart2(g);
|
||||||
|
@ -618,11 +618,14 @@ PGen PGen_1D_new_minMaxR(double period, ///< Distance between points.
|
||||||
PGen_1D_incrementDirection incdir ///< Order of generated points.
|
PGen_1D_incrementDirection incdir ///< Order of generated points.
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
extern const PGenClassInfo PGen_xyWeb;
|
extern const PGenClassInfo PGen_xyWeb;
|
||||||
PGen PGen_xyWeb_new(cart2_t b1, cart2_t b2, double rtol, cart2_t offset,
|
PGen PGen_xyWeb_new(cart2_t b1, cart2_t b2, double rtol, cart2_t offset,
|
||||||
double minR, bool inc_minR, double maxR, bool inc_maxR);
|
double minR, bool inc_minR, double maxR, bool inc_maxR);
|
||||||
|
|
||||||
|
/// Returns a number larger or equal than the number of all the points generated by a PGen_xyWeb.
|
||||||
|
size_t PGen_xyWeb_sizecap(cart2_t b1, cart2_t b2, double rtol, cart2_t offset,
|
||||||
|
double minR, bool inc_minR, double maxR, bool inc_maxR);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* THE NICE PART (adaptation of lattices2d.py)
|
* THE NICE PART (adaptation of lattices2d.py)
|
||||||
|
@ -796,6 +799,58 @@ points2d_rordered_t points2d_rordered_annulus(const points2d_rordered_t *orig, d
|
||||||
double maxr, bool maxr_inc);
|
double maxr, bool maxr_inc);
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/// Gives the frequency of \a n-th empty lattice mode at a given wave vector \a k.
|
||||||
|
double qpms_emptylattice2_mode_nth(
|
||||||
|
cart2_t b1_rec, ///< First reciprocal lattice base vector
|
||||||
|
cart2_t b2_rec, ///< Second reciprocal lattice base vector
|
||||||
|
double rtol, ///< Relative tolerance to detect right angles
|
||||||
|
cart2_t k, ///< The wave vector
|
||||||
|
double wave_speed, ///< Wave speed in a given medium (i.e. vacuum speed / refractive index).
|
||||||
|
size_t N ///< Index of the mode (note that degenerate modes are counted multiple times).
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Gives the first `maxindex` frequencies of empty lattice modes at a given wave vector \a k.
|
||||||
|
void qpms_emptylattice2_modes_maxindex(
|
||||||
|
double target_freqs[], ///< Target array of size maxindex.
|
||||||
|
cart2_t b1_rec, ///< First reciprocal lattice base vector
|
||||||
|
cart2_t b2_rec, ///< Second reciprocal lattice base vector
|
||||||
|
double rtol, ///< Relative tolerance to detect right angles
|
||||||
|
cart2_t k, ///< The wave vector
|
||||||
|
double wave_speed, ///< Wave speed in a given medium (i.e. vacuum speed / refractive index).
|
||||||
|
size_t maxindex ///< Number of the frequencies generated.
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Gives the frequencies of empty lattice modes at a given wave vector \a k up to \a maxfreq and one more.
|
||||||
|
/**
|
||||||
|
* The frequencies are saved to a newly allocated array *target_freqs (to be deallocated
|
||||||
|
* using free() by the caller).
|
||||||
|
*
|
||||||
|
* \returns Number of found mode frequencies lower or equal than \a maxfreq plus one.
|
||||||
|
*/
|
||||||
|
size_t qpms_emptylattice2_modes_maxfreq(
|
||||||
|
double **target_freqs,
|
||||||
|
cart2_t b1_rec, ///< First reciprocal lattice base vector
|
||||||
|
cart2_t b2_rec, ///< Second reciprocal lattice base vector
|
||||||
|
double rtol, ///< Relative tolerance to detect right angles
|
||||||
|
cart2_t k, ///< The wave vector
|
||||||
|
double wave_speed, ///< Wave speed in a given medium (i.e. vacuum speed / refractive index).
|
||||||
|
double maxfreq ///< The maximum frequency.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Gives the frequencies of two empty lattice modes nearest to \a omega at a given wave vector \a k.
|
||||||
|
void qpms_emptylattice2_modes_nearest(
|
||||||
|
double target[2], ///< Target array with lower ([0]) and upper ([1]) frequency.
|
||||||
|
cart2_t b1_rec, ///< First reciprocal lattice base vector
|
||||||
|
cart2_t b2_rec, ///< Second reciprocal lattice base vector
|
||||||
|
double rtol, ///< Relative tolerance to detect right angles
|
||||||
|
cart2_t k, ///< The wave vector
|
||||||
|
double wave_speed, ///< Wave speed in a given medium (i.e. vacuum speed / refractive index).
|
||||||
|
double omega ///< The frequency around which the frequencies are searched.
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* THE UGLY PART
|
* THE UGLY PART
|
||||||
|
|
|
@ -866,4 +866,83 @@ double l2d_unitcell_area(cart2_t b1, cart2_t b2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
double qpms_emptylattice2_mode_nth(
|
||||||
|
cart2_t b1_rec,
|
||||||
|
cart2_t b2_rec,
|
||||||
|
double rtol,
|
||||||
|
cart2_t k,
|
||||||
|
double c,
|
||||||
|
size_t N
|
||||||
|
);
|
||||||
|
|
||||||
|
void qpms_emptylattice2_modes_maxindex(
|
||||||
|
double target_freqs[],
|
||||||
|
cart2_t b1_rec,
|
||||||
|
cart2_t b2_rec,
|
||||||
|
double rtol,
|
||||||
|
cart2_t k,
|
||||||
|
double c,
|
||||||
|
size_t maxindex
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int dblcmp(const void *p1, const void *p2) {
|
||||||
|
const double *x1 = (double *) p1, *x2 = (double *) p2;
|
||||||
|
double dif = *x1 - *x2;
|
||||||
|
if(dif > 0) return 1;
|
||||||
|
else if (dif < 0) return -1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t qpms_emptylattice2_modes_maxfreq(double **target_freqs,
|
||||||
|
cart2_t b1, cart2_t b2, double rtol, cart2_t k,
|
||||||
|
double c, double maxfreq)
|
||||||
|
{
|
||||||
|
QPMS_UNTESTED;
|
||||||
|
l2d_reduceBasis(b1, b2, &b1, &b2);
|
||||||
|
double maxk_safe = cart2norm(k) + maxfreq / c + cart2norm(b1) + cart2norm(b2); // This is an overkill
|
||||||
|
size_t capacity = PGen_xyWeb_sizecap(b1, b2, rtol, k, 0, true, maxk_safe, true);
|
||||||
|
cart2_t *Kpoints;
|
||||||
|
QPMS_CRASHING_MALLOC(Kpoints, sizeof(cart2_t) * capacity);
|
||||||
|
PGen Kgen = PGen_xyWeb_new(b1, b2, rtol, k, 0, true, maxk_safe, true);
|
||||||
|
|
||||||
|
size_t generated;
|
||||||
|
PGenReturnDataBulk rd;
|
||||||
|
while((rd = PGen_fetch_cart2(&Kgen, capacity - generated, Kpoints + generated)).flags & PGEN_NOTDONE)
|
||||||
|
generated += rd.generated;
|
||||||
|
|
||||||
|
double *thefreqs;
|
||||||
|
QPMS_CRASHING_MALLOC(thefreqs, generated * sizeof(double));
|
||||||
|
for(size_t i = 0; i < generated; ++i) thefreqs[i] = cart2norm(Kpoints[i]) * c;
|
||||||
|
|
||||||
|
free(Kpoints);
|
||||||
|
|
||||||
|
qsort(thefreqs, generated, sizeof(double), dblcmp);
|
||||||
|
size_t count;
|
||||||
|
bool hitmax = false;
|
||||||
|
for(count = 0; count < generated; ++count)
|
||||||
|
if(thefreqs[count] > maxfreq) {
|
||||||
|
if(hitmax)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
hitmax = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*target_freqs = thefreqs;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qpms_emptylattice2_modes_nearest(double target[2],
|
||||||
|
cart2_t b1, cart2_t b2, double rtol,
|
||||||
|
cart2_t k, double c, double omega)
|
||||||
|
{
|
||||||
|
QPMS_UNTESTED;
|
||||||
|
double *freqlist;
|
||||||
|
size_t n = qpms_emptylattice2_modes_maxfreq(&freqlist,
|
||||||
|
b1, b2, rtol, k, c, omega);
|
||||||
|
target[0] = freqlist[n-2];
|
||||||
|
target[1] = freqlist[n-1];
|
||||||
|
free(freqlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue