I build a fluid model with a PID control system, and I wanna run my model until reaching a steady state and then keep the output signal of the PID system unchanged, so I could do step excitation stability tests. But right now I am not sure how to keep the output signal of the PID control system unchanged after a fixed time point. So I have to use a logical switch to change the signal source at a fixed time point.
My question is:
How could keep the output signal of a Block Component unchanged after a fixed time point?
I dont't think there is a suitable block in the Modelica Standard Library.
But would that code do it?
model KeepValueTime
extends Modelica.Blocks.Interfaces.SISO;
parameter Modelica.Units.SI.Time t = Modelica.Constants.inf "Time at which the value shall be kept";
Real u_keep(start=0) "Value to be output when 'keepValue = true'";
equation
if time < t then
y = u;
else
y = u_keep;
end if;
when time >= t then
u_keep = u;
end when;
annotation (uses(Modelica(version="4.0.0")));
end KeepValueTime;
A bit more general with a Boolean input:
model KeepValue
extends Modelica.Blocks.Interfaces.SISO;
Real u_keep(start=0) "Value to be output when 'keepValue = true'";
Modelica.Blocks.Interfaces.BooleanInput keepValue annotation (Placement(transformation(
extent={{-20,-20},{20,20}},
rotation=0,
origin={-120,80}), iconTransformation(extent={{-140,60},{-100,100}}, rotation=0)));
equation
if not keepValue then
y = u;
else
y = u_keep;
end if;
when keepValue then
u_keep = u;
end when;
annotation (uses(Modelica(version="4.0.0")));
end KeepValue;
A quick test:
...seems to do what you need:
An alternative to the solution suggested by Markus A. could be to switch the control error to zero. This will freeze the controller output, provided that the switch is done when the system is already in steady state (zero control error).
I've written a program to move around particles in a 3-D field based on a 3-D velocity field. However, I get a segmentation fault at the line when I update the particle positions, and I have no idea why! I wrote this program previously in a single file, and it worked fine. But now I'm getting the segmentation fault error when I have all the functions/subroutines in a module.
Edit: I implemented the suggestions below, and now the segmentation fault has moved from the update particle line to the line where I call writeResults. Any help is still appreciated!
Main Program:
program hw4Fortran
use hw4_module
implicit none
!Define types
integer::i ,j, k, num_ts, num_particles, field_size_x, field_size_y, &
field_size_z, num_arguments
type(vector),allocatable::vfield(:,:,:)
type(vector),allocatable::parray(:)
character(30)::out_file_basename, vel_file, part_file, filename, string_num_ts
!Read command line
num_arguments = NARGS()
if (num_arguments > 1) then
call GETARG(1, string_num_ts)
read(string_num_ts, *) num_ts
else
num_ts = 50
end if
if (num_arguments > 2) then
call GETARG(2, out_file_basename)
else
out_file_basename = "results"
end if
if (num_arguments > 3) then
call GETARG(3, vel_file)
else
end if
if (num_arguments > 4) then
call GETARG(4, part_file)
else
part_file = "particles.dat"
end if
!Open files
open(unit=1, file=vel_file)
open(unit=2, file=part_file)
!Read number of particles
num_particles = readNumParticles(2)
!Adjust for zero index
num_particles = num_particles - 1
!Allocate and read particle array
parray = readParticles(2, num_particles)
!Read field size
field_size_x = readFieldSize(1)
field_size_y = readFieldSize(1)
field_size_z = readFieldSize(1)
!Adjust for zero index
field_size_x = field_size_x - 1
field_size_y = field_size_y - 1
field_size_z = field_size_z - 1
!Allocate and read vector field
vfield = readVectorField(1, field_size_x, field_size_y, field_size_z)
!Move particles and write results
do i=0,num_ts
if (mod(i,10) == 0) then
write(filename, fmt = "(2A, I0.4, A)") trim(out_file_basename), "_", i, ".dat"
open(unit = 3, file=filename)
end if
do j=0, num_particles
if (i > 0) then
parray(j) = updateParticle(vfield(INT(FLOOR(parray(j)%x)),INT(FLOOR(parray(j)%y)),INT(FLOOR(parray(j)%z))), parray(j))
end if
if (mod(i,10) == 0) then
call writeResults(3, parray(j))
end if
end do
if (mod(i,10) == 0) then
close(3)
end if
end do
!Close files
close(1)
close(2)
!Deallocate arrays
deallocate(vfield)
deallocate(parray)
end program hw4Fortran
Module:
module hw4_module
implicit none
type vector
real::x,y,z
end type
contains
function readNumParticles(fp) result(num_particles)
integer::fp, num_particles
read(fp, *) num_particles
end function
function readParticles(fp, num_particles) result(parray)
integer::fp, num_particles, i
type(vector),allocatable::parray(:)
allocate(parray(0:num_particles))
do i=0, num_particles
read(fp, *) parray(i)
end do
end function
function readFieldSize(fp) result(field_size)
integer::fp, field_size
read(fp, *) field_size
end function
function readVectorField(fp, field_size_x, field_size_y, &
field_size_z) result(vfield)
integer::fp, field_size_x, field_size_y, field_size_z, i, j
type(vector),allocatable::vfield(:,:,:)
allocate(vfield(0:field_size_x,0:field_size_y,0:field_size_z))
do i=0, field_size_x
do j=0, field_size_y
read(fp, *) vfield(i,j,:)
end do
end do
end function
function updateParticle(velocity, old_particle) result(new_particle)
type(vector)::new_particle,old_particle,velocity
new_particle%x = old_particle%x + velocity%x
new_particle%y = old_particle%y + velocity%y
new_particle%z = old_particle%z + velocity%z
end function
subroutine writeResults(fp, particle)
integer::fp
type(vector)::particle
write(fp, *) particle%x, " ", particle%y, " ", particle%z
end subroutine
end module
This function
function readParticles(fp, num_particles) result(parray)
integer::fp, num_particles, i
type(vector),allocatable::parray(:)
allocate(parray(0:num_particles))
do i=0, num_particles
read(fp, *) parray(i)
end do
end function
allocates parray with index values 0:num_particles. Unfortunately, and this trips up many a newcomer to Fortran (some oldcomers too), those array bounds are not passed out to the calling code which will blithely assume an index range starting at 1. And then the code goes on to access parray(0) ... and the problem that John B warns of arises.
Fortran's capability of indexing arrays from an arbitrary integer value is never quite as useful as it seems. You can pass the bounds into and out of procedures, but who can be bothered ? Easier just to pretend that Fortran arrays index from 1 and apply that consistently throughout a program.
here is a simple version of what the OP is doing with allocate
module altest
contains
function setarray(n) result(x)
implicit none
integer, intent(in) :: n
integer , allocatable :: x(:)
allocate(x(n))
x(1)=1
end function
end module
program Console6
use altest
implicit none
integer,allocatable :: m(:)
m=setarray(2)
write(*,*)'m1',m(1)
end program Console6
It "appears" to be allocating an array x in the function and assigning that to an allocatable array m in the calling program. This compiles but throws a subscript out of bounds error on the write. (note this would likely be a seg fault if bounds checking is not enabled )
This can be fixed by separately allocating the array in the calling routine, or by passing the allocatable array as an argument:
module altest
contains
subroutine setarray(n,x)
implicit none
integer, intent(in) :: n
integer , allocatable :: x(:)
allocate(x(n))
x(1)=1
end subroutine
end module
program Console6
use altest
implicit none
integer,allocatable :: m(:)
call setarray(2,m)
write(*,*)'m1',m(1)
end program Console6
Edit - somewhat to my surprise, the second case works fine if we allocate with a zero lower bound in the sub allocate(x(0:n)) , the calling routine 'knows' the subscript starts at zero. ( Works with intel fortran v13 -- I have no Idea if this is a safe thing to do.. )
A segmentation fault normally indicates that your program is trying to access memory that does not belong to it.
When you say the error occurs "when I update the particle positions", I take it you mean this line:
updateParticle(vfield(INT(FLOOR(parray(j)%x)),INT(FLOOR(parray(j)%y)),INT(FLOOR(parray(j)%z))), parray(j))
An array-bounds violation in that statement seems entirely plausible, as I don't see anything in your code that would prevent the array indexes INT(FLOOR(parray(j)%x)) et al from falling outside the allocated dimensions of array vfield. Even if they are all in bounds at the initial step of the simulation, they may go out of bounds as the simulation proceeds.
Whether such a result in fact occurs appears to be data-dependent, not related to whether your functions appear in a module.
It looks like you have a C background. Could this be an off-by-one error? When looping in Fortran, the loop index goes all the way to the upper bound. Your Fortran loop:
do j=0, num_particles
! ...
end do
is equivalent to this C loop:
for (int j = 0; j <= num_particles; j++)
{
// ...
}
Note the <= sign, instead of <.
You may want to change your Fortran upper bound to num_particles - 1.
I'm implementing a low pass filter in C wih the PortAudio library.
I record my microphone input with a script from PortAudio itself. There I added the following code:
float cutoff = 4000.0;
float filter(float cutofFreq){
float RC = 1.0/(cutofFreq * 2 * M_PI);
float dt = 1.0/SAMPLE_RATE;
float alpha = dt/(RC+dt);
return alpha;
}
float filteredArray[numSamples];
filteredArray[0] = data.recordedSamples[0];
for(i=1; i<numSamples; i++){
if(i%SAMPLE_RATE == 0){
cutoff = cutoff - 400;
}
data.recordedSamples[i] = data.recordedSamples[i-1] + (filter(cutoff)*(data.recordedSamples[i] - data.recordedSamples[i-1]));
}
When I run this script for 5 seconds it works. But when I try to run this for more then 5 seconds it fails. The application records everything, but crashes on playback. If I remove the filter, the application works.
Any advice?
The problem:
you are lowering the cutoff frequency by 400 Hz everytime i%SAMPLE_RATE == 0
never stop so you go below zero
this is not done once per second !!!
instead every time your for passes through second barrier in your data
that can occur more often then you think if you are not calling your calls in the right place
which is not seen in your code
you are filtering in wrong oorder
... a[i]=f(a[i],a[i-1]; i++;
that means you are filtering with already filtered a[i-1] value
What to do with it
check the code placement
it should be in some event like on packed done sompling
or in thread after some Sleep(...); (or inside timer)
change the cut off changing (handle edge cases)
reverse filter for direction
Something like this:
int i_done=0;
void on_some_timer()
{
cutoff-=400;
if (cutoff<1) cutoff=1; // here change 1 for limit frequency
if (numSamples!=i_done)
for (i=numSamples-1,i>=i_done;i--)
data.recordedSamples[i] = data.recordedSamples[i-1] + (filter(cutoff)*(data.recordedSamples[i] - data.recordedSamples[i-1]));
i_done=numSamples;
}
if your code is already OK (you did not post th whole thing so I can missing something)
then just add the if (cutoff<1) cutoff=1; after cutoff change
I am pretty new to Ruby. I am college and just did a programming course that covered regular c. My final project for class was a slop intercept project, which was fairly easy, but i had to use functions for everything, for example:
#include <stdio.h>
#include <math.h>
int get_problem(int *choice){
do {
printf("Select the form that you would like to convert to slope-intercept form: \n");
printf("1) Two-Point form (you know two points on the line)\n");
printf("2) Point-slope form (you know the line's slope and one point)\n");
scanf("%d", &*choice);
if (*choice < 1 || *choice > 2){
printf("Incorrect choice\n");}
}while (*choice != 1 && *choice !=2);
return(*choice);
}
...
int main(void);
{
char cont;
do {
int choice;
double x1, x2, y1, y2;
double slope, intercept;
get_problem (&choice);
...
I have several more functions completing the entire program. I got a new job and i need to start learning Ruby, So for my first project I wanted to convert this program into Ruby, now I was able simply get rid of the functions and just run it without methods or procs. I wanted to know if it is possible to do the same thing, define a method, then call the method without giving an input, but getting back the variables stored in the method. Would it be possible using methods or procs. Here is a little of what i have so far using a proc.
get_problem = Proc.new {
begin
puts "Select the form that you would like to convert to slope-intercept form: "
puts "1) Two-Point form (you know two points on the line)"
puts "2) Point-slope form (you know the lines slope and one point)"
choice = gets.chomp.to_i
if (choice < 1 || choice > 2)
puts "Incorrect choice"
end
end while (choice != 1 && choice !=2)
}
....
begin
get_problem.call
case choice
when 1
get2_pt.call
display2_pt.call
slope_intcpt_from2_pt.call
when 2
get_pt_slope.call
display_pt_slope.call
intcpt_from_pt_slope.call
Now I know I probably have it all wrong, but I figured I would give it a shot. I have it as methods before where I had
def get_problem(choice)
....
end
....
get_problem(choice)
....
Is there something basic I am missing? As you can see, i used pointers in c and had to initialize the variables in the main.
Thank you for taking the time to help me out.
Robert
You can't pass a pointer to a variable in Ruby, but I don't think you need to do that to accomplish what you're trying to do. Try this:
def get_problem
puts "Select the form that you would like to convert to slope-intercept form: "
puts "1) Two-Point form (you know two points on the line)"
puts "2) Point-slope form (you know the lines slope and one point)"
loop do
choice = gets.chomp.to_i
return choice if [1, 2].include? choice
STDERR.puts "Incorrect choice: choose either 1 or 2"
end
end
choice = get_problem
puts "The user chose #{choice}"
This defines a method get_problem which loops until the user chooses either 1 or 2, and returns their chosen number, which you can store in a top-level variable choice.
Hello I am studying for a test for an intro to C programming class and yesterday I was trying to write this program to print out the even prime numbers between 2 and whatever number the user enters and I spent about 2 hours trying to write it properly and eventually I did it. I have 2 pictures I uploaded below. One of which displays the correct code and the correct output. The other shows one of my first attempts at the problem which didn't work correctly, I went back and made it as similar to the working code as I could without directly copying and pasting everything.
unfortunately new users aren't allowed to post pictures hopefully these links below will work.
This fails, it doesn't print all numbers in range with natural square root:
for (i = 2; i <= x; i++)
{
//non relevant line
a = sqrt(i);
aa = a * a;
if (aa == i);
printf("%d ",i);
}
source: http://i.imgur.com/WGG6n.jpg
While this succeeds, and prints even numbers with natural sqaure root
for (i = 2; i <= x; i++)
{
a = sqrt(i);
aa = a * a;
if (aa == i && ((i/2) *2) == i)
printf("%d ", i);
}
source: http://i.imgur.com/Kpvpq.jpg
Hopefully you can see and read the screen shots I have here. I know that the 'incorrect code' picture does not have the (i/2)*2 == i part but I figured that it would still print just the odd and even numbers, it also has the code to calculate "sqrd" but that shouldn't affect the output. Please correct me if I'm wrong on that last part though.
And Yes I am using Dev-C++ which I've read is kinda crappy of a program but I initally did this on code::blocks and it did the same thing...
Please I would very much appreciate any advice or suggestions as to what I did wrong 2 hours prior to actually getting the darn code to work for me.
Thank you,
Adam
your code in 'that' includes:
if (aa == i);
// ^
printf(...);
[note the ; at the end of the if condition]
Thus, if aa == i - an empty statement happens, and the print always occures, because it is out of the scope of the if statement.
To avoid this issue in the future, you might want to use explicit scoping1 [using {, } after control flow statements] - at least during your first steps of programming the language.
1: spartan programmers will probably hate this statement
Such errors are common. I use "step Over", "Step Into", "Break Points" and "watch window" to debug my program. Using these options, you can execute your program line by line and keep track of the variables used in each line. This way, u'll know which line is not getting executed in the desired way.