diff --git a/HySoP/hysop/operator/redistribute.py b/HySoP/hysop/operator/redistribute.py new file mode 100644 index 0000000000000000000000000000000000000000..442cccf2e19167847ca4db31cfc08fce8ffa557f --- /dev/null +++ b/HySoP/hysop/operator/redistribute.py @@ -0,0 +1,118 @@ +""" +@file redistribute.py +Setup for data transfer/redistribution between two parmes topologies. + +This operator is an inter operator which is supposed to define the process to +transfer variables and data from one operator to another. +This mainly concerns data redistribution if the two operators work on +different mpi topologies. + +When is it required to define an operator between op1 and op2? +If: +- the intersection between op1.output-variables and op2.input-variables + is not empty +- AND if the topology on which the variables of op1 are defined is different +from the one of op2 variables. + +Note Franck: this kind of operator may also be useful +to define the interpolation/filter process for data transfer for +a variable defined on several meshes. + +""" + +from parmepy.constants import debug +from parmepy.operator.continuous import Operator +from parmepy.mpi.topology import Bridge + + +class Redistribute(Operator): + """ + Interconnection between two operators. + SetUp will compute (or get if it already exists) a Bridge between two + topologies. + Apply redistributes data from opFrom topology to opTo topology. + + """ + @debug + def __init__(self, variables, opFrom, opTo): + + """ + Create an operator to distribute data between two mpi topologies for a + list of variables belonging to two operators. + + @param variables : the set of variables to be redistributed + @param opFrom : source operator + @param opTo : target (i.e.) the operator that handles the topology on + which data must be redistributed. + """ + + if isinstance(variables, list): + Operator.__init__(self, variables) + else: + Operator.__init__(self, [variables]) + + ## Source Operator + self.opFrom = opFrom + ## Targeted operator + self.opTo = opTo + + # Then check if variables belong to both operators + for v in self.variables: + assert v in opFrom.variables and v in opTo.variables, \ + 'Redistribute error : one of the variable is not present\ + in both source and target operator.' + + @debug + def setUp(self): + """ + Computes intersection of two topologies. + + """ + assert self.opFrom.isUp and self.opTo.isUp(), \ + 'You should setup both opFrom and opTo operators\ + before any attempt to setup a redistribute operator.' + + self.bridges = {} + for v in self.variables: + vd_from = self.opFrom.discreteFields[v] + vd_to = self.opTo.discreteFields[v] + self.bridges[v] = Bridge(vd_from.topology, vd_to.topology) + + self._isUpToDate = True + + def apply(self): + """ + Proceed with data redistribution from opFrom to opTo + """ + dim = self.domain.dimension + for v in self.variables: + br = self.bridges[v] + if v.isVector: + # Apply for each component of the data + for d in range(dim): + vTo = self.opTo.discreteFields[v].data[d] + vFrom = self.opFrom.discreteFields[v].data[d] + vTo[br.ito] = vFrom[br.ifrom] + + # scalar + else: + vTo = self.opTo.discreteFields[v].data + vFrom = self.opFrom.discreteFields[v].data + vTo[br.ito] = vFrom[br.ifrom] + #from parmepy.mpi import main_rank + + +# for rk in br.recvFrom.keys(): + # main_rank.Irecv() + + def __str__(self): + """ToString method""" + s = "Bridge from :\n " + str(self.opFrom) + s += "\n to operator:\n " + str(self.opTo) + s += "for variable(s) " + str([v.name for v in self.variables]) + return s + "\n" + +if __name__ == "__main__": + print __doc__ + print "- Provided class : Redistribute" + print Redistribute.__doc__