jax-am
jax-am copied to clipboard
Tolerances in load boundary condition definitions
Hello,
I'm currently working on implementing point loads in FEM simulations using your library and have some questions about the tolerance (atol
) used for defining load boundary conditions. I noticed that in some examples, including applications/fem/top_opt/box.py
, the load location function uses certain constants multiplied by the domain dimensions:
Lx, Ly, Lz = 2., 0.5, 1.
Nx, Ny, Nz = 80, 20, 40
meshio_mesh = box_mesh(Nx, Ny, Nz, Lx, Ly, Lz, data_path)
jax_mesh = Mesh(meshio_mesh.points, meshio_mesh.cells_dict['hexahedron'])
def fixed_location(point):
return np.isclose(point[0], 0., atol=1e-5)
# Note the tolerance here:
def load_location(point):
return np.logical_and(np.isclose(point[0], Lx, atol=1e-5), np.isclose(point[2], 0., atol=0.1*Lz+1e-5))
def dirichlet_val(point):
return 0.
def neumann_val(point):
return np.array([0., 0., -1e6])
From my understanding, there are two factors to consider when determining this tolerance. First, we need the tolerance (atol = c*Lz
) to be larger than the mesh edge length (dz = Lz/Nz
) to ensure that at least one node falls within this range. However, I also understand that the multiplication factor c
should ideally be decoupled from the mesh resolution to ensure consistent results across different mesh sizes.
Could you provide some guidance on choosing suitable tolerances and discuss any recommended practices or considerations? For instance, is there an optimal range or formula to calculate c
in relation to the mesh size or problem scale?
Also, I'm curious if there might be a more systematic way to handle this tolerance selection within the library itself, such as by providing a helper function to calculate suitable tolerances based on mesh size and problem scale. I believe this would greatly assist users in correctly applying loads and constraints to their simulations.
Thank you in advance for your help and guidance. I appreciate your work on this library and look forward to your response.
Thanks for your interest. We purposely let users handle atol
(rather than define it in a systematic way) since this is really problem dependent, and different users may have their own needs.
For this topology optimization problem, we use 10% (0.1*Lz+1e-5
) of the boundary length to approximate a point load. Note that Neumann boundary condition (or traction force B.C.) should be applied on at least one face of an element, not on a single point. Sometimes, we need to adjust that to 5%, for example, so it is better to leave it there and let users figure out what they need.
A good practice may be to return the number of nodes (for Dirichlet condition) or number of faces (for Neumann condition) and print this information out to inform users. We will add this feature in our future version.
Thank you for the quick response. You mentioned that setting atol
to 10% approximates a concentrated force/ point load. What is the closest approximation one could get with this approach? Would it correspond to a single element face with atol
spanning 2 or 3 neighboring mesh nodes depending on the chosen element type? I agree that it might be a good idea to return the number of nodes/ faces for boundary condition, or even assert that the number is nonzero.
I have just implemented a function to print out boundary info. Please use this to check if desired boundary conditions are imposed successfully. In you application code, problem.print_BC_info()
will print some useful information.
https://github.com/tianjuxue/jax-am/blob/1d34e869cec56a846aaf1c2fa3da488cfcb00a6f/jax_am/fem/core.py#L689-L716
As for how much atol
is suitable to approximate a point load. I guess there is really no universal answer. You could do just one element face, which is perfectly legal.