Octopus
young.F90
Go to the documentation of this file.
1!! Copyright (C) 2009 M. Verstraete
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21module young_oct_m
22 use debug_oct_m
23 use global_oct_m
24 use math_oct_m
27
28 implicit none
29
30 private
31
32 public :: &
33 young_init, &
38 young_end, &
40
41 type young_t
42 private
43 integer, public :: nyoung
44 integer :: nup, ndown, iyoung
45 integer, allocatable, public :: young_up(:,:)
46 integer, allocatable, public :: young_down(:,:)
47 end type young_t
48
49contains
50
51 !------------------------------------------------------------
52 subroutine young_init (this, nup, ndown)
53 integer, intent(in) :: nup, ndown
54 type(young_t), intent(inout) :: this
55
56 integer :: ipart
57
58 push_sub(young_init)
59
60 if (ndown > nup) then
61 write (message(1),'(a)') 'We only make 2-row Young diagrams with nup >= ndown'
62 call messages_fatal(1)
63 end if
64
65 this%nup = nup
66 this%ndown = ndown
67
68 this%nyoung = factorial(nup+ndown)
69 do ipart = 1, ndown
70 ! hook factor for down spin
71 this%nyoung = this%nyoung / (ndown-ipart+1)
72 ! hook factor for up spins which are paired to a down spin
73 this%nyoung = this%nyoung / (nup -ipart+2)
74 end do
75 do ipart = ndown+1, nup
76 ! hook factor for unpaired up spins
77 this%nyoung = this%nyoung / (nup -ipart+1)
78 end do
79
80 safe_allocate(this%young_up (1:nup, 1:this%nyoung))
81 safe_allocate(this%young_down(1:ndown,1:this%nyoung))
82
83 this%young_up(:, :) = -999
84 this%young_down(:, :) = -999
85
86 this%iyoung = 1
87 call young_fill (this, nup+ndown)
88
89 pop_sub(young_init)
90 end subroutine young_init
91
92
93 !------------------------------------------------------------
94 recursive subroutine young_fill (this, nn)
95 integer, intent(in) :: nn
96 type(young_t), intent(inout) :: this
97
98 integer :: idown, iup
99 push_sub(young_fill)
100
101 if (this%iyoung > this%nyoung) then
102 pop_sub(young_fill)
103 return
104 end if
105
106 ! find next lower right hand corner, in the down spins
107 do idown = this%ndown, 1, -1
108 if (this%young_down(idown, this%iyoung) == -999) then
109 this%young_down(idown, this%iyoung) = nn
110 ! call again with smaller diagram
111 if (nn > 1) then
112 call young_fill (this, nn-1)
113 else
114 this%iyoung = this%iyoung+1
115 if (this%iyoung <= this%nyoung) then
116 this%young_up(:,this%iyoung) = this%young_up(:,this%iyoung-1)
117 this%young_down(:,this%iyoung) = this%young_down(:,this%iyoung-1)
118 call young_reset_1val (this, 0)
119 end if
120 end if
121 exit
122 end if
123 end do
124
125 if (this%iyoung > this%nyoung) then
126 pop_sub(young_fill)
127 return
128 end if
129
130 ! find next lower right hand corner, in the up spins
131 do iup = this%nup, 1, -1
132 if (this%young_up(iup, this%iyoung) == -999) then
133 ! either in the unpaired spins
134 if (iup > this%ndown) then
135 this%young_up(iup, this%iyoung) = nn
136 ! call again with smaller diagram
137 if (nn > 1) then
138 call young_fill (this, nn-1)
139 else
140 this%iyoung = this%iyoung+1
141 if (this%iyoung <= this%nyoung) then
142 this%young_up(:,this%iyoung) = this%young_up(:,this%iyoung-1)
143 this%young_down(:,this%iyoung) = this%young_down(:,this%iyoung-1)
144 call young_reset_1val (this, 0)
145 end if
146 end if
147 ! or in the paired spins, provided the box below has been filled
148 else if (this%young_down(iup, this%iyoung) /= -999) then
149 this%young_up(iup, this%iyoung) = nn
150 ! call again with smaller diagram
151 if (nn > 1) then
152 call young_fill (this, nn-1)
153 else
154 this%iyoung = this%iyoung+1
155 if (this%iyoung <= this%nyoung) then
156 this%young_up(:,this%iyoung) = this%young_up(:,this%iyoung-1)
157 this%young_down(:,this%iyoung) = this%young_down(:,this%iyoung-1)
158 call young_reset_1val (this, 0)
159 end if
160 end if
161 end if
162 exit
163 end if
164 end do
165
166 if (this%iyoung > this%nyoung) then
167 pop_sub(young_fill)
168 return
169 end if
170
171 call young_reset_1val (this, nn)
172
173!
174! if (all(this%young_up(:,this%iyoung) /= nn) .and. all(this%young_down(:,this%iyoung) /= nn)) then
175! write (message(1),'(a,I7,a)') 'nn = ', nn, ' was not attributed to any box- this should not happen!'
176! call messages_fatal(1, namespace=namespace)
177! end if
178
179 pop_sub(young_fill)
180 end subroutine
181
182
183 !------------------------------------------------------------
184 subroutine young_reset_1val (this, nn)
185 type(young_t), intent(inout) :: this
186 integer, intent(in) :: nn
187
188 integer :: iup, idown
190 push_sub(young_reset_1val)
191
192 ! remove last entry in new diagram
193 do iup = 1, this%nup
194 if (this%young_up(iup,this%iyoung) == nn+1) this%young_up(iup,this%iyoung) = -999
195 end do
196 do idown = 1, this%ndown
197 if (this%young_down(idown,this%iyoung) == nn+1) this%young_down(idown,this%iyoung) = -999
198 end do
199
200 pop_sub(young_reset_1val)
201 end subroutine young_reset_1val
202
203
204 !------------------------------------------------------------
205 subroutine young_write (iunit, this)
206 integer, intent(in) :: iunit
207 type(young_t), intent(inout) :: this
208
209 integer :: iyoung
210
211 push_sub(young_write)
212
213 write (iunit, '(a,I4,a,I4,a)') ' Young diagrams for ', this%nup, ' spins up, and ', this%ndown, ' down '
214 do iyoung = 1, this%nyoung
215 call young_write_one (iunit, this, iyoung)
216 end do
217
218 pop_sub(young_write)
219 end subroutine young_write
220
221
222 !------------------------------------------------------------
223 subroutine young_write_one (iunit, this, iyoung)
224 integer, intent(in) :: iunit
225 type(young_t), intent(inout) :: this
226
227 integer, intent(in) :: iyoung
228
229 push_sub(young_write_one)
230
231 write (iunit,'(a,I7)') ' Young diagram ', iyoung
232 write (iunit,'(10I7)') this%young_up(:, iyoung)
233 write (iunit,'(10I7)') this%young_down(:, iyoung)
234
235 pop_sub(young_write_one)
236 end subroutine young_write_one
237
238
239 !------------------------------------------------------------
241 subroutine young_write_allspins (iunit, nparticles)
242 integer, intent(in) :: iunit, nparticles
243 integer :: nup, ndown
244 type(young_t) :: this
245
246 push_sub(young_write_allspins)
247
248 do ndown = 0, floor(nparticles * m_half)
249 nup = nparticles - ndown
250 call young_init (this, nup, ndown)
251 call young_write (iunit, this)
252 call young_end (this)
253 end do
254 pop_sub(young_write_allspins)
255
256 end subroutine young_write_allspins
257
258 !------------------------------------------------------------
259 subroutine young_ndiagrams (nparticles, ndiagrams)
260 integer, intent(in) :: nparticles
261 integer, intent(out) :: ndiagrams
262 integer :: nup, ndown
263 type(young_t) :: this
264
265 push_sub(young_ndiagrams)
266
267 ndiagrams = 0
268 do ndown = 0, floor(nparticles * m_half)
269 nup = nparticles - ndown
270 call young_init (this, nup, ndown)
271 ndiagrams = ndiagrams + this%nyoung
272 call young_end (this)
273 end do
274
275 pop_sub(young_ndiagrams)
276
277 end subroutine young_ndiagrams
278
279 !------------------------------------------------------------
280 subroutine young_end (this)
281 type(young_t), intent(inout) :: this
282
283 push_sub(young_end)
284
285 safe_deallocate_a(this%young_up)
286 safe_deallocate_a(this%young_down)
287
288 pop_sub(young_end)
289 end subroutine young_end
290
291end module young_oct_m
292
293!! Local Variables:
294!! mode: f90
295!! coding: utf-8
296!! End:
double floor(double __x) __attribute__((__nothrow__
real(real64), parameter, public m_half
Definition: global.F90:197
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
recursive integer function, public factorial(n)
Definition: math.F90:289
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:161
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:409
subroutine, public young_end(this)
Definition: young.F90:376
subroutine, public young_init(this, nup, ndown)
Definition: young.F90:148
recursive subroutine young_fill(this, nn)
Definition: young.F90:190
subroutine young_reset_1val(this, nn)
Definition: young.F90:280
subroutine, public young_ndiagrams(nparticles, ndiagrams)
Definition: young.F90:355
subroutine, public young_write_one(iunit, this, iyoung)
Definition: young.F90:319
subroutine, public young_write(iunit, this)
Definition: young.F90:301
subroutine, public young_write_allspins(iunit, nparticles)
routine gets all Young diagrams for all distributions of spins
Definition: young.F90:337