C++ implementing vector field

独自空忆成欢 提交于 2021-02-08 11:38:57

问题


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. 

VectorFieldError

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 vec3s 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!