Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
37378aa
feat: add field.py file, to evaluate values
carlos-adir Feb 26, 2024
359a035
feat: implement 'eval' on field
carlos-adir Feb 26, 2024
82590f6
test: un-skip axial and bending tests
carlos-adir Feb 26, 2024
b1cbd4b
feat: add ChargedField class
carlos-adir Feb 26, 2024
24be267
feat: add functions to compute winding number
carlos-adir Feb 27, 2024
a8cfe03
feat: add open newton cotes integration quadrature
carlos-adir Feb 27, 2024
6332734
refactor: move integrate_polygon into a class
carlos-adir Feb 27, 2024
305cc59
feat: add adaptative integratior for polynomials
carlos-adir Feb 27, 2024
54db49f
test: fix circle test when compute poly integrals
carlos-adir Feb 27, 2024
46a2a80
refactor: divide Curve class in two
carlos-adir Mar 4, 2024
593cb1d
feat: add winding number on curve
carlos-adir Mar 4, 2024
17320d0
feat: add geometry.py class to store curve labels
carlos-adir Mar 5, 2024
5bf7be1
refactor: move instances tracker into abcs.py file
carlos-adir Mar 5, 2024
05279e5
refactor: move all abstract methods into abcs.py
carlos-adir Mar 5, 2024
c6142d6
refactor: rename dataio.py methods
carlos-adir Mar 5, 2024
d1761f6
refactor: update Section to use Geometry class
carlos-adir Mar 5, 2024
2e40a65
refator: rename ConnectedGeometry to Geometry
carlos-adir Mar 5, 2024
b3d57e4
feat: add abstract class for section
carlos-adir Mar 5, 2024
8982b49
feat: add 'forces' and 'momentums' on ChargedField
carlos-adir Mar 5, 2024
adf6efb
feat: implement stress evaluation for Fz, Mx, My
carlos-adir Mar 5, 2024
48c900f
refactor: divide stress and strain in eval charged
carlos-adir Mar 5, 2024
513c7ed
feat: implement eval of strain in ChargedField
carlos-adir Mar 5, 2024
2b35e92
test: refactor test to ChargedField structure
carlos-adir Mar 5, 2024
431ad79
feat: increase version to 0.4.0
carlos-adir Mar 5, 2024
cb5dffd
docs: add logo #3
carlos-adir Mar 5, 2024
a1a52c8
fix: change annotations 'tuple' to 'Tuple'
carlos-adir Mar 5, 2024
664c562
refactor: remove unnecessary code
carlos-adir Mar 5, 2024
f02b172
test: increase number of tests
carlos-adir Mar 5, 2024
618bf9f
refactor: pre-compute mesh on adaptative integration
carlos-adir Mar 5, 2024
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[![Python Versions][pyversions-img]][pyversions-url]
[![License: MIT][license-img]][license-url]

![compmec-section logo](docs/source/img/logo.svg)
![compmec-section logo](docs/source/img/logo.png)

A python package for analysis of beam sections by using Boundary Element Method.

Expand Down
Binary file added docs/source/img/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "compmec-section"
version = "0.3.0"
version = "0.4.0"
description = "Analysis of beams cross-section using the boundary element method"
authors = ["Carlos Adir <carlos.adir.leite@gmail.com>"]
readme = "README.md"
Expand Down
5 changes: 4 additions & 1 deletion src/compmec/section/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
It uses mainly curves as boundary to compute the elements.
"""

from .curve import Curve
from .dataio import JsonIO
from .geometry import Geometry
from .material import Isotropic, Material
from .section import Section

__version__ = "0.3.0"
__version__ = "0.4.0"

if __name__ == "__main__":
pass
344 changes: 344 additions & 0 deletions src/compmec/section/abcs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,344 @@
"""
File that contains base classes
"""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any, Dict, Optional, Tuple, Union


class Tracker(ABC): # pylint: disable=too-few-public-methods
"""
Parent class to track all the instances
"""

instances = {}

@classmethod
def clear(cls, keys: Optional[Tuple[int]] = None):
"""
Remove node labels
"""
if keys is None:
cls.instances.clear()
return
for key in keys:
if key in cls.instances:
cls.instances.pop(key)

@classmethod
@abstractmethod
def _next_available_key(cls) -> Any:
"""
Protected method that gives next key
"""
raise NotImplementedError

def _get_key(self) -> Any:
"""
Protected method that gives the key of the instance by iterating
on the instances dictionary

Parameters
----------

:return: The instances key from the dictionary
:rtype: Any

"""
for key, instance in self.instances.items():
if id(instance) == id(self):
return key
return None

def _set_key(self, new_key: Any):
"""
Protected method that sets a new key for the instance.
Iterates over the dictionary and changes the name.

If `None` is given, it will attribute the next available key

Parameters
----------

:param new_key: The new instance key"
:type new_key: Any

"""
cur_key = self._get_key()
if new_key is None:
new_key = self._next_available_key()
elif cur_key == new_key:
return
elif new_key in self.instances:
msg = f"Key {new_key} is already used"
raise ValueError(msg)
elif cur_key is not None:
self.instances.pop(cur_key)
self.instances[new_key] = self


class LabeledTracker(Tracker):
"""
Labeled Base Tracker, to track instances of Curve and Node
"""

@classmethod
def _next_available_key(cls) -> str:
"""
Protected method that gives next key
"""
index = 1
while index in cls.instances:
index += 1
return index

@property
def label(self) -> int:
"""
Gives the instance label

:getter: Returns the instance's label
:setter: Attribuates a new label for instance
:type: str

"""
return int(self._get_key())

@label.setter
def label(self, new_label: Union[int, None]):
if new_label is not None:
new_label = int(new_label)
self._set_key(new_label)


class NamedTracker(Tracker):
"""
Named Base Tracker, to track instances of Material, Geometry and Section
"""

@classmethod
def _next_available_key(cls) -> str:
"""
Protected method that gives next key
"""
index = 1
while f"instance-{index}" in cls.instances:
index += 1
return f"instance-{index}"

@property
def name(self) -> str:
"""
Gives the instance name

:getter: Returns the instance's name
:setter: Attribuates a new name for instance
:type: str

"""
return str(self._get_key())

@name.setter
def name(self, new_name: Union[str, None]):
if new_name is not None:
new_name = str(new_name)
self._set_key(new_name)


class ICurve(ABC):
"""
Interface abstract curve to be parent of others.

This class serves as interface between the curves from others packaged
like nurbs.Curve, to this package, expliciting the minimum requirements
of a curve must have.
With this, it's possible to implement your own type of parametric curve
"""

@classmethod
@abstractmethod
def from_dict(cls, dictionary: Dict) -> ICurve:
"""
Gives a curve instance based on the given parameters
"""
raise NotImplementedError

@abstractmethod
def to_dict(self) -> Dict:
"""
Transforms a curve instance into a dictionary
"""
raise NotImplementedError

@property
@abstractmethod
def limits(self) -> Tuple[float]:
"""
Gives the curve's parametric interval

:getter: Returns the pair [a, b] in which curve is parametric defined
:type: Tuple[float]

"""
raise NotImplementedError

@property
@abstractmethod
def knots(self) -> Tuple[float]:
"""
Gives the curve's knots, in which the parametric interval is divided

:getter: Returns the knots that divides the curve's interval
:type: Tuple[float]

"""
raise NotImplementedError

@abstractmethod
def eval(self, parameters: Tuple[float]) -> Tuple[Tuple[float]]:
"""
Evaluates the curves at given parameters.

:param parameters: A vector-like of lenght n
:type parameters: Tuple[float]
:return: A matrix of shape (n, 2)
:rtype: Tuple[Tuple[float]]
"""
raise NotImplementedError

@abstractmethod
def winding(self, point: Tuple[float]) -> float:
"""
Computes the winding number of the given curve

The possible results are one in the interval [0, 1]

* 0 means the point is outside the internal curve
* 1 means the point is inside the internal curve
* in (0, 1) means it's on the boundary

:param point: A 2D-point
:type point: Tuple[float]
:return: The winding value with respect to the curve
:rtype: float

"""
raise NotImplementedError


class IMaterial(ABC):
"""
Material abstract class, the parent of other more specific materials
"""

@abstractmethod
def to_dict(self) -> Dict:
"""
Converts the material to a dictionary
"""
raise NotImplementedError

@classmethod
@abstractmethod
def from_dict(cls, dictionary: Dict) -> IMaterial:
"""
Converts the dictionary in a material instance
"""
raise NotImplementedError


class IFileIO(ABC):
"""
Abstract Reader class that serves as basic interface to read/save
informations from/to given file.
The file format is defined by child class.
"""

@abstractmethod
def is_open(self) -> bool:
"""
Tells if the reader is open
"""
raise NotImplementedError

@abstractmethod
def open(self, mode: str = "r"):
"""
Opens the file with given mode
"""
raise NotImplementedError

@abstractmethod
def close(self):
"""
Closes the file
"""
raise NotImplementedError

@abstractmethod
def load_nodes(self):
"""
Saves all the nodes from file into Node class
"""
raise NotImplementedError

@abstractmethod
def load_curves(self):
"""
Creates all the curves instances from file
"""
raise NotImplementedError

@abstractmethod
def load_materials(self):
"""
Creates all the materials instances from file
"""
raise NotImplementedError

@abstractmethod
def load_sections(self):
"""
Creates all the sections instances from file
"""
raise NotImplementedError


class IField(ABC):
"""
This is a base abstract class parent of others

It's responsible to decide if a given point is
inside/outside of given section.
"""

@property
@abstractmethod
def ndata(self) -> int:
"""
Gives the quantity of output numbers for one point

:getter: Returns the lenght of output data
:type: int
"""
raise NotImplementedError

@abstractmethod
def eval(self, points: Tuple[Tuple[float]]) -> Tuple[Tuple[float]]:
"""
Evaluate the field at given points

:param points: The wanted points, a matrix of shape (n, 2)
:type points: Tuple[Tuple[float]]
:return: The results in a matrix of shape (n, ndata)
:rtype: Tuple[Tuple[float]]
"""
raise NotImplementedError


class ISection(ABC): # pylint: disable=too-few-public-methods
"""
Section abstract class to serve as interface
"""
Loading