IR_PrintVisualizationSWE.scala 12.4 KB
Newer Older
1
2
package exastencils.applications.swe.ir

3
import scala.collection.immutable.ListMap
4
5
import scala.collection.mutable.ListBuffer

6
7
import exastencils.base.ir.IR_ArrayAccess
import exastencils.base.ir.IR_Assignment
8
9
import exastencils.base.ir.IR_Comment
import exastencils.base.ir.IR_ConstIndex
10
import exastencils.base.ir.IR_Expression
11
12
import exastencils.base.ir.IR_ExpressionIndex
import exastencils.base.ir.IR_ForLoop
13
import exastencils.base.ir.IR_IfCondition
14
import exastencils.base.ir.IR_ImplicitConversion._
15
import exastencils.base.ir.IR_Index
16
import exastencils.base.ir.IR_PointerDatatype
17
import exastencils.base.ir.IR_PreIncrement
18
import exastencils.base.ir.IR_SpecialDatatype
19
import exastencils.base.ir.IR_Statement
20
import exastencils.base.ir.IR_StringConstant
21
22
import exastencils.base.ir.IR_VariableAccess
import exastencils.base.ir.IR_VariableDeclaration
23
import exastencils.baseExt.ir.IR_ExpressionIndexRange
24
import exastencils.baseExt.ir.IR_LoopOverDimensions
25
import exastencils.baseExt.ir.IR_LoopOverFragments
26
27
import exastencils.config.Knowledge
import exastencils.core.Duplicate
28
import exastencils.domain.ir.IR_IV_IsValidForDomain
29
30
31
32
import exastencils.field.ir.IR_Field
import exastencils.field.ir.IR_FieldAccess
import exastencils.field.ir.IR_FieldCollection
import exastencils.field.ir.IR_IV_ActiveSlot
33
import exastencils.grid.ir.IR_AtNode
34
import exastencils.grid.ir.IR_VF_NodePositionAsVec
35
import exastencils.io.ir.IR_AccessPattern
36
import exastencils.io.ir.IR_DataBuffer
37
import exastencils.io.ir.IR_IV_TemporaryBuffer
38
39
40
41
import exastencils.logger.Logger
import exastencils.util.ir.IR_Print
import exastencils.visualization.ir.IR_PrintVisualizationTriangles

42
trait IR_PrintVisualizationSWE extends IR_PrintVisualizationTriangles {
43
44
  def numDimsGrid = 2

45
46
  def numCells_x : Int = etaDiscLower0.layout.layoutsPerDim(0).numInnerLayers
  def numCells_y : Int = etaDiscLower0.layout.layoutsPerDim(1).numInnerLayers
47
  def numCells_z = 1
48
  def numCellsPerFrag : IR_Expression = 2 * numCells_x * numCells_y * numCells_z
49

50
  override def dimsPositionsFrag : ListBuffer[IR_Expression] = if (Knowledge.swe_nodalReductionPrint) ListBuffer(numCells_x+1, numCells_y+1) else ListBuffer(6, numCells_x, numCells_y)
51

52
53
54
  // passed as arguments to function
  def discFieldCollection : ListBuffer[ListBuffer[IR_Field]]
  def nodalFieldCollection : ListBuffer[IR_Field]
55

56
57
  def nodalFields : ListMap[String, IR_Field] = ListMap(
    nodalFieldCollection.map(field => field.name -> field) : _*)
58
  def discFields : ListMap[String, ListBuffer[IR_Field]] = ListMap(
59
    discFieldCollection.map(discField => getBasenameDiscField(discField) -> discField) : _*)
60
61
62
  def discFieldsReduced : ListMap[String, IR_IV_TemporaryBuffer] = discFields.map { discField =>
    discField._1 -> IR_IV_TemporaryBuffer(discField._2.head.resolveBaseDatatype, IR_AtNode, discField._1, domainIndex, dimsPositionsFrag)
  }
63

64
  def etaDiscLower0 : IR_Field = IR_FieldCollection.getByIdentifier("etaDiscLower0", level).get
65
  def someCellField : IR_Field = etaDiscLower0
66

67
68
  def fields : ListMap[String, ListBuffer[IR_Field]] = nodalFields.map(field => field._1 -> ListBuffer(field._2)) ++ discFields
  def fieldnames : ListBuffer[String] = fields.keys.to[ListBuffer]
69
  def numFields : Int = fieldnames.length
70

71
72
  def nodePosVecAsDataBuffers(accessIndices: Option[ListBuffer[IR_Index]], datasets: Option[ListBuffer[IR_Expression]]) : ListBuffer[IR_DataBuffer] = {
    (0 until numDimsGrid).map(dim =>
73
      IR_DataBuffer(IR_VF_NodePositionAsVec.find(level).associatedField, accessIndices, if (datasets.isDefined) Some(datasets.get(dim)) else None, dim, canonicalFileLayout)
74
    ).to[ListBuffer]
75
  }
76

77
78
  // get the common prefix of a disc field and use as name (e.g. etaDiscLower0, etaDiscLower1, ... -> etaDisc)
  def getBasenameDiscField(discField : ListBuffer[IR_Field]) : String = {
79
80
81
82
83
84
    val basename = discField.map(_.name).reduce((a, b) => (a zip b).takeWhile(Function.tupled(_ == _)).map(_._1).mkString)
    if (basename.isEmpty) {
      Logger.error("\"IR_PrintVisualizationSWE:\" Could not extract a common name from disc field components. Components do not belong to the same disc field.")
    }

    basename
85
  }
86

87
88
89
90
91
92
93
94
  // access pattern dependent on reduction mode for blockstructured meshes
  def accessIndices : Option[ListBuffer[IR_Index]]= if (Knowledge.swe_nodalReductionPrint)
    None
  else
    Some(nodeOffsets.map(_.toExpressionIndex))

  def nodalAccess(field : IR_Field) = IR_AccessPattern((idx : IR_Index) => IR_FieldAccess(field, IR_IV_ActiveSlot(field), idx.toExpressionIndex), accessIndices)

95
  // glue logic for disc fields to be mapped to data buffers
96
  def discFieldsToDatabuffers(discField : ListBuffer[IR_Field]) : ListBuffer[IR_DataBuffer] = ???
97

98
  // calculating an average over a disc field to reduce the amount of data written to file
99
  def setupReducedData : ListBuffer[IR_Statement] = {
100
101
    var stmts : ListBuffer[IR_Statement] = ListBuffer()

102
103
104
105
    // allocate buffers before calculation
    discFieldsReduced.values.foreach { tmpBuf =>
      stmts += tmpBuf.allocateMemory
    }
106
107
108

    // compute averages and store into buffer before writing
    var stmtsFragLoop : ListBuffer[IR_Statement] = ListBuffer()
109
110
111
    discFieldsReduced.values.foreach { tmpBuf =>
      stmtsFragLoop += IR_Comment(s"\n Nodal data reduction for ${tmpBuf.name} \n")
      stmtsFragLoop ++= reducedCellPrint(IR_VariableAccess(tmpBuf.name, tmpBuf.resolveDatatype()), discFields(tmpBuf.name))
112
113
114
    }

    stmts += IR_LoopOverFragments(
115
      IR_IfCondition(IR_IV_IsValidForDomain(domainIndex),
116
117
118
119
120
121
122
        stmtsFragLoop
      )
    )

    stmts
  }

123
  // nodal data reduction
124
  def reducedCellPrint(buf : IR_VariableAccess, discField : ListBuffer[IR_Field], indentation : Option[IR_StringConstant] = None) : ListBuffer[IR_Statement] = {
125

126
127
    val low : ListBuffer[IR_Field] = discField.take(3)
    val upp : ListBuffer[IR_Field] = discField.takeRight(3)
128

129
    if (discField.length != 6) {
130
      Logger.error("Wrong usage of \"addReducedNodePrint\" in IR_PrintVisualizationSWE.")
131
132
    }

133
    def getIdxNodalLoop(idx : IR_ExpressionIndex) : IR_Expression = IR_ExpressionIndexRange(
134
135
136
137
      IR_ExpressionIndex((0 until numDimsGrid).toArray.map(dim => etaDiscLower0.layout.idxById("IB", dim) - Duplicate(etaDiscLower0.referenceOffset(dim)) : IR_Expression)),
      IR_ExpressionIndex((0 until numDimsGrid).toArray.map(dim => 1 + etaDiscLower0.layout.idxById("IE", dim) - Duplicate(etaDiscLower0.referenceOffset(dim)) : IR_Expression))
    ).linearizeIndex(idx)

138
    def storeOperation(toStore : IR_Expression, idx : IR_ExpressionIndex) : IR_Statement = buf.datatype match {
139
      case IR_SpecialDatatype("std::ofstream") => IR_Print(buf,
140
        (if (indentation.isDefined) indentation.get :: Nil else Nil) :+ toStore :+ IR_Print.newline : _*)
141
      case IR_PointerDatatype(_) => IR_Assignment(IR_ArrayAccess(buf, numPointsPerFrag * IR_LoopOverFragments.defIt + getIdxNodalLoop(idx)), toStore)
142
    }
143
144
145
146
147
148
149
150
151

    def constructLoopForDim(dim : Int, offStart : Int, offEnd : Int, loopStmts : IR_Statement*) = IR_ForLoop(
      IR_VariableDeclaration(IR_LoopOverDimensions.defItForDim(dim), etaDiscLower0.layout.idxById("IB", dim) + offStart - Duplicate(etaDiscLower0.referenceOffset(dim))),
      IR_LoopOverDimensions.defItForDim(dim) < etaDiscLower0.layout.idxById("IE", dim) - offEnd - Duplicate(etaDiscLower0.referenceOffset(dim)),
      IR_PreIncrement(IR_LoopOverDimensions.defItForDim(dim)),
      loopStmts.to[ListBuffer])

    var statementsFragLoop : ListBuffer[IR_Statement] = ListBuffer()

152
153
154
155
156
157
158
159
160
161
162
163
    // expression indices for the edges
    val baseIdx_edgeLower = IR_ExpressionIndex(IR_LoopOverDimensions.defItForDim(0), 0)
    val baseIdx_edgeLeft  = IR_ExpressionIndex(0, IR_LoopOverDimensions.defItForDim(1))
    val baseIdx_edgeRight = IR_ExpressionIndex(someCellField.layout.layoutsPerDim(0).numInnerLayers, IR_LoopOverDimensions.defItForDim(1))
    val baseIdx_edgeUpper = IR_ExpressionIndex(IR_LoopOverDimensions.defItForDim(0), someCellField.layout.layoutsPerDim(1).numInnerLayers)

    // expression indices for the corners
    val baseIdx_cornerLL = IR_ExpressionIndex(0, 0)
    val baseIdx_cornerLR = IR_ExpressionIndex(low(1).layout.layoutsPerDim(0).numInnerLayers, 0)
    val baseIdx_cornerUL = IR_ExpressionIndex(0, low(2).layout.layoutsPerDim(1).numInnerLayers)
    val baseIdx_cornerUR = IR_ExpressionIndex((0 until numDimsGrid).map(d => someCellField.layout.layoutsPerDim(d).numInnerLayers).toArray)

164
    statementsFragLoop += IR_Comment("lower left corner: vertex contained by 1 triangle")
165
166
167
    statementsFragLoop += storeOperation(
      IR_FieldAccess(low(0), IR_IV_ActiveSlot(low(0)), baseIdx_cornerLL),
      baseIdx_cornerLL)
168
169
170

    statementsFragLoop += IR_Comment("lowermost row w/o corners: vertex contained by 3 triangles")
    statementsFragLoop += constructLoopForDim(dim = 0, offStart = 1, offEnd = 0,
171
172
173
174
175
      storeOperation(
        (IR_FieldAccess(low(0), IR_IV_ActiveSlot(low(0)), baseIdx_edgeLower) +
          IR_FieldAccess(low(1), IR_IV_ActiveSlot(low(1)), baseIdx_edgeLower + IR_ConstIndex(-1, 0)) +
          IR_FieldAccess(upp(2), IR_IV_ActiveSlot(upp(2)), baseIdx_edgeLower + IR_ConstIndex(-1, 0))) / 3.0,
        baseIdx_edgeLower))
176
177

    statementsFragLoop += IR_Comment("lower right corner: vertex contained by 2 triangles")
178
179
180
181
    statementsFragLoop += storeOperation(
      (IR_FieldAccess(low(1), IR_IV_ActiveSlot(low(1)), baseIdx_cornerLR + IR_ConstIndex(-1, 0)) +
        IR_FieldAccess(upp(2), IR_IV_ActiveSlot(upp(2)), baseIdx_cornerLR + IR_ConstIndex(-1, 0))) / 2.0,
      baseIdx_cornerLR)
182
183
184
185

    statementsFragLoop += IR_Comment("inner rows")
    statementsFragLoop += constructLoopForDim(dim = 1, offStart = 1, offEnd = 0,
      IR_Comment("leftmost column: vertex contained by 3 triangles"),
186
187
188
189
190
      storeOperation(
        (IR_FieldAccess(low(0), IR_IV_ActiveSlot(low(0)), baseIdx_edgeLeft) +
          IR_FieldAccess(low(2), IR_IV_ActiveSlot(low(2)), baseIdx_edgeLeft + IR_ConstIndex(0, -1)) +
          IR_FieldAccess(upp(1), IR_IV_ActiveSlot(upp(1)), baseIdx_edgeLeft + IR_ConstIndex(0, -1))) / 3.0,
        baseIdx_edgeLeft),
191
192
      IR_Comment("inner points: vertex contained by 6 triangles"),
      constructLoopForDim(dim = 0, offStart = 1, offEnd = 0,
193
        storeOperation(
194
195
196
197
198
199
          (IR_FieldAccess(low(0), IR_IV_ActiveSlot(low(0)), IR_LoopOverDimensions.defIt(numDimsGrid)) +
            IR_FieldAccess(low(1), IR_IV_ActiveSlot(low(1)), IR_LoopOverDimensions.defIt(numDimsGrid) + IR_ConstIndex(-1, 0)) +
            IR_FieldAccess(upp(2), IR_IV_ActiveSlot(upp(2)), IR_LoopOverDimensions.defIt(numDimsGrid) + IR_ConstIndex(-1, 0)) +
            IR_FieldAccess(low(2), IR_IV_ActiveSlot(low(2)), IR_LoopOverDimensions.defIt(numDimsGrid) + IR_ConstIndex(0, -1)) +
            IR_FieldAccess(upp(1), IR_IV_ActiveSlot(upp(1)), IR_LoopOverDimensions.defIt(numDimsGrid) + IR_ConstIndex(0, -1)) +
            IR_FieldAccess(upp(0), IR_IV_ActiveSlot(upp(0)), IR_LoopOverDimensions.defIt(numDimsGrid) + IR_ConstIndex(-1, -1))) / 6.0,
200
          IR_LoopOverDimensions.defIt(numDimsGrid))),
201
      IR_Comment("rightmost column: vertex contained by 3 triangles"),
202
203
204
205
206
      storeOperation(
        (IR_FieldAccess(upp(0), IR_IV_ActiveSlot(upp(0)), baseIdx_edgeRight + IR_ConstIndex(-1, -1)) +
          IR_FieldAccess(low(1), IR_IV_ActiveSlot(low(1)), baseIdx_edgeRight + IR_ConstIndex(-1, 0)) +
          IR_FieldAccess(upp(2), IR_IV_ActiveSlot(upp(2)), baseIdx_edgeRight + IR_ConstIndex(-1, 0))) / 3.0,
        baseIdx_edgeRight)
207
208
209
    )

    statementsFragLoop += IR_Comment("upper left corner: vertex contained by 2 triangles")
210
211
212
213
    statementsFragLoop += storeOperation(
      (IR_FieldAccess(low(2), IR_IV_ActiveSlot(low(2)), baseIdx_cornerUL + IR_ConstIndex(0, -1)) +
        IR_FieldAccess(upp(1), IR_IV_ActiveSlot(upp(1)), baseIdx_cornerUL + IR_ConstIndex(0, -1))) / 2.0,
      baseIdx_cornerUL)
214
215
216

    statementsFragLoop += IR_Comment("uppermost row w/o corners: vertex contained by 3 triangles")
    statementsFragLoop += constructLoopForDim(dim = 0, offStart = 1, offEnd = 0,
217
218
219
220
221
      storeOperation(
        (IR_FieldAccess(upp(0), IR_IV_ActiveSlot(upp(0)), baseIdx_edgeUpper + IR_ConstIndex(-1, -1)) +
          IR_FieldAccess(low(2), IR_IV_ActiveSlot(low(2)), baseIdx_edgeUpper + IR_ConstIndex(0, -1)) +
          IR_FieldAccess(upp(1), IR_IV_ActiveSlot(upp(1)), baseIdx_edgeUpper + IR_ConstIndex(0, -1))) / 3.0,
        baseIdx_edgeUpper))
222
223

    statementsFragLoop += IR_Comment("upper right corner: vertex contained by 1 triangle")
224
225
226
    statementsFragLoop += storeOperation(
      IR_FieldAccess(upp(0), IR_IV_ActiveSlot(upp(0)), baseIdx_cornerUR + IR_ConstIndex(-1, -1)),
      baseIdx_cornerUR)
227
228
229
230

    statementsFragLoop
  }
}