Giter VIP home page Giter VIP logo

Comments (12)

armantekinalp avatar armantekinalp commented on September 24, 2024

Hello @ing1992

Your OnedirectionTorque implementation looks right. This class will apply a torque on the last element of the rod in the direction set by direction variable. Only problem is do not reshape self.torque_end it should be shape of (3,).

However, I think you should change the lines of code you added in your timoshenko.py file.
This code is using the UniformTorques class which is some other class to generate uniform torques.
timoshenko_sim.add_forcing_to(shearable_rod).using( UniformTorques,toque_end,direction)

I suggest you to do the following change to use OnedirectionTorque class.
timoshenko_sim.add_forcing_to(shearable_rod).using( OnedirectionTorque,torque_end=torque_end,direction=direction)

Let me know if this helps.

from pyelastica.

 avatar commented on September 24, 2024

from pyelastica.

armantekinalp avatar armantekinalp commented on September 24, 2024

Since the torque you are applying is in the rod direction, it generates torsion on the rod. You can check if your code works or not by just printing the twist value of the rod, which can be accessed by shareable_rod.kappa[2] . I suggest printing out the value kappa[2] and see if it is changing or not.

If you are interested in rod buckling, you should disturb the rod. Otherwise rod won't change its shape even though it is twisting. I suggest to add a small velocity disturbance at the middle node or nodes of the rod in normal or binormal direction, after you initialize the rod. You can play around with the value of the disturbance.

sherable_rod.velocity_collection[..., int(n_elem/2)][0] += 1E-3

You should see some movements in the rod, like it is buckling. However, if you want to generate plectonemes or solenoids, rod self-contact should be used. But we haven't released the code for self-contact yet, and planning to release it in future.

Let me know this helps.

from pyelastica.

Seren1ty-bot avatar Seren1ty-bot commented on September 24, 2024

Hi, I tried to implement this code on my Python (removed the @self.torque_end and changed the call from UniformTorques to OnedirectionTorque as mentioned in the first reply), but it gave the following error at the finalize section:

"TypeError: Unable to construct forcing class.\nDid you provide all necessary force properties?"

May I ask what went wrong?

from pyelastica.

armantekinalp avatar armantekinalp commented on September 24, 2024

Hi @Seren1ty-bot ,

I think some variable is missing when you do add_forcing_to. Could you please check the variable names and make sure you add everything that UniformTorques class uses to during initialization step?

If that not works please share the part of the code, where you add UniformTorques class in to your simulation.

from pyelastica.

Seren1ty-bot avatar Seren1ty-bot commented on September 24, 2024

My code is as follows:

torque = 10
direction1 = np.array([1.0, 0.0, 0.0]) #direction named separately to avoid clashing with direction of endpoint force)

timoshenko_sim.add_forcing_to(shearable_rod).using(
    UniformTorques,
    torque,
    direction1
)

I don't see any missing variables here, maybe it's because of the tweaks I made in the elastica py files? I copy pasted the class code into _elastica_numba / external_forces.py because I couldn't create the class directly in the current script. I also added the phrase OnedirectionTorque in elastica/external_forces.py.

from pyelastica.

armantekinalp avatar armantekinalp commented on September 24, 2024

Hi @Seren1ty-bot

Couple of things:

  1. Are there any other forcing class added to your simulation?

  2. Have you changed anything in UniformTorques class? Can you try this

timoshenko_sim.add_forcing_to(shearable_rod).using( UniformTorques, torque = torque, direction = direction1 )

  1. You don't need to add OnedirectionTorque class in to the core PyElastica files. You can have it on another script and import it from there. Keep in mind that you should import NoForces class like this from elastica.external_forces import NoForces.

Error you are getting, can be due to two reasons. First one is a variable is missing (or name typo) when you add forcing class to the simulation. Second one is during the forcing class initialization there is an error in the code. Maybe first try my suggestions above and if those do not work share the script here.

from pyelastica.

Seren1ty-bot avatar Seren1ty-bot commented on September 24, 2024
  1. I'm running the torque along with EndpointForce. I just added it into the first tutorial.
  2. No, I haven't changed anything in UniformTorques. The module works well, and I can even print out kappa values when applying a certain range of torque magnitude.
  3. I can't find the problem, so here's the Google Drive link to two of my files: the project file (untitled0) and the endpointtorque module script, which I put in site-package/elastica and called.
    https://drive.google.com/drive/folders/1k5Be1j3VsSxmRPy-8NgjKNr5jir_lYgC?usp=sharing
    Thank you.

from pyelastica.

armantekinalp avatar armantekinalp commented on September 24, 2024

These are the problems I see

  1. In your untitled0.py file you import endpointtorque but the name of the class is EndPointTorque.
  2. In your endpointtorque.py you have some mistakes. First you cannot write def init, you should write def __init__(self, ....)
  3. Second apply_torques method, you should first multiply end point torque with directors and then add to the external_torques .

here is my corrections

class EndPointTorque(NoForces):
    def __init__(self,torque,direction):
        self.torque= (torque * direction).reshape(3, 1) # defined in global frame, shape(3,1)
    def apply_torques(self, system, time: np.float = 0.0):
        system.external_torques[..., -1] += system.director_collection[..., -1] @ self.torque

from pyelastica.

Seren1ty-bot avatar Seren1ty-bot commented on September 24, 2024

I edited the code, but there was still error. I'll just leave out the line readings in between:

One end of the rod is now fixed in place
Forces added to the rod
Callback function added to the simulator
Traceback (most recent call last):
File "D:\Users\User\anaconda3\lib\site-packages\elastica\wrappers\forcing.py", line 157, in __call__
    return self._forcing_cls(*self._args, **self._kwargs)

TypeError: __init__() got an unexpected keyword argument 'torque'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
...
File "D:\Users\User\anaconda3\lib\site-packages\elastica\wrappers\forcing.py", line 160, in __call__
    r"Unable to construct forcing class.\n"
TypeError: Unable to construct forcing class.\nDid you provide all necessary force properties?

from pyelastica.

armantekinalp avatar armantekinalp commented on September 24, 2024

Hi @Seren1ty-bot

Below code is running on my local device. Can you copy on your local and try it again.

import numpy as np
# Import Wrappers 
from elastica.wrappers import BaseSystemCollection, Connections, Constraints, Forcing, CallBacks
# Import Cosserat Rod Class
from elastica.rod.cosserat_rod import CosseratRod
# Import Boundary Condition Classes
from elastica.boundary_conditions import OneEndFixedRod, FreeRod
from elastica.external_forces import NoForces, EndpointForces, UniformTorques, UniformForces
# Import Timestepping Functions
from elastica.timestepper.symplectic_steppers import PositionVerlet
from elastica.timestepper import integrate
from elastica.callback_functions import CallBackBaseClass
from collections import defaultdict
# from elastica import endpointtorque


class TimoshenkoBeamSimulator(BaseSystemCollection, Connections, Constraints, Forcing, CallBacks):
    pass

timoshenko_sim = TimoshenkoBeamSimulator()

# setting up test params
n_elem = 100

density = 1000
nu = 0.1
E = 1e6
# For shear modulus of 1e4, nu is 99!
poisson_ratio = 99


start = np.zeros((3,))
direction = np.array([0.0, 0.0, 1.0])
normal = np.array([0.0, 1.0, 0.0])
base_length = 3.0
base_radius = 0.25
base_area = np.pi * base_radius ** 2

shearable_rod = CosseratRod.straight_rod(
    n_elem,
    start,
    direction,
    normal,
    base_length,
    base_radius,
    density,
    nu,
    E,
    poisson_ratio,
)

timoshenko_sim.append(shearable_rod)

timoshenko_sim.constrain(shearable_rod).using(
    OneEndFixedRod, 
    constrained_position_idx=(0,), 
    constrained_director_idx=(0,)
)
print('One end of the rod is now fixed in place')

origin_force = np.array([0.0, 0.0, 0.0])
end_force = np.array([-10.0, 0.0, 0.0])
ramp_up_time = 5.0

timoshenko_sim.add_forcing_to(shearable_rod).using(
    EndpointForces, 
    origin_force, 
    end_force, 
    ramp_up_time=ramp_up_time
)

class EndPointTorque(NoForces):
    def __init__(self,torque,direction):
        self.torque= torque * direction # defined in global frame, shape(3,1)
    def apply_torques(self, system, time: np.float = 0.0):
        system.external_torques[..., -1] += system.director_collection[..., -1] @ self.torque

direction1 = np.array([1.0, 0.0, 0.0])
toque_end = -10
timoshenko_sim.add_forcing_to(shearable_rod).using(
EndPointTorque,torque=toque_end,direction=direction1)

print('Forces added to the rod')

class TimCallBack(CallBackBaseClass):
    """
    Call back function for continuum snake
    """

    def __init__(self, step_skip: int, callback_params: dict):
        CallBackBaseClass.__init__(self)
        self.every = step_skip
        self.callback_params = callback_params

    def make_callback(self, system, time, current_step: int):

        if current_step % self.every == 0:

            self.callback_params["time"].append(time)
            self.callback_params["step"].append(current_step)
            self.callback_params["position"].append(
                system.position_collection.copy()
            )
            self.callback_params["velocity"].append(
                system.velocity_collection.copy()
            )
            self.callback_params["avg_velocity"].append(
                system.compute_velocity_center_of_mass()
            )

            self.callback_params["center_of_mass"].append(
                system.compute_position_center_of_mass()
            )

            return

pp_list = defaultdict(list)
timoshenko_sim.collect_diagnostics(shearable_rod).using(
    TimCallBack, step_skip=200, callback_params=pp_list
)

print('Callback function added to the simulator')

timoshenko_sim.finalize()
print('System finalized')

final_time = 20.0
dl = base_length / n_elem
dt = 0.01 * dl
total_steps = int(final_time / dt)
print("Total steps to take", total_steps)

timestepper = PositionVerlet()
integrate(timestepper, timoshenko_sim, final_time, total_steps)

def analytical_result(arg_rod, arg_end_force, shearing=True, n_elem=500):
    base_length = np.sum(arg_rod.rest_lengths)
    arg_s = np.linspace(0.0, base_length, n_elem)
    if type(arg_end_force) is np.ndarray:
        acting_force = arg_end_force[np.nonzero(arg_end_force)]
    else:
        acting_force = arg_end_force
    acting_force = np.abs(acting_force)
    linear_prefactor    = -acting_force / arg_rod.shear_matrix[0, 0, 0]
    quadratic_prefactor = -acting_force / 2.0 * np.sum(arg_rod.rest_lengths / arg_rod.bend_matrix[0, 0, 0])
    cubic_prefactor     = (acting_force / 6.0) / arg_rod.bend_matrix[0, 0, 0] 
    if shearing:    
        return arg_s, arg_s*linear_prefactor + arg_s**2*quadratic_prefactor + arg_s**3*cubic_prefactor
    else:
        return arg_s, arg_s**2 * quadratic_prefactor + arg_s**3 * cubic_prefactor

def plot_timoshenko(shearable_rod, end_force):
    import matplotlib.pyplot as plt
    analytical_shearable_positon = analytical_result(shearable_rod, end_force, shearing=True)
   

    fig = plt.figure(figsize=(5, 4), frameon=True, dpi=150)
    ax = fig.add_subplot(111)
    ax.grid(b=True, which="major", color="grey", linestyle="-", linewidth = 0.25)

    ax.plot(analytical_shearable_positon[0],   analytical_shearable_positon[1],  "k--", label="Timoshenko")
  
    ax.plot(shearable_rod.position_collection[2, :], 
            shearable_rod.position_collection[0, :], 
            "b-", label="n="+str(shearable_rod.n_elems))
    

    
    ax.legend(prop={"size": 12})
    ax.set_ylabel('Y Position (m)', fontsize = 12)
    ax.set_xlabel('X Position (m)', fontsize = 12)
    plt.show()

plot_timoshenko(shearable_rod, end_force)
    
import matplotlib.pyplot as plt
from IPython import display

evolve_for_time = 20.0
update_interval = 1.0e-1

# update the plot every 1 second

from IPython.display import Video

def plot_video( plot_params: dict, video_name="video.mp4", margin=0.2, fps=15):  
    from matplotlib import pyplot as plt
    import matplotlib.animation as manimation

    positions_over_time = np.array(plot_params["position"])

    print("creating video -- this can take a few minutes")
    FFMpegWriter = manimation.writers["ffmpeg"]
    metadata = dict(title="Movie Test", artist="Matplotlib", comment="Movie support!")
    writer = FFMpegWriter(fps=fps, metadata=metadata)
    fig = plt.figure()
    plt.axis("equal")
    with writer.saving(fig, video_name, dpi=100):
        for time in range(1, len(plot_params["time"])):
            
            x = positions_over_time[time][2]
         
            y = positions_over_time[time][0]
            fig.clf()
            plt.plot(x, y, "-", linewidth=3)
            
            plt.xlim([0 - margin, 3 + margin])
            plt.ylim([-0.05 - margin, 0.01 + margin])
            writer.grab_frame()
    plt.close(fig)

filename_video = "continuum100.mp4"
plot_video(pp_list, video_name=filename_video, margin=0.02, fps=25)
    
Video("continuum100.mp4")

print(shearable_rod.kappa[2])

from pyelastica.

Seren1ty-bot avatar Seren1ty-bot commented on September 24, 2024

@armantekinalp It runs! I'll try to figure out the reasons why my previous attempts had failed. Thanks a lot for the help!

from pyelastica.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.