6 float r2,
hi,
hj, hig2, hjg2,
dx[3] = {0};
12 if (leaf->
items.empty()) [[unlikely]]
return;
14 auto activeRegion = Tree::Geo::Region(leaf->
range.low - 0.001, leaf->
range.high + 0.001);
18 auto *activeCell = (
Tree *)
nullptr;
19 while ((activeCell = activeRegionIter.next().value_or(
nullptr))) {
20 for (
auto localIdx = 0; localIdx < leaf->
items.size(); localIdx++) {
21 pi = &leaf->
items[localIdx];
23 auto hig =
hi * kernel_gamma;
26 if (!activeCell->range.overlaps({pi->_x - hig, pi->_x + hig}))
continue;
28 for (
auto activeIdx = 0; activeIdx < activeCell->items.size(); activeIdx++) {
29 pj = &activeCell->items[activeIdx];
32 for (
int k = 0; k < Geo::D::N; k++) {
37 auto hjg =
pj->
h * kernel_gamma;
41 if ((r2 > 0) & (r2 < hig2 | r2 < hjg2)) {
43 runner_iact_nonsym_density(r2,
dx,
hi,
pj->
h, pi,
pj,
a,
H);
51 float r2,
hi,
hj, hig2, hjg2,
dx[3] = {0};
57 if (leaf->
items.empty()) [[unlikely]]
return;
59 auto activeRegion = Tree::Geo::Region(leaf->
range.low - 0.001, leaf->
range.high + 0.001);
63 auto *activeCell = (
Tree *)
nullptr;
64 while ((activeCell = activeRegionIter.next().value_or(
nullptr))) {
65 for (
auto pidIdx = 0; pidIdx < pidCount; pidIdx++) {
66 pi = &leaf->
items[pids[pidIdx]];
68 auto hig =
hi * kernel_gamma;
71 if (!activeCell->range.overlaps({pi->_x - hig, pi->_x + hig}))
continue;
73 for (
auto activeIdx = 0; activeIdx < activeCell->items.size(); activeIdx++) {
74 pj = &activeCell->items[activeIdx];
77 for (
int k = 0; k < Geo::D::N; k++) {
82 auto hjg =
pj->
h * kernel_gamma;
86 if ((r2 > 0) & (r2 < hig2 | r2 < hjg2)) {
88 runner_iact_nonsym_density(r2,
dx,
hi,
pj->
h, pi,
pj,
a,
H);
96 const float hydro_h_max = hydro_properties->
h_max;
97 const float hydro_h_min = hydro_properties->
h_min;
99 const float hydro_eta_dim =
101 const int use_mass_weighted_num_ngb =
104 int redo = 0, count = 0;
107 float h_max = hydro_stats->
h_max;
119 if ((pid = (
int *)malloc(
sizeof(
int) * leaf->
items.size())) == NULL)
120 printf(
"Can't allocate memory for pid.");
121 if ((h_0 = (
float *)malloc(
sizeof(
float) * leaf->
items.size())) == NULL)
122 printf(
"Can't allocate memory for h_0.");
123 if ((left = (
float *)malloc(
sizeof(
float) * leaf->
items.size())) == NULL)
124 printf(
"Can't allocate memory for left.");
125 if ((right = (
float *)malloc(
sizeof(
float) * leaf->
items.size())) == NULL)
126 printf(
"Can't allocate memory for right.");
127 for (
int k = 0; k < leaf->
items.size(); k++) {
129 h_0[count] = leaf->
items[k].h;
131 right[count] = hydro_h_max;
136 for (
int num_reruns = 0; count > 0 && num_reruns < max_smoothing_iter;
143 for (
int i = 0; i < count; i++) {
149#ifdef SWIFT_DEBUG_CHECKS
151 if (!part_is_active(p, e)) error(
"Ghost applied to inactive particle");
155 const float h_init = h_0[i];
156 const float h_old = p->h;
157 const float h_old_dim = pow_dimension(h_old);
158 const float h_old_dim_minus_one = pow_dimension_minus_one(h_old);
161 int has_no_neighbours = 0;
166 has_no_neighbours = 1;
174 hydro_end_density(p, &
COSMO);
178 if (use_mass_weighted_num_ngb) {
179#if defined(GIZMO_MFV_SPH) || defined(GIZMO_MFM_SPH) || defined(SHADOWFAX_SPH)
181 "Can't use alternative neighbour definition with this scheme!");
183 const float inv_mass = 1.f / hydro_get_mass(p);
184 p->density.wcount = p->rho * inv_mass;
185 p->density.wcount_dh = p->density.rho_dh * inv_mass;
190 const float n_sum = p->density.wcount * h_old_dim;
191 const float n_target = hydro_eta_dim;
192 const float f = n_sum - n_target;
193 const float f_prime =
194 p->density.wcount_dh * h_old_dim +
195 hydro_dimension * p->density.wcount * h_old_dim_minus_one;
198 if (n_sum < n_target)
199 left[i] =
MAX(left[i], h_old);
200 else if (n_sum > n_target)
201 right[i] =
MAX(right[i], h_old);
203#ifdef SWIFT_DEBUG_CHECKS
205 if (left[i] > right[i])
206 error(
"Invalid left (%e) and right (%e)", left[i], right[i]);
211 if (((p->h >= hydro_h_max) && (
f < 0.f)) ||
212 ((p->h <= hydro_h_min) && (
f > 0.f))) {
219#ifdef EXTRA_HYDRO_LOOP
233 hydro_reset_gradient(p);
234 mhd_reset_gradient(p);
248 hydro_reset_acceleration(p);
259 h_new = h_old -
f / (f_prime + std::numeric_limits<float>::min());
262 if (num_reruns > max_smoothing_iter - 10) {
265 "Smoothing length convergence problem: iter=%d p->id=%lld "
266 "h_init=%12.8e h_old=%12.8e h_new=%12.8e f=%f f_prime=%f "
267 "n_sum=%12.8e n_target=%12.8e left=%12.8e right=%12.8e\n",
268 num_reruns, p->id, h_init, h_old, h_new,
f, f_prime, n_sum,
269 n_target, left[i], right[i]);
272#ifdef SWIFT_DEBUG_CHECKS
273 if (((
f > 0.f && h_new > h_old) || (
f < 0.f && h_new < h_old)) &&
274 (h_old < 0.999f * hydro_props->h_max))
276 "Smoothing length correction not going in the right direction");
280 h_new =
MIN(h_new, 2.f * h_old);
281 h_new =
MAX(h_new, 0.5f * h_old);
284 h_new =
MAX(h_new, left[i]);
285 h_new =
MIN(h_new, right[i]);
290 if (fabsf(h_new - h_old) > eps * h_old) {
295 if ((h_new == left[i] && h_old == right[i]) ||
296 (h_old == left[i] && h_new == right[i])) {
299 p->h = pow_inv_dimension(
300 0.5f * (pow_dimension(left[i]) + pow_dimension(right[i])));
309 if (p->h < hydro_h_max && p->h > hydro_h_min) {
314 left[redo] = left[i];
315 right[redo] = right[i];
319 hydro_init_part(p,
nullptr);
324 }
else if (p->h <= hydro_h_min) {
329 }
else if (p->h >= hydro_h_max) {
335 if (has_no_neighbours) {
337 hydro_part_has_no_neighbours(p,
xp, &
COSMO);
342 "Fundamental problem with the smoothing length iteration "
350 h_max =
MAX(h_max, p->h);
351 h_max_active =
MAX(h_max_active, p->h);
365 hydro_reset_acceleration(p);
381 "Smoothing length failed to converge for the following gas "
383 for (
int i = 0; i < count; i++) {
385 printf(
"ID: %lld, h: %g, wcount: %g\n", p->id, p->h, p->density.wcount);
388 printf(
"Smoothing length failed to converge on %i particles.\n", count);
399 hydro_stats->
h_max = h_max;
402#ifdef SWIFT_DEBUG_CHECKS
403 for (
int i = 0; i < c->hydro.count; ++i) {
404 const struct part *p = &c->hydro.parts[i];
405 const float h = c->hydro.parts[i].h;
406 if (part_is_inhibited(p, e))
continue;
408 if (
h > c->hydro.h_max)
409 error(
"Particle has h larger than h_max (id=%lld)", p->id);
410 if (part_is_active(p, e) &&
h > c->hydro.h_max_active)
411 error(
"Active particle has h larger than h_max_active (id=%lld)", p->id);