Example #1
0
 def __matmul__(self, other):
     """
     Multiplication of two TT-matrices
     """
     diff = len(self.n) - len(other.m)
     L = self if diff >= 0 else _tools.kron(self, matrix(_tools.ones(1, abs(diff))))
     R = other if diff <= 0 else _tools.kron(other, matrix(_tools.ones(1, abs(diff))))
     c = matrix()
     c.n = L.n.copy()
     c.m = R.m.copy()
     res = _vector.vector()
     res.d = L.tt.d
     res.n = c.n * c.m
     if L.is_complex or R.is_complex:
         res.r = _core_f90.core.zmat_mat(
             L.n, L.m, R.m, _np.array(
                 L.tt.core, dtype=_np.complex), _np.array(
                 R.tt.core, dtype=_np.complex), L.tt.r, R.tt.r)
         res.core = _core_f90.core.zresult_core.copy()
     else:
         res.r = _core_f90.core.dmat_mat(
             L.n, L.m, R.m, _np.real(
                 L.tt.core), _np.real(
                 R.tt.core), L.tt.r, R.tt.r)
         res.core = _core_f90.core.result_core.copy()
     _core_f90.core.dealloc()
     res.get_ps()
     c.tt = res
     return c
Example #2
0
 def __kron__(self, other):
     """ Kronecker product of two TT-matrices """
     if other is None:
         return self
     a = self
     b = other
     c = matrix()
     c.n = _np.concatenate((a.n, b.n))
     c.m = _np.concatenate((a.m, b.m))
     c.tt = _tools.kron(a.tt, b.tt)
     return c
Example #3
0
    def evaluate_mode(self, l, m, *args, **kwargs):
        """
        evaluate (l,m) mode and return FieldOut
        input: 
        spectral coefficients: dataT, dataP, 
        physical grid: r, theta, phi0
        kron: 'meridional' or 'equatorial'
        outpu: FieldOut
        e.g:
        evaluate_mode(l, m, FieldOut, dataT[i, :], dataP[i, :], r, theta, kron='meridional', phi0=p)
        """
        #print(l, m)
        # raise exception if wrong geometry
        if not (self.geometry == 'shell' or self.geometry == 'sphere'):
            raise NotImplementedError('makeMeridionalSlice is not implemented for the geometry: '+self.geometry)

        # prepare the input data
        #Evaluated fields 
        Field_r = args[0][0]
        Field_theta = args[0][1]
        Field_phi = args[0][2]
        #spectral coefficients
        modeT = args[1]
        modeP = args[2]
        #grid points 
        r = args[3]
        theta = args[4]
        phi = args[5]
        phi0 = kwargs['phi0']

        
        # define factor
        factor = 1. if m==0 else 2.

        if kwargs['kron'] == 'isogrid' or kwargs['kron'] == 'points':
            x = kwargs['x']
            if self.geometry == 'shell':
                # assume that the mode is weighted like Philippe sets it
                modeP[1:] *= 2.
                modeT[1:] *= 2.
                # prepare the q_part
                modeP_r = cheb.chebval(x, modeP)/r
                q_part = modeP_r * l*(l+1)
                
                # prepare the s_part
                dP = np.zeros_like(modeP)
                d_temp = cheb.chebder(modeP)
                dP[:len(d_temp)] = d_temp
                s_part = modeP_r + cheb.chebval(x, dP)/self.a
                                
                # prepare the t_part
                t_part = cheb.chebval(x, modeT)
                                
            elif self.geometry == 'sphere':
                #TODO: Leo
                q_part = None
                s_part = None
                t_part = None
        
        else: # hence either meridional or equatorial
            if self.geometry == 'shell':
                # prepare the q_part
                # q = l*(l+1) * Poloidal / r            
                # idct: inverse discrete cosine transform
                # type = 2: type of transform 
                # q = Field_radial 
                # prepare the q_part
                # idct = \sum c_n * T_n(xj)

                modeP_r = idct(modeP, type = 2)/r
                q_part = modeP_r * l*(l+1)
                
                # prepare the s_part
                # s_part = orthogonal to Field_radial and Field_Toroidal
                # s_part = (Poloidal)/r + d(Poloidal)/dr = 1/r d(Poloidal)/dr
                dP = np.zeros_like(modeP)
                d_temp = cheb.chebder(modeP)
                dP[:len(d_temp)] = d_temp
                s_part = modeP_r + idct(dP, type = 2)/self.a
                
                # prepare the t_part
                # t_part = Field_Toroidal                
                t_part = idct(modeT, type = 2)
                
            elif self.geometry == 'sphere':
                #TODO: Leo, Where do you get this???
                #print('modeP:', modeP.shape, modeP) #32
                #print('modeT:', modeT.shape, modeT) #32
                #print('r:',r.shape, r) # 64
                #print('specRes:',self.specRes)
                modeP_r = np.zeros_like(r)
                dP = np.zeros_like(r)
                t_part = np.zeros_like(r)

            for n in range(self.specRes.N):
                modeP_r=modeP_r+modeP[n]*wor.W(n, l, r)/r
                dP = dP+modeP[n]*wor.diffW(n, l, r)
                t_part = t_part + modeT[n]*wor.W(n,l,r)

            q_part =  modeP_r*l*(l+1)#same stuff
            s_part = modeP_r + dP 
        
        # depending on the kron type it changes how 2d data are formed
        # Mapping from qst to r,theta, phi 
        # phi0: azimuthal angle of meridional plane. It's also the phase shift of the flow with respect to the mantle frame, 
        if kwargs['kron'] == 'meridional':
            eimp = np.exp(1j *  m * phi0)
            
            idx_ = self.idx[l, m]
            Field_r += np.real(tools.kron(q_part, self.Plm[idx_, :]) *
                               eimp) * factor
            
            Field_theta += np.real(tools.kron(s_part, self.dPlm[idx_, :]) * eimp) * 2
            Field_theta += np.real(tools.kron(t_part, self.Plm_sin[idx_, :]) * eimp * 1j * m) * 2#factor
            Field_phi += np.real(tools.kron(s_part, self.Plm_sin[idx_, :]) * eimp * 1j * m) * 2#factor 
            Field_phi -= np.real(tools.kron(t_part, self.dPlm[idx_, :]) * eimp) * 2

        elif kwargs['kron'] == 'points':
            eimp = np.exp(1j *  m * phi)
            
            idx_ = self.idx[l, m]
            Field_r += np.real(q_part * self.Plm[idx_, :] * eimp) * factor
            Field_theta += np.real(s_part * self.dPlm[idx_, :] * eimp) * 2
            Field_theta += np.real(t_part * self.Plm_sin[idx_, :] * eimp * 1j * m) * 2#factor
            Field_phi += np.real(s_part * self.Plm_sin[idx_, :] * eimp * 1j * m) * 2#factor 
            Field_phi -= np.real(t_part * self.dPlm[idx_, :] * eimp) * 2

        elif kwargs['kron'] == 'equatorial':
            """
            eimp = np.exp(1j *  m * (phi0 + phi))
            
            idx_ = self.idx[l, m]
            Field_r += np.real(tools.kron(q_part, eimp) *
                               self.Plm[idx_, :][0]) * factor
            
            Field_theta += np.real(tools.kron(s_part, eimp)) * self.dPlm[idx_, :][0] * 2
            Field_theta += np.real(tools.kron(t_part, eimp) * 1j * m) * self.Plm_sin[idx_, :][0] * 2#factor
            Field_phi += np.real(tools.kron(s_part, eimp) * 1j * m) * self.Plm_sin[idx_, :][0] * 2#factor
            Field_phi -= np.real(tools.kron(t_part, eimp)) * self.dPlm[idx_, :][0] * 2
            """
            idx_ = self.idx[l, m]
            
            #Field_r += np.real(tools.kron(self.Plm[idx_, :], eimp) * q_part) * factor
            Field_r[:, m] += self.Plm[idx_, :] * q_part

            #Field_theta += np.real(tools.kron(self.dPlm[idx_, :], eimp) * s_part) * 2
            Field_theta[:, m] += self.dPlm[idx_, :] * s_part
            #Field_theta += np.real(tools.kron(self.Plm_sin[idx_, :], eimp * 1j * m) * t_part) * 2#factor
            Field_theta[:, m] += self.Plm_sin[idx_, :] * 1j * m * t_part
            #Field_phi += np.real(tools.kron(self.Plm_sin[idx_, :], eimp * 1j * m) * s_part) * 2#factor
            Field_phi[:, m] += self.Plm_sin[idx_, :]* 1j * m * s_part
            #Field_phi -= np.real(tools.kron(self.dPlm[idx_, :], eimp) * t_part) * 2
            Field_phi[:, m] -= self.dPlm[idx_, :] * t_part
            
        elif kwargs['kron'] == 'isogrid':
            #eimp = np.exp(1j *  m * (phi0 + phi))
            
            idx_ = self.idx[l, m]
            
            #Field_r += np.real(tools.kron(self.Plm[idx_, :], eimp) * q_part) * factor
            Field_r[:, m] += self.Plm[idx_, :] * q_part

            #Field_theta += np.real(tools.kron(self.dPlm[idx_, :], eimp) * s_part) * 2
            Field_theta[:, m] += self.dPlm[idx_, :] * s_part
            #Field_theta += np.real(tools.kron(self.Plm_sin[idx_, :], eimp * 1j * m) * t_part) * 2#factor
            Field_theta[:, m] += self.Plm_sin[idx_, :] * 1j * m * t_part
            #Field_phi += np.real(tools.kron(self.Plm_sin[idx_, :], eimp * 1j * m) * s_part) * 2#factor
            Field_phi[:, m] += self.Plm_sin[idx_, :]* 1j * m * s_part
            #Field_phi -= np.real(tools.kron(self.dPlm[idx_, :], eimp) * t_part) * 2
            Field_phi[:, m] -= self.dPlm[idx_, :] * t_part
            
        else:
            raise ValueError('Kron type not understood: '+kwargs['kron'])

        pass