1 |
!! |
2 |
!! Copyright (c) 2005 The University of Notre Dame. All Rights Reserved. |
3 |
!! |
4 |
!! The University of Notre Dame grants you ("Licensee") a |
5 |
!! non-exclusive, royalty free, license to use, modify and |
6 |
!! redistribute this software in source and binary code form, provided |
7 |
!! that the following conditions are met: |
8 |
!! |
9 |
!! 1. Redistributions of source code must retain the above copyright |
10 |
!! notice, this list of conditions and the following disclaimer. |
11 |
!! |
12 |
!! 2. Redistributions in binary form must reproduce the above copyright |
13 |
!! notice, this list of conditions and the following disclaimer in the |
14 |
!! documentation and/or other materials provided with the |
15 |
!! distribution. |
16 |
!! |
17 |
!! This software is provided "AS IS," without a warranty of any |
18 |
!! kind. All express or implied conditions, representations and |
19 |
!! warranties, including any implied warranty of merchantability, |
20 |
!! fitness for a particular purpose or non-infringement, are hereby |
21 |
!! excluded. The University of Notre Dame and its licensors shall not |
22 |
!! be liable for any damages suffered by licensee as a result of |
23 |
!! using, modifying or distributing the software or its |
24 |
!! derivatives. In no event will the University of Notre Dame or its |
25 |
!! licensors be liable for any lost revenue, profit or data, or for |
26 |
!! direct, indirect, special, consequential, incidental or punitive |
27 |
!! damages, however caused and regardless of the theory of liability, |
28 |
!! arising out of the use of or inability to use software, even if the |
29 |
!! University of Notre Dame has been advised of the possibility of |
30 |
!! such damages. |
31 |
!! |
32 |
!! SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your |
33 |
!! research, please cite the appropriate papers when you publish your |
34 |
!! work. Good starting points are: |
35 |
!! |
36 |
!! [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005). |
37 |
!! [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006). |
38 |
!! [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008). |
39 |
!! [4] Vardeman & Gezelter, in progress (2009). |
40 |
!! |
41 |
|
42 |
! vector_class.F90 |
43 |
!! Module Vector_class |
44 |
!! Fortran 95 Vector class module. Similar to java.util vector class. |
45 |
!! |
46 |
!! The Vector class implements a growable array of objects. Like an array, |
47 |
!! it contains components that can be accessed using an integer index. |
48 |
!! However, the size of a Vector can grow as needed to accommodate |
49 |
!! adding and removing items after the Vector has been created. |
50 |
!! Each vector tries to optimize storage management by maintaining a |
51 |
!! capacity and a capacityIncrement. The capacity is always at least as |
52 |
!! large as the vector size; |
53 |
!! it is usually larger because as components are added to the vector, |
54 |
!! the vector's storage increases in chunks the size of capacityIncrement. |
55 |
!! An application can increase the capacity of a vector before inserting a |
56 |
!! large number of components; this reduces the amount of incremental |
57 |
!! reallocation. |
58 |
!! |
59 |
!! |
60 |
!! @author J. Daniel Gezelter |
61 |
!! @author Charles F. Vardeman II |
62 |
!! @author Matthew Meineke |
63 |
!! @version $Id$, $Date$, $Name: not supported by cvs2svn $, $Revision$ |
64 |
|
65 |
module Vector_class |
66 |
|
67 |
implicit NONE |
68 |
PRIVATE |
69 |
|
70 |
public :: initialize |
71 |
public :: destroy |
72 |
public :: getSize |
73 |
public :: getElementAt |
74 |
public :: getPropertyListSize |
75 |
public :: getPropertyNameAt |
76 |
public :: addElement |
77 |
public :: setElementProperty |
78 |
public :: getElementProperty |
79 |
public :: getMatchingElementList |
80 |
public :: getFirstMatchingElement |
81 |
|
82 |
|
83 |
integer, parameter :: logical_data_type = 1 |
84 |
integer, parameter :: integer_data_type = 2 |
85 |
integer, parameter :: real_data_type = 3 |
86 |
|
87 |
!! |
88 |
type, public :: Vector |
89 |
PRIVATE |
90 |
integer :: initialCapacity = 10 |
91 |
integer :: capacityIncrement = 0 |
92 |
integer :: elementCount = 0 |
93 |
|
94 |
integer :: initialProperties = 5 |
95 |
integer :: PropertyIncrement = 0 |
96 |
integer :: propertyCount = 0 |
97 |
|
98 |
integer, pointer :: ElementData(:) => null() |
99 |
character(len=100), pointer :: PropertyDescriptions(:) => null() |
100 |
integer, pointer :: PropertyDataType(:) => null() |
101 |
real(kind = 8), pointer :: realElementProperties(:,:) => null() |
102 |
integer, pointer :: integerElementProperties(:,:) => null() |
103 |
logical, pointer :: logicalElementProperties(:,:) => null() |
104 |
end type Vector |
105 |
|
106 |
!! Initialize vector |
107 |
interface initialize |
108 |
module procedure initialize_0i |
109 |
module procedure initialize_1i |
110 |
module procedure initialize_2i |
111 |
module procedure initialize_3i |
112 |
module procedure initialize_4i |
113 |
end interface |
114 |
|
115 |
interface setElementProperty |
116 |
module procedure setElementPropertyReal |
117 |
module procedure setElementPropertyInt |
118 |
module procedure setElementPropertyLogical |
119 |
end interface |
120 |
|
121 |
interface getElementProperty |
122 |
module procedure getElementPropertyReal |
123 |
module procedure getElementPropertyInt |
124 |
module procedure getElementPropertyLogical |
125 |
end interface |
126 |
|
127 |
interface getMatchingElementList |
128 |
module procedure getMatchingElementList1i |
129 |
module procedure getMatchingElementList2i |
130 |
module procedure getMatchingElementList1l |
131 |
module procedure getMatchingElementList2l |
132 |
end interface |
133 |
|
134 |
interface getFirstMatchingElement |
135 |
module procedure getFirstMatchingElement1i |
136 |
module procedure getFirstMatchingElement2i |
137 |
module procedure getFirstMatchingElement1l |
138 |
module procedure getFirstMatchingElement2l |
139 |
end interface |
140 |
contains |
141 |
|
142 |
function getSize(this) result (ne) |
143 |
type(Vector), pointer :: this |
144 |
integer :: ne |
145 |
ne = this%elementCount |
146 |
end function getSize |
147 |
|
148 |
function getElementAt(this, loc) result (id) |
149 |
type(Vector), pointer :: this |
150 |
integer, intent(in) :: loc |
151 |
integer :: id |
152 |
id = this%ElementData(loc) |
153 |
end function getElementAt |
154 |
|
155 |
function getPropertyListSize(this) result (np) |
156 |
type(Vector), pointer :: this |
157 |
integer :: np |
158 |
np = this%propertyCount |
159 |
end function getPropertyListSize |
160 |
|
161 |
function getPropertyNameAt(this, loc) result (pn) |
162 |
type(Vector), pointer :: this |
163 |
integer, intent(in) :: loc |
164 |
character(len=len(this%PropertyDescriptions)) :: pn |
165 |
pn = this%PropertyDescriptions(loc) |
166 |
end function getPropertyNameAt |
167 |
|
168 |
function getFirstMatchingElement1i(this, MatchName, MatchValue) result (id) |
169 |
type(Vector), pointer :: this |
170 |
character(len=*), intent(in) :: MatchName |
171 |
integer, intent(in) :: MatchValue |
172 |
integer :: id |
173 |
integer :: i, j |
174 |
|
175 |
id = 0 |
176 |
|
177 |
do i = 1, this%propertyCount |
178 |
if (this%PropertyDescriptions(i) == MatchName) then |
179 |
do j = 1, this%elementCount |
180 |
if (this%integerElementProperties(j, i) == MatchValue) then |
181 |
id = j |
182 |
return |
183 |
endif |
184 |
enddo |
185 |
endif |
186 |
enddo |
187 |
return |
188 |
end function getFirstMatchingElement1i |
189 |
|
190 |
function getFirstMatchingElement2i(this, MatchName1, MatchValue1, & |
191 |
MatchName2, MatchValue2) result (id) |
192 |
type(Vector), pointer :: this |
193 |
character(len=*), intent(in) :: MatchName1, MatchName2 |
194 |
integer, intent(in) :: MatchValue1, MatchValue2 |
195 |
integer :: id |
196 |
integer :: i, j, MatchID1, MatchID2 |
197 |
logical :: found1 = .false. |
198 |
logical :: found2 = .false. |
199 |
|
200 |
id = 0 |
201 |
! first figure out which properties we are using to do the match: |
202 |
|
203 |
do i = 1, this%propertyCount |
204 |
if (this%PropertyDescriptions(i) == MatchName1) then |
205 |
MatchID1 = i |
206 |
found1 = .true. |
207 |
endif |
208 |
if (this%PropertyDescriptions(i) == MatchName2) then |
209 |
MatchID2 = i |
210 |
found2 = .true. |
211 |
endif |
212 |
|
213 |
if (found1.and.found2) then |
214 |
do j = 1, this%elementCount |
215 |
if ((this%integerElementProperties(j, MatchID1) == MatchValue1) & |
216 |
.and. & |
217 |
(this%integerElementProperties(j, MatchID2) ==MatchValue2)) & |
218 |
then |
219 |
id = j |
220 |
return |
221 |
endif |
222 |
enddo |
223 |
endif |
224 |
end do |
225 |
|
226 |
return |
227 |
end function getFirstMatchingElement2i |
228 |
|
229 |
function getFirstMatchingElement1l(this, MatchName, MatchValue) result (id) |
230 |
type(Vector), pointer :: this |
231 |
character(len=*), intent(in) :: MatchName |
232 |
logical, intent(in) :: MatchValue |
233 |
integer :: id |
234 |
integer :: i, j |
235 |
|
236 |
id = 0 |
237 |
|
238 |
do i = 1, this%propertyCount |
239 |
if (this%PropertyDescriptions(i) == MatchName) then |
240 |
do j = 1, this%elementCount |
241 |
if (this%logicalElementProperties(j, i) .eqv. MatchValue) then |
242 |
id = j |
243 |
return |
244 |
endif |
245 |
enddo |
246 |
endif |
247 |
enddo |
248 |
return |
249 |
end function getFirstMatchingElement1l |
250 |
|
251 |
function getFirstMatchingElement2l(this, MatchName1, MatchValue1, & |
252 |
MatchName2, MatchValue2) result (id) |
253 |
type(Vector), pointer :: this |
254 |
character(len=*), intent(in) :: MatchName1, MatchName2 |
255 |
logical, intent(in) :: MatchValue1, MatchValue2 |
256 |
integer :: id |
257 |
integer :: i, j, MatchID1, MatchID2 |
258 |
logical :: found1 = .false. |
259 |
logical :: found2 = .false. |
260 |
|
261 |
id = 0 |
262 |
! first figure out which properties we are using to do the match: |
263 |
|
264 |
do i = 1, this%propertyCount |
265 |
if (this%PropertyDescriptions(i) == MatchName1) then |
266 |
MatchID1 = i |
267 |
found1 = .true. |
268 |
endif |
269 |
if (this%PropertyDescriptions(i) == MatchName2) then |
270 |
MatchID2 = i |
271 |
found2 = .true. |
272 |
endif |
273 |
|
274 |
if (found1.and.found2) then |
275 |
do j = 1, this%elementCount |
276 |
if ((this%logicalElementProperties(j, MatchID1).eqv.MatchValue1) & |
277 |
.and. & |
278 |
(this%logicalElementProperties(j, MatchID2).eqv.MatchValue2)) & |
279 |
then |
280 |
id = j |
281 |
return |
282 |
endif |
283 |
enddo |
284 |
endif |
285 |
end do |
286 |
|
287 |
return |
288 |
end function getFirstMatchingElement2l |
289 |
|
290 |
subroutine getMatchingElementList1i(this, MatchName, MatchValue, & |
291 |
nMatches, MatchList) |
292 |
type(Vector), pointer :: this |
293 |
character(len=*), intent(in) :: MatchName |
294 |
integer, intent(in) :: MatchValue |
295 |
integer, intent(out) :: nMatches |
296 |
integer, pointer :: MatchList(:) |
297 |
integer :: i |
298 |
|
299 |
! first figure out which property we are using to do the match: |
300 |
|
301 |
do i = 1, this%propertyCount |
302 |
if (this%PropertyDescriptions(i) == MatchName) then |
303 |
call getAllMatches1i(this, i, MatchValue, nMatches, MatchList) |
304 |
return |
305 |
endif |
306 |
enddo |
307 |
return |
308 |
end subroutine getMatchingElementList1i |
309 |
|
310 |
subroutine getMatchingElementList2i(this, MatchName1, MatchValue1, & |
311 |
MatchName2, MatchValue2, nMatches, MatchList) |
312 |
type(Vector), pointer :: this |
313 |
character(len=*), intent(in) :: MatchName1, MatchName2 |
314 |
integer, intent(in) :: MatchValue1, MatchValue2 |
315 |
integer, intent(out) :: nMatches |
316 |
integer, pointer :: MatchList(:) |
317 |
integer :: i, MatchID1, MatchID2 |
318 |
logical :: found1 = .false. |
319 |
logical :: found2 = .false. |
320 |
|
321 |
! first figure out which properties we are using to do the match: |
322 |
|
323 |
do i = 1, this%propertyCount |
324 |
if (this%PropertyDescriptions(i) == MatchName1) then |
325 |
MatchID1 = i |
326 |
found1 = .true. |
327 |
endif |
328 |
if (this%PropertyDescriptions(i) == MatchName2) then |
329 |
MatchID2 = i |
330 |
found2 = .true. |
331 |
endif |
332 |
|
333 |
if (found1.and.found2) then |
334 |
call getAllMatches2i(this, MatchID1, MatchValue1, & |
335 |
MatchID2, MatchValue2, nMatches, MatchList) |
336 |
return |
337 |
endif |
338 |
enddo |
339 |
return |
340 |
end subroutine getMatchingElementList2i |
341 |
|
342 |
subroutine getMatchingElementList1l(this, MatchName, MatchValue, & |
343 |
nMatches, MatchList) |
344 |
type(Vector), pointer :: this |
345 |
character(len=*), intent(in) :: MatchName |
346 |
logical, intent(in) :: MatchValue |
347 |
integer, intent(out) :: nMatches |
348 |
integer, pointer :: MatchList(:) |
349 |
integer :: i |
350 |
|
351 |
! first figure out which property we are using to do the match: |
352 |
|
353 |
do i = 1, this%propertyCount |
354 |
if (this%PropertyDescriptions(i) == MatchName) then |
355 |
call getAllMatches1l(this, i, MatchValue, nMatches, MatchList) |
356 |
return |
357 |
endif |
358 |
enddo |
359 |
return |
360 |
end subroutine getMatchingElementList1l |
361 |
|
362 |
subroutine getMatchingElementList2l(this, MatchName1, MatchValue1, & |
363 |
MatchName2, MatchValue2, nMatches, MatchList) |
364 |
type(Vector), pointer :: this |
365 |
character(len=*), intent(in) :: MatchName1, MatchName2 |
366 |
logical, intent(in) :: MatchValue1, MatchValue2 |
367 |
integer, intent(out) :: nMatches |
368 |
integer, pointer :: MatchList(:) |
369 |
integer :: i, MatchID1, MatchID2 |
370 |
logical :: found1 = .false. |
371 |
logical :: found2 = .false. |
372 |
|
373 |
! first figure out which properties we are using to do the match: |
374 |
|
375 |
do i = 1, this%propertyCount |
376 |
if (this%PropertyDescriptions(i) == MatchName1) then |
377 |
MatchID1 = i |
378 |
found1 = .true. |
379 |
endif |
380 |
if (this%PropertyDescriptions(i) == MatchName2) then |
381 |
MatchID2 = i |
382 |
found2 = .true. |
383 |
endif |
384 |
|
385 |
if (found1.and.found2) then |
386 |
call getAllMatches2l(this, MatchID1, MatchValue1, & |
387 |
MatchID2, MatchValue2, nMatches, MatchList) |
388 |
return |
389 |
endif |
390 |
enddo |
391 |
return |
392 |
end subroutine getMatchingElementList2l |
393 |
|
394 |
subroutine getAllMatches1i(this, MatchID, MatchValue, nMatches, MatchList) |
395 |
type(Vector), pointer :: this |
396 |
integer, intent(in) :: MatchID |
397 |
integer, intent(in) :: MatchValue |
398 |
integer, pointer :: MatchList(:) |
399 |
integer, allocatable :: MatchListTemp(:) |
400 |
integer, intent(out) :: nMatches |
401 |
integer :: error, i |
402 |
|
403 |
if(associated(MatchList)) deallocate(MatchList) |
404 |
MatchList => null() |
405 |
|
406 |
allocate(MatchListTemp(this%elementCount), stat=error) |
407 |
if(error .ne. 0) write(*,*) 'Could not allocate MatchListTemp!' |
408 |
|
409 |
nMatches = 0 |
410 |
|
411 |
do i = 1, this%elementCount |
412 |
if (this%integerElementProperties(i, MatchID) == MatchValue) then |
413 |
nMatches = nMatches + 1 |
414 |
MatchListTemp(nMatches) = i |
415 |
endif |
416 |
enddo |
417 |
|
418 |
|
419 |
if (nMatches .ne. 0) then |
420 |
allocate(MatchList(nMatches), stat=error) |
421 |
if (error.ne.0) write(*, *) 'Could not allocate MatchList!' |
422 |
do i = 1, nMatches |
423 |
MatchList(i) = MatchListTemp(i) |
424 |
enddo |
425 |
endif |
426 |
|
427 |
deallocate(MatchListTemp) |
428 |
|
429 |
|
430 |
end subroutine getAllMatches1i |
431 |
|
432 |
subroutine getAllMatches2i(this, MatchID1, MatchValue1, & |
433 |
MatchID2, MatchValue2, nMatches, MatchList) |
434 |
type(Vector), pointer :: this |
435 |
integer, intent(in) :: MatchID1, MatchID2 |
436 |
integer, intent(in) :: MatchValue1, MatchValue2 |
437 |
integer, pointer :: MatchList(:) |
438 |
integer, allocatable :: MatchListTemp(:) |
439 |
integer, intent(out) :: nMatches |
440 |
integer :: error, i |
441 |
|
442 |
if(associated(MatchList)) deallocate(MatchList) |
443 |
MatchList => null() |
444 |
|
445 |
allocate(MatchListTemp(this%elementCount), stat=error) |
446 |
if(error .ne. 0) write(*,*) 'Could not allocate MatchListTemp!' |
447 |
|
448 |
nMatches = 0 |
449 |
|
450 |
do i = 1, this%elementCount |
451 |
if ((this%integerElementProperties(i, MatchID1) == MatchValue1) .and. & |
452 |
(this%integerElementProperties(i, MatchID2) == MatchValue2)) then |
453 |
nMatches = nMatches + 1 |
454 |
MatchListTemp(nMatches) = i |
455 |
endif |
456 |
enddo |
457 |
|
458 |
if (nMatches .ne. 0) then |
459 |
allocate(MatchList(nMatches), stat=error) |
460 |
if (error.ne.0) write(*, *) 'Could not allocate MatchList!' |
461 |
do i = 1, nMatches |
462 |
MatchList(i) = MatchListTemp(i) |
463 |
enddo |
464 |
endif |
465 |
|
466 |
deallocate(MatchListTemp) |
467 |
|
468 |
end subroutine getAllMatches2i |
469 |
|
470 |
subroutine getAllMatches1l(this, MatchID, MatchValue, nMatches, MatchList) |
471 |
type(Vector), pointer :: this |
472 |
integer, intent(in) :: MatchID |
473 |
logical, intent(in) :: MatchValue |
474 |
integer, pointer :: MatchList(:) |
475 |
integer, allocatable :: MatchListTemp(:) |
476 |
integer, intent(out) :: nMatches |
477 |
integer :: error, i |
478 |
|
479 |
if(associated(MatchList)) deallocate(MatchList) |
480 |
MatchList => null() |
481 |
|
482 |
allocate(MatchListTemp(this%elementCount), stat=error) |
483 |
if(error .ne. 0) write(*,*) 'Could not allocate MatchListTemp!' |
484 |
|
485 |
nMatches = 0 |
486 |
|
487 |
do i = 1, this%elementCount |
488 |
if (this%logicalElementProperties(i, MatchID).eqv.MatchValue) then |
489 |
nMatches = nMatches + 1 |
490 |
MatchListTemp(nMatches) = i |
491 |
endif |
492 |
enddo |
493 |
|
494 |
if (nMatches .ne. 0) then |
495 |
allocate(MatchList(nMatches), stat=error) |
496 |
if (error.ne.0) write(*, *) 'Could not allocate MatchList!' |
497 |
do i = 1, nMatches |
498 |
MatchList(i) = MatchListTemp(i) |
499 |
enddo |
500 |
endif |
501 |
|
502 |
deallocate(MatchListTemp) |
503 |
|
504 |
end subroutine getAllMatches1l |
505 |
|
506 |
subroutine getAllMatches2l(this, MatchID1, MatchValue1, & |
507 |
MatchID2, MatchValue2, nMatches, MatchList) |
508 |
type(Vector), pointer :: this |
509 |
integer, intent(in) :: MatchID1, MatchID2 |
510 |
logical, intent(in) :: MatchValue1, MatchValue2 |
511 |
integer, pointer :: MatchList(:) |
512 |
integer, allocatable :: MatchListTemp(:) |
513 |
integer, intent(out) :: nMatches |
514 |
integer :: error, i |
515 |
|
516 |
if(associated(MatchList)) deallocate(MatchList) |
517 |
MatchList => null() |
518 |
|
519 |
allocate(MatchListTemp(this%elementCount), stat=error) |
520 |
if(error .ne. 0) write(*,*) 'Could not allocate MatchListTemp!' |
521 |
|
522 |
nMatches = 0 |
523 |
|
524 |
do i = 1, this%elementCount |
525 |
if ((this%logicalElementProperties(i, MatchID1).eqv.MatchValue1) .and. & |
526 |
(this%logicalElementProperties(i, MatchID2).eqv.MatchValue2)) then |
527 |
nMatches = nMatches + 1 |
528 |
MatchListTemp(nMatches) = i |
529 |
endif |
530 |
enddo |
531 |
|
532 |
if (nMatches .ne. 0) then |
533 |
allocate(MatchList(nMatches), stat=error) |
534 |
if (error.ne.0) write(*, *) 'Could not allocate MatchList!' |
535 |
do i = 1, nMatches |
536 |
MatchList(i) = MatchListTemp(i) |
537 |
enddo |
538 |
endif |
539 |
|
540 |
deallocate(MatchListTemp) |
541 |
|
542 |
end subroutine getAllMatches2l |
543 |
|
544 |
|
545 |
subroutine getElementPropertyReal(this, id, PropName, pv) |
546 |
type(Vector), pointer :: this |
547 |
integer :: id, whichprop |
548 |
character(len=*) :: PropName |
549 |
real( kind = 8 ) :: pv |
550 |
|
551 |
whichprop = getPropertyIndex(this, PropName) |
552 |
if (whichprop .eq. 0 ) then |
553 |
write(*,*) 'unknown property: ', PropName |
554 |
pv = 0.0 |
555 |
else |
556 |
if (this%PropertyDataType(whichprop) .ne. real_data_type) then |
557 |
write(*,*) 'Property: ', PropName, " is not real data type." |
558 |
pv = 0.0 |
559 |
else |
560 |
pv = this%realElementProperties(id, whichprop) |
561 |
endif |
562 |
endif |
563 |
end subroutine getElementPropertyReal |
564 |
|
565 |
subroutine getElementPropertyInt(this, id, PropName, pv) |
566 |
type(Vector), pointer :: this |
567 |
integer :: id, whichprop |
568 |
character(len=*) :: PropName |
569 |
integer :: pv |
570 |
|
571 |
whichprop = getPropertyIndex(this, PropName) |
572 |
if (whichprop .eq. 0 ) then |
573 |
write(*,*) 'unknown property! ', PropName |
574 |
pv = 0 |
575 |
else |
576 |
if (this%PropertyDataType(whichprop) .ne. integer_data_type) then |
577 |
write(*,*) 'Property! ', PropName, " is not integer data type." |
578 |
pv = 0 |
579 |
else |
580 |
pv = this%integerElementProperties(id, whichprop) |
581 |
endif |
582 |
endif |
583 |
end subroutine getElementPropertyInt |
584 |
|
585 |
subroutine getElementPropertyLogical(this, id, PropName, pv) |
586 |
type(Vector), pointer :: this |
587 |
integer :: id, whichprop |
588 |
character(len=*) :: PropName |
589 |
logical :: pv |
590 |
|
591 |
whichprop = getPropertyIndex(this, PropName) |
592 |
if (whichprop .eq. 0 ) then |
593 |
write(*,*) 'unknown property! ', PropName |
594 |
pv = .false. |
595 |
else |
596 |
if (this%PropertyDataType(whichprop) .ne. logical_data_type) then |
597 |
write(*,*) 'Property! ', PropName, " is not logical data type." |
598 |
pv = .false. |
599 |
else |
600 |
pv = this%logicalElementProperties(id, whichprop) |
601 |
endif |
602 |
endif |
603 |
end subroutine getElementPropertyLogical |
604 |
|
605 |
function getPropertyIndex(this, PropName) result (id) |
606 |
type(Vector), pointer :: this |
607 |
integer :: id, i |
608 |
character(len=*) :: PropName |
609 |
|
610 |
do i = 1, this%propertyCount |
611 |
if (this%PropertyDescriptions(i) == PropName) then |
612 |
id = i |
613 |
return |
614 |
endif |
615 |
enddo |
616 |
id = 0 |
617 |
end function getPropertyIndex |
618 |
|
619 |
subroutine ensureCapacityHelper(this, minCapacity, minPropCap) |
620 |
type(Vector), pointer :: this, that |
621 |
integer, intent(in) :: minCapacity, minPropCap |
622 |
integer :: oldCapacity, oldPropCap |
623 |
integer :: newCapacity, newPropCap |
624 |
logical :: resizeFlag |
625 |
|
626 |
resizeFlag = .false. |
627 |
|
628 |
! first time: allocate a new vector with default size |
629 |
|
630 |
if (.not. associated(this)) then |
631 |
this => initialize() |
632 |
endif |
633 |
|
634 |
oldCapacity = size(this%ElementData) |
635 |
oldPropCap = size(this%PropertyDescriptions) |
636 |
|
637 |
if (minCapacity > oldCapacity) then |
638 |
if (this%capacityIncrement .gt. 0) then |
639 |
newCapacity = oldCapacity + this%capacityIncrement |
640 |
else |
641 |
newCapacity = oldCapacity * 2 |
642 |
endif |
643 |
if (newCapacity .lt. minCapacity) then |
644 |
newCapacity = minCapacity |
645 |
endif |
646 |
resizeFlag = .true. |
647 |
else |
648 |
newCapacity = oldCapacity |
649 |
endif |
650 |
|
651 |
!!! newCapacity is not set..... |
652 |
if (minPropCap > oldPropCap) then |
653 |
if (this%PropertyIncrement .gt. 0) then |
654 |
newPropCap = oldPropCap + this%PropertyIncrement |
655 |
else |
656 |
newPropCap = oldPropCap * 2 |
657 |
endif |
658 |
if (newPropCap .lt. minPropCap) then |
659 |
newPropCap = minPropCap |
660 |
endif |
661 |
resizeFlag = .true. |
662 |
else |
663 |
newPropCap = oldPropCap |
664 |
endif |
665 |
|
666 |
if (resizeFlag) then |
667 |
that => initialize(newCapacity, newPropCap, & |
668 |
this%capacityIncrement, this%PropertyIncrement) |
669 |
call copyAllData(this, that) |
670 |
this => destroy(this) |
671 |
this => that |
672 |
endif |
673 |
end subroutine ensureCapacityHelper |
674 |
|
675 |
subroutine copyAllData(v1, v2) |
676 |
type(Vector), pointer :: v1 |
677 |
type(Vector), pointer :: v2 |
678 |
integer :: i, j |
679 |
|
680 |
do i = 1, v1%elementCount |
681 |
v2%elementData(i) = v1%elementData(i) |
682 |
do j = 1, v1%propertyCount |
683 |
|
684 |
if (v1%PropertyDataType(j) .eq. integer_data_type) & |
685 |
v2%integerElementProperties(i,j) = & |
686 |
v1%integerElementProperties(i,j) |
687 |
|
688 |
if (v1%PropertyDataType(j) .eq. real_data_type) & |
689 |
v2%realElementProperties(i,j) = v1%realElementProperties(i,j) |
690 |
|
691 |
if (v1%PropertyDataType(j) .eq. logical_data_type) & |
692 |
v2%logicalElementProperties(i,j) = & |
693 |
v1%logicalElementProperties(i,j) |
694 |
enddo |
695 |
enddo |
696 |
|
697 |
do j = 1, v1%propertyCount |
698 |
v2%PropertyDescriptions(j) = v1%PropertyDescriptions(j) |
699 |
v2%PropertyDataType(j) = v1%PropertyDataType(j) |
700 |
enddo |
701 |
|
702 |
v2%elementCount = v1%elementCount |
703 |
v2%propertyCount = v1%propertyCount |
704 |
|
705 |
return |
706 |
end subroutine copyAllData |
707 |
|
708 |
function addElement(this) result (id) |
709 |
type(Vector), pointer :: this |
710 |
integer :: id |
711 |
integer :: error |
712 |
|
713 |
if (.not. associated(this)) then |
714 |
call ensureCapacityHelper(this,1,0) |
715 |
else |
716 |
call ensureCapacityHelper(this, this%elementCount + 1, this%PropertyCount) |
717 |
end if |
718 |
|
719 |
this%elementCount = this%elementCount + 1 |
720 |
|
721 |
!! We never use this and we set the entire array to the same value |
722 |
this%elementData = this%elementCount |
723 |
id = this%elementCount |
724 |
end function addElement |
725 |
|
726 |
recursive subroutine setElementPropertyReal(this, id, PropName, PropValue) |
727 |
type(Vector), pointer :: this |
728 |
integer :: id, i |
729 |
character(len=*), intent(in) :: PropName |
730 |
real( kind = 8 ), intent(in) :: PropValue |
731 |
logical :: foundit |
732 |
|
733 |
foundit = .false. |
734 |
|
735 |
! first make sure that the PropName isn't in the list of known properties: |
736 |
|
737 |
do i = 1, this%propertyCount |
738 |
if (PropName == this%PropertyDescriptions(i)) then |
739 |
foundit = .true. |
740 |
this%realElementProperties(id,i) = PropValue |
741 |
endif |
742 |
enddo |
743 |
|
744 |
if (.not.foundit) then |
745 |
call addPropertyToVector(this, PropName, real_data_type) |
746 |
call setElementPropertyReal(this, id, PropName, PropValue) |
747 |
endif |
748 |
end subroutine setElementPropertyReal |
749 |
|
750 |
recursive subroutine setElementPropertyInt(this, id, PropName, PropValue) |
751 |
type(Vector), pointer :: this |
752 |
integer :: id, i |
753 |
character(len=*), intent(in) :: PropName |
754 |
integer, intent(in) :: PropValue |
755 |
logical :: foundit |
756 |
|
757 |
foundit = .false. |
758 |
! first make sure that the PropName isn't in the list of known properties: |
759 |
do i = 1, this%propertyCount |
760 |
if (PropName == this%PropertyDescriptions(i)) then |
761 |
foundit = .true. |
762 |
this%integerElementProperties(id,i) = PropValue |
763 |
endif |
764 |
enddo |
765 |
|
766 |
if (.not.foundit) then |
767 |
call addPropertyToVector(this, PropName, integer_data_type) |
768 |
call setElementPropertyInt(this, id, PropName, PropValue) |
769 |
endif |
770 |
end subroutine setElementPropertyInt |
771 |
|
772 |
recursive subroutine setElementPropertyLogical(this, id, PropName, PropValue) |
773 |
type(Vector), pointer :: this |
774 |
integer :: id, i |
775 |
character(len=*), intent(in) :: PropName |
776 |
logical, intent(in) :: PropValue |
777 |
logical :: foundit |
778 |
|
779 |
foundit = .false. |
780 |
! first make sure that the PropName isn't in the list of known properties: |
781 |
do i = 1, this%propertyCount |
782 |
if (PropName == this%PropertyDescriptions(i)) then |
783 |
foundit = .true. |
784 |
this%logicalElementProperties(id,i) = PropValue |
785 |
endif |
786 |
enddo |
787 |
|
788 |
if (.not.foundit) then |
789 |
call addPropertyToVector(this, PropName, logical_data_type) |
790 |
call setElementPropertyLogical(this, id, PropName, PropValue) |
791 |
endif |
792 |
end subroutine setElementPropertyLogical |
793 |
|
794 |
subroutine addPropertyToVector(this, PropName, data_type) |
795 |
type(Vector), pointer :: this |
796 |
character(len=*), intent(in) :: PropName |
797 |
integer data_type |
798 |
|
799 |
call ensureCapacityHelper(this, this%elementCount, this%propertyCount + 1) |
800 |
this%propertyCount = this%propertyCount + 1 |
801 |
this%PropertyDescriptions(this%propertyCount) = PropName |
802 |
this%PropertyDataType(this%propertyCount) = data_type |
803 |
end subroutine addPropertyToVector |
804 |
|
805 |
function initialize_0i() result(this) |
806 |
type(Vector), pointer :: this |
807 |
this => initialize_2i(10, 5) |
808 |
end function initialize_0i |
809 |
|
810 |
function initialize_1i(nprop) result(this) |
811 |
integer, intent(in) :: nprop |
812 |
type(Vector), pointer :: this |
813 |
this => initialize_2i(10, nprop) |
814 |
end function initialize_1i |
815 |
|
816 |
function initialize_2i(cap, nprop) result(this) |
817 |
integer, intent(in) :: cap, nprop |
818 |
type(Vector), pointer :: this |
819 |
this => initialize_4i(cap, nprop, 0, 0) |
820 |
end function initialize_2i |
821 |
|
822 |
function initialize_3i(cap, nprop, capinc) result(this) |
823 |
integer, intent(in) :: cap, nprop, capinc |
824 |
type(Vector), pointer :: this |
825 |
this => initialize_4i(cap, nprop, capinc, 0) |
826 |
end function initialize_3i |
827 |
|
828 |
function initialize_4i(cap, nprop, capinc, propinc) result(this) |
829 |
integer, intent(in) :: cap, nprop, capinc, propinc |
830 |
integer :: error |
831 |
type(Vector), pointer :: this |
832 |
|
833 |
nullify(this) |
834 |
|
835 |
if (cap < 0) then |
836 |
write(*,*) 'Bogus Capacity:', cap |
837 |
return |
838 |
endif |
839 |
if (nprop < 0) then |
840 |
write(*,*) 'Bogus Number of Properties:', nprop |
841 |
return |
842 |
endif |
843 |
|
844 |
allocate(this,stat=error) |
845 |
if ( error /= 0 ) then |
846 |
write(*,*) 'Could not allocate Vector!' |
847 |
return |
848 |
end if |
849 |
|
850 |
this%initialCapacity = cap |
851 |
this%initialProperties = nprop |
852 |
this%capacityIncrement = capinc |
853 |
this%propertyIncrement = propinc |
854 |
|
855 |
allocate(this%elementData(this%initialCapacity), stat=error) |
856 |
if(error /= 0) write(*,*) 'Could not allocate elementData!' |
857 |
|
858 |
|
859 |
allocate(this%PropertyDescriptions(this%initialProperties), & |
860 |
stat=error) |
861 |
if(error /= 0) write(*,*) 'Could not allocate PropertyDescriptions!' |
862 |
|
863 |
allocate(this%PropertyDataType(this%initialProperties), & |
864 |
stat=error) |
865 |
if(error /= 0) write(*,*) 'Could not allocate PropertyDataType!' |
866 |
|
867 |
allocate(this%integerElementProperties(this%initialCapacity, & |
868 |
this%initialProperties), stat=error) |
869 |
if(error /= 0) write(*,*) 'Could not allocate integerElementProperties!' |
870 |
|
871 |
allocate(this%realElementProperties(this%initialCapacity, & |
872 |
this%initialProperties), stat=error) |
873 |
if(error /= 0) write(*,*) 'Could not allocate realElementProperties!' |
874 |
|
875 |
allocate(this%logicalElementProperties(this%initialCapacity, & |
876 |
this%initialProperties), stat=error) |
877 |
if(error .ne. 0) write(*,*) 'Could not allocate logicalElementProperties!' |
878 |
|
879 |
end function initialize_4i |
880 |
|
881 |
!! This function destroys the vector components.... |
882 |
function destroy(this) result(null_this) |
883 |
logical :: done |
884 |
type(Vector), pointer :: this |
885 |
type(Vector), pointer :: null_this |
886 |
|
887 |
if (.not. associated(this)) then |
888 |
null_this => null() |
889 |
return |
890 |
end if |
891 |
|
892 |
!! Walk down the list and deallocate each of the vector component |
893 |
if(associated(this%logicalElementProperties)) then |
894 |
deallocate(this%logicalElementProperties) |
895 |
this%logicalElementProperties=>null() |
896 |
endif |
897 |
if(associated(this%realElementProperties)) then |
898 |
deallocate(this%realElementProperties) |
899 |
this%realElementProperties=>null() |
900 |
endif |
901 |
if(associated(this%integerElementProperties)) then |
902 |
deallocate(this%integerElementProperties) |
903 |
this%integerElementProperties=>null() |
904 |
endif |
905 |
if(associated(this%PropertyDataType)) then |
906 |
deallocate(this%PropertyDataType) |
907 |
this%PropertyDataType=>null() |
908 |
endif |
909 |
if(associated(this%PropertyDescriptions)) then |
910 |
deallocate(this%PropertyDescriptions) |
911 |
this%PropertyDescriptions=>null() |
912 |
endif |
913 |
if(associated(this%elementData)) then |
914 |
deallocate(this%elementData) |
915 |
this%elementData=>null() |
916 |
endif |
917 |
deallocate(this) |
918 |
this => null() |
919 |
null_this => null() |
920 |
end function destroy |
921 |
|
922 |
end module Vector_class |