Line data Source code
1 : ! ***********************************************************************
2 : !
3 : ! Copyright (C) 2010-2019 The MESA Team
4 : !
5 : ! This program is free software: you can redistribute it and/or modify
6 : ! it under the terms of the GNU Lesser General Public License
7 : ! as published by the Free Software Foundation,
8 : ! either version 3 of the License, or (at your option) any later version.
9 : !
10 : ! This program is distributed in the hope that it will be useful,
11 : ! but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 : ! See the GNU Lesser General Public License for more details.
14 : !
15 : ! You should have received a copy of the GNU Lesser General Public License
16 : ! along with this program. If not, see <https://www.gnu.org/licenses/>.
17 : !
18 : ! ***********************************************************************
19 :
20 : module mesh_plan
21 :
22 : use const_def, only: dp, convective_mixing
23 : use num_lib
24 : use utils_lib
25 : use star_private_def
26 :
27 : implicit none
28 :
29 : private
30 : public :: do_mesh_plan
31 :
32 : logical, parameter :: plan_dbg = .false.
33 : integer, parameter :: kdbg = -1
34 :
35 : contains
36 :
37 10 : subroutine do_mesh_plan( &
38 : s, nz_old, max_allowed_nz, okay_to_merge, D_mix, &
39 : max_k_old_for_split_in, min_k_old_for_split_in, xq_old, dq_old, &
40 : min_dq_in, max_dq, min_dq_for_split, mesh_max_allowed_ratio, &
41 : do_not_split, num_gvals, gval_names, &
42 : gval_is_xa_function, gval_is_logT_function, gvals, &
43 : delta_gval_max, max_center_cell_dq, max_surface_cell_dq, min_surface_cell_dq, &
44 : max_num_subcells, max_num_merge_cells, max_num_merge_surface_cells, &
45 : nz_new, xq_new, dq_new, which_gval, comes_from, ierr)
46 : ! return keep_going, or terminate
47 : use mesh_functions, only: max_allowed_gvals
48 : ! inputs
49 : type (star_info), pointer :: s
50 : integer, intent(in) :: nz_old, max_allowed_nz, max_num_subcells, &
51 : max_num_merge_cells, max_num_merge_surface_cells, max_k_old_for_split_in, &
52 : min_k_old_for_split_in
53 : logical, intent(in) :: okay_to_merge
54 : real(dp), pointer :: D_mix(:) ! (nz_old)
55 : real(dp), pointer :: xq_old(:) ! (nz_old)
56 : real(dp), pointer :: dq_old(:) ! (nz_old)
57 : real(dp), intent(in) :: min_dq_in, max_dq, min_dq_for_split, mesh_max_allowed_ratio
58 : logical, pointer :: do_not_split(:)
59 : integer, intent(in) :: num_gvals
60 : character (len=32) :: gval_names(max_allowed_gvals)
61 : logical, dimension(max_allowed_gvals) :: gval_is_xa_function, gval_is_logT_function
62 : real(dp), pointer :: gvals(:,:) ! (nz_old, num_gvals)
63 : real(dp), pointer :: delta_gval_max(:) ! (nz_old)
64 : real(dp), intent(in) :: max_center_cell_dq, max_surface_cell_dq, &
65 : min_surface_cell_dq
66 : ! outputs
67 : integer, intent(out) :: nz_new
68 : real(dp), pointer :: xq_new(:), dq_new(:) ! (nz_new)
69 : ! must be allocated on entry; suggested size >= nz_old.
70 : ! reallocated as necessary if need to enlarge.
71 : ! size on return is >= nz_new.
72 : integer, pointer :: which_gval(:) ! (nz_new) for debugging.
73 : ! which_gval(k) = gval number that set the size for new cell k.
74 : ! size may have been reduced below gradient setting by other restrictions.
75 : integer, pointer :: comes_from(:) ! (nz_new)
76 : ! xq_old(comes_from(k)+1) > xq_new(k) >= xq_old(comes_from(k)), if comes_from(k) < nz_old.
77 : integer, intent(out) :: ierr
78 :
79 : integer :: j, k, k_old, k_new, nz, new_capacity, iounit, species, &
80 : max_k_old_for_split, min_k_old_for_split
81 10 : real(dp) :: D_mix_cutoff, next_xq, next_dq, max_dq_cntr, &
82 10 : dq_sum, min_dq, min_dq_for_xa, min_dq_for_logT
83 :
84 : logical, parameter :: write_plan_debug = .false.
85 :
86 : include 'formats'
87 :
88 10 : ierr = 0
89 :
90 10 : min_dq = min_dq_in
91 :
92 10 : if (max_k_old_for_split_in < 0) then
93 0 : max_k_old_for_split = nz_old + max_k_old_for_split_in
94 : else
95 10 : max_k_old_for_split = max_k_old_for_split_in
96 : end if
97 :
98 10 : if (min_k_old_for_split_in < 0) then
99 0 : min_k_old_for_split = nz_old + min_k_old_for_split_in
100 : else
101 10 : min_k_old_for_split = min_k_old_for_split_in
102 : end if
103 :
104 10 : if (max_dq < min_dq) then
105 0 : write(*,1) 'ERROR in controls: max_dq < min_dq', max_dq, min_dq
106 0 : ierr = -1
107 0 : return
108 : end if
109 :
110 10 : if (max_center_cell_dq < min_dq) then
111 0 : write(*,1) 'ERROR in controls: max_center_cell_dq < min_dq', max_center_cell_dq, min_dq
112 0 : ierr = -1
113 0 : return
114 : end if
115 :
116 10 : if (max_surface_cell_dq < min_dq) then
117 0 : write(*,1) 'ERROR in controls: max_surface_cell_dq < min_dq', max_surface_cell_dq, min_dq
118 0 : ierr = -1
119 0 : return
120 : end if
121 :
122 12095 : do k = 2, nz_old
123 12095 : if (xq_old(k) <= xq_old(k-1)) then
124 0 : write(*,3) 'bad xq_old', k, nz_old, xq_old(k), xq_old(k-1)
125 0 : ierr = -1
126 0 : return
127 : end if
128 : end do
129 :
130 10 : if (s% set_min_D_mix) then
131 : D_mix_cutoff = s% min_D_mix
132 : else
133 10 : D_mix_cutoff = 0
134 : end if
135 :
136 : if (write_plan_debug) call open_debug_file
137 :
138 : if (plan_dbg) then
139 : write(*,*) 'num_gvals', num_gvals
140 : do j=1,num_gvals
141 : write(*,*) j, trim(gval_names(j))
142 : end do
143 : write(*,'(A)')
144 : end if
145 :
146 10 : nz = nz_old
147 10 : species = s% species
148 :
149 : new_capacity = min(size(xq_new,dim=1), size(dq_new,dim=1), &
150 10 : size(which_gval,dim=1), size(comes_from,dim=1))
151 10 : max_dq_cntr = max(1d-20, max_center_cell_dq, 0.75d0*dq_old(nz_old))
152 :
153 12105 : comes_from(1:nz) = 0
154 10 : comes_from(1) = 1
155 :
156 10 : call pick_new_points(s, ierr)
157 10 : if (ierr /= 0) return
158 :
159 10 : if (min_k_old_for_split <= 1) then
160 10 : do while (dq_new(1) > max(max_surface_cell_dq,2*min_dq,min_dq_for_split))
161 0 : call split1(1, ierr)
162 10 : if (ierr /= 0) then
163 0 : write(*,*) 'failed trying to split surface cell'
164 0 : stop
165 : return
166 : end if
167 : end do
168 : end if
169 :
170 10 : call smooth_new_points(ierr) ! split as necessary
171 10 : if (ierr /= 0) return
172 :
173 : if (write_plan_debug) then
174 : close(iounit)
175 : end if
176 :
177 10 : if (ierr /= 0) return
178 :
179 :
180 : contains
181 :
182 :
183 : subroutine check_before_smooth(ierr)
184 : integer, intent(out) :: ierr
185 : integer :: k, k_old
186 : real(dp) :: xq0, xqold_start, xqold_end
187 :
188 : include 'formats'
189 : ierr = 0
190 : if (comes_from(1) /= 1 .or. xq_old(1) /= xq_new(1)) then
191 : write(*,*) 'mesh plan check_before_smooth: bad value from k=1'
192 : ierr = -1
193 : return
194 : end if
195 :
196 : do k = 2, nz_new
197 : xq0 = xq_new(k)
198 : k_old = comes_from(k)
199 : xqold_start = xq_old(k_old)
200 : if (k_old == nz_old) then
201 : xqold_end = 1d0
202 : else
203 : xqold_end = xq_old(k_old+1)
204 : end if
205 : if (k_old > comes_from(k-1)) then
206 : if (xq0 /= xqold_start) then
207 : write(*,'(A)')
208 : write(*,2) 'nz_new', nz_new
209 : write(*,2) 'k', k
210 : write(*,2) 'comes_from(k-1)', comes_from(k-1)
211 : write(*,2) 'k_old', k_old
212 : write(*,2) 'comes_from(k)', comes_from(k)
213 : write(*,2) 'nz_old', nz_old
214 : write(*,'(A)')
215 : write(*,2) 'xq0', k, xq0
216 : write(*,2) 'xqold_start', k_old, xqold_start
217 : write(*,2) 'xqold_end', k_old, xqold_end
218 : write(*,2) 'xqold_end - xqold_start', k_old, xqold_end - xqold_start
219 : write(*,2) 'xq0 - xqold_start', k_old, xq0 - xqold_start
220 : write(*,'(A)')
221 : write(*,2) 'xq_old(comes_from(k))', k, xq_old(comes_from(k))
222 : write(*,2) 'xq_old(comes_from(k-1))', k, xq_old(comes_from(k-1))
223 : write(*,'(A)')
224 : write(*,*) 'k_old > comes_from(k-1)', k_old > comes_from(k-1)
225 : write(*,*) 'xq0 /= xqold_start', xq0 /= xqold_start
226 : write(*,*) 'mesh plan check_before_smooth'
227 : ierr = -1
228 : return
229 : end if
230 : else if (k_old == comes_from(k-1)) then
231 : if (.not. (xq0 > xqold_start .and. xq0 < xqold_end)) then
232 : write(*,'(A)')
233 : write(*,*) '(.not. (xq0 > xqold_start .and. xq0 < xqold_end))', k_old
234 : write(*,2) 'xq_new(k)', k, xq_new(k)
235 : write(*,2) 'xq_old(k_old)', k, xq_old(k_old)
236 : write(*,2) 'xq_old(k_old+1)', k, xq_old(k_old+1)
237 : write(*,2) 'xqold_end', k, xqold_end
238 : write(*,'(A)')
239 : write(*,*) 'k_old == comes_from(k-1)', k_old == comes_from(k-1)
240 : write(*,*) '.not. (xq0 > xqold_start .and. xq0 < xqold_end)', &
241 : .not. (xq0 > xqold_start .and. xq0 < xqold_end)
242 : write(*,*) 'mesh plan check_before_smooth'
243 : ierr = -1
244 : return
245 : end if
246 : else
247 : write(*,*) 'comes_from(k) > comes_from(k-1)', k, comes_from(k), comes_from(k-1)
248 : write(*,*) 'mesh plan check_before_smooth'
249 : ierr = -1
250 : return
251 : end if
252 :
253 : cycle ! use the following for debugging
254 : if (dq_new(k-1) < 1d-6*dq_new(k) .or. dq_new(k) < 1d-6*dq_new(k-1)) then
255 : write(*,3) 'bad dq_new ratio', k, nz_new, dq_new(k)/dq_new(k-1), dq_new(k), dq_new(k-1)
256 : write(*,*) 'check_before_smooth'
257 : ierr = -1
258 : return
259 : end if
260 :
261 : end do
262 :
263 10 : end subroutine check_before_smooth
264 :
265 :
266 : subroutine test_new(ierr)
267 : integer, intent(out) :: ierr
268 : integer :: k, k_old
269 : include 'formats'
270 : ierr = 0
271 : do k = 1, nz_new
272 : if (dq_new(k) <= 0) then
273 : write(*,3) 'bad dq_new'
274 : write(*,2) 'dq_new', k, dq_new(k)
275 : write(*,2) 'dq_new', k-1, dq_new(k-1)
276 : write(*,2) 'xq_new', k, xq_new(k)
277 : write(*,2) 'xq_new', k-1, xq_new(k-1)
278 : write(*,3) 'comes_from', k, comes_from(k)
279 : write(*,3) 'comes_from', k-1, comes_from(k-1)
280 : write(*,2) 'nz_new', nz_new
281 : write(*,2) 'nz_old', nz_old
282 : write(*,2) 'dq_old(comes_from(k))', comes_from(k), dq_old(comes_from(k))
283 : write(*,2) 'dq_old(comes_from(k)-1)', comes_from(k)-1, dq_old(comes_from(k)-1)
284 : write(*,2) 'dq_old(comes_from(k)-2)', comes_from(k)-2, dq_old(comes_from(k)-2)
285 : write(*,2) 'xq_old(comes_from(k))', comes_from(k), xq_old(comes_from(k))
286 : write(*,2) 'xq_old(comes_from(k)-1)', comes_from(k)-1, xq_old(comes_from(k)-1)
287 : write(*,2) 'xq_old(comes_from(k)-2)', comes_from(k)-2, xq_old(comes_from(k)-2)
288 : write(*,*) 'test_new: mesh plan'
289 : ierr = -1
290 : return
291 : end if
292 : k_old = comes_from(k)
293 : if (k_old < 1 .or. k_old > nz_old) then
294 : write(*,*) 'bad value for comes_from', k, k_old
295 : write(*,*) 'test_new: mesh plan'
296 : ierr = -1
297 : return
298 : end if
299 : if (xq_new(k) < xq_old(k_old)) then
300 : write(*,3) '(xq_new(k) < xq_old(k_old))', k, k_old, &
301 : xq_new(k) - xq_old(k_old), xq_new(k), xq_old(k_old)
302 : write(*,*) 'test_new: mesh plan'
303 : ierr = -1
304 : return
305 : end if
306 : if (k_old < nz_old) then
307 : if (xq_new(k) > xq_old(k_old+1)) then
308 : write(*,3) '(xq_new(k) > xq_old(k_old+1))', k, k_old+1, &
309 : xq_new(k) - xq_old(k_old+1), xq_new(k), xq_old(k_old+1)
310 : write(*,*) 'test_new: mesh plan'
311 : ierr = -1
312 : return
313 : end if
314 : end if
315 : end do
316 : end subroutine test_new
317 :
318 :
319 128 : subroutine split1(k, ierr)
320 : integer, intent(in) :: k
321 : integer, intent(out) :: ierr
322 : integer :: kk, k_old, k_old_last, split_at_k_old
323 128 : real(dp) :: xq_mid, xq_end
324 : logical :: from_merger, dbg
325 :
326 : include 'formats'
327 128 : ierr = 0
328 :
329 128 : k_old = comes_from(k)
330 128 : k_old_last = -1
331 128 : xq_end = -1
332 128 : from_merger = (xq_new(k) == xq_old(k_old) .and. dq_new(k) > dq_old(k_old) + min_dq*1d-3)
333 :
334 128 : dbg = (k_old == -1)
335 :
336 128 : if (dbg) then
337 0 : write(*,2) 'start split1 k', k
338 0 : write(*,2) 'nz_old', nz_old
339 0 : write(*,2) 'nz_new', nz_new
340 0 : do kk=1400,nz_new
341 0 : if (dq_new(kk) < 1d-12) then
342 0 : write(*,2) 'dq_new(kk)', kk, dq_new(kk)
343 0 : call mesa_error(__FILE__,__LINE__,'debug: split1')
344 : end if
345 : end do
346 0 : do kk = 2, nz_new
347 0 : if (dq_new(kk-1) < 1d-6*dq_new(kk) .or. dq_new(kk) < 1d-6*dq_new(kk-1)) then
348 0 : write(*,3) 'bad dq_new ratio', kk, nz_new, dq_new(kk), dq_new(kk-1)
349 0 : call mesa_error(__FILE__,__LINE__,'debug: split1')
350 : end if
351 : end do
352 : end if
353 :
354 128 : if (from_merger) then ! find range of old cells that were merged to form k
355 128 : if (k == nz_new) then
356 0 : xq_end = 1
357 0 : k_old_last = nz_old
358 : else
359 128 : xq_end = xq_new(k+1)
360 128 : k_old_last = 0
361 256 : do kk = k_old+1, nz_old ! find last old cell included in k
362 256 : if (xq_old(kk) == xq_end) then
363 128 : k_old_last = kk-1; exit
364 : end if
365 128 : if (xq_old(kk) > xq_end) then
366 0 : write(*,*) 'oops'
367 0 : write(*,2) 'xq_old(kk)', kk, xq_old(kk)
368 0 : write(*,2) 'xq_old(kk-1)', kk-1, xq_old(kk-1)
369 0 : write(*,2) 'xq_end', k, xq_end
370 0 : write(*,*) 'split1'
371 0 : ierr = -1
372 0 : return
373 : end if
374 : end do
375 128 : if (k_old_last == k_old) then
376 : from_merger = .false.
377 128 : else if (k_old_last < k_old) then
378 0 : write(*,*) 'confusion in split1 for k_old_last'
379 0 : write(*,2) 'k_old', k_old
380 0 : write(*,2) 'k_old_last', k_old_last
381 0 : write(*,2) 'nz_old', nz_old
382 0 : write(*,2) 'k', k
383 0 : write(*,2) 'nz_new', nz_new
384 0 : write(*,'(A)')
385 0 : write(*,2) 'dq_new(k)', k, dq_new(k)
386 0 : write(*,2) 'dq_old(k_old)', k_old, dq_old(k_old)
387 0 : write(*,2) 'dq_new(k)-dq_old(k_old)', k_old, dq_new(k)-dq_old(k_old)
388 0 : write(*,'(A)')
389 0 : write(*,2) 'xq_new(k)', k, xq_new(k)
390 0 : write(*,2) 'xq_new(k)+dq_new(k)', k, xq_new(k)+dq_new(k)
391 0 : write(*,2) 'xq_end', k, xq_end
392 0 : write(*,*) 'split1'
393 0 : ierr = -1
394 0 : return
395 : end if
396 : end if
397 : end if
398 :
399 128 : if (nz_new == new_capacity) then ! increase allocated size
400 0 : new_capacity = (new_capacity*5)/4 + 10
401 0 : call realloc(s, nz_new, new_capacity, xq_new, dq_new, which_gval, comes_from, ierr)
402 0 : if (ierr /= 0) return
403 : end if
404 128 : nz_new = nz_new + 1
405 128 : if (max_allowed_nz > 0 .and. nz_new > max_allowed_nz) then
406 0 : write(*,*) 'tried to increase number of mesh points beyond max allowed nz', max_allowed_nz
407 0 : ierr = -1
408 0 : return
409 : end if
410 17004 : do kk = nz_new, k+1, -1
411 16876 : xq_new(kk) = xq_new(kk-1)
412 16876 : dq_new(kk) = dq_new(kk-1)
413 16876 : which_gval(kk) = which_gval(kk-1)
414 17004 : comes_from(kk) = comes_from(kk-1)
415 : end do
416 :
417 128 : if (from_merger) then ! split by breaking up the merger
418 128 : xq_mid = xq_new(k) + dq_new(k)*0.5d0
419 128 : split_at_k_old = k_old_last
420 146 : do kk = k_old+1, k_old_last ! check interior boundaries for closest to xq_mid
421 146 : if (xq_old(kk) >= xq_mid) then
422 110 : if (xq_old(kk) - xq_mid < xq_mid - xq_old(kk-1)) then ! xq_mid closer to xq_old(kk)
423 : split_at_k_old = kk
424 : else ! xq_mid closer to xq_old(kk-1)
425 0 : split_at_k_old = kk-1
426 : end if
427 : exit
428 : end if
429 : end do
430 128 : comes_from(k+1) = split_at_k_old
431 128 : xq_new(k+1) = xq_old(split_at_k_old)
432 256 : dq_new(k) = sum(dq_old(k_old:split_at_k_old-1))
433 256 : dq_new(k+1) = sum(dq_old(split_at_k_old:k_old_last))
434 : else
435 0 : dq_new(k:k+1) = dq_new(k)*0.5d0
436 0 : xq_new(k+1) = xq_new(k) + dq_new(k)
437 : ! fix up comes_from(k+1)
438 0 : comes_from(k+1) = nz_old ! just in case
439 0 : do k_old = comes_from(k), nz_old-1
440 0 : if (xq_new(k+1) <= xq_old(k_old+1)) then
441 0 : comes_from(k+1) = k_old
442 0 : exit
443 : end if
444 : end do
445 : end if
446 :
447 128 : if (dbg) then
448 0 : write(*,2) 'split1 dq_new k', k, dq_new(k)
449 0 : write(*,2) 'split1 dq_new k+1', k+1, dq_new(k+1)
450 0 : write(*,2) 'comes_from', k_old
451 0 : write(*,2) 'nz_old', nz_old
452 0 : write(*,2) 'nz_new', nz_new
453 0 : do kk=1400,nz_new
454 0 : if (dq_new(kk) < 1d-12) then
455 0 : write(*,2) 'dq_new(kk)', kk, dq_new(kk)
456 0 : call mesa_error(__FILE__,__LINE__,'debug: split1')
457 : end if
458 : end do
459 : end if
460 :
461 : end subroutine split1
462 :
463 :
464 31907 : logical function okay_to_split1(k_old, dq_new, remaining_dq_old)
465 : integer, intent(in) :: k_old
466 : real(dp), intent(in) :: dq_new, remaining_dq_old
467 31907 : real(dp) :: dr_old, min_dr, rR, rL, dlnR_new
468 : logical :: dbg
469 :
470 : include 'formats'
471 :
472 31907 : dbg = .false.
473 31907 : okay_to_split1 = .false.
474 31907 : if (do_not_split(k_old)) return
475 :
476 31907 : if (max(dq_new,remaining_dq_old) < max(min_dq_for_split,2*min_dq)) return
477 :
478 : if (dbg) then
479 : write(*,2) 'remaining_dq_old', k_old, remaining_dq_old
480 : write(*,1) 'dq_new', dq_new
481 : write(*,1) 'min_dq_for_split', min_dq_for_split
482 : write(*,1) 'min_dq', min_dq
483 : write(*,'(A)')
484 : end if
485 :
486 31907 : if (0d0 < remaining_dq_old .and. dq_new > 0.99d0*remaining_dq_old) then
487 : if (dbg) then
488 : write(*,2) 'dq_old', k_old, remaining_dq_old
489 : write(*,1) 'dq_new', dq_new
490 : write(*,1) 'dq_new/remaining_dq_old', dq_new/remaining_dq_old
491 : write(*,'(A)')
492 : end if
493 : return
494 : end if
495 :
496 31907 : if (k_old < nz_old) then
497 :
498 31907 : rR = s% r(k_old)
499 31907 : rL = s% r(k_old+1)
500 31907 : dr_old = rR - rL
501 31907 : min_dr = s% csound(k_old)*s% mesh_min_dr_div_cs
502 31907 : if (dr_old*dq_new/dq_old(k_old) < 2*min_dr) then
503 : return ! sound crossing time would be too small
504 : end if
505 :
506 31907 : min_dr = s% mesh_min_dr_div_dRstar*(s% r(1) - s% R_center)
507 31907 : if (dr_old*dq_new/dq_old(k_old) < 2*min_dr) then
508 : return ! new dr would be too small
509 : end if
510 :
511 31907 : if (s% mesh_min_dlnR > 0d0) then
512 31907 : dlnR_new = log((rL + dr_old*dq_new/dq_old(k_old))/rL)
513 31907 : if (dlnR_new < 2*s% mesh_min_dlnR) then
514 : ! the factor of 2 is a safety margin.
515 : return
516 : end if
517 : end if
518 :
519 : end if
520 31907 : okay_to_split1 = .true.
521 :
522 : end function okay_to_split1
523 :
524 :
525 10 : subroutine smooth_new_points(ierr)
526 : integer, intent(out) :: ierr
527 :
528 : logical :: dbg, done
529 : integer :: k, k_old
530 10 : real(dp) :: alfa
531 :
532 : include 'formats'
533 :
534 10 : ierr = 0
535 10 : dbg = .false.
536 10 : alfa = mesh_max_allowed_ratio
537 :
538 : do ! repeat until nothing left to do
539 : if (min_k_old_for_split <= 1 .and. &
540 20 : dq_new(1) > alfa*dq_new(2) .and. &
541 : okay_to_split1(1,dq_new(1),0d0)) then
542 0 : call split1(1,ierr)
543 0 : if (ierr /= 0) return
544 : cycle
545 : end if
546 20 : done = .true.
547 20 : k = 2
548 : do ! check for cell that is too large
549 21294 : if (k == nz_new) exit
550 21274 : k_old = comes_from(k)
551 : if (k_old <= max_k_old_for_split .and. &
552 : k_old >= min_k_old_for_split .and. &
553 21274 : okay_to_split1(k_old,dq_new(k),0d0) .and. &
554 : (dq_new(k) > max_dq .or. &
555 : dq_new(k) > alfa*dq_new(k+1) .or. &
556 20 : dq_new(k) > alfa*dq_new(k-1))) then
557 98 : call split1(k,ierr)
558 98 : if (ierr /= 0) return
559 : done = .false.
560 : ! don't increment k; want to recheck the cell in case need to split again
561 : else
562 21176 : k = k + 1
563 : end if
564 : end do
565 :
566 : if (dbg) then
567 : call test_new(ierr)
568 : if (ierr /= 0) call mesa_error(__FILE__,__LINE__,'debug: mesh_plan, smooth_new_points')
569 : end if
570 :
571 20 : if (done) exit
572 :
573 : ! now go in opposite direction
574 10 : done = .true.
575 10 : k = nz_new-1
576 : do
577 10643 : if (k == 1) exit
578 10633 : if (okay_to_split1(comes_from(k),dq_new(k),0d0) .and. &
579 10 : (dq_new(k) > alfa*dq_new(k+1) .or. dq_new(k) > alfa*dq_new(k-1))) then
580 30 : call split1(k,ierr)
581 30 : if (ierr /= 0) return
582 30 : done = .false.
583 30 : k = k + 1 ! recheck the same cell
584 : else
585 10603 : k = k - 1
586 : end if
587 : end do
588 :
589 : if (dbg) then
590 : call test_new(ierr)
591 : if (ierr /= 0) call mesa_error(__FILE__,__LINE__,'debug: mesh_plan, smooth_new_points')
592 : end if
593 :
594 20 : if (done) exit
595 :
596 : end do
597 :
598 : end subroutine smooth_new_points
599 :
600 :
601 10 : subroutine pick_new_points(s, ierr)
602 : type (star_info), pointer :: s
603 : integer, intent(out) :: ierr
604 :
605 : logical :: dbg, force_merge_with_one_more
606 10 : real(dp) :: maxval_delta_xa, next_dq_max, beta_limit, &
607 10 : remaining_dq_old, min_dr
608 : integer :: kk, k_old_init, k_old_next, k_old_next_max, j00, jm1, i, max_merge
609 :
610 : include 'formats'
611 :
612 10 : beta_limit = 0.1d0
613 :
614 10 : ierr = 0
615 10 : k_old = 1
616 10 : k_new = 1
617 10 : xq_new(1) = 0
618 10 : min_dr = s% mesh_min_dr_div_dRstar*(s% r(1) - s% R_center)
619 :
620 : do ! pick next point location
621 :
622 10495 : dbg = plan_dbg .or. (k_new == kdbg) !.or. (s% mesh_call_number == 2005)
623 :
624 : ! when reach this point,
625 : ! have set xq_new(k) for k = 1 to k_new, and dq_new(k) for k = 1 to k_new-1.
626 : ! and have finished using old points from 1 to k_old
627 : ! i.e., xq_old(k_old+1) > xq_new(k_new) >= xq_old(k_old)
628 :
629 10495 : k_old_init = k_old
630 :
631 10495 : if (k_new == 1) then
632 10 : next_dq_max = max_surface_cell_dq
633 : else
634 10485 : next_dq_max = dq_new(k_new-1)*mesh_max_allowed_ratio
635 : end if
636 :
637 : ! make initial choice based on gradients. may reduce later.
638 10495 : if (dbg) then
639 0 : write(*,'(A)')
640 0 : write(*,3) 'call pick_next_dq', k_old, k_new, next_dq_max
641 : end if
642 :
643 10495 : if (s% gradr(k_old) > s% grada(k_old) .and. &
644 : s% min_dq_for_xa_convective > 0d0) then
645 1325 : min_dq_for_xa = s% min_dq_for_xa_convective
646 : else
647 9170 : min_dq_for_xa = s% min_dq_for_xa
648 : end if
649 :
650 10495 : min_dq_for_logT = s% min_dq_for_logT
651 :
652 : next_dq = pick_next_dq(s, &
653 : dbg, next_dq_max, k_old, k_new, nz_old, num_gvals, &
654 : xq_new, dq_new, xq_old, dq_old, min_dq, min_dq_for_split, &
655 : min_dq_for_xa, min_dq_for_logT, &
656 : max_surface_cell_dq, max_dq_cntr, max_num_subcells, &
657 : gval_is_xa_function, gval_is_logT_function, gvals, &
658 10495 : delta_gval_max, gval_names, which_gval, ierr)
659 10495 : if (ierr /= 0) return
660 :
661 10495 : if (dbg) &
662 0 : write(*,3) 'pick_next_dq next_dq prev_dq', k_old, k_new, next_dq, dq_old(k_old)
663 :
664 10495 : if (k_new == 1) then
665 10 : max_merge = max_num_merge_surface_cells
666 : else
667 10485 : max_merge = max_num_merge_cells
668 : end if
669 :
670 10495 : if (k_old < nz_old) then
671 10485 : remaining_dq_old = xq_old(k_old+1)-xq_new(k_new)
672 : else
673 10 : remaining_dq_old = 1d0-xq_new(k_new)
674 : end if
675 :
676 10495 : if (next_dq < remaining_dq_old) then
677 0 : if (.not. okay_to_split1(k_old, next_dq, remaining_dq_old)) then
678 0 : next_dq = remaining_dq_old ! dq_old(k_old)
679 : end if
680 : end if
681 :
682 10495 : if (next_dq > max_dq) then
683 21 : if (xq_new(k_new) == xq_old(k_old)) then
684 2623 : do i = nz_old, k_old+1, -1
685 2623 : if (xq_old(i) - xq_new(k_new) <= max_dq) then
686 21 : next_dq = xq_old(i) - xq_new(k_new)
687 21 : exit
688 : end if
689 : end do
690 : end if
691 : end if
692 :
693 10495 : if (next_dq > max_dq) then
694 0 : next_dq = xq_old(k_old) + dq_old(k_old) - xq_new(k_new)
695 : end if
696 :
697 10495 : if (k_new == 1 .and. next_dq > max_surface_cell_dq) then
698 0 : if (k_old_init == -1 .and. .true.) write(*,*) 'next_dq > max_surface_cell_dq'
699 0 : next_dq = max_surface_cell_dq
700 : end if
701 :
702 : ! Enforce minimum surface‐cell dq
703 10495 : if (k_old == 1 .and. next_dq < min_surface_cell_dq) then
704 : !write(*,*) 'next_dq < min_surface_cell_dq'
705 0 : next_dq = min_surface_cell_dq
706 : end if
707 :
708 10495 : next_xq = xq_new(k_new) + next_dq
709 10495 : if (next_xq > 1d0 - min_dq) then
710 10 : next_xq = (1d0 + xq_new(k_new))/2d0
711 10 : if (k_old < nz_old) then ! make sure don't split current k_old for this case
712 0 : if (xq_old(k_old+1) > next_xq) next_xq = xq_old(k_old+1)
713 : end if
714 10 : next_dq = next_xq - xq_new(k_new)
715 : end if
716 :
717 10495 : if (k_old < nz_old) then
718 :
719 10485 : if (xq_new(k_new) == xq_old(k_old) .and. &
720 : next_dq > dq_old(k_old) - min_dq/2d0) then
721 :
722 10485 : if (.not. okay_to_merge) then
723 :
724 0 : k_old_next = k_old + 1
725 :
726 10485 : else if (k_old < min_k_old_for_split .or. &
727 : k_old > max_k_old_for_split) then
728 :
729 0 : k_old_next = k_old + 1
730 :
731 : else ! consider doing merge
732 :
733 10485 : if (next_dq > 1.5d0*dq_old(k_old)) then
734 7240 : next_dq = 0.9d0*next_dq ! to avoid split-merge flip-flops
735 7240 : next_xq = xq_new(k_new) + next_dq
736 : end if
737 :
738 10485 : k_old_next_max = min(nz_old, k_old + max_merge)
739 10485 : k_old_next = k_old_next_max ! will cut this back as necessary
740 22526 : do kk=k_old+1,k_old_next_max
741 209260 : maxval_delta_xa = maxval(abs(s% xa(:,kk)-s% xa(:,kk-1)))
742 188334 : j00 = maxloc(s% xa(:,kk),dim=1)
743 188334 : jm1 = maxloc(s% xa(:,kk-1),dim=1)
744 : if (maxval_delta_xa > s% max_delta_x_for_merge .or. &
745 20926 : j00 /= jm1 .or. is_convective_boundary(kk) .or. &
746 1600 : is_crystal_boundary(kk)) then
747 : ! don't merge across convective or crystal boundary
748 58 : k_old_next = kk-1
749 58 : exit
750 20868 : else if (next_xq <= xq_old(kk) + min_dq/2d0) then
751 8827 : k_old_next = max(k_old+1,kk-1)
752 8827 : exit
753 : end if
754 : end do
755 :
756 : end if
757 :
758 10485 : k_old_next = max(k_old_next, k_old+1)
759 10485 : next_xq = xq_old(k_old_next)
760 10485 : next_dq = next_xq - xq_new(k_new)
761 :
762 0 : else if (next_xq >= xq_old(k_old+1) - min_dq/2d0) then
763 : ! this is final subcell of a split, so adjust to finish the parent cell
764 :
765 0 : k_old_next = k_old+1
766 0 : next_xq = xq_old(k_old_next)
767 0 : next_dq = next_xq - xq_new(k_new)
768 :
769 : else ! non-final subcell of split
770 :
771 0 : k_old_next = k_old
772 :
773 : end if
774 :
775 10485 : if (next_xq == xq_old(k_old_next)) then
776 : ! finishing 1 or more old cells and not already at max merge.
777 : ! consider forcing a merge with the next cell to make this one larger.
778 10485 : force_merge_with_one_more = .false.
779 :
780 10485 : if (dq_old(k_old) < min_dq) then
781 : force_merge_with_one_more = .true.
782 10485 : else if (s% merge_if_dlnR_too_small) then
783 0 : if (xq_new(k_new) <= xq_old(k_old) .and. &
784 : s% lnR(k_old) - s% lnR(k_old_next) < s% mesh_min_dlnR) then
785 : force_merge_with_one_more = .true.
786 0 : else if (k_old_next == nz_old .and. s% R_center > 0) then
787 0 : force_merge_with_one_more = s% lnR(k_old_next) - log(s% R_center) < s% mesh_min_dlnR
788 : end if
789 : end if
790 :
791 10485 : if ((.not. force_merge_with_one_more) .and. s% merge_if_dr_div_cs_too_small) then
792 10485 : if (xq_new(k_new) <= xq_old(k_old) .and. &
793 : s% r(k_old) - s% r(k_old_next) < s% mesh_min_dr_div_cs*s% csound(k_old)) then
794 : force_merge_with_one_more = .true.
795 10485 : else if (k_old_next == nz_old) then
796 : force_merge_with_one_more = (s% r(k_old_next) - s% R_center) < &
797 10 : s% mesh_min_dr_div_cs*s% csound(k_old_next)
798 10 : if (force_merge_with_one_more .and. dbg) &
799 0 : write(*,3) 'do merge for k_old_next == nz_old', k_old, k_old_next, &
800 0 : s% r(k_old) - s% R_center, &
801 0 : s% mesh_min_dr_div_cs*s% csound(k_old_next), &
802 0 : s% mesh_min_dr_div_cs, s% csound(k_old_next)
803 : end if
804 : end if
805 :
806 10485 : if ((.not. force_merge_with_one_more) .and. &
807 : s% merge_if_dr_div_dRstar_too_small) then
808 10485 : if (xq_new(k_new) <= xq_old(k_old) .and. &
809 : s% r(k_old) - s% r(k_old_next) < min_dr) then
810 : force_merge_with_one_more = .true.
811 10485 : else if (k_old_next == nz_old) then
812 10 : force_merge_with_one_more = (s% r(k_old_next) - s% R_center) < min_dr
813 10 : if (force_merge_with_one_more .and. dbg) &
814 0 : write(*,3) 'do merge for k_old_next == nz_old', k_old, k_old_next, &
815 0 : s% r(k_old) - s% R_center, min_dr
816 : end if
817 : end if
818 :
819 10485 : if (force_merge_with_one_more) then
820 0 : k_old_next = k_old_next + 1
821 0 : if (k_old_next < nz_old) then
822 0 : next_xq = xq_old(k_old_next)
823 : else
824 0 : next_xq = 1d0
825 : end if
826 0 : next_dq = next_xq - xq_new(k_new)
827 0 : if (dbg) then
828 0 : write(*,3) 'force merge', k_old, k_new, next_xq, next_dq
829 0 : write(*,'(A)')
830 : end if
831 : end if
832 :
833 : end if
834 :
835 10485 : k_old = k_old_next
836 :
837 : end if
838 :
839 10495 : comes_from(k_new) = k_old_init
840 :
841 : ! check if we're done
842 10495 : if (1 - xq_new(k_new) < max_dq_cntr .or. 1 - next_xq < min_dq) then
843 10 : dq_new(k_new) = 1 - xq_new(k_new)
844 : exit
845 : end if
846 :
847 10485 : dq_new(k_new) = next_dq
848 :
849 10485 : if (k_new == new_capacity) then ! increase allocated size
850 0 : new_capacity = (new_capacity*5)/4 + 10
851 0 : call realloc(s, k_new, new_capacity, xq_new, dq_new, which_gval, comes_from, ierr)
852 0 : if (ierr /= 0) return
853 : end if
854 :
855 10485 : if (next_xq < xq_new(k_new)) then
856 0 : write(*,*) 'nz_old', nz_old
857 0 : write(*,*) 'k_new', k_new
858 0 : write(*,1) 'next_xq', next_xq
859 0 : write(*,1) 'xq_new(k_new)', xq_new(k_new)
860 0 : write(*,*) 'pick_new_points: next_xq < xq_new(k_new)'
861 0 : ierr = -1
862 0 : return
863 : end if
864 :
865 5656552 : dq_sum = sum(dq_new(1:k_new))
866 :
867 10485 : k_new = k_new + 1
868 10485 : if (max_allowed_nz > 0 .and. k_new > max_allowed_nz) then
869 0 : write(*,*) 'tried to increase number of mesh points beyond max allowed nz', max_allowed_nz
870 0 : ierr = -1
871 0 : return
872 : end if
873 :
874 10485 : xq_new(k_new) = next_xq
875 10485 : if (abs(xq_new(k_new) - dq_sum) > 1d-6) then
876 0 : write(*,'(A)')
877 0 : write(*,*) 'k_new', k_new
878 0 : write(*,1) 'xq_new(k_new) - dq_sum', xq_new(k_new) - dq_sum
879 0 : write(*,1) 'xq_new(k_new)', xq_new(k_new)
880 0 : write(*,1) 'dq_sum', dq_sum
881 0 : write(*,*) 'pick_new_points: abs(xq_new(k_new) - dq_sum) > 1d-6'
882 0 : ierr = -1
883 0 : return
884 : end if
885 : !write(*,2) 'xq_new(k_new) - dq_sum', k_new, xq_new(k_new) - dq_sum
886 :
887 : ! increment k_old if necessary
888 10485 : do while (k_old < nz_old)
889 10475 : if (xq_old(k_old+1) > next_xq) exit
890 10485 : k_old = k_old + 1
891 : end do
892 :
893 : end do
894 :
895 10 : nz_new = k_new
896 :
897 : if (plan_dbg) write(*,2) 'after pick_new_points: nz_new', nz_new
898 :
899 : end subroutine pick_new_points
900 :
901 :
902 20926 : logical function is_convective_boundary(kk)
903 : integer, intent(in) :: kk
904 20926 : is_convective_boundary = .false.
905 20926 : if (kk == nz) return
906 : is_convective_boundary = &
907 : (s% mixing_type(kk) == convective_mixing .and. &
908 : s% mixing_type(kk+1) /= convective_mixing) .or. &
909 : (s% mixing_type(kk+1) == convective_mixing .and. &
910 20916 : s% mixing_type(kk) /= convective_mixing)
911 : end function is_convective_boundary
912 :
913 20868 : logical function is_crystal_boundary(kk)
914 : integer, intent(in) :: kk
915 : if(s% do_phase_separation .and. & ! only need this protection when phase separation is on
916 20868 : s% m(kk) <= s% crystal_core_boundary_mass .and. &
917 : s% m(kk-1) >= s% crystal_core_boundary_mass) then
918 : is_crystal_boundary = .true.
919 : else
920 20868 : is_crystal_boundary = .false.
921 : end if
922 20868 : end function is_crystal_boundary
923 :
924 : subroutine open_debug_file
925 : include 'formats'
926 : open(newunit=iounit, file=trim('plan_debug.data'), action='write', iostat=ierr)
927 : if (ierr /= 0) then
928 : write(*, *) 'open plan_debug.data failed'
929 : call mesa_error(__FILE__,__LINE__,'debug do_mesh_plan')
930 : end if
931 : write(*,*) 'write plan_debug.data'
932 : end subroutine open_debug_file
933 :
934 :
935 : end subroutine do_mesh_plan
936 :
937 :
938 0 : subroutine realloc(s, old_size, new_capacity, xq_new, dq_new, which_gval, comes_from, ierr)
939 : use alloc
940 : type (star_info), pointer :: s
941 : integer, intent(in) :: old_size, new_capacity
942 : real(dp), pointer :: xq_new(:), dq_new(:)
943 : integer, pointer :: which_gval(:), comes_from(:)
944 : integer, intent(out) :: ierr
945 : integer, parameter :: extra = 100
946 0 : call realloc_integer_work_array(s, which_gval, old_size, new_capacity, extra, ierr)
947 0 : if (ierr /= 0) return
948 0 : call realloc_integer_work_array(s, comes_from, old_size, new_capacity, extra, ierr)
949 0 : if (ierr /= 0) return
950 0 : call realloc_work_array(s, .false., xq_new, old_size, new_capacity, extra, 'mesh_plan', ierr)
951 0 : if (ierr /= 0) return
952 0 : call realloc_work_array(s, .false., dq_new, old_size, new_capacity, extra, 'mesh_plan', ierr)
953 0 : if (ierr /= 0) return
954 0 : end subroutine realloc
955 :
956 :
957 10495 : real(dp) function pick_next_dq(s, &
958 : dbg, next_dq_max, k_old, k_new, nz_old, num_gvals, xq_new, dq_new, &
959 : xq_old, dq_old, min_dq, min_dq_for_split, min_dq_for_xa, min_dq_for_logT, &
960 : max_surface_cell_dq, max_dq_cntr, max_num_subcells, &
961 : gval_is_xa_function, gval_is_logT_function, gvals, delta_gval_max, &
962 10495 : gval_names, which_gval, ierr)
963 0 : use mesh_functions, only: max_allowed_gvals
964 : type (star_info), pointer :: s
965 : logical, intent(in) :: dbg
966 : integer, intent(in) :: k_old, k_new, nz_old, num_gvals, max_num_subcells
967 : real(dp), pointer :: xq_new(:), dq_new(:) ! (nz)
968 : real(dp), pointer :: xq_old(:) ! (nz_old)
969 : real(dp), pointer :: dq_old(:) ! (nz_old)
970 : logical, dimension(max_allowed_gvals) :: gval_is_xa_function, gval_is_logT_function
971 : real(dp), pointer :: gvals(:,:) ! (nz_old, num_gvals)
972 : real(dp), intent(in) :: &
973 : next_dq_max, min_dq, min_dq_for_split, &
974 : min_dq_for_xa, min_dq_for_logT, max_surface_cell_dq, max_dq_cntr
975 : real(dp), pointer :: delta_gval_max(:) ! (nz_old, num_gvals)
976 : character (len=32) :: gval_names(:) ! (num_gvals) for debugging.
977 : integer, pointer :: which_gval(:) ! (nz_new) for debugging.
978 : integer, intent(out) :: ierr
979 :
980 41980 : real(dp) :: nxt_dqs(num_gvals), default
981 : integer :: i, j, jmin, op_err
982 : logical :: pkdbg
983 :
984 : include 'formats'
985 :
986 10495 : pkdbg = dbg !.or. k_old == 4000
987 10495 : ierr = 0
988 :
989 10495 : if (pkdbg) write(*,*)
990 0 : if (pkdbg) write(*,2) 'dq_old(k_old)', k_old, dq_old(k_old)
991 :
992 10495 : if (k_new == 1) then
993 10 : pick_next_dq = min(1d0, sqrt(min_dq))
994 10485 : else if (k_new <= 20) then
995 190 : pick_next_dq = min(1-xq_new(k_new), 10*dq_new(k_new-1))
996 : else
997 10295 : pick_next_dq = 1-xq_new(k_new)
998 : end if
999 :
1000 41980 : nxt_dqs(:) = pick_next_dq
1001 10495 : if (k_old == nz_old) then
1002 10 : which_gval(k_new) = 0
1003 10 : pick_next_dq = max(min_dq, (1-xq_new(k_new)) - max_dq_cntr)
1004 10 : do i=1,10
1005 10 : if (1-xq_new(k_new) <= max_dq_cntr*i) then
1006 10 : pick_next_dq = (1-xq_new(k_new))/i
1007 10 : exit
1008 : end if
1009 : end do
1010 10 : return
1011 : end if
1012 :
1013 10485 : default = pick_next_dq ! default size. can be reduced according to gradients of gvals
1014 41940 : do j=1,num_gvals
1015 : nxt_dqs(j) = pick1_dq(s, &
1016 : j, next_dq_max, default, .false., k_old, k_new, nz_old, &
1017 : xq_new, xq_old, dq_old, min_dq, min_dq_for_xa, min_dq_for_logT, max_num_subcells, &
1018 : gval_is_xa_function(j), gval_is_logT_function(j), &
1019 31455 : gvals, delta_gval_max, gval_names, op_err)
1020 41940 : if (op_err /= 0) ierr = op_err
1021 : end do
1022 :
1023 52425 : jmin = minloc(nxt_dqs(:),dim=1)
1024 10485 : if (pkdbg) write(*,3) 'jmin, k_new, init pick_next_dq', jmin, k_new, pick_next_dq
1025 10485 : which_gval(k_new) = jmin
1026 10485 : pick_next_dq = max(min_dq, min(pick_next_dq, nxt_dqs(jmin)))
1027 :
1028 10495 : end function pick_next_dq
1029 :
1030 :
1031 31455 : real(dp) function pick1_dq(s, &
1032 : j, next_dq_max, default, dbg, k_old, k_new, nz_old, &
1033 : xq_new, xq_old, dq_old, min_dq, min_dq_for_xa, min_dq_for_logT, max_num_subcells, &
1034 31455 : is_xa_function, is_logT_function, gvals, delta_gval_max, gval_names, ierr)
1035 10495 : use num_lib, only: binary_search
1036 : type (star_info), pointer :: s
1037 : integer, intent(in) :: j
1038 : real(dp), intent(in) :: next_dq_max, default, min_dq, min_dq_for_xa, min_dq_for_logT
1039 : logical, intent(in) :: dbg
1040 : integer, intent(in) :: k_old, k_new, nz_old, max_num_subcells
1041 : real(dp), pointer :: xq_new(:) ! (nz)
1042 : real(dp), pointer :: xq_old(:) ! (nz_old)
1043 : real(dp), pointer :: dq_old(:) ! (nz_old)
1044 : logical :: is_xa_function, is_logT_function
1045 : real(dp), pointer :: gvals(:,:) ! (nz_old, num_gvals)
1046 : real(dp), pointer :: delta_gval_max(:) ! (nz_old, num_gvals)
1047 : character (len=32) :: gval_names(:) ! (num_gvals) for debugging.
1048 : integer, intent(out) :: ierr
1049 :
1050 31455 : real(dp) :: gnew, dgnew, gmax, gmin, xq, dq_next, dq_sum, sz, dval
1051 : integer :: k
1052 : logical :: dbg1
1053 :
1054 : include 'formats'
1055 :
1056 31455 : ierr = 0
1057 31455 : dbg1 = dbg !.or. (k_old == -1)
1058 :
1059 31455 : pick1_dq = default
1060 31455 : dq_next = -1
1061 :
1062 31455 : if (dbg1) write(*,*)
1063 0 : if (dbg1) write(*,*) 'find max allowed dq for gvals(:,j)', j
1064 : ! find max allowed dq for gvals(:,j)
1065 :
1066 : ! linear interpolate to estimate gvals(:,j) at q_new(k_new)
1067 31455 : dval = gvals(k_old,j) - gvals(k_old+1,j)
1068 :
1069 31455 : gnew = gvals(k_old+1,j) + dval*(xq_old(k_old+1) - xq_new(k_new))/dq_old(k_old)
1070 31455 : if (dbg1) write(*,*) trim(gval_names(j))
1071 :
1072 31455 : dgnew = min(delta_gval_max(k_old), delta_gval_max(k_old+1))
1073 31455 : gmax = gnew + dgnew
1074 31455 : gmin = gnew - dgnew
1075 :
1076 31455 : dq_sum = 0
1077 91915 : do k=k_old+1, nz_old
1078 :
1079 91915 : if (dbg1) write(*,2) 'gvals(k,j)', k, gvals(k,j), dq_sum, dq_old(k-1)
1080 :
1081 91915 : if (gvals(k,j) <= gmax .and. gvals(k,j) >= gmin) then
1082 75436 : if (xq_old(k-1) >= xq_new(k_new)) then
1083 75436 : dq_sum = dq_sum + dq_old(k-1)
1084 : else
1085 0 : if (dq_sum /= 0) then
1086 0 : write(*,*) '(dq_sum /= 0)'
1087 0 : write(*,*) 'pick1_dq'
1088 0 : ierr = -1
1089 0 : return
1090 : end if
1091 0 : dq_sum = xq_old(k) - xq_new(k_new)
1092 : end if
1093 75436 : if (is_bad(dq_sum)) then
1094 0 : write(*,2) 'dq_sum', k, dq_sum
1095 0 : write(*,*) 'pick1_dq'
1096 0 : ierr = -1
1097 0 : if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'mesh plan')
1098 0 : return
1099 : end if
1100 75436 : if (dq_sum >= next_dq_max) exit
1101 60690 : if (dq_sum >= default) then
1102 0 : dq_sum = default; exit
1103 : end if
1104 60690 : if (k < nz_old) cycle
1105 : ! pick location inside center zone
1106 230 : if (dbg1) write(*,*) 'pick location inside center zone'
1107 230 : if (gvals(k-1,j) < gvals(k,j)) then ! see where reach gmax in center cell
1108 230 : dq_next = find0(0d0, gvals(k-1,j)-gmax, dq_old(k-1), gvals(k,j)-gmax)
1109 230 : if (dbg1) write(*,1) 'gvals(k-1,j) < gvals(k,j)', dq_next
1110 0 : else if (gvals(k-1,j) > gvals(k,j)) then ! see where reach gmin
1111 0 : dq_next = find0(0d0, gvals(k-1,j)-gmin, dq_old(k-1), gvals(k,j)-gmin)
1112 0 : if (dbg1) then
1113 0 : write(*,1) 'gvals(k-1,j)-gmin', gvals(k-1,j)-gmin
1114 0 : write(*,1) 'gvals(k,j)-gmin', gvals(k,j)-gmin
1115 0 : write(*,1) 'dq_old(k-1)', dq_old(k-1)
1116 0 : write(*,1) 'gvals(k-1,j) > gvals(k,j)', dq_next
1117 0 : call mesa_error(__FILE__,__LINE__,'debug pick1_dq')
1118 : end if
1119 : else ! we're done -- don't need another point for this gval
1120 0 : dq_sum = default; exit ! just return the default
1121 : end if
1122 230 : if (dq_next > 1 - (xq_new(k_new) + min_dq)) then
1123 190 : dq_sum = default
1124 : else
1125 40 : dq_sum = dq_sum + dq_next
1126 : end if
1127 : exit
1128 : end if
1129 :
1130 16479 : if (gvals(k,j) > gmax) then ! estimate where = gmax
1131 16479 : dq_next = find0(0d0, gvals(k-1,j)-gmax, dq_old(k-1), gvals(k,j)-gmax)
1132 0 : else if (gvals(k,j) < gmin) then ! estimate where = gmin
1133 0 : dq_next = find0(0d0, gvals(k-1,j)-gmin, dq_old(k-1), gvals(k,j)-gmin)
1134 : end if
1135 16479 : if (is_bad(dq_next)) then
1136 0 : write(*,2) 'dq_next', k, dq_next
1137 0 : write(*,*) 'gvals(k,j) > gmax', gvals(k,j) > gmax
1138 0 : write(*,*) 'gvals(k,j) < gmin', gvals(k,j) < gmin
1139 0 : write(*,3) 'gvals(k-1,j)', k-1, j, gvals(k-1,j)
1140 0 : write(*,2) 'gmax', k, gmax
1141 0 : write(*,3) 'gvals(k,j)', k, j, gvals(k,j)
1142 0 : write(*,2) 'gmin', k, gmin
1143 0 : write(*,2) 'dq_old(k-1)', k, dq_old(k-1)
1144 0 : write(*,*) 'pick1_dq'
1145 0 : ierr = -1
1146 0 : if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'mesh plan')
1147 0 : return
1148 : end if
1149 16479 : if (xq_old(k-1) >= xq_new(k_new)) then
1150 16479 : dq_sum = dq_sum + dq_next
1151 : else
1152 0 : if (dq_sum /= 0) then
1153 0 : write(*,*) '(dq_sum /= 0)'
1154 0 : write(*,*) 'pick1_dq'
1155 0 : ierr = -1
1156 0 : return
1157 : end if
1158 0 : dq_sum = dq_next - (xq_new(k_new) - xq_old(k-1))
1159 : end if
1160 75206 : exit
1161 :
1162 : end do
1163 :
1164 31455 : if (dbg1) then
1165 0 : write(*,1) 'after loop: dq_sum', dq_sum, min_dq, default
1166 : end if
1167 :
1168 31455 : dq_sum = max(min_dq, dq_sum)
1169 31455 : xq = xq_new(k_new) + dq_sum
1170 31455 : if (dbg1) write(*,1) 'before round_off_xq', xq
1171 31455 : xq = round_off_xq(k_old, nz_old, max_num_subcells, xq, xq_old, dq_old, sz, ierr)
1172 31455 : if (ierr /= 0) return
1173 31455 : if (dbg1) then
1174 0 : write(*,1) 'after round_off_xq: xq', xq
1175 0 : write(*,1) 'xq_new(k_new)', xq_new(k_new)
1176 0 : write(*,1) 'xq - xq_new(k_new)', xq - xq_new(k_new)
1177 0 : write(*,1) 'sz', sz
1178 0 : write(*,1) 'min_dq', min_dq
1179 0 : write(*,1) 'default', default
1180 : end if
1181 31455 : pick1_dq = max(min_dq, sz, xq - xq_new(k_new))
1182 :
1183 31455 : if (is_xa_function .and. pick1_dq < min_dq_for_xa) &
1184 310 : pick1_dq = min_dq_for_xa
1185 :
1186 31455 : if (is_logT_function .and. pick1_dq < min_dq_for_logT) &
1187 0 : pick1_dq = min_dq_for_logT
1188 :
1189 31455 : if (dbg1) then
1190 0 : write(*,2) 'dq_sum', k_new, dq_sum
1191 0 : write(*,2) 'xq', k_new, xq
1192 0 : write(*,2) 'pick1_dq', k_new, pick1_dq
1193 0 : write(*,2) 'log pick1_dq', k_new, log10(pick1_dq)
1194 : end if
1195 :
1196 31455 : end function pick1_dq
1197 :
1198 :
1199 31455 : real(dp) function round_off_xq(k_old, nz_old, n, xq, xq_old, dq_old, sz, ierr)
1200 : ! adjust to match one of the candidate subcell locations
1201 : ! this prevents generating too many candidate new points
1202 : integer, intent(in) :: k_old, nz_old, n ! n is number of subcells
1203 : real(dp), intent(in) :: xq, xq_old(:), dq_old(:)
1204 : real(dp), intent(out) :: sz ! subcell size at new location
1205 : integer, intent(out) :: ierr
1206 :
1207 31455 : real(dp) :: dq, tmp
1208 : integer :: i, k, j, knxt
1209 : include 'formats'
1210 31455 : ierr = 0
1211 31455 : knxt = 0
1212 31455 : round_off_xq = -1
1213 31455 : if (xq >= xq_old(nz_old)) then
1214 230 : knxt = nz_old+1
1215 : else
1216 31225 : j = -1
1217 31225 : do k=k_old,1,-1
1218 31225 : if (xq_old(k) <= xq) then
1219 31225 : j = k+1; exit
1220 : end if
1221 : end do
1222 31225 : if (j <= 1) then
1223 0 : write(*,*) 'logic error in mesh plan: round_off_xq'
1224 0 : ierr = -1
1225 0 : return
1226 : end if
1227 104641 : do k=j,nz_old
1228 104641 : if (xq_old(k) > xq) then
1229 : knxt = k; exit
1230 : end if
1231 : end do
1232 : end if
1233 : ! xq is in old cell knxt-1
1234 : ! move location to next subcell boundary
1235 31455 : dq = xq - xq_old(knxt-1)
1236 31455 : sz = dq_old(knxt-1)/dble(n) ! size of subcells
1237 31455 : tmp = dq/sz
1238 31455 : if(tmp>huge(n)) tmp=huge(n)
1239 31455 : i = max(1,floor(tmp))
1240 31455 : if (knxt > nz_old) i = min(i,n/2) ! limit extrapolation into center
1241 31455 : dq = i*sz
1242 31455 : round_off_xq = xq_old(knxt-1) + dq
1243 31455 : if (dq <= 0) then
1244 0 : write(*,2) 'dq', knxt-1, dq, xq, xq_old(knxt-1), dq_old(knxt-1)
1245 0 : write(*,3) 'i n sz', i, n, sz
1246 0 : write(*,*) 'round_off_xq'
1247 0 : ierr = -1
1248 0 : return
1249 : end if
1250 31455 : end function round_off_xq
1251 :
1252 : end module mesh_plan
|