Note
Go to the end to download the full example code
Profiling the code
Using PatchMesher to model a quarter of the plate
# sphinx_gallery_thumbnail_path = '_static/profiler.png'
SPARSE = False
import math
import sys
import numpy as np
from femedu.examples import Example
from femedu.domain import System, Node
from femedu.solver import NewtonRaphsonSolver, SparseSolver
from femedu.elements.linear import Triangle
from femedu.materials import PlaneStress
from femedu.mesher import *
class ExamplePlate10(Example):
def problem(self):
# ========== setting mesh parameters ==============
Nx = 60 # number of elements in the mesh
Ny = 40 # number of elements in the mesh
Lx = 120.0 # length of plate in the x-direction
Ly = 80.0 # length of plate in the y-direction
R = Ly / 2.
# ========== setting material parameters ==============
params = dict(
E = 200., # Young's modulus
nu = 0.450, # Poisson's ratio
t = 1.00 # thickness of the plate
)
# ========== setting load parameters ==============
px = 20.0 # uniform load normal to x=const
py = 0.0 # uniform load normal to y=const
pxy = 0.0 # uniform shear load on x=const and y=const
# ========== setting analysis parameters ==============
target_load_level = 1.00 # reference load
max_steps = 2 # number of load steps: 2 -> [0.0, 1.0]
# define a list of target load levels
load_levels = np.linspace(0, target_load_level, max_steps)
#
# ==== Build the system model ====
#
model = System()
if SPARSE:
model.setSolver(SparseSolver())
else:
model.setSolver(NewtonRaphsonSolver())
# create nodes
# 3---------2
# | |
# | |
# | |
# 1---------1
pts = (
( 0, 0),
(Lx, 0),
(Lx, Ly),
(0, Ly),
)
mesher = PatchMesher(model, pts[0], pts[1], pts[2], pts[3])
nodes, elements = mesher.triangleMesh(Nx, Ny, Triangle, PlaneStress(params))
# define support(s)
## find nodes at y==0 and x==0
for node in nodes:
X = node.getPos()
if math.isclose(X[0], 0.0):
node.fixDOF('ux') # horizontal support left side
if math.isclose(X[1], 0.0):
node.fixDOF('uy') # vertical support at y==0
# ==== build the reference load ====
# nodal loads
dir = np.array([1.,0.]) # normal to surface
x0 = np.array([Lx,0.0]) # reference point on the surface
for node in nodes:
X = node.getPos()
if math.isclose(X[0],Lx):
print(node.getID(), node.getPos())
for elem in node.elements:
print('+', elem.getID(), end=' ')
for face in elem.faces:
dist = np.allclose( [ (x - x0) @ dir for x in face.pos ], 0.0 ) \
and np.allclose( [ t @ dir for t in face.tangent ], 0.0, atol=0.05)
if dist:
print(face.id, ":", face.area, end=' ')
face_idx = int(face.id[-1])
elem.setSurfaceLoad(face_idx, px, pxy)
print()
#model.plot(factor=0, title="undeformed system", filename="plate06_undeformed.png", show_bc=1, show_loads=1)
model.setLoadFactor(1.0)
model.solve()
#model.plot(factor=1., filename="plate06_deformed.png")
#model.solver.showKt(filename="plate06_spy_Kt.png")
#np.save("plate6_Kt.npy",model.solver.Kt)
Run the example by creating an instance of the problem and executing it by calling Example.run()
This time, we are running the example in the profiler, writing profiling data to file.
import cProfile
ex = ExamplePlate10()
if SPARSE:
cProfile.run('ex.run()','profile_data_sparse.txt')
else:
cProfile.run('ex.run()','profile_data_full.txt')
Node_1478 [120. 0.]
+ Elem_1936
+ Elem_1937 1937.2 : [[2. 0.]]
Node_1539 [120. 2.]
+ Elem_1937 1937.2 : [[2. 0.]]
+ Elem_2056
+ Elem_2057 2057.2 : [[2.00000000e+00 1.42108547e-14]]
Node_1600 [120. 4.]
+ Elem_2057 2057.2 : [[2.00000000e+00 1.42108547e-14]]
+ Elem_2176
+ Elem_2177 2177.2 : [[ 2.00000000e+00 -1.42108547e-14]]
Node_1661 [120. 6.]
+ Elem_2177 2177.2 : [[ 2.00000000e+00 -1.42108547e-14]]
+ Elem_2296
+ Elem_2297 2297.2 : [[2. 0.]]
Node_1722 [120. 8.]
+ Elem_2297 2297.2 : [[2. 0.]]
+ Elem_2416
+ Elem_2417 2417.2 : [[2. 0.]]
Node_1783 [120. 10.]
+ Elem_2417 2417.2 : [[2. 0.]]
+ Elem_2536
+ Elem_2537 2537.2 : [[2. 0.]]
Node_1844 [120. 12.]
+ Elem_2537 2537.2 : [[2. 0.]]
+ Elem_2656
+ Elem_2657 2657.2 : [[2. 0.]]
Node_1905 [120. 14.]
+ Elem_2657 2657.2 : [[2. 0.]]
+ Elem_2776
+ Elem_2777 2777.2 : [[2. 0.]]
Node_1966 [120. 16.]
+ Elem_2777 2777.2 : [[2. 0.]]
+ Elem_2896
+ Elem_2897 2897.2 : [[2. 0.]]
Node_2027 [120. 18.]
+ Elem_2897 2897.2 : [[2. 0.]]
+ Elem_3016
+ Elem_3017 3017.2 : [[2. 0.]]
Node_2088 [120. 20.]
+ Elem_3017 3017.2 : [[2. 0.]]
+ Elem_3136
+ Elem_3137 3137.2 : [[2. 0.]]
Node_2149 [120. 22.]
+ Elem_3137 3137.2 : [[2. 0.]]
+ Elem_3256
+ Elem_3257 3257.2 : [[2. 0.]]
Node_2210 [120. 24.]
+ Elem_3257 3257.2 : [[2. 0.]]
+ Elem_3376
+ Elem_3377 3377.2 : [[ 2.00000000e+00 -1.42108547e-14]]
Node_2271 [120. 26.]
+ Elem_3377 3377.2 : [[ 2.00000000e+00 -1.42108547e-14]]
+ Elem_3496
+ Elem_3497 3497.2 : [[2.00000000e+00 2.84217094e-14]]
Node_2332 [120. 28.]
+ Elem_3497 3497.2 : [[2.00000000e+00 2.84217094e-14]]
+ Elem_3616
+ Elem_3617 3617.2 : [[ 2.00000000e+00 -1.42108547e-14]]
Node_2393 [120. 30.]
+ Elem_3617 3617.2 : [[ 2.00000000e+00 -1.42108547e-14]]
+ Elem_3736
+ Elem_3737 3737.2 : [[2.00000000e+00 1.42108547e-14]]
Node_2454 [120. 32.]
+ Elem_3737 3737.2 : [[2.00000000e+00 1.42108547e-14]]
+ Elem_3856
+ Elem_3857 3857.2 : [[ 2.00000000e+00 -1.42108547e-14]]
Node_2515 [120. 34.]
+ Elem_3857 3857.2 : [[ 2.00000000e+00 -1.42108547e-14]]
+ Elem_3976
+ Elem_3977 3977.2 : [[ 2.00000000e+00 -1.42108547e-14]]
Node_2576 [120. 36.]
+ Elem_3977 3977.2 : [[ 2.00000000e+00 -1.42108547e-14]]
+ Elem_4096
+ Elem_4097 4097.2 : [[2.00000000e+00 2.84217094e-14]]
Node_2637 [120. 38.]
+ Elem_4097 4097.2 : [[2.00000000e+00 2.84217094e-14]]
+ Elem_4216
+ Elem_4217 4217.2 : [[ 2.00000000e+00 -1.42108547e-14]]
Node_2698 [120. 40.]
+ Elem_4217 4217.2 : [[ 2.00000000e+00 -1.42108547e-14]]
+ Elem_4336
+ Elem_4337 4337.2 : [[2.00000000e+00 1.42108547e-14]]
Node_2759 [120. 42.]
+ Elem_4337 4337.2 : [[2.00000000e+00 1.42108547e-14]]
+ Elem_4456
+ Elem_4457 4457.2 : [[ 2.00000000e+00 -1.42108547e-14]]
Node_2820 [120. 44.]
+ Elem_4457 4457.2 : [[ 2.00000000e+00 -1.42108547e-14]]
+ Elem_4576
+ Elem_4577 4577.2 : [[2. 0.]]
Node_2881 [120. 46.]
+ Elem_4577 4577.2 : [[2. 0.]]
+ Elem_4696
+ Elem_4697 4697.2 : [[2. 0.]]
Node_2942 [120. 48.]
+ Elem_4697 4697.2 : [[2. 0.]]
+ Elem_4816
+ Elem_4817 4817.2 : [[2. 0.]]
Node_3003 [120. 50.]
+ Elem_4817 4817.2 : [[2. 0.]]
+ Elem_4936
+ Elem_4937 4937.2 : [[2. 0.]]
Node_3064 [120. 52.]
+ Elem_4937 4937.2 : [[2. 0.]]
+ Elem_5056
+ Elem_5057 5057.2 : [[2. 0.]]
Node_3125 [120. 54.]
+ Elem_5057 5057.2 : [[2. 0.]]
+ Elem_5176
+ Elem_5177 5177.2 : [[2. 0.]]
Node_3186 [120. 56.]
+ Elem_5177 5177.2 : [[2. 0.]]
+ Elem_5296
+ Elem_5297 5297.2 : [[2. 0.]]
Node_3247 [120. 58.]
+ Elem_5297 5297.2 : [[2. 0.]]
+ Elem_5416
+ Elem_5417 5417.2 : [[2. 0.]]
Node_3308 [120. 60.]
+ Elem_5417 5417.2 : [[2. 0.]]
+ Elem_5536
+ Elem_5537 5537.2 : [[2. 0.]]
Node_3369 [120. 62.]
+ Elem_5537 5537.2 : [[2. 0.]]
+ Elem_5656
+ Elem_5657 5657.2 : [[2. 0.]]
Node_3430 [120. 64.]
+ Elem_5657 5657.2 : [[2. 0.]]
+ Elem_5776
+ Elem_5777 5777.2 : [[2.00000000e+00 2.84217094e-14]]
Node_3491 [120. 66.]
+ Elem_5777 5777.2 : [[2.00000000e+00 2.84217094e-14]]
+ Elem_5896
+ Elem_5897 5897.2 : [[ 2.00000000e+00 -2.84217094e-14]]
Node_3552 [120. 68.]
+ Elem_5897 5897.2 : [[ 2.00000000e+00 -2.84217094e-14]]
+ Elem_6016
+ Elem_6017 6017.2 : [[2. 0.]]
Node_3613 [120. 70.]
+ Elem_6017 6017.2 : [[2. 0.]]
+ Elem_6136
+ Elem_6137 6137.2 : [[2. 0.]]
Node_3674 [120. 72.]
+ Elem_6137 6137.2 : [[2. 0.]]
+ Elem_6256
+ Elem_6257 6257.2 : [[2. 0.]]
Node_3735 [120. 74.]
+ Elem_6257 6257.2 : [[2. 0.]]
+ Elem_6376
+ Elem_6377 6377.2 : [[2. 0.]]
Node_3796 [120. 76.]
+ Elem_6377 6377.2 : [[2. 0.]]
+ Elem_6496
+ Elem_6497 6497.2 : [[2. 0.]]
Node_3857 [120. 78.]
+ Elem_6497 6497.2 : [[2. 0.]]
+ Elem_6616
+ Elem_6617 6617.2 : [[2. 0.]]
Node_3918 [120. 80.]
+ Elem_6617 6617.2 : [[2. 0.]]
+
Now it’s time to process the profiling data
import pstats
from pstats import SortKey
if SPARSE:
p = pstats.Stats('profile_data_sparse.txt')
p.strip_dirs() #.sort_stats(-1).print_stats()
p.sort_stats(SortKey.NAME)
#p.print_stats()
p.sort_stats(SortKey.CUMULATIVE).print_stats(20)
p.sort_stats(SortKey.TIME).print_stats(20)
else:
p = pstats.Stats('profile_data_full.txt')
p.strip_dirs() #.sort_stats(-1).print_stats()
p.sort_stats(SortKey.NAME)
#p.print_stats()
p.sort_stats(SortKey.CUMULATIVE).print_stats(20)
p.sort_stats(SortKey.TIME).print_stats(20)
Fri Apr 26 00:03:38 2024 profile_data_full.txt
6567554 function calls (6303232 primitive calls) in 12.640 seconds
Ordered by: cumulative time
List reduced from 267 to 20 due to restriction <20>
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 12.655 12.655 {built-in method builtins.exec}
1 0.000 0.000 12.655 12.655 <string>:1(<module>)
1 0.000 0.000 12.655 12.655 Example.py:20(run)
1 0.006 0.006 12.655 12.655 plot_plate10.py:46(problem)
1 0.000 0.000 10.430 10.430 System.py:313(solve)
1 0.000 0.000 10.430 10.430 NewtonRaphsonSolver.py:13(solve)
4 0.000 0.000 9.177 2.294 NewtonRaphsonSolver.py:105(assemble)
4 1.922 0.481 9.177 2.294 Solver.py:166(assemble)
19200 0.081 0.000 5.349 0.000 Element.py:269(getForce)
19200 1.977 0.000 5.268 0.000 Triangle.py:80(updateState)
2 0.000 0.000 4.591 2.295 Solver.py:388(checkResiduum)
38400 0.469 0.000 2.470 0.000 Triangle.py:155(computeSurfaceLoads)
1 0.028 0.028 2.148 2.148 PatchMesher.py:99(triangleMesh)
115200 0.645 0.000 1.392 0.000 Face2D.py:54(computeNodalForces)
1 0.003 0.003 1.237 1.237 NewtonRaphsonSolver.py:58(solveSingleStep)
1 1.220 1.220 1.220 1.220 linalg.py:329(solve)
19200 0.030 0.000 1.175 0.000 Element.py:278(getLoad)
4800 0.133 0.000 1.135 0.000 Triangle.py:10(__init__)
254400/4800 0.426 0.000 0.888 0.000 copy.py:128(deepcopy)
4800 0.026 0.000 0.836 0.000 copy.py:259(_reconstruct)
Fri Apr 26 00:03:38 2024 profile_data_full.txt
6567554 function calls (6303232 primitive calls) in 12.640 seconds
Ordered by: internal time
List reduced from 267 to 20 due to restriction <20>
ncalls tottime percall cumtime percall filename:lineno(function)
19200 1.977 0.000 5.268 0.000 Triangle.py:80(updateState)
4 1.922 0.481 9.177 2.294 Solver.py:166(assemble)
1 1.220 1.220 1.220 1.220 linalg.py:329(solve)
153600 0.699 0.000 0.828 0.000 numeric.py:841(outer)
115200 0.645 0.000 1.392 0.000 Face2D.py:54(computeNodalForces)
639439 0.644 0.000 0.644 0.000 {built-in method numpy.array}
230400 0.499 0.000 0.696 0.000 Node.py:467(getIdx4Element)
38400 0.469 0.000 2.470 0.000 Triangle.py:155(computeSurfaceLoads)
19201 0.427 0.000 0.543 0.000 PlaneStress.py:25(updateState)
254400/4800 0.426 0.000 0.888 0.000 copy.py:128(deepcopy)
115201 0.335 0.000 0.425 0.000 numeric.py:67(zeros_like)
76800 0.299 0.000 0.645 0.000 Node.py:416(getDeformedPos)
77208 0.230 0.000 0.332 0.000 Node.py:313(getDisp)
38400 0.155 0.000 0.601 0.000 Triangle.py:163(<listcomp>)
24000 0.140 0.000 0.263 0.000 shape_base.py:219(vstack)
14400 0.138 0.000 0.279 0.000 Face2D.py:16(initialize)
19200/4800 0.136 0.000 0.752 0.000 copy.py:227(_deepcopy_dict)
4800 0.133 0.000 1.135 0.000 Triangle.py:10(__init__)
14400 0.121 0.000 0.405 0.000 Faces.py:10(__init__)
14400 0.098 0.000 0.503 0.000 Face2D.py:13(__init__)
Total running time of the script: (0 minutes 12.710 seconds)