maoptim.cpp
来自「电力系统稀疏矩阵计算类,用法范例代码,包括三个目录,MALIB(类),MATES」· C++ 代码 · 共 796 行 · 第 1/2 页
CPP
796 行
//===========================================================================
//
// EMS高级应用软件
//
//===========================================================================
// rev 0.0 7-29-2004 initial release Qwbin
// 版本 0.0 7-29-2004 第一次发布 齐文斌
// 1.0 1-27-2006 修改为C++vector方式 齐文斌
//---------------------------------------------------------------------------
#include <malib.h>
//************************************************************************
// maoptim - sparse matrix optimal ordering
// 稀疏矩阵优化排序----主控
// maorder_vt.push_back(maorderpt); 暂时放此
//************************************************************************
int EmsMatrix::maoptim()
{
int rc;
int n;
int nonsymmetric;
struct opworkst work; //临时空间,只有一个结构(一条纪录)
memset ( &work, 0, sizeof(work));
opinitialize (&work);
nonsymmetric = test_symmetry(&work);
if ( nonsymmetric )
make_symmetric ( &work );
if ( ! work.stat.overflow )
{
scheme1 ( &work );
while ( work.num_zero_fillin < work.num_zero_diagonal )//work.num_zero_fillin初始清零 mdn 8.11
{
n = work.num_zero_fillin;
reorder_scheme1 ( &work );
if ( work.num_zero_fillin == n )
{
printf("maoptim:REORDER FOR ZERO DIAGONAL FAILED %d \n", n );
break;
}
}
scheme2 ( &work );
}
opterminate ( &work );
if ( work.stat.overflow )
rc = !SUCCESS;
else
rc = SUCCESS;
return ( rc );
}
//************************************************************************
// initialize - initialize internal work areas
// 初始化,给 workpt赋初值
// 统计每列连接元素数statept->connection_cnt
//************************************************************************
// 函数名称: opinitialize
// 返回值: 无
// 函数功能: 形成链表,建立statest与linkst的关联结构,具体链表结构
// 图见潮流计算文档
// 变量说明: 1、linkcnt 为经验公式,意在开辟较大的链表空间
// 2、colstatept 指针指向当前节点所连当前支路的尾节点
// 注意事项: 链表中各链节众多指针的指向比较复杂,容易混淆,需注意
// 注释信息: mdn 8.16
//************************************************************************
void EmsMatrix::opinitialize(struct opworkst *workpt)
{
int i, j,linkcnt;
unsigned int size;
struct opstatest *statept, *colstatept;
struct oporderst *orderpt;
struct oplinkst *linkpt, *next_linkpt;
struct mastatest *mastatept;
struct maamtrxst *maamtrxpt;
//add by qwbin 2006-2-11
nmastate = mastate_vt.size();
nmaamtrx = maamtrx_vt.size(); nmagmtrx = magmtrx_vt.size(); //nmagmtrx = 12*nmaamtrx;
workpt->off_diagonalpt = nmagmtrx;
size = nmastate * sizeof( struct opstatest );
workpt->statept = (struct opstatest *)malloc(size);
memset ( (char *) workpt->statept, 0, size );
statept = workpt->statept;
for (i = 1; i <= nmastate; i++, statept++)
{
mastatept = mastate_vt[i-1];
statept->stateitm = i; //statept 重新编号
statept->maamtrx_itm = mastatept->maamtrx_itm;
statept->maamtrx_cnt = mastatept->maamtrx_cnt;
if ( mastatept->stat.active )
{
statept->stat.active = TRUE;
//对角元素为0的标志
if ( mastatept->diag == 0.0 )
{
statept->stat.zero_diag = TRUE;
statept->stat.reorder = TRUE;
workpt->num_zero_diagonal++;
}
}
}
size = nmastate * sizeof( struct oporderst );
workpt->orderpt = (struct oporderst *)malloc( size );
memset ( (char *) workpt->orderpt, 0, size );
for (i = 1, orderpt = workpt->orderpt; i <= nmastate; i++, orderpt++ )
orderpt->orderitm = i;
workpt->last_orderpt = orderpt - 1;
workpt->skip_orderpt = orderpt - AS_ORDER_SKIP;
//我理解这里是个经验值,没有精确的计算意义,对于列向量多的矩阵,参数必须增加
linkcnt = AS_ORDER_STATE_MULT*nmastate + AS_ORDER_AMTRX_MULT*nmaamtrx;
size = linkcnt * sizeof ( struct oplinkst );
workpt->linkpt = (struct oplinkst *)malloc( size );
workpt->garbagept = workpt->linkpt;
linkpt = workpt->linkpt;
//链表形成
for ( i = 0; i < linkcnt; i++ )
{
next_linkpt = linkpt + 1;
linkpt->linkpt = next_linkpt;
linkpt = next_linkpt;
}
linkpt--;
//linkpt指向最后一个地址
linkpt->linkpt = NULL;
statept = workpt->statept;
//以下代码的功能是:通过全部矩阵元素的遍历,找出与各节点的连接全部节点
// //对行循环statept++,改变了链表关系,指向前一LINKPT
for ( i = 0; i < nmastate; i++, statept++ ) //按节点循环 mdn 8.2
{
if ( statept->stat.active )
{
//行首元素.
//maamtrxpt = workpt->maamtrxpt + statept->maamtrx_itm - 1;
//对该行的列循环,形成linkpt链表(有元素存在,表示行,列标号的两节点关联)
for ( j = 0; j < statept->maamtrx_cnt; j++)//按节点所连支路循环 mdn 8.2
{
maamtrxpt =maamtrx_vt[j+statept->maamtrx_itm-1];
//矩阵元素对应列节点指针
colstatept = workpt->statept + maamtrxpt->colitm - 1;//指向当前节点所连支路的末端节点!mdn 8.6
if ( colstatept->stat.active )
{
//临时数据,前次linkpt记录
linkpt = workpt->garbagept; //临时变量,完成linkst结构链表的遍历 mdn 8.6
//记录下次linkpt值,下一次用
workpt->garbagept = linkpt->linkpt;//已经构造完毕,由此实现linkpt遍列
//linkpt->statept = 找到的矩阵元素对应列节点.
linkpt->statept = colstatept; //指向当前支路的尾节点 mdn 8.6
//行的下一LINK值与STATE的现在LINK一致 //内循环中statept指针是不变的
linkpt->linkpt = statept->linkpt; //形成前向链表 mdn 8.6
//返回给statept,记录下LINK指针
statept->linkpt = linkpt;//好象是为了变换指针,由此实现linkpt遍列,做临时变量用
//计数
statept->connection_cnt++;//当前节点的度 mdn 8.6
}
}
}
}
return;
}
//************************************************************************
// test_symmetry - test for symmetric matrix
// 统计mastate->cnt 比较statept的linkpt数是否一致.
//************************************************************************
// 函数名称: test_symmetry
// 返回值: int
// 函数功能: 用来测试形成的链表结构是否成称,即链表是否与原有节点导纳阵
// (或网络)结构相同。
// 判断原则: 比较statept->linkpt(指向行链表首链节)所连链表的链节数目是
// 否与statept->connection_cnt(节点导纳阵形成过程中计数)相等。
// 如二者相等,则说明链表结构对称;不等,则说明链表结构不对称,
// 需调用函数make_symmetric( ),以使链表结构对称。
// 变量说明:
// 注意事项: 链表中各链节众多指针的指向比较复杂,容易混淆,需注意
// 注释信息: mdn 8.16
//************************************************************************
int EmsMatrix::test_symmetry (struct opworkst *workpt)
{
int i, nrow = 0, nhole = 0;
int rc = SUCCESS;
struct opstatest *statept;
struct oplinkst *linkpt;
statept = workpt->statept;
for ( i = 0; i < nmastate; i++, statept++ )
{
linkpt = statept->linkpt; //指向当前节点所连最后一条支路的链节 mdn 8.10
while ( linkpt != NULL )
{
linkpt->statept->cnt++; //当前节点度加1 mdn 8.10
linkpt = linkpt->linkpt; //移到下一链节,此处为内存地址小的链节即上一支路 mdn 8.10
}
}
statept = workpt->statept;
for ( i = 0; i < nmastate; i++, statept++ )
{
if ( statept->cnt != statept->connection_cnt ) //不对称,即链表形成过程有误 mdn 8.10
{
nrow++;
rc = !SUCCESS;
nhole += abs( statept->cnt - statept->connection_cnt );
}
}
return ( rc );
}
//************************************************************************
// make_symmetric - establish symmetric matrix
// 形成对称矩阵
//************************************************************************
void EmsMatrix::make_symmetric( struct opworkst *workpt)
{
int i, nrow = 0, nhole = 0;
struct opstatest *statept, *jstatept;
struct oplinkst *linkpt, *jlinkpt;
statept = workpt->statept;
//对节点循环
for ( i = 0; i<nmastate; i++,statept++ )
{
linkpt = statept->linkpt;
while ( linkpt != NULL )
{
jstatept = linkpt->statept;
jlinkpt = jstatept->linkpt;
while ( jlinkpt != NULL )
{
if ( jlinkpt->statept == statept )
break;
jlinkpt = jlinkpt->linkpt;
}
linkpt = linkpt->linkpt;
if ( jlinkpt == NULL )
{
if ( workpt->garbagept == NULL )
{
linkpt = NULL;
workpt->stat.overflow = TRUE;
}
else
{
jstatept->stat.hole = TRUE;
nhole++;
jlinkpt = workpt->garbagept;
workpt->garbagept = jlinkpt->linkpt;
jlinkpt->statept = statept;
jlinkpt->linkpt = jstatept->linkpt;
jstatept->linkpt = jlinkpt;
}
}
}
if ( workpt->stat.overflow )
break;
}
return;
}
//************************************************************************
// scheme1 - perform scheme I ordering
// 形成序,按自然顺序,形成orderpt
//************************************************************************
//************************************************************************
// 函数名称: scheme1
// 返回值: 无
// 函数功能: 为节点优化编号的主要步骤之一,按各节点度由小到大的顺序排列,
// 通过numconpt指针(由base_numconpt处开始)找到度最小的节点链
// 表linkst,再通过linkpt->statept找到度最小的节点。
// 变量说明:
// 注意事项: 此处linkst链节含义(主要存储节点信息)不同于初始化中linkst链节
// 含义(主要存储节点所连支路信息)。
// 注释信息: mdn 8.16
//************************************************************************
void EmsMatrix::scheme1 ( struct opworkst *workpt )
{
int i, max_numcon,norder, cnt;
unsigned int size;
struct numconst *base_numconpt, *numconpt;
struct opstatest *statept;
struct oporderst *orderpt;
struct oplinkst *linkpt, *next_linkpt;
max_numcon = 0;
//找出各节点的度的最大值
for (i = 0, statept = workpt->statept; i < nmastate; i++, statept++ )//找出各节点的度的最大值 mdn 8.11
{
if ( statept->connection_cnt > max_numcon )
max_numcon = statept->connection_cnt;
}
max_numcon++;
size = ( max_numcon + 1 ) * sizeof ( struct numconst );
base_numconpt = (struct numconst *)malloc ( size );
memset ( (char *) base_numconpt, 0, size );
//对全部state循环,形成 numconpt,numconpt存放linkpt
for (i = 0, statept = workpt->statept; i < nmastate; i++, statept++ )//形成的链表结构详见图1 mdn 8.11
{
linkpt = workpt->garbagept;
workpt->garbagept = linkpt->linkpt;
if ( statept->stat.active )
cnt = statept->connection_cnt + 1;
else
cnt = 0;
numconpt = base_numconpt + cnt;
linkpt->statept = statept;
linkpt->linkpt = numconpt->linkpt;
numconpt->linkpt = linkpt;
}
orderpt = workpt->orderpt;
norder = 1;
//按自然顺序,形成orderpt,
for (i = 0, numconpt = base_numconpt; i <= max_numcon; i++, numconpt++ )////形成的链表结构详见图1 mdn 8.11
{
linkpt = numconpt->linkpt;
while ( linkpt != NULL )
{
statept = linkpt->statept;
orderpt->statept = statept;
statept->orderpt = orderpt;
next_linkpt = linkpt->linkpt;
linkpt->linkpt = workpt->garbagept;
workpt->garbagept = linkpt;
linkpt = next_linkpt;
orderpt++; // 为节点优化后的链表,orderpt->statept->stateitm为优化后的顺序所对应的原始节点号 mdn 8.11
norder++; //相当于I5,即优化后的排序 mdn 8.10
}
}
free ( base_numconpt );
return;
}
//************************************************************************
// reorder_scheme1 - reorder Scheme I for zero diagonals
// 0对角元放到最前
//************************************************************************
void EmsMatrix::reorder_scheme1 ( struct opworkst *workpt )
{
int i;
struct oporderst *orderpt, *new_orderpt, *last_orderpt;
struct oplinkst *linkpt;
//最后一行记录的指针
last_orderpt = workpt->orderpt + nmastate - 1;
orderpt = workpt->orderpt;
for ( i = 0; i < nmastate; i++, orderpt++ )
{
if ( orderpt->statept->stat.active )
{
//0对角元
if ( orderpt->statept->stat.reorder )
{
new_orderpt = last_orderpt;
linkpt = orderpt->statept->linkpt;
while ( linkpt != NULL )
{
//链接不为0对角元
if ( ! linkpt->statept->stat.reorder )
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?