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

Add mechanics submodule: SolidBody and SolidBodyPressure #216

Merged
merged 24 commits into from
May 2, 2022
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
split solidbody source files
adtzlr committed May 2, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 38b348a932fa292783a26a774724f997214a437f
3 changes: 2 additions & 1 deletion felupe/mechanics/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from ._solidbody import SolidBody, SolidBodyPressure
from ._solidbody import SolidBody
from ._solidbody_pressure import SolidBodyPressure
61 changes: 61 additions & 0 deletions felupe/mechanics/_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
"""
_______ _______ ___ __ __ _______ _______
| || || | | | | || || |
| ___|| ___|| | | | | || _ || ___|
| |___ | |___ | | | |_| || |_| || |___
| ___|| ___|| |___ | || ___|| ___|
| | | |___ | || || | | |___
|___| |_______||_______||_______||___| |_______|

This file is part of felupe.

Felupe is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Felupe is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Felupe. If not, see <http://www.gnu.org/licenses/>.

"""


class Assemble:
"A class with assembly methods of a SolidBody."

def __init__(self, vector, matrix):
self.vector = vector
self.matrix = matrix


class Evaluate:
"A class with evaluate methods of a SolidBody."

def __init__(self, gradient, hessian, cauchy_stress=None):
self.gradient = gradient
self.hessian = hessian

if cauchy_stress is not None:
self.cauchy_stress = cauchy_stress


class Results:
"A class with intermediate results of a SolidBody."

def __init__(self, stress=False, elasticity=False):

self.force = None
self.stiffness = None
self.kinematics = None

if stress:
self.stress = None

if elasticity:
self.elasticity = None
143 changes: 1 addition & 142 deletions felupe/mechanics/_solidbody.py
Original file line number Diff line number Diff line change
@@ -29,148 +29,7 @@
from .._assembly import IntegralForm, IntegralFormMixed, IntegralFormAxisymmetric
from ..constitution import AreaChange
from ..math import inv, dot


class Assemble:
"A class with assembly methods of a SolidBody."

def __init__(self, vector, matrix):
self.vector = vector
self.matrix = matrix


class Evaluate:
"A class with evaluate methods of a SolidBody."

def __init__(self, gradient, hessian, cauchy_stress=None):
self.gradient = gradient
self.hessian = hessian

if cauchy_stress is not None:
self.cauchy_stress = cauchy_stress


class Results:
"A class with intermediate results of a SolidBody."

def __init__(self, stress=False, elasticity=False):

self.force = None
self.stiffness = None
self.kinematics = None

if stress:
self.stress = None

if elasticity:
self.elasticity = None


class SolidBodyPressure:
"A hydrostatic pressure boundary on a SolidBody."

def __init__(self, field):

self.field = field

self._dV = self.field.region.dV
self._normals = self.field.region.normals

self.results = Results()
self.results.kinematics = self._extract(self.field)
self.assemble = Assemble(vector=self._vector, matrix=self._matrix)

self._form = {
Field: IntegralForm,
FieldMixed: IntegralFormMixed,
FieldsMixed: IntegralFormMixed,
FieldAxisymmetric: IntegralFormAxisymmetric,
}[type(self.field)]

self._kwargs = {
Field: dict(dV=self._dV, grad_v=True, grad_u=True),
FieldMixed: dict(dV=self._dV),
FieldsMixed: dict(dV=self._dV),
FieldAxisymmetric: dict(dV=self._dV, grad_v=True, grad_u=True),
}[type(self.field)]

self._IntForm = {
Field: IntegralForm,
FieldAxisymmetric: IntegralFormAxisymmetric,
}[type(self.field)]

self._area_change = AreaChange()

def _extract(self, field):

self.field = field
self.results.kinematics = (self.field.extract(),)

return self.results.kinematics

def _vector(self, field=None, pressure=1, parallel=False, jit=False, resize=None):

if field is not None:
self.field = field
self.results.kinematics = self._extract(field)

self.results.pressure = pressure

fun = pressure * self._area_change.function(
*self.results.kinematics,
self._normals,
parallel=parallel,
)

self.results.force = self._IntForm(
fun=fun, v=self.field, dV=self._dV, grad_v=False
).assemble(parallel=parallel, jit=jit)

if resize is not None:
self.results.force.resize(*resize.shape)

return self.results.force

def _matrix(self, field=None, pressure=1, parallel=False, jit=False, resize=None):

if field is not None:
self.field = field
self.results.kinematics = self._extract(field)

self.results.pressure = pressure

fun = pressure * self._area_change.gradient(
*self.results.kinematics,
self._normals,
parallel=parallel,
)
self.results.stiffness = self._IntForm(
fun=fun,
v=self.field,
u=self.field,
dV=self._dV,
grad_v=False,
grad_u=True,
).assemble(parallel=parallel, jit=jit)

if resize is not None:
self.results.stiffness.resize(*resize.shape)

return self.results.stiffness

def update(self, other_field, field=None):

if field is not None:
self.field = field

if isinstance(other_field, FieldMixed) or isinstance(other_field, FieldsMixed):
self.field.values = other_field[0].values
else:
self.field.values = other_field.values

self.results.kinematics = self._extract(self.field)

return self.field
from ._helpers import Assemble, Evaluate, Results


class SolidBody:
138 changes: 138 additions & 0 deletions felupe/mechanics/_solidbody_pressure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# -*- coding: utf-8 -*-
"""
_______ _______ ___ __ __ _______ _______
| || || | | | | || || |
| ___|| ___|| | | | | || _ || ___|
| |___ | |___ | | | |_| || |_| || |___
| ___|| ___|| |___ | || ___|| ___|
| | | |___ | || || | | |___
|___| |_______||_______||_______||___| |_______|

This file is part of felupe.

Felupe is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Felupe is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Felupe. If not, see <http://www.gnu.org/licenses/>.

"""

from .._field import Field, FieldMixed, FieldsMixed, FieldAxisymmetric
from .._assembly import IntegralForm, IntegralFormMixed, IntegralFormAxisymmetric
from ..constitution import AreaChange
from ._helpers import Assemble, Results


class SolidBodyPressure:
"A hydrostatic pressure boundary on a SolidBody."

def __init__(self, field):

self.field = field

self._dV = self.field.region.dV
self._normals = self.field.region.normals

self.results = Results()
self.results.kinematics = self._extract(self.field)
self.assemble = Assemble(vector=self._vector, matrix=self._matrix)

self._form = {
Field: IntegralForm,
FieldMixed: IntegralFormMixed,
FieldsMixed: IntegralFormMixed,
FieldAxisymmetric: IntegralFormAxisymmetric,
}[type(self.field)]

self._kwargs = {
Field: dict(dV=self._dV, grad_v=True, grad_u=True),
FieldMixed: dict(dV=self._dV),
FieldsMixed: dict(dV=self._dV),
FieldAxisymmetric: dict(dV=self._dV, grad_v=True, grad_u=True),
}[type(self.field)]

self._IntForm = {
Field: IntegralForm,
FieldAxisymmetric: IntegralFormAxisymmetric,
}[type(self.field)]

self._area_change = AreaChange()

def _extract(self, field):

self.field = field
self.results.kinematics = (self.field.extract(),)

return self.results.kinematics

def _vector(self, field=None, pressure=1, parallel=False, jit=False, resize=None):

if field is not None:
self.field = field
self.results.kinematics = self._extract(field)

self.results.pressure = pressure

fun = pressure * self._area_change.function(
*self.results.kinematics,
self._normals,
parallel=parallel,
)

self.results.force = self._IntForm(
fun=fun, v=self.field, dV=self._dV, grad_v=False
).assemble(parallel=parallel, jit=jit)

if resize is not None:
self.results.force.resize(*resize.shape)

return self.results.force

def _matrix(self, field=None, pressure=1, parallel=False, jit=False, resize=None):

if field is not None:
self.field = field
self.results.kinematics = self._extract(field)

self.results.pressure = pressure

fun = pressure * self._area_change.gradient(
*self.results.kinematics,
self._normals,
parallel=parallel,
)
self.results.stiffness = self._IntForm(
fun=fun,
v=self.field,
u=self.field,
dV=self._dV,
grad_v=False,
grad_u=True,
).assemble(parallel=parallel, jit=jit)

if resize is not None:
self.results.stiffness.resize(*resize.shape)

return self.results.stiffness

def update(self, other_field, field=None):

if field is not None:
self.field = field

if isinstance(other_field, FieldMixed) or isinstance(other_field, FieldsMixed):
self.field.values = other_field[0].values
else:
self.field.values = other_field.values

self.results.kinematics = self._extract(self.field)

return self.field
10 changes: 8 additions & 2 deletions tests/test_mechanics.py
Original file line number Diff line number Diff line change
@@ -61,8 +61,8 @@ def test_pressure():
umat = fe.LinearElastic(E=1, nu=0.3)

m = fe.Cube(n=3)
r = fe.RegionHexahedron(m)
u = fe.Field(r, dim=3)
h = fe.RegionHexahedron(m)
u = fe.Field(h, dim=3)

u.values = np.random.rand(*u.values.shape) / 10

@@ -99,6 +99,12 @@ def test_pressure():
c.update(u, v)
assert np.allclose(u.values, v.values)

w = fe.FieldsMixed(h)
w[0].values = np.random.rand(*w[0].values.shape) / 10

c.update(w, v)
assert np.allclose(w[0].values, v.values)


def pre(dim):