Sie sind auf Seite 1von 117

simufact.forming 13.

Scientific
Copyright 2015 simufact engineering gmbh
All rights reserved.

No part of this document may be reproduced, translated or transmitted in any form or by any means, electronically or mechanically, without prior
written permission of Simufact Engineering GmbH.

Proprietary Notice

Simufact Engineering GmbH reserves the right to make changes in specications and other information contained in this document without prior
notice.

ALTHOUGH DUE CARE HAS BEEN TAKEN TO PRESENT ACCURATE INFORMATION, SIMUFACT CORPORATION DISCLAIMS ALL
WARRANTIES WITH RESPECT TO THE CONTENTS OF THIS DOCUMENT (INCLUDING, WITHOUT LIMITATION, WARRANTIES
OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) EITHER EXPRESSED OR IMPLIED. SIMUFACT CORPO-
RATION SHALL NOT BE LIABLE FOR DAMAGES RESULTING FROM ANY ERROR CONTAINED HEREIN, INCLUDING, BUT NOT
LIMITED TO, FOR ANY SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION WITH
THE USE OF THIS DOCUMENT.

Trademarks

Simufact, Simufact.forming and other Simufact products are registered trademarks of Simufact Engineering GmbH.

MATILDA is a registered trademark of GMT Gesellschaft fr metallurgische Technologie- und Softwareentwicklung mbH, Berlin.

Windows is a registered trademark of Microsoft Corporation in the United States and other countries.

MSC, MSC.Marc and MSC.Dytran are registered trademarks of MSC.Software Corporation.

3Dconnexion and SpaceDevice are registered trademarks of 3Dconnexion Inc.

ABP THERMPROF is a registered trademark of ABP Induction Systems GmbH.

ProCAST is a registered trademark of ESI Group.

All other registered and unregistered trademarks in this document are the sole property of their respective owners.

Contact:

www.simufact.com/contact
13.2 simufact.forming

Table of Contents
1. User subroutines ........................................................................................................ 1
1.1. FORTRAN Guide (for FE-Solver) ...................................................................... 2
1.1.1. Compiler for version 13.x ....................................................................... 2
1.1.2. Common Block .................................................................................... 3
1.1.3. File Operations ..................................................................................... 4
1.1.4. Conditional statement ............................................................................ 5
1.1.5. Loops .................................................................................................. 5
1.1.6. Domain Decomposition Method .............................................................. 6
1.1.7. Debugging ........................................................................................... 9
1.2. Variable units ................................................................................................ 11
1.3. User subroutine and utility routines ................................................................... 11
1.3.1. Subroutine details ................................................................................ 11
1.3.2. Subroutine integration .......................................................................... 15
1.3.3. User variables ..................................................................................... 16
1.3.4. Utility routines .................................................................................... 18
1.3.5. Common user subroutines ..................................................................... 20
1.3.6. Post codes .......................................................................................... 22
1.4. User Subroutine: Examples .............................................................................. 23
1.4.1. State Variables .................................................................................... 23
1.4.2. Motion .............................................................................................. 31
1.4.3. Damage ............................................................................................. 35
1.4.4. Friction .............................................................................................. 39
1.4.5. Process report ..................................................................................... 45
1.4.6. Table evaluation .................................................................................. 48
1.4.7. Runtime local variables ........................................................................ 51
1.5. FORTRAN- C/C++ user subroutine interface ...................................................... 56
1.5.1. The interface ...................................................................................... 56
1.5.2. Example ............................................................................................ 59
2. User defined kinematic .............................................................................................. 65
2.1. User Kinematics ............................................................................................ 66
2.1.1. Graphical interface .............................................................................. 67
2.1.2. Tags and attributes .............................................................................. 72
2.1.3. The .kin Data ...................................................................................... 75
2.1.4. Example of the .kin data ....................................................................... 77
2.1.5. Solver and subroutine ........................................................................... 81
2.1.6. Example ............................................................................................ 93
3. User defined material .............................................................................................. 104
3.1. User defined material law .............................................................................. 105
3.1.1. Material information ........................................................................... 105
3.1.2. User subroutine ................................................................................. 110
3.1.3. Example ........................................................................................... 111

iii
13.2 simufact.forming

List of Figures
1.1. Activation of parallel computing (DDM) in Forming control ........................................... 7
1.2. Data flow in a DDM job .......................................................................................... 8
1.3. Linking user subroutine in Forming control ................................................................ 15
1.4. Subroutine in Additional files directory ...................................................................... 15
1.5. Linking pre-compiled solver in Forming control .......................................................... 16
1.6. Activating selected subroutine in Forming control ........................................................ 16
1.7. Variable definition in Forming control ....................................................................... 17
1.8. Flowchart highlighting subroutine call ....................................................................... 21
1.9. Activating nodal and elemental post variables ............................................................. 23
1.10. Nodal post variable name selection ......................................................................... 24
1.11. User element post variable name selection ................................................................ 24
1.12. Nodal and elemental state variables selection ............................................................ 25
1.13. Custom element and node variables in result tree ....................................................... 25
1.14. User defined real variables in Forming control .......................................................... 31
1.15. Supported damage model in Simufact.forming ........................................................... 35
1.16. "show process report" icon in Simufact.forming ......................................................... 46
1.17. Process report with effective plastic strain and effective stress ...................................... 46
1.18. Adding "effective stress" post variable to process report" ............................................. 47
1.19. Selecting "Solver mark" as trigger ........................................................................... 47
1.20. Table Id as input through integer user variables ......................................................... 49
1.21. Scaling factor as input through real user variables ...................................................... 50
1.22. Elemental post variables selection ........................................................................... 50
2.1. User kinematic: implementation ............................................................................... 67
2.2. Standard rolling model in Simufact.demos .................................................................. 68
2.3. Adding new kinematic in inventory window. .............................................................. 68
2.4. Dialog box for kinematic selection ............................................................................ 69
2.5. Default user-kinematics provided in the Simufact.forming ............................................. 69
2.6. "name" attribute in the kinematic GUI ....................................................................... 70
2.7. Tree-structure highlighting assignment of various informations in "user defined.xml" .......... 71
2.8. Screen-shot of the XML file in a text editor with syntax highlighting ............................... 71
2.9. Dialog box after modifying "user defined" xml file ...................................................... 72
2.10. Screen-shot of modified XML file with comments ..................................................... 74
2.11. Dialog box with input values ................................................................................. 77
2.12. Process-tree after adding and renaming the kinematic press .......................................... 78
2.13. Concept of sfukin subroutine to define new load case ................................................. 82
2.14. Modified model with symmetry planes ..................................................................... 94
2.15. Modified process tree and object windows of the model .............................................. 94
2.16. Modified kinematic dialog window ......................................................................... 95
3.1. Flow curve information created through table input .................................................... 106
3.2. Inventory window showing process of duplicating the material file ................................ 107
3.3. Removing the existing flow curve information .......................................................... 107
3.4. Adding a user defined material plasticity model ......................................................... 108
3.5. Dialog box to edit flow curve information ................................................................ 108
3.6. Dialog box to enter equation parameters ................................................................... 109
3.7. Save the created material file for future use .............................................................. 110
3.8. Parameters used in the example .............................................................................. 112

iv
13.2 simufact.forming

List of Tables
1.1. Selected list of available Element post code ................................................................ 22
1.2. Selected list of available Node post code ................................................................... 22

v
Scientific
13.2

1 User subroutines
13.2 User subroutines FORTRAN Guide (for FE-Solver)

Educational Objectives

Uses of user subroutine in Simufact.forming for better process control

Prerequisites

FORTRAN programing knowledge, general programing knowledge

1.1. FORTRAN Guide (for FE-Solver)


Simufact.forming support user subroutines written in FORTRAN programming language. In this manual, basic FOR-
TRAN commands are reviewed. Also, various user subroutine examples are discussed in detail in the subsequent
sections. For every example, the user subroutine source code and a tested simufact-project file can be accessed via
the scientific branch in the simufact.demos browser.

1.1.1. Compiler for version 13.x


To use FORTRAN user subroutine with Simufact.forming v13.2, additional programs are required:

On Windows:

Intel(R) FORTRAN Compiler Version 12.0.4

Requirement:

Microsoft(c) Visual Studio 2010

Windows Software Development Kit (SDK) for Windows Server

For parallel jobs, requirements are

Intel(R) MPI (iMPI) Version 3.1

MS MPI Version 1.0.640 from Microsoft Corporation

On Linux:

2
13.2 User subroutines Common Block

Intel(R) FORTRAN Compiler Version 12.0.4

The above information can also be found in first few lines in sfinclude_win64i8.bat file located in Simufact.forming
installation directory at:

C:\Program Files\simufact\forming\13.2\sfMarc\sf_tools

1.1.2. Common Block


FORTRAN common block provides global storage space that can be used to share large amount of information be-
tween different functions. This reduces the need to pass information through program arguments. Changing value of a
common block variable in one subroutine changes the global value of the variable. Predefined solver specific common
blocks can be used in subroutine by #include command as:

#include "creeps.cmn"

There are many common blocks that are used by the solver to store runtime information . The "creeps.cmn" common
block, for example, consist of all the time variables used in the simulation. All the available common blocks can be
found in the Simufact.forming installation directory at: C:\Program Files\simufact\forming\13.2\sfMarc\common.
A typical common block is defined as:

C***********************************************************************
C
C File: creeps.cmn
C
C MSC.Marc include file
C
real*8 cptim,timinc,timinc_p,timinc_s,timincm,
1 timinc_a,timinc_b,creept
integer icptim,icfte,icfst,
2 icfeq,icftm,icetem,mcreep,jcreep,icpa,icftmp,icfstr,
3 icfqcp,icfcpm,icrppr,icrcha,icpb,iicpmt,iicpa
real*8 time_beg_lcase,time_beg_inc,fractol,time_beg_pst
c
integer num_creepsr,num_creepsi,num_creeps2r
parameter(num_creepsr=40)
parameter(num_creepsi=18)
parameter(num_creeps2r=4)
common/marc_creeps/cptim,timinc,timinc_p,timinc_s,timincm,
1 timinc_a,timinc_b,creept(33),icptim,icfte,icfst,
2 icfeq,icftm,icetem,mcreep,jcreep,icpa,icftmp,icfstr,
3 icfqcp,icfcpm,icrppr,icrcha,icpb,iicpmt,iicpa
common/marc_creeps2/
x time_beg_lcase,time_beg_inc,fractol,time_beg_pst
c
c time_beg_lcase time at the beginning of the current load case
c time_beg_inc time at the beginning of the current increment
c fractol fraction of loadcase or increment time when we
c consider it to be finished
c time_beg_pst time corresponding to first increment to be
c read in from thermal post file for auto step
C***********************************************************************

1.1.2.1. Local common block


User should create a local common block to store temporary run time information such as counter, variables etc. This
will help to preserve the information when the function is revisited.

common /sfuser_1/ all integer variables

3
13.2 User subroutines File Operations

common /sfuser_2/ all real variables


common /sfuser_3/ all character variables
common /sfuser_4/ all pointer names

1.1.3. File Operations


1.1.3.1. File units
The FE-solver (sfMarc) uses various local auxiliary files for data storage. File unit numbers are used by the solver to
create and access these auxiliary files during runtime. From 0 to 130 file units are used by the solver. For example,
unit 0 (iprtl) is used for the job .log file where as unit 6 (kou) is used for .out file. For detailed descriptions of these
units, please refer to Marc Volume A: Theory and User Information : File Units. Users are advised to use file unit
greater than 500 to avoid conflict with those predefined by solver.

1.1.3.2. File open


To open a file, first the file name must be defined. A file created during the simulation has the job name associated
with it. The various file names are stored in the common block "jname". Variable kou (=6) and iprtl (=0) are defined
in the prepro.cmn and machin.cmn common blocks respectively. They define the file unit numbers for out and log
files respectively. Consider the following code block:

#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif

#include "jname.cmn" ! variable ilen, jidnam


#include "machin.cmn" ! variable iprtl
#include "prepro.cmn" ! variable kou

character*80 filen,cline
parameter (iunit=57)

filen=jidnam(:ilen(1))//'.dbg'

c To write information in Format 1001 in the log and output file


write(iprtl,1001)filen(:ilen(1))
write(kou,1001)filen(:ilen(1))
.....
.....
1001 format(/13x,
*'##########################################################',
* /13x'Debug information for myself will be written in file',
* /13x,a,' in Format for Version 13.2'
* /13x
*'##########################################################')

In the above code, format command is used to format the output. Argument 13x = 13 blank character space, a =
character, text is written inside quote ' ' and / is used for new line break. Both FORTRAN 77 and 90 standard can be
used in the subroutine. FORTRAN 77 requires command to begin with 7th character and finish within 72nd character
from left. If the command is long then continuation character (* in above example) has to be put in next line at 6th
character from left and then the command can continue. To read a file, the following code-snippets can be used in
the subroutine.

c To read a line in the file


open(iunit,file=filen,access='sequential',

4
13.2 User subroutines Conditional statement

* status='unknown',form='formatted')

c Read a line, jump to 110 when end of the file


100 read(iunit,'(a)',end=110) cline
goto 100
110 continue

1.1.4. Conditional statement


Conditional statement allows the program to make decision. There are two forms: the single if statement and the block-
if statement. Syntax of a single if statement is

if (logical expression) then


code-block
endif

Syntax of a block if statement:

if (logical expression) then


code-block
else if (logical expression) then
code-block
.....
.....
else
code-block
endif

Example of block-if statement:

if (i .lt. 5) then
write(*,*) "less than five"
else if(i .gt. 6) then
write(*,*) "more than five"
else if(i .eq. 5) then
write(*,*) "equal to five"
else
write(*,*) "invalid"
endif

1.1.5. Loops
Loops are used for repeated execution of a block of code. In FORTRAN this can be achieved by a "do-loop", "while-
loop" or "if-loop".

1.1.5.1. do-loop
There are two methods to write a do-loop:

do label variable = start, end, increment


code-block
label continue

do variable = start, end, increment


code-block
enddo

Examples: The following code print all even numbers between 1 to 20 in decreasing order.

5
13.2 User subroutines Domain Decomposition Method

do 99 i = 20, 1, -2
write(*,*) 'i =', i
99 continue

do i = 20, 1, -2
write(*,*) 'i =', i
enddo

1.1.5.2. do-while-loop
The while loop is used together with a do statement. The do-while loop executes the range of do construct until the
condition inside WHILE statement remains true. The do-while loop can also be written in two ways.

while (logical expr) do


code-block
enddo

do while (logical expr)


code-block
enddo

Example: The code print all even numbers between 1 to 20 in decreasing order.

i=20
do while (i.gt.1)
write(*,*) 'i =', i
i = i-2
enddo

1.1.5.3. if-loop
Loop can also be written through an if-goto statement.

label if (logical expr) then


code-block
goto label
endif

Example: The code print all even numbers between 1 to 20 in decreasing order.

i=20
99 if (i.gt.1) then
write(*,*) 'i =', i
i = i-2
goto 99
endif

1.1.6. Domain Decomposition Method


Simufact.forming uses Domain Decomposition method (DDM) as a parallelisation to reduce simulation time. DDM is
a parallel and scalable technique in which the system first divides the problem, that can be solved separately and at the
end merge the calculated results. DDM simulation can be used to shorten the simulation time by running the simulation
over multiple processors. Simufact.forming supports the parallel execution of simulation through DDM, only limited
by the availability of processing units in the system. Intel MPI service should be running on the system for using
DDM for Simufact.forming simulation. DDM can be activated in forming control under the parallelization option.
Each domain can then further parallelize through shared memory parallelization option. Number of cores defined in
the option will be allocated for each domain.

6
13.2 User subroutines Domain Decomposition Method

Figure 1.1. Activation of parallel computing (DDM) in Forming control


Silent features of using DDM with the user subroutine are:

Each domain is a separate job and runs independently to other domains. Memory is not shared among the domains.

User subroutines can be used in the same way as without DDM with special care for user defined local file handling.

The first domain job is labeled as a parent (master) job. All domain will create runtime files with a domain number
as prefix in the job name.

In a DDM simulation, important domain related information can be accessed in the user subroutine through following
variables

nprocd (from cdominfio.cmn) = number of processor used by the job


> 0 it is a DDM job
iparent (from cdominfo.cmn) = 0, then it is a parent job, important if an
activity has to be done by one domain only
iprcnm (from cdominfo.cmn) = gives the domain number in case of a DDM job
iddmarc (from gary.cmn) = flag for DDM with ARC file control
= 0, no such control
= 1, first run
= 2, restart run
jidnam (from jname.cmn) = jobname of each domain
jidnam _base (from jname.cmn)= base jobname

Following is the code snippet for creating name of the *.ARC file by the solver. Based on the job type(ddm or non
ddm job), file name can be different.

filen=jidnam(:ilen(1))//'_'//cbody(:ilenc)//
* '_'//cinc(:ilen0)//'.ARC'
if(nprocd.gt.0)then ! in case of DDM job
ilen1=last_char(jidnam_base)
filen=jidnam_base(:ilen1)//'_'//cbody(:ilenc)//
* '_'//cinc(:ilen0)//'.ARC'
endif

To exchange runtime information among the various domains, a function domflag() can be called within the sub-
routine. When a domflag() function is called in a ddm job, calculation in all the domain will be paused at the in-
stance. Values passed in domflag() arguments from all the domains will be analyzed and user defined mathematical
operations(like maximum, minimum, average, summation etc.) will be done. The result will then be returned to all the
domains and then the calculation will continue. Interface of a domflag() function is

domflag(iflag,dflag,ichck1,ichck2,num1,num2)
c***********************************************************************
c collects iflag and dflag from domains, performs mathematical
c operations within message passing, broadcast results to domains
c
c iflag = is an integer array to be shared among domains

7
13.2 User subroutines Domain Decomposition Method

c dflag = is a real array to be shared among domains


c ichck1 = is an integer array of same size as array iflag. Value in
this array determines which mathematical operation to
perform on integer array (iflag)
c ichck2 = is an integer array of same size as array dflag. Value in
this array determines which mathematical operation to
perform on real array (dflag)
c
c mathematical operation flags for ichck1 and ichck2 are
c ichck = 0: minimum, return the minimum value
c ichck = 1: maximum, return the maximum value
c ichck = 2: average, return the average
c ichck = 3: sum , add and return the sum
c ichck = 4: minimum above zero
c ichck = 5: sets exit message
c ichck = 6: maximum absolute value (sign is preserved)

c num1 and num2 is the size of integer and real arrays respectivly.
c
c Results of mathematical operation, can be accessed within a domain
c from the content of array iflag and dflag.
c
c***********************************************************************
if (nprocd.gt.0)call domflag(matid,dummy,1,0,1,0) !only for ddm job
if(nprocd.gt.0)then
dbuff1(1)=test_min
dbuff1(2)=test_max
itest1(1)=0 !get minimum value from all domain
itest1(2)=1 !get maximum value from all domain
call domflag(idum,dbuff1,0,itest1,0,2)
test_min=dbuff1(1)
test_max=dbuff1(2)
endif

For a DDM job, process flow path during simulation is shown in the sketch below.

Figure 1.2. Data flow in a DDM job

8
13.2 User subroutines Debugging

1.1.7. Debugging
It is possible to locate the cause of run-time and logical errors in user subroutine through a debugger. With the help of a
debugger, variable values and information flow through subroutine can be monitored during the simulation. This helps
to trace the source of logical error in the subroutine. A detailed process to set up the debugging environment with visual
studio debugger (v10) is described in this section. Please note that only non DDM job can be debugged in this method.

1. Setup debug environment: It is recommended to create two batch files and put them in a user path directory. This
will enable to call batch files from any directory through command line. The first is a command to invoke Intel
FORTRAN compiler and second is to start debugger.

a. To setup Intel FORTRAN compiler environment at a command line:

set INTEL_HOME="C:\Program Files (x86)\Intel\ComposerXE-2011"


call %INTEL_HOME%\bin\compilervars intel64

The above script is named as intel12.bat in this case, and saved in the user path directory. From a window
command line console (cmd.exe), executing intel12 should make the Intel FORTRAN compiler accessible at
the command prompt. If not then check for the correct installation directory of compiler and modify the above
code, or the location of intel12.bat file is not included in the local user path profile.

b. Set Simufact.forming installation path available for debugger:

@echo off
setlocal
call intel12
set FORMINGDIR=C:\Program Files\simufact\forming\13.2
set SDIR=D:\log
set BINDIR=%FORMINGDIR%\sfMarc\bin\win64i8
set AFMATDAT=%FORMINGDIR%sfMarc\AF_flowmat\
set EXITMSG=%SDIR%\MESSAGES
set LIBDIR=%FORMINGDIR%\sfMarc\lib\win64i8
set CUDADIR=%FORMINGDIR%\sfMarc\lib\win64i8\cuda
set MESHERDIR=%FORMINGDIR%\sfTools\sfMeshing\bin
set PATH=%MESHERDIR%;%BINDIR%;%LIBDIR%;%SDIR%;%PATH%;%CUDADIR%
call devenv
endlocal

The above code sets up the compile environment and adds various Simufact.forming libraries to the existing
system path. At end calls the visual studio debugger with command devenv. Running the above script should
open the visual studio debugger. Modify the various path depending upon local installation and settings. Give
the script a suitable name and store in a folder included in local user path profile.

The above setting has to be done once for a system.

2. Enable debug flag in Simufact.forming script: By default debug flag is switched off in Simufact.forming
script and should be manually enabled. Goto Simufact.forming installation directory at ..\simufact\form-
ing\13.2\sfMarc\sf_tools\. Open the file sfinclude_win64i8.bat and search for MARCDEBUG option.
Remove the REM in front of a line set MARCDEBUG=ON. The modified script should look as:

The above modification will create the solver binary with the debug flag for compiled subroutine code. Please note
that the job will run slower when subroutine is compiled with debug flag. Its recommended to switch off the debug
flag for actual simulation.

3. Create debug executable:

9
13.2 User subroutines Debugging

a. Setup the simulation job in Simufact.forming. In the solver option under forming control, attach the user sub-
routine that needs to be debugged.

b. Create the complete sfMarc input files in project's _Run_ directory by submitting the job. Various job files are
created in _Run_ directory. Simulation should then be safely stopped.

c. The _Run_ directory should contain the job input file (*.dat), material file(*.umt), copy of the user subroutine
and two batch files named runsf.bat and cleansf.bat. Open the runsf.bat in a text editor and copy and modify
the script partially as

call "C:/Program Files/simufact/13.2/sfMarc/sf_tools/run_sfMarc.bat" -u


"ufric" -j friction -b no -save yes

The last two argument -b no -save yes are added arguments. -save yes argument prevent deletion of
executable by Simufact.forming script after the job completion.

d. Open a command console (cmd.exe) in the _Run_ directory and execute the above modified code in the com-
mand prompt. This should creating a solver *.exe together with debug files with extension *.pdb. Simulation
can be terminated once these files are created. Double clicking cleansf.bat will clean the _Run_directory with
the temporary job runtime log/output files.

4. Debugging in visual studio debugger:

a. Open the visual studio debugger through the script described in first step.

b. Open the created solver executable (*.exe) in visual studio as Project/Solution as:

c. Open the subroutine as data:

d. Add the job file name (*.dat)as project argument with -j argument in project properties as

10
13.2 User subroutines Variable units

5. The project is ready for debugging in visual studio. Insert break points at different section of user subroutine that
need to be analysed. The debugger will pause when that portion of subroutines is executed.

It may happen that visual studio may complain of some missing *.dll or libraries. Check that the necessary runtime
dependencies/distributables are installed. If the error complains of missing function in existing libraries then it can
happen that the libraries in the system is old. Updating the program with latest version that initially provided the
libraries should get rid of error.

1.2. Variable units


By default Simufact.forming uses SI units for variables in the simulation. The use of incorrect units in the sim-
ulation can result in wrong simulation result. This becomes important when values are manually changes in the
job input (*.dat) or material file (*.umt) file before the simulation, or uses subroutine to perform calculation.
Also, Simufact.forming and SimufactGP use different default variable units. If a subroutine is shared between
Simufact.forming and SimufactGP then special care should be taken for variable units. Default units of the quantities
used in the simulation are tabulated below:

Variable units
Quantity SI Unit mm/tonne/s/K or SI-mm Conversion factor
(Simufact.forming) (SimufactGP) from SI to mm/tonne/s/K
Length m mm x 103
Time s s x1
Mass kg tonne (Mg) x 10-3
Force kg-m/s2 (N) tonne-mm/s2 (N) x1
3 3
Density kg/m tonne/mm x 10-12
Stress kg/m/s2 (N/m2) tonne/mm/s2 (N/mm2) x 10-6
Energy kg-m2/s2 (J) tonne/mm/s2 (kJ) x 103
Temperature K C - 273.15
2 2 2 2
Specific Heat Capacity m /s /K mm /s /C x 106
Heat Convection kg/s3/K tonne/s3/C x 10-3
Thermal Conductivity kg-m/s3/K tonne-mm/s3/C x1
Thermal Expansion m/m/K mm/mm/C x1

1.3. User subroutine and utility routines


User subroutine allow flexibility to customize the simulation process for non-standard problems. Users can either in-
troduce new physics in the simulation or can get the customised process output according to the need. User subroutines
are to be written with FORTRAN 77 or 90 standard , that can be easily linked with the solver to bypass the inbuilt
routine with the proper control setup. Comprehensive list of all the available subroutine files and its structure can be
found in the handbook from Marc manual, "Volume d". Interfaces of these subroutines are compatible when used in
Simufact.forming simulation. Subroutine written in C/C++ is also supported if the functions are embedded inside a
dll. For detail refer to section FORTRAN-C/C++ user subroutine Interface.

Special utility routines are available to retrieve nodal and elemental process variables during the simulation. These
routines are extremely helpful to retrieve process information in user subroutines as these may not be passed by the
solver to the subroutine.

1.3.1. Subroutine details


To use a subroutine successfully, it is important that the Intel FORTRAN Compiler should be installed in the system.
In Windows, Visual studio is additionally required to provide Linker. Linker attach the compiled subroutine's object
file to the standard solver. Consider the original user subroutine ueloop.f from Marc, which is called over all the

11
13.2 User subroutines Subroutine details

elements in a loop. This subroutine can be used to define or modify variables data stored in the common blocks during
various elemental loop

subroutine ueloop(m,n,iflag)
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
c ** Start of generated type statements **
integer iflag, m, n
c ** End of generated type statements **
c
c user routine that gets called in key element loops
c may be used in a variety of ways
c
c m element number
c n internal element number
c iflag 1 - opress loop, formation of load vector
c 2 - oasemb loop, formation of stiffness matrix
c 3 - oasmas loop, formation of mass matrix
c 4 - ogetst loop, stress recovery
c 5 - scimp loop, output phase
c
return
end

The subroutine is divided into different sections. In the top part the call arguments and common block are contained.
Call arguments describe the list of variables that are passed to the subroutine, for example m,n,iflag are variables
passed as arguments in this subroutine.

subroutine ueloop(m,n,iflag)

Common blocks are used to access the required variables as it is not possible to pass all the variables through call
argument. Almost all information is available through the usage of proper common blocks. Common blocks can be
activated by adding an #include command in the user subroutine. The syntax to use in the user subroutine is:
#include "yyy.cmn" where yyy.cmn is the name of the common block as:

#include "creeps.cmn"

List of all the common blocks used internally by the solver can be found at C:\Program Files\simu-
fact\forming\13.2\sfMarc\common installation directory. For more details about common blocks, refer to
Marc manual "Volume d".

Comments in the subroutine help to explain the variables and program functionality for easier understanding and
readability of the program code. Users can add their own code before the return statement. An example of the extended
user subroutine to calculate total elastic strain is given below. Two subroutines are used to get the desired results.
The first subroutine (ueloop) calculates and stores the incremental plastic strain (eplas) and the other (plotv) output
the values in results.

subroutine ueloop(m1,m2,iflag)
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
c ** Start of generated type statements **
#include "hards.cmn" !nstats
#include "creeps.cmn" !timinc
#include "arrays.cmn" !iintel

12
13.2 User subroutines Subroutine details

#include "elemdata.cmn" !ieltype


#include "space.cmn" !ints
#include "concom.cmn" !ipass
c
integer iflag, m1, m2
c ** End of generated type statements **
integer layer, icode,ioflag,ibodyid,nn1,inn,i1,ityp,iiflag
real*8 eplas,deplas
c
c user routine that gets called in key element loops
c may be used in a variety of ways
c
c m1 element number
c m2 internal element number
c iflag 1 - opress loop
c 2 - oasemb loop
c 3 - oasmas loop
c 4 - ogetst loop
c 5 - scimp loop (end of increment)
c
if(ipass.ne.1)goto 999 !Skip all non-mechanical loop
if(iflag.eq.5.and.nstats.gt.1)then
c utility routine to extract contact body ID
c
c ielem element number
c ibodyid body ID
c iiflag =0, user element number
c =1, element number is internal
iiflag=0
call get_bodyid(m1,ibodyid,iiflag)
if(ibodyid.ne.1)goto 999
c
c get number of integrationpoints for element (nn1)
ityp=ieltype(m2)
i1=ityp-1
nn1=ints(i1+iintel)
c
do inn=1,nn1
layer=1
icode=28 !strain rate
call get_elmvar(icode,m1,m2,inn,layer,deplas)
c calculate incremental plastic strain
deplas=deplas*timinc
c get 2nd state variable
icode=29 !2nd state variable
call get_elmvar(icode,m1,m2,inn,layer,eplas)
c cummulate value
eplas=eplas+deplas
c store 2nd state variable
ioflag=1
icode=29
call elmvar1(icode,m1,inn,layer,eplas,ioflag)
enddo
endif
999 return
end

subroutine plotv(v,s,sp,etot,eplas,ecreep,t,m,nn,kcus,ndi,

13
13.2 User subroutines Subroutine details

* nshear,jpltcd)
c* * * * * *
c define a variable for contour plotting (user subroutine).
c
c v variable to be put onto the post file
c s (idss) stress array
c sp stresses in preferred direction
c etot total strain (generalized)
c eplas total plastic strain
c ecreep total creep strain
c t array of state variable (temperature first)
c m(1) user element number
c m(2) internal element number
c m(3) material id
c m(4) internal material id
c nn integration point number
c kcus(1) layer number
c kcus(2) internal layer number
c ndi number of direct stress components
c nshear number of shear stress components
c jpltcd the absolute value of the user's entered post code
c
c the components of s, sp, etot, eplas and ecreep are given in the
order
c as defined in volume B for the current element.
c
c* * * * * *
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "matdat.cmn"
c ** Start of generated type statements **
real*8 ecreep, eplas, etot
integer jpltcd, kcus, m, ndi, nn, nshear
real*8 s, sp, t, v
c ** End of generated type statements **
dimension s(*),etot(*),eplas(*),ecreep(*),sp(*),m(4),kcus(2),
* t(*)

if(jpltcd.eq.1)then
v=t(2) !2nd state variable
endif
return
end

Several Simufact.forming specific subroutines have been developed. sfukin.f, user_fstress.f and urigid_rotate.f are
few among them. sfukin.f can be used for user kinematics as discussed in user kinematics section.

user_fstress.f subroutine can be used to compute flow stress based on user equation. The subroutine supports the
material input parameters from Simufact.material and Simufact.forming.

user_fstress(mats,ityp1,t1,ep1,er1,p1,fstress1)

c Input
c mats = material id
c ityp1 = equation type (>100)
c t1 = temperature

14
13.2 User subroutines Subroutine integration

c ep1 = plastic strain


c er1 = plastic strain rate
c p1 = material parameters from input (max 16)

c Output
c fstress1 = flow stress

urigid_rotate.f subroutine can be used to define rotational motion during the simulation.

urigid_rotate(phix,phiy,phiz,raxis,rangle,
& rsystem,timinc,ctime,idie,node,iflag)

c Input:
c idie = load controlled die id
c node = load controlled die - rotational control node id
c iflag = 0: compute rotation angle and axis
c = 1: compute only the local system rotation matrix

c Output:
c raxis(3) = rotation axis
c rsystem(3,3) = local system rotation matrix

1.3.2. Subroutine integration


This section explains the method to integrate the subroutine in the simulation process. For this, the subroutine has
to be written first. All available dummy subroutines are located in the installation folder of Simufact.forming at C:
\Program Files\simufact\forming\13.2\sfMarc\user. It is recommended that before modifying
any subroutine, it should be copied to another working directory, so that the original copy of the file exists. The copied
subroutine file can be linked with the process in the Forming control under the solver menu.

Figure 1.3. Linking user subroutine in Forming control


If the FORTRAN user subroutine is copied to the project's AdditionalFiles directory, then writing the complete file
name of subroutine in forming control is sufficient. Simufact.forming GUI will search in the project's AdditionalFiles
directory first.

Figure 1.4. Subroutine in Additional files directory

15
13.2 User subroutines User variables

With this convention, subroutine always remain with the project in case of transfer to another computer. If the linked
subroutine's complete path or file name is wrong then the text field will be highlighted in orange. Alternatively, a pre-
compiled solver (with extension .exe) can also be used. This can be linked in the Forming control window. Compiled
solver is created in the job run directory when a job is run with subroutines or alternatively can be created from
command line. This solver consist instruction from subroutine and can be used on machines without FORTRAN
compiler.

Figure 1.5. Linking pre-compiled solver in Forming control

In addition to linking the subroutine file as above, certain subroutines require additional steps of activation from the
Advanced Solver menu in Forming control. The following subroutines umotion, uhtcoe, uhtcon, ufric, sepstr and
sepfor when used, has also to be additionally activated from the User-defined > User variables > User
subroutine window under the Advanced solver option in forming control.

Figure 1.6. Activating selected subroutine in Forming control

1.3.3. User variables


Under process control > Advanced > User-defined window, there are option to define different type
of variable for the simulation. These variables can then be accessed through user subroutines.

16
13.2 User subroutines User variables

Figure 1.7. Variable definition in Forming control

In the above figure, there are settings for user variables, state variables and post variables. Their importance are
explained in details below: (refer to the number in red in figure above to the bullet list below)

1. User variables: Integer, real and string variables can be defined here. Content of these variables remains fixed
during the simulation. Solver allocates memory for user variables based on the number of variables defined here.
These variables definition can be used as input parameters for the simulation, keeping subroutine free from input
parameters.

To access these variables in subroutine, include the common block :#include "sf_userdata.cmn"

Through the above common block, in the subroutine one can determine if user variables are initialised or not.
If initialised then how many of each kind through

niuser = number of integer user variables defined in process control.

nruser = number of real user variables

nsuser = number of string user variables

Content of the variables can then be accessed in subroutines as:

iuserdata(i) : provide content of ith integer data

ruserdata(i) : provide content of ith real data

suserdata(i) : provide content of ith string data. At present length of the character array is set to 80.

2. State variables: If defined, the solver allocates extra memory to be used for information storage during the simula-
tion. State variables values can be read-write through the utility routines and post code. At re-meshing step, values
stored in the state variables will also be mapped with the same mapping-function as other simulation variables like
stress, strain etc. Value stored in these are of real types. State variables can be defined for every nodes as well
as for elements.

Nodal state variables for extra memory at each nodes. Variable nstatev from sf_userdata.cmn stores the number
of user defined nodal state variables.

Elemental state variables for extra memory at each integration point of elements. By default one state variable
is always initialised and used to store the temperature. So if the user needs 2 state variables, the value should be
set to 3. Variable nstats from hards.cmn stores the number of user defined elemental state variables.
17
13.2 User subroutines Utility routines

To access state variables, please refer to section utility routines and examples.

3. Post variables: These variables trigger the output of user defined post variables through subroutines upstno.f
(nodal) and/or plotv.f (elemental) output. At present only 20 post variables of either kind is supported from the
Simufact.forming interface. Refer to section post codes for common post code definition.

1.3.4. Utility routines


Following are the list of Simufact.forming specific utility routines through which all the nodal and elemental process
variables can be extracted. Examples provided in the next chapter uses these utility routines.

1.3.4.1. elmvar1()
elmvar1 should be used to extract elemental values from the simulation. Also it can be used to read and write the user
defined elemental variables. This can also be used to extract principle stress and strain at the element level.

elmvar1(icode,mmx,nny,kkcy1,var,ioflag)

Input
icode = post code
mmx = user element number
nny = integration point number
kkcy1 = layer number
ioflag = 0, read data
= 1, write data

var = output or save value, depending upon ioflag

userdefined elemental post code starts from 1000000 for example:


icode = 1000000+1 => temperature
= 1000000+2 => First user defined elemental variable and so on

1.3.4.2. get_elmvar()
get_elmvar should be used to get element values at the integration points.

get_elmvar(icode,mmx,mmy,nny,kkcy1,var)

Input
icode = post code
= 0 (pick up integration point coordinates)
mmx = user element number
mmy = internal element number
nny = integration point number
kkcy1 = layer number

Output
var = output value(s)

1.3.4.3. ndstatvar()
ndstatvar should be used to read and write the user defined nodal variables.

ndstatvar(istat,ind,var,ioflag)

Input
istat = user defined nodal variable id

18
13.2 User subroutines Utility routines

= 1 ,first user defined node variable


ind = node number
ioflag = 0, read data
= 1, write data

var = output or save value, depending upon ioflag

1.3.4.4. get_nodvar()
get_nodvar routine should be used to extract nodal values based on the user node numbers, nodal post codes and/or
element post codes. For element post codes, the integration point values will be extrapolated to the nodes and averaged.

get_nodvar(lnode,lnpost,lepost,var_node,var_elem,num_node,
num_npost,num_epost,nsize_node,iflag)

Input
lnode(num_node) = array of node numbers for which nodal and elemental
values are to be extracted
lnpost(num_npost) = array of nodal post codes
lepost(num_epost) = array of elemental post codes
num_node = number of nodes for which post code is requested
num_npost = number of nodal post codes requested for each node
num_epost = number of element post codes requested for each node
nsize_node = total dimension of nodal post results
iflag = 0 node numbers are external
= 1 node numbers are internal

Output
var_node(nsize_node,num_node) = return nodal results from nodal post codes
var_elem(num_epost,num_node) = return nodal results from element post
codes

1.3.4.5. get_bodyid()
This utility routine extract the contact body ID. Important to know if the element belongs to the workpiece or other
bodies. In a single workpiece job, elements will have the body id 1.

get_bodyid(ielem,ibodyid,iflag)

Input
ielem = element number
iflag = 0, element number is external
= 1, element number is internal

Output
ibodyid = body ID

1.3.4.6. get_material()
This utility routine extract the material id and number.

get_material(ielem,matnum,matid,iflag)

Input
ielem = element number
iflag = 0, element number is external
= 1, element number is internal

19
13.2 User subroutines Common user subroutines

Output
matnum = material number
matid = material id

1.3.4.7. tabva2()
This routine can help to extract values from the table driven input inside the user subroutine. This routine is useful if
the user wants to reference a value from a table that is being used by the solver.

call tabva2(refval, evalue, idtable, 0, 0)

Input
refval = reference value by which the output will be scaled
idtable = table id in the input file

Output
evalue = evaluated value

Solver already have the temperature information in the variable tempi. If the user wants to evaluate the value at a
different temperature then the user has to define different temperature as follow

1. Include the ctable common block #include "ctable.cmn"

2. set the temperature in variable tempi as tempi=user_temperature

3. call tabva2().

If the value of tempi is changed in the subroutine, then it should be reverted back to its original value.

1.3.5. Common user subroutines


Some of the commonly used subroutines are described in this section.

1.3.5.1. Incremental subroutines


These subroutines are called once every increment at different stages:

ubginc() : called at the beginning of every increment

ubgpass() : also called at the beginning of every increment but after calling ubginc(). This routine is called for
every pass of analysis and multiple times for a coupled analysis. A regular forming job has a coupled thermal and
mechanical passes where first call is a thermal pass with flag ipass=2 followed by mechanical with ipass=1. So
care should be taken for which pass should do the calculation.

ufninc() : called at end of the increment but before results are created for visualisation.

uedinc() : also called at end of every increment but after results are created for visualisation.

1.3.5.2. Elemental and nodal subroutines


These subroutines are called within an increment for every node or element accounted in the simulation.

ueloop() : called for every element in the simulation. Also called at different stages based on iflag value. With
iflag=1 called after ubginc() and before ubgpass(), With iflag=5 called before results are created.

plotv() : called for every integration point. Used to generate custom result output.

upstno() : called for every node. Used to generate custom nodal result output.

20
13.2 User subroutines Common user subroutines

User can also create local elemental / nodal loop within any subroutines. Care should be taken to filter out workpiece's
elements and/or nodes from those of the dies. Also refer to Marc Volume D: User Subroutines and Special Routines,
Output Quantities User Subroutines for more details about post processing. Below the flowchart shows the schematic
of the various routine call. This is not the complete flowchart of the simulation.

Start

inc = 1

inc = inc + 1

call ubginc ()

ielem = 1
elemental loop

ielm = ielm + 1 call ueloop ()

no
ielem > numel ?

yes

nodal loop inod = 1

inod = inod + 1

inod > numnp ?


no

yes

call ufninc ()

call plotv ()

call upstno ()

call uedinc ()

no
termination criteria reached?

yes

End

Figure 1.8. Flowchart highlighting subroutine call

21
13.2 User subroutines Post codes

1.3.6. Post codes


Post code are used in the utility routines to get the required nodal or elemental quantities from the system. Every
variable is assigned a unique post code.

1.3.6.1. Element post codes


Some of the common used element post codes are tabulated below. For list of all the available post codes, please refer
to Marc Volume C: Post (Model Definition Options).

Table 1.1. Selected list of available Element post code


icode Description
1-6 Components of strain. For rigid-perfectly plastic flow problems, compo-
nents of strain rate
7 Equivalent creep strain (integral of equivalent creep strain rate)
9 Total temperature
10 Increment of temperature
11-16 Components of stress
17 Equivalent von Mises stress
18 Mean normal stress (tensile positive) for Mohr-Coulomb
19 User-defined variable via the PLOTV user subroutine. See Marc Volume D:
User Subroutines and Special Routines.
21-26 Components of plastic strain
27 Equivalent plastic strain
28 Plastic strain rate
31-36 Components of creep strain
37 Equivalent creep strain
51-56 Real components of harmonic stress
57 Equivalent real harmonic stress
121-126 Elastic strain
127 Equivalent elastic strain

1.3.6.2. Node post codes


Following are the node post codes available for nodal values.

Table 1.2. Selected list of available Node post code


0 = Coordinates 1 = Displacement 2 = Rotation
3 = External force 4 = External moment 5 = Reaction force
6 = Reaction moment 7 = Fluid velocity 8 = Fluid pressure
9 = External fluid force 10 = Reaction fluid force 11 = Sound pressure
12 = External sound source 13 = Reaction sound source 14 = Temperature
15 = External heat flux 16 = Reaction heat flux 17 = Electric potential
18 = External electric charge 19 = Reaction electric charge 20 = Magnetic potential
21 = External electric current 22 = Reaction electric current 23 = Pore pressure
24 = External mass flux 25 = Reaction mass flux 26 = Bearing pressure

22
13.2 User subroutines User Subroutine: Examples

27 = Bearing force 28 = Velocity 29 = Rotational velocity


30 = Acceleration 31 = Rotational acceleration 32 = Modal mass
33 = Rotational modal mass 34 = Contact normal stress 35 = Contact normal force
36 = Contact friction stress 37 = Contact friction force 38 = Contact status
39 = Touched contact bodies 40 = Not available 41 = Pyrolyzed mass density
42 = Mass rate of gas 43 = Solid density rate 44 = Liquid density rate
45 = Coke density rate 46 = Tying force 47 = Coulomb force
48 = Tying moment

1.4. User Subroutine: Examples


Several examples of user subroutine in Simufact.forming are described in this section. A working model of the sim-
ulation project can be found through demo and examples browser. The subroutine is placed in their corresponding
project's Additional Files directory.

1.4.1. State Variables


Simufact.forming allows user to define additional memory for every node and elements to store additional informa-
tions during the simulation. This feature becomes useful, when in addition to usual output variables, additional in-
formation of nodal or/and elemental positions is required. One such example could be a total strain in the system.
Simufact.forming by default output elastic and plastic strains separately. Through elemental state variables, the two
can be combined and displayed. These variables are then calculated through a user-defined formula through user-
subroutines.

State variables can be displayed in result windows through activating post variables in the Forming control dialog box.
In the example, two nodes and one post variables are checked to be displayed.

Figure 1.9. Activating nodal and elemental post variables

23
13.2 User subroutines State Variables

These variables can be assigned a custom name by clicking the "write" icon on the right. The following box will open
where number of variables and its name can be assigned. These names will be used in the result tree.

Figure 1.10. Nodal post variable name selection

Figure 1.11. User element post variable name selection

Total number of user-defined variables has also to be specified for the solver. This can be done in Forming control at:
Forming control > Solver > Advanced option as shown below.

24
13.2 User subroutines State Variables

Figure 1.12. Nodal and elemental state variables selection


Number of element variables selected is two even though only one is required. By default the first element variable is
always assigned to temperature field. Therefore first elemental variable available for user is from position 2. There
is no such reservation in node variable list. Hence user can use node variables from position 1.

1.4.1.1. Example
A simple 2D upsetting model is made in Simufact.forming. Two node and one elemental user variables are considered.
In this example, the node variable, "user-nodevar-1", stores the increment values. The other node variable "outline-var"
stores 10x increment only at the border nodes. The element variable "Total-Strain" stores the total strain, elastic +
plastic, for every elements in the system. These custom variables are listed in the result window under miscellaneous.

Figure 1.13. Custom element and node variables in result tree

25
13.2 User subroutines State Variables

The following user subroutine was used. The subroutine is self explanatory with written comments. Four subroutines
were used: ueloop() and plotv() to calculate and plot the element variables where as, ufninc() and upstno() for node
variables.

subroutine ueloop(m1,m2,iflag)
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
c ** Start of generated type statements **
#include "hards.cmn" !nstats
#include "creeps.cmn" !timinc
#include "arrays.cmn" !iintel
#include "elemdata.cmn" !ieltype
#include "space.cmn" !ints
#include "concom.cmn" !ipass
c
integer iflag, m1, m2
c ** End of generated type statements **
integer layer, icode,ioflag,ibodyid,nn1,inn,i1,ityp,
*istat
real*8 eplas,deplas
c
c user routine that gets called in key element loops
c may be used in a variety of ways
c
c m1 user element number
c m2 internal element number
c iflag 1 - opress loop
c 2 - oasemb loop
c 3 - oasmas loop
c 4 - ogetst loop
c 5 - scimp loop (end of increment)
c
c IPASS = 1 STRESS
c IPASS = 2 HEAT TRANSFER
c IPASS = 3 FLUIDS
c IPASS = 4 JOULE HEATING
c IPASS = 5 DIFFUSION
c IPASS = 6 ELECTROSTATICS
c IPASS = 7 MAGNETOSTATIC
c IPASS = 8 ELECTROMAGNETICS

if(ipass.ne.1) goto 999 !only for stress pass


if(iflag.eq.5.and.nstats.gt.1)then
c utility routine to extract contact body ID
c
c ielem element number
c ibodyid body ID
c ioflag =0, user element number
c =1, element number is internal
ioflag=0
call get_bodyid(m1,ibodyid,ioflag)
if(ibodyid.ne.1)goto 999
c
c get number of integrationpoints for element (nn1)
ityp=ieltype(m2)

26
13.2 User subroutines State Variables

i1=ityp-1
nn1=ints(i1+iintel)
c
do inn=1,nn1
layer=1
icode=28 !strain rate
call get_elmvar(icode,m1,m2,inn,layer,deplas)
c calculate incremental plastic strain
deplas=deplas*timinc
c
c read data ioflag = 0
c write data ioflag = 1
c
c get 2nd state variable (ioflag=0)
istat=2
icode=1000000+istat
ioflag=0
call elmvar1(icode,m1,inn,layer,eplas,ioflag)
c cummulate value
eplas=eplas+deplas
c store 2nd state variable (ioflag=1)
istat=2
icode=1000000+istat
ioflag=1
call elmvar1(icode,m1,inn,layer,eplas,ioflag)
enddo
endif
999 return
end

subroutine plotv(v,s,sp,etot,eplas,ecreep,t,m,nn,kcus,ndi,
* nshear,jpltcd)
c* * * * * *
c
c define a variable for contour plotting (user subroutine).
c
c v variable to be put onto the post file
c s (idss) stress array
c sp stresses in preferred direction
c etot total strain (generalized)
c eplas total plastic strain
c ecreep total creep strain
c t array of state variable (temperature first)
c m(1) user element number
c m(2) internal element number
c m(3) material id
c m(4) internal material id
c nn integration point number
c kcus(1) layer number
c kcus(2) internal layer number
c ndi number of direct stress components
c nshear number of shear stress components
c jpltcd the absolute value of the user's entered post code
c
c
c the components of s, sp, etot, eplas and ecreep are given in the
order

27
13.2 User subroutines State Variables

c as defined in volume B for the current element.


c
c* * * * * *
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
c ** Start of generated type statements **
real*8 ecreep, eplas, etot
integer jpltcd, kcus, m, ndi, nn, nshear
real*8 s, sp, t, v
c ** End of generated type statements **
dimension s(*),etot(*),eplas(*),ecreep(*),sp(*),m(4),kcus(2),
* t(*)

if(jpltcd.eq.1)then
v=t(2) !2nd state variable
endif
return
end

c ###################################################

subroutine ufninc(inc,timinc,cptim,ipost,jxtrac)
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "spaceco.cmn"
#include "spacevec.cmn"

integer inc,ipost,jxtrac
real*8 timinc,cptim
c
c inc increment number
c timinc time step
c cptim time at begining of increment
c ipost current setting to control writing of post flag
c 0 - don't write
c 1 - write
c jxtrac control putting mesh on post file
c if set to 1, then lm(1)=3

integer ind,istat,ioflag,iind,ibd
real*8 var

if(inc.gt.0)then
ibd=1
ioflag=1
c read data ioflag = 0
c write data ioflag = 1
do ind=1,numnp_cn
istat=1
var=real(inc)

28
13.2 User subroutines State Variables

c saving "inc" in first node variable


call ndstatvar(istat,ind,var,ioflag)
c---------------------------------------------
istat=2
iind=inocon(ind)
if(iind.gt.0)then
var=real(inc)*10.d0
else
var=0.d0
endif
c saving "10 x inc" in only case of border node variable
call ndstatvar(istat,ind,var,ioflag)
enddo
endif
return
end

subroutine upstno(nqcode,nodeid,valno,nqncomp,nqtype,
* nqaver,nqcomptype,nqdatatype,
* nqcompname)
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
c ** Start of generated type statements **
integer nodeid, nqaver, nqcode, nqcomptype, nqdatatype, nqncomp
integer nqtype
real*8 valno
c ** End of generated type statements **
c
dimension valno(*)
character*24 nqcompname(*)
c
c input: nqcode user nodal post code , e.g. -1
c nodeid node id, external
c nqcompname not used (future expansion)
c
c output: valno() nodal values
c real/imag valno( 1: nqncomp) real
c valno(nqncomp+1:2*nqncomp) imag
c magn/phas valno( 1: nqncomp) magn
c valno(nqncomp+1:2*nqncomp) phas
c nqncomp number of values in valno
c nqtype 0 = scalar
c 1 = vector
c nqaver only for DDM 0 = sum over domains
c 1 = average over domains
c nqcomptype 0 = global coordinate system (x,y,z)
c 1 = shell (top,bottom,middle)
c 2 = order (1,2,3)
c nqdatatype 0 = default
c 1 = modal
c 2 = buckle
c 3 = harmonic real
c 4 = harmonic real/imaginary

29
13.2 User subroutines State Variables

c 5 = harmonic magnitude/phase
c
c
c to obtain nodal values to be used in this subroutine from
c the marc data base the general subroutine NODVAR is available:
c
c call nodvar(icod,nodeid,valno,nqncomp,nqdatatype)
c
c output: valno
c nqncomp
c nqdatatype
c
c input: nodeid
c icod
c 0='Coordinates '
c 1='Displacement '
c 2='Rotation '
c 3='External Force '
c 4='External Moment '
c 5='Reaction Force '
c 6='Reaction Moment '
c 7='Fluid Velocity '
c 8='Fluid Pressure '
c 9='External Fluid Force '
c 10='Reaction Fluid Force '
c 11='Sound Pressure '
c 12='External Sound Source '
c 13='Reaction Sound Source '
c 14='Temperature '
c 15='External Heat Flux '
c 16='Reaction Heat Flux '
c 17='Electric Potential '
c 18='External Electric Charge '
c 19='Reaction Electric Charge '
c 20='Magnetic Potential '
c 21='External Electric Current'
c 22='Reaction Electric Current'
c 23='Pore Pressure '
c 24='External Mass Flux '
c 25='Reaction Mass Flux '
c 26='Bearing Pressure '
c 27='Bearing Force '
c 28='Velocity '
c 29='Rotational Velocity '
c 30='Acceleration '
c 31='Rotational Acceleration '
c 32='Modal Mass '
c 33='Rotational Modal Mass '
c 34='Contact Normal Stress '
c 35='Contact Normal Force '
c 36='Contact Friction Stress '
c 37='Contact Friction Force '
c 38='Contact Status '
c 39='Contact Touched Body '
c 40='Herrmann Variable '
c 41='Density of Solid '
c 42='Mass Flow Rate of Gas '
c 43='Rt of Chnge of Pyrolysis '

30
13.2 User subroutines Motion

c 44='Rt of Chnge of Liquid Den'


c 45='Rt of Chnge of Coke Densi'
c
integer istat,ioflag,nodint,inid
real*8 var

c.....converting external nodeid to internal


c.....For version 12.0 and above
inid=nodint(nodeid)
if(nqcode.lt.0)then
istat=abs(nqcode)
ioflag=0
c only scalar values are supported so far for ARC
nqtype=0
nqdatatype=0
c read data ioflag = 0
c write data ioflag =1
call ndstatvar(istat,inid,var,ioflag)
valno(1)=var
endif
return
end

1.4.2. Motion
The user subroutine, umotion, can be used to define the motion of a body during the simulation. This subroutine
should be used only for bodies with velocity controlled rigid surfaces. This subroutine is called during the calculations
at the beginning of each time increment and the user return surface velocities for that increment. Also refer to Marc
Volume D: User Subroutines and Special Routines, User-defined Loading, Boundary Conditions, and State Variables
User Subroutines List for more details about motion.

1.4.2.1. Example
A simple 2D and 3D upsetting model is made in Simufact.forming. With the help of umotion() subroutine, the defor-
mation process will be stopped when the force on the top die exceeds the user defined force of 6kN. The movement
of the top die will be reversed with the user defined velocity of 20mm/sec. The control information, in this case force
and die velocity, are entered through the user defined variables defined under advanced solver options. The same
subroutine is used in both the job types.

Figure 1.14. User defined real variables in Forming control


Sample user subroutine for reversing the forming process in case the force exceeds the user defined value is given
below.

31
13.2 User subroutines Motion

subroutine motion(x,f,v,time,dtime,nsurf,inc)
c
c
c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
c
c user routine to provide surface motion data
c
c------------------------------------------------------------------------
c Caution: The increment number (inc), which is passed from the
c calling routine, is useful in making sure the data given
c is appropriately attributed to the relevant increments.
c For example, a center of rotation given for increment 0
c if(inc.eq.0) then
c x(1)=...
c etc.
c endif
c will be updated internally as motion and deformation take
c place. However, if the increment is not specified, then
c this center of rotation will be reset each time this routine
c is read, i.e. every increment. Obviously the results will
c be different for the two cases.
c
c The same caution is also applicable to the surface number
c (nsurf). Thus the data should be coupled only with the
c surface number(s) for which it is meant. For example:
c if(nsurf.eq.2 .or. nsurf.eq.4) then
c x(1)=...
c ...
c v(1)=...
c etc.
c endif
c
c Important: The correct use of increment numbers and surface numbers
c may give rise to more complex (or nested) if statements.
c For example:
c if(inc.eq.2 .and. nsurf.eq.3) then
c ...
c elseif(....) then
c if(....) then
c ...
c endif
c ...
c endif
c------------------------------------------------------------------------
c
c 2-d:
c input : nsurf - number of the surface for which data is
c requested
c time - the time at which data is requested
c dtime - the current time increment
c x(3) - current die defining coordinates:
c x(1) = 1st coordinate of center of
c rotation
c x(2) = 2nd coordinate of center of
c rotation
c x(3) = angle rotated around z-axis
c
c f(3) - the current surface load:

32
13.2 User subroutines Motion

c f(1) = 1st component of load


c f(2) = 2nd component of load
c f(3) = moment
c inc - the increment number
c
c output : v(3) - current surface velocities
c v(1) = 1st component of the velocity at
c the center of rotation.
c v(2) = 2nd component of the velocity at
c the center of rotation.
c v(3) = angular velocity
c
c 3-d:
c input : nsurf - the number of the surface for which data
c is requested
c time - the time at which data is requested
c dtime - the current time increment
c x(6) - current die defining coordinates:
c x(1) = 1st coordinate of center of
c rotation
c x(2) = 2nd coordinate of center of
c rotation
c x(3) = 3rd coordinate of center of
c rotation
c Axis for specifying angular velocity:
c x(4) = 1st component of direction cosine
c x(5) = 2nd component of direction cosine
c x(6) = 3rd component of direction cosine
c
c f(6) - the current surface load:
c f(1) = 1st component of load
c f(2) = 2nd component of load
c f(3) = 3nd component of load
c f(4) = 1st component of moment
c f(5) = 2nd component of moment
c f(6) = 3rd component of moment
c inc - the increment number
c
c output : v(4) - current surface velocities
c v(1) = 1st component of the velocity at
c the center of rotation
c v(2) = 2nd component of the velocity at
c the center of rotation
c v(3) = 3nd component of the velocity at
c the center of rotation
c v(4) = angular velocity around axis defined
c above with x(4), x(5), and x(6).
c
c
c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
c
c
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "spaceco.cmn" !contact body information, cbname, numdie_cn

33
13.2 User subroutines Motion

#include "machin.cmn" !iprtl


#include "prepro.cmn" !kou
#include "sf_userdata.cmn"
c ** Start of generated type statements **
real*8 dtime, f
integer inc, nsurf
real*8 time, v, x
c ** End of generated type statements **
dimension x(*),v(*),f(*)
character*24 cbody,cbody0
integer i,imvbody,i2switch,ilen1
real*8 mxforce,vel
c
c
c first find out with contact body ID should be moved
if(inc.eq.0.and.nsurf.eq.1)then
i2switch=0
cbody='Punch'
ilen1=index(cbody,' ') - 1
c nruser - number of real user variables
if(nruser.lt.2)then
write(iprtl,1001) nruser,2
call quit(13)
endif
c get information from user data block check units!!
c in forming SI-m unit are used
mxforce=ruserdata(2)*1000.d0
vel=ruserdata(1)/1000.d0
c get body id
do i=1,numdie_cn
cbody0=cbname(i)
if(cbody0(:ilen1).eq.cbody(:ilen1))then
imvbody=i
exit
endif
enddo
endif

c skip alll bodies which should not move


if(nsurf.ne.imvbody)goto 999
c
c check if max force is reached
if(i2switch.eq.0)then
if(abs(f(1)).gt.mxforce)then
write(kou,1002)mxforce, cbody(:ilen1),abs(f(1))
i2switch=1
endif
endif
c define velocity
v(1)=vel
if(i2switch.eq.1)v(1)=-v(1)
write(kou,1003)cbody(:ilen1),v(1)
999 return
1001 format(13x,'*** error ',
* 'Number of user defined real variables nruser:',i3,'
* is less then needed: ',i3,/13x,'check input deck!')
1002 format(13x,'max force of ',f12.6,' is reached in body:'a,
* ' force is:',f12.6)

34
13.2 User subroutines Damage

1003 format(13x,'Calculated velocity of Body ',a,' is:',f12.6)

end

1.4.3. Damage
Damage information during the simulation can be used to predict the failure of the workpiece. This is done by com-
paring the calculated solution to some failure criteria. Simufact.forming by default supports four damage models, i.e.
Cockroft Latham, Lemaitre, Oyane and Johnson-Cook models.

Figure 1.15. Supported damage model in Simufact.forming


However only one of them can be output in the simulation. With the usage of user subroutine, multiple custom damage
models can be simultaneously implemented in the simulation.

1.4.3.1. Example
In this example, damage values through three different models are calculated and stored in three elemental state vari-
ables. In addition to linking the subroutine, three elemental state variables and three user defined elemental post vari-
ables have to be selected and checked in the forming control. The example consist of two stages over stage control
and share the same user subroutine, as written below

subroutine ueloop(m1,m2,iflag)
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif

c* * * * * *
c..................
c Output values for the integral damage criteria
c damage growing at positive stress only
c..................
c 2 [Atk81] mean normal stress
c A. G. Atkins, 1981, Possible explanation for unexpected
c departures in hydrostatic tensionfracture strain
c relations. Metal Science, pp. 8183
c..................
c 3 [AyHi87] triaxiality
c M. Ayada, T. Higashino and K. Mori, 1987,
c Central Bursting in Extrusion of Inhomogeneous Materials.
c Advanced Technology of Plasticity, Vol. 1, pp. 553-558
c..................
c 4 [OySa80] modified triax
c M. Oyane, T. Sato, K. Okimoto and S. Shima, 1980,
c Criteria for ductile fracture and their applications,
c J. Mech. Work. Technol, Vol. 4, pp. 65-81

35
13.2 User subroutines Damage

c..................
c* * * * * *

c ** Start of generated type statements **


#include "hards.cmn" !nstats
#include "space.cmn" !ints
#include "creeps.cmn" !timinc
#include "concom.cmn" !ipass
#include "prepro.cmn" !kou
#include "machin.cmn" !iprtl
#include "arrays.cmn" !iintel
#include "elemdata.cmn" !ieltype
#include "marc_prestt.cmn" !iprestt_data

integer iflag, m1, m2


c ** End of generated type statements **

integer layer, icode,ioflag,ibodyid,nn1,inn,i1,ityp,


* istat,ndi,nshear
real*8 eplas,deplas,val,vmises,hydro,triax,erate
real*8 depsilon,ddamage,biggg,c
c
c user routine that gets called in key element loops
c may be used in a variety of ways
c
c m1 user element number
c m2 internal element number
c iflag 1 - opress loop
c 2 - oasemb loop
c 3 - oasmas loop
c 4 - ogetst loop
c 5 - scimp loop (end of increment)

c IPASS = 1 STRESS
c IPASS = 2 HEAT TRANSFER
c IPASS = 3 FLUIDS
c IPASS = 4 JOULE HEATING
c IPASS = 5 DIFFUSION
c IPASS = 6 ELECTROSTATICS
c IPASS = 7 MAGNETOSTATIC
c IPASS = 8 ELECTROMAGNETICS

if(ipass.ne.1) goto 999 !only for stress pass

if(inc.eq.0)then
c check first if total number is set correct for the job
if(nstats.lt.4)then
write(kou,1002)nstats,4
write(iprtl,1002)nstats,4
call quit(13)
endif

c initialization of the state variables


if(iprestt_data(1).ne.0) goto 100
c get number of integrationpoints for element (nn1)
ityp=ieltype(m2)
i1=ityp-1
nn1=ints(i1+iintel)

36
13.2 User subroutines Damage

do inn=1,nn1
ioflag=1 !write data
layer=1
do istat=2,4
icode=1000000+istat
c initialize to zero only if iprestt_data(1).eq.0 (no multistage job)
c not for a multistage job
val=0.0d0 !initialize to zero
call elmvar1(icode,m1,inn,layer,val,ioflag)
enddo
enddo
goto 999
endif

100 if(inc.eq.0) goto 999

if(iflag.eq.5.and.nstats.gt.1)then

c utility routine to extract contact body ID


c ielem element number
c ibodyid body ID
c ioflag =0, user element number
c =1, element number is internal
ioflag=0
call get_bodyid(m1,ibodyid,ioflag)
if(ibodyid.ne.1)goto 999
c
c get number of integrationpoints for element (nn1)
ityp=ieltype(m2)
i1=ityp-1
nn1=ints(i1+iintel)

do inn=1,nn1
layer=1
icode=17 !vonmises stress
call get_elmvar(icode,m1,m2,inn,layer,vmises)

icode=18 !hydrostatic stress


call get_elmvar(icode,m1,m2,inn,layer,hydro)

triax=hydro/vmises

if(triax.ge.0) then

c equivalent plastic strain increment delta_epsilon


c delta_epsilon = (d_epsilon/d_t) * delta_t
icode = 28 !plastic strain
call get_elmvar(icode,m1,m2,inn,layer,erate)
depsilon=erate*timinc

c.......................................................................
c2 Damage criteria by [Atk81] 1
istat=2
icode=1000000+istat
ioflag=0 !read previous value
call elmvar1(icode,m1,inn,layer,val,ioflag)

37
13.2 User subroutines Damage

ddamage = hydro * depsilon


val=val+ ddamage

ioflag=1 !write
call elmvar1(icode,m1,inn,layer,val,ioflag)

c.......................................................................
c3 Damage criteria by [AyaH87]
istat=3
icode=1000000+istat
ioflag=0 !read previous value
call elmvar1(icode,m1,inn,layer,val,ioflag)

ddamage = (hydro/vmises) * depsilon


val=val+ ddamage

ioflag=1 !write
call elmvar1(icode,m1,inn,layer,val,ioflag)

c.......................................................................
c4 Damage criteria by [OySa80]
istat=4
icode=1000000+istat
ioflag=0 !read previous value
call elmvar1(icode,m1,inn,layer,val,ioflag)

c=0.424
ddamage=(1+(hydro/(c*vmises)))*depsilon
val=val+ ddamage

ioflag=1 !write
call elmvar1(icode,m1,inn,layer,val,ioflag)
c.......................................................................
endif
enddo
endif

999 return
1002 format(13x,'*** error: Total number of state variables ',i5,
* ' is less than needed in plotv:',i5,
* /13x,'increase number to "element state variables" in
* job options under:',
* /13x,'Forming control-->Advanced-->Solver-->Advanced ',/)

end

subroutine plotv(v,s,sp,etot,eplas,ecreep,t,m,nn,kcus,ndi,
* nshear,jpltcd)
c* * * * * *
c
c define a variable for contour plotting (user subroutine).
c
c v variable to be put onto the post file
c s (idss) stress array
c sp stresses in preferred direction
c etot total strain (generalized)
c eplas total plastic strain

38
13.2 User subroutines Friction

c ecreep total creep strain


c t array of state variable (temperature first)
c m(1) user element number
c m(2) internal element number
c m(3) material id
c m(4) internal material id
c nn integration point number
c kcus(1) layer number
c kcus(2) internal layer number
c ndi number of direct stress components
c nshear number of shear stress components
c jpltcd the absolute value of the user's entered post code
c
c
c the components of s, sp, etot, eplas and ecreep are given in the
order
c as defined in volume B for the current element.
c
c* * * * * *
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
c ** Start of generated type statements **
real*8 ecreep, eplas, etot
integer jpltcd, kcus, m, ndi, nn, nshear
real*8 s, sp, t, v
c ** End of generated type statements **
dimension s(*),etot(*),eplas(*),ecreep(*),sp(*),m(4),kcus(2),
* t(*)

if(jpltcd.eq.2) v=t(2) !1st user state variable


if(jpltcd.eq.3) v=t(3) !2nd user state variable
if(jpltcd.eq.4) v=t(4) !3rd user state variable

return
end

1.4.4. Friction
Through the ufric subroutine, friction behaviour of the contact surfaces between the die and workpiece can be dynam-
ically changed. The ufric subroutine is called when either only shear or coulomb friction is added in the process tree.
The subroutine is called for every element containing nodes that are in contact with surfaces at the nodes.

1.4.4.1. Example
In the 2D upsetting example, material's roughness value is input through real user variables in forming control. Based
on the roughness value of surface node, friction coefficient is chosen in the ufric subroutine. At increment end, rough-
ness values for the surface nodes are changed as a function of von Mises and contact normal stress. The change rough-
ness value is then used to set the friction coefficient in the simulation in next increment.

subroutine ufric(mibody,x,fn,vrel,temp,yiel,fric,time,inc,nsurf)
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif

39
13.2 User subroutines Friction

#include "spaceco.cmn" !jfnold


#include "sf_userdata.cmn"
#include "prepro.cmn" !kou
c ** Start of generated type statements **
real*8 x, fn, fric
integer inc, mibody, nsurf
real*8 temp, time, vrel, yiel
c ** End of generated type statements **
dimension mibody(*),x(*),vrel(*),temp(*)
c
c user routine to define friction behavior
c
c Input
c for distributed friction based upon nodal stress
c
c mibody(1) - user element number
c mibody(2) - edge or face number
c mibody(3) - edge/face integration point number
c mibody(4) - internal element number
c fn - normal stress
c
c for nodal friction based upon nodal forces
c
c mibody(1) - user node number
c mibody(2) - not used
c mibody(3) - not used
c mibody(4) - internal node number
c fn - normal force
c
c for either model
c
c x - updated coordinates of contact point where friction is
being calculated
c vrel - relative sliding velocity in tangential direction(s)
c temp(1) - temperature
c temp(2) - voltage in Joule heating simulation
c yiel - flow stress
c time - time at begining of increment
c inc - increment number
c nsurf - surface being contacted by the side for which friction
c calculation is being made
c
c Output
c fric - friction coefficint or factor
c
c

c skip symmetry body


c jfnold(4,i) = 1 : rigid
c 2 : deformable
c 3 : symmetry
c 4 : heat-rigid
c 5 : workpiece (autoforge only)

real*8 xrough,xrough0
integer istat,ioflag

if(jfnold(4,nsurf).eq.3)goto 999

40
13.2 User subroutines Friction

c read data ioflag = 0


c write data ioflag = 1
ioflag=0
istat=1
call ndstatvar(istat,mibody(4),xrough,ioflag)
if(xrough.gt.0)then
if(xrough.lt.30.0) then
fric=0.15
elseif (xrough.lt.35.0) then
fric=0.25
elseif (xrough.lt.50.0) then
fric=0.40
else
fric=0.50
end if
endif

999 return
end

c
#####################################################################################
subroutine uedinc(inc,incsub)
c called from oscinc
c
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "sf_userdata.cmn"
#include "machin.cmn" !iprtl
#include "prepro.cmn" !kou
#include "spaceco.cmn"
#include "spacevec.cmn" !inocon
c
c... subroutine which is called at the end of each
c... increment
c...
c... inc : increment number
c... incsub: sub-increment number
c
c
c-------------------------------------------------------
c subroutine at the end of each inc
c can be used to initialize nodal state variables at inc 0
c-------------------------------------------------------
c ** Start of generated type statements **
integer inc, incsub
c ** End of generated type statements **
integer ind,istat,ioflag,iind
real*8 xrough,var

xrough=0.0d0 ! initialize
if(inc.eq.0)then
c
c check first if nodal state variable is defined

41
13.2 User subroutines Friction

c nstatev = number of nodal state variables


c nruser - number of real user variables
c ruserdata(nruser) - real user data array
c
if(nstatev.gt.0)then
if(nruser.gt.0)then
xrough=ruserdata(1)
else
write(kou,1002)nruser,1,xrough
call quit(13)
endif
else
write(iprtl,1001)nstatev,1
write(kou,1001)nstatev,1
call quit(13)
endif

do ind=1,numnp_cn
c figure out if node is a boundary node
c do nn=1,numnp
c inn=inocon(nn)
c if(inn.lt.0) then
c check if Internal Node belongs to body ibd only 2D
c if(abs(inn).eq.ibd) then
c endif
c elseif (inn.gt.0) then
c inn1=mod(inn,nbmx)
cc check if Boundary Node belongs to body ibd
c if (inn1.eq.ibd) then
c endif
c endif
iind=inocon(ind)
if(iind.gt.0)then
var=xrough
else
var=0.d0
endif
c read data ioflag = 0
c write data ioflag = 1
ioflag=1
istat=1
call ndstatvar(istat,ind,var,ioflag)
enddo
endif !end inc loop
999 return
1001 format(13x,'*** error ',
* 'Number of user defined nodal variables nstatev:',i3,'
* is less then needed: ',i3,/13x,'check input deck!')
1002 format(13x,'*** error ',
* 'Number of user defined real variables nruser:',i3,'
* is less then needed: ',i3,/13x,'fixed value is used: ',
* f12.6,' check input deck!')
end

subroutine ufninc(inc,timinc,cptim,ipost,jxtrac)
c
c ###########################################################

42
13.2 User subroutines Friction

c usersubroutine at the end of an increment before result output.


c use this routine to define any own state variables, will be
c called only after inc 1 and following
c ###########################################################
c
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
# include "sf_userdata.cmn"
# include "spaceco.cmn"
#include "prepro.cmn" !kou
c ** Start of generated type statements **
integer inc,ipost,jxtrac
real*8 timinc,cptim
c ** End of generated type statements **
c
c inc increment number
c timinc time step
c cptim time at begining of increment
c ipost current setting to control writing of post flag
c 0 - don't write
c 1 - write
c jxtrac control putting mesh on post file
c if set to 1, then lm(1)=3
integer ind,iflag,istat,lnode,lnpost,lepost,num_node,num_npost,
*num_epost,nsize_node,ioflag
real*8 xrough,xrough0,vmises,cstress,var_node,var_elem,x1
dimension lnode(1),lnpost(1),lepost(1),var_node(3,1),var_elem(1,1)
c ----------------------------------------------------------------------
c subroutine get_nodvar(lnode,lnpost,lepost,var_node,var_elem,
c & num_node,num_npost,num_epost,nsize_node,
c & iflag)
c
c routine to extract nodal values based on the user node numbers,
c nodal post codes and/or element post codes.
c for element post codes, the integration values will be extrapolated to
c the nodes and averaged.
c lnode(num_node) = array of node numbers for which nodal and elemental
values are to be extracted
c lnpost(num_npost) = array of nodal post codes
c lepost(num_epost) = array of elemental post codes
c num_node = number of nodes for which post code is requested
c num_npost = number of nodal post codes requested for each node
c num_epost = number of element post codes requested for each node
c nsize_node = total dimension of nodal post results
c iflag = 0 node numbers are external
c = 1 node numbers are internal
c Output
c var_node(nsize_node,num_node) = return nodal results from nodal post codes
c var_elem(num_epost,num_node) = return nodal results from element post
codes
c
c For example, for a post-code displacement and "Temperature"
c you will get 3 nodal displacements in X,Y,Z. and 1 nodal temperature
c In this case, num_npost=2 and nsize_node=4 (=3+1).
c iflag - =0 node numbers are external

43
13.2 User subroutines Friction

c =1 node numbers are internal


c----------------------------------------------------------------------------------
xrough0=ruserdata(1)
xrough=0.0d0 ! initialized
do ind=1,numnp_cn
c read data ioflag = 0
c write data ioflag = 1
ioflag=0
istat=1
call ndstatvar(istat,ind,xrough,ioflag)
c
if(xrough.gt.0)then !then boundary node which roughness
lnode(1)=ind
lnpost(1)=34 !34 Contact Normal Stress
lepost(1)=17 !17 Equivalent von Mises stress
num_node=1
num_npost=1
num_epost=1
nsize_node=3
c iflag =1 node numbers are internal
iflag=1
call get_nodvar(lnode,lnpost,lepost,var_node,
& var_elem,num_node,num_npost,num_epost,nsize_node,
& iflag)
vmises=var_elem(1,1)
cstress=abs(var_node(1,1))
if(vmises.gt.0.d0)then
x1=cstress/vmises
ioflag=1
istat=1
if(x1.ne.0.0) then
c reduce initial roughness based on normalised contact normal stress
x1=xrough0*(1 - x1*1000)
if(x1.lt.xrough) then !if roughness is smaller save it
call ndstatvar(istat,ind,x1,ioflag)
endif
endif
endif
endif
enddo
999 return
end

subroutine upstno(nqcode,nodeid,valno,nqncomp,nqtype,
* nqaver,nqcomptype,nqdatatype,
* nqcompname)
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "concom.cmn" ! variable inc
c ** Start of generated type statements **
integer nodeid, nqaver, nqcode, nqcomptype, nqdatatype, nqncomp
integer nqtype
real*8 valno
c ** End of generated type statements **
c

44
13.2 User subroutines Process report

dimension valno(*)
character*24 nqcompname(*)
c
c input: nqcode user nodal post code , e.g. -1
c nodeid node id
c nqcompname not used (future expansion)
c
c output: valno() nodal values
c real/imag valno( 1: nqncomp) real
c valno(nqncomp+1:2*nqncomp) imag
c magn/phas valno( 1: nqncomp) magn
c valno(nqncomp+1:2*nqncomp) phas
c nqncomp number of values in valno
c nqtype 0 = scalar
c 1 = vector
c nqaver only for DDM 0 = sum over domains
c 1 = average over domains
c nqcomptype 0 = global coordinate system (x,y,z)
c 1 = shell (top,bottom,middle)
c 2 = order (1,2,3)
c nqdatatype 0 = default
c 1 = modal
c 2 = buckle
c 3 = harmonic real
c 4 = harmonic real/imaginary
c 5 = harmonic magnitude/phase
c
c
integer istat,ioflag,nodint,inid
c
c.....converting external nodeid to internal
c.....For version 12.0
inid=nodint(nodeid)
valno(1)=0.d0
nqtype=0
nqdatatype=0
nqncomp=1
c
if(nqcode.eq.-1)then
ioflag=0
istat=1
c read data ioflag = 0
c write data ioflag = 1
call ndstatvar(istat,inid,valno(1),ioflag)
endif
return
end

1.4.5. Process report


A process report consisting of important simulation runtime parameters can be generated through "show process
report" button.

45
13.2 User subroutines Process report

Figure 1.16. "show process report" icon in Simufact.forming

The report consist of all the initial conditions of the simulation process as well as tabulated overview of the forces,
energy, torque and other mechanical information of the die and workpiece in the system. With the help of a subroutine,
it is possible to automatically include the snapshot of the forming process at a desired step in the process report. We
consider a hammer process for example. During runtime of the simulation, the subroutine creates a csv file named
"markers.csv" consisting of the increment number at the end of each hammer blow with the label "EndBlow". The
increment information is then used to extract the necessary snapshots of post variables for process report. To include,
first open the desired results which should be included in the process report.

Figure 1.17. Process report with effective plastic strain and effective stress

In the above process report two post variables, effective plastic strain and effective stress are included. To include a
post variable in the process report, first open the result window and right click to activate and then include the result
into process report as shown below.

46
13.2 User subroutines Process report

Figure 1.18. Adding "effective stress" post variable to process report"


In the next window select trigger as "Solver mark".

Figure 1.19. Selecting "Solver mark" as trigger


A process reported created afterwards will include the photo of added post variables. In similar way, multiple post
variables can be added.

1.4.5.1. Example
Following subroutine was used to create the file "markers.csv" containing last increment of every blow.

subroutine uedinc(inc,incsub)
c

47
13.2 User subroutines Table evaluation

#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "iautcr.cmn" !loadcn
#include "cstage.cmn" !istage0
#include "cdominfo.cmn" !iparent
c ** Start of generated type statements **
integer inc, incsub
c ** End of generated type statements **
c
integer output
character*10 cmarker1
character*16 filename
c... dummy user subroutine which is called at the end of each
c... increment
c...
c... inc : increment number
c... incsub: sub-increment number
c
output=201
cmarker1='endofblow'
filename='markers.csv'
C ifmode = 0 -- sequential formatted OLD file
C ifmode = 1 -- sequential formatted UNKNOWN file
C ifmode = 2 -- sequential formatted NEW file
C ifmode = 3 -- sequential formatted UNKNOWN, APPEND file
c
c ifltype = 2 -- other file
c
c call openfile(out,file,ifmode,ifltype)
c
c iparent is the parent domain. The file should be written only for the
parent domain, so that we get only one file.
if(iparent.ne.0)goto 999
if(inc.eq.0)then
call openfile(output,filename,1,2)
write(output,1001)inc,cmarker1
call closefile(output,filename,0,2)
endif
c check if end of loadcase loadcn=0 and in the forming stage istage0=3
if(loadcn.eq.0.and.istage0.eq.3)then
call openfile(output,filename,3,0)
write(output,1001)inc,cmarker1
call closefile(output,filename,0,2)
endif

999 return
1001 format(i10,',',a)
end

1.4.6. Table evaluation


In this example, tabva2() utility routine is used to calculate the values from the input data table used in the simulation
through user subroutine. Every input information gets a table ID for solver to distinguish between different tables.
The tabva2() utility routines helps user to calculate information from the table within the subroutine. User can use
the evaluated value further in their calculation.

48
13.2 User subroutines Table evaluation

1.4.6.1. Example
A simple upsetting job is set up. To know the table id given by the Forming gui, one should temporary start-stop
the simulation and browse the job *.dat and material *.umt file created in the job _Run_ directory. If the material
input file (*.umt) is opened in a text editor, various material parameters are provided as a table input as a function of
temperature. Below code shows the input information about Young's modulus from the example material file (*.umt)

$-----------------------------------------------------------------------------------------
$ youngs_modulus
$-----------------------------------------------------------------------------------------
table, youngs_modulus
$ table id, nb of independent variables, unit number to read data, disable
output, method to read function
11000,1,0,1,0,
$ temperature, nb of points, deny extrapolation
12,24,1,
$ temperature data
3.2315000000000+02,3.7315000000000+02,4.2315000000000+02,4.7315000000000+02,
5.2315000000000+02,5.7315000000000+02,6.2315000000000+02,6.7315000000000+02,
7.2315000000000+02,7.7315000000000+02,8.2315000000000+02,8.7315000000000+02,
9.2315000000000+02,9.7315000000000+02,1.0231500000000+03,1.0731500000000+03,
1.1231500000000+03,1.1731500000000+03,1.2231500000000+03,1.2731500000000+03,
1.3231500000000+03,1.3731500000000+03,1.4231500000000+03,1.4731500000000+03,
$ youngs_modulus data
2.1000000000000+11,2.0700000000000+11,2.0300000000000+11,2.0000000000000+11,
1.9600000000000+11,1.9300000000000+11,1.8800000000000+11,1.8400000000000+11,
1.7900000000000+11,1.7500000000000+11,1.6900000000000+11,1.6400000000000+11,
1.5800000000000+11,1.5300000000000+11,1.4700000000000+11,1.4000000000000+11,
1.3400000000000+11,1.2700000000000+11,1.2000000000000+11,1.1300000000000+11,
1.0600000000000+11,9.8000000000000+10,9.0000000000000+10,8.2000000000000+10,

In the example simulation, we consider three tables:

table id = 11000 : Young's modulus

table id = 11001 : Thermal expansion coefficient

table id = 11002 : Thermal conductivity

With the help of subroutine, at the every increment these values will be output in the results. Moreover the Young's
modulus value will be converted from Pascal to psi unit. Following settings are made in the Forming control
> Advanced > User defined

Including user subroutine and integer user variables as

Figure 1.20. Table Id as input through integer user variables


Using real user variables as scaling factor.

49
13.2 User subroutines Table evaluation

Figure 1.21. Scaling factor as input through real user variables

Check User-defined element variables and select three element variables and name them accordingly

Figure 1.22. Elemental post variables selection

Following subroutine was use to calculate the three table values and display the output. For this example only plotv
subroutine is used. The user can implement the tabva2 utility in most of the user subroutines.

c--------------------------------------------------------------
c Subroutine to show uses of tabva2 utility routine to extract
c user defined table information provided in the input during
c simulation
c--------------------------------------------------------------
subroutine plotv(v,s,sp,etot,eplas,ecreep,t,m,nn,kcus,ndi,
* nshear,jpltcd)
c* * * * * *
c define a variable for contour plotting (user subroutine).
c
c v variable to be put onto the post file
c s (idss) stress array
c sp stresses in preferred direction
c etot total strain (generalized)
c eplas total plastic strain
c ecreep total creep strain
c t array of state variable (temperature first)
c m(1) user element number
c m(2) internal element number
c m(3) material id
c m(4) internal material id
c nn integration point number
c kcus(1) layer number
c kcus(2) internal layer number
c ndi number of direct stress components
c nshear number of shear stress components
c jpltcd the absolute value of the user's entered post code
c

50
13.2 User subroutines Runtime local variables

c
c the components of s, sp, etot, eplas and ecreep are given in the
order
c as defined in volume B for the current element.
c* * * * * *

#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif

#include "ctable.cmn" !provides variable tempi


#include "sf_userdata.cmn" !provides user data

c ** Start of generated type statements **


real*8 ecreep, eplas, etot
integer jpltcd, kcus, m, ndi, nn, nshear
real*8 s, sp, t, v
c ** End of generated type statements **
dimension s(*),etot(*),eplas(*),ecreep(*),sp(*),m(4),kcus(2),
* t(*)

integer itableid
real*8 orig_tempi, cfactor

c -- check if number of post output is less or equal to the


c -- number of user provided in table id
if(jpltcd.le.niuser) then

c -- Copy user provided table id


itableid=iuserdata(jpltcd)

c -- Copy original tempi to orig_tempi for restoration later

orig_tempi=tempi
tempi=t(1) !First state varibale is the temperature
cfactor=1.0

c -- Selecting multiplier if provided by the user


if(jpltcd.le.nruser) cfactor=ruserdata(jpltcd)

c -- calling the table evaluation routine. The result is saved in


c -- variable v which is put in post file
call tabva2(cfactor,v,itableid,0,0)

c -- Restoring the variable tempi to its original value


tempi=orig_tempi
endif

return
end

1.4.7. Runtime local variables


Subroutines are called multiple times during the simulation. Local variables defined in a subroutine will be lost in
the subsequent visit if not stored properly. One way to save the local information is by making them global through
common block or module. This method is fine for a 2D and 3D (no ddm) simulation job. For a ddm job this method

51
13.2 User subroutines Runtime local variables

will fail at remeshing step as simulation is stopped at remeshing. Other method is to write the information to file and
read it back, as used in motion example earlier. However, if user wants to restart a job from earlier stage, then the
method will fail as Simufact.forming GUI will cleanup the run directory at restart loosing the information.

Here an example is provided to save the local variables when required. The example uses module to share the infor-
mation within different routines. At the end of increment the information will be written to the file and will be read
at the beginning in case there was remeshing. If user need to store information that is node/element specific, state
variables should be used. Information that is unique for an increment, irrespective of nodes/elements, should be used
to save through this method.

1.4.7.1. Example
A simple upsetting model is used. Through subroutine, increment information is saved in a *kin.res file.
Simufact.forming GUI will backup and replace the file if there is a job restart. If the job is restarted from earlier in-
crement, the correct saved information will be retrieved by the subroutine. User should modify the routine depending
upon number of variables to be saved. For demonstration, a real and an integer variable are assigned and initialized at
a beginning. The variables are then linearly increased by factor one and ten respectively and plotted in two post vari-
ables. User should stop the job and restart from earlier increment to see if the information are retained in the restart run.
c -- Module definition
module uservariables
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
c Define number of real and integer variable to save
integer,parameter :: number_real = 1
integer,parameter :: number_integer = 1

integer,dimension (number_integer) :: integer_array


real,dimension (number_real) :: real_array
end module

c -- Read the saved variable at start of increment


subroutine ubginc(inc,incsub)
use uservariables

#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "cdominfo.cmn"
#include "marc_prestt.cmn"

integer inc, incsub


c Initializing variable at simulation start
if(inc.eq.0.and.iprestt_data(23).eq.0) then
real_array(1)=0.0
integer_array(1)=0
endif
call readuservariables !in case of remeshing/Job restart
return
end

c -- Save the variable at end of increment

52
13.2 User subroutines Runtime local variables

subroutine ufninc(inc,timinc,cptim,ipost,jxtrac)
use uservariables
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
integer inc,ipost,jxtrac
real*8 timinc,cptim
c inc increment number
c timinc time step
c cptim time at begining of increment
c ipost current setting to control writing of post flag
c 0 - don't write
c 1 - write
c jxtrac control putting mesh on post file
c if set to 1, then lm(1)=3
integer ind,istat,ioflag,iind,ibd
real*8 var

if(inc.gt.0)then
real_array(1)=real_array(1)+1.0
integer_array(1)=integer_array(1)+10
endif
call saveuservariables ! Save the current state to file
return
end

c -- Plot the variables in this example


subroutine plotv(v,s,sp,etot,eplas,ecreep,t,m,nn,kcus,ndi,
* nshear,jpltcd)
use uservariables
c* * * * * *
c
c define a variable for contour plotting (user subroutine).
c
c v variable to be put onto the post file
c s (idss) stress array
c sp stresses in preferred direction
c etot total strain (generalized)
c eplas total plastic strain
c ecreep total creep strain
c t array of state variable (temperature first)
c m(1) user element number
c m(2) internal element number
c m(3) material id
c m(4) internal material id
c nn integration point number
c kcus(1) layer number
c kcus(2) internal layer number
c ndi number of direct stress components
c nshear number of shear stress components
c jpltcd the absolute value of the user's entered post code
c
c
c the components of s, sp, etot, eplas and ecreep are given in the
order

53
13.2 User subroutines Runtime local variables

c as defined in volume B for the current element.


c
c* * * * * *
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
c ** Start of generated type statements **
real*8 ecreep, eplas, etot
integer jpltcd, kcus, m, ndi, nn, nshear
real*8 s, sp, t, v
c ** End of generated type statements **
dimension s(*),etot(*),eplas(*),ecreep(*),sp(*),m(4)
dimension kcus(2),t(*)

if(jpltcd.eq.1) v=real_array(1)
if(jpltcd.eq.2) v=integer_array(1)
return
end

c -- Function to read saved variables after remeshing


subroutine readuservariables
use uservariables
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "op1.cmn"
#include "sfkin.cmn"
#include "concom.cmn"
#include "cdominfo.cmn"
#include "marc_prestt.cmn"

integer i,idone
integer :: iunit = 18
integer :: kin_unit = 57
real*8 dummy
character*(MAX_CARD_DIM_2) filen,filen2

c -- If called for first time then create the file


if(inc.eq.0.and.iprestt_data(23).eq.0.and.iparent.eq.0) then
call get_kin2res_filename(filen, filen2)
call openfile(iunit,filen,1,2)
call sfkin2res (iunit,kin_unit,0,0,0,1,2) !write
call closefile(iunit,filen,0,2)
return
endif

c Non DDM JOB after restart


if(inc.eq.0.and.iprestt_data(23).ne.0.and.nprocd.eq.0) then
call readresfile
endif

c DDM JOB after restart/Remeshing


if(inc.eq.0.and.iprestt_data(23).ne.0.and.nprocd.gt.0) then
c -- File will be read by each domain, one at a time

54
13.2 User subroutines Runtime local variables

do i=1,nprocd
if(i.eq.iprcnm) then
call readresfile
idone=i
endif
call domflag(idone,dummy,1,0,1,0)
enddo !i=1,nprocd
endif
return
end

c -- Function to read user variables


subroutine readresfile
use uservariables
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "op1.cmn"
#include "sfkin.cmn"

integer :: iunit = 18
integer :: kin_unit = 57
character*(MAX_CARD_DIM_2) filen,filen2

call get_kin2res_filename(filen, filen2)


call openfile(iunit,filen,1,0)
call sfkin2res (iunit,0,0,0,0,1,1) !read
integer_array(1:number_integer)=i2res(1:number_integer)
real_array(1:number_real)=x2res(1:number_real)
call closefile(iunit,filen,0,2)
return
end

c -- Function to save user variables


subroutine saveuservariables
use uservariables
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "op1.cmn"
#include "sfkin.cmn"
#include "concom.cmn"
#include "cdominfo.cmn"
#include "marc_prestt.cmn"

character*(MAX_CARD_DIM_2) filen,filen2
integer :: iunit = 18
integer :: kin_unit = 57
c Saved by only one domain
if (iparent.eq.0) then
call get_kin2res_filename(filen, filen2)
i2res(1:number_integer)=integer_array(1:number_integer)

55
13.2 User subroutines FORTRAN- C/C++ user subroutine
interface

x2res(1:number_real)=real_array(1:number_real)
call openfile(iunit,filen,1,0)
call sfkin2res (iunit,kin_unit,
+ number_integer,number_real,0,1,3) !append
call closefile(iunit,filen,0,2)
endif
return
end

c -- Function to get kinematic file name


subroutine get_kin2res_filename(filename1, filename2)
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "op1.cmn"
#include "jname.cmn"
#include "cdominfo.cmn"

integer i1,last_char
character*(MAX_CARD_DIM_2) filename1,filename2

if(nprocd.gt.0)then
i1=last_char(jidnam_base)
filename1=jidnam_base(:i1)//'_kin.res'
filename2=jidnam_base(:i1)//'_kin.res0'
else
i1=last_char(jidnam)
filename1=jidnam(:i1)//'_kin.res'
filename2=jidnam(:i1)//'_kin.res0'
endif
return
end

1.5. FORTRAN- C/C++ user subroutine inter-


face
Simufact.forming support user subroutine written in C/C++ together with subroutine in FORTRAN. This integration
will allow easy integration of already existing C/C++ code with minimal modification to Simufact.forming.

1.5.1. The interface


The Interface work in the following way: In Windows environment,

User creates a *.dll based on the C/C++ code and put the dll in the lib directory of the Simufact installation.

Through FORTRAN subroutine the above dll is called through a function. In the argument of the interface, user
transfers the various variables for calculation.

A Microsoft visual Studio project file will be provided for easy creation of the dll from the C/C++ code. However the
dll can be created by any C/C++ compiler. This tutorial is written for 64bit dll. For 32bit dll changes are required due
to handling of byte sizes for integers and real numbers.

For Linux architecture, user has to create dynamic library for linux with extension .so. With the provided cpp and
hearder files, make the library as:

56
13.2 User subroutines The interface

icpc -fPIC -c sfuserclib.cpp


icpc -shared -o libsfuserclib.so sfuserclib.o

The name of the library, libsfuserclib.so, in Linux and sfuserclib.dll in windows are important. The user can link mul-
tiple C/C++ files to create one library. This library should either be put in the lib directory of the Simufact installation
at C:\Program Files\simufact\forming\13.2\sfMarc\lib (for windows) or its path should be added
to LD_LIBRARY_PATH (in case of Linux) before submitting the job.

export LD_LIBRARY_PATH="/home/....../path_of_the_library":$LD_LIBRARY_PATH

In FORTRAN the interface is built as a function like

ret=sfcinterface(t,ni,nd,nc,iarray, darray, name)

where

ret: An integer value returned from the function. In the absence of the dll, this value will be -1. As C/C++ has an
option to return a value, this argument can be used as a flag to check the successful execution of the code.

t: An integer value as input. This value can be used to distinguish the different instances when the interface is called.
This value is used to determine which code block to execute in the dll. Through this features the same dll can be
used for various simulations and can be developed simultaneously in time with the added features without breaking
any earlier developed feature. The user just need to use a different t value.

ni, nd and nc: The variables corresponding to number of integers, double and characters respectively that will be
passed in the interface.

iarray, darray and name: Arrays containing integers, doubles and characters information respectively. Size of
these arrays are ni, nd and nc respectively.

The programing interface in the C/C++ side will be like

// sf_c++lib.cpp : Definiert die exportierten Funktionen fr die DLL-


Anwendung.
//

#include "sfuserclib.h"
#include <stdio.h>

/*----------------------------------------------------------------
This is the generic interface function for marc calling user c routines.
\param[in] type The type of function that has been called.
\param[in] nbInts The size of the integer array.
\param[in] nbDoubles The size of the double array.
\param[in] nbChar The size of the character array.
\param[in] ints The integer array.
\param[in] doubles The the double array.
\param[in] char The the character array.
------------------------------------------------------------------*/

int64_t sf_cInterface(int64_t * type, int64_t * nbInts, int64_t * nbDoubles,


int64_t * nbChars,
int64_t * ints, double *doubles, char * chars)
{

switch(*type)
{
case 101:
{
//Test case to print all the infromation of arrays passed from
fortran

57
13.2 User subroutines The interface

//The values will be printed in the jobname.log file


int i;
fprintf(stderr, "Calling default user c interface for function
code %d\n", *type);
fprintf(stderr, " integer (%d):\n", *nbInts);
for(i=0; i &lt; *nbInts; i++){
fprintf(stderr, "%d %d\n",i, ints[i]);
}

fprintf(stderr, " double (%d):\n", *nbDoubles);


for(int i=0; i &lt; *nbDoubles; i++){
fprintf(stderr, "%d %lf\n",i, doubles[i]);
}

fprintf(stderr, " chars (%d): '", *nbChars);


fprintf(stderr, "%s", chars);

fprintf(stderr, "'\n");
fprintf(stderr, " returning 101\n");
return 101;
}
break;

case 1: //Case 1
{
// Code related to case 1 comes here
// C/C++ code
//
return 1;
}
break;

case 2: //case 2
{
// Code related to case 2 comes here
// C/C++ code
//
return 2;
}
break;

default: // If type is none of the above


// Do nothing and return unique code, -100 in this example
fprintf(stderr, "Out of bound case, return -100\n");
return -100;
break;

}
}

Some silent features of the interface are:

The variables value changed in the C/C++ function will also be automatically realised in the FORTRAN side. This
can be used to pass complete Marc array through the interface. However the user should be careful not to change
the Marc specific array through the interface which may cause an error.

The array length can be changed in the C/C++ side if required. However care should be taken with the indexes as
in FORTRAN array index starts with 1 where as in C/C++ with 0.

58
13.2 User subroutines Example

1.5.2. Example
The motion example's subroutine is modified to control Maximum force and die velocity through the C/C++ interface.
To run this example, the user should either put the provided sfuserclib.dll or, created one and then replace in the lib
folder as explained earlier.

The user subroutine in FORTRAN calls the C/C++ interface with case flag 1

c--------------------------------------------------------------
c This routine demonstrate the control of motion of the die
c during the simulation. Control criteria can be entered
c through GUI which is then used in the subroutine
c
c The motion example routine is modified to get the maximum force
c and velocity from c-dll.
c--------------------------------------------------------------

subroutine ubginc(inc,incsub)

c--------------------------------------------------------------
c Subroutine to get value from c dll
c--------------------------------------------------------------

#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "sf_userdata.cmn" !User variable through gui
#include "machin.cmn" !iprtl
#include "cdominfo.cmn" !ddminfo nprocd

integer inc, incsub, icase, ni,nd,nc,ret,sfcinterface,iarray(1)


integer idummy
real*8 darray(2)
character*(10) cname

real*8 xforce,xvelocity
common/force_vel/xforce,xvelocity
if(inc.eq.0) then
c -- Initial initializing to low value
xforce=0.0
xvelocity=-1.0e19
c -- Do for only one domain
if((nprocd.eq.0).or.(iparent.eq.0)) then
cname='Motion'
ni=1 !no. of integer
nd=2 !no. of double
nc=6 !no. of character
iarray= (/ 0 /)
darray= (/ 0.0,0.0 /)
if(niuser.lt.1) then
write(iprtl,'(/,/7x,a)')
+ '*** Error ***: Missing case variable in gui.'
write(iprtl,'(7x,a,/,7x,a,/)')
+ 'Provide at least 1 integer user data as a case value',
+ 'Simulation halted'
call quit(13)

59
13.2 User subroutines Example

endif
c -- Get the case id from GUI
icase=iuserdata(1)
c -- Call the c routine with the case flag. Case flag will be used
c -- to seperate the different case call
ret=sfcinterface(icase,ni,nd,nc,iarray, darray, cname)

if(ret.eq.1 .or. ret.eq.2) then


xforce=darray(1) ! Force
xvelocity=darray(2) ! Velocity
write(iprtl,'(a,f8.2,a,f6.2,a)') 'Limiting force = ',
+ xforce/1000,' kN, velocity = ',xvelocity*1000,'mm/sec used.'
endif

if(ret.eq.-1.or.ret.eq.-100) then
if(ret.eq.-1) then
write(iprtl,'(a)') 'sfuserclib.dll does not exist'
elseif(ret.eq.-100) then
write(iprtl,'(a)') 'Unknown test case'
endif

write(iprtl,*)
+ 'Default: Max force=5000KN, velocity = 10mm/s assumed'
xforce=5000*1000
xvelocity=-15*0.001
endif

endif
endif

if(nprocd.gt.0) then
call domflag(idummy,xforce,0,1,0,1)
call domflag(idummy,xvelocity,0,1,0,1)
endif
return
end

c--------------------------------------------------------------
c Subroutine to define die velocity
c--------------------------------------------------------------
subroutine motion(x,f,v,time,dtime,nsurf,inc)

#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif

#include "spaceco.cmn" !contact body information, cbname, numdie_cn


#include "machin.cmn" !iprtl
#include "prepro.cmn" !kou
#include "sf_userdata.cmn" !User variable through gui
#include "cdominfo.cmn" !ddminfo nprocd
#include "dimen.cmn" !ncrd

c ** Start of generated type statements **


integer inc, nsurf

60
13.2 User subroutines Example

real*8 dtime, f, time, v, x


c ** End of generated type statements **
dimension x(*),v(*),f(*)

character*24 cbody,cbody0,fname
integer i,imvbody,i2switch,ilen1,ifunit
real*8 dummy1,zforce

real*8 xforce,xvelocity
common/force_vel/xforce,xvelocity

logical there

fname="motion.txt"

i2switch=0 !flag for die movement direction: Original(=0), or


reverse(=1)
imvbody=0 ! Body id of the die to monitor the movement

c -- The if command is executed once. In case of ddm job only parent


domain
c -- execute it.
if((nprocd.eq.0).or.(iparent.eq.0)) then
inquire( file=trim(fname), exist=there ) !check if file is
there.
if(.not. there) then
if(nsurf.eq.1) then
i2switch=0
c -- Die name defination of cbody is important.
c -- should be same as defined in gui
cbody='Top-die'
ilen1=index(cbody,' ') - 1
do i=1,numdie_cn
cbody0=cbname(i)
if(cbody0(1:ilen1).eq.cbody(1:ilen1))then
imvbody=i !extracts the body id and saces it
exit !skip remaining do loop
endif
enddo

ifunit=3000
call openfile(ifunit,trim(fname),1,2)
write(ifunit,*) imvbody,i2switch !write the file
call closefile(ifunit,trim(fname),0,2)
endif

else
ifunit=3001
call openfile(ifunit,trim(fname),1,2)
read(ifunit,*) imvbody,i2switch !read from file,
call closefile(ifunit,trim(fname),0,2)
endif

endif

c -- In case of ddm job, share the read value of imvbody & i2switch
c -- Since these balues will be >0 in parent domain and 0 in other domain
c -- Dom flag has been used to share the maximum value of imvbody &

61
13.2 User subroutines Example

c -- i2switch in all the domains


if(nprocd.gt.0) then
call domflag(i2switch,dummy1,1,0,1,0)
call domflag(imvbody,dummy1,1,0,1,0)
endif

c -- Skip alll bodies which should not move


if(nsurf.ne.imvbody)goto 999

c -- Get the absolute value of z-force on die depending upon 2d & 3d


c -- simulation
if(ncrd.eq.2) then !2D case
zforce=abs(f(1))
else !3d case
zforce=abs(f(3))
endif

c -- In case of original die direction, if force exceed maximum force


c -- then reverse the die direction
if((i2switch.eq.0).and.(zforce.gt.xforce))then
i2switch=1
c -- Done by only parent domain in case of ddm job.
if((nprocd.eq.0).or.(iparent.eq.0)) then
ifunit=3000
c -- Replace the original file with new interval
call openfile(ifunit,trim(fname),1,2)
write(ifunit,*) imvbody,i2switch
call closefile(ifunit,trim(fname),0,2)
endif

c -- Share the new value of i2switch in all the domain

if(nprocd.gt.0) then
call domflag(i2switch,dummy1,1,0,1,0)
endif
endif

c -- If maximum force reached, assign the new die velocity to the die
c -- Velocity sign is important wrt simulation direction
if(ncrd.eq.2) then !2D case
v(1)=xvelocity
if(i2switch.eq.1) v(1) = -v(1)
else !3D case
v(3)=xvelocity
if(i2switch.eq.1) v(3) = -v(3)
endif

999 return
1001 format(13x,'*** error ',
* 'Number of user defined real variables nruser:',i3,'
* is less then needed: ',i3,/13x,'check input deck!')
1002 format(13x,'max force of ',f12.6,' is reached in body:'a,
* ' force is:',f12.6)
1003 format(13x,'Calculated velocity of Body ',a,' is:',f12.6)

end

The example C/C++ interface used to determine the velocity:

62
13.2 User subroutines Example

// sf_c++lib.cpp : Definiert die exportierten Funktionen fr die DLL-


Anwendung.
//

#include "sfuserclib.h"
#include &lt;stdio.h&gt;

/**
This is the generic interface function for marc calling user c routines.
\param[in] type The type of function that has been called.
\param[in] nbInts The size of the integer array.
\param[in] nbDoubles The size of the double array.
\param[in] nbChar The size of the character array.
\param[in] ints The integer array.
\param[in] doubles The the double array.
\param[in] char The the character array.
*/

int64_t sf_cInterface(int64_t * type, int64_t * nbInts, int64_t * nbDoubles,


int64_t * nbChars,
int64_t * ints, double *doubles, char * chars)
{
switch(*type)
{
case 101:
{
//Test case to print all the infromation of arrays passed from
fortran
//The values will be printed in the job *.log file
int i;
fprintf(stderr, "Calling default user c interface for function
code %d\n", *type);
fprintf(stderr, " integer (%d):\n", *nbInts);
for(i=0; i &lt; *nbInts; i++){
fprintf(stderr, "%d %d\n",i, ints[i]);
}

fprintf(stderr, " double (%d):\n", *nbDoubles);


for(int i=0; i &lt; *nbDoubles; i++){
fprintf(stderr, "%d %lf\n",i, doubles[i]);

fprintf(stderr, " chars (%d): '", *nbChars);


fprintf(stderr, "%s", chars);

fprintf(stderr, "'\n");
fprintf(stderr, " returning 101\n");
return 101;
}
break;

case 1: //motion example 1


{
//max force of 6000KN and velocity of 20 mm/sec converted to
SI Units

doubles[0]=6000*1000;
doubles[1]=-20*0.001;

63
13.2 User subroutines Example

fprintf(stderr, "Case 1 with force and velocity %lf %lf


\n",doubles[0],doubles[1]);
return 1;
}
break;

case 2: //motion example 2


{
//max force of 4000KN and velocity of 10 mm/sec
doubles[0]=4000*1000;
doubles[1]=-10*0.001;
fprintf(stderr, "Case 2 with force and velocity %lf %lf
\n",doubles[0],doubles[1]);
return 2;
}
break;

default: // If type is none of the above


// Do nothing and return unique code, -100 in this example
fprintf(stderr, "Out of bound case, return -100\n");
return -100;
break;
}
}

64
Scientific
13.2

2 User defined kinematic


13.2 User defined kinematic User Kinematics

Educational Objectives

Uses of user subroutine in Simufact.forming for custom process kinematic

Prerequisites

FORTRAN programing knowledge, general programing knowledge

2.1. User Kinematics


User kinematics has been developed to model realistic forming steps like automatic reversal of rolls and workpiece
in the rolling process. The goal is to automatize the simulation with minimal user input, restricted to input variables,
initial geometries and plan of the rolling passes, to get the required process report from the simulation.

The idea is to extend the current graphical user interface so that the user do not have to make the input in a text file or
in a program source code. A developed template can be used by the user accurately as an integral part of the software.
The implementation is accomplished by developing the interface through an XML file.

User inputs from the graphical interface will be written to a file (.kin), which is then read by the solver and through
the user-subroutine necessary kinematics are implemented in the simulation. After calculation of the kinematics data,
definition of contacts etc., solver calls a writing subroutine to write another file (.kin.hist). Syntax of this file is identical
to the "History Definition" from the Marc Inputs (see Volume C). Solver reads the history data from the .kin.hist file
instead the original history data written in the input definition of the .dat file. The user subroutine is implemented
in FORTRAN90.

In addition to the previously input data for the process sequence, results from the previous steps are used to create
input data for the next step during the calibration and idle time between the passes. That is, the input variables for the
next pass are calculated during the simulation and for each load step, a new .kin.hist file is written.

The figure below illustrates the relationship between the kinematics and solver. The relevant custom user kinematics
and modules are highlighted in color.

66
13.2 User defined kinematic Graphical interface

Figure 2.1. User kinematic: implementation

This document will step by step explain the process to create and implement the user kinematic for process automati-
zation by incorporating already implemented functionalities.

2.1.1. Graphical interface


The graphical user interface in Simufact.forming solver is presented in this section. For more information about various
statement in the XML control file are compiled in the section "Tags and attributes of the XML control file".

To understand the feature, first open the standard model for rolling. This is available in the Simufact.demos:

67
13.2 User defined kinematic Graphical interface

Figure 2.2. Standard rolling model in Simufact.demos

In the Inventory window, new kinematics can be added by right mouse by Press> Kinematics...

Figure 2.3. Adding new kinematic in inventory window.

Dialog box for selecting the kinematics:

68
13.2 User defined kinematic Graphical interface

Figure 2.4. Dialog box for kinematic selection


Simufact.forming provides a default user defined kinematic. On selection, following dialog box is opened.

Figure 2.5. Default user-kinematics provided in the Simufact.forming


To understand the structure of this dialog box and its attributes, a xml file named "user defined.xml" is present in the in-
stallation path of Simufact.forming at C:\Program Files\simufact\forming\13.2\sfForming\Mas-
terLibrary\Kinematics. This file must be opened with a text editor. The file can be opened and viewed with
any editor (i.e. Notepad). However it is recommended to use an editor which supports syntax highlighting for XML,
which simplifies to work on the file.

The file "user defined.xml" consist of various tags. With the tags data can be classified and ordered. A tag starts with
"< >" and is closed by "< />". The tags generally comes in pair, for example:

69
13.2 User defined kinematic Graphical interface

<dialog name="userdefined"> [...] </dialog>

The complete "dialog" tag is described here with [...] between both the "dialog" tag. Attributes are generally assigned
to the beginning tag, as in this case the "name" attribute is assigned. Attributes can be changed to assigned other
properties.

From the above example the value of the attribute "name" is changed from "userdefined" to "My Name" as

<dialog name="My Name"> [...] </dialog>

Save the modified "user defined.xml" and then re-open the kinematics as explained above, Press> Kinematics..., so
now the following dialog opens:

Figure 2.6. "name" attribute in the kinematic GUI

The tags can also be used to custom input and process the data from the user. The complete structure of the file (without
the input field shown by "[...]") is structured as follows:

<?xml version="1.0" encoding="UTF-8"?>


<dialog name="My Name">
<kinematic name="USERKIN1" />
<image filename="user_defined.png" />
<allPass>
[Information related to all passes]
</allPass>
<perPass>
[Information related to individual pass]
</perPass>
</dialog>

First line is the header (header data) and is always required. The "dialog" tag has already been explained above. The
"kinematic" tag specifies the name of the file to be created, USERKIN1 in this case, and should not be changed unless
there is a compelling reason, such as use of multiple kinematics in the the model. The "image" tag specifies the image to
be displayed in the dialog box. The image should be in the same directory where the "user defined.xml" is present. The
"allPass" tag defines the kinematic information to be used in each pass (in every Heat), together with the information
of the available tools used in the model. The "perPass" tag contains the information that changes from pass to pass,
for example the preparation of the tools or velocity.

70
13.2 User defined kinematic Graphical interface

Inside the "allPass" tag, now three fields are created. One each for pusher, upper roll and lower roll. Therefore the
existing tags and attributes has to be accordingly adjusted. For each pass, also the roll speed and reduction of thickness
between the roll can be specified. The tag-structure creates the information tree which can be visualize as:

dialog

allPass perPass

upper roll roll speed


lower roll
decrease in roll height

manipulator

Figure 2.7. Tree-structure highlighting assignment


of various informations in "user defined.xml"

The final XML file after modification of the individual tags looks like this:

Figure 2.8. Screen-shot of the XML file in a text editor with syntax highlighting

The above modified XML data when opened through "user defined" kinematics in Simufact.forming gives the fol-
lowing dialog:

71
13.2 User defined kinematic Tags and attributes

Figure 2.9. Dialog box after modifying "user defined" xml file
We just generated an individual template that you can use to enter input data for simulation. The exact meaning and
explanation of the tags and their attributes are presented in the following sections.

2.1.2. Tags and attributes


Following are the range of values and input capabilities of the the individual attributes:

1. name

The name displayed on top of the dialog box.

2. showOnly

If this attribute is enabled, the field will be grayed out with specific value. The user cannot change the value.

3. isVisible

By default the isVisible attribute is enabled by default even it is missing. If it is disabled (isVisible="false"), the
value will be hidden in the dialog but is still written into the .kin data file at its defined kinPos position.

In the case that the hidden value is inside of the pass table the corresponding column will be hidden too.

4. dimensionIndex

Dimension values are entered so that the corresponding dimension of the value is determined .

5. unitIndex

Determines which unit system is to be used.

6. valueType

Determines the type of data used.

7. type

72
13.2 User defined kinematic Tags and attributes

Determines the type of field to be generated.

8. values

Pre-set with the starting value for the element when the dialog box is called.

9. kinPos

Determines the position in which the read data is to be written in the .kin data file. This is an important variable
that is being used both in xml and user subroutine.

The syntax presented here should always be maintained within a tag. In addition, each value must be properly assigned.
The values specified must be marked with quotation marks at the beginning and end of the value. This means that if
the attribute dimension index should be assigned for pressure, the the syntax should be as follows:

dimensionIndex="13"

Comments inside the code can be given by the following tag "<!--" and "-->":

<!-- Comment can be put inside this tag -->

Values assigned to the "name" attribute and its importance


string Display name for the Field string Display name for the Field

Values assigned to the "dimensionIndex" attribute and its importance


-1 Dimensionless 0 Acceleration
1 Angle 2 Electric current
3 Energy 4 Force
5 Length 6 Mass
7 Speed 8 Temperature
9 Time 10 Volume
11 Density 12 Power
13 Pressure 14 Thermal conductivity
15 Thermal expansion 16 absorption (radiation-) dose
17 Heat capacity 18 Specific heat capacity
19 Force per length 20 Voltage
21 Surface tension 22 Temperature Difference
23 Heat transfer coefficient 24 Strain rate
25 Latent heat 26 Percent
27 Frequency 28 Angular velocity
29 Thermal energy 30 Moment of inertia
31 Heat flux 32 Thermal flux
33 Torque 34 Grain size
35 Unit for data set 36 Torsional stiffness
37 Hardness

Values assigned to the "unitIndex" attribute and its importance


-1 Without unit 0 SI-unit
1 SI-mm-unit 2 Imperial unit
3 Anglo-American unit 4 Custom unit

73
13.2 User defined kinematic Tags and attributes

Values assigned to the "type" attribute and its importance


unit Values with unit and dimension
spinbox Values selection (double or integer)
seperator hyphen (No Functionality)
comboBox Drop-Down list item with tools
checkBox Yes/No Box
comboList Drop-Down list with the user created list
edit Test input field

Values assigned to the "valueType" attribute and its importance


Tool Tools provided in combo box
string text input
int integer input
double floating point number input

Values assigned to the "values" attribute and its importance


moved Moving tool
fixed Fixed tool
true/false 1=true and 0=false will be written in .kin file
List From n1:: value1; n2::value2, when value2 is selected, n2 is written in .kin file
Value Value such as "0" - is loaded at the start of the dialogue in the field

Values assigned to the "kinPos" attribute and its importance


i,j,k i-th data block, j-th value, k-th tool is written in the .kin file

With the various attributes available, it is apparent that not all of them are useful for a particular case. For example,
it is not sensible to connect a tool with a dimension and unit. Such input error will be caught by the program. For
two reasons it is advised to work consistently. First a nonsense entry can confuse the future user and second correct
assignment can remove compatibility issue of the interface with the future versions.

After inserting the explanatory comment, the example look like:

Figure 2.10. Screen-shot of modified XML file with comments

74
13.2 User defined kinematic The .kin Data

2.1.3. The .kin Data


After entering the input information through the XML dialog box, Simufact.forming creates a .kin file. This data file
contains all the input information. The position of the information in the file is through the attribute "kinPos" which
has been already presented. Users with no prior experience with creating a .dat file and unfamiliar to the concept of
data blocks, are recommend to check the handbook from Marc manual, "Volume C", where many important topics
are discussed.

The concept is that there are data blocks that contains a certain number of values. It is not mandatory that all data
blocks are always written. It may be possible that a file is complete in three lines with the first line of Block-1, the
second Block-2 and third block-5. Aim of this section is to explain the complete structure of .kin file so that user can
examine if all the input data has been read and transferred by Simufact.forming correctly.

The following tables are provided with four columns. The first column is specified with the position (when using the
fixed-format), the second contains the relative position (the first value, the second value ...), the third column contains
the data type (I = integer, A = characters, E = floating point or real numbers). Last column explains the data.

1. Datablock
Position fix Position free Type Importance
1-10 1. A USERKIN1 (number at the end can vary)

2. Datablock
Position fix Position free Type Importance
1-5 1. I Starting increment of the kinematic, default=0 (not supported)
6-10 2. I Kinematic type, default=1
11-15 3. I Error message flag, default=0
16-20 4. I Number of moving and force controlled tool
21-25 5. I Number of stationary object
26-30 6. I Maximum number of integers from the user
31-35 7. I Maximum number of floating point numbers from the user

The third Data block defines the moving tools, power-driven tools at the end of the list. This block is often repeated,
as in the second block at position 4.

3. Datablock
Position fix Position free Type Importance
1-24 1. A Name of the moving tool in .Dat file

The fourth Data block defines the stationary tools. This block is often repeated, as in the second block at position 5.

4. Datablock
Position fix Position free Type Importance
1-24 1. A Name of the stationary tool in .Dat file

5. Datablock
Position fix Position free Type Importance
1-5 1. I Total number of Heat
6-10 2. I Maximum number of pass in one Heat
11-20 3. E Global floating point variable, default=0.0
21-30 4. E Maximum power of the press, default=0.0 (->inactive)

The Blocks 6 and 7 are repeated for every Heat.

75
13.2 User defined kinematic The .kin Data

6. Datablock
Position fix Position free Type Importance
1-5 1. I Heat number
6-10 2. I Maximum number of pass in the Heat, default=1

7. Datablock
Position fix Position free Type Importance
1-5 1. I Heat number
6-15 2. E 1. floating point variable for the actual Heat, default=0.0
16-25 3. E 2. floating point variable for the actual Heat, default=0.0
26-35 4. E 3. floating point variable for the actual Heat, default=0.0
36-45 5. E 4. floating point variable for the actual Heat, default=0.0
46-55 6. E 5. floating point variable for the actual Heat, default=0.0

The blocks 8 to 11 are repeated for every pass in the Heat.

8. Datablock
Position fix Position free Type Importance
1-5 1. I Heat number
6-10 2. I Pass number in the Heat
11-15 3. I 1. Integer variable for the actual pass, default=0
16-20 4. I 2. Integer variable for the actual pass, default=0
21-25 5. I 3. Integer variable for the actual pass, default=0
26-30 6. I 4. Integer variable for the actual pass, default=0
31-35 7. I 5. Integer variable for the actual pass, default=0
36-40 8. I 6. Integer variable for the actual pass, default=0
41-45 9. I 7. Integer variable for the actual pass, default=0
46-50 10. I 8. Integer variable for the actual pass, default=0
51-55 11. I 9. Integer variable for the actual pass, default=0
56-60 12. I 10. Integer variable for the actual pass, default=0

9. Datablock
Position fix Position free Type Importance
1-5 1. I Heat number
6-10 2. I Pass Number in the Heat
11-20 3. E 1. floating point variable for the actual pass, default=0.0
21-30 4. E 2. floating point variable for the actual pass, default=0.0
31-40 5. E 3. floating point variable for the actual pass, default=0.0
41-50 6. E 4. floating point variable for the actual pass, default=0.0
51-60 7. E 5. floating point variable for the actual pass, default=0.0
61-70 8. E 6. floating point variable for the actual pass, default=0.0
71-80 9. E 7. floating point variable for the actual pass, default=0.0
81-90 10. E 8. floating point variable for the actual pass, default=0.0
91-100 11. E 9. floating point variable for the actual pass, default=0.0
101-110 12. E 10. floating point variable for the actual pass, default=0.0

76
13.2 User defined kinematic Example of the .kin data

The Blocks 10 and 11 are also repeated for each movable tools like second block, position 4.
10. Datablock
Position fix Position free Type Importance
1-10 1. E x-stroke
11-20 3. E y-stroke
21-30 4. E z-stroke
31-40 5. E x-velocity
41-50 6. E y-velocity
51-60 7. E z-velocity

11. Datenblock
Position fix Position free Type Description
1-10 1. E Rotation direction
11-20 3. E Rotational velocity
21-30 4. E x-direction
31-40 5. E y-direction
41-50 6. E z-direction

2.1.4. Example of the .kin data


The structures of the above mentioned table and lists are illustrated in the following example. We consider a rolling
process consisting of two passes and the relevant data are entered in the dialog box interface:

Figure 2.11. Dialog box with input values


After you enter the values, the dialog box can be closed. The newly created object is then assigned as usual in the
process tree. (If you are not sure how these steps are done, then it is strongly recommended to read the Basic Manual).
You should see the process tree look like this:

77
13.2 User defined kinematic Example of the .kin data

Figure 2.12. Process-tree after adding and renaming the kinematic press
The .kin file is created at the beginning of the initialisation process. To just create the .kin file, briefly start the simu-
lation and cancel the simulation when program moves to "start analysis" (see the status bar of the program at bottom).
The .kin file is created in the "_Run_" directory of the simulation. To access it simply press the key combination
"Ctrl+E" in Simufact.forming window. A explorer window opens with the "_Run_" directory. .kin file is inside this
directory. It can be open with any text editor.

As a reminder, here are values of the kinPos attribute used in the XML file:

Upper roll:

kinPos="3;1"

Lower roll:

kinPos="3;2"

Pusher:

kinPos="3;3"

Thickness reduction:

78
13.2 User defined kinematic Example of the .kin data

kinPos="9;8"

Roll speed:

kinPos="10;3;1"

The generated .kin file should look like this: (Bold numbers are the entry from the user through the dialog windows)

USERKIN1
$ Start increment, kinematic type, debug level, number of moving tools,
number of fixed tools, number of interger values, number of real values
0,1,0,3,0,10,10,
$ Moving body 1
Upperroll
$ Moving body 2
Lowerroll
$ Moving body 3
Pusher
$ Number of totals superpasses,max number of passes, initial height of dies,
max force for hydr. press
1,2,0.00000E+0,0.00000E+0,
$ Superpass number, number of passes in superpass
1,2,
$ Superpass number, real v1,real v2,real v3,real v4,real v5
1,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,
$ #Superpass,#pass,# of rolling passes,Outputfrequency for moving
pass,Outputfrequency for rolling pass,Outputfrequency for back rolling
pass,user int define 1,user int define 2,user int define 3,user int define
4,user int define 5,user int define 6
1,1,0,0,0,0,0,0,0,0,0,0,
$ #Superpass,#pass,# of rolling passes,factor for step size for moving pass
mani,factor for step size for rolling pass,factor for step size for rolling
back pass,Max. rotation step,user real define 1,user real define 2,user real
define 3,user real define 4,user real define 5
1,1,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E
+0,1.00000E-2,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,
$ Real parameter for Moving Body 1: translation:
xstroke,ystroke,zstroke,xvel,yvel,zvel
0.00000E+0,0.00000E+0,3.35103E+1,0.00000E+0,0.00000E+0,0.00000E+0,
$ rotation: rotdist,rotvel,xaxis,yaxis,zaxis
0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,
$ Real parameter for Moving Body 2: translation:
xstroke,ystroke,zstroke,xvel,yvel,zvel
0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,
$ rotation: rotdist,rotvel,xaxis,yaxis,zaxis
0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,
$ Real parameter for Moving Body 3: translation:
xstroke,ystroke,zstroke,xvel,yvel,zvel
0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,
$ rotation: rotdist,rotvel,xaxis,yaxis,zaxis
0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,
$ #Superpass,#pass,# of rolling passes,Outputfrequency for moving
pass,Outputfrequency for rolling pass,Outputfrequency for back rolling
pass,user int define 1,user int define 2,user int define 3,user int define
4,user int define 5,user int define 6
1,2,0,0,0,0,0,0,0,0,0,0,
$ #Superpass,#pass,# of rolling passes,factor for step size for moving pass
mani,factor for step size for rolling pass,factor for step size for rolling

79
13.2 User defined kinematic Example of the .kin data

back pass,Max. rotation step,user real define 1,user real define 2,user real
define 3,user real define 4,user real define 5
1,2,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E
+0,1.29999E-2,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,
$ Real parameter for Moving Body 1: translation:
xstroke,ystroke,zstroke,xvel,yvel,zvel
0.00000E+0,0.00000E+0,3.35103E+1,0.00000E+0,0.00000E+0,0.00000E+0,
$ rotation: rotdist,rotvel,xaxis,yaxis,zaxis
0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,
$ Real parameter for Moving Body 2: translation:
xstroke,ystroke,zstroke,xvel,yvel,zvel
0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,
$ rotation: rotdist,rotvel,xaxis,yaxis,zaxis
0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,
$ Real parameter for Moving Body 3: translation:
xstroke,ystroke,zstroke,xvel,yvel,zvel
0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,
$ rotation: rotdist,rotvel,xaxis,yaxis,zaxis
0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,0.00000E+0,

For better understanding of the .kin file, line-by line of the file will be explained. All the lines starting with a "$" are
comment lines and are not read by the system. Also to be noted that the lines are not terminated by a line feed or line
break. As can be seen from the above output, the numbering does not appear in all the line, for example from above
the first six printed lines are counted with only 5 lines.

It is also noted that the output value from the .kin file does not exactly match with the input value. There are two
reasons for it.

Rounding error : ex. 1.29999E-2 instead of 1.30000E-2

Unit conversion: The solver works in unit of meter [m] where as the input was in millimeter [mm]. Therefore 13mm
was converted to 1.30000E-2 m in the .kin data(implicit with [m]).

The following table shows the mapping (values that are assigned by the user are in bold). kinPos attribute are shown
only for the first value of the data block.

Allocation table
Line Data block kinPos Comment
1 1 1;1 do not change
2 comment
3 2 2;1 do not change
4 comment
5 3 3;1 moving tool 1
6 comment
7 3 3;2 moving tool 2
8 comment
9 3 3;3 moving tool 3
10 comment
11 5 5;1
12 comment
13 6 6;1 6;2 is for number of pass
14 comment

80
13.2 User defined kinematic Solver and subroutine

15 7 7;1 7;2 - 7;6 can be used freely (pass independent values)


16 comment
17 8 8;1 is repeated for every pass in a Heat
18 comment
19 9 9;1 9;8 corresponds to "thickness reduction" in Pass 1
20 comment
21 10 10;1;1 10;3;1 corresponds to "roll speed" in Pass 1
22 comment
23 11 11;1;1
24 comment
25 10 10;1;2
26 comment
27 11 11;1;2
28 comment
29 10 10;1;3
30 comment
31 11 11;1;3
32 From here repeat the blocks 8-11 for ever additional pass, i.e. all the entries from line 16

2.1.5. Solver and subroutine


2.1.5.1. Concept of sfukin-subroutine
The previous chapter explained the method to enter the user data and store in the file. The stored input data in the .kin
data file is to be used by the sfukin subroutine. First, we review the structure of the job input file (*.dat).

All information regarding the model are presented in the .dat file. This file can be roughly divided into three sections:

1. Parameter section consisting of general information and about the program version and release details.

2. Model definition: consist information about geometries of all the networks, materials and boundaries conditions.
These two sections will not be discussed as they are not relevant to the subroutine concept. These two sections as
well as history definitions are described in Marc manual "Volume C" in details.

3. History definition.

The history information is important for the user. All bodies, boundary conditions etc. information are to be used by
the model for next step simulation. Networks and constrain created in the previous load cases has to be considered.
However, addition of new objects or bodies in the "history definition" is not possible. This offers two main advantages:

1. when the value of load cases is not known, all the load cases can be calculated "on-the-fly".

2. load case data is always written after the calculation steps so that when writing a new load case data the information
from previous increment is considered.

81
13.2 User defined kinematic Solver and subroutine

.dat Data

Parameters Section

.kin data

Model Definition sfukin-subroutine


(Tools, Networks, Materials, Tabels)

create

replaces
History Definition .kin.Hist data
(Load cases)

Figure 2.13. Concept of sfukin subroutine to define new load case

2.1.5.2. The _kin.hist data


The _kin.hist data can be read similarly as the .kin data. The corresponding data blocks and values are taken from Marc
Manual "Volume C". Not all the maps (as each keywords to be called has to be defined in the data block ) defined in
"Volume C" are defined and activated in the sfukin-subroutine. The essential maps are presented here

Contact Table: The contact table serves two purposes. First it determines which body is in contact with each other
and what properties this contact have. Second all the bodies shown in the post-processing must be defined inside
the Contact table.

Motion Change: The "Motion Change" map is used for motion, change of motion (translational and rotation) and
its initiation. It is important to note that a translation or rotation motion will continues as long as until one changes.
That is, if in one case, the load "Motion Change" map is used for a roller to specify a speed, then the "Motion
Change" map in the following load is to be written (with zero entries) to stop the movement. Else the initiated roller
will run as long until it is terminated.

Release: The "Release" map can be used to release all the bodies in contact. This map should be used together with
the "Move" map, because a contact removed in an increment will be produced again by the contact search algorithm
in the next increment, which is not desirable.

Approach: The "Approach" map is used to bring the tools in contact with the workpiece. For this to work correctly,
a velocity as well as a search direction must be provided. Therefore, the "approach" map is always used with the
"Motion Change" map.

Move: The "Move" map allows the rigid body motions (translational and rotational). The advantage over the "Mo-
tion Change" map is the fewer required increments to execute it, resulting in relatively short time. This map is
mainly used for positioning of a tool at a defined position.

With these five maps, many kinematics and load cases can be designed. The decisive factor is the combination of
these maps and their configuration, as each map parameter is to be assigned. Before the parameters and variables of
the subroutine sfukin are discussed in following chapters, first we described the method to implement the subroutine
in Simufact.forming.

82
13.2 User defined kinematic Solver and subroutine

2.1.5.3. Inside sfukin.f routine


After knowing the process of making the necessary input and linking of solver or external compiler with the
Simufact.forming, the actual subroutine should be programmed. The subroutine is to be written in FORTRAN. There-
fore some general notes on subroutine programming are given next. In the next chapter, arrays and variables are ex-
plained together with the information exchange between the subroutine and the solver.

2.1.5.3.1. General Information


This compiling and linking of the solver is done with the Intel FORTRAN Compiler, version 12.0.4 or higher. The
programming of the subroutine should be in a fixed format. To implement a functionality in the code in the most
efficient way, the following points should be considered.

1. Concept buildup

Before the actual implementation of a function, a flowchart of the process should be built. This point is important
especially for large system processes. Time invested at the initial planning stage saves time later in the testing phase.

2. Minimum working example

A simple working subroutine should be created first to eliminate errors that may arise due to complex model
structure. A common source of error, which is already discussed in the creation of .kin file, is inconsistency in the
use of measuring units. Therefore the units expected by the solver in the chapter "arrays and variables" should be
kept in mind.

3. Documentation

It is recommended to insert meaningful and extensive comments in the code. This will ensure that the code is
maintainable and is understood by other users. This is especially important (also for the programmer) if the code
is to be used or/and further developed over a long period of time.

4. Testing

After the successful implementation of the concept for a minimal working example, the subroutine should be tested.
This should be tested for many cases as possible. Possible irregularities must be noted and documented so that at
later stage when one changes the parameters and comes across the errors, then the errors can be correctly diagnosed.

5. Model requirements and limitations

Often it is not possible or it requires lot of efforts to handle a difficult emerging problem. For a practical use of the
created subroutine model requirements and limitations must be defined. For example, before the simulation starts,
location of the work-piece and rotation direction of the axis has to be defined.

2.1.5.3.2. Naming convention of variables


Variables names in the subroutine are follow with a specific naming protocols.

All variables and arrays starting with "x" are of type Real*8 and should be used for real numbers.

All variables and arrays starting with "i" are of type Integer and should be used for integer numbers.

All variables and arrays starting with "c" are of type Character and should be used to store text information.

Local variables and arrays should be clearly marked, for example with "uk" after the first character.

So for example to initialize a counter, first character to be used is "i" (integer) followed by "uk" (local variable) and
subsequently with the name of the process to make the counter recognisable. Compliance with these rules and the
explicit definition of all variables (an implicit type definition is strongly discouraged), errors and conflicts can be
avoided. Another advantage is the quick identification of variables and arrays types.

83
13.2 User defined kinematic Solver and subroutine

2.1.5.3.3. Switches, counters and parameters


To program the load cases three elements are required:

Switches

A switch can be set to "1" (= active) or "0" (= inactive). For example, a Move-load case are set to be written, first the
corresponding switch must be set to "1" (in this case i2write (8) = 1). In the routine that calls the subroutine sfukin,
the set switches are evaluated. Before the call sfukin of the switches are set to "0" so that no cards are written by
default. This not apply to the switch always needed, the load case the title, the contact table and the Motion Change .
Write Should not these cards are written, they must be explicitly disabled.

Counters

As the sfukin subroutine is called in every increment (also for the zero increment) , counters are important to keep
track of the operations. For example, a counter (iuk_count) can be used for loading condition to be activated only
after the third iteration of the routine. The implementation can be like this: (lines beginning with C are comment
lines):

C Check if the increment has reached


if(iuk_count.eq.3)then
C Write the loading condition
xcontrols(44)=1.0d0
elseif(iuk_count.ne.3)then
C Increase counter by one
iuk_count=iuk_count+1
else
call quit(13)
endif

Several things should be clear in the above example . First the counter iuk_count should be initialized. This occurs
generally in the 0-increment (the variable iflag = 0 => 0-increment). Also in the else statement a function "call quit
(13)" is called. With this the program quit with an error message. Generally, it is useful to consider that a situation
may arise when none of the cases is satisfied. Therefore even for the program in cases where the possibility of error
is minimum, it is recommended that the "else" statement is always used to call a "quit" function.

Parameter

Parameters are needed to specify the boundary conditions. For example to implement a moving boundary condition,
one has to specify which body has to be moved, with or without symmetry, translation, rotation and center of
rotation. An examples is a workpiece with symmetry rotating counterclockwise around the z-axis as a center of
rotation and translated by 10mm along the X-axis can be implemented in the above example as:

C Check if the increment has reached


if(iuk_count.eq.3)then
C Write the loading condition
xcontrols(44)=1.0d0
C One body to be moved
nbd2mv = 1
C Parametering the move of the loading body
C Workpiece body number is "1"
xdefbd_move(1,1)=1.0d0
C Symmetry while moving the body
xdefbd_move(2,1)=1.0d0
C 10mm=0.01m translation in the x-axis
xdefbd_move(3,1)=0.01d0
C Rotation around z-axis
C -90=>clockwise rotation
C +90=>anti-clockwise rotation
xdefbd_move(8,1)=90.0d0

84
13.2 User defined kinematic Solver and subroutine

elseif(iuk_count.ne.3)then
C Increase counter by one
iuk_count=iuk_count+1
else
call quit(13)
endif

For better code readability, it is important to mention the comments and proper units even in small snippets of the
code.

2.1.5.4. Arrays and variables


2.1.5.4.1. Array: xcontrols
The xcontrols array stores various settings and information for the control functions. The details are explained below

xcontrols(9)
Dimension: 9
Data type: real*8
Index I/O Importance/Comment
1 I minimum element length in x-direction divided by 3 (can be use as control parameter)
2 I minimum element length in y-direction divided by 3 (can be use as control parameter)
3 I minimum element length in z-direction divided by 3 (can be use as control parameter)
4 I maximum Rotation per Increment
5 O maximum time for the next step
6 O "control"-Parameter (see volC, control(Histroy) Datablock 3, value 1)
7 O "control"-Parameter (see volC, control(Histroy) Datablock 4, value 1)
8 O Factor for re-meshing, 1.0d0= maintain element; <1.0d0= refine; >1.0d0= coarsen
9 O Process progress [%]

2.1.5.4.2. Array: icontrols


The icontrols integer array stores configuration for various settings. All the values are initialized 0 by default.

icontrols(5)
Dimension: 5
Data type: integer
Index I/O Importance/Comment
1 O Increment number for the next step
2 O "control"-Parameter (see volC, control(Histroy) Datablock 2, value 4)
3 O "approach"-Parameter
4 O Write process progress? 0=No : 1=Yes
5 O "load case"-Parameter (Number of active boundary conditions)
6 O Process report parameter, 0=No action, 1=write current increment in post.rep

2.1.5.4.3. Array: i2write


The i2write switch array is used to enable or disable the loading map in the _kin.hist file. By default, 1, 3 and 4 are
initialized to 1.

i2write(10)

85
13.2 User defined kinematic Solver and subroutine

Dimension: 10
Data type: integer
Index I/O Importance/Comment
1 O write "title"? 0=No : 1=Yes
2 O write "load case"? 0=No : 1=Yes
3 O write "contact table"? 0=No : 1=Yes
4 O write "motion change"? 0=No 1=Yes
5 O write "release"? 0=No : 1=Yes
6 O write "approach"? 0=No : 1=Yes
7 O write "gravity"? 0=No : 1=Yes
8 O write "move"? 0=No : 1=Yes
9 O Do Remeshing? 0=No : 1=Yes
10 O write stop criteria? 0=No : 1=Yes

2.1.5.4.4. Array: xbd_minmax


This array contains information about the maximum and minimum co-ordinates of the body i in space. By definition,
the first body is the workpiece, followed by the tools (initially moving tools, then fixed) and finally the symmetries.
The values in this array should not be overwritten. It can be used for the control purpose.
xbd_minmax(6,workpiece+ number. of tools (moving and fixed), Number of symmetries)
Dimension: 6*Total number of bodies
Data type: real*8
Index I/O Importance/Comment
1,i I min. x-coordinate of the body i
2,i I max. x-coordinate of the body i
3,i I min. y-coordinate of the body i
4,i I max. y-coordinate of the body i
5,i I min. z-coordinate of the body i
6,i I max. z-coordinate of the body i

2.1.5.4.5. Array: xbd_minmax_atstart


The xbd_minmax_atstart array contains the same entries as the xbd_minmax array but with the initial positions of all
the bodies instead of the current positions.

2.1.5.4.6. Array: xbdcntrls


The xbdcntrls array defines the contact and contact conditions as well as some additional properties related to the
individual bodies.
xcontrols(100,Anzahl d. Werkzeuge(bewegt und starr)+Anzahl d. Symmetrien)
Dimension: 100*Number of bodies without workpiece
Data type: real*8
Index I/O Importance/Comment
1,i I/O free
2,i I/O free
3,i I/O free
4,i I/O free

86
13.2 User defined kinematic Solver and subroutine

5,i I/O free


6,i I/O free
7,i I/O free
8,i I/O free
9,i I/O free
10,i I/O free
11,i I/O free
12,i I/O free
13,i I/O free
14,i I/O free
15,i I/O free
16,i I/O free
17,i I/O free
18,i I/O free
19,i I/O free
20,i O body i is force controlled? 0.0d0=No : 1.0d0=Yes
21,i - blocked
22,i - blocked
23,i I/O free
24,i I/O free
25,i I/O free
26,i I/O free
27,i I/O free
28,i O change rotational axis of body i? 0.0d0=No : 1.0d0=Yes (Parameter->
xmvbd_currmove(9-11,i))
29,i O change center of rotation of body i? 0.0d0=No : 1.0d0=Yes (Parameter->
xmvbd_currmove(12-14,i))
30,i O body i in contact with workpiece? 0.0d0=No : 1.0d0=Yes
31,i O contact tolerance of body i
32,i O separation force of body i
33,i O Coefficient of friction of body i
34,i O Contact bias factor of body i
35,i - blocked
36,i - blocked
37,i - blocked
38,i - blocked
39,i - blocked
40,i - blocked
41,i - blocked
42,i - blocked
43,i - blocked
44,i - blocked

87
13.2 User defined kinematic Solver and subroutine

45,i - blocked
46,i - blocked
47,i - blocked
48,i - blocked
49,i - blocked
50,i - blocked
51,i - blocked
52,i - blocked
53,i - blocked
54,i - blocked
55,i - blocked
56,i - blocked
57,i - blocked
58,i - blocked
59,i - blocked
60,i - blocked
61,i - blocked
62,i - blocked
63,i - blocked
64,i - blocked
65,i - blocked
66,i I/O free
67,i I/O free
68,i I/O free
69,i I/O free
70,i O force direction on body i due to Maximum Force Criterion. 1.0d0=x : 2.0d0=y : 3.0d0=z
71,i I/O free
72,i I/O free
73,i I/O free
74,i I/O free
75,i I/O free
76,i I/O free
77,i I/O free
78,i I/O free
79,i I/O free
80,i I/O free
81,i I/O free
82,i I/O free
83,i I/O free
84,i I/O free
85,i I/O free
86,i I/O free

88
13.2 User defined kinematic Solver and subroutine

87,i I/O free


88,i I/O free
89,i I/O free
80,i I/O free
91,i I/O free
92,i I/O free
93,i I/O free
94,i I/O free
95,i I/O free
96,i I/O free
97,i I/O free
98,i I/O free
99,i I/O free
100,i I/O free

2.1.5.4.7. Array: xdefbd_move


The xdefbd_move array is used as a parameter for boundary condition criteria. Next the variable nbd2mv, determining
the number of bodies to be moved, should be set. This array is a special array where the body index (index:1,i) with
value 1 may be assigned to workpiece as well as tool. Symmetry information tells to follow the applied symmetry
condition while moving. For example xdefbd_move(1,i)=1 represents the work piece if xdefbd_move(2,i)=1 whereas
it represent the tool at kinPos="3;1" when xdefbd_move(2,i)=0.

xdefbd_move(11, Number of moving bodies (must be set through ndb2mv))


Dimension: 11* Number of moving bodies
Data type: real*8
Index I/O Importance/Comment
1,i O body number of the moving bodies (1=Workpiece, 1,...,n=tools as in .kin data)
2,i O moving symmetry? 0.0d0=No : 1.0d0=Yes
3,i O translation in x-direction of the body considered in (1,i) [m]
4,i O translation in y-direction of the body considered in (1,i) [m]
5,i O translation in z-direction of the body considered in (1,i) [m]
6,i O rotation around the x-axis of the body considered in (1,i) [] (+=counterclockwise)
7,i O rotation around the y-axis of the body considered in (1,i) [] (+=counterclockwise)
8,i O rotation around the z-axis of the body considered in (1,i) [] (+=counterclockwise)
9,i O x-coordinate of the center of rotation of the body considered in (1,i)
10,i O y-coordinate of the center of rotation of the body considered in (1,i)
11,i O z-coordinate of the center of rotation of the body considered in (1,i)

2.1.5.4.8. Array: xmvbd_param


The xmvbd_param array contains the datablock 10 and 11 of the .kin file. This array make available the information
provided by the user input. It is important that the content of this array, the entered numerical values, must not be
changed in the subroutine.

xmvbd_param(11, number of moving bodies * number of heat * maximum number of passes per Heat)

89
13.2 User defined kinematic Solver and subroutine

Dimension: 11* number of moving bodies * number of heat * maximum number of passes per Heat
Data type: real*8
Index I/O Importance/Comment
1,i*j I kinPos=10,1,i in pass j
2,i*j I kinPos=10,2,i in pass j
3,i*j I kinPos=10,3,i in pass j
4,i*j I kinPos=10,4,i in pass j
5,i*j I kinPos=10,5,i in pass j
6,i*j I kinPos=10,6,i in pass j
7,i*j I kinPos=11,1,i in pass j
8,i*j I kinPos=11,2,i in pass j
9,i*j I kinPos=11,3,i in pass j
10,i*j I kinPos=11,4,i in pass j
11,i*j I kinPos=11,5,i in pass j

2.1.5.4.9. Array: xmvbd_currmove


The xmvbd_currmove array is counterpart to the xmvbd_param array providing parameters for the Motion change
load case. If no rotation axis is specified then the predefined rotation of the model is defined.

xmvbd_currmove(14, number of moving bodies * number of heat * maximum number of passes per Heat)
Dimension: 14* number of moving bodies * number of heat * maximum number of passes per Heat
Data type: real*8
Index I/O Importance/Comment
1,i O x-component of translation [m]
2,i O y-component of translation [m]
3,i O z-component of translation [m]
4,i O x-component of velocity [m/s]
5,i O y-component of velocity [m/s]
6,i O z-component of velocity [m/s]]
7,i O length of rotation [rad]
8,i O rotational velocity [rad/s]
9,i O direction cosine of x-component of the axis of rotation [ ] (-> xbdcntrls (28))
10,i O direction cosine of y-component of the axis of rotation [ ] (-> xbdcntrls (28))
11,i O direction cosine of z-component of the axis of rotation [ ] (-> xbdcntrls (28))
12,i O x-coordinate of the center of rotation (->xbdcntrls(29))
13,i O y-coordinate of the center of rotation (->xbdcntrls(29))
14,i O z-coordinate of the center of rotation (->xbdcntrls(29))

2.1.5.4.10. Array: xpass_info


The xpass_info array is the data block number 9 from the .kin file. Make sure that content is not changed in the
subroutine.

xpass_info(10, Anzahl der Hitzen * max. Anzahl Stiche pro Hitze)

90
13.2 User defined kinematic Solver and subroutine

Dimension: 10, Anzahl der Hitzen * max. Anzahl Stiche pro Hitze
Data type: real*8
Index I/O Importance/Comment
1,i I kinPos=9;3 in pass i
2,i I kinPos=9;4 in pass i
3,i I kinPos=9;5 in pass i
4,i I kinPos=9;6 in pass i
5,i I kinPos=9;7 in pass i
6,i I kinPos=9;8 in pass i
7,i I kinPos=9;9 in pass i
8,i I kinPos=9;10 in pass i
9,i I kinPos=9;11 in pass i
10,i I kinPos=9;12 in pass i

2.1.5.4.11. Array: ipass_info


The ipass_info array stores the information of the 8th datablock of the .kin data file.

ipass_info(10, number of Heat * maximum number of pass per Heat)


Dimension: 10, number of heat * maximum number of pass per Heat
Data type: integer
Index I/O Importance/Comment
1,i I kinPos=8;3 in pass i
2,i I kinPos=8;4 in pass i
3,i I kinPos=8;5 in pass i
4,i I kinPos=8;6 in pass i
5,i I kinPos=8;7 in pass i
6,i I kinPos=8;8 in pass i
7,i I kinPos=8;9 in pass i
8,i I kinPos=8;10 in pass i
9,i I kinPos=8;11 in pass i
10,i I kinPos=8;12 in pass i

2.1.5.4.12. Array: xmachine_info


The xmachine_info array stores the information of the 7th datablock of the .kin data file.

xmachine_info(10, number of Heat)


Dimension: 22, number of Heat
Data type: real*8
Index I/O Importance/Comment
1,i I number of pass in the Heat i
2,i I kinPos=7;2 in the Heat i
3,i I kinPos=7;3 in the Heat i
4,i I kinPos=7;4 in the Heat i

91
13.2 User defined kinematic Solver and subroutine

5,i I kinPos=7;5 in the Heat i


6,i I kinPos=7;6 in the Heat i
7,i I blocked
8,i I blocked
9,i I blocked
10,i I blocked
11,i I blocked
12,i I blocked
13,i I blocked
14,i I blocked
15,i I blocked
16,i I blocked
17,i I blocked
18,i I blocked
19,i I blocked
20,i I blocked
21,i I blocked
22,i I blocked

2.1.5.4.13. Array: inkininfo


The inkininfo array stores the information of the 2nd datablock of the .kin data file.

ikininfo(7)
Dimension: 7
Data type: integer
Index I/O Importance/Comment
1 I kinPos=2;1 (starting increment of the Kinematics)
2 I kinPos=2;2 (Kinematics type)
3 I kinPos=2;3 (debug level)
4 I kinPos=2;4 (number of moving tools)
5 I kinPos=2;5 (number of static tools)
6 I kinPos=2;6 (number of user editable integer variables)
7 I kinPos=2;7 (number of user editable real variables)
8 - blocked
9 - blocked
10 - blocked
11 - blocked
12 - blocked
13 - blocked

2.1.5.4.14. Other variables


The variables which are not listed in the array but used in the subroutine are listed alphabetically in the following
table. In the "type" column "char" stands for character and "int" for the integer types.

92
13.2 User defined kinematic Example

Other variables
Dimension: 1
Name Type I/O Importance/Comment
ctitle char O process name, also displayed in the .sts data by Simufact.forming
iflag int I iflag=0 => 0-increment is active
ikintype int I type of kinematics
inc_start int I restart required? 0=No : 1=Yes
load case char O Name of the load case (only for gravity)
mxip int I number of user editable integer variables per pass
mxp int I number of user editable real variables per pass
mxpass int I maximum number of passes in a Heat
mxsp int I number of user editable real variables per Heat
nmbdy int I total number of the bodies in the model
nmfixbdy int I total number of static tools
nmmvbdy int I total number of moving tools
numsuper int I number of Heat

2.1.6. Example
This chapter describes a sample subroutine consisting of examples from the previous chapter. By exploiting the four
fold symmetry of the model, the process consists of the following steps:

1. Due to symmetry, rolling with only top roll and workpiece will be modelled. Thickness reduction will be half of
that is entered.

2. In the first pass, the pusher will move the work-piece towards the roll from left to right.

3. In the second pass, the pusher will move the work-piece towards the roll achieving the two pass rolling from right
to left.

First open the rolling example from the Simufact.demos. Four-fold symmetry of the roll can be exploited in the model.
Following steps are required to prepare the model:

1. Delete the process "pass1-symmetry".

2. Delete the object "translation".

3. Delete the object "rotation".

4. Delete the body called "Lowerroll".

5. Translate "Upperroll" by 50mm in positive z direction.

6. Translate "Pusher" by 100mm in negative x-direction.

7. Translate "Workpiece" by 50mm in negative x-direction.

8. Insert two symmetry planes. First in the x-y plane by z=0 and second in the x-z plane by y=y(max) of the workpiece.

The modified model with the added symmetries should now look like this:

93
13.2 User defined kinematic Example

Figure 2.14. Modified model with symmetry planes

The process tree of the model and the object window is shown in the following image.

Figure 2.15. Modified process tree and object windows of the model

Since the lower roll is removed, the corresponding entry is deleted from the XML control file. The kinematic dialog
window now looks like (thickness reductions were also adjusted so that a realistic roller case) arises:

94
13.2 User defined kinematic Example

Figure 2.16. Modified kinematic dialog window

2.1.6.1. Subroutine: sfukin.f


After modifying the model, only source code for sfukin.f has to be written. A sample source sfukin.f looks like this:

c-------------------------------------------------------------------
c Subroutine for user-defined kinematic example
c Routine is to simulate two pass rolling
c-------------------------------------------------------------------
subroutine sfukin(xmvbd_currmove,xdefbd_move,xmvbd_param,
1 xbd_minmax,xbd_minmax_atstart,xcontrols,nmbdy,nmmvbdy,nmfixbdy,
2 mxsp,mxp,mxip,mxpass,numsuper,nbd2mv,ctitle,iarcoutput,iterm,
3 iflag,xpass_info,ipass_info,xmachine_info,ikininfo,xbdcntrls,
4 loadcase,icontrols,i2write,inc_start,ikintype)

C******************************************************************
C Don't change anything here - these are compiler options *
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
c
#include "sfkin.cmn"
#include "concom.cmn"
#include "machin.cmn"
#include "spaceco.cmn"
C******************************************************************
character*24 ctitle,loadcase

integer nmbdy,nmmvbdy,nmfixbdy,iarcoutput,iterm,iflag,mxsp,
1 mxp,mxpass,numsuper,ipass_info,ikininfo,mxip,ikintype,
2 nbd2mv,icontrols,i2write,inc_start

95
13.2 User defined kinematic Example

integer i

real*8 xmvbd_currmove,xmvbd_param,xbd_minmax,
1 xbd_minmax_atstart,xmachine_info,xpass_info,
2 xcontrols,xbdcntrls,xdefbd_move

dimension xmvbd_currmove(14,nmmvbdy),xdefbd_move(11,*),
1 xmvbd_param(14,nmmvbdy*numsuper*mxpass),
2 xbd_minmax(12,nmbdy),xbd_minmax_atstart(12,nmbdy),
3 xmachine_info(mxsp,numsuper),xpass_info(mxp,numsuper*mxpass),
4 ipass_info(mxp,numsuper*mxpass),xcontrols(*),
5 xbdcntrls(100,(nmmvbdy+nmfixbdy+1)),ikininfo(13),
6 icontrols(*),i2write(*)

intent(in) :: xmvbd_param,xbd_minmax,xbd_minmax_atstart,
1 xmachine_info,mxp,mxpass,numsuper,nmfixbdy,iflag,mxsp,
2 xpass_info,ipass_info,ikininfo,nmbdy,nmmvbdy,mxip

C*******************************************************************
C
C These section contains all variables that can be used within
C the sfukin subroutine
C I = Input (parsed in for controlling tasks)
C O = Output (variables that can be manipulated by the user)
C # = number
C
C xcontrols(9)
C (1) I - min. element feed size in x-direction /3
C (2) I - min. element feed size in y-direction /3
C (3) I - min. element feed size in z-direction /3
C (4) I - max. way of rotation per increment
C (5) O - max. time for the next step
C (6) O - "control (History)" (-> volC, Block 3, Position 1)
C (7) O - "control (History)" (-> volC, Block 4, Position 1)
C (8) O - remeshing factor (>0 => coarse, <0 =>fine)
C -> activate remeshing with i2write(9)=1
C (9) O - progress of process in %
C -> activate user progress with icontrols(4)=1
C
C icontrols(6)
C (1) O - number of increments for the next step
C (2) O - "control (History)" (-> volC, Block 2, Position 4)
C (3) O - approach parameter
C -> activate approach with i2write(6)=1
C (4) O - write user progress of the process (=1)
C (5) O - load case parameter (number of activated
C boundary conditions)
C (6) O - result flag (a file for an automated process
C report is written, if =1)
C
C i2write(10)
C 1=true 0=false
C (1) O - write title
C (2) O - write load case
C (3) O - write contact table
C (4) O - write motion change
C (5) O - write release
C (6) O - write approach

96
13.2 User defined kinematic Example

C (7) O - write gravity


C (8) O - write move
C (9) O - remesh
C (10) O - write terminate criteria
C
C xbd_minmax(6, # of all body)
C - first body is the workpiece (j,1)
C - then moving bodies
C - then fixed bodies
C - then symmetry
C (1,i) I - min. x-coordinate of body i at the moment
C (2,i) I - max. x-coordinate of body i at the moment
C (3,i) I - min. y-coordinate of body i at the moment
C (4,i) I - max. y-coordinate of body i at the moment
C (5,i) I - min. z-coordinate of body i at the moment
C (6,i) I - min. z-coordinate of body i at the moment
C
C xbd_minmax_atstart(6, # of all body)
C - same dimensions and meaning as xbd_minmax
C - position at the beginning of the simulation
C
C xbdcntrls(100, # of all body without the workpiece)
C - unmentioned indices can't be used
C (20,i) O - body i is load controlled (1.0d0=true)
C (28,i) O - change rot.axis for body i (1.0d0=true)
C -> directional cos of new axis is given
C in xmvbd_currmove(9-11,i)
C (29,i) O - change center of rotation for body i (1=true)
C -> coordinates of new point are given in
C xmvbd_currmove(12-14,i)
C (30,i) O - body i has contact to the workpiece (1=true)
C (31,i) O - contact tolerance for body i
C (32,i) O - separation force for body i
C (33,i) O - friction coefficient for body i
C (34,i) O - contact bias for body i
C (70,i) O - direction of force for force abort criterion
C 1.0d0=x, 2.0d0=y, 3.0d0=z
C
C xdefbd_move(11,nbd2mv)
C - if xdefbd_move is used nbd2mv has to be set to the number
C of body's that should be used with the move load case
C (1,i) O - body number of the body to move
C (2,i) O - move body with symmetry (1.0d0=true)
C (3,i) O - translation of body in x-direction [m]
C (4,i) O - translation of body in y-direction [m]
C (5,i) O - translation of body in z-direction [m]
C (6,i) O - rotation of body about x-axis []
C (7,i) O - rotation of body about y-axis []
C (8,i) O - rotation of body about z-axis []
C Note: a positive value for the rotation causes
C a counter clockwise rotation
C (9,i) O - center of rotation x-coordinate
C (10,i) O - center of rotation y-coordinate
C (11,i) O - center of rotation z-coordinate
C
C xmvbd_param(11,# of moving bodies * max. # of passes * # of Heat)
C - contains data out of the .kin-file
C (1,i*j) I - kinPos=10;1;i in pass j

97
13.2 User defined kinematic Example

C (2,i*j) I - kinPos=10;2;i in pass j


C (3,i*j) I - kinPos=10;3;i in pass j
C (4,i*j) I - kinPos=10;4;i in pass j
C (5,i*j) I - kinPos=10;5;i in pass j
C (6,i*j) I - kinPos=10;6;i in pass j
C (7,i*j) I - kinPos=11;1;i in pass j
C (8,i*j) I - kinPos=11;2;i in pass j
C (9,i*j) I - kinPos=11;3;i in pass j
C (10,i*j) I - kinPos=11;4;i in pass j
C (11,i*j) I - kinPos=11;5;i in pass j
C
C xmvbd_currmove(14,# of moving bodies*max. # of passes * # of Heat)
C - parameter for the motion change load case can be given here
C - all values for body i, where the order of bodies
C is given in the .kin-file
C Note: body 1 is not the workpiece in this case
C (1,i) O - x-component of translation of body i [m]
C (2,i) O - y-component of translation of body i [m]
C (3,i) O - z-component of translation of body i [m]
C (4,i) O - x-component of the velocity of body i [m/s]
C (5,i) O - y-component of the velocity of body i [m/s]
C (6,i) O - z-component of the velocity of body i [m/s]
C (7,i) O - length of the rotational path [rad]
C (8,i) O - rotational speed [rad/s]
C (9,i) O - directional cos of x-component of rotaxis []
C (10,i) O - directional cos of y-component of rotaxis []
C (11,i) O - directional cos of z-component of rotaxis []
C Note: activate xbdcntrls(28)
C (12,i) O - x-coordinate center of rotation
C (13,i) O - y-coordinate center of rotation
C (14,i) O - z-coordinate center of rotation
C Note: activate xbdcntrls(29)
C
C xpass_info(10, # of Heat * max. # of passes)
C - contains data out of the .kin-file
C (1,i) I - kinPos=9;3 in pass i
C (2,i) I - kinPos=9;4 in pass i
C (3,i) I - kinPos=9;5 in pass i
C (4,i) I - kinPos=9;6 in pass i
C (5,i) I - kinPos=9;7 in pass i
C (6,i) I - kinPos=9;8 in pass i
C (7,i) I - kinPos=9;9 in pass i
C (8,i) I - kinPos=9;10 in pass i
C (9,i) I - kinPos=9;11 in pass i
C (10,i) I - kinPos=9;12 in pass i
C
C ipass_info(10, # o Heat * max. # of passes)
C - contains data out of the .kin-file
C (1,i) I - kinPos=8;3 in pass i
C (2,i) I - kinPos=8;4 in pass i
C (3,i) I - kinPos=8;5 in pass i
C (4,i) I - kinPos=8;6 in pass i
C (5,i) I - kinPos=8;7 in pass i
C (6,i) I - kinPos=8;8 in pass i
C (7,i) I - kinPos=8;9 in pass i
C (8,i) I - kinPos=8;10 in pass i
C (9,i) I - kinPos=8;11 in pass i
C (10,i) I - kinPos=8;12 in pass i

98
13.2 User defined kinematic Example

C
C xmachine_info(10, # of Heat)
C - contains data out of the .kin-file
C - all unmentioned indices can't be used
C (1,i) I - number of passes in Heat i
C (2,i) I - kinPos=7;2 in Heat i
C (3,i) I - kinPos=7;3 in Heat i
C (4,i) I - kinPos=7;4 in Heat i
C (5,i) I - kinPos=7;5 in Heat i
C (6,i) I - kinPos=7;6 in Heat i
C
C ikininfo(7)
C - contains data out of the .kin-file
C - all unmentioned indices can't be used
C (1) I - kinPos=2;1 (starting increment of kinematic)
C (2) I - kinPos=2;2 (kinematic type)
C (3) I - kinPos=2;3 (debug level)
C (4) I - kinPos=2;4 (number of moving tools)
C (5) I - kinPos=2;5 (number of fixed tools)
C (6) I - kinPos=2;6 (number of user defined integer)
C (7) I - kinPos=2;7 (number of user defined real)
C
C other variables
C NAME TYPE I/O COMMENT
C ctitle char O process name
C iflag int I iflag=0 => 0-increment is running
C inkintype int I type of kinematic
C inc_start int I if 1 => restart is done
C loadcase char O name of load case (gravity)
C mxip int I max. # of user defined integer per pass
C mxp int I max. # of user defined real per pass
C mxpass int I max. # of passes in a Heat
C mxsp int I max. # of user defined real per Heat
C nmbdy int I # of all bodies in the model
C nmfixbdy int I # of all fixed bodies in the model
C nmmvbdy int I # of all moving bodies in the model
C numsuper int I # of Heats
c iterm: = 1 Flag to indicate the end of the whole job
C
C**********************************************************************
C User defined local variables
integer iuk_operation
c store user defined local variables in local common block
common /sfukin_1/iuk_operation
C**********************************************************************

if(ipass.ne.1) goto 999 ! skip non mechanical pass

if(iflag.eq.0) then
if(inc_start.eq.0) then
C Initializing the counter
iuk_operation=0
endif

if(inc_start.gt.0) then
C reading stored local variable
iuk_operation=i2res(1)
endif

99
13.2 User defined kinematic Example

goto 9999
endif

if(iuk_operation.eq.0)then
ctitle='Pass1: Roll positioning'

C Calculating the roll alignment in z direction


C Thickness of workpiece is to be reduced by half
C of the input value (3.0/2==1.5mm), xpass_info(6,1),
C provided in the kinematic-dialog window for the first pass
xdefbd_move(5,1)=xbd_minmax(6,1)-
& 0.5d0*xpass_info(6,1)-xbd_minmax(5,2)

C body number as in the .kin data


xdefbd_move(1,1)=1.0d0
C move the roll without symmetry
xdefbd_move(2,1)=0.0d0
C Only one body has to be moved in this step
nbd2mv = 1
C write the contact table for all the bodies
do i=1,(nmmvbdy+nmfixbdy)
xbdcntrls(30,i) = 1.0d0
enddo

C Use small time step for the movement


xcontrols(5)=0.01d0
C rigid body motion by an increment
icontrols(1)=1
C write title, contact table, motion change and movement
i2write(1)=1
i2write(3)=1
i2write(4)=1
i2write(8)=1
C counter increment
iuk_operation=iuk_operation+1

elseif(iuk_operation.eq.1)then
ctitle='Pass1: Workpiece positioning'

C The workpiece has to be moved


xdefbd_move(1,1)=1.0d0
C With Symmetry
xdefbd_move(2,1)=1.0d0
C Positioning the workpiece in x-direction
C with tolerance of 0.0054d0 m
xdefbd_move(3,1)=-xbd_minmax(2,1)
& -sqrt(0.18d0*xpass_info(6,1))+0.0054d0

C One body(work piece) is to be moved in this step


nbd2mv = 1
C writing contact table for all the bodies
do i=1,(nmmvbdy+nmfixbdy)
xbdcntrls(30,i) = 1.0d0
enddo

C small time step for the movement


xcontrols(5)=0.01d0

100
13.2 User defined kinematic Example

C rigid body motion by the increment


icontrols(1)=1
C write title, contact table, motion change and movement
i2write(1)=1
i2write(3)=1
i2write(4)=1
i2write(8)=1
C counter increase
iuk_operation=iuk_operation+1

elseif(iuk_operation.eq.2)then
ctitle='Pass1: Pusher Contact'

C Velocity for the searching the contact with the workpiece


C xmvbd_currmove(4,2)==> body with index 2(=pusher) is to
C move with velocity 0.01d0 m/sec in x-direction(index 4)
xmvbd_currmove(4,2)=0.01d0
C writing contact table for all the bodies
do i=1,(nmmvbdy+nmfixbdy)
xbdcntrls(30,i) = 1.0d0
enddo

C Activating the required load control


xcontrols(5)=0.01d0
icontrols(1)=1
i2write(1)=1
i2write(3)=1
i2write(4)=1
i2write(6)=1
icontrols(3)=4
C counter increase
iuk_operation=iuk_operation+1

elseif(iuk_operation.eq.3)then
C Actual rolling process takes place in this loop,
C Pusher is pushing the workpiece toward roll for rolling
ctitle='Pass1: Rolling process'
C Translate pusher by 0.01d0 in x-->direction
xmvbd_currmove(1,2)=0.01d0
C Pusher is to be moved with the velocity of
C Convert circumferential speed to linear speed (1/8 factor)
xmvbd_currmove(4,2)=0.0125*3.14d0*0.18d0*xmvbd_param(3,1)
C Roll will rotate by 144 degree (converted to radian)
xmvbd_currmove(7,1)=0.8*3.14d0
C Rotational speed of the roll for first pass,
C taken from the kin file. The value was provided
C by the user in kinematic-dialog window.
xmvbd_currmove(8,1)=xmvbd_param(3,1)
C writing contact table for all the bodies
do i=1,(nmmvbdy+nmfixbdy)
xbdcntrls(30,i) = 1.0d0
enddo

C Activating Required loading maps


i2write(1)=1
i2write(3)=1
i2write(4)=1
C counter increase

101
13.2 User defined kinematic Example

iuk_operation=iuk_operation+1

elseif(iuk_operation.eq.4)then
ctitle='Pass2:Preparing'
C In this step roll will be further lowered for second pass
C First body to be move slightly is the workpiece,
C to avoid crushing by the roll during lowering
xdefbd_move(1,1)=1.0d0
C With Symmetry
xdefbd_move(2,1)=1.0d0
C workpiece is moved by 19 mm in x-direction
xdefbd_move(3,1)= 0.019d0

C Second body to be moved is the roll (lowering the roll)


xdefbd_move(1,2)=1.0d0
C With out Symmetry
xdefbd_move(2,2)=0.0d0
C Calculate Roll delivery, in z direction, wrt. first pass
xdefbd_move(5,2)=-0.5d0*xpass_info(6,2)

C Third, the pusher is moved


C Third body is to be moved is pusher with body id=2
xdefbd_move(1,3)=2.0d0
C Positioning pusher in x-direction, other side by 200 mm
xdefbd_move(3,3)= 0.2d0

C Total three body is to be moved


nbd2mv = 3
C writing contact table for all the bodies
do i=1,(nmmvbdy+nmfixbdy)
xbdcntrls(30,i) = 1.0d0
enddo

C small time step for the movement


xcontrols(5)=0.01d0
C rigid body motion by the increment
icontrols(1)=1
C write title, contact tabele, motion change and movement
i2write(1)=1
i2write(3)=1
i2write(4)=1
i2write(8)=1
C counter increase
iuk_operation=iuk_operation+1

elseif(iuk_operation.eq.5)then
ctitle='Pass2: Pusher contact'
C Velocity for the searching the contact with the workpiece
xmvbd_currmove(4,2)=-0.01d0
C writing contact table for all the bodies
do i=1,(nmmvbdy+nmfixbdy)
xbdcntrls(30,i) = 1.0d0
enddo

C Activating the required load control


xcontrols(5)=0.01d0
icontrols(1)=1
icontrols(3)=4

102
13.2 User defined kinematic Example

i2write(1)=1
i2write(3)=1
i2write(4)=1
i2write(6)=1
icontrols(3)=4

C counter increase
iuk_operation=iuk_operation+1

elseif(iuk_operation.eq.6)then
ctitle='Pass2: Rolling process'
C Translate pusher by 0.01d0 in x-->direction
xmvbd_currmove(1,2)=0.01d0
C Converting the circumferential speed to linear speed
C (with 1/8 factor) in reverse direction
xmvbd_currmove(4,2)=-0.0125*3.14d0*0.18d0*xmvbd_param(3,3)
C Roll will rotate by 144 degree (converted to radian)
xmvbd_currmove(7,1)=0.8*3.14d0
C Rotational speed of the roll for second pass from kin file
C Value provided by user in kinematic window.( - for reverse)

xmvbd_currmove(8,1)=-xmvbd_param(3,3)
C writing contact table for all the bodies
do i=1,(nmmvbdy+nmfixbdy)
xbdcntrls(30,i) = 1.0d0
enddo

C Activating Required loading maps


i2write(1)=1
i2write(3)=1
i2write(4)=1
C counter increase
iuk_operation=iuk_operation+1

elseif(iuk_operation.eq.7)then
C Process_finished
iterm = 1
else
continue
endif
c
9999 continue
c storing local variable
iresdim=1
i2res(1)=iuk_operation
999 continue
return
end

In the above code, a local variable, iuk_operation, has been used to perform the process stepwise. By default, values of
the local variables are retained throughout the program execution due to compiler settings. This is valid if the process
is run on a single core process. When the program runs with parallel option, the values of local variables may be lost in
between the process steps when there is remeshing. Therefore, the critical local variables should also be saved through
i2res() variable. This can be achieved by including the sfkin.cmn common blocks.

#include "spaceco.cmn"
#include "sfkin.cmn"

103
Scientific
13.2

3 User defined material


13.2 User defined material User defined material law

Educational Objectives

Uses of user subroutine in Simufact.forming for dynamic material properties

Prerequisites

FORTRAN programing knowledge, general programing knowledge

3.1. User defined material law


Through the user subroutines, it is possible to define custom material laws through analytical equations in
Simufact.forming. Flow stress of the material as a function of plastic strain, plastic strain rate and temperature can
be defined and calculated in real time during the simulation. This can be achieved through the usage of subroutine
au_yiel() and user_fstress(). In the case of au_yiel(), all the parameters have to be defined within the subroutine. This
routine can be used if a simple flow stress equation is used for all the temperature. Uses of subroutine user_fstress()
provides more flexibility and greater process control for complex non continuous temperature dependence of flow
stress. It is common to have different values of flow stress at different temperatures (cold and hot forming), therefore
the material may have different constitutive equations for different temperatures. Flow stress of a material is a com-
plex function of process parameters such as strain, strain rate and temperature. In such cases using user_fstress()
subroutine helps to specify different flow stress equations with different parameters. This manual will focus on the
use of user_fstress() subroutine

To include the material law in the simulation, two step process has to be followed. First, the various parameters for the
material equation have to be built in the material database through Simufact.material. Second, the material equations
based on these parameters have to be described in the user subroutine in user_fstress() function. When the parameters
are populated in the material information through Simufact.material, It is important to provide a model number and
validity range in terms of strain, strain rate and temperature for which the model is valid. For example if the parameter
sets is assigned a model number 1 in Simufact.material, then the solver assigns the parameter lists with with the number
= 101 (model number 1-100 are reserved) and will pass these parameters along with model number, 101 in this case,
through call arguments in user_fstress() function. In addition to parameter list, current strain and strain rate are also
included in the argument list. In case the current strain or strain rate lies beyond the defined range for the model,
solver will provide the subroutine with only the upper or lower range value that is nearest to the actual value, instead
of actual strain/strain rate value.

It must be noted that the solver uses temperature range to determine the parameter sets that should be passed through
function arguments. If two different flow stress models are used for two different temperature ranges and there is
discontinuity between the temperature range, then the flows stress in the region of discontinuity will be linearly inter-
polated from the two end point values of the two models. For example if model (equation) 1 is valid till temperature
T1 and equation 2 is valid from temperature T2, then the flow stress at a temperature anywhere in between T1 and T2
is obtained by linear interpolation of the flow stress values from equation 1 at T1 and equation 2 at T2, as shown in
sketch below. If the material equation have the overlapping temperature range, the system will give an error.

3.1.1. Material information


Material database for flow stress model can be easily created through Simufact.material which then can be easily
imported in Simufact.forming. User has the option to create a custom material from scratch by unlocking the database.

105
13.2 User defined material Material information

However it is easier to make a copy of the near matching material information from the existing database and then
change the relevant field. The later process is recommended because less effort is required to add or change the material
properties, other information being remained unchanged. It is not recommended to edit and overwrite the already
existing material information. Instead first make a copy and then make the changes. A material information windows
looks like following.

Figure 3.1. Flow curve information created through table input

3.1.1.1. New material database


In this section, steps to create a new material database from an already existing one are described and an example
is given.

In Simufact.forming, first import a material information in inventory windows of Simufact.forming. The material
should be the nearest match to that being used for the simulation process so that only selected few information has
to be altered. In this example, we import stainless steel with DIN number 1.4571 which can be used for cold as well
as hot forming. The below figure shows the inventory window with a material file which can be duplicated through
right mouse click and can be renamed to a new material. The properties of the new material file can be opened by
double mouse click.

106
13.2 User defined material Material information

Figure 3.2. Inventory window showing process of duplicating the material file

The window shows various material properties which can be modified. For the flow curve menu in left, it shows the
existing information which can be removed by clicking minus "-" button in the right.

Figure 3.3. Removing the existing flow curve information

After removing the existing flow curve information, choose the "Analytical" options in the drop down menu below
flow curve approach, as marked 1 in the below figure. Then choose "User defined" in the plasticity model option and
confirm the choice by pressing the green "+" button, as shown by number 2 and 3 respectively in the figure below.

107
13.2 User defined material Material information

Figure 3.4. Adding a user defined material plasticity model

The following dialog box is to enter various parameters. Press the edit option to open the dialog box to enter the
various parameter to be used for the material model.

Figure 3.5. Dialog box to edit flow curve information

The dialog box for input of parameters looks like below figure. Value for various parameters can either have a constant
value or can be entered through a table.

108
13.2 User defined material Material information

Figure 3.6. Dialog box to enter equation parameters

To enter the values in the above dialog box follow the following:

1. Press green '+' button beside the temperature range option to activate the input fields.

2. Select the appropriate unit of temperature and stress from the drop down menu

3. First enter the range of temperature for which the parameters specified in this windows are to be used for the
calculations. Next enter the minimum and maximum value of strain and strain rate for which the model will be
valid. In addition total of maximum 16 different parameters value can be entered but not all have to be used. Values
of these parameters can be a constant or a function of time, temperature and strain rate. The relation has to be
entered through a table input. The solver will give an error if two equations have an overlapping temperature range,
so please avoid it.

4. Enter the model number. The solver will use the subroutine argument to pass the variable array set depending upon
the model number. So its important to assign a distinct model number.

5. Save them by clicking the apply button. To add parameters for another model, follow the above steps from 1 - 4
and can be repeated. Make sure that different model number is used for different parameters set.

The new material database created can be saved back in Simufact.material database for future use through "To Library"
option in the inventory window.

109
13.2 User defined material User subroutine

Figure 3.7. Save the created material file for future use

3.1.2. User subroutine


user_fstress() function will be used to define the analytical material law. The subroutine is called for each integration
point of the element where the flow stress of the material has to be calculated. The syntax of the subroutine is as follows

subroutine user_fstress(mats,ityp1,t1,ep1,er1,p1,fstress1)
c
c subroutine to compute flow stress based on user equation
c mats - material id
c ityp1 - equation type (>100)
c t1 - temperature
c ep1 - plastic strain
c er1 - plastic strain rate
c p1 - materia parameters from input
c fstress1 - flow stress
c
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
real*8 t1,ep1,er1,p1,fstress1,real_array
integer mats,ityp1,int_array
dimension p1(*)
cccccccccccccccccccccccccc

c USER DEFINED EQUATIONS

cccccccccccccccccccccccccc
return
end

Through the above subroutine, the various parameters defined in the the material information are passed to the function.
In the argument, solver pass the model number through variable ityp1 and parameter values through array p1(), like
p1(1), p1(2) and so on for parameter 1 and parameter 2 respectively. At the same time the current temperature, plastic
strain and strain rate are available through variables t1, ep1 and er1 respectively. Solver will use the temperature
field to determine which equation number and corresponding sets of parameters to be made available through function
arguments.

110
13.2 User defined material Example

3.1.3. Example
The below subroutine calculates the flow stress through a simple power law. In the subroutine two equations are
defined to calculate flow stress. The model number is chosen on the basis of the temperature. At low temperature the
first equation will be used where as the second one is used for high temperatures. In the example same simulation is
duplicated but for different temperatures. Comparing the Z-forces for two case should highlight the uses of different
flow stress due to different simulation temperature.

subroutine user_fstress(mats,ityp1,t1,ep1,er1,p1,fstress1)
c
c subroutine to compute flow stress based on user equation
c mats - material id
c ityp1 - equation type (>100)
c t1 - temperature
c ep1 - plastic strain
c er1 - plastic strain rate
c p1 - materia parameters from input
c fstress1 - flow stress
c
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
real*8 t1,ep1,er1,p1,fstress1,real_array
integer mats,ityp1,int_array
dimension p1(*)

c------Equation 1
if(ityp1.eq.101) then
fstress1=p1(1)*er1**p1(4)
if(fstress1.le.p1(2))fstress1=p1(2)
endif

c-------Equation 2
if(ityp1.eq.102) then
fstress1=p1(1)*er1**p1(4) * ep1**p1(3)
if(fstress1.le.p1(2))fstress1=p1(2)
endif

return
end

In the example, the same simulation is run at different temperature. Thus different material models are used to get flow
curve for the two cases. Two parameter sets are stored in the material file for two temperature range as shown below.

111
13.2 User defined material Example

Figure 3.8. Parameters used in the example

112

Das könnte Ihnen auch gefallen