Hi Resam,
sorry for my late response.
Here you (and anybody else interested) have my proposal for adding contact output to NPVI.
I started creating a module (1) where I will store all the information. I am sure you can do this using palloc and ualloc. Remember that my implemenattion was only a prototype.
Then allocating the arrays in celmt06.f (2), where I found that csw=14 was doing the trick. Again, this can be placed in a more convenient place. In csw=3,6 I save the information I require, while I am still inside the loops.
Finally, in uparaview_nurbs.f (3), I added some variables in order to write down the output only when there is a valid contact drive.
At this point, I am pretty sure that you may come up with a more elegant solution, as you have a better overview of NPVI.
Sorry that I am only adding schemes of the changes, as my contact 3D elements have a lot of other stuff that I would have to clean if I wanted to send it to you.
However, for the uparaview file it would be far easier. So please let me know if you need it.
Remarks:
a. As the number of gauss points in a contact element can be defined arbitrarily, I implemented the output based on POINTS only, (VTU Type=2). I also tried outputing the elements as shells (type=23). The former option is robust and shows all output I require so far. The latter looks good, but only works for 9 points, and even then it is not using the middle point to interpolate results.
b. I tried creating a different PIECE in paraview where I could have only contact output. It did not work as expected, because of the way Paraview uses those pieces internally. Pitty. Therefore, I had to add dummy contact output to all other points, and dummy "solid" output to all contact points.
c. it would be great if you can give me a hand with pressure output

1. The module
module contact_output
implicit none
save
integer iCont_data ! Flag for initialization of contact data
integer c_pairs
double precision,allocatable :: c_gpcds(:,:,:) ! coordinates of gauss points in contact elements (ndf,n_gp,c_pair)
double precision,allocatable :: c_gpdsp(:,:,:) ! displacements of gauss points in contact elements (ndf,n_gp,c_pair)
integer,allocatable :: c_status(:,:) !contact status at gauss point c_status(n_gp,c_pair)
double precision,allocatable :: c_gn(:,:) !penetration at gauss point c_gn(n_gp,c_pair)
c for IGA contact
integer iCont_points ! Flag for output as points (arbitrary number of points)
integer c_nodes ! number of nodes per element
integer,allocatable :: c_elpair(:) !number of elements per contact pair
data iCont_data/0/
data iCont_points/1/
data c_pairs/0/
end module
2. A scheme of the changes in Celmt06.f
subroutine celmt06 (...)
use contact_output
[...]
case(3,6)
cel_tmp = 0
c_elpair(npair) = neps_s(1)*neps_s(2)
do i= 1,npair-1
cel_tmp = cel_tmp + c_elpair(i)
end do
do ifac2 = 1,neps_s(2)
n1(2) = k_order1(2) + 1
do ifac1 = 1,neps_s(1)
n1(1) = k_order1(1) + 1
nng = 1
do ng2 = 1,ngauss
do ng1 = 1,ngauss
[...]
c save data for output purposes
if (iCont_points.eq.0) then
p = p_id(ng1,ng2)
if (ng1.eq.2 . AND. ng2.eq.2) goto 999 !Do nothing for the middle point
else if (iCont_points.eq.1) then
p = nng
end if !iCont_points
cel_id = iifac + cel_tmp
if (iCont_data.eq.1) then
do i=1,3
c_gpcds(i,p,cel_id) = xS(i)
end do
if (nng.eq.nngaus .AND. cel_id.eq.c_pairs) then
iCont_data = 2
end if
end if
do i=1,3
c_gpdsp(i,p,cel_id) = xS(i)-c_gpcds(i,p,cel_id)
end do
c_status(p,cel_id) = istgn !+istgt(p)
c_gn(p,cel_id) = ch2(p1(4),npt)!gn_int
if (c_gn(p,cel_id).gt.0) c_gn(p,cel_id) = 0.d0 !write zero when contact
[...]
case(14)
[...]
c allocate variables for user output
if (iCont_data.eq.0) then
c_pairs = c_pairs + neps_s(1)*neps_s(2)
if (npair.eq.numcp) then
if (iCont_points.eq.1) then ! for output as points only (default)
c_nodes = ngauss*ngauss
end if
allocate ( c_elpair(numcp) )
allocate ( c_gpcds(3,c_nodes,c_pairs) )
allocate ( c_gpdsp(3,c_nodes,c_pairs) )
allocate ( c_status(c_nodes,c_pairs) )
allocate ( c_gn(c_nodes,c_pairs) )
c_elpair(:) = 0
c_gpcds(:,:,:) = 0.0d0
c_gpdsp(:,:,:) = 0.0d0
c_status(:,:) = 0
iCont_data=1
end if !numcp
end if !iCont
3. A scheme of changes in uparaview_nurbs.f
subroutine uparaview_nurb(...)
use contact_output
[...]
if (ndrv.eq.2 .OR. ndrv.eq.6) then
write(plu,1020) numnp+c_nodes*c_pairs,numel+c_pairs !add contact elements
else
c_pairs = 0
write(plu,1020) numnp,numel ! Start Mesh/Piece Section
end if
[...]
write(plu,1010) '<Points>' ! Start Point/Node data
write(plu,1030) 'Float64','nodes',3
do i = 1,numnp
write(plu,2010) (x(ii,i),ii = 1,ndm) ,(0.0d0,ii = ndm+1,3)
write(plu,*)
end do ! i
if (ndrv.eq.2 .OR. ndrv.eq.06) then
do j=1,c_pairs
do i = 1,c_nodes
write(plu,2010) (c_gpcds(ii,i,j),ii = 1,ndm)
end do ! i
end do !j
end if
write(plu,1010) '</DataArray>' ! Close Node data
write(plu,1010) '</Points>' ! Close Points section
[...]
write(plu,1030) 'Float64','Principal Stress',7 ! Start Prin Stresses
do i = 1,numnp
do ii =1,7
write(plu,2000) psig(i,ii)
end do ! ii
write(plu,*)
end do ! i
if (ndrv.eq.2 .OR. ndrv.eq.6) then !dummy
do j=1,c_pairs
do i = 1,c_nodes
do ii = 1,7
write(plu,2000) 0.d0
end do ! ii
end do ! i
end do
end if
write(plu,1010) '</DataArray>' ! Close Prin Stresses
[...]
c Output contact variables
c ======================================================================
if (ndrv.eq.2 .OR. ndrv.eq.6) then
write(plu,1030) 'Int32','C_Status',1 ! Start contact status
do i = 1,numnp
write(plu,2020) 0 !dummy
end do ! i
do ii = 1,c_pairs
do i=1,c_nodes
write(plu,2020) c_status(i,ii)
end do
end do
write(plu,1010) '</DataArray>' ! Close contact status
write(plu,1030) 'Float64','C_gap',1 ! Start contact gap
do i = 1,numnp
write(plu,2000) 0.d0
end do ! i
do ii = 1,c_pairs
do i=1,c_nodes
write(plu,2000) c_gn(i,ii)
end do
end do
write(plu,1010) '</DataArray>' ! Close contact gap
end if