Difference between revisions of "Creating a Custom Imperfect Interface Law"
(18 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
This section explains how to write <tt>C++</tt> code create a custom [[Imperfect Interfaces|imperfect interface]] for use in [[NairnMPM]] along with available [[Contact Laws#Imperfect Interface Contact Laws|imperfect interface contact laws]] | This section explains how to write <tt>C++</tt> code create a custom [[Imperfect Interfaces|imperfect interface]] for use in [[NairnMPM]] along with available [[Contact Laws#Imperfect Interface Contact Laws|imperfect interface contact laws]]. | ||
== Getting Started == | == Getting Started == | ||
Line 7: | Line 7: | ||
=== Class Source Code === | === Class Source Code === | ||
Custom imperfect interface should start by duplicating <tt>NonlinearInterface.cpp</tt> and <tt>NonlinearInterface.hpp</tt> files (or the files for one of its subclasses). All custom lows should inherit from the <tt>NonlinearInterface</tt> class. The new contact law will be used along with other [[Contact Laws]] and therefore will need a unique name and ID (an integer). In the new contact law's header file, replace <tt>NONLINEARINTERFACELAW</tt> copies above with a defined constant representing the new contact law's ID (which by convention is in UPPERCASE) and replace the number in the new constant's definition with the new ID. For example: | Custom imperfect interface should start by duplicating <tt>NonlinearInterface.cpp</tt> and <tt>NonlinearInterface.hpp</tt> files (or the files for one of its subclasses). All custom lows should inherit from the [[Nonlinear Imperfect Interface|<tt>NonlinearInterface</tt> class]]. The new contact law will be used along with other [[Contact Laws]] and therefore will need a unique name and ID (an integer). In the new contact law's header file, replace <tt>NONLINEARINTERFACELAW</tt> copies above with a defined constant representing the new contact law's ID (which by convention is in UPPERCASE) and replace the number in the new constant's definition with the new ID. For example: | ||
#define MYINTERFACE 201 | #define MYINTERFACE 201 | ||
Line 38: | Line 38: | ||
<ol> | <ol> | ||
<li>Define an alias for relative path from <tt>makefile</tt> to the new material class files (in the list d) | <li>Define an alias for relative path from <tt>makefile</tt> to the new material class files (in the list d) | ||
<pre>MyMaterial = $(src)/Materials/ | <pre>MyMaterial = $(src)/Materials/MyInterface | ||
</pre> | </pre> | ||
<li>Add an object file to the list of "all compiled objects" in the form <tt> | <li>Add an object file to the list of "all compiled objects" in the form <tt>Myintefacel.o</tt>. | ||
<li>Add the new material's header file to the header file's needed to compile <tt>MaterialController.hpp</tt>. Using the alias defined in step 1, the added text will be <tt>$( | <li>Add the new material's header file to the header file's needed to compile <tt>MaterialController.hpp</tt>. Using the alias defined in step 1, the added text will be <tt>$(MyInterfacel).hpp</tt>. | ||
<li>Compile the new | <li>Compile the new contact law's source file with lines such as | ||
<pre> | <pre>MyInterfacl.o : $(MyInterface).cpp $(dprefix) $(MyInterface).hpp $(MaterialBase).hpp $(MPMBase).hpp \ | ||
$(CommonException).hpp | $(CommonException).hpp | ||
$(CC) $(CFLAGS) $(headers) -include $(prefix) $( | $(CC) $(CFLAGS) $(headers) -include $(prefix) $(MyInterface).cpp | ||
</pre> | </pre> | ||
The list of headers must include all headers explicitly (or implicitly) included in the new | The list of headers must include all headers explicitly (or implicitly) included in the new contact law's source code. The leading white space for lines 2 (and on) must use only tabs and only one tab for the final compilation line. | ||
</ol> | </ol> | ||
== Writing the | == Writing the Contact Law Class Source Code == | ||
The remaining steps can usually all be done by editing only the | The remaining steps can usually all be done by editing only the contact law's source code file. The requirements and optional methods are described in the following sections. This stage usually starts by keeping by deleting all methods in the copied file that are not listed below and then changing the class name in each definition (''e.g''., change <tt>NonlinearInterface::</tt> to <tt>MyInterface::</tt> in each method). Any methods deleted from the <tt>cpp</tt> file should have its template deleted from the <tt>hpp</tt> file as well. | ||
=== Creating Material Properties === | === Creating Material Properties === | ||
Usually a newly-created | Usually a newly-created contact law will have additional material properties than the parent law's (although reuse parent law properties when possible). To create such properties, you need to define them, allow them in input command files (''i.e.'', update the <tt>DTD</tt> file), set them in the contact law's class file, and use them in calculations. The following steps are needed: | ||
<ol> | <ol> | ||
Line 72: | Line 72: | ||
</ol> | </ol> | ||
One properties are signed, they are initialized and printed with the following methods: | |||
==== Required Initialization Methods ==== | ==== Required Initialization Methods ==== | ||
; <tt> | ; <tt>MyInterface::MyInterface(char *matName,int matID) : NonlinearInterface(matName,matID)</tt> | ||
: | : This method is the default constructor. It can initialize any custom interface properties to default values. It should als call constructor for the parent contact law class. If no defaults are needed, this method can be omitted. The <tt>MyInterface:::</tt> is the custom class name. This term is omitted from subsequent methods names (but is needed). | ||
; <tt> | ; <tt>char *InputContactProperty(char *xName,int &input,double &gScaling)</tt> | ||
: | : If <tt>xName</tt> string matches a property name for this material, set <tt>input</tt> to <tt>DOUBLE_NUM</tt> or <tt>INT_NUM</tt> (depending on the type of variable) and return a pointer to the class variable for that property. If <tt>gScaling</tt> is set, the input value will be multiplied by <tt>gScaling</tt> after it is read. If <tt>xName</tt> is not a recognized property return <tt>NonlinearInterface::InputMat(xName,input)</tt> to allow the super class to look for their valid property types (replace <tt NonlinearInterface</tt> with different name if you subclassed some other contact law). | ||
; <tt>void | ; <tt>void PrintContactLaw(void) const</tt> | ||
: This method should print all | : This method should print all properties or call a super class and then print just the new law properties. Use a style similar to other contact laws. To help in formatting, you can use the <tt>MaterialBase</tt> class method <tt>PrintProperty(label,prop,units)</tt> to print a label, a property numeric value, and units within one column. You can use several calls in sequence to get several properties on the same line. You can also call <tt>PrintProperty(text,right)</tt> to print text in a column and right or left justified if <tt>right</tt> is true or false. | ||
==== Required Accessors ==== | ==== Required Accessors ==== | ||
; <tt>const char *MaterialType(void)</tt> | ; <tt>const char *MaterialType(void)</tt> | ||
: Return a short name to describe the | : Return a short name to describe the imperfect interface law. This string is printed with contact law properties in the output of simulations. | ||
=== MPM Step Calculations === | |||
The remaining source code is to use the law in MPM calculations. Much of the work is done in the parent <tt>NonlinearInterface</tt> class. Your custom subclass only needs to return details about the contact law it self. The current implementation assumes a decoupled law that the normal and tangential forces are given by: | |||
; < | | ||
<math>T_n = f_n([u_n]) \qquad {\rm and } \qquad T_t = f_t([u_t])</math> | |||
or where normal traction <math>T_n</math> is a function only of normal interfacial discontinuity <math>[u_n]</math> and tangential traction <math>T_t</math> is a function only of tangential interfacial discontinuity <math>[u_t]</math>. This limitation may change in the future. As a result, each method defined below has two version - one for normal tractions and one for tangential tractions. | |||
== | ==== Check for Stability ==== | ||
; <tt>int CheckDnStability(double d,double m,double delta) const</tt><br><tt>int CheckDtStability(double d,double m,double delta) const</tt> | |||
: The size | : The size | ||
==== Interface Law Properties ==== | |||
=== | |||
; <tt>double GetFn(double delta,double area) const</tt><br><tt>double GetFt(double delta,double area) const</tt> | |||
: These methods (one for normal and one for tangential directions) should return the force due to the traction law at the provided the displacement discontinuity <tt>delta</tt>. The force must be in [[ConsistentUnits Command#Legacy and Consistent Units|Force units]] for given displacement in [[ConsistentUnits Command#Legacy and Consistent Units|Length units]]. Many imperfect interface laws give a traction or stress. To convert such a law to force, multiply the traction by the contact area (provided in the <tt>area</tt>). | |||
; <tt> | ; <tt>double GetFnPrime(double delta,double area) const</tt><br><tt>double GetFtPrime(double delta,double area) const</tt> | ||
: | : These methods (one for normal and one for tangential directions) should return derivative of the force due to the traction law at the provided the displacement discontinuity <tt>delta</tt>. The derivative must be in [[ConsistentUnits Command#Legacy and Consistent Units|Force units/Length units]] for given displacement in [[ConsistentUnits Command#Legacy and Consistent Units|Length units]]. Many imperfect interface laws give a traction or stress which have derivate for stress per unit length. To convert such a law proper derivative units, multiply the traction derivative by the contact area (provided in the <tt>area</tt>). | ||
; <tt>double GetFnEnergy(double delta,double tr) const</tt><br><tt>double GetFtPrime(double delta,double tr) const</tt> | |||
: These methods (one for normal and one for tangential directions) should return area under the traction law up to given displacement discontinuity in <tt>delta</tt> (in [[ConsistentUnits Command#Legacy and Consistent Units|Length units]]) at the calculated traction force in <tt>tr</tt> (in [[ConsistentUnits Command#Legacy and Consistent Units|Force units]]). The units of the return value should be [[ConsistentUnits Command#Legacy and Consistent Units|Energy units]]. Note that this current implementation of interfacial energy is based on assumption of an elastic imperfect interface. It can archived in the [[MPM Global Archiving Options|global archiving interface energy option]], but has no other affect on calculations. It does not contribute to dissipated energy and does not cause any temperature changes. Future versions of imperfect interface laws may allow for dissipated energy calculations. |
Latest revision as of 11:14, 14 April 2018
This section explains how to write C++ code create a custom imperfect interface for use in NairnMPM along with available imperfect interface contact laws.
Getting Started
The first steps are to create source files for the new interface law class, to give the law a unique name, and to allow the main NairnMPM code to instantiate the contact law to be used on cracks or in multimaterial mode.
Class Source Code
Custom imperfect interface should start by duplicating NonlinearInterface.cpp and NonlinearInterface.hpp files (or the files for one of its subclasses). All custom lows should inherit from the NonlinearInterface class. The new contact law will be used along with other Contact Laws and therefore will need a unique name and ID (an integer). In the new contact law's header file, replace NONLINEARINTERFACELAW copies above with a defined constant representing the new contact law's ID (which by convention is in UPPERCASE) and replace the number in the new constant's definition with the new ID. For example:
#define MYINTERFACE 201
All documented materials use numbers below 100. To avoid conflicts, those working on custom materials should use large numbers (>100).
Editing Required in Core Code
Almost all coding will be done in the new contact law class files, but for that law to be recognized as an option in NairnMPM, two places in the core code have to be edited first. These should be the only changes needed outside the new contact law's class files.
- Include the new contact law's header file at the top of Common/Read_XML/MaterialController.cpp:
#include "Materials/MyInterface.hpp"
or the appropriate relative path to the new contact law's header file.
- In MaterialController::AddMaterial(int matID,char *matName), add a new case in the switch(matID) section to call the default constructor of the new contact law when matID matches the new contact law's constant defined above.
case MYINTERFACE: newMaterial = new MyInterface(matName,matID); break;
If needed you can define a custom constructor and use that in this code (this need is rare).
Compiling with make Command
If you want to be able to do command-line compile using the make command, the new contact law source files need to be added to the file NairnMPM/build/makefile. The steps are best done by comparing to the NonlinearInterface entries in that makefile. The main makeFile editing steps are:
- Define an alias for relative path from makefile to the new material class files (in the list d)
MyMaterial = $(src)/Materials/MyInterface
- Add an object file to the list of "all compiled objects" in the form Myintefacel.o.
- Add the new material's header file to the header file's needed to compile MaterialController.hpp. Using the alias defined in step 1, the added text will be $(MyInterfacel).hpp.
- Compile the new contact law's source file with lines such as
MyInterfacl.o : $(MyInterface).cpp $(dprefix) $(MyInterface).hpp $(MaterialBase).hpp $(MPMBase).hpp \ $(CommonException).hpp $(CC) $(CFLAGS) $(headers) -include $(prefix) $(MyInterface).cpp
The list of headers must include all headers explicitly (or implicitly) included in the new contact law's source code. The leading white space for lines 2 (and on) must use only tabs and only one tab for the final compilation line.
Writing the Contact Law Class Source Code
The remaining steps can usually all be done by editing only the contact law's source code file. The requirements and optional methods are described in the following sections. This stage usually starts by keeping by deleting all methods in the copied file that are not listed below and then changing the class name in each definition (e.g., change NonlinearInterface:: to MyInterface:: in each method). Any methods deleted from the cpp file should have its template deleted from the hpp file as well.
Creating Material Properties
Usually a newly-created contact law will have additional material properties than the parent law's (although reuse parent law properties when possible). To create such properties, you need to define them, allow them in input command files (i.e., update the DTD file), set them in the contact law's class file, and use them in calculations. The following steps are needed:
- Define a class variable for the property in the .hpp file (usually int or double). It is best to define these properties in the protected section of the class, although public properties are sometimes needed (and are allowed).
- To allow the property in input files, select a unique property name (the name may or may not be same as variable in previous step). Define that property by name in the DTD file, usually as a simple XML element such as:
<!ELEMENT prop (#PCDATA)>
where prop is the new property name.
- Add that property's name to the list of allowed elements within the Material element definition (beginning in <!ELEMENT Material in the DTD file.
- Set some default value for the new property variable in the new material's constructor method.
One properties are signed, they are initialized and printed with the following methods:
Required Initialization Methods
- MyInterface::MyInterface(char *matName,int matID) : NonlinearInterface(matName,matID)
- This method is the default constructor. It can initialize any custom interface properties to default values. It should als call constructor for the parent contact law class. If no defaults are needed, this method can be omitted. The MyInterface::: is the custom class name. This term is omitted from subsequent methods names (but is needed).
- char *InputContactProperty(char *xName,int &input,double &gScaling)
- If xName string matches a property name for this material, set input to DOUBLE_NUM or INT_NUM (depending on the type of variable) and return a pointer to the class variable for that property. If gScaling is set, the input value will be multiplied by gScaling after it is read. If xName is not a recognized property return NonlinearInterface::InputMat(xName,input) to allow the super class to look for their valid property types (replace <tt NonlinearInterface with different name if you subclassed some other contact law).
- void PrintContactLaw(void) const
- This method should print all properties or call a super class and then print just the new law properties. Use a style similar to other contact laws. To help in formatting, you can use the MaterialBase class method PrintProperty(label,prop,units) to print a label, a property numeric value, and units within one column. You can use several calls in sequence to get several properties on the same line. You can also call PrintProperty(text,right) to print text in a column and right or left justified if right is true or false.
Required Accessors
- const char *MaterialType(void)
- Return a short name to describe the imperfect interface law. This string is printed with contact law properties in the output of simulations.
MPM Step Calculations
The remaining source code is to use the law in MPM calculations. Much of the work is done in the parent NonlinearInterface class. Your custom subclass only needs to return details about the contact law it self. The current implementation assumes a decoupled law that the normal and tangential forces are given by:
[math]\displaystyle{ T_n = f_n([u_n]) \qquad {\rm and } \qquad T_t = f_t([u_t]) }[/math]
or where normal traction [math]\displaystyle{ T_n }[/math] is a function only of normal interfacial discontinuity [math]\displaystyle{ [u_n] }[/math] and tangential traction [math]\displaystyle{ T_t }[/math] is a function only of tangential interfacial discontinuity [math]\displaystyle{ [u_t] }[/math]. This limitation may change in the future. As a result, each method defined below has two version - one for normal tractions and one for tangential tractions.
Check for Stability
- int CheckDnStability(double d,double m,double delta) const
int CheckDtStability(double d,double m,double delta) const - The size
Interface Law Properties
- double GetFn(double delta,double area) const
double GetFt(double delta,double area) const - These methods (one for normal and one for tangential directions) should return the force due to the traction law at the provided the displacement discontinuity delta. The force must be in Force units for given displacement in Length units. Many imperfect interface laws give a traction or stress. To convert such a law to force, multiply the traction by the contact area (provided in the area).
- double GetFnPrime(double delta,double area) const
double GetFtPrime(double delta,double area) const - These methods (one for normal and one for tangential directions) should return derivative of the force due to the traction law at the provided the displacement discontinuity delta. The derivative must be in Force units/Length units for given displacement in Length units. Many imperfect interface laws give a traction or stress which have derivate for stress per unit length. To convert such a law proper derivative units, multiply the traction derivative by the contact area (provided in the area).
- double GetFnEnergy(double delta,double tr) const
double GetFtPrime(double delta,double tr) const - These methods (one for normal and one for tangential directions) should return area under the traction law up to given displacement discontinuity in delta (in Length units) at the calculated traction force in tr (in Force units). The units of the return value should be Energy units. Note that this current implementation of interfacial energy is based on assumption of an elastic imperfect interface. It can archived in the global archiving interface energy option, but has no other affect on calculations. It does not contribute to dissipated energy and does not cause any temperature changes. Future versions of imperfect interface laws may allow for dissipated energy calculations.