编写的一个矩阵类(C++描述)

头文件 Matrix.h
#ifndef _Matrix_
#define _Matrix_

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <cmath>
#include <iomanip>

#include "AllocateArray.h"
using namespace std;


// --------------------------------------------------------------------------

class Matrix
{
public:

	Matrix();
	Matrix(int, int);
	Matrix(const string&);
	
	Matrix Transpose();
	Matrix AlgebraicComplement(int,int);
	Matrix Triangulate();
	Matrix Inverse();
	
	double OneNorm();
	double Det();

	

	void GaussSeidel(vector<double>& X, vector<double>& B, double eps = 1e-6);
	void GaussElimination(vector<double>& X, vector<double>& B);

	~Matrix();


private:

	vector<vector<double> > vvElem_;
	int nRow_;
	int nCol_;
	bool minu_;

public:

	//"<<"overload
	inline friend std::ostream& operator << (std::ostream& out, const Matrix& rhs)
	{
		out << "Rows = " << rhs.nRow_ << "	Columns = "
			<< rhs.nCol_ << endl;
		for( int i = 0; i < rhs.nRow_; i++)
		{
			for( int j = 0; j < rhs.nCol_; j++)
			{
				out << rhs.vvElem_[i][j] << "\t";

			}
			out << endl;

		}
		return out;
	}



	//"+" overload
	Matrix operator + (const Matrix& rhs);

	//"-" overload
	Matrix operator - (const Matrix& rhs);

	//"*" overload
	Matrix operator * (const Matrix& rhs);

	//"*" overload
	Matrix operator * (const vector<double>& Vb);

	//"()" overload
	double& operator () (int i, int j);

	//"+=" overload
	void operator += (const Matrix& rhs);

	//"-=" overload
	void operator -= (const Matrix& rhs);

	//"=" overload
	Matrix& operator = (const Matrix& rhs);

};






#endif
实现文件

Matrix::Matrix():nRow_(0),nCol_(0)
{

}

Matrix::Matrix(int Row, int Col):nRow_(Row), nCol_(Col)
{
	AllocateDim(vvElem_, nRow_, nCol_);
}

Matrix::Matrix(const string& fileName)
{
	ifstream	infile(fileName.c_str(), ios::in);
	string		dataInput;
	while(getline( infile, dataInput ))
	{
		stringstream temp(dataInput);
		double d;
		vector<double> tempV;
		while ( temp >> d)
		{
			tempV.push_back(d);
		}
		vvElem_.push_back(tempV);
		this->nCol_ = tempV.size();
		tempV.clear();
	}
	this->nRow_ = vvElem_.size();
}

// --------------------------------------------------------------------------
/// Geting a transposion of a matrix
/// 
/// @return no
/// 
/// @author Wang li
/// @date 2016-08-09
/// @reviser 
Matrix Matrix::Transpose()
{
	Matrix m(this->nCol_,this->nRow_);
	for( int i = 0; i <  m.nRow_; i++)
	{
		for ( int j = 0; j < m.nCol_; j++)
		{
			m.vvElem_[i][j]=this->vvElem_[j][i];
		}
	}
	return m;
}

// --------------------------------------------------------------------------
/// Getting a algebraic complement
/// 
/// @param ii row to split
/// @param jj column to split
/// 
/// @return Matrix
/// 
/// @author Wang li
/// @date 2016-08-09
/// @reviser 
Matrix Matrix::AlgebraicComplement(int ii, int jj)
{
	Matrix m(this->nRow_-1,this->nCol_-1);
	for( int i = 0; i <  m.nRow_; i++)
	{
		for ( int j = 0; j < m.nCol_; j++)
		{
			if( i < (ii -1) && j < (jj -1))
			{
				m.vvElem_[i][j]=this->vvElem_[i][j];
			}
			else if( i >= (ii -1) && j < (jj -1))
			{
				m.vvElem_[i][j]=this->vvElem_[i+1][j];
			}
			else if( i < (ii -1) && j >= (jj -1))
			{
				m.vvElem_[i][j]=this->vvElem_[i][j+1];
			}
			else if( i >= (ii -1) && j >= (jj -1))
			{
				m.vvElem_[i][j]=this->vvElem_[i+1][j+1];
			}
		}
	}
	return m;
}

// --------------------------------------------------------------------------
/// Geting a transposion of a matrix
/// 
/// @return no
/// 
/// @author Wang li
/// @date 2016-08-09
/// @reviser 
Matrix Matrix::Triangulate()
{
	Matrix m(*this);
	m.minu_ = false;
	bool flag = true ;
	for ( int i = 1; i < nRow_ ; i++)
		if ( flag)
		{
			for ( int j = i; j < nCol_ ; j++)
				if (flag)
				{
					if ( m.vvElem_[i-1][i-1] == 0)
					{
						flag = false;
						for ( int ii = i; ii < nRow_; ii++)
						{
							if ( m.vvElem_[ii][i-1] != 0)
							{

								for(int k = 0 ; k < nCol_; k++)
								{
									double temp = m.vvElem_[ii][k];
									m.vvElem_[ii][k] = m.vvElem_[i-1][k];
									m.vvElem_[i-1][k] = temp;
								}
								m.minu_ = !(m.minu_);
								flag = true;
								break;
							}					
						}
						
						if (!flag) 
						{ 
							break;
						}
						
						double a1a2(0.0);
						a1a2 = m.vvElem_[j][i-1] / m.vvElem_[i-1][i-1];
						for(int k = 0 ; k < nCol_; k++)
						{						
							m.vvElem_[j][k] -= m.vvElem_[i-1][k] * a1a2;
						}

					}
					else
					{	
						double a1a2(0);
						a1a2 = m.vvElem_[j][i-1] / m.vvElem_[i-1][i-1];
						for(int k = 0 ; k < nCol_; k++)
						{						
							m.vvElem_[j][k] -= m.vvElem_[i-1][k] * a1a2;
						}
					}
				}

		}


		return m;
}

// --------------------------------------------------------------------------
/// Getting a inversion of a matrix
/// 
/// @return Matrix
/// 
/// @author Wang li
/// @date 2016-08-09
/// @reviser 
Matrix Matrix::Inverse()
{
	Matrix m(*this);
	double detT = m.Det();
	
	for (int i = 0; i < m.nRow_; i++)
	{
		for (int j = 0; j < m.nCol_; j++)
		{
			m.vvElem_[j][i] = this->AlgebraicComplement(i+1,j+1).Det() * pow(-1.0,i+j) / detT ;
		}
	}

	return m;
}

// --------------------------------------------------------------------------
/// Using gusss elimination to solve a linear matrix equation
/// 
/// @return no
/// 
/// @author Zhang shuai
/// @date 2016-08-09
/// @reviser 
void Matrix::GaussElimination( vector<double>& X, vector<double>& B)
{
	//The Finite Volume Method in Computational Fluid Dynamics An Advanced Introduction with OpenFOAM
	if (vvElem_.size() == X.size() && vvElem_.size() == B.size())
	{
		int N = vvElem_.size();

		for (int k = 0; k < N - 1; k++)
		{
			for (int i = k + 1; i < N; i++)
			{
				double Ratio = vvElem_[i][k] / vvElem_[k][k];

				for (int j = k + 1; j < N; j++)
				{
					vvElem_[i][j] = vvElem_[i][j] - Ratio * vvElem_[k][j];
				}

				B[i] = B[i] - Ratio * B[k];
			}
		}

		X[N - 1] = B[N - 1] / vvElem_[N - 1][N - 1];

		for (int i = N - 2; i >= 0; i--)
		{
			double Term(0);

			for (int j = i + 1; j < N; j++)
			{
				Term = Term + vvElem_[i][j] * X[j];
			}

			X[i] = (B[i] - Term) / vvElem_[i][i];

		}
	}
	else
	{
		cerr << "The input dimension of array is not the same.\nPlease Check the input array." << endl;
	}
}

// --------------------------------------------------------------------------
/// Using gusss seidel iteration method to solve a linear matrix equation
/// 
/// @return no
/// 
/// @author Huang chao
/// @date 2016-08-09
/// @reviser 
void Matrix::GaussSeidel(vector<double>& X, vector<double>& B,double eps)
{
	double error,sum,w(1.3),test(0);
	bool flag(true);

	if (vvElem_.size() == X.size() && vvElem_.size() == B.size())
	{
		int N = vvElem_.size();
		vector<double> Xold(N);
		do
		{
			for(int i = 0; i < N; i++)
			{
				Xold[i] = X[i];
				sum =0.0;
				for(int j = 0; j < N; j++)
				{
					if(j != i) {sum += vvElem_[i][j] * X[j];}
				}

				X[i] = (B[i]-sum)/vvElem_[i][i];

			}

			for(int i = 0; i < N; i++)
			{
				X[i]=w*X[i]+(1-w)*Xold[i];
			}

			for(int i = 0; i < N; i++)
			{
				error=fabs(Xold[i]-X[i])/X[i];
				if(error < eps) {flag = false;}
			}
			test++;

		} while (flag);

	}
	else
	{
		cerr << "The input dimension of array is not the same.\nPlease Check the input array." << endl;
	}


}

// --------------------------------------------------------------------------
/// Getting a determinate of a matrix
/// 
/// @return double
/// 
/// @author Wang li
/// @date 2016-08-09
/// @reviser 
double Matrix::Det()
{
	Matrix m(*this);	

	m = m.Triangulate();

	double mut(1);
	for ( int i = 0 ; i < this->nRow_; i++)
	{
		mut *= m.vvElem_[i][i];
	}
	if(m.minu_) {mut = -mut;}

	return mut;
}

// --------------------------------------------------------------------------
/// Getting the one norm of a matrix
/// 
/// @return double
/// 
/// @author Huang chao
/// @date 2016-08-09
/// @reviser 
double Matrix::OneNorm()
{	
	double mut1(0.0);
	for ( int i = 0 ; i < this->nRow_; i++)
	{
		for ( int j = 0 ; j < this->nCol_; j++)
		{
			mut1 += fabs(vvElem_[i][j]);
		}	
	}
	return mut1;
}

// --------------------------------------------------------------------------
/// overload operator + of matrix
/// 
/// @return Matrix
/// 
/// @author Wang jian
/// @date 2016-08-09
/// @reviser 
Matrix Matrix::operator + (const Matrix& rhs)
{
	Matrix mTemp(rhs);

	cout << " mTemp.vvElem_.size():\t" <<mTemp.vvElem_.size() << endl;

	for(int i = 0; i < rhs.vvElem_.size(); i++)
	{
		for(int j = 0; j < rhs.vvElem_[0].size(); j++)
		{
			mTemp.vvElem_[i][j] = vvElem_[i][j] + rhs.vvElem_[i][j];
		}
	}

	return mTemp;
}

// --------------------------------------------------------------------------
/// overload operator - of matrix
/// 
/// @return Matrix
/// 
/// @author Wang jian
/// @date 2016-08-09
/// @reviser 
Matrix Matrix::operator - (const Matrix& rhs)
{
	Matrix mTemp(rhs);

	for(int i = 0; i < rhs.vvElem_.size(); i++)
	{
		for(int j = 0; j < rhs.vvElem_[0].size(); j++)
		{
			mTemp.vvElem_[i][j] = this->vvElem_[i][j] - rhs.vvElem_[i][j];
		}
	}

	return mTemp;

}

// --------------------------------------------------------------------------
/// overload operator * of matrix
/// 
/// @return Matrix
/// 
/// @author Wang jian
/// @date 2016-08-09
/// @reviser 
Matrix Matrix::operator * (const Matrix& rhs)
{
	if(this->vvElem_[0].size() != rhs.vvElem_.size())
	{
		cerr << " The Matrix A cannot be multiplied by Matrix B" << endl;
	}
	Matrix mTemp(rhs);

	for(int i = 0; i < this->vvElem_.size(); i++)
	{
		for(int j = 0; j < rhs.vvElem_[0].size(); j++)
		{
			mTemp.vvElem_[i][j] = 0.0;
		}
	}

	for(int i = 0; i < this->vvElem_.size(); i++)
	{
		for(int j = 0; j < this->vvElem_[0].size(); j++)
		{
			for(int k = 0; k < rhs.vvElem_[0].size(); k++)
			{
				mTemp.vvElem_[i][k] += this->vvElem_[i][j] * rhs.vvElem_[j][k];
			}		
		}
	}

	return mTemp;

}

// --------------------------------------------------------------------------
/// overload operator () of matrix
/// 
/// @return Matrix
/// 
/// @author Wang li
/// @date 2016-08-09
/// @reviser 
double& Matrix::operator () (int i, int j)
{

	return this->vvElem_[i][j];

}

// --------------------------------------------------------------------------
/// overload operator += of matrix
/// 
/// @return Matrix
/// 
/// @author Wang jian
/// @date 2016-08-09
/// @reviser 
void Matrix::operator += (const Matrix& rhs)
{
	for(int i = 0; i < rhs.vvElem_.size(); i++)
	{
		for(int j = 0; j < rhs.vvElem_[0].size(); j++)
		{
			this->vvElem_[i][j] = this->vvElem_[i][j] + rhs.vvElem_[i][j];
		}
	}
}

// --------------------------------------------------------------------------
/// overload operator -= of matrix
/// 
/// @return Matrix
/// 
/// @author Wang jian
/// @date 2016-08-09
/// @reviser 
void Matrix::operator -= (const Matrix& rhs)
{
	for(int i = 0; i < rhs.vvElem_.size(); i++)
	{
		for(int j = 0; j < rhs.vvElem_[0].size(); j++)
		{
			this->vvElem_[i][j] = this->vvElem_[i][j] - rhs.vvElem_[i][j];
		}
	}
}

// --------------------------------------------------------------------------
/// overload operator = of matrix
/// 
/// @return Matrix
/// 
/// @author Wang jian
/// @date 2016-08-09
/// @reviser 
Matrix& Matrix::operator = (const Matrix& rhs)
{
	this->nRow_ = rhs.nRow_;
	this->nCol_ = rhs.nCol_;

	this->vvElem_.resize(nRow_);
	for(int i = 0; i < rhs.nRow_; i++)
	{
		this->vvElem_[i].resize(nCol_);
	}


	for(int i = 0; i < rhs.nRow_; i++)
	{

		for(int j = 0; j < rhs.nCol_; j++)
		{
			this->vvElem_[i][j] = rhs.vvElem_[i][j];
		}

	}

	this->minu_ = rhs.minu_;

	return *this;

}

Matrix::~Matrix()
{
}


  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
### 回答1: 单元刚度矩阵是有限元分析中的一个重要概念,用于描述单元内部的物理特性和材料性质。下面是一个简单的C语言函数,用于计算一维杆单元的刚度矩阵。 ```c void getElementStiffnessMatrix(double E, double A, double L, double* k) { double k_val[2][2] = {{E*A/L, -E*A/L}, {-E*A/L, E*A/L}}; for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { k[i*2+j] = k_val[i][j]; } } } ``` 其中,E表示弹性模量,A表示截面积,L表示单元长度,k是一个指向长度为4的数组的指针,用于存储刚度矩阵的值。这个函数会计算一个2x2的刚度矩阵,并将其存储在k数组中,其中k[0]表示第一行第一列的元素,k[1]表示第一行第二列的元素,以此推。这个函数可以根据需要进行修改,以适应不同型的单元和不同的材料性质。 ### 回答2: 单元刚度矩阵是在有限元分析中使用的一个重要工具,它用于描述物体在应力作用下的刚度特性。在编写单元刚度矩阵时,需要考虑几个关键因素。 首先,我们需要确定所需的单元型,例如梁单元、块单元或平面单元。不同型的单元有不同的几何形状和约束条件,因此在编写单元刚度矩阵时需要注意相应的几何参数和边界约束。 其次,单元刚度矩阵编写涉及到计算单元的刚度系数,这些系数反映了物体在受力时的刚度特性。确定刚度系数的方法主要通过斯特拉斯解法或解析法。斯特拉斯解法通常涉及到将物体分割成单元,在每个单元上进行刚度矩阵的计算,再进行组装以得到整体刚度矩阵。解析法则通过使用适当的数学公式和物理规律直接计算刚度矩阵。 最后,还需考虑材料的弹性特性。刚度矩阵编写需要使用材料的弹性模量和泊松比等参数。这些参数通常需要通过材料力学测试或其他已知的方法获得。 总之,在编写单元刚度矩阵时需要考虑单元型、几何约束、刚度系数计算方法以及材料弹性特性等因素。合理编写刚度矩阵可以帮助我们准确地描述物体在受力时的刚度特性,为有限元分析提供可靠的依据。 ### 回答3: 单元刚度矩阵是在有限元分析中用于描述单元内各节点受力和位移之间关系的矩阵。在编写单元刚度矩阵的过程中,首先需要确定单元的几何形状和材料性质,以及边界条件。下面是编写单元刚度矩阵的一般步骤: 1. 构建单元刚度矩阵的初始形式:根据单元的几何形状和材料性质,可以推导出单元的刚度矩阵的初始形式。对于常见的单元型,如杆单元、梁单元和三角形单元,其初始刚度矩阵通常是已知的。 2. 将初始形式转化为全局坐标系:将初始刚度矩阵的局部坐标系转化为全局坐标系。这需要考虑到单元的位移和旋转矩阵。 3. 考虑边界条件和节点约束:将边界条件和节点约束应用到全局刚度矩阵中。这将导致一些行和列被清零,以反映具有约束自由度的节点。 4. 汇总单元刚度矩阵:将所有单元的刚度矩阵汇总成总体刚度矩阵。这需要将每个单元的刚度矩阵根据其节点的自由度索引插入到总体刚度矩阵中的相应位置。 5. 解决线性方程组:根据边界条件,将总体刚度矩阵进行约减,得到一个由未知位移组成的线性方程组。通过求解这个线性方程组,可以得到每个节点的位移和应力。 编写单元刚度矩阵需要对结构和有限元方法有深入的了解,并使用适当的数学推导和程序计算。这是有限元分析的核心内容之一,对于解决各种结构和工程问题具有重要作用。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值