• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TRI-AMDD / mpet / 8476080312

29 Mar 2024 01:46AM UTC coverage: 55.461% (-7.2%) from 62.648%
8476080312

Pull #126

github

d-cogswell
Adds a benchmark section to docs.
Pull Request #126: v1.0.0

2351 of 4239 relevant lines covered (55.46%)

2.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/mpet/plot/outmat2txt.py
1
"""This can be called to convert the default simulation output (.mat file) to csv files."""
2
import os
×
3

4
import numpy as np
×
5
import h5py
×
6

7
import mpet.plot.plot_data as plot_data
×
8
import mpet.utils as utils
×
9
from mpet.config import constants
×
10

11
# Strings to be used
12
RowsStr = "Rows correspond to time points (see generalData.txt).\n"
×
13
CCStr = "Columns correspond to cell center positions (see discData.txt)."
×
14
FCStr = "Columns correspond to face positions (see discData.txt)."
×
15
genDataHdr = ("Time [s], Filling fraction of anode, "
×
16
              + "Filling fraction of cathode, "
17
              + "Voltage [V], Current [C-rate], Current [A/m^2], "
18
              + "Power [W/m^2]")
19

20
zeroStr = "Zero is at the anode current collector."
×
21
dccpStr = "discretization cell center positions [m]. "
×
22
discCCbattery = ("Battery " + dccpStr + zeroStr)
×
23
discCCanode = ("Anode " + dccpStr + zeroStr)
×
24
discCCsep = ("Separator " + dccpStr + zeroStr)
×
25
discCCcathode = ("Cathode " + dccpStr + zeroStr)
×
26
discFC = ("Battery discretization face positions [m]. " + zeroStr)
×
27
particleIndxExpl = """
×
28
Particle output files are indexed such that Vol 0 is closest to the
29
anode current collector for both electrodes.  Indexing within volumes
30
is such that Part 0 is closest to the "carbon backbone" if simPartCond
31
was set to true for that electrode. Otherwise it is in arbitrary
32
order.
33
"""
34
particleDiscExpl = """
×
35
Particle discretization info follows.  Lengths and number of
36
discretization points are provided for each simulated particle.
37
Meshes are made as a linear space between zero and particle length
38
with the given number of points.  Rows correspond to different
39
simulation volumes with the first row being closest to the anode
40
current collector and the last closest to the cathode current
41
collector.  Columns represent individual particles within each
42
simulated volume in no particular order.
43
"""
44

45
elytecHdr = ("Electrolyte Concentrations [M]\n" + RowsStr + CCStr)
×
46
elytepHdr = ("Electrolyte Electric Potential [V]\n" + RowsStr + CCStr)
×
47
elyteiHdr = ("Electrolyte Current Density [A/m^2]\n" + RowsStr + FCStr)
×
48
elytediviHdr = ("Electrolyte Divergence of Current Density [A/m^3]\n"
×
49
                + RowsStr + CCStr)
50

51
seeDiscStr = "See discData.txt for particle indexing information."
×
52
partStr = "partTrode{l}vol{j}part{i}_"
×
53
solffStr = "Solid Filling Fractions"
×
54
solTail = ("\n" + RowsStr + CCStr + "\n" + seeDiscStr)
×
55
solHdr = (solffStr + solTail)
×
56
opStr = ", order parameter "
×
57
sol1Hdr = (solffStr + opStr + "1" + solTail)
×
58
sol2Hdr = (solffStr + opStr + "2" + solTail)
×
59
fnameSolL = "sld{l}Vol{j:03d}Part{i:03d}Conc"
×
60
fnameSolR = "Data.txt"
×
61
fnameSolBase = (fnameSolL + fnameSolR)
×
62
fnameSol1Base = (fnameSolL + "1" + fnameSolR)
×
63
fnameSol2Base = (fnameSolL + "2" + fnameSolR)
×
64

65
cbarHdrP1 = ("Average particle filling fractions.\n" + RowsStr)
×
66
cbarHdrP2 = """Columns correspond to particles specified by simulated
×
67
volume index / particle index within volume.
68
"""
69
cbarHdrBase = cbarHdrP1 + cbarHdrP2 + seeDiscStr + "\n"
×
70

71
bulkpHdrP2 = """Columns correspond to this electrode's cell center
×
72
positions (see discData.txt).
73
"""
74
bulkpHdr = ("Bulk electrode electric potential [V]\n" + RowsStr + bulkpHdrP2)
×
75
fnameBulkpBase = "bulkPot{l}Data.txt"
×
76

77
RowStrHdr1 = "First column corresponds to the cycle number.\n"
×
78
RowStrHdr2 = """Second, third and fourth columns respond to gravimetric charge capacity of limiting
×
79
electrode in mAh/g, gravimetric discharge capacity of limiting electrode in mAh/g, cycle
80
capacity fraction relative to original capacity, and cycle efficiency (discharge
81
capacity/charge capacity).\n"""
82
cyclerHdr = ("Cycling Data\n" + RowStrHdr1 + RowStrHdr2)
×
83
fnameCycleBase = "cycleData.txt"
×
84

85
RowStrHdr1Q = """Each (2*i,2*i+1) row represents the (V(t), Q(t)) in cycle i in units of
×
86
(V, Ah/m^2).\n"""
87
vQCyclerHdr = ("Voltage/Capacity Cycling Data\n" + RowStrHdr1Q)
×
88

89
RowStrHdr2Q = """Each (2*i,2*i+1) row represents the (V(t), dQ(t)dV) in cycle i in units of
×
90
(V, Ah/m^2).\n"""
91
vdQCyclerHdr = ("Voltage/dQ Cycling Data\n" + RowStrHdr2Q)
×
92

93

94
def main(indir, genData=True, discData=True, elyteData=True,
×
95
         csldData=True, cbarData=True, bulkpData=True):
96
    config = plot_data.show_data(
×
97
        indir, plot_type="params", print_flag=False, save_flag=False,
98
        data_only=True, color_changes=None, smooth_type=None)
99
    trodes = config["trodes"]
×
100
    CrateCurr = config["1C_current_density"]  # A/m^2
×
101
    psd_len_c = config["psd_len"]["c"]
×
102
    totalCycle = config["totalCycle"]
×
103
    Nv_c, Np_c = psd_len_c.shape
×
104
    dlm = ","
×
105

106
    def get_trode_str(tr):
×
107
        return ("Anode" if tr == "a" else "Cathode")
×
108
    if "a" in trodes:
×
109
        psd_len_a = config["psd_len"]["a"]
×
110
        Nv_a, Np_a = psd_len_a.shape
×
111
    tVec, vVec = plot_data.show_data(
×
112
        indir, plot_type="vt", print_flag=False, save_flag=False,
113
        data_only=True, color_changes=None, smooth_type=None)
114
    ntimes = len(tVec)
×
115

116
    if genData:
×
117
        ffVec_c = plot_data.show_data(
×
118
            indir, plot_type="soc_c", print_flag=False,
119
            save_flag=False, data_only=True, color_changes=None, smooth_type=None)[1]
120
        if "a" in trodes:
×
121
            ffVec_a = plot_data.show_data(
×
122
                indir, plot_type="soc_a", print_flag=False,
123
                save_flag=False, data_only=True, color_changes=None, smooth_type=None)[1]
124
        else:
125
            ffVec_a = np.ones(len(tVec))
×
126
        currVec = plot_data.show_data(
×
127
            indir, plot_type="curr", print_flag=False,
128
            save_flag=False, data_only=True, color_changes=None, smooth_type=None)[1]
129
        powerVec = plot_data.show_data(
×
130
            indir, plot_type="power", print_flag=False,
131
            save_flag=False, data_only=True, color_changes=None, smooth_type=None)[1]
132
        genMat = np.zeros((ntimes, 7))
×
133
        genMat[:,0] = tVec
×
134
        genMat[:,1] = ffVec_a
×
135
        genMat[:,2] = ffVec_c
×
136
        genMat[:,3] = vVec
×
137
        genMat[:,4] = currVec
×
138
        genMat[:,5] = currVec * CrateCurr
×
139
        genMat[:,6] = powerVec
×
140
        np.savetxt(os.path.join(indir, "generalData.txt"),
×
141
                   genMat, delimiter=dlm, header=genDataHdr)
142

143
    if discData:
×
144
        cellCentersVec, facesVec = plot_data.show_data(
×
145
            indir, plot_type="discData", print_flag=False,
146
            save_flag=False, data_only=True, color_changes=None, smooth_type=None)
147
        with open(os.path.join(indir, "discData.txt"), "w") as fo:
×
148
            print(discCCbattery, file=fo)
×
149
            print(",".join(map(str, cellCentersVec)), file=fo)
×
150
            offset = 0
×
151
            if "a" in trodes:
×
152
                print(file=fo)
×
153
                print(discCCanode, file=fo)
×
154
                print(",".join(map(str, cellCentersVec[:Nv_a])), file=fo)
×
155
                offset = Nv_a
×
156
            print(file=fo)
×
157
            print(discCCsep, file=fo)
×
158
            print(",".join(map(str, cellCentersVec[offset:-Nv_c])), file=fo)
×
159
            print(file=fo)
×
160
            print(discCCcathode, file=fo)
×
161
            print(",".join(map(str, cellCentersVec[-Nv_c:])), file=fo)
×
162
            print(file=fo)
×
163
            print(discFC, file=fo)
×
164
            print(",".join(map(str, facesVec)), file=fo)
×
165
            print(file=fo)
×
166
            print(particleIndxExpl, file=fo)
×
167
            print(particleDiscExpl, file=fo)
×
168
            for tr in trodes:
×
169
                print(file=fo)
×
170
                Trode = get_trode_str(tr)
×
171
                print((Trode + " particle sizes [m]"), file=fo)
×
172
                for vind in range(config["Nvol"][tr]):
×
173
                    print(",".join(map(str, config["psd_len"][tr][vind,:])), file=fo)
×
174
                print("\n" + Trode + " particle number of discr. points", file=fo)
×
175
                for vind in range(config["Nvol"][tr]):
×
176
                    print(",".join(map(str, config["psd_num"][tr][vind,:])), file=fo)
×
177

178
    if elyteData:
×
179
        valid_current = True
×
180
        # If there wasn't an electrolyte, then a ghost point variable wouldn't have been created,
181
        # so we'll get a KeyError in attempting to "plot" the electrolyte current density.
182
        try:
×
183
            plot_data.show_data(
×
184
                indir, plot_type="elytei", print_flag=False, save_flag=False, data_only=True,
185
                color_changes=None, smooth_type=None)
186
        except KeyError:
×
187
            valid_current = False
×
188
        elytecMat = plot_data.show_data(
×
189
            indir, plot_type="elytec", print_flag=False,
190
            save_flag=False, data_only=True, color_changes=None, smooth_type=None)[1]
191
        elytepMat = plot_data.show_data(
×
192
            indir, plot_type="elytep", print_flag=False,
193
            save_flag=False, data_only=True, color_changes=None, smooth_type=None)[1]
194
        np.savetxt(os.path.join(indir, "elyteConcData.txt"),
×
195
                   elytecMat, delimiter=dlm, header=elytecHdr)
196
        np.savetxt(os.path.join(indir, "elytePotData.txt"),
×
197
                   elytepMat, delimiter=dlm, header=elytepHdr)
198
        if valid_current:
×
199
            elyteiMat = plot_data.show_data(
×
200
                indir, plot_type="elytei", print_flag=False,
201
                save_flag=False, data_only=True, color_changes=None, smooth_type=None)[1]
202
            elytediviMat = plot_data.show_data(
×
203
                indir, plot_type="elytedivi", print_flag=False,
204
                save_flag=False, data_only=True, color_changes=None, smooth_type=None)[1]
205
            np.savetxt(os.path.join(indir, "elyteCurrDensData.txt"),
×
206
                       elyteiMat, delimiter=dlm, header=elyteiHdr)
207
            np.savetxt(os.path.join(indir, "elyteDivCurrDensData.txt"),
×
208
                       elytediviMat, delimiter=dlm, header=elytediviHdr)
209

210
    if csldData:
×
211
        dataFileName = "output_data"
×
212
        dataFile = os.path.join(indir, dataFileName)
×
213
        data = utils.open_data_file(dataFile)
×
214
        for tr in trodes:
×
215
            Trode = get_trode_str(tr)
×
216
            type2c = False
×
217
            if config[tr, "type"] in constants.one_var_types:
×
218
                str_base = partStr + "c"
×
219
            elif config[tr, "type"] in constants.two_var_types:
×
220
                type2c = True
×
221
                str1_base = partStr + "c1"
×
222
                str2_base = partStr + "c2"
×
223
            for i in range(config["Npart"][tr]):
×
224
                for j in range(config["Nvol"][tr]):
×
225
                    if type2c:
×
226
                        sol1 = str1_base.format(l=tr, i=i, j=j)
×
227
                        sol2 = str2_base.format(l=tr, i=i, j=j)
×
228
                        datay1 = utils.get_dict_key(data, sol1)
×
229
                        datay2 = utils.get_dict_key(data, sol2)
×
230
                        filename1 = fnameSol1Base.format(l=Trode, i=i, j=j)
×
231
                        filename2 = fnameSol2Base.format(l=Trode, i=i, j=j)
×
232
                        np.savetxt(os.path.join(indir, filename1), datay1,
×
233
                                   delimiter=dlm, header=sol1Hdr)
234
                        np.savetxt(os.path.join(indir, filename2), datay2,
×
235
                                   delimiter=dlm, header=sol2Hdr)
236
                    else:
237
                        sol = str_base.format(l=tr, i=i, j=j)
×
238
                        datay = utils.get_dict_key(data, sol)
×
239
                        filename = fnameSolBase.format(l=Trode, i=i, j=j)
×
240
                        np.savetxt(os.path.join(indir, filename), datay,
×
241
                                   delimiter=dlm, header=solHdr)
242

243
        # close file if it is a h5py file
244
        if isinstance(data, h5py._hl.files.File):
×
245
            data.close()
×
246

247
    if cbarData:
×
248
        cbarDict = plot_data.show_data(
×
249
            indir, plot_type="cbar_full", print_flag=False,
250
            save_flag=False, data_only=True, color_changes='discrete', smooth_type=None)
251
        for tr in trodes:
×
252
            Trode = get_trode_str(tr)
×
253
            fname = "cbar{l}Data.txt".format(l=Trode)
×
254
            Nv, Np = config["Nvol"][tr], config["Npart"][tr]
×
255
            NpartTot = Nv*Np
×
256
            cbarMat = np.zeros((ntimes, NpartTot))
×
257
            cbarHdr = cbarHdrBase
×
258
            partInd = 0
×
259
            for i in range(Nv):
×
260
                for j in range(Np):
×
261
                    cbarHdr += "{i}/{j},".format(j=j, i=i)
×
262
                    cbarMat[:,partInd] = cbarDict[tr][:,i,j]
×
263
                    partInd += 1
×
264
            np.savetxt(os.path.join(indir, fname), cbarMat,
×
265
                       delimiter=dlm, header=cbarHdr.rstrip(','))
266

267
    if bulkpData:
×
268
        if "a" in trodes:
×
269
            bulkp_aData = plot_data.show_data(
×
270
                indir, plot_type="bulkp_a", print_flag=False,
271
                save_flag=False, data_only=True, color_changes=None, smooth_type=None)[1]
272
            fname = fnameBulkpBase.format(l="Anode")
×
273
            np.savetxt(os.path.join(indir, fname), bulkp_aData,
×
274
                       delimiter=dlm, header=bulkpHdr)
275
        bulkp_cData = plot_data.show_data(
×
276
            indir, plot_type="bulkp_c", print_flag=False,
277
            save_flag=False, data_only=True, color_changes=None, smooth_type=None)[1]
278
        fname = fnameBulkpBase.format(l="Cathode")
×
279
        np.savetxt(os.path.join(indir, fname), bulkp_cData,
×
280
                   delimiter=dlm, header=bulkpHdr)
281

282
    if totalCycle > 1:
×
283
        # save general cycle data
284
        cycNum, cycleCapacityCh, cycleCapacityDisch = plot_data.show_data(
×
285
            indir, plot_type="cycle_capacity", print_flag=False, save_flag=False,
286
            data_only=True)
287
        cycleCapFrac = plot_data.show_data(
×
288
            indir, plot_type="cycle_cap_frac", print_flag=False,
289
            save_flag=False, data_only=True)[1]
290
        cycleEfficiency = plot_data.show_data(
×
291
            indir, plot_type="cycle_efficiency", print_flag=False,
292
            save_flag=False, data_only=True)[1]
293
        genMat = np.zeros((len(cycNum), 5))
×
294
        genMat[:,0] = cycNum
×
295
        genMat[:,1] = cycleCapacityCh
×
296
        genMat[:,2] = cycleCapacityDisch
×
297
        genMat[:,3] = cycleCapFrac
×
298
        genMat[:,4] = cycleEfficiency
×
299
        np.savetxt(os.path.join(indir, fnameCycleBase), genMat, delimiter=dlm,
×
300
                   header=cyclerHdr)
301

302
        # save QV and dQdV data
303
        voltCycle, capCycle = plot_data.show_data(
×
304
            indir, plot_type="cycle_Q_V", print_flag=False, save_flag=False,
305
            data_only=True)
306
        fname = "QVCycle.txt"
×
307
        genMat = np.zeros((voltCycle.shape[0]*2, voltCycle.shape[1]))
×
308
        genMat[:voltCycle.shape[0],:] = voltCycle
×
309
        genMat[voltCycle.shape[0]:voltCycle.shape[0]*2,:] = capCycle
×
310
        np.savetxt(os.path.join(indir, fname), genMat, delimiter=dlm,
×
311
                   header=vQCyclerHdr)
312

313
        voltCycle, dQdVCycle = plot_data.show_data(
×
314
            indir, plot_type="cycle_dQ_dV", print_flag=False, save_flag=False,
315
            data_only=True)
316
        fname = "dQdVCycle.txt"
×
317
        genMat = np.zeros((voltCycle.shape[0]*2, voltCycle.shape[1]))
×
318
        genMat[:voltCycle.shape[0],:] = voltCycle
×
319
        genMat[voltCycle.shape[0]:voltCycle.shape[0]*2,:] = dQdVCycle
×
320
        np.savetxt(os.path.join(indir, fname), genMat, delimiter=dlm,
×
321
                   header=vdQCyclerHdr)
322

323
        # close file if it is a h5py file
324
        if isinstance(data, h5py._hl.files.File):
×
325
            data.close()
×
326

327
    return
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc