Difference between revisions of "Programming"

From FEAP Wiki
Jump to navigation Jump to search
 
(10 intermediate revisions by 2 users not shown)
Line 1: Line 1:
FEAP is designed to allow users to modify the code for their owm purposes.  If at all possible, users should always use the user hooks provided in the user directory.  These allow users to make custom elements, material models, new FEAP commands, et cetera.  The [http://projects.ce.berkeley.edu/feap/pmanual85.pdf programmers manual] provides an introduction to programming in FEAP.
FEAP is designed to allow users to modify the code for their owm purposes.  If at all possible, users should always use the user hooks provided in the user directory.  These allow users to make custom elements, material models, new FEAP commands, et cetera.  The [http://projects.ce.berkeley.edu/feap/pmanual_86.pdf programmers manual] provides an introduction to programming in FEAP.


To use the user hooks, it is recommended to make a copy of the relevant stub file in a separate project directory.  Then add the full path name to this edited copy to main/makefile on the OBJECTS line so that it will be built into FEAP the next time you compile it.  If you are using windows, add the copy to your executable project.  Even though there is a version of the stub file in your FEAP archive file, the compiler should use your edited copy instead of the one in the archive.
To use the user hooks, it is recommended to make a copy of the relevant stub file in a separate project directory.  Then add the full path name to this edited copy to main/makefile on the OBJECTS line so that it will be built into FEAP the next time you compile it.  If you are using windows, add the copy to your executable project.  Even though there is a version of the stub file in your FEAP archive file, the compiler should use your edited copy instead of the one in the archive.
Line 9: Line 9:


=== User Elements ===
=== User Elements ===
==== AceGen and Mathematica ====
A template has been developed for generating user elements in an automated manner using AceGen and Mathematica. The Mathematica files, the generated user elements, examples, and benchmark examples can be found on the [https://github.com/bhajay/FEAP-AceGen FEAP-AceGen] GitHub repository. Detailed documentation about the template can be found in the [http://faculty.ce.berkeley.edu/sanjay/ucb_semm_2021_01.pdf SEMM report (UCB/SEMM-20211/01)].
=== User Interface Elements ===
=== User Interface Elements ===
=== User Memory Allocation ===
=== User Memory Allocation ===
Line 78: Line 81:
=== Assembling User Contributions to the Tangent and RHS ===
=== Assembling User Contributions to the Tangent and RHS ===
=== Calling MATLAB functions from FEAP ===
=== Calling MATLAB functions from FEAP ===
MATLAB functions can be called from FEAP if you have installed the MATLAB Engine (toolbox) when you set up MATLAB on your computer.  The basic steps to getting this work are gone over below for a specific use case where I would like to use a MATLAB (*.m) file to compute a material model response for a user material.
FEAP can be coupled to [[MATLAB]] using the MATLAB Engine.  This permits the two way exchange of data between FEAP and routines written in MATLAB.  A big advantage of this is that one can leverage the vast array of MATLAB utilities (albeit while paying MATLAB's performance penalty).
 
The basics steps are as follows.  (1) Have MATLAB and the MATLAB Engine installed. (2) Create a user macro that will start the MATLAB engine.  This permits communication between the MATLAB data space and FEAP's data space using Unix sockets. (3) Set up your user material routine to send FEAP data to MATLAB to compute the material response and to receive is back from MATLAB.  (4) Edit the makefile to allow for the compilation of subroutines with special MATLAB function calls as well as linking of the main program with the MATLAB Engine.
 
'''Setup the MATLAB Engine'''
 
The code to start up the MATLAB Engine will be placed in a user macro.  To initialize the MATLAB Engine we just need to call this macro command once at the start of a FEAP run.  For concreteness we use <code>umacr6</code>.  It is important to save the file using a .F extender instead of .f, so that the compiler will run the preprocessor on it before compiling; this is all tested on a Mac which should be the same as Linux too.  In the routine there are two user customizable strings: (a) The path to the matlab executable, '/Applications/MATLAB_2019a.app/bin/matlab' in my case, and the path to where my MATLAB *.m files are located, '/Users/sg/Feap/ver86/main' in my case.  To use the macro, just type <code>MLENgine</code> at the macro prompt.
<pre>
!$Id:$
      subroutine umacr6(lct,ctl)
 
!      * * F E A P * * A Finite Element Analysis Program
 
!....  Copyright (c) 1984-2019: Regents of the University of California
!                              All rights reserved
 
!-----[--.----+----.----+----.-----------------------------------------]
!    Modification log                                Date (dd/mm/year)
!      Original version                                    01/11/2006
!      1. Remove 'prt' from argument list                  09/07/2009
!      2. Add 'uhelpfl' comment option                    19/10/2017
!      3. Add 'help' comment option - replaces 'uhelpfl'  07/01/2019
!      4. Create the ML Engine init macro                  10/16/2019
!-----[--.----+----.----+----.-----------------------------------------]
!      Purpose:  Initialize the MATLAB Engine
 
!      Inputs:
!        lct      - Command character parameters
!        ctl(3)    - Command numerical parameters
 
!      Outputs:
!        N.B.  Users are responsible for command actions.  See
!              programmers manual for example.
!-----[--.----+----.----+----.-----------------------------------------]
      implicit  none
 
#    include "fintrf.h"
#    include "mleng.h"
 
      include  'iofile.h'
      include  'umac1.h'
 
      mwPointer engOpen
      integer :: status, engEvalString
 
      character (len=15) :: lct
 
      logical      :: pcomp
      real (kind=8) :: ctl(3)
 
      save
 
!    Set command word
 
      if(pcomp(uct,'mac6',4)) then      ! Usual    form
        uct = 'mlen'                    ! Specify 'name'
 
      elseif(pcomp(lct,'help',4)) then  ! Write help information
 
        write(*,*) 'COMMAND: MLENgine inits Matlab Engine'
 
      elseif(urest.eq.1) then          ! Read  restart data
 
      elseif(urest.eq.2) then          ! Write restart data
 
      else                              ! Perform user operation
 
        ep = engOpen('/Applications/MATLAB_R2019a.app/bin/matlab')
 
        if (ep.eq.0) then
          write(*,*) 'WARNING: Matlab engine failed to initialize'
          call plstop
        endif
        status = engEvalString(ep,'addpath /Users/sg/Feap/ver86/main')
        if (status.ne.0) write(*,*) 'WARNING: Matlab path not set'
 
 
      endif
 
      end subroutine umacr6
</pre>
Note that this macro also includes two *.h files
<pre>
#    include "fintrf.h"
#    include "mleng.h"
</pre>
The first is a MATLAB file and is located in the MATLAB application directory.  The second, I have placed in my FEAP main directoryIt contains the pointer to the MATLAB Engine object that is returned by the <code>endOpen()</code> function call.
It contents are
<pre>
      mwPointer      ep
      common /mleng/ ep
</pre>
 
'''User material'''
 
First I need a user material input routine.  This is standard, except I am going to be lazy and not read in any material properties (they will be hard wired in the code).  I will use <code>umati6.f</code> and give it the user name <code>MLMAterial</code>.
<pre>
!$Id:$
      subroutine umati6(vtype,vv, d, ud, n1,n3)
 
!      * * F E A P * * A Finite Element Analysis Program
 
!....  Copyright (c) 1984-2019: Regents of the University of California
!                              All rights reserved
 
!-----[--.----+----.----+----.-----------------------------------------]
!    Modification log                                Date (dd/mm/year)
!      Original version                                    01/11/2006
!-----[--.----+----.----+----.-----------------------------------------]
!      Purpose: User input for material model 6
 
!      Inputs:
!        vtype  - Name of material model
!        vv(5)  - Command line real data
!        d(*)  - Program material parameter data
 
!      Outputs:
!        ud(*)  - Material parameter data for model
!        n1    - Number of history items/point (time  dependent)
!        n3    - Number of history items/point (time independent)
!-----[--.----+----.----+----.-----------------------------------------]
      implicit  none
 
      character (len=15) :: vtype
 
      logical      :: pcomp
      integer      :: n1,n3
      real (kind=8) :: vv(5),d(*),ud(*)
 
!    Set command name
 
      if(pcomp(vtype,'mat6',4)) then    ! Default  form DO NOT CHANGE
        vtype = 'mlma'                  ! Specify 'name'
 
!    Input user data and save in ud(*) array
 
      else                              ! Perform input for user data
 
      endif
 
      end subroutine umati6
 
</pre>
 
'''The stress-strain routine'''
 
The stress strain routine will be linear elastic where the material properties will be hard wired into the MATLAB routine that computes the response based on the strain.  This is done in a MATLAB <code>umatl6.m</code> file which I place in my FEAP main directory (since that is where I told MATLAB to find such files).  The files looks like:
<pre>
function [sig,dd] = umatl6(eps)
% Compute the stress and moduli
% Linear isotropic elastic material with hardwired
% Elastic properties
 
% 6x6 symmetric identity
Isym      = eye(6,6);
Isym(4,4) = 0.5;
Isym(5,5) = 0.5;
Isym(6,6) = 0.5;
 
% 6x6 id outer-product id
ooo          = zeros(6,6);
ooo(1:3,1:3) = 1.0;
 
% Lame parameters
mu    = 10;
lambd = 10;
 
% Elasticity moduli 6x6
dd = 2*mu*Isym + lambd*ooo;
 
% Stress 6x1
sig = dd*eps;
 
end
</pre>
It expects a 6x1 strain vector and returns a 6x1 stress vector and a 6x6 modulus matrix.  My FEAP user material subroutine will call this MATLAB function with the strain and receive back the stress and modulus.  Since I am using user material 6, I place my FEAP code in <code>umatl6.F</code>; note the .F extender so that the preprocessor does its job correctly.
<pre>
!$Id:$
      subroutine umatl6(eps,theta,td,d,ud,hn,h1,nh,ii,istrt, sig,dd,isw)
!    subroutine umatl6( f ,detf ,td,d,ud,hn,h1,nh,ii,istrt, sig,dd,isw)
 
!      * * F E A P * * A Finite Element Analysis Program
 
!....  Copyright (c) 1984-2019: Regents of the University of California
!                              All rights reserved
 
!-----[--.----+----.----+----.-----------------------------------------]
!    Modification log                                Date (dd/mm/year)
!      Original version                                    01/11/2006
!-----[--.----+----.----+----.-----------------------------------------]
!    Purpose: User Constitutive Model 6
 
!    Input:
!          eps(*)  -  Current strains at point      (small deformation)
!                  -  Deformation gradient at point (finite deformation)
!          theta  -  Trace of strain at point
!                  -  Determinant of deformation gradient
!          td      -  Temperature change
!          d(*)    -  Program material parameters (ndd)
!          ud(*)  -  User material parameters (nud)
!          hn(nh)  -  History terms at point: t_n
!          h1(nh)  -  History terms at point: t_n+1
!          nh      -  Number of history terms
!          ii      -  Current point number
!          istrt  -  Start state: 0 = elastic; 1 = last solution
!          isw    -  Solution option from element
 
!    Output:
!          sig(*)  -  Stresses at point.
!                    N.B. 1-d models use only sig(1)
!          dd(6,*) -  Current material tangent moduli
!                    N.B. 1-d models use only dd(1,1) and dd(2,1)
!-----[--.----+----.----+----.-----------------------------------------]
      implicit none
 
#    include "fintrf.h"
#    include "mleng.h"
 
      mwPointer mxCreateDoubleMatrix, engGetVariable
      mwPointer ml_eps, ml_sig, ml_dd
      mwSize    N, M
#if MX_HAS_INTERLEAVED_COMPLEX
      mwPointer mxGetDoubles
#else
      mwPointer mxGetPr
#endif
 
      integer      :: status, engPutVariable, engEvalString
 
      integer      :: nh,istrt,isw, ii
      real (kind=8) :: td
      real (kind=8) :: eps(*),theta(*),d(*),ud(*),hn(nh),h1(nh)
      real (kind=8) :: sig(*),dd(6,*)
 
      if (isw.eq.3 .or. isw.eq.6 .or. isw.eq.4 .or. isw.eq.8) then
!    Compute and output stress (sig) and (moduli)
 
      ! Initialize Matlab data space (should be done just once
      ! instead of each time with a destroy).  Important use
      ! mwSize typed variables for all sizes
      N = 6
      M = 1
      ml_eps = mxCreateDoubleMatrix(N,M,0)
 
      ! Copy strains to Matlab data space
#if MX_HAS_INTERLEAVED_COMPLEX
      call mxCopyReal8ToPtr(eps, mxGetDoubles(ml_eps), N)
#else
      call mxCopyReal8ToPtr(eps, mxGetPr(ml_eps), N)
#endif     
 
      ! Place data in the MATLAB workspace (should pass along d, ud, hn, h1)
      status = engPutVariable(ep, 'eps', ml_eps)
      if (status.ne.0) then
        write(*,*) 'WARNING: sending strain to Matlab failed'
      endif
 
      ! Call the Matlab stress-strain function
      status = engEvalString(ep,'[sig,dd] = umatl6(eps);')
      if (status.ne.0) then
        write(*,*) 'WARNING: mymat.m eval failed'
      endif
 
      ! Get the stress and tangent from Matlab
      ml_sig = engGetVariable(ep, 'sig')
      ml_dd  = engGetVariable(ep, 'dd')
#if MX_HAS_INTERLEAVED_COMPLEX
      call mxCopyPtrToReal8(mxGetDoubles(ml_sig), sig,  N)
      call mxCopyPtrToReal8(mxGetDoubles(ml_dd ), dd , N*N)
#else
      call mxCopyPtrToReal8(mxGetPr(ml_sig), sig,  N)
      call mxCopyPtrToReal8(mxGetPr(ml_dd ), dd , N*N)
#endif
 
      call mxDestroyArray(ml_eps)
      call mxDestroyArray(ml_sig)
      call mxDestroyArray(ml_dd )
 
      endif
 
      end subroutine umatl6
</pre>
There is a lot to be explained here, best is to review the MATLAB Engine documentation, but here are a few main points.  (1) For every variable that you will send to MATLAB you need to create a pointer to its MATLAB version.  This is done with the function <code>mxCreateDoubleMatrix()</code> for double precision arrays.  It takes 3 arguments, number of rows, number of columns, and flag for if it is complex or not.  This command creates the pointer.  The MATLAB pointer is hooked to your FEAP Fortran array using <code>mxCopyReal8ToPtr()</code> (the syntax of which depends on you MATLAB version, which the preprocessor figures out).  (2) To send data from Fortran arrays to MATLAB arrays one uses the <code>engPutVariable()</code> function.  (3) To execute MATLAB commands in the MATLAB data space one uses the <code>engEvalString()</code> function.  In our case we evaluate the MATLAB function <code>umatl6()</code> which we wrote.  The return values end up in <code>sig</code> and <code>dd</code> in the MATLAB data space.  (3) To retrieve the values, we first set up a pointers to these MATLAB arrays using the <code>engGetVariable()</code> function.  We then copy the data from these pointers to our FEAP Fortran arrays using the <code>mxCopyPtrToReal8()</code> function. (4) Lastly, I destroy all the pointers with <code>mxDestroyArray()</code>.
 
Note there is a bit of waste here.  I should create the pointers only once and then destroy them only once where I terminate FEAP but that requires being more sophisticated and makes it harder to understand the basic steps.
 
'''Setting the makefiles'''
 
To get this all to compile, you need to edit the makefile in FEAP's main folder.  It needs to be able to find the MATLAB system include files and the location of the MATLAB libraries.  What you see below, is what I needed on my Mac.
<pre>
include ../makefile.in
 
MLROOT = /Applications/MATLAB_R2019a.app
 
OBJECTS = feap86.o umacr6.o umatl6.o umati6.o
 
 
#OBJECTS = feap86.o
 
feap: $(OBJECTS) $(ARFEAP)
        ranlib $(ARFEAP)
        $(FF) -Wl,-no_pie -o feap $(OBJECTS) \
        $(ARFEAP) -L/$(MLROOT)/bin/maci64 \
        $(LDOPTIONS) -leng -lmx
        dsymutil feap
        @@echo "--> FEAP executable made <--"
 
#      $(ARCHIVELIB) \
#      $(ARPACKLIB) \
#      $(ARFEAP) $(LDOPTIONS)
#      @@echo "--> FEAP executable made <--"
 
# UBUNTU and other GCC loader type machines
# Replace $(ARCHIVELIB) \ by:
#    -L$(FEAPHOME8_5)/packages/arpack/archive \
#    -Wl,-whole-archive -larchive -Wl,-no-whole-archive \
# Replace $(ARPACKLIB) \ by:
#    -L$(FEAPHOME8_5)/packages/arpack \
#    -Wl,-whole-archive -larpack -Wl,-no-whole-archive \
 
clean:
        rm -f *.o
        rm -f *genmod.mod
        rm -f *genmod.f90
        @@echo "--> Files cleaned <--"
 
fclean:
        rm -f feap
        rm -r -f feap*.dSYM
        @@echo "--> Feap cleaned <--"
 
%.o: %.F
        $(FF) -c $(FFOPTFLAG) -I$(FINCLUDE)  -I$(MLROOT)/extern/include $< -o $@
 
%.o: %.f
        $(FF) -c $(FFOPTFLAG) -I$(FINCLUDE) $< -o $@
 
%.o: %.f90
        $(FF) -c $(FFOPTFLAG) -I$(FINCLUDE) $< -o $@
 
%.o: %.c
        $(CC) -c $(CCOPTFLAG) -I$(CINCLUDE) $< -o $@
 
</pre>


=== User Functions ===
=== User Functions ===
Line 429: Line 89:
=== User Utility for Sparse Arrays ===
=== User Utility for Sparse Arrays ===
=== User Macro Commands ===
=== User Macro Commands ===
==== User Macro to reset element data ====
==== User Macro to reset material data ====
Copy one of the <code>umacrXX.f</code> files from the <code>user</code> folder to your working directory.  Add the include files
If one would like to change material properties in a computation from the command line, this is possible using a [[user macro customized to change material data]].
<pre>
include 'cdat1.h'
include 'pointer.h'
include 'comblk.h'
</pre>
Set the <code>uct</code> variable to what you would like to name your macro (4 letters).  Let's say
<pre>
  uct = 'resd'
</pre>
We will call the macro as <code>resd,,ma,dl,dv</code> where <code>ma</code> will correspond to our material number and <code>dl</code> the data location that we will change, and <code>dv</code> the new data value we would like to store.
Now after the <code>else</code> place the following code
<pre>
call resdsub(hr(np(25)),nint(ctl(1)),nint(ctl(2)),ctl(3))
</pre>
This will pass the location of the element data arrays for all materials and our 3 command line parameters <code>ma,dl,dv</code> to the subroutine <code>resdsub</code>; the first two parameters are passed as nearest integers and the data arrays are at offset <code>np(25)</code> in <code>hr</code>. The subroutine <code>resdsub</code> should look like
<pre>
subroutine resdsub(d,ma,dl,dv)
implicit none
include 'cdat1.h'
integer      :: ma, dl
real (kind=8) :: d(ndd,*), dv
 
d(dl,ma) = dv
 
end
</pre>
 


=== User Mesh Manipulation Commands ===
=== User Mesh Manipulation Commands ===
Line 473: Line 106:
=== Memory ===
=== Memory ===


'''Basics'''
FEAP's [[memory]] management system is based on a fixed location in the user memory space and offsets from that location to memory blocks obtained from the operating system via calls to malloc.
 
FEAP's memory management system utilizes an offset technique.  There are two (short arrays) <code>hr( )</code> of type real*8 and <code>mr( )</code> of type integer, which are both defined in the common block <code>comblk.h</code>.  When FEAP arrays are allocated they are done so using the system <code>malloc</code>.  This is either done in the source file <code>unix/memory/cmem.c</code>, if on Linux/MAC, or in the source file <code>windows/memory/setmem.f</code>, if on windows.
 
For each FEAP array that is allocated the offset to its location in memory in units of real*8 or integer chunks of memory is stored in the array <code>np( )</code>.  Thus for the DR array, array number 26, which holds the residual, its first element is equivalent to <code>hr(np(26))</code>.  For integer arrays like IE, array number 32, which holds the element assembly information, its first element is equivalent to <code>mr(np(32))</code>.  In this way FEAP provides a functionality to access all of its internal arrays through a combined use of the common blocks <code>comblk.h</code> and <code>pointer.h</code>, which contains the <code>np( )</code> array.
 
'''Checksumming FEAP arrays'''
 
When chasing memory errors under Linux/MAC there are two utility functions that can be helpful.  In particular
<pre>
  call cmemumark(np(xx),precision,ipr)
</pre>
computes and stores a checksum of the data associated with array xx (set xx to the number of the array you are interested in, set precision to either 1 for integer arrays or 2 for reals, set ipr to 1 for 8 byte integers and 2 for 4 byte integers).  You can then check the integrity of the data relative to this checksum at any other place in the code with
<pre>
  call cmemucheck(np(xx),precision,ipr,result)
</pre>
where <code>result</code> is an integer =1 for no change and =0 if the data has changed.
 
'''Checksumming FEAP array headers'''
 
Each FEAP array when allocated is also given a header block, the integrity of the header data to each FEAP array can be checked with
<pre>
  call cmemcheck(np(xx),precision,ipr)
</pre>
 
'''GDB is your friend'''
 
Sometimes data gets overwriting in strange ways and it is very hard to track down when certain arrays are being corrupted.  The very best way to debug such problems is to use GDB (or a similar debugger).  Make sure that you have compiled the code with the option to generate symbol tables <code> -g </code> on Linux/MAC systems.  Then start the code in the debugger <code> gdb feap </code>, set breakpoints and step/continue to see what is going on.
GDB is typically installed on Linux systems and if it is not, it can be easily installed with your distributions package manager.  If you are on a Mac, here are some brief instructions to authorize [[GDB]] on your computer.
 
A really useful feature is to use the watch command to allow the program to stop whenever a particular memory address is changed.  Suppose I am interest on when the first element of the residual array DR (array 26) changes.  I would do the following
<pre>
(gdb) break pnewprob_
</pre>
to first set a break point in pnewprob where DR is allocated.
<pre>
(gdb) run
</pre>
to get going.  Then when the program stops
<pre>
(gdb) break +646
</pre>
to set a break point after the point where DR has been allocated.
Alternately your debugger may accept
<pre>
(gdb) break pnewprob.f:646
</pre>
Then,
<pre>
(gdb) run
</pre>
Then
<pre>
(gdb) p np(26)
(gdb) p &hr(1)
</pre>
to get the offset to DR and the memory address of hr(1).  Suppose these were 195297 and 0xd1ba60.  Now compute the address of the first element of DR as 195297*8 + 0xd1ba60, the multiplier is 8(bytes) since DR is a double precision real array.  Note 195297*8 = 1562376 = 0x17d708.  Adding to the base address we get 0xe99168.  Now set a watch on this memory location and continue.  The program will stop whenever this address location is altered.
<pre>
(gdb) watch *(double *)0xe99168
(gdb) c
</pre>
 
See the [https://sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints.html GDB manual watchpoint section] for additional details.
 
'''Valgrind is incredible'''
 
A second very valuable debugging tool is [http://valgrind.org/ Valgrind].  This amazing tool can track down virtually any memory issue you may have with amazing efficiency.  Your code will run quite slow in valgrind, BUT it will help you locate error very fact.  Just install from the web site or from your package manager (yum, apt, dnf, port, fink, etc.).  To run simply type
<pre>
valgrind feap
</pre>
Make sure that you have compiled your code with the symbols, <code>-g</code>.

Latest revision as of 12:07, 29 June 2023

FEAP is designed to allow users to modify the code for their owm purposes. If at all possible, users should always use the user hooks provided in the user directory. These allow users to make custom elements, material models, new FEAP commands, et cetera. The programmers manual provides an introduction to programming in FEAP.

To use the user hooks, it is recommended to make a copy of the relevant stub file in a separate project directory. Then add the full path name to this edited copy to main/makefile on the OBJECTS line so that it will be built into FEAP the next time you compile it. If you are using windows, add the copy to your executable project. Even though there is a version of the stub file in your FEAP archive file, the compiler should use your edited copy instead of the one in the archive.

It is also recommended that you obtain a good Fortran reference book, e.g. Modern Fortran Explained by Metcalf, Reid, and Cohen.

Programmers Manual

The programmers manual can be found on the FEAP project site http://projects.ce.berkeley.edu/feap.

User Elements

AceGen and Mathematica

A template has been developed for generating user elements in an automated manner using AceGen and Mathematica. The Mathematica files, the generated user elements, examples, and benchmark examples can be found on the FEAP-AceGen GitHub repository. Detailed documentation about the template can be found in the SEMM report (UCB/SEMM-20211/01).

User Interface Elements

User Memory Allocation

User Block Generation

User Body Forces

User Materials

The method to implement a user material model in FEAP has been described in Section 4.2 of FEAP Programmer Manual. Here we would like to clarify a few things in the user material model with history variables.

The time-dependent history variables

The time-dependent variables are meant to be used for quantities that change in "TIME". That is if you have a solution that advances from time to the history variables for are stored in hr(nh1) and those for are stored in hr(nh2). These can be state variables in incremental stress-strain relations. In your solution algorithm, you must use the solution commands TIME and DT. The structure of your user material model should look like this:

1. In your umati*.f routine, set n1 equals the number of history variabales per Gauss point.

2. In your umodelf.f or umatl*.f subroutine, read the history variables from the previous globally converged time step from hn(*)

3. Compute new values of history variables

4. Write your newly computed history values to h1(*) for next time step . Do not write to hn(*)!

After that, FEAP will carry out a global Newton iteration.  If the global Newton iteration is not converged, then the values you wrote to h1(*) will be discarded and your routine will be called again. You will repeat again from step 2 until it is converged. Then, the values in h1(*) will be copied over into hn(*) for use in the next time step when you execute the next TIME command.

The time-independent history variables

If the history variable does not depend in time then we consider them to be independent of "TIME", so you could use the time-independent history variables as it only stores one copy of each value instead of two in the previous case. This type of history variable is more like a status variable depending on deformation. Here is the procedure to implement such kind of history variables,

1. In your umati*.f routine, set n3 equals the number of history variables per element.

2. In your umodelf.f or umatl*.f subroutine, read the history variables from the previous globally converged time step from hr(nh3+i) where i runs from 0 to the number of history variables (per gauss point) minus one and nh3 points to the location of first history variable for the current Gauss point.

3. Compute new values of history variables.

4. Update history variables in hr(*) with the newly computed values if needed.

Initialization of history variables in element or materials routines

The history variables are initialized to zero by default. But if you want to initialize any of the history variables to non-zero values you can do this when ISW .eq. 14. For example, if we have m history variables per gauss point, then you can initialize the time-dependent history variables to 1.0d0 in your umodelf.f or umatl*.f subroutine as follows,

c... INITIALIZE HISTORY VARIABLES
        IF (ISW .EQ. 14) THEN
            do i = 1, m 
                hn(i) = 1.0d0
                h1(i) = 1.0d0  
            end do 
        END IF

For time-independent history variables,

c... INITIALIZE HISTORY VARIABLES
        IF (ISW .EQ. 14) THEN
            do i = 0, (m - 1)
                hr(nh3 + i ) = 1.0d0
            end do 
        END IF

This segment of code will be executed for each Gauss point of each element.

(Note that this page is under development)

User Debugging File Outputs

User Transient Algorithms

User Export of Tangent and Residual for Code Coupling

Set User Data for Element Plotting

Assembling User Contributions to the Tangent and RHS

Calling MATLAB functions from FEAP

FEAP can be coupled to MATLAB using the MATLAB Engine. This permits the two way exchange of data between FEAP and routines written in MATLAB. A big advantage of this is that one can leverage the vast array of MATLAB utilities (albeit while paying MATLAB's performance penalty).

User Functions

Global User Parameters

Set User Boundary Codes

User Displacement Imports

User Utility for Sparse Arrays

User Macro Commands

User Macro to reset material data

If one would like to change material properties in a computation from the command line, this is possible using a user macro customized to change material data.

User Mesh Manipulation Commands

User Mesh Generation Commands

User Plotting Commands

User Mass Allocation

User Problem Inputs

When reading user inputs from the input file it is recommended that one use a Polling Input programing style.

Setting User Additions to the Profile

User Proportional Load

User Rotational Updates

Custom User Banner Messages

User Solvers

Memory

FEAP's memory management system is based on a fixed location in the user memory space and offsets from that location to memory blocks obtained from the operating system via calls to malloc.