问题
I'm trying to recreate a Plasma Simulation from Lubos Brieda (Plasma Simulations by Example). In doing so, I need to implement a 3D field filled with physical vectors containing the data of the electric field. (I don't want to use the template, I'm referring to vectors in the mathematical/physical sense.)
The book shows the creation of a Field and vec3 class, to create fields of certain types and arrays (vectors) with three components.
My goal is to find the easiest way to implement a vector field, as described above. Since the book mentions that the Field3
(= Field_<vec3<double>>
) type has been implemented (but hasn't), I assume there is an easy option to do so without having to create a new class. I tried using Field3 = Field_<vec3<double>>
but it always resulted in the following error:
Exception thrown: read access violation. **a** was nullptr.
Below you can see the code resulting in the error including the classes mentioned above. (I think I excluded everything non-essential. I left some comments with code lines you can use those to see that the rest of the code is working, only the Field3
type provokes the error.)
#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) {}
I hope you can help me figure out what to do and please let me know, if I can be of any assistance during that.
回答1:
I found a way to avoid the error, because it only comes up, when trying to initialize a vector field using operator=(0)
. But this command has to be used, if i want to initalize a scalar field with zeros. Thus using the same command for a vec3
-type results in the error mentioned above, since the overridden operator=
only works for scalar values. Luckily data[i][j] = new T[nk];
already initializes vec3
s with zeros (if T
is some kind of vec3
(like double3 = vec3<double>
as I would like to use)).
My solution is to switch operator=(0)
with:
if (!std::is_same<T, double3>::value) {operator=(0);}
So the scalar initialization is not used, when T
is of type double3
. In my case this should be sufficient, since all vector fields should be of type double
. Though if I want another type, I can just adapt the if-statement.
(I think it could also be possible to check whether T
is something like vec3<...>
, but I haven't tried around with this jet, because I don't seem to need any other type of vector field.)
来源:https://stackoverflow.com/questions/65752273/c-implementing-vector-field