Skip to content

Commit bad79ca

Browse files
Javier VeloMarDiehl
authored andcommitted
Support named mesh element groups for BC
Allow the use of named groups (labels) from the mesh file to apply BC and/or material ID, instead of numbers (tag). Using labels is still allowed for backwards compatibility. If a group has a label, either of the tag or the label can be used to reference it (but not both). Add error checks for: - Inexistent labels (i.e. trying to apply a BC onto a label not defined in the mesh file). - No groups defined for material ID assignment. - Groups must be created; they may or may not be named. Use the label for printing loadcase information, when appropriate. Update/improve some loadcase/boundary condition error messages.
1 parent 1ed2222 commit bad79ca

File tree

6 files changed

+316
-202
lines changed

6 files changed

+316
-202
lines changed

PRIVATE

src/IO.f90

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,8 @@ subroutine IO_error_new(error_ID, &
508508
! errors related to the mesh solver
509509
case (800)
510510
msg = 'invalid mesh'
511+
case (812)
512+
msg = 'invalid boundary conditions'
511513

512514
!-------------------------------------------------------------------------------------------------
513515
! errors related to the grid solver

src/mesh/DAMASK_mesh.f90

Lines changed: 69 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ program DAMASK_mesh
1111
use PetscDM
1212
use prec
1313
use CLI
14+
use IO
1415
use parallelization
1516
use materialpoint
1617
use discretization_mesh
@@ -40,10 +41,11 @@ program DAMASK_mesh
4041
logical :: &
4142
guess, & !< guess along former trajectory
4243
stagIterate
44+
logical, allocatable, dimension(:) :: &
45+
read_BC_entries
4346
integer :: &
4447
l, &
4548
m, &
46-
errorID, &
4749
cutBackLevel = 0, & !< cut back level \f$ t = \frac{t_{inc}}{2^l} \f$
4850
stepFraction = 0, & !< fraction of current time interval
4951
inc, & !< current increment in current load case
@@ -64,32 +66,29 @@ program DAMASK_mesh
6466
mech_u, &
6567
step_mech
6668
character(len=pSTRLEN) :: &
67-
incInfo, &
68-
loadcase_string
69+
incInfo
6970
integer :: &
71+
bc_tag, &
7072
stagItMax, & !< max number of field level staggered iterations
7173
maxCutBack, & !< max number of cutbacks
72-
skipBCTagDigits, & !< number of characters to skip to print BC tag (T descriptor)
73-
BCTag !< tag value read from YAML load file
74-
integer, allocatable, dimension(:) :: &
75-
knownBCTags !< array of read BC tags (check for duplicates)
76-
74+
skip_T1, skip_T2 !< number of characters to skip (T descriptor)
7775

7876
type(tLoadCase), allocatable, dimension(:) :: loadCases !< array of all load cases
7977
type(tSolutionState), allocatable, dimension(:) :: solres
8078
PetscInt :: boundary, dimPlex
8179
PetscErrorCode :: err_PETSc
8280
character(len=:), allocatable :: &
83-
fileContent, fname, tagPrintFormat
84-
character(len=6) :: BC_elem
81+
fileContent, fname
82+
character(len=pSTRLEN) :: &
83+
bc_label_name
8584

8685

8786
!--------------------------------------------------------------------------------------------------
8887
! init DAMASK (all modules)
8988
call materialpoint_initAll()
9089
print'(/,1x,a)', '<<<+- DAMASK_mesh init -+>>>'; flush(IO_STDOUT)
9190

92-
!---------------------------------------------------------------------
91+
!--------------------------------------------------------------------------------------------------
9392
! reading field information from numerics file and do sanity checks
9493
num_solver => config_numerics%get_dict('solver',defaultVal=emptyDict)
9594
num_mesh => num_solver%get_dict('mesh',defaultVal=emptyDict)
@@ -99,8 +98,10 @@ program DAMASK_mesh
9998
if (stagItMax < 0) call IO_error(301,ext_msg='N_staggered_iter_max')
10099
if (maxCutBack < 0) call IO_error(301,ext_msg='N_cutback_max')
101100

102-
! reading basic information from load case file and allocate data structure containing load cases
103-
call DMGetDimension(geomMesh,dimPlex,err_PETSc) !< dimension of mesh (2D or 3D)
101+
!--------------------------------------------------------------------------------------------------
102+
! reading basic information from load case file, allocate data structure containing load cases
103+
! and some checks for invalid tags/labels use
104+
call DMGetDimension(geomMesh,dimPlex,err_PETSc) ! dimension of mesh (2D or 3D)
104105
CHKERRA(err_PETSc)
105106
allocate(solres(1))
106107

@@ -117,31 +118,45 @@ program DAMASK_mesh
117118
load => YAML_str_asDict(fileContent)
118119
load_steps => load%get_list('loadstep')
119120

121+
allocate(read_BC_entries(mesh_nBoundaries), source = .false.)
120122
allocate(loadCases(size(load_steps)))
121123
do l = 1, size(load_steps)
122124
load_step => load_steps%get_dict(l)
123125
step_bc => load_step%get_dict('boundary_conditions')
124126
step_mech => step_bc%get_list('mechanical')
125127
allocate(loadCases(l)%mechBC(mesh_Nboundaries))
126-
loadCases(l)%mechBC(:)%nComponents = dimPlex !< X, Y (, Z) displacements
128+
loadCases(l)%mechBC(:)%nComponents = dimPlex ! X, Y (, Z) displacements
127129
do boundary = 1_pPETSCINT, mesh_Nboundaries
128130
allocate(loadCases(l)%mechBC(boundary)%dot_u(dimPlex), source = 0.0_pREAL)
129131
allocate(loadCases(l)%mechBC(boundary)%active(dimPlex), source = .false.)
130132
end do
131133

132-
allocate(knownBCTags(size(step_mech)), source = -1)
133134
do m = 1, size(step_mech)
134135
mech_BC => step_mech%get_dict(m)
135-
BCTag = mech_BC%get_asInt('tag')
136-
boundary = findloc(mesh_boundariesIS, BCtag, dim = 1)
137-
if (boundary == 0) then !< tag not defined in mesh file
138-
call IO_error(error_ID = 837, ext_msg = 'BC tag '//mech_BC%get_asStr('tag')// &
139-
' refers to inexistent node/edge/face mesh group')
140-
else if (findloc(knownBCTags, BCTag, dim = 1) /= 0) then !< duplicated tag
141-
call IO_error(error_ID = 837, ext_msg = 'BC redefinition not allowed (tag '// &
142-
mech_BC%get_asStr('tag')//')')
136+
if (mech_BC%contains('label')) then
137+
bc_label_name = mech_BC%get_asStr('label')
138+
boundary = findloc(mesh_BCLabels, bc_label_name, dim = 1)
139+
if (boundary == 0) & ! label not defined in mesh file
140+
call IO_error(812_pI16, 'label', trim(bc_label_name), 'not defined', emph = [2])
141+
if (read_BC_entries(boundary)) & ! duplicated label/tag
142+
call IO_error(812_pI16, 'duplicated entries: label', trim(bc_label_name), "and tag", &
143+
mesh_boundariesIS(boundary), emph = [2,4])
144+
read_BC_entries(boundary) = .true.
145+
loadCases(l)%mechBC(boundary)%use_label = .true.
146+
else if (mech_BC%contains('tag')) then
147+
bc_tag = mech_BC%get_asInt('tag')
148+
boundary = findloc(mesh_boundariesIS, bc_tag, dim = 1)
149+
if (boundary == 0) & ! tag not defined in mesh file
150+
call IO_error(812_pI16, 'tag', bc_tag, 'not defined', emph = [2])
151+
if (read_BC_entries(boundary)) & ! duplicated tag/label
152+
call IO_error(812_pI16, 'duplicated entries: tag', bc_tag, 'and label', &
153+
trim(mesh_BCLabels(boundary)), emph = [2, 4])
154+
read_BC_entries(boundary) = .true.
155+
loadCases(l)%mechBC(boundary)%use_label = .false.
156+
else
157+
call IO_error(837_pI16, 'entry'//IO_intAsStr(m)//': at least one of &
158+
& "tag/label" required')
143159
end if
144-
knownBCTags(m) = BCTag
145160
mech_u => mech_BC%get_list('dot_u')
146161
do component = 1, dimPlex
147162
if (mech_u%get_asStr(component) /= 'x') then
@@ -150,7 +165,7 @@ program DAMASK_mesh
150165
end if
151166
end do
152167
end do
153-
deallocate(knownBCTags)
168+
read_BC_entries = .false.
154169

155170
step_discretization => load_step%get_dict('discretization')
156171
loadCases(l)%t = step_discretization%get_asReal('t')
@@ -163,38 +178,45 @@ program DAMASK_mesh
163178
end if
164179
loadCases(l)%estimate_rate = (load_step%get_asBool('estimate_rate',defaultVal=.true.) .and. l>1)
165180
end do
181+
deallocate(read_BC_entries)
166182

167183
!--------------------------------------------------------------------------------------------------
168-
! consistency checks and output of load case
169-
errorID = 0
170-
skipBCTagDigits = 4+6+1+floor(log10(real(maxval(mesh_boundariesIS))))+1+2 !< Indentation(4)+BC_elem(6)+blank(1)+descriptor T(1)+NumDigits(floor(..)+1)+2(start printing after 1 blank)
171-
allocate(character(len=skipBCTagDigits) :: tagPrintFormat)
172-
write(tagPrintFormat,'(i0)') skipBCTagDigits
184+
! loadcase parameters checks and output of load case information
185+
skip_T1 = 4+max(len(PETSC_GENERIC_LABELS), maxval(len_trim(mesh_BCLabels)))+2 ! indentation(4)+length_longest_label+blank
186+
skip_T2 = skip_T1+1+floor(log10(real(maxval(mesh_boundariesIS))))+1+1+1 ! T1+"("+NumDigits(floor()+1)+")"+blank
173187
checkLoadcases: do l = 1, size(load_steps)
174-
write (loadcase_string, '(i0)' ) l
188+
if (loadCases(l)%N < 1) &
189+
call IO_error(813_pI16, 'loadcase', IO_intAsStr(l)//':', 'N', &
190+
'must be positive', emph = [3])
191+
if (loadCases(l)%f_out < 1) &
192+
call IO_error(813_pI16, 'loadcase', IO_intAsStr(l)//':', 'f_out', &
193+
'must be positive', emph = [3])
194+
175195
print'(/,1x,a,1x,i0)', 'load case:', l
176-
if (.not. loadCases(l)%estimate_rate) &
177-
print'(2x,a)', 'drop guessing along trajectory'
196+
if (.not. loadCases(l)%estimate_rate) print'(2x,a)', 'drop guessing along trajectory'
178197
print'(2x,a)', 'Field '//trim(FIELD_MECH_label)
179198

180199
do boundary = 1_pPETSCINT, mesh_Nboundaries
181-
BC_elem = merge('Vertex', merge('Edge ', 'Face ', dimplex == 2_pPETSCINT), &
182-
mesh_boundariesIdx(boundary) == mesh_BCTypeVertex)
200+
if (loadCases(l)%mechBC(boundary)%use_label) then
201+
bc_label_name = trim(mesh_BCLabels(boundary))
202+
else
203+
m = mesh_boundariesIdx(boundary)
204+
if (dimPlex == 2_pPETSCINT .and. m < 4) m = m + 1
205+
bc_label_name = PETSC_GENERIC_LABELS(m)
206+
end if
183207
do component = 1_pPETSCINT, dimPlex
184208
if (loadCases(l)%mechBC(boundary)%active(component)) &
185-
print'(4x,a,1x,i0,T'//tagPrintFormat//',a,1x,i1,1x,a,1x,f12.7)', &
186-
BC_elem, mesh_boundariesIS(boundary), &
187-
'Component', component, &
188-
'Value', loadCases(l)%mechBC(boundary)%dot_u(component)
209+
print'(4x,a,T'//IO_intAsStr(skip_T1)//',a,i0,a,'// &
210+
'T'//IO_intAsStr(skip_T2)//',a,1x,i1,1x,a,1x,f12.7)', &
211+
trim(bc_label_name), "(", mesh_boundariesIS(boundary), ")", &
212+
'Component', component, &
213+
'Value', loadCases(l)%mechBC(boundary)%dot_u(component)
189214
end do
190215
end do
191216

192-
print'(2x,a,T21,g0.6)', 'time:', loadCases(l)%t
193-
if (loadCases(l)%N < 1) errorID = 835 ! non-positive incs count
194-
print'(2x,a,T21,i0)', 'increments:', loadCases(l)%N
195-
if (loadCases(l)%f_out < 1) errorID = 836 ! non-positive result frequency
217+
print'(2x,a,T21,g0.6)', 'time:', loadCases(l)%t
218+
print'(2x,a,T21,i0)', 'increments:', loadCases(l)%N
196219
print'(2x,a,T21,i0)', 'output frequency:', loadCases(l)%f_out
197-
if (errorID > 0) call IO_error(error_ID = errorID, ext_msg = loadcase_string) ! exit with error message
198220
end do checkLoadcases
199221

200222
!--------------------------------------------------------------------------------------------------
@@ -213,8 +235,8 @@ program DAMASK_mesh
213235
call materialpoint_result(0,0.0_pREAL)
214236

215237
loadCaseLooping: do l = 1, size(load_steps)
216-
t_0 = t ! load case start time
217-
guess = loadCases(l)%estimate_rate ! change of load case? homogeneous guess for the first inc
238+
t_0 = t ! load case start time
239+
guess = loadCases(l)%estimate_rate ! change of load case? homogeneous guess for the first inc
218240

219241
incLooping: do inc = 1, loadCases(l)%N
220242
totalIncsCounter = totalIncsCounter + 1
@@ -292,7 +314,7 @@ program DAMASK_mesh
292314
print'(/,1x,a,1x,i0,1x,a)', 'increment', totalIncsCounter, 'NOT converged'
293315
end if; flush(IO_STDOUT)
294316

295-
if (mod(inc,loadCases(l)%f_out) == 0) then ! at output frequency
317+
if (mod(inc,loadCases(l)%f_out) == 0) then ! at output frequency
296318
print'(/,1x,a)', '... saving results ........................................................'
297319
call FEM_mechanical_updateCoords()
298320
call materialpoint_result(totalIncsCounter,t)

src/mesh/FEM_utilities.f90

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ module FEM_utilities
5050
integer :: nComponents = 0
5151
real(pREAL), allocatable, dimension(:) :: dot_u
5252
logical, allocatable, dimension(:) :: active
53+
logical :: use_label
5354
end type tMechBC
5455

5556
#if (PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR<23)
@@ -78,11 +79,11 @@ subroutine FEM_utilities_init(num_mesh)
7879
type(tDict), pointer :: &
7980
num_mech
8081
character(len=:), allocatable :: &
81-
petsc_options
82+
PETSc_options
8283
integer :: &
83-
p_s, & !< order of shape functions
84-
p_i !< integration order (quadrature rule)
85-
PetscErrorCode :: err_PETSc
84+
p_s, & ! order of shape functions
85+
p_i ! integration order (quadrature rule)
86+
PetscErrorCode :: err_PETSc
8687

8788

8889
print'(/,1x,a)', '<<<+- FEM_utilities init -+>>>'
@@ -151,61 +152,62 @@ end subroutine utilities_constitutiveResponse
151152
!--------------------------------------------------------------------------------------------------
152153
!> @brief Project BC values to local vector
153154
!--------------------------------------------------------------------------------------------------
154-
subroutine utilities_projectBCValues(dm_local,solution_local,section,mechBC,Delta_t,dimPlex)
155+
subroutine utilities_projectBCValues(dm_local,solution_local_vec,section,mechBC,Delta_t,dimPlex)
155156
DM :: dm_local
156-
Vec :: solution_local
157+
Vec :: solution_local_vec
157158
PetscSection :: section
158159
type(tMechBC), dimension(:), intent(in) :: &
159160
mechBC
160161
real(pREAL), intent(in) :: Delta_t
161162
PetscInt, intent(in) :: dimPlex
162163

163-
PetscInt :: component, boundary, bcSize, &
164-
nBcPoints, point, dof, numDof, numComp, offset
165-
IS :: bcPointsIS
164+
PetscInt :: component, boundary, bc_n_points, &
165+
points_IS_size, point, dof, n_field_dof, n_field_cmp, offset
166+
IS :: bc_points_IS
166167
PetscErrorCode :: err_PETSc
167-
PetscInt, pointer :: bcPoints(:)
168-
real(pREAL), pointer :: localArray(:)
169-
170-
character(len=11) :: setLabel
171-
172-
173-
do boundary = 1_pPETSCINT, mesh_Nboundaries; do component = 1_pPETSCINT, dimPlex
174-
if (mechBC(boundary)%active(component)) then
175-
setLabel = mesh_BCTypeLabel(mesh_boundariesIdx(boundary))
176-
call DMGetStratumSize(dm_local,setLabel,mesh_boundariesIS(boundary),bcSize,err_PETSc)
177-
if (bcSize > 0_pPETSCINT) then
178-
call DMGetStratumIS(dm_local,setLabel,mesh_boundariesIS(boundary),bcPointsIS,err_PETSc)
179-
CHKERRQ(err_PETSc)
180-
call PetscSectionGetFieldComponents(section,0_pPETSCINT,numComp,err_PETSc)
181-
CHKERRQ(err_PETSc)
182-
call ISGetSize(bcPointsIS,nBcPoints,err_PETSc)
183-
CHKERRQ(err_PETSc)
184-
if (nBcPoints > 0_pPETSCINT) call ISGetIndices(bcPointsIS,bcPoints,err_PETSc)
185-
call VecGetArray(solution_local,localArray,err_PETSc)
186-
CHKERRQ(err_PETSc)
187-
do point = 1_pPETSCINT, nBcPoints
188-
call PetscSectionGetFieldDof(section,bcPoints(point),0_pPETSCINT,numDof,err_PETSc)
189-
CHKERRQ(err_PETSc)
190-
call PetscSectionGetFieldOffset(section,bcPoints(point),0_pPETSCINT,offset,err_PETSc)
191-
CHKERRQ(err_PETSc)
192-
do dof = offset+component, offset+numDof, numComp
193-
localArray(dof) = localArray(dof) + mechBC(boundary)%dot_u(component)*Delta_t
194-
end do
195-
end do
196-
call VecRestoreArray(solution_local,localArray,err_PETSc)
197-
CHKERRQ(err_PETSc)
198-
call VecAssemblyBegin(solution_local, err_PETSc)
199-
CHKERRQ(err_PETSc)
200-
call VecAssemblyEnd(solution_local, err_PETSc)
201-
CHKERRQ(err_PETSc)
202-
if (nBcPoints > 0_pPETSCINT) call ISRestoreIndices(bcPointsIS,bcPoints,err_PETSc)
203-
CHKERRQ(err_PETSc)
204-
call ISDestroy(bcPointsIS,err_PETSc)
205-
CHKERRQ(err_PETSc)
206-
end if
207-
end if
208-
end do; end do
168+
PetscInt, pointer :: bc_points(:)
169+
real(pREAL), pointer :: solution_local(:)
170+
character(len=pSTRLEN) :: bc_label
171+
172+
173+
do boundary = 1, mesh_nBoundaries;
174+
bc_label = PETSC_GENERIC_LABELS(mesh_boundariesIdx(boundary))
175+
do component = 1_pPETSCINT, dimPlex
176+
if (mechBC(boundary)%active(component)) then
177+
call DMGetStratumSize(dm_local,bc_label,mesh_boundariesIS(boundary),bc_n_points,err_PETSc)
178+
if (bc_n_points > 0_pPETSCINT) then
179+
call DMGetStratumIS(dm_local,bc_label,mesh_boundariesIS(boundary),bc_points_IS,err_PETSc)
180+
CHKERRQ(err_PETSc)
181+
call PetscSectionGetFieldComponents(section,0_pPETSCINT,n_field_cmp,err_PETSc)
182+
CHKERRQ(err_PETSc)
183+
call ISGetSize(bc_points_IS,points_IS_size,err_PETSc)
184+
CHKERRQ(err_PETSc)
185+
if (points_IS_size > 0_pPETSCINT) call ISGetIndices(bc_points_IS,bc_points,err_PETSc)
186+
call VecGetArray(solution_local_vec,solution_local,err_PETSc)
187+
CHKERRQ(err_PETSc)
188+
do point = 1_pPETSCINT, points_IS_size
189+
call PetscSectionGetFieldDof(section,bc_points(point),0_pPETSCINT,n_field_dof,err_PETSc)
190+
CHKERRQ(err_PETSc)
191+
call PetscSectionGetFieldOffset(section,bc_points(point),0_pPETSCINT,offset,err_PETSc)
192+
CHKERRQ(err_PETSc)
193+
do dof = offset+component, offset+n_field_dof, n_field_cmp
194+
solution_local(dof) = solution_local(dof) + mechBC(boundary)%dot_u(component)*Delta_t
195+
end do
196+
end do
197+
call VecRestoreArray(solution_local_vec,solution_local,err_PETSc)
198+
CHKERRQ(err_PETSc)
199+
call VecAssemblyBegin(solution_local_vec, err_PETSc)
200+
CHKERRQ(err_PETSc)
201+
call VecAssemblyEnd(solution_local_vec, err_PETSc)
202+
CHKERRQ(err_PETSc)
203+
if (points_IS_size > 0_pPETSCINT) call ISRestoreIndices(bc_points_IS,bc_points,err_PETSc)
204+
CHKERRQ(err_PETSc)
205+
call ISDestroy(bc_points_IS,err_PETSc)
206+
CHKERRQ(err_PETSc)
207+
end if
208+
end if
209+
end do
210+
end do
209211

210212
end subroutine utilities_projectBCValues
211213

0 commit comments

Comments
 (0)