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, &
37 young_copy, &
39 young_end, &
41
42 type young_t
43 private
44 integer, public :: nyoung
45 integer :: nup, ndown, iyoung
46 integer, allocatable, public :: young_up(:,:)
47 integer, allocatable, public :: young_down(:,:)
48 end type young_t
49
50contains
51
52 !------------------------------------------------------------
53 subroutine young_init (this, nup, ndown)
54 integer, intent(in) :: nup, ndown
55 type(young_t), intent(inout) :: this
56
57 integer :: ipart
58
59 push_sub(young_init)
60
61 if (ndown > nup) then
62 write (message(1),'(a)') 'We only make 2-row Young diagrams with nup >= ndown'
63 call messages_fatal(1)
64 end if
65
66 this%nup = nup
67 this%ndown = ndown
68
69 this%nyoung = factorial(nup+ndown)
70 do ipart = 1, ndown
71 ! hook factor for down spin
72 this%nyoung = this%nyoung / (ndown-ipart+1)
73 ! hook factor for up spins which are paired to a down spin
74 this%nyoung = this%nyoung / (nup -ipart+2)
75 end do
76 do ipart = ndown+1, nup
77 ! hook factor for unpaired up spins
78 this%nyoung = this%nyoung / (nup -ipart+1)
79 end do
80
81 safe_allocate(this%young_up (1:nup, 1:this%nyoung))
82 safe_allocate(this%young_down(1:ndown,1:this%nyoung))
83
84 this%young_up(:, :) = -999
85 this%young_down(:, :) = -999
86
87 this%iyoung = 1
88 call young_fill (this, nup+ndown)
89
90 pop_sub(young_init)
91 end subroutine young_init
92
93
94 !------------------------------------------------------------
95 recursive subroutine young_fill (this, nn)
96 integer, intent(in) :: nn
97 type(young_t), intent(inout) :: this
98
99 integer :: idown, iup
100 push_sub(young_fill)
101
102 if (this%iyoung > this%nyoung) then
103 pop_sub(young_fill)
104 return
105 end if
106
107 ! find next lower right hand corner, in the down spins
108 do idown = this%ndown, 1, -1
109 if (this%young_down(idown, this%iyoung) == -999) then
110 this%young_down(idown, this%iyoung) = nn
111 ! call again with smaller diagram
112 if (nn > 1) then
113 call young_fill (this, nn-1)
114 else
115 this%iyoung = this%iyoung+1
116 if (this%iyoung <= this%nyoung) then
117 this%young_up(:,this%iyoung) = this%young_up(:,this%iyoung-1)
118 this%young_down(:,this%iyoung) = this%young_down(:,this%iyoung-1)
119 call young_reset_1val (this, 0)
120 end if
121 end if
122 exit
123 end if
124 end do
125
126 if (this%iyoung > this%nyoung) then
127 pop_sub(young_fill)
128 return
129 end if
130
131 ! find next lower right hand corner, in the up spins
132 do iup = this%nup, 1, -1
133 if (this%young_up(iup, this%iyoung) == -999) then
134 ! either in the unpaired spins
135 if (iup > this%ndown) then
136 this%young_up(iup, this%iyoung) = nn
137 ! call again with smaller diagram
138 if (nn > 1) then
139 call young_fill (this, nn-1)
140 else
141 this%iyoung = this%iyoung+1
142 if (this%iyoung <= this%nyoung) then
143 this%young_up(:,this%iyoung) = this%young_up(:,this%iyoung-1)
144 this%young_down(:,this%iyoung) = this%young_down(:,this%iyoung-1)
145 call young_reset_1val (this, 0)
146 end if
147 end if
148 ! or in the paired spins, provided the box below has been filled
149 else if (this%young_down(iup, this%iyoung) /= -999) then
150 this%young_up(iup, this%iyoung) = nn
151 ! call again with smaller diagram
152 if (nn > 1) then
153 call young_fill (this, nn-1)
154 else
155 this%iyoung = this%iyoung+1
156 if (this%iyoung <= this%nyoung) then
157 this%young_up(:,this%iyoung) = this%young_up(:,this%iyoung-1)
158 this%young_down(:,this%iyoung) = this%young_down(:,this%iyoung-1)
159 call young_reset_1val (this, 0)
160 end if
161 end if
162 end if
163 exit
164 end if
165 end do
166
167 if (this%iyoung > this%nyoung) then
168 pop_sub(young_fill)
169 return
170 end if
171
172 call young_reset_1val (this, nn)
173
174!
175! if (all(this%young_up(:,this%iyoung) /= nn) .and. all(this%young_down(:,this%iyoung) /= nn)) then
176! write (message(1),'(a,I7,a)') 'nn = ', nn, ' was not attributed to any box- this should not happen!'
177! call messages_fatal(1, namespace=namespace)
178! end if
179
180 pop_sub(young_fill)
181 end subroutine
182
183
184 !------------------------------------------------------------
185 subroutine young_reset_1val (this, nn)
186 type(young_t), intent(inout) :: this
187 integer, intent(in) :: nn
189 integer :: iup, idown
190
191 push_sub(young_reset_1val)
192
193 ! remove last entry in new diagram
194 do iup = 1, this%nup
195 if (this%young_up(iup,this%iyoung) == nn+1) this%young_up(iup,this%iyoung) = -999
196 end do
197 do idown = 1, this%ndown
198 if (this%young_down(idown,this%iyoung) == nn+1) this%young_down(idown,this%iyoung) = -999
199 end do
200
201 pop_sub(young_reset_1val)
202 end subroutine young_reset_1val
203
204
205 !------------------------------------------------------------
206 subroutine young_write (iunit, this)
207 integer, intent(in) :: iunit
208 type(young_t), intent(inout) :: this
209
210 integer :: iyoung
211
212 push_sub(young_write)
213
214 write (iunit, '(a,I4,a,I4,a)') ' Young diagrams for ', this%nup, ' spins up, and ', this%ndown, ' down '
215 do iyoung = 1, this%nyoung
216 call young_write_one (iunit, this, iyoung)
217 end do
218
219 pop_sub(young_write)
220 end subroutine young_write
221
222
223 !------------------------------------------------------------
224 subroutine young_write_one (iunit, this, iyoung)
225 integer, intent(in) :: iunit
226 type(young_t), intent(inout) :: this
227
228 integer, intent(in) :: iyoung
229
230 push_sub(young_write_one)
231
232 write (iunit,'(a,I7)') ' Young diagram ', iyoung
233 write (iunit,'(10I7)') this%young_up(:, iyoung)
234 write (iunit,'(10I7)') this%young_down(:, iyoung)
235
236 pop_sub(young_write_one)
237 end subroutine young_write_one
238
239
240 !------------------------------------------------------------
242 subroutine young_write_allspins (iunit, nparticles)
243 integer, intent(in) :: iunit, nparticles
244 integer :: nup, ndown
245 type(young_t) :: this
246
247 push_sub(young_write_allspins)
248
249 do ndown = 0, floor(nparticles * m_half)
250 nup = nparticles - ndown
251 call young_init (this, nup, ndown)
252 call young_write (iunit, this)
253 call young_end (this)
254 end do
255 pop_sub(young_write_allspins)
256
257 end subroutine young_write_allspins
258
259 !------------------------------------------------------------
260 subroutine young_ndiagrams (nparticles, ndiagrams)
261 integer, intent(in) :: nparticles
262 integer, intent(out) :: ndiagrams
263 integer :: nup, ndown
264 type(young_t) :: this
265
266 push_sub(young_ndiagrams)
267
268 ndiagrams = 0
269 do ndown = 0, floor(nparticles * m_half)
270 nup = nparticles - ndown
271 call young_init (this, nup, ndown)
272 ndiagrams = ndiagrams + this%nyoung
273 call young_end (this)
274 end do
275
276 pop_sub(young_ndiagrams)
277
278 end subroutine young_ndiagrams
279
280
281 !------------------------------------------------------------
282 subroutine young_copy (young_in, young_out)
283 type(young_t), intent(inout) :: young_in, young_out
284
285 push_sub(young_copy)
286
287 young_out%nup = young_in%nup
288 young_out%ndown = young_in%ndown
289 young_out%nyoung = young_in%nyoung
290
291 safe_allocate_source_a(young_out%young_up,young_in%young_up)
292 safe_allocate_source_a(young_out%young_down,young_in%young_down)
293
294 pop_sub(young_copy)
295 end subroutine young_copy
296
297
298 !------------------------------------------------------------
299 subroutine young_end (this)
300 type(young_t), intent(inout) :: this
301
302 push_sub(young_end)
303
304 safe_deallocate_a(this%young_up)
305 safe_deallocate_a(this%young_down)
306
307 pop_sub(young_end)
308 end subroutine young_end
309
310end module young_oct_m
311
312!! Local Variables:
313!! mode: f90
314!! coding: utf-8
315!! End:
double floor(double __x) __attribute__((__nothrow__
real(real64), parameter, public m_half
Definition: global.F90:193
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:115
recursive integer function, public factorial(n)
Definition: math.F90:285
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
subroutine, public young_copy(young_in, young_out)
Definition: young.F90:376
subroutine, public young_end(this)
Definition: young.F90:393
subroutine, public young_init(this, nup, ndown)
Definition: young.F90:147
recursive subroutine young_fill(this, nn)
Definition: young.F90:189
subroutine young_reset_1val(this, nn)
Definition: young.F90:279
subroutine, public young_ndiagrams(nparticles, ndiagrams)
Definition: young.F90:354
subroutine, public young_write_one(iunit, this, iyoung)
Definition: young.F90:318
subroutine, public young_write(iunit, this)
Definition: young.F90:300
subroutine, public young_write_allspins(iunit, nparticles)
routine gets all Young diagrams for all distributions of spins
Definition: young.F90:336