Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
thermal_soln.f90
Go to the documentation of this file.
1 !!****
2 !!
3 !! NAME
4 !! thermal_soln
5 !!
6 !! FUNCTION
7 !! This subroutine computes the thermal solution
8 !! at t=t+dt using the beta method.
9 !!
10 !! INPUTS
11 !! delt -- Length of one timestep
12 !! t -- Current timestep
13 !! rext_in -- External loads
14 !! global -- Holds all global quantities
15 !!
16 !! OUTPUTS
17 !! none
18 !!
19 !! USES
20 !! MPI
21 !!
22 !!****
23 
24 
25 SUBROUTINE thermal_soln(delt,t,rext_in,global,istep)
26 
27  USE implicit_global
28  USE comp_row_global
29  USE precision
31 
32  IMPLICIT NONE
33 
34  include 'mpif.h'
35 
36  ! ... variables
37  TYPE(rocfrac_global) :: global
38  REAL(kind=wp) :: delt, t
39  REAL(kind=wp), DIMENSION(1:global%NumNp) :: rext_in
40  INTEGER :: istep
41 
42  ! ... local variables
43  INTEGER :: bs95debug
44  INTEGER :: i, j, k, m, n, p, counter, ii
45  INTEGER :: newnrows_ceff, newnstart_ceff, newndim
46  REAL(kind=wp) :: contol, beta
47  REAL(kind=wp), DIMENSION(1:LNumNp) :: rint, rint2, rext_new, temp, reff
48  REAL(kind=wp), ALLOCATABLE, DIMENSION(:) :: newreff, newtemp
49  REAL(kind=wp), ALLOCATABLE, DIMENSION(:) :: bufsnd, ftemp
50  REAL(wp) :: per1, delay
51 
52 
53  ! ... Initialize
54  rint(:) = 0.0
55  rint2(:) = 0.0
56  temp(:) = 0.0
57  contol = 1.0e-09
58  beta = .5
59 
60  IF ( global%debug_state ) THEN
61  bs95debug = 1
62  ELSE
63  bs95debug = 0
64  END IF
65 
66  ! ... Assemble the temperature and load vectors
67  ! ... loop through all node points
68  DO i = 1, global%NumNp
69  ! ... if a node belongs to the current process
70  IF ( nodeproc(i) == myid ) THEN
71  ! ... k is the row index for the given node
72  k = local2global(i) - nstart_ktc + 1
73 
74  ! ... rext_new are external thermal loads for the timestep currently being calculated
75  rext_new( k ) = rext_in( i )
76 
77  ! ... temperature at each node at last timestep
78  temp( k ) = global%Temperature( i )
79 
80  END IF
81  END DO
82 
83  ! ... Output list of nodal temperatures
84 ! if (real(istep/10) == real(istep)/10) CALL RockOut_8node(global,istep)
85 ! if (istep < 31) CALL RockOut_8node(global,istep)
86  If (ALLOCATED(r_old) .eqv. .false.) then
87  ALLOCATE(rext_imp(lnumnp),r_old(lnumnp))
88  rext_imp = 0.0
89  r_old = 0.0
90  endif
91 
92 
93 
94  ! ... if it is the first timestep, then compute the effective capacitance matrix and
95  ! ... apply the boundary conditions.
96  ! ... this will only be done once unless
97  ! ... (1) the imposed temperature boundary conditions change
98  ! ... (2) the timestep changes
99  ! ... (3) the material properties change
100  IF (istep == 1) THEN
101 
102  IF(ALLOCATED(aval_ceff).EQV. .true.) DEALLOCATE(aval_ceff)
103  IF(ALLOCATED(cval_ceff).EQV. .true.) DEALLOCATE(cval_ceff)
104  IF(ALLOCATED(rp_ceff).EQV. .true.) DEALLOCATE(rp_ceff)
105  IF(ALLOCATED(ceff_fptp).EQV. .true.) DEALLOCATE(ceff_fptp)
106 
107 
108 
109  ! ... Create the effective capacitance matrix
110  !
111  !
112  ! m_eff = (1/dt * C + beta * K)
113  !
114  !
115 
116  print*,'FORMING EFFECTIVE CAPACITANCE MATRIX',myid
117 
118  ! ... For some reason, the first GNumNp is not used at all in 'comp_row_add'
119  ! ... The ouput from 'comp_row_add are stored in the global variables ..._temp
120  CALL comp_row_add(gnumnp,gnumnp,nrows_ktc,nrows_ktc,nnz_kt,nnz_c,1, &
121  rp_kt,cval_kt,beta*aval_kt,1,rp_c,cval_c,(1/delt)*aval_c)
122 
123  ALLOCATE(rp_ceff(nrows_ktc+1),cval_ceff(nnz_temp),aval_ceff(nnz_temp))
124 
125  ! ... compressed row vectors for the effective capacitance matrix
126  ! ... the vectors are stored under the global variables ..._ceff (implicit_global.f90)
127  nnz_ceff = nnz_temp
128  nstart_ceff = nstart_ktc
129  nrows_ceff = nrows_ktc
130  rp_ceff = rp_temp
131  cval_ceff = cval_temp
132  aval_ceff = aval_temp
133  DEALLOCATE(rp_temp,cval_temp,aval_temp)
134 
135  ! ... Enforce imposed temperature boundary conditions.
136  CALL enforcethermalbc(global%NumNp,lnumnp,temp,node_flag,boundary_value,0,myid)
137 
138  ! ... partition effective capacitance matrix into CeffFF, CeffPP, CeffFP.
139  ! ... multiply CeffFP by the prescribed temperatures
140  CALL partition_ceff(gnumnp,nrows_ceff,nnz_ceff,nstart_ceff,rp_ceff,cval_ceff,aval_ceff, &
141  newnrows_ceff,newnstart_ceff,newndim,temp,global)
142 
143  ! ... deallocate effective capacitance matrix, dimensions have changed after BCs removed
144 
145  DEALLOCATE(rp_ceff,cval_ceff,aval_ceff)
146 
147  ! ... position and size of local effective capacitance matrix have changed due to BC's applied
148  ! ... to global matrix
149  nrows_ceff = newnrows_ceff
150  nstart_ceff = newnstart_ceff
151 
152  ! ... reallocate local effective capacitance matrix to new dimensions, and assign new values
153  ALLOCATE(rp_ceff(nrows_ceff+1),cval_ceff(nnz_temp),aval_ceff(nnz_temp))
154  nnz_ceff = nnz_temp
155  rp_ceff = rp_temp
156  cval_ceff = cval_temp
157  aval_ceff = aval_temp
158  DEALLOCATE(rp_temp,cval_temp,aval_temp)
159 
160  CALL bs95setup(gnumnp,nnz_ceff,nstart_ceff-1,nrows_ceff,rp_ceff,cval_ceff,aval_ceff,1,bs95debug)
161  ENDIF
162 
163  ! ... initialize thermal load vectors
164  rint(:) = 0.0
165  rint2(:) = 0.0
166  reff(:) = 0.0
167 
168 
169  ! ... Calculate internal thermal loads at time = t
170  !
171  ! .
172  ! (1/dt * C - (1-beta) * K) * Temp
173  ! k
174  !
175  ! where C: thermal capacitance, K: thermal stiffness, dt: timestep,
176  ! Temp : temperature at timestep k
177  ! k
178  !
179 
180  ! ... calculate rint = [-(1-beta) * K] * Temp
181  CALL intload(gnumnp,nrows_ktc,nnz_kt,nstart_ktc,rp_kt,cval_kt,(-1.0*(1.0-beta)*aval_kt),temp,rint)
182 
183  ! ... calculate rint2 = [1/dt * C] * Temp
184  CALL intload(gnumnp,nrows_ktc,nnz_kt,nstart_ktc,rp_c,cval_c,1/delt*aval_c,temp,rint2)
185 
186 
187  ! ... Apply boundary conditions
188  counter=0
189  DO m = 1, gnumnp
190  DO i = 1, global%NumNp
191  IF (local2global(i) == m) THEN
192  IF (nodeproc(i) == myid) THEN
193  counter = counter + 1
194  IF(node_flag(i,1) == 7) THEN
195  ! ... imposed heat flux in wall normal
196  ! ... direction flowing into the solid
197  rext_imp(counter) = boundary_value(i,1)
198  ENDIF
199  ENDIF
200  ENDIF
201  ENDDO
202  ENDDO
203 
204 
205 
206  ! ... Construct the effective load vector
207  !
208  !
209  ! reff = (1/dt * C - (1-beta) * K) * Temp + (1-beta) * R + beta * R
210  ! k k k+1
211  !
212  !
213  !
214  ! where R = rext_new (time varying load) + rext_imp (load from input file)
215  ! k+1
216  !
217 
218  reff = rint + rint2 +(1.0 - beta) * r_old + beta * (rext_new + rext_imp)
219 
220  ! ... the current load vector is stored in r_old for the calculation at
221  ! ... the next timestep.
222  r_old = (rext_new + rext_imp)
223 
224  ! Allocate shortened arrays
225  ALLOCATE(newreff(1:nrows_ceff))
226  ALLOCATE(newtemp(1:nrows_ceff))
227 
228  ! ... Initialize newTemp
229  newtemp(:) = 0.0d0
230 
231  ! ... Remove rows from the effective load vector that are constrained by displacement BC's
232  CALL removebcht_reff(nstart_ktc,lnumnp,reff,nrows_ceff,newreff)
233 
234  newreff(:) = newreff(:) - ceff_fptp(:)
235 
236 
237 
238  !
239  ! Solve for nodal temperatures at time t + Dt
240  !
241  ! C Temp = R
242  ! k+1 k+1
243  !
244 
245  ! ... Solve using BlockSolve95 functions
246 
247 
248 
249  CALL bs95solve(nrows_ceff,newreff,newtemp,contol,bs95debug)
250 
251 ! CALL BS95FREE(BS95debug)
252 
253 
254  ! ... Put newTemp back into Temp, the full temperature vector for this process
255  ! ... without BCs missing
256  CALL removebcht_newtemp(nstart_ktc,lnumnp,temp,nrows_ceff,newtemp)
257 
258  ! Deallocate shortened arrays
259 
260  DEALLOCATE(newreff)
261  DEALLOCATE(newtemp)
262 
263 
264 
265 
266  IF(myid==0) print*,'ASSEMBLING NEW TEMPERATURE VECTOR'
267 
268 
269 
270  ! ... Put the vectors back into their Rocfrac equivalent vectors
271 
272  DO i = 1, global%NumNp
273  IF ( nodeproc(i) == myid ) THEN
274  k = local2global(i) - nstart_ktc + 1
275  global%Temperature( i ) = temp( k )
276  END IF
277  END DO
278 
279  ! ... Communicate variables to other processors and assemble
280 
281  IF (nprocs > 1) THEN
282 
283  ! clear the status and request vars
284  CALL mpi_barrier(rocstar_communicator,ierr)
285  ALLOCATE(req_rcv(1:nprocs))
286  ALLOCATE(req_snd(1:nprocs))
287  ALLOCATE(stat_snd(1:mpi_status_size,1:nprocs))
288  ALLOCATE(stat_rcv(1:mpi_status_size,1:nprocs))
289  DO i = 1, nprocs
290  req_rcv(i) = 0
291  req_snd(i) = 0
292  DO j = 1, mpi_status_size
293  stat_rcv(1,i) = 0
294  stat_snd(j,i) = 0
295  ENDDO
296  ENDDO
297 
298  ! ... receive from other procs
299  ! ... Allocate a buffer of size 2 times the number of nodes from
300  ! ... processor i. The buffer is orgnized as {node #, temp, node #, temp...}
301  CALL mpi_barrier(rocstar_communicator,ierr)
302  ALLOCATE(frmproc(1:numcommprocsfrom2))
303  DO i = 1, numcommprocsfrom2
304  ALLOCATE(frmproc(i)%rcvbuf(1:2*numcommnodesfrom2(i)))
305  CALL mpi_irecv(frmproc(i)%rcvbuf(1),2*numcommnodesfrom2(i), &
306  mpi_double_precision,commprocsfrom2(i),10,rocstar_communicator, &
307  req_rcv(i),ierr)
308  ENDDO
309 
310  ! ... Send to the other processes, the number of which is NumCommProcs2
311  ! ... Allocate a buffer of size 2 times the number of nodes going to
312  ! ... process i. The buffer is orgnized as {node #, temp, node #, temp...}
313  DO i = 1, numcommprocs2
314  ALLOCATE(bufsnd(1:2*numcommnodes2(i)))
315  counter = 0
316  DO j = 1, numcommnodes2(i)
317  counter = counter + 1
318  bufsnd(counter) = 1.0 * commnodes2(i,j)
319  ! ... k is the local node number that corresponds to the global node number
320  ! ... that this process is sending to process i. This processor has j nodes
321  ! ... to send to process i.
322  k = global2local(commnodes2(i,j))
323  counter = counter + 1
324  bufsnd(counter) = global%Temperature( k )
325  ENDDO
326  CALL mpi_send(bufsnd(:),2*numcommnodes2(i),mpi_double_precision, &
327  commprocs2(i),10,rocstar_communicator,ierr)
328  DEALLOCATE(bufsnd)
329  ENDDO
330  CALL mpi_waitall(nprocs,req_rcv,stat_rcv,ierr)
331 
332  ! ... deallocate status and request vars
333  DEALLOCATE(req_rcv)
334  DEALLOCATE(req_snd)
335  DEALLOCATE(stat_snd)
336  DEALLOCATE(stat_rcv)
337 
338  ! ... assemble into Rocfrac nodal variable vectors
339  ! ... loop through all processes from which this process has received information
340  DO i = 1, numcommprocsfrom2
341  counter = 0
342  ! ... loop through the number of nodes that were sent to this process
343  ! ... process i
344  DO j = 1, numcommnodesfrom2(i)
345  counter = counter + 1
346  ! ... frmproc(i)%rcvbuf(1+2*(j-1)) is the global node number of the informaition
347  ! ... frmproc(i)%rcvbuf(2*j)
348  k = global2local( int( frmproc(i)%rcvbuf(counter) ) ) ! local index of node
349  counter = counter + 1
350  global%Temperature( k ) = frmproc(i)%rcvbuf(counter)
351  END DO
352  END DO
353 
354  ! ... clear the receive buffer
355  DEALLOCATE(frmproc)
356 
357  ! ... Deallocate effective capacitance matrices for the current
358  ! ... timestep.
359 
360 
361  ENDIF
362 
363 
364 ! if (real(istep/10) == real(istep)/10 ) CALL RockOut_8node(global,istep)
365 
366 END SUBROUTINE thermal_soln
FT m(int i, int j) const
subroutine enforcethermalbc(NumNp, LocNumNp, Temp, node_flag, boundary_value, t, myid)
j indices k indices k
Definition: Indexing.h:6
subroutine comp_row_add(ndim, gndim, nrows1, nrows2, nnz1, nnz2, nstart1, rp1, cval1, aval1, nstart2, rp2, cval2, aval2)
blockLoc i
Definition: read.cpp:79
const NT & n
subroutine intload(ndim, nrows, nnz, nstart, rp, cval, aval, tempin, rint)
Definition: IntLoad.f90:30
virtual std::ostream & print(std::ostream &os) const
subroutine partition_ceff(ndim, nrows, nnz, nstart, rp1, cval, aval, newnrows, newnstart, newndim, ProcTemp, global)
j indices j
Definition: Indexing.h:6
subroutine removebcht_reff(nstart, ndim, pbar, newndim, newpbar)
Definition: RemoveBCHT.f90:26
subroutine removebcht_newtemp(nstart, ndim, a, newndim, newa)
Definition: RemoveBCHT.f90:95
subroutine thermal_soln(delt, t, rext_in, global, istep)