11module art
22
3+ use iso_fortran_env, only: wp= >real64
4+
35implicit none
46
57contains
68
7- pure subroutine logmart (A ,b ,relax ,x0 ,sigma ,max_iter ,x )
9+ pure subroutine logmart (A ,b ,relax ,x0 ,sigma ,max_iter , x )
810! delta Chisquare.
911! stopped if Chisquare increases.
1012!
@@ -30,45 +32,38 @@ pure subroutine logmart(A,b,relax,x0,sigma,max_iter,x)
3032! x = [1,2,3]
3133! b = A*x
3234
33- use iso_fortran_env, only: wp= >real64
34-
35-
3635! --- parameter check
3736real (wp), intent (in ) :: A(:,:), b(:)
38- real (wp), optional , value :: relax
39- real (wp), intent (in ),optional :: x0(:), sigma(:)
37+ real (wp), optional , value :: relax, sigma
38+ real (wp), intent (in ),optional :: x0(:)
4039integer , optional , value :: max_iter
4140real (wp), intent (out ) :: x(:)
4241
43- real (wp), dimension (size (b)) :: xA, op_sigma, W , op_b, arg,xold,c
42+ real (wp), dimension (size (b)) :: W( size (b)), x_prev,c , op_b
4443integer :: i
45- logical :: done
4644real (wp) :: t,chi2,chiold
4745
48- op_b = b
4946
5047if (.not. size (A,1 ) == size (b)) error stop ' A and b row numbers must match'
48+ if (any (A< 0 )) error stop ' A must be non-negative'
49+ if (any (b< 0 )) error stop ' b must be non-negative'
50+ op_b = b
51+ ! --- make sure there are no 0's in b
52+ where (op_b <= 1e-8 ) op_b = 1e-8_wp
5153
5254! --- set defaults
53- if (.not. present (relax)) relax = 1._wp
55+ if (.not. present (relax)) relax = 1
5456if (.not. present (max_iter)) max_iter = 200
57+ if (.not. present (sigma)) sigma = 1
5558
5659if (.not. present (x0)) then
57- x = matmul (transpose (A), b) / sum (A)
58- xA = matmul (A, x)
59- x = x * maxval (b) / maxval (xA)
60+ x = matmul (transpose (A), op_b) / sum (A)
61+ x = x * maxval (op_b) / maxval (matmul (A, x))
6062else
6163 x = x0
6264endif
6365
64- if (.not. present (sigma)) then
65- op_sigma = 1._wp
66- else
67- op_sigma = sigma
68- endif
6966
70- ! --- make sure there are no 0's in b
71- where (op_b<= 1e-8 ) op_b = 1e-8_wp
7267
7368! W=sigma;
7469! W=linspace(1,0,size(A,1))';
@@ -77,27 +72,28 @@ pure subroutine logmart(A,b,relax,x0,sigma,max_iter,x)
7772W = W / sum (W)
7873
7974! --- iterate solution
80- i= 0
81- done= .false.
82- arg= ((matmul (A,x) - op_b) / op_sigma)** 2
83- chi2 = sqrt (sum (arg))
84-
85- do while (.not. done)
86- i = i+1
87- xold = x
88- xA = matmul (A,x)
89- t = minval (1 / xA)
90- C = relax* t* (1 - (xA/ b))
75+ chi2 = chi_squared(A, op_b, x, sigma)
76+
77+ do i = 1 , max_iter
78+ x_prev = x
79+ t = minval (1 / matmul (A,x))
80+ C = relax* t* (1 - (matmul (A,x)/ op_b))
9181 x = x / (1 - x* matmul (transpose (A),W* C))
9282! monitor solution
9383 chiold = chi2
94- chi2 = sqrt ( sum (((xA - b)/ op_sigma)** 2 ) )
95- ! dchi2=(chi2-chiold)
96- done = ((chi2> chiold) .and. (i> 2 )) .or. (i== max_iter) .or. (chi2< 0.7 )
84+ chi2 = chi_squared(A, op_b, x, sigma)
85+ if (chi2 > chiold .and. i > 2 ) exit
9786enddo
9887
99- x = xold
88+ x = x_prev
10089
10190end subroutine logmart
10291
92+
93+ pure real (wp) function chi_squared(A, b, x, sigma)
94+ real (wp), intent (in ) :: A(:,:), b(:), x(:), sigma
95+ chi_squared = sqrt (sum (((matmul (A,x) - b) / sigma)** 2 ))
96+
97+ end function chi_squared
98+
10399end module art
0 commit comments