Skip to content

Commit b0626bb

Browse files
committed
Purity refactor
Purity refactor: > all math-operators return real array, all math-operators are **pure** functions. Why: + completely avoid memory leaks; + boost performance; + parallel-ready. This change addresses the need by: + eliminate all polymorphic, non pure function results. Side effects: It could be not fully backward compatible, however it seems quite so.
1 parent 7068e29 commit b0626bb

File tree

2 files changed

+62
-75
lines changed

2 files changed

+62
-75
lines changed

src/lib/foodie_integrand_object.f90

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,10 @@ module foodie_integrand_object
1111

1212
type, abstract :: integrand_object
1313
!< Abstract type for building FOODIE ODE integrators.
14-
integer(I_P) :: n=0_I_P !< ODE *space* dimension.
1514
#ifdef CAF
1615
class(*), allocatable :: dummy_to_allow_extensions[:] !< Dummy member to allow concrete extensions with coarray members.
1716
#endif
1817
contains
19-
! public methods
20-
procedure, pass(self), public :: set_dimension !< Set ODE *space* dimension.
2118
! public deferred procedures that concrete integrand-field must implement
2219
procedure(time_derivative), pass(self), deferred, public :: t !< Time derivative, residuals.
2320
! operators
@@ -60,9 +57,9 @@ module foodie_integrand_object
6057
function time_derivative(self, t) result(dState_dt)
6158
!< Time derivative function of integrand class, i.e. the residuals function.
6259
import :: integrand_object, R_P
63-
class(integrand_object), intent(in) :: self !< Integrand field.
64-
real(R_P), optional, intent(in) :: t !< Time.
65-
real(R_P) :: dState_dt(1:self%n) !< Result of the time derivative function of integrand field.
60+
class(integrand_object), intent(in) :: self !< Integrand field.
61+
real(R_P), optional, intent(in) :: t !< Time.
62+
real(R_P), allocatable :: dState_dt(:) !< Result of the time derivative function of integrand field.
6663
endfunction time_derivative
6764

6865
! operators
@@ -77,41 +74,41 @@ function local_error_operator(lhs, rhs) result(error)
7774
pure function integrand_op_real(lhs, rhs) result(operator_result)
7875
!< Asymmetric type operator `integrand.op.real`.
7976
import :: integrand_object, R_P
80-
class(integrand_object), intent(in) :: lhs !< Left hand side.
81-
real(R_P), intent(in) :: rhs(1:lhs%n) !< Right hand side.
82-
real(R_P) :: operator_result(1:lhs%n) !< Operator result.
77+
class(integrand_object), intent(in) :: lhs !< Left hand side.
78+
real(R_P), intent(in) :: rhs(1:) !< Right hand side.
79+
real(R_P), allocatable :: operator_result(:) !< Operator result.
8380
endfunction integrand_op_real
8481

8582
pure function real_op_integrand(lhs, rhs) result(operator_result)
8683
!< Asymmetric type operator `real.op.integrand`.
8784
import :: integrand_object, R_P
88-
class(integrand_object), intent(in) :: rhs !< Right hand side.
89-
real(R_P), intent(in) :: lhs(1:rhs%n) !< Left hand side.
90-
real(R_P) :: operator_result(1:rhs%n) !< Operator result.
85+
class(integrand_object), intent(in) :: rhs !< Right hand side.
86+
real(R_P), intent(in) :: lhs(1:) !< Left hand side.
87+
real(R_P), allocatable :: operator_result(:) !< Operator result.
9188
endfunction real_op_integrand
9289

9390
pure function integrand_op_real_scalar(lhs, rhs) result(operator_result)
9491
!< Asymmetric type operator `integrand.op.real`.
9592
import :: integrand_object, R_P
96-
class(integrand_object), intent(in) :: lhs !< Left hand side.
97-
real(R_P), intent(in) :: rhs !< Right hand side.
98-
real(R_P) :: operator_result(1:lhs%n) !< Operator result.
93+
class(integrand_object), intent(in) :: lhs !< Left hand side.
94+
real(R_P), intent(in) :: rhs !< Right hand side.
95+
real(R_P), allocatable :: operator_result(:) !< Operator result.
9996
endfunction integrand_op_real_scalar
10097

10198
pure function real_scalar_op_integrand(lhs, rhs) result(operator_result)
10299
!< Asymmetric type operator `real.op.integrand`.
103100
import :: integrand_object, R_P
104-
real(R_P), intent(in) :: lhs !< Left hand side.
105-
class(integrand_object), intent(in) :: rhs !< Right hand side.
106-
real(R_P) :: operator_result(1:rhs%n) !< Operator result.
101+
real(R_P), intent(in) :: lhs !< Left hand side.
102+
class(integrand_object), intent(in) :: rhs !< Right hand side.
103+
real(R_P), allocatable :: operator_result(:) !< Operator result.
107104
endfunction real_scalar_op_integrand
108105

109106
pure function symmetric_operator(lhs, rhs) result(operator_result)
110107
!< Symmetric type operator integrand.op.integrand.
111108
import :: integrand_object, R_P
112-
class(integrand_object), intent(in) :: lhs !< Left hand side.
113-
class(integrand_object), intent(in) :: rhs !< Right hand side.
114-
real(R_P) :: operator_result(1:lhs%n) !< Operator result.
109+
class(integrand_object), intent(in) :: lhs !< Left hand side.
110+
class(integrand_object), intent(in) :: rhs !< Right hand side.
111+
real(R_P), allocatable :: operator_result(:) !< Operator result.
115112
endfunction symmetric_operator
116113

117114
pure subroutine assignment_integrand(lhs, rhs)
@@ -124,17 +121,8 @@ pure subroutine assignment_integrand(lhs, rhs)
124121
pure subroutine assignment_real(lhs, rhs)
125122
!< Symmetric assignment integrand = integrand.
126123
import :: integrand_object, R_P
127-
class(integrand_object), intent(inout) :: lhs !< Left hand side.
128-
real(R_P), intent(in) :: rhs(1:lhs%n) !< Right hand side.
124+
class(integrand_object), intent(inout) :: lhs !< Left hand side.
125+
real(R_P), intent(in) :: rhs(1:) !< Right hand side.
129126
endsubroutine assignment_real
130127
endinterface
131-
132-
contains
133-
pure subroutine set_dimension(self, n)
134-
!< Set ODE *space* dimension.
135-
class(integrand_object), intent(inout) :: self !< Ingetrand.
136-
integer(I_P), intent(in) :: n !< ODE *space* dimension.
137-
138-
self%n = n
139-
endsubroutine set_dimension
140128
endmodule foodie_integrand_object

src/tests/accuracy/oscillation/oscillation_oscillator.f90

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ pure subroutine init(self, initial_state, frequency)
7979
real(R_P), intent(in) :: initial_state(1:2) !< Initial state of the Oscillation field vector.
8080
real(R_P), intent(in) :: frequency !< Frequency of oscillation.
8181

82-
self%n = 2
8382
self%U = initial_state
8483
self%f = frequency
8584
endsubroutine init
@@ -95,12 +94,12 @@ pure function output(self) result(state)
9594
! deferred methods
9695
pure function doscillator_dt(self, t) result(dState_dt)
9796
!< Time derivative of oscillator field.
98-
class(oscillator), intent(in) :: self !< Oscillation field.
99-
real(R_P), intent(in), optional :: t !< Time.
100-
real(R_P) :: dState_dt(1:self%n) !< Oscillation field time derivative.
97+
class(oscillator), intent(in) :: self !< Oscillation field.
98+
real(R_P), intent(in), optional :: t !< Time.
99+
real(R_P), allocatable :: dState_dt(:) !< Oscillation field time derivative.
101100

102-
dState_dt(1) = -self%f * self%U(2)
103-
dState_dt(2) = self%f * self%U(1)
101+
dState_dt = [-self%f * self%U(2), &
102+
self%f * self%U(1)]
104103
endfunction doscillator_dt
105104

106105
pure function local_error(lhs, rhs) result(error)
@@ -117,7 +116,7 @@ pure function local_error(lhs, rhs) result(error)
117116
select type(rhs)
118117
class is(oscillator)
119118
error = 0._R_P
120-
do i=1, lhs%n
119+
do i=1, size(lhs%U, dim=1)
121120
error = error + (lhs%U(i) - rhs%U(i)) ** 2 / lhs%U(i) ** 2
122121
enddo
123122
error = sqrt(error)
@@ -127,9 +126,9 @@ pure function local_error(lhs, rhs) result(error)
127126
! +
128127
pure function integrand_add_integrand(lhs, rhs) result(opr)
129128
!< `+` operator.
130-
class(oscillator), intent(in) :: lhs !< Left hand side.
131-
class(integrand_object), intent(in) :: rhs !< Right hand side.
132-
real(R_P) :: opr(1:lhs%n) !< Operator result.
129+
class(oscillator), intent(in) :: lhs !< Left hand side.
130+
class(integrand_object), intent(in) :: rhs !< Right hand side.
131+
real(R_P), allocatable :: opr(:) !< Operator result.
133132

134133
select type(rhs)
135134
class is(oscillator)
@@ -139,28 +138,28 @@ pure function integrand_add_integrand(lhs, rhs) result(opr)
139138

140139
pure function integrand_add_real(lhs, rhs) result(opr)
141140
!< `+ real` operator.
142-
class(oscillator), intent(in) :: lhs !< Left hand side.
143-
real(R_P), intent(in) :: rhs(1:lhs%n) !< Right hand side.
144-
real(R_P) :: opr(1:lhs%n) !< Operator result.
141+
class(oscillator), intent(in) :: lhs !< Left hand side.
142+
real(R_P), intent(in) :: rhs(1:) !< Right hand side.
143+
real(R_P), allocatable :: opr(:) !< Operator result.
145144

146145
opr = lhs%U + rhs
147146
endfunction integrand_add_real
148147

149148
pure function real_add_integrand(lhs, rhs) result(opr)
150149
!< `real +` operator.
151-
class(oscillator), intent(in) :: rhs !< Left hand side.
152-
real(R_P), intent(in) :: lhs(1:rhs%n) !< Left hand side.
153-
real(R_P) :: opr(1:rhs%n) !< Operator result.
150+
real(R_P), intent(in) :: lhs(1:) !< Left hand side.
151+
class(oscillator), intent(in) :: rhs !< Left hand side.
152+
real(R_P), allocatable :: opr(:) !< Operator result.
154153

155154
opr = lhs + rhs%U
156155
endfunction real_add_integrand
157156

158157
! *
159158
pure function integrand_multiply_integrand(lhs, rhs) result(opr)
160159
!< `*` operator.
161-
class(oscillator), intent(in) :: lhs !< Left hand side.
162-
class(integrand_object), intent(in) :: rhs !< Right hand side.
163-
real(R_P) :: opr(1:lhs%n) !< Operator result.
160+
class(oscillator), intent(in) :: lhs !< Left hand side.
161+
class(integrand_object), intent(in) :: rhs !< Right hand side.
162+
real(R_P), allocatable :: opr(:) !< Operator result.
164163

165164
select type(rhs)
166165
class is(oscillator)
@@ -170,45 +169,46 @@ pure function integrand_multiply_integrand(lhs, rhs) result(opr)
170169

171170
pure function integrand_multiply_real(lhs, rhs) result(opr)
172171
!< `* real_scalar` operator.
173-
class(oscillator), intent(in) :: lhs !< Left hand side.
174-
real(R_P), intent(in) :: rhs(1:lhs%n) !< Right hand side.
175-
real(R_P) :: opr(1:lhs%n) !< Operator result.
172+
class(oscillator), intent(in) :: lhs !< Left hand side.
173+
real(R_P), intent(in) :: rhs(1:) !< Right hand side.
174+
real(R_P), allocatable :: opr(:) !< Operator result.
176175

177176
opr = lhs%U * rhs
178177
endfunction integrand_multiply_real
179178

180179
pure function real_multiply_integrand(lhs, rhs) result(opr)
181180
!< `real_scalar *` operator.
182-
class(oscillator), intent(in) :: rhs !< Right hand side.
183-
real(R_P), intent(in) :: lhs(1:rhs%n) !< Left hand side.
184-
real(R_P) :: opr(1:rhs%n) !< Operator result.
181+
class(oscillator), intent(in) :: rhs !< Right hand side.
182+
real(R_P), intent(in) :: lhs(1:) !< Left hand side.
183+
real(R_P), allocatable :: opr(:) !< Operator result.
185184

186185
opr = lhs * rhs%U
187186
endfunction real_multiply_integrand
188187

189188
pure function integrand_multiply_real_scalar(lhs, rhs) result(opr)
190189
!< `* real_scalar` operator.
191-
class(oscillator), intent(in) :: lhs !< Left hand side.
192-
real(R_P), intent(in) :: rhs !< Right hand side.
193-
real(R_P) :: opr(1:lhs%n) !< Operator result.
190+
class(oscillator), intent(in) :: lhs !< Left hand side.
191+
real(R_P), intent(in) :: rhs !< Right hand side.
192+
real(R_P), allocatable :: opr(:) !< Operator result.
194193

195194
opr = lhs%U * rhs
196195
endfunction integrand_multiply_real_scalar
197196

198197
pure function real_scalar_multiply_integrand(lhs, rhs) result(opr)
199198
!< `real_scalar *` operator.
200-
real(R_P), intent(in) :: lhs !< Left hand side.
201-
class(oscillator), intent(in) :: rhs !< Right hand side.
202-
real(R_P) :: opr(1:rhs%n) !< Operator result.
199+
real(R_P), intent(in) :: lhs !< Left hand side.
200+
class(oscillator), intent(in) :: rhs !< Right hand side.
201+
real(R_P), allocatable :: opr(:) !< Operator result.
203202

204203
opr = lhs * rhs%U
205204
endfunction real_scalar_multiply_integrand
205+
206206
! -
207207
pure function integrand_sub_integrand(lhs, rhs) result(opr)
208208
!< `-` operator.
209-
class(oscillator), intent(in) :: lhs !< Left hand side.
210-
class(integrand_object), intent(in) :: rhs !< Right hand side.
211-
real(R_P) :: opr(1:lhs%n) !< Operator result.
209+
class(oscillator), intent(in) :: lhs !< Left hand side.
210+
class(integrand_object), intent(in) :: rhs !< Right hand side.
211+
real(R_P), allocatable :: opr(:) !< Operator result.
212212

213213
select type(rhs)
214214
class is(oscillator)
@@ -218,18 +218,18 @@ pure function integrand_sub_integrand(lhs, rhs) result(opr)
218218

219219
pure function integrand_sub_real(lhs, rhs) result(opr)
220220
!< `- real` operator.
221-
class(oscillator), intent(in) :: lhs !< Left hand side.
222-
real(R_P), intent(in) :: rhs(1:lhs%n) !< Right hand side.
223-
real(R_P) :: opr(1:lhs%n) !< Operator result.
221+
class(oscillator), intent(in) :: lhs !< Left hand side.
222+
real(R_P), intent(in) :: rhs(1:) !< Right hand side.
223+
real(R_P), allocatable :: opr(:) !< Operator result.
224224

225225
opr = lhs%U - rhs
226226
endfunction integrand_sub_real
227227

228228
pure function real_sub_integrand(lhs, rhs) result(opr)
229229
!< `real -` operator.
230-
class(oscillator), intent(in) :: rhs !< Left hand side.
231-
real(R_P), intent(in) :: lhs(1:rhs%n) !< Left hand side.
232-
real(R_P) :: opr(1:rhs%n) !< Operator result.
230+
class(oscillator), intent(in) :: rhs !< Left hand side.
231+
real(R_P), intent(in) :: lhs(1:) !< Left hand side.
232+
real(R_P), allocatable :: opr(:) !< Operator result.
233233

234234
opr = lhs - rhs%U
235235
endfunction real_sub_integrand
@@ -242,16 +242,15 @@ pure subroutine assign_integrand(lhs, rhs)
242242

243243
select type(rhs)
244244
class is(oscillator)
245-
lhs%n = rhs%n
246245
lhs%U = rhs%U
247246
lhs%f = rhs%f
248247
endselect
249248
endsubroutine assign_integrand
250249

251250
pure subroutine assign_real(lhs, rhs)
252251
!< `= real` operator.
253-
class(oscillator), intent(inout) :: lhs !< Left hand side.
254-
real(R_P), intent(in) :: rhs(1:lhs%n) !< Right hand side.
252+
class(oscillator), intent(inout) :: lhs !< Left hand side.
253+
real(R_P), intent(in) :: rhs(1:) !< Right hand side.
255254

256255
lhs%U = rhs
257256
endsubroutine assign_real

0 commit comments

Comments
 (0)