Changeset 4065 for trunk/LMDZ.COMMON/libf/evolution/orbit.F90
- Timestamp:
- Feb 12, 2026, 9:09:12 AM (2 weeks ago)
- File:
-
- 1 edited
-
trunk/LMDZ.COMMON/libf/evolution/orbit.F90 (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LMDZ.COMMON/libf/evolution/orbit.F90
r3991 r4065 13 13 !----------------------------------------------------------------------- 14 14 15 ! DECLARATION 16 ! ----------- 17 implicit none 18 19 ! MODULE VARIABLES 20 ! ---------------- 21 real, dimension(:), allocatable :: year_lask ! year before present from Laskar et al. 22 real, dimension(:), allocatable :: obl_lask ! obliquity [deg] 23 real, dimension(:), allocatable :: ecc_lask ! eccentricity 24 real, dimension(:), allocatable :: lsp_lask ! ls perihelie [deg] 25 integer :: iyear_lask ! Index of the line in the file year_obl_lask.asc corresponding to the closest lower year to the current year 15 ! DEPENDENCIES 16 ! ------------ 17 use numerics, only: dp, di, k4, largest_nb, minieps 18 19 ! DECLARATION 20 ! ----------- 21 implicit none 22 23 ! PARAMETERS 24 ! ---------- 25 ! File-related: 26 character(15), parameter :: orbitfile_name = 'obl_ecc_lsp.asc' 27 integer(di), protected :: iyear_lask! Index of the line in the file year_obl_lask.asc corresponding to the closest lower year to the current year 28 real(dp), dimension(:), allocatable, protected :: year_lask ! Current_year before present from Laskar et al. 29 real(dp), dimension(:), allocatable, protected :: obl_lask ! Obliquity in Laskar's data [deg] 30 real(dp), dimension(:), allocatable, protected :: ecc_lask ! Eccentricity in Laskar's data 31 real(dp), dimension(:), allocatable, protected :: lsp_lask ! Ls perihelie in Laskar's data [deg] 32 ! Planet-related: 33 real(dp), protected :: obliquity ! Planet obliquity [deg] 34 real(dp), protected :: eccentricity ! Orbit eccentricity 35 real(dp), protected :: ls_peri ! Solar longitude of the perihelion [deg] 36 real(dp), protected :: perihelion ! Perihelion [Mkm] 37 real(dp), protected :: semimaj_axis ! Semi-major axis [Mkm] 38 real(dp), protected :: aphelion ! Aphelion [Mkm] 39 real(dp), protected :: date_peri ! Date of perihelion [sol] 40 real(dp), protected :: sol_len_s ! Length of a sol [s] 41 real(dp), protected :: yr_len_sol ! Length of a year [sol] 42 ! Evolution-related: 43 logical(k4), protected :: evol_orbit ! Flag to follow the orbital parameters 44 logical(k4), protected :: evol_obl ! Flag the PEM to follow obliquity 45 logical(k4), protected :: evol_ecc ! Flag the PEM to follow eccenticity 46 logical(k4), protected :: evol_lsp ! Flag the PEM to follow Ls perihelie 47 real(dp), protected :: max_change_obl ! Maximum admissible change for obliquity 48 real(dp), protected :: max_change_ecc ! Maximum admissible change for eccentricity 49 real(dp), protected :: max_change_lsp ! Maximum admissible change for Lsp 26 50 27 51 contains … … 29 53 30 54 !======================================================================= 31 SUBROUTINE read_orbitpm(Year) 32 !----------------------------------------------------------------------- 33 ! NAME 34 ! read_orbitpm 35 ! 36 ! DESCRIPTION 37 ! Read Laskar orbital file and prepare arrays; locate index for 38 ! closest lower year relative to current simulation year. 55 SUBROUTINE set_orbit_config(evol_orbit_in,evol_obl_in,evol_ecc_in,evol_lsp_in,max_change_obl_in,max_change_ecc_in,max_change_lsp_in) 56 !----------------------------------------------------------------------- 57 ! NAME 58 ! set_orbit_config 59 ! 60 ! DESCRIPTION 61 ! Setter for 'orbit' configuration parameters. 62 ! 63 ! AUTHORS & DATE 64 ! JB Clement, 02/2026 65 ! 66 ! NOTES 67 ! 68 !----------------------------------------------------------------------- 69 70 ! DEPENDENCIES 71 ! ------------ 72 use utility, only: real2str, bool2str 73 use display, only: print_msg 74 75 ! DECLARATION 76 ! ----------- 77 implicit none 78 79 ! ARGUMENTS 80 ! --------- 81 logical(k4), intent(in) :: evol_orbit_in, evol_obl_in, evol_ecc_in, evol_lsp_in 82 real(dp), intent(in) :: max_change_obl_in, max_change_ecc_in, max_change_lsp_in 83 84 ! CODE 85 ! ---- 86 evol_orbit = evol_orbit_in 87 evol_obl = evol_obl_in 88 evol_ecc = evol_ecc_in 89 evol_lsp = evol_lsp_in 90 max_change_obl = max_change_obl_in 91 max_change_ecc = max_change_ecc_in 92 max_change_lsp = max_change_lsp_in 93 call print_msg('evol_orbit = '//bool2str(evol_orbit)) 94 call print_msg('evol_obl = '//bool2str(evol_obl)) 95 call print_msg('evol_ecc = '//bool2str(evol_ecc)) 96 call print_msg('evol_lsp = '//bool2str(evol_lsp)) 97 call print_msg('max_change_obl = '//real2str(max_change_obl)) 98 call print_msg('max_change_ecc = '//real2str(max_change_ecc)) 99 call print_msg('max_change_lsp = '//real2str(max_change_lsp)) 100 101 END SUBROUTINE set_orbit_config 102 !======================================================================= 103 104 !======================================================================= 105 SUBROUTINE init_orbit(obliquity_in,perihelion_in,aphelion_in,date_peri_in,yr_len_sol_in,sol_len_s_in) 106 !----------------------------------------------------------------------- 107 ! NAME 108 ! init_orbit 109 ! 110 ! DESCRIPTION 111 ! Initialize orbital characteristics of the planet. 112 ! 113 ! AUTHORS & DATE 114 ! JB Clement, 12/2025 115 ! 116 ! NOTES 117 ! Taken from 'iniorbit' in the Mars PCM. 118 !----------------------------------------------------------------------- 119 120 ! DEPENDENCIES 121 ! ------------ 122 use maths, only: pi 123 use display, only: print_msg 124 use utility, only: real2str 125 126 ! DECLARATION 127 ! ----------- 128 implicit none 129 130 ! ARGUMENTS 131 ! --------- 132 real(dp), intent(in) :: obliquity_in, perihelion_in, aphelion_in, date_peri_in, yr_len_sol_in, sol_len_s_in 133 134 ! LOCAL VARIABLES 135 ! --------------- 136 real(dp) :: zxref, zanom, zz, zx0, zdx 137 real(dp) :: lsp ! Solar longitude of the perihelion [rad] 138 integer(di) :: iter 139 140 ! CODE 141 ! ---- 142 ! Setters 143 obliquity = obliquity_in 144 perihelion = perihelion_in 145 aphelion = aphelion_in 146 date_peri = date_peri_in 147 sol_len_s = sol_len_s_in 148 yr_len_sol = yr_len_sol_in 149 150 ! Compute eccentricity and semi-major axis 151 eccentricity = (aphelion - perihelion)/(aphelion + perihelion) 152 semimaj_axis = 0.5_dp*(aphelion + perihelion) 153 154 ! Compute mean anomaly zanom 155 zz = (yr_len_sol - date_peri)/yr_len_sol 156 zanom = 2._dp*pi*(zz - nint(zz)) 157 zxref = abs(zanom) 158 159 ! Solve equation zx0 - e*sin(zx0) = zxref for eccentric anomaly zx0 using Newton method 160 zx0 = zxref + eccentricity*sin(zxref) 161 do iter = 1,100 162 zdx = -(zx0 - eccentricity*sin(zx0) - zxref)/(1._dp - eccentricity*cos(zx0)) 163 if (abs(zdx) <= 1.e-12_dp) exit 164 zx0 = zx0 + zdx 165 end do 166 167 zx0 = zx0 + zdx 168 if (zanom < 0.) zx0 = -zx0 169 170 ! Compute solar longitude of the perihelion 171 lsp = -2._dp*atan(sqrt((1._dp + eccentricity)/(1._dp - eccentricity))*tan(zx0/2._dp)) 172 lsp = modulo(lsp,2._dp*pi) 173 ls_peri = lsp*180._dp/pi ! Conversion in degree 174 175 call print_msg('Obliquity [deg] = '//real2str(obliquity)) 176 call print_msg('Eccentricity [-] = '//real2str(eccentricity)) 177 call print_msg('Ls of perihelion [deg] = '//real2str(ls_peri)) 178 call print_msg('Perihelion [Mkm] = '//real2str(perihelion)) 179 call print_msg('Aphelion [Mkm] = '//real2str(aphelion)) 180 call print_msg('Semi-major axis [Mkm] = '//real2str(semimaj_axis)) 181 call print_msg('Date of perihelion [sol] = '//real2str(date_peri)) 182 call print_msg('Length of a sol [s] = '//real2str(sol_len_s)) 183 call print_msg('Length of a year [sol] = '//real2str(yr_len_sol)) 184 185 END SUBROUTINE init_orbit 186 !======================================================================= 187 188 !======================================================================= 189 SUBROUTINE lsp2datep(lsp,datep) 190 !----------------------------------------------------------------------- 191 ! NAME 192 ! lsp2datep 193 ! 194 ! DESCRIPTION 195 ! Initialize orbital data of the planet. 196 ! 197 ! AUTHORS & DATE 198 ! JB Clement, 12/2025 199 ! 200 ! NOTES 201 ! Taken from 'lsp2solp' in the Mars PCM. 202 !----------------------------------------------------------------------- 203 204 ! DEPENDENCIES 205 ! ------------ 206 use maths, only: pi 207 208 ! DECLARATION 209 ! ----------- 210 implicit none 211 212 ! ARGUMENTS 213 ! --------- 214 real(dp), intent(in) :: lsp ! Ls at perihelion [deg] 215 real(dp), intent(out) :: datep ! Date at perihelion [sol] 216 217 ! LOCAL VARIABLES 218 ! --------------- 219 real(dp) :: zx0 ! Eccentric anomaly at Ls = 0 220 221 ! CODE 222 ! ---- 223 ! Compute orbit geometrical parameters 224 zx0 = -2._dp*atan(tan(0.5_dp*lsp*pi/180._dp)*sqrt((1._dp - eccentricity)/(1._dp + eccentricity))) 225 if (zx0 <= 0._dp) zx0 = zx0 + 2._dp*pi 226 227 ! Compute sol at perihelion 228 datep = yr_len_sol*(1._dp - (zx0 - eccentricity*sin(zx0))/(2._dp*pi)) 229 230 END SUBROUTINE lsp2datep 231 !======================================================================= 232 233 !======================================================================= 234 SUBROUTINE ini_orbit() 235 !----------------------------------------------------------------------- 236 ! NAME 237 ! ini_orbit 238 ! 239 ! DESCRIPTION 240 ! Initialize the parameters of module 'orbit'. 39 241 ! 40 242 ! AUTHORS & DATE … … 43 245 ! 44 246 ! NOTES 45 ! Converts kilo Earth years to Martian years using 'convert_years'.247 ! 46 248 !----------------------------------------------------------------------- 47 249 48 250 ! DEPENDENCIES 49 251 ! ------------ 50 use evolution, only: convert_years 252 use stoppage, only: stop_clean 253 254 ! DECLARATION 255 ! ----------- 256 implicit none 257 258 ! LOCAL VARIABLES 259 ! --------------- 260 integer(di) :: n ! Number of lines in the file 261 integer(di) :: ierr, funit 262 logical(k4) :: here 263 264 ! CODE 265 ! ---- 266 inquire(file = orbitfile_name,exist = here) 267 if (.not. here) call stop_clean(__FILE__,__LINE__,'cannot find required file "'//orbitfile_name//'"!',1) 268 269 ! Get the number of lines for Laskar's orbital file 270 open(newunit = funit,file = orbitfile_name,status = 'old',action = 'read',iostat = ierr) 271 if (ierr /= 0) call stop_clean(__FILE__,__LINE__,'error opening file "'//orbitfile_name//'"!',ierr) 272 n = 0 273 do 274 read(funit,*,iostat = ierr) 275 if (ierr /= 0) exit 276 n = n + 1 277 end do 278 close(funit) 279 280 ! Allocation of module arrays 281 if (.not. allocated(year_lask)) allocate(year_lask(n)) 282 if (.not. allocated(obl_lask)) allocate(obl_lask(n)) 283 if (.not. allocated(ecc_lask)) allocate(ecc_lask(n)) 284 if (.not. allocated(lsp_lask)) allocate(lsp_lask(n)) 285 286 END SUBROUTINE ini_orbit 287 !======================================================================= 288 289 !======================================================================= 290 SUBROUTINE end_orbit 291 !----------------------------------------------------------------------- 292 ! NAME 293 ! end_orbit 294 ! 295 ! DESCRIPTION 296 ! Deallocate orbital data arrays. 297 ! 298 ! AUTHORS & DATE 299 ! R. Vandemeulebrouck 300 ! JB Clement, 2023-2025 301 ! 302 ! NOTES 303 ! 304 !----------------------------------------------------------------------- 305 306 ! DECLARATION 307 ! ----------- 308 implicit none 309 310 ! CODE 311 ! ---- 312 if (allocated(year_lask)) deallocate(year_lask) 313 if (allocated(obl_lask)) deallocate(obl_lask) 314 if (allocated(ecc_lask)) deallocate(ecc_lask) 315 if (allocated(lsp_lask)) deallocate(lsp_lask) 316 317 END SUBROUTINE end_orbit 318 !======================================================================= 319 320 !======================================================================= 321 SUBROUTINE read_orbitpm(n_yr_sim) 322 !----------------------------------------------------------------------- 323 ! NAME 324 ! read_orbitpm 325 ! 326 ! DESCRIPTION 327 ! Read Laskar's orbital file and locate index for 328 ! closest lower year relative to current simulation year. 329 ! 330 ! AUTHORS & DATE 331 ! JB Clement, 2023-2025 332 ! 333 ! NOTES 334 ! 335 !----------------------------------------------------------------------- 336 337 ! DEPENDENCIES 338 ! ------------ 339 use evolution, only: pem_ini_date, r_plnt2earth_yr 340 use stoppage, only: stop_clean 341 use display, only: print_msg 342 use utility, only: real2str, int2str 51 343 52 344 ! DECLARATION … … 56 348 ! ARGUMENTS 57 349 ! --------- 58 real , intent(in) :: Year ! Martian year of the simulation350 real(dp), intent(in) :: n_yr_sim 59 351 60 352 ! LOCAL VARIABLES 61 353 ! --------------- 62 integer :: n ! Number of lines in Laskar files 63 integer :: ierr, i 64 65 ! CODE 66 ! ---- 67 n = 0 68 open(1,file = 'obl_ecc_lsp.asc',status = 'old',action = 'read') 69 do 70 read(1,*,iostat = ierr) 71 if (ierr /= 0) exit 72 n = n + 1 73 enddo 74 close(1) 75 allocate(year_lask(n),obl_lask(n),ecc_lask(n),lsp_lask(n)) 76 77 iyear_lask = 0 78 do i = 1,size(year_lask,1) 79 read(1,*) year_lask(i), obl_lask(i), ecc_lask(i), lsp_lask(i) 80 year_lask(i) = year_lask(i)*1000./convert_years ! Conversion from Laskar's kilo Earth years to PEM Martian years 81 if (year_lask(i) > Year) iyear_lask = i + 1 82 enddo 83 close(1) 84 if (iyear_lask == 0 .or. iyear_lask == size(year_lask,1) + 1) then 85 error stop 'The current year could not be found in the file "obl_ecc_lsp.asc".' 354 integer(di) :: ierr, funit, i, n 355 logical(k4) :: here 356 real(dp) :: current_year 357 358 ! CODE 359 ! ---- 360 call print_msg('> Reading "'//orbitfile_name//'"') 361 ! Compute the current year 362 current_year = pem_ini_date + n_yr_sim 363 call print_msg('Current year = '//real2str(current_year)) 364 365 inquire(file = orbitfile_name,exist = here) 366 if (.not. here) call stop_clean(__FILE__,__LINE__,'cannot find required file "'//orbitfile_name//'"!',1) 367 368 ! Read the Laskars's orbital file 369 open(newunit = funit,file = orbitfile_name,status = 'old',action = 'read',iostat = ierr) 370 if (ierr /= 0) call stop_clean(__FILE__,__LINE__,'error opening file "'//orbitfile_name//'"!',ierr) 371 n = size(year_lask,1) ! Number of lines in the file 372 iyear_lask = 0 ! Line number for closest lower year relative to current simulation year 373 do i = 1,n 374 read(funit,*) year_lask(i), obl_lask(i), ecc_lask(i), lsp_lask(i) 375 year_lask(i) = year_lask(i)*1000._dp/r_plnt2earth_yr ! Conversion from Laskar's kilo Earth years to planetary years 376 if (year_lask(i) > current_year) iyear_lask = i + 1 377 end do 378 close(funit) 379 if (iyear_lask == 0 .or. iyear_lask == n + 1) then 380 call stop_clean(__FILE__,__LINE__,'the current year could not be found in the file "'//orbitfile_name//'".',1) 86 381 else 87 write(*,*) 'The current year in the "obl_ecc_lsp.asc" file is at line:', iyear_lask88 end if382 call print_msg('The current year in "'//orbitfile_name//'" is at line '//int2str(iyear_lask)//'.') 383 end if 89 384 90 385 END SUBROUTINE read_orbitpm … … 92 387 93 388 !======================================================================= 94 SUBROUTINE end_orbit 95 !----------------------------------------------------------------------- 96 ! NAME 97 ! end_orbit 98 ! 99 ! DESCRIPTION 100 ! Deallocate orbital data arrays. 389 SUBROUTINE compute_maxyr_orbit(n_yr_sim,nmax_yr_runorb) 390 !----------------------------------------------------------------------- 391 ! NAME 392 ! compute_maxyr_orbit 393 ! 394 ! DESCRIPTION 395 ! Determine maximum number of years before orbital params change 396 ! beyond admissible thresholds. 101 397 ! 102 398 ! AUTHORS & DATE … … 105 401 ! 106 402 ! NOTES 107 ! 108 !----------------------------------------------------------------------- 109 110 ! DECLARATION 111 ! ----------- 112 implicit none 113 114 ! CODE 115 ! ---- 116 if (allocated(year_lask)) deallocate(year_lask) 117 if (allocated(obl_lask)) deallocate(obl_lask) 118 if (allocated(ecc_lask)) deallocate(ecc_lask) 119 if (allocated(lsp_lask)) deallocate(lsp_lask) 120 121 END SUBROUTINE end_orbit 122 !======================================================================= 123 124 !======================================================================= 125 SUBROUTINE orbit_param_criterion(i_myear,nyears_maxorb) 126 !----------------------------------------------------------------------- 127 ! NAME 128 ! orbit_param_criterion 129 ! 130 ! DESCRIPTION 131 ! Determine maximum PEM iterations before orbital params change 132 ! beyond admissible thresholds. 133 ! 134 ! AUTHORS & DATE 135 ! R. Vandemeulebrouck 136 ! JB Clement, 2023-2025 137 ! 138 ! NOTES 139 ! 140 !----------------------------------------------------------------------- 141 #ifdef CPP_IOIPSL 142 use IOIPSL, only: getin 143 #else 144 ! if not using IOIPSL, we still need to use (a local version of) getin 145 use ioipsl_getincom, only: getin 146 #endif 147 use planete_h, only: e_elips, obliquit, lsperi 148 use phys_constants, only: pi 149 use evolution, only: year_bp_ini, var_obl, var_ecc, var_lsp, convert_years 403 ! Handles Lsp modulo crossings. 404 !----------------------------------------------------------------------- 405 406 ! DEPENDENCIES 407 ! ------------ 408 use maths, only: pi 409 use evolution, only: pem_ini_date 410 use display, only: print_msg 411 use utility, only: real2str 150 412 151 413 ! DECLARATION … … 155 417 ! ARGUMENTS 156 418 ! --------- 157 real , intent(in) :: i_myear ! Martianyear of the simulation158 real , intent(out) :: nyears_maxorb ! Maximum number of iteration of the PEM before orb changestoo much419 real(dp), intent(in) :: n_yr_sim ! Current year of the simulation 420 real(dp), intent(out) :: nmax_yr_runorb ! Maximum number of years of the PEM before orbital parameters change too much 159 421 160 422 ! LOCAL VARIABLES 161 423 ! --------------- 162 real :: Year ! Year of the simulation 163 real :: Lsp ! Ls perihelion 164 real :: max_change_obl, max_change_ecc, max_change_lsp ! Maximum admissible change 165 real :: max_obl, max_ecc, max_lsp ! Maximum value of orbit param given the admissible change 166 real :: min_obl, min_ecc, min_lsp ! Minimum value of orbit param given the admissible change 167 real :: nyears_maxobl, nyears_maxecc, nyears_maxlsp ! Maximum year iteration before reaching an inadmissible value of orbit param 168 real :: xa, xb, ya, yb ! Variables for interpolation 169 logical :: found_obl, found_ecc, found_lsp ! Flag variables for orbital parameters 170 real :: lsp_corr ! Lsp corrected if the "modulo is crossed" 171 real :: delta ! Intermediate variable 172 real, dimension(:), allocatable :: lsplask_unwrap ! Unwrapped sequence of Lsp from Laskar's file 173 integer :: i 174 175 ! CODE 176 ! ---- 177 ! ********************************************************************** 178 ! 0. Initializations 179 ! ********************************************************************** 180 Year = year_bp_ini + i_myear ! We compute the current year 181 Lsp = lsperi*180./pi ! We convert in degree 182 183 call read_orbitpm(Year) ! Allocation of variables 184 185 write(*,*) 'orbit_param_criterion, Current year =', Year 186 write(*,*) 'orbit_param_criterion, Current obl. =', obliquit 187 write(*,*) 'orbit_param_criterion, Current ecc. =', e_elips 188 write(*,*) 'orbit_param_criterion, Current Lsp =', Lsp 424 real(dp) :: current_year 425 real(dp) :: max_obl, max_ecc, max_lsp 426 real(dp) :: min_obl, min_ecc, min_lsp 427 real(dp) :: nmax_yr_runobl, nmax_yr_runecc, nmax_yr_runlsp ! Maximum year iteration before reaching an inadmissible value of orbit param 428 real(dp) :: xa, xb, ya, yb 429 logical(k4) :: found_obl, found_ecc, found_lsp 430 real(dp) :: lsp_corr ! Lsp corrected if the "modulo is crossed" 431 real(dp) :: delta 432 real(dp), dimension(:), allocatable :: lsplask_unwrap 433 integer(di) :: i 434 435 ! CODE 436 ! ---- 437 if (.not. evol_orbit) then 438 nmax_yr_runorb = largest_nb ! Default huge value 439 return 440 end if 441 call print_msg('> Computing the accepted maximum number of years due to orbital parameters') 442 current_year = pem_ini_date + n_yr_sim ! We compute the current year 189 443 190 444 ! Unwrap the Lsp changes in Laskar's file … … 193 447 do i = iyear_lask,2,-1 194 448 delta = lsp_lask(i - 1) - lsp_lask(i) 195 if (delta > 180. ) then196 lsp_corr = lsp_lask(i - 1) - 360. 197 else if (delta < -180. ) then198 lsp_corr = lsp_lask(i - 1) + 360. 449 if (delta > 180._dp) then 450 lsp_corr = lsp_lask(i - 1) - 360._dp 451 else if (delta < -180._dp) then 452 lsp_corr = lsp_lask(i - 1) + 360._dp 199 453 else 200 454 lsp_corr = lsp_lask(i - 1) 201 end if455 end if 202 456 lsplask_unwrap(i - 1) = lsplask_unwrap(i) + lsp_corr - lsp_lask(i) 203 end do457 end do 204 458 205 459 ! Correct the current Lsp according to the unwrapping 206 delta = Lsp - lsplask_unwrap(iyear_lask) 207 if (delta > 180.) then 208 Lsp = Lsp - 360. 209 else if (delta < -180.) then 210 Lsp = Lsp + 360. 211 endif 212 213 ! Constant max change case 214 max_change_obl = 1. 215 max_change_ecc = 5.e-3 216 max_change_lsp = 20. 217 218 call getin('max_change_obl',max_change_obl) 219 max_obl = obliquit + max_change_obl 220 min_obl = obliquit - max_change_obl 221 write(*,*) 'Maximum obliquity accepted =', max_obl 222 write(*,*) 'Minimum obliquity accepted =', min_obl 223 224 call getin('max_change_ecc',max_change_ecc) 225 max_ecc = min(e_elips + max_change_ecc,1. - 1.e-10) ! ecc < 1. 226 min_ecc = max(e_elips - max_change_ecc,0.) ! ecc >= 0. 227 write(*,*) 'Maximum eccentricity accepted =', max_ecc 228 write(*,*) 'Minimum eccentricity accepted =', min_ecc 229 230 call getin('max_change_lsp',max_change_lsp) 231 max_lsp = Lsp + max_change_lsp 232 min_lsp = Lsp - max_change_lsp 233 write(*,*) 'Maximum Lsp accepted =', max_lsp 234 write(*,*) 'Minimum Lsp accepted =', min_lsp 235 ! End Constant max change case 236 237 ! If we do not want some orb parameter to change, they should not be a stopping criterion, 238 ! So the number of iteration corresponding is set to maximum 239 nyears_maxobl = 1000000. 240 nyears_maxecc = 1000000. 241 nyears_maxlsp = 1000000. 242 243 ! The maximum reachable year is found by interpolation according to the maximum admissible change of orbital parameters 460 delta = ls_peri - lsplask_unwrap(iyear_lask) 461 if (delta > 180._dp) then 462 ls_peri = ls_peri - 360._dp 463 else if (delta < -180._dp) then 464 ls_peri = ls_peri + 360._dp 465 end if 466 467 ! Maximum change accepted for orbital parameters 468 max_obl = obliquity + max_change_obl 469 min_obl = obliquity - max_change_obl 470 call print_msg('Obl. (current|accepted min|accepted max): '//real2str(obliquity)//' | '//real2str(min_obl)//real2str(max_obl)) 471 472 max_ecc = min(eccentricity + max_change_ecc,1. - minieps) ! ecc < 1. 473 min_ecc = max(eccentricity - max_change_ecc,0._dp) ! ecc >= 0. 474 call print_msg('Ecc. (current|accepted min|accepted max): '//real2str(eccentricity)//' | '//real2str(min_ecc)//' | '//real2str(max_ecc)) 475 476 max_lsp = ls_peri + max_change_lsp 477 min_lsp = ls_peri - max_change_lsp 478 call print_msg('Lsp (current|accepted min|accepted max): '//real2str(ls_peri)//' | '//real2str(min_lsp)//' | '//real2str(max_lsp)) 479 480 ! Initialization 481 nmax_yr_runobl = largest_nb ! Default huge value 482 nmax_yr_runecc = largest_nb ! Default huge value 483 nmax_yr_runlsp =largest_nb ! Default huge value 244 484 found_obl = .false. 245 485 found_ecc = .false. 246 486 found_lsp = .false. 247 if (.not. var_obl) found_obl = .true. 248 if (.not. var_ecc) found_ecc = .true. 249 if (.not. var_lsp) found_lsp = .true. 250 487 if (.not. evol_obl) found_obl = .true. 488 if (.not. evol_ecc) found_ecc = .true. 489 if (.not. evol_lsp) found_lsp = .true. 490 491 ! The maximum reachable year is found by interpolation according to the maximum admissible change of orbital parameters 251 492 do i = iyear_lask,2,-1 252 493 xa = year_lask(i) … … 254 495 255 496 ! Obliquity 256 if ( var_obl .and. .not. found_obl) then497 if (evol_obl .and. .not. found_obl) then 257 498 ya = obl_lask(i) 258 499 yb = obl_lask(i - 1) 259 500 if (yb < min_obl) then ! The minimum accepted is overtaken 260 n years_maxobl = (min_obl - ya)*(xb - xa)/(yb - ya) + xa - Year501 nmax_yr_runobl = (min_obl - ya)*(xb - xa)/(yb - ya) + xa - current_year 261 502 found_obl = .true. 262 503 else if (max_obl < yb) then ! The maximum accepted is overtaken 263 n years_maxobl = (max_obl - ya)*(xb - xa)/(yb - ya) + xa - Year504 nmax_yr_runobl = (max_obl - ya)*(xb - xa)/(yb - ya) + xa - current_year 264 505 found_obl = .true. 265 end if266 end if506 end if 507 end if 267 508 268 509 ! Eccentricity 269 if ( var_ecc .and. .not. found_ecc) then510 if (evol_ecc .and. .not. found_ecc) then 270 511 ya = ecc_lask(i) 271 512 yb = ecc_lask(i - 1) 272 513 if (yb < min_ecc) then ! The minimum accepted is overtaken 273 n years_maxecc = (min_ecc - ya)*(xb - xa)/(yb - ya) + xa - Year514 nmax_yr_runecc = (min_ecc - ya)*(xb - xa)/(yb - ya) + xa - current_year 274 515 found_ecc = .true. 275 516 else if (max_ecc < yb) then ! The maximum accepted is overtaken 276 n years_maxecc = (max_ecc - ya)*(xb - xa)/(yb - ya) + xa - Year517 nmax_yr_runecc = (max_ecc - ya)*(xb - xa)/(yb - ya) + xa - current_year 277 518 found_ecc = .true. 278 end if279 end if519 end if 520 end if 280 521 281 522 ! Lsp 282 if ( var_lsp .and. .not. found_lsp) then523 if (evol_lsp .and. .not. found_lsp) then 283 524 ya = lsplask_unwrap(i) 284 525 yb = lsplask_unwrap(i - 1) 285 526 if (yb < min_lsp) then ! The minimum accepted is overtaken 286 n years_maxlsp = (min_lsp - ya)*(xb - xa)/(yb - ya) + xa - Year527 nmax_yr_runlsp = (min_lsp - ya)*(xb - xa)/(yb - ya) + xa - current_year 287 528 found_lsp = .true. 288 529 else if (max_lsp < yb) then ! The maximum accepted is overtaken 289 n years_maxlsp = (max_lsp - ya)*(xb - xa)/(yb - ya) + xa - Year530 nmax_yr_runlsp = (max_lsp - ya)*(xb - xa)/(yb - ya) + xa - current_year 290 531 found_lsp = .true. 291 end if292 end if532 end if 533 end if 293 534 294 535 if (found_obl .and. found_ecc .and. found_lsp) exit ! The loop is left as soon as everything is found 295 end do536 end do 296 537 297 538 deallocate(lsplask_unwrap) 298 539 299 if (.not. found_obl) write(*,*) 'The maximum reachable year for obl. could not be found in the file "obl_ecc_lsp.asc".'300 if (.not. found_ecc) write(*,*) 'The maximum reachable year for ecc. could not be found in the file "obl_ecc_lsp.asc".'301 if (.not. found_lsp) write(*,*) 'The maximum reachable year for Lsp could not be found in the file "obl_ecc_lsp.asc".'302 303 write(*,*) 'Max. number of years for the obl. parameter =', nyears_maxobl 304 write(*,*) 'Max. number of years for the ecc. parameter =', nyears_maxecc 305 write(*,*) 'Max. number of years for the Lsp parameter =', nyears_maxlsp 306 307 n years_maxorb = min(nyears_maxobl,nyears_maxecc,nyears_maxlsp)308 if (n years_maxorb < 1.) nyears_maxorb = 1. ! nyears_maxorb should be at least equal to 1309 write(*,*) 'So the max. number of years for the orbital criteria =', nyears_maxorb 310 311 END SUBROUTINE orbit_param_criterion 312 !======================================================================= 313 314 !======================================================================= 315 SUBROUTINE set_new_orbitpm(i_myear,i_myear_leg) 316 !----------------------------------------------------------------------- 317 ! NAME318 ! set_new_orbitpm319 ! 320 ! DESCRIPTION321 ! Recompute orbit parameters from Laskar values at a new year and322 ! update planetary constants; handles Lsp modulo crossings.540 if (.not. found_obl) call print_msg('The maximum reachable year for obl. could not be found in "'//orbitfile_name//'".') 541 if (.not. found_ecc) call print_msg('The maximum reachable year for ecc. could not be found in "'//orbitfile_name//'".') 542 if (.not. found_lsp) call print_msg('The maximum reachable year for Lsp could not be found in "'//orbitfile_name//'".') 543 544 call print_msg('Number of years accepted for obl. = '//real2str(nmax_yr_runobl)) 545 call print_msg('Number of years accepted for ecc. = '//real2str(nmax_yr_runecc)) 546 call print_msg('Number of years accepted for Lsp = '//real2str(nmax_yr_runlsp)) 547 548 nmax_yr_runorb = min(nmax_yr_runobl,nmax_yr_runecc,nmax_yr_runlsp) 549 if (nmax_yr_runorb < 1._dp) nmax_yr_runorb = 1._dp ! nmax_yr_runorb should be at least equal to 1 550 551 call print_msg('So the max. number of years for the orbital criterion = '//real2str(nmax_yr_runorb)) 552 553 END SUBROUTINE compute_maxyr_orbit 554 !======================================================================= 555 556 !======================================================================= 557 SUBROUTINE update_orbit(n_yr_sim,n_yr_run) 558 !----------------------------------------------------------------------- 559 ! NAME 560 ! update_orbit 561 ! 562 ! DESCRIPTION 563 ! Update orbital parameters from Laskar values at a new year. 323 564 ! 324 565 ! AUTHORS & DATE … … 330 571 !----------------------------------------------------------------------- 331 572 332 use evolution, only: year_bp_ini, var_obl, var_ecc, var_lsp 333 use phys_constants, only: pi 334 use planete_h, only: e_elips, obliquit, lsperi, periheli, aphelie, p_elips, peri_day, year_day 573 use evolution, only: pem_ini_date 574 use maths, only: pi 335 575 use call_dayperi_mod, only: call_dayperi 576 use stoppage, only: stop_clean 577 use display, only: print_msg 578 use utility, only: real2str 336 579 337 580 ! DECLARATION … … 341 584 ! ARGUMENTS 342 585 ! --------- 343 real , intent(in) :: i_myear ! Number of simulated Martianyears344 real , intent(in) :: i_myear_leg! Number of iterations of the PEM586 real(dp), intent(in) :: n_yr_sim ! Number of simulated years 587 real(dp), intent(in) :: n_yr_run ! Number of iterations of the PEM 345 588 346 589 ! LOCAL VARIABLES 347 590 ! --------------- 348 real :: Year ! Year of the simulation 349 real :: Lsp ! Ls perihelion 350 real :: halfaxe ! Million of km 351 integer :: i 352 real :: unitastr 353 real :: xa, xb, ya, yb ! Variables for interpolation 354 logical :: found_year ! Flag variable 355 356 ! CODE 357 ! ---- 358 ! ********************************************************************** 359 ! 0. Initializations 360 ! ********************************************************************** 361 Year = year_bp_ini + i_myear ! We compute the current year 362 Lsp = lsperi*180./pi ! We convert in degree 363 364 write(*,*) 'set_new_orbitpm, Old year =', Year - i_myear_leg 365 write(*,*) 'set_new_orbitpm, Old obl. =', obliquit 366 write(*,*) 'set_new_orbitpm, Old ecc. =', e_elips 367 write(*,*) 'set_new_orbitpm, Old Lsp =', Lsp 368 write(*,*) 'set_new_orbitpm, New year =', Year 591 integer(di) :: i 592 real(dp) :: current_year, old_year, obl_old, ecc_old, lsp_old 593 real(dp) :: xa, xb, ya, yb ! Variables for interpolation 594 logical(k4) :: found_year 595 596 ! CODE 597 ! ---- 598 call print_msg('> Updating the orbital parameters for the new year') 599 current_year = pem_ini_date + n_yr_sim ! We compute the current year 600 old_year = current_year - n_yr_run 601 obl_old = obliquity 602 ecc_old = eccentricity 603 lsp_old = ls_peri 369 604 370 605 found_year = .false. 371 if ( Year < 0.) then606 if (current_year < 0._dp) then 372 607 do i = iyear_lask,2,-1 373 608 xa = year_lask(i) 374 609 xb = year_lask(i - 1) 375 if (xa <= Year .and. Year < xb) then610 if (xa <= current_year .and. current_year < xb) then 376 611 ! Obliquity 377 if ( var_obl) then612 if (evol_obl) then 378 613 ya = obl_lask(i) 379 614 yb = obl_lask(i - 1) 380 obliquit = (Year - xa)*(yb - ya)/(xb - xa) + ya381 end if615 obliquity = (current_year - xa)*(yb - ya)/(xb - xa) + ya 616 end if 382 617 383 618 ! Eccentricity 384 if ( var_ecc) then619 if (evol_ecc) then 385 620 ya = ecc_lask(i) 386 621 yb = ecc_lask(i - 1) 387 e _elips = (Year - xa)*(yb - ya)/(xb - xa) + ya388 end if622 eccentricity = (current_year - xa)*(yb - ya)/(xb - xa) + ya 623 end if 389 624 390 625 ! Lsp 391 if ( var_lsp) then626 if (evol_lsp) then 392 627 ya = lsp_lask(i) 393 628 yb = lsp_lask(i - 1) 394 if (abs(yb - ya) > 300. ) then ! If modulo is "crossed" through the interval629 if (abs(yb - ya) > 300._dp) then ! If modulo is "crossed" through the interval 395 630 if (ya < yb) then ! Lsp should be decreasing 396 ya = ya + 360. 631 ya = ya + 360._dp 397 632 else ! Lsp should be increasing 398 yb = yb + 360. 399 end if400 end if401 Lsp = modulo((Year - xa)*(yb - ya)/(xb - xa) + ya,360.)402 end if633 yb = yb + 360._dp 634 end if 635 end if 636 ls_peri = modulo((current_year - xa)*(yb - ya)/(xb - xa) + ya,360._dp) 637 end if 403 638 found_year = .true. 404 639 exit ! The loop is left as soon as the right interval is found 405 end if406 end do407 else if ( Year >= 0 .and. Year < 100.) then ! For present orbital characteristics408 if ( var_obl) obliquit = 25.19409 if ( var_ecc) e_elips = 0.0934410 if ( var_lsp) Lsp = 251.640 end if 641 end do 642 else if (current_year >= 0._dp .and. current_year < 100._dp) then ! For present orbital characteristics 643 if (evol_obl) obliquity = obl_lask(1) 644 if (evol_ecc) eccentricity = ecc_lask(1) 645 if (evol_lsp) ls_peri = lsp_lask(1) 411 646 found_year = .true. 412 endif 413 414 if (.not. found_year) error stop 'The new year could not be found in the file "obl_ecc_lsp.asc".' 415 416 write(*,*) 'set_new_orbitpm, New obl. =', obliquit 417 write(*,*) 'set_new_orbitpm, New ecc. =', e_elips 418 write(*,*) 'set_new_orbitpm, New Lsp =', Lsp 419 420 halfaxe = 227.94 421 Lsp = Lsp*pi/180. 422 periheli = halfaxe*(1 - e_elips) 423 aphelie = halfaxe*(1 + e_elips) 424 unitastr = 149.597927 425 p_elips = 0.5*(periheli + aphelie)*(1. - e_elips*e_elips)/unitastr 426 427 call call_dayperi(Lsp,e_elips,peri_day,year_day) 428 429 call end_orbit() 430 431 END SUBROUTINE set_new_orbitpm 647 end if 648 649 if (.not. found_year) call stop_clean(__FILE__,__LINE__,'the new year could not be found in the file "'//orbitfile_name//'".',1) 650 651 call lsp2datep(ls_peri,date_peri) 652 perihelion = semimaj_axis*(1._dp - eccentricity) 653 aphelion = semimaj_axis*(1._dp + eccentricity) 654 655 call print_msg('Year (ini|now) = '//real2str(old_year)//' | '//real2str(current_year)) 656 call print_msg('Obl. (ini|now) = '//real2str(obl_old)//' | '//real2str(obliquity)) 657 call print_msg('Ecc. (ini|now) = '//real2str(ecc_old)//' | '//real2str(eccentricity)) 658 call print_msg('Lsp (ini|now) = '//real2str(lsp_old)//' | '//real2str(ls_peri)) 659 660 END SUBROUTINE update_orbit 432 661 !======================================================================= 433 662 434 663 END MODULE orbit 435
Note: See TracChangeset
for help on using the changeset viewer.
