Skip to content

Commit 9a1e011

Browse files
committed
updates for bounds
fix var declaration add to unit test add verbose prints
1 parent 66bee8f commit 9a1e011

File tree

2 files changed

+68
-21
lines changed

2 files changed

+68
-21
lines changed

src/nlesolver_module.F90

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -280,27 +280,14 @@ subroutine set_status(me,istat,string,i,r)
280280
integer,intent(in),optional :: i !! an integer value to append
281281
real(wp),intent(in),optional :: r !! a real value to append
282282

283-
character(len=256) :: numstr !! for number fo string conversion
284283
character(len=:),allocatable :: message !! the full message to log
285284
integer :: iostat !! write `iostat` code
286285

287286
message = trim(string)
288-
if (present(i)) then
289-
numstr = ''
290-
write(numstr,fmt=*,iostat=iostat) i
291-
if (iostat/=0) numstr = '****'
292-
message = message//' '//trim(adjustl(numstr))
293-
end if
294-
if (present(r)) then
295-
numstr = ''
296-
write(numstr,fmt=*,iostat=iostat) r
297-
if (iostat/=0) numstr = '****'
298-
message = message//' '//trim(adjustl(numstr))
299-
end if
287+
if (present(i)) message = message//' '//int2str(i)
288+
if (present(r)) message = message//' '//real2str(r)
300289

301-
if (me%verbose) then
302-
write(me%iunit,'(A)',iostat=iostat) message
303-
end if
290+
if (me%verbose) write(me%iunit,'(A)',iostat=iostat) message
304291

305292
! store in the class:
306293
me%istat = istat
@@ -309,6 +296,42 @@ subroutine set_status(me,istat,string,i,r)
309296
end subroutine set_status
310297
!*****************************************************************************************
311298

299+
!*****************************************************************************************
300+
!>
301+
! Convert an integer to a string. Works for up to 256 digits.
302+
303+
function int2str(i) result(s)
304+
integer, intent(in) :: i !! integer to convert
305+
character(len=:),allocatable :: s !! string result
306+
character(len=256) :: tmp !! temp string
307+
integer :: iostat !! write `iostat` code
308+
write(tmp,fmt=*,iostat=iostat) i
309+
if (iostat/=0) then
310+
s = '****'
311+
else
312+
s = trim(adjustl(tmp))
313+
end if
314+
end function int2str
315+
!*****************************************************************************************
316+
317+
!*****************************************************************************************
318+
!>
319+
! Convert a real to a string. Works for up to 256 digits.
320+
321+
function real2str(r) result(s)
322+
real(wp), intent(in) :: r !! real to convert
323+
character(len=:),allocatable :: s !! string result
324+
character(len=256) :: tmp !! temp string
325+
integer :: iostat !! write `iostat` code
326+
write(tmp,fmt=*,iostat=iostat) r
327+
if (iostat/=0) then
328+
s = '****'
329+
else
330+
s = trim(adjustl(tmp))
331+
end if
332+
end function real2str
333+
!*****************************************************************************************
334+
312335
!*****************************************************************************************
313336
!>
314337
! Return the status code and message from the [[nlesolver_type]] class.
@@ -330,6 +353,7 @@ end subroutine set_status
330353
! * -13 -- Error: backtracking linesearch tau must be in range (0, 1)
331354
! * -14 -- Error: must specify grad_sparse, irow, and icol for sparsity_mode > 1
332355
! * -15 -- Error: irow and icol must be the same length
356+
! * -16 -- Error: xlow > xupp
333357
! * -999 -- Error: class has not been initialized
334358
! * 0 -- Class successfully initialized in [[nlesolver_type:initialize]]
335359
! * 1 -- Required accuracy achieved
@@ -448,14 +472,16 @@ subroutine initialize_nlesolver_variables(me,&
448472
!! At most `min(m,n)` vectors will be allocated.
449473
procedure(sparse_solver_func),optional :: custom_solver_sparse !! for `sparsity_mode=5`, this is the
450474
!! user-provided linear solver.
451-
logical,intent(in),optional :: bounds_mode !! how to handle the `x` variable bounds:
475+
integer,intent(in),optional :: bounds_mode !! how to handle the `x` variable bounds:
452476
!!
453477
!! * 0 = ignore bounds
454478
!! * 1 = use bounds (if specified) by adjusting the `x` vector
455479
!! at each step so that each individual `x` component is within
456480
!! the bounds
457-
real(wp),dimension(n),intent(in),optional :: xlow !! lower bounds for `x` (size is `n`). only used if `bounds_mode>0`.
458-
real(wp),dimension(n),intent(in),optional :: xupp !! upper bounds for `x` (size is `n`). only used if `bounds_mode>0`.
481+
real(wp),dimension(n),intent(in),optional :: xlow !! lower bounds for `x` (size is `n`). only used if `bounds_mode>0` and
482+
!! both `xlow` and `xupp` are specified.
483+
real(wp),dimension(n),intent(in),optional :: xupp !! upper bounds for `x` (size is `n`). only used if `bounds_mode>0` and
484+
!! both `xlow` and `xupp` are specified.
459485

460486
logical :: status_ok !! true if there were no errors
461487

@@ -473,6 +499,11 @@ subroutine initialize_nlesolver_variables(me,&
473499
!optional:
474500

475501
if (present(bounds_mode) .and. present(xlow) .and. present(xupp)) then
502+
if (any(xlow>xupp)) then ! check for consistency
503+
status_ok = .false.
504+
call me%set_status(istat = -16, string = 'Error: xlow > xupp')
505+
return
506+
end if
476507
me%bounds_mode = bounds_mode
477508
me%xupp = xupp
478509
me%xlow = xlow
@@ -962,7 +993,20 @@ subroutine adjust_x_for_bounds(me,x)
962993
class(nlesolver_type),intent(inout) :: me
963994
real(wp),dimension(me%n),intent(inout) :: x !! the `x` vector to adjust
964995

965-
if (me%bounds_mode==1) x = min(max(x,me%xlow),me%xupp)
996+
integer :: i !! counter
997+
998+
if (me%bounds_mode==1) then
999+
! x = min(max(x,me%xlow),me%xupp)
1000+
do i = 1, me%n
1001+
if (x(i)<me%xlow(i)) then
1002+
x(i) = me%xlow(i)
1003+
if (me%verbose) write(me%iunit, '(A)') 'x('//int2str(i)//') < xlow(i) : adjusting to lower bound'
1004+
else if (x(i)>me%xupp(i)) then
1005+
x(i) = me%xupp(i)
1006+
if (me%verbose) write(me%iunit, '(A)') 'x('//int2str(i)//') > xupp(i) : adjusting to upper bound'
1007+
end if
1008+
end do
1009+
end if
9661010

9671011
end subroutine adjust_x_for_bounds
9681012
!*****************************************************************************************

test/nlesolver_test_1.f90

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@ program nlesolver_test_1
9898
export_iteration = export,&
9999
n_intervals = n_intervals, &
100100
fmin_tol = fmin_tol, &
101-
verbose = verbose)
101+
verbose = verbose, &
102+
bounds_mode = 1, &
103+
xlow = [0.0_wp, -5.0_wp], &
104+
xupp = [1.0_wp, 0.0_wp])
102105
call solver%status(istat, message)
103106
write(*,'(I3,1X,A)') istat, message
104107
if (istat /= 0) error stop

0 commit comments

Comments
 (0)