Вы находитесь на странице: 1из 16

Using C++ Templates to Implement Finite Element Classes MARCO L.

BITTENCOURT Departamento de Projeto Mecnico a Faculdade de Engenharia Mecnica a Universidade Estadual de Campinas P.O. Box 6051, 13083-970, Campinas, SP, Brazil e-mail: mlb@fem.unicamp.br URL: http://www.fem.unicamp.br/~mlb

Using C++ Templates to Implement Finite Element Classes

ABSTRACT This paper presents the development of object-oriented nite element classes based on the concept of parameterized types or templates of the C++ programming language. Two parameterized array classes were implemented which are used extensively in other classes. The implementation was simple resulting in a set of manageable, ecient, and simple C++ nite element classes. Initially, object-oriented programming concepts, C++ templates, and template array classes are presented. Following, the nite element classes and some examples using those classes are also discussed. Keywords: Object-oriented programming, C++, Finite element method, Multigrid methods, Structural optimization.


The productivity of the software industry is still very small compared to the increasing development of the hardware industry in the last years. Object-oriented programming (OOP) has been used to improve the quality, productivity, and re-usability of software components. In this programming paradigm, the main agents or objects of the application must be identied. The objects have data and methods which describe their features and behavior. An object-oriented program is implemented as a set of classes and the objects are created by class instantiations. Two objects or instances of the same class are dierent only by the values stored in their variables. Therefore, classes are the basic modularization unit in an object-oriented environment. Objects communicate themselves by the message mechanism. A message species only the action to be executed. Based on its methods, the receiving object must interpret the message, execute the respective set of operations, and return the result to the sending instance. A class encapsulates information that is accessed only by sending messages. A message with the same name can represent dierent actions for distinct classes through the polymorphism concept. For example, the message + can be an addition for a matrix class and also a concatenation for a string class. The inheritance mechanism allows to implement class hierarchies in which lower level classes inherit data and methods of the higher levels classes. In this way, it is possible to extend and reuse classes in many applications by adding new variables and methods to describe more specic concepts in the class hierarchy. In procedural languages, the application is decomposed in functions and procedures. In object-oriented programming, objects represent some behavior using data and methods which . For example, vectors and matrices are common classes for linear algebra applications. Procedures for vector dot-product and matrix multiplication are implemented as methods of those classes. OOP concepts have been applied to structural analysis such as in some initial works (Bittencourt, 1990; Feijo, Guimares and Fancello, 1991; Filho and Devloo, 1991; Forde, Foschi o a and Stiemer, 1990; Miller, 1991; Scholz, 1992; Zimmermann, Dubois-P`lerin and Bomme, 1992). e One of the rst object-oriented programs is discussed in (Forde et al., 1990) using the Object NAP language written with C and Pascal procedures. Concurrency, distributed processing, 1

database, and nite element analysis software using the Flavors extension of the LISP language are presented in (Miller, 1991). An extension of the Smalltalk class hierarchy to nite element analysis is given in (Zimmermann et al., 1992). Due to the poor eciency of the Smalltalk environment, a C++ version of the same program was developed in (Dubois-P`lerin, Zimmere mann and Bomme, 1993). An extension to plasticity problems is implemented in (Mentrey e and Zimmermann, 1993). In (Zeglinski, Han and Aitchison, 1994), class hierarchies for matrices (symmetric, sparse, column, etc) and nite element entities are described. A C++ environment with interpreter and execution modules and interactive specication of parameters for linear and non-linear problems is presented in (Cardona, Klapka and Geradin, 1994). Object-oriented aspects applied to numerical analysis, class graphical representation, database, and composite materials are presented in (Adeli and Yu, 1995; Yu and Adeli, 1993). Articial intelligence concepts for object-oriented structural analysis are discussed in (Adeli and Yu, 1995; Yu and Adeli, 1993; Tworzydlo and Oden, 1993; Tworzydlo and Oden, 1995). Some recent applications of OOP in computational mechanics can be found in (Oate, Idelsohn and E. Dvorkin, 1998). n A group of researchers has developed C++ classes for database, numerical analysis, nite elements, mesh generation, error estimation, adaptive analysis, multigrid methods, structural optimization, and data visualization (see (Bittencourt, 1996; Dari, 1994; Vnere, 1996; Fane cello, Guimares, Feijo and Venere, 1991; Feijo et al., 1991; Guimares, Fancello, Feijo and a o o a o Feijo, 1994; Silva and Bittencourt, 2000) and papers therein). This paper presents the developo ment of nite element classes using C++ templates. Initially, object-oriented concepts such as modularization, abstraction, classes, and methods are discussed. A review of C++ templates, array template classes, and nite element classes are also discussed. Finally, some examples of structural optimization, adaptive procedures, and multigrid methods developed using the C++ classes are addressed.

Object-oriented Programming Concepts

The OOP methodology consists of dening and implementing abstract data type hierarchies. Abstract types are dened by data and associated procedures to manipulate the data. In C++, abstract types are implemented by self-sucient entities called classes. An object is an instance of some class. OOP is based on abstraction, encapsulation, modularization, inheritance, and polymorphism principles whose denitions are language independent. Abstraction consists of extracting the most relevant features of the system to be modeled. It provides adequate generalization and eliminates irrelevant details. In OOP, abstraction means to list the dening characteristics of classes. It also means to state the public interface of the classes, i.e., how their objects will be accessed and interact with other objects. The encapsulation concept hides the class internal implementation while the class interface is visible. Interaction among objects is done by the message mechanism. When an object receives a message, it performs an associated method. The implementation details are not known by the client code. This means that information is hidden outside the class and its derived classes. Information hiding is very useful. For example, if the class public interface is unaltered, the data structure and methods can be changed and these modications will be assimilated automatically in other classes and application programs. When abstraction and encapsulation are used, a system can be composed by a set of weakly-coupled modules. Therefore, code updating and error detection are simplied. However, there is a suitable modularization level beyond that loss of eciency begins. The class information can be specialized using the inheritance principle. Subclasses inherit 2

the characteristics (data and methods) of their super-classes. In this way, it is possible to reuse codes in many applications with consequent reduction in development time and costs. The inheritance principle with C++ virtual classes introduces an important generalization feature. Pointers to higher level objects of the class hierarchy can represent lower levels ones in application programs. This characteristic allows to develop type-independent code with dynamic binding at runtime. New classes can be added to the hierarchy and the application code will still work with this new type. Polymorphism means that objects will answer dierently for a same message. For instance, the message + may mean concatenation and sum, respectively, for string and matrix classes. Polymorphism and inheritance allows to achieve a fairly generic code that selects the methods to be performed at runtime.

C++ Templates

The C++ language allows the denition of functions and classes for which the data types are parameters. This feature is based on the concept of template functions and classes and uses the C++ keyword template. For instance, the following C++ statements implement a parameterized function to return the minimum of two numbers (i.e., integers, oat, or double) and a test program (Lippman, 1991).
template <class Type> Type min(Type a, Type b) { return a < b ? a : b; } void main() { min(10, 20); min(10.0, 20.0) }

//minimum of two integers //minimum of two doubles

The denition of a template function begins with the template keyword. The parameter list is bracketed by the characters < and > and can not be empty. The parameters are separated by a comma and their denition consist of the keyword class followed by an identier which can be a built-in or user-dened type (Lippman, 1991). Finite element programs use arrays of integer and double numbers to store nodal coordinates, element incidences, degrees of freedom numbering, and many other data. In C++ nite element codes, arrays of data structures and classes are also necessary to manipulate the nite element model. Based on that, two parameterized array classes were implemented respectively for built-in (class BuiltInArray) and user-dened (class Array) data types. Arrays of numbers are used frequently in the hierarchy of nite element classes presented in the following section. In addition, eciency and database management issues demanded the implementation of the built-in type array class. The header le of the general array class is presented below.
#ifndef ARRAY_H #define ARRAY_H template <class Type> class Array

{ long Size; Type *Ar; //array size //array pointer

//alloc memory for array void Alloc(long ArraySize=0, Type * PArray=0); public: //constructors Array(): Size(0), Ar(NULL) {} Array(long ArraySize, Type *Elements=0) { Alloc(ArraySize, Elements); } //copy-initializer Array(Array<Type> &Instance) { Alloc(Instance.Size, Instance.Ar); } ~Array() { Free(); } Array<Type> & operator=(Array<Type> &Instance); //destructor //operator =

//return element at position Index (no range checking) Type & operator[](long Index) { return(Ar[Index]); } operator Type * const() { return(Ar); } long GetSize() { return(Size); } void SetSize(long ArraySize=0); void Resize(long NewSize); void void void void //conversion of Array<Type> to Type * //return array size //set array size //set array size and copy the elements //print array //save array in database //restore from database //deallocate array

Print(FILE *File, char *Message=""); Save(char *TabName, int Version, char *Filename); Restore(char *TabName, int Version, char *Filename); Free();

}; #endif //ARRAY_H

The use of parameterized array classes has simplied considerably the implementation of the nite element classes. Most of their methods are implemented in the header le which simplies the complex tasks of code maintaince and updating. The classes presented in the following section use extensively database, error handling, and numerical procedures of the ACDP library (Guimares and Feijo, 1989). a o

Finite Element Classes

A set of C++ nite element classes was implemented using the template array classes Array and BuiltInArray. In this initial version, linear elastic problems have been considered. However, extensions to non-linear problems, uid dynamics, p-nite element version, and meshless methods have been implemented. Figure 1 shows the organization levels of the nite element classes. No inheritance relationships are implied by this level structure. The rst level implements basic data structures used extensively in the other levels. The classes manage dynamic memory allocation and perform mathematical procedures such as direct and iterative solution of systems of equations. Memory allocation is one of the main sources of errors in the development of C and C++ programs. Restricting the implementation of memory allocation procedures to the rst level classes simplies error tracking and correction. Classes for arrays, list, trees, vector, and matrices were implemented. As discussed in the 4

Level 2
Node, Material, FiniteElement,...

Level 1
Array, String, Vector, Matrix, SymmetricSparse,...

Level 4
FEModel, FELinearSolver

Level 3
Nodes, MaterialArray, FiniteElementGroup, FEGroups,...

Figure 1: Organization levels of the nite element classes. previous section, the classes Array and BuiltInArray are based on the template concept. The class String stores and manipulates character strings. The matrix classes implement numerical procedures for the solution of system of equations and eigenvalue problems. Specically, the classes Vector, Matrix, and SymmetricMatrix implement data structures and methods for vector, matrix, and symmetric matrix. A class hierarchy for global system matrices was developed. The generic class GlobalMatrix has common data structures and method for its subclasses. The classes SymmetricSkyline and SymmetricSparse store symmetric global matrices respectively in skyline and sparse formats. The SparseMatrix class stores non-symmetric sparse matrices. Gauss elimination and iterative (Jacobi, Gauss-Seidel, SOR, standard and pre-conditioned conjugate gradient) numerical methods were implemented in all matrix classes. Cache-based versions of the Gauss-Seidel method were developed to increase the computational performance of multigrid procedures. The second level has classes for basic nite element entities such as materials, nodes, nite elements, boundary conditions, and loads. The use of the array classes can be illustrated beginning at this level. The class Nodes stores nodal coordinates and its header le is presented below.
#ifndef NODES_H #define NODES_H class Nodes { protected: int Dim; long NNodes; BuiltInArray<double> Coords;

//problem dimension //number of nodes //nodal coordinates

public: //constructors Nodes(): Dim(0), NNodes(0), Coords() {} Nodes(int Dimension, long NumberNodes) { SetDimension(Dimension); //set dimension SetNumberNodes(NumberNodes); //set number of nodes } Nodes(Nodes &Instance) { operator=(Instance); } ~Nodes() { Dim = 0; NNodes = 0; } void operator=(Nodes &Instance); void SetNumberNodes(long NumberNodes); //copy-initializer //destructor //operator = //set number of nodes

void SetDimension(int Dimension); int GetDimension() { return(Dim); } long GetNumberNodes() { return(NNodes); }

//set problem dimension //return problem dimension //return number of nodes

//return coordinates of nodes in Incidence void GetNodalCoordinates(BuiltInArray<long> &Incidence, BuiltInArray<double> &Coordinates); //read number of nodes and nodal coordinates from a ascii file void Read(FILE *File); //save nodal coordinates in binary database void Save(char *TabName, int Version, char *FileName); //restore nodal coordinates from binary database void Restore(char *TabName, int Version, char *FileName); void PrintTit(FILE *File = stdout); //print nodal coordinates is ascii format void Free(); //deallocate memory space }; #endif //NODES_H

This class has variables for the problem dimension (one, two, and three-dimensions), total number of nodes, and an array to store the coordinate values. The memory allocation requirements for this class are implemented and managed by the BuiltInArray class. Most of the methods are implemented in the header le. The other methods are in the class denition le and in general have a very simple implementation as illustrated below.
void Nodes::GetNodalCoordinates(BuiltInArray<long> &Incidence, BuiltInArray<double> &Coordinates) { static char *nome = "Nodes::GetCoordinates"; TraceOn(nome); if(Incidence.GetSize() * Dim != Coordinates.GetSize()) Error(FATAL_ERROR, 1, "Different number of elements in the input arrays"); register long i, j; long huge *pInc = Incidence; double huge *PC; if(Dim == 1) //one-dimension for(i = 0; i < Incidence.GetSize(); i++, pInc++) { PC = Coords + (*pInc); Coordinates[i] = PC[0]; } else if(Dim == 2) //two-dimensions for(i = 0, j = 0; i < Incidence.GetSize(); i++, j+= 2, pInc++) { PC = Coords + (*pInc) * Dim; Coordinates[j] = PC[0]; Coordinates[j+1] = PC[1]; } else //three-dimensions

for(i = 0, j = 0; i < Incidence.GetSize(); i++, j+= 3, pInc++) { PC = Coords + (*pInc) * Dim; Coordinates[j] = PC[0]; Coordinates[j+1] = PC[1]; Coordinates[j+2] = PC[2]; } TraceOff(nome); }

FiniteElement is a generic virtual class from which all specic nite element types are derived. Triangular, rectangular, hexahedral, and tetrahedral elements were implemented for linear elastic behaviors (e.g., plane stress, plain strain, axi-symmetric, elastic solid). For example, PlaneStressTriangle is the class for plane stress triangular elements. Interpolation procedures based on Lagrange, Serendipty, and p-nite element shape functions were implemented based on the generic class ShapeFunctions and its derivatives. In analogous way, numerical integration rules are managed by the generic class NumericalIntegration and its derivatives. The classes EliminatedDOF and PrecribedDOF manage, respectively, homogeneous and non-homogeneous boundary conditions. The LoadCase class stores the equivalent nodal forces as an array of PrescribedDOF objects. Material is a generic virtual class to represent material behaviors. For while just elastic linear material has been considered. However, the class framework was designed to include new material constitutive relations in a simple way. A partial list of the Material header le is given bellow.
#ifndef MATERIAL_H #define MATERIAL_H #include "symmat.h" #include "biarray.h" #include "fem_defs.h" class Material { protected: int MaterialNum; MaterialApp_E MatApp;

//material number //material application

public: //constructors Material(): MaterialNum(0), MatApp(MAT_APP_NONE) {} Material(int MaterialNumber, MaterialApp_E Application=MAT_APP_NONE): MaterialNum(MaterialNumber), MatApp(Application) {} //destructor virtual ~Material() {} //operator = virtual void operator=(Material &Instance) = 0; //set material number

void SetNumber(int MaterialNumber=1) { MaterialNum = MaterialNumber; } //returns material number int GetNumber() { return(MaterialNum); } //returns material number virtual char *GetName() = 0; //returns material application MaterialApp_E GetApplication() { return(MatApp); } //set material properties virtual void SetProperties(BuiltInArray<double> &Properties)= 0; //return material properties virtual void GetProperties(BuiltInArray<double> &Properties) = 0; //returns the compliance matrix virtual void GetCMatrix(SymmetricMatrix &CMatrix) = 0; //returns the elasticity matrix virtual void GetDMatrix(SymmetricMatrix &DMatrix) = 0; }; #endif //MATERIAL_H

Many methods were declared as virtual methods and implemented in the derived classes such as those to setup the material properties and calculate the elasticity and compliance matrices. A partial list of the derived class IsotropicElasticMaterial is also presented bellow. Private methods were implemented to calculate the elasticity and compliance matrices based on the value stored in the variable MatApp of Material as for example the method GetPlaneStressDMatrix.
#ifndef ISOELMAT_H #define ISOELMAT_H #include "material.h" class IsotropicElasticMaterial: public Material { protected: double YoungModulus; //Youngs modulus double PoissonRatio; //Poissons coefficient double ThermalExpCoef; //thermal coefficient double Density; //density //returns the plane stress elasticity matrix void GetPlaneStressDMatrix(SymmetricMatrix &DMatrix); //returns the plane stress compliance matrix void GetPlaneStressCMatrix(SymmetricMatrix &CMatrix); public: //constructors IsotropicElasticMaterial(): Material(), YoungModulus(0.0), PoissonRatio(0.3), ThermalExpCoef(0.0), Density(0.0) {}

IsotropicElasticMaterial(int MaterialNumber, double E=0.0, double Nu=0.3, double AlfaT=0.0, double Rho=0.0, MaterialApp_E Application=MAT_APP_NONE): Material(MaterialNum, Application), YoungModulus(E), PoissonRatio(Nu), ThermalExpCoef(AlfaT), Density(Rho) {} //return material name char *GetName() { return("IsotropicElasticMaterial"); } //set material properties void SetProperties(BuiltInArray<double> &Properties); //return the compliance matrix void GetCMatrix(SymmetricMatrix &CMatrix); //returns the elasticity matrix void GetDMatrix(SymmetricMatrix &DMatrix); }; #endif //ISOELMAT_H

The third level implements arrays of the second level classes. For instance, the MaterialArray class stores the materials of the nite element analysis using an array of the class MatInfo. The data structures for these classes are given next.
class MaterialArray { protected: Array<MatInfo> MatAr; //material array ... }; class MatInfo { public: String MaterType; Material *Mater; ... };

//material name //pointer to Material

Other third level classes include DOFBoundaryConditions which manages homogeneous and non-homogeneous boundary conditions using respectively EliminatedDOF and PrescribedDOF arrays. The LoadCases class calculates the equivalent nodal forces for the load cases. They are stored in the database and retrieved to setup the global load vector during the nite element solution process. A nite element group is described by a sequence of elements with the same type, material and geometric properties. The class FiniteElementGroup has data for the nite element type, material number, geometric property number, number of elements, initial and nal element numbers as well an array of incidences and a pointer to a FiniteElement object. This pointer is initialized with the address of a derived FiniteElement class corresponding to the nite element type of the group. All groups have this working element to calculate element properties such as stiness matrices and stress tensor. The set of groups is stored as an array of FiniteElementGroup in the class FEGroups. The class Equations numbers the nodal degrees of freedom taking into account the boundary conditions. 9

Finally, the fourth level contains the nite element model class (FEModel) with all analysis attributes, as well the derived solver classes (e.g., FELinearSolver, FENonLinearSolver, and Multigrid). The same nite element data structure can be used in dierent structural analysis types. In addition, a nite element solver object has all data and methods required to manipulate and solve structural problems. The data structure for the FEModel class is given below.
class FEModel { protected: String FEMFile, OUTFile, LOGFile, DB; String Tit; Nodes Coords; LoadCases LCases; FEGroups Groups; MaterialArray Materials; Equations DOFEq; DOFBoundaryConditions BC; ... };

//input, output, log, database filenames //title //nodal coordenates //load cases //finite element groups //material types //dof numbering //boundary conditions

A partial list of the header le of the FELinearSolver is given bellow. This FEModel derived class declares variables for the global matrix, load and unknown vectors. The protected methods SetTopology and SetMatrix are used respectively to set up the global matrix topology and coecients. The nite element solution is calculated by the method Solver using an iterative or direct method specied with the method SetSolution.
#ifndef FESOLVE_H #define FESOLVE_H #include "femodel.h" class FELinearSolver: public { protected: GlobalMatrix *GlbMat; Vector Load, U; NumMeths_E Meth; long MNIT; double Prec; double NormRes; ConvCriterion_E Crit; Norm_E Norma; long NIT; FEModel

//system global matrix //load and unknown vectors //numerical solution method //maximum number of iterations //precision //residue norm of the iterative solution //convergence criterion //norm type //number of iterations

//setup global matrix topology void SetTopology(); //setup matrix coefficients void SetMatrix(); public: //constructors FELinearSolver(); FELinearSolver(char *DataFile, char *DBName, char *LOGFilename="",


char *Title = "", char *OUTFilename = ""); //set numerical solution method void SetSolution(NumMeths_E NumericalMethod=CGGS, long MaxNIT=1000, double Precision=1E-4, ConvCriterion_E Criterion=WEIGHT_RESIDUE, Norm_E Norm=EUCLIDEAN); //calculate the finite element solution void Solver(); }; #endif //FESOLVE_H


The nite element classes presented in the last section have been used to implement multigrid methods, adaptive procedures, sensitivity analysis, and structural optimization. Figure 2 shows a sequence of meshes obtained by applying the Zienkiewicz-Zhu error estimator (Zienkiewicz and Zhu, 1987) and solved using multigrid methods (Bittencourt and Feijo, 1998). Results of o parameter and shape optimization of two-dimensional elastic problems are illustrated in Figure 3 (Silva and Bittencourt, 1998; Silva and Bittencourt, 2000).

Figure 2: Sequence of meshes for multigrid procedures (Bittencourt and Feijo, 1998). o

(a) Initial shape mesh.

(b) Final shape mesh.

1 2 3 4 5 6 7 8 9 10 11

Von-Mis_1 2.0100E+01 1.8273E+01 1.6446E+01 1.4619E+01 1.2792E+01 1.0965E+01 9.1375E+00 7.3104E+00 5.4834E+00 3.6563E+00 1.8293E+00 2.2616E-03

1 2 3 4 5 6 7 8 9 10 11

Von-Mis_1 2.7687E+01 2.5170E+01 2.2653E+01 2.0137E+01 1.7620E+01 1.5103E+01 1.2587E+01 1.0070E+01 7.5531E+00 5.0364E+00 2.5197E+00 3.0158E-03

(c) Initial von Mises stress distribution.

(d) Final von Mises stress distribution.

Figure 3: Structural optimization examples (Silva and Bittencourt, 2000).


Software environments have been also implemented and some modules are based on the nite element classes presented in this paper. Figure 4 illustrates a software environment for structural analysis and optimization of two-dimensional elastic problems (Bittencourt, Galvo, a Silva and Feijo, 1998). All graphical representation is based on a NURBS data structure imo plemented in C++. The GEOMETRY module have resources for the interactive denition of two-dimensional domains. The automatic triangular mesh generation and the denition of the nite element attributes (e.g., element type, material and geometric properties, loads, and boundary conditions) are done in the MESH module. After calculating the nite element solution, the results can be visualized graphically and numerically using the VISUALIZATION module. Finally, design sensitivity and minimization procedures are implement in the module OPTIMIZATION to perform thickness and shape design optimizations.


(b) MESH.



Figure 4: Modules of the interactive program (Bittencourt et al., 1998).



A set of C++ nite element classes implemented using template array classes was presented. All memory management methods were implemented in the rst level classes and the development of the nite element classes was simple. The classes are more reliable and easier to maintain. Examples of multigrid methods, structural optimization, and adaptive methods were also presented. Extensions to the p-version of the nite element method, non-linear problems, uid dynamics, and meshless methods have been implemented.

This work was partially supported by Conselho Nacional de Desenvolvimento Cient co e Tecnolgico (CNPq Proc. 523.982/94-1, CNPq-RHAE Proc. 610.035/94-0), Fundao de Amo ca paro a Pesquisa do Estado de So Paulo (FAPESP Proc. 97/0540-0). The author is grateful a for the software facilities provided by the TACSOM Group (http://www.lncc.br/~tacsom).

Adeli, H. and Yu, G. (1995), An integrated computing environment for solution of complex engineering problems using the object-oriented programming paradigm and a blackboard architeture, Computer & Structures 54(2), 255265. Bittencourt, M. (1990), Static and dynamic analysis by substructuring and object-oriented programming (in Portuguese), Masters thesis, School of Mechanical Engineering, State University of Campinas, Brazil. Bittencourt, M. (1996), Adaptive iterative and multigrid methods applied to non-structured meshes (in Portuguese), PhD thesis, School of Mechanical Engineering, State University of Campinas, Brazil. Bittencourt, M. and Feijo, R. (1998), Object-oriented non-nested multigrid methods, in IV o World Conference on Computational Mechanics, Buenos Aires. Bittencourt, M., Galvo, M., Silva, C. and Feijo, R. (1998), An object-oriented interactive a o environment for structural analysis and optimization, Research report 01/99, Laboratrio o de Computao Cient ca ca, Rio de Janeiro. Cardona, A., Klapka, I. and Geradin, M. (1994), Design of a new nite element programming environment, Engineering Computations 11, 365381. Dari, E. (1994), Contribuciones a la triangulacin automtica de dominios tridimensionales, o a PhD thesis, Instituto Balseiro, Bariloche, Argentina. Dubois-P`lerin, Y., Zimmermann, T. and Bomme, P. (1993), Object-oriented nite element e programming: Iii. an ecient implementation in c++, Computer Methods in Applied Mechanics and Engineering 108, 165183. Fancello, E., Guimares, A., Feijo, R. and Venere, M. (1991), Automatic two-dimensional a o mesh generation using object-oriented programming, in Proceedings of 11th Brazilian Congress of Mechanical Engineering, Brazilian Association of Mechanical Sciences, So a Paulo, pp. 635638. 13

Feijo, R., Guimares, A. and Fancello, E. (1991), Algumas experiencias en la programacin o a o orientada por objetos y su aplicacin en el mtodo de los elementos nitos, Research report o e 15/91, National Laboratory of Scientic Computation, Rio de Janeiro, Brazil. Filho, J. and Devloo, P. (1991), Object oriented programming in scientic computations: the beginning of a new era, Engineering Computations 8, 818. Forde, B., Foschi, R. and Stiemer, S. (1990), Object-oriented nite element analysis, Computer & Structures 34, 355374. Guimares, A. C. S., Fancello, E. A., Feijo, G. R. and Feijo, R. A. (1994), SAFE - integrated a o o system for structural nite element analysis version 1.0, Technical report, National Laboratory for Scientic Computation, Rio de Janeiro, RJ, Brazil. Guimares, A. and Feijo, R. (1989), The ACDP System (in portuguese), Research report 27/89, a o National Laboratory of Scientic Computation, Rio de Janeiro, RJ, Brazil. Lippman, S. (1991), C++ primer, Addison-Wesley, Reading. Mentrey, P. and Zimmermann, T. (1993), Object-oriented non-linear nite element analysis: e application to j2 plasticity, Computer & Structures 49(5), 767777. Miller, G. (1991), An object-oriented approach to structural analysis and design, Computer & Structures 40, 7582. Oate, E., Idelsohn, I. and E. Dvorkin, e. (1998), in Computational mechanics new trends n and applications, CIMNE, Barcelona. Scholz, S. (1992), Elements of an object-oriented fem++ program in C++, Computer & Structures 43(3), 517529. Silva, C. and Bittencourt, M. (1998), An interactive object-oriented tool for structural optimization, in IV World Conference on Computational Mechanics, Buenos Aires. Silva, C. and Bittencourt, M. (2000), An object-oriented structural optimization program. to appear. Tworzydlo, W. and Oden, J. (1993), Towards an automated environment in computational mechanics, Computer Methods in Applied Mechanics and Engineering 104, 87143. Tworzydlo, W. and Oden, J. (1995), Knowledge-based methods and smart algorithms in computational mechanics, Engineering Fracture Mechanics 50(5), 759800. Vnere, M. (1996), Tcnicas adaptativas para el mtodo de elementos nitos en dos y tres e e e dimensiones, PhD thesis, Instituto Balseiro, Bariloche, Argentina. Yu, G. and Adeli, H. (1993), Object-oriented nite element analysis using EER model, Journal of Structural Engineering 119(9), 27632781. Zeglinski, G., Han, R. and Aitchison, P. (1994), Object oriented matrix classes for use in a nite element code using c++., International Journal for Numerical Methods in Engineering 37, 39213937. Zienkiewicz, O. and Zhu, J. (1987), A simple error estimator and adaptative procedure for practical engineering analysis, International Journal for Numerical Methods in Engineering 24, 337357. 14

Zimmermann, T., Dubois-P`lerin, Y. and Bomme, P. (1992), Object-oriented nite element e programming: I. govening principles, Computer Methods in Applied Mechanics and Engineering 98, 291303.