C++实现矢量场
C++ implementing vector field
我正在尝试从 Lubos Brieda(等离子模拟示例)重新创建等离子模拟。为此,我需要实现一个 3D 场,其中填充了包含电场数据的物理向量。 (我不想使用模板,我指的是 mathematical/physical 意义上的向量。)
本书展示了 Field 和 vec3 class 的创建,以创建具有三个组件的特定类型和数组(向量)的字段。
我的目标是找到实现向量场的最简单方法,如上所述。由于书中提到 Field3
(= Field_<vec3<double>>
) 类型已经实现(但还没有),我认为有一个简单的选择可以做到这一点而不必创建一个新的 class .我试过 using Field3 = Field_<vec3<double>>
但它总是导致以下错误:
Exception thrown: read access violation. **a** was nullptr.
您可以在下面看到导致错误的代码,包括上面提到的 classes。 (我想我排除了所有非必要的东西。我留下了一些带有代码行的注释,您可以使用它们来查看其余代码是否正常工作,只有 Field3
类型会引发错误。)
#include<iostream>
#include"World.h"
#include"Field_.h"
#include"vec3.h"
int main() {
World world(21, 21, 21);
return 0;
}
template <typename T>
struct vec3 {
// assign data
vec3(const T u, const T v, const T w) : d{ u,v,w } {}
vec3(const T a[3]) : d{ a[0],a[1],a[2] } {}
vec3() : d{ 0,0,0 } {}
//protected:
T d[3];
};
using double3 = vec3<double>; // three component vector with doubles
using int3 = vec3<int>;
#pragma once
#include"vec3.h"
template<typename T>
class Field_ { // underscore for undefined type
public:
// constructor
Field_(int ni, int nj, int nk) : ni{ ni }, nj{ nj }, nk{ nk }{
data = new T * *[ni]; // ni pointers to pointers of type T
for (int i = 0; i < ni; i++) {
data[i] = new T * [nj]; // allocte nj pointers to T
for (int j = 0; j < nj; j++)
data[i][j] = new T[nk]; // allocate nk objects of type T
}
operator=(0); // call the overloaded operator= function (initialize with 0)
}
// destructor, frees memory in reverse order
~Field_() {
if (data == nullptr) return; // return if unallocated
for (int i = 0; i < ni; i++) { // release memory in reverse order
for (int j = 0; j < nj; j++)
delete data[i][j];
delete data[i];
}
delete[] data;
data = nullptr; // mark as free
}
// overload the assignment operator
Field_<T>& operator= (const T s) {
std::cout << "Field_ operator=" << std::endl;
for (int i = 0; i < ni; i++)
for (int j = 0; j < nj; j++)
for (int k = 0; k < nk; k++)
data[i][j][k] = s;
return *this; // return reference to self
}
const int ni, nj, nk; // number of nodes
protected:
T*** data; // pointer of type T
};
using Field = Field_<double>; // field of doubles (scalar field)
using Field3 = Field_<double3>; // field of double3s (vector field)
#pragma once
#include"vec3.h"
#include"Field_.h"
class World {
public:
World(int ni, int nj, int nk); //constructor
const int ni, nj, nk;
//Field phi; //electric potential (scalar field)
Field3 ef; //electric field (vector field)
};
//World::World(int ni, int nj, int nk): ni{ ni }, nj{ nj }, nk{ nk }, phi(ni, nj, nk){}
//World::World(int ni, int nj, int nk) : ni{ ni }, nj{ nj }, nk{ nk }, phi(ni, nj, nk), ef(ni, nj, nk) {}
World::World(int ni, int nj, int nk) :
ni{ ni }, nj{ nj }, nk{ nk }, ef(ni, nj, nk) {}
我希望你能帮我弄清楚该怎么做,如果我能在此期间提供任何帮助,请告诉我。
我找到了避免该错误的方法,因为它只会在尝试使用 operator=(0)
初始化矢量场时出现。但是如果我想用零初始化一个标量场,就必须使用这个命令。因此,对 vec3
类型使用相同的命令会导致上述错误,因为覆盖的 operator=
仅适用于标量值。幸运的是 data[i][j] = new T[nk];
已经用零初始化了 vec3
s(如果 T
是某种 vec3
(就像我想使用的 double3 = vec3<double>
))。
我的解决方案是将 operator=(0)
切换为:
if (!std::is_same<T, double3>::value) {operator=(0);}
因此,当 T
的类型为 double3
时,不使用标量初始化。在我的例子中,这应该足够了,因为所有向量场都应该是 double
类型。虽然如果我想要另一种类型,我可以调整 if 语句。
(我认为也可以检查 T
是否类似于 vec3<...>
,但我还没有尝试使用这架飞机,因为我似乎不需要任何其他类型的矢量场.)
我正在尝试从 Lubos Brieda(等离子模拟示例)重新创建等离子模拟。为此,我需要实现一个 3D 场,其中填充了包含电场数据的物理向量。 (我不想使用模板,我指的是 mathematical/physical 意义上的向量。)
本书展示了 Field 和 vec3 class 的创建,以创建具有三个组件的特定类型和数组(向量)的字段。
我的目标是找到实现向量场的最简单方法,如上所述。由于书中提到 Field3
(= Field_<vec3<double>>
) 类型已经实现(但还没有),我认为有一个简单的选择可以做到这一点而不必创建一个新的 class .我试过 using Field3 = Field_<vec3<double>>
但它总是导致以下错误:
Exception thrown: read access violation. **a** was nullptr.
您可以在下面看到导致错误的代码,包括上面提到的 classes。 (我想我排除了所有非必要的东西。我留下了一些带有代码行的注释,您可以使用它们来查看其余代码是否正常工作,只有 Field3
类型会引发错误。)
#include<iostream>
#include"World.h"
#include"Field_.h"
#include"vec3.h"
int main() {
World world(21, 21, 21);
return 0;
}
template <typename T>
struct vec3 {
// assign data
vec3(const T u, const T v, const T w) : d{ u,v,w } {}
vec3(const T a[3]) : d{ a[0],a[1],a[2] } {}
vec3() : d{ 0,0,0 } {}
//protected:
T d[3];
};
using double3 = vec3<double>; // three component vector with doubles
using int3 = vec3<int>;
#pragma once
#include"vec3.h"
template<typename T>
class Field_ { // underscore for undefined type
public:
// constructor
Field_(int ni, int nj, int nk) : ni{ ni }, nj{ nj }, nk{ nk }{
data = new T * *[ni]; // ni pointers to pointers of type T
for (int i = 0; i < ni; i++) {
data[i] = new T * [nj]; // allocte nj pointers to T
for (int j = 0; j < nj; j++)
data[i][j] = new T[nk]; // allocate nk objects of type T
}
operator=(0); // call the overloaded operator= function (initialize with 0)
}
// destructor, frees memory in reverse order
~Field_() {
if (data == nullptr) return; // return if unallocated
for (int i = 0; i < ni; i++) { // release memory in reverse order
for (int j = 0; j < nj; j++)
delete data[i][j];
delete data[i];
}
delete[] data;
data = nullptr; // mark as free
}
// overload the assignment operator
Field_<T>& operator= (const T s) {
std::cout << "Field_ operator=" << std::endl;
for (int i = 0; i < ni; i++)
for (int j = 0; j < nj; j++)
for (int k = 0; k < nk; k++)
data[i][j][k] = s;
return *this; // return reference to self
}
const int ni, nj, nk; // number of nodes
protected:
T*** data; // pointer of type T
};
using Field = Field_<double>; // field of doubles (scalar field)
using Field3 = Field_<double3>; // field of double3s (vector field)
#pragma once
#include"vec3.h"
#include"Field_.h"
class World {
public:
World(int ni, int nj, int nk); //constructor
const int ni, nj, nk;
//Field phi; //electric potential (scalar field)
Field3 ef; //electric field (vector field)
};
//World::World(int ni, int nj, int nk): ni{ ni }, nj{ nj }, nk{ nk }, phi(ni, nj, nk){}
//World::World(int ni, int nj, int nk) : ni{ ni }, nj{ nj }, nk{ nk }, phi(ni, nj, nk), ef(ni, nj, nk) {}
World::World(int ni, int nj, int nk) :
ni{ ni }, nj{ nj }, nk{ nk }, ef(ni, nj, nk) {}
我希望你能帮我弄清楚该怎么做,如果我能在此期间提供任何帮助,请告诉我。
我找到了避免该错误的方法,因为它只会在尝试使用 operator=(0)
初始化矢量场时出现。但是如果我想用零初始化一个标量场,就必须使用这个命令。因此,对 vec3
类型使用相同的命令会导致上述错误,因为覆盖的 operator=
仅适用于标量值。幸运的是 data[i][j] = new T[nk];
已经用零初始化了 vec3
s(如果 T
是某种 vec3
(就像我想使用的 double3 = vec3<double>
))。
我的解决方案是将 operator=(0)
切换为:
if (!std::is_same<T, double3>::value) {operator=(0);}
因此,当 T
的类型为 double3
时,不使用标量初始化。在我的例子中,这应该足够了,因为所有向量场都应该是 double
类型。虽然如果我想要另一种类型,我可以调整 if 语句。
(我认为也可以检查 T
是否类似于 vec3<...>
,但我还没有尝试使用这架飞机,因为我似乎不需要任何其他类型的矢量场.)