Joe Riel

8049 Reputation

22 Badges

15 years, 12 days

MaplePrimes Activity

These are answers submitted by Joe Riel

Yes, the model incorporates back-emf.  The K constant is used to compute the back emf from the rotational velocity, as well as the torque from the current. The device equations are shown in the help page.

However, you shouldn't believe me---it's better to test the model yourself.  Do it the same way as you'd measure the back-emf in an actual motor:  turn the shaft and measure the open-circuit voltage.

@Earl The form you gave is a discrete event with a conditional trigger.  Discrete events occur during event iteration, which only occurs when there are discrete variables.  Event iteration is initiated by a continuous trigger.

Here's a brute force attempt to solve this. To make it checkable, I generalized the problem to an n-sided die, with markings from 1 to n. To make the run-time reasonable, the procedure Check, which checks whether all the digits have occurred, is compiled. For n = 5 it runs in about 1 minute. I haven't tried it with n=6, but expect it to take quite a while. The print statement prints the length of the current run that is being tested, that is there to give a relative feedback on progress.

Straight := module()
    ModuleApply := proc(n :: posint)
    local C, N, R, T, cnt, len;
        C := Array(1..n, 'datatype' = integer[4]);
        for len from n do
            N := n^len;
            R := Iterator:-MixedRadixTuples([n $ len]);
            cnt := 0;
            for T in R do
                C[] := 0;
                if Check(T,C,len,n) then
                    cnt := cnt+1;
                end if
            end do;
            if cnt/N >= 1/2 then
                return len;
            end if;
        end do;
    end proc;

    Check := proc(T :: Array, C :: Array, len :: posint, n :: posint)
    option autocompile;
    local k;
        for k to len do
            C[T[k]+1] := 1;
        end do;
        for k to n do
            if C[k] = 0 then
                return false;
            end if;
        end do;
        return true;
    end proc;

end module:


While it presumably won't help here as the suggested solutions are efficient and avoid set building altogether, since Maple 2016 there is an object, MutableSet, that has efficient methods for manipulating sets in Maple.

Use profiling.  There are exports in CodeTools:-Profiling that will help, but I generally use the low level commands.  For example

foo := proc(n::posint)
local i;
   # inefficient way to build a sequence
   s := NULL; 
   for i to n do
       s := s,i;
   end do;
end proc:
# set up profiling on foo
debugopts('traceproc' = foo):
# execute the procedure
# display the results
printf("%s\n", debugopts('procdump'=foo)):
foo := proc(n::posint)
local i, s;
     |Calls Seconds  Words|
PROC |    1   0.000   5447|
   1 |    1   0.000      0| s := NULL;
   2 |    1   0.000      0| for i to n do
   3 |  100   0.000   5447|     s := s, i
                            end do;
   4 |    1   0.000      0| s

That example wasn't particularly enlightening, but try it on your own procedure. Depending on what your procedure does, you might want to set debugopts('tracerealtime'=true) first, it causes the profiler to measure the actual elapsed time, versus the time taken in the Maple kernel.

The call to evalf is outside your loop.  When the loop exits, i is assigned 9 (1 more than the to value).

Here's an alternative view.  I put as little code as practical in the embedded component, typically a call to a procedure, possibly with an argument that identifies the embedded component.  The functionality is contained in the procedure, an export of a module. As an example, a button may contain 


while the startup region may contain

  _App := SomePackage:

where SomePackage is the name of a module that is saved in a Maple archive (mla). An advantage of this approach is that it's a lot easier to maintain the code. This may be overkill for your usage. A hybrid approach would be to insert the Maple code that defines the module into the startup region.

Followup The OP asked for an example. Here it is: I modified his original to use a package assigned in the startup region, and included a call to with so that the package exports, used by the sliders, can be accessed without referring to the package name.  While I don't always use with, one advantage to doing so is that the code in the embedded components is then, essentially, inert and error-free until the package is assigned.  Otherwise, if MyApp:-ChangeA() was inserted as the code for the A slider, any time the slider was clicked an error would be raised (and raised repeatedly, making it a pain to fix) stating that MyApp was not a module.

For complicated applications, using a single procedure call in an embedded component has a lot of practical advantages.  One of them is that it facilitates debugging.  For example, in the worksheet you can add and execute the line


then, when you move the A slider, the Maple debugger will be launched and you can step through ChangeA and, if desired, its call to UpdatePlot.

This happens because V, the formal parameter to your switch procedure, is passed a mutable object.  In the body of the procedure, the assignment W := V makes W point to the same structure that V points to.  So any changes in the procedure to W affects V. To avoid that you could use copy, for example, W := copy(V).  If V itself contains mutable structures you might do W := copy(V, 'deep'), where the deep option tells copy to recursively copy its content.

 Here's a more general way to reverse the content of a 1D rtable.

Reverse := proc(a :: rtable
                , { inplace :: truefalse := false }
                , $
local b,i;
    if not a :: 'rtable(1..)' then
        error "expecting one-dimensional rtable that starts at one";
    elif inplace then
        b := a;
        b := copy(a);
    end if;
    for i to iquo(upperbound(a),2) do
        (b[i],b[-i]) := (a[-i],a[i]);
    end do;
end proc:

I'd generally encode that as follows. Note the use of the remember option; that makes the operation much more efficient as previous results are reused.

v := proc(a)
option remember;
    v(a-1) + 6*v(a-2);
end proc:

# Assign the initial values (this writes to v's remember table)
v(1) := 1:
v(2) := 2:

for k to 20 do
    printf("v(%d) = %d\n", k, v(k) );
end do:

There is no formal parameter for the second positional argument. The dsolve routine does its own parameter processing and uses _rest, etc., to access the undeclared parameters. This might be because dsolve has been around for a long time and existed in some form before a lot of improvements to Maple's parameter processing were implemented. In this case, though, I suspect it has more to do with the second argument being optional.  An alternative would be to declare the second argument and give it a special default value then check for that, however, that isn't any better and the older code did the equivalent in a slightly different manner.


I'd change this to an answer, rather than a reply, if I knew how (thanks whoever did so).  The real confusion you are seeing is that you are using _nparams, rather than nargs or _npassed (a synonym). The _nparams value is based on the number of declared (formal) parameters, not the number of passed arguments.

I don't know what you want to plot; could you explain. That aside, the code can be slightly restructured to improve it.  Also, you might want to make H, etc. Vectors and Matrices rather than implicitly declared tables.

alpha := 0:
beta := 2:
Imax := 11:
Jmax := 11:
L := 10:
`Δζ` := L/(Imax-1):

`Δx` := `Δζ`:
`Δη` := 1/(Jmax-1):

x := Vector(Imax):
H := Vector(Imax):
H1 := Vector(Imax):
H2 := Vector(Imax):
y := Matrix(Imax,Jmax):
Y := Matrix(Imax,Jmax):

printlevel := 2:
for i to Imax do
    x[i] := `Δζ`*(i-1);
    H[i] := 3+2*tanh(x[i]-6);
    H1[i] := 0;
    H2[i] := -H[i];
    for j to Jmax do
        eta[j] := `Δη`*(j-1);
        z := (eta[j]-alpha)*ln((beta+1)/(beta-1))/(1-alpha);
        y[i, j] := -H[i]*(2*beta/(exp(z)+1)-beta-2*alpha)/(2*alpha+1);
        Y[i, j] := (H1[i]+(-H1[i]*x[i]+H2[i])/L)*eta[j]
    end do
end do:

Here's a different approach that doesn't allocate extra memory (doesn't generate new sets).

fnd := false:
for v in L2 do
    for e in L1 do 
        fnd := member(v,e); 
    until fnd; 
until fnd:

On exit, the variable fnd is assigned true if a vertex was found.  If true, e and v will be assigned the first edge and vertex found with v in e, which might be useful.

The problem is that the set S contains y[14], which is a procedure.  Fix the assignment to x[2], the reference to y[14] does not include the parentheses and argument.

The best approach depends on what you want to do with the result. 

Let nx be a piecewise whose condition is some arbitrary relation.

(**) nx := piecewise(x > 0, +1, -1);
(**) y := nx^n:
(**) simplify(y) assuming n :: even;                                                                                             
(**) simplify(y) assuming n :: odd;                                                   
                                  { -1        x <= 0
                                  { 1         0 < x

Another approach is to use a set to represent the possible values.

(**) nx := {+1,-1};                                                                   
                                    nx := {-1, 1}

(**) y := nx^~n;                                                                      
                                   y := {1, (-1) }

(**) simplify(y) assuming n :: even;                                                  

(**) simplify(y) assuming n :: odd;                                                   
                                       {-1, 1}

While I suspect that neither of these is what you're looking for, note that you can do

(**) nx := piecewise(x<0,-1,1):
(**) hx := convert(nx, Heaviside);
                             hx := 2 Heaviside(x) - 1

(**) y := hx^n;
                            y := (2 Heaviside(x) - 1)

(**) simplify(y) assuming n :: even;

(**) simplify(y) assuming n :: odd;
                                2 Heaviside(x) - 1

To generate the probability correctly, you need to generate all permutations of the 9 digits.

F := Permute(1..9):
picks := [seq(add(add(10^(i-1)*f[i+j],i=1..3),j=0..8,3),f = F)]:
rng := (min..max)(picks);
                        rng := 774 .. 2556
# Find unique values
vals := convert(picks,set):
num := numelems(vals);
                           num := 199
# Determine entry that occurs the most
A := Array(rng):
for val in picks do A[val] := A[val]+1; end do:
imax := max[index](A);
                          imax := 1764

Further While it is mostly pointless here, a better technique would be to avoid generating all the picks as a list.

T := table(sparse):
for f in F do
   val := add(add(10^(i-1)*f[i+j],i=1..3),j=0..8,3);
   T[val] := T[val] + 1;
end do:

A downside is that it is a little less convenient to find the max entry and associated value, however, because there are multiple indices with the same entry, we need to do this, regardless.

vmax := max(entries(T,'nolist'));
                                  vmax := 3888
for i in [indices(T,'nolist')] do 
    if T[i] = vmax then print(i) end if 
end do:

Those agree with the values you listed.

The Statistics package could be used here

X := RandomVariable(EmpiricalDistribution(picks)):
S := Sample(X,1000):
3 4 5 6 7 8 9 Last Page 5 of 103