00001 __copyright__ = """
00002 Copyright 2008 Sean Ross-Ross
00003 """
00004 __license__ = """
00005 This file is part of SLIMpy .
00006
00007 SLIMpy is free software: you can redistribute it and/or modify
00008 it under the terms of the GNU Lesser General Public License as published by
00009 the Free Software Foundation, either version 3 of the License, or
00010 (at your option) any later version.
00011
00012 SLIMpy is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015 GNU Lesser General Public License for more details.
00016
00017 You should have received a copy of the GNU Lesser General Public License
00018 along with SLIMpy . If not, see <http://www.gnu.org/licenses/>.
00019 """
00020
00021 from slimpy_base.Core.User.linop.rclinOp import linearop_r as LinearOperatorStruct
00022 from slimpy_base.Core.Interface.node import Source,Target
00023 from slimpy_base.Core.Interface.Structure import Structure
00024 from slimpy_base.Core.User.Structures.serial_vector import Vector
00025 from slimpy_base.User.AumentedMatrix.MetaSpace import MetaSpace
00026 from slimpy_base.User.AumentedMatrix.AugVector import AugVector
00027 from slimpy_base.Core.User.linop.LinearOperatorType import LinearOperatorType
00028 from slimpy_base.Environment.InstanceManager import InstanceManager
00029 from numpy import prod
00030
00031
00032
00033 class Meta( LinearOperatorStruct ):
00034 name = 'meta'
00035
00036 def __new__( cls, *params, **kparams ):
00037 return object.__new__(cls, *params, **kparams)
00038
00039
00040 def __init__( self, domain ):
00041 if isinstance( domain, MetaSpace):
00042 adj=False
00043
00044 num_blocks=domain.shape
00045 else:
00046 adj=True
00047
00048 num_blocks = domain['num_blocks']
00049
00050
00051 LinearOperatorStruct.__init__(self, domain,
00052
00053 num_blocks=tuple(num_blocks),
00054 adj=adj)
00055
00056 def applyop(self, other):
00057
00058 if self.isadj:
00059 ans = self.create_aug( other )
00060 else:
00061 ans = self.createmeta( other )
00062 return ans
00063
00064 def create_aug( self , other ):
00065
00066 already_exists = other.container.has_built_meta_info()
00067
00068
00069 cm = other.container.expand_meta( )
00070 lst = []; push = lst.append
00071 for cont in cm:
00072 push( Vector( cont ) )
00073
00074 aug_vec = AugVector( lst )
00075 aug_vec.resize( self.kparams['num_blocks'] )
00076
00077 aug_vec.meta = self.domain()
00078 aug_vec.meta['num_blocks'] = self.kparams['num_blocks']
00079
00080 aug_vec.meta_vector = other
00081
00082 if already_exists:
00083 return aug_vec
00084
00085 struct = Structure( )
00086
00087 command = struct.generate_command( 'meta' ,Source(other.container), **self.kparams )
00088
00089 for cont in cm:
00090 command.add_other_dep( Target( cont ) )
00091
00092 converter = other.container.get_converter( command )
00093 commpack = converter.convert( other, command )
00094
00095 commpack.target = None
00096 commpack.source = None
00097
00098 self.env['graphmgr'].graphAppend( commpack )
00099
00100 return aug_vec
00101
00102 def createmeta( self, other ):
00103
00104 if hasattr(other, 'meta_vector' ) and other.meta_vector is not None:
00105 return other.meta_vector
00106
00107 struct = Structure()
00108
00109 container = other.ravel()[0].container
00110 command = struct.generate_command( 'meta' , **self.kparams )
00111
00112 converter = container.get_converter( command)
00113
00114 compack, meta_container = converter.apply_command( command, other )
00115
00116 compack.source = container
00117 compack.target = meta_container
00118
00119 struct.env['graphmgr'].graphAppend( compack )
00120
00121 meta_container.contained = [ vec.container for vec in other.ravel().tolist() ]
00122
00123 return Vector( meta_container )
00124
00125
00126 class ScatterMPI( LinearOperatorStruct ):
00127 """
00128 mpi scatteroperator
00129 """
00130 name = "window_mpi"
00131
00132 def __init__( self, inSpace, num_blocks ):
00133 env = InstanceManager()
00134 np = env['slimvars']['np']
00135 if prod(num_blocks) != np:
00136 raise Exception( "num_blocks does not match mpi variable 'np', %(num_blocks)s != %(np)s " %vars() )
00137
00138 kparams = dict( num_blocks=tuple(num_blocks) )
00139
00140 LinearOperatorStruct.__init__( self, inSpace, **kparams )
00141
00142
00143
00144 @LinearOperatorType
00145 def MScatter( domain, num_blocks ):
00146 """
00147 helper function for ScatterMPI
00148 """
00149 S = ScatterMPI( domain, num_blocks)
00150 M = Meta( S.range() )
00151 return M(S)
00152
00153
00154
00155 class GhostTaper( LinearOperatorStruct ):
00156 """
00157 mpi scatteroperator
00158 """
00159 name = "ghost_taper"
00160
00161 def __init__( self, inSpace, eps ):
00162
00163 kparams = dict( eps=eps )
00164
00165 LinearOperatorStruct.__init__( self, inSpace, **kparams )
00166
00167
00168
00169 @LinearOperatorType
00170 def MGhostTaper( domain, eps):
00171 M1 = Meta( domain )
00172 G = GhostTaper( M1.range() , eps )
00173 M2 = Meta( G.range( ) )
00174 return M2( G( M1 ) )
00175