Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LocThermCap_v3d8.f90
Go to the documentation of this file.
1 
2 !!****
3 !!
4 !! NAME
5 !! LocThermCap_v3d8
6 !!
7 !! FUNCTION
8 !! This subroutine constructs the process local capacitance matrix
9 !! for volumetric stess 8 node, 3d elements as a consistent matrix.
10 !! The resulting matrix is put into the variables in comp_row_global.
11 !!
12 !! INPUTS
13 !! NumEl -- The number of elements that this processor knows about
14 !! NumNp -- The number of nodes that this processor knows about
15 !! NumMat -- The global number of materials in the structure
16 !! coor -- The coordinates of each of the nodes
17 !! nodes -- The connectivity table
18 !! MatType -- Mapping of material types to elements
19 !! ri -- Gauss point positions within an element
20 !! rho -- Density of the materials
21 !! cap -- Specific heat capacity of the materials
22 !! ElConnVol -- The connectivity table (redundant)
23 !!
24 !! OUTPUTS
25 !! none
26 !!
27 !! USES
28 !! none
29 !!
30 !!****
31 
32 SUBROUTINE locthermcap_v3d8( NumEl, NumNP, NumMat, &
33  coor, nodes, mattype, ri, rho, cap, elconnvol )
34 
35  USE precision
36  USE implicit_global
37  USE comp_row_global
39 
40  IMPLICIT NONE
41 
42  include 'mpif.h'
43 
44  ! ... Input variables
45  INTEGER :: numel, numnp, nummat
46  INTEGER, DIMENSION(1:NumEl) :: mattype
47  INTEGER, DIMENSION(1:8,1:NumEl) :: nodes
48  REAL(KIND=wp), DIMENSION(1:3,1:NumNP) :: coor
49  REAL(KIND=wp), DIMENSION(1:3,1:8) :: ri
50  REAL(KIND=wp), DIMENSION(1:NumMat) :: rho, cap
51  INTEGER, DIMENSION(1:8,1:NumEl) :: elconnvol
52 
53  ! ... Internal variables
54  REAL(kind=wp), DIMENSION(1:8) :: n
55  REAL(kind=wp), DIMENSION(1:8,1:3) :: dn
56  REAL(kind=wp), DIMENSION(1:8,1:8) :: ntn
57  INTEGER :: igpt
58  INTEGER :: ngpts = 8
59  INTEGER :: ielem
60  INTEGER :: imat
61  INTEGER :: i, j, k, l, tempi, tempj
62  INTEGER :: dof1, dof2, gdof1, gdof2, ldof1, ldof2
63  REAL(kind=wp) :: tempval, tempval2, tempval3
64  INTEGER :: nnzold
65  REAL(kind=wp) :: element_volume
66  REAL(kind=wp), DIMENSION(1:3,1:3) :: jac, jacinv
67  REAL(kind=wp) :: detj
68  ! ... diag_width is the max number of non-zero elements expected in a row
69  ! ... in the global capacitance matrix. There might be some algorithm to determine that a
70  ! ... priori. But right now its set to 30
71  INTEGER :: diag_width = 30
72  REAL(kind=wp) :: t1,t2,t3,t4
73  LOGICAL :: error
74  INTEGER :: n1,n2,n3,n4,n5,n6,n7,n8
75  REAL(kind=wp),DIMENSION(1:3,1:8) :: coordtmp
76  INTEGER,DIMENSION(1:8) :: l2g_temp
77 
78  ! ... Output variables
79  INTEGER, ALLOCATABLE, DIMENSION(:) :: rp, cval
80  REAL(KIND=wp), ALLOCATABLE, DIMENSION(:) :: aval
81  REAL(kind=wp), ALLOCATABLE, DIMENSION(:,:) :: glmassmat
82 
83  ! ... 'values' and 'col_index' are the vectors 'aval' and 'cval'
84  ! ... respectively. Their size is also allocated using diag_width
85  REAL(kind=wp), ALLOCATABLE, DIMENSION(:) :: values
86  INTEGER, ALLOCATABLE, DIMENSION(:) :: col_index
87  INTEGER :: nnz
88 
89 
90  ! ... Initialize the output variables
91 
92  ! ALLOCATE(rp(1:3*GNumNp+1))
93  ! ALLOCATE(cval(1:1))
94  ! ALLOCATE(aval(1:1))
95  ! ALLOCATE(GlMassMat(1:3*GNumNp,1:3*GNumNp))
96 
97  ! ... allocate enough memory of the values, col_index (=aval,cval)
98  ! ... vectors to hold diag_width values for each row of the
99  ! ... explicit mass matrix.
100  ALLOCATE(values(1:gnumnp*diag_width))
101  ALLOCATE(col_index(1:gnumnp*diag_width))
102 
103 
104 
105  nnz = 1
106  ! rp(1) = 0
107  !rp(2:3*GNumNp+1) = 1
108  ! cval(1) = 0
109  ! aval(1) = 0.0
110  !GlMassMat(:,:)=0.0
111  col_index(:)=-1
112  values(:)=0.0
113 
114  ! PRINT*,'Entering Do loop', myid
115  CALL mpi_barrier(rocstar_communicator,ierr)
116  CALL cpu_time(t1)
117  ! Loop through the elements
118  DO ielem = 1, numel
119 
120  ! ... Node positions
121  n1 = elconnvol(1,ielem)
122  n2 = elconnvol(2,ielem)
123  n3 = elconnvol(3,ielem)
124  n4 = elconnvol(4,ielem)
125  n5 = elconnvol(5,ielem)
126  n6 = elconnvol(6,ielem)
127  n7 = elconnvol(7,ielem)
128  n8 = elconnvol(8,ielem)
129  ! ... x,y,z coordtmpinates of node n#.
130  coordtmp(1,1) = coor(1,n1)
131  coordtmp(2,1) = coor(2,n1)
132  coordtmp(3,1) = coor(3,n1)
133  coordtmp(1,2) = coor(1,n2)
134  coordtmp(2,2) = coor(2,n2)
135  coordtmp(3,2) = coor(3,n2)
136  coordtmp(1,3) = coor(1,n3)
137  coordtmp(2,3) = coor(2,n3)
138  coordtmp(3,3) = coor(3,n3)
139  coordtmp(1,4) = coor(1,n4)
140  coordtmp(2,4) = coor(2,n4)
141  coordtmp(3,4) = coor(3,n4)
142  coordtmp(1,5) = coor(1,n5)
143  coordtmp(2,5) = coor(2,n5)
144  coordtmp(3,5) = coor(3,n5)
145  coordtmp(1,6) = coor(1,n6)
146  coordtmp(2,6) = coor(2,n6)
147  coordtmp(3,6) = coor(3,n6)
148  coordtmp(1,7) = coor(1,n7)
149  coordtmp(2,7) = coor(2,n7)
150  coordtmp(3,7) = coor(3,n7)
151  coordtmp(1,8) = coor(1,n8)
152  coordtmp(2,8) = coor(2,n8)
153  coordtmp(3,8) = coor(3,n8)
154 
155  ! Find which material this element is made of
156  imat = mattype(ielem)
157 
158  ! ... Initialize stuff
159  ntn(:,:) = 0.0
160  element_volume = 0.0
161 
162  ! ... Loop throught the gauss points in this element
163  DO igpt = 1, ngpts
164 
165  ! ... Find the shape functions N and the derivative dN
166  ! ... at gauss point = igpt
167  n(:) = 0.0
168  dn(:,:) = 0.0
169  CALL get_shape(ri,n,dn,igpt)
170 
171  ! ... Find the volume of the element
172  jac(1:3,1:3) = 0.0
173  jacinv(1:3,1:3) = 0.0
174  CALL get_jacobien(coordtmp,3,8,dn,jac,jacinv,detj,error)
175  element_volume = element_volume + detj ! * w
176 
177  ! ... Integrate and assemble into NtN
178  DO i = 1, 8
179  DO j = 1, 8
180  ntn(i,j) = ntn(i,j) + cap(imat)*rho(imat)*n(i)*n(j)*detj ! * w
181  ENDDO
182  ENDDO
183 
184  ENDDO
185 
186 
187  ! ... Local element capacitance matrix computed
188  ! ... now assemble
189 
190  DO i = 1, 8 ! node1 loop
191  gdof1 = local2global(elconnvol(i,ielem))
192  ldof1 = i
193  DO j = 1, 8 ! node2 loop
194  ldof2 = j
195  gdof2 = local2global(elconnvol(j,ielem))
196 
197  ! ... Make sure the matrix is exactly symmetric
198  IF ( ldof1 <= ldof2 ) THEN
199  tempval = ntn(ldof1,ldof2)
200  ELSE
201  tempval = ntn(ldof2,ldof1)
202  ENDIF
203 
204  IF ( tempval == 0.0 ) THEN
205  print*,'ZERO DETECTED IN LOCAL CAPACITANCE MATRIX!',gdof1,gdof2,myid
206  END IF
207  tempi = (gdof1-1)*diag_width
208  DO k=1,diag_width
209  ! ... if index k in col_index is empty, then fill index k
210  ! ... in col_index and values with the corresponding column
211  ! ... index and capacitance matix entry
212  IF(col_index(tempi+k).EQ.-1)THEN
213  !col_index(tempi+k)=gdof2-1
214  col_index(tempi+k)=gdof2
215  values(tempi+k)=tempval
216 
217  EXIT
218  ! ... Ex., if, for a given row, column 5 needs be inserted, but
219  ! ... col_val(...k,k+1,..)=<...4,6...>, shift k+1,to k+2,... then
220  ! ... insert 5 at k+1.
221  ELSEIF((col_index(tempi+k).LT.gdof2).AND.(col_index(tempi+k+1).GT.gdof2))THEN
222  DO l= diag_width-1, k+1, -1
223  tempj = col_index(tempi+l)
224  col_index(tempi+l+1)=tempj
225  tempval2 = values(tempi+l)
226  values(tempi+l+1) = tempval2
227  ENDDO
228  !col_index(tempi+k+1) = gdof2-1
229  col_index(tempi+k+1) = gdof2
230  values(tempi+k+1) = tempval
231  EXIT
232  ! ... if entry in k is less than given column number, but no entry in k+1
233  ! ... then enter column value into k+1
234  ELSEIF((col_index(tempi+k).LT.gdof2).AND.(col_index(tempi+k+1).EQ.-1))THEN
235  values(tempi+k+1)=tempval
236  col_index(tempi+k+1)=gdof2
237  EXIT
238  ! ... if the column value entered into k is the same as the given
239  ! ... column value, then add the new entry into k in the values (=aval)
240  ! ... vector.
241  ELSEIF(col_index(tempi+k).EQ.gdof2)THEN
242  values(tempi+k)= values(tempi+k) + tempval
243  EXIT
244  ! ... if column value in k is greater than the given column value,
245  ! ... shift values k,k+1,... to k+1,k+2... and enter given column
246  ! ... value and capacitance value into col_index and values vectors.
247  ELSEIF(col_index(tempi+k).GT.gdof2)THEN
248  DO l= diag_width-1, k, -1
249  tempj = col_index(tempi+l)
250  col_index(tempi+l+1)=tempj
251  tempval2 = values(tempi+l)
252  values(tempi+l+1) = tempval2
253  ENDDO
254  col_index(tempi+k) = gdof2
255  values(tempi+k) = tempval
256  EXIT
257  ENDIF
258  ENDDO
259  ENDDO
260  ENDDO
261  ENDDO
262  if(myid.eq.0) print*,'FINISHED FORMING GLB CAPACITANCE MATRIX FOR ELEMENT',ielem
263 
264  ! ... Determining the exact number of non-zero elements in the global mass matrix
265  tempi=0
266  DO i= 1,gnumnp*diag_width
267  IF (col_index(i).NE.-1)THEN
268  tempi = tempi + 1
269  ENDIF
270  ENDDO
271 
272  ! ... Allocating cval_temp, aval_temp and rp_temp
273  ALLOCATE(rp_temp(1:gnumnp+1))
274  ALLOCATE(cval_temp(1:tempi))
275  ALLOCATE(aval_temp(1:tempi))
276  tempj=tempi
277 
278  ! ... Populating aval-temp, cval_temp
279  tempi=1
280  DO i= 1, gnumnp*diag_width
281  IF (col_index(i).NE.-1)THEN
282  cval_temp(tempi) = col_index(i)
283  aval_temp(tempi) = values(i)
284  tempi = tempi + 1
285  ENDIF
286  ENDDO
287 
288  ! ... Populating rp_temp
289  rp_temp(1) = 0
290  DO i = 1, gnumnp
291  tempi = 0
292  ! ... loop through row i, look for non-zeros
293  DO j = 1, diag_width
294  IF (col_index((i-1)*diag_width+j).NE.-1)THEN
295  tempi = tempi + 1
296  ENDIF
297  ENDDO
298  rp_temp(i+1) = rp_temp(i) + tempi
299  ENDDO
300 
301  ! ... cval_temp(i) = cval_temp(i)-1 per C standards for BLOCKSOLVE95
302  DO i=1,tempj
303  cval_temp(i)=cval_temp(i)-1
304  ENDDO
305  nnz = tempj
306  nnz_temp = nnz
307 
308  DEALLOCATE(col_index)
309  DEALLOCATE(values)
310 
311 END SUBROUTINE locthermcap_v3d8
j indices k indices k
Definition: Indexing.h:6
subroutine locthermcap_v3d8(NumEl, NumNP, NumMat, coor, nodes, MatType, ri, rho, cap, ElConnVol)
subroutine get_jacobien(coords, mcrd, nnode, dn, jac, jacinv, detj, error)
Definition: v3d8_me.f90:1003
blockLoc i
Definition: read.cpp:79
const NT & n
virtual std::ostream & print(std::ostream &os) const
j indices j
Definition: Indexing.h:6
subroutine get_shape(r, n, dn, igpt)
Definition: v3d8_me.f90:846