LCOV - code coverage report
Current view: top level - star/private - solve_omega_mix.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 341 0
Test Date: 2025-05-08 18:23:42 Functions: 0.0 % 7 0

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2012  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 solve_omega_mix
      21              : 
      22              :       use star_private_def
      23              :       use const_def, only: qp, dp, i8
      24              : 
      25              :       implicit none
      26              : 
      27              :       private
      28              :       public :: do_solve_omega_mix
      29              : 
      30              :       contains
      31              : 
      32            0 :       integer function do_solve_omega_mix(s, dt_total)
      33              :          use star_utils, only: start_time, update_time, total_angular_momentum
      34              :          use mix_info, only: update_rotation_mixing_info
      35              :          use hydro_rotation, only: get_rotation_sigmas, set_omega, set_i_rot
      36              : 
      37              :          type (star_info), pointer :: s
      38              :          real(dp), intent(in) :: dt_total
      39              : 
      40              :          integer :: ierr, nz, k, max_iters_per_substep, &
      41              :             max_iters_total, total_num_iters, num_iters
      42              :          integer(i8) :: time0
      43              :          integer :: steps_used, max_steps, min_steps
      44            0 :          real(qp) :: remaining_time, total_time, time, dt, &
      45            0 :             J_tot0, J_tot1, max_del, avg_del, &
      46            0 :             tol_correction_max, tol_correction_norm
      47            0 :          real(dp) :: total
      48            0 :          real(dp), pointer, dimension(:) :: am_sig_omega, am_sig_j
      49            0 :          real(qp), pointer, dimension(:) :: du, d, dl, x, b, bp, vp, xp, dX, X_0, X_1, rhs, del
      50              :          logical :: okay, recalc_mixing_info_each_substep
      51              :          logical, parameter :: dbg = .false.
      52              : 
      53              :          include 'formats'
      54              : 
      55            0 :          do_solve_omega_mix = keep_going
      56              : 
      57            0 :          ierr = 0
      58              : 
      59            0 :          nz = s% nz
      60            0 :          total_time = dt_total
      61            0 :          time = 0
      62            0 :          max_steps = 20
      63            0 :          min_steps = 4
      64            0 :          max_iters_per_substep = 4
      65            0 :          max_iters_total = 40
      66            0 :          total_num_iters = 0
      67            0 :          tol_correction_max = 1d-4
      68            0 :          tol_correction_norm = 1d-7
      69              : 
      70              :          ! update omega for new i_rot and previous j_rot to conserve angular momentum
      71            0 :          call set_i_rot(s, .false.)
      72            0 :          call set_omega(s, 'solve_omega_mix')
      73              : 
      74            0 :          if (dt_total <= 0d0) return
      75              : 
      76            0 :          if (s% doing_timing) call start_time(s, time0, total)
      77              : 
      78            0 :          s% extra_jdot(1:nz) = 0
      79            0 :          s% extra_omegadot(1:nz) = 0
      80              : 
      81            0 :          if (s% use_other_torque) then
      82            0 :             call s% other_torque(s% id, ierr)
      83            0 :             if (ierr /= 0) then
      84            0 :                if (s% report_ierr .or. dbg) &
      85            0 :                   write(*, *) 'solve_omega_mix: other_torque returned ierr', ierr
      86            0 :                return
      87              :             end if
      88              :          end if
      89              : 
      90            0 :          if (associated(s% binary_other_torque)) then
      91              :             call s% binary_other_torque(s% id, ierr)
      92            0 :             if (ierr /= 0) then
      93            0 :                if (s% report_ierr .or. dbg) &
      94            0 :                   write(*, *) 'solve_omega_mix: binary_other_torque returned ierr', ierr
      95            0 :                return
      96              :             end if
      97              :          end if
      98              : 
      99              :          call do_alloc(ierr)
     100            0 :          if (ierr /= 0) then
     101            0 :             do_solve_omega_mix = terminate
     102            0 :             s% termination_code = t_solve_omega_mix
     103            0 :             s% result_reason = nonzero_ierr
     104            0 :             if (s% report_ierr) write(*,*) 'allocate failed in do_solve_omega_mix'
     105            0 :             return
     106              :          end if
     107              : 
     108            0 :          J_tot0 = total_angular_momentum(s)
     109              : 
     110            0 :          okay = .true.
     111            0 :          do k=1,nz
     112            0 :             if (is_bad_num(s% omega(k)) .or. abs(s% omega(k)) > 1d50) then
     113            0 :                if (s% stop_for_bad_nums) then
     114            0 :                   write(*,2) 's% omega(k)', k, s% omega(k)
     115            0 :                   call mesa_error(__FILE__,__LINE__,'solve omega')
     116              :                end if
     117              :                okay = .false.
     118              :                exit
     119              :             end if
     120              :          end do
     121              :          if (.not. okay) then
     122            0 :             write(*,2) 'model_number', s% model_number
     123            0 :             call mesa_error(__FILE__,__LINE__,'start solve omega: bad num omega')
     124              :          end if
     125              : 
     126            0 :          steps_used = 0
     127            0 :          recalc_mixing_info_each_substep = s% recalc_mixing_info_each_substep
     128              : 
     129              :       step_loop: do while &
     130            0 :                (total_time - time > 1d-10*total_time .and. &
     131            0 :                   steps_used < max_steps)
     132              : 
     133            0 :             if (steps_used > 0 .and. recalc_mixing_info_each_substep) then
     134              :                call update_rotation_mixing_info(s,ierr)
     135            0 :                if (ierr /= 0) then
     136            0 :                   do_solve_omega_mix = terminate
     137            0 :                   s% termination_code = t_solve_omega_mix
     138            0 :                   s% result_reason = nonzero_ierr
     139            0 :                   if (s% report_ierr) write(*,*) 'update_rotation_mixing_info failed in do_solve_omega_mix'
     140            0 :                   return
     141              :                end if
     142              :             end if
     143              : 
     144            0 :             if (steps_used == 0 .or. recalc_mixing_info_each_substep) then
     145            0 :                if (steps_used > 0) then
     146            0 :                   do k=1,nz
     147            0 :                      am_sig_omega(k) = s% am_sig_omega(k)
     148            0 :                      am_sig_j(k) = s% am_sig_j(k)
     149              :                   end do
     150              :                end if
     151            0 :                call get_rotation_sigmas(s, 1, nz, dt_total, ierr)
     152            0 :                if (ierr /= 0) then
     153            0 :                   do_solve_omega_mix = terminate
     154            0 :                   s% termination_code = t_solve_omega_mix
     155            0 :                   s% result_reason = nonzero_ierr
     156            0 :                   if (s% report_ierr) write(*,*) 'get_rotation_sigmas failed in do_solve_omega_mix'
     157            0 :                   return
     158              :                end if
     159            0 :                if (steps_used > 0) then
     160            0 :                   do k=1,nz
     161            0 :                      s% am_sig_omega(k) = 0.5d0*(s% am_sig_omega(k) + am_sig_omega(k))
     162            0 :                      s% am_sig_j(k) = 0.5d0*(s% am_sig_j(k) + am_sig_j(k))
     163              :                   end do
     164              :                end if
     165              :             end if
     166              : 
     167            0 :             steps_used = steps_used + 1
     168              : 
     169            0 :             dt = 0.5d0*min_mixing_timescale()
     170            0 :             remaining_time = total_time - time
     171            0 :             dt = max(dt, 1d-6*remaining_time)
     172            0 :             dt = min(dt, real(dt_total/min_steps,kind=qp))
     173            0 :             if (dt >= remaining_time) then
     174            0 :                dt = remaining_time
     175              :             else
     176            0 :                dt = min(dt, 0.5d0*remaining_time)
     177              :             end if
     178            0 :             if (steps_used >= max_steps) dt = remaining_time  ! just go for it
     179              :             if (dbg) write(*,3) 'mix dt', &
     180              :                   s% model_number, steps_used, dt, dt/remaining_time
     181              : 
     182              :             ! X_0 is omega at start of substep
     183              :             ! X_1 is current candidate for omega at end of substep
     184              :             ! dX = X_1 - X_0
     185            0 :             do k=1,nz
     186            0 :                X_0(k) = s% omega(k)
     187            0 :                X_1(k) = X_0(k)
     188            0 :                dX(k) = 0d0
     189              :             end do
     190              : 
     191            0 :          solve_loop: do num_iters = 1, max_iters_per_substep
     192              : 
     193            0 :                if (total_num_iters >= max_iters_total) then
     194            0 :                   s% retry_message = 'solve omega mix failed to converge in allowed number of steps'
     195            0 :                   do_solve_omega_mix = retry
     196            0 :                   exit step_loop
     197              :                end if
     198              : 
     199            0 :                total_num_iters = total_num_iters+1
     200              : 
     201            0 :                if (s% use_other_torque_implicit) then
     202            0 :                   call s% other_torque_implicit(s% id, ierr)
     203            0 :                   if (ierr /= 0) then
     204            0 :                      s% retry_message = 'other_torque_implicit returned ierr'
     205            0 :                      do_solve_omega_mix = retry
     206            0 :                      exit step_loop
     207              :                   end if
     208              :                end if
     209              : 
     210            0 :                if (associated(s% binary_other_torque_implicit)) then
     211              :                   call s% binary_other_torque_implicit(s% id, ierr)
     212            0 :                   if (ierr /= 0) then
     213            0 :                      s% retry_message = 'binary_other_torque_implicit returned ierr'
     214            0 :                      do_solve_omega_mix = retry
     215            0 :                      exit step_loop
     216              :                   end if
     217              :                end if
     218              : 
     219            0 :                call create_matrix_and_rhs(dt)
     220              : 
     221              :                ! solve for del
     222            0 :                call solve_tridiag(dl, d, du, rhs(1:nz), del(1:nz), nz, ierr)
     223            0 :                if (ierr /= 0) then
     224            0 :                   s% retry_message = 'matrix solve failed in solve mix'
     225            0 :                   do_solve_omega_mix = retry
     226            0 :                   exit step_loop
     227              :                end if
     228              : 
     229              :                ! apply the correction dX = dX + del
     230              :                ! X_1 = X_0 + dX
     231              :                ! X_0 is omega at start of substep
     232              :                ! X_1 is candidate for omega at end of substep
     233            0 :                do k=2,nz
     234            0 :                   dX(k) = dX(k) + del(k)
     235            0 :                   X_1(k) = X_0(k) + dX(k)
     236            0 :                   s% omega(k) = X_1(k)
     237              :                end do
     238            0 :                s% omega(1) = s% omega(2)
     239              : 
     240              :                ! if correction small enough, exit solve_loop
     241            0 :                max_del = maxval(abs(del(1:nz)))
     242            0 :                avg_del = sum(abs(del(1:nz)))/nz
     243            0 :                if (max_del <= tol_correction_max .and. avg_del <= tol_correction_norm) then
     244              :                   if (dbg) &
     245              :                      write(*,3) 'substep converged: iters max_del avg_del dt/total', &
     246              :                         steps_used, num_iters, max_del, avg_del, dt/total_time
     247              :                   exit solve_loop  ! this substep is done
     248              :                end if
     249              : 
     250            0 :                if (num_iters == max_iters_per_substep) then
     251            0 :                   s% retry_message = 'num_iters == max_iters_per_substep in solve mix'
     252            0 :                   do_solve_omega_mix = retry
     253            0 :                   exit step_loop
     254              :                end if
     255              : 
     256              :             end do solve_loop
     257              : 
     258            0 :             time = time + dt
     259              : 
     260              :          end do step_loop
     261              : 
     262              :          !if (recalc_mixing_info_each_substep) &
     263              :          !   write(*,3) 'omega mix steps_used', steps_used, s% model_number
     264              : 
     265              :          if (dbg) write(*,2) 'omega mix steps_used', steps_used
     266              : 
     267            0 :          s% num_rotation_solver_steps = max(steps_used, s% num_rotation_solver_steps)
     268              : 
     269            0 :          if (do_solve_omega_mix == keep_going .and. total_time - time > 1d-10*total_time) then
     270            0 :             do_solve_omega_mix = retry
     271            0 :             s% retry_message = 'failed in mixing angular momentum'
     272              :          end if
     273              : 
     274              :          if (do_solve_omega_mix == keep_going) then
     275              : 
     276            0 :             okay = .true.
     277            0 :             do k=1,nz
     278            0 :                if (is_bad_num(s% omega(k)) .or. abs(s% omega(k)) > 1d50) then
     279            0 :                   write(*,2) 's% omega(k)', k, s% omega(k)
     280              :                   okay = .false.
     281              :                   exit
     282              :                end if
     283              :             end do
     284              :             if (.not. okay) then
     285            0 :                write(*,2) 'model_number', s% model_number
     286            0 :                call mesa_error(__FILE__,__LINE__,'end solve omega')
     287              :             end if
     288              : 
     289            0 :             do k=1,nz
     290            0 :                s% j_rot(k) = s% i_rot(k)% val*s% omega(k)
     291              :             end do
     292              : 
     293            0 :             if (.not. (s% use_other_torque .or. s% use_other_torque_implicit .or. &
     294              :                   associated(s% binary_other_torque))) then
     295              : 
     296              :                ! check conservation for cases with no extra torque
     297            0 :                J_tot1 = total_angular_momentum(s)  ! what we have
     298              : 
     299            0 :                if (abs(J_tot0 - J_tot1) > s% angular_momentum_error_retry*abs(J_tot0)) then
     300            0 :                   s% retry_message = 'retry: failed to conserve angular momentum in mixing'
     301            0 :                   write(*,*) "angular momentum error larger than angular_momentum_error_retry", abs(J_tot0 - J_tot1)/abs(J_tot0)
     302            0 :                   do_solve_omega_mix = retry
     303            0 :                else if (abs(J_tot0 - J_tot1) > s% angular_momentum_error_warn*abs(J_tot0)) then
     304            0 :                   write(*,*) "angular momentum error larger than angular_momentum_error_warn", abs(J_tot0 - J_tot1)/abs(J_tot0)
     305              :                end if
     306              :                if (dbg) then
     307              :                   write(*,2) 'final J_tot1', s% model_number, J_tot1
     308              :                   write(*,2) '(J_tot1 - J_tot0)/J_tot0', &
     309              :                      steps_used, (J_tot1 - J_tot0)/J_tot0, J_tot0, J_tot1
     310              :                end if
     311              :             end if
     312              : 
     313              :          end if
     314              : 
     315              :          if (dbg) write(*,*)
     316              : 
     317            0 :          call dealloc
     318              : 
     319            0 :          if (s% doing_timing) &
     320            0 :             call update_time(s, time0, total, s% time_solve_omega_mix)
     321              : 
     322              : 
     323              :          contains
     324              : 
     325              : 
     326            0 :          subroutine do_alloc(ierr)
     327            0 :             use alloc, only: non_crit_get_quad_array
     328              :             integer, intent(out) :: ierr
     329            0 :             call do_work_arrays(.true.,ierr)
     330              : 
     331            0 :             call non_crit_get_quad_array(s, du, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     332            0 :             if (ierr /= 0) return
     333            0 :             call non_crit_get_quad_array(s, d, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     334            0 :             if (ierr /= 0) return
     335            0 :             call non_crit_get_quad_array(s, dl, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     336            0 :             if (ierr /= 0) return
     337            0 :             call non_crit_get_quad_array(s, x, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     338            0 :             if (ierr /= 0) return
     339            0 :             call non_crit_get_quad_array(s, b, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     340            0 :             if (ierr /= 0) return
     341            0 :             call non_crit_get_quad_array(s, bp, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     342            0 :             if (ierr /= 0) return
     343            0 :             call non_crit_get_quad_array(s, vp, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     344            0 :             if (ierr /= 0) return
     345            0 :             call non_crit_get_quad_array(s, xp, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     346            0 :             if (ierr /= 0) return
     347            0 :             call non_crit_get_quad_array(s, dX, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     348            0 :             if (ierr /= 0) return
     349            0 :             call non_crit_get_quad_array(s, X_0, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     350            0 :             if (ierr /= 0) return
     351            0 :             call non_crit_get_quad_array(s, X_1, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     352            0 :             if (ierr /= 0) return
     353            0 :             call non_crit_get_quad_array(s, rhs, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     354            0 :             if (ierr /= 0) return
     355            0 :             call non_crit_get_quad_array(s, del, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     356            0 :             if (ierr /= 0) return
     357              : 
     358            0 :          end subroutine do_alloc
     359              : 
     360              : 
     361            0 :          subroutine dealloc
     362            0 :             use alloc, only: non_crit_return_quad_array
     363            0 :             call do_work_arrays(.false.,ierr)
     364              : 
     365            0 :             call non_crit_return_quad_array(s, du, 'solve_omega_mix')
     366            0 :             call non_crit_return_quad_array(s, d, 'solve_omega_mix')
     367            0 :             call non_crit_return_quad_array(s, dl, 'solve_omega_mix')
     368            0 :             call non_crit_return_quad_array(s, x, 'solve_omega_mix')
     369            0 :             call non_crit_return_quad_array(s, b, 'solve_omega_mix')
     370            0 :             call non_crit_return_quad_array(s, bp, 'solve_omega_mix')
     371            0 :             call non_crit_return_quad_array(s, vp, 'solve_omega_mix')
     372            0 :             call non_crit_return_quad_array(s, xp, 'solve_omega_mix')
     373              : 
     374            0 :             call non_crit_return_quad_array(s, dX, 'solve_omega_mix')
     375            0 :             call non_crit_return_quad_array(s, X_0, 'solve_omega_mix')
     376            0 :             call non_crit_return_quad_array(s, X_1, 'solve_omega_mix')
     377            0 :             call non_crit_return_quad_array(s, rhs, 'solve_omega_mix')
     378            0 :             call non_crit_return_quad_array(s, del, 'solve_omega_mix')
     379              : 
     380            0 :          end subroutine dealloc
     381              : 
     382              : 
     383            0 :          subroutine do_work_arrays(alloc_flag, ierr)
     384            0 :             use alloc, only: work_array
     385              :             logical, intent(in) :: alloc_flag
     386              :             integer, intent(out) :: ierr
     387              :             logical, parameter :: crit = .false.
     388              :             ierr = 0
     389              :             call work_array(s, alloc_flag, crit, &
     390            0 :                am_sig_omega, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     391            0 :             if (ierr /= 0) return
     392              :             call work_array(s, alloc_flag, crit, &
     393            0 :                am_sig_j, nz, nz_alloc_extra, 'solve_omega_mix', ierr)
     394            0 :             if (ierr /= 0) return
     395            0 :          end subroutine do_work_arrays
     396              : 
     397              : 
     398            0 :          subroutine solve_tridiag(sub, diag, sup, rhs, x, n, ierr)
     399              :             !      sub - sub-diagonal
     400              :             !      diag - the main diagonal
     401              :             !      sup - sup-diagonal
     402              :             !      rhs - right hand side
     403              :             !      x - the answer
     404              :             !      n - number of equations
     405              : 
     406              :             integer, intent(in) :: n
     407              :             real(qp), dimension(:), intent(in) :: sup, diag, sub
     408              :             real(qp), dimension(:), intent(in) :: rhs
     409              :             real(qp), dimension(:), intent(out) :: x
     410              :             integer, intent(out) :: ierr
     411              : 
     412            0 :             real(qp) :: m
     413              :             integer :: i
     414              : 
     415            0 :             ierr = 0
     416              : 
     417            0 :             bp(1) = diag(1)
     418            0 :             vp(1) = rhs(1)
     419              : 
     420            0 :             do i = 2,n
     421            0 :                m = sub(i-1)/bp(i-1)
     422            0 :                bp(i) = diag(i) - m*sup(i-1)
     423            0 :                vp(i) = rhs(i) - m*vp(i-1)
     424              :             end do
     425              : 
     426            0 :             xp(n) = vp(n)/bp(n)
     427            0 :             x(n) = xp(n)
     428            0 :             do i = n-1, 1, -1
     429            0 :                xp(i) = (vp(i) - sup(i)*xp(i+1))/bp(i)
     430            0 :                x(i) = xp(i)
     431              :             end do
     432              : 
     433            0 :          end subroutine solve_tridiag
     434              : 
     435              : 
     436            0 :          real(dp) function min_mixing_timescale() result(dt)
     437              :             integer :: k
     438              :             real(dp) :: &  ! use dp instead of qp to get same answer in ifort and gfortran
     439            0 :                omega, irot, irot_mid_00, am_sig_omega_00, c_omega_00, del00_omega, &
     440            0 :                omega_mid_00, am_sig_irot_00, c_irot_00, del00_irot, &
     441            0 :                dmbar, irot_mid_m1, am_sig_omega_m1, c_omega_m1, delm1_omega, &
     442            0 :                omega_mid_m1, am_sig_irot_m1, c_irot_m1, delm1_irot, &
     443            0 :                d2omega, d2irot, dt00
     444              : 
     445              :             include 'formats'
     446              : 
     447            0 :             dt = 1d99
     448              : 
     449            0 :             do k = 1, nz
     450              : 
     451            0 :                omega = s% omega(k)
     452            0 :                irot = s% i_rot(k)% val
     453              : 
     454            0 :                if (k < nz) then
     455              : 
     456            0 :                   irot_mid_00 = 0.5d0*(irot + s% i_rot(k+1)% val)
     457            0 :                   am_sig_omega_00 = s% am_sig_omega(k) + s% am_sig_j(k)
     458            0 :                   c_omega_00 = am_sig_omega_00*irot_mid_00
     459            0 :                   del00_omega = omega - s% omega(k+1)
     460              : 
     461            0 :                   omega_mid_00 = 0.5d0*(omega + s% omega(k+1))
     462            0 :                   am_sig_irot_00 = s% am_sig_j(k)
     463            0 :                   c_irot_00 = am_sig_irot_00*omega_mid_00
     464            0 :                   del00_irot = irot - s% i_rot(k+1)% val
     465              : 
     466              :                else
     467              : 
     468              :                   c_omega_00 = 0
     469              :                   del00_omega = 0
     470              :                   c_irot_00 = 0
     471              :                   del00_irot = 0
     472              : 
     473              :                end if
     474              : 
     475            0 :                if (k > 1) then
     476              : 
     477            0 :                   if (k < nz) then
     478            0 :                      dmbar = 0.5d0*(s% dm(k-1) + s% dm(k))
     479              :                   else
     480            0 :                      dmbar = 0.5d0*s% dm(k-1) + s% dm(k)
     481              :                   end if
     482              : 
     483            0 :                   irot_mid_m1 = 0.5d0*(s% i_rot(k-1)% val + irot)
     484            0 :                   am_sig_omega_m1 = s% am_sig_omega(k-1) + s% am_sig_j(k-1)
     485            0 :                   c_omega_m1 = am_sig_omega_m1*irot_mid_m1
     486            0 :                   delm1_omega = s% omega(k-1) - omega
     487              : 
     488            0 :                   omega_mid_m1 = 0.5d0*(s% omega(k-1) + omega)
     489            0 :                   am_sig_irot_m1 = s% am_sig_j(k-1)
     490            0 :                   c_irot_m1 = am_sig_irot_m1*omega_mid_m1
     491            0 :                   delm1_irot = s% i_rot(k-1)% val - irot
     492              : 
     493              :                else
     494              : 
     495            0 :                   dmbar = 0.5d0*s% dm(k)
     496            0 :                   c_omega_m1 = 0
     497            0 :                   delm1_omega = 0
     498            0 :                   c_irot_m1 = 0
     499            0 :                   delm1_irot = 0
     500              : 
     501              :                end if
     502              : 
     503            0 :                if (k == 1) then
     504            0 :                   d2omega = -c_omega_00*del00_omega
     505            0 :                   d2irot = -c_irot_00*del00_irot
     506            0 :                else if (k == nz) then
     507            0 :                   d2omega = c_omega_m1*delm1_omega
     508            0 :                   d2irot = c_irot_m1*delm1_irot
     509              :                else
     510            0 :                   d2omega = c_omega_m1*delm1_omega - c_omega_00*del00_omega
     511            0 :                   d2irot = c_irot_m1*delm1_irot - c_irot_00*del00_irot
     512              :                end if
     513              : 
     514              :                dt00 = max(1d-12,abs(omega))*irot/ &
     515              :                   max(1d-50, abs((d2omega + d2irot)/dmbar + &
     516            0 :                                  s% extra_omegadot(k)*irot + s% extra_jdot(k)))
     517            0 :                if (dt00 < dt) dt = dt00
     518              : 
     519              :             end do
     520              : 
     521            0 :          end function min_mixing_timescale
     522              : 
     523              : 
     524            0 :          subroutine create_matrix_and_rhs(dt)
     525              :             ! basic equation from Heger, Langer, & Woosley, 2000, eqn 46.
     526              :             ! with source terms added.
     527              :             ! and term for j curvature as well as omega curvature
     528              :             real(qp), intent(in) :: dt
     529              :             integer :: k
     530              :             real(qp) :: &
     531            0 :                dmbar, f, &
     532            0 :                omega, omega_mid_00, omega_mid_m1, &
     533            0 :                irot, irot_mid_00, irot_mid_m1, &
     534            0 :                am_sig_omega_00, am_sig_omega_m1, c_omega_00, c_omega_m1, &
     535            0 :                am_sig_irot_00, am_sig_irot_m1, c_irot_00, c_irot_m1, &
     536            0 :                d_c_irot_00_domega_p1, d_c_irot_00_domega_00, &
     537            0 :                d_c_irot_m1_domega_00, d_c_irot_m1_domega_m1, &
     538            0 :                del00_omega, delm1_omega, &
     539            0 :                del00_irot, delm1_irot, &
     540            0 :                d2omega, d_d2omega_domega_p1, d_d2omega_domega_m1, d_d2omega_domega_00, &
     541            0 :                d2irot, d_d2irot_domega_p1, d_d2irot_domega_m1, d_d2irot_domega_00
     542              : 
     543              :             include 'formats'
     544              : 
     545            0 :             do k = 1, nz
     546              : 
     547            0 :                omega = s% omega(k)
     548            0 :                irot = s% i_rot(k)% val
     549              : 
     550            0 :                if (k < nz) then
     551              : 
     552            0 :                   irot_mid_00 = 0.5d0*(irot + s% i_rot(k+1)% val)
     553            0 :                   am_sig_omega_00 = s% am_sig_omega(k) + s% am_sig_j(k)
     554            0 :                   c_omega_00 = am_sig_omega_00*irot_mid_00
     555            0 :                   del00_omega = omega - s% omega(k+1)
     556              : 
     557            0 :                   omega_mid_00 = 0.5d0*(omega + s% omega(k+1))
     558            0 :                   am_sig_irot_00 = s% am_sig_j(k)
     559            0 :                   c_irot_00 = am_sig_irot_00*omega_mid_00
     560            0 :                   d_c_irot_00_domega_p1 = 0.5d0*am_sig_irot_00
     561            0 :                   d_c_irot_00_domega_00 = 0.5d0*am_sig_irot_00
     562            0 :                   del00_irot = irot - s% i_rot(k+1)% val
     563              : 
     564              :                else
     565              : 
     566              :                   c_omega_00 = 0
     567              :                   del00_omega = 0
     568              :                   c_irot_00 = 0
     569              :                   d_c_irot_00_domega_p1 = 0
     570              :                   d_c_irot_00_domega_00 = 0
     571              :                   del00_irot = 0
     572              : 
     573              :                end if
     574              : 
     575            0 :                if (k > 1) then
     576              : 
     577            0 :                   if (k < nz) then
     578            0 :                      dmbar = 0.5d0*(s% dm(k-1) + s% dm(k))
     579              :                   else
     580            0 :                      dmbar = 0.5d0*s% dm(k-1) + s% dm(k)
     581              :                   end if
     582              : 
     583            0 :                   irot_mid_m1 = 0.5d0*(s% i_rot(k-1)% val + irot)
     584            0 :                   am_sig_omega_m1 = s% am_sig_omega(k-1) + s% am_sig_j(k-1)
     585            0 :                   c_omega_m1 = am_sig_omega_m1*irot_mid_m1
     586            0 :                   delm1_omega = s% omega(k-1) - omega
     587              : 
     588            0 :                   omega_mid_m1 = 0.5d0*(s% omega(k-1) + omega)
     589            0 :                   am_sig_irot_m1 = s% am_sig_j(k-1)
     590            0 :                   c_irot_m1 = am_sig_irot_m1*omega_mid_m1
     591            0 :                   d_c_irot_m1_domega_00 = 0.5d0*am_sig_irot_m1
     592            0 :                   d_c_irot_m1_domega_m1 = 0.5d0*am_sig_irot_m1
     593            0 :                   delm1_irot = s% i_rot(k-1)% val - irot
     594              : 
     595              :                else
     596              : 
     597            0 :                   dmbar = 0.5d0*s% dm(k)
     598            0 :                   c_omega_m1 = 0
     599            0 :                   delm1_omega = 0
     600            0 :                   c_irot_m1 = 0
     601            0 :                   d_c_irot_m1_domega_00 = 0
     602            0 :                   d_c_irot_m1_domega_m1 = 0
     603            0 :                   delm1_irot = 0
     604              : 
     605              :                end if
     606              : 
     607            0 :                if (k == 1) then
     608            0 :                   d2omega = -c_omega_00*del00_omega
     609            0 :                   d2irot = -c_irot_00*del00_irot
     610            0 :                else if (k == nz) then
     611            0 :                   d2omega = c_omega_m1*delm1_omega
     612            0 :                   d2irot = c_irot_m1*delm1_irot
     613              :                else
     614            0 :                   d2omega = c_omega_m1*delm1_omega - c_omega_00*del00_omega
     615            0 :                   d2irot = c_irot_m1*delm1_irot - c_irot_00*del00_irot
     616              :                end if
     617            0 :                d_d2omega_domega_00 = -(c_omega_m1 + c_omega_00)
     618              :                d_d2irot_domega_00 = &
     619            0 :                   d_c_irot_m1_domega_00*delm1_irot - d_c_irot_00_domega_00*del00_irot
     620              : 
     621              :                ! X_1 = X_0 + dX
     622              :                ! X_0 is omega at start of substep
     623              :                ! X_1 is candidate for omega at end of substep
     624              : 
     625              :                ! residual = dX - dt*(((d2omega+d2irot)/dmbar + extra_jdot)/irot + extra_omegadot)
     626              :                ! J = d(residual)/d(omega)
     627              :                ! del is linear estimate of change to dX to make residual = 0
     628              :                ! solve J*del = -residual == rhs
     629              : 
     630              :                rhs(k) = -dX(k) + &
     631              :                   dt*(((d2omega + d2irot)/dmbar + &
     632            0 :                         s% extra_jdot(k))/irot + s% extra_omegadot(k))
     633              : 
     634            0 :                f = dt/(dmbar*irot)
     635            0 :                d(k) = 1d0 - (d_d2omega_domega_00 + d_d2irot_domega_00)*f
     636              : 
     637            0 :                if (k < nz) then
     638            0 :                   d_d2omega_domega_p1 = c_omega_00
     639            0 :                   d_d2irot_domega_p1 = -d_c_irot_00_domega_p1*del00_irot
     640            0 :                   du(k) = -(d_d2omega_domega_p1 + d_d2irot_domega_p1)*f
     641              :                end if
     642              : 
     643            0 :                if (k > 1) then
     644            0 :                   d_d2omega_domega_m1 = c_omega_m1
     645            0 :                   d_d2irot_domega_m1 = d_c_irot_m1_domega_m1*delm1_irot
     646            0 :                   dl(k-1) = -(d_d2omega_domega_m1 + d_d2irot_domega_m1)*f
     647              :                end if
     648              : 
     649            0 :                if (s% use_other_torque_implicit) then
     650              :                   d(k) = d(k) - &
     651              :                      dt*(s% d_extra_jdot_domega_00(k)/irot + &
     652            0 :                            s% d_extra_omegadot_domega_00(k))
     653            0 :                   if (k < nz) &
     654              :                      du(k) = du(k) - &
     655              :                         dt*(s% d_extra_jdot_domega_p1(k)/irot + &
     656            0 :                               s% d_extra_omegadot_domega_p1(k))
     657            0 :                   if (k > 1) &
     658              :                      dl(k-1) = dl(k-1) - &
     659              :                         dt*(s% d_extra_jdot_domega_m1(k)/irot + &
     660            0 :                               s% d_extra_omegadot_domega_m1(k))
     661              :                end if
     662              : 
     663              :             end do
     664              : 
     665            0 :          end subroutine create_matrix_and_rhs
     666              : 
     667              :       end function do_solve_omega_mix
     668              : 
     669              :       end module solve_omega_mix
        

Generated by: LCOV version 2.0-1