2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2013-04-18 22:10:49 +05:30
|
|
|
!> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH
|
|
|
|
!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH
|
|
|
|
!> @author Christoph Koords, Max-Planck-Institut für Eisenforschung GmbH
|
|
|
|
!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH
|
2019-01-28 19:06:44 +05:30
|
|
|
!> @brief Sets up the mesh for the solver MSC.Marc
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2014-04-29 23:20:59 +05:30
|
|
|
module mesh
|
2019-06-13 04:09:35 +05:30
|
|
|
use IO
|
|
|
|
use prec
|
|
|
|
use math
|
|
|
|
use mesh_base
|
|
|
|
use DAMASK_interface
|
|
|
|
use IO
|
|
|
|
use debug
|
|
|
|
use numerics
|
|
|
|
use FEsolving
|
|
|
|
use element
|
|
|
|
use discretization
|
|
|
|
use geometry_plastic_nonlocal
|
|
|
|
use HDF5_utilities
|
|
|
|
use results
|
|
|
|
|
|
|
|
implicit none
|
|
|
|
private
|
2019-10-13 15:49:37 +05:30
|
|
|
|
|
|
|
type tCellNodeDefinition
|
|
|
|
integer, dimension(:,:), allocatable :: parents
|
|
|
|
integer, dimension(:,:), allocatable :: weights
|
|
|
|
end type tCellNodeDefinition
|
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
real(pReal), public, protected :: &
|
2019-10-14 00:04:20 +05:30
|
|
|
mesh_unitlength !< physical length of one unit in mesh
|
|
|
|
|
|
|
|
integer, dimension(:,:), allocatable, target :: &
|
|
|
|
mesh_mapFEtoCPelem, & !< [sorted FEid, corresponding CPid]
|
|
|
|
mesh_mapFEtoCPnode !< [sorted FEid, corresponding CPid]
|
2012-03-09 01:55:28 +05:30
|
|
|
|
2019-06-08 15:30:28 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-10-14 00:04:20 +05:30
|
|
|
! DEPRECATED
|
|
|
|
real(pReal), dimension(:,:,:), allocatable, public :: &
|
|
|
|
mesh_ipCoordinates !< IP x,y,z coordinates (after deformation!)
|
2019-06-08 15:30:28 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
|
2019-10-14 00:04:20 +05:30
|
|
|
|
2019-06-08 15:30:28 +05:30
|
|
|
integer, dimension(:,:), allocatable :: &
|
2019-10-13 15:49:37 +05:30
|
|
|
connectivity_elem
|
2019-06-05 23:48:19 +05:30
|
|
|
|
2013-01-16 16:10:53 +05:30
|
|
|
|
2019-06-08 15:30:28 +05:30
|
|
|
type(tMesh) :: theMesh
|
|
|
|
|
2019-06-05 23:48:19 +05:30
|
|
|
integer,dimension(:,:,:), allocatable :: &
|
2019-10-14 00:04:20 +05:30
|
|
|
mesh_cell2 !< cell connectivity for each element,ip/cell
|
2019-01-24 14:34:43 +05:30
|
|
|
|
2019-06-06 11:07:37 +05:30
|
|
|
integer, dimension(:,:,:,:), allocatable :: &
|
2019-10-12 22:54:03 +05:30
|
|
|
mesh_ipNeighborhood2 !< 6 or less neighboring IPs as [element_num, IP_index, neighbor_index that points to me]
|
2019-10-08 20:56:02 +05:30
|
|
|
|
2013-04-22 00:18:59 +05:30
|
|
|
|
2013-04-18 22:10:49 +05:30
|
|
|
public :: &
|
|
|
|
mesh_init, &
|
2018-09-23 21:27:48 +05:30
|
|
|
mesh_FEasCP
|
2019-01-28 19:06:44 +05:30
|
|
|
|
|
|
|
|
2019-01-28 18:23:44 +05:30
|
|
|
contains
|
|
|
|
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief initializes the mesh by calling all necessary private routines the mesh module
|
|
|
|
!! Order and routines strongly depend on type of solver
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2013-02-05 18:57:37 +05:30
|
|
|
subroutine mesh_init(ip,el)
|
2018-01-10 21:43:25 +05:30
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
integer, intent(in) :: el, ip
|
|
|
|
|
|
|
|
integer, parameter :: FILEUNIT = 222
|
2019-10-13 01:28:26 +05:30
|
|
|
character(len=pStringLen), dimension(:), allocatable :: inputFile !< file content, separated per lines
|
2019-10-14 00:04:20 +05:30
|
|
|
integer :: &
|
|
|
|
mesh_NelemSets
|
2019-10-14 00:22:49 +05:30
|
|
|
real(pReal), dimension(:,:), allocatable :: &
|
|
|
|
mesh_node, & !< node x,y,z coordinates (after deformation! ONLY FOR MARC!!!
|
|
|
|
mesh_node0 !< node x,y,z coordinates (initially!)
|
2019-10-13 01:28:26 +05:30
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
integer :: j, fileFormatVersion, elemType, &
|
|
|
|
mesh_maxNelemInSet, &
|
2019-06-13 10:31:35 +05:30
|
|
|
mesh_nElems, &
|
2019-06-13 04:09:35 +05:30
|
|
|
hypoelasticTableStyle, &
|
|
|
|
initialcondTableStyle
|
2019-10-08 20:56:02 +05:30
|
|
|
integer, dimension(:), allocatable :: &
|
|
|
|
marc_matNumber !< array of material numbers for hypoelastic material (Marc only)
|
2019-10-14 00:04:20 +05:30
|
|
|
integer, dimension(:), allocatable :: &
|
|
|
|
microstructureAt, &
|
|
|
|
homogenizationAt
|
|
|
|
character(len=64), dimension(:), allocatable :: &
|
|
|
|
mesh_nameElemSet
|
|
|
|
integer, dimension(:,:), allocatable :: &
|
|
|
|
mesh_mapElemSet !< list of elements in elementSet
|
|
|
|
integer:: &
|
|
|
|
mesh_Nnodes !< total number of nodes in mesh
|
2019-10-12 18:33:26 +05:30
|
|
|
|
|
|
|
real(pReal), dimension(:,:), allocatable :: &
|
|
|
|
ip_reshaped
|
2019-02-03 15:42:23 +05:30
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
write(6,'(/,a)') ' <<<+- mesh init -+>>>'
|
2019-02-03 15:42:23 +05:30
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
mesh_unitlength = numerics_unitlength ! set physical extent of a length unit in mesh
|
2019-10-13 01:28:26 +05:30
|
|
|
inputFile = IO_read_ASCII(trim(modelName)//trim(InputFileExtension))
|
2019-02-03 15:42:23 +05:30
|
|
|
|
2019-10-08 13:00:32 +05:30
|
|
|
! parsing Marc input file
|
2019-10-13 01:28:26 +05:30
|
|
|
fileFormatVersion = mesh_marc_get_fileFormat(inputFile)
|
|
|
|
call mesh_marc_get_tableStyles(initialcondTableStyle,hypoelasticTableStyle,inputFile)
|
2019-10-08 13:00:32 +05:30
|
|
|
if (fileFormatVersion > 12) &
|
2019-10-13 15:06:21 +05:30
|
|
|
marc_matNumber = mesh_marc_get_matNumber(hypoelasticTableStyle,inputFile)
|
|
|
|
call mesh_marc_count_nodesAndElements(mesh_nNodes, mesh_nElems, inputFile)
|
|
|
|
|
|
|
|
call IO_open_inputFile(FILEUNIT,modelName)
|
2019-10-08 13:00:32 +05:30
|
|
|
call mesh_marc_count_elementSets(mesh_NelemSets,mesh_maxNelemInSet,FILEUNIT)
|
2019-06-13 04:09:35 +05:30
|
|
|
allocate(mesh_nameElemSet(mesh_NelemSets)); mesh_nameElemSet = 'n/a'
|
|
|
|
allocate(mesh_mapElemSet(1+mesh_maxNelemInSet,mesh_NelemSets),source=0)
|
|
|
|
call mesh_marc_map_elementSets(mesh_nameElemSet,mesh_mapElemSet,FILEUNIT)
|
2019-06-13 10:31:35 +05:30
|
|
|
allocate (mesh_mapFEtoCPelem(2,mesh_nElems), source = 0)
|
2019-10-08 20:56:02 +05:30
|
|
|
call mesh_marc_map_elements(hypoelasticTableStyle,mesh_nameElemSet,mesh_mapElemSet,&
|
|
|
|
mesh_nElems,fileFormatVersion,marc_matNumber,FILEUNIT)
|
2019-06-13 04:09:35 +05:30
|
|
|
allocate (mesh_mapFEtoCPnode(2,mesh_Nnodes),source=0)
|
2019-10-13 14:12:34 +05:30
|
|
|
call mesh_marc_map_nodes(mesh_Nnodes,inputFile) !ToDo: don't work on global variables
|
2019-06-13 04:09:35 +05:30
|
|
|
|
2019-10-13 14:12:34 +05:30
|
|
|
mesh_node0 = mesh_marc_build_nodes(mesh_Nnodes,inputFile)
|
2019-06-13 11:01:45 +05:30
|
|
|
mesh_node = mesh_node0
|
2019-06-13 04:09:35 +05:30
|
|
|
|
|
|
|
elemType = mesh_marc_getElemType(mesh_nElems,FILEUNIT)
|
|
|
|
|
|
|
|
call theMesh%init('mesh',elemType,mesh_node0)
|
2019-06-13 10:31:35 +05:30
|
|
|
call theMesh%setNelems(mesh_nElems)
|
2019-06-13 04:09:35 +05:30
|
|
|
|
2019-10-08 13:00:32 +05:30
|
|
|
allocate(microstructureAt(theMesh%nElems), source=0)
|
|
|
|
allocate(homogenizationAt(theMesh%nElems), source=0)
|
2019-02-03 15:42:23 +05:30
|
|
|
|
2019-10-14 01:15:08 +05:30
|
|
|
connectivity_elem = mesh_marc_buildElements(mesh_nElems,theMesh%elem%nNodes,FILEUNIT)
|
2019-10-12 22:54:03 +05:30
|
|
|
call mesh_marc_buildElements2(microstructureAt,homogenizationAt, &
|
2019-10-14 00:04:20 +05:30
|
|
|
mesh_nElems,theMesh%elem%nNodes,mesh_nameElemSet,mesh_mapElemSet,&
|
|
|
|
initialcondTableStyle,FILEUNIT)
|
2019-06-13 04:09:35 +05:30
|
|
|
close (FILEUNIT)
|
2019-10-13 02:10:00 +05:30
|
|
|
|
|
|
|
|
|
|
|
#if defined(DAMASK_HDF5)
|
|
|
|
call results_openJobFile
|
|
|
|
call HDF5_closeGroup(results_addGroup('geometry'))
|
2019-10-13 15:49:37 +05:30
|
|
|
call results_writeDataset('geometry',connectivity_elem,'C',&
|
2019-10-13 02:10:00 +05:30
|
|
|
'connectivity of the elements','-')
|
|
|
|
call results_closeJobFile
|
|
|
|
#endif
|
|
|
|
|
2019-10-14 01:15:08 +05:30
|
|
|
call buildCells(mesh_Nnodes,theMesh%elem,connectivity_elem)
|
2019-06-13 04:09:35 +05:30
|
|
|
|
|
|
|
allocate(mesh_ipCoordinates(3,theMesh%elem%nIPs,theMesh%nElems),source=0.0_pReal)
|
2019-02-03 15:42:23 +05:30
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
call IP_neighborhood2
|
2019-02-03 15:42:23 +05:30
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
if (usePingPong .and. (mesh_Nelems /= theMesh%nElems)) &
|
2019-10-08 13:00:32 +05:30
|
|
|
call IO_error(600) ! ping-pong must be disabled when having non-DAMASK elements
|
2019-06-13 04:09:35 +05:30
|
|
|
if (debug_e < 1 .or. debug_e > theMesh%nElems) &
|
2019-10-08 13:00:32 +05:30
|
|
|
call IO_error(602,ext_msg='element') ! selected element does not exist
|
2019-06-13 04:09:35 +05:30
|
|
|
if (debug_i < 1 .or. debug_i > theMesh%elem%nIPs) &
|
2019-10-08 13:00:32 +05:30
|
|
|
call IO_error(602,ext_msg='IP') ! selected element does not have requested IP
|
2019-02-02 20:27:05 +05:30
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
FEsolving_execElem = [ 1,theMesh%nElems ] ! parallel loop bounds set to comprise all DAMASK elements
|
|
|
|
allocate(FEsolving_execIP(2,theMesh%nElems), source=1) ! parallel loop bounds set to comprise from first IP...
|
|
|
|
FEsolving_execIP(2,:) = theMesh%elem%nIPs
|
2019-06-06 11:07:37 +05:30
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
allocate(calcMode(theMesh%elem%nIPs,theMesh%nElems))
|
|
|
|
calcMode = .false. ! pretend to have collected what first call is asking (F = I)
|
|
|
|
calcMode(ip,mesh_FEasCP('elem',el)) = .true. ! first ip,el needs to be already pingponged to "calc"
|
2019-10-08 13:00:32 +05:30
|
|
|
|
2019-10-12 18:33:26 +05:30
|
|
|
ip_reshaped = reshape(mesh_ipCoordinates,[3,theMesh%elem%nIPs*theMesh%nElems])
|
2019-10-08 13:00:32 +05:30
|
|
|
call discretization_init(microstructureAt,homogenizationAt,&
|
2019-10-12 18:33:26 +05:30
|
|
|
ip_reshaped,&
|
2019-10-08 13:00:32 +05:30
|
|
|
mesh_node0)
|
2019-10-12 19:55:59 +05:30
|
|
|
#if defined(DAMASK_HDF5)
|
2019-10-12 18:33:26 +05:30
|
|
|
call results_openJobFile
|
|
|
|
call results_writeDataset('geometry',ip_reshaped,'x_c', &
|
|
|
|
'cell center coordinates','m')
|
|
|
|
call results_writeDataset('geometry',mesh_node0,'x_n', &
|
|
|
|
'nodal coordinates','m')
|
|
|
|
call results_closeJobFile()
|
2019-10-12 19:55:59 +05:30
|
|
|
#endif
|
2019-10-08 13:00:32 +05:30
|
|
|
call geometry_plastic_nonlocal_setIPneighborhood(mesh_ipNeighborhood2)
|
2019-02-02 20:27:05 +05:30
|
|
|
|
2012-03-09 01:55:28 +05:30
|
|
|
end subroutine mesh_init
|
2009-01-20 00:12:31 +05:30
|
|
|
|
2014-04-04 20:10:30 +05:30
|
|
|
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-02-03 15:42:23 +05:30
|
|
|
!> @brief Figures out version of Marc input file format
|
2018-01-10 21:43:25 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-10-13 01:28:26 +05:30
|
|
|
integer function mesh_marc_get_fileFormat(fileContent)
|
2019-05-15 02:42:32 +05:30
|
|
|
|
2019-10-13 01:28:26 +05:30
|
|
|
character(len=pStringLen), dimension(:), intent(in) :: fileContent !< file content, separated per lines
|
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
integer, allocatable, dimension(:) :: chunkPos
|
2019-10-13 01:28:26 +05:30
|
|
|
integer :: l
|
|
|
|
|
|
|
|
do l = 1, size(fileContent)
|
|
|
|
chunkPos = IO_stringPos(fileContent(l))
|
|
|
|
if ( IO_lc(IO_stringValue(fileContent(l),chunkPos,1)) == 'version') then
|
|
|
|
mesh_marc_get_fileFormat = IO_intValue(fileContent(l),chunkPos,2)
|
2019-06-13 04:09:35 +05:30
|
|
|
exit
|
|
|
|
endif
|
|
|
|
enddo
|
2018-01-10 21:43:25 +05:30
|
|
|
|
2019-10-13 01:28:26 +05:30
|
|
|
end function mesh_marc_get_fileFormat
|
2018-01-10 21:43:25 +05:30
|
|
|
|
2018-01-11 21:41:03 +05:30
|
|
|
|
2018-01-10 21:43:25 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-02-03 15:42:23 +05:30
|
|
|
!> @brief Figures out table styles for initial cond and hypoelastic
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-10-13 01:28:26 +05:30
|
|
|
subroutine mesh_marc_get_tableStyles(initialcond,hypoelastic,fileContent)
|
2019-05-15 02:42:32 +05:30
|
|
|
|
2019-10-13 15:06:21 +05:30
|
|
|
integer, intent(out) :: initialcond, hypoelastic
|
|
|
|
character(len=pStringLen), dimension(:), intent(in) :: fileContent !< file content, separated per lines
|
2018-01-10 21:43:25 +05:30
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
integer, allocatable, dimension(:) :: chunkPos
|
2019-10-13 01:28:26 +05:30
|
|
|
integer :: l
|
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
initialcond = 0
|
|
|
|
hypoelastic = 0
|
2009-10-12 21:31:49 +05:30
|
|
|
|
2019-10-13 01:28:26 +05:30
|
|
|
do l = 1, size(fileContent)
|
|
|
|
chunkPos = IO_stringPos(fileContent(l))
|
|
|
|
if ( IO_lc(IO_stringValue(fileContent(l),chunkPos,1)) == 'table' .and. chunkPos(1) > 5) then
|
|
|
|
initialcond = IO_intValue(fileContent(l),chunkPos,4)
|
|
|
|
hypoelastic = IO_intValue(fileContent(l),chunkPos,5)
|
2019-06-13 04:09:35 +05:30
|
|
|
exit
|
|
|
|
endif
|
|
|
|
enddo
|
2009-10-12 21:31:49 +05:30
|
|
|
|
2019-10-13 01:28:26 +05:30
|
|
|
end subroutine mesh_marc_get_tableStyles
|
2009-04-03 12:33:25 +05:30
|
|
|
|
2019-02-03 15:42:23 +05:30
|
|
|
|
2018-01-10 21:43:25 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-02-03 16:58:04 +05:30
|
|
|
!> @brief Figures out material number of hypoelastic material
|
2018-01-10 21:43:25 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-10-13 15:06:21 +05:30
|
|
|
function mesh_marc_get_matNumber(tableStyle,fileContent)
|
2019-05-15 02:42:32 +05:30
|
|
|
|
2019-10-13 15:06:21 +05:30
|
|
|
integer, intent(in) :: tableStyle
|
|
|
|
character(len=pStringLen), dimension(:), intent(in) :: fileContent !< file content, separated per lines
|
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
integer, dimension(:), allocatable :: mesh_marc_get_matNumber
|
2018-01-10 21:43:25 +05:30
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
integer, allocatable, dimension(:) :: chunkPos
|
2019-10-13 15:06:21 +05:30
|
|
|
integer :: i, j, data_blocks, l
|
|
|
|
|
|
|
|
do l = 1, size(fileContent)
|
|
|
|
chunkPos = IO_stringPos(fileContent(l))
|
|
|
|
if ( IO_lc(IO_stringValue(fileContent(l),chunkPos,1)) == 'hypoelastic') then
|
|
|
|
if (len(trim(fileContent(l+1)))/=0) then
|
|
|
|
chunkPos = IO_stringPos(fileContent(l+1))
|
|
|
|
data_blocks = IO_intValue(fileContent(l+1),chunkPos,1)
|
|
|
|
else
|
|
|
|
data_blocks = 1
|
|
|
|
endif
|
|
|
|
allocate(mesh_marc_get_matNumber(data_blocks), source = 0)
|
|
|
|
do i = 0, data_blocks - 1
|
|
|
|
j = i*(2+tableStyle) + 1
|
|
|
|
chunkPos = IO_stringPos(fileContent(l+1+j))
|
|
|
|
mesh_marc_get_matNumber(i+1) = IO_intValue(fileContent(l+1+j),chunkPos,1)
|
|
|
|
enddo
|
|
|
|
exit
|
|
|
|
endif
|
2019-06-13 04:09:35 +05:30
|
|
|
enddo
|
2018-01-10 21:43:25 +05:30
|
|
|
|
2019-10-13 15:06:21 +05:30
|
|
|
end function mesh_marc_get_matNumber
|
2018-01-10 21:43:25 +05:30
|
|
|
|
2012-06-15 21:40:21 +05:30
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-02-03 17:24:10 +05:30
|
|
|
!> @brief Count overall number of nodes and elements
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-10-13 15:06:21 +05:30
|
|
|
subroutine mesh_marc_count_nodesAndElements(nNodes, nElems, fileContent)
|
2019-06-13 04:09:35 +05:30
|
|
|
|
2019-10-13 15:06:21 +05:30
|
|
|
integer, intent(out) :: nNodes, nElems
|
|
|
|
character(len=pStringLen), dimension(:), intent(in) :: fileContent !< file content, separated per lines
|
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
integer, allocatable, dimension(:) :: chunkPos
|
2019-10-13 15:06:21 +05:30
|
|
|
integer :: l
|
2009-01-20 00:12:31 +05:30
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
nNodes = 0
|
|
|
|
nElems = 0
|
2009-01-20 00:12:31 +05:30
|
|
|
|
2019-10-13 15:06:21 +05:30
|
|
|
do l = 1, size(fileContent)
|
|
|
|
chunkPos = IO_stringPos(fileContent(l))
|
|
|
|
if (IO_lc(IO_StringValue(fileContent(l),chunkPos,1)) == 'sizing') then
|
|
|
|
nElems = IO_IntValue (fileContent(l),chunkPos,3)
|
|
|
|
elseif (IO_lc(IO_StringValue(fileContent(l),chunkPos,1)) == 'coordinates') then
|
|
|
|
chunkPos = IO_stringPos(fileContent(l+1))
|
|
|
|
nNodes = IO_IntValue (fileContent(l+1),chunkPos,2)
|
2019-06-13 04:09:35 +05:30
|
|
|
endif
|
|
|
|
enddo
|
2009-01-20 00:12:31 +05:30
|
|
|
|
2019-10-13 15:06:21 +05:30
|
|
|
end subroutine mesh_marc_count_nodesAndElements
|
2012-06-15 21:40:21 +05:30
|
|
|
|
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-02-03 15:42:23 +05:30
|
|
|
!> @brief Count overall number of element sets in mesh.
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-05-17 16:13:42 +05:30
|
|
|
subroutine mesh_marc_count_elementSets(nElemSets,maxNelemInSet,fileUnit)
|
2019-05-15 02:42:32 +05:30
|
|
|
|
2019-06-06 16:38:10 +05:30
|
|
|
integer, intent(out) :: nElemSets, maxNelemInSet
|
2019-06-13 04:09:35 +05:30
|
|
|
integer, intent(in) :: fileUnit
|
2009-01-20 00:12:31 +05:30
|
|
|
|
2019-06-06 16:38:10 +05:30
|
|
|
integer, allocatable, dimension(:) :: chunkPos
|
|
|
|
character(len=300) :: line
|
2009-10-12 21:31:49 +05:30
|
|
|
|
2019-06-06 16:38:10 +05:30
|
|
|
nElemSets = 0
|
|
|
|
maxNelemInSet = 0
|
2009-01-20 00:12:31 +05:30
|
|
|
|
2019-06-06 16:38:10 +05:30
|
|
|
rewind(fileUnit)
|
|
|
|
do
|
|
|
|
read (fileUnit,'(A300)',END=620) line
|
|
|
|
chunkPos = IO_stringPos(line)
|
2009-10-12 21:31:49 +05:30
|
|
|
|
2019-06-06 16:38:10 +05:30
|
|
|
if ( IO_lc(IO_StringValue(line,chunkPos,1)) == 'define' .and. &
|
|
|
|
IO_lc(IO_StringValue(line,chunkPos,2)) == 'element' ) then
|
|
|
|
nElemSets = nElemSets + 1
|
|
|
|
maxNelemInSet = max(maxNelemInSet, IO_countContinuousIntValues(fileUnit))
|
|
|
|
endif
|
|
|
|
enddo
|
2009-01-20 00:12:31 +05:30
|
|
|
|
2012-03-09 01:55:28 +05:30
|
|
|
620 end subroutine mesh_marc_count_elementSets
|
2007-04-25 13:03:24 +05:30
|
|
|
|
2009-01-20 00:12:31 +05:30
|
|
|
|
2019-02-03 15:42:23 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief map element sets
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-02-03 16:58:04 +05:30
|
|
|
subroutine mesh_marc_map_elementSets(nameElemSet,mapElemSet,fileUnit)
|
2019-05-15 02:42:32 +05:30
|
|
|
|
2019-06-06 16:38:10 +05:30
|
|
|
character(len=64), dimension(:), intent(out) :: nameElemSet
|
|
|
|
integer, dimension(:,:), intent(out) :: mapElemSet
|
2019-06-13 04:09:35 +05:30
|
|
|
integer, intent(in) :: fileUnit
|
2018-01-10 21:43:25 +05:30
|
|
|
|
2019-06-06 16:38:10 +05:30
|
|
|
integer, allocatable, dimension(:) :: chunkPos
|
|
|
|
character(len=300) :: line
|
|
|
|
integer :: elemSet
|
|
|
|
|
|
|
|
elemSet = 0
|
|
|
|
|
|
|
|
rewind(fileUnit)
|
|
|
|
do
|
2019-06-13 10:55:26 +05:30
|
|
|
read (fileUnit,'(A300)',END=620) line
|
2019-06-06 16:38:10 +05:30
|
|
|
chunkPos = IO_stringPos(line)
|
|
|
|
if( (IO_lc(IO_stringValue(line,chunkPos,1)) == 'define' ) .and. &
|
|
|
|
(IO_lc(IO_stringValue(line,chunkPos,2)) == 'element' ) ) then
|
|
|
|
elemSet = elemSet+1
|
|
|
|
nameElemSet(elemSet) = trim(IO_stringValue(line,chunkPos,4))
|
|
|
|
mapElemSet(:,elemSet) = IO_continuousIntValues(fileUnit,size(mapElemSet,1)-1,nameElemSet,mapElemSet,size(nameElemSet))
|
|
|
|
endif
|
|
|
|
enddo
|
2018-01-10 21:43:25 +05:30
|
|
|
|
2019-06-13 10:55:26 +05:30
|
|
|
620 end subroutine mesh_marc_map_elementSets
|
2010-05-06 22:10:47 +05:30
|
|
|
|
|
|
|
|
2019-06-06 16:38:10 +05:30
|
|
|
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief Maps elements from FE ID to internal (consecutive) representation.
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-10-08 20:56:02 +05:30
|
|
|
subroutine mesh_marc_map_elements(tableStyle,nameElemSet,mapElemSet,nElems,fileFormatVersion,matNumber,fileUnit)
|
2019-05-15 02:42:32 +05:30
|
|
|
|
2019-06-05 16:27:08 +05:30
|
|
|
integer, intent(in) :: fileUnit,tableStyle,nElems,fileFormatVersion
|
2019-10-08 20:56:02 +05:30
|
|
|
integer, dimension(:), intent(in) :: matNumber
|
2019-02-03 17:24:10 +05:30
|
|
|
character(len=64), intent(in), dimension(:) :: nameElemSet
|
2019-05-15 02:14:38 +05:30
|
|
|
integer, dimension(:,:), intent(in) :: &
|
2019-02-03 17:24:10 +05:30
|
|
|
mapElemSet
|
2012-06-15 21:40:21 +05:30
|
|
|
|
2019-05-15 02:14:38 +05:30
|
|
|
integer, allocatable, dimension(:) :: chunkPos
|
2018-02-02 19:36:13 +05:30
|
|
|
character(len=300) :: line, &
|
|
|
|
tmp
|
2012-06-15 21:40:21 +05:30
|
|
|
|
2019-05-15 02:14:38 +05:30
|
|
|
integer, dimension (1+nElems) :: contInts
|
|
|
|
integer :: i,cpElem
|
2012-06-15 21:40:21 +05:30
|
|
|
|
2019-05-15 02:14:38 +05:30
|
|
|
cpElem = 0
|
|
|
|
contInts = 0
|
2013-12-11 22:19:20 +05:30
|
|
|
rewind(fileUnit)
|
2012-06-15 21:40:21 +05:30
|
|
|
do
|
2019-06-13 10:55:26 +05:30
|
|
|
read (fileUnit,'(A300)',END=620) line
|
2015-08-28 13:08:48 +05:30
|
|
|
chunkPos = IO_stringPos(line)
|
2019-06-05 16:27:08 +05:30
|
|
|
if (fileFormatVersion < 13) then ! Marc 2016 or earlier
|
2019-05-15 02:14:38 +05:30
|
|
|
if( IO_lc(IO_stringValue(line,chunkPos,1)) == 'hypoelastic' ) then
|
2019-05-17 16:13:42 +05:30
|
|
|
do i=1,3+TableStyle ! skip three (or four if new table style!) lines
|
2019-02-02 21:54:00 +05:30
|
|
|
read (fileUnit,'(A300)') line
|
2018-02-02 19:36:13 +05:30
|
|
|
enddo
|
2019-02-03 21:10:15 +05:30
|
|
|
contInts = IO_continuousIntValues(fileUnit,nElems,nameElemSet,&
|
2019-02-03 17:24:10 +05:30
|
|
|
mapElemSet,size(nameElemSet))
|
2018-02-02 19:36:13 +05:30
|
|
|
exit
|
|
|
|
endif
|
2019-02-03 15:42:23 +05:30
|
|
|
else ! Marc2017 and later
|
2019-05-15 02:14:38 +05:30
|
|
|
if ( IO_lc(IO_stringValue(line,chunkPos,1)) == 'connectivity') then
|
2019-06-13 10:55:26 +05:30
|
|
|
read (fileUnit,'(A300)',END=620) line
|
2018-02-02 19:36:13 +05:30
|
|
|
chunkPos = IO_stringPos(line)
|
2019-10-08 20:56:02 +05:30
|
|
|
if(any(matNumber==IO_intValue(line,chunkPos,6))) then
|
2018-02-02 19:36:13 +05:30
|
|
|
do
|
2019-06-13 10:55:26 +05:30
|
|
|
read (fileUnit,'(A300)',END=620) line
|
2018-02-02 19:36:13 +05:30
|
|
|
chunkPos = IO_stringPos(line)
|
2019-05-15 02:14:38 +05:30
|
|
|
tmp = IO_lc(IO_stringValue(line,chunkPos,1))
|
2019-02-03 15:42:23 +05:30
|
|
|
if (verify(trim(tmp),"0123456789")/=0) then ! found keyword
|
2018-02-02 19:36:13 +05:30
|
|
|
exit
|
|
|
|
else
|
2019-05-15 02:14:38 +05:30
|
|
|
contInts(1) = contInts(1) + 1
|
2018-02-02 19:36:13 +05:30
|
|
|
read (tmp,*) contInts(contInts(1)+1)
|
|
|
|
endif
|
|
|
|
enddo
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
enddo
|
2019-06-13 10:55:26 +05:30
|
|
|
620 do i = 1,contInts(1)
|
2019-05-15 02:14:38 +05:30
|
|
|
cpElem = cpElem+1
|
|
|
|
mesh_mapFEtoCPelem(1,cpElem) = contInts(1+i)
|
2018-02-02 19:36:13 +05:30
|
|
|
mesh_mapFEtoCPelem(2,cpElem) = cpElem
|
|
|
|
enddo
|
|
|
|
|
2019-06-16 00:12:16 +05:30
|
|
|
call math_sort(mesh_mapFEtoCPelem)
|
2009-01-20 00:12:31 +05:30
|
|
|
|
2012-06-15 21:40:21 +05:30
|
|
|
end subroutine mesh_marc_map_elements
|
2009-10-12 21:31:49 +05:30
|
|
|
|
|
|
|
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief Maps node from FE ID to internal (consecutive) representation.
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-10-13 14:12:34 +05:30
|
|
|
subroutine mesh_marc_map_nodes(nNodes,fileContent)
|
2012-06-15 21:40:21 +05:30
|
|
|
|
2019-10-13 14:12:34 +05:30
|
|
|
integer, intent(in) :: nNodes
|
|
|
|
character(len=pStringLen), dimension(:), intent(in) :: fileContent !< file content, separated per lines
|
2009-10-12 21:31:49 +05:30
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
integer, allocatable, dimension(:) :: chunkPos
|
2019-10-13 14:12:34 +05:30
|
|
|
integer :: i, l
|
2012-06-15 21:40:21 +05:30
|
|
|
|
2019-10-13 14:12:34 +05:30
|
|
|
do l = 1, size(fileContent)
|
|
|
|
chunkPos = IO_stringPos(fileContent(l))
|
|
|
|
if( IO_lc(IO_stringValue(fileContent(l),chunkPos,1)) == 'coordinates' ) then
|
2019-06-13 04:09:35 +05:30
|
|
|
do i = 1,nNodes
|
2019-10-13 14:12:34 +05:30
|
|
|
mesh_mapFEtoCPnode(1,i) = IO_fixedIntValue (fileContent(l+1+i),[0,10],1)
|
2019-06-13 04:09:35 +05:30
|
|
|
mesh_mapFEtoCPnode(2,i) = i
|
|
|
|
enddo
|
|
|
|
exit
|
|
|
|
endif
|
|
|
|
enddo
|
2012-06-15 21:40:21 +05:30
|
|
|
|
2019-10-13 14:12:34 +05:30
|
|
|
call math_sort(mesh_mapFEtoCPnode)
|
2018-01-10 21:43:25 +05:30
|
|
|
|
2012-06-15 21:40:21 +05:30
|
|
|
end subroutine mesh_marc_map_nodes
|
2009-10-12 21:31:49 +05:30
|
|
|
|
|
|
|
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief store x,y,z coordinates of all nodes in mesh.
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-10-13 14:12:34 +05:30
|
|
|
function mesh_marc_build_nodes(nNode,fileContent) result(nodes)
|
2009-10-12 21:31:49 +05:30
|
|
|
|
2019-10-13 14:12:34 +05:30
|
|
|
integer, intent(in) :: nNode
|
|
|
|
character(len=pStringLen), dimension(:), intent(in) :: fileContent !< file content, separated per lines
|
|
|
|
|
2019-06-13 11:01:45 +05:30
|
|
|
real(pReal), dimension(3,nNode) :: nodes
|
2019-06-13 04:09:35 +05:30
|
|
|
integer, dimension(5), parameter :: node_ends = [0,10,30,50,70]
|
|
|
|
integer, allocatable, dimension(:) :: chunkPos
|
2019-10-13 14:12:34 +05:30
|
|
|
integer :: i,j,m,l
|
2009-10-12 21:31:49 +05:30
|
|
|
|
2019-10-13 14:12:34 +05:30
|
|
|
do l = 1, size(fileContent)
|
|
|
|
chunkPos = IO_stringPos(fileContent(l))
|
|
|
|
if( IO_lc(IO_stringValue(fileContent(l),chunkPos,1)) == 'coordinates' ) then
|
2019-06-13 11:01:45 +05:30
|
|
|
do i=1,nNode
|
2019-10-13 14:12:34 +05:30
|
|
|
m = mesh_FEasCP('node',IO_fixedIntValue(fileContent(l+1+i),node_ends,1))
|
2019-06-13 04:09:35 +05:30
|
|
|
do j = 1,3
|
2019-10-13 14:12:34 +05:30
|
|
|
nodes(j,m) = mesh_unitlength * IO_fixedNoEFloatValue(fileContent(l+1+i),node_ends,j+1)
|
2019-06-13 04:09:35 +05:30
|
|
|
enddo
|
|
|
|
enddo
|
|
|
|
exit
|
|
|
|
endif
|
|
|
|
enddo
|
2009-10-12 21:31:49 +05:30
|
|
|
|
2019-10-13 14:12:34 +05:30
|
|
|
end function mesh_marc_build_nodes
|
2009-10-12 21:31:49 +05:30
|
|
|
|
2012-03-09 01:55:28 +05:30
|
|
|
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-06-06 16:38:10 +05:30
|
|
|
!> @brief Gets element type (and checks if the whole mesh comprises of only one type)
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-06-06 16:38:10 +05:30
|
|
|
integer function mesh_marc_getElemType(nElem,fileUnit)
|
|
|
|
|
|
|
|
integer, intent(in) :: &
|
|
|
|
nElem, &
|
|
|
|
fileUnit
|
|
|
|
|
|
|
|
type(tElement) :: tempEl
|
|
|
|
integer, allocatable, dimension(:) :: chunkPos
|
|
|
|
character(len=300) :: line
|
|
|
|
integer :: i,t
|
|
|
|
|
|
|
|
t = -1
|
|
|
|
|
|
|
|
rewind(fileUnit)
|
|
|
|
do
|
2019-06-13 10:55:26 +05:30
|
|
|
read (fileUnit,'(A300)',END=620) line
|
2019-06-06 16:38:10 +05:30
|
|
|
chunkPos = IO_stringPos(line)
|
|
|
|
if( IO_lc(IO_stringValue(line,chunkPos,1)) == 'connectivity' ) then
|
|
|
|
read (fileUnit,'(A300)') line ! Garbage line
|
|
|
|
do i=1,nElem ! read all elements
|
|
|
|
read (fileUnit,'(A300)') line
|
|
|
|
chunkPos = IO_stringPos(line)
|
|
|
|
if (t == -1) then
|
|
|
|
t = mapElemtype(IO_stringValue(line,chunkPos,2))
|
|
|
|
call tempEl%init(t)
|
|
|
|
mesh_marc_getElemType = t
|
|
|
|
else
|
|
|
|
if (t /= mapElemtype(IO_stringValue(line,chunkPos,2))) call IO_error(191,el=t,ip=i)
|
|
|
|
endif
|
|
|
|
call IO_skipChunks(fileUnit,tempEl%nNodes-(chunkPos(1)-2))
|
|
|
|
enddo
|
|
|
|
exit
|
|
|
|
endif
|
|
|
|
enddo
|
2009-10-12 21:31:49 +05:30
|
|
|
|
2019-10-05 20:48:21 +05:30
|
|
|
contains
|
2019-02-02 20:47:52 +05:30
|
|
|
|
2019-06-06 16:38:10 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief mapping of Marc element types to internal representation
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
integer function mapElemtype(what)
|
|
|
|
|
|
|
|
character(len=*), intent(in) :: what
|
|
|
|
|
|
|
|
select case (IO_lc(what))
|
|
|
|
case ( '6')
|
|
|
|
mapElemtype = 1 ! Two-dimensional Plane Strain Triangle
|
|
|
|
case ( '155', &
|
|
|
|
'125', &
|
|
|
|
'128')
|
|
|
|
mapElemtype = 2 ! Two-dimensional Plane Strain triangle (155: cubic shape function, 125/128: second order isoparametric)
|
|
|
|
case ( '11')
|
|
|
|
mapElemtype = 3 ! Arbitrary Quadrilateral Plane-strain
|
|
|
|
case ( '27')
|
|
|
|
mapElemtype = 4 ! Plane Strain, Eight-node Distorted Quadrilateral
|
|
|
|
case ( '54')
|
|
|
|
mapElemtype = 5 ! Plane Strain, Eight-node Distorted Quadrilateral with reduced integration
|
|
|
|
case ( '134')
|
|
|
|
mapElemtype = 6 ! Three-dimensional Four-node Tetrahedron
|
|
|
|
case ( '157')
|
|
|
|
mapElemtype = 7 ! Three-dimensional, Low-order, Tetrahedron, Herrmann Formulations
|
|
|
|
case ( '127')
|
|
|
|
mapElemtype = 8 ! Three-dimensional Ten-node Tetrahedron
|
|
|
|
case ( '136')
|
|
|
|
mapElemtype = 9 ! Three-dimensional Arbitrarily Distorted Pentahedral
|
|
|
|
case ( '117', &
|
|
|
|
'123')
|
|
|
|
mapElemtype = 10 ! Three-dimensional Arbitrarily Distorted linear hexahedral with reduced integration
|
|
|
|
case ( '7')
|
|
|
|
mapElemtype = 11 ! Three-dimensional Arbitrarily Distorted Brick
|
|
|
|
case ( '57')
|
|
|
|
mapElemtype = 12 ! Three-dimensional Arbitrarily Distorted quad hexahedral with reduced integration
|
|
|
|
case ( '21')
|
|
|
|
mapElemtype = 13 ! Three-dimensional Arbitrarily Distorted quadratic hexahedral
|
|
|
|
case default
|
|
|
|
call IO_error(error_ID=190,ext_msg=IO_lc(what))
|
|
|
|
end select
|
|
|
|
|
|
|
|
end function mapElemtype
|
|
|
|
|
|
|
|
|
2019-06-13 10:55:26 +05:30
|
|
|
620 end function mesh_marc_getElemType
|
2010-05-06 22:10:47 +05:30
|
|
|
|
|
|
|
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-10-12 22:54:03 +05:30
|
|
|
!> @brief Stores node IDs
|
2012-06-15 21:40:21 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-10-13 02:10:00 +05:30
|
|
|
function mesh_marc_buildElements(nElem,nNodes,fileUnit)
|
2019-05-15 02:42:32 +05:30
|
|
|
|
2019-06-06 16:38:10 +05:30
|
|
|
integer, intent(in) :: &
|
2019-06-13 10:31:35 +05:30
|
|
|
nElem, &
|
2019-10-05 20:48:21 +05:30
|
|
|
nNodes, & !< number of nodes per element
|
2019-06-06 16:38:10 +05:30
|
|
|
fileUnit
|
2019-10-13 02:10:00 +05:30
|
|
|
|
|
|
|
integer, dimension(nElem,nNodes) :: &
|
|
|
|
mesh_marc_buildElements
|
2019-06-06 16:38:10 +05:30
|
|
|
|
|
|
|
integer, allocatable, dimension(:) :: chunkPos
|
|
|
|
character(len=300) line
|
|
|
|
|
2019-06-13 10:31:35 +05:30
|
|
|
integer, dimension(1+nElem) :: contInts
|
2019-06-06 16:38:10 +05:30
|
|
|
integer :: i,j,t,sv,myVal,e,nNodesAlreadyRead
|
|
|
|
|
|
|
|
rewind(fileUnit)
|
|
|
|
do
|
|
|
|
read (fileUnit,'(A300)',END=620) line
|
|
|
|
chunkPos = IO_stringPos(line)
|
|
|
|
if( IO_lc(IO_stringValue(line,chunkPos,1)) == 'connectivity' ) then
|
|
|
|
read (fileUnit,'(A300)',END=620) line ! garbage line
|
2019-06-13 10:31:35 +05:30
|
|
|
do i = 1,nElem
|
2019-06-06 16:38:10 +05:30
|
|
|
read (fileUnit,'(A300)',END=620) line
|
|
|
|
chunkPos = IO_stringPos(line)
|
|
|
|
e = mesh_FEasCP('elem',IO_intValue(line,chunkPos,1))
|
|
|
|
if (e /= 0) then ! disregard non CP elems
|
|
|
|
nNodesAlreadyRead = 0
|
|
|
|
do j = 1,chunkPos(1)-2
|
2019-10-13 15:49:37 +05:30
|
|
|
mesh_marc_buildElements(j,e) = &
|
|
|
|
mesh_FEasCP('node',IO_IntValue(line,chunkPos,j+2))
|
2019-06-06 16:38:10 +05:30
|
|
|
enddo
|
|
|
|
nNodesAlreadyRead = chunkPos(1) - 2
|
2019-10-05 20:48:21 +05:30
|
|
|
do while(nNodesAlreadyRead < nNodes) ! read on if not all nodes in one line
|
2019-06-06 16:38:10 +05:30
|
|
|
read (fileUnit,'(A300)',END=620) line
|
|
|
|
chunkPos = IO_stringPos(line)
|
|
|
|
do j = 1,chunkPos(1)
|
2019-10-13 15:49:37 +05:30
|
|
|
mesh_marc_buildElements(nNodesAlreadyRead+j,e) = &
|
|
|
|
mesh_FEasCP('node',IO_IntValue(line,chunkPos,j))
|
2019-06-06 16:38:10 +05:30
|
|
|
enddo
|
|
|
|
nNodesAlreadyRead = nNodesAlreadyRead + chunkPos(1)
|
|
|
|
enddo
|
|
|
|
endif
|
|
|
|
enddo
|
|
|
|
exit
|
|
|
|
endif
|
|
|
|
enddo
|
2019-10-13 15:23:35 +05:30
|
|
|
|
|
|
|
620 end function mesh_marc_buildElements
|
2019-10-12 22:54:03 +05:30
|
|
|
|
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief Stores homogenization and microstructure ID
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
subroutine mesh_marc_buildElements2(microstructureAt,homogenizationAt, &
|
2019-10-14 00:04:20 +05:30
|
|
|
nElem,nNodes,nameElemSet,mapElemSet,initialcondTableStyle,fileUnit)
|
2019-10-12 22:54:03 +05:30
|
|
|
|
|
|
|
integer, dimension(:), intent(out) :: &
|
|
|
|
microstructureAt, &
|
|
|
|
homogenizationAt
|
|
|
|
integer, intent(in) :: &
|
|
|
|
nElem, &
|
|
|
|
nNodes, & !< number of nodes per element
|
|
|
|
initialcondTableStyle, &
|
|
|
|
fileUnit
|
2019-10-14 00:04:20 +05:30
|
|
|
character(len=64), dimension(:), intent(in) :: &
|
|
|
|
nameElemSet
|
|
|
|
integer, dimension(:,:), intent(in) :: &
|
|
|
|
mapElemSet !< list of elements in elementSet
|
2019-10-12 22:54:03 +05:30
|
|
|
|
|
|
|
integer, allocatable, dimension(:) :: chunkPos
|
|
|
|
character(len=300) line
|
|
|
|
|
|
|
|
integer, dimension(1+nElem) :: contInts
|
|
|
|
integer :: i,j,t,sv,myVal,e,nNodesAlreadyRead
|
|
|
|
|
2019-10-13 15:23:35 +05:30
|
|
|
rewind(fileUnit)
|
2019-06-06 16:38:10 +05:30
|
|
|
read (fileUnit,'(A300)',END=630) line
|
|
|
|
do
|
|
|
|
chunkPos = IO_stringPos(line)
|
|
|
|
if( (IO_lc(IO_stringValue(line,chunkPos,1)) == 'initial') .and. &
|
|
|
|
(IO_lc(IO_stringValue(line,chunkPos,2)) == 'state') ) then
|
|
|
|
if (initialcondTableStyle == 2) read (fileUnit,'(A300)',END=630) line ! read extra line for new style
|
|
|
|
read (fileUnit,'(A300)',END=630) line ! read line with index of state var
|
|
|
|
chunkPos = IO_stringPos(line)
|
|
|
|
sv = IO_IntValue(line,chunkPos,1) ! figure state variable index
|
|
|
|
if( (sv == 2).or.(sv == 3) ) then ! only state vars 2 and 3 of interest
|
|
|
|
read (fileUnit,'(A300)',END=630) line ! read line with value of state var
|
|
|
|
chunkPos = IO_stringPos(line)
|
|
|
|
do while (scan(IO_stringValue(line,chunkPos,1),'+-',back=.true.)>1) ! is noEfloat value?
|
|
|
|
myVal = nint(IO_fixedNoEFloatValue(line,[0,20],1),pInt) ! state var's value
|
|
|
|
if (initialcondTableStyle == 2) then
|
|
|
|
read (fileUnit,'(A300)',END=630) line ! read extra line
|
|
|
|
read (fileUnit,'(A300)',END=630) line ! read extra line
|
|
|
|
endif
|
|
|
|
contInts = IO_continuousIntValues& ! get affected elements
|
2019-10-14 00:04:20 +05:30
|
|
|
(fileUnit,nElem,nameElemSet,mapElemSet,size(nameElemSet))
|
2019-06-06 16:38:10 +05:30
|
|
|
do i = 1,contInts(1)
|
|
|
|
e = mesh_FEasCP('elem',contInts(1+i))
|
2019-10-08 13:00:32 +05:30
|
|
|
if (sv == 2) microstructureAt(e) = myVal
|
|
|
|
if (sv == 3) homogenizationAt(e) = myVal
|
2019-06-06 16:38:10 +05:30
|
|
|
enddo
|
|
|
|
if (initialcondTableStyle == 0) read (fileUnit,'(A300)',END=630) line ! ignore IP range for old table style
|
|
|
|
read (fileUnit,'(A300)',END=630) line
|
|
|
|
chunkPos = IO_stringPos(line)
|
|
|
|
enddo
|
|
|
|
endif
|
|
|
|
else
|
|
|
|
read (fileUnit,'(A300)',END=630) line
|
|
|
|
endif
|
|
|
|
enddo
|
|
|
|
|
2019-10-12 22:54:03 +05:30
|
|
|
630 end subroutine mesh_marc_buildElements2
|
2019-02-02 21:54:00 +05:30
|
|
|
|
|
|
|
|
2019-10-14 01:15:08 +05:30
|
|
|
subroutine buildCells(nNodes,elem,connectivity_elem)
|
2019-05-17 16:52:52 +05:30
|
|
|
|
2019-10-14 01:15:08 +05:30
|
|
|
integer, intent(in) :: nNodes
|
2019-10-08 22:22:34 +05:30
|
|
|
type(tElement), intent(in) :: elem
|
2019-06-12 22:38:38 +05:30
|
|
|
integer,dimension(:,:), intent(in) :: connectivity_elem
|
2019-10-08 22:22:34 +05:30
|
|
|
|
|
|
|
integer,dimension(:), allocatable :: candidates_local
|
|
|
|
integer,dimension(:,:), allocatable :: parentsAndWeights,candidates_global, connectivity_cell_reshape
|
2019-06-13 03:35:29 +05:30
|
|
|
integer,dimension(:,:,:), allocatable :: connectivity_cell
|
2019-10-08 22:22:34 +05:30
|
|
|
|
2019-10-13 15:49:37 +05:30
|
|
|
type(tCellNodeDefinition), dimension(:), allocatable :: cellNodeDefinition
|
|
|
|
|
2019-06-13 04:09:35 +05:30
|
|
|
integer :: e, n, c, p, s,i,m,j,nParentNodes,nCellNode,Nelem,candidateID
|
2019-06-12 22:38:38 +05:30
|
|
|
|
2019-10-14 01:15:08 +05:30
|
|
|
Nelem = size(connectivity_elem,1)
|
2019-05-17 16:52:52 +05:30
|
|
|
|
|
|
|
!---------------------------------------------------------------------------------------------------
|
|
|
|
! initialize global connectivity to negative local connectivity
|
2019-06-12 22:38:38 +05:30
|
|
|
allocate(connectivity_cell(elem%NcellNodesPerCell,elem%nIPs,Nelem))
|
|
|
|
connectivity_cell = -spread(elem%cell,3,Nelem) ! local cell node ID
|
2019-05-17 16:52:52 +05:30
|
|
|
|
|
|
|
!---------------------------------------------------------------------------------------------------
|
2019-06-12 22:38:38 +05:30
|
|
|
! set connectivity of cell nodes that coincide with FE nodes (defined by 1 parent node)
|
|
|
|
! and renumber local (negative) to global (positive) node ID
|
|
|
|
do e = 1, Nelem
|
|
|
|
do c = 1, elem%NcellNodes
|
|
|
|
realNode: if (count(elem%cellNodeParentNodeWeights(:,c) /= 0) == 1) then
|
2019-05-17 16:52:52 +05:30
|
|
|
where(connectivity_cell(:,:,e) == -c)
|
|
|
|
connectivity_cell(:,:,e) = connectivity_elem(c,e)
|
|
|
|
end where
|
|
|
|
endif realNode
|
|
|
|
enddo
|
|
|
|
enddo
|
2019-10-14 01:15:08 +05:30
|
|
|
nCellNode = nNodes
|
2019-05-17 16:52:52 +05:30
|
|
|
|
2019-10-13 15:49:37 +05:30
|
|
|
|
|
|
|
allocate(cellNodeDefinition(elem%nNodes-1))
|
2019-05-17 16:52:52 +05:30
|
|
|
|
2019-06-12 22:38:38 +05:30
|
|
|
!---------------------------------------------------------------------------------------------------
|
|
|
|
! set connectivity of cell nodes that are defined by 2,...,nNodes real nodes
|
|
|
|
do nParentNodes = 2, elem%nNodes
|
2019-05-17 16:52:52 +05:30
|
|
|
|
2019-06-12 22:38:38 +05:30
|
|
|
! get IDs of local cell nodes that are defined by the current number of parent nodes
|
|
|
|
candidates_local = [integer::]
|
|
|
|
do c = 1, elem%NcellNodes
|
|
|
|
if (count(elem%cellNodeParentNodeWeights(:,c) /= 0) == nParentNodes) &
|
|
|
|
candidates_local = [candidates_local,c]
|
|
|
|
enddo
|
|
|
|
s = size(candidates_local)
|
|
|
|
|
|
|
|
if (allocated(candidates_global)) deallocate(candidates_global)
|
2019-06-13 10:31:35 +05:30
|
|
|
allocate(candidates_global(nParentNodes*2+2,s*Nelem)) ! stores parent node ID + weight together with element ID and cellnode id (local)
|
|
|
|
parentsAndWeights = reshape([(0, i = 1,2*nParentNodes)],[nParentNodes,2]) ! (re)allocate
|
2019-06-12 22:38:38 +05:30
|
|
|
|
|
|
|
do e = 1, Nelem
|
|
|
|
do i = 1, size(candidates_local)
|
2019-06-13 10:31:35 +05:30
|
|
|
candidateID = (e-1)*size(candidates_local)+i ! including duplicates, runs to (Nelem*size(candidates_local))
|
|
|
|
c = candidates_local(i) ! c is local cellnode ID for connectivity
|
2019-06-12 22:38:38 +05:30
|
|
|
p = 0
|
|
|
|
do j = 1, size(elem%cellNodeParentNodeWeights(:,c))
|
|
|
|
if (elem%cellNodeParentNodeWeights(j,c) /= 0) then ! real node 'j' partly defines cell node 'c'
|
|
|
|
p = p + 1
|
|
|
|
parentsAndWeights(p,1:2) = [connectivity_elem(j,e),elem%cellNodeParentNodeWeights(j,c)]
|
|
|
|
endif
|
|
|
|
enddo
|
|
|
|
! store (and order) real node IDs and their weights together with the element number and local ID
|
|
|
|
do p = 1, nParentNodes
|
|
|
|
m = maxloc(parentsAndWeights(:,1),1)
|
|
|
|
|
|
|
|
candidates_global(p, candidateID) = parentsAndWeights(m,1)
|
|
|
|
candidates_global(p+nParentNodes, candidateID) = parentsAndWeights(m,2)
|
|
|
|
candidates_global(nParentNodes*2+1:nParentNodes*2+2,candidateID) = [e,c]
|
|
|
|
|
2019-06-13 10:31:35 +05:30
|
|
|
parentsAndWeights(m,1) = -huge(parentsAndWeights(m,1)) ! out of the competition
|
2019-06-12 22:38:38 +05:30
|
|
|
enddo
|
|
|
|
enddo
|
|
|
|
enddo
|
2019-05-17 16:52:52 +05:30
|
|
|
|
2019-06-12 22:38:38 +05:30
|
|
|
! sort according to real node IDs + weight (from left to right)
|
2019-06-13 10:31:35 +05:30
|
|
|
call math_sort(candidates_global,sortDim=1) ! sort according to first column
|
2019-06-12 22:38:38 +05:30
|
|
|
|
|
|
|
do p = 2, nParentNodes*2
|
|
|
|
n = 1
|
|
|
|
do while(n <= size(candidates_local)*Nelem)
|
|
|
|
j=0
|
|
|
|
do while (n+j<= size(candidates_local)*Nelem)
|
|
|
|
if (candidates_global(p-1,n+j)/=candidates_global(p-1,n)) exit
|
|
|
|
j = j + 1
|
|
|
|
enddo
|
|
|
|
e = n+j-1
|
|
|
|
if (any(candidates_global(p,n:e)/=candidates_global(p,n))) &
|
|
|
|
call math_sort(candidates_global(:,n:e),sortDim=p)
|
|
|
|
n = e+1
|
2019-05-17 16:52:52 +05:30
|
|
|
enddo
|
2019-06-12 22:38:38 +05:30
|
|
|
enddo
|
|
|
|
|
2019-06-13 10:31:35 +05:30
|
|
|
i = uniqueRows(candidates_global(1:2*nParentNodes,:))
|
2019-10-13 15:49:37 +05:30
|
|
|
allocate(cellNodeDefinition(nParentNodes-1)%parents(i,nParentNodes))
|
|
|
|
allocate(cellNodeDefinition(nParentNodes-1)%weights(i,nParentNodes))
|
2019-06-12 22:38:38 +05:30
|
|
|
|
|
|
|
i = 1
|
|
|
|
n = 1
|
|
|
|
do while(n <= size(candidates_local)*Nelem)
|
2019-10-13 15:49:37 +05:30
|
|
|
j=0
|
|
|
|
parentsAndWeights(:,1) = candidates_global(1:nParentNodes,n+j)
|
|
|
|
parentsAndWeights(:,2) = candidates_global(nParentNodes+1:nParentNodes*2,n+j)
|
|
|
|
e = candidates_global(nParentNodes*2+1,n+j)
|
|
|
|
c = candidates_global(nParentNodes*2+2,n+j)
|
2019-06-12 22:38:38 +05:30
|
|
|
|
2019-10-13 15:49:37 +05:30
|
|
|
do while (n+j<= size(candidates_local)*Nelem)
|
|
|
|
if (any(candidates_global(1:2*nParentNodes,n+j)/=candidates_global(1:2*nParentNodes,n))) exit
|
|
|
|
where (connectivity_cell(:,:,candidates_global(nParentNodes*2+1,n+j)) == -candidates_global(nParentNodes*2+2,n+j)) ! still locally defined
|
|
|
|
connectivity_cell(:,:,candidates_global(nParentNodes*2+1,n+j)) = nCellNode + i ! gets current new cell node id
|
|
|
|
end where
|
2019-06-12 22:38:38 +05:30
|
|
|
|
2019-10-13 15:49:37 +05:30
|
|
|
j = j+1
|
|
|
|
enddo
|
|
|
|
cellNodeDefinition(nParentNodes-1)%parents(i,:) = parentsAndWeights(:,1)
|
|
|
|
cellNodeDefinition(nParentNodes-1)%weights(i,:) = parentsAndWeights(:,2)
|
|
|
|
i = i+1
|
|
|
|
n = n+j
|
2019-06-12 22:38:38 +05:30
|
|
|
|
|
|
|
enddo
|
|
|
|
nCellNode = nCellNode + i
|
2019-10-14 00:39:49 +05:30
|
|
|
|
|
|
|
|
2019-06-13 10:31:35 +05:30
|
|
|
enddo
|
2019-10-14 01:15:08 +05:30
|
|
|
|
|
|
|
mesh_cell2 = connectivity_cell
|
2019-06-13 04:09:35 +05:30
|
|
|
|
2019-09-24 10:43:52 +05:30
|
|
|
contains
|
|
|
|
!------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief count unique rows (same rows need to be stored consecutively)
|
|
|
|
!------------------------------------------------------------------------------------------------
|
2019-06-13 10:31:35 +05:30
|
|
|
pure function uniqueRows(A) result(u)
|
|
|
|
|
|
|
|
integer, dimension(:,:), intent(in) :: A !< array, rows need to be sorted
|
|
|
|
|
|
|
|
integer :: &
|
|
|
|
u, & !< # of unique rows
|
|
|
|
r, & !< row counter
|
|
|
|
d !< duplicate counter
|
|
|
|
|
|
|
|
u = 0
|
|
|
|
r = 1
|
|
|
|
do while(r <= size(A,2))
|
|
|
|
d = 0
|
|
|
|
do while (r+d<= size(A,2))
|
|
|
|
if (any(A(:,r)/=A(:,r+d))) exit
|
|
|
|
d = d+1
|
|
|
|
enddo
|
|
|
|
u = u+1
|
|
|
|
r = r+d
|
|
|
|
enddo
|
|
|
|
|
|
|
|
end function uniqueRows
|
|
|
|
|
2019-06-13 03:35:29 +05:30
|
|
|
end subroutine buildCells
|
2019-05-17 16:52:52 +05:30
|
|
|
|
2019-06-06 11:07:37 +05:30
|
|
|
|
2019-10-12 22:54:03 +05:30
|
|
|
!---------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief cell neighborhood
|
|
|
|
!---------------------------------------------------------------------------------------------------
|
2019-06-05 04:06:25 +05:30
|
|
|
subroutine IP_neighborhood2
|
|
|
|
|
2019-06-05 22:23:02 +05:30
|
|
|
integer, dimension(:,:), allocatable :: faces
|
2019-10-12 22:54:03 +05:30
|
|
|
integer, dimension(:), allocatable :: face
|
2019-06-06 11:07:37 +05:30
|
|
|
integer :: e,i,f,c,m,n,j,k,l,p, current, next,i2,e2,n2,k2
|
|
|
|
logical :: match
|
2019-10-12 22:54:03 +05:30
|
|
|
|
2019-06-06 11:07:37 +05:30
|
|
|
allocate(faces(size(theMesh%elem%cellface,1)+3,size(theMesh%elem%cellface,2)*theMesh%elem%nIPs*theMesh%Nelems))
|
2019-06-05 04:06:25 +05:30
|
|
|
|
2019-06-06 11:07:37 +05:30
|
|
|
! store cell face definitions
|
2019-06-05 22:23:02 +05:30
|
|
|
f = 0
|
2019-06-05 11:52:34 +05:30
|
|
|
do e = 1,theMesh%nElems
|
|
|
|
do i = 1,theMesh%elem%nIPs
|
2019-06-05 22:23:02 +05:30
|
|
|
do n = 1, theMesh%elem%nIPneighbors
|
|
|
|
f = f + 1
|
|
|
|
face = mesh_cell2(theMesh%elem%cellFace(:,n),i,e)
|
2019-06-06 11:07:37 +05:30
|
|
|
storeSorted: do j = 1, size(face)
|
2019-06-05 22:23:02 +05:30
|
|
|
faces(j,f) = maxval(face)
|
|
|
|
face(maxloc(face)) = -huge(1)
|
2019-06-06 11:07:37 +05:30
|
|
|
enddo storeSorted
|
|
|
|
faces(j:j+2,f) = [e,i,n]
|
2019-06-05 22:23:02 +05:30
|
|
|
enddo
|
2019-06-05 11:52:34 +05:30
|
|
|
enddo
|
|
|
|
enddo
|
|
|
|
|
2019-06-05 22:23:02 +05:30
|
|
|
! sort ..
|
|
|
|
call math_sort(faces,sortDim=1)
|
|
|
|
do p = 2, size(faces,1)-2
|
|
|
|
n = 1
|
|
|
|
do while(n <= size(faces,2))
|
|
|
|
j=0
|
|
|
|
do while (n+j<= size(faces,2))
|
|
|
|
if (faces(p-1,n+j)/=faces(p-1,n)) exit
|
|
|
|
j = j + 1
|
|
|
|
enddo
|
|
|
|
e = n+j-1
|
|
|
|
if (any(faces(p,n:e)/=faces(p,n))) call math_sort(faces(:,n:e),sortDim=p)
|
|
|
|
n = e+1
|
|
|
|
enddo
|
|
|
|
enddo
|
|
|
|
|
2019-06-06 11:07:37 +05:30
|
|
|
allocate(mesh_ipNeighborhood2(3,theMesh%elem%nIPneighbors,theMesh%elem%nIPs,theMesh%nElems),source=0)
|
|
|
|
|
|
|
|
! find IP neighbors
|
|
|
|
f = 1
|
|
|
|
do while(f <= size(faces,2))
|
|
|
|
e = faces(size(theMesh%elem%cellface,1)+1,f)
|
|
|
|
i = faces(size(theMesh%elem%cellface,1)+2,f)
|
|
|
|
n = faces(size(theMesh%elem%cellface,1)+3,f)
|
|
|
|
|
|
|
|
if (f < size(faces,2)) then
|
|
|
|
match = all(faces(1:size(theMesh%elem%cellface,1),f) == faces(1:size(theMesh%elem%cellface,1),f+1))
|
|
|
|
e2 = faces(size(theMesh%elem%cellface,1)+1,f+1)
|
|
|
|
i2 = faces(size(theMesh%elem%cellface,1)+2,f+1)
|
|
|
|
n2 = faces(size(theMesh%elem%cellface,1)+3,f+1)
|
|
|
|
else
|
|
|
|
match = .false.
|
|
|
|
endif
|
|
|
|
|
|
|
|
if (match) then
|
|
|
|
if (e == e2) then ! same element. MD: I don't think that we need this (not even for other elements)
|
|
|
|
k = theMesh%elem%IPneighbor(n, i)
|
|
|
|
k2 = theMesh%elem%IPneighbor(n2,i2)
|
|
|
|
endif
|
|
|
|
mesh_ipNeighborhood2(1:3,n, i, e) = [e2,i2,n2]
|
|
|
|
mesh_ipNeighborhood2(1:3,n2,i2,e2) = [e, i, n]
|
|
|
|
f = f +1
|
|
|
|
endif
|
|
|
|
f = f +1
|
|
|
|
enddo
|
2019-06-05 04:06:25 +05:30
|
|
|
|
|
|
|
end subroutine IP_neighborhood2
|
|
|
|
|
2019-10-12 22:54:03 +05:30
|
|
|
|
2019-02-02 21:54:00 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief Gives the FE to CP ID mapping by binary search through lookup array
|
|
|
|
!! valid questions (what) are 'elem', 'node'
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2019-05-15 02:14:38 +05:30
|
|
|
integer function mesh_FEasCP(what,myID)
|
2019-02-02 21:54:00 +05:30
|
|
|
|
2019-06-16 00:12:16 +05:30
|
|
|
character(len=*), intent(in) :: what
|
|
|
|
integer, intent(in) :: myID
|
|
|
|
|
|
|
|
integer, dimension(:,:), pointer :: lookupMap
|
|
|
|
integer :: lower,upper,center
|
|
|
|
|
|
|
|
mesh_FEasCP = 0
|
|
|
|
select case(IO_lc(what(1:4)))
|
|
|
|
case('elem')
|
|
|
|
lookupMap => mesh_mapFEtoCPelem
|
|
|
|
case('node')
|
|
|
|
lookupMap => mesh_mapFEtoCPnode
|
|
|
|
case default
|
|
|
|
return
|
|
|
|
endselect
|
|
|
|
|
|
|
|
lower = 1
|
|
|
|
upper = int(size(lookupMap,2),pInt)
|
|
|
|
|
|
|
|
if (lookupMap(1,lower) == myID) then ! check at bounds QUESTION is it valid to extend bounds by 1 and just do binary search w/o init check at bounds?
|
|
|
|
mesh_FEasCP = lookupMap(2,lower)
|
|
|
|
return
|
|
|
|
elseif (lookupMap(1,upper) == myID) then
|
|
|
|
mesh_FEasCP = lookupMap(2,upper)
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
binarySearch: do while (upper-lower > 1)
|
|
|
|
center = (lower+upper)/2
|
|
|
|
if (lookupMap(1,center) < myID) then
|
|
|
|
lower = center
|
|
|
|
elseif (lookupMap(1,center) > myID) then
|
|
|
|
upper = center
|
|
|
|
else
|
|
|
|
mesh_FEasCP = lookupMap(2,center)
|
|
|
|
exit
|
|
|
|
endif
|
|
|
|
enddo binarySearch
|
2019-02-02 21:54:00 +05:30
|
|
|
|
|
|
|
end function mesh_FEasCP
|
|
|
|
|
2012-08-16 20:25:23 +05:30
|
|
|
end module mesh
|