#!/usr/bin/env python # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # # # CitcomS.py by Eh Tan, Eun-seo Choi, and Pururav Thoutireddy. # Copyright (C) 2002-2005, California Institute of Technology. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # from pyre.components.Component import Component class Coupler(Component): def __init__(self, name, facility): Component.__init__(self, name, facility) self.all_variables = None self.communicator = None self.srcCommList = [] self.sinkComm = None self.remoteSize = 0 self.synchronized = True self.done = False self.coupled_steps = 1 return def initialize(self, solver): # when monitor_max_T is on, the timestep size might get changed # inside the tsolver, which will cause trouble in coupler # synchronization. assert solver.inventory.tsolver.inventory.monitor_max_T == False, \ 'Error: solver.tsolver.monitor_max_T must be off!' self.communicator = solver.communicator self.srcCommList = solver.myPlus # number of processors in the remote solver self.remoteSize = len(self.srcCommList) # only one of remotePlus is sinkComm self.sinkComm = solver.remotePlus[self.communicator.rank] self.all_variables = solver.all_variables # init'd Convertor singleton, this must be done before any other # exchanger call from ExchangerLib import initConvertor initConvertor(self.inventory.dimensional, self.inventory.transformational, self.all_variables) return def launch(self, solver): # these functions are defined in the subclass self.createMesh() self.createSourceSink() self.createBC() if self.inventory.two_way_communication: self.createII() return def modifyT(self, bbox): # modify read-in temperature field from ExchangerLib import modifyT modifyT(bbox, self.all_variables) return def preVSolverRun(self): # do nothing, overridden by EmbeddedCoupler return def postVSolverRun(self): # do nothing, overridden by ContainingCoupler return def endTimestep(self, steps, done): # 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) if done or (recv == END_SIMULATION_SIGNAL): done = True break elif recv == KEEP_WAITING_SIGNAL: pass elif recv == NEW_STEP_SIGNAL: if self.synchronized: #print self.name, 'exchanging timestep =', steps self.coupled_steps = self.exchangeSignal(steps) #print self.name, 'exchanged timestep =', self.coupled_steps break else: raise ValueError, \ "Unexpected signal value, singnal = %d" % recv return done class Inventory(Component.Inventory): import pyre.inventory as prop # updating the temperature field in the containing solver or not two_way_communication = prop.bool("two_way_communication", default=True) # if dimensional is True, quantities exchanged are dimensional dimensional = prop.bool("dimensional", default=False) # if transformational is True, quantities exchanged are in standard # (ie. Cartesian) coordinate system transformational = prop.bool("transformational", default=False) # version __id__ = "$Id$" # End of file