目的是在二维环境下模拟一个真正的平板电容器。电枢的电位固定在+V和-V上,在模拟单元的边缘电位为零。在电容器板之间放置介质材料。通过数值确定板上的电荷和积分电场的流动,计算了电容。结果与不考虑边缘效应的公式进行了比较。
我正在寻找使它更高效的方法,以及如何使用一些功能,因为我不认为它看起来很清楚。
#include
#include
#include
#include
using namespace std;
int main(int argc, const char * argv[])
{
double Lx,Ly;//lunghezze lati cella di simulazione
int Nx,Ny;//numero punti lungo x e y
double Px,Py;//posizione rispetto all'origine del vertice della prima piastra
double Zx,Zy;//posizione rispetto all'angolo del bordo a destra del vertice della seconda piastra
double Lc;//spessore della piastra
double Hc;//altezza piastra
int dist_type;//tipo di distribuzione di carica: 1-uniforme
double thrs;//valore soglia per convergenza
double V;
double Nstampa;
int iCount;
int phi_bordo=0.;//funzione phi sul bordo
double hx,hy;
double diff=1e10;
ofstream fphi,fcharge, ffield;
cout.precision(10);
cout << "Lato cella lungo x\n";
cin >> Lx;
cout << "Lato cella lungo y\n";
cin >> Ly;
cout << "Numero punti lungo x\n";
cin >> Nx;
cout << "Numero punti lungo y\n";
cin >> Ny;
cout << "Vertice piastra 1 in x\n";
cin >> Px;
cout << "Vertice piastra 2 in y\n";
cin >> Py;
cout << "Vertice piastra 1 in x\n";
cin >> Zx;
Zx = Lx - Zx;
cout << "Vertice piastra 2 in y\n";
cin >> Zy;
cout << "Spessore piastra \n";
cin >> Lc;
cout << "Altezza piastra \n";
cin >> Hc;
cout << "Potenziale piastre (in Volt) \n";
cin >> V;
cout << "Soglia per convergenza \n";
cin >> thrs;
double* phi0= new double[Nx*Ny];//funzione da trovare
double* phi1= new double[Nx*Ny];//funzione da trovare
double* phi2= new double[Nx*Ny];//funzione da trovare
double* ftilde=new double[Nx*Ny];//distribuzione di carica e fattori bordo
double* mphi= new double[Nx*Ny];
hx=Lx/(Nx-1.);
hy=Ly/(Ny-1.);
iCount=0; //iCount corrisponde all'indice l delle dispense l = j*Nx + i con i,j indici rispettivamente di xi e yj
//infatti stiamo calcolando ftilde che è l'array indicizzato con l
for(int j=0;j=Px && x<=(Px+Lc) && y>=Py && y<=(Py+Hc)) {
ftilde[iCount]=V;
}
else if(x>=Zx && x<=(Zx+Lc) && y>=Zy && y<=(Zy+Hc)){
ftilde[iCount]=-V;
}
else{
ftilde[iCount]=0.;
}
//potenziale sul bordo della cella
if(i==0 || i==(Nx-1) || j==0 || j==(Ny-1)){
ftilde[iCount]+=phi_bordo;
}
iCount++;
}
}
//metti phi0 in condizioni iniziali quindi pari a 0
for(int i=0;ithrs){
for(int i=0;i0){
jCount=j*Nx+(i-1); // m = l-1
mphi[iCount]+=-phi0[jCount]/pow(hx,2)/div;
}
if(i0){
jCount=(j-1)*Nx+i;// m = l - Nx
mphi[iCount]+=-phi0[jCount]/pow(hy,2)/div;
}
if(j发布于 2023-03-05 14:23:27
关于混合语言的
我看你的程序是为意大利用户准备的。但是开发人员说的是什么语言呢?注释也都是意大利语,但是变量的名称是意大利语(例如,Nstampa、Flusso1)和英语(dist_type,iCount)的混合。
在使用哪种语言时要保持一致。当然,C++语言的关键字以及标准库中的函数和类型的名称都是英语,这一点也没有帮助。所以我建议你用英语写你所有的代码。如果您希望只有意大利开发人员在这个项目上工作,那么在注释中使用意大利语是可以的。当然,写到std::cout的文本应该是用户所期望的语言,所以如果这是意大利语的话,那也没关系。
短变量名可以节省一些输入量,但很难准确地说明它们的含义。如果我看到代码中使用了Lx,我不确定L是否代表长度,但是即使我知道,长度是多少?电容器本身的长度?还是其中的一个细胞?一个更好的变量名是cell_size_x。
为什么有三个数组-- phi0、phi1和phi2?phi到底是什么意思?通量?阶段?角度?声明中的评论根本没有提到这一点。
如果您使用的是一本书或一篇文章中的一些公式,并且希望在代码中使用与它们在这些公式中使用的符号相同的符号,这是保持变量名简短的一个有效理由,但在这种情况下,您必须在代码中添加到图书或纸张的链接。
structs中
我看到您创建了5个数组,保存了模拟中每个单元格的信息。考虑创建一个保存有关单个单元格的所有信息的struct,然后只需创建一个数组:
struct Cell {
double phi0;
double phi1;
double phi2;
double ftilde;
double mphi;
};
Cell* cells = new Cell[Nx * Ny];
…
for (int i = 0; i < Nx * Ny; i++) {
cells[i].phi1 = cells[i].ftilde;
cells[i].phi0 = cells[i].ftilde;
cells[i].phi2 = 0;
}你也有几个二维矢量。为此创建一个struct也很有帮助。例如:
struct Vec2 {
double x;
double y;
};
Vec2 cell_size; // replaces Lx and Ly如果添加运算符重载,它们就会变得更有用,因此您可以像使用常规的ints和doubles那样对它们进行计算。但是,自己创建这个库可能需要很多工作,所以我建议您选择一个为您实现向量类型的库,例如GLM,但也有许多其他人。
而不是用new分配数组,而必须记住要使用delete,而是使用std::vector。内存泄漏,因为您注释掉了Emat和E的D34语句。
使用std::vector还有其他好处:您可以在某些地方使用range-for语句。考虑:
struct Cell {…};
std::vector cells(Nx * Ny);
…
for (auto& cell: cells) {
cell.phi1 = cell.ftilde;
cell.phi0 = cell.ftilde;
cell.phi2 = 0;
}我看到8.8541878e-12在您的代码中多次使用的数字。与其每次写出来,不如为它定义一个常量,例如:
constexpr double e0 = 8.854187812813e-12; // Vacuum permitivity in Farads/meter请注意,e0类似于这个常量通常使用的数学表示法\epsilon_0,如果不熟悉它的人正在阅读代码,注释将对其进行更详细的解释。
您已经注意到代码看起来不太好,并且可以从函数中受益。一种很好的开始方法是将main()重写成描述您需要在很高级别上做的事情的东西。例如,程序中有以下步骤:
您可以这样编写您的main():
struct State {
// All the variables needed to run the simulation
…
}
static void read_parameters(State& state) {
cout << "Lato cella lungo x\n";
cin >> state.Lx;
…
}
static void initialize_state(State& state) {
…
state.cells.resize(state.Nx * state.Ny);
…
for (auto& cell: state.cells) {
cell.phi1 = cell.ftilde;
cell.phi0 = cell.ftilde;
cell.phi2 = 0;
}
…
}
static void run_simulation(State& state) {
…
}
static void process_results(State& state) {
…
}
static void write_results(State &state) {
std::ofstream fcharge("carica.dat");
std::ofstream fphi("phi.dat");
std::ofstream ffield("campo.dat");
…
}
int main() {
State state;
read_parameters(state);
initialize_state(state);
run_simulation(state);
process_results(state);
write_results(state);
}一些新功能也会非常大,您可以进一步将它们分开。一个好的经验法则是函数不应该大于一个屏幕。此外,在示例中,程序中使用的所有状态都在struct State中,并传递给每个函数。然而,并不是每个函数都需要访问所有的东西,所以struct State可能会被分成多个structs,因此限制了每个函数可以获得哪些信息。您可能需要迭代这个过程几次才能达到这样一种情况:您有许多小的、简洁的函数和类型,这些函数和类型共同构成了一个内聚程序。
创建函数和structs的另一个好处是,它们的名字将描述它们所做的事情。这有助于记录代码,减少添加注释的需要。
https://codereview.stackexchange.com/questions/283725
复制相似问题