Source code for pyrodeo.coords

# -*- coding: utf-8 -*-
"""Coordinate class used in pyrodeo.

The Coordinate class hold the x, y and z coordinates as 3D ndarrays. In addition, it holds the step size in x, y and z and the size of the grid in x, y and z.
"""

from __future__ import print_function

import numpy as np

[docs]class Coordinates(object): """Class containing coordinates used in pyrodeo. Args: x (ndarray): 2D ndarray containing x coordinates y (ndarray): 2D ndarray containing y coordinates z (ndarray): 2D ndarray containing z coordinates log_radial (:obj:`bool`, optional): Flag whether x is a logarithmic radial coordinate. Note: The validity of the arrays is not checked! To be used in a simulation, they should have the same shape, with x[:,j,k] containing the x coordinates for all j,k, y[i,:,k] containing the y coordinates for all i,k and z[i,j,:] containing the z coordinates for all i,j. In addition, x, y and z should have a constant step size. The following public attributes are available: Attributes: x (ndarray): 2D ndarray containing x coordinates y (ndarray): 2D ndarray containing y coordinates z (ndarray): 3D ndarray containing z coordinates dimensions ([int, int, int]): grid dimensions in the x, y and z direction dxyz ([float, float, float]): step size in the x, y and z direction log_radial (:obj:`bool`, optional): Flag whether x is a logarithmic radial coordinate. """ def __init__(self, x, y, z, log_radial=False): self.dimensions = (len(x[:,0,0]), len(y[0,:,0]), len(z[0,0,:])) self.dxyz = [0.0, 0.0, 0.0] self.log_radial = log_radial if self.dimensions[0] > 1: self.dxyz[0] = x[1,0,0] - x[0,0,0] if self.log_radial == True: self.dxyz[0] = np.log(x[1,0,0]/x[0,0,0]) if self.dimensions[1] > 1: self.dxyz[1] = y[0,1,0] - y[0,0,0] if self.dimensions[2] > 1: self.dxyz[2] = z[0,0,1] - z[0,0,0] self.x = x self.y = y self.z = z
[docs] @classmethod def from_1d(cls, x, y, z, log_radial=False): """Initialize from 1D arrays. Build coordinates from existing 1D ndarrays (should include ghost cells). Calculate dimensions and step sizes. Args: x (ndarray): 1D ndarray containing x coordinates y (ndarray): 1D ndarray containing y coordinates z (ndarray): 1D ndarray containing z coordinates log_radial (:obj:`bool`, optional): Flag whether x is a logarithmic radial coordinate. Note: The validity of arrays x, y and z is not checked. They should have constant step size. """ x, y, z = np.meshgrid(x, y, z, indexing='ij') return cls(x, y, z, log_radial=log_radial)
[docs] @classmethod def from_dims(cls, dimensions=(100, 1, 1), domain=([-0.5, 0.5], [], []), log_radial=False): """Initialize from dimensions and domain size. Build coordinates given the dimensions of the grid and the size of the domain. Some basic checks are performed to ensure the resulting coordinates are valid. Args: dimensions (:obj:`(int,int,int)`, optional): Dimensions of the grid domain (:obj:`([float,float],[float,float],[float,float])`, optional): Domain boundaries in x, y and z log_radial (:obj:`bool`, optional): Flag whether x will be a logarithmic radial coordinate. """ # Check if dimensions valid if len(dimensions) != 3: raise TypeError('Expected dimensions to have three elements') if (dimensions[1] != 1 and len(domain[1]) != 2): raise TypeError('Invalid y domain') if (dimensions[2] != 1 and len(domain[2]) != 2): raise TypeError('Invalid z domain') if np.max(dimensions) <= 1: raise ValueError('Need one dimension to be larger than 1') # Check if domain is valid if len(domain) != 3: raise TypeError('Expected domain to have three elements') # Step sizes dxy = [0.0, 0.0, 0.0] # Add x if necessary if dimensions[0] > 1: if domain[0][1] <= domain[0][0]: raise ValueError('Invalid x domain') # Convert boundaries to log if log_radial is True: domain[0][0] = np.log(domain[0][0]) domain[0][1] = np.log(domain[0][1]) dxy[0] = (domain[0][1] - domain[0][0])/np.float(dimensions[0]) # x coordinates, including two ghost cells on either side x = np.linspace(domain[0][0] - 1.5*dxy[0], domain[0][1] + 2.5*dxy[0], dimensions[0] + 4, endpoint=False) # Make x normal radius (but unevenly spaced!) if log_radial is True: x = np.exp(x) else: x = [0.0] # Add y if necessary if dimensions[1] > 1: if domain[1][1] <= domain[1][0]: raise ValueError('Invalid y domain') dxy[1] = (domain[1][1] - domain[1][0])/np.float(dimensions[1]) y = np.linspace(domain[1][0] - 1.5*dxy[1], domain[1][1] + 2.5*dxy[1], dimensions[1] + 4, endpoint=False) else: y = [0.0] # Add z if necessary if dimensions[2] > 1: if domain[2][1] <= domain[2][0]: raise ValueError('Invalid z domain') dxy[2] = (domain[2][1] - domain[2][0])/np.float(dimensions[2]) z = np.linspace(domain[2][0] - 1.5*dxy[2], domain[2][1] + 2.5*dxy[2], dimensions[2] + 4, endpoint=False) else: z = [0.0] return cls.from_1d(x, y, z, log_radial=log_radial)
def __str__(self): """Show information about coordinates.""" return 'Coordinate object, part of pyrodeo. \n \ Grid dimensions (nx, ny, nz): {} \n \ Domain size x (including ghost zones): {}, {} \n \ Domain size y (including ghost zones): {}, {} \n \ Domain size z (including ghost zones): {}, {}\n'.format(np.shape(self.x), np.min(self.x), np.max(self.x), np.min(self.y), np.max(self.y), np.min(self.z), np.max(self.z))