当前位置:文档之家› LibSVM-2.8程序代码注释

LibSVM-2.8程序代码注释

LibSVM-2.8程序代码注释
LibSVM-2.8程序代码注释

LibSVM-2.8程序代码注释

刘国平(ahphone@https://www.doczj.com/doc/9416804.html,)

2005-08-06

我不经心地,服下你调好的毒

我知道今后我将万劫不复

但是你的红唇仍让我屈服

四月的樱花火红满天

我和你的梦,却要一以何处去缱绻?虽然人间的情爱万万千千

世上已有太多崩毁的誓言

七个黑夜,七个白天

我为你写下的歌,彩绘的纸笺

却只能随着晚风

飘在大海的岸边

我仍愿服下你精心为我调好的毒

从你那深情的吻

吞下我与你在人间

最后的流光万千辗转朱颜……

第一章LibSVM结构

一、文件结构

整个LibSVM由两个文件组成,svm.h, svm.cpp。其中svm.h中定义了使用LibSVM所需要的数据结构和函数。

数据结构:

struct svm_node:数据节点,每个节点只是单个样本矢量中的一个特征。

struct svm_problem :数据集,存放所有样本矢量的数据结构。

struct svm_parameter:SVM参数。

其实应该还有一个数据结构存放在头文件中:

struct svm_model :训练好的训练模型。

二、类结构图

其中有两组关键的类:

1、QMatrix类:包括QMatrix, Kernel, SVC_Q, SVR_Q, ONE_CLASS_Q;

2、Solver类:包括Solver, Solver_NU;

(矢量图,可以调整放大倍数)

第二章: 头文件SVM.h

本文件只是定义了若干个结构体,和若干接口函数。严格的来说,它们并不是接口函数,因为实际上整个代码里面,可以直接访问的函数还有其他。但事实上,如果仅仅是应用一下这份代码的话,只要知道这几个函数就可以了。

2.1 struct svm_node

struct svm_node { int index ; double value ;

};

struct svm_node 用来存储单一向量中的单个特征,例如: 向量 x1={ 0.002, 0.345, 4, 5.677};

那么用struct svm_node 来存储时就使用一个包含5个svm_node 的数组来存储此4维向量,内存映象如下:

其中如果value 为0.00,该特征将不会被存储,其中(特征3)被跳过:

0.00不保留的好处在于,做点乘)(y x 的时候,可以加快计算速度,对于稀疏矩阵,更能充分体现这种数据结构的优势。但做归一化时,操作就比较麻烦了。(类型转换不再说明)

2.2 struct svm_problem

struct svm_problem { int l ; double *y ;

struct svm_node **x ;

};

struct svm_problem 存储本次参加运算的所有样本(数据集),及其所属类别。在某些数据挖掘实现中,常用DataSet 来实现。 int l ;记录样本总数

double *y ;指向样本所属类别或者回归值的数组。在多类问题中,因为使用了one-agianst-one 方法,可能原始样本中y[i]的内容是1.0,2.0,3.0,…,也就是属于类别1,2,3,但但参与多类计算时,参加分类的两类所对应的y[i]内容是+1,和-1。 Struct svm_node **x ;指向一个存储内容为指针的数组;

如下图,最右边的四个长条格同上表,存储三维数据。(黑边框的是最主要的部分)

这样的数据结构有一个直接的好处,可以用x[i][j]来访问其中的某一元素(如果value 为0.00的也全部保留的话)。

私下认为其中有一个败笔,就是把svm_node* x_space 放到结构外面去了。

2.3 enums

enum { C_SVC , NU_SVC , ONE_CLASS , EPSILON_SVR , NU_SVR }; /* svm_type */ enum { LINEAR , POLY , RBF , SIGMOID }; /* kernel_type */

支持向量机类型以及若干文献: C-SVC :

C.J.C. Burges. A tutorial on support vector machines for pattern recognition. Data Mining and Knowledge Discovery , 2(2):955-974, 1998.

NU_SVC : (待补充)

2.4 struct svm_parameter

struct svm_parameter { int svm_type ;//SVM 类型,见前enum int kernel_type ;//核函数 double degree ; /* for poly */

double gamma ;

/* for poly/rbf/sigmoid */

double coef0; /* for poly/sigmoid */

/* these are for training only */ double cache_size ; /* in MB */ double eps ; /* stopping criteria */ double C ;

/* for C_SVC, EPSILON_SVR and NU_SVR */

int nr_weight

;

/* for C_SVC */

int *weight_label ; /* for C_SVC */ double * weight ; /* for C_SVC */

double nu ;

/* for NU_SVC, ONE_CLASS, and NU_SVR */

double p; /* for EPSILON_SVR */

int shrinking; /* use the shrinking heuristics */

int probability; /* do probability estimates */

};

部分参数解释,(附核函数)

double degree;//就是2式中的d

double gamma; //就是2,3,4式中的gamma

2.5 struct struct svm_model

struct svm_model

{

svm_parameter param; // parameter

int nr_class; // number of classes, = 2 in regression/one class svm

int l; // total #SV

svm_node **SV; // SVs (SV[l])

double **sv_coef; // coefficients for SVs in decision functions (sv_coef[n-1][l]) double *rho; // constants in decision functions (rho[n*(n-1)/2])

double *probA; // pariwise probability information

double *probB;

// for classification only

int *label; // label of each class (label[n])

int *nSV; // number of SVs for each class (nSV[n])

// nSV[0] + nSV[1] + ... + nSV[n-1] = l

// XXX

int free_sv; // 1 if svm_model is created by svm_load_model

// 0 if svm_model is created by svm_train

};

结构体svm_model用于保存训练后的训练模型,当然原来的训练参数也必须保留。本来这个结构体应该是在svm.cpp中,为统一起见,一起描述。

2.6 接口函数

//以下接口函数设计得非常合理,最后一节详细说明

//最主要的驱动函数,训练数据

struct svm_model *svm_train(const struct svm_problem *prob, const struct svm_parameter *param);

//用SVM做交叉验证

void svm_cross_validation(const struct svm_problem *prob, const struct svm_parameter

*param, int nr_fold, double *target);

//保存训练好的模型到文件

int svm_save_model(const char *model_file_name, const struct svm_model *model);

//从文件中把训练好的模型读到内存中

struct svm_model *svm_load_model(const char *model_file_name);

//得到数据集的SVM类型(必须经过训练得到模型后才可以用)

int svm_get_svm_type(const struct svm_model *model);

//得到数据集的类别数(必须经过训练得到模型后才可以用)

int svm_get_nr_class(const struct svm_model *model);

//得到数据集的类别标号(必须经过训练得到模型后才可以用)

void svm_get_labels(const struct svm_model *model, int *label);

//LibSvm2.6新增函数

double svm_get_svr_probability(const struct svm_model *model);

//用训练好的模型预报样本的值,输出结果保留到数组中。(并非接口函数)

void svm_predict_values(const struct svm_model *model, const struct svm_node *x, double* dec_values);

//预报某一样本的值

double svm_predict(const struct svm_model *model, const struct svm_node *x);

// LibSvm2.6新增函数

double svm_predict_probability(const struct svm_model *model, const struct svm_node *x, double* prob_estimates);

//消除训练的模型,释放资源

void svm_destroy_model(struct svm_model *model);

// LibSvm2.6新增函数

void svm_destroy_param(struct svm_parameter *param);

//检查输入的参数,保证后面的训练能正常进行。

const char *svm_check_parameter(const struct svm_problem *prob, const struct

svm_parameter *param);

// LibSvm2.6新增函数

int svm_check_probability_model(const struct svm_model *model);

第三章:SVM.cpp文件

3.1 宏

.头文件:

从整个.cpp文件来看,感觉有些头文件是多余的,不知何故,反正多包含头文件不会犯错。

后面的typedef,特别是typedef float Qfloat,是为了方便控制内存存储的精度。

#include

#include

#include

#include

#include

#include

#include

#include "svm.h"

typedef float Qfloat;

typedef signed char schar;

//.以下是定义的几个主要的模板,主要是为了比较大小,交换数据和完全复制数据。

Min()和Max()在中提供了相应的函数,这里的处理是为了兼容Microsoft VC++编译器。因为VC对标准模板库(STL)支持得不是很好。下面对min, max的处理方法非常经典。

#ifndef min

template inline T min(T x,T y) { return (x

#endif

#ifndef max

template inline T max(T x,T y) { return (x>y)?x:y; }

#endif

//这里的克隆函数是完全克隆,不同于一般的复制。操作结束后,内部的所有数据和指针完全一样。

template inline void swap(T& x, T& y) { T t=x; x=y; y=t; }

template inline void clone(T*& dst, S* src, int n)

{

dst = new T[n];

memcpy((void *)dst,(void *)src,sizeof(T)*n);

}

//这里使用了define,非内联函数

#define Malloc(type,n) (type *)malloc((n)*sizeof(type))

一般来说,在cpp中使用delete比较正规,在c中使用malloc比较正规。LibSVM比较好地贯彻了这点,malloc用在接口函数中。

//以下的函数用作调试。跳过~ #if 1

void info (char *fmt ,...) { va_list ap ; va_start (ap ,fmt ); vprintf (fmt ,ap ); va_end (ap );

}

void info_flush () { fflush (stdout ); }

#elsevoid info (char *fmt ,...) {} void info_flush () {} #endif

//以下部分为svm.cpp 中的类继承和组合图: (实线表示继承关系,虚线表示组合关系),更正规的图例见第一章。

3.2 类Cache

本类主要负责运算所涉及的内存的管理,包括申请、释放等。本类对理解核心代码关系不

大,如果弄不清楚影响也不大。可以跳过。 类定义: class Cache { public : Cache (int l ,int size ); ~Cache ();

int get_data (const int

index , Qfloat **data , int len ); void swap_index (int i , int j ); // future_option private :

int l ;

int size ; struct head_t { head_t *prev , *next ; // a cicular list Qfloat *data ; int len ;

// data[0,len) is cached in this entry

};

head_t * head ; head_t lru_head ;

void lru_delete (head_t *h ); void lru_insert (head_t *h );

};

成员变量:

head_t * head ; //变量指针,该指针用来记录程序所申请的内存,单块申请到的内存用struct head_t 来记录所申请内存的指针,并记录长度。而且通过双向的指针,形成链表,增加寻址的速度。记录所有申请到的内存,一方面便于释放内存,另外方便在内存不够时适当释放一部分已经申请到的内存。

head_t lru_head ; //双向链表的头。 int l ; //样本总数。

int size ; //所指定的全部内存,据说用Mb 做单位。

成员函数:

void lru_delete (head_t *h ); //从双向环形链表中删除某个元素的链接,不删除、不释放该元素所涉及的内存。一般是删除当前所指向的元素。

void lru_insert (head_t *h ); //在链表后面插入一个新的链接;其实就是在lru_head 后添加。(环形的嘛)

Cache (int l ,int size );

构造函数。该函数根据样本数L ,申请

L 个head_t 的空间。根据说明,该区域会初始化为0。Lru_head 因为尚没有head_t 中申请到内存,故双向链表指向自己。至于size 的处理,先将原来的byte 数目转化为float 的数目,然后扣除L 个head_t 的内存数目。size 为程序指定的内存大小4M/40M 。size 不要设得太小。

int get_data (const int index , Qfloat **data , int len );

该函数保证head_t[index]中至少有len 个float 的内存,并且将可以使用的内存块的指针放

在data 指针中。返回值为申请到的内存。

函数首先将head_t[index]从链表中断开,如果head_t[index]原来没有分配内存,则跳过断开这步。计算当前head_t[index]已经申请到的内存,如果不够,释放部分内存(怀疑这样做的动机:老数据为什么就可以释放,而不真的另外申请一块?老数据没用了?),等内存足够后,重新分配内存。重新使head_t[index]进入双向链表。并返回申请到的内存的长度。

//返回值不为申请到的内存的长度,为head_t[index]原来的数据长度h->len 。 调用该函数后,程序会计算),(j

i

j

i

x x K y y Q ∑=

的值,并将其填入data 所指向的内存区

域,如果下次index 不变,正常情况下,不用重新计算该区域的值。若index 不变,则get_data()返回值len 与本次传入的len 一致,从Kernel::get_Q( )中可以看到,程序不会重新计算。从而提高运算速度。

While 循环内的部分基本上难得用到一次。

void swap_index (int i , int j );

交换head_t[i] 和head_t[j]的内容,先从双向链表中断开,交换后重新进入双向链表中。对后面的处理不理解,可能是防止中head_t[i] 和head_t[j]可能有一方并未申请内存。但h ->len > i 和 h ->len > j 无法解释。

for (head_t *h = lru_head .next ; h !=&lru_head ; h =h ->next ) { if (h ->len > i ) { if (h ->len > j ) swap (h ->data [i ],h ->data [j ]);

else { // give up lru_delete (h ); free (h ->data ); size += h ->len ; h ->data = 0; h ->len = 0;

}

}

}

后注:这部分内容我几次读过,都不太清楚,如果有谁弄懂了,请告知。

3.3 类QMatrix

class QMatrix { public:

virtual Qfloat *get_Q(int column, int len) const = 0; virtual Qfloat *get_QD() const = 0;

virtual void swap_index(int i, int j) const = 0;

};

纯虚类。理论上用户只要能在需要的时候,提供必要的数据,就可以实现其它的变形支持向量机。用户可以自己实现数据矩阵(很大的哦),然后直接提供给Solver。

3.4 类Kernel

class Kernel {

public:

Kernel(int l, svm_node * const * x, const svm_parameter& param);

virtual ~Kernel();

static double k_function(const svm_node *x, const svm_node *y, const svm_parameter& param);

virtual Qfloat *get_Q(int column, int len) const = 0;

virtual void swap_index(int i, int j) const// no so const...

{

swap(x[i],x[j]);

if(x_square) swap(x_square[i],x_square[j]);

}

protected:

double (Kernel::*kernel_function)(int i, int j) const;

private:

const svm_node **x;

double *x_square;

// svm_parameter

const int kernel_type;

const double degree;

const double gamma;

const double coef0;

static double dot(const svm_node *px, const svm_node *py);

double kernel_linear(int i, int j) const(skipped)

double kernel_poly(int i, int j) const(skipped)

double kernel_rbf(int i, int j) const(skipped)

double kernel_sigmoid(int i, int j) const(skipped)

};

成员变量:

const svm_node **x; //用来指向样本数据,每次数据传入时通过克隆函数来实现,完全重新分配内存,主要是为处理多类着想。

double *x_square; //使用RBF核才使用。

const int kernel_type; //核函数类型.

const double degree; // kernel_function

const double gamma ; // kernel_function const double coef0; // kernel_function 成员函数:

Kernel (int l , svm_node * const * x , const svm_parameter & param );

构造函数。初始化类中的部分常量、指定核函数、克隆样本数据。如果使用RBF 核函数,则计算x-sqare[i].

static double dot (const svm_node *px , const svm_node *py );

点乘两个样本数据,按svm_node 中index (一般为特征)进行运算,一般来说,index 中1,2,…直到-1。返回点乘总和。

例如:x1 = { 1,2,3} , x2 = {4, 5, 6} 总和为sum = 1*4 + 2*5 + 3*6 ;在svm_node[3]中存储index = -1时,停止计算。

static double k_function (const svm_node *x , const svm_node *y , const svm_parameter & param );

核函数。但只有在预报时才用到。

其中RBF 部分很有讲究。因为存储时,0值不保留。如果所有0值都保留,第一个while 就可以都做完了;如果第一个while 做不完,在x ,y 中任意一个出现index = -1,第一个while 就停止,剩下的代码中两个while 只会有一个工作,该循环直接把剩下的计算做完。

virtual Qfloat *get_Q (int column , int len ) const = 0; virtual Qfloat *get_QD () const = 0;

纯虚函数,将来在子类中实现。相当重要的函数。

virtual void swap_index (int i , int j )

虚函数,x[i]和x[j]中所存储指针的内容。如果x_square 不为空,则交换相应的内容。

double (Kernel ::*kernel_function )(int i , int j ) const ;

函数指针,根据相应的核函数类型,来决定所使用的函数。在计算矩阵Q 时使用。

),(j i j i x x K y y Q ∑=

1、j T i j i x x x x K =

),(

2、0,)(),(>+=γγd j T

i j i r x x x x K

3、0),exp(),(2

>--=γγj i j i x x x x K

4、)tanh(),(r x x x x K j T

i j i +=γ

3.4 类Solver

class Solver {

public:

Solver() {};

virtual ~Solver() {};

struct SolutionInfo {

double obj;

double rho;

double upper_bound_p;

double upper_bound_n;

double r; // for Solver_NU

};

void Solve(int l, const Kernel& Q, const double *b_, const schar *y_, double *alpha_, double Cp, double Cn, double eps,

SolutionInfo* si, int shrinking);

protected:

int active_size;

schar *y;

double *G; // gradient of objective function

enum { LOWER_BOUND, UPPER_BOUND, FREE };

char *alpha_status; // LOWER_BOUND, UPPER_BOUND, FREE

double *alpha;

const Kernel *Q;

double eps;

double Cp,Cn;

double *b;

int *active_set;

double *G_bar; // gradient, if we treat free variables as 0

int l;

bool unshrinked; // XXX

double get_C(int i) { }

void update_alpha_status(int i) { }

bool is_upper_bound(int i) { return alpha_status[i] == UPPER_BOUND; } bool is_lower_bound(int i) { return alpha_status[i] == LOWER_BOUND; } bool is_free(int i) { return alpha_status[i] == FREE; }

void swap_index(int i, int j);

void reconstruct_gradient();

virtual int select_working_set(int &i, int &j);

virtual double calculate_rho();

virtual void do_shrinking ();

};

成员变量:

int active_size ; // 计算时实际参加运算的样本数目,经过shrink 处理后,该数目会小于全部样本总数。

schar *y ; //样本所属类别,该值只取+1/-1 。虽然可以处理多类,最终是用两类SVM 完成的。

double *G; //梯度,计算公式如下(公式3.5)[1]:

t t t G f p Q =?=+)()(αα

在代码实现中,用b[i]来代替公式中的p 。

char *alpha_status ; //][i α的状态,根据情况分为 0][≤i α, c i ≥][α和0][0<

double *alpha ; //i α

const Kernel *Q ; //指定核。核函数和Solver 相互结合,可以产生多种SVC,SVR double eps ; //误差限

double *b ; //见double *G 的说明。 int *active_set ; // double *G_bar ;

//

G -

,(这名字取的)。计算公式如下:

l i Q C G C

ij j ,...,1,==∑=-

α

该值可以在对样本集做shrink 时,减小重建梯度的计算量。

∑∑<<==+

=C

l

j j ij ij Q j Q G G α

αα01

_

int l ; //样本总数 bool unshrinked ; // 成员函数:

double get_C (int i )

返回对应于样本的C 。 设置不同的Cp 和Cn 是为了处理数据的不平衡。见 《 6 Unbalanced data 》[1],有时Cp=Cn 。

void swap_index (int i , int j );

完全交换样本i 和样本j 的内容,包括所申请的内存的地址。

void reconstruct_gradient ();

重新计算梯度。G_bar[i]在初始化时并未加入b[i],所以程序首先增加b[i]。Shrink 后依然参加运算的样本位于active_size 和L-1位置上。在0~active_size 之间的alpha[i]如果在区间(0,c)

上,才有必要更新相应的active_size 和L-1位置上的样本的梯度。

virtual int select_working_set (int &i , int &j ) 选择工作集。公式如下:

}

0,1|)({},,1|)(min({arg }0,1|)({},,1|)(max({arg >=-?<-=?≡>-=?<=-?≡t t t t t t t t t t t t y f C y f j y f C y f i αααααααα

virtual void do_shrinking ();

对样本集做缩减。大致是当C <<α0时,(还有两种情况)程序认为该样本可以不参加下次迭代。(C <<α0时,为内部点)程序会减小active_size ,为(内部点)增加位置。active_size 表明了不可以参加下次迭代的样本的最小标号,在active_size 与L 之间的元素都对分类没有贡献。

程序中k--是为了消除交换后的影响,使重新换来的样本也被检查一次。

如果程序在缩减一次后没有达到结束条件,就重新构造梯度矢量,并再缩减一次(总觉得这里不太严密)。

virtual double calculate_rho ();

计算ρ值。见3.7[1]节,The calculation of b or

ρ

∑=<<=<

1

,01

,01

1

)(yi C yi C i

f r ααα

2

2

1r r +=

ρ

void Solve (int l , const Kernel & Q , const double *b_, const schar *y_,

double *alpha_, double Cp , double Cn , double eps , SolutionInfo * si , int shrinking );

//程序较大,逐步分解 part 1

// initialize alpha_status { alpha_status = new char [l ]; for (int i =0;i

update_alpha_status (i );

}

更新一下alpha 的状态 part 2

// initialize active set (for shrinking) {

active_set = new int [l ];

for (int i =0;i

active_set [i ] = i ; active_size = l ;

}

为缩减做准备,将来要做交换 part 3 // initialize gradient { G = new double [l ]; G_bar = new double [l ]; int i ;

for (i =0;i

}

for (i =0;i

for (j =0;j

G_bar [j ] += get_C (i ) * Q_i [j ];

}

}

G_bar [j ]的生成公式如下:(注意,其中不包含b[i]的值)

l i Q C G C

ij j ,...,1,==∑=-

α

因为第一次建立G(i),所以没有判断alpha 的状态。而是按公式,全部计算了一遍。 get_Q (i ,l )返回的值是ij Q 矩阵中的第i 列,而不是第i 行,这是需要注意的地方。

再往下是大循环:

如果有必要,先进行筛选,使部分数据不再参加运算;选择工作集;更新alpha_i, alpha_j,其更新的思路是保证:j old j i old i j new j i new

i y y y y αααα+=+;对于边界情况,有特殊处理,主要是考

虑i i

C ≤≤α0的要求。当某一alpha 小于0时,做适当调整,调整的结果是alpha_i, alpha_j 仍然在

i i C ≤≤α0范围内,同时其和同原来一样。对于推导过程,可以参考Sequential Minimal

Optimization for SVM

part 4

更新G(i),根据j i αα,的变化更新; // update G double delta_alpha_i = alpha [i ] - old_alpha_i ; double delta_alpha_j = alpha [j ] - old_alpha_j ;

for (int k =0;k

} part 5

以下是更新alpha_status 和_

G ,ahpha 状态更新较简单,根据alpha 状态前后是否有变化,适当更新,更新的内容参考公式l i Q C G C

ij j ,...,1,==∑=-α

// update alpha_status and G_bar { bool ui = is_upper_bound (i ); bool uj = is_upper_bound (j ); update_alpha_status (i ); update_alpha_status (j ); int k ;

if (ui != is_upper_bound (i ))//更新alpha_i 的影响 { Q_i = Q .get_Q (i ,l ); if (ui ) for (k =0;k

G_bar [k ] -= C_i * Q_i [k ];

else for (k =0;k

G_bar [k ] += C_i * Q_i [k ]; }

if (uj != is_upper_bound (j )) //更新alpha_j 的影响 { Q_j = Q .get_Q (j ,l ); if (uj )

for (k =0;k

G_bar [k ] -= C_j * Q_j [k ];

else for (k =0;k

G_bar [k ] += C_j * Q_j [k ];

}

}

part 6

以下计算目标函数值,因为t t p Q G )(+=α,而目标值为αααT T p Q +2

1

,故:

// calculate objective value { double v = 0; int i ;

for (i =0;i

v += alpha [i ] * (G [i ] + b [i ]);

si ->obj = v /2;

} part 7 回送结果。 // put back the solution { for (int i =0;i

alpha_[active_set [i ]] = alpha [i ];

}

2.3 类Solver_NU

class Solver_NU : public Solver { public : Solver_NU () {}

void Solve (int l , const Kernel & Q , const double *b , const schar *y , double *alpha , double Cp , double Cn , double eps , SolutionInfo * si , int shrinking ) { this ->si = si ;

Solver ::Solve (l ,Q ,b ,y ,alpha ,Cp ,Cn ,eps ,si ,shrinking ); }

private :

SolutionInfo *si ;

int select_working_set (int &i , int &j );

double calculate_rho ();

程序代码注释编写规范

程序代码注释编写规范 为提高控制程序的阅读性与可理解性,现制定相关代码程序代码注释编写的编写规范。 一般情况下,源程序有效注释量必须在20%以上,注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不能太少,注释语言必须准确、易懂、简洁。 常规注释有以下两种方式。 单行:以"//"符号开始,任何位于该符号之后的本行文字都视为注释。 多行:以"/*"符号开始,以"*/"结束。任何介于这对符号之间的文字都视为注释。 一、说明性文件 说明性文件(如头文件.h文件、.inc文件、.def文件、编译说明文件.cfg等)头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、修改日志等,头文件的注释中还应有函数功能简要说明。 示例:下面这段头文件的头注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。 /************************************************* COPYRIGHT (C), MicTiVo International. Co., Ltd. File NAME: // 文件 Author: Version: Date: // 作者、版本及完成日期 DESCRIPTION: // 用于详细说明此程序文件完成的主要功能,与其他模块 // 或函数的接口,输出值、取值范围、含义及参数间的控 // 制、顺序、独立或依赖等关系 Others: // 其它内容的说明 Function List: // 主要函数列表,每条记录应包括函数名及功能简要说明 1.... History: // 修改历史记录列表,每条修改记录应包括修改日期、修改 // 者及修改内容简述 1. Date: Author: Modification: 2. .. *************************************************/ 二、源文件头 源文件头部应进行注释,列出:版权说明、版本号、生成日期、作者、模块目的/功能、主要函数及其功能、修改日志等。 示例:下面这段源文件的头注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。 /************************************************************ COPYRIGHT (C), MicTiVo International. Co., Ltd. FileName: Author:

UMAT全过程

UMAT全过程——技术篇 1.ABAQUS中非线性问题的处理2.用户子程序接口3.用户子程序和主程序的结合4.用户材料子程序UMAT接口的原理5.UMAT子程序流程ABAQUS是怎么计算的 I.ABAQUS一共有42个用户子程序接口,15个应用程序接口,可以定义包括边界条 件,荷载条件,接触条件,材料特性以及利用用户子程序和其它应用软件进行数值交换。 1.根据ABAQUS提供的相应接口,按照FORTRAN语法自己编写的代码,是一个独立的程序单元,可以独立地被储存和编译,也能被其他程序单元引用。 I.一般结构形式 II. 一个算例中,可以用到多个用户子程序,但必须把它们放在一个以.for为扩展名的文件中。 III.运行带有用户子程序的算例的两种方法 1.在CAE中运行,在EDIT JOB菜单中的GENRAL子菜单的USERSUBROUTINE GILE对话框中选择用户子程序所在的文件 2.在https://www.doczj.com/doc/9416804.html,MAND中运行语法如下 IV.编制用户子程序时应注意: 1.用户子程序相互之间不能调用,可以调用用户自己编写的Fortran子程序和 ABAQUS应用程序,ABAQUS应用程序必须由用户子程序调用。编写Fortran子程序时,建议子程序以K开头,以免和ABAQUS内部程序冲突。2.用户在用户子程序中利用OPEN打开外部文件时,要注意以下两点: (1)设备号的选择有限制,只能取15~18和大于100的设备号 (2)用户需提供外部文件的绝对路径而不是相对路径。3.对于不同的用户子程序,ABAQUS调用的时间不相同,有的在每个STEP的开始,有的在结尾,有的在每个 INCREMENT的开始。(当ABAQUS在调用用户子程序时,都会把当前的STEP 和INCREMENT 利用用户子程序的两个实参KSTEP 和KINC 传给用户子程序,用户可把他们输出到外部文件中,这样可清楚知道何时调用) V.ABAQUS提供给用户定义自己的材料属性的Fortran程序接口,用户材料子程序 UMAT 通过与ABAQUS主求解程序的接口实现与ABAQUS的资料交流,输入文件中,使用“UESER MATERIAL”表示定义用户材料属性。 I.UMAT子程序采用Fortran语言编制,包括以下几个部分:子程序定义语句、 ABAQUS 定义的参数说明、用户定义的局部变量说明、用户编制的程序主体、子程序返回和结束语句。I.

C语言注释规范

C语言注释规范 1.注释原则 同一软件项目开发中,尽量保持代码注释规范和统一。 注释方便了代码的阅读和维护。 边写代码边注释,修改代码时要相应修改注释,保证注释和代码的一致性。 注释要简洁明确,不要出现形容词。 对于写的好的注释,我们将是第一个受益者。 大型软件开发中,通过别人的注释可以快速知道他人所写函数的功能,返回值,参数的使用。 2.文件头部的注释 示例: / * Program Assignment : 该文件的作用 * Author: 作者 * Date: 2013/8/6 14:34 * Description: 该文件的描述 *****/ /* * Source code in : 源代码的路径 * Function List: * initLinear 初始化线性表 * destoryLinear 释放线性表申请的空间 * isLinearEmpty 判断线性表是否为空 * isLinearFull 判断线性表是否为满 * getLinearElementValue 取得下标为index的元素的值 */ 注意:这个函数列表可以快速查询到我们想要了解的函数。 3.结构体,全局变量等的注释 示例: typedef POLYNOMIAL USER_TYPE; /* 新的数据类型的描述*/ int a; /* 全局变量的作用*/ /* 说明结构体的功能*/ typedef struct LINEAR { USER_TYPE *data; /* 每个成员的意义(作用) */ int maxRoom; /* 每个成员的意义(作用) */

int elementCount; /* 每个成员的意义(作用) */ }LINEAR; 4.函数的注释 在逻辑性较强的的地方加入注释,以便其他人的理解,在一定的程度上排除bug。 示例: /* * Function Name: getLinearElementIndex * Purpose: 取得元素的index值 * Params : * @LINEAR linear 线性表实例 * @USER_TYPE var 类型为USER_TYPE的实例 * @int (*)() cmp 提供接口,让用户定义具体比较函数 * Return: int 返回元素的index值 * Limitation: 如果返回-1,则代表不存在var的元素 */ int getLinearElementIndex(LINEAR linear, USER_TYPE var, int (*cmp)()) { /* * 如果逻辑太过复杂,这里写明该算法的过程和思路。 */ boolean found = FALSE; int i; for(i = 0; i < && !found; i++) if(cmp[i], var) == 0) found = TRUE; if(i >= i = NOT_FOUND; return i; }

华为JAVA编程规范

1 Java 编程规范 1.1 排版 1.1.1 规则 规则1程序块要采用缩进风格编写,缩进的空格数为4个,不允许使用TAB缩进。(1.42+) 说明:缩进使程序更易阅读,使用空格缩进可以适应不同操作系统与不同开发工具。 规则2分界符(如大括号…{?和…}?)应各独占一行,同时与引用它们的语句左对齐。在函数体的开始、类和接口的定义、以及if、for、do、while、switch、case语句中的程序 或者static、,synchronized等语句块中都要采用如上的缩进方式。(1.42+) 示例: if (a>b) { doStart(); } 规则3较长的语句、表达式或参数(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐, 语句可读。(1.42+) 示例: if (logger.isDebugEnabled()) { logger.debug("Session destroyed,call-id" + event.getSession().getCallId()); } 规则4不允许把多个短语句写在一行中,即一行只写一条语句(1.42+) 说明:阅读代码更加清晰 示例:如下例子不符合规范。 Object o = new Object(); Object b = null; 规则5if, for, do, while, case, switch, default 等语句自占一行,且if, for, do, while,switch等语句的执行语句无论多少都要加括号{},case 的执行语句中如果定义变量必须加括号{}。 (1.42+) 说明:阅读代码更加清晰,减少错误产生 示例: if (a>b) { doStart(); }

ABAQUS子程序UMAT里弹塑本构的实现

前言 有限元法是工程中广泛使用的一种数值计算方法。它是力学、计算方法和计算机技术相结合的产物。在工程应用中,有限元法比其它数值分析方法更流行的一个重要原因在于:相对与其它数值分析方法,有限元法对边界的模拟更灵活,近似程度更高。所以,伴随着有限元理论以及计算机技术的发展,大有限元软件的应用证变得越来越普及。 ABAQUS软件一直以非线性有限元分析软件而闻名,这也是它和ANSYS,Nastran等软件的区别所在。非线性有限元分析的用处越来越大,因为在所用材料非常复杂很多情况下,用线性分析来近似已不再有效。比方说,一个复合材料就不能用传统的线性分析软件包进行分析。任何与时间有关联,有较大位移量的情况都不能用线性分析法来处理。多年前,虽然非线性分析能更适合、更准确的处理问题,但是由于当时计算设备的能力不够强大、非线性分析软件包线性分析功能不够健全,所以通常采用线性处理的方法。 这种情况已经得到了极大的改善,计算设备的能力变得更加强大、类似ABAQUS这样的产品功能日臻完善,应用日益广泛。 非线性有限元分析在各个制造行业得到了广泛应用,有不少大型用户。航空航天业一直是非线性有限元分析的大客户,一个重要原因是大量使用复合材料。新一代波音 787客机将全部采用复合材料。只有像 ABAQUS这样的软件,才能分析包括多个子系统的产品耐久性能。在汽车业,用线性有限元分析来做四轮耐久性分析不可能得到足够准确的结果。分析汽车的整体和各个子系统的性能要求(如悬挂系统等)需要进行非线性分析。在土木工程业, ABAQUS能处理包括混凝土静动力开裂分析以及沥青混凝土方面的静动力分析,还能处理高度复杂非线性材料的损伤和断裂问题,这对于大型桥梁结构,高层建筑的结构分析非常有效。 瞬态、大变形、高级材料的碰撞问题必须用非线性有限元分析来计算。线性分析在这种情况下是不适用的。以往有一些专门的软件来分析碰撞问题,但现在ABAQUS在通用有限元软件包就能解决这些问题。所以,ABAQUS可以在一个软件完成线性和非线性分析。 ABAQUS给用户提供了强大二次开发接口,尤其是在材料本构方面,给用户开发符合实际工程的材料本构模型提供了强大帮助,本文将针对其用户材料子程序展开研究,总结常用材料模型的开发方法。

程序代码编写规范

程序编写规范及约定 (仅供内部使用) 文档作者:_______________ 日期:___/___/___ 开发/测试经理:_______________ 日期:___/___/___ 项目经理:_______________ 日期:___/___/___ 请在这里输入公司名称 版权所有不得复制

目录 程序编写规范及约定 (3) 1编写目的 (3) 2代码编写风格 (3) 2.1单元风格 (3) 2.2语句风格 (3) 3命名规则 (3) 3.1命名约定 (3) 3.1.1标志符 (3) 3.1.2类class (3) 3.1.3枚举类型enum (4) 3.1.4委托delegate (4) 3.1.5常量const (4) 3.1.6接口interface (4) 3.1.7方法function (4) 3.1.8命名空间namespace (4) 3.1.9参数 (4) 3.1.10局部变量 (5) 3.1.11数据成员 (5) 3.1.12自定义异常类 (5) 3.1.13命名缩写 (5) 3.1.14数据库命名 (5) 3.2代码编写命名规范 (6) 3.3界面常用控件命名约定 (6) 3.4文件命名规范 (7) 3.4.1文档文件命名 (7) 3.4.2配置文件命名 (7) 3.4.3程序文件命名 (7)

程序编写规范及约定 1编写目的 为了使编写代码具有可读性、可理解性、可维护性,对程序编写人员代码实行统一风格,使得程序代码能够以名称反映含义、以形式反映结构。此文档可供程序代码编写人员及代码维护人员使用。 2代码编写风格 2.1单元风格 2.2语句风格 3命名规则 3.1命名约定 Pascal和Camel命名约定: 编程的命名方式主要有Pascal和Camel两种(Pascal:每个单词的首字母大写,例如ProductType;Camel:首个单词的首字母小写,其余单词的首字母大写,例如productType) 3.1.1标志符 规则:Pascal、Camel 实例与描述:例子说明 3.1.2类class 规则:Pascal 实例与描述:Application

abaqus简单umat子程序

SUBROUTINE UMAT(STRESS,STATEV,DDSDDE,SSE,SPD,SCD,RPL,DDSDDT, 1 DRPLDE,DRPLDT,STRAN,DSTRAN,TIME,DTIME,TEMP,DTEMP,PREDEF,DPRED, 2 CMNAME,NDI,NSHR,NTENS,NSTATV,PROPS,NPROPS,COORDS,DROT, 3 PNEWDT,CELENT,DFGRD0,DFGRD1,NOEL,NPT,LAYER,KSPT,KSTEP,KINC) include 'aba_param.inc' CHARACTER*8 CMNAME DIMENSION STRESS(NTENS),STATEV(NSTATV),DDSDDE(NTENS,NTENS), 1 DDSDDT(NTENS),DRPLDE(NTENS),STRAN(NTENS),DSTRAN(NTENS), 2 TIME(2),PREDEF(1),DPRED(1),PROPS(NPROPS),COORDS(3),DROT(3,3), 3 DFGRD0(3,3),DFGRD1(3,3) C UMAT FOR ISOTROPIC ELASTICITY C CANNOT BE USE D FOR PLAN E STRESS C ---------------------------------------------------------------- C PROPS(1) - E C PROPS(2) - NU C ---------------------------------------------------------------- C IF (NDI.NE.3) THEN WRITE (*,*) 'THIS UMAT MAY ONLY BE USED FOR ELEMENTS 1 WITH THREE DIRECT STRESS COMPONENTS' CALL XIT ENDIF open(400,file='D:\test.txt') C ELASTIC PROPERTIES EMOD=PROPS(1) ENU=PROPS(2) EBULK3=EMOD/(1-2*ENU) EG2=EMOD/(1+ENU) EG=EG2/2 EG3=3*EG ELAM=(EBULK3-EG2)/3 write(400,*) 'temp=',temp C ELASTIC STIFFNESS C DO K1=1, NDI DO K2=1, NDI DDSDDE(K2, K1)=ELAM END DO DDSDDE(K1, K1)=EG2+ELAM

程序代码注释编写规范

程序代码注释编写规范 XXX份公司

为提高控制程序的阅读性与可理解性,现制定相关代码程序代码注释编写的编写规范。 一般情况下,源程序有效注释量必须在20%以上,注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不能太少,注释语言必须准确、易懂、简洁。 常规注释有以下两种方式。 单行:以"//"符号开始,任何位于该符号之后的本行文字都视为注释。 多行:以"/*"符号开始,以"*/"结束。任何介于这对符号之间的文字都视为注释。 一、说明性文件 说明性文件(如头文件.h文件、.inc文件、.def文件、编译说明文件.cfg等)头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、修改日志等,头文件的注释中还应有函数功能简要说明。 示例:下面这段头文件的头注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。 /************************************************* COPYRIGHT (C), MicTiVo International. Co., Ltd. File NAME: // 文件 Author: Version: Date: // 作者、版本及完成日期 DESCRIPTION: // 用于详细说明此程序文件完成的主要功能,与其他模块 // 或函数的接口,输出值、取值范围、含义及参数间的控 // 制、顺序、独立或依赖等关系 Others: // 其它内容的说明 Function List: // 主要函数列表,每条记录应包括函数名及功能简要说明 1.... History: // 修改历史记录列表,每条修改记录应包括修改日期、修改 // 者及修改内容简述 1. Date: Author: Modification: 2. .. *************************************************/ 二、源文件头 源文件头部应进行注释,列出:版权说明、版本号、生成日期、作者、模块目的/功能、主要函数及其功能、修改日志等。 示例:下面这段源文件的头注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。 /************************************************************

程序代码注释编写规范

百度文库- 让每个人平等地提升自我 1 程序代码注释编写规范 为提高控制程序的阅读性与可理解性,现制定相关代码程序代码注释编写的编写规范。 一般情况下,源程序有效注释量必须在20%以上,注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不能太少,注释语言必须准确、易懂、简洁。 常规注释有以下两种方式。 单行:以"文件、.inc文件、.def文件、编译说明文件.cfg等)头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、修改日志等,头文件的注释中还应有函数功能简要说明。 示例:下面这段头文件的头注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。 /************************************************* (C), MicTiVo International. Co., Ltd. 1.File : . History: Date: Author: Modification: 2. .. *************************************************/ 一、源文件头 源文件头部应进行注释,列出:版权说明、版本号、生成日期、作者、模块目的/功能、主要函数及其功能、修改日志等。 示例:下面这段源文件的头注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。 /************************************************************ (C), MicTiVo International. Co., Ltd. FileName: Author: Version : Date: : / /*receive _process() */ 意:与溢出中断写初值不同}

ABAQUS-二次开发资料-UMAT

各个楼层及内容索引 2-------------------------------------什么是UMAT 3-------------------------------------UMAT功能简介 4-------------------------------------UMAT开始的变量声明 5-------------------------------------UMAT中各个变量的详细解释 6-------------------------------------关于沙漏和横向剪切刚度 7-------------------------------------UMAT流程和参数表格实例展示 8-------------------------------------FORTRAN语言中的接口程序Interface 9-------------------------------------关于UMAT是否可以用Fortran90编写的问题 10-17--------------------------------Fortran77的一些有用的知识简介 20-25\30-32-----------------------弹塑性力学相关知识简介 34-37--------------------------------用户材料子程序实例JOhn-cook模型压缩包下载 38-------------------------------------JOhn-cook模型本构简介图 40-------------------------------------用户材料子程序实例JOhn-cook模型完整程序+david详细注解[欢迎大家来看看,并提供意见,完全是自己的diy的,不保证完全正确,希望共同探讨,以便更正,带"?"部分,还望各位大师\同仁指教] 1什么是UMAT??? 1.1 UMAT功能简介!!![-摘自庄茁老师的书 UMAT子程序具有强大的功能,使用UMAT子程序: (1)可以定义材料的本构关系,使用ABAQUS材料库中没有包含的材料进行计算,扩充程序 功能。ABAQUS软件2003年度用户年会论文集 (2)几乎可以用于力学行为分析的任何分析过程,几乎可以把用户材料属性赋予ABAQUS中 的任何单元; (3)必须在UMAT中提供材料本构模型的雅可比(Jacobian)矩阵,即应力增量对应变增量 的变化率。 (4)可以和用户子程序“USDFLD”联合使用,通过“USDFLD”重新定义单元每一物质点上传 递到UMAT中场变量的数值。 1.2 UMAT开始的变量声明 由于主程序与UMAT之间存在数据传递,甚至共用一些变量,因此必须遵守有关书写格式,UMAT中常用的变量在文件开头予以定义,通常格式为: SUBROUTINE UMAT(STRESS,STATEV,DDSDDE,SSE,SPD,SCD, 1 RPL,DDSDDT,DRPLDE,DRPLDT, 2STRAN,DSTRAN,TIME,DTIME,TEMP,DTEMP,PREDEF,DPRED,CMNAME 3 NDI,NSHR,NTENS,NSTATV,PROPS,NPROPS,COORDS,DROT,PNEWDT,

C语言编写规范之注释

1、头文件包含Includes 2、私有类型定义 Private typedef 3、私有定义Private define 4、私有宏定义 Private macro 5、私有变量 Private variables 6、私有函数原型Private function prototypes 7、私有函数Private functions 8、私有函数前注释 /****************************************************************************** * * Function Name : FSMC_NOR_Init * Description : Configures the FSMC and GPIOs to interface with the NOR memory. * This function must be called before any write/read operation * on the NOR. * Input : None * Output : None * Return : None ******************************************************************************* / 9、程序块采用缩进风格编写,缩进空格为4。 10、相对独立的程序块之间、变量说明之后必须加空行; 11、较长的字符(>80字符)要分成多行书写,长表达式要在低优先级操作符划分新行,操作符放在新行之首,新行要恰当缩进,保持排版整齐; 12、循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首; 13、若函数或过程中的参数较长,则要进行适当的划分。 14、不允许把多个短语句写在一行中,即一行只写一条语句。 15、if、for、do、while、case、switch、default等语句自占一行,且if、for、 do、while等语句的执行语句部分无论多少都要加括号{}。 16、对齐只使用空格键,不使用TAB键; 17、 函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格,case 语句下的情况处理语句也要遵从语句缩进要求 18、 程序块的分界符(如C/C++语言的大括号‘{’和‘}’)应各独占一行并且位于同一 列,同时与引用它们的语句左对齐。在函数体的开始、类的定义、结构的定义、枚举的定义以 及if、for、do、while、switch、case语句中的程序都要采用如上的缩进方式。 19、 在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或

程序源代码注释规范

程序注释规范说明 程序注释规范应包括以下三方面: 一、文件头部注释 在代码文件的头部进行注释,这样做的好处在于,我们能对代码文件做变更跟踪。在代码头部分标注出创始人、创始时间、修改人、修改时间、代码的功能,这在团队开发中必不可少,它们可以使后来维护/修改的同伴在遇到问题时,在第一时间知道他应该向谁去寻求帮助,并且知道这个文件经历了多少次迭代、经历了多少个程序员的开发和修改。 样本: /***************************************************** ** 作者:Liuchao ** 创始时间:2007-11-12 ** 修改人:Liuchao ** 修改时间:2007-11-12 ** 修改人:Liaochao ** 修改时间:2007-11-12 ** 描述: ** 主要用于产品信息的资料录入,… *****************************************************/ 二、函数、属性、类等注释 请使用///三斜线注释,这种注释是基于XML的,不仅能导出XML制作帮助文档,而且在各个函数、属性、类等的使用中,编辑环境会自动带出注释,方便你的开发。以protected,protected Internal,public声明的定义注释都建议以这样命名方法。 例如: ///

/// 用于从ERP系统中捞出产品信息的类 ///

class ProductTypeCollector { … } 三、逻辑点注释 在我们认为逻辑性较强的地方加入注释,说明这段程序的逻辑是怎样的,以方便我们自己后来的理解以及其他人的理解,并且这样还可以在一定程度上排除BUG。在注释中写明我们的逻辑思想,对照程序,判断程序是否符合我们的初衷,如果不是,则我们应该仔细思考耀修改的是注释还是程序了… 四、变量注释 我们在认为重要的变量后加以注释,说明变量的含义,以方便我们自己后来的理解以及其他人的理解,并且这样还可以在一定程度上排除BUG.我们常用///三斜线注释。 /// 用于从ERP系统中捞出产品信息的类 class ProductTypeCollector { int STData;/// … }

Abaqus材料用户子程序UMAT基础知识与手册例子完整解释

1、为何需要使用用户材料子程序(User-Defined Material, UMAT )? 很简单,当ABAQUS 没有提供我们需要的材料模型时。所以,在决定自己定义一种新的材料模型之前,最好对ABAQUS 已经提供的模型心中有数,并且尽量使用现有的模型,因为这些模型已经经过详细的验证,并被广泛接受。 UMAT 子程序具有强大的功能,使用UMAT 子程序: (1)可以定义材料的本构关系,使用ABAQUS 材料库中没有包含的材料进行计算,扩充程序功能。 (2) 几乎可以用于力学行为分析的任何分析过程,几乎可以把用户材料属性赋予ABAQU S 中的任何单元。 (3) 必须在UMAT 中提供材料本构模型的雅可比(Jacobian )矩阵,即应力增量对应变增量的变化率。 (4) 可以和用户子程序“USDFLD ”联合使用,通过“USDFLD ”重新定义单元每一物质点上传递到UMAT 中场变量的数值。 2、需要哪些基础知识? 先看一下ABAQUS 手册(ABAQUS Analysis User's Manual )里的一段话: Warning: The use of this option generally requires considerable expertise(一定的专业知识). The user is cautioned that the implementation (实现) of any realistic constitutive (基本) model requires extensive (广泛的) development and testing. Initial testing on a single eleme nt model with prescribed traction loading (指定拉伸载荷) is strongly recommended. 但这并不意味着非力学专业,或者力学基础知识不很丰富者就只能望洋兴叹,因为我们的任务不是开发一套完整的有限元软件,而只是提供一个描述材料力学性能的本构方程(Constitutive equation )而已。当然,最基本的一些概念和知识还是要具备的,比如: 应力(stress),应变(strain )及其分量; volumetric part 和deviatoric part ;模量(modul us )、泊松比(Poisson’s ratio)、拉梅常数(Lame constant);矩阵的加减乘除甚至求逆;还有一些高等数学知识如积分、微分等。 3、UMAT 的基本任务? 我们知道,有限元计算(增量方法)的基本问题是: 已知第n 步的结果(应力,应变等)n σ,n ε,然后给出一个应变增量1+n d ε,计算新的应力1+n σ。UMAT 要完成这一计算,并要计算Jacobian 矩阵DDSDDE(I,J) =εσΔ?Δ?/。σΔ是应力增量矩阵(张量或许更合适),εΔ是应变增量矩阵。DDSDDE(I,J) 定义了第J 个应变分量的微小变化对

UMAT子程序在复合材料强度分析中的应用

UMAT子程序在复合材料强度分析中 的应用 本例使用UMAT用户子程序进行复合材料单层板的应力分析和渐进损伤压缩强度分析,介绍UMA T用户子程序编写方法及在Abaqus/CAE中的设置。本章使用最大应变强度理论作为复合材料单层板的失效准则,相应的Fortran程序简单易读,便于理解UAMT子程序的工作原理。 知识要点: 强度分析 UMAT用户子程序 最大应变理论 刚度折减讲师:孔祥宏 版本:Abq 6.14 难度: 关键词:强度分析,UMAT

『 2 』 第&章复合材料分析入门 &.1 本章内容简介 本章通过两个实例介绍UMAT用户子程序在复合材料单层板的应力分析和强度分析中的应用。在第一个实例中,对一个简单的复合材料单层板进行应力分析,UMAT子程序主要计算应力,不进行强度分析,本例用于验证UMA T子程序的计算精度。在第二个实例中,对复合材料单层板进行渐进损伤强度分析,UMAT子程序用于应力计算、强度分析和刚度折减。 本章所用复合材料为T700/BA9916,材料属性如表&-1所示。 表&-1 T700/BA9916材料属性 参数值强度值 E1/GPa 114 X T/MPa 2688 E2/GPa 8.61 X C/MPa 1458 E3/GPa 8.61 Y T/MPa 69.5 μ120.3 Y C/MPa 236 μ130.3 Z T/MPa 55.5 μ230.45 Z C/MPa 175 G12/GPa 4.16 S XY/MPa 136 G13/GPa 4.16 S XZ/MPa 136 G23/GPa 3.0 S YZ/MPa 95.6

java注释规范总结大全

在软件开发的过程中总是强调注释的规范,但是没有一个具体的标准进行说明,通常都是在代码编写规范中简单的描述几句,不能作为一个代码注释检查的标准和依据,做什么都要有一个依据吗:),现在我特整理了一个《Java的注释规范》,内容来自网络、书籍和自己的实际积累。 JA V A注释规范 版本/状态作者版本日期 1.0 ghc 2008-07-02 一、背景 1、当我们第一次接触某段代码,但又被要求在极短的时间内有效地分析这段代码,我们需要什么样的注释信息? 2、怎么样避免我们的注释冗长而且凌乱不堪呢? 3、在多人协同开发、维护的今天,我们需要怎么样的注释来保证高质、高交的进行开发和维护工作呢? 二、意义 程序中的注释是程序设计者与程序阅读者之间通信的重要手段。应用注释规范对于软件本身和软件开发人员而言尤为重要。并且在流行的敏捷开发思想中已经提出了将注释转为代码的概念。好的注释规范可以尽可能的减少一个软件的维护成本, 并且几乎没有任何一个软件,在其整个生命周期中,均由最初的开发人员来维护。好的注释规范可以改善软件的可读性,可以让开发人员尽快而彻底地理解新的代码。好的注释规范可以最大限度的提高团队开发的合作效率。长期的规范性编码还可以让开发人员养成良好的编码习惯,甚至锻炼出更加严谨的思维能力。 三、注释的原则 1、注释形式统一 在整个应用程序中,使用具有一致的标点和结构的样式来构造注释。如果在其他项目组发现他们的注释规范与这份文档不同,按照他们的规范写代码,不要试图在既成的规范系统中引入新的规范。 2、注释的简洁 内容要简单、明了、含义准确,防止注释的多义性,错误的注释不但无益反而有害。 3、注释的一致性 在写代码之前或者边写代码边写注释,因为以后很可能没有时间来这样做。另外,如果有机会复查已编写的代码,在今天看来很明显的东西六周以后或许就不明显了。通常描述性注释先于代码创建,解释性注释在开发过程中创建,提示性注释在代码完成之后创建。修改代码的同时修改相应的注释,以保证代码与注释的同步。 4、注释的位置 保证注释与其描述的代码相邻,即注释的就近原则。对代码的注释应放在其上方相邻或右方的位置,不可放在下方。避免在代码行的末尾添加注释;行尾注释使代码更难阅读。不过在批注变量声明时,行尾注释是合适的;在这种情况下,将所有行尾注释要对齐。 5、注释的数量 注释必不可少,但也不应过多,在实际的代码规范中,要求注释占程序代码的比例达到20%左右。注释是对代码的“提示”,而不是文档,程序中的注释不可喧宾夺主,注释太多了会让人眼花缭乱,注释的花样要少。不要被动的为写注释而写注释。 6、删除无用注释

java编程规范+数据库命名规范

Java编程规范 本编程规范建立在标准的Java编程规范的基础上,如和标准的Java编程规范有冲突,以本编程规范为准。 1.1 程序结构 包名 引入包/类名 类注释 类 常量//常量注释 构造器注释 构造器 构造器注释 构造器 方法注释 方法 方法注释 方法 1.2 命名规范 命名规范使得程序更易理解,可读性更强。并且能够提供函数和标识符的信息。 文件命名规范: java程序使用如下的文件名后缀: 文件类型后缀 Java 源文件.java Java 字节码文件.class 对系统的文件命名方式有待于根据实际业务决定。 包命名规范: 包名应该唯一,它的前缀可以为任何小写的ASCII字符,包名按照公司内部的命名规范,这些规范指出了某种目录名,主要包括部门,项目,机器,或者登录名。 命名规则为: app.系统名.模块名.xxx.xxx 包命名举例: app.oa.interceptor.xxx app.oa.sys.xxx 类命名规范: 类名应该是名词,并且是大小写混合的。首字母要大写。尽量保证类名简单并且描述性强。避免使用只取单词首字母的简写或者单词的缩写形式,除非缩写形式比单词的完整形式更常用(例如:URL或者HTML)。文件名必须和public的类名保持一致,注意大小写(JBuilder 等一些编译器可以忽略大小写,要特别注意)。如是实现类命名后缀+Impl。 类命名举例: classLoginAction; classUserServiceImpl; 接口命名规范:

接口命名方式与类命名方式相同。 接口命名举例: interfaceIUserService; interfaceSysYhjsDAO; 方法命名规范; 方法名应该为动词,并且是大小写混合的。首字母要小写,方法名的第 二个单词的第一个字母大写。 方法命名举例: String getNoticeNo(); Collection findByCondition(String); 变量命名规范 变量,以及所有的类实例应为首字母小写的大小写混合形式。变量名的第二个单词 的首字母大写。变量名的首字母不能为下划线或者$符。 变量名应该尽可能的短小,但要有意义。变量名应该便于记忆,也就是说变量名应 该尽可能的做到见名知意。除了暂时使用的变量外(一般用于循环变量),应该避免使 用只有一个字母的变量名。对于临时变量一般说来:i,j,k,m,n代表整型变量。c,d,e代表字符型变量。 变量命名举例: String dataType; String name; inti; char c; 常量命名规范: 声明为类常量的变量或者ANSI常量应该全部为大写字母,并且每个单词间用下划 线“_”隔开。为了便于调试,应避免使用ANSI常量。 常量命名举例: static final int MIN_WIDTH = 4; 1.3 注释规范 Java 提供了两种类型的注释:程序注释和文档注释。程序注释是由分隔符/*…*/,和// 隔开的部分,这些注释和C++ 中的注释一样。文档注释(即“doc 注释”)是Java 独有的。由分隔符/**…*/隔开。使用javadoc工具能够将文档注释抽取出来形成HTML 文件。程序注释主要是对程序的某部分具体实现方式的注释。文档注释是对程序的描述性注释,主要是提供给不需要了解程序具体实现的开发者使用。注释应该是代码的概括性描述,提供不易直接从代码中得到的信息,并且只包含对阅读和理解程序有用的信息。例如注释中包含相应的包如何编译或者在哪个目录下,而不应该包括这个包驻留在哪儿的信息。注释中可以描述一些精妙的算法和一些不易理解的设计思想,但应该避免那些在程序代码中很清楚的表达出来的信息。尽可能的避免过时的信息。错误的注释比没有注释更有害。经常性的注释有时也反映出代码质量的低下。 …程序注释: 程序注释有四种格式:块注释格式,单行注释,跟随注释,行尾注释 ?块注释格式 块注释主要用于描述:文件、方法、数据结构和算法。一般在文件或者方法定义的 之前使用。也可以用在方法定义里面,如果块注释放在函数或者方法定义里,它必须与它所描述的代码具有相同的缩进形式。

代码编写规范说明书

代码编写规范说明书(c#.net与https://www.doczj.com/doc/9416804.html,)目录 1 目的 2 范围 3 注释规范 3.1 概述 3.2 自建代码文件注释 3.3 模块(类)注释 3.4 类属性注释 3.5 方法注释 3.6 代码间注释 4 命名总体规则 5 命名规范 5.1 变量(Variable)命名 5.2 常量命名 5.3 类(Class)命名 5.4 接口(Interface)命名 5.5 方法(Method)命名 5.6 名称空间Namespace)命名 6 编码规则 6.1 错误检查规则 6.2 大括号规则 6.3 缩进规则 6.4 小括号规则 6.5 If Then Else规则 6.6 比较规则 6.7 Case规则 6.8 对齐规则 6.9 单语句规则 6.10 单一功能规则 6.11 简单功能规则 6.12 明确条件规则 6.13 选用FALSE规则 6.14 独立赋值规则 6.15 定义常量规则 6.16 模块化规则 6.17 交流规则 7 编程准则 7.1 变量使用 7.2 数据库操作 7.3 对象使用 7.4 模块设计原则 7.5 结构化要求 7.6 函数返回值原则 8 代码包规范 8.1 代码包的版本号

8.2 代码包的标识 9 代码的控制 9.1 代码库/目录的建立 9.2 代码归档 10 输入控制校验规则 10.1 登陆控制 10.2 数据录入控制 附件1:数据类型缩写表 附件2:服务器控件名缩写表 1 目的 一.为了统一公司软件开发设计过程的编程规范 二.使网站开发人员能很方便的理解每个目录,变量,控件,类,方法的意义 三.为了保证编写出的程序都符合相同的规范,保证一致性、统一性而建立的程序编码规范。 四.编码规范和约定必须能明显改善代码可读性,并有助于代码管理、分类范围适用于企业所有基于.NET平台的软件开发工作 2 范围 本规范适用于开发组全体人员,作用于软件项目开发的代码编写阶段和后期维护阶段。 3 注释规范 3.1 概述 a) 注释要求英文及英文的标点符号。 b) 注释中,应标明对象的完整的名称及其用途,但应避免对代码过于详细的描述。 c) 每行注释的最大长度为100个字符。 d) 将注释与注释分隔符用一个空格分开。 e) 不允许给注释加外框。 f) 编码的同时书写注释。 g) 重要变量必须有注释。 h) 变量注释和变量在同一行,所有注释必须对齐,与变量分开至少四个“空格”键。 如:int m_iLevel,m_iCount; // m_iLevel ....tree level // m_iCount ....count of tree items string m_strSql; //SQL i) 典型算法必须有注释。 j) 在循环和逻辑分支地方的上行必须就近书写注释。 k) 程序段或语句的注释在程序段或语句的上一行 l) 在代码交付之前,必须删掉临时的或无关的注释。 m) 为便于阅读代码,每行代码的长度应少于100个字符。 3.2 自建代码文件注释 对于自己创建的代码文件(如函数、脚本),在文件开头,一般编写如下注释: /****************************************************** FileName: Copyright (c) 2004-xxxx *********公司技术开发部 Writer: create Date: Rewriter:

相关主题
文本预览