Pre/Post deep learning
Some deep learning workflow applied to physics contexts require the projection of fields defined on an unstructured mesh onto a rectilinear grid, and inversely.
The mesh and solution associated to a previously computed flow field is read (see also Fig. 2, top-left image):
1import numpy as np
2
3#################
4# PREPROCESSING #
5#################
6
7# Read the solution generated by a physical code
8from BasicTools.IO import XdmfReader as XR
9reader = XR.XdmfReader(filename = "PrePostDeepLearning_Input.xmf")
10reader.Read()
11
12dom = reader.xdmf.GetDomain(0)
13grid = dom.GetGrid(0)
14
15# Read the mesh
16uMesh = grid.GetSupport()
17# convert all data to the correct binary (float64, int64) representation for the c++ part of BasicTools
18uMesh.ConvertDataForNativeTreatment()
19
20# Read the solution field 'U'
21indexU = grid.GetPointFieldsNames().index("U")
22U = grid.GetPointFields()[indexU][:,0:2]
23
24# Create a rectilinear mesh of size 48*48 excluding the left part of the mesh (x<0)
25Nx = 48
26Ny = 48
27uMesh.ComputeBoundingBox()
28Lx = uMesh.boundingMax[0] - 0.
29Ly = uMesh.boundingMax[1] - uMesh.boundingMin[1]
30
31from BasicTools.Containers.ConstantRectilinearMesh import ConstantRectilinearMesh
32rectMesh = ConstantRectilinearMesh(dim=2)
33rectMesh.SetDimensions([Nx,Ny])
34rectMesh.SetSpacing([Lx/(Nx-1), Ly/(Ny-1)])
35rectMesh.SetOrigin([0., uMesh.boundingMin[1]])
36
37# Compute the projection operator from unstructured mesh to structured mesh
38from BasicTools.Containers.UnstructuredMeshCreationTools import CreateMeshFromConstantRectilinearMesh
39from BasicTools.FE.FETools import PrepareFEComputation
40from BasicTools.Containers.UnstructuredMeshFieldOperations import GetFieldTransferOp
41from BasicTools.FE.Fields.FEField import FEField
42
43unstructuredRectMesh = CreateMeshFromConstantRectilinearMesh(rectMesh)
44space, numberings, _offset, _NGauss = PrepareFEComputation(uMesh, numberOfComponents = 2)
45inputFEField = FEField(name="U",mesh=uMesh, space=space, numbering=numberings[0])
46methods = ["Interp/Nearest","Nearest/Nearest","Interp/Clamp","Interp/Extrap","Interp/ZeroFill"]
47operator, status = GetFieldTransferOp(inputFEField, unstructuredRectMesh.nodes, method = methods[2], verbose=True)
48
49# Compute the projected field on the structured mesh
50projectedU = operator.dot(U)
51
52# Export the structured mesh and projected field in xdmf format (in ASCII)
53# To visualize this xdmf file you can use ParaView (downloadable from https://www.paraview.org/)
54from BasicTools.IO import XdmfWriter as XW
55writer = XW.XdmfWriter('PrePostDeepLearning_OutputI.xdmf')
56writer.SetHdf5(False)
57writer.Open()
58writer.Write(rectMesh,PointFields=[projectedU.reshape((Nx,Ny,2))], PointFieldsNames=["U"])
59writer.Close()
60
61
62##################
63# POSTPROCESSING #
64##################
65
66# Compute the projection operator from the structured mesh to the unstructured mesh (inverse projection)
67space, numberings, _offset, _NGauss = PrepareFEComputation(unstructuredRectMesh)
68inputFEField = FEField(name="U",mesh=unstructuredRectMesh,space=space,numbering=numberings[0])
69operator, status = GetFieldTransferOp(inputFEField, uMesh.nodes, method = methods[2], verbose=True)
70
71# Compute the inverse-projected projected field on the unstructured mesh
72inverseProjected_ProjectedU = operator.dot(projectedU)
73
74# Export the unstructured mesh and inverse-projected projected field in xdmf format
75# To visualize this xdmf file you can use ParaView (downloadable from https://www.paraview.org/)
76writer = XW.XdmfWriter('PrePostDeepLearning_OutputII.xdmf')
77writer.SetHdf5(False)
78writer.Open()
79writer.Write(uMesh, PointFields=[inverseProjected_ProjectedU], PointFieldsNames=["U"])
80writer.Close()
81
82
83##################
84# CHECK ACCURACY #
85##################
86
87# Create a clippedMesh from the unstructured mesh by removing the left part (x<0)
88# (with field, inverse-projected projected field and difference between them)
89from BasicTools.Containers.Filters import ElementFilter
90from BasicTools.FE.FETools import ComputePhiAtIntegPoint, ComputeL2ScalarProducMatrix
91from BasicTools.Containers.UnstructuredMeshInspectionTools import ExtractElementsByElementFilter
92from BasicTools.Containers.UnstructuredMeshModificationTools import CleanLonelyNodes
93from BasicTools.Containers.UnstructuredMeshFieldOperations import CopyFieldsFromOriginalMeshToTargetMesh
94
95uMesh.nodeFields['delta'] = U - inverseProjected_ProjectedU
96
97elFilter = ElementFilter(uMesh, zone = lambda p: (-p[:,0]))
98unstructuredMeshClipped = ExtractElementsByElementFilter(uMesh, elFilter)
99CleanLonelyNodes(unstructuredMeshClipped)
100unstructuredMeshClipped.ConvertDataForNativeTreatment()
101
102CopyFieldsFromOriginalMeshToTargetMesh(uMesh, unstructuredMeshClipped)
103nbeOfNodes = unstructuredMeshClipped.GetNumberOfNodes()
104
105deltaClippedMesh = unstructuredMeshClipped.nodeFields['delta']
106
107from BasicTools.Helpers.TextFormatHelper import TFormat
108from BasicTools.Helpers.Timer import Timer
109
110print("Compute the L2(Omega) norm of delta by applying numerical quadrature from Lagrange P1")
111print("Finite element integration using three different methods")
112
113#### Method 1
114print(TFormat.Center(TFormat.InRed("Method 1: ")+TFormat.InBlue("'by hand'")))
115
116timer = Timer("Duration of method 1")
117#compute method 1 three times
118for i in range(3):
119 timer.Start()
120 integrationWeights, phiAtIntegPoint = ComputePhiAtIntegPoint(unstructuredMeshClipped)
121
122 vectDeltaAtIntegPoints = np.empty((2,phiAtIntegPoint.shape[0]))
123 for i in range(2):
124 vectDeltaAtIntegPoints[i] = phiAtIntegPoint.dot(deltaClippedMesh[:,i])
125
126 normDeltaMethod1 = np.sqrt(np.einsum('ij,ij,j', vectDeltaAtIntegPoints, vectDeltaAtIntegPoints, integrationWeights, optimize = True))
127 timer.Stop()
128
129print("norm(Delta) =", normDeltaMethod1)
130############
131
132#### Method 2
133print(TFormat.Center(TFormat.InRed("Method 2: ")+TFormat.InBlue("using the mass matrix")))
134
135timer = Timer("Duration of method 2").Start()
136
137massMatrix = ComputeL2ScalarProducMatrix(unstructuredMeshClipped, 2)
138
139normDeltaMethod2 = np.sqrt(np.dot(deltaClippedMesh.ravel(order='F'), massMatrix.dot(deltaClippedMesh.ravel(order='F'))))
140
141timer.Stop()
142print("norm(Delta) =", normDeltaMethod2)
143############
144
145#### Method 3
146print(TFormat.Center(TFormat.InRed("Method 3: ")+TFormat.InBlue("using the weak form engine")))
147
148from BasicTools.FE.Integration import IntegrateGeneral
149from BasicTools.FE.SymWeakForm import GetField, GetTestField
150from BasicTools.FE.Spaces.FESpaces import LagrangeSpaceP1, ConstantSpaceGlobal
151from BasicTools.FE.DofNumbering import ComputeDofNumbering
152
153timer = Timer("Duration of method 3").Start()
154
155U = GetField("U",2)
156Tt = GetTestField("T",1)
157
158wf = U.T*U*Tt
159
160#unstructuredMeshClipped
161numbering = ComputeDofNumbering(unstructuredMeshClipped,LagrangeSpaceP1)
162field1 = FEField("U_0",mesh=unstructuredMeshClipped,space=LagrangeSpaceP1,numbering=numbering, data = deltaClippedMesh[:,0])
163field1.ConvertDataForNativeTreatment()
164field2 = FEField("U_1",mesh=unstructuredMeshClipped,space=LagrangeSpaceP1,numbering=numbering, data = deltaClippedMesh[:,1])
165field2.ConvertDataForNativeTreatment()
166
167numbering = ComputeDofNumbering(unstructuredMeshClipped,ConstantSpaceGlobal)
168unkownField = FEField("T",mesh=unstructuredMeshClipped,space=ConstantSpaceGlobal,numbering=numbering)
169
170elFilter = ElementFilter(unstructuredMeshClipped)
171
172K, F = IntegrateGeneral(mesh=unstructuredMeshClipped,
173 wform=wf,
174 constants={},
175 fields=[field1,field2],
176 unkownFields=[unkownField],
177 integrationRuleName="LagrangeP1",
178 elementFilter=elFilter)
179
180normDeltaMethod3 = np.sqrt(F[0])
181
182timer.Stop()
183print("norm(Delta) =", normDeltaMethod2)
184############
185
186print(Timer.PrintTimes())
187
188
189