Skip to content
Snippets Groups Projects
Commit fedd4f58 authored by Jean-Matthieu Etancelin's avatar Jean-Matthieu Etancelin
Browse files

Clean field and domain. Fixing operator (begin). Fix doxyfile.

parent 22f15694
No related branches found
No related tags found
No related merge requests found
This diff is collapsed.
......@@ -4,14 +4,15 @@ from .domain import Domain
from .grid import CartesianGrid
import numpy as np
class Box(Domain):
"""
Periodic box representation.
Note FP : BC as parameter may be better?
Note FP : BC as parameter may be better?
"""
def __init__(self,dimension=3,length=[1.0,1.0,1.0], origin=[0.,0.,0.]):
def __init__(self, dimension=3, length=[1.0, 1.0, 1.0], origin=[0., 0., 0.]):
"""
Constructor.
Create a Box from a dimension, length and minimum position.
......@@ -33,21 +34,21 @@ class Box(Domain):
self.boundaries = np.zeros((self.dimension))
self.boundaries[:] = PERIODIC
def discretize(self,resolution):
def discretize(self, resolution):
"""Box discretization method.
Use an array for discreteDomain??? i.e to associate several discretisations for the same domain.
Or maybe this should be a member of the fields??
"""
self.discreteDomain = CartesianGrid(resolution,self)
self.discreteDomain = CartesianGrid(resolution, self)
return self.discreteDomain
def __str__(self):
""" Doc display. """
s = str(self.dimension)+"D box (parallelepipedic or rectangular) domain : \n"
s += " origin : "+str(self.origin)+", maxPosition :"+str(self.max)+", lengthes :"+str(self.length)+"."
s = str(self.dimension) + "D box (parallelepipedic or rectangular) domain : \n"
s += " origin : " + str(self.origin) + ", maxPosition :" + str(self.max) + ", lengthes :" + str(self.length) + "."
return s
if __name__ == "__main__":
print __doc__
print "- Provided class : Box."
......
......@@ -5,16 +5,16 @@
Physical domain discretization
"""
from abc import ABCMeta, abstractmethod
from abc import ABCMeta,abstractmethod
class DiscreteDomain:
""" Abstract description of a discretized physical domain. """
__metaclass__=ABCMeta
__metaclass__ = ABCMeta
@abstractmethod
def __init__(self,domain=None):
def __init__(self, domain=None):
"""
Constructor.
Create a DiscreteDomain with a given discretization.
......
# -*- coding: utf-8 -*-
"""@package parmepy.domain.domain
Classes for physical domains description. """
Classes for physical domains description.
"""
from abc import ABCMeta, abstractmethod
from abc import ABCMeta,abstractmethod
class Domain:
"""Abstract description of physical domain. """
__metaclass__=ABCMeta
__metaclass__ = ABCMeta
@abstractmethod
def __init__(self, dimension):
"""
@param dimension integer : domain dimension.
"""
......@@ -23,7 +24,7 @@ class Domain:
self.discreteDomain = None
@abstractmethod
def discretize(self,resolution=None):
def discretize(self, resolution=None):
"""
@param resolution : discretization specifications.
"""
......
......@@ -7,12 +7,12 @@ Cartesian grid definition
from .discrete import DiscreteDomain
import numpy as np
class CartesianGrid(DiscreteDomain):
""" Discrete box representation as a cartesian grid. """
def __init__(self,resolution,domain):
DiscreteDomain.__init__(self,domain)
assert(self.dimension==len(resolution))
def __init__(self, resolution, domain):
DiscreteDomain.__init__(self, domain)
assert(self.dimension == len(resolution))
self.origin = domain.origin
self.length = domain.length
self.resolution = resolution
......@@ -51,7 +51,7 @@ class CartesianGrid(DiscreteDomain):
"""
ToString method.
"""
s = str(self.dimension)+"D cartesian grid with resolution equal to : "+str(self.resolution)+".\n"
s = str(self.dimension) + "D cartesian grid with resolution equal to : " + str(self.resolution) + ".\n"
return s
if __name__ == "__main__":
......
......@@ -6,13 +6,14 @@
from .continuous import ContinuousField
from .discrete import DiscreteField
class AnalyticalField(ContinuousField):
"""
A variable (continuous) defined with an analytic formula.
"""
def __init__(self, dimension, domain, formula=None, scalar=False, name=""):
def __init__(self, domain, name="", formula=None):
"""
Constructor.
Create an AnalyticalField from a formula.
......@@ -21,22 +22,20 @@ class AnalyticalField(ContinuousField):
@param dimension : variable dimension.
@param formula : function defining the variable.
"""
ContinuousField.__init__(self, dimension, domain)
ContinuousField.__init__(self, domain, name)
## Analytic formula.
self.formula = formula
## Is scalar variable
self.scalar = scalar
self.name = name
def discretize(self, d_spec=None):
def discretize(self, topology=None):
"""
AnalyticalField discretization method.
Create an DiscreteField.DiscreteField from given specifications.
@param d_spec : discretization specifications, not used.
Create an DiscreteField from given topology.
"""
if self.discreteField is None:
self.discreteField = DiscreteField(domain=self.domain.discreteDomain, dimension=self.dimension, initialValue=self.formula, scalar=self.scalar, spec=d_spec, name=self.name)
self.__fieldId += 1
self.discreteField.append(ScalarField(self, topology, name=self.name + "_D_" + str(self.__fieldId),
idFromParent=self.__fieldId))
self.discreteField[self.__fieldId].initialize(self.formula)
return self.discreteField[self.__fieldId], self.__fieldId
def value(self, pos):
"""
......
......@@ -3,13 +3,13 @@
@package parmepy.fields.continuous
Continuous variable description
"""
from .discrete import ScalarField
class ContinuousField(object):
""" A variable defined on a physical domain """
def __init__(self,domain,name="?"):
def __init__(self, domain, name="?"):
"""
Constructor.
Create a ContinuousField.
......@@ -30,23 +30,24 @@ class ContinuousField(object):
## list of the various discretizations of this field
self.discreteField = []
def discretize(self,topology=None):
def discretize(self, topology=None):
"""
discretization of the field on a topology
"""
self.__fieldId += 1
self.discreteField.append(ScalarField(self,topology,name=self.name+"_D_"+str(self.__fieldId),idFromParent=self.__fieldId))
return self.discreteField[self.__fieldId],self.__fieldId
self.discreteField.append(ScalarField(self, topology, name=self.name + "_D_" + str(self.__fieldId),
idFromParent=self.__fieldId))
return self.discreteField[self.__fieldId], self.__fieldId
def __str__(self):
""" Field info display """
s = self.name + ' , ' + str(self.dimension)+'D field with the following discretizations:\n'
s = self.name + ' , ' + str(self.dimension) + 'D field with the following discretizations:\n'
if len(self.discreteField) != 0:
for i in range(len(self.discreteField)):
s += self.discreteField[i].__str__()
else :
s+="None."
else:
s += "None."
return s
......
......@@ -3,52 +3,58 @@
@package parmepy.fields.discrete
"""
import numpy as np
from ..constants import *
import evtk.hl as evtk
class ScalarField(object):
"""
A scalar field, defined on each grid of each subdomain of the given topology.
"""
def __init__(self,parent,topology=None,name="?",idFromParent=None):
def __init__(self, parent, topology=None, name="?", idFromParent=None):
if(topology is not None):
self.topology = topology
else :
else:
raise NotImplementedError()
self.name = name
self.dimension = topology.domain.dimension
resolution = self.topology.mesh.resolution
# zeros or empty???
self.data = np.zeros((resolution),dtype=PARMES_REAL,order=ORDER)
self.__parentField=parent
## \todo is numpy array zeros or empty???
self.data = np.zeros((resolution), dtype=PARMES_REAL, order=ORDER)
self.__parentField = parent
self.__idFromParent = idFromParent
def __str__(self):
""" Display class information """
s = '['+str(self.topology.rank)+'] '
s += " id "+ str(self.__idFromParent)+", "
s+= self.name+" "+str(self.dimension)+'D discrete field with resolution '
s += str(self.data.shape)+"."
s = '[' + str(self.topology.rank) + '] '
s += " id " + str(self.__idFromParent) + ", "
s += self.name + " " + str(self.dimension) + 'D discrete field with resolution '
s += str(self.data.shape) + "."
return s + "\n"
def __getitem__(self,i):
def __getitem__(self, i):
""" Access to the content of the field """
return self.data.__getitem__(i)
def __setitem__(self,i,value):
def __setitem__(self, i, value):
"""
Set the content of the field component at position i
Usage :
A = ScalarField(topo)
A[2,1,1] = 12.0 # Calls A.data[2,1,1] = 12.0
"""
self.data.__setitem__(i,value)
self.data.__setitem__(i, value)
def initialize(self, formula=None):
"""
Initialize values with given formula
\todo Ecrire l'initialisation efficace en python.
"""
raise NotImplementedError("Not yet implemented")
## def init(self):
## if not self.initialValue is None:
......@@ -69,41 +75,49 @@ class ScalarField(object):
## self.contains_data = True
## else:
## raise ValueError("Creating DiscreteVariable with incorrect domain dimension.")
def tofile(self,filename):
evtk.imageToVTK(filename, pointData = {"scalar" : self.data} )
def tofile(self, filename):
evtk.imageToVTK(filename, pointData={"scalar": self.data})
class VectorField(object):
"""
A vector field, defined on each grid of each subdomain of the given topology.
"""
def __init__(self,topology,name=""):
def __init__(self, topology, name=""):
self.topology = topology
self.name = name
self.dimension = topology.domain.dimension
resolution = self.topology.mesh.resolution
self.data = np.zeros((resolution),dtype=PARMES_REAL)
self.data = np.zeros((resolution), dtype=PARMES_REAL, order=ORDER)
def __str__(self):
""" Display class information """
s = self.name+": "+str(self.dimension)+"D scalar field of shape " + str(self.data.shape)
s = self.name + ": " + str(self.dimension) + "D scalar field of shape " + str(self.data.shape)
return s + "\n"
def __getitem__(self,i):
def __getitem__(self, i):
""" Access to the content of the field """
return self.data.__getitem__(i)
def __setitem__(self,i,value):
def __setitem__(self, i, value):
"""
Set the content of the field component at position i
Usage :
A = ScalarField(topo)
A[2,1,1] = 12.0 # Calls A.data[2,1,1] = 12.0
"""
self.data.__setitem__(i,value)
self.data.__setitem__(i, value)
def initialize(self, formula):
"""
Initialize values with given formula
\todo Ecrire l'initialisation efficace en python.
"""
raise NotImplementedError("Not yet implemented")
if __name__ == "__main__":
print __doc__
print "- Provided class : ScalarField"
......
"""
@package parmepy.domain.topology
MPI Topologies
MPI Topologies
"""
import numpy as np
import mpi4py.MPI as MPI
from ..constants import *
class CartesianTopology(object):
"""
"""
Define an MPI cartesian topology with an associated mesh for each sub-domain.
Keyword arguments :
- domain : the geometry; it must be a box.
- resolution : global resolution
- dim : dimension of the topology
- comm : MPI communicator used to create this topology
- periods : periodicity of the topology (in each direction)
- ghosts : number of poinst in the ghost layer
Define an MPI cartesian topology with an associated mesh for each sub-domain.
Keyword arguments :
- domain : the geometry; it must be a box.
- resolution : global resolution
- dim : dimension of the topology
- comm : MPI communicator used to create this topology
- periods : periodicity of the topology (in each direction)
- ghosts : number of poinst in the ghost layer
"""
def __init__(self, domain, resolution, dim=None, dims=None, comm=MPI.COMM_WORLD, periods=None, ghosts=None):
## Associated domain
self.domain = domain
# Compute the "optimal" processus distribution for each direction of the grid topology
nbprocs = comm.Get_size()
if(dims is None):
assert(dim is not None)
self.dims = np.asarray(MPI.Compute_dims(nbprocs, dim))
# Topology dimension
self.dim = dim
else:
self.dims = np.asarray(dims)
self.dim = self.dims.size
# Define the topology
# default period status is periodic
if(periods is None):
self.periods = self.dim * (True,)
self.topo = comm.Create_cart(self.dims, periods=self.periods)
"""
def __init__(self,domain,resolution,dim=None,dims=None,comm=MPI.COMM_WORLD,periods=None,ghosts=None):
# Size of the topology
self.size = self.topo.Get_size()
# Rank of the current process, in the new topology
self.rank = self.topo.Get_rank()
# Coordinates of the current process
self.coords = self.topo.Get_coords(self.rank)
# Neighbours
# self.neighbours = np.zeros((dim,2))
self.down, self.up = self.topo.Shift(XDIR, 1)
if(self.dim > 1):
self.west, self.east = self.topo.Shift(YDIR, 1)
if(self.dim > 2):
self.south, self.north = self.topo.Shift(ZDIR, 1)
# ghost layer (default = 0)
if(ghosts is None):
self.ghosts = np.zeros((self.domain.dimension))
# Global resolution
self.resolution = np.asarray(resolution)
nbpoints = self.resolution[:self.dim] // self.dims
remainingPoints = self.resolution[:self.dim] % self.dims
localResolution = self.resolution.copy()
localResolution[:self.dim] = nbpoints
for i in range(self.dim):
if(self.coords[i] == self.dims[i] - 1):
localResolution[i] = nbpoints[i] + remainingPoints[i]
start = np.zeros((domain.dimension))
start[:self.dim] = self.coords * nbpoints
self.mesh = LocalMesh(self.rank, resolution=localResolution, start=start, ghosts=self.ghosts)
## Associated domain
self.domain=domain
# Compute the "optimal" processus distribution for each direction of the grid topology
nbprocs = comm.Get_size()
if(dims is None):
assert(dim is not None)
self.dims=np.asarray(MPI.Compute_dims(nbprocs,dim))
# Topology dimension
self.dim=dim
else:
self.dims=np.asarray(dims)
self.dim = self.dims.size
# Define the topology
# default period status is periodic
if(periods is None):
self.periods = self.dim*(True,)
self.topo = comm.Create_cart(self.dims,periods=self.periods)
def __str__(self):
""" Topology info display """
s = '=======================================================\n'
if(self.rank == 0):
s += str(self.dim) + 'D cartesian Topology of size ' + str(self.dims) + '\n'
s += str(self.mesh)
s += '=======================================================\n'
return s
# Size of the topology
self.size = self.topo.Get_size()
# Rank of the current process, in the new topology
self.rank = self.topo.Get_rank()
# Coordinates of the current process
self.coords = self.topo.Get_coords(self.rank)
# Neighbours
# self.neighbours = np.zeros((dim,2))
self.down,self.up=self.topo.Shift(XDIR,1)
if(self.dim>1) :
self.west,self.east=self.topo.Shift(YDIR,1)
if(self.dim>2) :
self.south,self.north=self.topo.Shift(ZDIR,1)
# ghost layer (default = 0)
if(ghosts is None):
self.ghosts = np.zeros((self.domain.dimension))
# Global resolution
self.resolution = np.asarray(resolution)
nbpoints = self.resolution[:self.dim]//self.dims
remainingPoints = self.resolution[:self.dim]%self.dims
localResolution = self.resolution.copy()
localResolution[:self.dim] = nbpoints
for i in range(self.dim):
if(self.coords[i] == self.dims[i]-1):
localResolution[i] = nbpoints[i]+remainingPoints[i]
start = np.zeros((domain.dimension))
start[:self.dim]=self.coords*nbpoints
self.mesh = LocalMesh(self.rank,resolution=localResolution,start=start,ghosts=self.ghosts)
def __str__(self):
""" Topology info display """
s ='=======================================================\n'
if(self.rank==0):
s += str(self.dim)+'D cartesian Topology of size '+str(self.dims)+'\n'
s += str(self.mesh)
s +='=======================================================\n'
return s
class FFTTopology(object):
""" A 2D or 3D MPI cartesian topology
"""
def __init__(self, dim=2,comm=MPI.COMM_WORLD,nbprocs=MPI.COMM_WORLD.Get_size(),periods=3*(True,),dims=(1,1,1)):
"""
A 2D or 3D MPI cartesian topology
"""
# Topology dimension
self.dim=dim
# Compute the "optimal" processus distribution for each direction of the grid topology
dims=MPI.Compute_dims(nbprocs,dim)
self.dims=np.ones((dim+1))
self.dims[0:dim] = np.asarray(dims)
# Define the topology
self.topo = comm.Create_cart(self.dims,periods=periods[0:dim+1])
# Size of the topology
sizeT = self.topo.Get_size()
# Rank of the current process
self.rank = self.topo.Get_rank()
# Coordinates of the current process
self.coords = self.topo.Get_coords(self.rank)
# Neighbours
# self.neighbours = np.zeros((dim,2))
self.down,self.up=self.topo.Shift(XDIR,1)
if(dim>1) :
self.west,self.east=self.topo.Shift(YDIR,1)
if(dim>2) :
self.south,self.north=self.topo.Shift(ZDIR,1)
def __init__(self, dim=2, comm=MPI.COMM_WORLD, nbprocs=MPI.COMM_WORLD.Get_size(), periods=3 * (True,), dims=(1, 1, 1)):
# Topology dimension
self.dim = dim
# Compute the "optimal" processus distribution for each direction of the grid topology
dims = MPI.Compute_dims(nbprocs, dim)
self.dims = np.ones((dim + 1))
self.dims[0:dim] = np.asarray(dims)
# Define the topology
self.topo = comm.Create_cart(self.dims, periods=periods[0:dim + 1])
# Size of the topology
sizeT = self.topo.Get_size()
# Rank of the current process
self.rank = self.topo.Get_rank()
# Coordinates of the current process
self.coords = self.topo.Get_coords(self.rank)
# Neighbours
# self.neighbours = np.zeros((dim,2))
self.down, self.up = self.topo.Shift(XDIR, 1)
if(dim > 1):
self.west, self.east = self.topo.Shift(YDIR, 1)
if(dim > 2):
self.south, self.north = self.topo.Shift(ZDIR, 1)
def __str__(self):
""" Topology info display """
s = '======================================================='
s += str(self.dim) + 'D FFT Topology of size ' + str(self.dims)
s += self.mesh.__str__
s += '======================================================='
return s
def __str__(self):
""" Topology info display """
s ='======================================================='
s += str(self.dim)+'D FFT Topology of size '+str(self.dims)
s+=self.mesh.__str__
s+='======================================================='
return s
class LocalMesh(object):
"""
"""
"""
"""
def __init__(self, rank, resolution, start, ghosts=np.zeros((3))):
# Current process rank in the topology that owns this mesh
self.rank = rank
# Local resolution
self.resolution = resolution.copy() + 2 * ghosts
# index of the lower point (in each dir) in the global mesh
self.start = start
# index of the upper point (in each dir), global mesh
self.end = self.start + self.resolution - 1
# Mesh step size
def __str__(self):
""" Local mesh display """
s = '[' + str(self.rank) + '] Local mesh resolution :' + str(self.resolution) + '\n'
s += 'Global indices :' + str(self.start) + '\n'
return s
def __init__(self,rank,resolution,start,ghosts=np.zeros((3))) :
# Current process rank in the topology that owns this mesh
self.rank = rank
# Local resolution
self.resolution = resolution.copy()+2*ghosts
# index of the lower point (in each dir) in the global mesh
self.start = start
# index of the upper point (in each dir), global mesh
self.end = self.start + self.resolution - 1
# Mesh step size
def __str__(self):
""" Local mesh display """
s = '['+str(self.rank)+'] Local mesh resolution :'+str(self.resolution)+'\n'
s+= 'Global indices :'+str(self.start)+'\n'
return s
if __name__ == "__main__" :
print "This module defines the following classes:"
print "- CartesianTopology: ", CartesianTopology.__doc__
print "- FFTTopology: ", FFTTopology.__doc__
print "- LocalMesh: ", LocalMesh.__doc__
if __name__ == "__main__":
print "This module defines the following classes:"
print "- CartesianTopology: ", CartesianTopology.__doc__
print "- FFTTopology: ", FFTTopology.__doc__
print "- LocalMesh: ", LocalMesh.__doc__
# -*- coding: utf-8 -*-
"""
@package Operator
Operator representation
@package parmepy.operator.Advection
Advection operator representation
"""
from ..Param import *
from ContinuousOperator import ContinuousOperator
from AdvectionDOp import AdvectionDOp
from .continuous import ContinuousOperator
from .advection_d import AdvectionDOp
class Advection(ContinuousOperator):
......@@ -18,15 +18,14 @@ class Advection(ContinuousOperator):
Constructor.
Create an Advection operator from given variables velocity and scalar.
@param velocity ContinuousVariable.ContinuousVariable : velocity variable.
@param scalar ContinuousVariable.ContinuousVariable : scalar variable.
@param velocity ContinuousField : velocity variable.
@param scalar ContinuousField : scalar variable.
"""
ContinuousOperator.__init__(self)
## advection velocity variable
self.velocity = velocity
## advected scalar variable
self.scalar = scalar
self.addVariable([self.velocity, self.scalar])
def discretize(self, spec=None):
"""
......
from ContinuousOperator import ContinuousOperator
from Advection import Advection
from DiscreteOperator import DiscreteOperator
from AdvectionDOp import AdvectionDOp
from InterpolationDOp import InterpolationDOp
from RemeshingDOp import RemeshingDOp
from TagDOp import TagDOp
from VelocityOp import VelocityOp
"""
@package parmepy.operator
Everything concerning operators.
"""
# -*- coding: utf-8 -*-
"""
@package Operator
Operator representation
@package operator
Discrete advection representation
"""
from ..Param import *
from DiscreteOperator import DiscreteOperator
from .discrete import DiscreteOperator
import pyopencl as cl
import time
providedClass = "AdvectionDOp"
class AdvectionDOp(DiscreteOperator):
"""
......
# -*- coding: utf-8 -*-
"""
@package Operator
@package parmepy.operator.continuous
Operator representation
"""
from ..Param import *
from abc import ABCMeta, abstractmethod
class ContinuousOperator:
......@@ -11,6 +12,9 @@ class ContinuousOperator:
Continuous operator abstract description.
"""
__metaclass__ = ABCMeta
@abstractmethod
def __init__(self):
"""
Constructor.
......@@ -18,24 +22,10 @@ class ContinuousOperator:
"""
## Application domains of the variables.
self.domains = []
## Variables
self.variables = []
## Operator discretization.
self.discreteOperator = None
def addVariable(self, cVariable):
"""
Add an continuous variables to the operator.
Also add variables' domains to the operator.
@param cVariable ContinuousVariable.ContinuousVariable : variables to add.
"""
for v in cVariable:
if self.variables.count(v) == 0:
self.variables.append(v)
if self.domains.count(v.domain) == 0:
self.domains.append(v.domain)
@abstractmethod
def discretize(self, spec=None):
"""
Abstract method.
......
# -*- coding: utf-8 -*-
"""
@package Operator
Operator representation
@package operator
Discrete operator representation
"""
from ..Param import *
from abc import ABCMeta, abstractmethod
class DiscreteOperator:
......@@ -11,6 +11,9 @@ class DiscreteOperator:
Abstract description of a discretized operator.
"""
__metaclass__ = ABCMeta
@abstractmethod
def __init__(self):
"""
Constructor.
......@@ -18,27 +21,12 @@ class DiscreteOperator:
"""
## Application domains of the variables.
self.domains = []
## Variables
self.variables = []
## Operator numerical method.
self.numMethod = []
self.is_splittable = True
self.gpu_kernel = None
self.gpu_kernel_name = ""
def addVariable(self, cVariable):
"""
Add an discrete variables to the operator.
Also add variables' domains to the operator.
@param cVariable DiscreteVariable.DiscreteVariable : variables to add.
"""
for v in cVariable:
if self.variables.count(v) == 0:
self.variables.append(v)
if self.domains.count(v.domain) == 0:
self.domains.append(v.domain)
def setMethod(self, method):
"""
Set the numerical method used by operator when calling applyOperator.
......@@ -47,6 +35,7 @@ class DiscreteOperator:
"""
self.numMethod = method
@abstractmethod
def setResultVariable(self):
"""
Abstract method, apply operaton on a variable.
......@@ -54,6 +43,7 @@ class DiscreteOperator:
"""
raise NotImplementedError("Need to override method in a subclass of " + providedClass)
@abstractmethod
def applyOperator(self):
"""
Abstract method, apply operaton on a variable.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment