Skip to content

Commit

Permalink
Merge pull request #20 from compmec/dev-0.4.0
Browse files Browse the repository at this point in the history
Dev 0.4.0
  • Loading branch information
carlos-adir authored Mar 5, 2024
2 parents 4b32bcd + 618bf9f commit e807b38
Show file tree
Hide file tree
Showing 19 changed files with 1,391 additions and 499 deletions.
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 <[email protected]>"]
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

0 comments on commit e807b38

Please sign in to comment.