Revision 0f2912211f8bd9f87ace5f5447f8e91242595f9f authored by Eh Tan on 17 July 2007, 22:49:10 UTC, committed by Eh Tan on 17 July 2007, 22:49:10 UTC
1 parent 6ff6d36
Raw File
MultiC_Coupler.py
#!/usr/bin/env python

#
#containing coupler with more than one coupled embedded coupler
#

from ContainingCoupler import ContainingCoupler

class MultiC_Coupler(ContainingCoupler):


    def __init__(self, name, facility):
        ContainingCoupler.__init__(self, name, facility)

        self.srcCommList2 = []
        self.sinkComm2 = None
        self.remoteSize2 = 0
        return


    def initialize(self, solver):
        ContainingCoupler.initialize(self, solver)

        self.srcCommList2 = solver.myPlus2

        # number of processors in the remote solver2
        self.remoteSize2 = len(self.srcCommList2)

        # only one of remotePlus2 is sinkComm2
        self.sinkComm2 = solver.remotePlus2[self.communicator.rank]

        # allocate space
        self.remoteBdryList2 = range(self.remoteSize2)
        self.sourceList2 = range(self.remoteSize2)
        self.outletList2 = range(self.remoteSize2)

        ###
        return


    def createMesh(self):
        # Create BoundedMesh objects.
        from ExchangerLib import exchangeBoundedBox, createInterior, createEmptyBoundary


        ContainingCoupler.createMesh(self)

        # the bounding box of the mesh on remote solver2
        self.remoteBBox2 = \
                         exchangeBoundedBox(self.globalBBox,
                                            self.communicator.handle(),
                                            self.srcCommList2[0].handle(),
                                            self.srcCommList2[0].size - 1)


        # the nodes within remoteBBox2
        self.interior2, self.myBBox2 = createInterior(self.remoteBBox2,
                                                    self.all_variables)

        # an empty boundary object,\
        # which will be filled by a remote boundary obj.
        for i in range(self.remoteSize2):
            self.remoteBdryList2[i] = createEmptyBoundary()


        return


    def createSource(self):

        ContainingCoupler.createSource(self)

        # the source objects will send boundary conditions to remote sink2
        from ExchangerLib import CitcomSource_create
        for i, comm, b in zip(range(self.remoteSize2),
                              self.srcCommList2,
                              self.remoteBdryList2):
            # sink is always in the last rank of a communicator
            sinkRank2 = comm.size - 1

            # the sources will communicate with the sink in EmbeddedCoupler
            # during creation stage
            self.sourceList2[i] = CitcomSource_create(comm.handle(),
                                                     sinkRank2,
                                                     b,
                                                     self.myBBox2,
                                                     self.all_variables)

        return


    def createSink(self):

        ContainingCoupler.createSink(self)

        # the sink obj. will receive interior
        # temperature from remote sources
        from ExchangerLib import Sink_create

        # the sink will communicate with the source in EmbeddedCoupler
        # during creation stage
        self.sink2 = Sink_create(self.sinkComm2.handle(),
                                self.remoteSize2,
                                self.interior2)
        return


    def createBC(self):

        ContainingCoupler.createBC(self)

        # boundary conditions will be sent by SVTOutlet, which sends
        # stress, velocity, and temperature
        import Outlet
        for i, src in zip(range(self.remoteSize2),
                          self.sourceList2):
            self.outletList2[i] = Outlet.SVTOutlet(src, self.all_variables)
        return

    def createII(self):

        ContainingCoupler.createII(self)


        # interior temperature will be received by TInlet
        import Inlet
        self.inlet2 = Inlet.TInlet(self.interior2,
                                  self.sink2,
                                  self.all_variables)
        return


    # initTemperature

    # restartTemperature

    # modifyT

    def postVSolverRun(self):

        ContainingCoupler.postVSolverRun(self)

        # send computed velocity to ECPLR2 for its BCs
        for outlet in self.outletList2:
            outlet.send()
        return


    def newStep(self):

        ContainingCoupler.newStep(self)

        # update the temperature field in the overlapping region
        if self.inventory.two_way_communication:
            # receive temperture field from EmbeddedCoupler
            self.inlet2.recv()
            self.inlet2.impose()
        return

    def stableTimestep(self, dt):
        #used by controller

        from ExchangerLib import exchangeTimestep
        remote_dt = exchangeTimestep(dt,
                                     self.communicator.handle(),
                                     self.srcCommList[0].handle(),
                                     self.srcCommList[0].size - 1)
        remote_dt2 = exchangeTimestep(dt,
                                     self.communicator.handle(),
                                     self.srcCommList2[0].handle(),
                                     self.srcCommList2[0].size - 1)

        assert remote_dt < dt, \
               'Size of dt in the esolver is greater than dt in the csolver!'
        assert remote_dt2 < dt, \
               'Size of dt in the esolver is greater than dt in the csolver2!'

        #print "%s - old dt = %g   exchanged dt = %g" % (
        #       self.__class__, dt, remote_dt)
        return dt

    def exchangeSignal2(self, signal):
        from ExchangerLib import exchangeSignal
        newsgnl = exchangeSignal(signal,
                                 self.communicator.handle(),
                                 self.srcCommList2[0].handle(),
                                 self.srcCommList2[0].size - 1)
        return newsgnl

    def endTimestep(self, steps, done):
        #########################################
        ##  fundamentally changed revision
        #########################################

        # exchange predefined signal btwn couplers
        # the signal is used to sync the timesteps
        KEEP_WAITING_SIGNAL = 0
        NEW_STEP_SIGNAL = 1
        END_SIMULATION_SIGNAL = 2

        if done:
            sent = END_SIMULATION_SIGNAL
        elif self.synchronized:
            sent = NEW_STEP_SIGNAL
        else:
            sent = KEEP_WAITING_SIGNAL

        while 1:
            recv = self.exchangeSignal(sent)
            recv2= self.exchangeSignal2(sent)

            if done or (recv == END_SIMULATION_SIGNAL) or \
               (recv2 == END_SIMULATION_SIGNAL):
                done = True
                break
            elif (recv == KEEP_WAITING_SIGNAL) or \
                 (recv2 == KEEP_WAITING_SIGNAL):
                pass
            elif (recv == NEW_STEP_SIGNAL) and \
                 (recv2 == NEW_STEP_SIGNAL):
                sent = NEW_STEP_SIGNAL
                if self.synchronized:
                    #print self.name, 'exchanging timestep =', steps
                    self.coupled_steps = self.exchangeSignal(steps)
                    self.coupled_steps2 = self.exchangeSignal2(steps)
                    #print self.name, 'exchanged timestep =', self.coupled_steps
                break
            else:
                raise ValueError, \
                      "Unexpected signal value, singnal = %d" % recv

        return done



# version

__id__ = "$Id$"

# End of file
back to top