@@ -77,56 +77,83 @@ module foodie_integrator_adams_bashforth_moulton
7777! <
7878
7979use foodie_adt_integrand, only : integrand
80- use foodie_error_codes, only : ERROR_BAD_STEPS_NUMBER
80+ use foodie_error_codes, only : ERROR_UNSUPPORTED_SCHEME
8181use foodie_kinds, only : I_P, R_P
8282use foodie_integrator_adams_bashforth, only : integrator_adams_bashforth
8383use foodie_integrator_adams_moulton, only : integrator_adams_moulton
8484use foodie_integrator_object, only : integrator_object
85- use foodie_utils, only : is_admissible
8685
8786implicit none
8887private
8988public :: integrator_adams_bashforth_moulton
9089
91- character (len= 99 ), parameter :: supported_steps= ' 1-16' ! < List of supported steps number. Valid format is `1-2,4,9-23...`.
92- integer (I_P), parameter :: min_ss= 1 ! < Minimum number of steps supported.
93- integer (I_P), parameter :: max_ss= 16 ! < Maximum number of steps supported.
90+ character (len= 99 ), parameter :: class_name_= ' adams_bashforth_moulton' ! < Name of the class of schemes.
91+ character (len= 99 ), parameter :: supported_schemes_(1 :16 )= [trim (class_name_)// ' _1 ' , &
92+ trim (class_name_)// ' _2 ' , &
93+ trim (class_name_)// ' _3 ' , &
94+ trim (class_name_)// ' _4 ' , &
95+ trim (class_name_)// ' _5 ' , &
96+ trim (class_name_)// ' _6 ' , &
97+ trim (class_name_)// ' _7 ' , &
98+ trim (class_name_)// ' _8 ' , &
99+ trim (class_name_)// ' _9 ' , &
100+ trim (class_name_)// ' _10' , &
101+ trim (class_name_)// ' _11' , &
102+ trim (class_name_)// ' _12' , &
103+ trim (class_name_)// ' _13' , &
104+ trim (class_name_)// ' _14' , &
105+ trim (class_name_)// ' _15' , &
106+ trim (class_name_)// ' _16' ] ! < List of supported schemes.
94107
95108type, extends(integrator_object) :: integrator_adams_bashforth_moulton
96109 ! < FOODIE integrator: provide an explicit class of Adams-Bashforth-Moulton multi-step schemes, from 1st to 4rd order accurate.
97110 ! <
98111 ! < @note The integrator must be created or initialized (predictor and corrector schemes selection) before used.
99112 private
100- integer (I_P) :: steps=- 1 ! < Number of time steps.
113+ integer (I_P), public :: steps= 0 ! < Number of time steps.
101114 type (integrator_adams_bashforth) :: predictor ! < Predictor solver.
102115 type (integrator_adams_moulton) :: corrector ! < Corrector solver.
103116 contains
104117 ! deferred methods
118+ procedure , pass(self) :: class_name ! < Return the class name of schemes.
105119 procedure , pass(self) :: description ! < Return pretty-printed object description.
106120 procedure , pass(lhs) :: integr_assign_integr ! < Operator `=`.
121+ procedure , pass(self) :: is_supported ! < Return .true. if the integrator class support the given scheme.
122+ procedure , pass(self) :: supported_schemes ! < Return the list of supported schemes.
107123 ! public methods
108- procedure , pass(self) :: destroy ! < Destroy the integrator.
109- procedure , pass(self) :: init ! < Initialize (create) the integrator.
110- procedure , pass(self) :: integrate ! < Integrate integrand field.
111- procedure , nopass :: is_supported ! < Check if the queried number of steps is supported or not.
112- procedure , nopass :: min_steps ! < Return the minimum number of steps supported.
113- procedure , nopass :: max_steps ! < Return the maximum number of steps supported.
124+ procedure , pass(self) :: destroy ! < Destroy the integrator.
125+ procedure , pass(self) :: initialize ! < Initialize (create) the integrator.
126+ procedure , pass(self) :: integrate ! < Integrate integrand field.
127+ procedure , pass(self) :: scheme_number ! < Return the scheme number in the list of supported schemes.
114128endtype integrator_adams_bashforth_moulton
115129
116130contains
117131 ! deferred methods
132+ pure function class_name (self )
133+ ! < Return the class name of schemes.
134+ class(integrator_adams_bashforth_moulton), intent (in ) :: self ! < Integrator.
135+ character (len= 99 ) :: class_name ! < Class name.
136+
137+ class_name = trim (adjustl (class_name_))
138+ end function class_name
139+
118140 pure function description (self , prefix ) result(desc)
119141 ! < Return a pretty-formatted object description.
120142 class(integrator_adams_bashforth_moulton), intent (in ) :: self ! < Integrator.
121143 character (* ), intent (in ), optional :: prefix ! < Prefixing string.
122144 character (len= :), allocatable :: desc ! < Description.
123145 character (len= :), allocatable :: prefix_ ! < Prefixing string, local variable.
124146 character (len= 1 ), parameter :: NL= new_line(' a' ) ! < New line character.
147+ integer (I_P) :: s ! < Counter.
125148
126149 prefix_ = ' ' ; if (present (prefix)) prefix_ = prefix
127150 desc = ' '
128- desc = desc// prefix_// ' Adams-Bashforth-Moulton multi-step schemes class' // NL
129- desc = desc// prefix_// ' Supported steps numbers: [' // trim (adjustl (supported_steps))// ' ]'
151+ desc = desc// prefix_// ' Adams-Bashforth-Moulton multi-step (predictor-corrector) schemes class' // NL
152+ desc = desc// prefix_// ' Supported schemes:' // NL
153+ do s= lbound (supported_schemes_, dim= 1 ), ubound (supported_schemes_, dim= 1 ) - 1
154+ desc = desc// prefix_// ' + ' // supported_schemes_(s)// NL
155+ enddo
156+ desc = desc// prefix_// ' + ' // supported_schemes_(ubound (supported_schemes_, dim= 1 ))
130157 end function description
131158
132159 pure subroutine integr_assign_integr (lhs , rhs )
@@ -143,33 +170,64 @@ pure subroutine integr_assign_integr(lhs, rhs)
143170 endselect
144171 end subroutine integr_assign_integr
145172
173+ elemental function is_supported (self , scheme )
174+ ! < Return .true. if the integrator class support the given scheme.
175+ class(integrator_adams_bashforth_moulton), intent (in ) :: self ! < Integrator.
176+ character (* ), intent (in ) :: scheme ! < Selected scheme.
177+ logical :: is_supported ! < Inquire result.
178+ integer (I_P) :: s ! < Counter.
179+
180+ is_supported = .false.
181+ do s= lbound (supported_schemes_, dim= 1 ), ubound (supported_schemes_, dim= 1 )
182+ if (trim (adjustl (scheme)) == trim (adjustl (supported_schemes_(s)))) then
183+ is_supported = .true.
184+ return
185+ endif
186+ enddo
187+ end function is_supported
188+
189+ pure function supported_schemes (self ) result(schemes)
190+ ! < Return the list of supported schemes.
191+ class(integrator_adams_bashforth_moulton), intent (in ) :: self ! < Integrator.
192+ character (len= 99 ), allocatable :: schemes(:) ! < Queried scheme.
193+
194+ allocate (schemes(lbound (supported_schemes_, dim= 1 ):ubound (supported_schemes_, dim= 1 )))
195+ schemes = supported_schemes_
196+ end function supported_schemes
197+
146198 ! public methods
147199 elemental subroutine destroy (self )
148200 ! < Destroy the integrator.
149201 class(integrator_adams_bashforth_moulton), intent (inout ) :: self ! < Integrator.
150202
151203 call self% destroy_abstract
152- self% steps = - 1
204+ self% steps = 0
153205 call self% predictor% destroy
154206 call self% corrector% destroy
155207 end subroutine destroy
156208
157- subroutine init (self , steps )
209+ subroutine initialize (self , scheme )
158210 ! < Create the actual Adams-Bashforth-Moulton integrator: initialize the *b* coefficients.
159- class(integrator_adams_bashforth_moulton), intent (inout ) :: self ! < Integrator.
160- integer (I_P), intent (in ) :: steps ! < Number of time steps used.
211+ class(integrator_adams_bashforth_moulton), intent (inout ) :: self ! < Integrator.
212+ character (* ), intent (in ) :: scheme ! < Selected scheme.
213+ character (len= 99 ), allocatable :: schemes_ab(:) ! < Adams-Bashforth schemes.
214+ character (len= 99 ), allocatable :: schemes_am(:) ! < Adams-Moulton schemes.
215+ integer (I_P) :: scheme_number_ ! < Scheme number in the list of supported schemes.
161216
162- if (self% is_supported(steps )) then
217+ if (self% is_supported(scheme = scheme )) then
163218 call self% destroy
164- self% steps = steps
165- call self% predictor% init(steps= steps)
166- call self% corrector% init(steps= steps-1 )
219+ scheme_number_ = self% scheme_number(scheme= scheme)
220+ schemes_ab = self% predictor% supported_schemes()
221+ schemes_am = self% corrector% supported_schemes()
222+ call self% predictor% initialize(scheme= schemes_ab(scheme_number_))
223+ call self% corrector% initialize(scheme= schemes_am(scheme_number_))
224+ self% steps = self% predictor% steps
167225 else
168- call self% trigger_error(error= ERROR_BAD_STEPS_NUMBER, &
169- error_message= ' bad (unsupported) number of time steps ' , &
226+ call self% trigger_error(error= ERROR_UNSUPPORTED_SCHEME, &
227+ error_message= ' " ' // trim ( adjustl (scheme)) // ' " unsupported scheme ' , &
170228 is_severe= .true. )
171229 endif
172- end subroutine init
230+ end subroutine initialize
173231
174232 subroutine integrate (self , U , previous , Dt , t , iterations )
175233 ! < Integrate field with Adams-Bashforth-Moulton class scheme.
@@ -185,25 +243,19 @@ subroutine integrate(self, U, previous, Dt, t, iterations)
185243 call self% predictor% update_previous(U= U, previous= previous)
186244 end subroutine integrate
187245
188- elemental function is_supported (steps )
189- ! < Check if the queried number of steps is supported or not.
190- integer (I_P), intent (in ) :: steps ! < Number of time steps used.
191- logical :: is_supported ! < Is true is the steps number is in *supported_steps*.
192-
193- is_supported = is_admissible(n= steps, adm_range= trim (supported_steps))
194- end function is_supported
195-
196- pure function min_steps ()
197- ! < Return the minimum number of steps supported.
198- integer (I_P) :: min_steps ! < Minimum number of steps supported.
199-
200- min_steps = min_ss
201- end function min_steps
202-
203- pure function max_steps ()
204- ! < Return the maximum number of steps supported.
205- integer (I_P) :: max_steps ! < Maximum number of steps supported.
246+ elemental function scheme_number (self , scheme )
247+ ! < Return the scheme number in the list of supported schemes.
248+ class(integrator_adams_bashforth_moulton), intent (in ) :: self ! < Integrator.
249+ character (* ), intent (in ) :: scheme ! < Selected scheme.
250+ integer (I_P) :: scheme_number ! < Scheme number in the list of supported schemes.
251+ integer (I_P) :: s ! < Counter.
206252
207- max_steps = max_ss
208- end function max_steps
253+ scheme_number = 0
254+ do s= lbound (supported_schemes_, dim= 1 ), ubound (supported_schemes_, dim= 1 )
255+ if (trim (adjustl (scheme)) == trim (adjustl (supported_schemes_(s)))) then
256+ scheme_number = s
257+ exit
258+ endif
259+ enddo
260+ end function scheme_number
209261endmodule foodie_integrator_adams_bashforth_moulton
0 commit comments