Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Density #111

Merged
merged 17 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,29 @@ dmypy.json

# Pyre type checker
.pyre/

# LaTex files
## Do not ignore the documentation document
!documentation/main.pdf

## Core latex/pdflatex auxiliary files:
*.aux
*.lof
*.log
*.lot
*.fls
*.out
*.toc
*.fmt
*.fot
*.cb
*.cb2
.*.lb

## Build tool auxiliary files:
*.fdb_latexmk
*.synctex
*.synctex(busy)
*.synctex.gz
*.synctex.gz(busy)
*.pdfsync
21 changes: 19 additions & 2 deletions conmech/dynamics/dynamics.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ def __init__(
self.acceleration_operator: np.ndarray
self.elasticity: np.ndarray
self.viscosity: np.ndarray
self._w_matrix = None
self._w_matrix: np.ndarray = None
self._local_stifness_matrices: np.ndarray = None
self.__relaxation: Optional[np.ndarray] = None
self.__relaxation_tensor: Optional[float] = None
self.thermal_expansion: np.ndarray
Expand All @@ -107,14 +108,19 @@ def remesh(self, boundaries_description, create_in_subprocess):
super().mesh.remesh(boundaries_description, create_in_subprocess)
self.reinitialize_matrices()

def reinitialize_matrices(self):
def reinitialize_matrices(self, elements_density: Optional[np.ndarray] = None):
(
self.element_initial_volume,
self.volume_at_nodes,
U,
V,
self._w_matrix,
self._local_stifness_matrices,
) = get_basic_matrices(elements=self.mesh.elements, nodes=self.moved_nodes)

if elements_density is not None:
self._w_matrix = self.asembly_w_matrix_with_density(elements_density)

(
self.acceleration_operator,
self.elasticity,
Expand Down Expand Up @@ -165,6 +171,17 @@ def reinitialize_matrices(self):
free_indices=self.mesh.free_indices,
)

def asembly_w_matrix_with_density(self, elements_density: np.ndarray):
w_matrix = np.zeros_like(self._w_matrix)
for element_index, element in enumerate(self.mesh.elements):
for i, global_i in enumerate(element):
for j, global_j in enumerate(element):
w_matrix[:, :, global_i, global_j] += (
elements_density[element_index]
* self._local_stifness_matrices[:, :, element_index, i, j]
)
return w_matrix

@property
def with_temperature(self):
return isinstance(self.body_prop, TemperatureBodyProperties)
Expand Down
27 changes: 23 additions & 4 deletions conmech/dynamics/factory/_dynamics_factory_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ def get_edges_features_matrix_numba(elements, nodes):
(FEATURE_MATRIX_COUNT, nodes_count, nodes_count), dtype=np.double
)
element_initial_volume = np.zeros(elements_count)
# Local stifness matrices (w[0, 0], w[0, 1], w[1, 0], w[1, 1]) per mesh element
# Detailed description can be found in [LSM] Local stifness matrix
local_stifness_matrices = np.empty(
(DIMENSION, DIMENSION, elements_count, element_size, element_size)
)

for element_index in range(elements_count): # TODO: #65 prange?
element = elements[element_index]
Expand All @@ -40,9 +45,21 @@ def get_edges_features_matrix_numba(elements, nodes):
)
int_matrix = np.array(
[
[0, 1 / 6 * element_nodes[:, 0].sum(), 1 / 6 * element_nodes[:, 1].sum()],
[1 / 6 * element_nodes[:, 0].sum(), 1 / 12 * int_sqr[0], 1 / 24 * int_xy],
[1 / 6 * element_nodes[:, 1].sum(), 1 / 24 * int_xy, 1 / 12 * int_sqr[1]],
[
0,
1 / 6 * element_nodes[:, 0].sum(),
1 / 6 * element_nodes[:, 1].sum(),
],
[
1 / 6 * element_nodes[:, 0].sum(),
1 / 12 * int_sqr[0],
1 / 24 * int_xy,
],
[
1 / 6 * element_nodes[:, 1].sum(),
1 / 24 * int_xy,
1 / 12 * int_sqr[1],
],
]
)
jacobian = np.abs(np.linalg.det(element_nodes[1:] - element_nodes[0]))
Expand Down Expand Up @@ -85,6 +102,8 @@ def get_edges_features_matrix_numba(elements, nodes):

w = [[i_d_phi * j_d_phi for j_d_phi in j_d_phi_vec] for i_d_phi in i_d_phi_vec]

local_stifness_matrices[:, :, element_index, i, j] = element_volume * np.asarray(w)

edges_features_matrix[:, element[i], element[j]] += element_volume * np.array(
[
volume_at_nodes,
Expand All @@ -100,7 +119,7 @@ def get_edges_features_matrix_numba(elements, nodes):
)

# Performance TIP: we need only sparse, triangular matrix (?)
return edges_features_matrix, element_initial_volume
return edges_features_matrix, element_initial_volume, local_stifness_matrices


@numba.njit
Expand Down
3 changes: 2 additions & 1 deletion conmech/dynamics/factory/_dynamics_factory_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ def get_edges_features_matrix_numba(elements, nodes):
]
)

return edges_features_matrix, element_initial_volume
# TODO: #115 compute local_stifness_matrices which should be returned as 3rd value
return edges_features_matrix, element_initial_volume, None
wprzadka marked this conversation as resolved.
Show resolved Hide resolved


@numba.njit
Expand Down
10 changes: 6 additions & 4 deletions conmech/dynamics/factory/dynamics_factory_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ def get_basic_matrices(elements: np.ndarray, nodes: np.ndarray):
dimension = len(elements[0]) - 1
factory = get_factory(dimension)

edges_features_matrix, element_initial_volume = factory.get_edges_features_matrix(
elements, nodes
)
(
edges_features_matrix,
element_initial_volume,
local_stifness_matrices,
) = factory.get_edges_features_matrix(elements, nodes)

volume_at_nodes = edges_features_matrix[0]
U = edges_features_matrix[1]
Expand All @@ -42,7 +44,7 @@ def get_basic_matrices(elements: np.ndarray, nodes: np.ndarray):
for k in range(factory.dimension)
]
)
return element_initial_volume, volume_at_nodes, U, V, W
return element_initial_volume, volume_at_nodes, U, V, W, local_stifness_matrices
wprzadka marked this conversation as resolved.
Show resolved Hide resolved


def get_dynamics(elements: np.ndarray, body_prop: BodyProperties, U, V, W):
Expand Down
10 changes: 10 additions & 0 deletions conmech/simulations/problem_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ def solving_method(self, value: str) -> None:
self.__set_step_solver(value)
self.__set_second_step_solver(value)

def refresh_solvers(self):
self.__set_step_solver(self.solving_method)
self.__set_second_step_solver(self.solving_method)

def __set_step_solver(self, value):
solver_class: Type[Solver] = SolversRegistry.get_by_name(
solver_name=value, problem=self.problem
Expand Down Expand Up @@ -376,6 +380,12 @@ def solve(self, *, initial_displacement: Callable, verbose: bool = False, **kwar
return state


class NonHomogenousSolver(StaticSolver):
def update_density(self, density: np.ndarray):
self.body.reinitialize_matrices(density)
self.refresh_solvers()


class QuasistaticRelaxation(ProblemSolver):
def __init__(self, setup: RelaxationQuasistaticProblem, solving_method: str):
"""Solves general Contact Mechanics problem.
Expand Down
Binary file added documentation/main.pdf
Binary file not shown.
29 changes: 29 additions & 0 deletions documentation/main.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
\documentclass{article}

\usepackage{url}
\usepackage{amsmath}


\title{Conmech documentation}

\begin{document}

\maketitle

\subsection*{[LSM] Local stifness matrix}

\[
w_e^{kl} = \left[
\int_{T_e} \frac{\partial \phi_i}{\partial x_k}\frac{\partial \phi_j}{\partial x_l}dx
\right]_{i,j=1, \dots, N_e} \qquad \forall k,l \in \{1, 2\}
\]

\begin{tabular}{ll}
Where & $e$ is the index of the element\\
& $N_e$ is number of vertices of element $e$\\
& $T_e$ is the surface of the mesh element $e$\\
& $\phi_j$ is $j$-th base function of the element $e$
\end{tabular}


\end{document}
63 changes: 63 additions & 0 deletions examples/example_density.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""
Created at 02.09.2023
"""
from dataclasses import dataclass

import numpy as np
from conmech.helpers.config import Config
from conmech.mesh.boundaries_description import BoundariesDescription
from conmech.plotting.drawer import Drawer
from conmech.scenarios.problems import StaticDisplacementProblem
from conmech.simulations.problem_solver import NonHomogenousSolver

from examples.p_slope_contact_law import make_slope_contact_law


@dataclass
class StaticSetup(StaticDisplacementProblem):
grid_height: ... = 1.0
elements_number: ... = (2, 5)
mu_coef: ... = 4
la_coef: ... = 4
contact_law: ... = make_slope_contact_law(slope=1)

@staticmethod
def inner_forces(x, t=None):
return np.array([0, 0])

@staticmethod
def outer_forces(x, t=None):
return np.array([0, 0.1]) if x[1] < 0.2 and x[0] > 2.2 else np.array([0, 0])

@staticmethod
def friction_bound(u_nu: float) -> float:
return 0

boundaries: ... = BoundariesDescription(
contact=lambda x: x[1] == 0 and x[0] < 0.2, dirichlet=lambda x: x[0] == 0
)


def main(config: Config):
"""
Entrypoint to example.

To see result of simulation you need to call from python `main(Config().init())`.
"""
setup = StaticSetup(mesh_type="cross")
runner = NonHomogenousSolver(setup, "schur")

elem_centers = np.empty(shape=(len(runner.body.mesh.elements), 2))
for idx, elem in enumerate(runner.body.mesh.elements):
verts = runner.body.mesh.initial_nodes[elem]
elem_centers[idx] = np.sum(verts, axis=0) / len(elem)
density = np.asarray([1 if x[0] < 1 else 0.2 for x in elem_centers])

runner.update_density(density)

state = runner.solve(verbose=True, initial_displacement=setup.initial_displacement)
Drawer(state=state, config=config).draw(show=config.show, save=config.save)


if __name__ == "__main__":
main(Config().init())
8 changes: 6 additions & 2 deletions tests/test_conmech/unit_test/test_matrices.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ def test_matrices_2d_integrals():
)

# Act
edges_features_matrix, element_initial_volume = sut_2d(elements=elements, nodes=initial_nodes)
edges_features_matrix, element_initial_volume, _ = sut_2d(
elements=elements, nodes=initial_nodes
)

# Assert
np.testing.assert_allclose(element_initial_volume.sum(), area)
Expand Down Expand Up @@ -50,7 +52,9 @@ def test_matrices_3d_integrals():
)

# Act
edges_features_matrix, element_initial_volume = sut_3d(elements=elements, nodes=initial_nodes)
edges_features_matrix, element_initial_volume, _ = sut_3d(
elements=elements, nodes=initial_nodes
)

# Assert
np.testing.assert_allclose(element_initial_volume.sum(), 1)
Expand Down
Loading