Add tools or demos that create plasma from 2D and 3D profiles defined on triangular and tetrahedral meshes
The issue is already discussed in #211 and #336. The tools for triangular meshes are needed to port the edge plasma profiles from cherab/solps to cherab/core. The tools for tetrahedral meshes may be required for the users working with the EMC3-Eirene data.
For scalar fields, the Discrete2DMesh and Discrete3DMesh interpolators can be used for triangular and tetrahedral meshes respectively. For vector fields we need to add the Vector3D versions of these interpolators to Raysect. At the moment I propose adding the following functions in cherab/tools/plasmas:
def plasma_from_2d_profiles(vertex_coords, triangles, electron_density, electron_temperature, species_density=None, species_temperature=None,
parent=None, transform=None, name='Mesh2D Plasma'):
"""
Creates Plasma object from the plasma profiles defined on a triangular 2d mesh.
:param ndarray vertex_coords: An array of vertex coordinates (R, Z) with shape Nx2.
:param ndarray triangles: An array of vertex indices defining the mesh triangles,
with shape Mx3.
:param ndarray electron_density: Electron density profile of shape Mx1.
:param ndarray electron_temperature: Electron temperature profile of shape Mx1.
:param ndarray species_density (optional): A dict with (element/isotope, charge) keys
containing density profile of shape Mx1of each plasma species.
:param ndarray species_temperature (optional): A dict with (element/isotope, charge) keys
containing temperature profile of shape Mx1 of each plasma species.
:param Node parent (optional): The plasma's parent node in the scenegraph, e.g. a World object.
:param AffineMatrix3D transform (optional): Affine matrix describing the location and orientation
of the plasma in the world.
:param str name (optional): User friendly name for this plasma (default = "Mesh2D Plasma").
:rtype: Plasma
"""
def plasma_from_3d_profiles(vertex_coords, tetrahedras, electron_density, electron_temperature, species_density=None, species_temperature=None,
parent=None, transform=None, name='Mesh3D Plasma'):
"""
Creates Plasma object from the plasma profiles defined on a triangular 2d mesh.
:param ndarray vertex_coords: An array of vertex coordinates (X, Y, Z) with shape Nx3.
:param ndarray triangles: An array of vertex indices defining the mesh triangles,
with shape Mx3.
:param ndarray electron_density: Electron density profile of shape Mx1.
:param ndarray electron_temperature: Electron temperature profile of shape Mx1.
:param ndarray species_density (optional): A dict with (element/isotope, charge) keys
containing density profile of shape Mx1 of each plasma species.
:param ndarray species_temperature (optional): A dict with (element/isotope, charge) keys
containing temperature profile of shape Mx1 of each plasma species.
:param Node parent (optional): The plasma's parent node in the scenegraph, e.g. a World object.
:param AffineMatrix3D transform (optional): Affine matrix describing the location and orientation
of the plasma in the world.
:param str name (optional): User friendly name for this plasma (default = "Mesh3D Plasma").
:rtype: Plasma
"""
These functions will support vector fields as well (b_field, electron_velocity and species_velocity) once the Vector3D versions of Discrete2DMesh and Discrete3DMesh are implemented.
Thanks for explanation @vsnever , I would then suggest including a one more function, which would return the species distributions, which you could assign to already existing plasmas.
In #336 @jacklovell just suggested that these tools might not be needed at all. Well, indeed, maybe demo scripts will do better.
You can make something like a vector2d.Discrete2DMesh already using raysect.core.math.function.vector3d.FloatToVector3DFunction2D. Just use separate float.Discrete2DMesh functions for each of the x, y and z components of the vector fields. OK, performance may not be as good as a dedicated vector mesh function if you're making 3 function calls rather than 1, but it would at least allow you to implement the required functionality now without having to add additional arguments later and break backwards compatibility.
Thanks for the tips with FloatToVector3DFunction2D, @jacklovell. I suspected that something like that must exist.
Now I think that the demos would do better. These function do not cover all possible cases while hiding from the user the process of creating the plasma from the meshes.
In #336 @jacklovell just suggested that these tools might not be needed at all. Well, indeed, maybe demo scripts will do better.
I think that having a howto build plasma with mesh data would be more suitable. I think that users should be softly guided to a basic minimum knowledge of how a code/framework works, at least in the case of the core package. This in my opinion means you have to stop at some point of automation, which in this case might actually be no automatic creation of plasma from mesh data. So, I would suggest only creating demos for now and we will see.
In case of Generomak I would add a function to load the plasma from the data, because we will only have 3 cases: edge, core, and maybe edge+core. It will be useful for the demos.