From cc0e8354c5091219270590f10c0f0c885ef80dcf Mon Sep 17 00:00:00 2001
From: Dave Whipp <dwhipp@dal.ca>
Date: Mon, 10 Jan 2011 16:23:15 +0000
Subject: [PATCH] Updated to do a proper majority rule for full elements.
 Similar to the make_cut.f90 update

---
 src/pressure_cut.f90 | 364 +++++++++++++++++++++++++++----------------
 1 file changed, 233 insertions(+), 131 deletions(-)

diff --git a/src/pressure_cut.f90 b/src/pressure_cut.f90
index 979eb054..c8a899d9 100644
--- a/src/pressure_cut.f90
+++ b/src/pressure_cut.f90
@@ -20,7 +20,6 @@ recursive subroutine pressure_cut (params,level,levelmax,icon,x,y,z,mat,       &
                                    materialn,u,v,w,temp,pressure,strain,nnode, &
                                    lsf,nlsf,r0,s0,t0,rst,icut,ileaves,         &
                                    eviscosity)
-                                   
 
 !------------------------------------------------------------------------------|
 !(((((((((((((((( Purpose of the routine  ))))))))))))))))))))))))))))))))))))))
@@ -53,166 +52,268 @@ use definitions
 
 implicit none
 
-type (parameters) params
-integer level
-integer levelmax
-integer icon(params%mpe)
-double precision x(nnode),y(nnode),z(nnode)
-type (material) mat(0:params%nmat)
-integer materialn(0:nlsf)
-double precision u(nnode),v(nnode),w(nnode)
-double precision temp(nnode)
-double precision pressure
-double precision strain(nnode)
-integer nnode
-double precision lsf(params%mpe,nlsf)
-integer nlsf
-double precision r0,s0,t0,rst
-integer icut
-integer ileaves
-double precision eviscosity
+type(parameters),intent(in) :: params
+integer,intent(in) :: level
+integer,intent(in) :: levelmax
+integer,intent(in) :: icon(params%mpe)
+double precision,intent(in) :: x(nnode),y(nnode),z(nnode)
+type(material),intent(in) :: mat(0:params%nmat)
+integer,intent(in) :: materialn(0:nlsf)
+double precision,intent(in) :: u(nnode),v(nnode),w(nnode)
+double precision,intent(in) :: temp(nnode)
+double precision,intent(inout) :: pressure
+double precision,intent(in) :: strain(nnode)
+integer,intent(in) :: nnode
+double precision,intent(in) :: lsf(params%mpe,nlsf)
+integer,intent(in) :: nlsf
+double precision,intent(in) :: r0,s0,t0,rst
+integer,intent(out) :: icut
+integer,intent(in) :: ileaves
+double precision,intent(in) :: eviscosity
 
 !------------------------------------------------------------------------------|
 !(((((((((((((((( declaration of the subroutine internal variables )))))))))))))
 !------------------------------------------------------------------------------|
 
-integer err,i,j,k,ii,jj,kk,levelp,matel,jcut
-double precision r(params%mpe),s(params%mpe),t(params%mpe)
-double precision h(params%mpe),vol_lsf0
-double precision r0p,s0p,t0p,rstp,dt,eps
-double precision viscosity,density,penal,expon,diffusivity,heat
-double precision pressurep,prod,volmax
-double precision,dimension(:,:),allocatable::lsfp
-double precision,dimension(:),allocatable::vol_lsf
-character (len=8) plasticity_type
-double precision plasticity_parameters(9)
+integer :: matel,matrule,i,j,k,err
+double precision :: prod,vol_lsf0,eps,pressurep
+double precision,allocatable :: vol_lsf(:)
 
 !------------------------------------------------------------------------------|
 !------------------------------------------------------------------------------|
 
 eps=1.d-10
+icut=0
 
 if (level.eq.0) then
-   pressure=0.d0
+  pressure=0.d0
 endif
 
 matel=materialn(0)
+matrule=params%matrule
 
 do i=1,nlsf
    prod=lsf(1,i)
    do k=2,params%mpe
-      if (prod*lsf(k,i).le.0.d0) goto 222
+      if (prod*lsf(k,i).le.0.d0 .and. icut.eq.0) then
+        icut=1
+        allocate (vol_lsf(nlsf),stat=err) ; if (err.ne.0) call stop_run ('Error alloc vol_lsf in make_cut$')
+        call get_mat_volume(params,nlsf,lsf,vol_lsf,vol_lsf0)
+        if (vol_lsf0.gt.eps .or. level.gt.0) matrule=0
+        if (matrule.eq.1 .or. matrule.eq.2) then                                ! Use majority or minority rule
+          call set_elem_props(params,mat,matrule,nlsf,nnode,icon,level,        &
+                             materialn,vol_lsf,vol_lsf0,x,y,z,u,v,w,temp,      &
+                             pressure,strain,r0,s0,t0,rst,eviscosity)
+        else                                                                    ! Use divFEM
+          if (level.eq.levelmax) then
+          call set_elem_props(params,mat,matrule,nlsf,nnode,icon,level,        &
+                             materialn,vol_lsf,vol_lsf0,x,y,z,u,v,w,temp,      &
+                             pressure,strain,r0,s0,t0,rst,eviscosity)
+          else
+            call divide_element(params,mat,level,levelmax,nlsf,nnode,icon,     &
+                               ileaves,materialn,lsf,r0,s0,t0,rst,x,y,z,u,v,w, &
+                               temp,pressure,strain,eviscosity)
+          endif
+        endif
+        deallocate (vol_lsf)
+      endif
    enddo
-   if (prod.lt.0.d0) then
-      matel=materialn(i)
+   if (prod.lt.0.d0 .and. icut.eq.0) then
+     matel=materialn(i)
    endif
 enddo
 
-call make_pressure (params,icon,x,y,z,mat(matel)%viscosity,mat(matel)%penalty, &
-                   mat(matel)%expon,u,v,w,temp,pressurep,strain,nnode,r0,s0,t0,&
-                   rst,mat(matel)%plasticity_type,&
-                   mat(matel)%plasticity_parameters,eviscosity)
+if (icut.eq.0) then
+  call make_pressure(params,icon,x,y,z,mat(matel)%viscosity,mat(matel)%penalty,&
+                    mat(matel)%expon,u,v,w,temp,pressurep,strain,nnode,r0,s0,  &
+                    t0,rst,mat(matel)%plasticity_type,                         &
+                    mat(matel)%plasticity_parameters,eviscosity)
 
-pressure=pressure+pressurep/(8.d0**level)
+  pressure=pressure+pressurep/(8.d0**level)
+endif
 
-icut=0
+end subroutine pressure_cut
 
-return
+!-------------------------------------------------------------------------------
 
-222   continue
+subroutine get_mat_volume (params,nlsf,lsf,vol_lsf,vol_lsf0)
 
-icut=1
+use definitions
 
-! when we get to the bottom of the division
-! we use an approximate algorithm
+implicit none
 
-if (level.eq.levelmax) then
-   allocate (vol_lsf(nlsf),stat=err) ; if (err.ne.0) call stop_run ('Error alloc vol_lsf in pressure_cut$')
-   do i=1,nlsf
-      call compute_positive_volume (lsf(1,i),vol_lsf(i),params%levelapprox)
-   enddo
-   vol_lsf=1.d0-vol_lsf
+type(parameters),intent(in) :: params
+integer,intent(in) :: nlsf
+double precision,intent(in)  :: lsf(params%mpe,nlsf)
+double precision,intent(out) :: vol_lsf(nlsf)
+double precision,intent(out) :: vol_lsf0
 
-   if (.not.params%excl_vol) then
-      do i=1,nlsf-1
-         vol_lsf(i)=vol_lsf(i)-vol_lsf(i+1)
-      enddo
-   end if
-
-    do i=1,nlsf
-       vol_lsf(i)=max(vol_lsf(i),0.d0)
-       vol_lsf(i)=min(vol_lsf(i),1.d0)
-    enddo
-    vol_lsf0=1.d0-sum(vol_lsf)
-
-    if (vol_lsf0.gt.eps) then                                                   ! Element contains void, always use divFEM
-      viscosity=0.d0
-      penal=0.d0
-      expon=0.d0
-      do i=1,nlsf
-        matel=materialn(i)
-        viscosity=viscosity+vol_lsf(i)*mat(matel)%viscosity
-        penal=penal+vol_lsf(i)*mat(matel)%penalty
-        expon=expon+vol_lsf(i)*mat(matel)%expon
-      enddo
-      matel=materialn(0)
-      viscosity=viscosity+vol_lsf0*mat(matel)%viscosity
-      penal=penal+vol_lsf0*mat(matel)%penalty
-      expon=expon+vol_lsf0*mat(matel)%expon
-    elseif (params%matrule.eq.1) then                                           ! Assign material properties of volumetric majority material
-      matel=params%materialn(sum(maxloc(vol_lsf)))
-      viscosity=mat(matel)%viscosity
-      penal=mat(matel)%penalty
-      expon=mat(matel)%expon
-    elseif (params%matrule.eq.2) then                                           ! Assign material properties of volumetric minority material
-      matel=params%materialn(sum(minloc(vol_lsf)))
-      viscosity=mat(matel)%viscosity
-      penal=mat(matel)%penalty
-      expon=mat(matel)%expon
-    else
-      if (params%matrule.ne.0) print *,'Invalid matrule value, using divFEM'
-      viscosity=0.d0
-      penal=0.d0
-      expon=0.d0
-      do i=1,nlsf
-        matel=materialn(i)
-        viscosity=viscosity+vol_lsf(i)*mat(matel)%viscosity
-        penal=penal+vol_lsf(i)*mat(matel)%penalty
-        expon=expon+vol_lsf(i)*mat(matel)%expon
-      enddo
-      matel=materialn(0)
-      viscosity=viscosity+vol_lsf0*mat(matel)%viscosity
-      penal=penal+vol_lsf0*mat(matel)%penalty
-      expon=expon+vol_lsf0*mat(matel)%expon
-    endif
-
-    if (maxval(vol_lsf).gt.0.d0) then
-      if (params%matrule.eq.2) then
-        matel=params%materialn(sum(minloc(vol_lsf)))
-        plasticity_type=mat(matel)%plasticity_type
-        plasticity_parameters=mat(matel)%plasticity_parameters
-      else
-        matel=params%materialn(sum(maxloc(vol_lsf)))
-        plasticity_type=mat(matel)%plasticity_type
-        plasticity_parameters=mat(matel)%plasticity_parameters
-      endif
-    else
-      matel=params%materialn(0)
-      plasticity_type=mat(matel)%plasticity_type
-      plasticity_parameters=mat(matel)%plasticity_parameters
-    endif
-
-   call make_pressure (params,icon,x,y,z,viscosity,penal,expon,u,v,w,temp,     &
-                      pressurep,strain,nnode,r0,s0,t0,rst,plasticity_type,     &
-                      plasticity_parameters,eviscosity)
-   pressure=pressure+pressurep/(8.d0**level)
-   deallocate (vol_lsf)
-   return
+!------------------------------------------------------------------------------|
+!(((((((((((((((( declaration of the subroutine internal variables )))))))))))))
+!------------------------------------------------------------------------------|
+
+integer :: i
+
+!-------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------
+
+do i=1,nlsf
+  call compute_positive_volume (lsf(1,i),vol_lsf(i),params%levelapprox)
+enddo
+vol_lsf=1.d0-vol_lsf
+
+if (.not.params%excl_vol) then
+  do i=1,nlsf-1
+    vol_lsf(i)=vol_lsf(i)-vol_lsf(i+1)
+  enddo
 endif
 
-! If we are not at the bottom level, we keep dividing
+! this is a little fix that is necessary due to the finite precision with which
+! we compute the positive volumes and could lead to a contributing volume being
+! either marginally negative or greater than 1
+do i=1,nlsf
+  vol_lsf(i)=max(vol_lsf(i),0.d0)
+  vol_lsf(i)=min(vol_lsf(i),1.d0)
+enddo
+vol_lsf0=1.d0-sum(vol_lsf)
+
+end subroutine get_mat_volume
+
+!-------------------------------------------------------------------------------
 
-allocate (lsfp(params%mpe,nlsf),stat=err) ; if (err.ne.0) call stop_run ('Error alloc lsfp in pressure_cut$')
+subroutine set_elem_props (params,mat,matrule,nlsf,nnode,icon,level,materialn, &
+                          vol_lsf,vol_lsf0,x,y,z,u,v,w,temp,pressure,strain,r0,&
+                          s0,t0,rst,eviscosity)
+
+use definitions
+
+implicit none
+
+type(parameters),intent(in) :: params
+type(material),intent(in)   :: mat(0:params%nmat)
+integer,intent(in) :: matrule
+integer,intent(in) :: nlsf
+integer,intent(in) :: nnode
+integer,intent(in) :: icon(params%mpe)
+integer,intent(in) :: level
+integer,intent(in) :: materialn(0:nlsf)
+double precision,intent(in) :: vol_lsf(nlsf)
+double precision,intent(in) :: vol_lsf0
+double precision,intent(in) :: x(nnode),y(nnode),z(nnode)
+double precision,intent(in) :: u(nnode),v(nnode),w(nnode)
+double precision,intent(in) :: temp(nnode)
+double precision,intent(in) :: strain(nnode)
+double precision,intent(in) :: r0,s0,t0,rst
+double precision,intent(in) :: eviscosity
+double precision,intent(out) :: pressure
+
+!------------------------------------------------------------------------------|
+!(((((((((((((((( declaration of the subroutine internal variables )))))))))))))
+!------------------------------------------------------------------------------|
+
+integer :: matel,i
+double precision :: eps,viscosity,penal,expon,pressurep
+double precision :: plasticity_parameters(9)
+character(len=8) :: plasticity_type
+
+!-------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------
+
+eps=1.d-10
+
+select case (matrule)
+case (1)                                                                        ! Assign material properties of volumetric majority material
+  matel=materialn(sum(maxloc(vol_lsf)))
+  viscosity=mat(matel)%viscosity
+  penal=mat(matel)%penalty
+  expon=mat(matel)%expon
+  plasticity_type=mat(matel)%plasticity_type
+  plasticity_parameters=mat(matel)%plasticity_parameters
+
+case(2)                                                                         ! Assign material properties of volumetric minority material
+  matel=materialn(sum(minloc(vol_lsf)))
+  viscosity=mat(matel)%viscosity
+  penal=mat(matel)%penalty
+  expon=mat(matel)%expon
+  plasticity_type=mat(matel)%plasticity_type
+  plasticity_parameters=mat(matel)%plasticity_parameters
+
+case default
+  if (matrule.ne.0) write(*,*) 'Invalid matrule value, using divFEM'
+  viscosity=0.d0
+  penal=0.d0
+  expon=0.d0
+  do i=1,nlsf
+    matel=materialn(i)
+    viscosity=viscosity+vol_lsf(i)*mat(matel)%viscosity
+    penal=penal+vol_lsf(i)*mat(matel)%penalty
+    expon=expon+vol_lsf(i)*mat(matel)%expon
+  enddo
+  matel=materialn(0)
+  viscosity=viscosity+vol_lsf0*mat(matel)%viscosity
+  penal=penal+vol_lsf0*mat(matel)%penalty
+  expon=expon+vol_lsf0*mat(matel)%expon
+  matel=materialn(sum(maxloc(vol_lsf)))
+  plasticity_type=mat(matel)%plasticity_type
+  plasticity_parameters=mat(matel)%plasticity_parameters
+
+end select
+
+if (maxval(vol_lsf).lt.eps) then
+  matel=materialn(0)
+  plasticity_type=mat(matel)%plasticity_type
+  plasticity_parameters=mat(matel)%plasticity_parameters
+endif
+
+call make_pressure (params,icon,x,y,z,viscosity,penal,expon,u,v,w,temp,        &
+                   pressurep,strain,nnode,r0,s0,t0,rst,plasticity_type,        &
+                   plasticity_parameters,eviscosity)
+
+pressure=pressure+pressurep/(8.d0**level)
+
+end subroutine set_elem_props
+
+!-------------------------------------------------------------------------------
+
+subroutine divide_element(params,mat,level,levelmax,nlsf,nnode,icon,ileaves,   &
+                         materialn,lsf,r0,s0,t0,rst,x,y,z,u,v,w,temp,pressure, &
+                         strain,eviscosity)
+
+use definitions
+
+implicit none
+
+type(parameters),intent(in) :: params
+type(material),intent(in)   :: mat(0:params%nmat)
+integer,intent(in) :: level
+integer,intent(in) :: levelmax
+integer,intent(in) :: nlsf
+integer,intent(in) :: nnode
+integer,intent(in) :: icon(params%mpe)
+integer,intent(in) :: ileaves
+integer,intent(in) :: materialn(0:nlsf)
+double precision,intent(in) :: lsf(params%mpe,nlsf)
+double precision,intent(in) :: r0,s0,t0,rst
+double precision,intent(in) :: x(nnode),y(nnode),z(nnode)
+double precision,intent(in) :: u(nnode),v(nnode),w(nnode)
+double precision,intent(in) :: temp(nnode)
+double precision,intent(in) :: strain(nnode)
+double precision,intent(in) :: eviscosity
+double precision,intent(inout) :: pressure
+
+!------------------------------------------------------------------------------|
+!(((((((((((((((( declaration of the subroutine internal variables )))))))))))))
+!------------------------------------------------------------------------------|
+
+integer :: err,i,j,k,ii,jj,kk,levelp,jcut
+double precision,allocatable :: lsfp(:,:)
+double precision :: r(params%mpe),s(params%mpe),t(params%mpe),h(params%mpe)
+double precision :: r0p,s0p,t0p,rstp
+
+!-------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------
+
+allocate (lsfp(params%mpe,nlsf),stat=err) ; if (err.ne.0) call stop_run ('Error alloc lsfp in make_cut$')
 
 do kk=1,2
    t(1:4)=-1.d0+float(kk-1)
@@ -252,6 +353,7 @@ do kk=1,2
          t0p=t0+rst*(t(1)+1.d0)/2.d0
          rstp=rst/2.d0
          levelp=level+1
+
          call pressure_cut (params,levelp,levelmax,icon,x,y,z,mat,materialn,u, &
                            v,w,temp,pressure,strain,nnode,lsfp,nlsf,r0p,s0p,   &
                            t0p,rstp,jcut,ileaves,eviscosity)
@@ -261,7 +363,7 @@ enddo
 
 deallocate (lsfp)
 
-return
-end
-!------------------------------------------------------------------------------|
-!------------------------------------------------------------------------------|
\ No newline at end of file
+end subroutine divide_element
+
+!-------------------------------------------------------------------------------
+!-------------------------------------------------------------------------------
\ No newline at end of file
-- 
GitLab