Simufact Forming 2023.2 Scientific Tutorial
Simufact Forming 2023.2 Scientific Tutorial
2
Scientific Tutorial
Hexagon reserves the right to make changes in specifications and other information contained in this document without prior notice. The concepts,
methods, and examples presented in this text are for illustrative and educational purposes only, and are not intended to be exhaustive or to apply
to any particular engineering problem or design. Hexagon assumes no liability or responsibility to any person or company for direct or indirect
damages resulting from the use of any information contained herein. This notice shall be marked on any reproduction of this documentation, in
whole or in part. Any reproduction or distribution of this document, in whole or in part, without the prior written consent of Hexagon is prohibited.
This software may contain certain third-party software that is protected by copyright and licensed from third party licensors. Additional terms
and conditions and/or notices may apply for certain third-party software. Such additional third-party software terms and conditions and/or notices
may be set forth in documentation and/or at http://www.mscsoftware.com/thirdpartysoftware (or successor website designated by Hexagon from
time to time).
This product includes software developed by the University of Chicago, as Operator of Argonne National Laboratory.
PCGLSS 8.0, Copyright © 1992-2023 Computational Applications and System Integration Inc. All rights reserved. Portion of this software are
owned by Siemens Product Lifecycle Management Software, Inc. © Copyright 2023.
Trademarks
The Hexagon logo, Hexagon, MSC, MSC Nastran, Adams, Dytran, Marc, Mentat, Patran, Simufact, Simufact Forming, Simufact Welding and
Simufact Additive are trademarks or registered trademarks of Hexagon AB and/or its subsidiaries in the United States and/or other countries.
Windows is a trademark or registered trademark of Microsoft Corporation in the United States and other countries.
FLEXlm and FLEXNet Publisher are trademarks or registered trademarks of Flexera Software.
Magics and Materialize are trademarks or registered trademarks of Materialize NV and/or its subsidiaries.
Contact:
http://www.simufact.com/contact
2023.2 Simufact Forming
Table of Contents
1. User subroutines ........................................................................................................ 1
1.1. FORTRAN guide (for FE-Solver) ....................................................................... 2
1.1.1. Common block ..................................................................................... 3
1.1.2. File operations ...................................................................................... 5
1.1.3. Conditional statement ............................................................................ 6
1.1.4. Loops .................................................................................................. 7
1.1.5. Domain decomposition method (DDM) ..................................................... 8
1.1.6. Debugging ......................................................................................... 10
1.2. Variable units ................................................................................................ 12
1.3. Coordinate axis ............................................................................................. 13
1.4. User subroutine and utility routines ................................................................... 13
1.4.1. Subroutine details ................................................................................ 14
1.4.2. Subroutine integration .......................................................................... 18
1.4.3. User variables, state variables and post variables ....................................... 19
1.4.4. Utility routines .................................................................................... 21
1.4.5. Common user subroutines ..................................................................... 28
1.4.6. Post codes .......................................................................................... 30
1.5. User subroutine: Examples .............................................................................. 32
1.5.1. State and post variables ........................................................................ 32
1.5.2. Motion .............................................................................................. 41
1.5.3. Damage ............................................................................................. 45
1.5.4. Friction .............................................................................................. 51
1.5.5. Table evaluation .................................................................................. 59
1.5.6. Restart with global variables ................................................................. 62
1.5.7. Electrical contact coefficient .................................................................. 69
1.6. FORTRAN- C/C++ user subroutine interface ...................................................... 72
1.6.1. The interface ...................................................................................... 72
1.6.2. Example ............................................................................................ 75
2. User defined kinematic .............................................................................................. 82
2.1. User defined kinematic v1 ............................................................................... 83
2.1.1. Graphical interface .............................................................................. 84
2.1.2. Tags and attributes .............................................................................. 89
2.1.3. The .kin Data ...................................................................................... 92
2.1.4. Example of the .kin data ....................................................................... 94
2.1.5. Solver and subroutine ........................................................................... 98
2.1.6. Example ........................................................................................... 110
2.2. Translation files ........................................................................................... 121
2.2.1. Language dependent content ................................................................ 121
2.2.2. Creating translation files ..................................................................... 122
2.3. User defined kinematic v2 ............................................................................. 124
2.3.1. Graphical interface ............................................................................. 124
2.3.2. Tags and attributes ............................................................................. 126
2.3.3. The .kin data ..................................................................................... 130
2.3.4. Example of the .kin data ..................................................................... 131
2.3.5. Solver and subroutine: sfukin2 ............................................................. 132
2.3.6. Kin file: reading and saving information ................................................ 133
2.3.7. Example ........................................................................................... 134
3. User defined material .............................................................................................. 150
3.1. User-defined material law .............................................................................. 151
3.1.1. Material information ........................................................................... 152
3.1.2. User subroutine ................................................................................. 157
3.1.3. Example ........................................................................................... 158
ii
Scientific Tutorial
2023.2
1 User subroutines
2023.2 User subroutines FORTRAN guide (for FE-Solver)
Educational Objectives
Prerequisites
Please note: In order to make use of and compile subroutines additional software is required which is not includ-
ed and not licensed as part of Simufact Forming. For example a compiler and a development environment is nec-
essary. For more detailed information on the software requirements, installation and configuration, please refer to
the Installation_guideline_Simufact_Forming_en.pdf. After installing all required external software you can test
your configuration using the subroutine compile_test.f provided in "C:\Program Files\simufact\forming\2023.2\sf-
Marc\tools\test". The usage of the subroutine is commented in the file itself. It can be used with any process.
In this manual some basic FORTRAN 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 working project file for
Simufact Forming can be accessed via the scientific branch in the Simufact demos browser. The examples will only
run successfully, in case all relevant external software is installed.
• "C:\Program Files\simufact\forming\2023.2\sfMarc\user"
Information on file units in the Marc Volume A (search for "File Units"):
2
2023.2 User subroutines Common block
• "C:\Program Files\simufact\forming\2023.2\doc\TechnicalReferences\sfMarc"
• "C:\Program Files\simufact\forming\2023.2\doc\TechnicalReferences\sfMarc"
• "C:\Program Files\simufact\forming\2023.2\sfMarc\common"
There are many common blocks that are used by the solver to store runtime information. The creeps.cmn common
block, for example, consists of all the time related variables used in the simulation. All available common blocks can
be found in the Simufact Forming installation directory at:
C:\Program Files\simufact\forming\2023.2\sfMarc\common
Please note that required parameters, e.g. the current increment, current body-id or current element-number, is often
available as an argument of the used subroutine. If it is not available, you might be able to access it through a common
block. Examples for relevant variables are:
Table 1.1.
Common-Block Variable Description
creeps.cmn timinc Duration of current increment
concom.cmn inc Current increment number
prepro.cmn kou File unit for .out-file
machin.cmn iprtl File unit for .log-file
3
2023.2 User subroutines Common block
3 icfqcp,icfcpm,icrppr,icrcha,icpb,iicpmt,iicpa
common/marc_creeps2/
x time_beg_lcase,time_beg_inc,fractol,time_beg_pst,
x fraction_donn,timinc_ol2
c
c cptim Total time at begining of increment.
c timinc Incremental time for this step.
c icfte Local copy number of slopes of creep strain rate function
c versus temperature. Is -1 if exponent law used.
c icfst Local copy number of slopes of creep strain rate function
c versus equivalent stress. Is -1 if exponent law used.
c icfeq Local copy number of slopes of creep strain rate function
c versus equivalent strain. Is -1 if exponent law used.
c icftm Local copy number of slopes of creep strain rate function
c versus time. Is -1 if exponent law used.
c icetem Element number that needs to be checked for creep
convergence
c or, if negative, the number of elements that need to
c be checked. In the latter case the elements to check
c are stored in ielcp.
c mcreep Maximum nuber of iterations for explicit creep.
c jcreep Counter of number of iterations for explicit creep
c procedure. jcreep must be .le. mcreep
c icpa(1-6) Pointer to constants in creep strain rate expression.
c icftmp Pointer to temperature dependent creep strain rate data.
c icfstr Pointer to equivalent stress dependent creep strain rate
data.
c icfqcp Pointer to equivalent creep strain dependent creep strain
c rate data.
c icfcpm Pointer to equivalent creep strain rate dependent
c creep strain rate data.
c icrppr Permanent copy of icreep
c icrcha Control flag for creep convergence checking , if set to
c 1 then testing on absolute change in stress and creep
c strain, not relative testing. Input data.
c icpb(1-4) Pointer to storage of material id cross reference numbers.
c iicpmt creep law type ID
c =1 - power law
c =2 - solder
c =3 - steady-creep
c =4 - hyperbolic steady-creep
c iicpa Pointer to table IDs for constants in creep strain rate
c expression
c
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
c timinc_old Time step of the previous increment
C
C***********************************************************************
!!
4
2023.2 User subroutines File operations
Information about some of the important variables defined in the common block are also explained through the com-
ment.
Users can also create their own local common blocks to store temporary run time information such as counter, variables
etc. This will help to preserve the stored informations when the function is revisited.
To open a file, 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.cmn. Variable kou (= unit 6) and iprtl (= unit 0) are
defined in the prepro.cmn and machin.cmn common blocks respectively. Consider the following code block:
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
character*80 filen,cline
parameter (iunit=57)
filen=jidnam(:ilen(1))//'.dbg'
In the above code, the command format is used to format the output. The arguments are:
5
2023.2 User subroutines Conditional statement
Both FORTRAN 77 and 90 standards can be used in the subroutine. FORTRAN 77 requires the command to begin
with the 7th character and finish within the 72nd character from the left. If the command is longer then the continuation
character * (compare in above example) has to be put in the next line at 6th character from the left and then the command
can continue (from 7th character). To read a file, the following code-snippets can be used in the subroutine:
Debugging
Writing into a file can be an easy way for debugging, although it can slow down the performance of your subroutine.
The file can be used, to print the current value of used variables or to print informative messages, e.g. in case a
condition is met. In order to create a file for debugging, you can specify a file unit and use the FORTRAN write
statement as follows:
open(unit=3001, name="_debug.txt")
write(3001, *) "Hello World"
where in this example 3001 is the file unit and * is used to specify that default formating should be applied. The file
is created in the _Run_-folder of the simulation.
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"
6
2023.2 User subroutines Loops
else
write(*,*) "invalid"
endif
1.1.4. Loops
Loops are used for repeated execution of a block of the code. In FORTRAN this can be achieved by a "do loop", a
"do-while loop" or a "if loop".
do loop
There are two methods to write a do loop (with and without a label):
Examples: The following code prints all even numbers between 1 to 20 in decreasing order:
do 99 i = 20, 1, -2
write(*,*) 'i =', i
99 continue
do i = 20, 1, -2
write(*,*) 'i =', i
enddo
do-while loop
The while loop is used together with a do statement. The do-while loop executes the range of the do construct until
the condition inside the while statement remains true. The do-while loop can also be written in two ways:
Example: The code prints all even numbers between 1 to 20 in decreasing order:
i=20
do while (i.gt.1)
write(*,*) 'i =', i
i = i-2
enddo
if loop
7
2023.2 User subroutines Domain decomposition method
(DDM)
goto label
endif
Example: The code prints 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
When using DDM in combination with a subroutine you have to make sure that the implications mentioned
below are considered in your subroutine.
• Each domain is a separate job and runs independently to the 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 domains will create runtime files with a domain number
as prefix in the job name.
For a DDM simulation, important domain related informations can be accessed in the user subroutine through the
following variables:
8
2023.2 User subroutines Domain decomposition method
(DDM)
= 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 the name of the *.ARC-file by the solver. Based on the job type (DDM or
non DDM), the file names 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, the calculation in all domains 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 results will then be returned to all
the domains and then the calculation will continue. The call to domflag() with dummy arguments can also used to
synchronise the domain position during calculations in case one domain might take longer time than other. In this
case the faster domains will wait for the slower domain to finish the calculations before continuing. The 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
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
9
2023.2 User subroutines Debugging
The process flow path for a DDM job during the simulation is shown in the figure below:
• marc: FEM solver runs analysis in DDM fashion and returns to sf_exeddm when remeshing is required
• sfremap: Program that merges domain-based *ARC-files, calls sfmultimesh and does the data mapping, returns to
sf_exeddm with a merged *.ARC-file
1.1.6. Debugging
It is possible to locate the cause of run-time and logical errors in a user subroutine through a debugger. With the help of
a debugger, variable values and information flow through the subroutine can be monitored during the simulation. This
helps to trace the source of a logical error in the subroutine. A detailed process to set up the debugging environment
with the debugger in Microsoft Visual Studio (2022) is described in this section. Please note that only non DDM jobs
can be debugged with this method.
1. Setup the 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 the command line. The first is a command to invoke
the Intel FORTRAN compiler and the second is to start the debugger.
Create a first batch script file and name it as intel_comp.bat, add the following two lines to it and save it in
the user path directory:
From a command line console (cmd.exe) executing intel_comp.bat should make the Intel FORTRAN compiler
accessible at the command prompt. If not, please check for the correct installation directory of the compiler and
modify the above code. Also check if the location of intel_comp.bat file is included in the local user path profile.
b. In the second batch script, set the Simufact Forming installation path available for the debugger:
@echo off
setlocal
10
2023.2 User subroutines Debugging
call intel_comp
set FORMINGDIR=C:\Program Files\simufact\forming\2023.2
set SDIR=D:\log
set BINDIR=%FORMINGDIR%\sfMarc\bin\win64i8
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 compiler environment and adds various Simufact Forming libraries to the existing
system path. At the end it calls the Visual Studio debugger with the command devenv. Running the above script
should open the Visual Studio debugger. Modify the various paths depending upon the local installation and
settings. Give the script a suitable name and store it in a folder included in the local user path profile.
2. Enable the debug flag in the Simufact Forming script: By default the debug flag is switched off in Simufact
Forming script and should be manually enabled. Go to the Simufact Forming installation directory at C:\Program
Files\simufact\forming\2023.2\sfMarc\tools, open the file include_win64i8.bat and search for
the option MARCDEBUG. Remove the REM in front of the line set MARCDEBUG=ON. The modified script should
look as:
The above modification will create the solver binary with the debug flag for the compiled subroutine code. Please
note that the job will run slower when the subroutine is compiled with the debug flag. It is recommended to switch
off the debug flag for actual simulations.
a. Setup the simulation job in Simufact Forming. Attach the user subroutine that needs to be debugged in the solver
option in the forming control.
b. Create the complete input files in the directory _Run_ of the project by submitting the job. Various job files are
created in the _Run_ directory. The simulation should then be safely stopped.
c. The _Run_ directory should contain the job input file (*.dat), the material file (*.umt), a copy of the user
subroutine and two batch files named runsf.bat and cleansf.bat. Open the file runsf.bat in a text editor and
copy and modify the script as:
The last two arguments -b no -save yes are added arguments. The argument -save yes prevents the
deletion of the executable by the Simufact Forming script after the job is completed.
d. Open a command console (cmd.exe) in the _Run_ directory and execute the above modified code in the com-
mand prompt. This should create a solver *.exe together with debug files with the extension *.pdb. The simula-
tion can be terminated once these files are created. Double-clicking on cleansf.bat will clean the _Run_ directory
with the temporary job runtime log/output files.
a. Open the Visual Studio debugger through the script described in the first step.
b. Open the created solver executable (*.exe) in Visual Studio as Project/Solution as:
11
2023.2 User subroutines Variable units
d. Add the job file name (*.dat) as project argument with the argument -j in the project properties as
5. Now the project is ready for debugging in Visual Studio. Insert break points at different sections of the user sub-
routine that need to be analysed. The debugger will pause when that portion of the subroutine is executed.
It may happen that Visual Studio complains of some missing *.dll-files or libraries. Check that the necessary runtime
dependencies/distributables are installed. If the error complains of missing functions in existing libraries then it is due
to the libraries in the system are old. Updating the program with the latest version that initially provided the libraries
should get rid of the error.
Variable units
12
2023.2 User subroutines Coordinate axis
2D
3D
13
2023.2 User subroutines Subroutine details
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. A comprehensive list of all the available subroutine files and its structure can be found
in the Marc manual "Volume D", see "C:\Program Files\simufact\forming\2023.2\doc\TechnicalReferences\sfMarc" .
Interfaces of these subroutines are compatible when used in a Simufact Forming simulation. Subroutines written in
C/C++ are also supported if the functions are embedded inside a DLL (Dynamic Link Library). For more details refer
to the section "FORTRAN-C/C++ user subroutine Interface" of this tutorial.
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 they may not be available through
subroutine's interface.
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
c 2 - oasemb loop
c 3 - oasmas loop
c 4 - ogetst loop
c 5 - scimp loop
c
return
end
The subroutine is divided into different sections. The top part contains the call arguments and the common block. Call
arguments describe the list of variables that are passed to the subroutine, for example m, n, iflag are variables that
are 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 a 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"
A list of all common blocks used internally by the solver can be found at C:\Program Files\simufact\form-
ing\2023.2\sfMarc\common. For more details about common blocks, refer to the Marc manual "Volume D".
14
2023.2 User subroutines Subroutine details
Comments in the subroutine help to explain the variables and program functionality for easier understanding and
readability of the program code. Comment lines are beginning with a character c. 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) outputs the values to the result for visualization.
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
15
2023.2 User subroutines Subroutine details
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
16
2023.2 User subroutines Subroutine details
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
if(jpltcd.eq.1)then
c get elastic strain
icode=127 !equivalent elastic strain post code
ioflag=0 !read
call elmvar1(icode,m(1),nn,kcus(1),v,ioflag)
v=v+t(2) !add 2nd saved 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 Chapter 2.
The subroutine user_fstress.f can be used to compute the flow stress based on a user equation. This subroutine supports
the material input parameters from Simufact Material and Simufact Forming.
subroutine user_fstress(ilst,ityp1,t1,ep1,er1,p1,fstress1)
c
c subroutine to compute flow stress based on user equation
c ilst(1) - material id
c ilst(2) - element id
c ilst(3) - integration point
c ilst(4) - layer id
c ilst(5) - internal layer number
c ityp1 - equation type (>100)
c Note
c This is the "Model number" defined in the GUI + 100
c E.g. If "2" is defined in the GUI, ityp1 is 102
c t1 - temperature
c ep1 - plastic strain
c er1 - plastic strain rate
c p1 - material parameters from input
c fstress1 - flow stress
The subroutine urigid_rotate.f can be used to define rotational motion during the simulation.
urigid_rotate(phix,phiy,phiz,raxis,rangle,
& rsystem,timinc,ctime,idie,node,iflag)
17
2023.2 User subroutines Subroutine integration
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
18
2023.2 User subroutines User variables, state variables and post
variables
With this convention, the subroutine always remains with the project in case of transferring it to another computer.
If the complete path or file name of the linked subroutine 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, too. A compiled solver is created in the run directory of the job when a job is run using subroutines or
alternatively can be created from the command line. This solver contains instructions from the subroutine and can be
used on machines without a FORTRAN compiler.
In addition to linking the subroutine file as above, certain subroutines require additional steps of activation from the
menu Advanced > User-defined in the forming control. When using the following subroutines: umotion, uhtcoe,
uhtcon, ufric, sepstr and sepfor, additionally have to be activated in the forming control under Advanced > User-
defined > User subroutine.
User variables are used to provide numerical input for the simulation through the GUI. This avoids manual adjustment
of the source code, when the value of the input variables changes. A possible example could be a diameter which
changes from one simulation to another. In that case a variable for this diameter can be defined in the user variables
section in the GUI. The user can change this value before starting the simulation. In the subroutine this value is
accessible through the common block "sf_userdata.cmn".
19
2023.2 User subroutines User variables, state variables and post
variables
State variables, in contrast to user variables which allow external change of one single value, can be changed only
directly through the subroutine but not externally from the GUI. However, their usage and number has to be declared in
the GUI, to make sure enough memory is allocated. State variables are used to store intermediary results or calculated
variables for each element or node at a given moment and therefore capture the state of the body at that moment. A
typical application could be a constant value which is added to each node or a user specific formula which is evaluated
for each node/element. The concept of state variables is a general concept which is also used in the solver itself, to
store the internal marc specific results. The values of these internal state variables are accessible from the subroutine
and can be used for the calculation of own result values, which can then be stored in own state variables. Please refer
to Section Post codes for more details on how to access the solver internal result variables.
Post variables can be used to display any arithmetical output in the GUI. In a typical use case the value of the state
variable is not only relevant for calculation inside the subroutine but should also be accessible as a user specific result
value in the GUI. In that case, the values of the original state variable are copied into a post variable solely available
within the subroutines upstno.f (nodal) and plotv.f (elemental). The typical work flow is as follows: The results
created in the main subroutine, e.g. ufninc (nodal) or ueloop (elemental) are written to the state variable using the
utility function ndstatvar() (nodal) or elmvar1() (elemental). The value of these state variables are then accessed from
inside the subroutine upstno (nodal) or plotv.f (elemental) using the same utility functions ndstatvar() or elmvar1() but
this time with reading flag. The obtained results are then assigned to the post variable for the solver to write into the
result file which gets displayed by the GUI. The subroutines upstno.f and plotv.f are called as often as the total number
of post variables requires. For example, for a total of 2 node variables, during the first call the result are written in
the first nodal variable and during the second call the result are written into the second nodal variable. To define the
number of required calls, the use of post variables has to be declared in the post variable section in the GUI. Also
meaningful names for each variable can be given in the post variable section. For more details, please see the example
in the section User subroutine - examples.
As shown in the figure below, all three types of variables: user variables, state variables and post variables can be
defined in the Simufact GUI. Details on the programmatic use of these variables can be found below. The numbers
in the list refers to the red numbers in the figure:
• To access these variables in a subroutine, include the common block: #include "sf_userdata.cmn"
20
2023.2 User subroutines Utility routines
• Through the above common block one can determine in the subroutine if user variables are initialized or not. If
initialized then it can be defined how many of each kind are to be initialized through:
• suserdata(i): provide content of ith string data. At present the length of the character array is set to 80.
2. State variables: The solver allocates extra memory to be used for information storage during the simulation based
on the number defined here. The state variable values can be read and written through the utility routines and post
codes. At a remeshing step the values stored in the state variables will also be mapped with the same mapping
function as other simulation variables like stress, strain etc. The values stored in these variables are of real type.
State variables can be defined for nodes as well as for elements:
• Nodal state variables for extra memory at each nodes. The 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 the elements. By default one state variable
is always initialized and is used to store the temperature. So, if the user needs 2 state variables, the value should
be set to 3. The variable nstats from hards.cmn stores the number of user-defined elemental state variables.
Relevant utility routines for accessing and writing into user-defined state variables are ndstatvar (nodal) and elm-
var1 (elemental). Please refer to the section Utility routines for more details on access of state variables and ex-
amples.
3. Post variables: These variables trigger the output of user-defined post variables through the 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.4.4.1. elmvar1()
elmvar1 should be used to extract elemental values from the simulation. It can also 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
21
2023.2 User subroutines Utility routines
Output:
var = output or save value, depending upon ioflag
1.4.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.4.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
= 1 ,first user defined node variable
ind = node number
ioflag = 0, read data
= 1, write data
Output:
var = output or save value, depending upon ioflag
1.4.4.4. get_nodvar()
get_nodvar 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
22
2023.2 User subroutines Utility routines
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.4.4.5. get_bodyid()
This utility routine extracts the contact body ID. It is important to know if the element belongs to the workpiece or to
other bodies. In a single workpiece job, the workpiece 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.4.4.6. get_material()
This utility routine extracts 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
Output:
matnum = material number
matid = material id
1.4.4.7. read_kin_version2()
read_kin_version2 is used to read the user kinematic kin file format, version 2. This routine will read rest of the kin
file and copy the information in modules to be available globally. The routine only reads second and third data block
entry. The first block is read elsewhere, so it is important to call this routine only in sfukin2 subroutine when called
with iflag=0.
read_kin_version2(ifunit,ierrcode)
Input:
ifunit = unit number of already opened kin-file
Output:
ierrcode = non zero if solver gets error reading kin file
1.4.4.8. index_info()
This integer function returns an integer value associated with the unique name used in kin file format 2. The search
is case in-sensitive.
23
2023.2 User subroutines Utility routines
index_info(uname)
Input:
uname = unique identifier word
Output:
index_info = index value where "uname" information is stored
returns -1 when no "uname" is found
1.4.4.9. get_body_bc()
This utility routine is used to get point load and fixed displacement boundary condition information for a body. Through
this information, a boundary condition of a body can be enabled and disabled on demand. Syntax of a routine is:
get_body_bc(ibd,ibc_ptld,ibc_dit)
Input:
ibd = body number
Output:
ibc_ptld = point load boundary condition index number
ibc_dit = fixed displacement boundary condition index number
The extracted boundary condition index can be saved for enabling it later, for example in force controlled bodies.
1.4.4.10. change_lcase_title()
change_lcase_title can be used to change the name of load case that appears in the .sts file.
change_lcase_title(lctitle)
Input:
lctitle = New load case title, maximum of 24 character length
1.4.4.11. sfkinbd()
To get bounding box, minimum and maximum coordinates of a body in x, y, and z direction, this utility routine can
be used. The syntax is:
sfkinbd(ibody1,xmin,xmax,iflag)
Input:
ibody1 = body id whose current min-max need to be calculated
iflag = not used. put 0
Output:
xmin(3) = minimum coordinate of body in x, y and z direction
xmax(3) = maximum coordinate of body in x, y and z direction
1.4.4.12. apply_fixed_bc()
Utility routine to apply fixed boundary condition. The syntax is:
apply_fixed_bc(ibd,ipos,vel)
24
2023.2 User subroutines Utility routines
Input:
ibd = body number
ipos = position in xkinbcvel
vel(3) = velocity (in x, y ,z)
1.4.4.13. activate_force_bc()
This logical function is used to make a body force controlled when force switch criteria are satisfied. This routine is
a logical function which returns true when the boundary condition is successfully activated. For a body to be force
activated, point load boundary condition and fixed displacement boundary condition id is required.
activate_force_bc(ibc_ptld,ibc_dit,kdir)
Input:
ibc_ptld = ptld boundary condition index for the body
ibc_dit = dit boundary condition index for the body
kdir = direction of activation (1=x-axis; 2=y-axis, 3=z-axis)
Output:
activate_force_bc = true if activation succeeds else false
1.4.4.14. calc_ring_ypos()
calc_ring_ypos can be used to determine ring thickness along y-axis (x=0) at certain height. This logical routine
search the intercept of ring mesh along:
25
2023.2 User subroutines Utility routines
calc_ring_ypos(atheight,yposition,ibodyid)
Input:
ibodyid = bodyid of ring
atheight = relative height in z direction where the y position will be
measured
Output:
yposition (4) = is a real array of size 4
returns the ring absolute y coordinate from left
calc_ring_ypos = TRUE if all the four points could be found else FALSE
The accuracy of result depend upon the mesh size of the ring. With this routine, ring diameter (inner and outer), left
and right ring thickness can be calculated.
1.4.4.15. new_position_on_arc()
This routine calculates the position of body when moved on an arc path with an angle.
new_position_on_arc(x0,y0,rad,x1,y1,beta,x2,y2)
Input:
x0,y0 = arc center coordinate (x,y)
rad = arc radius
x1,y1 = current position on arc
beta = move the point by ange beta (radian)
Output:
x2,y2 = new position(x,y)
1.4.4.16. twocirc_intersec()
This routine returns the intercept coordinates of two circle. The syntax of the routine is
twocirc_intersec(x1,y1,r1,x2,y2,r2,sx1,sy1,sx2,sy2,nintersec)
Input:
x1,y1,r1 = center x-, y-coordinate and radius of circle 1
x2,y2,r2 = center x-, y-coordinate and radius of circle 2
Output:
sx1,sy1 = x- and y-coordinates of intersection 1 (if existent)
sx2,sy2 = x- and y-coordinates of intersection 2 (if existent)
nintersec = number of intersections
1.4.4.17. get_val_table()
get_val_table can be used to evaluate table information that is entered through kinematic xml dialog. GUI writes
the table information in the dat file and the table id in the kin file. With table id and the value of first column, the
corresponding 2nd column value can be evaluated.
get_val_table(id_tab,col1,col2)
Input:
id_tab = table id
26
2023.2 User subroutines Utility routines
Output:
col2 = corresponding second column value
Solver will linearly interpolate the value between two points. Note: Only one independent variable for table is sup-
ported at present.
1.4.4.18. 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.
Input:
refval = reference value by which the output will be scaled
idtable = table id in the input file
Output:
evalue = evaluated value
The solver already has 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 a different temperature as following:
3. Call tabva2().
If the value of tempi is changed in the subroutine, then it should be reverted back to its original value.
1.4.4.19. trackmypoint()
trackmypoint can be used to extract particle information
trackmypoint(ipointid,ipostcode,results,iflag)
Input:
ipointid = particle id
ipostcode = element postcode of result variable
Output:
results = return results() array
iflag = returns extraction status as:
Positive: Successful, size of resultarray
Negative: extraction unsuccessful
-1: Something unknown went wrong
-2: Invalid point id, point id does not exist
-3: Post code not supported
-4: Point lies inside inactive element, nothing will be
calculated
Example:
For position call the routine with ipostcode =0. Coordinates (x,y,z) will be returned in xcoords(1:3) array for point
i. Value of iflag will be set to 3.
27
2023.2 User subroutines Common user subroutines
call trackmypoint(i,0,xcoords,iflag)
Please note that this routine is currently not supported for DDM.
• 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 coupled thermal and mechanical
passes where the first call is a thermal pass with flag ipass=2 followed by a mechanical with ipass=1. So care
should be taken for which pass the calculation should be done.
• ufninc() : called at the end of every increment but before the results are created for visualization.
• uedinc() : also called at the end of every increment but after the results are created for visualization.
• ueloop() : called for every element in the simulation. Also called at different stages based on the value of iflag.
With iflag=1 the routine is called after ubginc(). And before ubgpass() with iflag=5, it is called before the
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.
Users can also create local elemental/nodal loops within any subroutine. Care should be taken to filter out the elements
and/or nodes of the workpiece from those of the dies. Also refer to Marc Volume D: User Subroutines and Special
Routines - Output Quantities User Subroutines for more details about postprocessing. The flowchart below shows the
schematic of the various routine calls. This is not the complete flowchart of the simulation.
28
2023.2 User subroutines Common user subroutines
29
2023.2 User subroutines Post codes
There exist elemental as well as nodal process variables.They can be accessed and used for calculation of own result
values, see section User variables, state variables and post variables. The access to these internal state variables is
read-only. For user-defined state variables, read and write access is available. A short overview on how to access state
variables is provided below. Detailed explanations of the functions can be found in the section Utility routines.
There exist two different numberings for node and element variables: Internal (marc) and external (user) node/element
numbering. The external node/element ids are based on the actual user input (GUI) and hence can be found in the .dat-
file. The internal node/element ids are only available for the solver. They are created in the process of optimizing
the formulation of the underlying mathematical problem for numerical reasons. The external ids are unique, which is
especially relevant for DDM Jobs. The numbering for internal Ids is based on the domains, i.e. the same internal id
will exist in different domains and is therefore not unique.
Depending on the purpose and application of available utility functions, either internal or external are required as
input. During programming, it is important to make sure, which type of node/element id is available (e.g. passed
as an argument to the user defined subroutine) and which type is required by the utility routines used for querying
result values. Using the wrong type of id may result in wrong calculation results and solver crashes. For converting
internal into external node ids and vice versa the integer functions nodext() and nodint() are available. For converting
element ids, ielext() and ielint() can be used, see examples below. For more details refer to Marc Volume D: Chapter
1 Introduction in "C:\Program Files\simufact\forming\2023.2\doc\TechnicalReferences\sfMarc"
30
2023.2 User subroutines Post codes
31
2023.2 User subroutines User subroutine: Examples
State variables can be displayed in the result window through activating post variables in the forming control dialog
window. In this example, two nodal and one elemental post variables are defined to be displayed.
32
2023.2 User subroutines State and post variables
Custom names can be assigned to these variables by clicking on the "edit/show" icon ( ) on the right. The following
window will open where the number of variables and its names can be assigned. These names will be used in the
result tree (under User-defined).
33
2023.2 User subroutines State and post variables
1.5.1.1. Example
A simple 2D upsetting model is made in Simufact Forming. Two nodal and one elemental user variables are considered.
In this example, the first node variable "user-nodevar" stores the increment number and the second node variable
"outline-variable" stores 10x increment number only at the border nodes. The element variable "Total-strain" stores
34
2023.2 User subroutines State and post variables
the total strain (elastic strain + plastic strain) for every element in the model. These custom variables are listed in the
result window under User-defined.
Figure 1.15. User-defined element and node variables in the result tree
The used user subroutine is shown below. The subroutine is self-explanatory with the written comments. Four sub-
routines are used within it: ueloop() and plotv() to calculate and plot the element variables whereas ufninc() and
upstno() are used for the 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
35
2023.2 User subroutines State and post variables
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)
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
36
2023.2 User subroutines State and post variables
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
if(jpltcd.eq.1)then
c get elastic strain
icode=127 !equivalent elastic strain post code
ioflag=0 !read
call elmvar1(icode,m(1),nn,kcus(1),v,ioflag)
v=v+t(2) !add 2nd saved 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" !inocon
integer inc,ipost,jxtrac
real*8 timinc,cptim
c
c inc increment number
c timinc time step
c cptim time at begining of increment
37
2023.2 User subroutines State and post variables
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)
c saving "inc" in first node variable
call ndstatvar(istat,ind,var,ioflag)
c---------------------------------------------
istat=2
c determine boundary node, i.e. return value of inocon>0
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
38
2023.2 User subroutines State and post variables
39
2023.2 User subroutines State and post variables
return
end
This subroutine has to be specified in the forming control as shown in the following figure:
40
2023.2 User subroutines Motion
1.5.2. Motion
The user subroutine umotion can be used to define the motion of a body during the simulation. This subroutine should
only be used for bodies with velocity controlled rigid surfaces. This subroutine is called during the calculation at the
beginning of each time increment and returns the 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.
1.5.2.1. Example
A simple 2D and 3D upsetting model is set up in Simufact Forming. With the help of the subroutine umotion(),
the deformation 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 then be reversed with the user-defined velocity of 20mm/sec. The control information,
in this case die force and die velocity, are entered through the user-defined variables defined in the forming control
under Advanced > User-defined. The same subroutine is used for both simulation types (2D and 3D). Additionally
the box for the subroutine umotion has to be checked in the tab User subroutine.
41
2023.2 User subroutines Motion
Figure 1.17. User-defined real variables and subroutine in the forming control
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:
42
2023.2 User subroutines Motion
43
2023.2 User subroutines Motion
44
2023.2 User subroutines Damage
end
1.5.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 seven damage models,
i.e. Cockroft-Latham, Modified Mohr-Coulomb, Lemaitre, Oyane, Johnson-Cook, Gurson and Bonora.
However only one of them can be selected as output in the simulation. With the help of a user subroutine, multiple
user-defined damage models can be implemented simultaneously in the simulation.
45
2023.2 User subroutines Damage
1.5.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 more elemental state variables and three user-defined elemental post
variables have to be selected and defined in the forming control, as shown in the figures below:
subroutine ueloop(m1,m2,iflag)
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
46
2023.2 User subroutines Damage
#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 tension–fracture strain
c relations. Metal Science, pp. 81–83
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
c..................
c* * * * * *
c IPASS = 1 STRESS
c IPASS = 2 HEAT TRANSFER
c IPASS = 3 FLUIDS
c IPASS = 4 JOULE HEATING
47
2023.2 User subroutines Damage
c IPASS = 5 DIFFUSION
c IPASS = 6 ELECTROSTATICS
c IPASS = 7 MAGNETOSTATIC
c IPASS = 8 ELECTROMAGNETICS
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
if(iflag.eq.5.and.nstats.gt.1)then
do inn=1,nn1
layer=1
icode=17 !vonmises stress
call get_elmvar(icode,m1,m2,inn,layer,vmises)
48
2023.2 User subroutines Damage
triax=hydro/vmises
if(triax.ge.0) then
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)
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)
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
49
2023.2 User subroutines Damage
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
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(*)
return
50
2023.2 User subroutines Friction
end
In the results some negative damage values may occur. During remeshing the results of the integration points of the
old elements have to be transferred to the integration points of the new elements. This is done by interpolation and
if needed geometrically by extrapolation. This leads to some unavoidable inaccuracy and in this case to the negative
damage values.
The user may add a check to the user subroutine to force the calculated damage values to be equal or bigger than zero.
1.5.4. Friction
Through the subroutine ufric, the friction behavior of the contact surfaces between the die and the workpiece can be
changed dynamically. The ufric subroutine is called when either only shear or coulomb friction is added in the process
tree. The subroutine is called for outer elements and all nodes that lie on the workpiece surface. The subroutine only
works for node to segment contact.
1.5.4.1. Example
In the 2D upsetting example, the starting roughness value of the material is input through a real user variable in the
forming control. Based on the roughness value of the surface node, the friction coefficient is chosen in the ufric
subroutine. At the end of each increment, the roughness values for the surface nodes are changed as a function of
von Mises and contact normal stress. The changed roughness value is then used to set the friction coefficient in the
simulation for the next increment. For using ufric subroutine, an extra subroutine flag needs to be activated in the
GUI. The definition of the user subroutine and the nodal state and post variables are shown in the figures below:
51
2023.2 User subroutines Friction
subroutine ufric(mibody,x,fn,vrel,temp,yiel,fric,time,inc,nsurf)
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
52
2023.2 User subroutines Friction
#endif
real*8 xrough,xrough0
integer istat,ioflag
53
2023.2 User subroutines Friction
if(jfnold(4,nsurf).eq.3)goto 999
c #############################################################
subroutine uedinc(inc,incsub)
c called from oscinc
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
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
54
2023.2 User subroutines Friction
c
c check first if nodal state variable is defined
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
55
2023.2 User subroutines Friction
subroutine ufninc(inc,timinc,cptim,ipost,jxtrac)
c
c ###########################################################
c usersubroutine at the end of an increment before result output.
c ###########################################################
c
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
56
2023.2 User subroutines Friction
c ###########################################################
c subroutine for result output
c ###########################################################
subroutine upstno(nqcode,nodeid,valno,nqncomp,nqtype,
* nqaver,nqcomptype,nqdatatype,
* nqcompname)
57
2023.2 User subroutines Friction
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
58
2023.2 User subroutines Table evaluation
1.5.5.1. Example
A simple upsetting job is set up. To know the table id given by the Simufact Forming GUI, one should temporarily
start and stop the simulation and browse for the job *.dat- and material *.umt-file created in the _Run_ directory of
the process. Open the material input file (*.umt) in a text editor to see that various material parameters are provided in
a table as a function of the temperature. The input information about the Young's modulus from the example material
file (*.umt) is shown below:
$---------------------------------------------------------------
$ 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,
With the help of the subroutine the current values of these temperature dependent material data will be calculated and
reported at every increment during the simulation. Moreover the Young's modulus value will be converted from the
unit Pascal to Psi. The following settings are made in Forming control > Advanced > User-defined:
59
2023.2 User subroutines Table evaluation
• Check the user-defined element post variables and select three element variables and rename them accordingly
60
2023.2 User subroutines Table evaluation
The following subroutine was used to calculate the three table values and display the output. For this example only
the plotv subroutine is used. A user can implement the tabva2 utility in most of the user subroutines. The common
file, ctable.cmn, contains the list of all the independent variables that could be used for the table. In this example,
temperature is used as an independent variable in input hence the variable tempi is updated with the temperature for
the solver to extract the corresponding value.
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
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
61
2023.2 User subroutines Restart with global variables
implicit none
#else
implicit logical (a-z)
#endif
integer itableid
real*8 orig_tempi, cfactor
orig_tempi=tempi
tempi=t(1) !First state varibale is the temperature
cfactor=1.0
return
end
The solver process might be stopped at any time, e.g. through user intervention, simulation errors or for remeshing
purpose. To properly continue the simulation from a desired restart point all required history dependent information
that is needed in the next steps or increment has to be available and hence must be saved in advance. This also holds for
62
2023.2 User subroutines Restart with global variables
variables which are defined in user subroutines. There are several implemented options to ensure that this is the case.
For example when using state variables (see chapter state variables and post variables) the handling of the accessibility
is ensured by the solver. But when using own common blocks, global variables in modules or even local variables in a
subroutine, this behaviour has to be implemented by the user. Simufact Forming provides an option to store variables
in a file, with the specific ending "kin.res", which is then automatically stored in the results folder when the simulation
aborts. The information therefore remains available for the restart and only hast to be read back accordingly to their
variables.
1.5.6.1. Example
The provided example shows how to share local variables by making them global through a module and additionally
saving the content to *kin.res-file for restart purposes. Making local variables global through common blocks or
modules is a general way for sharing variables among other subroutines or transfer the results throughout multiple
calls of the same subroutine. Another method for sharing is to write the information to a file and read it back, as used
in the motion example earlier. Both methods however get problematic when a restart should be considered:
Global variables in modules are lost when the solver stops. This can already be observed for a normal simulation
when no restart behaviour is required but DDM is used. For a DDM job the simulation is internally stopped as soon as
remeshing occurs and restarted subsequently. The second method - writing information to a general file and reading
it back - will fail for restart as the Simufact Forming GUI will cleanup the run directory at the restart and so the
information gets lost. In both cases the *kin.res-file solution should be applied. The Simufact Forming GUI will
backup the kin.res file before cleaning the directory and will restore them for restart. Also if the job is copied (with
results), the kin.res file is copied, too and is available for possible restart of the job. The usage of the *kin.res-file is
demonstrated in this example.
There are two steps demonstrated: Sharing variables between subroutine calls and supporting of restart. At the end
of each increment the information will be written to the file and will be read at the beginning in case there was a
remeshing. Information that is unique for an increment and is needed for calculations in next increment, irrespective
of nodes/elements, should be saved through this method. If the user needs to store information that is node/element
specific, state variables should be used instead. The handling of state variables in case of a restart is provided by the
solver automatically. The information stored at the state variables will also be mapped to the new mesh by the solver at
the remeshing. Note: In case of result transfer between a multi stage process, the state variables are also automatically
transferred to the next stage, as long as the identical number of state variables is defined in the Forming dialog for
each process.
In this example a simple upsetting model is used. Through the subroutine, increment information is saved in a file
*kin.res. The Simufact Forming GUI will backup and replace the file if there is a job restart. If the job is restarted
from an earlier increment, the correct saved information will be retrieved by the subroutine. Users should modify the
routine depending upon the number of variables to be saved. For demonstration, a real and an integer variable are
assigned and initialized at the beginning. The variables are then linearly increased by factor of one and ten respectively
and plotted in two post variables. Users should stop the running job and restart it from an earlier increment to see if
the information are retained in the restart run. The values of the two post variables can be selected in the result view
under User-defined.
The figures below show the definition of the subroutine and of the post variables in the forming control:
63
2023.2 User subroutines Restart with global variables
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
64
2023.2 User subroutines Restart with global variables
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "cdominfo.cmn"
#include "marc_prestt.cmn"
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
65
2023.2 User subroutines Restart with global variables
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
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
66
2023.2 User subroutines Restart with global variables
integer i,idone
integer :: iunit = 18
integer :: kin_unit = 57
real*8 dummy
character*(MAX_CARD_DIM_2) filen,filen2
integer :: iunit = 18
integer :: kin_unit = 57
character*(MAX_CARD_DIM_2) filen,filen2
67
2023.2 User subroutines Restart with global variables
end
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)
x2res(1:number_real)=real_array(1:number_real)
call openfile(iunit,filen,3,0)
call sfkin2res (iunit,kin_unit,
+ number_integer,number_real,0,1,3) !append
call closefile(iunit,filen,0,2)
endif
return
end
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
68
2023.2 User subroutines Electrical contact coefficient
end
1.5.7.1. Example
A 2D-Spotwelding process from the demo and example is considered. The provided user subroutine need to be linked
to the simulation through the forming control.
User should make sure that the following modifications are carried out for all the contact pairs
entry in the contact table, for which user want the solver to calculate electrical contact conductivity
through the linked subroutine. Also the change need to be made for the same contact pairs under
different loadcases.
69
2023.2 User subroutines Electrical contact coefficient
Consider the 2nd and 3rd line from bottom and change the 4th entry from 1 to 101 so that uelcnco() subroutine is
called for this contact pair.
101 is the equation type which can be used in the user subroutine to implement different formula for different contact
interface. A different equation type for another contact pair can be used to implement different calculation formula in
the subroutine for different contact pair. Any number greater than 100 will trigger solver to call uelcnco() subroutine.
The numbers highlighted as xpar(1), xpar(2) etc. are parameters that can also be changed. The meaning of these are
described in the subroutine headers. Entry of the above two input data cards (lines) can be described as:
subroutine uelcnco(iequ,mibody,ibody1,ibody2,nodnum,xpar,
& valnod,uecc)
c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
c user subroutine to returns user electrical contact coefficient
(conductance)
c
c Based on Bay and Wanheim's model described in equation(9.26)
70
2023.2 User subroutines Electrical contact coefficient
71
2023.2 User subroutines FORTRAN- C/C++ user subroutine
interface
c Calculating resistivity
ro1=xpar(1)*xpar(4)
ro2=xpar(2)*xpar(4)
ro3=xpar(3)*xpar(4)
if(sig_n.ne.0.0d0) then
c contact resistivity, Bay-Wanheim model
uecc=1.5d0*(f_stress/sig_n)*(ro1+ro2)+ro3
return
end
• The user creates a *.dll based on the C/C++ code and puts the *.dll-file in the lib directory of the Simufact installation.
72
2023.2 User subroutines The interface
• Through the FORTRAN subroutine the above created *.dll-file is called through a function. In the argument of the
interface, the user transfers the various variables for the calculation.
A Microsoft Visual Studio project file (sfuserclib.vcxproj) will be provided for easy creation of the *.dll-file from the
C/C++ code. However the *.dll-file 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 the byte sizes for integers and real numbers.
For Linux architecture, the user has to create a dynamic library for linux with the extension .so. With the provided
*.cpp and header file (*.h, referenced in the *.cpp-file), make the library as:
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\2023.2\sfMarc\lib\win64i8 (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
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 needs to use a different t value.
• ni, nd and nc: The variables corresponding to the number of integers, doubles and characters respectively that will
be passed in the interface.
• iarray, darray and name: Arrays containing integers, doubles and characters information respectively. The size
of these arrays are ni, nd and nc respectively.
#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.
------------------------------------------------------------------*/
73
2023.2 User subroutines The interface
switch(*type)
{
case 101:
{
//Test case to print all the infromation of arrays passed from
fortran
//The values will be printed in the jobname.log file
int i;
fprintf(stderr, "Calling default user c interface for function
code %lld\n", *type);
fprintf(stderr, " integer (%lld):\n", *nbInts);
for(i=0; i < *nbInts; i++){
fprintf(stderr, "%d %lld\n",i, ints[i]);
}
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;
}
}
74
2023.2 User subroutines Example
• The variable values changed in the C/C++ function will also automatically be realized in the FORTRAN side. This
can be used to pass the complete Marc array through the interface. However the user should be careful not to change
the Marc specific array through the interface, because that 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 whereas in C/C++ it starts with 0.
1.6.2. Example
The example subroutine for a user-defined motion is modified to control the maximum force and die velocity through
the C/C++ interface. To run this example, the user should first create and link the dynamic library as explained earlier.
The user subroutine in FORTRAN calls the C/C++ interface with the case flag 1 or 2:
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
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 /)
75
2023.2 User subroutines Example
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)
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.-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
76
2023.2 User subroutines Example
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"
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)
77
2023.2 User subroutines Example
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 &
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
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!')
78
2023.2 User subroutines Example
end
#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.
*/
fprintf(stderr, "'\n");
fprintf(stderr, " returning 101\n");
return 101;
}
break;
79
2023.2 User subroutines Example
doubles[0]=6000*1000;
doubles[1]=-20*0.001;
fprintf(stderr, "Case 1 with force and velocity %lf %lf
\n",doubles[0],doubles[1]);
return 1;
}
break;
The FORTRAN subroutine and the case ID (1 or 2) to determine the maximum force and the velocity from the dll
have to be specified in the forming control under Advanced > User-defined as shown in the picture below:
Figure 1.34. Set the user subroutine and case ID in the forming control
The subroutine umotion will be used, so it has to be selected in the tab User subroutine:
80
2023.2 User subroutines Example
81
Scientific Tutorial
2023.2
Educational Objectives
Prerequisites
The idea is to extend the current graphical user interface so that the user does 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 of 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.
Simufact Forming 15 introduces a new version of the user defined kinematic (see Section 2.3). Both versions have
different functionalities so that the new version does not necessarily replace the previous one. The following chapter
explains the background and basics of the first user defined kinematic version. A lot of this applies to the new version
as well so the contents are important no matter which kinematic version is used.
With Simufact Forming 15 the data format of the XML file that describes the content and appearance of
the user defined kinematic dialog had to be changed. The new file ending is .udk (user defined kinematic
file). It is still an XML file but with a different file suffix. Please change the file suffix of already existing
.xml files to .udk. Additionally all files used by the kinematics file such as images or infosheets need
to be placed in a corresponding sub folder. Sub folder name should be equal to the base name of the
.udk file <baseName>.udk.
83
2023.2 User defined kinematic Graphical interface
With Simufact Forming 15 the definition of language settings dependent translations for the user defined
graphical user interface (GUI) is possible with the use of a so-called translation file (.tr). Their use will
be described in Section 2.2.
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.
To understand the feature, first open the standard model for rolling. This is available in the Simufact Demos:
84
2023.2 User defined kinematic Graphical interface
In the object catalog, new kinematics can be added via right mouse click Press > User-defined.
On selection, the following dialog box is opened. In this dialog all files ending with .udk present in the master library
of Simufact Forming and in the folder Additional Files of the current project are displayed. Therefore you can select
between different kinematics. In this view only default user defined kinematic of Simufact Forming can be selected.
85
2023.2 User defined kinematic Graphical interface
It can be used as a template for generating own kinematics. To understand the structure of this dialog box and its at-
tributes, we will use the corresponding template XML file named user-kinematics.udk which is present in the installa-
tion path of Simufact Forming at C:\Program Files\simufact\forming\2023.2\sfForming\Mas-
terlibrary\Kinematics. Before editing, make a copy of the existing file as a backup. When opening the user
defined press as described above, you can now select between these two kinematics. We will modify the file user-
kinematics.udk which must be opened with a text editor in order to start editing. Any editor can be used (e.g. Notepad).
However it is recommended to use an editor which supports syntax highlighting for XML, which simplifies working
on the file. In the following, this file is edited in order to explain the various possibilities.
86
2023.2 User defined kinematic Graphical interface
The file user-kinematics.udk consist of various tags. With the tags data can be classified and ordered. A tag starts with
"< >" and is closed by "< />". The tags generally come in pairs, for example:
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 assign other properties.
Close the dialog box in Simufact Forming. Then, from the above example change the value in the of the attribute
name from "User-defined kinematics" to "My Name" as
Save the modified user-kinematics.udk and then re-open the kinematics as explained above, Press > User-defined,
so now the following dialog opens:
The tags can also be used to customize input and processing of data from the user. The complete structure of the file
(without the input field shown by "[...]") is structured as follows:
87
2023.2 User defined kinematic Graphical interface
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 model. The image tag specifies the image to
be displayed in the dialog box. The image should be in the corresponding folder, which is in the same directory as the
user-kinematics.udk and has the same base name. 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 positioning of the tools or their velocity.
Inside the allPass tag, now three fields are created. One each for pusher, upper roll and lower roll. Therefore the
existing tags and attributes have to be adjusted accordingly. 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 visualized as:
dialog
allPass perPass
manipulator
The final .udk file after modification of the individual tags looks like this:
Figure 2.9. Screen-shot of the .udk file in a text editor with syntax highlighting
The above modified .udk file when opened in Simufact Forming gives the following dialog:
88
2023.2 User defined kinematic Tags and attributes
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.
1. name
The name that is used to identify the input field. It is shown in the GUI if no corresponding label is defined in
a translation file.
2. showOnly
If this attribute is enabled, the field will be grayed out with specific value. The user cannot change the value.
3. isVisible
In case 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. If no unitIndex is defined, the SI system is used by default.
89
2023.2 User defined kinematic Tags and attributes
6. valueType
7. type
8. singleStep
If the type is spinbox you can define the stepping by which the value is changed each time you click the
corresponding arrow of the spinbox.
9. values
Pre-set with the starting value for the element when the dialog box is called.
10.min
Define a minimum value this input field should have. If the input is below that value it will be highlighted in the
GUI with an orange background. The field type has to be unit or spinbox.
11.max
Define a maximum value this input field should have. If the input is above that value it will be highlighted in the
GUI with an orange background. The field type has to be unit or spinbox.
12.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 the .udk file and the 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 syntax should be as follows:
dimensionIndex="13"
Comments inside the code can be given by the following tag "<!--" and "-->":
90
2023.2 User defined kinematic Tags and attributes
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 future versions of Simufact Forming.
91
2023.2 User defined kinematic The .kin Data
In short, the concept is that there are data blocks that contain 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 of block 2 and a third of block 5. Aim of this section is to explain the complete structure of the .kin file so
that the user can examine if all 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.
92
2023.2 User defined kinematic The .kin Data
The third Data block defines the moving tools, power-driven tools at the end of the list. This block is as often repeated,
as defined in the second block at position 4.
The fourth Data block defines the stationary tools. This block is as often repeated, as defined in the second block at
position 5.
93
2023.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.
94
2023.2 User defined kinematic Example of the .kin data
Figure 2.13. 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 simulation
and cancel the simulation when program moves to "start analysis" (see bottom status bar). 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
95
2023.2 User defined kinematic Example of the .kin data
window or right click on the process icon and select Open process folder. An explorer window opens with the "_Run_"
directory. The .kin file is inside this directory. It can be opened with any text editor.
As a reminder, here are values of the kinPos attribute used in the .udk file:
• Upper roll:
kinPos="3;1"
• Lower roll:
kinPos="3;2"
• Pusher:
kinPos="3;3"
• Thickness reduction:
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
96
2023.2 User defined kinematic Example of the .kin data
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
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 note, 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 lines, for example from above the
first six printed lines are counted with only 5 lines.
Also note, that the output value from the .kin file does not exactly match with the input value. There are two reasons
for it.
• Unit conversion: The solver works in unit of meter [m] where as the input was in millimeter [mm]. Therefore 13
mm 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
97
2023.2 User defined kinematic Solver and subroutine
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
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 every additional pass, i.e. all the entries from line 16
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.
98
2023.2 User defined kinematic Solver and subroutine
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.
.dat Data
Parameters Section
.kin data
create
replaces
History Definition .kin.Hist data
(Load cases)
• 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.
99
2023.2 User defined kinematic Solver and subroutine
• 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.
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.
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.
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.
• 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.
100
2023.2 User defined kinematic Solver and subroutine
• 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.
• 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):
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:
101
2023.2 User defined kinematic Solver and subroutine
For better code readability, it is important to mention the comments and proper units even in small snippets of the
code.
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 [%]
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)
102
2023.2 User defined kinematic Solver and subroutine
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
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)
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
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.
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.
103
2023.2 User defined kinematic Solver and subroutine
104
2023.2 User defined kinematic Solver and subroutine
105
2023.2 User defined kinematic Solver and subroutine
106
2023.2 User defined kinematic Solver and subroutine
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)
xmvbd_param(11, number of moving bodies * number of heat * maximum number of passes per Heat)
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
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))
107
2023.2 User defined kinematic Solver and subroutine
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))
108
2023.2 User defined kinematic Solver and subroutine
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
109
2023.2 User defined kinematic Example
10 - blocked
11 - blocked
12 - blocked
13 - blocked
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 (Rolling -> Flat Rolling -> Hot Rolling). Four-fold sym-
metry of the roll can be exploited in the model. Following steps are required to prepare the model:
1. Delete the process 'Pass1-2D', 'Pass2-3D' and delete the stage control.
3. Delete the object 'Compressed+x' and the contact table in Process 'Pass1-3D'.
110
2023.2 User defined kinematic Example
5. Add the modified user defined press from the previous sections (right click on presses -> user-defined).
6. Add the press to the process and assign the object 'UpperRoller' and 'Pusher-1' to it.
8. Translate 'UpperRoller' by 50mm in positive z direction and center the x-position of the roll around the origin.
11.To speed up the simulation for demonstrati◘on purpose a coarser mesh can be used, e.g. element size =1.8mm.
12.Insert two symmetry planes. First in the x-y plane by z=z(min) 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:
The process tree of the model and the object window is shown in the following image.
111
2023.2 User defined kinematic Example
Figure 2.16. 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):
112
2023.2 User defined kinematic Example
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
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)
113
2023.2 User defined kinematic Example
114
2023.2 User defined kinematic Example
115
2023.2 User defined kinematic Example
116
2023.2 User defined kinematic Example
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
goto 9999
endif
if(iuk_operation.eq.0)then
ctitle='Pass1: Roll positioning'
117
2023.2 User defined kinematic Example
enddo
elseif(iuk_operation.eq.1)then
ctitle='Pass1: Workpiece positioning'
elseif(iuk_operation.eq.2)then
ctitle='Pass1: Pusher Contact'
118
2023.2 User defined kinematic Example
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
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
119
2023.2 User defined kinematic Example
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 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
120
2023.2 User defined kinematic Translation files
do i=1,(nmmvbdy+nmfixbdy)
xbdcntrls(30,i) = 1.0d0
enddo
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"
1. Use short and universally understandable names for the entries in your .udk (and therefore .kin) file and display
different, more descriptive names in the GUI.
2. Make the more descriptive names language dependent, depending on the language setting used in the Simufact
Forming GUI.
This feature is supported for both the versions of user defined kinematic, i.e. v1 and v2.
121
2023.2 User defined kinematic Creating translation files
Language Suffix
Chinese (simplified) <filename>_zh-tw
Chinese (traditional) <filename>_zh-cn
German <filename>_de
English <filename>_en
Japanese <filename>_ja
Polish <filename>_pl
Russian <filename>_ru
Turkish <filename>_tr
The logic for the language dependent content is as follows: The GUI will look for the files with the appropriate suffix
depending on the current Simufact Forming language setting. For example if your Simufact Forming GUI is set to Eng-
lish, it will first check for <yourkinematicname>_en.tr (translation file), <yourkinematicname>_en.pdf (infosheet)
and <imagenames>_en.png (images shown in the GUI; can have different file formats). If no such files are available
it will check for the same files (except the translation file) without the suffix. For example if <imagename>_en.png
does not exist it will check for <imagename>.png. The translation file is an exception to this and is only used with
the appropriate suffix.
2. Create a new file in the corresponding folder (folder has to have the same name as the .udk file and be in the same
directory). The filename should be <yourkinematicname>_<languageSuffix>.tr (e.g. mykinematic_en.tr).
3. Open Simufact Forming and set the language to be the same as <languageSuffix>.
As soon as the the dialog is opened, Simufact Forming will read the translation file. Entries that are missing from
the translation file will be automatically added. Entries that are in the translation file but no longer used in the .udk
file will be marked as obsolete and sorted to the bottom of the translation file.
122
2023.2 User defined kinematic Creating translation files
6. Open the translation file with any text editor. You will see all names used in the user defined dialog with empty
label and description elements.
When creating a new translation file please consider where the current directory is from where the .udk
file is loaded. It is only loaded from the Masterlibrary directory if you open a new project and insert
the press for the first time. As soon as you confirm the press dialog for the first time it will be saved
in the AdditionalFiles folder in this project. If you open this press again in this project it will be loaded
from there and not from the Masterlibrary. In this case a possible translation file needs to be created in
<yourProject>/AdditionalFiles/<yourkinematicname>/.
As stated in point 6, the translation file contains a label and a description entry for every name in the .udk file.
If a translation file exists for the language that Simufact Forming is currently running in, the GUI of the user defined
press will not show the name of the entry used in the .udk file, but the content of the according label in the .tr file.
The content of the description will be shown in the brief description window of the dialog. This allows to use
short names in the .udk file to keep formulas and the .kin file tidy and at the same time use longer, more descriptive
names in the GUI. Simply edit the label and description contents in the translation file as shown in the two
following figures:
123
2023.2 User defined kinematic User defined kinematic v2
The following chapter explains all the changes that were made. There will be many references to the first kinematic
version so you should be familiar with the previous chapter as well. To use the new features you have to set your
kinematics (.udk) file to version 2 as follows:
The following figure shows a sample screen shot of the user defined press of the model which was created with the
user defined kinematic v2:
124
2023.2 User defined kinematic Graphical interface
One of the main changes is the possibility to add more pages to the user defined dialog. This allows for the input of huge
numbers of input parameters while keeping everything well sorted. The single pages can be grouped in subdivisions
for a better overview. In the .udk file this is defined with the new page tag and subdivision attribute:
You can find the .udk file for this ring rolling example in the AdditionalFiles folder of the mentioned
Demos&Examples model.
From Simufact Forming 15 onwards you can use a translation file (.tr) to create a language dependent GUI. In this
translation file you can define additional descriptions for each field which will show in the brief description when you
hover your mouse pointer over the respective field. It is also possible to create language dependent infosheets which
can be directly linked to the user defined dialog. For more information about this please see Section 2.2.
It is now possible to import or export every value of the GUI from or to a CSV file. This allows for an easy filling
of big dialogs. The format of the CSV file is as follows:
125
2023.2 User defined kinematic Tags and attributes
.
TABLES <!-- marks table input-->
name
x-value1,x-value2,...
y-value1,y-value2,...
name
x-value1,x-value2,...
y-value1,y-value2,...
The name for each value corresponds to the name defined in the .udk file. The import and export always employs the
SI-m unit system. Values which are calculated by a formula will not be exported and cannot be imported. The dialog
wide import does no error checking, so the user is responsible for providing a valid input CSV file.
The perPass table is not compatible with user defined kinematic v2 and had to be removed. If you use that feature you
should stick with the previous kinematic version.
1. name
The name that is used to identify the input field. It is shown in the GUI if no corresponding label is defined in a
translation file. For kinematic v2, this name should be unique as solver will use this name to differentiate between
the entered values.
2. showOnly
If this attribute is enabled, the field will be grayed out with specific value. The user cannot change the value.
3. isVisible
In case 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. If no unitIndex is defined, the SI system is used by default.
6. valueType
7. type
8. singleStep
126
2023.2 User defined kinematic Tags and attributes
If the type is spinbox you can define the stepping by which the value is changed each time you click the
corresponding arrow of the spinbox.
9. values
Pre-set with the starting value for the element when the dialog box is called.
10.min
Define a minimum value this input field should have. If the input is below that value it will be highlighted in the
GUI with an orange background. The field type has to be unit or spinbox.
11.max
Define a maximum value this input field should have. If the input is above that value it will be highlighted in the
GUI with an orange background. The field type has to be unit or spinbox.
12.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 in the .udk file.
New attribute
13.formula
Add this attribute to entries with the type of unit and enter a formula to automatically calculate the input field
from other values. Use the name of other entries to use them for the calculation. Their type has to be either a unit
or a spinbox. A formula could look like this:
Set up like this, the GUI automatically calculates the ring thickness T_blank from the input values of the outer
diameter OD_blank and the inner diameter ID_blank (compare Figure 2.22). Note, that the entry names shown
in the GUI are different because a translation file is used.
The formula syntax is very flexible. For example you can use:
• Arithmetical operators: + , - , * , / , ^
• Functions: sin( ), cos( ), asin( ), sinh( ), lg( ), sqrt( ), abs( ), rad( ), ...
• Constants: pi, e
There are numerous checks done to ensure that the used syntax is valid. If the GUI recognizes a formula as invalid
(e. g. uses a variable name that does not exist) it will mark the field with a red background to get the users attention.
You cannot confirm a dialog that contains an invalid formula. The results that are calculated by a valid formula are
set to showOnly="true". This means they are greyed out and the user cannot enter anything in the field.
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 syntax should be as follows:
dimensionIndex="13"
127
2023.2 User defined kinematic Tags and attributes
Comments inside the code can be given by the following tag "<!--" and "-->":
128
2023.2 User defined kinematic Tags and attributes
New type
table
You can now add tabular input data to your user defined GUI. The table always consists of 2 columns. The columns
are not associated to a dimension index. This means that you can use these tables for any combination of values, as
long as your user subroutine handles them correctly. You can define default value pairs to be in the table with the
values attribute. The respective code in the .udk file might look like this:
A table entry in the .udk file will show as a table icon in the GUI. A click on the icon opens the default Simufact
Forming table dialog, where you can manually create a table, view, edit, and im- or export it:
Figure 2.23. Using tabular input data with the user defined GUI
The content of these tables will be written to the .dat file. The .kin file will contain the corresponding table ID.
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
129
2023.2 User defined kinematic The .kin data
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 future versions of Simufact Forming.
Following block should be repeated for all variables defined in 2nd block, 4th field:
130
2023.2 User defined kinematic Example of the .kin data
There are several requirements that have to be met in your corresponding .udk file. If you make a mistake there,
Simufact Forming will prompt a warning message when opening the press dialog. The requirements are:
• All names have to be unique. However, labels in the translation file (which are shown in the GUI) do not have to be.
• Maximum length of a unique name is 20 characters. See kin file format: 3rd data block, 1st field: A, 1-20.
• Unique names and other strings should not contain '$' (.dat and .kin comment) or ',' (.dat and .kin field separator).
• All entries are stored in kinPos="3;x". You have to use an ascending order starting at "kinPos=3;1",
followed by "kinPos="3;2", "kinPos="3;3", etc. for each page.
• If comboboxes are used to select tool geometries, the values entry must not be fixed. It should be moved or
omitted altogether. No matter if it is actually moved by a press or not.
'$' comments are continuously allowed and will be used to separate the .kin file for easier readability. Every page of
your dialog, as well as every separator line will be automatically added as a comment.
Please see the next chapter for an example .kin file using the new format.
Also notice that the unique name is the name, defined in the .udk file. The translated name, defined as a label in the
translation file will also be written to the respective entry in the .kin file to allow for a good readability. In comparison
to the previous kinematic version, the order of the entries is more straight forward. Because every entry of every page
starts with kinPos="3;1", they are written to the .kin file in the same order as they are written in the .udk file.
Solver uses the unique name as identifier in this kin format compared to earlier one. Order of variables written in the
kin file is not important for the solver. So, a new variables or page can be added later to the GUI without affecting
the earlier written subroutines.
131
2023.2 User defined kinematic Solver and subroutine: sfukin2
$ user kinematic
USERKIN,2,
In above example, line beginning with '$' symbol is considered as a comment line and will be ignored by the solver.
In the second line the word "USERKIN,2," informs the solver that the kin file format is for a user-kinematic, version
2. With this information solver will call the kinematic routine sfukin2(). Interface of the sfukin2() is as shown below:
subroutine sfukin2(x,f,v,time,dtime,nsurf,kin_unit,iunit,iflag)
use userkinmodule
c-------------------------------------------------------------
c user subroutine to control user defined kinematic, version 2
c-------------------------------------------------------------
c iunit - unit number for _kin.res (=18)
c kin_unit - unit number for .kin file (=57)
c
c iflag = 0 initialize routine and read data
c called at beginning, increment 0
c also called at beginning after ddm remeshing
c iflag = 1 calculates velocity
c called at every increment, for each cycle and each body (nsurf)
c
c iflag = 2 called at end of increment only once without body information
The sfukin2() routine will be called multiple times during the simulation runtime. These call can be differentiated
by the value of variable iflag.
132
2023.2 User defined kinematic Kin file: reading and saving informa-
tion
• iflag=0: called only once at increment 0 at the beginning of simulation. In this call, rest of the kin file should be read
and saved in the memory. Also, initialization of various runtime flags, memory allocations should be done during
this call. For restart support, this call should be used to read the earlier saved variables.
• iflag=1: called at each cycle during the increment. Within each cycle, the routine is separately called for each body
present in the simulation. So, if the simulation contains 7 bodies, then this routine will be called 7 times with different
body id defined by nsurf. Value of nsurf can be used to know for which body the call is being made. Only during
this call, velocity of the body defined locally will be used by the solver to move the body. Both linear and rotational
velocity can be provided during the call.
• iflag=2: called only once at the end of each increment. This call should be used to output process logs and saving
important process information for next increment or restart.
In case of parallel DDM job, each domain will call the routine separately in parallel. The routine interaction with the
solver is explained by the sketch below
Solver
sfukin2 FEM
(.F) Calculation Results
call read_kin_version2(kin_unit,kinerror)
kinerror will be non-zero in case error occurs during reading the kin file. This can be used to stop the simulation and
investigate the cause of error. The information from, 2nd and 3rd data block of kin file is read by above routine and
stored in several variables inside global module name userkinmodule.
For example, the information of second data block from a kin file
0,0,0,30,0,18,6,2,
ival2ndblock(1) = 0
ival2ndblock(2) = 0
133
2023.2 User defined kinematic Example
ival2ndblock(3) = 0
ival2ndblock(4) = 30
ival2ndblock(5) = 0
ival2ndblock(6) = 18
ival2ndblock(7) = 6
ival2ndblock(8) = 2
Solver will then use the value of 4th integer values above to allocate the memory for storage of information for 3rd
data block onwards. In above example, solver will allocate various arrays of length 30 and will read the subsequent
kin files. Solver uses six arrays to save the information of all the 3rd block input. For example consider the following
lines from the kin file
D_CR_L,7,0,0.00000E+0,Diameter,auto,
R_CR_L,2,0,3.85000E-1,Radius,,
H_CR_L,2,0,3.80000E-1,Height,,
The above information will be read and stored in various array as shown in figure below.
Index
i D_CR_L 7 0 0.00E+00 Diameter auto
subroutine sfukin2(x,f,v,time,dtime,nsurf,kin_unit,iunit,iflag)
use userkinmodule
Unique variable name assigned in xml file is used to identify the array index information. A utility routine, index_info,
can be used to get the array index information of D_CR_L in above example. With the array information.
idx_height1=index_info('H_CR_L')
The extracted index information, idx_height1, should be saved in a common block so that the search is done only
once and not repeated every time. Also note the search is case insensitive. All the 3rd block informations from kin
file will be available in subroutine as
2.3.7. Example
To view the example please open the User kinematics 2: ring rolling model from the Demos&Examples browser
in the scientific category:
134
2023.2 User defined kinematic Example
135
2023.2 User defined kinematic Example
Figure 2.28. Comparison between user-defined GUI and respective .udk file
As explained in the previous chapter, it is possible to show translated names (labels) in the GUI instead of the unique
names used in the .udk file (and transferred to the .f subroutine via the .kin file). The respective .tr translation files
which control that are also located in the Additional files folder. Following a comparison between the English .tr file
and the .udk file:
136
2023.2 User defined kinematic Example
• Finish dimension - Outer diameter: Acts as the single termination criteria. When this ring diameter is reached,
the simulation stops.
• Die association: Select which die component in the process covers which role of the ring rolling tools.
• Angular velocity of main roll: Basis for the calculation of the axial roll velocities.
• Axial roll angle: Required for the calculation of the axial roll rotational velocities.
• Radial and axial rolling curves: Required table input to control radial and axial reduction as functions of current
ring diameter or ring thickness.
• Centering rolls geometries: Required to calculate the circular path on which the centering rolls will move.
• Main roll
• Mandrel
• Rotating freely
• Axial rolls
• Axial frame movement /Y-velocity is synchronized with ring growth (ring position between axial rolls is al-
ways constant)
• Centering rolls
• Rotating freely
You can change the die geometries to adapt this model to your own ring rolling process. If you want to use profiled
geometries you will have to adapt the control routine to account for this change. You can additionally implement your
own control algorithm to make the subroutine more realistic. The subroutine supports DDM and restart functionality.
This has to be considered, when adapting it to your need. Please note that for any changes in the subroutine, a compiler
is needed, to update the solver executable. The compilation of the subroutine has to be specified in the Forming Control.
1. iflag=0
The call will be done once at the beginning at zero increment. In the provided example, following actions are done.
137
2023.2 User defined kinematic Example
• extracting the index information of important input variables and saving in local common block for later use
• Memory allocation for bodies that should freely rotate based on the contact. Die insert should be used in the model
setting for these bodies. After memory allocation, the control node of translation, jfnold(1,bodyid), is saved in
the kinbcnd for the motion. The velocity of these bodies should then be applied through apply_fixed_bc()
routine.
2. iflag=1
The call is made at every cycle within an increment. Furthermore the call will be made for each body (nsurf) in the
simulation. Analysing the nsurf, the following actions are done.
• If called for workpiece, calculations based on the rolling curves which are time dependent are done and stored
for later use.
• First the outer diameter is calculated by averaging the bounding box dimensions. Additionally the workpiece
center coordinates are stored.
• The positioning of the axial rolls with respect to the workpiece position is stored, to manage the axial rolls y-
movement based on the ring growth. If the ring diameter increases, the axial rolls follow this movement.
• Ring thickness is calculated based on averaging the two workpiece thicknesses measured at the x=0 plane at
the specified z-value.
• Z-Velocity of upper axial rolls is calculated. The target height for the calculated thickness is extracted from
the table input height-thickness curve. Additionally the current height is calculated as the distance of the axial
rolls. If the height decreases, the z-velocity is set such that the height difference is achieved in this increment.
Note that the z-velocity is always negative, so the axial rolls cannot move back again.
• Calculate mandrel velocity. This is done by evaluating the ring growth velocity curve for the current diameter.
If the ring growth velocity is positive, the target diameter is calculated and the mandrel feed is determined
based on current ring thickness and a rough volume estimation.
• If called for main roll, the angular velocity from input is provided for main roll rotation.
• If called for mandrel, the calculated y-velocity (see call workpiece) is applied . As the mandrel needs free rotation,
the y-velocity needs to be applied through the fixed boundary conditions.
• If called for bottom axial roll, y- and rotational velocity is provided, which were calculated when call was made
for workpiece.
• If called for upper axial roll, the previously calculated y- and rotational velocity as well as the z-velocity is
applied.
• If called for center roll 1 or 2, the roll is moved to the target position considering intersection of two circles
for calculating the center. The velocity is applied through the application of fixed boundary conditions for free
rotation.
3. iflag=2
The call is made once at end of each increment. In the provided example following actions are done in this call:
• ring diameter is calculated to be updated for THS plot. Value of xkinbc(1) and xkinbc(2) from sfkin.cmn is
updated with current and previous ring diameter respectively.
138
2023.2 User defined kinematic Example
• current ring diameter is checked against the desired ring diameter. If the check is positive, then simulation is
stopped by setting the variable iotnum from iautcr.cmn to next increment number. Simulation will then not
continue in the next increment.
The subroutine used in the example is listed verbatim below. Several Marc specific variables have been used inside.
All the variables that have not been locally defined will be defined in the common blocs. To know more information
about it, please search the variables name against the list of common blocks under Simufact Forming installation
directory at C:\Program Files\simufact\forming\2023.2\sfMarc\common
module sfukin2_module
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
real*8 cr_l_armx, cr_l_army, cr_r_armx, cr_r_army
real*8 tang_vel_mr, term1, yoffset_ini
endmodule sfukin2_module
subroutine sfukin2(x,f,v,time,dtime,nsurf,kin_unit,iunit,iflag)
use userkinmodule
use sfukin2_module
c-------------------------------------------------------------
c user subroutine to control user defined kinematic, version 2
c-------------------------------------------------------------
c iunit - unit number for _kin.res (=18)
c kin_unit - unit number for .kin file (=57)
c
c isfkin=15: User defined kinematic version 2
c
c iflag = 0 initialize routine and read data
c called at beginning, increment 0
c also called at beginning after ddm remeshing
c iflag = 1 calculates velocity
c called at every increment, for each cycle and each body(nsurf)
c
c iflag = 2 called at end of increment only once without body information
c
c
c The below value is only true in case when call is made with iflag=1
c
c input : nsurf - surface(body) number for which data 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
139
2023.2 User defined kinematic Example
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "sfkin.cmn"
#include "concom.cmn"
#include "iautcr.cmn"
#include "machin.cmn"
#include "memory.cmn"
#include "prepro.cmn"
#include "feature.cmn"
#include "spaceco.cmn"
#include "creeps.cmn"
c ** Start of generated type statements **
c-------------------------------------------------------
integer nsurf,kin_unit,iunit,iflag
real*8 dtime,f,time, v,x
dimension x(*),v(*),f(*)
c-------------------------------------------------------
c ** End of generated type statements **
integer i,index_info,nintersec,kinerror
integer idx_height1,idx_height2,idx_length1,idx_length2
integer idx_mainroll,idx_mandrel,idx_ax_upper,idx_ax_bottom
integer idx_cr_left,idx_cr_right,idx_md_rgr_tab
integer idx_axu_tab,idx_larm_rad,idx_rarm_rad
integer idx_od,idx_id,idx_wt,idx_ht
real*8 xmin(3),xmax(3),x_mr,y_mr,yy(4)
real*8 r_thick,ring_height,axr_rvel,axr_yvel,axr_zvel,h_up_axr
real*8 r_ht,z_low,z_up,r_ht_curr,radius_mr
real*8 cr_x,cr_y,cr_r,sx1,sy1,sx2,sy2,sin_alpha,yoffset
real*8 roll_x,roll_y,arm_radius,dia_inner,half_angle
real*8 ring_dia,wp_x,wp_y,wp_r
real*8 half,z_measure,yvel_mand,rgv,d1,rt1,rt2,dx,v0
140
2023.2 User defined kinematic Example
character*20 name_ring_rolling
logical calc_ring_ypos
common/my_cmn/idx_mainroll,idx_mandrel,idx_ax_upper,kinerror,
& idx_ax_bottom,idx_cr_left,idx_cr_right,z_measure,
& idx_md_rgr_tab,idx_od,idx_id,idx_wt,idx_ht,
& idx_axu_tab,wp_x,wp_y,wp_r,idx_larm_rad,idx_rarm_rad,
& sin_alpha,axr_rvel,axr_yvel,axr_zvel,yvel_mand
c=======================================================================
if(iflag.eq.0) then
c-----------------------------------------------------------------------
c iflag = 0 Initialization
c-----------------------------------------------------------------------
ifeat(195)=0
call change_lcase_title(trim(name_ring_rolling))
call read_kin_version2(kin_unit,kinerror)
idx_md_rgr_tab=index_info('RC_MD_RGR')
idx_axu_tab=index_info('RC_AX_U')
idx_larm_rad=index_info('R_CR_L')
idx_rarm_rad=index_info('R_CR_R')
idx_od=index_info('OD_finish')
idx_id=index_info('ID_finish')
idx_wt=index_info('T_finish')
idx_ht=index_info('H_finish')
radius_mr=half*(xmax(2)-xmin(2))
idx_height1=index_info('H_CR_L')
idx_height2=index_info('H_CR_R')
idx_length1=index_info('L_CR_L')
idx_length2=index_info('L_CR_R')
141
2023.2 User defined kinematic Example
call marcfalloc(mxkinbcnd*3,8,1,pxkinbcdsp,
& 'pxkinbcdsp ',mem_none,kinerror)
call marcfalloc(mxkinbcnd*3,4,1,pkinbcnd,
& 'pkinbcnd ',mem_none,kinerror)
yoffset_ini=xmin(2)
142
2023.2 User defined kinematic Example
axr_rvel=tang_vel_mr/(term1-sin_alpha*yoffset_ini)
z_measure=rvarvalue(index_info('Z_point'))
write(iprtl,8008)z_measure
write(kou,8008)z_measure
call change_lcase_title(trim(name_ring_rolling))
call sfukin2_restart(iflag)
c=======================================================================
elseif(iflag.eq.1) then
c-----------------------------------------------------------------------
c iflag = 1 velocity calculation
c-----------------------------------------------------------------------
c skipping calculation for non mechanical pass and with
c zero time increment
axr_yvel=0.0d0
if(yoffset.lt.yoffset_ini) then
axr_yvel=(yoffset-yoffset_ini)/dtime
endif
axr_rvel=tang_vel_mr/(term1-sin_alpha*yoffset)
143
2023.2 User defined kinematic Example
rt1=yy(2)-yy(1) !left
rt2=yy(4)-yy(3) !right
r_thick=half*(rt1+rt2) !average of left and right
call sfkinbd(ivarvalue(idx_ax_upper),xmin,xmax,0)
z_up=xmin(3)
144
2023.2 User defined kinematic Example
v(4)=axr_rvel
endif
call sfkinbd(ivarvalue(idx_cr_left),xmin,xmax,0)
c Calculate roll center coordinates
cr_x=half*(xmax(1) + xmin(1)) !x
cr_y=half*(xmax(2) + xmin(2)) !y
cr_r=half*(xmax(1) - xmin(1)) !radius
arm_radius=rvarvalue(idx_larm_rad)
call twocirc_intersec(0.0d0,wp_y,(wp_r+cr_r),
& cr_l_armx,cr_l_army,arm_radius,
& sx1,sy1,sx2,sy2,nintersec)
if (nintersec.eq.2) then
c find the "left" intersection point
if (sx1.gt.sx2) then
roll_x = sx1
roll_y = sy1
else
roll_x = sx2
roll_y = sy2
endif
v(1)=(roll_x-cr_x)/dtime
v(2)=(roll_y-cr_y)/dtime
endif
call apply_fixed_bc(nsurf,2,v(1:3))
endif
arm_radius=rvarvalue(idx_rarm_rad)
145
2023.2 User defined kinematic Example
roll_x = sx2
roll_y = sy2
endif
v(1)=(roll_x-cr_x)/dtime
v(2)=(roll_y-cr_y)/dtime
endif
call apply_fixed_bc(nsurf,3,v(1:3))
endif
endif
c=======================================================================
elseif(iflag.eq.2) then
c-----------------------------------------------------------------------
c iflag = 2 End of increment call
c-----------------------------------------------------------------------
c calculate ring diameter and update for THS plot
call sfkinbd(1,xmin,xmax,0)
ring_height=xmax(3)-xmin(3)
if(calc_ring_ypos(z_measure,yy,1)) then !ring profile only along
x=0,z=mid ring
ring_dia=yy(4)-yy(1)
if(inc.eq.0) then
xkinbc(1)=ring_dia ! Outer ring diameter along y axis
xkinbc(2)=ring_dia
else
xkinbc(2)=xkinbc(1) !old diameter
xkinbc(1)=ring_dia
endif
dia_inner=yy(3)-yy(2)
r_thick=half*(yy(4)+yy(2)-yy(3)-yy(1)) !average of left and right
if(inc.eq.0) then
write(kou,8002) "initial ring dimension"
write(kou,8003) ring_dia,dia_inner,r_thick,ring_height
write(kou,8002) "desired ring dimension"
write(kou,8003) rvarvalue(idx_od),rvarvalue(idx_id),
& rvarvalue(idx_wt),rvarvalue(idx_ht)
write(kou,8004)
else
write(kou,8002) "current ring dimension"
write(kou,8003) ring_dia,dia_inner,r_thick,ring_height
146
2023.2 User defined kinematic Example
return
7001 format(/13x,'*** error enter non-zero axial roll angle',es21.13)
8001 format(13x,a,' (x,y) :',2es21.13)
8002 format(/,/10x,41('-'),/12x,a,x,'(m)',/10x,41('-'))
8003 format(12x,'outer diameter :',es21.13,/,
& 12x,'inner diameter :',es21.13,/,
& 12x,'ring thickness :',es21.13,/,
& 12x,' ring height :',es21.13)
subroutine sfukin2_restart(iflag)
use sfukin2_module
c-------------------------------------------------------
c function to create kin.res file for restart/prestate
c-------------------------------------------------------
c iflag = 0 to read back if the job is restart
c = 2 to write information on disk for prestate/restart
c
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
#include "op1.cmn"
#include "jname.cmn"
#include "sfkin.cmn"
#include "cdominfo.cmn"
#include "concom.cmn"
#include "marc_prestt.cmn"
#include "iautcr.cmn"
integer iflag,iunit
integer n_int,n_real,n_char
character*(MAX_CARD_DIM_2) filen
logical ddmjob,begin,restart
c unit number
iunit=2021
ddmjob=.false.
begin=.false.
restart=.false.
147
2023.2 User defined kinematic Example
if(inc.eq.0) begin=.true.
if(nprocd.gt.0) ddmjob=.true.
if(iprestt_data(23).gt.0) restart=.true.
c create file name, donot change the name for GUI support
if(ddmjob)then
filen=trim(jidnam_base)//'_kin.res'
else
filen=trim(jidnam)//'_kin.res'
endif
c If restart job
if(iflag.eq.0) then
if(restart) then
c open and read _kin.res
call openfile(iunit,filen,1,5)
call sfkin2res (iunit,0,0,0,0,1,1) !read
c ------------COPY BACK----
c copy back integers
iotnum=i2res(1)
if(iparent.eq.0) then
c ------------SAVE important variables----
c saving integers
i2res(1)=iotnum
c saving real/doubles
x2res(1)=cr_l_armx
x2res(2)=cr_l_army
x2res(3)=cr_r_armx
x2res(4)=cr_r_army
x2res(5)=tang_vel_mr
x2res(6)=term1
x2res(7)=yoffset_ini
x2res(8)=xkinbc(1)
x2res(9)=xkinbc(2)
c update how many integers and real are saved
148
2023.2 User defined kinematic Example
n_int=1
n_real=9
n_char=0
c -------------------------
if(begin .and. .not.restart) then
call openfile(iunit,filen,1,5)
call sfkin2res (iunit,iunit+1,n_int,n_real,n_char,1,2) !write !
change the numbers
else
call openfile(iunit,filen,3,5)
call sfkin2res (iunit,iunit+1,n_int,n_real,n_char,1,3) !append
endif
call flush(iunit)
call closefile(iunit,filen,0,2)
endif !iparent
endif !if(iflag.eq.0) then
return
end
149
Scientific Tutorial
2023.2
Educational Objectives
Prerequisites
To include the material law in the simulation, two steps have to be performed. First, various parameters for the material
equation have to be determined in the material database through Simufact Material. Second, the material equations
based on these parameters have to be described in the user subroutine user_fstress(). When the parameters are defined
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 set is assigned
with the model number 1 in Simufact Material, then the solver assigns the parameter lists with the number 101 (model
numbers 1-100 are reserved internally) and will pass these parameters along with the model number 101 (in this case)
through the call arguments in the user_fstress() function. In addition to the parameter list, current strain and strain rate
are also included in the argument list. In case that the current strain or strain rate lies beyond the defined range for the
model, the solver will provide the subroutine with only the upper or lower range value that is nearest to the actual value.
It must be noted that the solver uses temperature ranges to determine the parameter sets that should be passed through
the function arguments. If two different flow stress models are used for two different temperature ranges and there
is discontinuity between the temperature ranges, then the flow stress in the region of discontinuity will be linearly
interpolated from the two end point values of the two models. For example, if equation 1 is valid till temperature
T1_max and equation 2 is valid from temperature T2_min, then the flow stress at a temperature anywhere in between
T1_max and T2_min is obtained by linear interpolation of the flow stress values from equation 1 at T1_max and
equation 2 at T2_min, as shown in the figure below. If the material equations have an overlapping temperature range,
the system will give an error.
151
2023.2 User defined material Material information
Figure 3.1. Flow curves for different temperature ranges and linear interpolation
152
2023.2 User defined material Material information
In Simufact Forming, first import a material in the inventory window. The imported material should be the nearest
matching 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 for hot forming.
The figure below shows the inventory window with a material that can be duplicated through right mouse click and
can be renamed afterwards.
Figure 3.3. Inventory window showing process of duplicating the material file
The properties window of the new material can be opened by a double mouse click on it. The window shows various
material properties that can be modified. For the flow curve menu on the left, it shows the existing data which can be
removed by clicking on the minus "-" button on the right.
153
2023.2 User defined material Material information
After removing the existing flow curve data, choose the Flow curve approach Analytical in the drop down menu,
as marked with 1 in the figure below. 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.
154
2023.2 User defined material Material information
In the following dialog window various parameters can be entered to describe the flow curves. Press the edit button
to open the dialog window:
155
2023.2 User defined material Material information
Figure 3.6. Open the dialog window to edit the flow curve data
The dialog window for the parameter definition looks like in the figure below. The values for various parameters can
either have a constant value or can be entered through a table.
156
2023.2 User defined material User subroutine
To enter the values in the above dialog window follow the following steps:
1. Press the 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 temperature range for which the parameters specified in this window are to be used in the calculations.
Next enter the minimum and maximum values of strain and strain rate for which the model will be valid. In addition
total of maximum 16 different parameter values can be entered but not all have to be used. The 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 itype1 to pass the variable array set depending
upon the model number. itype1 is 100 plus the model number entered here. Because of this it is important to assign
a distinct model number.
5. Save the entries by clicking the apply button. To add parameters for another model, repeat the above steps from 1
- 4. Make sure that different model numbers are used for different parameter sets.
Different temperature ranges can share either the same model number (i.e. the same equation defined in user_fstress.f)
using different parameters or different model number. Both is supported and both may be reasonable depending on
the behavior of your material and your design of the user subroutine. Take care to define the material accordingly.
The new created material database can be saved in the Simufact Material database for future use through the "To
Library" option in the inventory window.
Figure 3.8. Save the created material file for future use
subroutine user_fstress(ilst,ityp1,t1,ep1,er1,p1,fstress1)
c
c subroutine to compute flow stress based on user equation
c ilst(1) - material id
157
2023.2 User defined material Example
cccccccccccccccccccccccccc
return
end
Through the above subroutine, the various parameters defined in the material information are passed to the function. In
the argument, the solver passes the model number through the variable ityp1 and parameter values through arrays 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 the variables t1, ep1 and er1 respectively. The solver will use the
temperature field to determine which equation number and corresponding sets of parameters to be made available
through the function arguments.
3.1.3. Example
The subroutine shown below calculates the flow stress through a simple power law. Two equations are defined to
calculate the flow stress. The equation number is chosen on the basis of the temperature. At low temperature the first
equation will be used whereas the second one is used for high temperatures.
subroutine user_fstress(ilst,ityp1,t1,ep1,er1,p1,fstress1)
c
c subroutine to compute flow stress based on user equation
c ilst(1) - material id
c ilst(2) - user element number
c ilst(3) - integration point
c ilst(4) - layer id
c ilst(5) - internal layer number
c ityp1 - equation type (>100)
c Note
c This is the "Model number" defined in the GUI + 100
c E.g. If "2" is defined in the GUI, ityp1 is 102
c t1 - temperature
c ep1 - plastic strain
c er1 - plastic strain rate
158
2023.2 User defined material Example
real*8 t1,ep1,er1,p1,fstress1
integer ilst,ityp1
dimension p1(*),ilst(*)
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 this example, the same simulation is set up with different temperature objects (500°C respectively 1000°C) for the
workpiece and the dies. Thus different equations are used to get the flow curve for the two cases. Two parameter sets
are defined in the material file for two temperature ranges as shown below:
159
2023.2 User defined material Example
160
Hexagon is a global leader in digital reality solutions, combining sensor,
software and autonomous technologies. We are putting data to work
to boost efficiency, productivity, quality and safety across industrial,
manufacturing, infrastructure, public sector, and mobility applications.
Copyright © 2023 Hexagon AB and/or its subsidiaries. All rights reserved. Hexagon, the Hexagon logo, and
other logos, product and service names of Hexagon and its subsidiaries are trademarks or registered
trademarks of Hexagon AB and/or its subsidiaries in the United States and/or other countries. All other
trademarks belong to their respective owners.