Пример #1
0
 def WriteMP3dFile(self, aqui, listEsp, Tbase, Etemps, opt, parmk=None):
     self.interpreter = MtInterpreter(self.model, opt)
     aqui.createZoneTransient()
     self.zoneTransient = aqui.getZoneTransient()
     self.tlist = self.zoneTransient['tlist']
     [aL, aT, aZ, rf] = zip(*Tbase['Transp'])[1]
     self.WriteNamFile(opt, rf)
     if opt in ['MT3D', 'SEAWAT']: self.mcomp = self.ncomp = 1
     else:
         self.mcomp, self.ncomp, self.anySol = listEsp['mcomp'], listEsp[
             'ncomp'], listEsp['anySol']
     if opt in ['MT3D', 'SEAWAT']:
         l = 'T'  # transport que traceur
         trans = self.model.Aquifere.getZoneTransient()['Transport']
     if opt == 'SEAWAT':
         self.WriteVdfFile()
     if opt == 'PHT3D':
         self.WritePht3dFile(aqui, Tbase, listEsp, parmk)
         self.WritePhreeqc(aqui, Tbase, listEsp)
         trans = self.model.Aquifere.getZoneTransient()['PHT3D']
     for n in ['btn', 'adv', 'dsp']:
         self.writeFile(n, opt)
     if len(trans) > 0: self.writeFile('ssm', opt)
     ##        self.WriteBtnFile(aqui,Tbase,listEsp,Etemps,opt);
     ##        self.WriteAdvFile(Tbase,opt);
     ##        self.WriteDspFile(aqui,Tbase,opt);
     ##        self.WriteSsmFile(aqui,Tbase,listEsp,Etemps,opt);
     self.WriteGcgFile(Tbase, opt)
     if rf > 1:
         self.WriteRctFile(aqui, Tbase, listEsp,
                           opt)  # case with retardation
     if self.model.getDualPoro() and opt == 'PHT3D':
         self.WriteRct1File(aqui, Tbase, listEsp,
                            opt)  # dual porosity exists
     return
Пример #2
0
    def WriteMP3dFile(self, aqui,listEsp,Tbase,Etemps,opt,parmk=None):
        self.interpreter=MtInterpreter(self.model,opt)
        aqui.createZoneTransient();
        self.zoneTransient = aqui.getZoneTransient()
        self.tlist=self.zoneTransient['tlist']
        [aL,aT,aZ,rf] = zip(*Tbase['Transp'])[1]
        self.WriteNamFile(opt,rf)
        if opt in ['MT3D','SEAWAT']:self.mcomp=self.ncomp=1
        else :
            self.mcomp,self.ncomp,self.anySol=listEsp['mcomp'],listEsp['ncomp'],listEsp['anySol']
        if opt in ['MT3D','SEAWAT']:
            l='T' # transport que traceur
            trans=self.model.Aquifere.getZoneTransient()['Transport']
        if opt=='SEAWAT':
            self.WriteVdfFile()
        if opt=='PHT3D':
            self.WritePht3dFile(aqui,Tbase,listEsp,parmk)
            self.WritePhreeqc(aqui,Tbase,listEsp);
            trans=self.model.Aquifere.getZoneTransient()['PHT3D']
        for n in ['btn','adv','dsp']: self.writeFile(n,opt)
        if len(trans)>0: self.writeFile('ssm',opt)
##        self.WriteBtnFile(aqui,Tbase,listEsp,Etemps,opt);
##        self.WriteAdvFile(Tbase,opt);
##        self.WriteDspFile(aqui,Tbase,opt);
##        self.WriteSsmFile(aqui,Tbase,listEsp,Etemps,opt);
        self.WriteGcgFile(Tbase,opt);
        if rf>1: self.WriteRctFile(aqui,Tbase,listEsp,opt) # case with retardation
        if self.model.getDualPoro() and opt=='PHT3D':
            self.WriteRct1File(aqui,Tbase,listEsp,opt)  # dual porosity exists
        return 
Пример #3
0
class MP3dWriter:
    def __init__(self, model, path, name):
        self.model, self.gui = model, model.gui
        self.pPath, self.pName = path, name
        self.fullPath = path + os.sep + name
        self.ncomp, self.mcomp = 1, 1

    def CreateFile(self, extension, mode):
        filename = self.pPath + os.sep + extension
        file_descriptor = open(filename, mode)
        return file_descriptor

    def WriteMP3dFile(self, aqui, listEsp, Tbase, Etemps, opt, parmk=None):
        self.interpreter = MtInterpreter(self.model, opt)
        aqui.createZoneTransient()
        self.zoneTransient = aqui.getZoneTransient()
        self.tlist = self.zoneTransient['tlist']
        [aL, aT, aZ, rf] = zip(*Tbase['Transp'])[1]
        self.WriteNamFile(opt, rf)
        if opt in ['MT3D', 'SEAWAT']: self.mcomp = self.ncomp = 1
        else:
            self.mcomp, self.ncomp, self.anySol = listEsp['mcomp'], listEsp[
                'ncomp'], listEsp['anySol']
        if opt in ['MT3D', 'SEAWAT']:
            l = 'T'  # transport que traceur
            trans = self.model.Aquifere.getZoneTransient()['Transport']
        if opt == 'SEAWAT':
            self.WriteVdfFile()
        if opt == 'PHT3D':
            self.WritePht3dFile(aqui, Tbase, listEsp, parmk)
            self.WritePhreeqc(aqui, Tbase, listEsp)
            trans = self.model.Aquifere.getZoneTransient()['PHT3D']
        for n in ['btn', 'adv', 'dsp']:
            self.writeFile(n, opt)
        if len(trans) > 0: self.writeFile('ssm', opt)
        ##        self.WriteBtnFile(aqui,Tbase,listEsp,Etemps,opt);
        ##        self.WriteAdvFile(Tbase,opt);
        ##        self.WriteDspFile(aqui,Tbase,opt);
        ##        self.WriteSsmFile(aqui,Tbase,listEsp,Etemps,opt);
        self.WriteGcgFile(Tbase, opt)
        if rf > 1:
            self.WriteRctFile(aqui, Tbase, listEsp,
                              opt)  # case with retardation
        if self.model.getDualPoro() and opt == 'PHT3D':
            self.WriteRct1File(aqui, Tbase, listEsp,
                               opt)  # dual porosity exists
        return

    def WriteNamFile(self, opt, rf):
        f1 = self.CreateFile(opt + '.nam', 'w')
        f1.write('List  7  ' + opt + '.out\n')
        if opt == 'SEAWAT':
            f2 = open(self.fullPath + '.nam', 'r')
            f2.readline()
            for ll in f2:
                f1.write(ll)
            f2.close()
        else:
            f1.write('FTL  66 ' + self.pName + '.flo\n')
        f1.write('BTN  31 ' + opt + 'btn.dat\n ADV  32    ' + opt +
                 'adv.dat\n')
        f1.write('DSP  33 ' + opt + 'dsp.dat\n SSM  34    ' + opt +
                 'ssm.dat\n')
        f1.write('GCG  35 ' + opt + 'gcg.dat\n')
        if opt == 'PHT3D':
            f1.write('PHC  64    ' + opt + '_ph.dat\n')
        if rf > 1 or self.model.getDualPoro():
            f1.write('RCT  36 ' + opt + 'rct.dat\n')
        f1.close()

    #*********************** generic file writer ****************
    def writeFile(self, name, opt):
        """to write any modflow file.
        reads the keyword file and prints all keywords by types : param (0D)
        vector (1D) array (2D). types are found by (dim1,dim2).."""
        f1 = open(self.pPath + os.sep + opt + name + '.dat', 'w')
        ptslist, arrlist = [], []
        n1 = Mkey.groups.keys()
        #print n1,name
        for n in n1:
            if n.split('.')[1] == name: llist = Mkey.groups[n]
        for ll in llist:
            cond = Mkey.lines[ll]['cond']
            #print 'mflw 1',cond,self.testCondition(cond)
            if self.testCondition(cond) == False: continue
            kwlist = Mkey.lines[ll]['kw']
            kw0 = kwlist[0].split('(')[0]
            ktyp = Mkey.lines[ll]['type']
            #print 'mtw',kw0,ktyp
            if ktyp in ['arr', 'vec', 'xarr']:
                arr, aname = self.interpreter.getArray(kw0)

            if ktyp == 'vec':  # a vector
                self.writeVecMT3D(arr, f1)
                exec('self.' + kw0 + '=' + str(arr[0]))

            elif ktyp == 'string':  # a string to print
                s = self.interpreter.getParm(kw0)
                f1.write(s)
                #exec('self.'+kw0+'='+s[:2])

            elif ktyp == 'arr':  # one array
                self.writeBlockMT3D(arr, f1, aname)
            elif ktyp == 'xarr':  # several arrays
                for i in range(len(arr)):
                    self.writeBlockMT3D(arr[i], f1, aname[i])

            elif ktyp == 'parr':  # one variable, p arrays: one for each period
                nper = self.interpreter.getNper()
                for ip in range(nper):
                    arr = self.interpreter.getArrayPeriod(kw0, ip)
                    arrlist.append(arr)

            elif ktyp == 'nvec2':  # list of periods or others
                vlist = []
                for k in kwlist:
                    a = k.split('(')
                    b, c = self.interpreter.getArray(a[0])
                    vlist.append(b)
                nlines = len(vlist[0])
                s = ''
                for j in range(nlines):
                    for ik in range(3):
                        val = vlist[ik][j]
                        s += str(val)[:9].ljust(9) + ' '  #' %9.3e'%val#
                    s += '\n'
                    for ik in range(3, 7):
                        val = vlist[ik][j]
                        s += str(val)[:9].ljust(9) + ' '  #' %9.3e'%val #
                    s += '\n'
                f1.write(s)

            elif ktyp == 'npoints':  # points on the grid stored in alist (for ssm)
                nper = self.interpreter.getNper()
                print 'opt', opt
                for ip in range(nper):
                    plist = self.interpreter.getPointsPer(opt, ip)
                    il, ir, ic, typ, v = plist
                    s = str(len(il)) + '\n'
                    #print len(il),len(ir),len(ic),len(typ),len(v)
                    for i in range(len(il)):
                        s += str(il[i] + 1).ljust(10) + str(ir[i] + 1).ljust(
                            10) + str(ic[i] + 1).ljust(10)
                        if opt == 'MT3D':
                            s += '%9.3e ' % float(v[i]) + str(
                                typ[i]).rjust(9) + '\n'
                        elif opt == 'PHT3D':
                            s += '       0.' + str(
                                typ[i]).ljust(10) + v[i] + '\n'
                    ptslist.append(s)

            else:  # classical parameters
                for k in kwlist:
                    val = str(self.interpreter.getParm(k))
                    try:
                        int(val)
                        exec('self.' + k + '=' + val)  #
                    except ValueError:
                        if val[0] != '#':
                            exec('self.' + k + '=\'' + val + '\'')
                    if val != ' ': f1.write(val[:9].ljust(9) + ' ')
                if val != ' ': f1.write('\n')

        if len(arrlist) + len(
                ptslist
        ) > 0:  # write the variables by period saved in a list previously
            nper = self.interpreter.getNper()
            for ip in range(nper):
                if len(arrlist) > ip:
                    if type(arrlist[ip]) == type(
                        [5, 6]):  # case of recharge with several species
                        f1.write('1         \n')
                        for j in range(len(arrlist[ip])):
                            self.writeMatMT3D(arrlist[ip][j], f1)
                    else:
                        f1.write('1         \n')
                        self.writeMatMT3D(arrlist[ip], f1)
                if len(ptslist) > ip: f1.write(ptslist[ip])
        print 'print ' + name + ' done'
        f1.close()

    #**************** test condition **********************
    def testCondition(self, cond):
        """ test if the condition is satisfied"""
        a = True
        if cond != '':
            if len(cond.split('and')) > 1:
                c1 = cond.split('and')
                c2 = '(self.' + c1[0].strip() + ')'
                for i in range(1, len(c1)):
                    c2 += ' and (self.' + c1[i].strip() + ')'
            elif len(cond.split('or')) > 1:
                c1 = cond.split('or')
                c2 = '(self.' + c1[0] + ')'
                for i in range(1, len(c1)):
                    c2 += ' or (self.' + c1[i].strip() + ')'
            else:
                c2 = 'self.' + cond
            exec('a=' + c2)
            #print 'cond',c2,a;
        if a or cond == '': return True
        return False

    #************************ writeture du fichier GCG ***********************************
    def WriteGcgFile(self, Tbase, opt):
        f1 = self.CreateFile(opt + 'gcg.dat', 'w')

        it, mxiter, isolve, ncrs, accl, cclose, iprgcg = zip(
            *Tbase['Solver'])[1]
        f1.write('%9i %9i %9i %9i\n' %
                 (int(it), int(mxiter), int(isolve), int(ncrs)))
        f1.write('%9i %9.4e %9i\n' % (accl, cclose, int(iprgcg)))
        f1.close()  #fermer le fichier gcg

        #*************************** write RCT file for sorption *********************
    def WriteRctFile(self, aqui, Tbase, listE, opt):
        """ writes an RCT file in case of retardation """
        f1 = self.CreateFile(opt + 'rct.dat', 'w')
        nrow = int(aqui.getFullGrid()['ny'])
        nlay = aqui.getNbCouches()
        if aqui.getDim() in ['Xsection', 'Radial']: nlay = nrow
        [aL, aT, aZ, rf] = zip(*Tbase['Transp'])[1]
        Isothm, Ireact, Irctop, Igetsc = 1, 0, 2, 0
        f1.write('%9i %9i %9i %9i\n' % (Isothm, Ireact, Irctop, Igetsc))
        # Rec 2 : Rohb (2b and 2c not used here)
        poro = obj2matBlock(aqui, 'Porosite')
        rhob = 2650. * (1. - poro)
        #print nlay,shape(poro),shape(rhob)
        for l in range(nlay):
            self.writeMatMT3D(rhob[l] * self.radfact, f1,
                              'Rhob')  # rhob matric(ncol,nrow) en kg/m3
        # line E3 sorption (isothm>0)
        Kd = (float(rf) - 1.) * poro / rhob
        for l in range(nlay):
            self.writeMatMT3D(Kd[l], f1, 'Kd')
        # line E4 2nd sorption coeff not used here
        for l in range(nlay):
            f1.write('         0  0.0 \n')
        f1.close()

        #*************************** write RCT file for 2domain *********************
    def WriteRct1File(self, aqui, Tbase, listE, opt):
        """ writes an RCT file in case of double porosity"""
        f1 = self.CreateFile(opt + 'rct.dat', 'w')
        nlay = aqui.getNbCouches()
        if aqui.getDim() in ['Xsection', 'Radial']:
            nlay = nrow
            nrow = 1
        # Rec1 : Isothm, Ireact, Irctop, IGetsc Irctop 0
        # 2domain : Isothm : 5 dual domain( no sorption), igetsc>0 : initial conc read here
        Isothm, Ireact, Irctop, Igetsc = 5, 0, 1, 1
        f1.write('%9i %9i %9i %9i\n' % (Isothm, Ireact, Irctop, Igetsc))
        # Rec 2 : Rohb do not enter if isothm=5
        # Rec3 Prsty2 only for dual domain (isothm 5 or 6)
        # the porosity matrix comes from Pht3D immobile solutions, line Imm_poro
        opt1 = opt * 1
        if opt == 'MT3D': opt1 = 'Transport'
        mS = obj2matBlockNb(aqui, opt1, 'zon')
        m0 = mS[0] * 0
        imm_s = Tbase['Immobile']['Solutions']
        ie = imm_s['rows'].index('Imm_poro')
        for l in range(nlay):
            poro = m0 + float(imm_s['data'][ie][1])  # data[1] backgrd
            for s in range(self.nsol - 1):
                poro[abs(mS[l]) / 1000 == s + 1] = float(imm_s['data'][ie][s +
                                                                           2])
            self.writeMatMT3D(poro, f1, 'Poro')
        # Rec4 : if Igetsc>0 initial conc in immob phase for each species
        # run along the Chemistry to find the species for whic conc are needed
        short = ['k', 'i', 'kim', 'p', 'e', 's', 'kp']
        ntot = 0
        div = [1000, 1000, 1000, 100, 10, 100, 1]
        lon = ['Solutions'] * 3
        lon.extend(['Phases', 'Exchange', 'Surface', 'Phases'])
        for ik in range(len(short)):
            l0 = listE[short[ik]]  # list of species present in chemistry
            for esp in l0:
                if esp in ['Imm_poro', 'Transf_coeff']: continue
                kw = lon[ik]
                imm = Tbase['Immobile'][kw].copy()
                ntot += 1
                ie = imm['rows'].index(esp)
                #print 'mtpht rct',kw,esp,ie
                for l in range(nlay):
                    cnc = m0 + float(imm['data'][ie][1])
                    #print imm['data'][ie][1]
                    nsp = len(imm['cols']) - 1
                    for s in range(
                            nsp -
                            1):  # to find the place where BC is true solution
                        cnc[abs(mS[l]) / div[ik] == s + 1] = float(
                            imm['data'][ie][s + 2])
                    self.writeMatMT3D(cnc, f1, esp)
        # Rec 5 sorption1 (each species)
        for i in range(ntot):
            f1.write('        0  0.0 \n')
        # Rec6 sorption 2, here mass transfer coeff for all species
        ie = imm_s['rows'].index('Transf_coeff')
        for i in range(ntot):
            for l in range(nlay):
                tcoeff = m0 + float(imm_s['data'][ie][1])  # data[1] backgrd
                for s in range(
                        self.nsol -
                        1):  # to find the place where BC is true solution
                    tcoeff[abs(mS[l]) / 1000 == s + 1] = float(
                        imm_s['data'][ie][s + 2])
                self.writeMatMT3D(tcoeff, f1, 'Transf Coeff')
        #REc7 RC1 parm for fisrt order deg1
        for i in range(ntot):
            f1.write('        0  0.0 \n')
        #REc8 RC2 parm for fisrt order deg 2
        for i in range(ntot):
            f1.write('        0  0.0 \n')
        f1.close()

    #********************************* Ecire fichier VDF for Seawat ********************
    def WriteVdfFile(self):
        f1 = self.CreateFile('Seawatvdf.dat', 'w')
        ##        1. MTDNCONC MFNADVFD NSWTCPL IWTABLE
        ##        Mtdconc=0 density specified =n dens calculated from n species
        ##        MFNADVFD=2 centre in sapce, ><2 upstream weigthed
        ##        NSWTCPL max number of non linear iterations if 0 or 1 explicit coupling
        ##        iwtable : 0 water table correction not applied, >0 applied
        Mtdnconc, Mfnadvdf, Nswtcpl, Iwtable = 1, 1, 1, 0
        f1.write(' %9i %9i %9i %9i   Mtdnconc Mfnadvdf Nswtcpl Iwtable \n' %
                 (Mtdnconc, Mfnadvdf, Nswtcpl, Iwtable))
        ##        2. DENSEMIN DENSEMAX min an dmax density if 0 not limitation
        Densemin, Densemax = 0, 0
        f1.write(' %9i %9i   DENSEMIN DENSEMAX \n' % (Densemin, Densemax))
        ##        If NSWTCPL is greater than 1, then read item 3.
        ##        3. DNSCRIT convergene criterion difference in density
        Dnscrit = 1e-3
        if Nswtcpl > 1: f1.write(' %9.4e  \n' % Dnscrit)
        ##        4. DENSEREF DENSESLP
        Denseref, Denseslp = 1000., .7143  # Care in kg/m3, slp for freash and sea water
        f1.write(' %9i %9i  DENSEREF DENSESLP \n' % (Denseref, Denseslp))
        ##        5. FIRSTDT ength of first time step
        Firstdt = 1e-3
        f1.write(' %9.4e  \n' % Firstdt)
        ##        FOR EACH STRESS PERIOD (read items 6 and 7 only if MTDNCONC = 0)
        ##        6. INDENSE if<0 val of dense reused form prev tstep
        ##          =0 Dense=ref >=1 dense read from item 7 =2 read from 7 but as conc
        ##        Read item 7 only if INDENSE is greater than zero
        ##        7. [DENSE(NCOL,NROW)] – U2DREL
        ##        Item 7 is read for each layer in the grid.
        nper = len(self.tlist)
        Indense = -1
        for ip in range(nper):
            if Mtdnconc == 0: f1.write(' %9i %9i  INDENSE \n' % Indense)
        f1.close()

    #********************************* Ecire fichier Pht3d ********************
    def WritePht3dFile(self, aqui, Tbase, listE, parmk):
        f1 = self.CreateFile('PHT3D_ph.dat', 'w')
        #PH1 Record: OS TMP_LOC RED_MOD TEMP ASBIN EPS_AQU EPS_PH PACK_SZ
        # OS 1 iterative, 2 sequential. que 2 implemente
        # TMP_LOC : 0 writere dans temp, 1 : writere sur dir local
        # REd mode : 0 pH pe vairables, 1 : pe fixe, 2 : pH et pe fixes (plus rapide)
        # TEmp temperature, ASBIN : 0 : writeture fich binaire, 1 :ascii
        # eps_aqu et eps_ph : si 0 calcul partout
        # pack_sz : taille des paquets pour phreeqc 4000 chiffre OK
        temp = Tbase['PHparm'][0][1]
        os0, tmp, fix0, asbin, eps0, eps1, pack = 2, 1, 0, 0, 1e-10, .001, 2000
        f1.write('%9i %9i %9i %9.1f %9i %9.1e %9.5f %9i\n' %
                 (os0, tmp, fix0, temp, asbin, eps0, eps1, pack))
        dcharge = Tbase['PHparm'][1][1]
        f1.write('%9i\n' % dcharge)  # PH2 v2 diif de charge admissibe
        # determiner le noimbre d'esp cinetiques et en faire la liste
        nInorg = len(listE['i'])
        #+len(self.lists);
        nKmob = len(listE['k'])
        nKimob = len(listE['kim'])
        nMinx = len(listE['p'])
        nExch = len(listE['e'])
        f1.write('%9i\n' % (nInorg))  # PH3 nb compose inorganiques
        f1.write('%9i\n' % (nMinx))  # PH4 nb mineraux
        f1.write('%9i %9i\n' %
                 (nExch, 0))  # PH5 nb ech ions, 0 je sais pas pourquoi
        # PH6 surface complexation
        nSurf = len(listE['s'])
        f1.write('%9i\n' % nSurf)
        #PH7 Record: NR_MOB_KIN NR_MIN_KIN NR_SURF_KIN NR_IMOB_KIN
        # nb especes cinetiques mobiles, minerales, surfaces et substeps pour plus tard
        nKsurf, nKmin = 0, len(listE['kp'])
        f1.write('%9i %9i %9i %9i\n' % (nKmob, nKmin, nKsurf, nKimob))
        # PH8 : NR_OUTP_SPEC (complexes) PR_ALKALINITY_FLAG (futur)
        f1.write('%9i %9i\n' % (0, 0))
        ## nb unites inutile car pht3d considere que tout est en jour
        Chem = Tbase['Chemistry']
        if Chem.has_key('Rates'):
            rates = Chem['Rates']
            for nom in listE['k']:
                iek = rates['rows'].index(nom)
                f1.write(nom + '%5i \n ' % (parmk[nom]))  #param k
                for ip in range(parmk[nom]):
                    f1.write('%9.5e \n' % float(rates['data'][iek][ip + 2]))
                f1.write('-formula ' + rates['data'][iek][-1] +
                         '\n')  # formula
        #for n in self.lists: f1.write(n+' \n') #  species
        optsu = Tbase['PHparm'][2][1]
        for n in listE['i']:
            add = ''
            if optsu.strip() == n: add = ' charge'
            f1.write(n.replace('(+', '(') + add +
                     '\n')  # que reac isntant et AE, pH pe
        # kinetic immobile
        if Chem.has_key('Rates'):
            rates = Chem['Rates']
            for nom in listE['kim']:
                iek = rates['rows'].index(nom)
                f1.write(nom + '%5i \n ' % (parmk[nom]))  #param k
                for ip in range(parmk[nom]):
                    f1.write('%9.5e \n' % float(rates['data'][iek][ip + 2]))
                f1.write('-formula ' + rates['data'][iek][-1] +
                         '\n')  # formula
        for p in listE['p']:
            ip = Chem['Phases']['rows'].index(p)
            f1.write(p + '  ' + str(Chem['Phases']['data'][ip][1]) +
                     ' \n')  # phase name + SI backgrd
        for n in listE['e']:
            f1.write(n + ' -1 \n')  # exchanger
        if Chem.has_key('Surface'):  # surface
            su = Chem['Surface']
            l = len(su['cols'])
            for esp in listE['s']:
                st = esp
                ies = su['rows'].index(esp)
                for i in range(l - 2, l):
                    st += ' ' + str(su['data'][ies][i])
                f1.write(st + ' \n')
            optsu = Tbase['PHparm'][3][1]
            if optsu in ['no_edl', 'diffuse_layer']:
                f1.write('-' + optsu + '\n')
        if Chem.has_key('Kinetic_Minerals'):
            kp = Chem['Kinetic_Minerals']
            for nom in listE['kp']:
                iek = kp['rows'].index(nom)
                f1.write(nom + '%5i \n ' % (parmk[nom]))  #param k
                for ip in range(parmk[nom]):
                    f1.write('%9.5e \n' % float(kp['data'][iek][ip + 1]))
        f1.close()

    #  ''''''''''''''''''''''''''''''' fonction writeMatMT3D '''''''''''''''''''''''''''
    def writeVecMT3D(self, v, f1, name=' '):
        l = len(v)
        a = str(type(v[0]))
        if a[13:16] == 'int': typ = 'I'
        else: typ = 'G'
        if amin(v) == amax(v):
            f1.write('         0 %7.3e  #' % (amin(v)) + name + '\n')
            return
        if typ == 'I':
            fmt = '      100    1      (' + str(l) + 'I' + str(ln) + ')'
        else:
            fmt = '      100    1.0      (' + str(l) + 'G12.4)'
        f1.write(fmt)
        f1.write('\n')

        if typ == 'I': fmt = '%' + str(ln) + 'i'
        else: fmt = '%+11.4e '
        for i in range(l):
            f1.write(fmt % v[i])
        f1.write('\n')

    def writeMatMT3D(self, m, f1, name=' '):
        if len(shape(m)) <= 1: return self.writeVecMT3D(m, f1, name)
        [l, c] = shape(m)
        ln = 3
        a = str(type(m[0, 0]))
        if a[13:16] == 'int': typ = 'I'
        else: typ = 'G'
        if amin(amin(m)) == amax(amax(m)):
            if typ == 'I':
                f1.write('         0 %8i #' % (amin(amin(m))) + name[:6] +
                         '\n')
            else:
                f1.write('         0 %7.3e #' % (amin(amin(m))) + name[:6] +
                         '\n')
            return
        if typ == 'I':
            fmt = '      100    1      (' + str(c) + 'I' + str(ln) + ')'
        else:
            fmt = '      100    1.0      (' + str(c) + 'G12.4) #' + name[:6]
        f1.write(fmt + '\n')

        if typ == 'I': fmt = '%' + str(ln) + 'i'
        else: fmt = '%11.4e '
        for i in range(l - 1, -1, -1):
            for j in range(c):
                f1.write(fmt % m[i][j])
            f1.write('\n')

    def writeBlockMT3D(self, m, f1, name=' '):
        if len(shape(m)) == 3:
            nlay, a, b = shape(m)
            for l in range(nlay):
                self.writeMatMT3D(m[l], f1, name)
        else:
            self.writeMatMT3D(m, f1, name)

    def WritePhreeqc(self, aqui, Tbase, listE):
        """this routine writes a phreeqc file where all solutions are written in
        phreqc format to be able to test their equilibrium before running pht3d
        1. tabke background, then cycle through pht3d zones
        2. get the solution number, phase number...it does not take rates
        3 write them in phreeqc format"""
        f1 = self.CreateFile('solutions.phrq', 'w')
        f1.write('Database ' + self.pPath + '\pht3d_datab.dat \n')
        zones = aqui.getZoneList('PHT3D')
        nzone = len(zones)
        for i in range(nzone):
            z = zones[i]
            val = z.getVal()
            if type(val) == type([5]):
                val = int(val[0].split()[1])  #case of transient chemistry
            else:
                val = int(val)
            f1.write('Solution ' + str(i) + ' \n units mol/L \n')
            solu = Tbase['Chemistry']['Solutions']
            nsol = val / 1000
            for esp in listE['i']:  # go through phase list
                ie = solu['rows'].index(esp)
                #print esp,phases['rows'],ip,phases['data'][ip] # index of the phase
                conc = solu['data'][ie][nsol +
                                        1]  #backgr concentration of species
                f1.write(esp + ' ' + str(conc) + '\n')
            f1.write('Equilibrium_Phases ' + str(i) + '\n')
            phases = Tbase['Chemistry']['Phases']
            nphas = mod(val, 1000) / 100
            for esp in listE['p']:  # go through phase list
                ip = phases['rows'].index(esp)
                #print esp,phases['rows'],ip,phases['data'][ip] # index of the phase
                IS, conc = phases['data'][ip][
                    nphas * 2 + 1:nphas * 2 +
                    3]  #backgr SI and concentration of phase
                f1.write(esp + ' ' + str(IS) + ' ' + str(conc) + '\n')
            f1.write('end \n')
        f1.close()
Пример #4
0
class MP3dWriter:

    def __init__(self, model, path, name):
        self.model,self.gui = model, model.gui
        self.pPath,self.pName = path,name;
        self.fullPath = path + os.sep + name
        self.ncomp, self.mcomp= 1,1

    def CreateFile(self, extension, mode):
        filename = self.pPath + os.sep+extension
        file_descriptor = open(filename, mode)
        return file_descriptor

    def WriteMP3dFile(self, aqui,listEsp,Tbase,Etemps,opt,parmk=None):
        self.interpreter=MtInterpreter(self.model,opt)
        aqui.createZoneTransient();
        self.zoneTransient = aqui.getZoneTransient()
        self.tlist=self.zoneTransient['tlist']
        [aL,aT,aZ,rf] = zip(*Tbase['Transp'])[1]
        self.WriteNamFile(opt,rf)
        if opt in ['MT3D','SEAWAT']:self.mcomp=self.ncomp=1
        else :
            self.mcomp,self.ncomp,self.anySol=listEsp['mcomp'],listEsp['ncomp'],listEsp['anySol']
        if opt in ['MT3D','SEAWAT']:
            l='T' # transport que traceur
            trans=self.model.Aquifere.getZoneTransient()['Transport']
        if opt=='SEAWAT':
            self.WriteVdfFile()
        if opt=='PHT3D':
            self.WritePht3dFile(aqui,Tbase,listEsp,parmk)
            self.WritePhreeqc(aqui,Tbase,listEsp);
            trans=self.model.Aquifere.getZoneTransient()['PHT3D']
        for n in ['btn','adv','dsp']: self.writeFile(n,opt)
        if len(trans)>0: self.writeFile('ssm',opt)
##        self.WriteBtnFile(aqui,Tbase,listEsp,Etemps,opt);
##        self.WriteAdvFile(Tbase,opt);
##        self.WriteDspFile(aqui,Tbase,opt);
##        self.WriteSsmFile(aqui,Tbase,listEsp,Etemps,opt);
        self.WriteGcgFile(Tbase,opt);
        if rf>1: self.WriteRctFile(aqui,Tbase,listEsp,opt) # case with retardation
        if self.model.getDualPoro() and opt=='PHT3D':
            self.WriteRct1File(aqui,Tbase,listEsp,opt)  # dual porosity exists
        return 
        
    def WriteNamFile(self,opt,rf):
        f1 = self.CreateFile(opt+'.nam','w');
        f1.write('List  7  '+opt+'.out\n')
        if opt=='SEAWAT':
            f2=open(self.fullPath+'.nam','r');f2.readline()
            for ll in f2: f1.write(ll)
            f2.close()
        else : f1.write('FTL  66 '+self.pName+'.flo\n')
        f1.write('BTN  31 '+opt+'btn.dat\n ADV  32    '+opt+'adv.dat\n')
        f1.write('DSP  33 '+opt+'dsp.dat\n SSM  34    '+opt+'ssm.dat\n')
        f1.write('GCG  35 '+opt+'gcg.dat\n')
        if opt=='PHT3D':
            f1.write('PHC  64    '+opt+'_ph.dat\n')
        if rf>1 or self.model.getDualPoro():
            f1.write('RCT  36 '+opt+'rct.dat\n')
        f1.close()

    #*********************** generic file writer ****************
    def writeFile(self,name,opt):
        """to write any modflow file.
        reads the keyword file and prints all keywords by types : param (0D)
        vector (1D) array (2D). types are found by (dim1,dim2).."""
        f1=open(self.pPath +os.sep+opt+ name+'.dat','w');
        ptslist,arrlist=[],[]
        n1=Mkey.groups.keys();#print n1,name
        for n in n1:
            if n.split('.')[1]==name: llist=Mkey.groups[n]
        for ll in llist:
            cond=Mkey.lines[ll]['cond'];#print 'mflw 1',cond,self.testCondition(cond)
            if self.testCondition(cond)==False :continue
            kwlist=Mkey.lines[ll]['kw'];kw0=kwlist[0].split('(')[0]
            ktyp=Mkey.lines[ll]['type'];#print 'mtw',kw0,ktyp
            if ktyp in ['arr','vec','xarr']: arr,aname=self.interpreter.getArray(kw0)
            
            if ktyp=='vec': # a vector
                self.writeVecMT3D(arr,f1)
                exec('self.'+kw0+'='+str(arr[0]))
                
            elif ktyp=='string': # a string to print 
                s=self.interpreter.getParm(kw0);f1.write(s)
                #exec('self.'+kw0+'='+s[:2])
                
            elif ktyp=='arr': # one array
                self.writeBlockMT3D(arr,f1,aname)
            elif ktyp=='xarr': # several arrays
                for i in range(len(arr)): self.writeBlockMT3D(arr[i],f1,aname[i])
                
            elif ktyp=='parr': # one variable, p arrays: one for each period
                nper=self.interpreter.getNper()
                for ip in range(nper):
                    arr=self.interpreter.getArrayPeriod(kw0,ip)
                    arrlist.append(arr)
        
            elif ktyp=='nvec2': # list of periods or others
                vlist=[]
                for k in kwlist:
                    a=k.split('(')
                    b,c=self.interpreter.getArray(a[0]);vlist.append(b)
                nlines=len(vlist[0]);s=''
                for j in range(nlines):
                    for ik in range(3):
                        val=vlist[ik][j];s+=str(val)[:9].ljust(9)+' ' #' %9.3e'%val# 
                    s+='\n'
                    for ik in range(3,7):
                        val=vlist[ik][j];s+=str(val)[:9].ljust(9)+' ' #' %9.3e'%val #
                    s+='\n'
                f1.write(s)
                
            elif ktyp=='npoints': # points on the grid stored in alist (for ssm)
                nper=self.interpreter.getNper();print 'opt',opt
                for ip in range(nper):
                    plist=self.interpreter.getPointsPer(opt,ip)
                    il,ir,ic,typ,v=plist;s=str(len(il))+'\n'
                    #print len(il),len(ir),len(ic),len(typ),len(v)
                    for i in range(len(il)):
                        s+=str(il[i]+1).ljust(10)+str(ir[i]+1).ljust(10)+str(ic[i]+1).ljust(10)
                        if opt=='MT3D': s+='%9.3e '%float(v[i])+str(typ[i]).rjust(9)+'\n'
                        elif opt=='PHT3D': s+='       0.'+str(typ[i]).ljust(10)+v[i]+'\n'
                    ptslist.append(s)
                    
            else : # classical parameters
                for k in kwlist:
                    val=str(self.interpreter.getParm(k));
                    try : int(val); exec('self.'+k+'='+val) #
                    except ValueError:
                        if val[0]!='#' : exec('self.'+k+'=\''+val+'\'') 
                    if val!=' ': f1.write(val[:9].ljust(9)+' ')
                if val!=' ': f1.write('\n')
                
        if len(arrlist)+len(ptslist)>0: # write the variables by period saved in a list previously
            nper=self.interpreter.getNper()
            for ip in range(nper):
                if len(arrlist)>ip:
                    if type(arrlist[ip])==type([5,6]): # case of recharge with several species
                        f1.write('1         \n');
                        for j in range(len(arrlist[ip])): self.writeMatMT3D(arrlist[ip][j],f1)
                    else: f1.write('1         \n');self.writeMatMT3D(arrlist[ip],f1)
                if len(ptslist)>ip: f1.write(ptslist[ip])
        print 'print '+name+' done'
        f1.close()

    #**************** test condition **********************
    def testCondition(self,cond):
        """ test if the condition is satisfied"""
        a=True
        if cond!='':
            if len(cond.split('and'))>1:
                c1=cond.split('and'); c2='(self.'+c1[0].strip()+')'
                for i in range(1,len(c1)): c2+=' and (self.'+c1[i].strip()+')'
            elif len(cond.split('or'))>1:
                c1=cond.split('or'); c2='(self.'+c1[0]+')'
                for i in range(1,len(c1)): c2+=' or (self.'+c1[i].strip()+')'
            else : c2='self.'+cond
            exec('a='+c2);#print 'cond',c2,a;
        if a or cond=='': return True
        return False  

    #************************ writeture du fichier GCG ***********************************
    def WriteGcgFile(self, Tbase,opt):
        f1 = self.CreateFile(opt+'gcg.dat','w')
        
        it, mxiter, isolve, ncrs, accl, cclose, iprgcg = zip(*Tbase['Solver'])[1]
        f1.write('%9i %9i %9i %9i\n' %(int(it),int(mxiter),int(isolve),int(ncrs)))
        f1.write('%9i %9.4e %9i\n' %(accl,cclose,int(iprgcg)))
        f1.close()  #fermer le fichier gcg

        #*************************** write RCT file for sorption *********************
    def WriteRctFile(self,aqui,Tbase,listE,opt):
        """ writes an RCT file in case of retardation """
        f1 = self.CreateFile(opt+'rct.dat','w')
        nrow = int(aqui.getFullGrid()['ny'])
        nlay = aqui.getNbCouches()
        if aqui.getDim() in ['Xsection','Radial']: nlay=nrow
        [aL,aT,aZ,rf] = zip(*Tbase['Transp'])[1]
        Isothm, Ireact,Irctop, Igetsc = 1,0,2,0
        f1.write('%9i %9i %9i %9i\n' %(Isothm, Ireact,Irctop, Igetsc))
        # Rec 2 : Rohb (2b and 2c not used here)
        poro = obj2matBlock(aqui,'Porosite');rhob = 2650.*(1.-poro);#print nlay,shape(poro),shape(rhob)
        for l in range(nlay):
            self.writeMatMT3D(rhob[l]*self.radfact,f1,'Rhob') # rhob matric(ncol,nrow) en kg/m3
        # line E3 sorption (isothm>0)
        Kd = (float(rf)-1.)*poro/rhob
        for l in range(nlay):
            self.writeMatMT3D(Kd[l],f1,'Kd')
        # line E4 2nd sorption coeff not used here
        for l in range(nlay): f1.write('         0  0.0 \n')
        f1.close()
            
        #*************************** write RCT file for 2domain *********************
    def WriteRct1File(self,aqui,Tbase,listE,opt):
        """ writes an RCT file in case of double porosity"""
        f1 = self.CreateFile(opt+'rct.dat','w')
        nlay = aqui.getNbCouches()
        if aqui.getDim() in ['Xsection','Radial']:
            nlay=nrow;nrow=1
        # Rec1 : Isothm, Ireact, Irctop, IGetsc Irctop 0
        # 2domain : Isothm : 5 dual domain( no sorption), igetsc>0 : initial conc read here
        Isothm, Ireact,Irctop, Igetsc = 5,0,1,1
        f1.write('%9i %9i %9i %9i\n' %(Isothm, Ireact,Irctop, Igetsc))
        # Rec 2 : Rohb do not enter if isothm=5
        # Rec3 Prsty2 only for dual domain (isothm 5 or 6)
        # the porosity matrix comes from Pht3D immobile solutions, line Imm_poro
        opt1=opt*1;
        if opt=='MT3D':opt1='Transport'
        mS=obj2matBlockNb(aqui,opt1,'zon');
        m0=mS[0]*0;imm_s=Tbase['Immobile']['Solutions']
        ie=imm_s['rows'].index('Imm_poro');
        for l in range(nlay):
            poro=m0+float(imm_s['data'][ie][1]) # data[1] backgrd
            for s in range(self.nsol-1):
                poro[abs(mS[l])/1000==s+1]=float(imm_s['data'][ie][s+2])
            self.writeMatMT3D(poro,f1,'Poro')
        # Rec4 : if Igetsc>0 initial conc in immob phase for each species 
        # run along the Chemistry to find the species for whic conc are needed
        short=['k','i','kim','p','e','s','kp'];ntot=0
        div=[1000,1000,1000,100,10,100,1]
        lon=['Solutions']*3;lon.extend(['Phases','Exchange','Surface','Phases'])
        for ik in range(len(short)):
            l0=listE[short[ik]]  # list of species present in chemistry
            for esp in l0:
                if esp in ['Imm_poro','Transf_coeff']: continue
                kw=lon[ik];imm=Tbase['Immobile'][kw].copy();ntot+=1
                ie=imm['rows'].index(esp);#print 'mtpht rct',kw,esp,ie
                for l in range(nlay):
                    cnc=m0+float(imm['data'][ie][1]);#print imm['data'][ie][1]
                    nsp=len(imm['cols'])-1
                    for s in range(nsp-1): # to find the place where BC is true solution
                        cnc[abs(mS[l])/div[ik]==s+1]=float(imm['data'][ie][s+2])
                    self.writeMatMT3D(cnc,f1,esp)
        # Rec 5 sorption1 (each species)
        for i in range(ntot): f1.write('        0  0.0 \n')
        # Rec6 sorption 2, here mass transfer coeff for all species
        ie=imm_s['rows'].index('Transf_coeff');
        for i in range(ntot):
            for l in range(nlay):
                tcoeff=m0+float(imm_s['data'][ie][1]) # data[1] backgrd
                for s in range(self.nsol-1): # to find the place where BC is true solution
                    tcoeff[abs(mS[l])/1000==s+1]=float(imm_s['data'][ie][s+2])
                self.writeMatMT3D(tcoeff,f1,'Transf Coeff')
        #REc7 RC1 parm for fisrt order deg1
        for i in range(ntot): f1.write('        0  0.0 \n')
        #REc8 RC2 parm for fisrt order deg 2
        for i in range(ntot): f1.write('        0  0.0 \n')
        f1.close()

    #********************************* Ecire fichier VDF for Seawat ********************
    def WriteVdfFile(self):
        f1 = self.CreateFile('Seawatvdf.dat','w')
##        1. MTDNCONC MFNADVFD NSWTCPL IWTABLE
##        Mtdconc=0 density specified =n dens calculated from n species
##        MFNADVFD=2 centre in sapce, ><2 upstream weigthed
##        NSWTCPL max number of non linear iterations if 0 or 1 explicit coupling
##        iwtable : 0 water table correction not applied, >0 applied
        Mtdnconc,Mfnadvdf,Nswtcpl,Iwtable=1,1,1,0
        f1.write(' %9i %9i %9i %9i   Mtdnconc Mfnadvdf Nswtcpl Iwtable \n' %(Mtdnconc,Mfnadvdf,Nswtcpl,Iwtable))
##        2. DENSEMIN DENSEMAX min an dmax density if 0 not limitation
        Densemin,Densemax=0,0
        f1.write(' %9i %9i   DENSEMIN DENSEMAX \n' %(Densemin,Densemax))
##        If NSWTCPL is greater than 1, then read item 3.
##        3. DNSCRIT convergene criterion difference in density
        Dnscrit=1e-3
        if Nswtcpl>1: f1.write(' %9.4e  \n' %Dnscrit)
##        4. DENSEREF DENSESLP
        Denseref,Denseslp=1000.,.7143 # Care in kg/m3, slp for freash and sea water
        f1.write(' %9i %9i  DENSEREF DENSESLP \n' %(Denseref,Denseslp))
##        5. FIRSTDT ength of first time step
        Firstdt=1e-3
        f1.write(' %9.4e  \n' %Firstdt)
##        FOR EACH STRESS PERIOD (read items 6 and 7 only if MTDNCONC = 0)
##        6. INDENSE if<0 val of dense reused form prev tstep
##          =0 Dense=ref >=1 dense read from item 7 =2 read from 7 but as conc
##        Read item 7 only if INDENSE is greater than zero
##        7. [DENSE(NCOL,NROW)] – U2DREL
##        Item 7 is read for each layer in the grid.
        nper=len(self.tlist);Indense=-1
        for ip in range(nper):
            if Mtdnconc==0: f1.write(' %9i %9i  INDENSE \n' %Indense)
        f1.close()

    #********************************* Ecire fichier Pht3d ********************
    def WritePht3dFile(self,aqui,Tbase,listE,parmk):
        f1 = self.CreateFile('PHT3D_ph.dat','w')
        #PH1 Record: OS TMP_LOC RED_MOD TEMP ASBIN EPS_AQU EPS_PH PACK_SZ
        # OS 1 iterative, 2 sequential. que 2 implemente
        # TMP_LOC : 0 writere dans temp, 1 : writere sur dir local
        # REd mode : 0 pH pe vairables, 1 : pe fixe, 2 : pH et pe fixes (plus rapide)
        # TEmp temperature, ASBIN : 0 : writeture fich binaire, 1 :ascii
        # eps_aqu et eps_ph : si 0 calcul partout
        # pack_sz : taille des paquets pour phreeqc 4000 chiffre OK
        temp=Tbase['PHparm'][0][1]
        os0, tmp, fix0, asbin, eps0, eps1, pack = 2,1,0,0,1e-10,.001,2000
        f1.write('%9i %9i %9i %9.1f %9i %9.1e %9.5f %9i\n' %(os0,tmp,fix0,temp,asbin,eps0,eps1,pack))
        dcharge=Tbase['PHparm'][1][1]
        f1.write('%9i\n' %dcharge)# PH2 v2 diif de charge admissibe
        # determiner le noimbre d'esp cinetiques et en faire la liste
        nInorg=len(listE['i']); #+len(self.lists);
        nKmob = len(listE['k']);nKimob = len(listE['kim']);
        nMinx= len(listE['p']);nExch=len(listE['e'])
        f1.write('%9i\n' %(nInorg))# PH3 nb compose inorganiques
        f1.write('%9i\n' %(nMinx))# PH4 nb mineraux
        f1.write('%9i %9i\n' %(nExch, 0))# PH5 nb ech ions, 0 je sais pas pourquoi
        # PH6 surface complexation 
        nSurf=len(listE['s']);f1.write('%9i\n' %nSurf)
        #PH7 Record: NR_MOB_KIN NR_MIN_KIN NR_SURF_KIN NR_IMOB_KIN
        # nb especes cinetiques mobiles, minerales, surfaces et substeps pour plus tard
        nKsurf,nKmin = 0,len(listE['kp'])
        f1.write('%9i %9i %9i %9i\n' %(nKmob, nKmin, nKsurf, nKimob))
        # PH8 : NR_OUTP_SPEC (complexes) PR_ALKALINITY_FLAG (futur)
        f1.write('%9i %9i\n' %(0,0))
        ## nb unites inutile car pht3d considere que tout est en jour
        Chem=Tbase['Chemistry']
        if Chem.has_key('Rates'):
            rates=Chem['Rates'];
            for nom in listE['k']:
                iek = rates['rows'].index(nom);
                f1.write(nom+'%5i \n '%(parmk[nom]))  #param k
                for ip in range(parmk[nom]):
                    f1.write('%9.5e \n' %float(rates['data'][iek][ip+2]))
                f1.write('-formula '+rates['data'][iek][-1] +'\n') # formula
        #for n in self.lists: f1.write(n+' \n') #  species
        optsu=Tbase['PHparm'][2][1];
        for n in listE['i']:
            add='';
            if optsu.strip()==n: add=' charge'
            f1.write(n.replace('(+','(')+add+'\n') # que reac isntant et AE, pH pe
        # kinetic immobile
        if Chem.has_key('Rates'):
            rates=Chem['Rates'];
            for nom in listE['kim']:
                iek = rates['rows'].index(nom);
                f1.write(nom+'%5i \n '%(parmk[nom]))  #param k
                for ip in range(parmk[nom]):
                    f1.write('%9.5e \n' %float(rates['data'][iek][ip+2]))
                f1.write('-formula '+rates['data'][iek][-1] +'\n') # formula
        for p in listE['p']:
            ip=Chem['Phases']['rows'].index(p)
            f1.write(p+'  '+str(Chem['Phases']['data'][ip][1])+' \n') # phase name + SI backgrd
        for n in listE['e']: f1.write(n+' -1 \n') # exchanger
        if Chem.has_key('Surface'): # surface
            su=Chem['Surface'];l=len(su['cols'])
            for esp in listE['s']:
                st=esp;ies=su['rows'].index(esp)
                for i in range(l-2,l): st+=' '+str(su['data'][ies][i])
                f1.write(st+' \n') 
            optsu=Tbase['PHparm'][3][1]
            if optsu in ['no_edl','diffuse_layer']: f1.write('-'+optsu+'\n')
        if Chem.has_key('Kinetic_Minerals'):
            kp=Chem['Kinetic_Minerals']
            for nom in listE['kp']:
                iek = kp['rows'].index(nom);
                f1.write(nom+'%5i \n '%(parmk[nom]))  #param k
                for ip in range(parmk[nom]):
                    f1.write('%9.5e \n' %float(kp['data'][iek][ip+1]))
        f1.close()

    #  ''''''''''''''''''''''''''''''' fonction writeMatMT3D '''''''''''''''''''''''''''
    def writeVecMT3D(self, v, f1, name=' '):
        l = len(v);a=str(type(v[0]))
        if a[13:16]=='int': typ='I'
        else : typ='G'
        if amin(v)==amax(v):
            f1.write('         0 %7.3e  #'%(amin(v)) +name+'\n')
            return
        if typ=='I': fmt='      100    1      ('+str(l)+'I'+str(ln)+')'
        else : fmt='      100    1.0      ('+str(l)+'G12.4)'            
        f1.write(fmt)
        f1.write('\n')
        
        if typ=='I': fmt='%'+str(ln)+'i'
        else : fmt='%+11.4e '
        for i in range(l):
            f1.write(fmt %v[i])
        f1.write('\n')
        
    def writeMatMT3D(self,m,f1,name=' '):
        if len(shape(m))<=1: return self.writeVecMT3D(m,f1,name)
        [l,c] = shape(m);ln=3;a=str(type(m[0,0]))
        if a[13:16]=='int': typ='I'
        else : typ='G'
        if amin(amin(m))==amax(amax(m)):
            if typ=='I':f1.write('         0 %8i #'%(amin(amin(m))) +name[:6]+'\n' )
            else:f1.write('         0 %7.3e #' %(amin(amin(m))) +name[:6]+'\n' )
            return
        if typ=='I': fmt='      100    1      ('+str(c)+'I'+str(ln)+')'
        else : fmt='      100    1.0      ('+str(c)+'G12.4) #'+name[:6]          
        f1.write(fmt+'\n')
        
        if typ=='I': fmt='%'+str(ln)+'i'
        else : fmt='%11.4e '         
        for i in range(l-1,-1,-1):
            for j in range(c):
                f1.write(fmt %m[i][j])
            f1.write('\n')
        
    def writeBlockMT3D(self,m,f1,name=' '):
        if len(shape(m))==3:
            nlay,a,b=shape(m)
            for l in range(nlay): self.writeMatMT3D(m[l],f1,name)
        else : self.writeMatMT3D(m,f1,name)

    def WritePhreeqc(self,aqui,Tbase,listE):
        """this routine writes a phreeqc file where all solutions are written in
        phreqc format to be able to test their equilibrium before running pht3d
        1. tabke background, then cycle through pht3d zones
        2. get the solution number, phase number...it does not take rates
        3 write them in phreeqc format"""
        f1 = self.CreateFile('solutions.phrq','w')
        f1.write('Database '+self.pPath+'\pht3d_datab.dat \n')
        zones=aqui.getZoneList('PHT3D')
        nzone=len(zones)
        for i in range(nzone):
            z=zones[i];val=z.getVal()
            if type(val)==type([5]): val=int(val[0].split()[1]) #case of transient chemistry
            else : val=int(val)
            f1.write('Solution '+str(i)+' \n units mol/L \n')
            solu=Tbase['Chemistry']['Solutions'];
            nsol=val/1000
            for esp in listE['i']: # go through phase list
                ie=solu['rows'].index(esp);#print esp,phases['rows'],ip,phases['data'][ip] # index of the phase
                conc=solu['data'][ie][nsol+1] #backgr concentration of species
                f1.write(esp+' '+str(conc)+'\n')
            f1.write('Equilibrium_Phases '+str(i)+'\n')
            phases=Tbase['Chemistry']['Phases'];
            nphas=mod(val,1000)/100
            for esp in listE['p']: # go through phase list
                ip=phases['rows'].index(esp);#print esp,phases['rows'],ip,phases['data'][ip] # index of the phase
                IS,conc=phases['data'][ip][nphas*2+1:nphas*2+3] #backgr SI and concentration of phase
                f1.write(esp+' '+str(IS)+' '+str(conc)+'\n')
            f1.write('end \n')
        f1.close()