Source code for felupe._assembly._integral
# -*- 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/>.
"""
import numpy as np
from scipy.sparse import bmat, vstack
from .._field._axi import FieldAxisymmetric
from .._field._base import Field
from .._field._planestrain import FieldPlaneStrain
from ._axi import IntegralFormAxisymmetric
from ._weak import WeakForm
[docs]class IntegralForm:
def __init__(self, fun, v, dV, u=None, grad_v=None, grad_u=None):
self.fun = fun
self.v = v.fields
self.nv = len(self.v)
self.dV = dV
if u is not None:
self.u = u.fields
self.nu = len(self.u)
else:
self.u = None
self.nu = None
IntForm = {
Field: WeakForm,
FieldPlaneStrain: WeakForm,
FieldAxisymmetric: IntegralFormAxisymmetric,
}[type(self.v[0])]
if isinstance(self.v[0], FieldAxisymmetric):
for i in range(1, len(self.v)):
self.v[i].radius = self.v[0].radius
if grad_v is None:
self.grad_v = np.zeros_like(self.v, dtype=bool)
self.grad_v[0] = True
else:
self.grad_v = grad_v
if grad_u is None and u is not None:
self.grad_u = np.zeros_like(self.u, dtype=bool)
self.grad_u[0] = True
else:
self.grad_u = grad_u
self.forms = []
if len(fun) == self.nv and u is None:
# LinearForm
self.mode = 1
self.i = np.arange(self.nv)
self.j = np.zeros_like(self.i)
for fun, v, grad_v in zip(self.fun, self.v, self.grad_v):
f = IntForm(fun=fun, v=v, dV=self.dV, grad_v=grad_v)
self.forms.append(f)
elif len(fun) == np.sum(1 + np.arange(self.nv)) and u is not None:
# BilinearForm
self.mode = 2
self.i, self.j = np.triu_indices(self.nv)
for a, (i, j) in enumerate(zip(self.i, self.j)):
f = IntForm(
self.fun[a],
v=self.v[i],
dV=self.dV,
u=self.u[j],
grad_v=self.grad_v[i],
grad_u=self.grad_u[j],
)
self.forms.append(f)
else:
raise ValueError("Unknown input format.")
[docs] def assemble(self, values=None, parallel=False, block=True):
out = []
if values is None:
values = [None] * len(self.forms)
for val, form in zip(values, self.forms):
out.append(form.assemble(val, parallel=parallel))
if block and self.mode == 2:
K = np.zeros((self.nv, self.nv), dtype=object)
for a, (i, j) in enumerate(zip(self.i, self.j)):
K[i, j] = out[a]
if i != j:
K[j, i] = out[a].T
return bmat(K).tocsr()
if block and self.mode == 1:
return vstack(out).tocsr()
else:
return out
[docs] def integrate(self, parallel=False):
out = []
for form in self.forms:
out.append(form.integrate(parallel=parallel))
return out