Skip to content

Commit

Permalink
Merge branch 'devel' of https://github.com/elmercsc/elmerfem into devel
Browse files Browse the repository at this point in the history
  • Loading branch information
Juha Ruokolainen committed Aug 21, 2024
2 parents a45a835 + cd1b270 commit 09fce14
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 24 deletions.
7 changes: 4 additions & 3 deletions elmergrid/src/egmesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -9906,7 +9906,7 @@ int CreateDualGraph(struct FemType *data,int unconnected,int info)
int *invrow,*invcol;
struct CRSType *dualgraph;

printf("Creating a dual graph of the finite element mesh\n");
if(info) printf("Creating a dual graph of the finite element mesh\n");

dualgraph = &data->dualgraph;
if(dualgraph->created) {
Expand All @@ -9924,7 +9924,7 @@ int CreateDualGraph(struct FemType *data,int unconnected,int info)
/* If a dual graph only for the unconnected nodes is requested do that.
Basically the connected nodes are omitted in the graph. */
if( unconnected ) {
printf("Removing connected nodes from the dual graph\n");
if(info) printf("Removing connected nodes from the dual graph\n");
if( data->nodeconnectexist ) {
if(info) printf("Creating connected elements list from the connected nodes\n");
SetConnectedElements(data,info);
Expand Down Expand Up @@ -10034,6 +10034,7 @@ int CreateDualGraph(struct FemType *data,int unconnected,int info)
}
else {
dualsize = freeelements;
if(info) printf("Allocating for the dual graph for %d with %d connections\n",dualsize,totcon);
dualrow = Ivector(0,dualsize);
for(i=1;i<=dualsize;i++)
dualrow[i] = 0;
Expand All @@ -10053,7 +10054,7 @@ int CreateDualGraph(struct FemType *data,int unconnected,int info)
goto omstart;
}

if( orphanelements ) {
if( orphanelements && info ) {
printf("There are %d elements in the dual mesh that are not connected!\n",orphanelements);
if(unconnected) printf("The orphan elements are likely caused by the hybrid partitioning\n");
}
Expand Down
75 changes: 58 additions & 17 deletions fem/src/modules/TopoOpt.F90
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ SUBROUTINE TopoOpt( Model,Solver,dt,Transient )
TYPE(Matrix_t), POINTER :: Fmat
REAL(KIND=dp), ALLOCATABLE :: local_sol_array(:,:), local_sol(:)
REAL(KIND=dp), POINTER :: ce(:), dc(:), dv(:), dv0(:), bw(:), xTopo(:), xPhys(:), xMult(:)
INTEGER :: TimesVisited = 0, dim, dofs, Niter, i, j, n, m, Nelems, Nnodes, nsize
INTEGER :: TimesVisited = 0, dim, dofs, Niter, i, j, n, m, Nelems, Nnodes, nsize, cMode
REAL(KIND=dp) :: volFrac, penal, emin, efrac, gt, obj, val, wmin, Diff(3)
TYPE(Solver_t), POINTER :: PhysSolver
TYPE(Mesh_t), POINTER :: Mesh
Expand All @@ -99,7 +99,7 @@ SUBROUTINE TopoOpt( Model,Solver,dt,Transient )
SAVE :: TimesVisited, Fmat, xTopo, xPhys, xMult, Niter, PhysSolver, dim, Mesh, &
local_sol_array, local_sol, ce, dc, dv, dv0, bw, wmin, FilterMethod, FilterType, &
gt, Nnodes, Nelems, uVar, aVar, dofs, Nodes, PdeFilter, SimpleFilter, Diff, nsize, &
ElemPerm, Csymmetry, SolveAdj
ElemPerm, Csymmetry, SolveAdj, obj


CALL Info(Caller,'-------------------------------------------')
Expand Down Expand Up @@ -260,8 +260,8 @@ SUBROUTINE TopoOpt( Model,Solver,dt,Transient )
CASE DEFAULT
CALL Fatal(Caller,'Uknown filtering method: '//TRIM(FilterMethod))
END SELECT
END IF

END IF ! TimesVisited==0
IF(InfoActive(20)) THEN
CALL VectorValuesRange(PhysSolver % Matrix % Values,SIZE(PhysSolver % Matrix % Values),'Kmat')
CALL VectorValuesRange(uVar % Values,SIZE(uVar % Values),TRIM(uVar % Name))
Expand All @@ -280,9 +280,28 @@ SUBROUTINE TopoOpt( Model,Solver,dt,Transient )
END IF

! Gradients/Sensitivities with respect to the SIMP objective function and
! the volume constraint.
obj = ObjectiveGradients(xPhys,ce,dc,dv0)
! the volume constraint.
cMode = GetCycleMode()
! 0 - normal
! 1 - init cycle
! 2 - mid cycle
! 3 - end cycle

IF( cMode == 0 .OR. cMode == 1 ) THEN
obj = 0.0_dp
dc = 0.0_dp
END IF

CALL ObjectiveGradients(xPhys,ce,dc,dv0,obj)

IF( cMode == 1 .OR. cMode == 2 ) THEN
CALL Info(Caller,'Mid of cycle, finishing early!')
GOTO 1
END IF

obj = ParallelReduction( obj )


IF(InfoActive(20)) THEN
CALL VectorValuesRange(xPhys,SIZE(xPhys),'xPhys')
CALL VectorValuesRange(ce,SIZE(ce),'ce')
Expand Down Expand Up @@ -345,28 +364,52 @@ SUBROUTINE TopoOpt( Model,Solver,dt,Transient )
Solver % Variable % Values = obj
END IF

! Multiplier for local stiffness matrix of the external solver.
xMult = emin + efrac * xPhys**penal

IF(ASSOCIATED(bw)) THEN
CALL DefineTopologyBW(dv0,xPhys,bw)
END IF

IF(InfoActive(20)) THEN
CALL VectorValuesRange(xPhys,SIZE(xPhys),'xPhys2')
END IF

! Multiplier for local stiffness matrix of the external solver.
1 xMult = emin + efrac * xPhys**penal

TimesVisited = TimesVisited + 1

CONTAINS

FUNCTION GetCycleMode() RESULT ( Mode )
INTEGER :: Mode
INTEGER :: nCycle, nT

Mode = 0
nCycle = ListGetInteger( Model % Simulation,'Periodic Timesteps',Found )
nT = TimesVisited

! 1st iteration make a something to create asymmetry
IF(nCycle == 0 .OR. nT == 0 ) RETURN

SELECT CASE( MODULO(nT,nCycle) )
CASE( 0 )
Mode = 3
CASE( 1 )
Mode = 1
CASE DEFAULT
Mode = 2
END SELECT

END FUNCTION GetCycleMode



!---------------------------------------------------------------------
!> xphys: in [0,1], densities used for scaling the material properties
!> ce: elementsize energies before scaling by density
!> dc: gradient with respect to objective function.
!> dv: gradient with respect to volume constraint.
!---------------------------------------------------------------------
FUNCTION ObjectiveGradients(x,ce,dc,dv) RESULT ( obj )
SUBROUTINE ObjectiveGradients(x,ce,dc,dv,obj)
REAL(KIND=dp), POINTER :: x(:)
REAL(KIND=dp), POINTER :: ce(:),dc(:),dv(:)
REAL(KIND=dp) :: obj
Expand Down Expand Up @@ -399,17 +442,15 @@ FUNCTION ObjectiveGradients(x,ce,dc,dv) RESULT ( obj )
ce(i) = SUM( local_sol(1:m) * MATMUL( Stiff, local_sol(1:m) ) )
END DO

! Objective function
obj = SUM( (emin + efrac*( x**penal ) ) * ce )

!PRINT *,'Objective:',obj,emin,efrac,penal,SUM(x),SUM(ce)

! Derivative of elemental energy
dc = -penal*x**(penal-1) * efrac * ce
dc = dc - penal*x**(penal-1) * efrac * ce

obj = ParallelReduction( obj )
! Objective function
obj = obj + SUM( (emin + efrac*( x**penal ) ) * ce )

END FUNCTION ObjectiveGradients
END SUBROUTINE ObjectiveGradients


!--------------------------------------------------------------------------
Expand Down
10 changes: 6 additions & 4 deletions fem/tests/TopoOptElast2DCompliance/case.sif
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ Simulation
Coordinate System = Cartesian
Simulation Type = Steady state
Steady State Max Iterations = 5 !1000
Output Intervals = 1
Output Intervals = 0

! Post File = a.vtu
! vtu: Save Bulk Only = Logical True
! vtu: ascii output = logical True
Post File = a.vtu
vtu: Save Bulk Only = Logical True
vtu: ascii output = logical True

Mesh Levels = 1
End
Expand Down Expand Up @@ -107,6 +107,8 @@ Solver 2
Bisection Search Tolerance = Real 1.0e-3

Solver Timing = True

Create BW Topology = Logical True
End


Expand Down

0 comments on commit 09fce14

Please sign in to comment.