ddfem 1.0.10__py3-none-any.whl → 1.0.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. ddfem/__init__.py +9 -5
  2. ddfem/__main__.py +11 -12
  3. ddfem/boundary.py +2 -2
  4. ddfem/data/2.11.dev20250709/extra.modules +14 -0
  5. ddfem/data/2.11.dev20250709/femscheme_0bb54cd4f1cd1df2477f5f59393c6a2e.cc +43 -0
  6. ddfem/data/2.11.dev20250709/femscheme_5c9e2700386c07226eb4db155fa5ef14.cc +43 -0
  7. ddfem/data/2.11.dev20250709/femscheme_765ef00d995a939c34bdc0d0cc4847ca.cc +43 -0
  8. ddfem/data/2.11.dev20250709/femspace_11b3436cb033df683615c50d5d4239bd_f14dd0b3b474c0cd816334330f55ad72.cc +45 -0
  9. ddfem/data/2.11.dev20250709/femspace_f4f043307753c8e74af23c94c28a3b0d_438586e783f51d84a82e82b0d8daceea.cc +45 -0
  10. ddfem/data/2.11.dev20250709/{integrands_3bde0abfafcf45a3cff4d1029568ab5cv1_3_a524c1196983e65de1c06d7d6afdeb44.cc → integrands_0003e4cbb961fd653fe295d2c4fa50a7v1_3_a524c1196983e65de1c06d7d6afdeb44.cc} +367 -14
  11. ddfem/data/2.11.dev20250709/{integrands_2e6d4e3b5cff269867d26022ac7cee09v1_3_a524c1196983e65de1c06d7d6afdeb44.cc → integrands_0fa4a1c37449cf574971977e10cf682av1_3_a524c1196983e65de1c06d7d6afdeb44.cc} +8 -8
  12. ddfem/data/2.11.dev20250709/{integrands_96ea175da69be26acf1a8d94dc0b3c93v1_3_a524c1196983e65de1c06d7d6afdeb44.cc → integrands_29b696aa653181a57d036f771efa8be9v1_3_a524c1196983e65de1c06d7d6afdeb44.cc} +8 -8
  13. ddfem/data/2.11.dev20250709/integrands_536f9ba0ea4ecd1f7d4e2bc43ef29d08v1_3_a524c1196983e65de1c06d7d6afdeb44.cc +453 -0
  14. ddfem/data/2.11.dev20250709/{integrands_008eefa148b772fa3192dd3c1728c140v1_3_a524c1196983e65de1c06d7d6afdeb44.cc → integrands_5907ab5c70328c21dd308abf09e529aev1_3_a524c1196983e65de1c06d7d6afdeb44.cc} +8 -8
  15. ddfem/data/2.11.dev20250709/{integrands_59ef814e4fbd86ef9c0aeac61e84e9a7v1_3_a524c1196983e65de1c06d7d6afdeb44.cc → integrands_68eba4e963a61031a52da3365f515585v1_3_a524c1196983e65de1c06d7d6afdeb44.cc} +8 -8
  16. ddfem/data/2.11.dev20250709/integrands_83927be37e79b291517b827b9ddc1983v1_3_a524c1196983e65de1c06d7d6afdeb44.cc +533 -0
  17. ddfem/data/2.11.dev20250709/integrands_8ed2f23c088e3a3d82a3259b663796c7v1_3_a524c1196983e65de1c06d7d6afdeb44.cc +533 -0
  18. ddfem/data/2.11.dev20250709/integrands_af3bbe7d629df162ef8c570e1503bf62v1_3_a524c1196983e65de1c06d7d6afdeb44.cc +762 -0
  19. ddfem/data/2.11.dev20250709/{integrands_00ee9b3b89e4e44212e5b7ad7948a24ev1_3_a524c1196983e65de1c06d7d6afdeb44.cc → integrands_d0634430f14d3432dae186e57ec5aecav1_3_a524c1196983e65de1c06d7d6afdeb44.cc} +8 -8
  20. ddfem/data/2.11.dev20250709/intro.modules +33 -102
  21. ddfem/data/2.11.dev20250709/localfunction_10f9d7a54f79c12d6ca923b9ee56b80d_a524c1196983e65de1c06d7d6afdeb44.cc +324 -0
  22. ddfem/data/2.11.dev20250709/localfunction_10f9d7a54f79c12d6ca923b9ee56b80d_af122c1df944c95cd395ec0f91d0f970.cc +322 -0
  23. ddfem/data/2.11.dev20250709/localfunction_1c20e613977d8cea4cf5227c12aa68a6_a524c1196983e65de1c06d7d6afdeb44.cc +164 -0
  24. ddfem/data/2.11.dev20250709/{localfunction_191355e6250b2d2e260d96f519ad9976_a524c1196983e65de1c06d7d6afdeb44.cc → localfunction_217e4bf8b368a7768c4897cf58f71d84_a524c1196983e65de1c06d7d6afdeb44.cc} +14 -14
  25. ddfem/data/2.11.dev20250709/localfunction_22e797a8f3e8c322f33c41e07bd15165_a524c1196983e65de1c06d7d6afdeb44.cc +1445 -0
  26. ddfem/data/2.11.dev20250709/localfunction_2e2afc8df6107683d574a8d96d5249f4_af122c1df944c95cd395ec0f91d0f970.cc +512 -0
  27. ddfem/data/2.11.dev20250709/localfunction_32613626342183eafa360dc1f0f18924_a524c1196983e65de1c06d7d6afdeb44.cc +1425 -0
  28. ddfem/data/2.11.dev20250709/localfunction_37174cfc9d6bf565336cac0d2ea785f5_a524c1196983e65de1c06d7d6afdeb44.cc +786 -0
  29. ddfem/data/2.11.dev20250709/{localfunction_d75993d7ae5919d23117b153e900840d_a524c1196983e65de1c06d7d6afdeb44.cc → localfunction_3d957c5b2628e5120636b8e3f461bc0d_a524c1196983e65de1c06d7d6afdeb44.cc} +64 -29
  30. ddfem/data/2.11.dev20250709/localfunction_3ecaa105be9e3abddf3a85d8adc5d36f_a524c1196983e65de1c06d7d6afdeb44.cc +697 -0
  31. ddfem/data/2.11.dev20250709/{localfunction_f626cd43dc8558135fe0b32cde016644_a524c1196983e65de1c06d7d6afdeb44.cc → localfunction_3ecaf7de7505b53bb0b5fb6d78549387_a524c1196983e65de1c06d7d6afdeb44.cc} +14 -14
  32. ddfem/data/2.11.dev20250709/{localfunction_1d27a90a52b9053192c9cc902283f79b_a524c1196983e65de1c06d7d6afdeb44.cc → localfunction_4192604521151252f1c8fa56a1f9f226_a524c1196983e65de1c06d7d6afdeb44.cc} +14 -14
  33. ddfem/data/2.11.dev20250709/localfunction_4976bbef3267846b59f3a26497ffe9db_a524c1196983e65de1c06d7d6afdeb44.cc +474 -0
  34. ddfem/data/2.11.dev20250709/{localfunction_a8c726f728cd35d137188b33301aeef1_a524c1196983e65de1c06d7d6afdeb44.cc → localfunction_4adfaf8a08fac23151af0b1e790db1f7_a524c1196983e65de1c06d7d6afdeb44.cc} +14 -14
  35. ddfem/data/2.11.dev20250709/{localfunction_00f2e5593eeb23f01906255d67244f6e_a524c1196983e65de1c06d7d6afdeb44.cc → localfunction_4f6a526abfe63959f81b09a5796c5eb1_a524c1196983e65de1c06d7d6afdeb44.cc} +44 -29
  36. ddfem/data/2.11.dev20250709/localfunction_5591a2c803b9658084d8f11d44bf3ae1_a524c1196983e65de1c06d7d6afdeb44.cc +485 -0
  37. ddfem/data/2.11.dev20250709/localfunction_6363af791dde11d699a9a3d876cc5d9a_a524c1196983e65de1c06d7d6afdeb44.cc +549 -0
  38. ddfem/data/2.11.dev20250709/localfunction_6363af791dde11d699a9a3d876cc5d9a_af122c1df944c95cd395ec0f91d0f970.cc +547 -0
  39. ddfem/data/2.11.dev20250709/localfunction_6eccfc8fd91ce34d81e7c3962ece5d94_a524c1196983e65de1c06d7d6afdeb44.cc +766 -0
  40. ddfem/data/2.11.dev20250709/localfunction_762aa49bc5a47ad3d8d8bbde36b42ee5_a524c1196983e65de1c06d7d6afdeb44.cc +723 -0
  41. ddfem/data/2.11.dev20250709/localfunction_76e8db0f046ac9e37a793e0bb13eea7b_a524c1196983e65de1c06d7d6afdeb44.cc +292 -0
  42. ddfem/data/2.11.dev20250709/localfunction_7792f4273b0fd848c5a0fc9d6f12683e_a524c1196983e65de1c06d7d6afdeb44.cc +280 -0
  43. ddfem/data/2.11.dev20250709/localfunction_7f7ef99c50708814ba5a82b0956b0aed_a524c1196983e65de1c06d7d6afdeb44.cc +461 -0
  44. ddfem/data/2.11.dev20250709/localfunction_898de4ae138e0ed305ef1399c66aa10a_a524c1196983e65de1c06d7d6afdeb44.cc +313 -0
  45. ddfem/data/2.11.dev20250709/{localfunction_1d13146d4bff10e178aba773fe2a9f1d_a524c1196983e65de1c06d7d6afdeb44.cc → localfunction_a99a0c7f35b06ac5a1fa7f081b5e64f9_a524c1196983e65de1c06d7d6afdeb44.cc} +14 -14
  46. ddfem/data/2.11.dev20250709/{localfunction_82d7cb9338bf118426fac2abf41a91a4_a524c1196983e65de1c06d7d6afdeb44.cc → localfunction_cda923259a47bb19861404a9fdb64303_a524c1196983e65de1c06d7d6afdeb44.cc} +14 -14
  47. ddfem/data/2.11.dev20250709/localfunction_d3d9b8a21e3075c9ff40117c5244f28e_a524c1196983e65de1c06d7d6afdeb44.cc +381 -0
  48. ddfem/data/2.11.dev20250709/localfunction_d4b9ca85d48735ee01f395a42eaa0cee_af122c1df944c95cd395ec0f91d0f970.cc +774 -0
  49. ddfem/data/2.11.dev20250709/localfunction_dd1fb4bd60f2d8b3a062dbbdaedb9fee_a524c1196983e65de1c06d7d6afdeb44.cc +869 -0
  50. ddfem/data/2.11.dev20250709/localfunction_dd5ab085a9d94f578c1f3d337ea360a3_a524c1196983e65de1c06d7d6afdeb44.cc +161 -0
  51. ddfem/data/2.11.dev20250709/{localfunction_aeb3d963412cdc65630e0a4c3c0dde0f_a524c1196983e65de1c06d7d6afdeb44.cc → localfunction_e2b19c5987f9b6fb0cd5453bfa7f4f9f_a524c1196983e65de1c06d7d6afdeb44.cc} +14 -30
  52. ddfem/data/extra.modules +13 -0
  53. ddfem/examples/beam.py +43 -50
  54. ddfem/examples/chemical_reaction.py +1 -1
  55. ddfem/examples/five_circle_flat.py +42 -28
  56. ddfem/examples/linear_elasticity.py +5 -1
  57. ddfem/examples/triple_circle.py +86 -83
  58. ddfem/examples/triple_circle_beam.py +71 -61
  59. ddfem-1.0.11.dist-info/METADATA +78 -0
  60. ddfem-1.0.11.dist-info/RECORD +124 -0
  61. ddfem/data/2.11.dev20250709/boundary.modules +0 -9
  62. ddfem/data/2.11.dev20250709/femspace_90f0a9524a8cb701e8ee5027b7658a0e_0faf32f13b591f4f60f83c591507b9be.cc +0 -40
  63. ddfem/data/2.11.dev20250709/geometry.modules +0 -84
  64. ddfem/data/2.11.dev20250709/hierarchicalgrid_472c2c2d007bf5604887ab2f16b7eb13.cc +0 -30
  65. ddfem/data/2.11.dev20250709/hierarchicalgrid_966e2a5c8356c5b278ccd3acad180f0a.cc +0 -30
  66. ddfem/data/2.11.dev20250709/localfunction_10ad0a2d88c74db5f4bf5f81e138974f_a524c1196983e65de1c06d7d6afdeb44.cc +0 -135
  67. ddfem/data/2.11.dev20250709/localfunction_1460b632dc5919e94a2147108f4f34f4_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -468
  68. ddfem/data/2.11.dev20250709/localfunction_161bbe6dde741c6e3f90c2919b8d17a4_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -171
  69. ddfem/data/2.11.dev20250709/localfunction_268716e3e3ec528038367ee04d335ea1_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -289
  70. ddfem/data/2.11.dev20250709/localfunction_29566243d89228735978e58471af60be_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -246
  71. ddfem/data/2.11.dev20250709/localfunction_2a890b2a64788a92607670296c0d37ac_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -311
  72. ddfem/data/2.11.dev20250709/localfunction_2bbefabe87db948827d02bdb8d69a7d1_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -240
  73. ddfem/data/2.11.dev20250709/localfunction_34a46b87fa5c0a5a4f0bc44949f2eda9_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -239
  74. ddfem/data/2.11.dev20250709/localfunction_3c10414582133a0fa8e341c4544a97c7_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -220
  75. ddfem/data/2.11.dev20250709/localfunction_3dfb73430ddb90a26b6f50f85e52e2a4_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -216
  76. ddfem/data/2.11.dev20250709/localfunction_3e323e81c52891c0ecb656eac273e52f_a524c1196983e65de1c06d7d6afdeb44.cc +0 -135
  77. ddfem/data/2.11.dev20250709/localfunction_465e17370f4344b8997151adacf7aec6_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -403
  78. ddfem/data/2.11.dev20250709/localfunction_57e9651c5364ef528f41cf138e126115_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -272
  79. ddfem/data/2.11.dev20250709/localfunction_5c2a00bf7ec417475a0a378ed462beeb_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -350
  80. ddfem/data/2.11.dev20250709/localfunction_5d71e054c405bc6584738437908af804_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -364
  81. ddfem/data/2.11.dev20250709/localfunction_6343878b30d190cc70b631d882009dec_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -342
  82. ddfem/data/2.11.dev20250709/localfunction_639a3f3873411f43337e687cb070368f_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -230
  83. ddfem/data/2.11.dev20250709/localfunction_6661b21a0e1340a9a9f7b32da595f130_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -468
  84. ddfem/data/2.11.dev20250709/localfunction_75e876499fa3b7abc096aa08f88a1c2d_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -213
  85. ddfem/data/2.11.dev20250709/localfunction_8647b4efdf8a37595f73652bc1905df2_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -335
  86. ddfem/data/2.11.dev20250709/localfunction_86a0670f34bf2ac8155423a1c1bc2e75_a524c1196983e65de1c06d7d6afdeb44.cc +0 -135
  87. ddfem/data/2.11.dev20250709/localfunction_98b32c4b5bc0d8083f3d2c394aa33429_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -340
  88. ddfem/data/2.11.dev20250709/localfunction_9b741917efb5aa6a09e375272e4ae3aa_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -317
  89. ddfem/data/2.11.dev20250709/localfunction_a369aff055312b472a92ee7e257534ff_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -392
  90. ddfem/data/2.11.dev20250709/localfunction_a6cc88a79948487ce95a6c3f22487b36_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -395
  91. ddfem/data/2.11.dev20250709/localfunction_aa506761997f291dfd2e62b678f010b2_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -280
  92. ddfem/data/2.11.dev20250709/localfunction_b5edf0c36f0fc96cc6f5f3677c6557a1_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -214
  93. ddfem/data/2.11.dev20250709/localfunction_bdfb7ddf42a423f7d0791458634d4b8f_a524c1196983e65de1c06d7d6afdeb44.cc +0 -135
  94. ddfem/data/2.11.dev20250709/localfunction_c3d0902cf8bb4b86b62a2293de2b74e9_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -1131
  95. ddfem/data/2.11.dev20250709/localfunction_cf4a29dc25e72137baf2f8fb8b8d3c50_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -267
  96. ddfem/data/2.11.dev20250709/localfunction_d40efa41ac661ff77278d2ae4812b06d_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -377
  97. ddfem/data/2.11.dev20250709/localfunction_e69118a51208cfab8a028711e966e76c_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -236
  98. ddfem/data/2.11.dev20250709/localfunction_e9c8d4f4cedd30cab76a588b95bbccab_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -325
  99. ddfem/data/2.11.dev20250709/localfunction_f0d3fe89de368f7ea295a1982a807bd8_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -281
  100. ddfem/data/2.11.dev20250709/localfunction_f4b1d42cbb447375f39ed834570cd3f0_a524c1196983e65de1c06d7d6afdeb44.cc +0 -135
  101. ddfem/data/2.11.dev20250709/localfunction_fb15e1ad2c62e6660c67949fcf166d81_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -339
  102. ddfem/data/2.11.dev20250709/localfunction_fb17410b0b5d479dce9ffc6f9d61ab37_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -317
  103. ddfem/data/2.11.dev20250709/localfunction_fc22d5adaf3b9563160dc2aec55e8ba1_19659fe2f2f74bcfb5d532f1a0d38be9.cc +0 -113
  104. ddfem/data/2.11.dev20250709/referenceelements_fe266b8abf61f4601198949ea6b0dfd3.cc +0 -24
  105. ddfem/data/2.11.dev20250709/transformers.modules +0 -13
  106. ddfem/data/2.11.dev20250709/yaspcoordinates_dim2_ctdouble.cc +0 -55
  107. ddfem/data/2.11.dev20250709/yaspcoordinates_dim3_ctdouble.cc +0 -55
  108. ddfem-1.0.10.dist-info/METADATA +0 -101
  109. ddfem-1.0.10.dist-info/RECORD +0 -138
  110. {ddfem-1.0.10.dist-info → ddfem-1.0.11.dist-info}/WHEEL +0 -0
  111. {ddfem-1.0.10.dist-info → ddfem-1.0.11.dist-info}/licenses/LICENSE +0 -0
  112. {ddfem-1.0.10.dist-info → ddfem-1.0.11.dist-info}/top_level.txt +0 -0
@@ -15,15 +15,11 @@ pip install dune-fem
15
15
  """
16
16
  )
17
17
 
18
- from dune.alugrid import aluConformGrid as leafGridView
19
- from dune.fem import adapt, mark, markNeighbors
20
- from dune.fem.function import gridFunction
21
- from dune.fem.space import lagrange
22
- from dune.fem.view import adaptiveLeafGridView
23
18
  from dune.grid import cartesianDomain
24
19
  from dune.ufl import Constant, Space
25
20
  from ufl import SpatialCoordinate, sqrt
26
21
 
22
+ from ddfem import GridView
27
23
  from ddfem import geometry as gm
28
24
  from ddfem.geometry.domain_dune import DomainDune
29
25
 
@@ -61,7 +57,7 @@ def getDomain(
61
57
 
62
58
  h_max = h * 3
63
59
  h_min = h / 2
64
- radius = 5
60
+ radius = 4
65
61
 
66
62
  x = SpatialCoordinate(Space(2))
67
63
  sdf = omega(x)
@@ -70,51 +66,61 @@ def getDomain(
70
66
  r_min = epsilon.value
71
67
  r_max = radius * epsilon.value
72
68
  dist = np.abs(sdf((x, y)))
73
- if dist <= r_min:
74
- return geom.characteristic_length_min
75
- elif dist >= r_max:
76
- return geom.characteristic_length_max
77
- else:
78
- # Linear
79
- m = (geom.characteristic_length_max - geom.characteristic_length_min) / (
80
- r_max - r_min
81
- )
82
- return m * (dist - r_min) + geom.characteristic_length_min
83
69
 
84
- if version == "cartesian":
85
- domain = cartesianDomain(*domain_range, initial_gridsize)
86
- epsilon = get_eps(h)
70
+ gmax = geom.characteristic_length_max
71
+ gmin = geom.characteristic_length_min
87
72
 
88
- elif version == "fitted":
89
- if pygmsh is None:
90
- raise AttributeError("'fitted' requires install pygmsh")
91
- with pygmsh.occ.Geometry() as geom:
92
- geom.characteristic_length_max = h_max
93
- geom.characteristic_length_min = h_min
94
- epsilon = get_eps(h_min)
73
+ if False:
74
+ # Linear
75
+ if dist <= r_min:
76
+ return gmin
77
+ elif dist >= r_max:
78
+ return gmax
79
+ else:
80
+ m = (gmax - gmin) / (r_max - r_min)
81
+ return m * (dist - r_min) + gmin
95
82
 
96
- disks = [geom.add_disk([c[1][0], c[1][1], 0.0], c[0]) for c in balls]
83
+ else:
84
+ # Exponential
85
+ R = int(2 * np.log2(gmax / gmin))
86
+ j = max(0, min(R, (dist * R) / r_max - 0.5))
87
+ # j = max(0, min(R, np.floor(dist * R / r_max)))
88
+ return gmax * 0.5 ** ((R - j) / 2)
97
89
 
98
- ds = geom.boolean_union([disks[0], disks[1]])
99
- shape = geom.boolean_intersection([ds, disks[2]])
100
- if inverted:
101
- rectangle = geom.add_rectangle(
102
- [domain_range[0][0], domain_range[0][1], 0.0],
103
- domain_range[1][0] - domain_range[0][0],
104
- domain_range[1][1] - domain_range[0][1],
105
- )
106
- geom.boolean_difference(rectangle, shape)
90
+ omega.epsilon = get_eps(h_min)
91
+ if version == "cartesian":
92
+ omega.epsilon = get_eps(h)
93
+ domain = cartesianDomain(*domain_range, initial_gridsize)
107
94
 
108
- geom.set_mesh_size_callback(
109
- lambda dim, tag, x, y, z, lc: spacing(x, y, epsilon),
110
- ignore_other_mesh_sizes=True,
111
- )
112
- mesh = geom.generate_mesh()
113
- points, cells = mesh.points, mesh.cells_dict
114
- domain = {
115
- "vertices": points[:, :2].astype(float),
116
- "simplices": cells["triangle"].astype(int),
117
- }
95
+ # elif version == "fitted":
96
+ # if pygmsh is None:
97
+ # raise AttributeError("'fitted' requires install pygmsh")
98
+ # with pygmsh.occ.Geometry() as geom:
99
+ # geom.characteristic_length_max = h_max / sqrt(2)
100
+ # geom.characteristic_length_min = h_min / sqrt(2)
101
+
102
+ # disks = [geom.add_disk([c[1][0], c[1][1], 0.0], c[0]) for c in balls]
103
+
104
+ # ds = geom.boolean_union([disks[0], disks[1]])
105
+ # shape = geom.boolean_intersection([ds, disks[2]])
106
+ # if inverted:
107
+ # rectangle = geom.add_rectangle(
108
+ # [domain_range[0][0], domain_range[0][1], 0.0],
109
+ # domain_range[1][0] - domain_range[0][0],
110
+ # domain_range[1][1] - domain_range[0][1],
111
+ # )
112
+ # geom.boolean_difference(rectangle, shape)
113
+
114
+ # geom.set_mesh_size_callback(
115
+ # lambda dim, tag, x, y, z, lc: spacing(x, y, omega.epsilon),
116
+ # ignore_other_mesh_sizes=True,
117
+ # )
118
+ # mesh = geom.generate_mesh()
119
+ # points, cells = mesh.points, mesh.cells_dict
120
+ # domain = {
121
+ # "vertices": points[:, :2].astype(float),
122
+ # "simplices": cells["triangle"].astype(int),
123
+ # }
118
124
 
119
125
  elif version == "dune_adaptive":
120
126
  gridsize = [int(j * h / h_max) for j in initial_gridsize]
@@ -124,9 +130,8 @@ def getDomain(
124
130
  if pygmsh is None:
125
131
  raise AttributeError("'gmsh_adaptive' requires install pygmsh")
126
132
  with pygmsh.occ.Geometry() as geom:
127
- geom.characteristic_length_max = h_max
128
- geom.characteristic_length_min = h_min
129
- epsilon = get_eps(h_min)
133
+ geom.characteristic_length_max = h_max / sqrt(2)
134
+ geom.characteristic_length_min = h_min / sqrt(2)
130
135
 
131
136
  geom.add_rectangle(
132
137
  [domain_range[0][0], domain_range[0][1], 0.0],
@@ -135,7 +140,7 @@ def getDomain(
135
140
  )
136
141
 
137
142
  geom.set_mesh_size_callback(
138
- lambda dim, tag, x, y, z, lc: spacing(x, y, epsilon),
143
+ lambda dim, tag, x, y, z, lc: spacing(x, y, omega.epsilon),
139
144
  ignore_other_mesh_sizes=True,
140
145
  )
141
146
  mesh = geom.generate_mesh()
@@ -145,13 +150,12 @@ def getDomain(
145
150
  "simplices": cells["triangle"].astype(int),
146
151
  }
147
152
 
148
- elif version == "gmsh_embedded":
153
+ elif version == "gmsh_embedded" or version == "fitted":
149
154
  if pygmsh is None:
150
155
  raise AttributeError("'fitted' requires install pygmsh")
151
156
  with pygmsh.occ.Geometry() as geom:
152
- geom.characteristic_length_max = h_max
153
- geom.characteristic_length_min = h_min
154
- epsilon = get_eps(h_min)
157
+ geom.characteristic_length_max = h_max / sqrt(2)
158
+ geom.characteristic_length_min = h_min / sqrt(2)
155
159
 
156
160
  disks = [geom.add_disk([c[1][0], c[1][1], 0.0], c[0]) for c in balls]
157
161
 
@@ -165,53 +169,52 @@ def getDomain(
165
169
 
166
170
  geom.boolean_fragments(rectangle, shape)
167
171
 
172
+ geom.add_physical(shape, label="fitted_domain")
173
+
168
174
  geom.set_mesh_size_callback(
169
- lambda dim, tag, x, y, z, lc: spacing(x, y, epsilon),
175
+ lambda dim, tag, x, y, z, lc: spacing(x, y, omega.epsilon),
170
176
  ignore_other_mesh_sizes=True,
171
177
  )
172
178
  mesh = geom.generate_mesh()
173
179
  points, cells = mesh.points, mesh.cells_dict
180
+
181
+ if version == "fitted":
182
+ fitted_domain_indices = mesh.cell_sets_dict["fitted_domain"]["triangle"]
183
+ mesh_cells = cells["triangle"][fitted_domain_indices].astype(int)
184
+ else:
185
+ mesh_cells = cells["triangle"].astype(int)
186
+
174
187
  domain = {
175
188
  "vertices": points[:, :2].astype(float),
176
- "simplices": cells["triangle"].astype(int),
189
+ "simplices": mesh_cells,
177
190
  }
178
191
 
179
192
  else:
180
193
  raise ValueError("invalid mesh type")
181
194
 
182
- gridView = adaptiveLeafGridView(leafGridView(domain))
183
-
184
195
  if version == "dune_adaptive":
185
- omega.epsilon = get_eps(h_min)
186
- omega.epsilon.value *= radius
187
- epsilon_value = omega.epsilon.value
188
-
189
- marker = mark
190
-
191
196
  refinements = int(2 * np.log2(h_max / h_min))
192
-
193
- region = gridFunction(
194
- omega.phi(x) * (1 - omega.phi(x)), gridView=gridView
195
- ) # interface
196
-
197
- for j in range(1, refinements + 1):
198
-
199
- omega.epsilon.value = epsilon_value * j / refinements
200
- marker(region, 0.00247262315663, maxLevel=refinements) # 1 epsilon
201
-
202
- adapt(gridView.hierarchicalGrid)
203
-
204
- h_min = h_max * 0.5 ** (j / 2)
205
- epsilon = get_eps(h_min)
206
-
207
- omega.epsilon = epsilon
208
- domain = omega
197
+ gridView = GridView(
198
+ domain,
199
+ omega,
200
+ filterTolerance=10 * omega.epsilon.value,
201
+ factor=radius,
202
+ refinements=refinements,
203
+ adaptLevels=adaptLevels,
204
+ )
205
+ h_min = h_max * 0.5 ** (refinements / 2)
206
+ omega.epsilon = get_eps(h_min)
207
+ else:
208
+ gridView = GridView(
209
+ domain,
210
+ omega,
211
+ filterTolerance=10 * omega.epsilon.value,
212
+ )
209
213
 
210
214
  domain = DomainDune(omega, gridView)
211
- domain.adapt(level=adaptLevels)
212
215
 
213
216
  print(
214
- f"h_max={h_max}, h_min={h_min * 0.5 ** (adaptLevels / 2)}, epsilon={epsilon.value}"
217
+ f"h_max={h_max}, h_min={h_min * 0.5 ** (adaptLevels / 2)}, epsilon={omega.epsilon.value}"
215
218
  )
216
219
 
217
220
  return gridView, domain
@@ -7,6 +7,10 @@ except ImportError:
7
7
 
8
8
  try:
9
9
  import dune
10
+ from dune.fem import adapt, mark, markNeighbors
11
+ from dune.fem.function import gridFunction
12
+ from dune.fem.view import adaptiveLeafGridView, filteredGridView
13
+ from dune.alugrid import aluConformGrid as leafGridView
10
14
  except ImportError:
11
15
  print(
12
16
  """
@@ -15,16 +19,12 @@ pip install dune-fem
15
19
  """
16
20
  )
17
21
 
18
- from dune.alugrid import aluConformGrid as leafGridView
19
- from dune.fem import adapt, mark, markNeighbors
20
- from dune.fem.function import gridFunction
21
- from dune.fem.space import lagrange
22
- from dune.fem.utility import gridWidth
23
- from dune.fem.view import adaptiveLeafGridView
22
+
24
23
  from dune.grid import cartesianDomain
25
24
  from dune.ufl import Constant, Space
26
- from ufl import SpatialCoordinate, as_vector, sqrt
25
+ from ufl import SpatialCoordinate, sqrt
27
26
 
27
+ from ddfem import GridView
28
28
  from ddfem import geometry as gm
29
29
  from ddfem.geometry.domain_dune import DomainDune
30
30
 
@@ -37,16 +37,17 @@ def getDomain(initialRefine, version, adaptLevels=0, epsFactor=4.5, dirichlet=Tr
37
37
 
38
38
  if dirichlet:
39
39
  domain_range = [
40
- [-0.8 + shiftx, -0.8 + shifty, 0.1], # -0.5
41
- [0.8 + shiftx, 0.8 + shifty, 3.3], # 3.2
40
+ [-0.75 + shiftx, -0.75 + shifty, 0.1], # -0.5
41
+ [0.75 + shiftx, 0.75 + shifty, 3.3], # 3.2
42
42
  ]
43
- initial_gridsize = [60, 60, 60]
43
+ # initial_gridsize = [60, 60, 60]
44
+ initial_gridsize = [25, 25, 25]
44
45
  else:
45
46
  domain_range = [
46
- [-0.8 + shiftx, -0.8 + shifty, 0.0 - 0.5],
47
- [0.8 + shiftx, 0.8 + shifty, 3.2 + 0.5],
47
+ [-0.75 + shiftx, -0.75 + shifty, 0.0 - 0.25],
48
+ [0.75 + shiftx, 0.75 + shifty, 3.2 + 0.25],
48
49
  ]
49
- initial_gridsize = [60, 60, 80]
50
+ initial_gridsize = [25, 25, 40]
50
51
  initial_gridsize = [i * 2**initialRefine for i in initial_gridsize]
51
52
  h = sqrt(
52
53
  ((domain_range[1][0] - domain_range[0][0]) / initial_gridsize[0]) ** 2
@@ -69,16 +70,16 @@ def getDomain(initialRefine, version, adaptLevels=0, epsFactor=4.5, dirichlet=Tr
69
70
 
70
71
  face_2d.name = "beam"
71
72
 
72
- if dirichlet:
73
+ if dirichlet and not version == "fitted":
73
74
  length = 4
74
75
  else:
75
76
  length = 3.2
76
77
  omega = face_2d.extrude(length, True)
77
78
  omega.name = "full"
78
79
 
79
- h_max = h * 3
80
- h_min = h / 2
81
- radius = 3
80
+ h_max = h * 4
81
+ h_min = h / 3
82
+ radius = 0.5 # 3
82
83
 
83
84
  x = SpatialCoordinate(Space(3))
84
85
  sdf = omega(x)
@@ -87,28 +88,39 @@ def getDomain(initialRefine, version, adaptLevels=0, epsFactor=4.5, dirichlet=Tr
87
88
  r_min = epsilon.value
88
89
  r_max = radius * epsilon.value
89
90
  dist = np.abs(sdf((x, y, z)))
90
- if dist <= r_min:
91
- return geom.characteristic_length_min
92
- elif dist >= r_max:
93
- return geom.characteristic_length_max
94
- else:
91
+
92
+ gmax = geom.characteristic_length_max
93
+ gmin = geom.characteristic_length_min
94
+
95
+ if False:
95
96
  # Linear
96
- m = (geom.characteristic_length_max - geom.characteristic_length_min) / (
97
- r_max - r_min
98
- )
99
- return m * (dist - r_min) + geom.characteristic_length_min
97
+ if dist <= r_min:
98
+ return gmin
99
+ elif dist >= r_max:
100
+ return gmax
101
+ else:
102
+ m = (gmax - gmin) / (r_max - r_min)
103
+ return m * (dist - r_min) + gmin
104
+
105
+ else:
106
+ # Exponential
107
+ R = int(3 * np.log2(gmax / gmin))
108
+ j = max(0, min(R, (dist * R) / r_max - 0.5))
109
+ # j = max(0, min(R, np.floor(dist * R / r_max)))
110
+ return gmax * 0.5 ** ((R - j) / 3)
111
+
112
+ omega.epsilon = get_eps(h_min)
100
113
 
101
114
  if version == "cartesian":
115
+ omega.epsilon = get_eps(h)
102
116
  domain = cartesianDomain(*domain_range, initial_gridsize)
103
- epsilon = get_eps(h)
104
117
 
105
118
  elif version == "fitted":
106
119
  if pygmsh is None:
107
120
  raise AttributeError("'fitted' requires install pygmsh")
108
121
  with pygmsh.occ.Geometry() as geom:
109
- geom.characteristic_length_max = h_max
110
- geom.characteristic_length_min = h_min
111
- epsilon = get_eps(h_min)
122
+ geom.characteristic_length_max = h_max / sqrt(2)
123
+ geom.characteristic_length_min = h_min / sqrt(2)
112
124
 
113
125
  disks = [geom.add_disk([c[1][0], c[1][1], 0.0], c[0]) for c in balls]
114
126
 
@@ -117,7 +129,7 @@ def getDomain(initialRefine, version, adaptLevels=0, epsFactor=4.5, dirichlet=Tr
117
129
  geom.extrude(shape, [0, 0, length])
118
130
 
119
131
  geom.set_mesh_size_callback(
120
- lambda dim, tag, x, y, z, lc: spacing(x, y, z, epsilon),
132
+ lambda dim, tag, x, y, z, lc: spacing(x, y, z, omega.epsilon),
121
133
  ignore_other_mesh_sizes=True,
122
134
  )
123
135
  mesh = geom.generate_mesh()
@@ -135,9 +147,8 @@ def getDomain(initialRefine, version, adaptLevels=0, epsFactor=4.5, dirichlet=Tr
135
147
  if pygmsh is None:
136
148
  raise AttributeError("'gmsh_adaptive' requires install pygmsh")
137
149
  with pygmsh.occ.Geometry() as geom:
138
- geom.characteristic_length_max = h_max
139
- geom.characteristic_length_min = h_min
140
- epsilon = get_eps(h_min)
150
+ geom.characteristic_length_max = h_max / sqrt(2)
151
+ geom.characteristic_length_min = h_min / sqrt(2)
141
152
 
142
153
  geom.add_box(
143
154
  [0.0, 0.0, 0.0],
@@ -149,7 +160,7 @@ def getDomain(initialRefine, version, adaptLevels=0, epsFactor=4.5, dirichlet=Tr
149
160
  )
150
161
 
151
162
  geom.set_mesh_size_callback(
152
- lambda dim, tag, x, y, z, lc: spacing(x, y, z, epsilon),
163
+ lambda dim, tag, x, y, z, lc: spacing(x, y, z, omega.epsilon),
153
164
  ignore_other_mesh_sizes=True,
154
165
  )
155
166
  mesh = geom.generate_mesh()
@@ -161,48 +172,47 @@ def getDomain(initialRefine, version, adaptLevels=0, epsFactor=4.5, dirichlet=Tr
161
172
  else:
162
173
  raise ValueError("invalid mesh type")
163
174
 
164
- gridView = adaptiveLeafGridView(leafGridView(domain))
165
- # return gridView, None
166
-
167
175
  if version == "dune_adaptive":
168
- # omega.epsilon = get_eps(h)
176
+ refinements = int(3 * np.log2(h_max / h_min))
177
+ gridView = GridView(
178
+ domain,
179
+ omega,
180
+ factor=radius,
181
+ refinements=refinements,
182
+ adaptLevels=adaptLevels,
183
+ filterTolerance=0.08,
184
+
185
+ )
186
+ h_min = h_max * 0.5 ** (refinements/3+1)
187
+ omega.epsilon.value = get_eps(h_min).value
188
+ """
189
+ gridView = adaptiveLeafGridView(leafGridView(domain))
169
190
  omega.epsilon = get_eps(h_min)
170
191
  omega.epsilon.value *= radius
171
192
  epsilon_value = omega.epsilon.value
172
-
173
193
  marker = mark
174
-
175
194
  refinements = int(3 * np.log2(h_max / h_min))
176
195
  region = gridFunction(
177
196
  omega.phi(x) * (1 - omega.phi(x)), gridView=gridView
178
197
  ) # interface
179
-
180
- for j in range(1, refinements + 1):
181
- print("refining:", j, gridView.size(2), flush=True)
182
- if gridView.size(2) > 5e5:
183
- assert j == refinements
184
- j -= 1
185
- break
198
+ for j in range(1, refinements-1):
199
+ print("refining:", j, gridView.size(3), flush=True)
200
+ # if gridView.size(3) > 1e5:
201
+ # break
186
202
  omega.epsilon.value = epsilon_value * j / refinements
187
203
  marker(region, 0.00247262315663, maxLevel=refinements) # epsilon
188
204
  adapt(gridView.hierarchicalGrid)
189
-
190
- # markNeighbors(region, 0.1, maxLevel=refinements)
191
- # marker(region, 0.2, maxLevel=refinements)
192
- # adapt(gridView.hierarchicalGrid)
193
- # omega.epsilon.value = omega.epsilon.value * 2**(-1/3)
194
-
195
- h_min = h_max * 0.5 ** (j / 3)
196
- epsilon = get_eps(h_min)
197
-
198
- omega.epsilon = epsilon
199
- domain = omega
205
+ h_min = h_max * 0.5 ** (refinements/3)
206
+ omega.epsilon.value = get_eps(h_min).value
207
+ gridView = filteredGridView(gridView, lambda e:1, 1, useFilteredIndexSet=True)
208
+ """
209
+ else:
210
+ gridView = GridView(domain)
200
211
 
201
212
  domain = DomainDune(omega, gridView)
202
- # domain.adapt(level=adaptLevels)
203
213
 
204
214
  print(
205
- f"h_max={h_max}, h_min={h_min * 0.5 ** (adaptLevels / 3)}, epsilon={epsilon.value}"
215
+ f"h_max={h_max}, h_min={h_min * 0.5 ** (adaptLevels / 2)}, epsilon={omega.epsilon.value}"
206
216
  )
207
217
 
208
218
  return gridView, domain
@@ -0,0 +1,78 @@
1
+ Metadata-Version: 2.4
2
+ Name: ddfem
3
+ Version: 1.0.11
4
+ Summary: Diffuse domain finite element solver
5
+ Author-email: Luke Benfield <luke.benfield@warwick.ac.uk>, Andreas Dedner <a.s.dedner@warwick.ac.uk>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://gitlab.dune-project.org/dune-fem/ddfem
8
+ Project-URL: Issues, https://gitlab.dune-project.org/dune-fem/ddfem/-/issues
9
+ Project-URL: Documentation, https://ddfem.readthedocs.io/en/latest/index.html
10
+ Project-URL: Repository, https://gitlab.dune-project.org/dune-fem/ddfem.git
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: fenics-ufl==2022.2.0
17
+ Requires-Dist: numpy
18
+ Requires-Dist: setuptools<79.1
19
+ Provides-Extra: dune
20
+ Requires-Dist: dune-fem==2.11.dev20250709; extra == "dune"
21
+ Requires-Dist: dune_alugrid==2.11.dev20250709; extra == "dune"
22
+ Requires-Dist: dune_common==2.11.dev20250709; extra == "dune"
23
+ Requires-Dist: dune_fem-dg==2.11.dev20250709; extra == "dune"
24
+ Requires-Dist: dune_geometry==2.11.dev20250709; extra == "dune"
25
+ Requires-Dist: dune_grid==2.11.dev20250709; extra == "dune"
26
+ Requires-Dist: dune_istl==2.11.dev20250709; extra == "dune"
27
+ Requires-Dist: dune_localfunctions==2.11.dev20250709; extra == "dune"
28
+ Requires-Dist: pygmsh; extra == "dune"
29
+ Provides-Extra: doc
30
+ Requires-Dist: jupyter; extra == "doc"
31
+ Requires-Dist: jupytext; extra == "doc"
32
+ Requires-Dist: nbsphinx; extra == "doc"
33
+ Requires-Dist: sphinx_rtd_theme; extra == "doc"
34
+ Requires-Dist: twine; extra == "doc"
35
+ Requires-Dist: build; extra == "doc"
36
+ Provides-Extra: dev
37
+ Requires-Dist: ddfem[doc,dune]; extra == "dev"
38
+ Dynamic: license-file
39
+
40
+ # Diffuse Domain Finite Element Methods
41
+
42
+ [ddfem][0] is a Python package that simplifies the transformation
43
+ of a wide range of PDEs using the Diffuse Domain Method.
44
+ While the original PDE will often be defined on a complex domain,
45
+ after the transformation it can be solved on simple e.g. square domain.
46
+ The original geometry is embedded in the simpler domain using
47
+ a phase-field function representation.
48
+ We provide implementations for different versions of the Diffuse Domain Method
49
+ making it easy to compare and chose the most suitable version for the problem at hand.
50
+ Adding new versions is also straightforward.
51
+ Furthermore, we provide a new approach
52
+ to combine multiple boundary conditions
53
+ of different types on distinct boundary segments.
54
+
55
+ The geometry subpackage provides several simple signed distance functions (SDF),
56
+ and operators to allow an easy definition of the complex domain.
57
+
58
+ We have designed the package to have a wide compatibility with existing finite element solvers,
59
+ as all transformations are performed using the Unified Form Language,
60
+ [UFL][2] and do not require any other external packages.
61
+
62
+ While not required, we recommend using [Dune-Fem][1]
63
+ as it enables some optimisations for form compiling,
64
+ and can improve the mesh by utilising the different grid views.
65
+ We have used this package to test the package and
66
+ for all examples used throughout this tutorial.
67
+
68
+ ## Getting started
69
+
70
+ How to install the package using `pip` is discussed in our [tutorial][4].
71
+
72
+ Enjoy - and let us know of any [issues][3] you encountered
73
+
74
+ [0]: https://ddfem.readthedocs.io/en/latest/index.html
75
+ [1]: https://www.dune-project.org/modules/dune-fem/
76
+ [2]: https://github.com/FEniCS/ufl
77
+ [3]: https://gitlab.dune-project.org/dune-fem/ddfem/-/issues
78
+ [4]: https://ddfem.readthedocs.io/en/latest/installation.html